Browse Source

docs: add DOA family goal design spec

Sisyphus 1 month ago
parent
commit
2300f2981b
1 changed files with 301 additions and 0 deletions
  1. 301 0
      docs/superpowers/specs/2026-09-12-doa-family-goal-design.md

+ 301 - 0
docs/superpowers/specs/2026-09-12-doa-family-goal-design.md

@@ -0,0 +1,301 @@
+# 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` 阶段表
+```sql
+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` 目标表
+```sql
+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表合一)
+```sql
+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 示例
+
+```java
+// 创建阶段请求
+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()` 中按顺序添加(迁移编号接当前最大编号):
+
+```java
+// 迁移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/XML + 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 天 |
+| 5. 前端:doa-week-edit.vue(计划/复盘编辑) | 0.5 天 |
+| 6. 联调 + 小程序真机预览 | 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)。