版本: v1.0 日期: 2026-09-12 状态: 待审查
family_challenge + family_challenge_progress + family_challenge_participant。引入 DOA(目标-计划-复盘) 体系:
| 决策点 | 结论 |
|---|---|
| 与共同挑战关系 | 并列新模块 |
| 目标领域 | 固定 5 个:健康(身)、事业(富)、家庭关系(行)、社会关系(行)、帮助他人(行+富) |
| 阶段周期 | 自选(2/4/8/12 周),创建时指定 |
| 用户模型 | 统一「能登录用户」,无「孩子」概念;不能登录成员由能登录用户代管 |
| 家庭可见性 | 同家庭成员互相可见,仅能编辑自己(或代管)的 |
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 周记录';
doa_week 聚合计算:完成周数占比、各目标达成度| domain 值 | 中文名 | 五维 | 图标/颜色建议 |
|---|---|---|---|
| health | 健康 | 身 | 🏃 #FF8C42 |
| wealth | 事业 | 富 | 💼 #F59E0B |
| family | 家庭关系 | 行 | 👨👩👧 #10B981 |
| social | 社会关系 | 行 | 🤝 #6366F1 |
| help | 帮助他人 | 行+富 | 🤲 #FF6B9D |
「孩子」= 不能登录用户(
family_member.userId为空 / 关联 User 无 openid) 「成年人」= 能登录用户(有 openid,可自主操作)
| 操作 | 能登录用户(自己) | 能登录用户(代管不可登录成员) | 不能登录成员 |
|---|---|---|---|
| 创建阶段 | ✅ 为自己 | ✅ 为代管成员 | ❌ |
| 编辑计划/复盘 | ✅ | ✅ | ❌ |
| 查看所有家庭成员 DOA | ✅ | ✅ | ❌(无登录态) |
memberId 必须属于当前用户家庭(family_id 一致)member_id ≠ 当前用户 currentMemberId,但需同家庭 + 目标成员 memberType=localController: 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> |
// 创建阶段请求
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;
}
创建阶段:
memberId(或默认当前成员)属于当前家庭durationWeeks ∈ {2,4,8,12}goals 数量 1-3,domain 去重end_date = start_date + durationWeeks * 7 - 1(周一起算)doa_stagedoa_goaldoa_week(week_no=1..N,week_start/week_end 自动计算,status=pending)周计划/复盘:
week.status = pending|planned 时可写status=planned;复盘写入 → status=reviewedpages/health/ 分包)| 页面 | 路径 | 说明 |
|---|---|---|
| DOA 总览 | doa-index.vue |
家庭各成员阶段卡片,点击进详情 |
| 创建/编辑阶段 | doa-stage-create.vue |
弹窗或页面,选成员/周期/目标 |
| 阶段详情 | doa-stage-detail.vue |
目标列表 + 周时间线(卡片流) |
| 周编辑 | doa-week-edit.vue |
计划/复盘切换编辑 |
pages/health/challenge-manage.vue 顶部新增 tab:
共同挑战(现有)个人目标(新)→ 跳转 doa-index.vue| 现有组件 | 复用方式 |
|---|---|
FamilyChallengeCard.vue |
不复用,DOA 卡片结构不同(领域标签+周进度条) |
getFamilyMemberList |
复用,获取家庭成员列表(含 memberType) |
| 日期格式化工具 | 复用 utils/format.js 的 parseDate + formatDate |
textarea 多行文本,每行一个行动(参考 ABC A 表「明确人事时地」)textarea 对应 ABC B 表五问yyyy-MM-dd(仅日期)或 yyyy-MM-dd HH:mm:ss| 项 | 决策 | 理由 |
|---|---|---|
| 自动积分奖励 | ❌ 不做 | 与现有 PointsService/ChallengeScoreService 耦合复杂,YAGNI;v1 仅记录展示 |
| 周计划结构化输入 | ❌ 自由文本 | ABC A 表也是逐行记录「日期+行动」;v1 不做按天/按时段结构化 |
| 不能登录成员的阶段创建 | ✅ 代管人创建 | 遵循现有 memberType=local 的代管模式 |
| 阶段内修改目标 | ✅ 允许 | active 状态下可增删目标(去重 domain) |
| 周期跨月/跨年 | ✅ 支持 | 数据库存 DATE,前端按周渲染即可 |
在 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 完整定义。
| 任务 | 预估 |
|---|---|
| 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 天 |
doa-index.vue 显示全家当前阶段、目标领域、本周进度mvn clean compile 通过,小程序 HBuilderX 打包无报错completed?请审查以上设计文档。如需修改请告诉我,确认无误后我将 commit 并进入下一步(writing-plans)。