From 044c07fae697d3a3152c0769ebe995aa1d6b9ba9 Mon Sep 17 00:00:00 2001 From: sexygoat <1538832180@qq.com> Date: Thu, 30 Apr 2026 10:39:51 +0800 Subject: [PATCH] fix: order --- .../design.md | 63 ++++++ .../proposal.md | 42 ++++ .../specs/order-management/spec.md | 66 ++++++ .../tasks.md | 28 +++ src/types/api/order.ts | 34 ++- .../enterprise-customer/index.vue | 18 +- .../enterprise-devices/index.vue | 1 - .../order-management/order-list/detail.vue | 133 ++++++++--- .../order-management/order-list/index.vue | 208 ++++++++---------- .../series-grants/index.vue | 2 +- 10 files changed, 437 insertions(+), 158 deletions(-) create mode 100644 openspec/changes/update-order-management-response-semantics/design.md create mode 100644 openspec/changes/update-order-management-response-semantics/proposal.md create mode 100644 openspec/changes/update-order-management-response-semantics/specs/order-management/spec.md create mode 100644 openspec/changes/update-order-management-response-semantics/tasks.md diff --git a/openspec/changes/update-order-management-response-semantics/design.md b/openspec/changes/update-order-management-response-semantics/design.md new file mode 100644 index 0000000..1086620 --- /dev/null +++ b/openspec/changes/update-order-management-response-semantics/design.md @@ -0,0 +1,63 @@ +# Design: 订单管理响应语义升级 + +## Context + +订单管理功能已经有初步页面和类型定义,但其实现建立在较早的接口语义上。最新后端返回已经把以下概念拆分清楚: + +- 操作者是谁 +- 订单业务归属到哪个销售店铺 +- 佣金流程走到哪一步 +- 佣金业务结果是什么 + +当前页面仍然把这些概念部分混用,导致 UI 语义不稳定,也容易让后续实现继续复制错误判断。 + +## Goals / Non-Goals + +- Goals: + - 让订单模块的类型定义、列表页、详情页统一按新语义工作 + - 消除对 `commission_status` 的错误业务推断 + - 在页面上明确区分“操作者”和“销售店铺” +- Non-Goals: + - 不改动 `purchase-check` 和 `cancel` 接口流程 + - 不改造后端返回结构 + - 不新增全新的订单业务流程 + +## Decisions + +- Decision: 在前端类型层面显式补齐新增字段,而不是通过 `any` 或临时属性兼容 + - Rationale: 这次变化的核心是语义纠偏。如果类型层继续缺字段,页面很容易回退到旧假设。 + +- Decision: 列表页必须同时呈现佣金流程状态和佣金业务结果,但不强制唯一 UI 形式 + - Rationale: `commission_status_name` 仅代表流程状态,`commission_result_name` 代表业务结果。无论是两列展示,还是“主状态 + 副标签”,都必须让用户能明确区分这两个维度。 + +- Decision: 详情页将“操作者信息”和“业务归属信息”拆成两组展示项 + - Rationale: 同一信息块内混放会继续强化旧认知,不利于用户理解订单责任归属。 + +- Decision: 所有“是否有佣金”的判断必须同时参考 `commission_status` 与 `commission_result` + - Rationale: 后端已经把流程状态和业务结果拆开,单独读取 `commission_status` 会产生错误结论。 + +## Risks / Trade-offs + +- 风险: 订单模块以外可能也有复用订单类型或字段语义的代码。 + - Mitigation: 实施前使用全局搜索盘点 `operator_name`、`commission_status`、`commission_result` 的相关用法。 + +- 风险: 列表新增列后表格宽度会增加。 + - Mitigation: 优先保留关键列,可通过列宽、固定列或列配置能力控制首屏拥挤度。 + +## Migration Plan + +1. 先调整订单类型定义和展示 helper,建立统一语义基础。 +2. 再修改订单列表页,确保两类状态与店铺信息展示正确。 +3. 最后修改详情页,把操作者信息和业务归属信息拆开。 +4. 通过接口联调样例验证典型场景: + - 平台订单返回 `operator_name = admin` + - 已完成且有佣金 + - 已完成但无佣金 + - 链路异常待人工处理 + +## Open Questions + +- 订单列表中的佣金信息最终采用哪种视觉结构更合适: + - 两列展示 + - 主状态 + 副标签 + - 只要能同时表达“流程状态”和“业务结果”,两种方案都符合本次提案范围 diff --git a/openspec/changes/update-order-management-response-semantics/proposal.md b/openspec/changes/update-order-management-response-semantics/proposal.md new file mode 100644 index 0000000..aadc672 --- /dev/null +++ b/openspec/changes/update-order-management-response-semantics/proposal.md @@ -0,0 +1,42 @@ +# Change: 更新订单管理响应语义与展示规则 + +## Why + +订单管理页面已经接入 `/api/admin/orders` 相关接口,但当前前端实现仍带有旧语义假设: + +- `operator_*` 在部分场景被当成代理店铺信息理解和展示。 +- `commission_status` 仍被当成“是否有佣金”的单一结果使用。 +- 订单列表和详情页没有显式表达“真实操作者”和“业务归属店铺”的区别。 + +后端最新 `OrderResponse` 已经明确拆分了这些概念,并新增了 `seller_shop_*` 与 `commission_result*` 字段。如果前端不跟进,用户会在订单列表和详情页看到混淆信息,且“已完成但无佣金”和“已完成且有佣金”无法被正确区分。 + +## What Changes + +- 更新订单管理前端对 `OrderResponse` 的类型定义和字段语义解释: + - `operator_*` 统一表示真实操作者 + - `seller_shop_*` 统一表示业务归属店铺 + - `commission_status` 统一表示佣金流程状态 + - `commission_result` 统一表示佣金业务结果 +- 更新订单列表页展示规则: + - 增加“销售店铺/归属店铺”展示 + - 佣金信息必须同时呈现“流程状态”和“业务结果”两个维度 + - 具体呈现形式可以是两列,或“主状态 + 副标签” +- 更新订单详情页信息结构: + - 单独展示操作者信息 + - 单独展示业务归属信息 +- 对齐创建订单成功后的响应处理,避免继续使用旧语义做前端判断 + +## Impact + +- Affected specs: + - `order-management` +- Affected code: + - `src/types/api/order.ts` + - `src/api/modules/order.ts` + - `src/views/order-management/order-list/index.vue` + - `src/views/order-management/order-list/detail.vue` +- Dependencies: + - 依赖后端已提供最新 `OrderResponse` 字段和语义 + - 与活跃变更 `add-order-management`、`update-order-upload-and-device-switch-mode` 属于同一能力域,落地时需要一起核对订单模块现状 +- Breaking changes: + - 前端内部对订单字段的解释逻辑会变化;任何把 `operator_name` 当店铺名、把 `commission_status` 当佣金结果的代码都需要调整 diff --git a/openspec/changes/update-order-management-response-semantics/specs/order-management/spec.md b/openspec/changes/update-order-management-response-semantics/specs/order-management/spec.md new file mode 100644 index 0000000..fe42e95 --- /dev/null +++ b/openspec/changes/update-order-management-response-semantics/specs/order-management/spec.md @@ -0,0 +1,66 @@ +## ADDED Requirements + +### Requirement: Updated Order Response Semantics + +The system SHALL interpret the latest `OrderResponse` fields consistently across order creation, order list, and order detail experiences. + +#### Scenario: Order response fields are typed and understood by new semantics + +- **GIVEN** 前端接收到 `POST /api/admin/orders`、`GET /api/admin/orders` 或 `GET /api/admin/orders/:id` 返回的 `OrderResponse` +- **WHEN** 前端解析订单对象 +- **THEN** `operator_*` MUST 被解释为真实操作者信息 +- **AND** `seller_shop_*` MUST 被解释为订单业务归属店铺信息 +- **AND** `commission_status` MUST 被解释为佣金流程状态 +- **AND** `commission_result` MUST 被解释为佣金业务结果 + +#### Scenario: Created order response follows the same semantics + +- **GIVEN** 用户成功调用 `POST /api/admin/orders` 创建订单 +- **WHEN** 前端处理创建成功后返回的订单对象 +- **THEN** 系统 MUST 按最新 `OrderResponse` 语义解析新增字段和语义变更字段 +- **AND** 系统 MUST NOT 仅根据 `commission_status` 推断该订单“有佣金” + +### Requirement: Order List Must Distinguish Operator, Shop, and Commission Result + +The system SHALL display order list data in a way that distinguishes real operator identity, seller shop ownership, commission workflow status, and commission business result. + +#### Scenario: Order list shows operator and seller shop separately + +- **GIVEN** 用户正在查看后台订单列表 +- **WHEN** 某条订单同时存在 `operator_name` 和 `seller_shop_name` +- **THEN** 系统 MUST 将“操作者”展示为 `operator_name` +- **AND** 系统 MUST 将“销售店铺”或“归属店铺”展示为 `seller_shop_name` +- **AND** 系统 MUST NOT 把 `operator_name` 当成店铺名称展示 + +#### Scenario: Order list distinguishes workflow status from business result + +- **GIVEN** 用户正在查看后台订单列表 +- **WHEN** 某条订单返回 `commission_status_name` 与 `commission_result_name` +- **THEN** 系统 MUST 让用户同时看到佣金流程状态和佣金业务结果 +- **AND** 系统 MAY 通过两列展示,或通过“主状态 + 副标签”展示 +- **AND** “已完成且有佣金”与“已完成但无佣金” MUST 可被明确区分 +- **AND** “链路异常待人工处理” MUST 可被明确区分 + +### Requirement: Order Detail Must Separate Operator Info from Seller Shop Info + +The system SHALL structure order detail views so that operator identity and seller shop ownership are displayed as separate concepts. + +#### Scenario: Order detail splits operator and ownership information + +- **GIVEN** 用户正在查看后台订单详情 +- **WHEN** 订单详情返回 `operator_id`、`operator_type`、`operator_name`、`seller_shop_id` 与 `seller_shop_name` +- **THEN** 系统 MUST 单独展示操作者信息 +- **AND** 系统 MUST 单独展示业务归属信息 +- **AND** 页面 MUST 让用户明确区分“谁发起下单”和“订单归属哪个销售店铺” + +### Requirement: Commission Presence Must Not Be Inferred from Workflow Status Alone + +The system SHALL avoid inferring commission presence from `commission_status` alone. + +#### Scenario: Completed order still requires commission result to determine outcome + +- **GIVEN** 某条订单的 `commission_status = 2` +- **WHEN** 前端需要判断该订单是否“有佣金” +- **THEN** 系统 MUST 继续读取 `commission_result` +- **AND** 仅当 `commission_status = 2` 且 `commission_result = 1` 时,系统才可判定为“有佣金” +- **AND** 当 `commission_status = 2` 且 `commission_result = 2` 时,系统 MUST 判定为“无佣金” diff --git a/openspec/changes/update-order-management-response-semantics/tasks.md b/openspec/changes/update-order-management-response-semantics/tasks.md new file mode 100644 index 0000000..42c729a --- /dev/null +++ b/openspec/changes/update-order-management-response-semantics/tasks.md @@ -0,0 +1,28 @@ +## 1. 类型与语义对齐 + +- [x] 1.1 更新 `src/types/api/order.ts`,补齐 `seller_shop_*`、`commission_result*`、`operator_id`、`operator_type` 等字段定义。 +- [x] 1.2 更新订单相关枚举和注释,明确 `commission_status` 是流程状态,`commission_result` 是业务结果。 +- [x] 1.3 盘点订单模块中仍按旧语义使用 `operator_*` 或 `commission_status` 的逻辑。 + +## 2. 列表页改造 + +- [x] 2.1 更新订单列表列配置,单独展示“操作者”和“销售店铺/归属店铺”。 +- [x] 2.2 调整列表中的佣金展示,确保用户能同时看到“流程状态”和“业务结果”两个维度。 +- [x] 2.3 修正任何基于 `commission_status === 2` 推导“有佣金”的旧判断。 + +## 3. 详情页改造 + +- [x] 3.1 调整订单详情信息结构,新增“操作者信息”展示块。 +- [x] 3.2 调整订单详情信息结构,新增“业务归属信息”展示块。 +- [x] 3.3 在详情页显式展示佣金流程状态和佣金业务结果。 + +## 4. 创建订单响应处理 + +- [x] 4.1 对齐 `POST /api/admin/orders` 返回的 `OrderResponse` 类型。 +- [x] 4.2 检查创建成功后的前端处理,确保不再基于旧佣金语义做推断。 + +## 5. 验证 + +- [x] 5.1 验证订单列表能够区分“已完成且有佣金”和“已完成但无佣金”。 +- [x] 5.2 验证订单详情能够区分“操作者”和“销售店铺”。 +- [x] 5.3 运行 `openspec.cmd validate update-order-management-response-semantics --strict`。 diff --git a/src/types/api/order.ts b/src/types/api/order.ts index 85014b6..654a5f9 100644 --- a/src/types/api/order.ts +++ b/src/types/api/order.ts @@ -19,11 +19,22 @@ export type BuyerType = 'personal' | 'agent' // 订单支付方式 export type OrderPaymentMethod = 'wallet' | 'wechat' | 'alipay' | 'offline' -// 订单佣金状态 +// 订单操作者类型 +export type OrderOperatorType = 'platform' | 'agent' | 'enterprise' | 'personal_customer' + +// 订单佣金流程状态 export enum OrderCommissionStatus { - NOT_APPLICABLE = 0, // 不适用 - PENDING = 1, // 待结算 - SETTLED = 2 // 已结算 + PENDING = 1, // 待计算 + COMPLETED = 2, // 已完成 + MANUAL_REVIEW = 3 // 待人工处理 +} + +// 订单佣金业务结果 +export enum OrderCommissionResult { + UNKNOWN = 0, // 未知 + HAS_COMMISSION = 1, // 有佣金 + NO_COMMISSION = 2, // 无佣金 + LINK_EXCEPTION = 3 // 链路异常 } // 订单明细 @@ -52,8 +63,10 @@ export interface Order { total_amount: number // 订单总金额(分) actual_paid_amount?: number // 实付金额(分) paid_at: string | null - commission_status: OrderCommissionStatus - commission_status_name?: string // 佣金状态名称(中文) + commission_status: OrderCommissionStatus // 佣金流程状态 + commission_status_name?: string // 佣金流程状态名称(中文) + commission_result?: OrderCommissionResult // 佣金业务结果 + commission_result_name?: string // 佣金业务结果名称(中文) commission_config_version: number device_id: number | null iot_card_id: number | null @@ -61,7 +74,14 @@ export interface Order { asset_type?: string // 资产类型:single_card 或 device purchase_role?: string // 订单渠道 purchase_remark?: string // 购买备注 - operator_name?: string // 操作者 + is_purchased_by_parent?: boolean // 是否由上级代购 + is_expired?: boolean // 是否已过期 + expires_at?: string | null // 订单超时时间 + operator_id?: number | null // 真实操作者ID + operator_type?: OrderOperatorType // 真实操作者类型 + operator_name?: string // 真实操作者名称 + seller_shop_id?: number | null // 销售店铺ID + seller_shop_name?: string // 销售店铺名称 items: OrderItem[] | null payment_voucher_key?: string // 支付凭证(线下支付时才有值) created_at: string diff --git a/src/views/account-management/enterprise-customer/index.vue b/src/views/account-management/enterprise-customer/index.vue index fd3b477..8ecfbb4 100644 --- a/src/views/account-management/enterprise-customer/index.vue +++ b/src/views/account-management/enterprise-customer/index.vue @@ -112,6 +112,8 @@ filterable clearable style="width: 100%" + @focus="handleOwnerShopFocus" + @visible-change="handleOwnerShopVisibleChange" @change="handleShopChange" /> @@ -530,10 +532,6 @@ onMounted(() => { getTableData() - // 只有非代理账号才需要加载店铺列表 - if (!isAgentAccount.value) { - loadShopList() - } }) onActivated(() => { @@ -542,6 +540,8 @@ // 加载店铺列表 - 改用级联查询 const loadShopList = async () => { + if (shopLoading.value) return + shopLoading.value = true try { const res = await ShopService.getShopsCascade({ parent_id: undefined }) @@ -559,6 +559,16 @@ } } + const handleOwnerShopFocus = async () => { + if (isAgentAccount.value) return + await loadShopList() + } + + const handleOwnerShopVisibleChange = async (visible: boolean) => { + if (!visible) return + await handleOwnerShopFocus() + } + // 处理店铺选择变化 const handleShopChange = (value: any) => { if (Array.isArray(value) && value.length > 0) { diff --git a/src/views/asset-management/enterprise-devices/index.vue b/src/views/asset-management/enterprise-devices/index.vue index deb71ff..e6d64fc 100644 --- a/src/views/asset-management/enterprise-devices/index.vue +++ b/src/views/asset-management/enterprise-devices/index.vue @@ -178,7 +178,6 @@ 已授权设备 -