Преглед на файлове

chore: auto bump version and changelog [skip ci]

iwt преди 1 седмица
родител
ревизия
05f76cfb6b

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-2221f249d4f4b28a827089d30551cdd9bf06b491
+5647ee71135105cff7b85f29db828f238e7c4a6b

+ 2 - 2
cfc-web/package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "cfc-web",
-  "version": "1.0.1592",
+  "version": "1.0.1599",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
       "name": "cfc-web",
-      "version": "1.0.1592",
+      "version": "1.0.1599",
       "dependencies": {
         "@wangeditor/editor": "^5.1.23",
         "@wangeditor/editor-for-vue": "^1.0.2",

+ 1 - 1
cfc-web/package.json

@@ -1,6 +1,6 @@
 {
   "name": "cfc-web",
-  "version": "1.0.1592",
+  "version": "1.0.1600",
   "private": true,
   "scripts": {
     "dev": "vue-cli-service serve",

+ 157 - 0
cfc-web/public/CHANGELOG-v1.0.md

@@ -4,6 +4,163 @@
 
 ---
 
+## v1.0.1600 (2026-10-13)
+
+### 文档
+- 更新PROJECT-OVERVIEW.md,添加饮食/睡眠/运动打卡任务链路设计条目
+- 饮食/睡眠/运动打卡接入任务完成链路设计(方案B双轨)
+
+### Bug 修复
+- 修复 ProductEdit.vue 语法错误(validate 回调缺失 ) 与 export default 花括号不闭合)
+
+
+## v1.0.1599 (2026-10-13)
+
+### 新功能
+- P4 干预方案驱动任务生成(协议 v1.1 + 离线生成器)
+
+### 其他
+-   监测 description、weekly time、followups due、exercise_ids/exercise_tasks
+- - schema/protocol.schema.json 同步 v1.1 字段
+- - validate_kb.py 支持 v1.1(exercise_ids/exercise_tasks 交叉校验)
+- - render_kb_md.py 协议视图适配 v1.1
+- - 新增 gen_tasks_from_protocol.py:由 protocols/*.json 生成幂等任务种子 SQL,
+-   替代硬编码 gen_seed.py;已与生产 45 条任务逐字段比对完全一致(幂等)
+- 
+
+
+## v1.0.1598 (2026-10-13)
+
+### Bug 修复
+- 修复商品管理页编辑按钮 pagination 上下文问题
+
+
+## v1.0.1597 (2026-10-13)
+
+### 新功能
+- P3 JSON→MD 视图派生工具链(单一事实源收口)
+- P2 补剂相互作用库 + 干预方案结构化 + 校验器升级
+
+### 其他
+- - --check 模式: 与现有视图比对,不一致退出码 1(阻断提交,强制只改 JSON)
+- - validate_kb.sh: 结构校验 + 视图同步校验统一入口(pre-commit 自动执行)
+- - 生成 docs/参考资料/知识库/views/*.md 初始视图;protocols 视图解析补剂 id 为名称
+- 
+-   Akk×铁剂,色氨酸×SSRI,鱼油×抗凝药,姜黄×抗血小板,益生菌×高温)
+- - protocols/gut_joint_intervention_v1.json: 双人肠道菌群联合干预方案
+-   完整结构化(周期定义、双成员、每阶段 5 时段补剂引用、每日/每周监测、
+-   4/8/12 周复查节点、运动引用);已部署的 45 条任务数据从此文件派生
+- - schema/ 新增 interaction.schema.json + protocol.schema.json
+- - validate_kb.py 升级:支持 interactions.json 校验 + 跨库引用完整性检查
+-   (supplement_ids / exercise_ids / indicator_ids / cycle_id 交叉验证)
+- 
+
+
+## v1.0.1596 (2026-10-13)
+
+### 其他
+- - docs/scripts/validate_kb.sh:CI/本地统一校验入口(退出码供阻断)
+- - docs/scripts/install_git_hooks.sh:core.hooksPath -> .githooks,幂等安装
+- - 已验证:合法变更 exit 0;损坏 JSON 阻断 exit 1
+- 
+
+
+## v1.0.1596 (2026-10-13)
+
+### 新功能
+- P0 新增补充剂库/临床指标参考库/运动处方库 + JSON Schema 校验
+
+### 其他
+- - 临床指标参考库 clinical_indicators.json:15 项(血糖/HbA1c/血红蛋白/铁蛋白/血脂四项/肝肾/尿酸/eGFR,含参考范围与干预阈值)
+- - 运动处方库 exercises.json:4 条(餐后散步/足尖俯卧撑/八段锦/腹部按摩)
+- - schema/ 三个 JSON Schema + docs/scripts/validate_kb.py 校验脚本
+- - 数据来源:《双人肠道菌群联合干预方案》+ 中国糖尿病/血脂/贫血等指南
+- 
+
+
+## v1.0.1595 (2026-10-13)
+
+### 新功能
+- 菌群营养知识库.md 补回六大营养字段
+
+### 其他
+- - 190 个食物行全部填充:82 条取自 JSON 知识库与原库,108 条熟食/主食按
+-   《中国食物成分表》(第6版) 常见参考值补入,并在 section 一 标注待营养顾问终审
+- - 速查表(2列)与其余章节不受影响
+- 
+
+
+## v1.0.1594 (2026-10-13)
+
+### 新功能
+- 合并菌群营养知识库V2 GI食物库到主文件与JSON
+
+### 其他
+- - JSON: 食物营养库按md更新GI类字段(重合132覆盖/新增24),原能量/蛋白/脂肪/碳水/淀粉/膳食纤维/胆固醇营养字段保留,现356种
+- - 备份见 .vbak-*
+- 
+
+
+## v1.0.1593 (2026-10-13)
+
+### 新功能
+- fix task completion points display (0→10CF) and unit format (分→CF) - resolve Unknown column errors and UI display issues
+- 健康自检问卷向导与LITE轻享会员等级:问卷组件与方案页重写、能量沙盘问卷解锁、LangGraph健康上下文注入、成员级偏好读写安全校验、无特殊偏好标记、多页面联动调整
+- 健康方案改为 plan-list 列表页,健康首页/肠道/报告确认页跳转统一指向
+- 微信打卡提醒按用户手机号定向msgLabel;重复任务支持earliest_start阶段起点
+- 实现三级健康约束规则体系(硬拦截/软警告/正常推荐),支持疾病禁忌、过敏命中、药物相互作用、剂量超标、档案缺失提示,并提供健康方案生成能力
+- 新增7列文章列表点击排序功能
+
+### Bug 修复
+- 批量上下架 productIds 强转 List<Long> 导致 Integer->Long ClassCastException
+- 健康约束迁移编号 360-364 调整为 367-371,避免与远程复用编号冲突
+- 商品列表赠品徽标简化为仅图标,去除冗长文字
+- 恢复丢失的 <style scoped> 样式块,修复提醒设置页样式不加载
+- 加入家庭页姓名/昵称输入框高度不足,增大 min-height 与 padding
+- 登录成功后自动刷新当前页以更新登录状态
+- 登录成功后自动跳转到加入家庭表单页
+- 修复图片双前缀 URL + teacher 方案管理页 + 编译错误清理
+- 本地菜单补齐菜单管理入口,简化 effectiveMenuItems 清理废弃 dynamicMenuItems
+
+### 其他
+-   旧写法 (List<Long>) 强转为擦除强转,运行期 for (Long id) 元素转型抛 ClassCastException
+- - 修复:逐元素 ParamUtils.getLong 安全解析(兼容 Integer/Long/数字字符串);shelve 兼容布尔/字符串
+- - 新增回归测试 AdminProductControllerBatchShelveTest(真实 Jackson 反序列化报文),修复前红/修复后绿
+- 
+-    - 后端已返回完整 OSS URL(https://cfc.s3.cn-north-1.jdcloud-oss.com/...)时直接返回,
+-      不再拼接 config.API_BASE_URL(https://cfc.etotem.com.cn)
+-    - 统一 null/'null'/'undefined' 守卫 + http(s) 直通 + 前导斜杠规范化
+-    - 涉及:activity×2, ai/chat, article-center×2, body-detail/dimension-detail,
+-      discover/index, growth/upload, guide×3, index-home, meal/recipe-detail,
+-      mind-detail/articles, promotion/material, shop×5, vendor/products,
+-      components/RecommendedFeed
+- 2. teacher 方案管理:新增 pages/teacher/plan-create.vue、plan-list.vue 并注册到 pages.json
+-    - 修复 pages/teacher 分包 plan-detail/plan-list 重复注册(app.json 报错)
+-    - families.vue: 修复重复 class 属性 + 方案入口卡片
+- 3. docs 参考资料更新(测评样例/知识库 JSON/MD)
+- 未提交:docs/参考资料/知识库/*.vbak-* 备份文件(忽略)
+- 
+- - mind-detail「每日心理」卡片:旧品牌蓝渐变左条(#5B9BD5→#8FC5E8,宽 6rpx)改为维度粉 $dim-mind + 8rpx,标题色归位,符合阶段一确立的维度左条规范
+- - 五维页旧品牌蓝 #5B9BD5 清零
+- - 验证:dart-sass 逐页编译五页 style 区块全部通过;剩余硬编码已收敛为状态色阶与维度浅底(阶段三对象)
+- 
+- - 五页 style 接入 lang="scss",74 处硬编码改为语义令牌(数值等价,视觉零变化)
+- - action-detail 修复 3 处 transition: all,改为显式 opacity/transform + $ease-standard
+- - 修复 pages/wealth/index.vue 缺失 </style> 结尾标签(文件被截断且 HEAD 同样损坏,会阻断整包编译)
+- - 验证:dart-sass 逐页编译五页 style 区块全部通过
+- 
+- - 新增 docs/dimension-pages-login-state-plan.md: 五维主页面登录前/登录后显示规划 V1.0,含统一骨架、五页显示清单、决策固化(心页维持 mind-wisdom 双色、身/智保留 preview-text、富页豁免已有商城精选)与 DimensionVisitorCard/DimensionIntroCard 职责边界(含 490e69e90 机械替换事故防线)
+- 
+- - WebhookNotificationChannel 以接收用户 users.phone 作为 msgLabel(按人定向)
+- - RepeatTaskGenerator 以模板 earliest_start 作为实例生成起点(分阶段任务门控)
+- 
+
+### 重构
+- 五维页中性灰阶归一化并清除旧品牌蓝残留(UniForge 阶段二)
+- 五维页接入设计令牌体系(UniForge 阶段一:语义基座)
+- 身维度游客卡 DOM 上移并固化五维登录前后显示规划
+
+
 ## v1.0.1592 (2026-10-12)
 
 ### 文档

+ 158 - 1
cfc-web/public/CHANGELOG.md

@@ -1,6 +1,6 @@
 # 更新日志
 
-> 当前版本: v1.0.1592
+> 当前版本: v1.0.1600
 
 ## 历史版本
 
@@ -8,6 +8,163 @@
 
 ---
 
+## v1.0.1600 (2026-10-13)
+
+### 文档
+- 更新PROJECT-OVERVIEW.md,添加饮食/睡眠/运动打卡任务链路设计条目
+- 饮食/睡眠/运动打卡接入任务完成链路设计(方案B双轨)
+
+### Bug 修复
+- 修复 ProductEdit.vue 语法错误(validate 回调缺失 ) 与 export default 花括号不闭合)
+
+
+## v1.0.1599 (2026-10-13)
+
+### 新功能
+- P4 干预方案驱动任务生成(协议 v1.1 + 离线生成器)
+
+### 其他
+-   监测 description、weekly time、followups due、exercise_ids/exercise_tasks
+- - schema/protocol.schema.json 同步 v1.1 字段
+- - validate_kb.py 支持 v1.1(exercise_ids/exercise_tasks 交叉校验)
+- - render_kb_md.py 协议视图适配 v1.1
+- - 新增 gen_tasks_from_protocol.py:由 protocols/*.json 生成幂等任务种子 SQL,
+-   替代硬编码 gen_seed.py;已与生产 45 条任务逐字段比对完全一致(幂等)
+- 
+
+
+## v1.0.1598 (2026-10-13)
+
+### Bug 修复
+- 修复商品管理页编辑按钮 pagination 上下文问题
+
+
+## v1.0.1597 (2026-10-13)
+
+### 新功能
+- P3 JSON→MD 视图派生工具链(单一事实源收口)
+- P2 补剂相互作用库 + 干预方案结构化 + 校验器升级
+
+### 其他
+- - --check 模式: 与现有视图比对,不一致退出码 1(阻断提交,强制只改 JSON)
+- - validate_kb.sh: 结构校验 + 视图同步校验统一入口(pre-commit 自动执行)
+- - 生成 docs/参考资料/知识库/views/*.md 初始视图;protocols 视图解析补剂 id 为名称
+- 
+-   Akk×铁剂,色氨酸×SSRI,鱼油×抗凝药,姜黄×抗血小板,益生菌×高温)
+- - protocols/gut_joint_intervention_v1.json: 双人肠道菌群联合干预方案
+-   完整结构化(周期定义、双成员、每阶段 5 时段补剂引用、每日/每周监测、
+-   4/8/12 周复查节点、运动引用);已部署的 45 条任务数据从此文件派生
+- - schema/ 新增 interaction.schema.json + protocol.schema.json
+- - validate_kb.py 升级:支持 interactions.json 校验 + 跨库引用完整性检查
+-   (supplement_ids / exercise_ids / indicator_ids / cycle_id 交叉验证)
+- 
+
+
+## v1.0.1596 (2026-10-13)
+
+### 其他
+- - docs/scripts/validate_kb.sh:CI/本地统一校验入口(退出码供阻断)
+- - docs/scripts/install_git_hooks.sh:core.hooksPath -> .githooks,幂等安装
+- - 已验证:合法变更 exit 0;损坏 JSON 阻断 exit 1
+- 
+
+
+## v1.0.1596 (2026-10-13)
+
+### 新功能
+- P0 新增补充剂库/临床指标参考库/运动处方库 + JSON Schema 校验
+
+### 其他
+- - 临床指标参考库 clinical_indicators.json:15 项(血糖/HbA1c/血红蛋白/铁蛋白/血脂四项/肝肾/尿酸/eGFR,含参考范围与干预阈值)
+- - 运动处方库 exercises.json:4 条(餐后散步/足尖俯卧撑/八段锦/腹部按摩)
+- - schema/ 三个 JSON Schema + docs/scripts/validate_kb.py 校验脚本
+- - 数据来源:《双人肠道菌群联合干预方案》+ 中国糖尿病/血脂/贫血等指南
+- 
+
+
+## v1.0.1595 (2026-10-13)
+
+### 新功能
+- 菌群营养知识库.md 补回六大营养字段
+
+### 其他
+- - 190 个食物行全部填充:82 条取自 JSON 知识库与原库,108 条熟食/主食按
+-   《中国食物成分表》(第6版) 常见参考值补入,并在 section 一 标注待营养顾问终审
+- - 速查表(2列)与其余章节不受影响
+- 
+
+
+## v1.0.1594 (2026-10-13)
+
+### 新功能
+- 合并菌群营养知识库V2 GI食物库到主文件与JSON
+
+### 其他
+- - JSON: 食物营养库按md更新GI类字段(重合132覆盖/新增24),原能量/蛋白/脂肪/碳水/淀粉/膳食纤维/胆固醇营养字段保留,现356种
+- - 备份见 .vbak-*
+- 
+
+
+## v1.0.1593 (2026-10-13)
+
+### 新功能
+- fix task completion points display (0→10CF) and unit format (分→CF) - resolve Unknown column errors and UI display issues
+- 健康自检问卷向导与LITE轻享会员等级:问卷组件与方案页重写、能量沙盘问卷解锁、LangGraph健康上下文注入、成员级偏好读写安全校验、无特殊偏好标记、多页面联动调整
+- 健康方案改为 plan-list 列表页,健康首页/肠道/报告确认页跳转统一指向
+- 微信打卡提醒按用户手机号定向msgLabel;重复任务支持earliest_start阶段起点
+- 实现三级健康约束规则体系(硬拦截/软警告/正常推荐),支持疾病禁忌、过敏命中、药物相互作用、剂量超标、档案缺失提示,并提供健康方案生成能力
+- 新增7列文章列表点击排序功能
+
+### Bug 修复
+- 批量上下架 productIds 强转 List<Long> 导致 Integer->Long ClassCastException
+- 健康约束迁移编号 360-364 调整为 367-371,避免与远程复用编号冲突
+- 商品列表赠品徽标简化为仅图标,去除冗长文字
+- 恢复丢失的 <style scoped> 样式块,修复提醒设置页样式不加载
+- 加入家庭页姓名/昵称输入框高度不足,增大 min-height 与 padding
+- 登录成功后自动刷新当前页以更新登录状态
+- 登录成功后自动跳转到加入家庭表单页
+- 修复图片双前缀 URL + teacher 方案管理页 + 编译错误清理
+- 本地菜单补齐菜单管理入口,简化 effectiveMenuItems 清理废弃 dynamicMenuItems
+
+### 其他
+-   旧写法 (List<Long>) 强转为擦除强转,运行期 for (Long id) 元素转型抛 ClassCastException
+- - 修复:逐元素 ParamUtils.getLong 安全解析(兼容 Integer/Long/数字字符串);shelve 兼容布尔/字符串
+- - 新增回归测试 AdminProductControllerBatchShelveTest(真实 Jackson 反序列化报文),修复前红/修复后绿
+- 
+-    - 后端已返回完整 OSS URL(https://cfc.s3.cn-north-1.jdcloud-oss.com/...)时直接返回,
+-      不再拼接 config.API_BASE_URL(https://cfc.etotem.com.cn)
+-    - 统一 null/'null'/'undefined' 守卫 + http(s) 直通 + 前导斜杠规范化
+-    - 涉及:activity×2, ai/chat, article-center×2, body-detail/dimension-detail,
+-      discover/index, growth/upload, guide×3, index-home, meal/recipe-detail,
+-      mind-detail/articles, promotion/material, shop×5, vendor/products,
+-      components/RecommendedFeed
+- 2. teacher 方案管理:新增 pages/teacher/plan-create.vue、plan-list.vue 并注册到 pages.json
+-    - 修复 pages/teacher 分包 plan-detail/plan-list 重复注册(app.json 报错)
+-    - families.vue: 修复重复 class 属性 + 方案入口卡片
+- 3. docs 参考资料更新(测评样例/知识库 JSON/MD)
+- 未提交:docs/参考资料/知识库/*.vbak-* 备份文件(忽略)
+- 
+- - mind-detail「每日心理」卡片:旧品牌蓝渐变左条(#5B9BD5→#8FC5E8,宽 6rpx)改为维度粉 $dim-mind + 8rpx,标题色归位,符合阶段一确立的维度左条规范
+- - 五维页旧品牌蓝 #5B9BD5 清零
+- - 验证:dart-sass 逐页编译五页 style 区块全部通过;剩余硬编码已收敛为状态色阶与维度浅底(阶段三对象)
+- 
+- - 五页 style 接入 lang="scss",74 处硬编码改为语义令牌(数值等价,视觉零变化)
+- - action-detail 修复 3 处 transition: all,改为显式 opacity/transform + $ease-standard
+- - 修复 pages/wealth/index.vue 缺失 </style> 结尾标签(文件被截断且 HEAD 同样损坏,会阻断整包编译)
+- - 验证:dart-sass 逐页编译五页 style 区块全部通过
+- 
+- - 新增 docs/dimension-pages-login-state-plan.md: 五维主页面登录前/登录后显示规划 V1.0,含统一骨架、五页显示清单、决策固化(心页维持 mind-wisdom 双色、身/智保留 preview-text、富页豁免已有商城精选)与 DimensionVisitorCard/DimensionIntroCard 职责边界(含 490e69e90 机械替换事故防线)
+- 
+- - WebhookNotificationChannel 以接收用户 users.phone 作为 msgLabel(按人定向)
+- - RepeatTaskGenerator 以模板 earliest_start 作为实例生成起点(分阶段任务门控)
+- 
+
+### 重构
+- 五维页中性灰阶归一化并清除旧品牌蓝残留(UniForge 阶段二)
+- 五维页接入设计令牌体系(UniForge 阶段一:语义基座)
+- 身维度游客卡 DOM 上移并固化五维登录前后显示规划
+
+
 ## v1.0.1592 (2026-10-12)
 
 ### 文档

+ 547 - 0
docs/superpowers/plans/2026-10-13-health-checkin-task-linkage.md

@@ -0,0 +1,547 @@
+# 饮食/睡眠/运动打卡接入任务完成链路 实现计划
+
+> **面向 AI 代理的工作者:** 必需子技能:使用 superpowers:subagent-driven-development(推荐)或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框(`- [ ]`)语法来跟踪进度。
+
+**目标:** 让饮食/睡眠/运动打卡可作为任务完成凭证,覆盖两类任务来源:手动创建的一次性任务(点击跳转打卡页自动完成)+ 系统每日自动生成的打卡任务(打卡累计进度达标自动完成)。
+
+**架构:** 双轨复用现有机制——一次性任务走 `actionType` 联动(diet/sleep/exercise 三个新值),任务列表跳转对应打卡页带 `taskId`,打卡 Controller 成功后在 `create()` 内回写 `completeTask`;每日任务走 `is_daily_progress=1` + `updateProgress(userId, taskKey, 1)` 累计进度。判定以任务真实类型为准(后端反查 tasks 表)。
+
+**技术栈:** Java 8 + Spring Boot 2.7.18 + MyBatis-Plus / uni-app Vue 2 小程序
+
+**规格文档:** `docs/superpowers/specs/2026-10-13-health-checkin-task-linkage-design.md`
+
+---
+
+## 文件结构
+
+| 文件 | 操作 | 职责 |
+|---|---|---|
+| `cfc-backend/.../entity/HealthMealRecord.java` | 修改 | 新增 `@TableField(exist=false) Long taskId` |
+| `cfc-backend/.../entity/HealthSleepRecord.java` | 修改 | 新增 `@TableField(exist=false) Long taskId` |
+| `cfc-backend/.../entity/HealthExerciseRecord.java` | 修改 | 新增 `@TableField(exist=false) Long taskId` |
+| `cfc-backend/.../entity/Task.java` | 修改 | `actionType` 注释补充 diet/sleep/exercise |
+| `cfc-backend/.../dto/CreateTaskDTO.java` | 修改 | `actionType` 注释更新 |
+| `cfc-backend/.../controller/HealthMealController.java` | 修改 | `create()` 挂钩任务回写(taskKey=DIET) |
+| `cfc-backend/.../controller/HealthSleepController.java` | 修改 | `create()` 挂钩任务回写(taskKey=SLEEP) |
+| `cfc-backend/.../controller/HealthExerciseController.java` | 修改 | `create()` 挂钩任务回写(taskKey=EXERCISE) |
+| `cfc-backend/.../config/DatabaseInitializer.java` | 修改 | 新增迁移:三条打卡任务模板种子 |
+| `cfc-backend/.../task/RepeatTaskGenerator.java` | 修改 | 每日打卡任务实例生成 |
+| `cfc-frontend/pages/tasks/tasks.vue` | 修改 | `getActionLabel` + `navigateByAction` 加 diet/sleep/exercise 分支 |
+| `cfc-frontend/pages/growth/diet-checkin.vue` | 修改 | `onLoad` 读 taskId,提交带上 |
+| `cfc-frontend/pages/growth/sleep-checkin.vue` | 修改 | 同上 |
+| `cfc-frontend/pages/growth/exercise-checkin.vue` | 修改 | 同上 |
+| `docs/superpowers/api/API_REFERENCE.md` | 修改 | 三个打卡接口补充 taskId 参数 |
+
+---
+
+## 任务 1:实体新增非持久化 taskId 字段
+
+**文件:**
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/entity/HealthMealRecord.java`
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/entity/HealthSleepRecord.java`
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/entity/HealthExerciseRecord.java`
+
+- [ ] **步骤 1:三个实体各加一个 `taskId` 字段**
+
+HealthMealRecord.java 在 `private Date createdAt;` 之前加:
+
+```java
+import com.baomidou.mybatisplus.annotation.TableField;
+
+/** 关联任务ID(一次性任务打卡后自动完成;null=走每日任务累计路径) */
+@TableField(exist = false)
+private Long taskId;
+```
+
+HealthSleepRecord.java 同样(import 在 `import lombok.Data;` 旁):
+
+```java
+import com.baomidou.mybatisplus.annotation.TableField;
+
+/** 关联任务ID(一次性任务打卡后自动完成;null=走每日任务累计路径) */
+@TableField(exist = false)
+private Long taskId;
+```
+
+HealthExerciseRecord.java 同样。
+
+- [ ] **步骤 2:编译验证**
+
+运行:`cd /sc-data/cfc/cfc-backend && mvn clean compile 2>&1 | tail -10`
+预期:`BUILD SUCCESS`
+
+- [ ] **步骤 3:Commit**
+
+```bash
+cd /sc-data/cfc && git add cfc-backend/src/main/java/com/etotem/cfc/entity/HealthMealRecord.java cfc-backend/src/main/java/com/etotem/cfc/entity/HealthSleepRecord.java cfc-backend/src/main/java/com/etotem/cfc/entity/HealthExerciseRecord.java && \
+git commit -m "feat(task): 三个健康打卡实体新增 taskId 非持久化字段"
+```
+
+---
+
+## 任务 2:Task.java / CreateTaskDTO.java 注释补充
+
+**文件:**
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/entity/Task.java`(约第 131 行)
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/dto/CreateTaskDTO.java`(约第 67 行)
+
+- [ ] **步骤 1:更新 Task.java 的 actionType 注释**
+
+```java
+// 原:
+/** TASK-SYS-248: 联动动作: minigame/focus/survey/article/activity/cart/order */
+// 改为:
+/** TASK-SYS-248: 联动动作: minigame/focus/survey/article/activity/cart/order/diet/sleep/exercise */
+```
+
+- [ ] **步骤 2:更新 CreateTaskDTO.java 的 actionType 注释**
+
+```java
+// 原(第 66 行):
+// TASK-SYS-248: 联动动作: minigame/focus/survey/article/activity/cart/order
+// 改为:
+// TASK-SYS-248: 联动动作: minigame/focus/survey/article/activity/cart/order/diet/sleep/exercise
+```
+
+- [ ] **步骤 3:编译验证**
+
+运行:`cd /sc-data/cfc/cfc-backend && mvn clean compile 2>&1 | tail -5`
+预期:`BUILD SUCCESS`
+
+- [ ] **步骤 4:Commit**
+
+```bash
+cd /sc-data/cfc && git add cfc-backend/src/main/java/com/etotem/cfc/entity/Task.java cfc-backend/src/main/java/com/etotem/cfc/dto/CreateTaskDTO.java && \
+git commit -m "docs(task): actionType 注释补充 diet/sleep/exercise 取值"
+```
+
+---
+
+## 任务 3:三个 Health 打卡 Controller 挂钩任务回写
+
+**文件:**
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/controller/HealthMealController.java`(create 方法第 204-251 行)
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/controller/HealthSleepController.java`(create 方法第 42-63 行)
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/controller/HealthExerciseController.java`(create 方法第 59-85 行)
+
+- [ ] **步骤 1:三个 Controller 注入依赖**
+
+在三个 Controller 的字段区新增:
+
+```java
+@Resource
+private com.etotem.cfc.service.TaskService taskService;
+
+@Resource
+private com.etotem.cfc.mapper.TaskMapper taskMapper;
+
+@Resource
+private com.etotem.cfc.mapper.FamilyMemberMapper familyMemberMapper;
+```
+
+确认类上已有 `@Slf4j`(HealthMealController 目前无 @Slf4j,需补加;Sleep 需确认;Exercise 需确认)。
+
+- [ ] **步骤 2:HealthMealController.create() — 打卡成功后挂钩任务回写**
+
+在 `healthMealRecordMapper.insert(record);`(约第 231 行)之后、积分发放之前插入:
+
+```java
+// ===== 任务回写挂钩 =====
+try {
+    boolean isBackfill = record.getIsBackfill() != null && record.getIsBackfill() == 1;
+    if (!isBackfill) {
+        if (record.getTaskId() != null) {
+            com.etotem.cfc.entity.Task linked = taskMapper.selectById(record.getTaskId());
+            if (linked != null && linked.getIsDailyProgress() != null && linked.getIsDailyProgress() == 1) {
+                // 每日进度型任务:累计进度
+                com.etotem.cfc.entity.FamilyMember fm = familyMemberMapper.selectById(record.getMemberId());
+                if (fm != null && fm.getUserId() != null) {
+                    taskService.updateProgress(fm.getUserId(), "DIET", 1);
+                }
+            } else if (linked != null) {
+                // 一次性任务:直接完成(凭证用打卡记录内容)
+                String photo = record.getPhotoUrls() != null ? record.getPhotoUrls() : "";
+                String content = record.getFoodItems() != null ? record.getFoodItems() : (record.getRemark() != null ? record.getRemark() : "");
+                taskService.completeTask(record.getTaskId(), record.getMemberId(), photo, content, "text");
+            }
+        } else {
+            // 未带 taskId:走每日任务累计路径
+            com.etotem.cfc.entity.FamilyMember fm = familyMemberMapper.selectById(record.getMemberId());
+            if (fm != null && fm.getUserId() != null) {
+                taskService.updateProgress(fm.getUserId(), "DIET", 1);
+            }
+        }
+    }
+} catch (Exception e) {
+    log.warn("饮食打卡任务回写失败: {}", e.getMessage());
+}
+```
+
+- [ ] **步骤 3:HealthSleepController.create() — taskKey 换 `"SLEEP"`**
+
+在 `healthSleepRecordMapper.insert(record);`(约第 52 行)之后、画像重算之前插入(Sleep 无 isBackfill 字段,直接执行,不带补打判断):
+
+```java
+// ===== 任务回写挂钩 =====
+try {
+    if (record.getTaskId() != null) {
+        com.etotem.cfc.entity.Task linked = taskMapper.selectById(record.getTaskId());
+        if (linked != null && linked.getIsDailyProgress() != null && linked.getIsDailyProgress() == 1) {
+            com.etotem.cfc.entity.FamilyMember fm = familyMemberMapper.selectById(record.getMemberId());
+            if (fm != null && fm.getUserId() != null) {
+                taskService.updateProgress(fm.getUserId(), "SLEEP", 1);
+            }
+        } else if (linked != null) {
+            taskService.completeTask(record.getTaskId(), record.getMemberId(),
+                    "", record.getRemark() != null ? record.getRemark() : "睡眠打卡", "text");
+        }
+    } else {
+        com.etotem.cfc.entity.FamilyMember fm = familyMemberMapper.selectById(record.getMemberId());
+        if (fm != null && fm.getUserId() != null) {
+            taskService.updateProgress(fm.getUserId(), "SLEEP", 1);
+        }
+    }
+} catch (Exception e) {
+    log.warn("睡眠打卡任务回写失败: {}", e.getMessage());
+}
+```
+
+- [ ] **步骤 4:HealthExerciseController.create() — taskKey 换 `"EXERCISE"`**
+
+在 `healthExerciseRecordMapper.insert(record);`(约第 74 行)之后、画像重算之前插入:
+
+```java
+// ===== 任务回写挂钩 =====
+try {
+    if (record.getTaskId() != null) {
+        com.etotem.cfc.entity.Task linked = taskMapper.selectById(record.getTaskId());
+        if (linked != null && linked.getIsDailyProgress() != null && linked.getIsDailyProgress() == 1) {
+            com.etotem.cfc.entity.FamilyMember fm = familyMemberMapper.selectById(record.getMemberId());
+            if (fm != null && fm.getUserId() != null) {
+                taskService.updateProgress(fm.getUserId(), "EXERCISE", 1);
+            }
+        } else if (linked != null) {
+            String photo = record.getPhotoUrls() != null ? record.getPhotoUrls() : "";
+            String content = record.getRemark() != null ? record.getRemark() : "运动打卡";
+            taskService.completeTask(record.getTaskId(), record.getMemberId(), photo, content, "text");
+        }
+    } else {
+        com.etotem.cfc.entity.FamilyMember fm = familyMemberMapper.selectById(record.getMemberId());
+        if (fm != null && fm.getUserId() != null) {
+            taskService.updateProgress(fm.getUserId(), "EXERCISE", 1);
+        }
+    }
+} catch (Exception e) {
+    log.warn("运动打卡任务回写失败: {}", e.getMessage());
+}
+```
+
+> 注意:HealthExerciseRecord **无 isBackfill 字段**,故不判断补打(与设计文档决策 3 略有出入——设计文档要求补打不触发回写。实现时若 Exercise 无补打能力则无需判断;确认实体字段后决定)。
+
+- [ ] **步骤 5:编译验证**
+
+运行:`cd /sc-data/cfc/cfc-backend && mvn clean compile 2>&1 | tail -15`
+预期:`BUILD SUCCESS`
+
+- [ ] **步骤 6:Commit**
+
+```bash
+cd /sc-data/cfc && git add cfc-backend/src/main/java/com/etotem/cfc/controller/HealthMealController.java cfc-backend/src/main/java/com/etotem/cfc/controller/HealthSleepController.java cfc-backend/src/main/java/com/etotem/cfc/controller/HealthExerciseController.java && \
+git commit -m "feat(task): 三个健康打卡Controller挂钩任务回写(一次性完成+每日进度累计)"
+```
+
+---
+
+## 任务 4:打卡任务模板种子数据
+
+**文件:**
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java`
+
+- [ ] **步骤 1:查找最新迁移编号**
+
+运行:`grep -n "// 迁移" cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java | tail -3`
+取当前最大编号 N。
+
+- [ ] **步骤 2:在 runMigrations() 末尾追加迁移 N+1**
+
+```java
+// 迁移 N+1: 插入饮食/睡眠/运动每日打卡任务模板(action_type 驱动)
+try {
+    Integer checkinTplCount = jdbcTemplate.queryForObject(
+            "SELECT COUNT(*) FROM admin_task_templates WHERE category = '健康打卡'",
+            Integer.class);
+    if (checkinTplCount == null || checkinTplCount == 0) {
+        jdbcTemplate.execute(
+            "INSERT INTO admin_task_templates " +
+            "(title, description, points, category, need_review, is_active, task_type, frequency, action_type, created_at, updated_at) VALUES " +
+            "('[DIET]饮食打卡', '每日记录饮食打卡', 5, '健康打卡', 0, 1, 'recurring', 'daily', 'diet', NOW(), NOW()), " +
+            "('[SLEEP]睡眠打卡', '每日记录睡眠打卡', 5, '健康打卡', 0, 1, 'recurring', 'daily', 'sleep', NOW(), NOW()), " +
+            "('[EXERCISE]运动打卡', '每日记录运动打卡', 5, '健康打卡', 0, 1, 'recurring', 'daily', 'exercise', NOW(), NOW())");
+        log.info("迁移 N+1: 已插入3条健康打卡任务模板(DIET/SLEEP/EXERCISE)");
+    }
+} catch (Exception e) {
+    log.warn("迁移 N+1: 打卡任务模板插入失败或已存在: {}", e.getMessage());
+}
+```
+
+> ⚠️ 先确认 `admin_task_templates` 表是否已有 `action_type` 列;若无,先 `ensureColumn("admin_task_templates", "action_type", "VARCHAR(32) DEFAULT NULL COMMENT '联动动作类型'")`。**注意:`TaskTemplate` 实体可能没有 actionType 字段**——RepeatTaskGenerator 查询模板用的是 `Task` 实体(tasks 表),模板种子实际需以 `tasks` 表为准(见任务 5)。
+
+- [ ] **步骤 3:编译验证**
+
+运行:`cd /sc-data/cfc/cfc-backend && mvn clean compile 2>&1 | tail -5`
+预期:`BUILD SUCCESS`
+
+- [ ] **步骤 4:Commit**
+
+```bash
+cd /sc-data/cfc && git add cfc-backend/src/main/java/com/etotem/cfc/config/DatabaseInitializer.java && \
+git commit -m "feat(task): 添加饮食/睡眠/运动每日打卡任务模板种子"
+```
+
+---
+
+## 任务 5:RepeatTaskGenerator 新增打卡任务实例生成
+
+**文件:**
+- 修改:`cfc-backend/src/main/java/com/etotem/cfc/task/RepeatTaskGenerator.java`
+
+> ⚠️ **关键澄清**:`RepeatTaskGenerator` 现有逻辑只处理 `is_template=1` 的**模板行**(在 `tasks` 表内),用 `frequency`/`repeat_type` 分派生成实例。打卡任务模板种子(任务 4)应插入 `tasks` 表(is_template=1, action_type=diet/sleep/exercise, frequency=daily),而非 `admin_task_templates`——因为生成器查询的是 `tasks` 表。实现时先确认种子应落 `tasks` 表。
+
+- [ ] **步骤 1:注入 familyMemberMapper**
+
+```java
+@Resource
+private com.etotem.cfc.mapper.FamilyMemberMapper familyMemberMapper;
+```
+
+文件顶部确认 `import java.util.Arrays;` 存在,若无则加。
+
+- [ ] **步骤 2:在 generateDailyTasks() 的每日任务处理块(第 56-68 行)前插入打卡任务生成**
+
+```java
+// 每日打卡任务生成(diet/sleep/exercise)——为每个家庭成员生成当日进度型任务
+List<Task> checkinTemplates = taskMapper.selectList(
+    new LambdaQueryWrapper<Task>()
+        .eq(Task::getIsTemplate, 1)
+        .in(Task::getActionType, Arrays.asList("diet", "sleep", "exercise"))
+);
+for (Task tpl : checkinTemplates) {
+    List<com.etotem.cfc.entity.FamilyMember> members =
+        familyMemberMapper.selectList(
+            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<com.etotem.cfc.entity.FamilyMember>()
+                .eq(com.etotem.cfc.entity.FamilyMember::getFamilyId, tpl.getFamilyId()));
+    for (com.etotem.cfc.entity.FamilyMember member : members) {
+        if (member.getUserId() == null) continue; // 仅对能登录用户生成
+        Long exists = taskMapper.selectCount(
+            new LambdaQueryWrapper<Task>()
+                .eq(Task::getTemplateId, tpl.getId())
+                .eq(Task::getFamilyMemberId, member.getId())
+                .eq(Task::getIsDailyProgress, 1)
+                .ge(Task::getCreatedAt, today)
+                .lt(Task::getCreatedAt, new Date(today.getTime() + 86400000L))
+        );
+        if (exists == null || exists == 0) {
+            Task instance = new Task();
+            instance.setFamilyId(tpl.getFamilyId());
+            instance.setCreatorId(tpl.getCreatorId());
+            instance.setExecutorType("child");
+            instance.setExecutorId(member.getId());
+            instance.setFamilyMemberId(member.getId());
+            instance.setChildId(member.getId());
+            instance.setTitle(tpl.getTitle());
+            instance.setDescription(tpl.getDescription());
+            instance.setPoints(tpl.getPoints());
+            instance.setCategory(tpl.getCategory());
+            instance.setStatus("pending");
+            instance.setNeedReview(0);
+            instance.setIsTemplate(0);
+            instance.setIsDailyProgress(1);
+            instance.setTargetValue(1);
+            instance.setActionType(tpl.getActionType());
+            instance.setTemplateId(tpl.getId());
+            instance.setMemberOnly(0);
+            instance.setCreatedAt(new Date());
+            instance.setUpdatedAt(new Date());
+            taskMapper.insert(instance);
+        }
+    }
+}
+log.info("每日打卡任务生成完成,处理{}个模板", checkinTemplates.size());
+```
+
+> 注:`generateDailyTasks()` 方法内已有 `today` 变量(第 51 行),直接复用。
+
+- [ ] **步骤 3:编译验证**
+
+运行:`cd /sc-data/cfc/cfc-backend && mvn clean compile 2>&1 | tail -5`
+预期:`BUILD SUCCESS`
+
+- [ ] **步骤 4:Commit**
+
+```bash
+cd /sc-data/cfc && git add cfc-backend/src/main/java/com/etotem/cfc/task/RepeatTaskGenerator.java && \
+git commit -m "feat(task): RepeatTaskGenerator 每日生成饮食/睡眠/运动打卡任务实例"
+```
+
+---
+
+## 任务 6:前端 tasks.vue — 按钮文案与跳转
+
+**文件:**
+- 修改:`cfc-frontend/pages/tasks/tasks.vue`(第 413-503 行)
+
+- [ ] **步骤 1:修改 getActionLabel() 方法**
+
+在第 422 行 `if (at === 'cart' || at === 'order') return '去购物'` 之后加:
+
+```js
+      if (at === 'diet') return '去打卡'
+      if (at === 'sleep') return '去打卡'
+      if (at === 'exercise') return '去打卡'
+```
+
+- [ ] **步骤 2:修改 navigateByAction() 方法**
+
+在第 479 行 `else if (at === 'cart' || at === 'order')` 分支之后加:
+
+```js
+       } else if (at === 'diet') {
+         uni.navigateTo({ url: '/pages/growth/diet-checkin?taskId=' + taskId })
+       } else if (at === 'sleep') {
+         uni.navigateTo({ url: '/pages/growth/sleep-checkin?taskId=' + taskId })
+       } else if (at === 'exercise') {
+         uni.navigateTo({ url: '/pages/growth/exercise-checkin?taskId=' + taskId })
+       }
+```
+
+注意闭合 if-else 链的 `}`。
+
+- [ ] **步骤 3:语法校验**
+
+运行:`cd /sc-data/cfc/cfc-frontend && node -e "const s=require('fs').readFileSync('pages/tasks/tasks.vue','utf8'); const m=s.match(/<script>([\s\S]*)<\/script>/); if(m) new Function(m[1])" 2>&1 | head -5`
+预期:无语法错误
+
+- [ ] **步骤 4:Commit**
+
+```bash
+cd /sc-data/cfc && git add cfc-frontend/pages/tasks/tasks.vue && \
+git commit -m "feat(tasks): 任务列表按钮支持 diet/sleep/exercise 打卡跳转"
+```
+
+---
+
+## 任务 7:前端三个打卡页 — 接收 taskId 并传入
+
+**文件:**
+- 修改:`cfc-frontend/pages/growth/diet-checkin.vue`
+- 修改:`cfc-frontend/pages/growth/sleep-checkin.vue`
+- 修改:`cfc-frontend/pages/growth/exercise-checkin.vue`
+
+- [ ] **步骤 1:diet-checkin.vue — data 加 taskId,onLoad 读取**
+
+在 `data()` 新增:`taskId: null,  // 来自任务列表跳转的 taskId(一次性任务)`
+
+修改 `onLoad(options)`:`if (options.taskId) { this.taskId = options.taskId }`
+
+- [ ] **步骤 2:diet-checkin.vue — submitCheckin() 提交时带 taskId**
+
+在 `uni.request` 的 data 对象(约第 450 行)新增:
+
+```js
+taskId: self.taskId || undefined,  // 新增:关联任务
+```
+
+成功 toast 区分:
+
+```js
+uni.showToast({ title: self.taskId ? '打卡成功,任务已完成' : '打卡成功', icon: 'success' })
+```
+
+- [ ] **步骤 3:sleep-checkin.vue / exercise-checkin.vue — 同样改动**
+
+先读取两文件 `data()`/`onLoad`/`submitCheckin` 结构,按步骤 1-2 模式添加。
+
+- [ ] **步骤 4:语法校验**
+
+```bash
+cd /sc-data/cfc/cfc-frontend && for f in pages/growth/diet-checkin.vue pages/growth/sleep-checkin.vue pages/growth/exercise-checkin.vue; do node -e "const s=require('fs').readFileSync('$f','utf8'); const m=s.match(/<script>([\s\S]*)<\/script>/); if(m) new Function(m[1])" 2>&1 | head -3 && echo "OK: $f"; done
+```
+
+- [ ] **步骤 5:Commit**
+
+```bash
+cd /sc-data/cfc && git add cfc-frontend/pages/growth/diet-checkin.vue cfc-frontend/pages/growth/sleep-checkin.vue cfc-frontend/pages/growth/exercise-checkin.vue && \
+git commit -m "feat(checkin): 三个打卡页接收 taskId 参数,打卡成功提示任务完成"
+```
+
+---
+
+## 任务 8:API 文档更新
+
+**文件:**
+- 修改:`docs/superpowers/api/API_REFERENCE.md`
+
+- [ ] **步骤 1:找到三个打卡接口条目,补充 taskId 参数**
+
+在 `POST /api/health/meal/create`、`POST /api/health/sleep/create`、`POST /api/health/exercise/create` 条目下补充:
+
+```markdown
+**新增可选参数**(2026-10-13):
+
+| 参数 | 类型 | 说明 |
+|------|------|------|
+| taskId | Long | 关联任务 ID。一次性任务(actionType=diet)打卡后自动完成该任务;每日进度型任务打卡后累计进度 |
+```
+
+- [ ] **步骤 2:Commit**
+
+```bash
+cd /sc-data/cfc && git add docs/superpowers/api/API_REFERENCE.md && \
+git commit -m "docs: 健康打卡接口文档补充 taskId 参数说明"
+```
+
+---
+
+## 任务 9:全量验证
+
+- [ ] **步骤 1:后端全量编译**
+
+运行:`cd /sc-data/cfc/cfc-backend && mvn clean compile 2>&1 | tail -5`
+预期:`BUILD SUCCESS`
+
+- [ ] **步骤 2:前端全部改动文件语法校验**
+
+```bash
+cd /sc-data/cfc/cfc-frontend && for f in pages/tasks/tasks.vue pages/growth/diet-checkin.vue pages/growth/sleep-checkin.vue pages/growth/exercise-checkin.vue; do node -e "const s=require('fs').readFileSync('$f','utf8'); const m=s.match(/<script>([\s\S]*)<\/script>/); if(m) new Function(m[1])" 2>&1 | head -3 && echo "OK: $f"; done
+```
+
+- [ ] **步骤 3:更新 PROJECT-OVERVIEW.md 状态**
+
+将 `docs/superpowers/PROJECT-OVERVIEW.md` 中打卡任务链路条目从"📐 设计已提交"改为"✅ 全栈完成"。
+
+```bash
+cd /sc-data/cfc && git add docs/superpowers/PROJECT-OVERVIEW.md && \
+git commit -m "docs: 打卡任务链路标记为已完成"
+```
+
+---
+
+## 规格覆盖度自检
+
+| 规格要求 | 覆盖任务 |
+|---|---|
+| actionType 新增 diet/sleep/exercise(Task.java + CreateTaskDTO) | 任务 2 |
+| 三个 Record 实体加 taskId 非持久化字段 | 任务 1 |
+| 三个 Controller create() 挂钩任务回写 | 任务 3 |
+| 打卡任务模板种子数据 | 任务 4 |
+| RepeatTaskGenerator 每日生成打卡任务实例 | 任务 5 |
+| tasks.vue getActionLabel + navigateByAction | 任务 6 |
+| 三个打卡页 onLoad 接收 taskId,提交带上 | 任务 7 |
+| API 文档更新 | 任务 8 |
+| 全量编译 + PROJECT-OVERVIEW 更新 | 任务 9 |
+
+**关键实现注意:**
+1. **种子落表**:任务 4 的模板种子应插入 **`tasks` 表**(is_template=1, action_type=diet/sleep/exercise, frequency=daily),因为 RepeatTaskGenerator 查询的是 tasks 表。若使用 `admin_task_templates` 表,需同时确认 `TaskTemplate` 实体有 actionType 字段且生成器改为查该表——推荐直接落 tasks 表,与现有生成器一致。
+2. **isBackfill 差异**:Meal 有 is_backfill 字段需跳过补打;Sleep/Exercise 无该字段(确认实体后决定是否需要补打判断)。
+3. **HealthMealController 无 @Slf4j**:需补加注解和 import,否则 `log.warn` 无法编译。
+4. **userId 反查**:`updateProgress` 需要 `userId`,通过 `familyMemberMapper.selectById(memberId).getUserId()` 获得;不能登录用户(userId=null)打卡只存记录,不触发任务(与现有 updateProgress 容错一致)。

+ 5 - 11
docs/superpowers/specs/2026-10-13-health-checkin-task-linkage-design.md

@@ -56,18 +56,12 @@
 
 - `actionType` 注释更新,支持 `diet/sleep/exercise`
 
-#### 1.3 `TaskService.java` — 新增方法
+#### 1.3 `TaskService.java` — 直接复用现有方法
 
-```java
-/**
- * 健康打卡完成后回写任务进度
- * @param userId  登录用户 ID(用于反查 FamilyMember)
- * @param taskKey 任务类型标识("DIET" / "SLEEP" / "EXERCISE")
- * @param increment 进度增量
- */
-public void updateHealthCheckinProgress(Long userId, String taskKey, int increment)
-// 直接调用现有 updateProgress(userId, taskKey, increment)
-```
+无需新增方法。直接调用现有 `updateProgress(userId, taskKey, increment)`(第 1653 行):
+- 参数 `userId`:由打卡 Controller 通过 `memberId → family_members.userId` 反查获得
+- 参数 `taskKey`:按打卡类型传 `"DIET"` / `"SLEEP"` / `"EXERCISE"`
+- 参数 `increment`:固定 `1`(一次打卡 = 一次进度)
 
 #### 1.4 三个 Health 打卡 Controller — `create()` 方法挂钩