This commit is contained in:
136
openspec/changes/update-exchange-flow-direct-type/design.md
Normal file
136
openspec/changes/update-exchange-flow-direct-type/design.md
Normal file
@@ -0,0 +1,136 @@
|
||||
## Context
|
||||
|
||||
现有换货管理系统仅支持物流换货流程,包含:创建 → 待填写信息 → 待发货 → 已发货 → 已完成 五个阶段。部分场景下(如现场换货、远程换货等),不需要物流环节,直接完成换货即可。
|
||||
|
||||
后端已实现直接换货类型的数据库字段和 API 接口升级,前端需要适配新的接口规范和 UI 交互。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
### Goals
|
||||
|
||||
- 支持创建直接换货单,自动完成换货流程
|
||||
- 适配后端新增的 flow_type、shipped_at、completed_at 字段
|
||||
- 根据流程类型动态控制 UI 展示和操作权限
|
||||
- 保持向后兼容,历史数据正常展示
|
||||
|
||||
### Non-Goals
|
||||
|
||||
- 不涉及客户端换货接口改造
|
||||
- 不修改换货单状态定义
|
||||
- 不改变物流换货的原有流程逻辑
|
||||
|
||||
## Decisions
|
||||
|
||||
### 1. 流程类型枚举定义
|
||||
|
||||
```typescript
|
||||
export enum ExchangeFlowType {
|
||||
SHIPPING = 'shipping', // 物流换货
|
||||
DIRECT = 'direct' // 直接换货
|
||||
}
|
||||
|
||||
export const EXCHANGE_FLOW_TYPE_MAP = {
|
||||
[ExchangeFlowType.SHIPPING]: '物流换货',
|
||||
[ExchangeFlowType.DIRECT]: '直接换货'
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale**: 使用枚举统一管理流程类型,避免硬编码字符串,方便维护和扩展。
|
||||
|
||||
### 2. 创建表单的条件渲染
|
||||
|
||||
使用 `v-if` 根据选中的 flow_type 动态显示字段:
|
||||
|
||||
- flow_type = 'direct' 时,显示"新资产标识符"和"是否迁移数据"
|
||||
- flow_type = 'shipping' 时,隐藏这些字段
|
||||
|
||||
**Rationale**: 符合 Element Plus 表单最佳实践,避免不必要的字段提交。
|
||||
|
||||
**Alternatives considered**:
|
||||
- 使用 `v-show` 隐藏:会导致隐藏字段仍参与表单验证
|
||||
- 使用动态表单项:增加复杂度,不够直观
|
||||
|
||||
### 3. 详情页按钮权限控制
|
||||
|
||||
在详情页组件中定义计算属性:
|
||||
|
||||
```typescript
|
||||
const canShip = computed(() =>
|
||||
exchange.value.flow_type === 'shipping' && exchange.value.status === 2
|
||||
)
|
||||
|
||||
const canComplete = computed(() =>
|
||||
exchange.value.flow_type === 'shipping' && exchange.value.status === 3
|
||||
)
|
||||
|
||||
const canCancel = computed(() =>
|
||||
exchange.value.flow_type === 'shipping' && [1, 2].includes(exchange.value.status)
|
||||
)
|
||||
```
|
||||
|
||||
**Rationale**: 将权限逻辑集中在计算属性中,模板中直接使用 `v-if`,代码清晰且易于测试。
|
||||
|
||||
### 4. 信息区块隐藏策略
|
||||
|
||||
对于 direct 类型,收货信息和物流信息区块采用以下策略:
|
||||
|
||||
- **选择方案**: 使用 `v-if="exchange.flow_type === 'shipping'"` 完全隐藏
|
||||
- **原因**: direct 类型这些字段为 null,显示空白区块或"不适用"会造成页面冗余
|
||||
|
||||
**Alternatives considered**:
|
||||
- 显示"不适用"占位:增加不必要的视觉噪音
|
||||
- 显示空区块:用户体验不佳
|
||||
|
||||
### 5. API 错误处理
|
||||
|
||||
后端对不合法操作返回 400 错误,前端需要:
|
||||
|
||||
1. 在操作按钮级别根据 flow_type 和 status 做前置检查(优先)
|
||||
2. 对后端返回的错误消息直接展示(兜底)
|
||||
|
||||
**Rationale**: 前置检查提供更好的用户体验,后端错误处理作为安全兜底。
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk: 历史数据 flow_type 为空
|
||||
|
||||
**Mitigation**: 后端承诺 flow_type 为空时等同于 'shipping',前端在渲染时做兼容处理:
|
||||
|
||||
```typescript
|
||||
const flowType = exchange.flow_type || 'shipping'
|
||||
```
|
||||
|
||||
### Trade-off: UI 复杂度增加
|
||||
|
||||
引入流程类型后,详情页的条件渲染逻辑增多。
|
||||
|
||||
**Mitigation**:
|
||||
- 使用计算属性封装权限判断逻辑
|
||||
- 添加单元测试覆盖不同流程类型的渲染场景
|
||||
|
||||
## Migration Plan
|
||||
|
||||
### 阶段 1: API 类型升级(无破坏性)
|
||||
|
||||
- 更新 TypeScript 接口定义
|
||||
- 向后兼容,不影响现有调用
|
||||
|
||||
### 阶段 2: UI 适配(向后兼容)
|
||||
|
||||
- 列表页新增流程类型列和筛选
|
||||
- 详情页新增时间戳展示
|
||||
- 历史数据按 shipping 处理,正常显示
|
||||
|
||||
### 阶段 3: 创建功能升级(新增能力)
|
||||
|
||||
- 新增流程类型选择
|
||||
- 支持创建 direct 类型换货单
|
||||
|
||||
### 阶段 4: 测试与发布
|
||||
|
||||
- 功能测试、回归测试
|
||||
- 灰度发布,监控错误
|
||||
|
||||
## Open Questions
|
||||
|
||||
无
|
||||
@@ -0,0 +1,27 @@
|
||||
# Change: 换货流程升级 - 新增直接换货类型
|
||||
|
||||
## Why
|
||||
|
||||
现有换货流程仅支持物流换货(shipping),需要填写收货信息、发货、确认完成等多个步骤,流程较长。部分场景下需要支持直接换货(direct),即创建后立即完成,无需物流环节,提升换货效率。
|
||||
|
||||
## What Changes
|
||||
|
||||
- **新增** 换货流程类型(flow_type)字段,支持 `shipping`(物流换货)和 `direct`(直接换货)两种类型
|
||||
- **新增** 发货时间(shipped_at)和完成时间(completed_at)字段,用于记录换货流程关键时间节点
|
||||
- **修改** 创建换货单接口,支持选择流程类型和直接换货参数
|
||||
- **修改** 换货单列表接口,新增流程类型筛选和资产标识符模糊查询
|
||||
- **修改** 换货单详情接口,返回流程类型和时间戳信息
|
||||
- **修改** 发货、确认完成、取消换货接口,增加流程类型限制逻辑
|
||||
- **BREAKING** direct 类型换货单不支持发货、确认完成和取消操作
|
||||
- **BREAKING** 取消换货仅支持 shipping 流程且状态为待填写信息或待发货时
|
||||
|
||||
## Impact
|
||||
|
||||
- **Affected specs**: exchange-management(新建)
|
||||
- **Affected code**:
|
||||
- `src/api/modules/exchange.ts` - API 类型定义和接口调用
|
||||
- 换货单列表页面 - 新增流程类型列和筛选项
|
||||
- 换货单详情页面 - 根据流程类型控制按钮和信息区块显示
|
||||
- 创建换货单弹窗 - 新增流程类型选择和相关字段
|
||||
- **Database**: `tb_exchange_order` 表新增 `flow_type`、`shipped_at`、`completed_at` 字段
|
||||
- **API compatibility**: 向后兼容,历史数据 flow_type 为空时视为 shipping
|
||||
@@ -0,0 +1,199 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 换货流程类型支持
|
||||
|
||||
系统 SHALL 支持两种换货流程类型:物流换货(shipping)和直接换货(direct),用于满足不同场景下的换货需求。
|
||||
|
||||
#### Scenario: 创建物流换货单
|
||||
|
||||
- **WHEN** 用户选择"物流换货"类型创建换货单
|
||||
- **THEN** 换货单状态为"待填写信息"(status=1),flow_type 为 "shipping"
|
||||
- **AND** 需要后续填写收货信息、发货、确认完成等步骤
|
||||
|
||||
#### Scenario: 创建直接换货单
|
||||
|
||||
- **WHEN** 用户选择"直接换货"类型并填写新资产标识符创建换货单
|
||||
- **THEN** 换货单状态为"已完成"(status=4),flow_type 为 "direct"
|
||||
- **AND** completed_at 字段记录当前时间
|
||||
- **AND** 无需填写收货信息和发货流程
|
||||
|
||||
#### Scenario: 历史数据兼容
|
||||
|
||||
- **WHEN** 读取 flow_type 为空的历史换货单
|
||||
- **THEN** 系统应将其视为"物流换货"(shipping)类型
|
||||
- **AND** 按照物流换货流程展示和处理
|
||||
|
||||
### Requirement: 换货时间戳记录
|
||||
|
||||
系统 SHALL 记录换货流程中的关键时间节点,包括发货时间(shipped_at)和完成时间(completed_at)。
|
||||
|
||||
#### Scenario: 物流换货发货时间记录
|
||||
|
||||
- **WHEN** 物流换货单执行发货操作
|
||||
- **THEN** shipped_at 字段记录发货时间
|
||||
- **AND** 换货单状态变更为"已发货"(status=3)
|
||||
|
||||
#### Scenario: 物流换货完成时间记录
|
||||
|
||||
- **WHEN** 物流换货单确认完成
|
||||
- **THEN** completed_at 字段记录完成时间
|
||||
- **AND** 换货单状态变更为"已完成"(status=4)
|
||||
|
||||
#### Scenario: 直接换货完成时间记录
|
||||
|
||||
- **WHEN** 创建直接换货单
|
||||
- **THEN** completed_at 字段立即记录创建时间
|
||||
- **AND** shipped_at 字段为 null(无发货环节)
|
||||
|
||||
### Requirement: 创建换货单流程类型选择
|
||||
|
||||
用户在创建换货单时 SHALL 能够选择换货流程类型,并根据选择的类型填写相应的必填字段。
|
||||
|
||||
#### Scenario: 选择直接换货时必填新资产标识符
|
||||
|
||||
- **WHEN** 用户选择"直接换货"类型
|
||||
- **THEN** 表单必须显示"新资产标识符"输入框(必填)
|
||||
- **AND** 必须显示"是否迁移数据"开关(可选,默认 false)
|
||||
|
||||
#### Scenario: 选择物流换货时隐藏直接换货字段
|
||||
|
||||
- **WHEN** 用户选择"物流换货"类型
|
||||
- **THEN** 表单不显示"新资产标识符"和"是否迁移数据"字段
|
||||
- **AND** 仅需填写换货原因、旧资产类型和旧资产标识符
|
||||
|
||||
#### Scenario: 提交直接换货单参数
|
||||
|
||||
- **WHEN** 用户提交直接换货单
|
||||
- **THEN** 请求参数 MUST 包含 flow_type="direct"、new_identifier 和 migrate_data
|
||||
- **AND** 后端返回状态为"已完成"的换货单
|
||||
|
||||
### Requirement: 换货单列表流程类型筛选
|
||||
|
||||
用户在换货单列表页 SHALL 能够按流程类型筛选换货单,并查看流程类型信息。
|
||||
|
||||
#### Scenario: 显示流程类型列
|
||||
|
||||
- **WHEN** 用户查看换货单列表
|
||||
- **THEN** 列表 MUST 显示"流程类型"列
|
||||
- **AND** 该列显示"物流换货"或"直接换货"
|
||||
|
||||
#### Scenario: 按流程类型筛选
|
||||
|
||||
- **WHEN** 用户在筛选区选择流程类型(全部/物流换货/直接换货)
|
||||
- **THEN** 列表仅显示选中类型的换货单
|
||||
- **AND** 查询参数 flow_type 传递对应值(shipping/direct)
|
||||
|
||||
#### Scenario: 资产标识符模糊查询
|
||||
|
||||
- **WHEN** 用户输入资产标识符进行搜索
|
||||
- **THEN** 系统同时匹配旧资产标识符和新资产标识符
|
||||
- **AND** 返回所有匹配的换货单
|
||||
|
||||
### Requirement: 换货单详情流程类型展示
|
||||
|
||||
换货单详情页 SHALL 根据流程类型动态展示相关信息和时间戳。
|
||||
|
||||
#### Scenario: 显示流程类型和时间戳
|
||||
|
||||
- **WHEN** 用户查看换货单详情
|
||||
- **THEN** 详情页 MUST 显示"流程类型"字段(物流换货/直接换货)
|
||||
- **AND** 对于物流换货,显示"发货时间"(shipped_at,已发货后有值)
|
||||
- **AND** 对于所有已完成的换货单,显示"完成时间"(completed_at)
|
||||
|
||||
#### Scenario: 直接换货隐藏收货和物流信息
|
||||
|
||||
- **WHEN** 用户查看直接换货单详情
|
||||
- **THEN** 详情页不显示"收货信息"区块
|
||||
- **AND** 详情页不显示"物流信息"区块
|
||||
|
||||
#### Scenario: 物流换货正常显示所有信息
|
||||
|
||||
- **WHEN** 用户查看物流换货单详情
|
||||
- **THEN** 详情页显示"收货信息"区块(填写后有值)
|
||||
- **AND** 详情页显示"物流信息"区块(发货后有值)
|
||||
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: 换货单发货操作限制
|
||||
|
||||
系统 SHALL 仅允许物流换货单执行发货操作,直接换货单不支持发货。
|
||||
|
||||
**原有行为**: 所有状态为"待发货"的换货单均可执行发货操作。
|
||||
|
||||
**新行为**: 仅 flow_type="shipping" 且 status=2(待发货)的换货单可执行发货操作。
|
||||
|
||||
#### Scenario: 物流换货单可以发货
|
||||
|
||||
- **WHEN** 换货单 flow_type="shipping" 且 status=2
|
||||
- **THEN** 详情页显示"发货"按钮
|
||||
- **AND** 用户可以填写快递公司、快递单号等信息并提交
|
||||
|
||||
#### Scenario: 直接换货单不可发货
|
||||
|
||||
- **WHEN** 换货单 flow_type="direct"
|
||||
- **THEN** 详情页不显示"发货"按钮
|
||||
- **AND** 如果前端误调用发货接口,后端返回 400 错误:"流程类型不支持该操作"
|
||||
|
||||
#### Scenario: 前端阻止不合法发货操作
|
||||
|
||||
- **WHEN** 详情页加载换货单数据
|
||||
- **THEN** 前端根据 flow_type 和 status 判断是否显示"发货"按钮
|
||||
- **AND** 仅在 flow_type="shipping" 且 status=2 时显示
|
||||
|
||||
### Requirement: 换货单确认完成操作限制
|
||||
|
||||
系统 SHALL 仅允许物流换货单在已发货状态下执行确认完成操作,直接换货单自动完成。
|
||||
|
||||
**原有行为**: 状态为"已发货"的换货单可执行确认完成操作。
|
||||
|
||||
**新行为**: 仅 flow_type="shipping" 且 status=3(已发货)的换货单可执行确认完成操作。
|
||||
|
||||
#### Scenario: 物流换货单可以确认完成
|
||||
|
||||
- **WHEN** 换货单 flow_type="shipping" 且 status=3
|
||||
- **THEN** 详情页显示"确认完成"按钮
|
||||
- **AND** 用户点击后换货单状态变更为"已完成"
|
||||
|
||||
#### Scenario: 直接换货单不可确认完成
|
||||
|
||||
- **WHEN** 换货单 flow_type="direct"
|
||||
- **THEN** 详情页不显示"确认完成"按钮
|
||||
- **AND** 如果前端误调用完成接口,后端返回 400 错误
|
||||
|
||||
#### Scenario: 前端阻止不合法完成操作
|
||||
|
||||
- **WHEN** 详情页加载换货单数据
|
||||
- **THEN** 前端根据 flow_type 和 status 判断是否显示"确认完成"按钮
|
||||
- **AND** 仅在 flow_type="shipping" 且 status=3 时显示
|
||||
|
||||
### Requirement: 换货单取消操作限制
|
||||
|
||||
系统 SHALL 仅允许物流换货单在待填写信息或待发货状态下取消,直接换货单和已发货的物流换货单不可取消。
|
||||
|
||||
**原有行为**: 状态为"待填写信息"或"待发货"的换货单可取消。
|
||||
|
||||
**新行为**: 仅 flow_type="shipping" 且 status IN (1, 2) 的换货单可取消。
|
||||
|
||||
#### Scenario: 物流换货单待发货前可取消
|
||||
|
||||
- **WHEN** 换货单 flow_type="shipping" 且 status=1 或 status=2
|
||||
- **THEN** 详情页显示"取消"按钮
|
||||
- **AND** 用户可以取消换货单
|
||||
|
||||
#### Scenario: 物流换货单已发货后不可取消
|
||||
|
||||
- **WHEN** 换货单 flow_type="shipping" 且 status=3
|
||||
- **THEN** 详情页不显示"取消"按钮
|
||||
- **AND** 如果前端误调用取消接口,后端返回错误
|
||||
|
||||
#### Scenario: 直接换货单不可取消
|
||||
|
||||
- **WHEN** 换货单 flow_type="direct"
|
||||
- **THEN** 详情页不显示"取消"按钮
|
||||
- **AND** 如果前端误调用取消接口,后端返回 400 错误:"流程类型不支持该操作"
|
||||
|
||||
#### Scenario: 前端阻止不合法取消操作
|
||||
|
||||
- **WHEN** 详情页加载换货单数据
|
||||
- **THEN** 前端根据 flow_type 和 status 判断是否显示"取消"按钮
|
||||
- **AND** 仅在 flow_type="shipping" 且 status IN (1, 2) 时显示
|
||||
55
openspec/changes/update-exchange-flow-direct-type/tasks.md
Normal file
55
openspec/changes/update-exchange-flow-direct-type/tasks.md
Normal file
@@ -0,0 +1,55 @@
|
||||
## 1. API 类型定义更新
|
||||
|
||||
- [x] 1.1 更新 `ExchangeQueryParams` 接口,新增 `flow_type` 和 `identifier` 查询参数
|
||||
- [x] 1.2 更新 `CreateExchangeRequest` 接口,新增 `flow_type`、`new_identifier`、`migrate_data` 字段
|
||||
- [x] 1.3 更新 `ExchangeResponse` 接口,新增 `flow_type`、`flow_type_name`、`shipped_at`、`completed_at` 字段
|
||||
|
||||
## 2. 创建换货单功能
|
||||
|
||||
- [x] 2.1 更新创建换货单弹窗,新增流程类型选择器(单选:物流换货/直接换货)
|
||||
- [x] 2.2 实现流程类型切换逻辑,direct 时显示新资产标识符和数据迁移开关
|
||||
- [x] 2.3 更新表单验证规则,direct 时 new_identifier 必填
|
||||
- [x] 2.4 更新 API 调用,传递完整的创建参数
|
||||
|
||||
## 3. 换货单列表功能
|
||||
|
||||
- [x] 3.1 新增流程类型列,显示"物流换货"或"直接换货"
|
||||
- [x] 3.2 新增流程类型筛选下拉框(全部/物流换货/直接换货)
|
||||
- [x] 3.3 更新资产标识符搜索为模糊查询(同时匹配旧资产和新资产)
|
||||
- [x] 3.4 更新列表查询参数,支持 flow_type 和 identifier 筛选
|
||||
|
||||
## 4. 换货单详情功能
|
||||
|
||||
- [x] 4.1 新增流程类型展示字段(flow_type_name)
|
||||
- [x] 4.2 新增发货时间(shipped_at)和完成时间(completed_at)展示
|
||||
- [x] 4.3 根据 flow_type 控制操作按钮显示:
|
||||
- direct 类型隐藏"发货"、"确认完成"、"取消"按钮
|
||||
- shipping + status=1 仅显示"取消"
|
||||
- shipping + status=2 显示"发货"和"取消"
|
||||
- shipping + status=3 仅显示"确认完成"
|
||||
- [x] 4.4 根据 flow_type 控制信息区块显示:
|
||||
- direct 类型隐藏或标记"不适用"收货信息和物流信息区块
|
||||
|
||||
## 5. 发货功能
|
||||
|
||||
- [x] 5.1 在发货前检查 flow_type,仅允许 shipping 类型
|
||||
- [x] 5.2 对 direct 类型返回的 400 错误进行友好提示
|
||||
|
||||
## 6. 确认完成功能
|
||||
|
||||
- [x] 6.1 在确认完成前检查 flow_type,仅允许 shipping 且 status=3
|
||||
- [x] 6.2 对 direct 类型返回的错误进行友好提示
|
||||
|
||||
## 7. 取消换货功能
|
||||
|
||||
- [x] 7.1 在取消前检查 flow_type 和 status,仅允许 shipping 且 status 为 1 或 2
|
||||
- [x] 7.2 对不符合条件的操作返回友好提示
|
||||
|
||||
## 8. 测试与验证
|
||||
|
||||
- [ ] 8.1 测试创建物流换货单,验证原有流程正常
|
||||
- [ ] 8.2 测试创建直接换货单,验证自动完成逻辑
|
||||
- [ ] 8.3 测试列表筛选,验证 flow_type 和 identifier 查询正确
|
||||
- [ ] 8.4 测试详情页按钮和区块显示,验证不同流程类型的 UI 差异
|
||||
- [ ] 8.5 测试操作限制,验证 direct 类型不可发货、完成、取消
|
||||
- [ ] 8.6 测试历史数据兼容性,验证 flow_type 为空时视为 shipping
|
||||
Reference in New Issue
Block a user