5.1 KiB
5.1 KiB
会员卡编辑功能设计
日期: 2026-04-07 状态: 已批准
1. 概述
在管理后台会员列表中,点击会员 item 时弹出的详情弹窗增加"编辑"能力。管理员可编辑指定用户的卡种、卡有效期、剩余次数,也可清空/解除会员卡。
前置约束:
- 一个用户只能拥有一张会员卡
- 支持清空卡(解除会员资格)
2. 交互设计
2.1 弹窗结构
┌─────────────────────────────────┐
│ 会员详情 [×] │
├──────────┬──────────────────────┤
│ 详情 │ 编辑 │ ← Tab 切换
├──────────┴──────────────────────┤
│ 头像 / 昵称 / OpenID / 手机号 │
│ ───────────────────────────── │
│ 会员卡信息区(根据 Tab 显示) │
│ 预约统计(总/完成/取消) │
│ ───────────────────────────── │
│ [关闭] │
└─────────────────────────────────┘
2.2 无卡用户交互
- 详情 Tab 显示"暂无会员卡"提示
- 显示"去开卡"按钮,点击切换到编辑 Tab
- 编辑 Tab 中卡种 picker 默认选中列表第一项,有效期自动计算
2.3 状态说明
| 场景 | Tab 初始显示 | 编辑表单状态 |
|---|---|---|
| 有卡用户 | 详情 Tab | 预填充当前数据 |
| 无卡用户 | 详情 Tab(提示无卡) | 空白表单,卡种默认选中第一项 |
3. 表单字段
| 字段 | 组件 | 条件 | 说明 |
|---|---|---|---|
| 卡种 | picker | 必填 | 从 CardType 表读取,按 sortOrder 排序 |
| 剩余次数 | input (number) | TIMES / TRIAL 类型 | 默认填充卡种的 totalTimes |
| 生效日期 | date picker | 必填 | 默认当天 |
| 有效期至 | date picker | 必填 | 自动计算,支持手动调整 |
3.1 卡种切换逻辑
切换卡种时:
remainingTimes自动填充新卡种的totalTimes(TIMES/TRIAL 类型)expireDate按新卡种durationDays重新计算起始日期- 编辑器内手动修改过
expireDate时,不再自动覆盖
4. API 设计
4.1 获取用户会员卡
GET /admin/members/:userId/membership
响应:
{
"userId": "uuid",
"membership": {
"id": "uuid",
"cardTypeId": "uuid",
"remainingTimes": 10,
"startDate": "2026-01-01",
"expireDate": "2026-04-01",
"status": "ACTIVE",
"cardType": { ... }
} | null
}
4.2 创建或更新会员卡
PUT /admin/members/:userId/membership
请求体:
{
"cardTypeId": "uuid",
"remainingTimes": 10,
"startDate": "2026-04-07",
"expireDate": "2026-07-07"
}
业务逻辑:
- 若该用户已有 membership → 更新
- 若该用户无 membership → 创建新的
status由后端根据 expireDate 和 remainingTimes 自动计算
4.3 解除会员卡
DELETE /admin/members/:userId/membership
业务逻辑:
- 将 membership 的
status标记为EXPIRED(软删除,便于审计) - 不物理删除记录
5. 数据模型
5.1 会员卡状态自动计算规则
if (expireDate < now) → EXPIRED
else if (remainingTimes === 0) → USED_UP
else → ACTIVE
5.2 变更日志
通过现有的 BookingStatusHistory 表记录操作(tbd: 是否需要独立 MembershipChangeLog 表,待实现时确认)。
6. 错误处理
| 场景 | 处理 |
|---|---|
| 卡种不存在 | 后端返回 404,前端提示"卡种不存在" |
| 有效期早于生效日期 | 前端表单校验失败,提示"有效期不能早于生效日期" |
| 次数为负数 | 前端表单校验失败,提示"次数不能为负数" |
| 网络错误 | Toast 提示"网络错误,请重试" |
| 清空卡确认 | 弹出确认对话框,提示"确定要解除该用户的会员卡吗?" |
7. 涉及改动
后端
packages/server/src/membership/membership.controller.ts— 新增三个 admin 接口packages/server/src/membership/membership.service.ts— 新增getUserMembership/updateUserMembership/deleteUserMembershippackages/server/src/user/user.controller.ts— 无改动(列表接口保持不变)
前端
packages/app/src/stores/admin.ts— 新增三个 store actionpackages/app/src/pages/admin/members.vue— 将详情弹窗改造为 Tab 模式,新增编辑表单
8. UI 细节
8.1 Tab 切换
- 详情/编辑 Tab 横向排列,激活态有下划线指示
- 无卡用户点击"去开卡"后,自动切到编辑 Tab
8.2 编辑表单提交
- 保存成功后 Toast 提示"保存成功"
- 自动切回详情 Tab 并刷新数据
- 保存按钮点击后置灰,防止重复提交
8.3 清空卡
- 需二次确认
- 成功后弹窗关闭,列表自动刷新