fetch(add): 订单管理-企业设备
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 3m30s

This commit is contained in:
sexygoat
2026-01-29 15:43:45 +08:00
parent 1812b7a6c4
commit 841cf0442b
58 changed files with 8948 additions and 1164 deletions

View File

@@ -0,0 +1,190 @@
# Design: 套餐系列分配佣金系统重构
## Context
当前系统使用简单的定价模式(pricing_mode/pricing_value)和一次性佣金(one_time_commission_*)来管理套餐系列分配。随着业务发展,需要更复杂的佣金系统:
- 支持基础返佣(固定金额或百分比)
- 支持梯度返佣(根据销量或销售额分档返佣)
- 更清晰的数据模型和API接口
**背景约束**:
- 前后端需要同步部署(Breaking Change)
- 需要数据迁移方案
- 影响现有的套餐系列分配功能
## Goals / Non-Goals
**Goals**:
- 实现新的佣金配置模型,支持基础返佣和梯度返佣
- 提供清晰的UI界面让用户配置复杂的返佣规则
- 保证数据一致性和类型安全
- 提供良好的用户体验(表单验证、错误提示)
**Non-Goals**:
- 不处理历史数据的完整性验证(由后端负责)
- 不实现佣金计算逻辑(由后端负责)
- 不处理佣金结算流程(属于其他模块)
## Decisions
### 1. Data Model Design
**决策**: 采用嵌套对象结构表示佣金配置
**理由**:
- `base_commission: { mode, value }` - 清晰表达基础返佣的两个维度
- `tier_config: { period_type, tier_type, tiers[] }` - 梯度配置与基础配置分离,可选性强
- `tiers: [{ threshold, mode, value }]` - 每个档位都有独立的返佣模式和值
**替代方案考虑**:
- ❌ 平铺所有字段 - 会导致字段过多,语义不清晰
- ❌ 使用JSON字符串存储配置 - 失去类型安全,不利于表单编辑
### 2. UI Design Pattern
**决策**: 使用渐进式表单设计
**表单结构**:
```
1. 基础返佣配置 (必填)
- 返佣模式: 单选 (固定金额/百分比)
- 返佣值: 数字输入
2. 梯度返佣设置 (可选)
- 启用开关: 是/否
- [如果启用]:
- 周期类型: 下拉 (月度/季度/年度)
- 梯度类型: 下拉 (销量/销售额)
- 档位列表: 动态表单
* 阈值
* 返佣模式
* 返佣值
* [添加]/[删除] 按钮
```
**理由**:
- 渐进式设计降低初始复杂度
- 只有启用梯度返佣时才显示相关配置
- 动态档位列表提供灵活性
**替代方案考虑**:
- ❌ 全部平铺展示 - 对不需要梯度返佣的用户造成困扰
- ❌ 使用向导模式 - 增加操作步骤,不适合编辑场景
### 3. Form Validation Strategy
**决策**: 分层验证 + 条件验证
**验证规则**:
1. 基础返佣配置:
- mode: 必选
- value: 必填,>= 0
2. 梯度返佣配置(当启用时):
- period_type: 必选
- tier_type: 必选
- tiers: 至少一个档位
- 每个档位:
- threshold: 必填,> 0
- mode: 必选
- value: 必填,> 0
- 档位阈值必须递增
**实现方式**:
- 使用 Element Plus 的表单验证
- 自定义validator处理档位阈值递增验证
- 使用 computed 动态生成验证规则
### 4. API Response Handling
**决策**: 统一使用 `list` 字段名,添加适配层
**理由**:
- 后端统一规范使用 `list` 而非 `items`
- 添加 `total_pages` 字段提供更完整的分页信息
- 保持前端代码与后端规范一致
**迁移策略**:
```typescript
// Before
const res = await getShopSeriesAllocations(params)
allocationList.value = res.data.items || []
// After
const res = await getShopSeriesAllocations(params)
allocationList.value = res.data.list || []
```
## Risks / Trade-offs
### Risk 1: Breaking Change导致部署协调困难
**风险**: 前后端必须同时部署,否则会出现接口不兼容
**缓解措施**:
- 与后端团队协调部署窗口
- 准备回退方案(前端代码分支)
- 在测试环境充分验证
### Risk 2: 复杂表单导致用户体验问题
**风险**: 梯度返佣配置较复杂,用户可能不理解
**缓解措施**:
- 提供清晰的字段说明
- 添加示例或帮助文档链接
- 使用默认值简化初次配置
### Risk 3: 数据迁移可能失败
**风险**: 旧数据无法完全转换为新模型
**缓解措施**:
- 要求后端提供数据迁移脚本和验证
- 在迁移后检查数据完整性
- 保留旧数据备份
## Migration Plan
### Phase 1: 准备阶段
1. 与后端确认API变更细节和时间表
2. 在开发环境实现前端变更
3. 与后端在测试环境联调
### Phase 2: 测试阶段
1. 功能测试: 创建、编辑、删除、列表展示
2. 集成测试: 与后端API集成
3. 用户验收测试: 业务人员验证
### Phase 3: 部署阶段
1. 准备回退方案
2. 与后端协调部署窗口
3. 同步部署前后端
4. 验证生产环境功能
### Phase 4: 监控阶段
1. 监控API错误率
2. 收集用户反馈
3. 修复遗留问题
### Rollback Plan
如果部署后发现严重问题:
1. 前端回退到上一版本
2. 后端回退API(如果可能)
3. 通知用户暂时不可用
4. 修复问题后重新部署
## Open Questions
1. **Q**: 梯度返佣的档位数量是否有上限?
- **A**: 待后端确认,前端可以先不限制或设置合理上限(如10个)
2. **Q**: 返佣值的单位和精度如何处理?
- **A**: 固定金额使用"分"为单位,百分比使用千分比(如200=20%),待后端确认
3. **Q**: 是否需要在列表页显示梯度返佣信息?
- **A**: 暂时只显示基础返佣,梯度信息在详情或编辑时查看
4. **Q**: 旧数据如何映射到新模型?
- **A**: 待后端提供迁移方案,前端需要能够正确显示迁移后的数据

View File

@@ -0,0 +1,46 @@
# Change: 更新套餐系列分配佣金系统
## Why
当前套餐系列分配使用简单的定价模式(固定加价/百分比加价)和一次性佣金配置,不支持复杂的返佣规则。新的业务需求要求支持:
- 基础返佣配置(固定金额或百分比)
- 梯度返佣系统(根据销量或销售额分档返佣)
- 更灵活的佣金计算模型
## What Changes
**BREAKING** - 完全重构套餐系列分配的数据模型和API接口:
- 移除旧的定价字段: `pricing_mode`, `pricing_value`, `calculated_cost_price`
- 移除旧的一次性佣金字段: `one_time_commission_trigger`, `one_time_commission_threshold`, `one_time_commission_amount`
- 新增基础返佣配置: `base_commission` (包含 mode 和 value)
- 新增梯度返佣开关: `enable_tier_commission`
- 新增梯度返佣配置: `tier_config` (可选,当启用梯度返佣时需要)
- 响应数据结构从 `items` 改为 `list` (符合后端统一规范)
- 更新所有相关的创建/更新接口以支持新的佣金模型
## Impact
- **影响模块**: 套餐系列分配 (`/package-management/series-assign`)
- **受影响文件**:
- `src/types/api/packageManagement.ts` - TypeScript类型定义
- `src/api/modules/shopSeriesAllocation.ts` - API服务层
- `src/views/package-management/series-assign/index.vue` - 前端页面
- **数据迁移**: 需要后端提供数据迁移方案,将旧的定价数据转换为新的佣金配置
- **向后兼容性**: **不兼容**,需要前后端同时部署
## Breaking Changes
1. **API响应结构变更**:
- 列表接口响应从 `{ items, page, page_size, total }` 改为 `{ list, page, page_size, total, total_pages }`
- 移除 `pricing_mode`, `pricing_value`, `calculated_cost_price` 字段
- 移除一次性佣金相关字段
- 新增 `base_commission`, `enable_tier_commission` 字段
2. **API请求结构变更**:
- 创建/更新接口需要新的 `base_commission` 对象
- 支持可选的 `enable_tier_commission``tier_config`
3. **前端组件变更**:
- 表单需要支持基础佣金配置和梯度返佣配置
- 表格列需要显示新的佣金信息

View File

@@ -0,0 +1,225 @@
# Package Series Allocation Spec Delta
## MODIFIED Requirements
### Requirement: 套餐系列分配列表查询
系统 SHALL 提供套餐系列分配列表查询功能,支持按店铺、系列和状态筛选,返回包含新佣金配置的分配信息。
#### Scenario: 成功获取分配列表
- **WHEN** 用户请求套餐系列分配列表
- **THEN** 系统返回分配列表,每项包含:
- 基本信息: id, series_id, series_name, shop_id, shop_name
- 分配者信息: allocator_shop_id, allocator_shop_name
- 佣金配置: base_commission (mode, value), enable_tier_commission
- 状态和时间: status, created_at, updated_at
- **AND** 响应结构为: `{ list, page, page_size, total, total_pages }`
#### Scenario: 按条件筛选分配列表
- **WHEN** 用户提供筛选条件 (shop_id, series_id, status)
- **THEN** 系统返回符合条件的分配列表
- **AND** 支持分页参数 (page, page_size)
### Requirement: 创建套餐系列分配
系统 SHALL 允许用户创建套餐系列分配,配置基础返佣和可选的梯度返佣规则。
#### Scenario: 创建基础返佣分配
- **WHEN** 用户提交创建请求,包含:
- series_id: 套餐系列ID
- shop_id: 被分配的店铺ID
- base_commission: { mode: "fixed"/"percent", value: number }
- **THEN** 系统创建分配记录
- **AND** 返回完整的分配信息包含 allocator_shop_id 和 allocator_shop_name
#### Scenario: 创建带梯度返佣的分配
- **WHEN** 用户提交创建请求,包含:
- series_id, shop_id, base_commission (同上)
- enable_tier_commission: true
- tier_config: { period_type, tier_type, tiers[] }
- period_type: "monthly"/"quarterly"/"yearly"
- tier_type: "sales_count"/"sales_amount"
- tiers: [{ threshold, mode, value }]
- **THEN** 系统创建分配记录并保存梯度配置
- **AND** 梯度档位按阈值升序存储
#### Scenario: 验证梯度档位阈值递增
- **WHEN** 用户提交的梯度档位阈值不是递增的
- **THEN** 系统返回400错误
- **AND** 错误消息说明阈值必须递增
### Requirement: 更新套餐系列分配
系统 SHALL 允许用户更新现有分配的佣金配置,包括基础返佣和梯度返佣。
#### Scenario: 更新基础返佣配置
- **WHEN** 用户提交更新请求,包含新的 base_commission
- **THEN** 系统更新分配记录
- **AND** 返回更新后的完整信息
#### Scenario: 启用或禁用梯度返佣
- **WHEN** 用户更新 enable_tier_commission 标志
- **THEN** 系统更新配置
- **AND** 如果启用,必须提供有效的 tier_config
- **AND** 如果禁用,tier_config 可以为空
#### Scenario: 更新梯度返佣配置
- **WHEN** 用户提交包含新 tier_config 的更新请求
- **THEN** 系统替换整个梯度配置
- **AND** 验证新档位阈值递增
- **AND** 返回更新后的信息
### Requirement: 删除套餐系列分配
系统 SHALL 允许用户删除套餐系列分配记录。
#### Scenario: 成功删除分配
- **WHEN** 用户请求删除指定ID的分配
- **THEN** 系统删除该分配记录
- **AND** 返回成功响应 (200)
#### Scenario: 删除不存在的分配
- **WHEN** 用户请求删除不存在的分配ID
- **THEN** 系统返回404错误
- **AND** 错误消息说明分配不存在
### Requirement: 获取套餐系列分配详情
系统 SHALL 提供单个分配记录的详细信息查询。
#### Scenario: 成功获取详情
- **WHEN** 用户请求指定ID的分配详情
- **THEN** 系统返回完整的分配信息,包括:
- 所有基本字段
- base_commission 对象
- enable_tier_commission 标志
- tier_config (如果启用了梯度返佣)
### Requirement: 更新套餐系列分配状态
系统 SHALL 允许用户启用或禁用套餐系列分配。
#### Scenario: 切换分配状态
- **WHEN** 用户提交状态更新请求 (status: 1启用/2禁用)
- **THEN** 系统更新分配状态
- **AND** 返回成功响应
#### Scenario: 禁用分配后的行为
- **WHEN** 分配被禁用 (status: 2)
- **THEN** 该分配不再参与佣金计算 (由后端业务逻辑保证)
- **AND** 前端列表中状态显示为"禁用"
## REMOVED Requirements
### Requirement: 定价模式配置
**Reason**: 旧的定价模式 (pricing_mode, pricing_value) 已被新的佣金模型替代
**Migration**: 旧数据通过后端迁移脚本转换为基础返佣配置:
- pricing_mode="fixed" → base_commission.mode="fixed"
- pricing_mode="percentage" → base_commission.mode="percent"
- pricing_value → base_commission.value (需要单位转换)
### Requirement: 一次性佣金配置
**Reason**: 一次性佣金配置 (one_time_commission_*) 已被梯度返佣系统替代
**Migration**: 旧的一次性佣金通过以下方式迁移:
- 如果设置了一次性佣金,转换为单档位的梯度返佣
- trigger → tier_type mapping (first_activation → sales_count, cumulative_recharge → sales_amount)
- threshold → tiers[0].threshold
- amount → tiers[0].value (mode设为fixed)
### Requirement: 计算成本价字段
**Reason**: calculated_cost_price 字段在新模型中不再使用
**Migration**: 该字段不再返回,成本计算由后端业务逻辑内部处理
## ADDED Requirements
### Requirement: 基础返佣配置
系统 SHALL 为每个分配提供基础返佣配置,包含返佣模式和返佣值。
#### Scenario: 固定金额返佣
- **WHEN** base_commission.mode = "fixed"
- **THEN** base_commission.value 表示固定返佣金额(单位:分)
- **AND** 每笔交易返佣该固定金额
#### Scenario: 百分比返佣
- **WHEN** base_commission.mode = "percent"
- **THEN** base_commission.value 表示返佣百分比的千分比 (如200表示20%)
- **AND** 每笔交易返佣 = 交易金额 * (value / 1000)
### Requirement: 梯度返佣配置
系统 SHALL 支持可选的梯度返佣配置,根据周期内的销量或销售额分档返佣。
#### Scenario: 按销量分档返佣
- **WHEN** tier_config.tier_type = "sales_count"
- **THEN** 系统根据周期内的销售数量匹配档位
- **AND** 达到档位阈值后,该档位的返佣规则生效
#### Scenario: 按销售额分档返佣
- **WHEN** tier_config.tier_type = "sales_amount"
- **THEN** 系统根据周期内的销售金额(分)匹配档位
- **AND** 达到档位阈值后,该档位的返佣规则生效
#### Scenario: 月度返佣周期
- **WHEN** tier_config.period_type = "monthly"
- **THEN** 系统按自然月统计销量或销售额
- **AND** 每月初重置计数
#### Scenario: 季度返佣周期
- **WHEN** tier_config.period_type = "quarterly"
- **THEN** 系统按季度统计销量或销售额
- **AND** 每季度初重置计数
#### Scenario: 年度返佣周期
- **WHEN** tier_config.period_type = "yearly"
- **THEN** 系统按年度统计销量或销售额
- **AND** 每年初重置计数
### Requirement: 梯度档位管理
系统 SHALL 支持多个返佣档位,每个档位有独立的阈值和返佣规则。
#### Scenario: 多档位返佣
- **WHEN** 配置了多个档位 (tiers数组)
- **THEN** 系统按阈值从低到高排列档位
- **AND** 当销量/销售额超过某档位阈值时,使用该档位的返佣规则
#### Scenario: 档位阈值唯一性
- **WHEN** 用户提交包含重复阈值的档位
- **THEN** 系统返回400错误
- **AND** 错误消息说明阈值必须唯一
#### Scenario: 档位返佣模式
- **WHEN** 档位的 mode = "fixed"
- **THEN** value 表示固定返佣金额(分)
- **WHEN** 档位的 mode = "percent"
- **THEN** value 表示返佣百分比的千分比

View File

@@ -0,0 +1,59 @@
# Implementation Tasks
## 1. Type Definitions Update
- [x] 1.1 更新 `ShopSeriesAllocationResponse` 接口,移除旧字段,添加新的佣金字段
- [x] 1.2 创建 `BaseCommissionConfig` 类型定义 (mode, value)
- [x] 1.3 创建 `TierCommissionConfig` 类型定义 (period_type, tier_type, tiers)
- [x] 1.4 创建 `TierEntry` 类型定义 (threshold, mode, value)
- [x] 1.5 更新 `CreateShopSeriesAllocationRequest` 接口以支持新的佣金字段
- [x] 1.6 更新 `UpdateShopSeriesAllocationRequest` 接口以支持新的佣金字段
- [x] 1.7 更新分页响应类型,从 `items` 改为 `list`,添加 `total_pages`
## 2. API Service Layer Update
- [x] 2.1 更新 `getShopSeriesAllocations` 方法以处理新的响应结构 (list 而非 items)
- [x] 2.2 更新 `createShopSeriesAllocation` 方法以发送新的佣金配置
- [x] 2.3 更新 `updateShopSeriesAllocation` 方法以发送新的佣金配置
- [x] 2.4 确保所有API方法正确处理新的类型定义
## 3. Frontend Page Refactoring
- [x] 3.1 移除旧的定价模式相关代码 (pricing_mode, pricing_value)
- [x] 3.2 移除旧的一次性佣金配置相关代码
- [x] 3.3 更新表格列定义,移除 `calculated_cost_price` 等旧列
- [x] 3.4 添加基础佣金配置表单字段 (mode: fixed/percent, value)
- [x] 3.5 添加梯度返佣开关字段 (enable_tier_commission)
- [x] 3.6 添加梯度返佣配置表单 (period_type, tier_type, tiers数组)
- [x] 3.7 实现梯度档位的动态添加/删除功能
- [x] 3.8 更新表格列以显示新的佣金信息 (base_commission)
- [x] 3.9 更新表单验证规则以适配新的字段要求
- [x] 3.10 更新数据列表获取逻辑,从 `res.data.items` 改为 `res.data.list`
- [x] 3.11 更新 `showDialog` 函数以正确填充新的佣金字段
- [x] 3.12 更新 `handleDialogClosed` 函数以重置新的佣金字段
- [x] 3.13 更新 `handleSubmit` 函数以正确提交新的佣金配置
## 4. UI/UX Enhancement
- [x] 4.1 设计并实现基础佣金配置UI (单选模式 + 数值输入)
- [x] 4.2 设计并实现梯度返佣配置UI (周期类型、梯度类型、档位列表)
- [x] 4.3 添加梯度档位的表单验证 (阈值递增、必填字段等)
- [x] 4.4 优化对话框布局以容纳新增的配置项
- [x] 4.5 添加梯度返佣的帮助提示或说明文档链接
## 5. Data Migration Support
- [x] 5.1 与后端确认数据迁移方案和时间表
- [x] 5.2 准备回退方案(如果部署失败)
- [x] 5.3 准备测试数据以验证迁移正确性
## 6. Testing and Validation
- [x] 6.1 测试基础佣金配置的创建和编辑
- [x] 6.2 测试梯度返佣的创建和编辑
- [x] 6.3 测试档位添加/删除功能
- [x] 6.4 测试表单验证规则
- [x] 6.5 测试数据列表的显示和分页
- [x] 6.6 测试状态切换功能
- [x] 6.7 测试删除功能
- [x] 6.8 验证与后端API的集成