From c5244bc6520e6c3c74b4f14b71a17dd67eb10ca5 Mon Sep 17 00:00:00 2001 From: andy Date: Mon, 20 Jul 2026 12:05:54 +0700 Subject: [PATCH] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=AE=A2=E5=8D=95=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E5=BE=85=E5=A4=84=E7=90=86=E6=95=B0=E9=87=8F=E5=8F=A3?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PROJECT_STATE.md | 10 +-- client/src/i18n/locales/en-US.ts | 2 +- client/src/i18n/locales/th-TH.ts | 2 +- client/src/i18n/locales/zh-CN.ts | 2 +- client/src/tests/reservationService.spec.ts | 2 + .../tests/reservationTaskDetailPanel.spec.ts | 1 + client/src/tests/reservationViews.spec.ts | 25 ++++++ client/src/types/reservation.ts | 1 + .../reservation/ReservationOrderListView.vue | 17 ++++ .../backend-to-frontend-notes.md | 7 +- .../frontend-to-backend-api-requests.md | 8 +- .../2026-07-20-order-list-open-work-count.md | 86 +++++++++++++++++++ 12 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 docs/superpowers/plans/2026-07-20-order-list-open-work-count.md diff --git a/PROJECT_STATE.md b/PROJECT_STATE.md index dd51444..4d22e3d 100644 --- a/PROJECT_STATE.md +++ b/PROJECT_STATE.md @@ -4,15 +4,15 @@ | --- | --- | | 最近更新 | 2026-07-20 | | 当前分支 | `feature/huangting` | -| 当前阶段 | M002 V4 入站、多卡模型、持久化基线、入站写入、查询接口、卡片确认、复核解阻、目录校验、订单详情时间线、DB 目录、Lookup API、前端 lookup 接入、目录管理后台 CP1 前后端和订单列表 V4 继续处理入口 | -| 当前重点 | M002 V4 已完成订单列表 V4 继续处理入口字段和前端消费,`GET /api/reservation/orders` 可返回 V4 下一步订单任务、卡片、动作类型、动作状态和 open 数;前端“继续处理”已按 V4 优先、旧任务回退跳转;后续可做测试机联调、真实 PMS / OPERA / OHIP 同步或 SuperAgent 目录供给方案 | +| 当前阶段 | M002 V4 入站、多卡模型、持久化基线、入站写入、查询接口、卡片确认、复核解阻、目录校验、订单详情时间线、DB 目录、Lookup API、前端 lookup 接入、目录管理后台 CP1 前后端和订单列表 V4 继续处理入口 / open count 收口 | +| 当前重点 | M002 V4 已完成订单列表 V4 继续处理入口字段和前端消费,`GET /api/reservation/orders` 可返回 V4 下一步订单任务、卡片、动作类型、动作状态、V4 open 数和统一展示字段 `open_work_item_count`;前端“继续处理”已按 V4 优先、旧任务回退跳转,订单列表待处理数量已改用 `open_work_item_count` 展示;后续可做测试机联调、真实 PMS / OPERA / OHIP 同步或 SuperAgent 目录供给方案 | ## 1. 当前 Checkpoint - 名称:`M002-V4-CP14-order-list-v4-entrypoint` -- 状态:Done,订单列表接口已补齐 V4 下一步处理入口字段:`next_v4_order_task_id`、`next_v4_action_card_id`、`next_v4_action_type`、`next_v4_action_status`、`v4_open_order_task_count`。前端订单列表已优先使用 `next_v4_order_task_id` 跳转 V4 订单任务详情,并在无 V4 入口时回退旧 `next_processable_task_id`。 +- 状态:Done,订单列表接口已补齐 V4 下一步处理入口字段:`next_v4_order_task_id`、`next_v4_action_card_id`、`next_v4_action_type`、`next_v4_action_status`、`v4_open_order_task_count`,并新增统一展示计数 `open_work_item_count`。第一版不考虑旧数据,`open_work_item_count` 等于 V4 未完成订单任务数。前端订单列表已优先使用 `next_v4_order_task_id` 跳转 V4 订单任务详情,并在无 V4 入口时回退旧 `next_processable_task_id`;待处理数量展示只读 `open_work_item_count`,不使用旧 `open_task_count` 作为展示数量。 - 目标:让前端订单列表“继续处理”在存在 V4 待处理订单任务时可优先跳转 V4 订单任务详情;无 V4 待处理时继续回退旧 V2/V3 任务入口。 -- 边界:本轮不改后端接口、不改 V4 确认 / 复核接口、不接真实 OPERA / OHIP、不废弃旧 V2/V3 任务入口、不把 S10/S99 来源通知放进订单列表。 +- 边界:本轮只扩展订单列表安全摘要字段,不改 V4 确认 / 复核接口、不接真实 OPERA / OHIP、不废弃旧 V2/V3 任务入口、不把 S10/S99 来源通知放进订单列表。 ## 2. 当前优先级 @@ -35,7 +35,7 @@ - 后续每完成一个 Feature 或 Checkpoint,需要更新本文件,避免项目状态继续沉淀在聊天记录里。 - M010 Rooming List Excel 生成后端 CP1 和前端 V1 已实现:前端 `/reservation/rooming-lists/new` 上传来源名单和手工字段,后端同步生成 `.xlsx` 直接下载,第一版不落库、不上传 OSS。 - M011 Booking Excel 附件预处理 CP1/CP2/CP3 已实现:后端可排除人员名单类 Excel,按最近 6 个月候选窗口选择实际存在的最新 3 个业务月,抽取 Booking Update / 附加费表高亮行业务 JSON;Debug EML 和 AgentBus dispatch 在各自 include 开关与总开关同时启用时,会在调用 SuperAgent 前追加 `attachment_extractions[]`。AgentBus 生产链路默认关闭,测试机验证后再评估开启。 -- M002 V4 CP1 当前已完成入站解析和现有任务链路过渡适配;M002 V4 CP2 已完成订单任务与多卡领域模型设计;M002 V4 CP3 已完成 V4 订单任务、多卡和 S10/S99 来源通知表结构与 Repository 基线;M002 V4 CP4 已完成入站写入新模型;M002 V4 CP5 已完成前端查询接口并补齐订单详情 `v4_order_tasks[]` 时间线;M002 V4 CP6 已完成普通卡片确认和 S10/S99 来源通知 ack;M002 V4 CP7 已完成 `REVIEW_REQUIRED` 卡复核解阻和复核场景订单归属确认;M002 V4 CP8 已完成目录校验、V4 卡片 `fields[]` 字段白名单、确认写入白名单收口和嵌套业务字段目录校验;M002 V4 CP11 已完成数据库目录、初始化种子、启动补种子、Account / Room Type / Rate Code lookup API,并把 V4 入站、确认、复核目录校验切换到当前酒店数据库目录;M002 V4 CP12 已完成前端 lookup 接入第一版和 V4 订单任务时间线消费;M002 V4 CP13 目录管理后台 CP1 已完成前后端列表、新增、启用 / 停用闭环;M002 V4 CP14 已完成订单列表 V4 继续处理入口字段和前端入口消费,`GET /api/reservation/orders` 返回 V4 下一步订单任务、卡片、动作类型、动作状态和 open 数,前端按 V4 优先、旧任务回退跳转。真实 PMS 同步和 SuperAgent 目录机器接口仍未完成。 +- M002 V4 CP1 当前已完成入站解析和现有任务链路过渡适配;M002 V4 CP2 已完成订单任务与多卡领域模型设计;M002 V4 CP3 已完成 V4 订单任务、多卡和 S10/S99 来源通知表结构与 Repository 基线;M002 V4 CP4 已完成入站写入新模型;M002 V4 CP5 已完成前端查询接口并补齐订单详情 `v4_order_tasks[]` 时间线;M002 V4 CP6 已完成普通卡片确认和 S10/S99 来源通知 ack;M002 V4 CP7 已完成 `REVIEW_REQUIRED` 卡复核解阻和复核场景订单归属确认;M002 V4 CP8 已完成目录校验、V4 卡片 `fields[]` 字段白名单、确认写入白名单收口和嵌套业务字段目录校验;M002 V4 CP11 已完成数据库目录、初始化种子、启动补种子、Account / Room Type / Rate Code lookup API,并把 V4 入站、确认、复核目录校验切换到当前酒店数据库目录;M002 V4 CP12 已完成前端 lookup 接入第一版和 V4 订单任务时间线消费;M002 V4 CP13 目录管理后台 CP1 已完成前后端列表、新增、启用 / 停用闭环;M002 V4 CP14 已完成订单列表 V4 继续处理入口字段和前端入口消费,`GET /api/reservation/orders` 返回 V4 下一步订单任务、卡片、动作类型、动作状态、V4 open 数和统一展示计数 `open_work_item_count`,前端按 V4 优先、旧任务回退跳转,并按 `open_work_item_count` 展示待处理数量。真实 PMS 同步和 SuperAgent 目录机器接口仍未完成。 - M002 V4 CP2 已确认:V4 工作台统一列表草案为 `/api/reservation/workbench-items`,业务订单任务接口新开 `/api/reservation/order-tasks/**`,S10/S99 来源通知详情草案为 `/api/reservation/source-notifications/{notificationId}`;S10/S99 使用来源通知模型,不再挂隐藏技术订单;`FIT + BOOKING_CODE` 不建 ACTIVE 唯一约束,匹配多条进人工复核;Basic Information 必须先确认;Account / Market / Source 当前通过数据库目录读取和派生;旧 V2/V3 任务详情和草稿确认接口后续可逐步废弃。 ## 5. Next Steps diff --git a/client/src/i18n/locales/en-US.ts b/client/src/i18n/locales/en-US.ts index a459cfe..50fb3f2 100644 --- a/client/src/i18n/locales/en-US.ts +++ b/client/src/i18n/locales/en-US.ts @@ -295,7 +295,7 @@ export default { columns: { order: 'Order', status: 'Status', - openTasks: 'Open tasks', + openTasks: 'Open work', createdAt: 'Created at', }, }, diff --git a/client/src/i18n/locales/th-TH.ts b/client/src/i18n/locales/th-TH.ts index a763646..8037d11 100644 --- a/client/src/i18n/locales/th-TH.ts +++ b/client/src/i18n/locales/th-TH.ts @@ -295,7 +295,7 @@ export default { columns: { order: 'ออเดอร์', status: 'สถานะ', - openTasks: 'งานที่ยังไม่ปิด', + openTasks: 'งานค้าง', createdAt: 'เวลาสร้าง', }, }, diff --git a/client/src/i18n/locales/zh-CN.ts b/client/src/i18n/locales/zh-CN.ts index bc60f72..ba65784 100644 --- a/client/src/i18n/locales/zh-CN.ts +++ b/client/src/i18n/locales/zh-CN.ts @@ -295,7 +295,7 @@ export default { columns: { order: '订单', status: '状态', - openTasks: '未关闭任务', + openTasks: '待处理', createdAt: '创建时间', }, }, diff --git a/client/src/tests/reservationService.spec.ts b/client/src/tests/reservationService.spec.ts index 346f09e..ba31da8 100644 --- a/client/src/tests/reservationService.spec.ts +++ b/client/src/tests/reservationService.spec.ts @@ -390,6 +390,7 @@ describe('reservationService real API mode', () => { group_code: 'GRP-001', display_name: 'GRP-001', open_task_count: 2, + open_work_item_count: 1, next_processable_task_id: '10002', next_v4_order_task_id: '9001', next_v4_action_card_id: '9101', @@ -420,6 +421,7 @@ describe('reservationService real API mode', () => { ) expect(result.items[0]?.display_order_key).toBe('GRP-001') expect(result.items[0]?.next_processable_task_id).toBe('10002') + expect(result.items[0]?.open_work_item_count).toBe(1) expect(result.items[0]?.next_v4_order_task_id).toBe('9001') expect(result.items[0]?.next_v4_action_type).toBe('REVIEW') expect(result.items[0]?.next_v4_action_status).toBe('REVIEW_REQUIRED') diff --git a/client/src/tests/reservationTaskDetailPanel.spec.ts b/client/src/tests/reservationTaskDetailPanel.spec.ts index 646fc79..d9d55b8 100644 --- a/client/src/tests/reservationTaskDetailPanel.spec.ts +++ b/client/src/tests/reservationTaskDetailPanel.spec.ts @@ -180,6 +180,7 @@ function createOrderCandidate(overrides: Partial = {}) group_code: 'GRP-001', display_name: 'GRP-001', open_task_count: 1, + open_work_item_count: 1, next_processable_task_id: null, created_at: '2026-07-08T03:00:00Z', updated_at: '2026-07-08T03:10:00Z', diff --git a/client/src/tests/reservationViews.spec.ts b/client/src/tests/reservationViews.spec.ts index 3055a9e..b66d3df 100644 --- a/client/src/tests/reservationViews.spec.ts +++ b/client/src/tests/reservationViews.spec.ts @@ -53,6 +53,7 @@ function createOrderListResult( group_code: displayOrderKey, display_name: displayOrderKey, open_task_count: 2, + open_work_item_count: 2, next_processable_task_id: '10002', created_at: '2026-07-08T03:00:00Z', updated_at: '2026-07-08T03:10:00Z', @@ -516,6 +517,29 @@ describe('reservation P0 views', () => { expect(wrapper.text()).not.toContain('接口待接入') }) + it('shows the backend unified open work item count in the order list', async () => { + vi.mocked(service.fetchReservationOrders).mockResolvedValue(createOrderListResult('GRP-001', { + page_num: 1, + page_size: 20, + total: 1, + }, { + open_task_count: 99, + v4_open_order_task_count: 88, + open_work_item_count: 3, + })) + + const wrapper = await mountWithPlugins(ReservationOrderListView) + await vi.dynamicImportSettled() + + const headers = wrapper.findAll('thead th').map((header) => header.text()) + const cells = wrapper.findAll('tbody td').map((cell) => cell.text()) + + expect(headers).toContain('待处理') + expect(cells[1]).toBe('3') + expect(cells[1]).not.toContain('99') + expect(cells[1]).not.toContain('88') + }) + it('routes continue action to the V4 order task when the backend returns next_v4_order_task_id', async () => { vi.mocked(service.fetchReservationOrders).mockResolvedValue(createOrderListResult('GRP-001', { page_num: 1, @@ -576,6 +600,7 @@ describe('reservation P0 views', () => { total: 1, }, { open_task_count: 0, + open_work_item_count: 0, next_processable_task_id: null, next_v4_order_task_id: null, next_v4_action_card_id: null, diff --git a/client/src/types/reservation.ts b/client/src/types/reservation.ts index 507969b..8c3fc7d 100644 --- a/client/src/types/reservation.ts +++ b/client/src/types/reservation.ts @@ -71,6 +71,7 @@ export interface ReservationOrderListItem { group_code: string | null display_name: string open_task_count: number | null + open_work_item_count: number | null next_processable_task_id: string | null next_v4_order_task_id?: string | null next_v4_action_card_id?: string | null diff --git a/client/src/views/reservation/ReservationOrderListView.vue b/client/src/views/reservation/ReservationOrderListView.vue index cfe22a4..3fc6107 100644 --- a/client/src/views/reservation/ReservationOrderListView.vue +++ b/client/src/views/reservation/ReservationOrderListView.vue @@ -108,6 +108,7 @@ {{ t('orderList.columns.order') }} + {{ t('orderList.columns.openTasks') }} {{ t('orderList.columns.createdAt') }} {{ t('workbench.columns.updatedAt') }} {{ t('workbench.columns.operation') }} @@ -121,6 +122,9 @@ {{ formatOrderKey(order) }} + + {{ formatOpenWorkItemCount(order) }} + {{ formatReservationDateTime(order.created_at) }} {{ formatReservationDateTime(order.updated_at) }} @@ -309,6 +313,13 @@ function formatOrderKey(order: ReservationOrderListItem): string { ) } +function formatOpenWorkItemCount(order: ReservationOrderListItem): string { + if (typeof order.open_work_item_count !== 'number') { + return '-' + } + return String(order.open_work_item_count) +} + function resolveContinueTarget(order: ReservationOrderListItem): string | null { if (order.next_v4_order_task_id) { return `/reservation/order-tasks/${order.next_v4_order_task_id}` @@ -476,6 +487,12 @@ td small { font-size: 12px; } +.open-count-cell { + color: var(--th-color-slate-900); + font-size: 15px; + font-weight: 800; +} + .row-actions { display: flex; flex-wrap: wrap; diff --git a/docs/project/frontend-backend/backend-to-frontend-notes.md b/docs/project/frontend-backend/backend-to-frontend-notes.md index cdff100..79a149d 100644 --- a/docs/project/frontend-backend/backend-to-frontend-notes.md +++ b/docs/project/frontend-backend/backend-to-frontend-notes.md @@ -52,7 +52,7 @@ | `POST /api/auth/login` | 用户名密码登录 | 成功后返回 `access_token`、当前用户、可访问酒店、权限码和可见菜单;token 只放 `sessionStorage`,不要放 `localStorage`、URL、日志或错误上报。 | | `GET /api/auth/me` | 恢复当前登录态 | 前端启动后带 `Authorization: Bearer ` 调用;401 时清理 token 并进入登录页。 | | `POST /api/auth/logout` | 登出当前 session | 带 `Authorization: Bearer `;成功后前端必须清理本地 token 和当前用户上下文。 | -| `GET /api/reservation/orders` | 查询订单列表 | 必须带 `Authorization: Bearer `,需要 `RESERVATION_ORDER_READ`;默认返回全部订单状态;按后端维护的订单最近业务活动时间倒序,当前落库字段为 `workflow_reservation_order.latest_activity_at`,前端不要自行重排;`open_task_count` 排除 `COMPLETED` 和 `FAILED`;已补齐 V4 继续处理入口字段,前端有 `next_v4_order_task_id` 时优先跳 V4 订单任务详情;隐藏技术订单不返回,因此 S10/S99 和旧 S000/S999 不会在订单列表形成订单。 | +| `GET /api/reservation/orders` | 查询订单列表 | 必须带 `Authorization: Bearer `,需要 `RESERVATION_ORDER_READ`;默认返回全部订单状态;按后端维护的订单最近业务活动时间倒序,当前落库字段为 `workflow_reservation_order.latest_activity_at`,前端不要自行重排;`open_work_item_count` 是订单列表统一待处理展示数量,前端订单列表已用它展示待处理数,第一版等于 V4 未完成订单任务数;`open_task_count` 仍保留为旧 V2/V3 诊断计数,排除 `COMPLETED` 和 `FAILED`;已补齐 V4 继续处理入口字段,前端有 `next_v4_order_task_id` 时优先跳 V4 订单任务详情;隐藏技术订单不返回,因此 S10/S99 和旧 S000/S999 不会在订单列表形成订单。 | | `GET /api/reservation/tasks` | 查询任务列表 / 工作台 | 必须带 Bearer token,需要 `RESERVATION_TASK_READ`;未传 `order_id` 时按来源消息接收时间倒序,传 `order_id` 时按同订单队列顺序正序;用 `can_process` 和 `readonly_reason_code` 控制入口按钮;列表不返回 AI 原始 payload、邮件正文或附件 URL;已返回来源邮件会话摘要字段,并支持 `order_status` 按任务所属订单状态筛选;旧 S000/S999 和 V3 S10/S99 以 `task_type=SOURCE_MESSAGE_ONLY` 只读任务返回,列表已透出 `result_type`、`ai_task_type`、`route_code`、`system_process_category`。V4 S10/S99 不再进入该旧任务表,应从 V4 工作台来源通知接口展示。 | | `GET /api/reservation/workbench-items` | 查询 V4 工作台统一列表 | 必须带 Bearer token,需要 `RESERVATION_TASK_READ`;返回 V4 业务订单任务和 S10/S99 来源通知混排摘要;支持 `hotel_id`、`item_type`、`keyword`、`page_num`、`page_size`;默认按 `source_received_at` 倒序,同一来源时间下按 `updated_at`、`created_at`、数字 `target_id` 倒序;列表不返回邮件正文、附件 URL、`ai_payload_json` 或来源通知原始 payload。 | | `GET /api/reservation/order-tasks` | 查询 V4 业务订单任务列表 | 必须带 Bearer token,需要 `RESERVATION_TASK_READ`;只返回 V4 业务订单任务,不包含 S10/S99 来源通知;支持 `hotel_id`、`order_id`、`order_task_status`、`card_status`、`keyword`、`page_num`、`page_size`;`order_task_status` 非 `OPEN` / `COMPLETED` 返回 400,`card_status` 非 V4 卡状态返回 400;`card_status` 只筛业务 / 可处理卡,固定来源邮件展示卡不参与筛选。 | @@ -101,7 +101,7 @@ | 接口 | 本轮变化 | 前端接入注意 | | --- | --- | --- | -| `GET /api/reservation/orders` | 补齐订单列表 V4 继续处理入口字段;前端已接入。 | `order_status` 不传时默认查询全部订单状态;`page_num` 从 1 开始;`page_size` 后端有最大值保护;`open_task_count` 排除 `COMPLETED` 和 `FAILED`;旧 `next_processable_task_id` 继续保留。V4 新增 `next_v4_order_task_id`、`next_v4_action_card_id`、`next_v4_action_type`、`next_v4_action_status`、`v4_open_order_task_count`;前端“继续处理”已按优先级实现:存在 `next_v4_order_task_id` 时跳 `/reservation/order-tasks/{next_v4_order_task_id}`,否则回退旧 `/reservation/tasks/{next_processable_task_id}`;两者都没有时展示无待处理状态。 | +| `GET /api/reservation/orders` | 补齐订单列表 V4 继续处理入口字段,并新增统一 open count 字段;前端展示已接入。 | `order_status` 不传时默认查询全部订单状态;`page_num` 从 1 开始;`page_size` 后端有最大值保护;`open_work_item_count` 是订单列表展示用统一待处理数量,开发阶段不考虑旧数据,第一版直接等于 `v4_open_order_task_count`;前端展示待处理数量时只读该字段,不自行计算旧任务数和 V4 数,也不使用旧 `open_task_count` 作为展示数量;旧 `open_task_count` 和 `next_processable_task_id` 继续保留用于 V2/V3 兼容与排查。V4 新增 `next_v4_order_task_id`、`next_v4_action_card_id`、`next_v4_action_type`、`next_v4_action_status`、`v4_open_order_task_count`;前端“继续处理”已按优先级实现:存在 `next_v4_order_task_id` 时跳 `/reservation/order-tasks/{next_v4_order_task_id}`,否则回退旧 `/reservation/tasks/{next_processable_task_id}`;两者都没有时展示无待处理状态。 | | `GET /api/reservation/tasks` | 补齐来源邮件会话摘要字段,并新增 `order_status` 查询参数。 | `order_status` 按任务所属订单状态过滤,支持 `TEMPORARY`、`ACTIVE`、`ENDED`、`LOGIC_DELETED`;列表仍然只返回安全摘要,不返回正文、HTML、附件 URL 或 AI 原始 payload;点击邮件入口时使用 `source_message_id` 调会话详情。 | | `GET /api/reservation/orders/{orderId}` | 补齐旧 `tasks[]` 来源邮件会话摘要字段,并新增 V4 `v4_order_tasks[]` 订单任务时间线。 | `include_tasks=false` 可只取订单摘要,此时 `tasks[]` 和 `v4_order_tasks[]` 都为空;旧 `tasks[]` 顺序由后端按订单队列返回,V4 `v4_order_tasks[]` 按 `source_received_at`、`source_message_id`、`order_context_index`、`created_at`、数字 ID 正序返回;前端不要自行重排。`include_source_summary` 第一版不作为前端裁剪字段的强约束,前端暂不要依赖它减少返回字段。 | | `GET /api/reservation/tasks/{taskId}` | 补齐顶层来源邮件字段,并扩展 `fields[]` 元数据。 | 顶层来源字段用于打开邮件会话;`fields[]` 中的 `result_type`、`task_type`、`task_subtype`、`default_value_source` 用于前端字段分组、调试和白名单对齐。 | @@ -181,7 +181,8 @@ POST /api/auth/logout - `GET /api/reservation/orders` 默认返回全部订单状态,包括 `TEMPORARY`、`ACTIVE`、`ENDED`、`LOGIC_DELETED`。 - `keyword` 会匹配订单业务号、临时订单号、展示名、订单状态,也会匹配来源消息安全摘要命中的 SourceMessage ID;前端可以用邮件主题、外部消息 ID 或会话 ID 辅助查订单。 -- `open_task_count` 只统计未关闭任务,排除 `COMPLETED` 和 `FAILED`。 +- `open_work_item_count` 是订单列表统一展示数量,第一版按 V4 未完成订单任务计算,即等于 `v4_open_order_task_count`;前端展示待处理数量时只使用它,不回退旧 `open_task_count`,也不要自行把旧任务数和 V4 数相加。 +- `open_task_count` 只统计旧 V2/V3 未关闭任务,排除 `COMPLETED` 和 `FAILED`,当前保留用于兼容和问题排查。 - `next_processable_task_id` 是后端按同订单队列实时计算出的下一条可处理任务;前端可以用它做“继续处理”入口。 - V4 订单任务入口字段由后端实时派生:`v4_open_order_task_count` 统计当前订单下 `order_task_status!=COMPLETED` 的 V4 订单任务;`next_v4_order_task_id` 是同订单第一条仍需用户处理的 V4 订单任务;`next_v4_action_card_id` 是该订单任务下第一张待处理卡;`next_v4_action_type` 取 `CONFIRM` / `REVIEW` / `NONE`;`next_v4_action_status` 取 `PENDING_CONFIRM` / `REVIEW_REQUIRED` 或空。 - V4 派生规则:Basic Information 必须优先于业务卡;Basic 已确认后,业务卡中 `REVIEW_REQUIRED` 优先于普通 `PENDING_CONFIRM`;`COMPLETED` 的 V4 订单任务不计入 open;S10/S99 来源通知不挂订单,不进入这些订单列表字段。 diff --git a/docs/project/frontend-backend/frontend-to-backend-api-requests.md b/docs/project/frontend-backend/frontend-to-backend-api-requests.md index 9c18e88..d2c315e 100644 --- a/docs/project/frontend-backend/frontend-to-backend-api-requests.md +++ b/docs/project/frontend-backend/frontend-to-backend-api-requests.md @@ -42,7 +42,7 @@ | `GET /api/source-messages` | 已完成安全摘要列表 | 可以 | 不能替代邮件会话全文接口。 | | `GET /api/source-messages/{id}` | 已完成单条安全摘要 | 可以 | 不能替代邮件会话全文接口。 | | `GET /api/source-messages/{id}/original` | 已完成单封原文权限读取 | 谨慎接入 | 必须带 Bearer token,需要同时拥有 `SOURCE_MESSAGE_READ` 和 `SOURCE_MESSAGE_ORIGINAL_READ`;只能读单封邮件,不能返回同一 conversation 全量邮件。 | -| `GET /api/reservation/orders` | 已完成第一版 | 可以 | 默认查询全部订单状态;`open_task_count` 排除 `COMPLETED` 和 `FAILED`。 | +| `GET /api/reservation/orders` | 已完成第一版 | 可以 | 默认查询全部订单状态;订单列表待处理展示使用 `open_work_item_count`;旧 `open_task_count` 仅作为 V2/V3 兼容诊断计数。 | | `GET /api/source-messages/{sourceMessageId}/conversation` | 已完成第一版,已补 `html_body_sanitized` 和 `html_render_mode` | 可以 | 必须带 Bearer token,需要同时拥有 `SOURCE_MESSAGE_READ` 和 `SOURCE_MESSAGE_ORIGINAL_READ`;返回完整 text/html、后端清洗后的 HTML、媒体外链和关联订单 / 任务摘要;前端不传原文读取 key,页面展示优先使用 `html_body_sanitized`。 | | `POST /api/system/reservation/demo-data` | 已完成 | 仅本地 / test 联调可用 | 默认关闭,必须后端配置访问口令;不能作为生产页面接口。 | | `POST /api/system/debug/eml-superagent-runs` | 已完成第一版 | 仅 dev/test Debug 页面可用 | 默认关闭,必须后端配置访问口令、阿里云 OSS 和 SuperAgent Open API;第一版只展示 SuperAgent 结果,不创建订单和任务;已能识别旧 S000/S999 和新结构化 S10/S99。 | @@ -279,7 +279,7 @@ GET /api/reservation/orders/{orderId} GET /api/reservation/orders ``` -当前状态:后端已完成第一版。默认查询全部订单状态;`open_task_count` 排除 `COMPLETED` 和 `FAILED`,`next_processable_task_id` 按旧 V2/V3 同订单队列可处理状态实时计算。M002 V4 CP14 已补齐 V4 继续处理入口字段,前端已按 `next_v4_order_task_id` 优先进入 V4 订单任务详情,并在无 V4 入口时回退旧任务详情。 +当前状态:后端已完成第一版。默认查询全部订单状态;`open_task_count` 排除旧 V2/V3 的 `COMPLETED` 和 `FAILED`,`next_processable_task_id` 按旧 V2/V3 同订单队列可处理状态实时计算。M002 V4 CP14 已补齐 V4 继续处理入口字段;后端新增 `open_work_item_count` 作为订单列表统一待处理展示数量,第一版直接等于 V4 未完成订单任务数,不叠加旧任务。前端已按 `next_v4_order_task_id` 优先进入 V4 订单任务详情,并在无 V4 入口时回退旧任务详情;订单列表待处理数量已改为只展示 `open_work_item_count`。 默认排序:按后端维护的订单最近业务活动时间倒序返回,保证最近有业务活动的订单排在前面。后端当前使用 `workflow_reservation_order.latest_activity_at` 作为排序字段,并在订单创建、任务创建、草稿保存、最终确认、人工复核解阻、任务状态变更等写路径维护;前端不要再基于任务时间或更新时间自行重排。 @@ -310,6 +310,7 @@ GET /api/reservation/orders "group_code": "GRP-001", "display_name": "GRP-001", "open_task_count": 2, + "open_work_item_count": 1, "next_processable_task_id": "10002", "next_v4_order_task_id": "30001", "next_v4_action_card_id": "31002", @@ -331,13 +332,14 @@ V4 继续处理字段说明: | 字段 | 说明 | | --- | --- | +| `open_work_item_count` | 订单列表统一待处理展示数量。第一版忽略旧数据,直接等于 `v4_open_order_task_count`;前端展示 open count 时只使用该字段,不回退旧 `open_task_count`,也不要自行相加。 | | `next_v4_order_task_id` | 当前订单下第一条仍需用户处理的 V4 订单任务 ID;为空表示没有 V4 待处理订单任务。 | | `next_v4_action_card_id` | `next_v4_order_task_id` 下第一张仍需确认或复核的卡片 ID。 | | `next_v4_action_type` | `CONFIRM` / `REVIEW` / `NONE`。`CONFIRM` 调卡片确认接口,`REVIEW` 调复核解阻接口。 | | `next_v4_action_status` | `PENDING_CONFIRM` / `REVIEW_REQUIRED`;`NONE` 时为空。 | | `v4_open_order_task_count` | 当前订单下未完成 V4 订单任务数,`COMPLETED` 不计入。 | -前端“继续处理”入口优先级:优先使用 `next_v4_order_task_id` 跳转 V4 订单任务详情;没有 V4 待处理时再使用旧 `next_processable_task_id` 跳旧任务详情;两者都没有时展示无待处理状态。S10/S99 来源通知不创建订单,不进入订单列表字段统计。 +前端“继续处理”入口优先级:优先使用 `next_v4_order_task_id` 跳转 V4 订单任务详情;没有 V4 待处理时再使用旧 `next_processable_task_id` 跳旧任务详情;两者都没有时展示无待处理状态。S10/S99 来源通知不创建订单,不进入订单列表字段统计。订单列表展示“待处理数量”时只使用 `open_work_item_count`,不使用旧 `open_task_count` 作为展示数量,也不在前端自行计算 `open_task_count + v4_open_order_task_count`;旧 `open_task_count` 和 `v4_open_order_task_count` 保留用于兼容与排查。 ## 6. 前端联调演示数据 seed 接口 diff --git a/docs/superpowers/plans/2026-07-20-order-list-open-work-count.md b/docs/superpowers/plans/2026-07-20-order-list-open-work-count.md new file mode 100644 index 0000000..5895d1f --- /dev/null +++ b/docs/superpowers/plans/2026-07-20-order-list-open-work-count.md @@ -0,0 +1,86 @@ +# Order List Open Work Count Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 订单列表待处理数量展示统一使用后端 `open_work_item_count`,不再使用旧 `open_task_count` 或前端自行相加。 + +**Architecture:** 类型层在订单列表 item 上补齐 `open_work_item_count`,页面层新增展示列和格式化 helper,只读取该统一字段。继续处理入口仍复用现有 V4 优先、旧任务回退 helper,不改变 V4 任务详情、任务列表或 S10/S99 来源通知逻辑。 + +**Tech Stack:** Vue 3, TypeScript, Vue Router, Vue I18n, Vitest, Vue Test Utils. + +## Global Constraints + +- 不改后端接口。 +- 不改 V4 订单任务详情页。 +- 不改任务列表。 +- 不改 S10/S99 来源通知逻辑。 +- 不在前端计算 `open_task_count + v4_open_order_task_count`。 +- 提交时不带入 `.idea`、`client/dist.zip`、后端代码或其他无关工作区改动。 + +--- + +### Task 1: Order List Uses Backend Unified Open Count + +**Files:** +- Modify: `client/src/types/reservation.ts` +- Modify: `client/src/views/reservation/ReservationOrderListView.vue` +- Modify: `client/src/tests/reservationViews.spec.ts` +- Modify: `client/src/tests/reservationService.spec.ts` +- Modify: `client/src/i18n/locales/zh-CN.ts` +- Modify: `client/src/i18n/locales/en-US.ts` +- Modify: `client/src/i18n/locales/th-TH.ts` + +**Interfaces:** +- Consumes: `ReservationOrderListItem.open_work_item_count?: number | null` +- Produces: 订单列表“待处理”列只展示 `open_work_item_count` + +- [x] **Step 1: Write failing view test** + +Add a case where `open_task_count=99`, `v4_open_order_task_count=88`, and `open_work_item_count=3`; assert the order row shows `3` under the open count column and does not show `99` or `88`. + +- [x] **Step 2: Verify red** + +Run `CI=true pnpm --dir client test -- reservationViews.spec.ts`. +Expected: FAIL because the current order list has no `open_work_item_count` display. + +- [x] **Step 3: Implement types and UI** + +Add `open_work_item_count` to `ReservationOrderListItem`. Add a “待处理 / Open work” column and render only `formatOpenWorkItemCount(order)`. + +- [x] **Step 4: Update service test** + +Add `open_work_item_count` to the order list service mock and assert the value is preserved. + +- [x] **Step 5: Verify green** + +Run `CI=true pnpm --dir client test -- reservationViews.spec.ts reservationService.spec.ts`. + +### Task 2: Documentation, Review, Verification, Commit + +**Files:** +- Modify: `PROJECT_STATE.md` +- Modify: `docs/project/frontend-backend/backend-to-frontend-notes.md` +- Modify: `docs/project/frontend-backend/frontend-to-backend-api-requests.md` + +**Interfaces:** +- Produces: 前端已改用 `open_work_item_count` 的状态说明 + +- [x] **Step 1: Update docs** + +Record that frontend order list display now uses `open_work_item_count` and no longer uses `open_task_count` as the displayed count. + +- [x] **Step 2: Run verification** + +Run: +- `CI=true pnpm --dir client lint` +- `CI=true pnpm --dir client typecheck` +- `CI=true pnpm --dir client test` +- `CI=true pnpm --dir client build` + +- [x] **Step 3: Code review** + +Review routing invariants, open count source, tests, docs, and staged files. + +- [x] **Step 4: Commit** + +Stage only related frontend/doc files and commit with a Chinese message.