فهرست منبع

chore(web): build v1.0.1797 for cfclub deployment

Xiaogang Liao 2 هفته پیش
والد
کامیت
be9e539bb7
4فایلهای تغییر یافته به همراه329 افزوده شده و 3 حذف شده
  1. 1 1
      cfc-web/.last_build_commit
  2. 1 1
      cfc-web/package.json
  3. 163 0
      cfc-web/public/CHANGELOG-v1.0.md
  4. 164 1
      cfc-web/public/CHANGELOG.md

+ 1 - 1
cfc-web/.last_build_commit

@@ -1 +1 @@
-52f08920f12ce5339e107999f3473d965c2c971f
+2c9ad007953d83ab6e36bf0504df7529642c6dbc

+ 1 - 1
cfc-web/package.json

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

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

@@ -4,6 +4,169 @@
 
 ---
 
+## v1.0.1797 (2026-10-26)
+
+### 文档
+- 补充品牌话术/商业模式/物料设计资料与 工作文稿(采访稿、文案包、募资方案等)
+- 五维测评客观化系统设计与开发计划(方法矩阵/计分算法/任务分解 P0-P2)
+- 活动创建活动页体验修正 + 人群/费用重构方案(A1/A2/A3/G1/G2)
+- 报告代传功能修复方案(T29,分三批 B1/B2/B3)
+- 食材推荐/查询 报告入口收敛 + 家庭总览持久化最小值 方案(T28)
+- 报告代传功能运行态验证报告(任务 proxy-verify-20261025)
+- 报告代传核查报告 V3(补测试数据清理记录与运行态修正)
+- T24 睡眠打卡500+双身份 bug 设计 / T25 统一成员选择器设计 / 双身份只读诊断SQL
+
+### 新功能
+- GEO 分享优化(about 页注册、分享标题统一、5 页 shareMixin、首页 GEO 摘要、sitemap 与 SEO 文档)
+- T22 方案→任务回流传真(懒回填当次消费+实例透传来源+级联兜底+任务中心标签)
+- 团队页新增我的推荐人、消费额分级统计与层级树,清理富维度页推荐码残留
+- T25 统一成员选择器 — 折叠同用户重复行,消除「本人+本人对应成员」双项
+
+### Bug 修复
+- 任务列表页默认展示本人任务,与首页「我的任务」同口径
+- 双身份确定性解析 + 诊断/合并 SQL 脚本产出(T24-C,只提交不执行)
+- 睡眠打卡完成接口幂等热修 + 打卡页冗余 /complete 移除(T24-A / T24-B)
+
+### 其他
+- (users 表家长账号、无 family_members 行)的本人行 id 为 users.id,不属于
+- family_members 主键空间。任务列表页把它当 memberId 传给 getTodayTasks,后端
+- 按 family_member_id = users.id 过滤,恰好命中同 id 的其他家庭成员任务。
+- 修复(仅 pages/tasks/tasks.vue,后端不动):
+- - resolveSelfMemberId:source='parent' 时 selfMemberId 置 null,改由后端 JWT
+-   currentMemberId 兜底
+- - loadInitialData:默认视图不再预设 selectedMemberId,loadTodayTasks() 不带
+-   memberId,与首页「我的任务」走完全相同的路径
+- - onMemberSelect:任何 isSelf 一律 selectMember(null),「本人」chip 由
+-   self-active="!selectedMemberId" 保持高亮
+- - isOwnTask:改为按当前查看对象判断,查看其他成员且 selfMemberId 不可解析时
+-   视为他人任务,保留「仅能完成自己的」护栏(后端 completeTask 成员不匹配时
+-   仍幂等返回、不改数据不发奖)
+- 
+-   · A1 时间选择器改为原生 multiSelector 双列滚动,选择时即 5 分钟粒度,删除三处提示文案
+-   · A2 audienceScope/audienceType 两列 + 结算按参与者身份分类 + 仅会员硬门禁
+-   · A3 活动费用展示层统一(详情页/列表/海报/报名弹窗/后台)
+-   · G1 L1 文案层家长/孩子中性化
+-   · G2 L2/L3 契约与 DB 列名中性化(依赖 T25 收口后执行)
+- - 同步更新 tools/xaf_agent_hub/tasks_backlog.json:
+-   · updated 切至 2026-10-26
+-   · discipline 写入单一事实源(370 字符)
+-   · 新增 A1/A2/A3/G1/G2 五条任务(pending)
+-   · 保留 T15/T16 等已完成 session_id/done_at 元信息
+- cfclub 基线 164c9fbc5 → 新增提交(2 文件 +500 / -18)
+- 
+- - 需求2:家庭总览持久化表 family_food_overview,值为成员最新指数最小值(替代前端实时平均)
+- - 迁移415 / 9个后端文件 + 2个前端文件 / 验收 AC-01~AC-12
+- 
+-   去掉 :class 内联方法调用,改为预计算 _filterId=memberIdOf
+- - gut-flora-detail / report-detail / report-confirm: 成员选择器与候选列表
+-   预计算 _mid 供 :class 内联比较,loadFamilyMembers 走 normalizeMembers,
+-   selectAndClose/createMember setter 统一 memberIdOf
+- - interaction-log: loadMembers 走 normalizeMembers + findSelfMember/membersExceptSelf,
+-   :key 与 selectedMemberId 改用 canonical memberId/selectorKey
+- - doa-stage-create: members 折叠后按 canonical memberId 比对与提交
+- - report-upload: resolveMemberId 委托 memberIdOf,familyMembers 折叠
+- - energy/index: 家族成员列表折叠防御层
+- - MemberChipPicker: 多选语义不变,仅补折叠防御层(消除同一用户双 chip)
+- - activity-detail: 报名人 memberId 去掉 userId 兜底,与 'c_'+id 前缀口径一致
+- 
+- - diet/records、growth/caution-detail、health/gut-flora-foods-detail:
+-   内联 member-bar 换成 MemberSelector(minimal),主键由 (item.id || item.userId)
+-   改为 canonical memberId;「全部」由合成伪项改为组件的 overview 聚合项
+- - psych-assessment/index、cognitive-hall:
+-   内联 member-tabs 换成 MemberSelector(minimal, embedded),保留
+-   「选择测评对象:」文案;成员列表先经 normalizeMembers 折叠
+- - MemberSelector:showSelf=false 时保留本人行(按昵称展示),
+-   避免该形态下本人被静默丢弃
+- - memberNormalize:新增 resolveMemberId,把 URL/缓存里的历史标识
+-   (users.id、遗留 children.id)归一到 familyMemberId
+- 顺带修正:原先「全量成员」列表用 userId 优先、而选中写入用 id 优先,
+- 两者不一致导致选中项不高亮。
+- 
+- - P0-5:proxy-parse 返回 200 但不建草稿、不返 draftId → 前端「确认入库」恒命中「没有可确认的草稿」,代传主链路完全不可用
+- - P0-1/P0-2:setProxyUploader 不写 proxy_upload_note(UPDATE 语句无该列)、remark 硬编码「募极生物肠道菌群检测报告」
+- - P0-4:proxy-confirm 响应无 aiAnalysis 键(前端解读卡片永不显示)+ AI 解读异常被静默吞掉、主流程仍成功
+- - P1-1:/api/family/member/list 忽略请求体 familyId,teacher 只见自己、admin 跨家庭 403
+- - P1-2:FamilyAccessInterceptor 在有效家庭集合为空时放行 → 未绑定家庭的 teacher 可为任意家庭代传
+- - P2-6:匿名访问走业务 code 500 而非 401(角色校验早于 OSS 写入,刷存储风险已排除)
+- - 补充实锤:跨家庭 subjectId 错绑、admin-list/report-list/report-detail 字段缺失、teacher 历史列表恒空
+- - 测试库写入(health_reports 36/37、health_report_drafts 98/99、users 81317)已全部清理
+- 
+- 渲染成两项(「本人」+「本人所对应的成员」),且各页以 userId 作选择器主键,
+- 与后端 member 级接口口径不一致(food-query 传 users.id 而写入键为 family_members.id)。
+- 改动:
+- - 新增 components/MemberSelector.vue:strip / tabs / minimal 三形态,渲染前
+-   统一规范化,emit canonical memberId(= family_members.id)
+- - 新增 utils/memberNormalize.js:按 user_id 折叠,canonical 优先级
+-   isSelf → active → 数据量多 → id 最小;每用户至多一行、isSelf 唯一
+- - FamilyMemberVO 增 familyMemberId,setter 兜底保证各构造点不漏设
+- - 旧组件 FamilyMemberStrip / DimensionMemberTabs 改为薄包装委托
+- - 8 页迁移:parent-index / child-index / member-home-detail / action-detail
+-   (strip),body-detail / mind-detail / wealth / wisdom-detail(tabs)
+- - food-query:memberId 主键由 userId 改为 canonical memberId,「个人」= isSelf 行
+- - tasks:内联 member-chip 改为 MemberSelector minimal,本人走 canonical memberId
+- 边界:前端折叠仅为防御层,重复行外键数据丢失问题由 T24-C 数据合并根治。
+- 本次不含 DB 迁移,不执行数据变更。
+- 
+- - JwtInterceptor 旧 .last("LIMIT 1") 无排序,currentMemberId 请求间漂移;
+- - FamilyMemberService.listMembers 去重比较器用 .max() + 反向比较器
+-   (active 返回 -1、updated_at 用 b.compareTo(a)),实际选中"非 active /
+-   最早 updated_at"行,与注释意图相反,isSelf 标错行 → 前端呈现两个身份。
+- 代码改动:
+- - JwtInterceptor:177-182:改为确定性 ORDER BY
+-   status='active' → is_admin=1 → id 最小;
+- - FamilyMemberService.listMembers:修复反向比较器,新增 statusRank 静态
+-   助手,选主成员口径与 JwtInterceptor 一致(非 recycled → is_admin → id 最小);
+- - schema.sql:tasks 表补齐 family_member_id 列(与迁移 2134-2141 同步,
+-   修复既有 schema.sql 缺口)。
+- 脚本产出(均【只提交,不执行】,供 DBA 在只读从库演练、受控窗口执行):
+- - 2026-10-25-dual-identity-diagnostic.sql:只读诊断(重复组/家长本人型/
+-   外键分布/疑似悬空),零风险,备份库可直接跑;
+- - 2026-10-25-dual-identity-merge.sql:高危合并迁移
+-   · canonical 规则:ref_total 最多 → status='active' → id 最小;
+-   · 备份表 family_members_bak_20261025 + 映射表 fm_merge_map(回滚依赖);
+-   · 92 个 (表,列) 引用迁移(information_schema 守卫,schema 漂移自动跳过并告警);
+-   · 唯一键冲突预检 + 冲突处理(画像/偏好/徽章/能量/关系边等以 canonical 为准,
+-     cf_balance 专项求和并入 canonical,不丢 CF 值);
+-   · JSON 数组用 JSON_TABLE 重组(不破坏格式),VARCHAR 逗号串按边界 REPLACE;
+-   · tasks.child_id 仅对 executor_type 非 parent 改写(防误改 users.id);
+-   · DELETE 重复行 + UNIQUE(user_id, family_id)(NULL 不违反唯一,可容本地成员);
+-   · 执行后校验 + 逐组/全量回滚说明。
+- - PROJECT-OVERVIEW.md:登记两份新计划文档与实施状态。
+- 验证:mvn compile 通过(exit 0);改动 .vue 均未变(本次无前端改动)。
+- agent 未连接任何生产库、未执行任何 DB 写操作。
+- 
+- {"code":500,"message":"任务不存在、无权完成或状态已变更"},但首页任务卡片已消失。
+- 根因(见 docs/superpowers/plans/2026-10-25-task-complete-500-bug.md):
+- 1. 打卡 create 落库后已按任务归属自动完成(updateCheckinTaskProgress →
+-    awardTaskCompletionRewards,status 真落库为 completed);
+- 2. 前端 create 成功后仍冗余调用一次 /complete,且传操作视角成员 M_front;
+- 3. 双身份(同一 user_id 多条 family_members 行)下 M_front ≠ task.familyMemberId
+-    命中旧 587 行;无双身份时任务已 completed 命中旧 591 行;
+- 4. 两种触发旧代码均 return null → TaskController:139 吐 500。
+- T24-A(后端幂等热修):
+- - TaskService.completeTask:task=null 仍返回 null(任务不存在);
+-   已是 completed / pending_review → 幂等返回成功;
+-   成员不匹配 → 不改数据不发奖,幂等返回成功并打 warn 供排查双身份。
+- - 复用既有 result 结构:pointsEarned=0、newBalance=当前积分、
+-   alreadyCompleted=true;needReview 对 pending_review 保留 true。
+- - 新增私有 helper buildIdempotentCompleteResult。
+- T24-B(前端去冗余 + 饮水后端对齐):
+- - 删除 sleep/exercise/diet/water 四个打卡页的冗余 POST /complete
+-   (含 water-index.vue 重复 url 键)及无用的 completeTaskApi import;
+- - HealthWaterController 与睡眠/运动/饮食对齐:先按任务归属自纠成员,
+-   再按 taskId 调 updateCheckinTaskProgress(首页卡片精确消失);
+-   无 taskId 时 updateProgress 显式传 familyMemberId,避免 LIMIT 1 漂移。
+- 验证:mvn compile 通过;4 个改动 .vue ESM 语法校验通过;
+- audit-mp-antipatterns 0 error;audit-duplicate-api-calls 0 error;
+- cfc-web webpack build 通过(小程序打包按规范仍由 HBuilderX 完成)。
+- 【只提交不执行】双身份诊断/合并 SQL 在后续提交,供 DBA 在只读从库/受控窗口执行。
+- 
+
+### 重构
+- T25 P2 — 报告归属/互动/DOA/能量/上传页统一 memberId 口径 + 折叠同用户重复行
+- T25 P2 — 戒备/饮食记录/测评页内联选择器改用统一组件
+
+
 ## v1.0.1796 (2026-10-25)
 
 ### 文档

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

@@ -1,6 +1,6 @@
 # 更新日志
 
-> 当前版本: v1.0.1796
+> 当前版本: v1.0.1797
 
 ## 历史版本
 
@@ -8,6 +8,169 @@
 
 ---
 
+## v1.0.1797 (2026-10-26)
+
+### 文档
+- 补充品牌话术/商业模式/物料设计资料与 工作文稿(采访稿、文案包、募资方案等)
+- 五维测评客观化系统设计与开发计划(方法矩阵/计分算法/任务分解 P0-P2)
+- 活动创建活动页体验修正 + 人群/费用重构方案(A1/A2/A3/G1/G2)
+- 报告代传功能修复方案(T29,分三批 B1/B2/B3)
+- 食材推荐/查询 报告入口收敛 + 家庭总览持久化最小值 方案(T28)
+- 报告代传功能运行态验证报告(任务 proxy-verify-20261025)
+- 报告代传核查报告 V3(补测试数据清理记录与运行态修正)
+- T24 睡眠打卡500+双身份 bug 设计 / T25 统一成员选择器设计 / 双身份只读诊断SQL
+
+### 新功能
+- GEO 分享优化(about 页注册、分享标题统一、5 页 shareMixin、首页 GEO 摘要、sitemap 与 SEO 文档)
+- T22 方案→任务回流传真(懒回填当次消费+实例透传来源+级联兜底+任务中心标签)
+- 团队页新增我的推荐人、消费额分级统计与层级树,清理富维度页推荐码残留
+- T25 统一成员选择器 — 折叠同用户重复行,消除「本人+本人对应成员」双项
+
+### Bug 修复
+- 任务列表页默认展示本人任务,与首页「我的任务」同口径
+- 双身份确定性解析 + 诊断/合并 SQL 脚本产出(T24-C,只提交不执行)
+- 睡眠打卡完成接口幂等热修 + 打卡页冗余 /complete 移除(T24-A / T24-B)
+
+### 其他
+- (users 表家长账号、无 family_members 行)的本人行 id 为 users.id,不属于
+- family_members 主键空间。任务列表页把它当 memberId 传给 getTodayTasks,后端
+- 按 family_member_id = users.id 过滤,恰好命中同 id 的其他家庭成员任务。
+- 修复(仅 pages/tasks/tasks.vue,后端不动):
+- - resolveSelfMemberId:source='parent' 时 selfMemberId 置 null,改由后端 JWT
+-   currentMemberId 兜底
+- - loadInitialData:默认视图不再预设 selectedMemberId,loadTodayTasks() 不带
+-   memberId,与首页「我的任务」走完全相同的路径
+- - onMemberSelect:任何 isSelf 一律 selectMember(null),「本人」chip 由
+-   self-active="!selectedMemberId" 保持高亮
+- - isOwnTask:改为按当前查看对象判断,查看其他成员且 selfMemberId 不可解析时
+-   视为他人任务,保留「仅能完成自己的」护栏(后端 completeTask 成员不匹配时
+-   仍幂等返回、不改数据不发奖)
+- 
+-   · A1 时间选择器改为原生 multiSelector 双列滚动,选择时即 5 分钟粒度,删除三处提示文案
+-   · A2 audienceScope/audienceType 两列 + 结算按参与者身份分类 + 仅会员硬门禁
+-   · A3 活动费用展示层统一(详情页/列表/海报/报名弹窗/后台)
+-   · G1 L1 文案层家长/孩子中性化
+-   · G2 L2/L3 契约与 DB 列名中性化(依赖 T25 收口后执行)
+- - 同步更新 tools/xaf_agent_hub/tasks_backlog.json:
+-   · updated 切至 2026-10-26
+-   · discipline 写入单一事实源(370 字符)
+-   · 新增 A1/A2/A3/G1/G2 五条任务(pending)
+-   · 保留 T15/T16 等已完成 session_id/done_at 元信息
+- cfclub 基线 164c9fbc5 → 新增提交(2 文件 +500 / -18)
+- 
+- - 需求2:家庭总览持久化表 family_food_overview,值为成员最新指数最小值(替代前端实时平均)
+- - 迁移415 / 9个后端文件 + 2个前端文件 / 验收 AC-01~AC-12
+- 
+-   去掉 :class 内联方法调用,改为预计算 _filterId=memberIdOf
+- - gut-flora-detail / report-detail / report-confirm: 成员选择器与候选列表
+-   预计算 _mid 供 :class 内联比较,loadFamilyMembers 走 normalizeMembers,
+-   selectAndClose/createMember setter 统一 memberIdOf
+- - interaction-log: loadMembers 走 normalizeMembers + findSelfMember/membersExceptSelf,
+-   :key 与 selectedMemberId 改用 canonical memberId/selectorKey
+- - doa-stage-create: members 折叠后按 canonical memberId 比对与提交
+- - report-upload: resolveMemberId 委托 memberIdOf,familyMembers 折叠
+- - energy/index: 家族成员列表折叠防御层
+- - MemberChipPicker: 多选语义不变,仅补折叠防御层(消除同一用户双 chip)
+- - activity-detail: 报名人 memberId 去掉 userId 兜底,与 'c_'+id 前缀口径一致
+- 
+- - diet/records、growth/caution-detail、health/gut-flora-foods-detail:
+-   内联 member-bar 换成 MemberSelector(minimal),主键由 (item.id || item.userId)
+-   改为 canonical memberId;「全部」由合成伪项改为组件的 overview 聚合项
+- - psych-assessment/index、cognitive-hall:
+-   内联 member-tabs 换成 MemberSelector(minimal, embedded),保留
+-   「选择测评对象:」文案;成员列表先经 normalizeMembers 折叠
+- - MemberSelector:showSelf=false 时保留本人行(按昵称展示),
+-   避免该形态下本人被静默丢弃
+- - memberNormalize:新增 resolveMemberId,把 URL/缓存里的历史标识
+-   (users.id、遗留 children.id)归一到 familyMemberId
+- 顺带修正:原先「全量成员」列表用 userId 优先、而选中写入用 id 优先,
+- 两者不一致导致选中项不高亮。
+- 
+- - P0-5:proxy-parse 返回 200 但不建草稿、不返 draftId → 前端「确认入库」恒命中「没有可确认的草稿」,代传主链路完全不可用
+- - P0-1/P0-2:setProxyUploader 不写 proxy_upload_note(UPDATE 语句无该列)、remark 硬编码「募极生物肠道菌群检测报告」
+- - P0-4:proxy-confirm 响应无 aiAnalysis 键(前端解读卡片永不显示)+ AI 解读异常被静默吞掉、主流程仍成功
+- - P1-1:/api/family/member/list 忽略请求体 familyId,teacher 只见自己、admin 跨家庭 403
+- - P1-2:FamilyAccessInterceptor 在有效家庭集合为空时放行 → 未绑定家庭的 teacher 可为任意家庭代传
+- - P2-6:匿名访问走业务 code 500 而非 401(角色校验早于 OSS 写入,刷存储风险已排除)
+- - 补充实锤:跨家庭 subjectId 错绑、admin-list/report-list/report-detail 字段缺失、teacher 历史列表恒空
+- - 测试库写入(health_reports 36/37、health_report_drafts 98/99、users 81317)已全部清理
+- 
+- 渲染成两项(「本人」+「本人所对应的成员」),且各页以 userId 作选择器主键,
+- 与后端 member 级接口口径不一致(food-query 传 users.id 而写入键为 family_members.id)。
+- 改动:
+- - 新增 components/MemberSelector.vue:strip / tabs / minimal 三形态,渲染前
+-   统一规范化,emit canonical memberId(= family_members.id)
+- - 新增 utils/memberNormalize.js:按 user_id 折叠,canonical 优先级
+-   isSelf → active → 数据量多 → id 最小;每用户至多一行、isSelf 唯一
+- - FamilyMemberVO 增 familyMemberId,setter 兜底保证各构造点不漏设
+- - 旧组件 FamilyMemberStrip / DimensionMemberTabs 改为薄包装委托
+- - 8 页迁移:parent-index / child-index / member-home-detail / action-detail
+-   (strip),body-detail / mind-detail / wealth / wisdom-detail(tabs)
+- - food-query:memberId 主键由 userId 改为 canonical memberId,「个人」= isSelf 行
+- - tasks:内联 member-chip 改为 MemberSelector minimal,本人走 canonical memberId
+- 边界:前端折叠仅为防御层,重复行外键数据丢失问题由 T24-C 数据合并根治。
+- 本次不含 DB 迁移,不执行数据变更。
+- 
+- - JwtInterceptor 旧 .last("LIMIT 1") 无排序,currentMemberId 请求间漂移;
+- - FamilyMemberService.listMembers 去重比较器用 .max() + 反向比较器
+-   (active 返回 -1、updated_at 用 b.compareTo(a)),实际选中"非 active /
+-   最早 updated_at"行,与注释意图相反,isSelf 标错行 → 前端呈现两个身份。
+- 代码改动:
+- - JwtInterceptor:177-182:改为确定性 ORDER BY
+-   status='active' → is_admin=1 → id 最小;
+- - FamilyMemberService.listMembers:修复反向比较器,新增 statusRank 静态
+-   助手,选主成员口径与 JwtInterceptor 一致(非 recycled → is_admin → id 最小);
+- - schema.sql:tasks 表补齐 family_member_id 列(与迁移 2134-2141 同步,
+-   修复既有 schema.sql 缺口)。
+- 脚本产出(均【只提交,不执行】,供 DBA 在只读从库演练、受控窗口执行):
+- - 2026-10-25-dual-identity-diagnostic.sql:只读诊断(重复组/家长本人型/
+-   外键分布/疑似悬空),零风险,备份库可直接跑;
+- - 2026-10-25-dual-identity-merge.sql:高危合并迁移
+-   · canonical 规则:ref_total 最多 → status='active' → id 最小;
+-   · 备份表 family_members_bak_20261025 + 映射表 fm_merge_map(回滚依赖);
+-   · 92 个 (表,列) 引用迁移(information_schema 守卫,schema 漂移自动跳过并告警);
+-   · 唯一键冲突预检 + 冲突处理(画像/偏好/徽章/能量/关系边等以 canonical 为准,
+-     cf_balance 专项求和并入 canonical,不丢 CF 值);
+-   · JSON 数组用 JSON_TABLE 重组(不破坏格式),VARCHAR 逗号串按边界 REPLACE;
+-   · tasks.child_id 仅对 executor_type 非 parent 改写(防误改 users.id);
+-   · DELETE 重复行 + UNIQUE(user_id, family_id)(NULL 不违反唯一,可容本地成员);
+-   · 执行后校验 + 逐组/全量回滚说明。
+- - PROJECT-OVERVIEW.md:登记两份新计划文档与实施状态。
+- 验证:mvn compile 通过(exit 0);改动 .vue 均未变(本次无前端改动)。
+- agent 未连接任何生产库、未执行任何 DB 写操作。
+- 
+- {"code":500,"message":"任务不存在、无权完成或状态已变更"},但首页任务卡片已消失。
+- 根因(见 docs/superpowers/plans/2026-10-25-task-complete-500-bug.md):
+- 1. 打卡 create 落库后已按任务归属自动完成(updateCheckinTaskProgress →
+-    awardTaskCompletionRewards,status 真落库为 completed);
+- 2. 前端 create 成功后仍冗余调用一次 /complete,且传操作视角成员 M_front;
+- 3. 双身份(同一 user_id 多条 family_members 行)下 M_front ≠ task.familyMemberId
+-    命中旧 587 行;无双身份时任务已 completed 命中旧 591 行;
+- 4. 两种触发旧代码均 return null → TaskController:139 吐 500。
+- T24-A(后端幂等热修):
+- - TaskService.completeTask:task=null 仍返回 null(任务不存在);
+-   已是 completed / pending_review → 幂等返回成功;
+-   成员不匹配 → 不改数据不发奖,幂等返回成功并打 warn 供排查双身份。
+- - 复用既有 result 结构:pointsEarned=0、newBalance=当前积分、
+-   alreadyCompleted=true;needReview 对 pending_review 保留 true。
+- - 新增私有 helper buildIdempotentCompleteResult。
+- T24-B(前端去冗余 + 饮水后端对齐):
+- - 删除 sleep/exercise/diet/water 四个打卡页的冗余 POST /complete
+-   (含 water-index.vue 重复 url 键)及无用的 completeTaskApi import;
+- - HealthWaterController 与睡眠/运动/饮食对齐:先按任务归属自纠成员,
+-   再按 taskId 调 updateCheckinTaskProgress(首页卡片精确消失);
+-   无 taskId 时 updateProgress 显式传 familyMemberId,避免 LIMIT 1 漂移。
+- 验证:mvn compile 通过;4 个改动 .vue ESM 语法校验通过;
+- audit-mp-antipatterns 0 error;audit-duplicate-api-calls 0 error;
+- cfc-web webpack build 通过(小程序打包按规范仍由 HBuilderX 完成)。
+- 【只提交不执行】双身份诊断/合并 SQL 在后续提交,供 DBA 在只读从库/受控窗口执行。
+- 
+
+### 重构
+- T25 P2 — 报告归属/互动/DOA/能量/上传页统一 memberId 口径 + 折叠同用户重复行
+- T25 P2 — 戒备/饮食记录/测评页内联选择器改用统一组件
+
+
 ## v1.0.1796 (2026-10-25)
 
 ### 文档