|
@@ -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)。
|