输入关键词开始搜索

家庭管理(上)

301. 家庭创建/加入:Repository + Service + Step 2 UI

日期: 2026-05-20 关联开发任务: 阶段 3 任务 3.1 创建/加入家庭 关联设计文档: 004.数据库设计文档 §4.2-4.3、003.详细设计文档 §2 界面二


一、问题/需求

注册流程的 Step 2 是家庭关系绑定——用户必须创建新家庭或通过 6 位邀请码加入已有家庭才能完成注册。需要从数据层到 UI 层完整实现这个流程。


二、思路

  1. 数据层先行:Family + FamilyMember 两个 Repository,遵循 UserRepository 模板
  2. Service 编排:FamilyService 负责 createFamily(生成邀请码 + 设户主)和 joinFamily(验证邀请码)
  3. Step 2 UI:独立 FamilySetupPage,创建/加入两个按钮,加入用底部 Drawer 抽屉
  4. 注册流程串联:RegisterWindow 用 StackView 管理 Step1→Step2,Step1 先调用 AuthService.registerUser() 拿到 userId,再传给 Step2

三、逻辑推导

3.1 注册顺序

Step 1 (RegisterPage)
  ├── 填表 → 校验 → AuthService.registerUser()
  ├── 拿到 userId → push Step 2
  └── ❌ 不能在 Step 2 后才注册——因为 FamilyService 需要 userId
Step 2 (FamilySetupPage)
  ├── 创建家庭 → FamilyService.createFamily(userId)
  └── 加入家庭 → FamilyService.joinFamily(userId, inviteCode)

3.2 邀请码策略

  • 6 位字母数字(排除 I/O/0/1 易混淆字符)
  • QRandomGenerator::global() 生成
  • 不设过期(invite_code_expires_at = NULL
  • 唯一性由 family_repository.getByInviteCode() 调用方自行保证重试(当前概率足够低,暂不做)

四、实施方案

文件清单

src/data/family_entity.h                 ← Family + FamilyMember 实体
src/data/family_repository.h/.cpp        ← Family CRUD + getByInviteCode
src/data/family_member_repository.h/.cpp ← 成员 add/remove/query
src/core/family_service.h/.cpp           ← createFamily / joinFamily
src/ui/qml/FamilySetupPage.qml           ← Step 2 UI
src/ui/qml/RegisterWindow.qml            ← StackView 串联两步骤

依赖注入链

main.cpp
  ├── FamilyRepository(&app)
  ├── FamilyMemberRepository(&app)
  └── FamilyService(familyRepo, memberRepo, &app)
      └── setContextProperty("familyService")

五、踩坑

现象根因修复
FamilySetupPage 中 session.userId 为空注册未完成前 session 未设置改用 RegisterWindow.registeredUserId 属性传递
两个步骤 UI 大小不一致RegisterWindow 固定 420×680,Page 内部用 anchors 自适应统一窗口尺寸
Drawer 挡住主按钮Drawer 高度 260,edge: Qt.BottomEdge正常

六、验证

验证项结果
注册→创建家庭→数据库写入 families + family_members
邀请码 6 位大写字母数字
户主 role=owner
邀请码无效 → “邀请码无效,请核对后重试”
重复加入 → “你已经是该家庭的成员”