fix: 换货
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 5m12s

This commit is contained in:
sexygoat
2026-06-03 17:53:19 +08:00
parent 3e6b3981f4
commit c5dae2993b
23 changed files with 797 additions and 10804 deletions

View 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

View File

@@ -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

View File

@@ -0,0 +1,199 @@
## ADDED Requirements
### Requirement: 换货流程类型支持
系统 SHALL 支持两种换货流程类型物流换货shipping和直接换货direct用于满足不同场景下的换货需求。
#### Scenario: 创建物流换货单
- **WHEN** 用户选择"物流换货"类型创建换货单
- **THEN** 换货单状态为"待填写信息"status=1flow_type 为 "shipping"
- **AND** 需要后续填写收货信息、发货、确认完成等步骤
#### Scenario: 创建直接换货单
- **WHEN** 用户选择"直接换货"类型并填写新资产标识符创建换货单
- **THEN** 换货单状态为"已完成"status=4flow_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) 时显示

View 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