f7cef30b9c
补齐订单、优惠券、主题、插件、公告与支付管理页面, 接入对应后台接口、路由入口与工具层类型定义。 同时修复套餐页开关初始化误写问题,避免浏览即触发写操作。 在订阅协议侧为 Stash 导出增加 AnyTLS 版本守卫, 未知版本或低于 3.3.0 时不再导出该协议,并补充回归测试与知识记录。
197 lines
10 KiB
Markdown
197 lines
10 KiB
Markdown
# 变更提案: admin-frontend-coupon-management
|
||
|
||
## 元信息
|
||
```yaml
|
||
类型: 新功能
|
||
方案类型: implementation
|
||
优先级: P1
|
||
状态: 执行中
|
||
创建: 2026-04-24
|
||
```
|
||
|
||
---
|
||
|
||
## 1. 需求
|
||
|
||
### 背景
|
||
当前 `admin-frontend` 已完成仪表盘、用户管理、节点管理、套餐管理与系统配置,但“订阅管理”分组下的“优惠券管理”仍是禁用占位。用户本轮明确要求参考 `apple/DESIGN.md`、项目级 `.helloagents/DESIGN.md` 与提供的两张参考图,继续补完真正可用的优惠券管理页面,包括列表工作台与新增/编辑弹窗。
|
||
|
||
### 目标
|
||
- 开放侧边栏中的“优惠券管理”入口,并接入真实页面与路由。
|
||
- 基于现有 Laravel `coupon/*` 接口,完成优惠券列表、搜索、类型筛选、启停、删除、新增与编辑。
|
||
- 页面视觉延续当前 Apple 化后台,尽量还原参考图中的黑白结构、紧凑表格与表单弹窗。
|
||
|
||
### 约束条件
|
||
```yaml
|
||
技术约束: 继续使用 Vue3 + TypeScript + Element Plus + Vite,不引入额外状态管理或重型日期/富文本依赖
|
||
业务约束: 后端接口仅使用现有 `/coupon/fetch` `/coupon/generate` `/coupon/update` `/coupon/drop`,不改 Laravel API
|
||
数据约束: 套餐限制项沿用现有 `/plan/fetch` 返回结果,优惠券周期限制遵循后端 legacy period 键值
|
||
视觉约束: 遵循 `apple/DESIGN.md` 与 `.helloagents/DESIGN.md`,保持与仪表盘/套餐管理同一视觉家族
|
||
```
|
||
|
||
### 验收标准
|
||
- [ ] 左侧“订阅管理”分组中的“优惠券管理”由禁用态切换为真实可点击入口,并进入独立页面。
|
||
- [ ] 优惠券管理页支持真实数据读取、关键字搜索、类型筛选、本地分页、启用开关、编辑和删除。
|
||
- [ ] “添加优惠券 / 编辑优惠券”弹窗支持名称、批量生成数量、自定义优惠码、类型和值、有效期、总使用次数、每人使用次数、指定周期与指定订阅。
|
||
- [ ] 页面中的类型标签、剩余次数、每人限制、有效期与过期提示可正确展示,并与后端字段含义一致。
|
||
- [ ] `admin-frontend` 构建通过,且知识库同步反映“优惠券管理”已从占位入口升级为真实页面。
|
||
|
||
---
|
||
|
||
## 2. 方案
|
||
|
||
### 技术方案
|
||
1. 扩展 `src/types/api.d.ts` 与 `src/api/admin.ts`,新增优惠券列表项、保存载荷、分页查询与计划选项的类型、请求封装。
|
||
2. 新增 `src/utils/coupons.ts`,集中处理优惠券类型标签、legacy period 选项、时间范围换算、表单默认值、列表本地过滤与过期文案。
|
||
3. 新增 `src/views/subscriptions/CouponsView.vue` 与 `CouponEditorDialog.vue`:
|
||
- `CouponsView` 负责黑色首屏、工具条、表格、分页、行内开关与操作按钮。
|
||
- `CouponEditorDialog` 负责新增/编辑表单、指定周期/订阅、时间范围和数值字段校验。
|
||
4. 在 `AdminLayout.vue` 与 `router/index.ts` 中启用“优惠券管理”菜单与 `/subscriptions/coupons` 路由,同时保持“订单管理 / 礼品卡管理”为未完成状态。
|
||
|
||
### 影响范围
|
||
```yaml
|
||
涉及模块:
|
||
- admin-frontend/src/layouts: 开放优惠券菜单入口
|
||
- admin-frontend/src/router: 新增优惠券管理路由
|
||
- admin-frontend/src/api: 新增 coupon 接口封装
|
||
- admin-frontend/src/types: 新增优惠券类型定义
|
||
- admin-frontend/src/utils: 新增优惠券数据转换与展示逻辑
|
||
- admin-frontend/src/views/subscriptions: 新增优惠券页面、弹窗与样式
|
||
预计变更文件: 7-9
|
||
```
|
||
|
||
### 风险评估
|
||
| 风险 | 等级 | 应对 |
|
||
|------|------|------|
|
||
| `/coupon/fetch` 的服务端筛选能力有限,关键字无法同时覆盖名称与券码 | 中 | 前端优先一次拉取合理数量后做本地搜索与分页,避免错误的 AND 过滤 |
|
||
| 编辑接口复用 `/coupon/generate`,字段与新增表单共用,空值和 legacy period 容易提交错误 | 中 | 在 `utils/coupons.ts` 中统一序列化,空数组转 `undefined`,时间统一转 Unix 秒 |
|
||
| 参考图包含较丰富的表格状态与表单布局,若实现不克制容易脱离既有后台风格 | 中 | 复用现有 Apple Admin token、表格与弹窗风格,不额外引入第二套后台皮肤 |
|
||
|
||
---
|
||
|
||
## 3. 技术设计(可选)
|
||
|
||
### 架构设计
|
||
```mermaid
|
||
flowchart TD
|
||
A[CouponsView] --> B[admin.ts coupon 接口]
|
||
A --> C[coupons.ts 展示/序列化工具]
|
||
A --> D[CouponEditorDialog]
|
||
D --> B
|
||
D --> C
|
||
D --> E[getPlans]
|
||
```
|
||
|
||
### API设计
|
||
#### GET /coupon/fetch
|
||
- **请求**: `{ current, pageSize }`
|
||
- **响应**: `{ total, current_page, per_page, last_page, data[] }`
|
||
|
||
#### POST /coupon/generate
|
||
- **请求**: `{ id?, generate_count?, name, code?, type, value, started_at, ended_at, limit_use?, limit_use_with_user?, limit_plan_ids?, limit_period? }`
|
||
- **响应**: `{ status, data }`
|
||
|
||
#### POST /coupon/update
|
||
- **请求**: `{ id, show }`
|
||
- **响应**: `{ status, data }`
|
||
|
||
### 数据模型
|
||
| 字段 | 类型 | 说明 |
|
||
|------|------|------|
|
||
| id | number | 优惠券 ID |
|
||
| show | boolean | 是否启用 |
|
||
| name | string | 优惠券名称 |
|
||
| type | 1 \| 2 | 1=按金额优惠,2=按比例优惠 |
|
||
| value | number | 金额分/折扣整数 |
|
||
| code | string | 券码 |
|
||
| limit_use | number \| null | 总可用次数 |
|
||
| limit_use_with_user | number \| null | 每人可用次数 |
|
||
| limit_plan_ids | string[] \| null | 限制套餐 |
|
||
| limit_period | string[] \| null | legacy 周期键 |
|
||
| started_at / ended_at | number | 生效时间范围(Unix 秒) |
|
||
|
||
---
|
||
|
||
## 4. 核心场景
|
||
|
||
### 场景: 运营创建单张优惠券
|
||
**模块**: admin-frontend/subscriptions
|
||
**条件**: 管理员已登录,进入 `#/subscriptions/coupons`
|
||
**行为**: 点击“添加优惠券”,填写名称、类型、金额、有效期并提交
|
||
**结果**: 新优惠券保存成功,列表刷新并展示新记录
|
||
|
||
### 场景: 运营批量生成优惠码
|
||
**模块**: admin-frontend/subscriptions
|
||
**条件**: 管理员在新增弹窗中填写 `generate_count`
|
||
**行为**: 提交批量生成请求
|
||
**结果**: 后端批量创建优惠券,前端提示成功并刷新列表
|
||
|
||
### 场景: 运营筛选并停用过期优惠券
|
||
**模块**: admin-frontend/subscriptions
|
||
**条件**: 列表中存在多种类型与已过期记录
|
||
**行为**: 使用关键字或类型筛选找到目标记录,关闭启用开关
|
||
**结果**: 对应优惠券 `show=false`,列表状态即时更新
|
||
|
||
---
|
||
|
||
## 5. 技术决策
|
||
|
||
### admin-frontend-coupon-management#D001: 优惠券列表采用真实接口 + 本地搜索/筛选/分页
|
||
**日期**: 2026-04-24
|
||
**状态**: ✅采纳
|
||
**背景**: 后端 `/coupon/fetch` 支持分页,但关键字筛选以 `where like` 串联多个字段时不适合做“名称或券码”搜索。
|
||
**选项分析**:
|
||
| 选项 | 优点 | 缺点 |
|
||
|------|------|------|
|
||
| A: 完全依赖后端筛选 | 数据量更轻 | 关键字搜索能力受限,名称/券码无法自然并行匹配 |
|
||
| B: 拉取合理数量后本地搜索/筛选/分页 | 交互更贴近参考图,搜索更灵活 | 极大数据量下效率不如纯服务端 |
|
||
**决策**: 选择方案 B
|
||
**理由**: 当前后台优惠券数量通常不大,本地处理可更稳定满足截图中的使用方式。
|
||
**影响**: `CouponsView.vue`、`admin.ts`、`coupons.ts`
|
||
|
||
### admin-frontend-coupon-management#D002: 新增与编辑共用同一弹窗,并统一序列化到 `/coupon/generate`
|
||
**日期**: 2026-04-24
|
||
**状态**: ✅采纳
|
||
**背景**: 后端没有独立的 coupon save/update 表单接口,新增与编辑都通过 `generate` 处理。
|
||
**选项分析**:
|
||
| 选项 | 优点 | 缺点 |
|
||
|------|------|------|
|
||
| A: 新增/编辑拆两套表单 | 心智更直观 | 代码重复,字段校验需要维护两份 |
|
||
| B: 共用一个表单模型与序列化逻辑 | 结构更稳定,便于维护 | 需要额外处理编辑态初始值 |
|
||
**决策**: 选择方案 B
|
||
**理由**: 与当前套餐编辑抽屉模式一致,能减少重复逻辑并提高一致性。
|
||
**影响**: `CouponEditorDialog.vue`、`utils/coupons.ts`
|
||
|
||
### admin-frontend-coupon-management#D003: 编辑态继续采用居中弹窗而非侧边抽屉
|
||
**日期**: 2026-04-24
|
||
**状态**: ✅采纳
|
||
**背景**: 参考图中优惠券编辑器为居中对话框,且字段密度更适合聚焦式表单。
|
||
**选项分析**:
|
||
| 选项 | 优点 | 缺点 |
|
||
|------|------|------|
|
||
| A: 复用抽屉模式 | 与套餐管理统一 | 与参考图差异更大,纵向表单视觉焦点分散 |
|
||
| B: 改为居中弹窗 | 更贴近参考图,聚焦更强 | 需要单独编写对话框布局样式 |
|
||
**决策**: 选择方案 B
|
||
**理由**: 这页的主要新增价值就在参考图里的“表格 + 弹窗”组合,值得贴近还原。
|
||
**影响**: `CouponEditorDialog.vue` 及其样式
|
||
|
||
---
|
||
|
||
## 6. 成果设计
|
||
|
||
### 设计方向
|
||
- **美学基调**: Apple Admin Promotions。像 Apple 后台里的运营配置页,黑色首屏负责建立业务主题,正文工作台回到白底高密度表格,让折扣配置看起来更像精密运营台而不是营销页面。
|
||
- **记忆点**: 大标题“优惠券管理”与白色表格之间形成明显的黑白切面;弹窗内部用整齐的双列字段和轻描边区块还原截图的“精密表单感”。
|
||
- **参考**: `apple/DESIGN.md`、`.helloagents/DESIGN.md`、用户上传的优惠券列表与添加弹窗截图
|
||
|
||
### 视觉要素
|
||
- **配色**: 首屏 `#000000`,工作区 `#ffffff`,页面背景 `#f5f5f7`,强调色 `#0071e3`,过期提示用浅红底 `rgba(201, 52, 40, 0.08)`
|
||
- **字体**: 延续项目现有系统字体栈,标题走大字号紧行高,表格与辅助信息维持更轻的运营化层级
|
||
- **布局**: 首屏 Hero + 工具条 + 表格工作台;编辑器采用居中弹窗,字段按双列网格排布,底部操作区固定在弹窗底部
|
||
- **动效**: 保留开关切换、弹窗开合、按钮 hover 与筛选状态切换的轻量动效,不引入额外炫技动画
|
||
- **氛围**: 工作台继续使用克制阴影、圆角白底与 Apple 式留白,避免多余卡片堆叠
|
||
|
||
### 技术约束
|
||
- **可访问性**: 交互控件保留可见焦点,状态信息不只依赖颜色,危险操作保留明确文案
|
||
- **响应式**: 桌面优先;窄屏下 Hero、工具条和弹窗网格折叠为单列,确保表单仍可完整操作
|