|
|
@@ -0,0 +1,208 @@
|
|
|
+# 规格文档:注册零填写 + 信息按需补充
|
|
|
+
|
|
|
+**日期:** 2026-09-28
|
|
|
+**状态:** 设计稿
|
|
|
+**前置文档:**
|
|
|
+- `2026-08-04-registration-profile-backfill-design.md`(注册引导 + 按需补充回写,本设计继承其回写机制)
|
|
|
+- `2026-08-04-registration-profile-backfill.md`(对应实施计划)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 1. 概述
|
|
|
+
|
|
|
+**核心诉求:取消用户注册时的信息填写步骤,注册成功直接进首页;所有个人信息在功能实际需要时补充。**
|
|
|
+
|
|
|
+用户原话:「取消用户注册时填写信息一项,所有信息都在需要时补充,各个功能要列出要使用的信息。」
|
|
|
+
|
|
|
+三个目标:
|
|
|
+
|
|
|
+1. **注册零填写**:可登录用户手机号登录即注册,登录成功直接进首页,不跳任何信息填写页
|
|
|
+2. **功能→信息映射**:每个功能列出其使用的用户信息字段,缺失时在功能内就地补充并自动回写
|
|
|
+3. **接受邀请必填**:接受家庭邀请时,真实姓名 + 家庭身份必填(仅此场景强制)
|
|
|
+
|
|
|
+## 2. 角色模型(统一口径)
|
|
|
+
|
|
|
+系统角色分三大类(不区分"家长/孩子"语义,新功能禁止引入孩子概念):
|
|
|
+
|
|
|
+| 角色类别 | 说明 | 注册/创建方式 |
|
|
|
+|---------|------|--------------|
|
|
|
+| **可登录用户** | 手机号+微信注册,可登录小程序 | 注册零填写,登录即注册,直接进首页 |
|
|
|
+| **服务用户** | 成长规划师等,需资质审核 | 独立注册流程 `pages/guide/register`(证书/照片/身份证,本方案不改动) |
|
|
|
+| **不可登录用户** | 无登录账号,由家庭管理员创建 | 家庭成员管理页添加(`pages/family/add-member`),填昵称/辈分/性别/生日等 |
|
|
|
+
|
|
|
+**数据归属**:可登录用户信息存 `users` 表;不可登录用户信息存 `family_members` 表;同一家庭的可登录用户可代管不可登录用户数据。
|
|
|
+
|
|
|
+## 3. 现状分析
|
|
|
+
|
|
|
+| 项目 | 现状 | 问题 |
|
|
|
+|------|------|------|
|
|
|
+| 注册流程 | 登录成功 → `needsRoleSelect=true`(新用户)→ 跳 `user-edit?autoParent=true` 全字段表单 | **强制填写,与"注册零填写"诉求冲突** |
|
|
|
+| 默认昵称 | 后端注册时已设默认(`用户+手机尾号` / `微信用户`),不依赖前端 | ✅ 可复用 |
|
|
|
+| 接受邀请 | `join.vue` → 已登录用户跳 `user-edit?autoParent=true`(全字段 + 家庭身份下拉) | 全字段表单过重,且家庭身份非必填 |
|
|
|
+| 添加成员 | `add-member.vue` 填手机号时提示「若手机号已注册,将自动关联该账号」 | 需求改为「提示是否邀请加入」 |
|
|
|
+| 按需回写 | `profile-field-usage.js` + `profile-backfill.js` + 后端 backfill 接口已就绪;仅活动报名接入 | 映射表不完整,各功能未接入 |
|
|
|
+
|
|
|
+## 4. 设计决策记录
|
|
|
+
|
|
|
+| # | 决策 | 结论 |
|
|
|
+|---|------|------|
|
|
|
+| 1 | 注册后是否填写 | **完全零填写,登录成功直接进首页**(头像/昵称均不填,昵称用后端默认) |
|
|
|
+| 2 | 角色注册 | 可登录用户默认直接进首页;服务用户保留独立注册流程;不可登录用户由家庭管理员添加 |
|
|
|
+| 3 | 接受家庭邀请 | **新增独立页面**(内容与 user-edit 相同),真实姓名 + 家庭身份必填,其余选填 |
|
|
|
+| 4 | 功能→信息映射 | 更新 `profile-field-usage.js` 建立完整映射(本次仅出文档,各功能后续逐个接入) |
|
|
|
+| 5 | 添加成员手机号冲突 | 手机号已被注册 → 提示「是否邀请该用户加入家庭」 |
|
|
|
+| 6 | `needsRoleSelect` | 后端字段保留,前端不再消费(登录不再跳转) |
|
|
|
+| 7 | `user-edit.vue` | 保留「个人中心编辑资料」用途,`autoParent=true` 新用户流程停用 |
|
|
|
+
|
|
|
+## 5. 详细设计
|
|
|
+
|
|
|
+### 5.1 注册零填写(可登录用户)
|
|
|
+
|
|
|
+**文件:** `pages/login/login.vue`
|
|
|
+
|
|
|
+`completeLogin()`(L177-178)改造:
|
|
|
+
|
|
|
+```
|
|
|
+当前:
|
|
|
+ if (data.needsRoleSelect || hasPendingFamilyInvite) {
|
|
|
+ uni.redirectTo('/pages/user-edit/user-edit?...&autoParent=true')
|
|
|
+ } else {
|
|
|
+ self.handlePostLoginRouting()
|
|
|
+ }
|
|
|
+
|
|
|
+改为:
|
|
|
+ // 注册零填写:needsRoleSelect 不再触发跳转
|
|
|
+ // 家庭邀请衔接:有 pendingFamilyInviteCode → 直接进 join-form 填真实姓名+家庭身份
|
|
|
+ var pendingInvite = uni.getStorageSync('pendingFamilyInviteCode')
|
|
|
+ if (pendingInvite) {
|
|
|
+ uni.redirectTo({ url: '/pages/invite/join-form?familyInviteCode=' + encodeURIComponent(pendingInvite) })
|
|
|
+ } else {
|
|
|
+ self.handlePostLoginRouting()
|
|
|
+ }
|
|
|
+```
|
|
|
+
|
|
|
+- 新用户(`needsRoleSelect=true`)**不再跳 user-edit**,登录成功直接进首页(后端默认昵称兜底)
|
|
|
+- 未登录用户点家庭邀请链接 → join.vue 引导登录 → 登录成功 → 直接进 **join-form**(衔接闭环)
|
|
|
+- 后端 `needsRoleSelect` 字段保留在 `LoginResultDTO`,前端不再消费
|
|
|
+
|
|
|
+**文件:** `pages/user-edit/user-edit.vue`
|
|
|
+
|
|
|
+- `isNewUserFlow`(`autoParent=true` 分支)停用:`onLoad` 不再处理 `autoParent=true` / `needsRoleSelect=true` 参数,统一走普通编辑模式
|
|
|
+- `confirmRole` / `selectRole` / 角色选择区:仅保留非新用户进入时的行为(实际个人中心编辑不涉及角色选择,相关区块可清理或保留不显示)
|
|
|
+- 家庭邀请相关(`hasPendingFamilyInvite` / `familyRole` 区块 / `requestJoinByCode`)逻辑迁移至新页面 5.2
|
|
|
+- 保留:头像/昵称/真实姓名/性别/生日/出生时辰/民族/血型/学历/婚姻/地区/兴趣/饮食偏好 全字段编辑(个人中心入口)
|
|
|
+
|
|
|
+### 5.2 接受家庭邀请简化表单(新页面)
|
|
|
+
|
|
|
+**新增文件:** `pages/invite/join-form.vue`(注册到 `pages.json` 的 `pages/invite` 分包)
|
|
|
+
|
|
|
+**页面内容:** 字段与 `user-edit.vue` 编辑模式相同,但仅强制两项:
|
|
|
+
|
|
|
+| 字段 | 必填 | 说明 |
|
|
|
+|------|:----:|------|
|
|
|
+| **真实姓名** | ✅ | 家庭管理员据此识别申请人 |
|
|
|
+| **家庭身份** | ✅ | 爸爸/妈妈/爷爷/奶奶/姥爷/姥姥/其他(复用 `familyRoleOptions`) |
|
|
|
+| 昵称 | 选填 | 为空时前端用默认(`用户+手机尾号`),不强制触发后端重算 |
|
|
|
+| 头像/性别/生日/其他 | 选填 | 可顺手填,不填不影响加入申请 |
|
|
|
+
|
|
|
+**交互流程:**
|
|
|
+
|
|
|
+```
|
|
|
+join.vue(已登录、不在目标家庭)
|
|
|
+ → goJoinForm() 跳 /pages/invite/join-form?familyInviteCode=xxx
|
|
|
+ → 填写真实姓名 + 家庭身份(其余选填)
|
|
|
+ → 保存:updateUserInfo(realName, nickname, avatar, ...)(可选字段透传)
|
|
|
+ + requestJoinByCode(inviteCode, familyRole) 提交加入申请
|
|
|
+ → 成功 toast「加入家庭申请已提交,等待管理员审批」→ goHome
|
|
|
+
|
|
|
+join.vue(未登录)
|
|
|
+ → goLogin → 登录成功后 login.vue completeLogin 检测到 pendingFamilyInviteCode
|
|
|
+ → 跳 join-form(衔接闭环)
|
|
|
+```
|
|
|
+
|
|
|
+**`join.vue` 改造(L261-284):**
|
|
|
+
|
|
|
+- `goUserEdit()` 改为 `goJoinForm()`:跳 `/pages/invite/join-form?familyInviteCode=...&token=...&userId=...`
|
|
|
+- `goNext()` 未登录分支(L274-278)保持不变:调 `goLogin()`;登录后由 login.vue 完成衔接(见上面流程)
|
|
|
+- 复制 `user-edit.vue` 的 `requestJoinByCode` 调用逻辑到新页面(`user-edit.vue` 中 L754-768 相关逻辑迁移)
|
|
|
+
|
|
|
+**`user-edit.vue` 家庭邀请逻辑清理:**
|
|
|
+- `hasPendingFamilyInvite` 计算属性移除(已无引用)
|
|
|
+- `familyRole` form 字段、L48-57 家庭身份区块移除
|
|
|
+- L754-768 保存时提交加入申请逻辑移除(迁移至 join-form)
|
|
|
+
|
|
|
+### 5.3 功能→信息字段映射表(文档 + 配置更新)
|
|
|
+
|
|
|
+**新增/更新:** `cfc-frontend/utils/profile-field-usage.js`
|
|
|
+
|
|
|
+完整映射(基于全前端探查):
|
|
|
+
|
|
|
+| 字段 | 功能场景 | 页面 | 字段去向 | 现状 |
|
|
|
+|------|---------|------|---------|------|
|
|
|
+| **realName 真实姓名** | 活动报名 | activity-detail | user/member | 手动填,未回写 |
|
|
|
+| | 接受家庭邀请 | invite/join-form | user | **本次新增必填** |
|
|
|
+| | 创建联系人 | ContactImport | 独立实体 | 自填 |
|
|
|
+| **phone 手机号** | 活动报名 | activity-detail | user/member | ✅ 已回写 |
|
|
|
+| | 添加成员关联账号 | add-member | member | 本次改「邀请加入」提示 |
|
|
|
+| **birthday 生日** | 家庭天盘 | tianpan/* | user/member | 后端计算生肖/五行/生命数字,前端缺失无引导 |
|
|
|
+| | 测评年龄计算 | assessment/* | member | 后端计算,前端缺失无引导 |
|
|
|
+| | 健康报告匹配 | health/report-* | member | 报告页自填(newMember) |
|
|
|
+| | 饮食推荐 | nutrition-profile | member | 后端计算 |
|
|
|
+| **birthHour 出生时辰** | 家庭天盘 | tianpan/* | user/member | 后端计算 |
|
|
|
+| **gender 性别** | 家庭天盘 | tianpan/* | user/member | 后端计算 |
|
|
|
+| | 测评维度计算 | assessment/* | member | 后端计算 |
|
|
|
+| | 健康报告匹配 | health/report-* | member | 报告页自填 |
|
|
|
+| **dietPreferences 饮食偏好** | 饮食推荐 | nutrition-profile | user/member | 后端计算 |
|
|
|
+| **address 地区** | 收货地址(独立地址簿) | shop/* | 独立实体 | 不走个人信息 |
|
|
|
+| | 活动地点 | activity-detail | user | 低优先级 |
|
|
|
+| **avatar/nickname** | 全局展示(家庭成员列表/评论/推荐人) | 各页 | user/member | 后端默认昵称兜底 |
|
|
|
+
|
|
|
+**约定:** 功能页接入时在 `scenes` 中登记本场景;回写前校验字段属于本场景(`profile-backfill.js` 已实现该机制);回写白名单沿用后端 6 字段(phone/gender/birthday/birthHour/dietPreferences/address)+ realName(本次新增,后端白名单同步加)。
|
|
|
+
|
|
|
+**后端回写白名单扩展:** `UserService.backfillProfile()` 的 `USER_BACKFILL_WHITELIST` 增加 `"realName"`(`MEMBER_BACKFILL_WHITELIST` 同步确认 family_members 是否有 realName 列;无则维持 phone/gender/birthday/birthHour)。
|
|
|
+
|
|
|
+> 各功能页「缺失即就地补充 + 回写」的接入不在本次范围,按映射表后续逐个排期实施(P2+)。
|
|
|
+
|
|
|
+### 5.4 添加成员手机号冲突 → 邀请加入
|
|
|
+
|
|
|
+**文件:** `pages/family/add-member.vue`
|
|
|
+
|
|
|
+- L78-80 提示文案:「填写手机号可关联已有账号 / 若手机号已注册,将自动关联该账号」→ 改为「填写手机号可在已注册时邀请加入」
|
|
|
+- 提交时(`doSubmit`)若填了手机号:调后端查询该手机号是否已被注册(新增或复用接口,如 `POST /api/user/check-phone-exists`)
|
|
|
+ - 已注册 → 弹确认「该手机号已被注册,是否邀请该用户加入家庭?」→ 确认 → 跳转邀请流程(携带手机号/邀请码);取消 → 继续以不可登录用户身份添加(不关联账号)
|
|
|
+ - 未注册 → 正常添加
|
|
|
+- 后端新增接口需确认是否已有类似能力(`FamilyMemberService` / `UserService` 查询 phone)
|
|
|
+
|
|
|
+## 6. 实施范围
|
|
|
+
|
|
|
+| 阶段 | 内容 | 说明 |
|
|
|
+|------|------|------|
|
|
|
+| **P0(本次)** | 注册零填写(login.vue)+ user-edit 新用户流程停用 + join-form 新页面 + join.vue 衔接 + 映射表更新 + add-member 手机号冲突提示 | 可单独上线 |
|
|
|
+| **P2+(后续逐个接入)** | 天盘/测评/健康报告/饮食推荐等页面的「缺失就地补充 + 回写」接入 | 按映射表排期 |
|
|
|
+
|
|
|
+## 7. 验收标准
|
|
|
+
|
|
|
+- [ ] 新用户手机号登录 → 登录成功 → **直接进首页**,不出现任何信息填写页
|
|
|
+- [ ] `user-edit` 不再接受 `autoParent=true` 新用户流程参数(个人中心编辑资料正常)
|
|
|
+- [ ] 接受家庭邀请(join.vue 已登录场景)→ 跳 `join-form`:真实姓名 + 家庭身份必填,其余选填;提交后调 `requestJoinByCode` 等待管理员审批
|
|
|
+- [ ] `profile-field-usage.js` 映射表完整(真实姓名/手机号/生日/出生时辰/性别/饮食偏好/地区 + 各自场景)
|
|
|
+- [ ] 后端 backfill 白名单增加 `realName`(若 member 表无 realName 列则确认边界)
|
|
|
+- [ ] add-member 填已注册手机号 → 提示「邀请加入」,确认后走邀请流程
|
|
|
+- [ ] `mvn clean compile` 通过;前端语法/结构校验通过
|
|
|
+- [ ] 不破坏:服务用户注册流程、个人中心编辑、现有活动报名回写
|
|
|
+
|
|
|
+## 8. 实现决策(已完成评估)
|
|
|
+
|
|
|
+| # | 项 | 决策 |
|
|
|
+|---|----|------|
|
|
|
+| 1 | 手机号已注册查询接口 | 复用现有 `POST /api/auth/check-phone`(前端已封装 `checkPhone(phone)` in api.js L344) |
|
|
|
+| 2 | member 表 realName 列 | `family_members` 无 real_name 列(仅 nickname/phone/gender/birthday/birthHour 等);**realName 只加进 USER 回写白名单**(member 白名单维持 phone/gender/birthday/birthHour 4 字段) |
|
|
|
+| 3 | join-form 与 user-edit 字段共用 | 本期直接新建,不抽公共组件;二期优化时考虑复用 |
|
|
|
+
|
|
|
+## 9. 文档索引更新
|
|
|
+
|
|
|
+本设计同步更新 `docs/superpowers/PROJECT-OVERVIEW.md` v2.13(2026-09-28)。
|
|
|
+
|
|
|
+## 10. 待实施
|
|
|
+
|
|
|
+详见 `docs/superpowers/plans/2026-09-28-registration-zero-fill.md`(编写中)。
|