2026-09-12-doa-family-goal-design.md 12 KB

DOA 家庭打卡:个人目标-周计划-周复盘 设计文档

版本: v1.0 日期: 2026-09-12 状态: 待审查


1. 背景与目标

1.1 现状

  • 现有「共同挑战」:家庭级、打卡制、结果导向。表结构 family_challenge + family_challenge_progress + family_challenge_participant。
  • 缺乏个人级、过程导向、结构化复盘的机制。

1.2 目标

引入 DOA(目标-计划-复盘) 体系:

  • D/O:每阶段每人定 1-3 个量化目标(挂 5 固定领域),每周制定行动计划
  • A:每周末按 ABC 记录表四问复盘(达成 / 体验 / 行得通与要提升 / 下周挑战)
  • 并列模块:与共同挑战互不干扰,入口在同一页面不同 tab

1.3 核心约束(已确认)

决策点 结论
与共同挑战关系 并列新模块
目标领域 固定 5 个:健康(身)、事业(富)、家庭关系(行)、社会关系(行)、帮助他人(行+富)
阶段周期 自选(2/4/8/12 周),创建时指定
用户模型 统一「能登录用户」,无「孩子」概念;不能登录成员由能登录用户代管
家庭可见性 同家庭成员互相可见,仅能编辑自己(或代管)的

2. 数据模型

2.1 新增 4 张表

doa_stage 阶段表

CREATE TABLE doa_stage (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    family_id BIGINT NOT NULL COMMENT '家庭ID',
    member_id BIGINT NOT NULL COMMENT '目标归属成员',
    title VARCHAR(200) COMMENT '阶段主题(可选,如暑期习惯养成)',
    start_date DATE NOT NULL COMMENT '阶段开始',
    end_date DATE NOT NULL COMMENT '阶段结束',
    duration_weeks TINYINT NOT NULL COMMENT '周期周数:2/4/8/12',
    status ENUM('active','completed','cancelled') DEFAULT 'active',
    created_by BIGINT NOT NULL COMMENT '创建人 userId(代管时为代管人)',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_family_member (family_id, member_id),
    INDEX idx_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DOA 阶段';

doa_goal 目标表

CREATE TABLE doa_goal (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    stage_id BIGINT NOT NULL COMMENT '所属阶段',
    domain ENUM('health','wealth','family','social','help') NOT NULL COMMENT '领域',
    content VARCHAR(500) NOT NULL COMMENT '量化目标,如:体重降到 172 以下',
    status ENUM('active','achieved','abandoned') DEFAULT 'active',
    sort_order TINYINT DEFAULT 0 COMMENT '同阶段内排序',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_stage (stage_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DOA 阶段目标';

doa_week 周记录表(A表+B表合一)

CREATE TABLE doa_week (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    stage_id BIGINT NOT NULL COMMENT '所属阶段',
    week_no TINYINT NOT NULL COMMENT '第几周(1起)',
    week_start DATE NOT NULL COMMENT '本周开始(周一)',
    week_end DATE NOT NULL COMMENT '本周结束(周日)',
    -- A表:周行动宣告计划
    plan TEXT COMMENT '本周行动清单,每行一个行动',
    -- B表:周复盘五问
    achieved TEXT COMMENT '本周达成了什么',
    experience TEXT COMMENT '有什么体验',
    worked TEXT COMMENT '行得通的',
    improve TEXT COMMENT '要提升/行不通的',
    next_challenge TEXT COMMENT '下周挑战自己什么',
    status ENUM('pending','planned','reviewed') DEFAULT 'pending',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    UNIQUE KEY uk_stage_week (stage_id, week_no),
    INDEX idx_stage (stage_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DOA 周记录';

C表(累计成就)不落库

  • 由 doa_week 聚合计算:完成周数占比、各目标达成度

2.2 领域映射(前端展示用)

domain 值 中文名 五维 图标/颜色建议
health 健康 身 🏃 #FF8C42
wealth 事业 富 💼 #F59E0B
family 家庭关系 行 👨‍👩‍👧 #10B981
social 社会关系 行 🤝 #6366F1
help 帮助他人 行+富 🤲 #FF6B9D

3. 权限模型

3.1 概念澄清

「孩子」= 不能登录用户(family_member.userId 为空 / 关联 User 无 openid) 「成年人」= 能登录用户(有 openid,可自主操作)

3.2 权限矩阵

操作 能登录用户(自己) 能登录用户(代管不可登录成员) 不能登录成员
创建阶段 ✅ 为自己 ✅ 为代管成员 ❌
编辑计划/复盘 ✅ ✅ ❌
查看所有家庭成员 DOA ✅ ✅ ❌(无登录态)

3.3 校验规则

  • 所有 memberId 必须属于当前用户家庭(family_id 一致)
  • 代管时:目标 member_id ≠ 当前用户 currentMemberId,但需同家庭 + 目标成员 memberType=local

4. 后端 API 设计

Controller: DoaController
Base Path: /api/doa(全部 @PostMapping)

接口 路径 请求体 响应
创建阶段 /stage/create {memberId?, title, durationWeeks, goals:[{domain,content}]} {stageId}
阶段详情 /stage/detail {stageId} DoaStageVO{stage, goals, weeks[]}
家庭总览 /overview {} List<DoaMemberVO>{memberId,nickname,currentStage?,goals[],weekProgress}
取消阶段 /stage/cancel {stageId} Void
提交周计划 /week/plan {weekId, plan} Void
提交周复盘 /week/review {weekId, achieved, experience, worked, improve, nextChallenge} Void
周记录列表 /week/list {stageId} List<DoaWeekVO>

4.1 DTO 示例

// 创建阶段请求
public class CreateStageRequest {
    private Long memberId;          // 可选:代管时传目标成员;不传默认当前成员
    private String title;           // 可选
    private Integer durationWeeks;  // 必填:2/4/8/12
    private List<GoalDTO> goals;    // 1-3 条,每条:domain + content
}

// 目标 DTO
public class GoalDTO {
    private String domain;  // health/wealth/family/social/help
    private String content; // 量化目标文本
}

// 周计划/复盘请求
public class WeekPlanRequest { private String plan; }
public class WeekReviewRequest {
    private String achieved;
    private String experience;
    private String worked;
    private String improve;
    private String nextChallenge;
}

4.2 Service 关键逻辑

创建阶段:

  1. 校验 memberId(或默认当前成员)属于当前家庭
  2. 校验 durationWeeks ∈ {2,4,8,12}
  3. 校验 goals 数量 1-3,domain 去重
  4. 计算 end_date = start_date + durationWeeks * 7 - 1(周一起算)
  5. 写 doa_stage
  6. 批量写 doa_goal
  7. 预生成 N 条 doa_week(week_no=1..N,week_start/week_end 自动计算,status=pending)

周计划/复盘:

  • 仅当 week.status = pending|planned 时可写
  • 计划写入 → status=planned;复盘写入 → status=reviewed

5. 前端页面设计

5.1 页面结构(pages/health/ 分包)

页面 路径 说明
DOA 总览 doa-index.vue 家庭各成员阶段卡片,点击进详情
创建/编辑阶段 doa-stage-create.vue 弹窗或页面,选成员/周期/目标
阶段详情 doa-stage-detail.vue 目标列表 + 周时间线(卡片流)
周编辑 doa-week-edit.vue 计划/复盘切换编辑

5.2 入口集成

  • pages/health/challenge-manage.vue 顶部新增 tab:
    • 共同挑战(现有)
    • 个人目标(新)→ 跳转 doa-index.vue

5.3 关键组件复用

现有组件 复用方式
FamilyChallengeCard.vue 不复用,DOA 卡片结构不同(领域标签+周进度条)
getFamilyMemberList 复用,获取家庭成员列表(含 memberType)
日期格式化工具 复用 utils/format.js 的 parseDate + formatDate

5.4 交互细节

  • 周计划输入:v1 使用 textarea 多行文本,每行一个行动(参考 ABC A 表「明确人事时地」)
  • 周复盘:五个 textarea 对应 ABC B 表五问
  • 日期显示:统一 yyyy-MM-dd(仅日期)或 yyyy-MM-dd HH:mm:ss

6. 简化决策(v1 范围)

项 决策 理由
自动积分奖励 ❌ 不做 与现有 PointsService/ChallengeScoreService 耦合复杂,YAGNI;v1 仅记录展示
周计划结构化输入 ❌ 自由文本 ABC A 表也是逐行记录「日期+行动」;v1 不做按天/按时段结构化
不能登录成员的阶段创建 ✅ 代管人创建 遵循现有 memberType=local 的代管模式
阶段内修改目标 ✅ 允许 active 状态下可增删目标(去重 domain)
周期跨月/跨年 ✅ 支持 数据库存 DATE,前端按周渲染即可

7. 数据库迁移

在 DatabaseInitializer.runMigrations() 中按顺序添加(迁移编号接当前最大编号):

// 迁移X: 创建 doa_stage 表
try {
    jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS doa_stage (" +
        "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
        "family_id BIGINT NOT NULL, " +
        "member_id BIGINT NOT NULL, " +
        "title VARCHAR(200), " +
        "start_date DATE NOT NULL, " +
        "end_date DATE NOT NULL, " +
        "duration_weeks TINYINT NOT NULL, " +
        "status VARCHAR(20) DEFAULT 'active', " +
        "created_by BIGINT NOT NULL, " +
        "created_at DATETIME DEFAULT CURRENT_TIMESTAMP, " +
        "updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
        "INDEX idx_family_member (family_id, member_id), " +
        "INDEX idx_status (status) " +
        ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='DOA 阶段'");
    log.info("已创建 doa_stage 表");
} catch (Exception e) {}

// 迁移X+1: 创建 doa_goal 表
// 迁移X+2: 创建 doa_week 表
// ... 同理

同步更新 schema.sql:在文件末尾追加三表 CREATE TABLE IF NOT EXISTS 完整定义。


8. 开发任务拆解(供后续 writing-plans 使用)

任务 预估
1. 后端:Entity/Mapper + DoaService + DoaController 1.5 天
2. 后端:DatabaseInitializer 迁移 + schema.sql 同步 + 编译验证 0.5 天
3. 前端:api.js 新增 doa 系列接口封装 0.5 天
4. 前端:doa-index.vue(总览 + tab 入口) 1 天
5. 前端:doa-stage-create.vue(创建弹窗/页) 0.5 天
6. 前端:doa-stage-detail.vue(详情 + 周时间线) 1 天
7. 前端:doa-week-edit.vue(计划/复盘编辑) 0.5 天
8. 联调 + 小程序真机预览 1 天
合计 ~6.5 天

9. 验收标准

  1. 创建阶段:家庭成员 A 能为自己创建 4 周、3 个不同领域目标的阶段
  2. 代管:家庭成员 A 能为同家庭不能登录成员 B 创建阶段
  3. 周计划:成员 A 在周一能写本周计划,周五能看到已写
  4. 周复盘:成员 A 在周日能填五问复盘,提交后不可再改
  5. 总览:doa-index.vue 显示全家当前阶段、目标领域、本周进度
  6. 权限:成员 A 看不到成员 C 的编辑按钮,只能看
  7. 编译:mvn clean compile 通过,小程序 HBuilderX 打包无报错

10. 待确认项(需用户审查)

  1. 阶段周期选择 UI:v1 用下拉选择 2/4/8/12 周,是否需要自定义输入?
  2. 目标内容校验:是否强制要求量化(如必须含数字/单位)?v1 仅非空校验
  3. 周复盘必填字段:五问是否全必填?v1 全部可选(允许只填部分)
  4. 阶段结束后自动结算:v1 无自动结算逻辑,仅状态标记;是否需要阶段结束自动 completed?

请审查以上设计文档。如需修改请告诉我,确认无误后我将 commit 并进入下一步(writing-plans)。