Feature Spec: 账号登录
Status: Active · Map: 5.x 账号 [P1+] · Phase: P1
规范:../feature-design.md
关联:profile-bootstrap.md
1. 功能定义
| 字段 |
内容 |
| Name |
账号登录(手机号+密码) |
| Purpose |
跨设备持久用户身份;未登录不可生成/查看生日衍生结果 |
| Business Goal |
数据归属清晰;为会员与深度版付费打底 |
| In |
Out |
| 注册 / 登录 / 登出 / me |
微信 OAuth、短信 OTP(后续) |
| 设备身份绑定到已注册账号 |
游客可看完整报告 |
| Bearer Session |
运营 Admin 登录(独立) |
2. 用户价值
- 换手机后仍能看到自己的档案与报告。
- 登录后输入生日一次生成、各页直读。
- N/A(登录本身免费)。
3. 用户角色
| Actor |
能力 |
| Visitor |
仅设备身份;可打开登录页;不可建档出结果 |
| User(已注册) |
CRUD 本人档案与 TA;读已生成报告 |
| VIP / DeepAccess |
同前,权益不变 |
4. 用户流程
5. 页面设计
| 路由 |
页面 |
/login |
LoginPage(注册/登录切换) |
/mine |
展示账号手机号尾号 + 退出 |
6. 页面状态规范
| 状态 |
UI |
| Loading |
登录中 |
| Error |
密码错误 / 手机号已注册 |
| Normal |
跳转 redirect 或 /mine |
7. Business Rules
| ID |
Rule |
| R1 |
临时开放: 任意非空手机号 + 任意密码均可登录;未注册则自动建号写入 DB |
| R2 |
登录/注册统一走 OpenLogin;不校验历史密码,仍会更新 password_hash 记录本次输入 |
| R3 |
登录成功后:签发 session;device_identities.user_id 改绑到账号 |
| R4 |
生成/查看档案与报告 API 必须已注册(users.phone 非空)且有效 session 或已绑设备账号 |
| R5 |
登出作废 session;设备可再登录其他账号 |
| R6 |
正式环境恢复校验前须改回本 Spec |
| R7 |
新账号未填昵称时,服务端用「意象词+场景词」词库(100×100)随机生成,如心语岛、微光谷 |
| R8 |
账号昵称可在个人档案页修改(PATCH /auth/me);首页与各页「自己」展示位统一用昵称(合盘/问答/星座/档案卡) |
| R9 |
账号头像可在「我的」页更换:相册或拍照上传;服务端持久化;GET /auth/me 返回 avatar_url;未设置时 UI 用愈心小人正面默认头像(public/default-avatar.png,源图 public/logo/愈心小人1.png) |
8. 数据模型影响
users.phone UNIQUE · users.password_hash · users.nickname · users.avatar_url
user_sessions(token, user_id, expires_at)
- 本地文件:
data/avatars/{user_id}.{jpg|png|webp}(进程相对路径)
9. API 需求
| Method |
Path |
说明 |
| POST |
/api/v1/auth/register |
注册(可带 nickname) |
| POST |
/api/v1/auth/login |
登录 |
| POST |
/api/v1/auth/logout |
登出 |
| GET |
/api/v1/auth/me |
当前账号(含 avatar_url) |
| PATCH |
/api/v1/auth/me |
更新昵称 { nickname } |
| POST |
/api/v1/auth/me/avatar |
multipart file;jpeg/png/webp;≤2MB → 更新 avatar_url |
| GET |
/api/v1/media/avatars/:file |
公开读头像文件 |
10. 权限设计
| 能力 |
Visitor |
User |
| register/login |
✓ |
✓ |
| profiles / reports 写读 |
✗ |
✓ |
| 上传头像 |
✗ |
✓ |
| 读头像媒体 |
✓ |
✓ |
11. 埋点
经统一 track()(见 analytics.md · ops-analytics.md)。
非 P1 核心漏斗 5 事件;接入后走自有 POST /analytics/events(及可选 GA)。
禁止参数含手机号、明文密码、头像绝对 URL / user_id。
| Event |
触发 |
可选 params |
auth_register |
账号新建成功(含 OpenLogin 自动建号,is_new=true) |
source: login_page |
auth_login |
已有账号登录成功(is_new=false) |
source: login_page |
auth_logout |
用户在「我的」点退出且本地 session 已清 |
surface: mine |
avatar_sheet_opened |
「我的」打开更换头像 sheet |
surface: mine |
avatar_upload_succeeded |
头像上传 API 成功且 UI 刷新为新图 |
source: album | camera |
avatar_upload_failed |
头像上传失败(校验/网络/服务端) |
source: album | camera · reason: too_large | bad_type | network | server | unknown |
nickname_updated |
PATCH 昵称成功 |
surface: profile |
page_view 对 /login · /mine 由路由自动采集,本 Spec 不重复定义。
实现状态: 事件名以本表为准;H5 已挂 Login / Mine / Profile(track → 自有 ingest + 可选 GA)。
12. 测试验收标准
| Given |
When |
Then |
| 新设备 |
未登录 POST portrait |
401 |
| 注册成功 |
建档 |
200 且生成报告包 |
| 登录另一设备 |
list profiles |
见同一账号数据 |
| 已登录设备 |
POST logout 后无 Bearer 再 GET /auth/me |
401(设备已解绑,刷新不再显示登录态) |
13. AI 开发前检查