Feature Spec: 生日包生成(档案引导)
Status: Active · Map: 1.1 个人档案 · Phase: P1
关联:account-auth.md · profile.md · portrait.md · star-profile.md
1. 功能定义
| 字段 |
内容 |
| Name |
生日衍生数据一次生成与覆盖 |
| Purpose |
输入/修改生日后服务端一次性生成并落库;结果页优先读缓存 |
| Business Goal |
降低重复输入;保证本人与 TA 数据归属同一账号 |
| In |
Out |
| Self / Other 档案创建与生日变更触发 |
无档案凭空出合盘 |
| 单人:portrait · star · rhythm |
意象卡片抽牌(配额玩法,不预生成) |
| 有 Self+Other:relation + synastry 成对覆盖 |
附近的人合盘(进页再算) |
2. 用户价值
- 填一次生日,解码/星座/节律可直接看。
- 添加的 TA 挂在账号下;与本人关系/合盘一并备好。
- 改生日自动覆盖旧结果。
3. 用户角色
仅 已登录 User。Visitor 被鉴权拦截。
4. 用户流程
5. 页面设计
| 路由 |
行为变更 |
/portrait /star /rhythm |
有 Self → 读 latest;无 → 引导 /profile 或登录 |
/relation /synastry |
选已有 Self+TA → 读 latest pair;缺则引导加档案 |
/profile |
创建/改生日后展示「已生成」提示 |
6. 页面状态规范
| 状态 |
UI |
| Loading |
生成中/拉取中 |
| Empty |
无档案 → 去建档;未登录 → 去登录 |
| Normal |
展示缓存报告 |
| Error |
重试 |
7. Business Rules
| ID |
Rule |
| R1 |
仅登录用户可写档案 |
| R2 |
Create/Update 若 birth_date(或 time/place)相对旧值变化 → GenerateBundle |
| R3 |
覆盖=同 user + profile + type(+ peer)软删旧报告再插入 |
| R4 |
Other 档案 user_id 必须=当前账号;删除 Other 时软删其单人报告及含其 peer 的配对报告 |
| R5 |
结果页不得再要求重复输入已知生日,除非用户主动改档案 |
8. 数据模型影响
growth_reports.peer_profile_id nullable(配对报告)
- 索引便于 latest 查询
9. API 需求
| Method |
Path |
说明 |
| POST/PATCH |
/profiles |
成功后服务端同步 GenerateBundle |
| GET |
/reports/latest |
profile_id · type · 可选 peer_profile_id |
现有 POST /reports/* 保留(幂等覆盖),供重算;主路径以 latest 为准。
10. 权限设计
同 account-auth:必须 User。
11. 埋点
profile_bootstrap_done · report_cache_hit
12. 测试验收标准
| Given |
When |
Then |
| 登录用户建 Self |
POST profile |
DB 有 portrait/star/rhythm |
| 再加 Other |
POST other |
有 relation+synastry 相对 Self |
| 改 Self 生日 |
PATCH |
旧报告 soft-deleted,新报告可读 |
| 登录用户开 /portrait |
GET latest |
无需再填生日 |
13. AI 开发前检查