# Phase 1 用户故事与验收标准
> 基于 `phase1-product-plan.md` 与 `1.0产品对齐方案.md`,每个用户故事包含:标题、描述、验收标准、优先级
---
## EPIC 1:能量盘生成与展示(P0)
### US-1.1 生日输入与咨询发起
**作为** 数字能量师/C端用户
**我希望** 输入姓名和出生年月日,发起一次能量盘咨询
**以便** 获取能量盘展示和AI解读服务
**验收标准(输入表单):**
1. 输入页面包含:**被咨询者姓名**(选填,即能量盘主人姓名)、出生年份(4位数字)、月份(1-12)、日期(1-31)
2. 月份和日期支持数字键盘输入,也有下拉选择器
3. 验证:年份必须为 1900-当前年份、月份 1-12、日期根据月份合法性验证
4. 输入无效时显示具体错误提示(如"请输入正确的出生日期")
5. "想了解的问题" 输入框限制 100 字以内(输入时实时显示剩余字数)
6. 点击"开始咨询"后**先检查登录状态**:
- **未登录** → 携带 `birthday`、`name`、`questions` 参数跳转到登录页(`/pages/login/index`)
- **已登录** → 正常调用 `POST /api/consultation/start`
7. 已登录用户自动填入自己姓名和生日(用户注册时已填 `name` 和 `birth_date`),但允许修改(能量师可输入客户信息)
**验收标准(咨询会话管理):**
7. 后端按照 **userId + name + birthday** 唯一确定一条咨询记录(同用户+同姓名+同生日始终返回同一条记录)
8. 同一用户对同一姓名+生日重复点击"开始咨询",后端直接返回已有的咨询记录 + 完整聊天历史,**不创建新记录**;前端 toast 提示"已找到您之前的咨询记录"
9. 输入的姓名+生日是**全新**组合时,前端弹出确认对话框:"此姓名+生日将开启全新的能量盘咨询,确认吗?"
10. 用户确认后,后端计算完整的数字能量盘(24个位置),创建新咨询记录,并返回结果
11. 用户取消确认,停留在首页,不跳转、不创建
12. 点击"开始咨询"到能量盘渲染完成,总耗时不超过 3 秒
13. 能量盘计算全部由后端 `CalculatorService` 完成,前端只负责展示(`calculator.js` 保留为降级兜底,不作为主路径)
14. 能量盘页面 URL 可分享
### US-1.2 三角形能量盘可视化展示
**作为** 数字能量师
**我希望** 看到一个清晰、美观的数字三角形,每个位置都标有数字
**以便** 直接用于客户讲解
**验收标准:**
1. 页面展示完整的24个数字位置(8个底部输入位 A-H + 7个三角内部位 I-O + 9个外部三组位 P-X)
2. 内部三角形布局严格遵循(新字母命名):
```
O
/ \
M N
/ \ / \
I J K L
```
3. 底部输入框布局:日(2位)| 月(2位)| 年(4位),从左到右排列(已改为"日月年"顺序)
4. 外部三组以T形线段连接三角内部对应位置:
- 左侧组(R, P, Q)对应 21-40 岁,由 I, J, M 计算
- 右侧组(U, S, T)对应 61+ 岁,由 K, L, N 计算
- 顶部组(X, V, W)对应 41-60 岁,由 M, N, O 计算
5. 外部三组使用独立的计算值,非内部数字的直接重复
6. 每个数字使用单独的圆形/方形卡片展示,字体清晰易读
7. 五区使用不同背景色区分(左区/中区/右区/父源/母源/主性格)
8. 数字颜色:1-9 每个数字有独立颜色(参考能量数字配色)
9. 卓越数(11/22/33)用特殊标记突出
10. 底部显示姓名和出生日期信息
### US-1.3 能量盘数字位置命名与计算规则(对照表)
**作为** 开发团队
**我希望** 有一份完整的位置命名与计算规则对照表作为开发基准
**以便** 前后端计算逻辑一致,避免歧义
#### 1. 完整字母命名表(A-X)
##### 输入层(8位)—— 生日原始数字
| 字母 | 来源 | 示例 1990-01-15 | 说明 |
|------|------|----------------|------|
| A | 年份千位 | 1 | 年[0] |
| B | 年份百位 | 9 | 年[1] |
| C | 年份十位 | 9 | 年[2] |
| D | 年份个位 | 0 | 年[3] |
| E | 月份十位 | 0 | 月[0] |
| F | 月份个位 | 1 | 月[1] |
| G | 日期十位 | 1 | 日[0] |
| H | 日期个位 | 5 | 日[1] |
##### 内部计算层(7位)
| 字母 | 公式 | 中文名 | 旧名对照 | 视觉层级 |
|------|------|-------|---------|---------|
| I | `reduce(E+F)` | 月能量 | 旧 F | 底部左1 |
| J | `reduce(G+H)` | 日能量 | 旧 G | 底部左2 |
| K | `reduce(A+B)` | 年前半 | 旧 H | 底部右1 |
| L | `reduce(C+D)` | 年后半 | 旧 I | 底部右2 |
| M | `reduce(I+J)` | 青年综合数 | 不变 | 中层左 |
| N | `reduce(K+L)` | 晚年综合数 | 不变 | 中层右 |
| O | `reduce(M+N)` | **主性格数** | 不变 | 顶层 |
##### 外部三组(9位)
| 字母 | 公式 | 中文名 | 年龄区间 | 所属组 |
|------|------|-------|---------|-------|
| P | `reduce(I+M)` | 左侧左子(left-L) | 21-40 | 左侧 |
| Q | `reduce(J+M)` | 左侧右子(left-R) | 21-40 | 左侧 |
| R | `reduce(P+Q)` | **左侧主数(left)** | 21-40 | 左侧 |
| S | `reduce(K+N)` | 右侧左子(right-L) | 61+ | 右侧 |
| T | `reduce(L+N)` | 右侧右子(right-R) | 61+ | 右侧 |
| U | `reduce(S+T)` | **右侧主数(right)** | 61+ | 右侧 |
| V | `reduce(M+O)` | 顶部左子(top-L) | 41-60 | 顶部 |
| W | `reduce(N+O)` | 顶部右子(top-R) | 41-60 | 顶部 |
| X | `reduce(V+W)` | **顶部主数(top)** | 41-60 | 顶部 |
#### 2. 视觉布局示意
```
X
↙ ↘
V W
↙ ↘
M ───────────── N
↙ ↘ ↙ ↘
P Q S T
↙ ↘ ↙ ↘
I ─────────── J K ─────────── L
R (21-40) U (61+)
底部输入: 日 G H | 月 E F | 年 A B C D
```
#### 3. 外部三组年龄映射
| 组 | 位置 | 年龄区间 | 关联内部位 |
|----|------|---------|----------|
| 左侧组 (R, P, Q) | 三角形左外侧 | **21-40岁** | 基于 I, J, M |
| 顶部组 (X, V, W) | 三角形顶外侧 | **41-60岁** | 基于 M, N, O |
| 右侧组 (U, S, T) | 三角形右外侧 | **61+岁** | 基于 K, L, N |
#### 4. 计算精度说明
- `reduce(N)` 定义:各位数字相加归约至个位,但 11/22/33 保留为卓越数
- 所有 `+` 操作符均先执行普通加法,再调用 `reduce()` 归约
- 外部三组**必须使用独立的归约计算**,不得直接引用内部数字值
#### 5. 后端 API 返回结构(`POST /api/consultation/start` 响应示例)
```json
{
"recordId": 42,
"isNew": false,
"chartData": {
"positions": {
"I": 1, "J": 2, "K": 3, "L": 4,
"M": 5, "N": 6, "O": 7,
"P": 8, "Q": 9, "R": 1,
"S": 2, "T": 3, "U": 4,
"V": 5, "W": 6, "X": 7
},
"mainCharacter": 7,
"isMasterNumber": false
},
"messages": []
}
```
---
### US-1.4 数字点击查看含义
**作为** 数字能量师
**我希望** 点击三角形中的每个数字可以查看该位置的含义和能量解读
**以便** 快速向客户解释能量盘
**验收标准(交互):**
1. 点击三角形中任一数字卡片(A-X 任一位置),从屏幕底部弹出该位置的详细面板
2. 点击效果分为两层:
- 轻点数字卡片 → 弹出解释面板
- 面板弹出时,数字卡片高亮状态(边框发光 + 放大 1.1 倍)
3. 打开新面板时自动关闭前一个面板
4. 关闭方式:点击面板外部遮罩区 / 点击关闭图标 / 再次点击同一数字
5. 关闭面板后高亮状态取消
**验收标准(面板内容):**
6. 面板标题区域显示位置名称(如"主性格")、字母编号(如 O)、对应数字
7. 面板内容按 Tab 切换展示:
- **Tab 1 - 含义**:该位置的核心能量含义(如"主性格:代表一个人与生俱来的天赋和性格特质")
- **Tab 2 - 特征**:该数字在该位置的具体性格/运势描述(如"O=7 代表分析力强、追求真理")
- **Tab 3 - 建议**:该位置该数字的注意事项和提升建议
8. 面板底部显示数字的能量强弱 / 吉凶指示(如"吉数 ★★★★☆")
9. 若该位置数字与相邻位置形成特定组合,面板顶部提示"该数字与 X 形成 XX 组合",可点击查看组合含义
10. 面板内容中的"组合"和"特征"描述,后续可通过管理后台配置
**验收标准(交互细节):**
11. 面板高度不超过屏幕 60%,内容可滚动
12. 面板弹出动画:从底部平滑滑入(300ms ease-out)
13. 连续快速点击不同数字时,面板内容直接替换,不重复弹入动画
14. 面板支持手势下滑关闭(drag-to-dismiss)
---
## EPIC 2:分享与导出(P0)
### US-2.1 能量盘分享图片
**作为** 数字能量师
**我希望** 将能量盘生成为一张精美的图片,分享到微信或保存到相册
**以便** 发给客户或在朋友圈展示
**验收标准(入口与权限):**
1. 分享按钮位于能量盘展示页底部,始终可见
2. 点击分享按钮,底部弹出分享方式选择菜单:
- "保存到相册"
- "分享给微信好友"
- "分享到朋友圈"
3. 免费用户每日限制分享 1 次,点击后显示剩余次数(如"今日还剩 1 次")
4. 免费用户用完今日次数后,按钮置灰,提示"升级能量师享无限次分享"
5. 已付费用户不限次数,不显示剩余次数
**验收标准(分享卡片生成):**
6. 分享卡片在客户端生成(使用 canvas 绘图),不依赖后端
7. 卡片内容包含:
- 顶部:品牌 Logo + "数字能量命理分析" 标题
- 中部:三角能量盘图(颜色和样式与 app 内一致)
- 底部:用户姓名 + 出生日期 + 生成日期
- 右下角:小字水印(平台名称/二维码)
8. 卡片设计使用样式指南中的品牌色系统(主色 #B8860B / 金色系)
9. 横向卡片比例 4:3,宽度适配主流手机屏幕(建议 1080px 基准)
**验收标准(保存与分享):**
10. 保存到相册:调用 `uni.saveImageToPhotosAlbum`,保存成功后 toast 提示"已保存到相册"
11. 分享给微信好友:调用 `uni.share`(或小程序原生转发),携带卡片图片和默认文案"看看你的数字能量盘"
12. 分享到朋友圈:调用小程序端朋友圈分享 API(走官方渠道)
13. 分享后返回 app 时,若为免费用户则扣除当日次数,显示更新后的剩余次数
**验收标准(限制与风控):**
14. 免费用户每日分享**到微信/朋友圈**的次数在服务端记录,防止客户端篡改
15. 分享次数限制仅对"分享到微信/朋友圈"生效;**保存到相册**不限制次数(客户端canvas生成无法强控)
16. 每日 0 点重置次数,后端接口 `POST /api/user/share-quota` 返回当日剩余次数
17. 分享卡片不得包含用户微信号、手机号等敏感信息
### US-2.2 能量盘PDF导出
**作为** 数字能量师
**我希望** 将能量盘导出为 PDF 文件,可以直接打印或微信发送
**以便** 客户获得正式的纸质/电子版报告
**验收标准(权限与入口):**
1. "导出 PDF" 按钮位于能量盘展示页顶部操作栏(仅已付费用户可见)
2. 未付费用户点击不可见或置灰 + 提示"升级能量师可导出 PDF 报告"
3. 点击后出现加载指示器(loading + 进度百分比),防止重复点击
4. 生成过程不超过 5 秒,超过 5 秒则显示"生成较慢,请稍候…"
**验收标准(PDF 内容与排版):**
5. PDF 采用 A4 竖版(210mm × 297mm),页边距上下 15mm、左右 12mm
6. 第一页内容按以下布局:
- 头部:品牌 Logo + "数字能量命理分析报告" 标题(居中)
- 副标题:生成日期 + 报告编号(格式:YYYYMMDD-XXXXX)
- 用户信息区:姓名 / 出生日期 / 主性格数字
- 三角能量盘图:占页面 40% 高度,清晰可辨各位置数字
- 表格区:24 个位置的字母编号、数字值、位置名称三列展示
- 左中右三区标注:左侧(21-40 岁)/ 顶部(41-60 岁)/ 右侧(61+ 岁)
7. PDF 使用品牌色系(金色 #B8860B 为标题色,深棕色 #4A3728 为正文字体)
8. PDF 支持中文显示,字体嵌入(或使用系统黑体/宋体)
9. 如有能量盘批注内容(US-7.1),在 PDF 第二页以附录形式呈现
**验收标准(导出流程):**
10. PDF 由后端生成(通过 iText 或 Apache PDFBox 库),前端仅发起请求
11. 前端调用 `POST /api/export/pdf` 传入 `chartId`,后端返回 PDF 文件流
12. 前端接收文件流后,使用 `uni.openDocument` 打开微信文件预览
13. 微信文件预览界面支持:转发给好友 / 保存到本地 / 发送到电脑
14. 导出记录保存在数据库 `export_logs` 表,便于统计
**验收标准(限制):**
15. 已付费用户导出 PDF **不限制次数**
16. 同一能量盘重复导出不重新生成,直接返回已缓存的文件(缓存有效期 7 天)
---
## EPIC 3:AI 解读(P0)
### US-3.1 AI 解读展示
**作为** 数字能量师
**我希望** 在能量盘生成后,看到由AI自动生成的完整文字解读
**以便** 直接发给客户或稍作润色后使用,节省自己查资料写解读的时间
**验收标准:**
1. 能量盘展示页底部有"查看AI解读"按钮,点击跳转到AI解读页
2. 解读内容通过 **Dify Workflow**(工作流)生成,技术架构详见**附录B**
3. 前端调用后端 `POST /api/chart/interpret`,后端转发至 Dify Workflow API(`POST /v1/workflows/run`)
4. 首次加载等待时间 < 10 秒(含 Dify Workflow 执行时间);超过 8 秒显示"AI 正在深度分析中,请稍候…"
5. 加载过程中显示骨架屏或loading动画,避免用户以为卡死
6. 解读内容至少包含以下章节:
- **主性格解读**:顶端数字的核心特质、性格描述、代表人物
- **左区(21-40岁)**:早年运势、成长环境(对应 P/Q/R 位置)
- **顶部(41-60岁)**:中年事业、人际关系(对应 V/W/X 位置)
- **右区(61+岁)**:晚年成就、财运趋势(对应 S/T/U 位置)
7. 每个章节独立卡片展示,可折叠展开
8. 解读内容基于能量盘的实际数字,同一数字对不同能量盘解读不同(位置差异)
9. 页面底部显示"本解读由AI生成,仅供参考"的免责声明
10. Dify Workflow 输出解析:后端收到 Dify 返回的 `data.outputs` JSON 后,原样或稍作格式化后返回前端
### US-3.2 AI 解读的免费/付费控制
**作为** 平台运营者
**我希望** 控制AI解读功能的免费与付费边界
**以便** 激励用户订阅C端年费或能量师年费
**验收标准:**
1. 未付费用户点击"查看AI解读"时,仅显示**主性格概要**(1段文字)
2. 未付费用户每日可查看主性格概要 1 次(**此配额与 US-3.4 的 3 轮 AI 问答独立计数,互不消耗**)
3. 五区完整解读仅在已付费后可用(C端¥131或能量师¥1,314+)
4. 解读页底部显示"¥131 开通完整解读"引导卡片(免费用户可见)
5. 已付费用户可无限次查看完整解读
6. 每次解读请求记录到数据库,用于成本控制和限流
### US-3.4 AI 交互问答(免费/付费控制)
**作为** 平台运营者
**我希望** 控制AI问答互动功能的免费次数,且限定在同一个能量盘上
**以便** 防止用户通过切换生日绕过每日限制,同时保证体验清晰可预期
**验收标准(配额控制):**
1. 未付费用户每日可进行 3 轮 AI 问答互动(每日配额全局统一,不按能量盘拆分)
2. 此 3 轮互动**绑定到当前咨询的能量盘上**,用户不能通过创建多个生日能量盘来获得额外免费次数
3. 已付费用户不受次数限制
4. 用户在能量盘页顶部看到剩余次数提示:"今日 {{usedChats}}/{{maxChats}} 轮"
5. 当用户在已用满3次的能量盘上新建**另一个生日**的咨询时:
- 前端弹出确认对话框
- 对话框提示:"此生日将开启全新的能量盘咨询,今日剩余互动次数仍为 0 次,确定吗?"
- 用户确认后创建新咨询,次数不重置
6. 超出每日次数后,AI 输入框和快捷问题按钮隐藏,显示引导卡片:"今日 AI 解读次数已用完,开通会员享无限次"
7. 每日次数在 `lastQuotaDate` 跨日时自动归零
**验收标准(Dify Chatflow 集成):**
8. 问答交互通过 **Dify Chatflow**(对话工作流)实现,详见**附录B**
9. 前端调用 `POST /api/chat/send` 发送用户消息,传入 `{ chartId, message }`
10. 后端 `ChatService` 将消息转发至 Dify Chatflow API(`POST /v1/chat-messages`)
11. Chatflow 保持多轮对话上下文(通过 Dify 的 `conversation_id`),无需后端自行维护会话历史
12. 后端在首次向 Dify 发送消息时,将能量盘 24 个数字(A-X)作为 Chatflow 的 `inputs` 传入,后续轮次无需重复传入
13. Dify Chatflow 返回的答案中,如果包含数字能量学专业术语,后端不做二次处理,直接透传
14. 后端每次问答调用前检查用户配额(未付费用户当日≤3轮),超限则不调用 Dify,直接返回错误码
### US-3.3 解读内容缓存
**作为** 系统
**我希望** 同一能量盘的重复解读请求不重复调用LLM API
**以便** 控制成本,避免同一能量盘每次查看都消耗API费用
**验收标准:**
1. 首次生成解读后,将解读内容与能量盘ID绑定存储到数据库
2. 后续同一能量盘再次查看解读时,直接从数据库读取,不调用LLM
3. 用户可在AI解读页右上角菜单中点击"重新生成解读",覆盖旧的缓存内容(重新调用 Dify Workflow)
4. 解读缓存永久保留,不自动过期
5. 重新生成时弹出确认框:"重新生成将覆盖已有解读内容,确定吗?"
---
## EPIC 4:付费与订阅(P0)
### US-4.1 能量师付费订阅
**作为** 数字能量师
**我希望** 看到清晰的定价方案并进行年费支付
**以便** 获得AI完整解读、分销推广等全部功能
**验收标准:**
1. 付费入口:未付费用户在首页/能量盘页/解读页/分享时均会看到升级引导
2. 付费页展示:
- 功能对比表(普通用户 vs 能量师)
- 价格:种子价 ¥1,314 / 标准价 ¥1,986(通过 `POST /api/pricing/current` 获取)
- 种子价提示:根据 `seedReason` 展示不同文案
- `eligible`:"仅剩 XX 个种子名额" + "有效期至 YYYY-MM-DD"
- `not_founder_code` / `no_referrer`:"种子价仅限创始人邀请用户"
- `expired`:"种子价活动已结束"
- `quota_full`:"种子名额已满"
- "立即开通"支付按钮
3. 通过微信支付完成订阅
4. 支付成功后,用户状态即时更新(`vipEndTime += 365天`)
5. 支付成功后,自动生成专属6位推广码(如无已有)
6. 支付成功后,自动跳转到分销面板(或引导页)
7. 支付失败显示友好提示
### US-4.2 种子价自动判断
**作为** 平台
**我希望** 系统自动判断用户是否享受种子价
**以便** 运营策略自动化,无需人工干预
**种子会员定义:**
种子会员 = 在种子价**有效期内**且**名额未满**时,以种子价(¥1,314)付费成为能量师的用户。
**验收标准:**
1. 用户在支付页看到的价格由后端接口 `POST /api/pricing/current` 返回,前端不做判断
2. `isSeedPrice = true` 需**同时满足两个条件**:
- **条件① 有效期**:当前时间 ≤ `sys_config.pricing.practitioner.seed_period_end`(种子价有效期截止时间)
- **条件② 名额**:已以种子价付费的能量师记录数 < `sys_config.pricing.practitioner.seed_limit`(默认 300)
3. 两个条件任一不满足 → `isSeedPrice = false`,返回标准价
4. 种子价名额计数方式:统计 `orders` 表中 `product_type='practitioner'` AND `status='paid'` AND `is_seed_price=true` 的记录数
5. 订单创建时将种子价状态锁定(`is_seed_price` 写入订单,不因后续条件变化而改变)
6. 有效期过期后,即使名额未满,所有新用户看到标准价
7. 名额满后,即使仍在有效期内,所有新用户看到标准价
8. 种子价名额上限和有效期均可在管理后台动态修改(`pricing.practitioner.seed_limit`、`pricing.practitioner.seed_period_end`)
### US-4.3 订阅状态与续费
**作为** 付费能量师
**我希望** 在个人中心看到我的订阅状态、到期日,并能续费
**以便** 管理我的会员身份
**验收标准:**
1. 个人中心("我的"页面)显示用户头像、昵称、角色标签(普通用户/C端年费/能量师 🌟)
2. 角色标签使用暗金色 #C9A84C,字体 12px
3. 用户卡片下方按角色显示**会员状态卡片**:
- **普通用户**(`vipType=NULL`):品牌色(墨蓝 #1E3A5F)渐变卡片 + 权益摘要(3-4项)+ "立即开通 ¥131/年"按钮
- **C端年费**(`vipType='annual'`,有效期内):橙色渐变卡片 + "已开通C端会员" + 有效期 + "升级能量师"按钮
- **能量师**(`vipType='practitioner'`,有效期内):紫色渐变卡片 + "能量师会员 🌟" + 有效期 + "续费"按钮
- **已过期**(`vipEndTime < now`):灰色卡片 + "已过期"标记 + "重新开通"按钮
4. 种子价会员在状态卡片下方额外显示"🌱 种子价专属标记"(暗金文字,淡金色背景)
5. 到期前 7 天在状态卡片上方显示黄色 banner:"⏰ 您的会员即将到期,请及时续费"
6. 资料不完整的用户(`profile_incomplete = true`)在状态卡片上方显示引导 banner:"📝 请完善个人资料,开启能量匹配"
7. 到期后自动降级为普通用户,分销面板入口隐藏
8. 续费操作按**标准价**执行(种子价仅限首次)
9. 续费成功后有效期在原到期日基础上延长1年
### US-4.4 年费升级能量师(升级定价与流程)
**作为** C端年费用户
**我希望** 从年费升级为能量师时,按已付年费的剩余价值抵扣差价
**以便** 不需要重复支付已经买过的部分
**验收标准(升级定价):**
1. 用户现有 `vipType='annual'` 且 `vipEndTime > now`,可在"我的"页面 → 会员状态卡片(C端年费)点击"升级能量师"按钮
2. 升级价格由后端计算,公式:
```
已付年费金额 = 该用户最近一笔 annual 订单的 amount(默认 ¥131)
已用天数 = 从 annual 支付成功日到当前日的天数
剩余价值 = 已付年费金额 × (365 - 已用天数) / 365
升级价格 = 当前能量师定价(种子/标准)− 剩余价值
```
3. 计算示例:用户 B 在 1月1日付 ¥131,第100天升级(种子价 ¥1,314):
```
剩余价值 = ¥131 × (365-100)/365 = ¥95.11
升级价格 = ¥1,314 − ¥95.11 = ¥1,218.89
```
4. 升级价格 < 0(理论极限)→ 按 ¥0.01 收取
5. 升级后 `vipType` 从 `'annual'` 变更为 `'practitioner'`
6. 升级后 `vipEndTime` 按能量师续费规则处理(在原能量师到期日 +365天,不叠加年费剩余天数)
7. 升级不享受种子价(种子价仅限首次购买 practitioner,见 US-4.2)
8. 升级后推广码不变(如之前已有推广码)
**验收标准(前端流程):**
9. 个人中心 → 升级能量师 → 展示升级详情卡片:
- 原年费支付金额:¥131
- 年费剩余价值:¥95.11("已使用 100/365 天")
- 能量师当前定价:¥1,314
- 应付差价:¥1,218.89
- 支付按钮:"支付 ¥1,218.89"
10. 升级详情卡片下方附带**权益对比**(精简表格),说明能量师相比年费额外获得的能力:推广能量师赚固定佣金(¥500+¥100)、客户批注与标签管理等
11. 点击支付 → 调 `POST /api/pay/create` 传 `{ productType: 'practitioner', isUpgrade: true, previousOrderId: xxx }`
12. 支付成功后调 `paySuccess()` → `vipType` 更新 + 佣金结算(见 US-6.3 升级场景)
**验收标准(接口):**
13. `POST /api/pricing/upgrade` 新增接口:传入 `userId`,返回升级价格详情
14. `POST /api/pay/create` 新增字段:
- `isUpgrade: boolean`
- `previousOrderId: Long`(原年费订单ID,用于佣金补差)
---
## EPIC 5:用户注册与资料(P1)
### US-5.1 微信登录 + 注册信息完善
**作为** 用户
**我希望** 通过微信授权一键登录,随后补充生日和性别完成注册
**以便** 使用能量盘分析和未来的能量匹配社交功能
**验收标准(微信授权登录):**
1. 首次使用点击登录按钮时,弹出微信授权(`uni.login` 获取 code)
2. 授权后自动获取微信昵称和头像(`uni.getUserProfile`),用户可修改
3. 用户拒绝授权昵称/头像时,仍然可以使用 code 登录,昵称默认为"微信用户"
4. 后续使用自动登录(token 未过期时跳过授权)
5. 首次登录后端返回 `{ token, isNewUser: true, profileIncomplete: true }`
6. 老用户登录返回 `{ token, isNewUser: false, profileIncomplete: false }`
7. 老用户(旧版未填生日/性别的)返回 `{ token, profileIncomplete: true }`,引导补全资料
**验收标准(注册信息完善页):**
8. 新用户或资料不全的用户,微信授权后自动跳转到**注册完善页**(非首页)
9. 注册完善页表单包含以下字段:
| 字段 | 必填 | 预填 | 说明 |
|------|------|------|------|
| 头像 | 是 | 微信头像 | 可点击更换(从相册选择) |
| 昵称 | 是 | 微信昵称 | 1-20 字 |
| 性别 | 是 | 空 | 男 / 女,radio 选择 |
| 出生日期 | 是 | 空 | 年月日选择器,同能量盘生日 |
| 个人简介 | 否 | 空 | 限 100 字,用于社交展示 |
| 所在城市 | 否 | 空 | 微信定位或手动选择 |
| 兴趣标签 | 否 | 空 | 多选:读书/运动/音乐/旅行/禅修/创业/心理学/玄学 |
| 想认识 | 否 | 空 | 单选:不限 / 朋友 / 导师 / 同修 |
10. 点击"提交"调用 `POST /api/profile/complete` 保存所有资料
11. 提交后标记用户 `profile_complete = true`
12. 提交成功后跳转到首页,进入正常使用流程
13. 资料不完整的用户在个人中心显示引导 banner:"请完善个人资料,开启能量匹配"
14. 用户可随时在个人中心 → 编辑资料 修改所有字段
**验收标准(后端与数据库变更):**
15. `users` 表新增字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `gender` | `TINYINT` | 0=未知, 1=男, 2=女 |
| `birth_date` | `DATE` | 出生日期(用于能量盘+社交) |
| `bio` | `VARCHAR(200)` | 个人简介 |
| `city` | `VARCHAR(50)` | 所在城市 |
| `tags` | `VARCHAR(200)` | 兴趣标签,逗号分隔 |
| `looking_for` | `TINYINT` | 0=不限, 1=朋友, 2=导师, 3=同修 |
| `profile_complete` | `TINYINT(1)` | 0=资料未完善, 1=资料已完善 |
| `birth_year` | `INT` | 出生年份(冗余,从 birth_date 提取) |
| `birth_month` | `INT` | 出生月份(冗余) |
| `birth_day` | `INT` | 出生日期(冗余) |
16. `POST /api/auth/login` 响应增加 `profileIncomplete` 字段
17. 新增 `POST /api/profile/complete` 接口,接收所有注册字段
18. 新增 `POST /api/profile/update` 接口,允许修改任意字段
19. `POST /api/profile/info` 响应增加全部新字段,额外新增 `isSeedPriceUser`(Boolean — 当前用户是否以种子价购买的能量师)
**验收标准(老用户兼容):**
20. 已注册的老用户登录时,如果 `profile_complete = false`,登录后显示完善引导
21. 老用户不强制立即完善,可以正常使用能量盘功能
22. 老用户在个人中心中看到"完善资料"入口和引导
### US-5.2 历史咨询记录
**作为** 能量师
**我希望** 查看我过去的所有咨询记录
**以便** 回顾和继续之前的咨询
**验收标准:**
1. "我的"页面 → "我的服务"分组包含两个入口:
- "📋 我的分析" → 跳转到咨询记录列表页
- "🔮 我的能量盘" → 跳转到我的能量盘列表页
2. 我的能量盘:
- 展示所有**姓名与当前用户注册姓名一致、生日与当前用户注册生日一致**的咨询记录
- 即:`chart_record.name == user.name AND chart_record.birthday == user.birth_date`
- 若用户修改过注册姓名,旧的我的能量盘变为普通咨询记录
- 列表样式与"我的分析"相同(姓名、生日、咨询时间、最后一条消息摘要)
3. 我的分析(历史咨询记录列表)按最后互动时间倒序排列
4. 点击记录可跳转到对应的能量盘展示页,并恢复完整的聊天历史
5. 支持单条删除
6. 同一用户+同一姓名+同一生日永远返回同一条咨询记录(`(userId, name, birthday)` 联合唯一)
7. 免费用户仅能看到近 7 天记录,已付费用户可见全部
**验收标准(个人中心统计卡片):**
8. "我的"页面 → 用户卡片下方增加**统计卡片区**,根据不同用户角色展示不同统计项:
| 角色 | 展示统计项 | 数据来源 |
|------|-----------|---------|
| 普通用户 | 累计咨询次数、今日剩余AI问答次数 | `chart_records` 计数 + `daily_quota` |
| C端会员 | 累计咨询次数、累计推广收益(元)、推广人数 | `chart_records` + `commissions` 汇总 |
| 超级会员 | 累计咨询次数、累计推广收益(元)、关系人数 | `chart_records` + `commissions` + `relations` 计数 |
| 能量师 | 累计咨询次数、累计推广收益(元)、客户数、本月收入(元) | `chart_records` + `commissions` + 各表汇总 |
9. 统计卡片样式:
- 浅灰蓝背景 `#F7F8FC`,圆角 `12px`,内边距 `16px`
- 每项统计显示:数字(大号加粗)+ 标签(小号灰色文字)
- 多统计项水平等宽排列
10. 数字为 0 时正常显示"0",不隐藏
11. 所有统计值后端计算返回(`POST /api/profile/stats`),前端仅做渲染
### US-5.3 个人资料编辑(为陌生社交准备)
**作为** 用户
**我希望** 在个人中心编辑我的昵称、头像、简介、标签、城市等资料
**以便** 未来通过能量匹配结识志同道合的朋友
**验收标准:**
1. "我的"页面 → 用户卡片 → 头像旁的✏️图标(或文字链接)→ 跳转到编辑资料页
2. 编辑页包含:头像、昵称、性别、生日、简介、城市、兴趣标签、想认识
3. 资料字段定义同 US-5.1 注册完善页
4. 修改后调用 `POST /api/profile/update`
5. 修改成功后本地更新并提示"保存成功"
6. **陌生社交广场和能量匹配功能不属于 Phase 1,此处仅预留用户资料字段**
注:能量匹配社交将根据用户的能量盘主性格数(O)、外部三组数(R/U/X)等计算能量兼容度,推荐匹配用户。此功能在 Phase 2 规划。
---
## EPIC 6:分销推广与佣金(P0-P1)
### US-6.1 推广码生成(付费后生成)
**作为** 付费用户(C端 / 能量师)
**我希望** 在首次付费后自动获得专属推广码
**以便** 分享给微信好友来发展下级并赚取佣金
**验收标准:**
1. 推广码在**注册时不生成**,仅在**首次支付成功后**生成(¥131年费 / ¥1,314+能量师费任一触发)
2. 推广码规则:6位大写字母+数字,字符集去掉易混淆的 `O/0/I/1`(即 `ABCDEFGHJKLMNPQRSTUVWXYZ23456789`)
3. 推广码冲突时自动重新生成,保证全局唯一
4. 推广码永久有效,不随年费到期失效
5. 普通用户(未付费)没有推广码,也没有分销入口
6. 推广码展示在分销面板顶部,支持一键复制和生成推广海报
7. 推广码下游用于:分享带参注册(US-6.2)和佣金结算(US-6.3 / US-6.4)
---
### US-6.2 分享带参注册与上下级绑定
**作为** 平台
**我希望** 当用户通过推广链接/扫码打开小程序时,自动记录上下级关系
**以便** 为佣金分成打好基础
**验收标准:**
**验收标准(分享链路与前端缓存):**
1. 推广链接格式:`/pages/index/index?ref=ABC123`(6位推广码)
2. 分享卡片 / 小程序码同样携带 `ref` 参数
3. 用户通过推广链接打开小程序时,`onLoad(options)` 读取 `options.query.ref`,转为大写后写入缓存 `pending_referrer`
4. **每次点击新链接都覆盖**已有值,以用户**最后一次点击的链接**为准
5. `pending_referrer` **仅在用户完成微信登录后**才提交到后端建立关系,**不登录不建立关系**
6. 登录成功后立即清除 `pending_referrer`(无论绑定成功与否)
7. 登录中途中断(拒绝授权)→ 不清除 `pending_referrer`,下次触发登录仍携带
**前端流程(咨询→登录→关系绑定):**
8. 用户打开首页(`index/index.vue`)→ 填写姓名、生日、问题 → **无需登录**
9. 点击"开始咨询" → **检查 token**:
- 未登录 → 携带参数 `birthday`, `name`, `questions` 跳转到登录页 `login/index.vue`
- 已登录 → 直接调用 `POST /api/consultation/start`
10. 登录页流程:
- 微信授权登录成功 → 从 `pending_referrer` 读取推广码提交后端 → 清除缓存
- 登录成功且是**首次注册用户**(`profileIncomplete=true`)→ 弹出**资料完善浮层**,预填首页传入的 `birthday` 和 `name`
- 浮层允许用户 **保存** 或 **跳过**
- 资料完善后(保存或跳过)→ 继续进入能量盘页
11. 始终不登录的用户(关闭登录页)→ `pending_referrer` 保留但**永不使用**,无关系绑定
**后端注册逻辑(`UserService.loginOrRegister()`):**
12. 用户不存在(新用户)+ `referrerCode` 有效 → `invitedBy = 上级ID`
13. 用户不存在 + `referrerCode` 无效 → `invitedBy = null`(静默降级,不报错)
14. 用户不存在 + `referrerCode` 为空 → `invitedBy = null`(正常注册)
15. 用户不存在 + `referrerCode` 为**自己的新openid** → `invitedBy = null`(防止自邀请)
16. 用户**已存在** → 忽略所有 `referrerCode`,不覆盖已有 `invitedBy`(关系一次性锁定)
17. `referrerCode` 查询不到对应上级 → 静默跳过,不抛异常
**数据库更新:**
18. 绑定成功后,如果上级存在,`inviter.directCount += 1`(实时更新统计字段)
**边界与异常:**
19. 注册接口网络失败 → 保留 `pending_referrer`,重试时继续携带
20. 同一设备切换微信账号 → 新的 openid 按新用户处理,正常绑定关系
---
### US-6.3 B端佣金结算(能量师→能量师,固定金额)
**作为** 平台
**我希望** 当能量师A的下级B升级为能量师时,自动结算固定金额佣金
**以便** 能量师获得推广收益
**验收标准:**
**触发条件:**
1. 订单 `productType = "practitioner"` 且支付成功 → 进入 B端佣金结算流程
2. 订单 `productType = "annual"` → 走 US-6.4 C端佣金(互斥分支)
**佣金计算——按推荐人身份分两种情况:**
3. **推荐人 A 是能量师(`vipType='practitioner'`)** → 按标准固定金额:
| 级别 | 默认值 | 配置键 |
|------|--------|--------|
| L1(直接上级) | ¥500 | `commission.practitioner.l1` |
| L2(上上级) | ¥100 | `commission.practitioner.l2` |
4. **推荐人 A 是 C端年费用户(`vipType='annual'`)** → L1 拿半额:
| 级别 | 默认值 | 配置键 |
|------|--------|--------|
| L1(直接上级) | ¥200 | `commission.practitioner.l1_cend` |
| L2(上上级) | ¥100(不变) | `commission.practitioner.l2` |
5. 推荐人 A 既不是能量师也不是 C端年费(`vipType=null` 等异常情况)→ L1/L2 不创建佣金
6. 佣金单位为**分**(避免浮点精度问题)
**升级场景佣金补差(`isUpgrade=true`):**
7. 当订单标记 `isUpgrade=true`(从年费升级到能量师),L1/L2 佣金需**扣除**已支付过的年费佣金:
```
应发佣金 = 本次应发金额 − 该买家此前 annual 订单已支付给同一收款人的佣金总额
```
8. 计算逻辑:
- 查询 `commissions` 表中,同一 `buyer_id` + 同一 `收款人` 且 `product_type='annual'` 的所有佣金之和
- 从本次 practitioner 佣金中减去该金额
- 若差值 ≤ 0(理论情况),则本条佣金不创建
9. 示例——首次直接购买能量师(非升级,对比参考):
```
用户C为新用户(无年费记录),通过上级A(能量师)链接直接购买能量师 ¥1,314
isUpgrade = false → 全额发放:L1 = ¥500,L2 = ¥100
无年费佣金可扣除
```
10. 示例——年费升级补差:
```
用户B第1天付¥131(annual),上级A获¥52.40(40%)
用户B第100天升级能量师(种子价¥1,314),上级A是能量师→应发¥500
实际发放:¥500 − ¥52.40 = ¥447.60
```
10. 示例——C端推荐人升级补差:
```
用户B第1天付¥131(annual),上级A(C端)获¥52.40(40%)
用户B第100天升级能量师,上级A是C端→应发半额¥200
实际发放:¥200 − ¥52.40 = ¥147.60
```
**收款人资格:**
11. L1:`buyer.invitedBy` 对应的上级存在 → 按上述规则计算
12. L2:上级的 `invitedBy` 对应的上上级存在 → 按上述规则计算(L2 不因身份打折,仅 L1 打折)
13. 收款人不存在时 → 静默跳过,不报错
**状态与幂等:**
14. 佣金 `status` 直接写入 `"settled"`(即时到账,无 pending 冷静期)
15. 同一 `outTradeNo` 重复回调 → 幂等处理,不创建重复佣金
16. 佣金固定金额不受种子价/标准价差异影响(C端半额同样固定)
**统计更新:**
17. L1 创建时:`inviter.directCount += 1`,`inviter.convertedCount += 1`
18. L2 创建时:`inviter2.indirectCount += 1`
**配置项(后台可配):**
| 配置键 | 默认值 | 说明 |
|--------|--------|------|
| `commission.practitioner.l1` | `50000` | B端一级佣金—能量师推荐(分) |
| `commission.practitioner.l1_cend` | `20000` | B端一级佣金—C端推荐(分) |
| `commission.practitioner.l2` | `10000` | B端二级佣金(分) |
---
### US-6.4 C端佣金结算(年费推荐,比例分成)
**作为** 平台
**我希望** 当C端用户B通过上级A的链接注册并付费 ¥131 时,自动按比例分成
**以便** 激励所有付费用户推广
**验收标准:**
**触发条件:**
1. 订单 `productType = "annual"` 且支付成功 → 进入 C端佣金结算流程
**佣金计算:**
2. 直接佣金(L1):`totalFee × directRate / 10000`,从 `sys_config` 读取 `commission.annual.direct_rate`(默认 `4000` = 40%)
3. 上级佣金(L2):`totalFee × upstreamRate / 10000`,从 `sys_config` 读取 `commission.annual.upstream_rate`(默认 `500` = 5%)
4. 金额计算使用**整数截断**(非四舍五入),剩余零头归平台
> **注意**:年费佣金在后续用户升级能量师时可能被部分抵扣(见 US-6.3 升级补差逻辑)。`paySuccess()` 记录原始佣金(用于后续补差计算),补差逻辑在升级时执行。
> 因此 C端佣金的 `status` 仍直接写入 `"settled"`,不需要等待升级再结算。若后续升级,再由 US-6.3 扣除已付金额。
**收款人资格(与 B端不同):**
5. L1:`buyer.invitedBy` 对应的上级**必须已付费**(`referralCode != null`),才创建佣金
6. L2:上级的 `invitedBy` 对应的上上级**必须已付费**(`referralCode != null`),才创建佣金
7. C端佣金**不要求**收款人是"能量师"(practitioner),只要曾经付费即可
**状态与幂等:**
8. 佣金 `status` 直接写入 `"settled"`
9. 幂等处理同 US-6.3
**与 B端的差异:**
10. C端佣金不更新 `directCount/convertedCount/indirectCount`(这些统计仅用于B端"升级能量师")
11. C端佣金比例灵活(后台可配 0%~100%),B端固定金额
**每笔 ¥131 分配示例:**
| 分配对象 | 比例 | 金额 |
|---------|------|------|
| 直接上级 | 40% | ¥52.40 |
| 上上级 | 5% | ¥6.55 |
| 平台 | 55% | ¥72.05 |
**配置项(后台可配):**
| 配置键 | 默认值 | 说明 |
|--------|--------|------|
| `commission.annual.direct_rate` | `4000` | C端直接佣金比例(万分比,4000=40%) |
| `commission.annual.upstream_rate` | `500` | C端上级佣金比例(万分比,500=5%) |
---
### US-6.5 分销面板
**作为** 能量师
**我希望** 在分销面板中查看我的推广收益和团队数据
**以便** 追踪推广效果,激励持续推广
**验收标准:**
**入口权限:**
1. "我的"页面 → "我的服务"分组 → "💰 我的推广"入口 → 跳转到分销面板
2. **仅付费用户可见**(`vipEndTime > now`),普通用户看不到入口
3. 付费到期后入口自动隐藏
**页面结构(自上而下):**
**① 推广码卡片:**
4. 显示推广码 `我的推广码: ABC123` + 复制按钮
5. "生成推广海报"按钮 → 调用后端生成含小程序码的海报
6. 无推广码(极端情况)→ 显示"推广码生成中…"
**② 收益统计卡片(三列等宽):**
7. 总收益:累计所有佣金总额(`status = settled`)
8. **累计收益**:当前总收益金额(Phase 1 不提现,故不称"可提现"以免误解;页面加注"提现功能即将开放")
9. 今日新增:当日 00:00 至今产生的佣金总额
10. 金额以元为单位,保留两位小数(后端存储分,前端 `/100`)
**③ 团队统计(三列):**
11. 直接下级:`directCount`
12. 间接下级:`indirectCount`
13. 升级下级:`convertedCount`
14. 零数据时显示引导文案:"暂无推广数据,分享推广码给好友开始赚取佣金"
**④ 佣金明细列表(最近50条):**
15. 显示:时间(MM-DD HH:mm)、来源(匿名"用户****")、级别(L1/L2标签)、金额(+¥XXX.XX)、状态
16. 按时间倒序排列
17. 空数据时显示"暂无佣金记录"引导
**⑤ 推广工具区:**
18. "📱 生成推广海报" → 合成含小程序码的分享海报
19. "🔗 复制推广链接" → 复制带 ref 参数的小程序路径到剪贴板
20. "📊 提现申请" → **置灰不可点击**,显示"即将开放"(Phase 1 不做提现)
**页面状态:**
21. **Loading 状态**:各区块显示骨架屏脉冲动画
22. **错误状态**:顶部显示错误提示条 + "点击重试"按钮
23. **空数据状态**:佣金列表/团队统计显示引导文案
24. **下拉刷新**:重新请求所有数据
**后端 API 需求:**
| 接口 | 说明 |
|------|------|
| `POST /api/profile/info` | 含 `referralCode`(已有) |
| `POST /api/commission/list` | 佣金明细列表(已有) |
| `POST /api/commission/stats` | **新增**:总收益+可提现+今日新增+团队统计 |
---
### US-6.6 C端年费订阅入口
**作为** 免费用户(C端)
**我希望** 在AI解读页底部看到 ¥131 开通完整解读的引导
**以便** 一键订阅获取完整服务
**验收标准:**
**入口位置(用户已确认选项1——能量盘解读页底部):**
1. `chart/index.vue` 底部(聊天区下方)固定显示订阅卡片(免费用户)
2. 已付费用户(C端或能量师) → 不显示订阅卡片,改为显示"✅ 已开通"徽章+生成推广海报入口
**交互流程(未登录):**
3. 显示完整订阅卡片:🔮 AI解读会员 ¥131/年,列出权益(无限AI解读、个性化报告、推广赚佣金)
4. 点击"登录后开通 ¥131" → 先跳登录页,登录后自动跳转支付页
**交互流程(已登录未付费):**
5. 显示同上"立即开通 ¥131"按钮
6. 点击 → 跳转支付页 `product=annual`,金额 ¥131
**交互流程(已付费):**
7. 订阅卡片替换为灰色小徽章"✅ 已开通AI解读 | 有效期至 2027-05-28"
8. 已付费用户显示"📱 生成推广海报"入口
9. 能量师(practitioner)显示"✅ 已开通能量师"
**支付页适配:**
10. `payment/index.vue` 支持 URL 参数 `product`:
- `product=annual` → 显示 C端年费 ¥131 和对应权益列表
- `product=practitioner` → 显示能量师价格(通过 API 获取种子/标准价)
11. `createOrder` 接口接收 `productType` 参数
**后端适应:**
12. Order `productType` 字段新增枚举值:`"annual"` | `"super_member"`(超级会员) | `"practitioner"` | `"practitioner_plan"`(人工方案)
13. User `vipType` 字段(`"annual"` | `"super_annual"`(超级会员) | `"practitioner"` | `null`)
14. `paySuccess()` 佣金结算按 `productType` 分支:
- `annual` → US-6.4 C端年费佣金
- `super_member` → US-10.4 超级会员佣金结算
- `practitioner` → US-6.3 B端佣金(含推荐人身份判断 + isUpgrade 补差)
- `practitioner_plan` → US-9.5/9.6 人工方案佣金(通过 CommerceService 结算,平台留存模型)
---
## EPIC 9:学业方向分析与人工方案(P1)
> **场景**:家长为孩子选择学业方向,通过AI解读初步了解孩子的天赋倾向,如需深度方案可申请能量师出方案。
> **佣金模型**:人工方案采用**平台佣金留存模型**(区别于年费的固定金额/比例模型),所有分销佣金从平台留存部分支出。
> **商城底座**:引入 lilishop(`iwt/lilishop`)作为商城引擎,本期通过 `CommerceService` 接口层预留对接,暂不实现实际商城付费。
---
### US-9.1 学业方向AI深度解读
**作为** 家长
**我希望** 输入孩子的生日后,看到针对学业方向的AI深度解读
**以便** 了解孩子的天赋倾向,为学业规划提供参考
**验收标准:**
**入口:**
1. 在能量盘解读页(`chart/index.vue`)的 AI 解读内容区域,学业方向分析作为**解读内容的组成部分**嵌入展示,不设独立页面入口和菜单项
2. 解读页底部增加"🎓 学业方向分析"按钮,点击后调用新接口 `POST /api/chart/academic-orientation`
3. 解读结果以折叠卡片形式嵌入在通用解读内容下方,与主性格概要共用同一会话上下文
**AI 解读内容:**
3. 后端转发至 Dify **学业方向专用 Workflow**,能量盘24个数字(A-X)作为 `inputs`
4. 解读内容至少包含以下章节:
- **天赋倾向**:基于主性格数字+外部三组数的自然天赋分析
- **适合方向**:文科倾向/理科倾向/艺术特长/体育潜能等,用百分比表示匹配度
- **学习特征**:专注力、理解方式、学习节奏偏好(基于J/K/L位置分析)
- **亲子沟通建议**:针对该能量盘类型的孩子,应采用的沟通和教育方式
- **关键期提醒**:V/W/X中年区对应的升学/职业选择重要节点
5. 每个章节独立卡片展示,可折叠展开
6. 页面底部显示"💡 以上分析由AI生成,如需人工深度方案,可申请能量师出方案"
**付费控制:**
7. 免费用户每日可查看 1 次学业方向解读(与 US-3.2 主性格概要**独立配额**,互不消耗)
8. 已付费用户(C端/能量师)不限次
9. 超出次数后显示引导卡片:"今日学业分析次数已用完,开通会员享无限次"
**技术架构:**
10. 在 Dify 平台新增学业方向 Workflow,Workflow 输入为 24 个能量盘数字(A-X),输出为结构化 JSON
11. 后端 `DifyService` 新增方法 `interpretAcademicOrientation(AcademicRequest request)`
12. 解读结果缓存同 US-3.3(同一能量盘+同一天内重复请求返回缓存内容)
---
### US-9.2 申请能量师出方案
**作为** 家长
**我希望** 在AI学业解读后,申请能量师为孩子出具深度人工方案
**以便** 获得比AI更个性化的专业指导
**验收标准:**
**入口与表单:**
1. AI学业解读页底部固定"申请能量师出方案"按钮
2. 通用AI解读页底部也显示"💼 申请人工深度方案"按钮
3. 点击后弹出半屏表单,包含:
- **需求类型**:学业方向 / 职业规划 / 亲子关系 / 其他(单选)
- **具体需求描述**:文本输入框,限300字
- **期望价格范围**:下拉选项(¥50-99 / ¥100-299 / ¥300-499 / ¥500-999 / 面议)
4. 提交后生成一条"方案需求单"记录
**需求分配:**
5. 如果用户有 `invitedBy` 且上级是能量师(`vipType='practitioner'`)→ 自动把需求单分配给该能量师
6. 如果没有上级能量师 → 显示"暂未开放系统分配,请通过推荐链接找到专属能量师"
7. 分配后能量师收到通知(US-8.3 消息通知或在能量师工作台看到)
**数据库新增:**
8. `plan_requests` 表:`id, userId, chartId, requestType, description, budgetRange, assignedPractitionerId, status(pending/accepted/negotiating/paid/completed/cancelled), price, createdAt, updatedAt`
---
### US-9.3 能量师介入AI会话
**作为** 能量师
**我希望** 看到向我咨询用户的AI会话,并可以发起介入
**以便** 在用户需要时主动提供专业建议,促成人工方案
**验收标准:**
**触发条件:**
1. 仅 `invitedBy` 关系链中的能量师(B推荐A,A是B的上级)才能介入B的AI会话
2. 能量师在"能量师工作台"看到下级用户的咨询记录列表(来自 `invitedBy` 关系链,仅显示有实际咨询的用户)
3. 列表显示:用户头像/昵称/能量盘日期/最后活跃时间
**介入流程:**
4. 能量师点击某个用户 → 进入"咨询监看"页面(只读模式查看AI聊天记录)
5. 页面底部有"介入会话"按钮
6. 点击后,用户侧聊天界面出现系统消息:**"🔔 能量师 张三 已进入本次咨询"**
7. 能量师侧出现输入框,可发送文字消息
8. 用户侧聊天流中,能量师消息显示为:**"👤 能量师张三:消息内容"**(绿色气泡,区别于AI的灰色气泡)
9. AI继续正常回答,能量师和AI的回答在聊天中交替显示
**权限边界:**
10. 用户随时可"请出能量师"(在消息长按菜单中选择"结束能量师介入")
11. 用户主动关闭后,能量师侧显示"用户已结束本次协同咨询"
12. 每次介入在 `chat_interventions` 表记录
**数据库新增:**
13. `chat_interventions` 表:`id, sessionId, practitionerId, startTime, endTime, endedBy(user/practitioner)`
14. `chat_messages` 表新增 `senderType` 枚举:`ai` / `user` / `practitioner` / `system` / `proposal`
---
### US-9.4 方案价格协商
**作为** 能量师
**我希望** 在聊天中向用户发送方案提议,并可与用户协商价格
**以便** 双方达成一致后完成付费
**验收标准:**
**出方案提议:**
1. 能量师在聊天输入框左侧有"📋 出方案"按钮
2. 点击弹出结构化表单:
- 方案标题(限50字)
- 方案描述(限500字)
- 方案价格(手动输入,单位元,整数,范围受系统配置限制)
3. 发送后在聊天中显示方案卡片(嵌入消息格式)
**方案卡片交互:**
4. 卡片包含:标题、描述、价格(¥XXX)、能量师名称
5. 用户侧卡片有三个操作按钮:
- **"💰 接受并支付"** → 进入 US-9.5 支付流程
- **"💬 议价"** → 弹出输入框,用户输入期望价格
- **"❌ 不感兴趣"** → 卡片标记为已拒绝,通知能量师
6. 用户议价后,能量师侧收到新消息:"用户希望价格改为 ¥XXX"
7. 能量师可:
- 接受新价 → 发送更新后的方案卡片(价格更新)
- 坚持原价 → 回复文字说明
- 提出折中价 → 发送新的方案卡片
**状态管理:**
8. 一条 `plan_requests` 记录对应多轮协商历史
9. 每次更新价格或状态在 `plan_request_logs` 表记录
10. 最大协商轮次 5 轮(超限后只能接受或拒绝当前价格)
**数据库新增:**
11. `plan_request_logs` 表:`id, planRequestId, action(propose/counter/accept/reject), oldPrice, newPrice, message, operatorId, createdAt`
---
### US-9.5 方案付费与交付
**作为** 家长
**我希望** 接受能量师方案报价后在线支付,并收到完整的方案报告
**以便** 获得专业的学业指导
**验收标准:**
**支付:**
1. 用户点击"接受并支付" → 弹出半屏支付确认页
2. 支付确认页显示:服务名称、能量师名称、协商价格、微信支付按钮
3. 点击支付 → `createOrder(productType="practitioner_plan", planRequestId=xxx)`
4. 订单 `productType = "practitioner_plan"`(新增类型)
5. 支付回调 → 调用 `CommerceService.onPaymentSuccess()` 处理平台佣金计算
**平台佣金计算(StubCommerceService):**
6. 读取分类佣金率:`commerce.category.practitioner_plan.commission_rate`(默认 `3000` = 30%)
7. 平台佣金 = 总价 × commission_rate / 10000(单位分)
8. 能量师应结算 = 总价 - 平台佣金
9. 如有上级推荐 → 从平台佣金中提取分销佣金:
- 直接上级提成 = 平台佣金 × `commission.practitioner_plan.referral_rate` / 10000(默认 `2000` = 20%)
- 上上级提成 = 平台佣金 × `commission.practitioner_plan.upstream_rate` / 10000(默认 `500` = 5%)
**示例计算:**
```
方案价 ¥299,平台佣金率 30%
平台佣金 = ¥299 × 30% = ¥89.70
能量师结算 = ¥299 - ¥89.70 = ¥209.30
有直接上级:分销佣金 = ¥89.70 × 20% = ¥17.94
平台净留 = ¥89.70 - ¥17.94 = ¥71.76
```
**交付:**
10. 能量师收到支付成功通知
11. 能量师工作台出现"方案交付入口"
12. 交付支持三种方式:
- **文字方案**:富文本编辑器输入,保存到 `plan_deliveries.text_content`
- **PDF方案**:上传PDF文件(与US-2.2共用PDF生成能力)
- **图文报告**:混合内容,包含能量盘截图+文字解读
13. 交付后用户收到通知 + 聊天显示"📄 您的学业方案已交付"
14. 用户可查看/下载方案,平台不额外限制次数
**评价与完成:**
15. 用户确认接收方案 → 状态 `completed`
16. 用户可对能量师服务进行评分(1-5星)+ 文字评价
17. 评价写入 `practitioner_ratings` 表
**数据库新增:**
18. `plan_deliveries` 表:`id, planRequestId, deliveryType(text/pdf/mixed), textContent, fileUrl, createdAt`
19. `practitioner_ratings` 表:`id, planRequestId, userId, practitionerId, score(1-5), comment, createdAt`
---
### US-9.6 人工方案分销佣金(平台留存口径)
**作为** 平台
**我希望** 当用户购买人工方案时,从平台佣金中自动结算分销佣金
**以便** 激励推广者推荐用户给能量师
**验收标准:**
**触发条件:**
1. 订单 `productType = "practitioner_plan"` 且支付成功 → 进入分佣流程
2. 佣金来自平台留存部分(不是从能量师结算金额中扣除)
**佣金参数:**
| 参数 | 默认值 | 配置键 |
|------|--------|--------|
| 平台佣金率 | 30% | `commerce.category.practitioner_plan.commission_rate` |
| 直接上级分销比例 | 20%(占平台佣金) | `commission.practitioner_plan.referral_rate` |
| 上上级分销比例 | 5%(占平台佣金) | `commission.practitioner_plan.upstream_rate` |
**计算逻辑:**
3. `platformCommission = totalFee × commission_rate / 10000`
4. `referralCommission = platformCommission × referral_rate / 10000`
5. `upstreamCommission = platformCommission × upstream_rate / 10000`
6. 收款人资格同 US-6.4(须已付费用户才可收款)
**状态与幂等:**
7. 佣金 `status` 写入 `"settled"`(即时到账)
8. 同一 `outTradeNo` 重复回调 → 幂等处理
**示例:**
```
方案价 ¥299(29,900分)
平台佣金率 30%
平台佣金 = 29,900 × 30% = 8,970分 = ¥89.70
直接上级佣金 = 8,970 × 20% = 1,794分 = ¥17.94
上上级佣金 = 8,970 × 5% = 448分 = ¥4.48
能量师结算 = 29,900 - 8,970 = 20,930分 = ¥209.30
平台净留 = 8,970 - 1,794 - 448 = 6,728分 = ¥67.28
```
---
### CommerceService 接口层(商城预留)
> 本期不实现 lilishop 对接,先定义接口 + 桩实现。
**接口:**
```java
public interface CommerceService {
/** 创建商品(能量师上架服务) */
String createProduct(CommerceProductDTO product);
/** 创建订单 */
String createOrder(CommerceOrderDTO order);
/** 订单支付回调处理 */
void onPaymentSuccess(String orderSn, String payOrderNo);
/** 查询订单 */
CommerceOrderDTO getOrder(String orderSn);
/** 获取店铺结算信息 */
CommerceSettlementDTO getSettlement(String storeId);
/** 记录分销订单 */
void recordDistribution(String orderSn);
}
```
**Phase 1 桩实现(StubCommerceService):**
| 方法 | 实现策略 |
|------|---------|
| `createProduct` | 写入本地 `commerce_goods` 映射表 |
| `createOrder` | 走现有本地 `orders` 表 + 标记 `commerceReady=false` |
| `onPaymentSuccess` | 执行本地佣金计算逻辑(US-9.5 验收标准6-9) |
| `getSettlement` | 从本地佣金表聚合统计 |
| `recordDistribution` | 走现有 `commissions` 表逻辑 |
**Phase 2+ 对接 lilishop:**
- `createProduct` → lilishop Goods API
- `createOrder` → lilishop Order API
- `onPaymentSuccess` → 创建 StoreFlow + DistributionOrder
- `getSettlement` → lilishop Bill API
- `recordDistribution` → lilishop Distribution API
**数据库新增:**
```sql
-- lilishop 商品映射表(预留)
CREATE TABLE `commerce_goods` (
`id` bigint PRIMARY KEY AUTO_INCREMENT,
`store_id` varchar(32) NOT NULL COMMENT '能量师storeId(= userId)',
`product_type` varchar(32) NOT NULL COMMENT '商品类型:practitioner_plan',
`lilishop_goods_id` varchar(32) DEFAULT NULL COMMENT 'lilishop商品ID(Phase 2 填充)',
`category_path` varchar(255) DEFAULT NULL COMMENT 'lilishop分类路径',
`price` bigint NOT NULL COMMENT '价格(分)',
`status` varchar(16) DEFAULT 'active' COMMENT '状态',
`created_at` datetime NOT NULL,
`updated_at` datetime DEFAULT NULL
);
```
---
### US-7.1 能量盘批注
**作为** 能量师
**我希望** 在能量盘图上添加文字批注或标记
**以便** 为每个客户记录个性化的解读要点
**验收标准(入口与权限):**
1. "编辑批注"按钮位于能量盘展示页右上角菜单中(仅已付费用户可见)
2. 未付费用户看不到该按钮
3. **批注模式建议方案(开发选其一):**
- **方案A(推荐)**:在能量盘页面底部展开批注编辑面板,能量盘操作和数字点击互不干扰,无需切换模式。用户点击数字后可快速插入 `【位置X】` 标签到批注文本
- **方案B(备选)**:点击"编辑批注"进入专用模式,能量盘页面其他操作暂时禁用,底部显示批注编辑区域
4. 批注内容支持富文本(加粗、斜体、分段、列表),最大 2000 字
5. 批注内容与 `chartId` 绑定,不同能量盘各自独立
6. 批注支持按能量盘位置打标签,格式示例:`【主性格O】天生领导者,数字1能量突出`
7. 同一位置的多条批注自动折叠,点击展开
8. 保存批注调用 `POST /api/chart/annotation/save`,传入 `chartId` + `content`
9. 保存成功后 toast 提示"批注已保存",编辑区域收起
10. 取消编辑时,若有未保存内容,弹出确认框"有未保存的内容,确定放弃?"
**验收标准(批注展示):**
11. 已有批注的能量盘,在数字卡片上方显示小黄点标记(🟡)
12. 退出批注模式后,能量盘页底部显示批注摘要区域(展开/折叠),显示最近 3 条批注
13. 点击"查看全部批注"跳到批注完整列表页
14. 批注列表页按位置分组,按创建时间倒序排列
15. 导出的 PDF(US-2.2)第二页包含批注内容
16. 批注支持删除(长按批注 → 确认删除)
**验收标准(后端与存储):**
17. 新增 `chart_annotations` 表:
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | `BIGINT PK` | 主键 |
| `chart_id` | `BIGINT` | 关联能量盘记录 |
| `user_id` | `BIGINT` | 批注人(能量师) |
| `position` | `VARCHAR(2)` | 关联位置字母(A-X),可为 null |
| `content` | `TEXT` | 批注内容(富文本 HTML) |
| `created_at` | `DATETIME` | 创建时间 |
| `updated_at` | `DATETIME` | 最后修改时间 |
18. 新增接口:
- `POST /api/annotation/save` — 保存/更新批注
- `POST /api/annotation/list` — 获取能量盘批注列表(按 chartId)
- `POST /api/annotation/delete` — 删除单条批注
### US-7.2 客户标签分组
**作为** 能量师
**我希望** 为能量盘记录添加简单的标签或分组
**以便** 对客户进行分类管理
**验收标准(标签创建与选择):**
1. 发起咨询时(生日输入页确认弹窗中)显示"添加标签(选填)"区域
2. 标签区域包含:标签输入框 + "新建"按钮 + 已创建的标签列表(可点击选择)
3. 新建标签:输入 2-8 字,自动分配随机颜色,点击确定后存入用户标签库
4. 已有标签以胶囊样式展示:`[🟢 老客户]` `[🟠 朋友推荐]` `[🔵 线上引流]`
5. 一个能量盘最多绑 3 个标签,超出提示"最多选择 3 个标签"
**验收标准(标签展示与筛选):**
6. 能量盘列表中,每条记录右侧展示标签胶囊
7. 历史列表顶部增加标签筛选栏,可选择一个或多个标签组合筛选:
- 未选择任何标签时:显示所有记录
- 选择标签时:AND 逻辑(同时包含所有选中标签的记录)
- 支持"全部"按钮一键清除筛选
8. 已打标签的能量盘记录,在列表中有标签标识,方便快速识别
**验收标准(标签管理):**
9. 个人中心 → 我的标签:展示该能量师创建的所有标签
10. 标签管理操作:
- 编辑标签名称
- 修改标签颜色(从预设 8 色中选择)
- 删除标签(删除后将移除所有关联能量盘上的该标签)
11. 删除标签时弹出确认:"删除后,所有关联能量盘上的该标签将被移除,确定?"
**验收标准(后端与存储):**
12. 新增 `user_labels` 表:
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | `BIGINT PK` | 主键 |
| `user_id` | `BIGINT` | 能量师 ID |
| `name` | `VARCHAR(20)` | 标签名称 |
| `color` | `VARCHAR(7)` | 颜色值(如 #4CAF50) |
| `created_at` | `DATETIME` | 创建时间 |
13. 新建关联表 `chart_labels`(能量盘-标签多对多):
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | `BIGINT PK` | 主键 |
| `chart_id` | `BIGINT` | 能量盘记录 ID |
| `label_id` | `BIGINT` | 标签 ID |
| `created_at` | `DATETIME` | 关联时间 |
14. 新增接口:
- `POST /api/label/create` — 新建标签
- `POST /api/label/list` — 获取标签列表
- `POST /api/label/update` — 编辑标签名称/颜色
- `POST /api/label/delete` — 删除标签
- `POST /api/chart/label/set` — 为能量盘设置标签
- `POST /api/chart/label/list` — 获取能量盘标签列表(按 chartId)
---
## EPIC 8:管理后台(P0-P1)
### US-8.1 系统配置管理
**作为** 运营管理员
**我希望** 在管理后台可视化编辑定价和佣金参数
**以便** 灵活调整运营策略,无需开发介入
---
#### 8.1.1 验收标准
**DDL & Entity:**
1. 新建 `sys_config` 表,结构如下:
```sql
CREATE TABLE `sys_config` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`config_key` VARCHAR(64) NOT NULL COMMENT '配置键(点分命名法)',
`config_value` VARCHAR(255) DEFAULT NULL COMMENT '配置值(始终使用字符串存储)',
`description` VARCHAR(255) DEFAULT NULL COMMENT '中文说明',
`value_type` VARCHAR(20) NOT NULL DEFAULT 'string' COMMENT 'int | price | percent | string',
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_config_key` (`config_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
2. 预置 **20 条**种子数据(见下,含 super_member 定价与佣金)。
**后端:SysConfigService + 内存缓存:**
3. `@PostConstruct loadAllToCache()`:启动时将全量配置读入 `ConcurrentHashMap`
4. 对外提供 `getString(key, default)`、`getInt(key, default)` 两个读方法,O(1) 取值
5. `key` 不存在时 → 返回代码中传入的 `defaultValue`,**永不抛异常**
6. `updateConfig(key, value)`:更新 DB + 同步写入缓存,**无需重启**
7. `batchUpdate(Map)`:循环调用 `updateConfig`,整个操作在 `@Transactional` 中
**管理后台 API:**
8. `POST /api/admin/config/list` → 返回 `List`(含全部字段)
9. `POST /api/admin/config/update` → 接收 `{ "configKey": "value", ... }` → 批量更新
**小程序端 API:`POST /api/pricing/current`:**
```json
// Request: 无参数
// Response:
{
"code": 0,
"data": {
"seedPrice": 131400, // pricing.practitioner.seed(分)
"standardPrice": 198600, // pricing.practitioner.standard(分)
"annualFee": 13100, // pricing.annual(分)
"isSeedPrice": true, // 当前用户是否能享受种子价(双条件判断)
"seedReason": "eligible", // "eligible"=双条件均满足 | "expired"=有效期已过 | "quota_full"=名额已满
"remainingSeats": 298, // 种子名额余量
"seedLimit": 300, // 名额上限
"seedPeriodEnd": "2027-05-31T23:59:59" // 种子价有效期截止时间
}
}
```
10. `isSeedPrice` 的计算逻辑(双条件,全部满足才为 `true`):
- 条件①:当前时间 ≤ `pricing.practitioner.seed_period_end`
- 条件②:已以种子价付费的能量师数 < `seedLimit`(统计 `orders` 中 `product_type='practitioner'` AND `status='paid'` AND `is_seed_price=true` 的记录数)
- `seedReason` 字段用于前端展示不同提示文案(如"种子价已过期"、"种子名额已满"等)
**管理后台页面(`src/views/settings/index.vue`):**
11. 左侧菜单新增"系统配置"入口,路由 `/settings`,图标 ⚙️
12. 页面分为三个卡片区域,每个卡片顶部有"恢复初始值"按钮(仅重置单个卡片内的字段为种子数据):
- hover 时 tooltip 显示具体初始值(如"恢复为 ¥500")
- 点击后弹出确认框:"将恢复本卡片内所有字段为初始值,确定吗?"
**定价配置卡片:**
13. 六个输入项:能量师种子价、标准价、种子价名额上限、种子价有效期截止时间、C端年费、**超级会员年费(¥1,314,固定价)**
14. 用户输入的是**元(整数)**,提交时自动 ×100 转为分(有效期除外)
15. 种子价名额上限下方实时显示"当前已使用:X / Y"(调用 `countByProductTypeAndStatus` + `isSeedPrice=true`)
16. 修改数量时,"已使用"比例随之动态变化
17. 种子价有效期使用 `el-date-picker`(datetime 类型),显示格式 `YYYY-MM-DD HH:mm:ss`,存储格式为 ISO 8601 字符串
18. 有效期下方显示当前状态:"🟢 有效期剩余 XX 天" 或 "🔴 已过期"(根据当前时间与 `seed_period_end` 比较)
19. 定价卡片顶部注释:"种子价双条件:①在有效期内 ②名额未满,两者同时满足才生效"
**B端佣金配置卡片:**
17. **三个输入项**:
- L1 佣金—能量师推荐(¥500)
- L1 佣金—C端推荐(¥200,新增)
- L2 佣金(¥100,不限推荐人身份)
18. 输入单位为元(整数),提交时 ×100 转为分
19. 每个输入项下方实时显示比例计算:
- "L1(能量师推荐)¥500 = 种子价 38.1% / 标准价 25.2%"
- "L1(C端推荐)¥200 = 种子价 15.2% / 标准价 10.1%"
- "L2 ¥100 = 种子价 7.6% / 标准价 5.0%"
20. 比例随定价或佣金值的修改**实时联动更新**
**C端佣金配置卡片:**
21. 两个输入项:直接佣金比例(40%)、上级佣金比例(5%)
22. 输入单位为"%"(整数,如输入"40"表示40%),提交时转为万分比 ×100
23. 下方实时显示金额分配预览:
- "每笔 ¥131:直接 ¥52.40(40.0%)/ 上级 ¥6.55(5.0%)/ 平台 ¥72.05(55.0%)"
24. 费率修改时金额分配**实时联动更新**
**保存逻辑:**
25. 点击"保存全部配置"按钮 → 触发 `POST /api/admin/config/update`
26. 所有字段批量提交,不逐个保存
27. 保存前做前端校验:金额 > 0、比例 0-100%、名额上限 > 0
28. 保存成功 → ElMessage.success("配置已保存,已实时生效")
29. 保存失败 → ElMessage.error("保存失败:" + 错误详情)
30. 前端无 `el-form` 的 reset 行为 —— 用户手动刷新页面可恢复到上次保存的值
**错误与边界:**
31. 网络失败时显示"保存失败,请重试",页面不跳转,已修改的值保留在输入框中
32. 同时两个管理员保存 → 后保存的覆盖先保存的,不做冲突检测(Phase 1 简化)
33. 输入非法值时(如空字符串、负数),`el-input-number` 的 min 属性直接阻止输入
34. 所有金额字段不允许出现小数(元为整数输入,单位转换在后端)
---
#### 8.1.2 后端接口规格
**`POST /api/admin/config/list`**
```json
// Response:
{
"code": 0,
"data": [
{
"id": 1,
"configKey": "pricing.practitioner.seed",
"configValue": "131400",
"description": "能量师种子价(分)",
"valueType": "price",
"updatedAt": "2026-05-28T10:00:00"
}
// ... 共 9 条(基础定价4+有效期1+佣金3+佣金1,详见种子数据SQL)
]
}
```
**`POST /api/admin/config/update`**
```json
// Request:
{
"pricing.practitioner.seed": "131400",
"commission.practitioner.l1": "60000"
}
// Response: { "code": 0 }
```
**`POST /api/admin/config/reset`**(可选,单条重置)
```json
// Request: { "configKey": "commission.practitioner.l1" }
// Response: { "code": 0, "data": { "configKey": "commission.practitioner.l1", "configValue": "50000" } }
```
---
#### 8.1.3 后端类设计
| 类名 | 位置 | 说明 |
|------|------|------|
| `SysConfig` | `entity/` | JPA 实体 |
| `SysConfigRepository` | `repository/` | JPA 接口 |
| `SysConfigService` | `service/` | 配置 CRUD + 内存缓存 |
| `AdminConfigController` | `controller/` | `/api/admin/config/*` 端点 |
| `PricingController` | `controller/` | `/api/pricing/current` 小程序端端点 |
| `OrderRepository` | `repository/` | 新增 `countByProductTypeAndStatus()` |
**`SysConfigService` 核心代码:**
```java
@Service
public class SysConfigService {
private final ConcurrentHashMap cache = new ConcurrentHashMap<>();
private final SysConfigRepository repository;
@PostConstruct
public void loadAllToCache() {
cache.clear();
repository.findAllByOrderByConfigKeyAsc()
.forEach(cfg -> cache.put(cfg.getConfigKey(), cfg.getConfigValue()));
}
public String getString(String key, String defaultValue) {
return cache.getOrDefault(key, defaultValue);
}
public int getInt(String key, int defaultValue) {
String val = cache.get(key);
if (val == null) return defaultValue;
try { return Integer.parseInt(val); }
catch (NumberFormatException e) { return defaultValue; }
}
@Transactional
public void updateConfig(String key, String value) {
SysConfig cfg = repository.findByConfigKey(key)
.orElseGet(() -> new SysConfig(key, value, "auto", "string"));
cfg.setConfigValue(value);
cfg.setUpdatedAt(LocalDateTime.now());
repository.save(cfg);
cache.put(key, value);
}
public void batchUpdate(Map configs) {
configs.forEach(this::updateConfig);
}
}
```
---
#### 8.1.4 管理后台前端规格
| 文件 | 操作 | 说明 |
|------|------|------|
| `src/views/settings/index.vue` | **新增** | 系统配置页面(~200行) |
| `src/router/index.ts` | 修改 | 新增 `/settings` 路由 |
| `src/layout/index.vue` | 修改 | 新增菜单项 |
**侧边栏菜单新增:**
```vue
系统配置
```
**页面组件结构:**
```
settings/index.vue
├── el-card (header-toolbar: "系统配置" + [保存全部配置])
├── el-card (定价配置)
│ ├── el-form-item: 能量师种子价 → el-input-number(min=0, max=999999, step=100)
│ ├── el-form-item: 能量师标准价 → el-input-number(...)
│ ├── el-form-item: 种子价名额上限 → el-input-number(min=1, max=99999, step=50)
│ ├── el-form-item: 种子价有效期 → el-date-picker(type="datetime", format="YYYY-MM-DD HH:mm:ss")
│ ├── 注记:种子价双条件(有效期+名额)
│ ├── el-form-item: C端年费 → el-input-number(...)
│ └── el-form-item: 超级会员年费 → el-input-number(min=0, max=999999, step=100)
├── el-card (B端佣金配置)
│ ├── el-form-item: L1 佣金(能量师推荐)→ el-input-number
│ ├── el-form-item: L1 佣金(C端推荐)→ el-input-number
│ ├── el-form-item: L2 佣金 → el-input-number
│ └── 实时比例显示
├── el-card (超级会员佣金配置)
│ ├── el-form-item: 直接佣金比例 → el-input-number(min=0, max=10000, step=500)
│ ├── el-form-item: 上级佣金比例 → el-input-number(min=0, max=5000, step=100)
│ └── 实时分配预览:每笔¥1,314→直接¥394.20(30%) / 上级¥65.70(5%) / 平台¥853.10(65%)
└── el-card (人工方案配置 — EPIC 9)
│ ├── el-form-item: 平台佣金率 → el-input-number(min=0, max=10000, step=500)
│ │ └── 注记:方案价 × 佣金率 = 平台收入,剩余结算给能量师
│ ├── el-form-item: 分销佣金占比(直接) → el-input-number(min=0, max=10000, step=500)
│ │ └── 注记:从平台佣金中提取 × 此比例 = 直接上级佣金
│ ├── el-form-item: 分销佣金占比(上级) → el-input-number(min=0, max=5000, step=100)
│ │ └── 注记:从平台佣金中提取 × 此比例 = 上上级佣金
│ ├── el-form-item: 方案最低价 → el-input-number(min=0, max=999999, step=100)
│ ├── el-form-item: 方案最高价 → el-input-number(min=0, max=999999, step=100)
│ │ └── 实时预览示例:方案价¥299→佣金¥89.70→能量师¥209.30→分销¥17.94
│ └── el-form-item: 最大协商轮次 → el-input-number(min=1, max=20, step=1)
└── el-card (关系类型配置)
├── el-form-item: 关系类型列表 → 动态表格
│ ├── 列1: 编码(code)→ el-input,如 "spouse"
│ ├── 列2: 显示名称(label)→ el-input,如 "夫妻/伴侣"
│ ├── 列3: 图标(icon)→ el-input,如 "👫"
│ ├── 列4: 说明(desc)→ el-input,如 "婚姻或恋爱关系能量匹配"
│ └── 行操作 → [新增一行] [删除] 按钮
├── el-form-item: 操作说明
│ └── 注记:"修改关系类型后,已有关系人的 relation_type 不变,仅影响新增时的选项列表"
└── el-form-item: 预览 → 实时展示当前配置的图标+名称列表(只读)
```
**表单校验规则:**
| 字段 | 校验规则 |
|------|---------|
| 所有金额(元) | > 0,整数,≤ 999999 |
| 比例(%) | 0-100,整数 |
| 名额上限 | ≥ 1,≤ 99999 |
---
#### 8.1.5 种子数据 SQL
```sql
INSERT INTO `sys_config` (`config_key`, `config_value`, `description`, `value_type`) VALUES
('pricing.practitioner.seed', '131400', '能量师种子价(分)', 'price'),
('pricing.practitioner.standard', '198600', '能量师标准价(分)', 'price'),
('pricing.practitioner.seed_limit', '300', '种子价名额上限', 'int'),
('pricing.practitioner.seed_period_end', '2027-05-31T23:59:59', '种子价有效期截止时间(ISO 8601)', 'datetime'),
('pricing.annual', '13100', 'C端年费(分)', 'price'),
('commission.practitioner.l1', '50000', 'B端一级佣金-能量师推荐(分)', 'price'),
('commission.practitioner.l1_cend', '20000', 'B端一级佣金-C端推荐(分)', 'price'),
('commission.practitioner.l2', '10000', 'B端二级佣金(分)', 'price'),
('commission.annual.direct_rate', '4000', 'C端直接佣金比例(万分比)', 'percent'),
('commission.annual.upstream_rate', '500', 'C端上级佣金比例(万分比)', 'percent'),
('commerce.category.practitioner_plan.commission_rate', '3000', '人工方案平台佣金率(万分比)', 'percent'),
('commission.practitioner_plan.referral_rate', '2000', '人工方案分销佣金占比(万分比)', 'percent'),
('commission.practitioner_plan.upstream_rate', '500', '人工方案上级佣金占比(万分比)', 'percent'),
('plan_request.enabled', 'true', '人工方案功能开关', 'bool'),
('plan_request.max_negotiation_rounds', '5', '最大协商轮次', 'int'),
('plan_request.auto_cancel_hours', '72', '协商超时自动取消(小时)', 'int'),
('plan_request.min_price', '5000', '方案最低价(分)', 'price'),
('plan_request.max_price', '999900', '方案最高价(分)', 'price'),
('pricing.super_member', '131400', '超级会员年费(分)', 'price'),
('commission.super_member.direct_rate', '3000', '超级会员直接佣金比例(万分比,3000=30%)', 'percent'),
('commission.super_member.upstream_rate', '500', '超级会员上级佣金比例(万分比,500=5%)', 'percent'),
('relation.types', '[{\"code\":\"spouse\",\"label\":\"夫妻/伴侣\",\"icon\":\"👫\",\"desc\":\"婚姻或恋爱关系能量匹配\"},{\"code\":\"parent\",\"label\":\"父母\",\"icon\":\"👨👧\",\"desc\":\"与父母的能量互动与孝顺建议\"},{\"code\":\"child\",\"label\":\"子女\",\"icon\":\"👶\",\"desc\":\"与子女的能量互动与教育建议\"},{\"code\":\"grandparent\",\"label\":\"祖父母\",\"icon\":\"👴\",\"desc\":\"与祖辈的能量互动与关怀建议\"},{\"code\":\"grandchild\",\"label\":\"孙子女\",\"icon\":\"👼\",\"desc\":\"与孙辈的能量互动与成长建议\"},{\"code\":\"colleague\",\"label\":\"同事\",\"icon\":\"👔\",\"desc\":\"职场合作者能量匹配\"},{\"code\":\"friend\",\"label\":\"朋友\",\"icon\":\"🤝\",\"desc\":\"社交友谊兼容性\"},{\"code\":\"superior\",\"label\":\"上级\",\"icon\":\"📊\",\"desc\":\"与上级管理者的能量关系\"},{\"code\":\"subordinate\",\"label\":\"下级\",\"icon\":\"📊\",\"desc\":\"与下属的能量关系\"}]', '关系类型配置(JSON数组,含code/label/icon/desc)', 'json'),
```
---
#### 8.1.6 测试用例
| # | 场景 | 步骤 | 预期 |
|---|------|------|------|
| 1 | 初始加载 | 打开系统配置页 | 20个字段显示正确的默认值 |
| 2 | 修改定价 | 种子价改为 ¥2,000 → 保存 | 下次 `POST /api/pricing/current` 返回 seedPrice=200000 |
| 3 | 修改佣金 | L1 改为 ¥600 → 保存 | 新订单的佣金 amount=60000 |
| 4 | 比例联动 | 直接佣金改为 50% | 下方显示"每笔¥131:直接¥65.50 / 上级¥6.55 / 平台¥58.95" |
| 5 | 比例联动反向 | 种子价改为 ¥2,000 | B端卡片"L1占种子价%"从38.1%变为25.0% |
| 6 | 输入校验 | 在金额框输入 -100 | el-input-number 阻止输入,值保持为 0 |
| 7 | 保存失败 | 网络断开后保存 | 显示"保存失败",输入值保留不丢失 |
| 8 | 保存后立即生效 | 改种子价为 ¥2,000 → 保存 → 新用户打开支付页 | 显示 ¥2,000 |
| 9 | 缓存同步 | API 直接改 DB → 调用 getInt() | 返回值仍为旧值(下次 loadAllToCache 或调用 updateConfig 后更新) |
| 10 | 种子名额展示 | 3笔已支付 practitioner 种子价订单 | 显示"已使用:3 / 300" |
| 11 | 种子有效期展示 | 有效期设为未来日期 | 显示"🟢 有效期剩余 XX 天" |
| 12 | 种子有效期过期 | 有效期设为过去日期 | 显示"🔴 已过期" |
---
### US-8.2 订单管理
**作为** 运营管理员
**我希望** 查看所有订单记录,按产品类型和状态筛选
**以便** 核对收入和对账
---
#### 8.2.1 验收标准
**后端 API(补全 `AdminController.listOrders()`):**
1. `POST /api/admin/orders` → 接收筛选参数,返回分页订单列表
```json
// Request:
{
"productType": "", // 筛选:"" 全部 | "practitioner" | "annual" | "super_member"
"status": "", // 筛选:"" 全部 | "paid" | "pending"
"page": 1,
"pageSize": 20
}
// Response:
{
"code": 0,
"data": {
"list": [
{
"id": 1,
"userId": 42,
"outTradeNo": "202605280001",
"totalFee": 131400,
"productType": "practitioner",
"isSeedPrice": true,
"status": "paid",
"payType": "wxpay",
"paidAt": "2026-05-28T10:00:00",
"createdAt": "2026-05-28T09:59:00"
}
],
"total": 128,
"page": 1,
"pageSize": 20
}
}
```
2. 后端在 `OrderRepository` 中新增分页+动态筛选查询方法(使用 `Specification` 或 `@Query` 动态拼接)
**前端页面:**
3. 表格列:ID、订单号、用户ID、产品类型("能量师" / "年费")、金额(¥格式)、种子价标记、状态(已支付/待支付)、支付时间
4. 产品类型使用 el-tag 展示:能量师→蓝色,年费→绿色
5. 种子价订单显示 🌱 种子 el-tag(橙色),hover 提示"种子价购买"
6. 状态使用 el-tag:已支付→success,待支付→warning
7. 表格上方的工具栏包含两个筛选器:
- 产品类型:el-select(全部 / 能量师 / C端年费)
- 状态:el-select(全部 / 已支付 / 待支付)
8. 筛选器 change 时重新请求接口
9. 底部分页组件:显示总条数,支持切换页码
**当前代码待补全:**
- `AdminController.listOrders()` 目前返回 `Result.success(null)` → 需替换为真实数据
- `Order` 实体和 `OrderRepository` 已有,但缺 `productType` 和 `isSeedPrice` 字段 → 需新增
- 订单表 `orders` 需增加 `product_type` 和 `is_seed_price` 列
- 分页需引入 `Pageable` + `Specification`(或简单用 `PageRequest`)
---
#### 8.2.2 后端类变更
| 类名 | 变更 | 说明 |
|------|------|------|
| `Order.java` | 新增字段 | `productType` (String)、`isSeedPrice` (Boolean) |
| `OrderRepository` | 新增方法 | `countByProductTypeAndStatus(productType, status)` |
| `OrderRepository` | 新增方法 | `findAll(Specification, Pageable)` 或 `findByProductTypeAndStatus` |
| `AdminController` | 重写 `listOrders()` | 支持筛选+分页 |
---
### US-8.3 佣金查看
**作为** 运营管理员
**我希望** 查看所有佣金记录和统计
**以便** 了解分销推广效果
---
#### 8.3.1 验收标准
**后端 API(增强现有):**
1. `POST /api/admin/commissions` → 支持分页和按级别筛选
```json
// Request:
{
"level": 0, // 0: 全部 | 1: L1 | 2: L2
"page": 1,
"pageSize": 20
}
// Response:
{
"code": 0,
"data": {
"list": [
{
"id": 1,
"orderId": 101,
"fromUserId": 42,
"toUserId": 10,
"level": 1,
"amount": 50000,
"status": "settled",
"remark": "直接推荐升级能量师",
"createdAt": "2026-05-28T10:00:00"
}
],
"total": 56,
"page": 1,
"pageSize": 20,
"summary": {
"settledTotal": 350000, // 已结算总佣金(分)
"pendingTotal": 0, // 待结算总佣金(分,Phase 1 始终为 0)
"grandTotal": 350000, // 总佣金(分)
"countByLevel": { // 各级别笔数
"1": 12,
"2": 8
}
}
}
}
```
2. 当前 `AdminController.listAllCommissions()` 返回 `commissionRepository.findAll()`(无分页)→ 需重写
**前端页面(增强现有 `commissions/index.vue`):**
3. 顶部统计卡片(已有框架)→ 增强:
- 已结算佣金:¥3,500.00(绿色)
- 待结算佣金:¥0.00(黄色,Phase 1 恒为 0,保留字段显示)
- 总佣金:¥3,500.00
- **新增第四个卡片**:总笔数(L1: 12 笔 / L2: 8 笔)
4. 表格列(增强现有):ID、订单ID、来源用户ID、获得用户ID、级别(L1/L2 el-tag)、金额(¥格式)、备注(remark 字段)、状态、创建时间
5. 新增级别筛选器:el-select(全部 / L1 / L2),筛选时重新请求接口
6. 底部分页:当前 `:total="commissions.length"` 是前端假分页,改为后端真分页
7. 备注列显示 remark 内容(如"直接推荐升级能量师"、"C端年费直接推荐佣金 (40%)")
---
#### 8.3.2 前后端差距分析
| 当前状态 | 目标状态 | 工作量 |
|---------|---------|--------|
| `AdminController.listAllCommissions()` 无分页,无筛选 | 分页 + level 筛选 + summary 统计 | M |
| `CommissionRepository` 无分页方法 | 新增 `findAll(Specification, Pageable)` | S |
| 前端假分页(全量拉取) | 后端真分页 | M |
| 前端无 level 筛选 | 新增 el-select 筛选器 | S |
| 前端无备注列 | 新增 remark 列 | S |
| 前端无笔数统计卡片 | 新增第四个统计卡片 | S |
---
### US-8.4 提现管理(推迟至 Phase 2)
**已决策:推迟,当前不做。**
---
## 开发优先级总表
| 用户故事 | 优先级 | 预估工期 | 依赖 | 状态 |
|----------|--------|---------|------|------|
| US-1.1 生日输入与咨询发起 | P0 | 3天 | US-5.1(需登录)| ✅ |
| US-1.2 三角形可视化 | P0 | 3天 | US-1.1 | ✅ |
| US-1.4 数字点击查看含义 | P2 | 1天 | US-1.2 | ✅ |
| US-2.1 分享图片 | P0 | 2天 | US-1.2 | ✅ |
| US-2.2 PDF导出 | P0 | 2天 | US-1.2 | ✅ |
| US-3.1 AI解读展示 | P0 | 2天 | US-1.1 + Dify Workflow配置(附录B) | ✅ |
| US-3.2 AI解读免费/付费控制 | P0 | 1天 | US-3.1 | ✅ |
| US-3.3 解读内容缓存 | P0 | 1天 | US-3.1 | ✅ |
| US-3.4 AI交互问答(免费/付费控制) | P0 | 2天 | US-1.1 + Dify Chatflow配置(附录B) | ✅ |
| US-4.1 能量师付费订阅 | P0 | 2天 | US-5.1 | ✅ |
| US-4.2 种子价自动判断 | P0 | 1天 | US-8.1 | ✅ |
| US-4.3 订阅状态与续费 | P0 | 1天 | US-4.1 | ✅ |
| US-4.4 年费升级能量师(升级定价) | P1 | 1.5天 | US-4.1 + US-4.2 | ✅ |
| US-5.1 微信登录+注册信息完善 | P1 | 3天 | 无 | ✅ |
| US-5.2 历史咨询记录 | P1 | 2天 | US-5.1 | ✅ |
| US-5.3 个人资料编辑(社交预留) | P2 | 1天 | US-5.1 | ✅ |
| US-6.1 推广码生成 | P0 | 1天 | US-4.1 | ✅ |
| US-6.2 分享带参注册与上下级绑定 | P0 | 2天 | US-5.1 | ✅ |
| US-6.3 B端佣金结算(含升级补差+C端半额) | P0 | 3天 | US-4.1 + US-6.2 + US-4.4 + US-8.1 | ✅ |
| US-6.4 C端佣金结算 | P0 | 1天 | US-6.6 + US-6.3 + US-8.1 | ✅ |
| US-6.5 分销面板 | P1 | 2天 | US-6.1 + US-6.3 | ✅ |
| US-6.6 C端年费订阅入口 | P0 | 1.5天 | US-3.2 + US-4.1 | ✅ |
| US-7.1 批注功能 | P2 | 2天 | P0完成 | ✅ |
| US-7.2 客户分组 | P2 | 2天 | P0完成 | ✅ |
| US-8.1 系统配置管理 | **P0** | **2天** | **无(独立基础设施)** | ✅ |
| US-8.2 订单管理 | P1 | 1.5天 | US-4.1 + Order 新增字段 | ✅ |
| US-8.3 佣金查看 | P1 | 1天 | US-6.3 | ✅ |
| US-9.1 学业方向AI解读 | P1 | 2天 | US-1.1 + Dify学业Workflow | ✅ |
| US-9.2 申请能量师出方案 | P1 | 1.5天 | US-5.1 + US-9.1 | ✅ |
| US-9.3 能量师介入AI会话 | P1 | 2天 | US-5.1 + US-3.4 | ✅ |
| US-9.4 方案价格协商 | P1 | 1.5天 | US-9.3 | ✅ |
| US-9.5 方案付费与交付 | P1 | 2天 | US-9.4 + CommerceService 接口 | ✅ |
| US-9.6 人工方案分销佣金 | P1 | 1天 | US-9.5 + US-8.1 | ✅ |
---
## 咨询+能量盘依赖图
```
US-5.1 微信登录
│
▼
US-1.1 生日输入与咨询发起(后端查重(userId+name+birthday)→确认弹窗→后台计算→返回展示)
│
├──► US-1.2 三角形可视化(24位置新命名 I-X)
├──► US-3.4 AI交互问答(每日3轮,绑定当前能量盘)
│
▼
US-5.2 历史咨询记录(按 userId+name+birthday 唯一归组,可恢复聊天历史)
```
## 分销相关依赖图
```
US-8.1 系统配置管理(独立基础设施——最先完成)
│
├──► US-4.2 种子价判断
├──► US-6.3 B端佣金(读取 L1/L2 金额)
└──► US-6.4 C端佣金(读取直接/上级比例)
US-5.1 微信登录
│
▼
US-6.2 分享带参注册(需要 openid)
│
▼ 绑定上下级关系
│
US-4.1 能量师付费 + US-6.6 C端年费订阅
│ │
▼ ▼
US-6.1 推广码生成 US-6.4 C端佣金结算
│ │
▼ │
US-6.3 B端佣金结算 ◄──────────────┘(共享 paySuccess() 分支)
│
▼
US-6.5 分销面板(前端展示所有数据)
```
## EPIC 9 依赖图(学业方向+人工方案)
```
US-8.1 系统配置(人工方案参数——独立基础设施)
│
▼
US-9.1 学业方向AI解读(Dify学业Workflow)
│
▼
US-9.2 申请能量师出方案
│
├──(有上级能量师)──► US-9.3 能量师介入AI会话
│ │
└──(无上级)→ 提示找推荐链接 │
▼
US-9.4 方案价格协商
│
▼
US-9.5 方案付费与交付
│ │
│ ▼
│ US-9.6 人工方案分销佣金
│
▼
CommerceService 接口层(lilishop预留)
```
## 排期建议
| 周次 | 交付内容 |
|------|---------|
| **Week 1** | US-5.1 登录+注册完善 → US-8.1 系统配置(独立基础设施) |
| **Week 2** | US-1.1 咨询发起(依赖US-5.1登录) → US-1.2 三角可视化 → US-1.3 计算规则实现(附录A Step 1-6) |
| **Week 3** | US-3.1 AI解读 + Dify Workflow配置(附录B) → US-3.3 缓存 → US-3.2 免费/付费控制 |
| **Week 4** | US-3.4 AI问答 + Dify Chatflow配置(附录B) → US-2.1 分享图片 → US-2.2 PDF导出 |
| **Week 5** | US-4.1 能量师付费 + US-4.2 种子价 + US-6.6 C端订阅入口 → **US-9.1 学业Dify Workflow配置** |
| **Week 6** | US-6.2 带参注册 → US-6.1 推广码 → US-6.3 B端佣金(含升级补差) |
| **Week 7** | US-6.4 C端佣金 → US-6.5 分销面板 + US-8.2 订单管理 → **US-9.2 需求单 + US-9.3 介入会话** |
| **Week 8** | 联调测试 + US-8.3 佣金查看 + US-4.3 订阅状态/续费 + US-4.4 升级能量师 + BUG修复 |
| **Week 9+** | **US-9.4 价格协商 + US-9.5 付费交付 + US-9.6 分佣 → CommerceService 接口层** |
| **Week 10+** | **US-10.1 超级会员订阅入口 + US-10.2 支付开通 + US-10.5 关系页签 → TabBar改造 + US-10.6 关系人管理与双能量盘对比 → Dify关系Workflow + US-10.7 八星号码分析 → Dify号码Workflow + US-10.4 佣金结算 + US-10.3 升级路径** |
> **Phase 1 总预估:约 8 周核心功能 + 2 周超级会员功能(合计约 10 周)**
> 排期原则:先做核心流程(登录→能量盘→AI),再做支付分销。US-8.1(配置系统)作为基础设施优先完成,保障后续所有定价依赖。
> P2 功能(US-1.4 数字点击含义 / US-5.3 资料编辑 / US-7.x 批注与标签)可在 Phase 1 后期或 Phase 2 迭代。
---
## EPIC 10:超级会员订阅与关系能量分析(P1)
### US-10.1 超级会员订阅入口
**作为** 普通用户/C端用户
**我希望** 在各入口看到超级会员 ¥1,314 的订阅引导
**以便** 了解权益并一键升级,获取关系能量分析能力
**验收标准:**
**入口位置(3处):**
1. **关系页签付费引导页**(`pages/relations/index.vue`,非会员可见):
- 全屏展示超级会员功能预览:👫 夫妻合盘 / 👨👩👧👦 亲子匹配 / 👔 同事能量 / 🤝 朋友分析 / 📊 上下级 / 🔢 号码八星
- 底部固定按钮"开通超级会员 ¥1,314/年"
- 权益列表:无限AI解读 + 无限问答 + PDF导出不限次 + 无限关系人 + 推广赚佣金
- 底部小字:"已有超级会员?去登录 →"
2. **我的页面VIP卡片**(`pages/profile/index.vue`,非超级会员可见):
- C端年费用户显示升级引导:"🔗 升级超级会员 ¥1,314,解锁关系能量分析"
- 普通用户显示订阅卡片:"🏆 超级会员 ¥1,314/年 查看全部权益 →"
3. **AI解读页底部**(`chart/index.vue`,C端用户可见):
- C端用户底部引导卡片:"🔗 升级超级会员,查看你与TA的能量匹配"
- 普通用户底部引导卡片:"🏆 开通超级会员 ¥1,314,享无限解读+关系分析"
**交互流程:**
4. 点击任一"开通超级会员"按钮 → 跳转支付页 `product=super_member`,金额 ¥1,314
5. 未登录用户点击 → 先跳登录页,登录后自动跳转支付页
6. 已付费超级会员 → 不显示订阅卡片,显示"✅ 已开通超级会员"徽章 + 有效期
---
### US-10.2 超级会员支付与开通
**作为** 用户
**我希望** 完成微信支付后自动开通超级会员
**以便** 立即使用关系分析功能
**验收标准:**
**支付流程:**
1. 支付页 `payment/index.vue` 支持 `product=super_member`:
- 显示"超级会员 ¥1,314/年"标题
- 权益列表(卡片式):
- 🔗 关系能量分析(夫妻/亲子/同事/朋友/上下级/号码)
- 🤖 AI完整解读(无限次)
- 💬 AI问答互动(无限轮)
- 📄 PDF报告导出(无限次)
- 💰 推广赚佣金
- 支付按钮:"¥1,314 立即开通"
- 小字:"付款即同意《用户协议》"
2. `POST /api/pay/create` 接收 `productType=super_member`
3. 微信支付回调 `paySuccess()` 处理:
- `vipType` 设为 `'super_annual'`
- `vipEndTime` 设为 `当前时间 + 365天`
- 若用户首次付费,自动生成推广码(`referralCode`)
- 触发佣金结算(US-10.4)
4. 支付成功 → 跳转关系页首页,Toast "🎉 超级会员已开通!"
**续费逻辑:**
5. 到期前 7 天,我的页面显示续费提醒
6. 续费价格同标准价 ¥1,314(固定,无种子价)
7. 到期后降级为普通用户(vipType → NULL),关系页签变为付费引导页
---
### US-10.3 升级路径:C端↔超级↔能量师
**作为** 平台
**我希望** 支持年费升级与补差逻辑
**以便** 用户按需升级,无需重复付费
**验收标准:**
**场景①:C端年费 → 超级会员(补差价升级)**
1. C端用户(`vipType='annual'`)在我的页面看到"升级超级会员"入口
2. 点击后显示升级定价面板:
- 原价:¥1,314
- 年费剩余价值:(¥131 ÷ 365)× 剩余天数
- 应付 = ¥1,314 − 年费剩余价值
- 示例:已使用 100 天,剩余 265 天 → 剩余价值 = ¥131 × 265/365 ≈ ¥95.11 → 应付 = ¥1,314 − ¥95.11 = ¥1,218.89
3. 用户确认后 → 生成订单 `productType=super_member`,标记 `isUpgrade=true`,`originalProductType='annual'`
4. 支付成功后 → `vipType` 升级为 `'super_annual'`,`vipEndTime` 设为 `当前时间 + 365天`
5. C端佣金**不补扣**(已发放的年费佣金保持,超级会员佣金正常发放)
**场景②:超级会员 → 能量师(补差价+佣金补差升级)**
6. 超级会员(`vipType='super_annual'`)看到"升级能量师"入口
7. 升级定价:
- 种子价判断:若满足双条件(有效期+名额)→ 种子价 ¥1,314;否则标准价 ¥1,986
- 年费剩余价值:(¥1,314 ÷ 365)× 剩余天数
- 应付 = 能量师价格 − 超级会员剩余价值
8. 升级订单标记 `isUpgrade=true`,`originalProductType='super_member'`
9. **佣金补差**(同 US-6.3 升级补差逻辑):
- 查询 `commissions` 表中同一买家 + 同一收款人 + `product_type='super_member'` 的所有佣金之和
- 从本次 practitioner 佣金中减去该金额
- 若差值 ≤ 0,则本条佣金不创建
**场景③:C端年费 → 超级 → 能量师(两次升级累加)**
10. C端→超级的佣金不补扣
11. 超级→能量师时,扣除超级会员阶段已发的佣金(不含C端阶段)
12. 能量师价格评估种子价资格时,以首次付费身份为准
**不支持的路径:**
13. 普通用户 → 超级会员:全价 ¥1,314(无种子价)
14. 能量师 → 超级会员:不支持降级
---
### US-10.4 超级会员佣金结算
**作为** 平台
**我希望** 超级会员推广产品时自动结算佣金
**以便** 激励超级会员参与推广
**验收标准:**
**触发条件:**
1. 订单 `productType='super_member'` 且支付成功 → 进入超级会员佣金结算流程
2. 订单 `productType='annual'` → 走 US-6.4 C端佣金
3. 订单 `productType='practitioner'` → 走 US-6.3 B端佣金
**佣金计算——超级会员推广不同产品的差异化规则:**
4. **超级会员推广C端年费(¥131)** → 比例分成(同C端用户规则):
| 级别 | 默认值 | 配置键 |
|------|--------|--------|
| L1(直接上级) | 40% | `commission.annual.direct_rate`(复用) |
| L2(上上级) | 5% | `commission.annual.upstream_rate`(复用) |
5. **超级会员推广超级会员(¥1,314)** → 比例分成(专有配置):
| 级别 | 默认值 | 说明 |
|------|--------|------|
| L1(直接上级) | 30%(¥394.20) | L1超级会员佣金比例 |
| L2(上上级) | 5%(¥65.70) | L2超级会员佣金比例 |
| 平台留存 | 65%(¥853.10) | — |
| 分配对象 | 比例 | 金额 |
|---------|------|------|
| 直接上级 | 30% | ¥394.20 |
| 上上级 | 5% | ¥65.70 |
| 平台 | 65% | ¥853.10 |
6. **超级会员推广能量师(¥1,314+)** → 固定金额(同C端推荐能量师规则):
| 级别 | 默认值 | 说明 |
|------|--------|------|
| L1(直接上级) | ¥200 | 复用 `commission.practitioner.l1_cend` |
| L2(上上级) | ¥100 | 复用 `commission.practitioner.l2` |
**收款人资格:**
7. L1:`buyer.invitedBy` 对应的上级必须已付费(`referralCode != null`),才创建佣金
8. L2:上级的 `invitedBy` 对应的上上级必须已付费(`referralCode != null`),才创建佣金
9. 收款人不存在时 → 静默跳过,不报错
**升级场景佣金补差(`isUpgrade=true` 且 `originalProductType='super_member'`):**
10. 从超级会员升级为能量师的订单触发补差(同 US-6.3 逻辑):
- 应发佣金 = 本次 practitioner 应发金额 − 该买家此前 super_member 订单已支付给同一收款人的佣金总额
- 若差值 ≤ 0,则不创建
**状态与幂等:**
11. 佣金 `status` 直接写入 `"settled"`(即时到账)
12. 同一 `outTradeNo` 重复回调 → 幂等处理
13. 佣金固定金额/U 不受种子价/标准价差异影响
**统计更新:**
14. L1 创建时:`inviter.directCount += 1`,`inviter.convertedCount += 1`
15. L2 创建时:`inviter2.indirectCount += 1`
**配置项(后台可配):**
| 配置键 | 默认值 | 说明 |
|--------|--------|------|
| `pricing.super_member` | `131400` | 超级会员年费(分) |
| `commission.super_member.direct_rate` | `3000` | 超级会员直接佣金比例(万分比,3000=30%) |
| `commission.super_member.upstream_rate` | `500` | 超级会员上级佣金比例(万分比,500=5%) |
> 超级会员推广C端年费和能量师的佣金,复用现有配置项,不新增。
> 超级会员种子价不设置(固定 ¥1,314),因此不涉及种子价相关配置。
---
### US-10.5 关系页签入口与付费引导
**作为** 用户
**我希望** 在 tabBar 中看到"关系"入口
**以便** 快速了解并使用关系能量分析功能
**验收标准:**
**TabBar 配置:**
1. 小程序底部 TabBar 变更为 4 个页签(移除能量盘页签):
| 顺序 | 页签 | 页面路径 | 图标 |
|------|------|---------|------|
| ① | 首页 | `pages/index/index` | 🏠 |
| ② | **关系** | **`pages/relations/index`** | **🔗** |
| ③ | 分析 | `pages/records/index` | 📋 |
| ④ | 我的 | `pages/profile/index` | 👤 |
2. 能量盘页面(`pages/chart/index`)不作为 tabBar 入口,通过首页"开始咨询"和"分析"历史记录跳转访问
**非超级会员 → 付费引导页:**
3. 非超级会员(`vipType NOT IN ('super_annual')`)点击"关系"页签 → 展示功能预览页(不直接拦截,而是内容替换):
- 顶部标题:🔗 数字能量关系
- 功能介绍卡片(6个,各带示例图/图标):
- 👫 夫妻合盘:输入伴侣生日,看两人能量匹配度
- 👨👩👧👦 亲子匹配:了解孩子天赋,优化亲子沟通
- 👔 同事合作:分析职场合作能量,找到最佳搭档
- 🤝 朋友兼容:看友谊能量,理解彼此差异
- 📊 上下级关系:了解职场层级能量互动
- 🔢 号码能量:车牌号、手机号八星能量解码
- 底部固定按钮:"🔥 开通超级会员 ¥1,314/年"
- 点击按钮 → 跳转支付页 `product=super_member`
**超级会员 → 关系分析首页:**
4. 超级会员(`vipType='super_annual'`)正常展示关系分析功能(见 US-10.6 / US-10.7)
**身份标识:**
5. 超级会员在我的页面展示"🏆 超级会员"角标
6. 超级会员在 AI 问答回复尾部小字:"🔗 试试关系分析 →"
---
### US-10.6 添加关系人与多人关系能量分析
**作为** 超级会员
**我希望** 添加关系人、选中多人向 AI 提问并进入对话分析
**以便** 从数字能量角度理解人际关系互动
**验收标准:**
**关系首页布局:**
1. 关系页首页(`pages/relations/index.vue`)默认展示**当前用户自己的能量盘**(简化版三角图,仅显示主性格 O + 内外三层关键数字)
2. 首页上半部分:用户能量盘卡片 + "+ 添加关系人" CTA 按钮
3. 首页下半部分:按关系类型分组的**关系人列表**
**添加关系人入口:**
4. 点击"+ 添加关系人"弹出选择面板,选择**关系类型**(类型列表由 `sys_config` 中的 `relation.types` 配置项动态加载,详见 US-8.1):
| 关系类型 | 编码 | 说明 |
|---------|------|------|
| 👫 夫妻/伴侣 | `spouse` | 婚姻或恋爱关系能量匹配 |
| 👨👧 父母 | `parent` | 与父母的能量互动与孝顺建议 |
| 👶 子女 | `child` | 与子女的能量互动与教育建议 |
| 👴 祖父母 | `grandparent` | 与祖辈的能量互动与关怀建议 |
| 👼 孙子女 | `grandchild` | 与孙辈的能量互动与成长建议 |
| 👔 同事 | `colleague` | 职场合作者能量匹配 |
| 🤝 朋友 | `friend` | 社交友谊兼容性 |
| 📊 上级 | `superior` | 与上级管理者的能量关系 |
| 📊 下级 | `subordinate` | 与下属的能量关系 |
> 上表为系统默认值,管理员可在管理后台「关系类型配置」卡片中增删改关系类型。前端通过 `POST /api/config/relation-types` 获取当前可用类型列表。
5. 选择关系类型后 → 填写关系人信息:
- **姓名**(必填,2-10字)
- **出生年月日**(必填,与US-1.1相同输入格式:年/月/日)
- **性别**(选填)
- **备注**(选填,如"公司合伙人""大儿子")
6. 提交 → 调 `POST /api/relation/create` → 后端计算该关系人的能量盘并创建记录
**关系人列表:**
7. 关系人列表按关系类型分组展示,每组展示关系类型图标+标签
8. 每个条目展示:
- 关系人姓名 + 关系类型图标
- 上次分析时间(若从未分析显示"待分析")
- 操作按钮组:「分析」→ 进入多人分析流程
9. 列表支持下拉刷新、按关系类型筛选
10. 空状态:"还没有添加关系人,点击上方按钮开始探索吧 →"
**多人分析流程(核心功能):**
11. 点击任一关系人的「分析」按钮,或点击用户自己能量盘上的「发起分析」,进入**多人分析选择页**(`pages/relations/analysis-select.vue`):
12. 选择页布局:
- 顶部:输入框 — "输入您想咨询的问题"(必填,如"我俩在事业发展上是否互补?""孩子适合往哪个方向培养?")
- 中部:**分析成员选择区** — 默认选中当前用户 + 所选关系人,可额外勾选更多关系人(支持多选,至少选2人)
- 每个成员项展示:头像/姓名/关系类型标签 + 勾选框
- 底部:「开始分析」大按钮
13. 点击"开始分析" → 调 `POST /api/relation/analysis/start` → 创建分析会话 → 跳转到**分析对话页**
14. **分析对话页**(`pages/relations/analysis-chat.vue`)类似 AI 问答页面:
- 顶部导航栏:标题"关系能量分析" + 参与成员列表图标(点击可展开查看当前分析的成员信息)
- 消息区:显示 AI 分析回复 + 用户追问,与普通聊天 UI 一致
- 输入区:用户可继续追问(保持上下文),每个问题自动带上当前分析会话 ID + 参与成员清单作为上下文
- 参与成员不可在对话中途更改(若要变更成员,需结束当前分析重新选择)
15. 分析记录自动保存,可在**分析记录列表**中回溯 → 入口在关系首页顶部标签切换:「关系人」「分析记录」
**分析记录管理:**
16. 分析记录列表(`pages/relations/analysis-records.vue`):
- 按最后互动时间倒序排列
- 每条记录展示:分析问题摘要、参与人数、最后消息时间
- 点击 → 进入对应的分析对话页并恢复完整聊天历史
- 支持单条删除
17. 分析记录与普通咨询记录**互不干扰**(分开两张表或通过 type 字段区分)
**关系人管理:**
18. 长按关系人条目 → 弹出操作菜单:编辑 / 删除
19. 编辑:可修改备注和关系类型(不可修改生日,若填错需删除重建)
20. 删除:确认弹窗"确认删除 [姓名]?此操作不可恢复"
21. 删除后同时删除关联的分析记录(分析记录内容保留但标记"成员已删除")
**后端设计:**
22. 新增 `relations` 表:
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | `BIGINT PK` | 主键 |
| `user_id` | `BIGINT` | 超级会员ID |
| `relation_type` | `VARCHAR(20)` | 关系类型编码,对应 `relation.types` 配置项中的 code 值(spouse/parent/child/grandparent/grandchild/colleague/friend/superior/subordinate 为默认值) |
| `name` | `VARCHAR(20)` | 关系人姓名 |
| `birthday` | `VARCHAR(10)` | 出生年月日(YYYY-MM-DD) |
| `gender` | `VARCHAR(4)` | 性别,可为 NULL |
| `remark` | `VARCHAR(100)` | 备注,可为 NULL |
| `chart_id` | `BIGINT` | 关系人能量盘ID(ChartRecord 外键) |
| `created_at` | `DATETIME` | 创建时间 |
| `updated_at` | `DATETIME` | 更新时间 |
23. 新增 `relation_analysis_records` 表:
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | `BIGINT PK` | 主键 |
| `user_id` | `BIGINT` | 超级会员ID |
| `question` | `VARCHAR(500)` | 用户咨询的问题 |
| `member_ids` | `TEXT` | 参与分析的关系人ID列表(JSON数组,含用户自己的 chart_id) |
| `member_snapshot` | `TEXT` | 成员快照(JSON,含姓名/关系类型/chart_id,保证删除后仍可查看) |
| `last_message_at` | `DATETIME` | 最后消息时间 |
| `created_at` | `DATETIME` | 创建时间 |
| `updated_at` | `DATETIME` | 更新时间 |
24. 新增接口:
| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/relation/create` | POST | 添加关系人(含能量盘计算) |
| `/api/relation/list` | POST | 获取关系人列表(支持 type 筛选) |
| `/api/relation/update` | POST | 修改备注/关系类型 |
| `/api/relation/delete` | POST | 删除关系人 |
| `/api/relation/analysis/start` | POST | 发起分析(创建分析会话,返回 session_id) |
| `/api/relation/analysis/list` | POST | 分析记录列表 |
| `/api/relation/analysis/detail` | POST | 分析记录详情+成员信息 |
| `/api/relation/analysis/delete` | POST | 删除分析记录 |
| `/api/relation/analysis/chat/send` | POST | 发送分析对话消息(调 Dify Chatflow) |
| `/api/relation/analysis/chat/history` | POST | 获取分析对话历史 |
25. 新增关系人时,若系统已有所需生日(此人之前在任何 ChartRecord 中存在),直接复用已计算的 ChartRecord(按 `birthday` 查重),不重复计算
26. 超级会员无上限添加关系人(不限量)
27. 分析对话通过 Dify **Chatflow**(非 Workflow)实现,输入参数:用户问题 + 参与成员的 24 位数字数组 + 关系类型标签,输出自然语言回答
**后续迭代(Phase 1 不实现):**
- 匹配度评分计算与展示
- 结构化 AI 解读维度(沟通/情感/事业分项评分)
- AI 解读一键生成分享截图
### US-10.7 八星号码能量分析
**作为** 超级会员
**我希望** 输入车牌号或手机号,查看数字能量分布
**以便** 了解号码对运势的潜在影响
**验收标准:**
**输入页面(`pages/relations/number-analysis.vue`):**
1. 关系页首页"号码分析"入口 → 进入号码分析页
2. 顶部选项卡切换:📱 手机号 | 🚗 车牌号
3. 输入框:
- **手机号**:11位数字,自动格式化(xxx xxxx xxxx)
- **车牌号**:省份简称(下拉选择)+ 字母数字组合(≤7位)
4. 输入校验:手机号必须 11 位纯数字,车牌号必填省份 + 号码
5. 点击"分析"按钮 → 调 `POST /api/relation/number-analyze`
**号码能量计算规则(八星数字能量):**
6. 后端将号码字符串按**相邻两位一组**的滑动窗口拆分,每对数字映射到八星能量类型:
| 星位 | 数字组合 | 能量属性 |
|------|---------|---------|
| 💰 **天医** | 13, 31, 68, 86, 94, 49, 72, 27 | 财富、正姻缘 |
| 🏆 **延年** | 19, 91, 78, 87, 34, 43, 26, 62 | 事业、领导力 |
| 🌱 **生气** | 14, 41, 67, 76, 93, 39, 82, 28 | 贵人、社交 |
| 🔒 **伏位** | 11, 22, 33, 44, 66, 77, 88, 99 | 稳定、保守 |
| ⚡ **绝命** | 12, 21, 69, 96, 84, 48, 73, 37 | 决断、冲动 |
| ⚠️ **祸害** | 17, 71, 89, 98, 46, 64, 23, 32 | 口舌、是非 |
| 👻 **五鬼** | 18, 81, 79, 97, 36, 63, 42, 24 | 变动、才华 |
| 💔 **六煞** | 16, 61, 74, 47, 38, 83, 92, 29 | 偏桃花、情绪 |
7. 统计每种能量出现的次数和占比
8. 综合评级:根据吉星(天医/延年/生气)与凶星(绝命/祸害/五鬼/六煞)的比例给出总分(0-100)
**号码分析结果展示:**
9. 结果页面分两部分:
- **第一部分:能量分布图**
```
号码:138 1234 5678
能量分布:
💰 天医 ████████░░ 2次(13, 68)
🏆 延年 ████░░░░░░ 1次(19)
🌱 生气 ██████░░░░ 1次(14)
🔒 伏位 ██████████ 3次(33, 44, 66)
⚡ 绝命 ██░░░░░░░░ 0次
⚠️ 祸害 ██░░░░░░░░ 0次
👻 五鬼 ████░░░░░░ 1次(78)
💔 六煞 ████░░░░░░ 1次(34)
综合评分:78/100 ⭐ 中上
```
- **第二部分:AI智能解读**(调 Dify 号码分析 Workflow):
- 整体能量倾向
- 吉星集中领域(如"天医双现,财运旺盛")
- 凶星提醒(如"五鬼+六煞组合,注意情绪波动")
- 改善建议(如"建议保留13-68组合的吉星能量")
10. 底部"保存到关系人列表"按钮(可选,将号码作为关系人的一种类型保存)
11. 分析结果支持分享截图
**后端设计:**
12. 新增号码分析记录表 `number_analyses`:
| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | `BIGINT PK` | 主键 |
| `user_id` | `BIGINT` | 超级会员ID |
| `number_type` | `VARCHAR(10)` | 号码类型(phone / license_plate) |
| `number_raw` | `VARCHAR(20)` | 原始号码 |
| `energy_result` | `TEXT` | 能量分析结果JSON |
| `score` | `INT` | 综合评分(0-100) |
| `ai_analysis_cache` | `TEXT` | AI解读缓存 |
| `created_at` | `DATETIME` | 创建时间 |
13. 新增接口:
| 端点 | 方法 | 说明 |
|------|------|------|
| `/api/relation/number-analyze` | POST | 提交号码分析 |
| `/api/relation/number-history` | POST | 获取历史号码分析记录 |
| `/api/relation/number-detail` | POST | 获取单条号码分析详情 |
14. 相同的号码+同用户,24小时内重复请求 → 返回缓存结果(同 US-3.3 缓存策略)
15. 号码分析限价:超级会员不限次(非会员不可用)
**Dify Workflow 配置:**
16. 新增**号码能量分析 Workflow**,输入为号码能量分布JSON + 原始号码,输出为智能解读文本
17. 与关系分析 Workflow 共享同一套数字能量学知识库
---
### EPIC 10 依赖图
```
US-5.1 微信登录
│
▼
US-10.5 关系页签入口与付费引导(tabBar改造)
│ │
│ (非会员) (超级会员)
▼ ▼
US-10.1 超级会员订阅入口 ──► US-10.6 关系人+双能量盘
│ │
▼ ├──► Dify 关系分析 Workflow
US-10.2 支付与开通 │
│ ▼
├──► US-10.3 升级路径 US-10.7 八星号码分析
│ ├── C端→超级→能量师 │
│ └── 佣金补差 └──► Dify 号码分析 Workflow
│
▼
US-10.4 超级会员佣金结算
│
├── US-6.4 C端佣金(推广C端)
├── (新品)超级会员佣金(推广超级会员,30%+5%)
└── US-6.3 B端佣金(推广能量师,复用半额固定)
```
---
## 附录A:【新计算规则】代码文件变更清单
> 以下清单基于新命名体系(A-X)和咨询会话管理需求,列出所有需修改的代码文件及变更内容。
### A.1 后端 Java
| 文件 | 变更类型 | 变更内容 |
|------|---------|---------|
| `CalculatorService.java` | 重写 | 内部7位从 `F,G,H,I,M,N,O` → `I,J,K,L,M,N,O`;新增外部9位 `P,Q,R,S,T,U,V,W,X` 的独立计算;新增 `calculateFullTriangle()` 返回全部24个位置 |
| `ChartService.java` | 改造 | 新增 `startConsultation(userId, name, birthday, questions)` 方法,含:①查 userId+name+birthday 是否已有记录;②已有则直接返回+聊天历史;③无则服务器端调 `CalculatorService` 计算+创建记录+可选首次AI解读 |
| `ChartController.java` | 改造 | 保留 `/api/chart/create`(兼容旧版);**新增 `POST /api/consultation/start` → 调 `ChartService.startConsultation()`** |
| `ChartRecord.java` | 微调 | 新增 `lastInteractionAt` 字段(`LocalDateTime`,用于列表排序);加 `@Table(uniqueConstraints=...)` 定义 `(userId, name, birthday)` 联合唯一 |
| `ChartRecordRepository.java` | 新增 | `Optional findByUserIdAndNameAndBirthday(Long userId, String name, String birthday)` |
| `UserService.java` | 微调 | `checkDailyQuota()` 和 `consumeQuota()` 已有逻辑不变(3次/天全局计数),但新增注释明确"非VIP每日3次绑定当前能量盘,切换生日不重置" |
| `ProfileController.java` | 微调 | 咨询列表接口按 `lastInteractionAt` 倒序 |
| `DifyService.java` | **新增** | Dify API 客户端,封装 `POST /v1/workflows/run`(能量盘解读)和 `POST /v1/chat-messages`(AI问答)两个接口;含签名、错误重试、超时处理,详见**附录B** |
| `ChatService.java` | 改造 | 原直调 LLM 逻辑改为调 `DifyService`;解读生成走 `DifyService.runWorkflow()`;问答走 `DifyService.sendChatMessage()`;在调用前检查配额(US-3.4) |
### A.2 前端 Vue / JS
| 文件 | 变更类型 | 变更内容 |
|------|---------|---------|
| `client/utils/calculator.js` | 废弃/降级 | `calculateTriangle()` 保留为离线兜底,不再作为主路径调用;内部命名改为 `I,J,K,L,M,N,O`;新增 `calculateFullTriangle()` 含外部 P-X;主入口加注释 `@deprecated 请使用后端计算` |
| `client/stores/chart.js` | 改造 | `computeChart()` 不再调 `calculateTriangle()`,改为调 `consultationApi.start()`;返回数据中的 `positions` 直接写入 `currentChart`;不再调 `analyzeTriangle()`(由后端返回) |
| `client/components/TriangleChart.vue` | 重写 matrix() | `innerBottom` 从 `[d.F,d.G,d.H,d.I]` → `[d.I,d.J,d.K,d.L]`;`outerLeft` 从 `{main:d.M, sub:[d.F,d.G]}` → `{main:d.R, sub:[d.P,d.Q]}`;`outerRight` 从 `{main:d.N, sub:[d.H,d.I]}` → `{main:d.U, sub:[d.S,d.T]}`;`outerTop` 从 `{main:d.O, sub:[d.M,d.N]}` → `{main:d.X, sub:[d.V,d.W]}` |
| `client/pages/index/index.vue` | 改造 | `onAnalyze()` 改为:①调 `POST /api/consultation/start`(传 birthday + name + questions);②若返回 `isNew=true` 且 `requireConfirmation=true` 则弹确认框;③确认后再次请求;④成功后跳转 `chart/index`;⑤"想了解的问题"加 `maxlength=100` + 实时字数显示 |
| `client/utils/api.js` | 新增 | `consultationApi`:`start(data)` → `POST /api/consultation/start`;`detail(id)` → `POST /api/consultation/detail` |
| `client/pages/chart/index.vue` | 微调 | 适配新的 API 返回结构(`chartData.positions` 含全部 I-X);`onMounted` 加载历史消息逻辑不变 |
| `client/pages/records/index.vue` | 微调 | 列表按 `lastInteractionAt` 排序;详情页恢复聊天历史逻辑不变 |
### A.3 数据库
| 变更 | 说明 |
|------|------|
| `chart_records` 表加联合唯一索引 | `UNIQUE INDEX uk_user_name_birthday (user_id, name, birthday)`,确保同用户+同姓名+同生日只有一条咨询记录 |
| `chart_records` 表加字段 | `last_interaction_at DATETIME`,默认等于 `created_at`,每次 AI 聊天时更新,用于列表排序 |
| `chart_records` 表现有字段 | `chart_data` 列存储的 JSON 结构从 7个旧位置 → 16个新位置(内部 I-O + 外部 P-X) |
### A.4 变更执行顺序
```
Step 1: US-1.3(本对照表)→ 开发团队通读,确保理解命名对应关系
Step 2: 数据库迁移 → 加索引+字段
Step 3: CalculatorService.java → 重写为新命名+外部计算
Step 4: ChartService.java + ChartController.java → 新增 startConsultation()
Step 5: stores/chart.js + api.js → 前端调后端新接口(主路径走后端;后端不可用时 calculator.js 降级兜底,仅展示离线计算版能量盘,不提供AI解读和咨询记录)
Step 6: TriangleChart.vue → matrix() 改用新命名+独立外部值
Step 7: pages/index/index.vue → 确认弹窗 + 100字限制
Step 8: Dify 配置 →
8a. 在 Dify 平台创建 Workflow(能量盘解读)和 Chatflow(AI问答)
8b. 上传知识库文档(数字能量学语料)
8c. 发布工作流,获取 API Key
Step 9: DifyService.java + ChatService.java → 集成 Dify API
Step 10: 联调 → 前后端打通 end-to-end,含 Dify 工作流调试验收
```
---
## 附录B:Dify AI 架构设计
> Dify 是开源 LLM 应用开发平台,提供可视化工作流编排、RAG 知识库、模型管理等能力。
> 本项目使用 Dify 的两个应用类型:**Workflow**(能量盘解读生成)和 **Chatflow**(AI交互问答)。
### B.1 整体架构
```
┌─────────────────────────────────────────────────────────┐
│ 微信小程序前端 │
│ POST /api/chart/interpret POST /api/chat/send │
└────────────────────┬─────────────────────┬──────────────┘
│ │
┌────────────────────▼─────────────────────▼──────────────┐
│ Java 后端 (Spring Boot) │
│ │
│ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ChatController│ │ChartController│ │ChatService │ │
│ └──────┬──────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └──────────┬──────┘ │ │
│ │ │ │
│ ┌──────────▼──────────┐ ┌───────────▼────────┐ │
│ │ DifyService.java │ │ DifyService.java │ │
│ │ runWorkflow() │ │ sendChatMessage() │ │
│ └──────────┬──────────┘ └───────────┬─────────┘ │
└────────────────────┼─────────────────────────┼───────────┘
│ │
┌────────────────────▼─────────────────────────▼───────────┐
│ Dify API (自建部署 / SaaS) │
│ │
│ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ Workflow(解读) │ │ Chatflow(问答) │ │
│ │ │ │ │ │
│ │ 开始 → 知识检索 │ │ 开始 → 接收消息 │ │
│ │ → LLM生成解读 │ │ → 知识检索 → LLM回答 │ │
│ │ → 格式化输出 │ │ → 返回答案 │ │
│ └────────┬─────────┘ └──────────┬───────────┘ │
│ │ │ │
│ └──────────┬───────────────┘ │
│ │ │
│ ┌──────────▼──────────┐ │
│ │ 知识库(RAG) │ │
│ │ ├─ 主性格含义库 │ │
│ │ ├─ 组合数字含义库 │ │
│ │ ├─ 三区年龄解读库 │ │
│ │ └─ 常见能量盘案例库 │ │
│ └─────────────────────┘ │
└──────────────────────────────────────────────────────────┘
```
**关键原则:**
- Java 后端是**最薄的一层**,只做:参数校验 → 配额检查 → 调用 Dify API → 透传结果
- 所有 AI 逻辑(prompt 设计、知识检索策略、输出格式)都在 Dify 工作流中配置
- 修改解读模板或知识内容不需要改 Java 代码,只需要在 Dify 平台更新工作流
### B.2 Dify Workflow(能量盘解读)—— 一次性解读生成
**用途:** US-3.1 AI解读展示
**Dify 应用类型:** **Workflow(工作流)**——单轮执行,无需维护对话历史
**触发方式:** API 调用,blocking 模式
**输入变量:**
| 变量名 | 类型 | 说明 |
|--------|------|------|
| `chart` | `object` | 24个能量盘位置的值 `{ A:8, B:1, ..., X:5 }` |
| `name` | `string` | 用户姓名 |
| `birthday` | `string` | 出生日期 `YYYY-MM-DD` |
**工作流节点编排:**
```
[开始节点]
↓
[知识检索 1] 查主性格(O)含义
↓
[知识检索 2] 查左区(P,R)21-40岁解读
↓
[知识检索 3] 查顶部(V,X)41-60岁解读
↓
[知识检索 4] 查右区(S,U)61+岁解读
↓
[知识检索 5] 查特殊组合(如 I+J=11, M+O 等)
↓
[LLM 节点]
系统提示词:
"你是一个专业的数字能量学分析师。
根据以下能量盘数据和检索到的知识,生成完整的能量盘解读。
必须严格按照以下结构输出..."
↓
[代码节点 / 输出解析]:确保输出 JSON 结构正确
↓
[结束节点] → 输出 `{ sections: [...], summary: "..." }`
```
**输出格式(`data.outputs`):**
```json
{
"sections": [
{
"title": "主性格解读",
"position": "O",
"value": 6,
"content": "主性格数字 6 代表…",
"keywords": ["责任心", "家庭", "关爱"]
},
{
"title": "左区(21-40岁)",
"positions": ["P", "Q", "R"],
"values": [8, 3, 2],
"content": "左区数字组合 8-3-2 代表…"
},
{
"title": "顶部(41-60岁)",
"positions": ["V", "W", "X"],
"values": [4, 1, 5],
"content": "顶部数字组合 4-1-5 代表…"
},
{
"title": "右区(61+岁)",
"positions": ["S", "T", "U"],
"values": [6, 8, 5],
"content": "右区数字组合 6-8-5 代表…"
}
],
"summary": "整体能量盘评价…",
"combination_notes": ["数字 I(4)+J(3)=7,形成…", "M(7)+O(6)=13→4,形成…"]
}
```
### B.3 Dify Chatflow(AI交互问答)—— 多轮对话
**用途:** US-3.4 AI交互问答
**Dify 应用类型:** **Chatflow(对话工作流)**——多轮对话,自动维护 `conversation_id`
**触发方式:** API 调用,streaming 模式(打字机效果)
**第一轮消息传入的上下文变量:**
```json
{
"inputs": {
"chart": { "A":8, "B":1, "C":9, "D":6, "E":3, "F":0, "G":1, "H":4,
"I":4, "J":3, "K":6, "L":5, "M":7, "N":2, "O":6,
"P":8, "Q":3, "R":2, "S":6, "T":8, "U":5, "V":4, "W":1, "X":5 },
"user_name": "张三",
"birthday": "1996-03-14"
},
"query": "我的主性格数字6代表什么?",
"user": "uid_123",
"response_mode": "streaming"
}
```
**后续轮次:** 只传 `query` + `conversation_id`,无需重复传入能量盘数据
**Chatflow 节点编排:**
```
[开始节点]
↓
[问题分类节点]
├─ 问数字含义 → [知识检索] → [LLM 回答]
├─ 问运势建议 → [知识检索] → [LLM 回答]
└─ 其他问题 → [LLM 直接回答]
↓
[LLM 节点]
系统提示词:
"你是一个数字能量学咨询助手。
用户的能量盘数据已作为上下文变量传入。
请基于用户的能量盘数据和知识库内容回答问题。
如果问题涉及具体数字,请引用该数字在能量盘中的位置和含义。"
↓
[结束节点] → 输出答案文本
```
### B.4 知识库设计
需要在 Dify 平台创建的知识库文档:
| 文档名称 | 内容 | 用途 |
|----------|------|------|
| **数字能量学基础** | 数字 1-9 的基础能量含义、吉凶属性 | LLM 基础理解 |
| **主性格数字解读** | 每个主性格数字(1-9)的详细性格特质、优缺点、代表人物 | 主性格解读 |
| **位置含义对照表** | 每个位置(A-X)代表的人生领域和能量属性 | 各章节解读 |
| **组合数字解读** | 常见数字组合(如11/22/33/13/14等)的特殊含义 | 组合分析 |
| **三区年龄段解读** | 21-40 / 41-60 / 61+ 三个年龄段的典型命理模式 | 三区解读 |
| **常见能量盘案例** | 典型能量盘 + 完整解读示例(Few-shot 示例) | 提升解读质量 |
**文档格式建议:**
- 每个文档的结构化程度越高越好,推荐 Markdown 表格 + 标题层级
- 示例格式:
```markdown
# 主性格数字 7
## 核心特质
- 关键词:分析力、哲学思维、追求真理
- 能量属性:精神导向,向内探索
## 性格描述
主性格数字7的人天生具有强烈的分析能力和探索精神…
## 优势
- 逻辑思维强
- 善于发现规律
- 独立自主
## 劣势
- 容易多疑
- 社交上偏孤僻
- 过度分析导致行动迟缓
## 代表人物
- 爱因斯坦、达芬奇
```
### B.5 Java 后端集成
**`DifyService.java` 核心接口:**
```java
@Service
public class DifyService {
// 配置(从 application.yml 读取)
@Value("${dify.api-base}")
private String apiBase; // e.g. "https://api.dify.ai/v1"
@Value("${dify.workflow-api-key}")
private String workflowApiKey; // 能量盘解读 Workflow 密钥
@Value("${dify.chatflow-api-key}")
private String chatflowApiKey; // AI问答 Chatflow 密钥
/**
* 调用 Dify Workflow 生成能量盘解读(US-3.1)
* @param chartData 24个数字的 Map
* @param userName 用户姓名
* @param birthday 出生日期
* @return 结构化解读结果(sections + summary)
*/
public InterpretationResult runInterpretation(
Map chartData, String userName, String birthday
) {
// 1. 构造 inputs
// 2. POST /v1/workflows/run (blocking)
// 3. 解析 data.outputs 为 InterpretationResult
// 4. 超时 15s,重试 1 次
}
/**
* 调用 Dify Chatflow 发送消息(US-3.4)
* @param chartData 24个数字(仅首轮传入)
* @param conversationId 已有会话ID(后续轮次)
* @param query 用户问题
* @param userId 用户标识
* @param isFirstRound 是否首轮
* @return Dify 流式响应或阻塞响应
*/
public ChatResponse sendChatMessage(
Map chartData,
String conversationId,
String query,
String userId,
boolean isFirstRound
) {
// 1. 首轮时传入 inputs(chart 数据)
// 2. POST /v1/chat-messages (streaming)
// 3. 返回 SSE 流或阻塞结果
}
}
```
**`ChatService.java` 改造要点:**
```java
@Service
public class ChatService {
public ChatResponse sendMessage(Long userId, Long chartId, String message) {
// 1. 检查用户配额(US-3.4)
if (!isVip(userId) && getTodayQuota(userId) >= 3) {
throw new BusinessException("今日AI问答次数已用完");
}
// 2. 获取能量盘数据
ChartRecord record = chartRecordRepository.findById(chartId);
Map chartData = record.getChartData();
// 3. 调用 Dify(Chatflow)
String conversationId = record.getDifyConversationId();
boolean isFirstRound = (conversationId == null);
ChatResponse response = difyService.sendChatMessage(
chartData, conversationId, message, userId.toString(), isFirstRound
);
// 4. 首次对话保存 conversationId
if (isFirstRound) {
record.setDifyConversationId(response.getConversationId());
chartRecordRepository.save(record);
}
// 5. 消耗配额
consumeQuota(userId);
return response;
}
}
```
**`application.yml` 新增配置:**
```yaml
dify:
api-base: https://api.dify.ai/v1
workflow-api-key: app-xxxxx # 能量盘解读 Workflow
chatflow-api-key: app-yyyyy # AI问答 Chatflow
timeout: 15000 # 单次调用超时 15s
```
### B.6 Dify 部署模式建议
| 模式 | 适用阶段 | 说明 |
|------|---------|------|
| **Dify SaaS(cloud.dify.ai)** | 开发/测试 | 快速上手,无需自建,有免费额度 |
| **自建部署(Docker)** | 生产 | 数据不出域,可控成本,建议生产环境使用 |
自建部署参考:`https://github.com/langgenius/dify`
### B.7 开发流程建议
1. **先配知识库**:在 Dify 平台创建知识库,上传数字能量学语料文档
2. **再搭 Workflow**:创建能量盘解读工作流,配置节点链,用测试数据调通
3. **再搭 Chatflow**:创建 AI 问答对话工作流,测试多轮对话
4. **Java 集成**:开发 `DifyService.java`,调通 Workflow 和 Chatflow 两个 API
5. **联调验收**:前端通过后端调用 Dify,验证解读质量和问答效果
### B.8 与 US 的对应关系
| Dify 组件 | 对应 US | 备注 |
|-----------|---------|------|
| Workflow(能量盘解读) | US-3.1 AI解读展示、US-3.2 付费控制 | Workflow 输出由 US-3.2 决定是否全文展示 |
| **Workflow(学业方向)** | **US-9.1 学业方向AI解读** | **新增专用Workflow,输入24个A-X数字,输出学业方向分析JSON** |
| Chatflow(AI问答) | US-3.4 AI交互问答 | 配额控制在 Java 后端,不经过 Dify;能量师介入消息不走Dify |
| 知识库 | US-3.1、US-3.4、US-9.1 | 三个工作流共用同一套知识库 |
| 无(纯后端) | US-3.3 解读内容缓存、US-9.5 CommerceService | 缓存逻辑在 Java 后端,不涉及 Dify |
---
## 附录C:四类用户角色权限对照表
> 覆盖系统所有功能的权限边界,按角色逐一对比。Phase 1 覆盖四类用户(含新增超级会员)。
### C.1 概览
| | 普通用户 | C端年费用户 | **家庭套餐** | **超级会员(暂缓)** | 能量师用户 |
|--|---------|------------|-------------|-------------------|-----------|
| **年费** | ¥0 | ¥131 | **¥686** | **¥1,314(暂缓上线)** | ¥1,314(种子)/ ¥1,986(标准) |
| **数据库标记** | `vipType=NULL` | `vipType='annual'` | **`vipType='family_plan'`** | `vipType='super_annual'`(预留) | `vipType='practitioner'` |
| **到期降级** | — | → 普通用户 | → 普通用户 | → 普通用户(上线后) | → 普通用户 |
| **续费价格** | — | 标准价 ¥131 | 标准价 ¥686 | 标准价 ¥1,314(固定价) | 标准价 ¥1,986 |
| **定位** | 浏览体验 | 给自己看,轻度社交 | **家庭关系能量分析** | 待定(后续能量包) | 给客户看,商业工具 |
| **可咨询人数** | 3人 | **9人** | **9人** | 9人(暂缓) | 不限 |
| **每人聊天次数** | 3次/天 | **不限** | **不限** | 不限(暂缓) | 不限 |
| **关系能量分析** | ❌ | ❌ | **✅** | ✅(暂缓) | ✅ |
| **八星号码分析** | ❌ | ❌ | ❌ | ✅(暂缓) | ✅ |
| **推广佣金** | ❌ | ✅ | **✅** | ✅(暂缓) | ✅(固定金额) |
### C.2 功能权限总表
```
能力 普通用户 C端¥131 家庭套餐¥686 超级¥1,314(缓) 能量师¥1,314+
──────────────── ─────── ─────── ────────── ────────────── ──────────────
生成能量盘 ✅ ✅ ✅ ✅ ✅
查看能量盘可视化 ✅ ✅ ✅ ✅ ✅
数字点击查看含义 ✅ ✅ ✅ ✅ ✅
AI解读·主性格概要 1次/天 不限 不限 不限 不限
AI解读·完整五区 ❌ ✅ ✅ ✅ ✅
AI问答互动 3轮/天 不限 不限 不限 不限
学业方向AI解读 1次/天 不限 不限 不限 不限
分享图片到微信 1次/天 不限 不限 不限 不限
导出PDF报告 ❌ ✅ ✅ ✅ ✅
🔗 关系能量分析 ❌ ❌ ✅ ✅(缓) ✅
👫 九类关系人 ❌ ❌ ✅ ✅(缓) ✅
🔢 八星号码分析 ❌ ❌ ❌ ✅(缓) ✅
历史记录查看 近7天 全部 全部 全部 全部
推广码+分销面板 ❌ ✅ ✅ ✅(缓) ✅
直接邀请佣金 ❌ 40% 40% 40%(缓) 40%
间接邀请积分 ❌ 10积分 10积分 10积分(缓) 10积分
团队月度分红 ❌ ❌ ❌ ❌ 5%(团队销售额)
申请能量师出方案 ✅ ✅ ✅ ✅ ✅
能量师介入AI会话 ❌(被动) ❌(被动) ❌(被动) ❌(缓/被动) ✅(主动)
接受人工方案付费 ✅ ✅ ✅ ✅ ✅
能量盘批注(P2) ❌ ✅ ✅ ✅ ✅
客户标签分组(P2) ❌ ❌ ❌ ❌ ✅
个人资料编辑 ✅ ✅ ✅ ✅ ✅
个人中心标签 "普通用户" "C端会员" "家庭套餐会员" "🏆超级会员(缓)" "能量师"
订阅引导卡片 可见 不可见 不可见 不可见 不可见
续费提醒 — 到期前7天 到期前7天 到期前7天 到期前7天
```
能力 普通用户 C端¥131 **超级¥1,314** 能量师¥1,314+
───────────────────────── ────────── ────────── ────────────── ──────────────
生成能量盘 ✅ ✅ ✅ ✅
查看能量盘可视化 ✅ ✅ ✅ ✅
数字点击查看含义 ✅ ✅ ✅ ✅
AI解读·主性格概要 1次/天 不限 不限 不限
AI解读·完整五区 ❌ ✅ ✅ ✅
AI问答互动 3轮/天 不限 不限 不限
学业方向AI解读 1次/天 不限 不限 不限
分享图片到微信 1次/天 不限 不限 不限
导出PDF报告 ❌ 不限 不限 不限
🔗 关系能量分析(US-10) ❌ ❌ **✅ 全功能** ❌
👫 夫妻/亲子/同事/朋友/上下级 ❌ ❌ **✅** ❌
🔢 八星号码分析 ❌ ❌ **✅** ❌
历史记录查看 近7天 全部 全部 全部
推广码+分销面板 ❌ ✅ ✅ ✅
推广C端年费得佣金 ❌ 40%+5%分成 40%+5%分成 40%+5%分成
推广超级会员得佣金 ❌ ❌ 30%+5%分成 ❌
推广能量师年费得佣金 ❌ ❌ ¥200 + ¥100 ¥500 + ¥100
申请能量师出方案 ✅ ✅ ✅ ✅
能量师介入AI会话 ❌(被动) ❌(被动) ❌(被动) ✅(主动)
接受人工方案付费 ✅ ✅ ✅ ✅
能量盘批注(P2) ❌ ✅ ✅ ✅
客户标签分组(P2) ❌ ❌ ❌ ✅
个人资料编辑 ✅ ✅ ✅ ✅
个人中心标签 "普通用户" "C端会员" **"🏆 超级会员"** "能量师"
订阅引导卡片 可见 不可见 不可见 不可见
续费提醒 — 到期前7天 到期前7天 到期前7天
```
### C.3 按场景的用户体验流程
#### 场景 1:首次进入
```
所有用户
│
├─ 微信登录 → 完善资料(昵称/头像/生日/性别)
│
└─ 输入生日 → 生成能量盘 → 查看能量盘图 → 查看主性格概要(免费1次)
│
├─ 遇到付费墙(完整解读/PDF/无限问答)
│ └─ 看到 ¥131 开通引导卡片
│
└─ 保持免费用户,每日 3 轮问答 + 1 次分享
```
#### 场景 2:升级为 C端年费(¥131)
```
普通用户点击"开通 ¥131"
│
├─ 微信支付 ¥131
├─ vipType → 'annual', vipEndTime → +365天
├─ 推广码自动生成
│
└─ 解锁能力:
├─ AI完整解读(无限次)
├─ AI问答(不限轮数)
├─ 分享图片(不限次)
├─ PDF导出(不限次)
├─ 历史记录(全部)
├─ 分销面板可见
└─ 推广C端年费赚 40% 直接佣金
```
#### 场景 2.5:升级为家庭套餐(¥686)
```
普通用户或C端用户点击"开通家庭套餐 ¥686"
│
├─ 微信支付 ¥686
├─ vipType → 'family_plan', vipEndTime → +365天
├─ 推广码自动生成(若首次付费)
│
└─ 解锁能力(在C端基础上增加):
├─ 关系能量分析(九类关系人:夫妻/父母/子女/祖父母/孙子女/同事/朋友/上级/下级)
├─ 添加关系人(不限数量)
├─ 多人分析选择 + AI对话分析 + 分析记录
├─ 推广任意付费产品赚 40% 直接佣金
└─ 间接邀请获得 10 积分/次
```
> **注意**:家庭套餐 ≠ C端补差价,是独立购买项(¥686)。非付费会员不能直接购买家庭套餐,需先成为C端会员或直接购买家庭套餐。
---
#### 场景 3:升级为能量师(¥1,314 / ¥1,986)
```
用户点击"开通能量师"
│
├─ 有效期内 + 名额未满 → 种子价 ¥1,314
├─ 其他情况 → 标准价 ¥1,986
├─ 微信支付 → vipType → 'practitioner', vipEndTime → +365天
├─ 推广码自动生成(若首次付费)
│
└─ 解锁能力(在C端基础上增加):
├─ 推广能量师年费赚 ¥500 + ¥100
├─ 客户标签分组(P2)
└─ 能量盘批注(P2,C端也有但用途不同)
```
### C.4 关键决策点
**能量师 vs C端——AI能力完全一致。**
两者在AI解读和问答上没有任何区别(都不限次、完整内容),差异只在于:
| 维度 | C端¥131 | 能量师¥1,314+ |
|------|---------|--------------|
| 分销产品 | 仅 C端年费 | C端年费 + 能量师年费 |
| 佣金模式 | 比例(40%+5%) | 比例 + 固定(¥500+¥100) |
| 种子价资格 | ❌ | ✅(有效期内+名额未满) |
| 客户管理 | ❌ 不需要 | ✅ 批注+标签 |
| 使用场景 | 自己看命理 | 为客户解读 |
这意味着如果能量师**不打算做推广**,¥1,314+相比¥131的额外价值只有批注和标签(P2功能)。这可能影响高客单价转化策略——需要在能量师权益中强化"商业工具"的价值感知。
**普通用户的能量盘创建无限。**
目前仅限制了AI问答3轮/天和AI解读1次/天,但普通用户可创建任意数量的能量盘。每个能量盘可获得一次免费主性格概要,理论上可通过不停创建新能量盘获取多次概要。此场景消耗成本较低(1段文本),暂不设限。
### C.5 数据库字段
```sql
-- users 表相关字段
vipType: NULL 'annual' 'super_annual' 'practitioner'
vipEndTime: NULL 2027-05-29 2027-05-29 2027-05-29
referralCode: NULL 'A3X7K9' 'S5T7M9' 'B2Y4M8'
profile_complete: true/false true/false true/false true/false
-- 关联表
┌─ orders ─────────────────────┐
│ user_id, product_type, │
│ amount, status, invited_by │
└──────────────────────────────┘
┌─ commissions ────────────────┐
│ order_id, level, amount, │
│ status (pending/settled) │
└──────────────────────────────┘
```
### C.6 与 US 映射
| 约束规则 | 所在用户故事 |
|---------|------------|
| AI解读:普通用户仅主性格概要1次/天 | US-3.2 |
| AI问答:普通用户3轮/天全局计数 | US-3.4 |
| 分享图片:普通用户1次/天 | US-2.1 |
| PDF导出:仅付费用户可用,不限次 | US-2.2 |
| 历史记录:普通用户仅7天 | US-5.2 |
| 推广码:仅付费后生成 | US-6.1 |
| 分销面板:仅付费用户可见 | US-6.5 |
| C端佣金:上级须已付费才结算 | US-6.4 |
| 批注:仅已付费用户 | US-7.1 |
| 标签:仅能量师(practitioner)可用 | US-7.2 |
| 学业方向AI解读:普通用户1次/天 | US-9.1 |
| 能量师介入AI会话:仅上级能量师可介入 | US-9.3 |
| 人工方案分佣:平台留存模型 | US-9.6 |
| 关系能量分析:仅超级会员可用 | US-10.5 / US-10.6 |
| 八星号码分析:仅超级会员可用 | US-10.7 |
| 超级会员佣金:30%+5%比例分成 | US-10.4 |
| 升级补差:超级→能量师佣金补差 | US-10.3 |