fetch(add): 订单管理-企业设备
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 3m30s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 3m30s
This commit is contained in:
332
openspec/changes/add-package-management-system/design.md
Normal file
332
openspec/changes/add-package-management-system/design.md
Normal file
@@ -0,0 +1,332 @@
|
||||
# Design Document: 套餐管理系统实现
|
||||
|
||||
## Context
|
||||
|
||||
实现完整的套餐管理系统,包括4个核心模块。该系统需要支持多级代理商体系的套餐分配和定价管理。
|
||||
|
||||
**背景**:
|
||||
- 项目已有类型定义(src/types/api/package.ts),但使用不同的字段命名和枚举值
|
||||
- 后端 API 已实现,使用下划线命名(如 `series_name`)
|
||||
- 前端项目统一使用 CommonStatus 枚举(0:禁用, 1:启用)
|
||||
- 参考实现:`/system/role` 页面使用了组件化架构
|
||||
|
||||
**约束**:
|
||||
- 必须保留现有类型定义文件,不能破坏现有代码
|
||||
- 需要兼容后端 API 的字段命名规范
|
||||
- 需要适配项目的状态枚举规范
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
### Goals
|
||||
1. 实现4个核心模块的完整 CRUD 功能
|
||||
2. 建立统一的 API 服务层,封装后端接口
|
||||
3. 实现组件化的页面结构,参考 `/system/role`
|
||||
4. 支持复杂的定价规则(系列加价 vs 单套餐覆盖)
|
||||
5. 确保数据隔离和权限控制
|
||||
|
||||
### Non-Goals
|
||||
1. 不重构现有的 package.ts 类型定义
|
||||
2. 不实现套餐的实时统计和报表功能(后续迭代)
|
||||
3. 不实现套餐批量导入功能(后续迭代)
|
||||
4. 不实现套餐的版本管理功能
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: API 字段命名策略
|
||||
|
||||
**问题**:后端使用下划线命名(snake_case),前端类型通常使用驼峰命名(camelCase)。
|
||||
|
||||
**决策**:
|
||||
- API 请求/响应保持下划线命名,与后端保持一致
|
||||
- 创建新的类型文件 `packageManagement.ts`,使用下划线命名
|
||||
- 在表单提交和响应处理时不做转换,直接使用下划线字段
|
||||
|
||||
**理由**:
|
||||
- 减少转换层的复杂性和错误风险
|
||||
- 与后端 API 文档保持一致,便于对照
|
||||
- TypeScript 支持下划线字段名,不影响类型安全
|
||||
|
||||
**示例**:
|
||||
```typescript
|
||||
export interface PackageSeriesResponse {
|
||||
id: number
|
||||
series_code: string // 下划线命名
|
||||
series_name: string
|
||||
status: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
```
|
||||
|
||||
### Decision 2: 状态值映射
|
||||
|
||||
**问题**:文档中状态是 `1:启用, 2:禁用`,但项目 CommonStatus 是 `0:禁用, 1:启用`。
|
||||
|
||||
**决策**:
|
||||
- **在常量配置中定义套餐专用的状态枚举**
|
||||
- **前端页面使用项目统一的 CommonStatus(0/1)**
|
||||
- **在 API 服务层进行状态值映射转换**
|
||||
|
||||
**映射规则**:
|
||||
```typescript
|
||||
// 前端 -> 后端
|
||||
CommonStatus.ENABLED (1) -> API Status (1)
|
||||
CommonStatus.DISABLED (0) -> API Status (2)
|
||||
|
||||
// 后端 -> 前端
|
||||
API Status (1) -> CommonStatus.ENABLED (1)
|
||||
API Status (2) -> CommonStatus.DISABLED (0)
|
||||
```
|
||||
|
||||
**理由**:
|
||||
- 保持前端 UI 的一致性
|
||||
- 避免混淆项目开发者
|
||||
- 集中在 API 服务层处理差异
|
||||
|
||||
### Decision 3: 模块拆分策略
|
||||
|
||||
**问题**:是创建单个 package.ts 服务,还是拆分为多个服务文件?
|
||||
|
||||
**决策**:拆分为4个独立的服务文件:
|
||||
1. `packageSeries.ts` - 套餐系列管理
|
||||
2. `package.ts` - 套餐管理
|
||||
3. `myPackage.ts` - 代理可售套餐
|
||||
4. `shopPackageAllocation.ts` - 单套餐分配
|
||||
|
||||
**理由**:
|
||||
- 每个模块功能独立,职责清晰
|
||||
- 便于维护和扩展
|
||||
- 符合单一职责原则
|
||||
- 便于团队协作(不同开发者负责不同模块)
|
||||
|
||||
**替代方案**:
|
||||
- 单个 package.ts 文件 - **拒绝**,文件过大,难以维护
|
||||
|
||||
### Decision 4: 定价规则实现
|
||||
|
||||
**问题**:代理商的套餐成本价有两种计算方式:系列加价和单套餐覆盖。
|
||||
|
||||
**决策**:
|
||||
- **后端负责成本价计算**,前端只展示结果
|
||||
- 前端接收 `price_source` 字段,标识价格来源
|
||||
- 单套餐分配创建时,保存 `calculated_cost_price`(系列规则计算的价格)供参考
|
||||
|
||||
**数据流**:
|
||||
```
|
||||
1. 系列分配:pricing_mode + pricing_value -> 后端计算 -> cost_price
|
||||
2. 单套餐分配:直接设置 cost_price(覆盖系列规则)
|
||||
3. 前端展示:price_source 标识使用了哪种规则
|
||||
```
|
||||
|
||||
**理由**:
|
||||
- 计算逻辑复杂,集中在后端便于维护
|
||||
- 前端只负责展示,降低复杂度
|
||||
- 保留 calculated_cost_price 便于调试和审计
|
||||
|
||||
### Decision 5: 表单验证策略
|
||||
|
||||
**问题**:客户端验证 vs 服务端验证。
|
||||
|
||||
**决策**:**双重验证**
|
||||
- 客户端:使用 Element Plus 的 FormRules 进行基础验证
|
||||
- 服务端:后端 API 进行完整验证并返回详细错误
|
||||
|
||||
**客户端验证规则**:
|
||||
- 必填字段检查
|
||||
- 长度限制(如系列名称 1-255 字符)
|
||||
- 数值范围(如套餐时长 1-120 月)
|
||||
- 格式验证(如价格必须为正整数)
|
||||
|
||||
**理由**:
|
||||
- 客户端验证提升用户体验,即时反馈
|
||||
- 服务端验证保证数据安全性和完整性
|
||||
- 符合 Web 应用最佳实践
|
||||
|
||||
### Decision 6: 页面组件化结构
|
||||
|
||||
**问题**:页面结构如何组织?
|
||||
|
||||
**决策**:参考 `/system/role` 页面,使用组件化结构:
|
||||
```vue
|
||||
<template>
|
||||
<ArtTableFullScreen>
|
||||
<ArtSearchBar /> <!-- 搜索栏 -->
|
||||
<ElCard>
|
||||
<ArtTableHeader /> <!-- 表格头部:刷新、列设置、操作按钮 -->
|
||||
<ArtTable /> <!-- 数据表格 -->
|
||||
<ElDialog /> <!-- 新增/编辑对话框 -->
|
||||
</ElCard>
|
||||
</ArtTableFullScreen>
|
||||
</template>
|
||||
```
|
||||
|
||||
**理由**:
|
||||
- 与项目现有页面风格一致
|
||||
- 复用成熟的组件,减少开发工作量
|
||||
- 便于维护和扩展
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk 1: 后端 API 未完成
|
||||
|
||||
**风险**:后端接口可能尚未实现或与文档不一致。
|
||||
|
||||
**缓解措施**:
|
||||
1. 先实现 API 服务层,使用 TypeScript 类型约束
|
||||
2. 使用 Mock 数据进行前端开发(已有示例)
|
||||
3. 与后端团队确认 API 规范和联调时间
|
||||
4. 预留 API 调试和修正时间
|
||||
|
||||
### Risk 2: 状态值映射可能遗漏
|
||||
|
||||
**风险**:在某些地方忘记转换状态值,导致显示错误。
|
||||
|
||||
**缓解措施**:
|
||||
1. 在 API 服务层统一处理转换
|
||||
2. 创建工具函数封装映射逻辑
|
||||
3. 编写单元测试覆盖映射函数
|
||||
4. Code Review 时重点检查状态相关代码
|
||||
|
||||
### Risk 3: 定价规则理解偏差
|
||||
|
||||
**风险**:对定价规则的理解与实际业务需求有偏差。
|
||||
|
||||
**缓解措施**:
|
||||
1. 在实现前与产品确认定价规则
|
||||
2. 编写测试用例覆盖各种定价场景
|
||||
3. 在 UI 上清晰展示价格来源和计算方式
|
||||
4. 预留调整空间,避免硬编码
|
||||
|
||||
### Trade-off 1: 类型定义冗余
|
||||
|
||||
**取舍**:保留旧的 package.ts 类型定义,新增 packageManagement.ts。
|
||||
|
||||
**代价**:
|
||||
- 存在两套类型定义,可能造成混淆
|
||||
- 占用额外的代码空间
|
||||
|
||||
**收益**:
|
||||
- 不影响现有代码,向后兼容
|
||||
- 新旧系统可以并存,降低迁移风险
|
||||
- 未来可以逐步迁移到新类型
|
||||
|
||||
### Trade-off 2: 状态值映射增加复杂度
|
||||
|
||||
**取舍**:在 API 服务层进行状态值转换。
|
||||
|
||||
**代价**:
|
||||
- 增加一层转换逻辑
|
||||
- 可能影响性能(微小)
|
||||
|
||||
**收益**:
|
||||
- 前端 UI 保持一致性
|
||||
- 业务逻辑更清晰
|
||||
- 便于后续维护
|
||||
|
||||
## Migration Plan
|
||||
|
||||
### Phase 1: 基础设施(1-2天)
|
||||
1. 创建类型定义文件
|
||||
2. 创建常量配置文件
|
||||
3. 设置状态映射工具函数
|
||||
|
||||
### Phase 2: API 服务层(2-3天)
|
||||
1. 实现4个 API 服务模块
|
||||
2. 编写单元测试(可选)
|
||||
3. 使用 Mock 数据测试
|
||||
|
||||
### Phase 3: 页面实现(4-5天)
|
||||
1. 套餐系列管理页面(1天)
|
||||
2. 套餐管理页面(1.5天)
|
||||
3. 代理可售套餐页面(1天)
|
||||
4. 单套餐分配页面(1.5天)
|
||||
|
||||
### Phase 4: 集成测试(1-2天)
|
||||
1. 与后端 API 联调
|
||||
2. 端到端功能测试
|
||||
3. 修复 Bug 和优化
|
||||
|
||||
### Phase 5: 上线(1天)
|
||||
1. Code Review
|
||||
2. 合并代码
|
||||
3. 部署到测试环境
|
||||
4. 部署到生产环境
|
||||
|
||||
**总计**:9-13 个工作日
|
||||
|
||||
### Rollback Plan
|
||||
|
||||
如果出现严重问题,回滚步骤:
|
||||
1. 从 Git 回滚到上一个稳定版本
|
||||
2. 移除新增的路由配置
|
||||
3. 移除新增的 API 服务导出
|
||||
4. 通知用户功能暂时不可用
|
||||
|
||||
### Decision 7: 错误处理策略
|
||||
|
||||
**问题**:如何统一处理各类错误和异常?
|
||||
|
||||
**决策**:分层错误处理机制
|
||||
- **网络错误**:axios 拦截器统一捕获,显示通用错误提示
|
||||
- **401 未认证**:自动跳转到登录页面
|
||||
- **403 无权限**:显示权限不足提示,不跳转
|
||||
- **400 业务错误**:根据错误信息显示具体提示(ElMessage.error)
|
||||
- **表单验证错误**:在表单字段下显示错误提示
|
||||
|
||||
**错误提示方式**:
|
||||
```typescript
|
||||
// 网络错误或服务器错误
|
||||
ElMessage.error('网络错误,请稍后重试')
|
||||
|
||||
// 业务错误(后端返回的具体错误)
|
||||
ElMessage.error(res.message || '操作失败')
|
||||
|
||||
// 操作成功
|
||||
ElMessage.success('操作成功')
|
||||
```
|
||||
|
||||
**理由**:
|
||||
- 统一的错误处理提升用户体验
|
||||
- 分层处理避免重复代码
|
||||
- 清晰的错误提示帮助用户理解问题
|
||||
|
||||
### Decision 8: Loading 状态管理
|
||||
|
||||
**问题**:如何管理各种操作的加载状态?
|
||||
|
||||
**决策**:细粒度的 loading 状态管理
|
||||
|
||||
**Loading 状态分类**:
|
||||
```typescript
|
||||
const loading = ref(false) // 表格数据加载
|
||||
const submitLoading = ref(false) // 表单提交
|
||||
const deleteLoading = ref<Record<number, boolean>>({}) // 删除操作(可选)
|
||||
```
|
||||
|
||||
**状态管理规则**:
|
||||
- **列表查询**:表格显示 loading 遮罩
|
||||
- **新增/编辑提交**:提交按钮显示 loading,禁用表单
|
||||
- **删除操作**:可选择在按钮上显示 loading 或全局 loading
|
||||
- **状态切换**:ElSwitch 自带 loading 效果,先更新 UI 再调用 API
|
||||
|
||||
**理由**:
|
||||
- 细粒度控制提供更好的交互反馈
|
||||
- 防止重复提交
|
||||
- 清晰标识正在进行的操作
|
||||
|
||||
## Open Questions
|
||||
|
||||
1. **Q**: 套餐被删除后,历史订单如何处理?
|
||||
**A**: 待产品确认,可能需要软删除机制
|
||||
|
||||
2. **Q**: 代理商可以自行调整套餐售价吗?
|
||||
**A**: 待产品确认,当前设计只展示建议售价
|
||||
|
||||
3. **Q**: 套餐系列和套餐是否支持批量操作(批量启用/禁用)?
|
||||
**A**: 当前不支持,后续迭代考虑
|
||||
|
||||
4. **Q**: 是否需要套餐变更历史记录?
|
||||
**A**: 后端可能有审计日志,前端暂不展示
|
||||
|
||||
5. **Q**: 单套餐分配的"原计算成本价"是否需要实时更新?
|
||||
**A**: 待确认,当前设计是创建时计算一次,不自动更新
|
||||
143
openspec/changes/add-package-management-system/proposal.md
Normal file
143
openspec/changes/add-package-management-system/proposal.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# Change: 套餐管理系统实现
|
||||
|
||||
## Why
|
||||
|
||||
根据业务需求文档(docs/套餐.md),需要实现完整的套餐管理系统,包括4个核心模块:
|
||||
|
||||
1. **套餐系列管理** - 管理套餐的分类和组织
|
||||
2. **套餐管理** - 管理具体的套餐产品(流量、价格、时长等)
|
||||
3. **代理可售套餐** - 代理商查看被分配的可售套餐及定价
|
||||
4. **单套餐分配** - 为代理商分配特定套餐并设置成本价
|
||||
|
||||
当前系统虽然有套餐相关的类型定义(src/types/api/package.ts)和部分页面骨架,但缺少完整的 API 对接和业务逻辑实现。此变更将实现完整的套餐管理能力。
|
||||
|
||||
## What Changes
|
||||
|
||||
### 1. API 层实现
|
||||
|
||||
采用模块化设计,拆分为 4 个独立的 API 服务文件:
|
||||
|
||||
- **新增**: `src/api/modules/packageSeries.ts` - 套餐系列 API 服务
|
||||
- 套餐系列列表查询(分页、筛选)
|
||||
- 创建套餐系列
|
||||
- 获取套餐系列详情
|
||||
- 更新套餐系列
|
||||
- 删除套餐系列
|
||||
- 更新套餐系列状态
|
||||
|
||||
- **新增**: `src/api/modules/package.ts` - 套餐管理 API 服务
|
||||
- 套餐列表查询(分页、多条件筛选)
|
||||
- 创建套餐
|
||||
- 获取套餐详情
|
||||
- 更新套餐
|
||||
- 删除套餐
|
||||
- 更新套餐状态
|
||||
- 更新套餐上架状态
|
||||
- 获取系列下拉选项(用于表单选择)
|
||||
|
||||
- **新增**: `src/api/modules/myPackage.ts` - 代理可售套餐 API 服务
|
||||
- 我的可售套餐列表查询
|
||||
- 获取可售套餐详情
|
||||
- 我的被分配系列列表
|
||||
|
||||
- **新增**: `src/api/modules/shopPackageAllocation.ts` - 单套餐分配 API 服务
|
||||
- 单套餐分配列表查询
|
||||
- 创建单套餐分配
|
||||
- 获取单套餐分配详情
|
||||
- 更新单套餐分配
|
||||
- 删除单套餐分配
|
||||
- 更新单套餐分配状态
|
||||
|
||||
- **修改**: `src/api/modules/index.ts` - 导出新增的服务模块
|
||||
- 导出 PackageSeriesService
|
||||
- 导出 PackageService
|
||||
- 导出 MyPackageService
|
||||
- 导出 ShopPackageAllocationService
|
||||
|
||||
### 2. 类型定义增强
|
||||
|
||||
- **新增**: `src/types/api/packageManagement.ts` - 完整的套餐管理类型定义
|
||||
- 匹配文档的 API 字段(下划线命名)
|
||||
- 包含所有请求/响应类型
|
||||
- 包含分页结果类型
|
||||
|
||||
### 3. 页面实现
|
||||
|
||||
**套餐系列管理** (`src/views/package-management/package-series/index.vue`)
|
||||
- 列表展示(支持名称搜索、状态筛选)
|
||||
- 新增/编辑套餐系列
|
||||
- 删除套餐系列
|
||||
- 状态开关(启用/禁用)
|
||||
|
||||
**套餐管理** (`src/views/package-management/package-list/index.vue`)
|
||||
- 列表展示(支持多条件筛选:名称、系列、状态、上架状态、套餐类型)
|
||||
- 新增/编辑套餐
|
||||
- 删除套餐
|
||||
- 状态开关(启用/禁用)
|
||||
- 上架状态开关(上架/下架)
|
||||
|
||||
**代理可售套餐** (`src/views/package-management/my-packages/index.vue`)
|
||||
- 查看被分配的套餐列表(支持系列、类型筛选)
|
||||
- 查看套餐详情(成本价、建议售价、利润空间等)
|
||||
- 查看被分配系列列表
|
||||
|
||||
**单套餐分配** (`src/views/package-management/package-assign/index.vue`)
|
||||
- 分配列表(支持店铺、套餐、状态筛选)
|
||||
- 创建分配(选择套餐、店铺、设置成本价)
|
||||
- 编辑分配(修改成本价)
|
||||
- 删除分配
|
||||
- 状态管理(启用/禁用)
|
||||
|
||||
### 4. 常量配置
|
||||
|
||||
- **新增**: `src/config/constants/package.ts` - 套餐相关常量
|
||||
- 套餐类型枚举(formal/addon)
|
||||
- 流量类型枚举(real/virtual)
|
||||
- 上架状态枚举(1:上架, 2:下架)
|
||||
- 定价模式枚举(fixed/percent)
|
||||
- 价格来源枚举(series_pricing/package_override)
|
||||
|
||||
### 5. 路由配置
|
||||
|
||||
已存在的路由(无需修改):
|
||||
- `/package-management/package-series` - 套餐系列管理
|
||||
- `/package-management/package-list` - 套餐管理
|
||||
- `/package-management/package-assign` - 单套餐分配
|
||||
|
||||
需要新增的路由:
|
||||
- **新增**: `src/router/routesAlias.ts` - 添加路由别名
|
||||
- `MyPackages = '/package-management/my-packages'` - 代理可售套餐
|
||||
|
||||
- **新增**: `src/router/routes/asyncRoutes.ts` - 添加路由配置
|
||||
- `/package-management/my-packages` - 代理可售套餐页面路由
|
||||
|
||||
## Impact
|
||||
|
||||
### 受影响的规范
|
||||
- `package-series-management` - 新增能力
|
||||
- `package-management` - 新增能力
|
||||
- `my-packages` - 新增能力
|
||||
- `shop-package-allocation` - 新增能力
|
||||
|
||||
### 受影响的代码
|
||||
- `src/api/modules/*` - 新增 4 个 API 服务模块
|
||||
- `src/types/api/*` - 新增类型定义文件
|
||||
- `src/views/package-management/*` - 4 个页面完整实现
|
||||
- `src/config/constants/*` - 新增常量配置
|
||||
- `src/router/routes/asyncRoutes.ts` - 路由配置
|
||||
|
||||
### 依赖关系
|
||||
- 依赖现有的组件库(ArtTable、ArtSearchBar、ArtTableHeader 等)
|
||||
- 依赖现有的 HTTP 请求工具(request.ts)
|
||||
- 依赖现有的权限控制和路由守卫
|
||||
- 依赖 ShopService(用于单套餐分配页面的店铺选择器)
|
||||
- 后端 API 需已实现(docs/套餐.md 中定义的接口)
|
||||
|
||||
**注意事项**:
|
||||
- ShopService 应该已经存在于 src/api/modules/shop.ts
|
||||
- 如果不存在,需要先实现或使用 Mock 数据
|
||||
|
||||
### 风险评估
|
||||
- **低风险**: 独立模块,不影响现有功能
|
||||
- **API 依赖**: 需确保后端接口已实现并联调
|
||||
- **权限控制**: 需配置对应的菜单和按钮权限
|
||||
@@ -0,0 +1,110 @@
|
||||
# My Packages (代理可售套餐) Specification
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 我的可售套餐列表查询
|
||||
|
||||
系统 SHALL 提供代理商查询被分配套餐的功能。
|
||||
|
||||
#### Scenario: 查询当前代理商的可售套餐
|
||||
|
||||
- **WHEN** 代理商用户访问可售套餐页面
|
||||
- **THEN** 系统显示被分配给该代理商的套餐列表
|
||||
- **AND** 每个套餐包含:套餐ID、套餐编码、套餐名称、套餐类型、系列信息
|
||||
- **AND** 显示成本价(cost_price,单位:分)
|
||||
- **AND** 显示建议售价(suggested_retail_price,单位:分)
|
||||
- **AND** 显示利润空间(profit_margin = 建议售价 - 成本价)
|
||||
- **AND** 显示价格来源(series_pricing:系列加价 / package_override:单套餐覆盖)
|
||||
- **AND** 显示套餐状态和上架状态
|
||||
- **AND** 支持分页,每页最多100条记录
|
||||
|
||||
#### Scenario: 按系列筛选
|
||||
|
||||
- **WHEN** 代理商选择特定系列ID筛选
|
||||
- **THEN** 系统返回该系列下的所有可售套餐
|
||||
|
||||
#### Scenario: 按套餐类型筛选
|
||||
|
||||
- **WHEN** 代理商选择套餐类型(formal/addon)筛选
|
||||
- **THEN** 系统返回该类型的所有可售套餐
|
||||
|
||||
### Requirement: 可售套餐详情查询
|
||||
|
||||
系统 SHALL 允许代理商查看单个可售套餐的详细信息。
|
||||
|
||||
#### Scenario: 查询套餐详情
|
||||
|
||||
- **WHEN** 代理商点击查看套餐详情
|
||||
- **THEN** 系统显示套餐完整信息
|
||||
- **AND** 包含套餐描述、流量信息、时长等
|
||||
- **AND** 显示定价详情(成本价、建议售价、利润空间、价格来源)
|
||||
- **AND** 显示系列信息
|
||||
|
||||
#### Scenario: 查询未分配的套餐
|
||||
|
||||
- **WHEN** 代理商查询未被分配的套餐ID
|
||||
- **THEN** 系统返回404错误或无权访问错误
|
||||
|
||||
### Requirement: 我的被分配系列列表
|
||||
|
||||
系统 SHALL 提供代理商查询被分配系列的功能。
|
||||
|
||||
#### Scenario: 查询被分配系列列表
|
||||
|
||||
- **WHEN** 代理商访问被分配系列列表
|
||||
- **THEN** 系统显示分配给该代理商的系列列表
|
||||
- **AND** 每个系列包含:分配ID、系列ID、系列编码、系列名称
|
||||
- **AND** 显示定价模式(fixed:固定金额 / percent:百分比)
|
||||
- **AND** 显示定价值(pricing_value)
|
||||
- **AND** 显示分配者店铺名称
|
||||
- **AND** 显示可售套餐数量
|
||||
- **AND** 显示状态
|
||||
- **AND** 支持分页
|
||||
|
||||
### Requirement: 成本价计算规则
|
||||
|
||||
系统 SHALL 根据价格来源计算代理商的成本价。
|
||||
|
||||
#### Scenario: 系列加价模式(series_pricing)
|
||||
|
||||
- **WHEN** 套餐通过系列分配获得定价
|
||||
- **AND** 定价模式为 fixed(固定金额)
|
||||
- **THEN** 成本价 = 套餐价格 + 固定加价金额
|
||||
|
||||
- **WHEN** 定价模式为 percent(百分比)
|
||||
- **THEN** 成本价 = 套餐价格 × (1 + 加价百分比)
|
||||
|
||||
#### Scenario: 单套餐覆盖模式(package_override)
|
||||
|
||||
- **WHEN** 套餐被单独分配并设置了成本价
|
||||
- **THEN** 成本价 = 单套餐分配中设置的成本价
|
||||
- **AND** 价格来源显示为 package_override
|
||||
|
||||
### Requirement: 数据隔离
|
||||
|
||||
系统 SHALL 确保代理商只能查看被分配给自己的套餐。
|
||||
|
||||
#### Scenario: 数据访问隔离
|
||||
|
||||
- **WHEN** 代理商查询可售套餐列表
|
||||
- **THEN** 系统仅返回分配给该代理商的套餐
|
||||
- **AND** 不显示其他代理商的套餐信息
|
||||
|
||||
#### Scenario: 跨代理商访问保护
|
||||
|
||||
- **WHEN** 代理商尝试访问未分配给自己的套餐详情
|
||||
- **THEN** 系统返回403无权访问错误
|
||||
|
||||
### Requirement: 权限控制
|
||||
|
||||
系统 SHALL 对可售套餐查询功能实施权限控制。
|
||||
|
||||
#### Scenario: 仅代理商可访问
|
||||
|
||||
- **WHEN** 非代理商用户访问可售套餐接口
|
||||
- **THEN** 系统返回403无权访问错误
|
||||
|
||||
#### Scenario: 未认证用户访问
|
||||
|
||||
- **WHEN** 未登录用户访问可售套餐接口
|
||||
- **THEN** 系统返回401未认证错误
|
||||
@@ -0,0 +1,159 @@
|
||||
# Package Management Specification
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 套餐列表查询
|
||||
|
||||
系统 SHALL 提供套餐列表查询功能,支持分页和多条件筛选。
|
||||
|
||||
#### Scenario: 查询所有套餐
|
||||
|
||||
- **WHEN** 用户访问套餐管理页面
|
||||
- **THEN** 系统显示套餐列表,包含套餐编码、套餐名称、系列ID、套餐类型、流量、价格、状态、上架状态等
|
||||
- **AND** 支持按套餐名称模糊搜索
|
||||
- **AND** 支持按系列ID筛选
|
||||
- **AND** 支持按状态筛选(启用/禁用)
|
||||
- **AND** 支持按上架状态筛选(上架/下架)
|
||||
- **AND** 支持按套餐类型筛选(formal/addon)
|
||||
- **AND** 支持分页,每页最多100条记录
|
||||
|
||||
#### Scenario: 多条件组合查询
|
||||
|
||||
- **WHEN** 用户同时使用多个筛选条件
|
||||
- **THEN** 系统返回满足所有条件的套餐列表
|
||||
|
||||
### Requirement: 创建套餐
|
||||
|
||||
系统 SHALL 允许管理员创建新的套餐。
|
||||
|
||||
#### Scenario: 成功创建套餐
|
||||
|
||||
- **WHEN** 用户填写必填字段(套餐编码、套餐名称、套餐类型、套餐时长、套餐价格)
|
||||
- **AND** 可选填写系列ID、流量信息、成本价、建议售价等
|
||||
- **AND** 提交表单
|
||||
- **THEN** 系统创建套餐,默认状态为启用,默认上架状态为下架
|
||||
- **AND** 返回创建的套餐详情
|
||||
|
||||
#### Scenario: 套餐编码唯一性验证
|
||||
|
||||
- **WHEN** 用户使用已存在的套餐编码创建套餐
|
||||
- **THEN** 系统返回错误提示"套餐编码已存在"
|
||||
|
||||
#### Scenario: 验证套餐时长范围
|
||||
|
||||
- **WHEN** 套餐时长小于1个月或大于120个月
|
||||
- **THEN** 系统返回验证错误"套餐时长必须在1-120个月之间"
|
||||
|
||||
#### Scenario: 流量类型与流量额度关系
|
||||
|
||||
- **WHEN** 流量类型为真流量(real)
|
||||
- **THEN** 真流量额度(real_data_mb)必须大于0
|
||||
- **AND** 总流量额度(data_amount_mb)等于真流量额度
|
||||
|
||||
- **WHEN** 流量类型为虚流量(virtual)
|
||||
- **THEN** 虚流量额度(virtual_data_mb)必须大于0
|
||||
- **AND** 真流量额度和虚流量额度之和等于总流量额度
|
||||
|
||||
### Requirement: 查看套餐详情
|
||||
|
||||
系统 SHALL 允许用户查看单个套餐的详细信息。
|
||||
|
||||
#### Scenario: 查询存在的套餐
|
||||
|
||||
- **WHEN** 用户通过套餐ID查询详情
|
||||
- **THEN** 系统返回该套餐的完整信息,包括所有字段
|
||||
|
||||
#### Scenario: 查询不存在的套餐
|
||||
|
||||
- **WHEN** 用户查询不存在的套餐ID
|
||||
- **THEN** 系统返回404错误
|
||||
|
||||
### Requirement: 更新套餐
|
||||
|
||||
系统 SHALL 允许管理员更新套餐信息。
|
||||
|
||||
#### Scenario: 成功更新套餐
|
||||
|
||||
- **WHEN** 用户修改套餐的可变字段(名称、时长、价格、流量等)
|
||||
- **AND** 提交更新
|
||||
- **THEN** 系统更新套餐信息
|
||||
- **AND** 返回更新后的套餐详情
|
||||
|
||||
#### Scenario: 套餐编码不可修改
|
||||
|
||||
- **WHEN** 用户尝试修改套餐编码
|
||||
- **THEN** 系统忽略该字段,不允许修改
|
||||
|
||||
### Requirement: 删除套餐
|
||||
|
||||
系统 SHALL 允许管理员删除套餐。
|
||||
|
||||
#### Scenario: 成功删除套餐
|
||||
|
||||
- **WHEN** 用户删除未被使用的套餐
|
||||
- **THEN** 系统删除该套餐
|
||||
- **AND** 返回成功状态
|
||||
|
||||
#### Scenario: 删除被分配的套餐
|
||||
|
||||
- **WHEN** 用户删除已被分配给代理商的套餐
|
||||
- **THEN** 系统返回错误提示"该套餐已被分配,无法删除"
|
||||
|
||||
### Requirement: 套餐状态管理
|
||||
|
||||
系统 SHALL 支持套餐启用/禁用状态管理。
|
||||
|
||||
#### Scenario: 启用套餐
|
||||
|
||||
- **WHEN** 用户将禁用状态的套餐切换为启用
|
||||
- **THEN** 系统更新状态为启用(status=1)
|
||||
|
||||
#### Scenario: 禁用套餐
|
||||
|
||||
- **WHEN** 用户将启用状态的套餐切换为禁用
|
||||
- **THEN** 系统更新状态为禁用(status=2)
|
||||
- **AND** 该套餐将不可用于新的分配或充值
|
||||
|
||||
### Requirement: 套餐上架状态管理
|
||||
|
||||
系统 SHALL 支持套餐上架/下架状态管理。
|
||||
|
||||
#### Scenario: 上架套餐
|
||||
|
||||
- **WHEN** 用户将下架状态的套餐切换为上架
|
||||
- **THEN** 系统更新上架状态为上架(shelf_status=1)
|
||||
- **AND** 该套餐将对代理商可见
|
||||
|
||||
#### Scenario: 下架套餐
|
||||
|
||||
- **WHEN** 用户将上架状态的套餐切换为下架
|
||||
- **THEN** 系统更新上架状态为下架(shelf_status=2)
|
||||
- **AND** 该套餐将对代理商不可见
|
||||
|
||||
### Requirement: 套餐类型支持
|
||||
|
||||
系统 SHALL 支持两种套餐类型。
|
||||
|
||||
#### Scenario: 正式套餐
|
||||
|
||||
- **WHEN** 创建套餐类型为 formal 的套餐
|
||||
- **THEN** 系统记录为正式套餐
|
||||
|
||||
#### Scenario: 附加套餐
|
||||
|
||||
- **WHEN** 创建套餐类型为 addon 的套餐
|
||||
- **THEN** 系统记录为附加套餐
|
||||
|
||||
### Requirement: 权限控制
|
||||
|
||||
系统 SHALL 对套餐管理功能实施权限控制。
|
||||
|
||||
#### Scenario: 未认证用户访问
|
||||
|
||||
- **WHEN** 未登录用户访问套餐管理接口
|
||||
- **THEN** 系统返回401未认证错误
|
||||
|
||||
#### Scenario: 无权限用户访问
|
||||
|
||||
- **WHEN** 已登录但无权限的用户访问套餐管理接口
|
||||
- **THEN** 系统返回403无权访问错误
|
||||
@@ -0,0 +1,116 @@
|
||||
# Package Series Management Specification
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 套餐系列列表查询
|
||||
|
||||
系统 SHALL 提供套餐系列列表查询功能,支持分页和条件筛选。
|
||||
|
||||
#### Scenario: 查询所有套餐系列
|
||||
|
||||
- **WHEN** 用户访问套餐系列管理页面
|
||||
- **THEN** 系统显示套餐系列列表,包含系列名称、系列编码、描述、状态、创建时间、更新时间
|
||||
- **AND** 支持按系列名称模糊搜索
|
||||
- **AND** 支持按状态筛选(启用/禁用)
|
||||
- **AND** 支持分页,每页最多100条记录
|
||||
|
||||
#### Scenario: 空列表处理
|
||||
|
||||
- **WHEN** 没有符合条件的套餐系列
|
||||
- **THEN** 系统显示空状态提示
|
||||
|
||||
### Requirement: 创建套餐系列
|
||||
|
||||
系统 SHALL 允许管理员创建新的套餐系列。
|
||||
|
||||
#### Scenario: 成功创建套餐系列
|
||||
|
||||
- **WHEN** 用户填写系列编码、系列名称(必填)
|
||||
- **AND** 可选填写描述(最大500字符)
|
||||
- **AND** 提交表单
|
||||
- **THEN** 系统创建套餐系列,默认状态为启用
|
||||
- **AND** 返回创建的套餐系列详情
|
||||
|
||||
#### Scenario: 系列编码重复
|
||||
|
||||
- **WHEN** 用户使用已存在的系列编码创建套餐系列
|
||||
- **THEN** 系统返回错误提示"系列编码已存在"
|
||||
|
||||
#### Scenario: 验证系列名称长度
|
||||
|
||||
- **WHEN** 系列名称长度小于1或大于255个字符
|
||||
- **THEN** 系统返回验证错误
|
||||
|
||||
### Requirement: 查看套餐系列详情
|
||||
|
||||
系统 SHALL 允许用户查看单个套餐系列的详细信息。
|
||||
|
||||
#### Scenario: 查询存在的套餐系列
|
||||
|
||||
- **WHEN** 用户通过系列ID查询详情
|
||||
- **THEN** 系统返回该套餐系列的完整信息
|
||||
|
||||
#### Scenario: 查询不存在的套餐系列
|
||||
|
||||
- **WHEN** 用户查询不存在的系列ID
|
||||
- **THEN** 系统返回404错误
|
||||
|
||||
### Requirement: 更新套餐系列
|
||||
|
||||
系统 SHALL 允许管理员更新套餐系列信息。
|
||||
|
||||
#### Scenario: 成功更新套餐系列
|
||||
|
||||
- **WHEN** 用户修改系列名称或描述
|
||||
- **AND** 提交更新
|
||||
- **THEN** 系统更新套餐系列信息
|
||||
- **AND** 返回更新后的套餐系列详情
|
||||
|
||||
#### Scenario: 系列编码不可修改
|
||||
|
||||
- **WHEN** 用户尝试修改系列编码
|
||||
- **THEN** 系统忽略该字段,不允许修改
|
||||
|
||||
### Requirement: 删除套餐系列
|
||||
|
||||
系统 SHALL 允许管理员删除套餐系列。
|
||||
|
||||
#### Scenario: 成功删除套餐系列
|
||||
|
||||
- **WHEN** 用户删除未被套餐使用的系列
|
||||
- **THEN** 系统删除该套餐系列
|
||||
- **AND** 返回成功状态
|
||||
|
||||
#### Scenario: 删除被使用的套餐系列
|
||||
|
||||
- **WHEN** 用户删除已被套餐关联的系列
|
||||
- **THEN** 系统返回错误提示"该系列下存在套餐,无法删除"
|
||||
|
||||
### Requirement: 套餐系列状态管理
|
||||
|
||||
系统 SHALL 支持套餐系列状态的开关管理。
|
||||
|
||||
#### Scenario: 启用套餐系列
|
||||
|
||||
- **WHEN** 用户将禁用状态的系列切换为启用
|
||||
- **THEN** 系统更新状态为启用(status=1)
|
||||
|
||||
#### Scenario: 禁用套餐系列
|
||||
|
||||
- **WHEN** 用户将启用状态的系列切换为禁用
|
||||
- **THEN** 系统更新状态为禁用(status=2)
|
||||
- **AND** 该系列下的套餐可能受到影响(业务规则)
|
||||
|
||||
### Requirement: 权限控制
|
||||
|
||||
系统 SHALL 对套餐系列管理功能实施权限控制。
|
||||
|
||||
#### Scenario: 未认证用户访问
|
||||
|
||||
- **WHEN** 未登录用户访问套餐系列管理接口
|
||||
- **THEN** 系统返回401未认证错误
|
||||
|
||||
#### Scenario: 无权限用户访问
|
||||
|
||||
- **WHEN** 已登录但无权限的用户访问套餐系列管理接口
|
||||
- **THEN** 系统返回403无权访问错误
|
||||
@@ -0,0 +1,164 @@
|
||||
# Shop Package Allocation (单套餐分配) Specification
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 单套餐分配列表查询
|
||||
|
||||
系统 SHALL 提供单套餐分配记录的查询功能。
|
||||
|
||||
#### Scenario: 查询所有单套餐分配
|
||||
|
||||
- **WHEN** 管理员访问单套餐分配管理页面
|
||||
- **THEN** 系统显示单套餐分配列表
|
||||
- **AND** 每条记录包含:分配ID、套餐ID、套餐编码、套餐名称
|
||||
- **AND** 显示被分配的店铺ID和店铺名称
|
||||
- **AND** 显示覆盖的成本价(cost_price,单位:分)
|
||||
- **AND** 显示原计算成本价(calculated_cost_price,供参考)
|
||||
- **AND** 显示关联的系列分配ID
|
||||
- **AND** 显示状态、创建时间、更新时间
|
||||
- **AND** 支持分页,每页最多100条记录
|
||||
|
||||
#### Scenario: 按店铺筛选
|
||||
|
||||
- **WHEN** 管理员选择特定店铺ID筛选
|
||||
- **THEN** 系统返回该店铺的所有单套餐分配记录
|
||||
|
||||
#### Scenario: 按套餐筛选
|
||||
|
||||
- **WHEN** 管理员选择特定套餐ID筛选
|
||||
- **THEN** 系统返回该套餐的所有分配记录
|
||||
|
||||
#### Scenario: 按状态筛选
|
||||
|
||||
- **WHEN** 管理员选择状态(启用/禁用)筛选
|
||||
- **THEN** 系统返回符合状态条件的分配记录
|
||||
|
||||
### Requirement: 创建单套餐分配
|
||||
|
||||
系统 SHALL 允许管理员为店铺分配特定套餐并设置成本价。
|
||||
|
||||
#### Scenario: 成功创建单套餐分配
|
||||
|
||||
- **WHEN** 管理员选择套餐ID、店铺ID
|
||||
- **AND** 设置覆盖的成本价(必填,最小值为0)
|
||||
- **AND** 提交分配
|
||||
- **THEN** 系统创建单套餐分配记录
|
||||
- **AND** 计算并保存原计算成本价(基于系列分配规则)
|
||||
- **AND** 返回创建的分配详情,包括关联的系列分配ID
|
||||
|
||||
#### Scenario: 重复分配检查
|
||||
|
||||
- **WHEN** 管理员为同一店铺分配已分配过的套餐
|
||||
- **THEN** 系统返回错误提示"该套餐已分配给此店铺"
|
||||
|
||||
#### Scenario: 店铺和套餐验证
|
||||
|
||||
- **WHEN** 管理员使用不存在的店铺ID或套餐ID
|
||||
- **THEN** 系统返回错误提示"店铺或套餐不存在"
|
||||
|
||||
### Requirement: 查看单套餐分配详情
|
||||
|
||||
系统 SHALL 允许管理员查看单个分配记录的详细信息。
|
||||
|
||||
#### Scenario: 查询存在的分配记录
|
||||
|
||||
- **WHEN** 管理员通过分配ID查询详情
|
||||
- **THEN** 系统返回该分配记录的完整信息
|
||||
- **AND** 包含套餐完整信息、店铺信息、定价信息
|
||||
|
||||
#### Scenario: 查询不存在的分配记录
|
||||
|
||||
- **WHEN** 管理员查询不存在的分配ID
|
||||
- **THEN** 系统返回404错误
|
||||
|
||||
### Requirement: 更新单套餐分配
|
||||
|
||||
系统 SHALL 允许管理员更新单套餐分配的成本价。
|
||||
|
||||
#### Scenario: 成功更新成本价
|
||||
|
||||
- **WHEN** 管理员修改覆盖的成本价
|
||||
- **AND** 提交更新
|
||||
- **THEN** 系统更新成本价
|
||||
- **AND** 返回更新后的分配详情
|
||||
|
||||
#### Scenario: 成本价验证
|
||||
|
||||
- **WHEN** 管理员设置成本价小于0
|
||||
- **THEN** 系统返回验证错误"成本价必须大于等于0"
|
||||
|
||||
### Requirement: 删除单套餐分配
|
||||
|
||||
系统 SHALL 允许管理员删除单套餐分配记录。
|
||||
|
||||
#### Scenario: 成功删除分配
|
||||
|
||||
- **WHEN** 管理员删除单套餐分配记录
|
||||
- **THEN** 系统删除该分配记录
|
||||
- **AND** 该店铺将无法再以此定价售卖该套餐
|
||||
- **AND** 返回成功状态
|
||||
|
||||
#### Scenario: 删除正在使用的分配
|
||||
|
||||
- **WHEN** 管理员删除正在被订单使用的分配记录
|
||||
- **THEN** 系统可能返回警告或阻止删除(根据业务规则)
|
||||
|
||||
### Requirement: 单套餐分配状态管理
|
||||
|
||||
系统 SHALL 支持单套餐分配的启用/禁用状态管理。
|
||||
|
||||
#### Scenario: 启用分配
|
||||
|
||||
- **WHEN** 管理员将禁用状态的分配切换为启用
|
||||
- **THEN** 系统更新状态为启用(status=1)
|
||||
- **AND** 该店铺可以使用此定价售卖套餐
|
||||
|
||||
#### Scenario: 禁用分配
|
||||
|
||||
- **WHEN** 管理员将启用状态的分配切换为禁用
|
||||
- **THEN** 系统更新状态为禁用(status=2)
|
||||
- **AND** 该店铺将无法使用此定价售卖套餐
|
||||
|
||||
### Requirement: 成本价优先级规则
|
||||
|
||||
系统 SHALL 实现单套餐分配成本价覆盖系列分配规则。
|
||||
|
||||
#### Scenario: 单套餐分配优先
|
||||
|
||||
- **WHEN** 店铺同时拥有系列分配和单套餐分配
|
||||
- **THEN** 系统使用单套餐分配的成本价
|
||||
- **AND** 原计算成本价(calculated_cost_price)保存系列分配规则计算的价格,供参考
|
||||
|
||||
#### Scenario: 仅系列分配
|
||||
|
||||
- **WHEN** 店铺只有系列分配,没有单套餐分配
|
||||
- **THEN** 系统使用系列分配规则计算成本价
|
||||
|
||||
### Requirement: 关联系列分配追踪
|
||||
|
||||
系统 SHALL 追踪单套餐分配与系列分配的关联关系。
|
||||
|
||||
#### Scenario: 记录关联的系列分配
|
||||
|
||||
- **WHEN** 创建单套餐分配时
|
||||
- **THEN** 系统记录关联的系列分配ID(allocation_id)
|
||||
- **AND** 用于追溯定价来源
|
||||
|
||||
### Requirement: 权限控制
|
||||
|
||||
系统 SHALL 对单套餐分配管理功能实施权限控制。
|
||||
|
||||
#### Scenario: 未认证用户访问
|
||||
|
||||
- **WHEN** 未登录用户访问单套餐分配接口
|
||||
- **THEN** 系统返回401未认证错误
|
||||
|
||||
#### Scenario: 无权限用户访问
|
||||
|
||||
- **WHEN** 已登录但无权限的用户访问单套餐分配接口
|
||||
- **THEN** 系统返回403无权访问错误
|
||||
|
||||
#### Scenario: 仅管理员可操作
|
||||
|
||||
- **WHEN** 非管理员用户尝试创建、更新或删除单套餐分配
|
||||
- **THEN** 系统返回403无权访问错误
|
||||
156
openspec/changes/add-package-management-system/tasks.md
Normal file
156
openspec/changes/add-package-management-system/tasks.md
Normal file
@@ -0,0 +1,156 @@
|
||||
# Implementation Tasks
|
||||
|
||||
## 1. 基础设施准备
|
||||
|
||||
- [ ] 1.1 创建套餐管理类型定义文件(src/types/api/packageManagement.ts)
|
||||
- [ ] 1.2 创建套餐常量配置文件(src/config/constants/package.ts)
|
||||
- [ ] 1.3 导出常量配置到 constants/index.ts
|
||||
|
||||
## 2. API 服务层实现
|
||||
|
||||
### 2.1 套餐系列 API(packageSeries.ts)
|
||||
- [ ] 2.1.1 实现 getPackageSeries(套餐系列列表)
|
||||
- [ ] 2.1.2 实现 createPackageSeries(创建套餐系列)
|
||||
- [ ] 2.1.3 实现 getPackageSeriesDetail(获取套餐系列详情)
|
||||
- [ ] 2.1.4 实现 updatePackageSeries(更新套餐系列)
|
||||
- [ ] 2.1.5 实现 deletePackageSeries(删除套餐系列)
|
||||
- [ ] 2.1.6 实现 updatePackageSeriesStatus(更新套餐系列状态)
|
||||
|
||||
### 2.2 套餐管理 API(package.ts)
|
||||
- [ ] 2.2.1 实现 getPackages(套餐列表)
|
||||
- [ ] 2.2.2 实现 createPackage(创建套餐)
|
||||
- [ ] 2.2.3 实现 getPackageDetail(获取套餐详情)
|
||||
- [ ] 2.2.4 实现 updatePackage(更新套餐)
|
||||
- [ ] 2.2.5 实现 deletePackage(删除套餐)
|
||||
- [ ] 2.2.6 实现 updatePackageStatus(更新套餐状态)
|
||||
- [ ] 2.2.7 实现 updatePackageShelfStatus(更新套餐上架状态)
|
||||
|
||||
### 2.3 代理可售套餐 API(myPackage.ts)
|
||||
- [ ] 2.3.1 实现 getMyPackages(我的可售套餐列表)
|
||||
- [ ] 2.3.2 实现 getMyPackageDetail(获取可售套餐详情)
|
||||
- [ ] 2.3.3 实现 getMySeriesAllocations(我的被分配系列列表)
|
||||
|
||||
### 2.4 单套餐分配 API(shopPackageAllocation.ts)
|
||||
- [ ] 2.4.1 实现 getShopPackageAllocations(单套餐分配列表)
|
||||
- [ ] 2.4.2 实现 createShopPackageAllocation(创建单套餐分配)
|
||||
- [ ] 2.4.3 实现 getShopPackageAllocationDetail(获取单套餐分配详情)
|
||||
- [ ] 2.4.4 实现 updateShopPackageAllocation(更新单套餐分配)
|
||||
- [ ] 2.4.5 实现 deleteShopPackageAllocation(删除单套餐分配)
|
||||
- [ ] 2.4.6 实现 updateShopPackageAllocationStatus(更新单套餐分配状态)
|
||||
|
||||
- [ ] 2.5 在 src/api/modules/index.ts 中导出所有新服务
|
||||
|
||||
## 3. 页面实现
|
||||
|
||||
### 3.1 套餐系列管理页面(package-series/index.vue)
|
||||
- [ ] 3.1.1 实现列表展示(表格、分页)
|
||||
- [ ] 3.1.2 实现搜索栏(系列名称、状态筛选)
|
||||
- [ ] 3.1.3 实现新增对话框(表单验证)
|
||||
- [ ] 3.1.4 实现编辑功能(复用新增对话框,根据 dialogType 区分新增/编辑)
|
||||
- [ ] 3.1.5 实现删除功能(二次确认)
|
||||
- [ ] 3.1.6 实现状态开关(启用/禁用)
|
||||
- [ ] 3.1.7 集成 API 服务并处理加载状态
|
||||
|
||||
### 3.2 套餐管理页面(package-list/index.vue)
|
||||
- [ ] 3.2.1 实现列表展示(表格、分页)
|
||||
- [ ] 3.2.2 实现搜索栏(名称、系列、状态、上架状态、类型筛选)
|
||||
- [ ] 3.2.3 实现系列下拉选择器(加载套餐系列列表,只显示启用状态)
|
||||
- [ ] 3.2.4 实现新增对话框(表单验证、系列选择)
|
||||
- [ ] 3.2.5 实现编辑功能(复用新增对话框,根据 dialogType 区分新增/编辑)
|
||||
- [ ] 3.2.6 实现删除功能(二次确认)
|
||||
- [ ] 3.2.7 实现状态开关(启用/禁用)
|
||||
- [ ] 3.2.8 实现上架状态开关(上架/下架)
|
||||
- [ ] 3.2.9 集成 API 服务并处理加载状态
|
||||
|
||||
### 3.3 代理可售套餐页面(my-packages/index.vue)
|
||||
- [ ] 3.3.1 创建页面文件和基本结构
|
||||
- [ ] 3.3.2 实现列表展示(表格、分页)
|
||||
- [ ] 3.3.3 实现搜索栏(系列、类型筛选)
|
||||
- [ ] 3.3.4 实现详情对话框(显示成本价、建议售价、利润空间)
|
||||
- [ ] 3.3.5 实现被分配系列列表Tab(可选)
|
||||
- [ ] 3.3.6 集成 API 服务并处理加载状态
|
||||
|
||||
### 3.4 单套餐分配页面(package-assign/index.vue)
|
||||
- [ ] 3.4.1 创建页面文件和基本结构
|
||||
- [ ] 3.4.2 实现列表展示(表格、分页)
|
||||
- [ ] 3.4.3 实现搜索栏(店铺、套餐、状态筛选)
|
||||
- [ ] 3.4.4 实现套餐下拉选择器(加载套餐列表,只显示启用且上架的套餐)
|
||||
- [ ] 3.4.5 实现店铺下拉选择器(使用 ShopService 加载店铺列表)
|
||||
- [ ] 3.4.6 实现新增对话框(套餐选择、店铺选择、成本价输入)
|
||||
- [ ] 3.4.7 实现编辑功能(单独对话框或复用新增对话框,只允许修改成本价)
|
||||
- [ ] 3.4.8 实现删除功能(二次确认)
|
||||
- [ ] 3.4.9 实现状态管理(启用/禁用开关)
|
||||
- [ ] 3.4.10 集成 API 服务并处理加载状态
|
||||
|
||||
## 4. 路由配置
|
||||
|
||||
- [ ] 4.1 在 asyncRoutes.ts 中添加 my-packages 路由配置
|
||||
- [ ] 4.2 验证路由权限配置正确
|
||||
|
||||
## 5. 集成测试
|
||||
|
||||
### 5.1 套餐系列管理测试
|
||||
- [ ] 5.1.1 测试列表查询(空列表、有数据、分页)
|
||||
- [ ] 5.1.2 测试搜索功能(名称模糊搜索、状态筛选)
|
||||
- [ ] 5.1.3 测试新增功能(成功、编码重复、字段验证)
|
||||
- [ ] 5.1.4 测试编辑功能(成功、字段验证)
|
||||
- [ ] 5.1.5 测试删除功能(成功、有关联套餐时禁止删除)
|
||||
- [ ] 5.1.6 测试状态切换(启用→禁用、禁用→启用)
|
||||
- [ ] 5.1.7 测试权限控制(未登录、无权限)
|
||||
|
||||
### 5.2 套餐管理测试
|
||||
- [ ] 5.2.1 测试列表查询(空列表、有数据、分页)
|
||||
- [ ] 5.2.2 测试多条件筛选(名称、系列、状态、上架状态、类型)
|
||||
- [ ] 5.2.3 测试系列下拉选择器(只显示启用状态的系列)
|
||||
- [ ] 5.2.4 测试新增功能(成功、编码重复、时长验证、流量验证)
|
||||
- [ ] 5.2.5 测试编辑功能(成功、字段验证)
|
||||
- [ ] 5.2.6 测试删除功能(成功、已分配时禁止删除)
|
||||
- [ ] 5.2.7 测试状态切换(启用→禁用、禁用→启用)
|
||||
- [ ] 5.2.8 测试上架状态切换(上架→下架、下架→上架)
|
||||
- [ ] 5.2.9 测试权限控制(未登录、无权限)
|
||||
|
||||
### 5.3 代理可售套餐测试
|
||||
- [ ] 5.3.1 测试列表查询(空列表、有数据、分页)
|
||||
- [ ] 5.3.2 测试筛选功能(按系列、按类型)
|
||||
- [ ] 5.3.3 测试详情查询(显示成本价、建议售价、利润空间、价格来源)
|
||||
- [ ] 5.3.4 测试数据隔离(只能看到分配给自己的套餐)
|
||||
- [ ] 5.3.5 测试被分配系列列表(如果实现)
|
||||
- [ ] 5.3.6 测试权限控制(非代理商用户无法访问)
|
||||
|
||||
### 5.4 单套餐分配测试
|
||||
- [ ] 5.4.1 测试列表查询(空列表、有数据、分页)
|
||||
- [ ] 5.4.2 测试筛选功能(按店铺、按套餐、按状态)
|
||||
- [ ] 5.4.3 测试套餐下拉选择器(只显示启用且上架的套餐)
|
||||
- [ ] 5.4.4 测试店铺下拉选择器(加载店铺列表)
|
||||
- [ ] 5.4.5 测试新增功能(成功、重复分配、成本价验证)
|
||||
- [ ] 5.4.6 测试编辑功能(修改成本价)
|
||||
- [ ] 5.4.7 测试删除功能(成功、有订单时的处理)
|
||||
- [ ] 5.4.8 测试状态切换(启用→禁用、禁用→启用)
|
||||
- [ ] 5.4.9 测试价格覆盖规则(单套餐分配优先于系列分配)
|
||||
- [ ] 5.4.10 测试权限控制(仅管理员可操作)
|
||||
|
||||
### 5.5 通用功能测试
|
||||
- [ ] 5.5.1 测试所有页面的表单验证(必填、长度、格式)
|
||||
- [ ] 5.5.2 测试所有页面的 loading 状态(列表、提交、删除)
|
||||
- [ ] 5.5.3 测试所有页面的错误处理(网络错误、业务错误)
|
||||
- [ ] 5.5.4 测试所有页面的二次确认(删除操作)
|
||||
- [ ] 5.5.5 测试分页功能(换页、改变每页数量)
|
||||
- [ ] 5.5.6 测试刷新功能(列表刷新)
|
||||
- [ ] 5.5.7 测试列显示/隐藏功能
|
||||
- [ ] 5.5.8 测试状态值映射(前端0/1与后端1/2的转换)
|
||||
|
||||
## 6. 代码优化和文档
|
||||
|
||||
- [ ] 6.1 代码格式化和 ESLint 检查
|
||||
- [ ] 6.2 添加必要的注释
|
||||
- [ ] 6.3 更新 API 文档(如需要)
|
||||
- [ ] 6.4 提交代码并创建 PR
|
||||
|
||||
## 注意事项
|
||||
|
||||
- 所有页面需参考 `/system/role` 页面的组件化结构
|
||||
- 使用统一的 `CommonStatus` 常量(需要注意文档中的状态值映射)
|
||||
- API 字段使用下划线命名(如 `series_name`),前端类型使用驼峰命名
|
||||
- 所有删除操作需要二次确认
|
||||
- 所有表单需要完整的验证规则
|
||||
- 统一使用 Element Plus 的 Message 和 MessageBox 组件
|
||||
Reference in New Issue
Block a user