[ { "id": "T15", "title": "规划师培训认证前端:认证中心/课程/题库管理端 + 小程序培训中心页", "priority": "P0", "module": "fullstack", "instance": "", "status": "done", "spec": "docs/superpowers/specs/2026-10-22-planner-learning-assessment-gate-design.md", "prompt": "规格文档 2026-10-22-planner-learning-assessment-gate-design.md 后端已全量落地(迁移394-401 九表 + PlannerCertificationService 认证状态机 + PlannerCertificationGuard 中央闸门 + 规划师端7接口 + 管理端26接口),但前端缺失,本任务补齐:①小程序规划师端「培训认证」中心页:展示类别(planner/nutritionist/assessor)认证状态、课程列表与学习进度(planner_courses/planner_course_progress)、考试入口(planner_exam_attempts)、线下课打卡(activity_checkins);②cfc-web 管理端三页:认证看板(审批/状态流转,对接管理端26接口)、课程管理(CRUD + 关联类别)、题库管理(题目/试卷维护);③引导计划:认证通过后 Guide.status=active 的联动说明与失败态提示。落点:cfc-frontend/pages/guide/ 新增 training 相关页面并注册 pages.json;cfc-web/src/views/ 新增 admin 认证管理页 + 路由 + perm 配置;utils/api.js 与 cfc-web/src/api/ 增加对应封装。验收要点:后端已存在的 7+26 接口全部被前端调用;认证状态机 init/learning→exam_passed→certified 在小程序可视可操作;管理端可完成课程/题库维护与认证审批;mvn clean compile 与两前端 node --check/build 通过;不触碰后端 Java 代码(除非发现接口缺口,需先回来汇报)。", "session_id": "ses_e9183f23cffe6q3vnmLOWy9lyq", "dispatched_at": "2026-10-24 23:16:26", "dispatched_to": "lan-248", "model": "axonhub/deepseek", "done_at": "2026-10-25 00:51:52" }, { "id": "T16", "title": "后台多渠道发货对话框:按 deliveryType 切换快递/同城/自提/虚拟商品", "priority": "P1", "module": "fullstack", "instance": "", "status": "done", "spec": "docs/superpowers/specs/2026-10-22-fulfillment-multi-mode-design.md", "prompt": "规格 2026-10-22-fulfillment-multi-mode-design.md:管理端发货要对齐微信小程序后台四种方式——快递 logistics_type=1 / 同城配送 2(ProductOrder.deliveryMethod 的注释已含 6=同城配送)/ 用户自提 4(不再跳过微信同步)/ 虚拟商品 3(支付成功自动发货 autoShipVirtualOrder 幂等 fail-open)。现后端已具备 ship(orderNo, shipType, ...) 与 WechatService.uploadShippingInfo 按 logisticsType 1/2/3/4 分流;缺口在 cfc-web 发货对话框仍是旧的仅快递/自提二态(OrderManage.vue / OrderDetail.vue 中 deliveryMethod==2 才显示自提)。本任务:①OrderManage.vue 发货对话框按订单 deliveryMethod 切换表单字段(快递=物流公司+单号;同城配送=配送公司+运单;自提=仅确认提示,仍同步微信 logisticsType=4;虚拟商品=展示自动发货状态,按钮置灰并说明);②OrderDetail.vue 配送方式展示扩展为 1/2/3/4/5/6 全编码可读文案与图标;③确认发货后子订单明细同样是微信对照 logisticsType 传参。落点:cfc-web/src/views/admin/OrderManage.vue、OrderDetail.vue,必要时改 src/api/。验收要点:四类订单发货表单正确切换且微信同步参数类型正确(同城走 logistics_type=2 需单号公司、自提=4 无单号、虚拟=3 自动发货不弹表单);deliveryMethod=6 的订单显示「同城配送」而非「快递」;vue-cli-service build SUCCESS;微信 upload_shipping_info URL 带 /wxa 前缀;不改后端接口签名。", "session_id": "ses_e9183e8f9ffeXVXv6Wiv5TFKhk", "dispatched_at": "2026-10-24 23:16:28", "dispatched_to": "lan-248", "model": "axonhub/deepseek", "done_at": "2026-10-24 23:58:46" }, { "id": "T17", "title": "报告快速分析:Redis 每日频控(免费1次/日)+ 付费多轮 + 配额联动", "priority": "P1", "module": "backend", "instance": "", "status": "done", "spec": "docs/superpowers/specs/2026-09-10-report-quick-analyze-design.md", "prompt": "规格 2026-09-10-report-quick-analyze-design.md 与扩展版 2026-09-13-report-quick-analyze-extend-design.md:报告详情页快速分析需免费版每日 1 次 Redis 计数、付费版多轮,复用 chat_graph + AiGateway/langgraph,LangGraph 零改动。现状:后端已有 POST /api/chat/report/analyze(AIChatController#report/analyze,与 /chat/send 共用 buildChatInputs),前端 report-detail.vue 已接入报告反馈入口,但「每日限次」与「付费多轮」尚未落地(代码检索未发现 reportAnalyzeLimit/多轮配额逻辑)。本任务:①引入 Redis 依赖与配置(application.yml 已有 redis 配置则复用),新增 ReportAnalyzeQuotaService:免费用户每日 1 次(key=report:analyze:{userId}:{yyyyMMdd},INCR+EXPIRE),会员按 membership levels features/maxDailyAnalyze 配置次数;②超限返回 Result 明确 message(区分「今日已用完/请升级会员」);③前端 report-detail.vue 消费限次结果:展示剩余次数、超限弹窗带升级入口(跳 membership 页);④付费多轮在同一订单/会话内计数,不可重复刷。落点:cfc-backend/src/main/java/com/etotem/cfc/service/ 新增 QuotaService + AIChatController 限流接线;cfc-frontend/pages/health/report-detail.vue 适配。验收要点:免费用户第 2 次调用被拒且 Redis key 到期后恢复;会员次数准确;mvn clean compile 通过;新增 2-3 个纯 Mockito 单测(不依赖真实 Redis,可用模拟);API_REFERENCE 4.x 同步限次语义。", "session_id": "ses_e9183dc8fffecmHzAeN1UWqMuu", "dispatched_at": "2026-10-24 23:16:32", "dispatched_to": "pub-iwintrue", "model": "etotem/deepseek", "done_at": "2026-10-25 00:21:24" }, { "id": "T18", "title": "五维自检深度 AI 集成(P1-1 历史趋势解读 + P1-2 Chat 上下文注入)", "priority": "P1", "module": "fullstack", "instance": "", "status": "done", "spec": "docs/superpowers/specs/2026-08-31-self-check-ai-integration-design.md", "prompt": "规格 2026-08-31-self-check-ai-integration-design.md:P0-1 纯AI替换静态建议与 P0-2 用户点击生成健康计划已在 self-check-result.vue 落地(有 AI 解读区块、生成健康计划按钮、self-check-ai.vue AI出题页),P1-1 历史趋势AI解读与 P1-2 Chat 上下文注入未实现。本任务:①P1-1:自检结果页新增「历史趋势」区块,调后端聚合该成员历次自检得分(FiveDimensionSelfCheck 表按维度)→ 组装上下文 → 走 AiGateway/langgraph chat_graph 生成趋势解读(上升/下降/波动 + 建议),展示折线趋势与 AI 解读文字;②P1-2:AIChatController 或统一上下文中注入最近一次自检摘要(维度分 + 低分项),使 /chat/send 能针对自检结果连续对话;③后端零 LangGraph 改动,仅 Java 侧组装 prompt 上下文(遵循 AiGateway 熔断/超时/Fallback 规范)。落点:cfc-backend/src/main/java/com/etotem/cfc/service/ 新增 SelfCheckTrendService(或扩展 FiveDimensionSelfCheckService)+ AIChatController 上下文注入;cfc-frontend/pages/family/self-check-result.vue 新增趋势区块。验收要点:3 次以上自检记录可出趋势解读;无记录时优雅降级(隐藏区块或引导);Chat 提问「我上次自检哪项最低」能答对;mvn clean compile + node --check 通过;新增单测覆盖上下文拼装与历史聚合。", "session_id": "ses_e9183d076ffegxj0N2urb9YYoQ", "dispatched_at": "2026-10-24 23:16:34", "dispatched_to": "pub-iwintrue", "model": "etotem/deepseek", "done_at": "2026-10-25 04:29:24" }, { "id": "T19-A", "title": "营养商品标注·A线:Product 营养成分(热量/蛋白质/脂肪/碳水/膳食纤维)+ 管理端录入 + 小程序展示", "priority": "P2", "module": "fullstack", "instance": "pub-iwintrue", "status": "done", "spec": "docs/superpowers/specs/2026-10-27-nutrition-product-tagging-prd.md", "prompt": "A 线(营养成分)。已派发。两条硬约束已写进指令:① 迁移必须写进 DatabaseInitializer.runMigrations()(application.yml 无 schema 自动初始化,只改 schema.sql 线上不建列);② 必须扩展 ProductService.syncFromProduct()(调用点 316/355/592),否则营养侧永远拿不到数据。营养基准加 nutrition_basis 列(默认 per_100g,预留每份)。留空存 NULL 不是 0。无数据整块隐藏。禁止治疗/保健功能宣称。 | 原判定=从未开工,2026-10-27 派发。", "session_id": "ses_e91745133ffebXvnPFXhnF7SBM", "dispatched_at": "2026-10-24 23:33:31", "dispatched_to": "pub-iwintrue", "model": "axonhub/deepseek", "done_at": "2026-10-26 12:45", "note": "已 push origin/feature/nutrition-product-tagging = 328443d43(feat(shop) 迁移417+后台录入+小程序展示)。2026-10-27 复核分支存在,标记 done。原 instance 字段混写会话ID,已拆分。" }, { "id": "T20", "title": "食材营养均衡分析链路落地(diet-ingredient-balance)", "priority": "P2", "module": "fullstack", "instance": "", "status": "done", "spec": "docs/superpowers/specs/2026-09-13-diet-ingredient-balance-design.md", "prompt": "规格 2026-09-13-diet-ingredient-balance-design.md 设计的是饮食均衡分析(按食材类别/营养素覆盖评估家庭成员食谱缺口),目前代码检索未发现对应实现(无 ingredientBalance 相关后端类与前端页面)。本任务按规格落地最小可用的 P0 范围:①后端新增 DietBalanceService:入参家庭成员的饮食偏好/忌口/近期打卡(diet_checkin / diet_preferences),输出五类食材(谷薯/蔬果/肉蛋奶/豆坚果/油盐)覆盖度与缺口建议(缺口建议可调用 AiGateway/langgraph 生成自然语言,失败降级为模板文案);暴露 POST /api/diet/balance 接口(Result 包装 + JWT 鉴权);②小程序新增或复用 diet 页展示均衡结果(雷达/环形 canvas 或纯文本卡片均可),入口放在 dial 打卡页或 diet-index;③涉及新表则优先 DB 迁移幂等,尽量复用现有表。落点:cfc-backend/src/main/java/com/etotem/cfc/service/DietBalanceService.java + controller/diet/DietBalanceController.java + 迁移(如需要);cfc-frontend/pages/diet/ 新增 balance 区块。验收要点:mvn clean compile 通过;接口可按成员返回均衡评分与缺口清单;无打卡数据时给出可用默认分析或友好空态;新增 2 个纯 Mockito 单测;API_REFERENCE 同步新增接口(4.x 递增)。", "session_id": "ses_e91742972ffeTwqN5eAge61gQp", "dispatched_at": "2026-10-24 23:33:40", "dispatched_to": "lan-204", "model": "axonhub/deepseek", "done_at": "2026-10-25 00:21:24" }, { "id": "T21", "title": "团队层级树形可视化完善 + 富页面推荐码清理", "priority": "P2", "module": "frontend", "instance": "", "status": "done", "spec": "docs/superpowers/specs/2026-09-09-team-hierarchy-design.md", "prompt": "规格 2026-09-09-team-hierarchy-design.md:团队层级树从下往上生长 + 团队消费额分级统计 + 直推成员消费/CF明细 + 我的推荐人展示 + 去掉富页面推荐码。现状:promotion/team.vue 已有团队统计卡(团队规模/返佣比例/档位)、L1/L2 Tab、成员列表、成长曲线与消费曲线(canvas),后端 CommissionController 已提供 team/team/list/team/consumption/my-referrer/team/tree/team/growth-curve/team/all-members-consumption-curve 等接口;「我的推荐人展示」与「树形生长图」「富页面推荐码移除」未确认落地。本任务:①team.vue 增加「我的推荐人」区块(调 /my-referrer,无推荐人时展示邀请入口);②在现有列表/曲线基础上叠加层级树形视图(用后端 /team/tree 扁平数据递归渲染成员树,方向自下而上为符合规格,如 canvas 成本高可先以嵌套列表+缩进呈现,注明偏离);③检索并移除富(profile)页面的推荐码展示(规格明确要求去掉),并核对 promotion 页不受影响;④消费分级统计(按档位聚合)若接口已存在则前端展示。落点:cfc-frontend/pages/promotion/team.vue、profile 相关页面;必要时补 utils/api.js 封装(后端接口已存在则零后端改动)。验收要点:node --check 通过;我的推荐人/无推荐人引导正确;树形视图数据与 /team/tree 响应一致;富页面不再出现推荐码;不影响现有 L1/L2 列表与曲线。", "session_id": "ses_e9163b087ffefjmH21pIB4bieD", "dispatched_at": "2026-10-24 23:51:40", "dispatched_to": "local-45278", "model": "axonhub/deepseek", "done_at": "2026-10-25 10:02:27" }, { "id": "T22", "title": "方案→任务全链路回流传真(plan_json.sections[].tasks 驱动任务中心,含删除/降级兜底验收)", "priority": "P2", "module": "fullstack", "instance": "", "status": "done", "spec": "docs/superpowers/plans/2026-09-04-plan-to-task-unification.md", "prompt": "实现计划 2026-09-04-plan-to-task-unification.md 与本仓库 AGENTS.md 所述:plan_json.sections[].tasks 是唯一事实源,配套 plan-standard-content(2026-08-28)已有 LangGraph 输出 tasks + 正则兜底 + 存量懒加载回填 + 规划师端结构化编辑 UI。任务要求对「方案→任务」全链路做一次端到端确认与收尾:①确认 approveAndPublish 后 HealthPlan 的 plan_json.sections[].tasks 是否正确生成 tasks 实例(source_type=plan,关联 taskId),缺失时是否有懒加载回填兜底;②确认方案删除(2026-10-17 已实施)与每日实例二次删除对 plan 任务同样生效;③确认小程序任务中心 tasks.vue 对 plan 来源任务的展示(来源标签/跳转方案页/完成回写);④管理端/schema:确认无孤儿任务(方案删任务留)与重复生成(重复发布同方案不应重复插任务,应幂等);⑤如发现缺口,修复修复,不做范围外重构。落点:cfc-backend TaskPlanService/GrowthTaskService/HealthPlanService 相关链路 + cfc-frontend/pages/tasks/tasks.vue。验收要点:发布含 tasks 的方案后任务中心可见 plan 任务且不重复;删除方案后其 tasks 级联删除(含每日实例);对存量无 plan_json.tasks 的方案懒加载回填生效;mvn clean compile 通过;补 2-3 个单测覆盖幂等与级联。", "session_id": "ses_e9163add7ffe5EmrvRRcAB3Adv", "dispatched_at": "2026-10-24 23:51:41", "dispatched_to": "local-45278", "model": "axonhub/deepseek", "done_at": "2026-10-25 02:23:36" }, { "id": "F-8", "title": "F-8 清理", "priority": "P2", "module": "backend", "instance": "", "status": "done", "spec": "docs/superpowers/plans/2026-10-24-cf-value-unification-plan.md", "prompt": "实现「F-8 清理」。完整规格见仓库内设计文档 docs/superpowers/plans/2026-10-24-cf-value-unification-plan.md(请先读取该文档,定位到「F-8 清理」对应的批次/章节,按其口径实现)。\n\n纪律:\n- git fetch origin cfclub → 基于 origin/cfclub 新建 feature/ 分支(不要合并主干);\n- 只 git add 自己新增/修改的文件;\n- 先 mvn -pl cfc-backend -am compile 通过,再 cfc-web npm run build/lint 通过;\n- 不新增 DB 迁移,除非文档明确要求;\n- 完成后 git push -u origin feature/,回报 commit 哈希、改动文件清单、编译/构建结果;\n- 不要自行合并 cfclub;\n- 若指定规格文档在 checkout 中不存在,请停止并在回复中说明,不要凭空实现。", "generated_from": "sync_design_tasks", "generated_at": "2026-10-25 13:17:06", "session_id": "ses_e8e7c1499ffe868UgJouwwo1jj", "dispatched_at": "2026-10-25 13:23:53", "dispatched_to": "local-45278", "model": "axonhub/deepseek", "done_at": "2026-10-25 15:59:37" }, { "id": "AL-1", "title": "后台素材库(asset-library) 恢复续做(上一会话卡死已中断重派)", "priority": "P1", "module": "fullstack", "instance": "", "status": "done", "spec": "docs/superpowers/plans/2026-10-26-asset-library-design.md", "prompt": "规格见 docs/superpowers/plans/2026-10-26-asset-library-design.md;派发指令为 self-contained 内联版(已含 data-layer/后端接口/前端改造/纪律)。上一会话 ses_e8e8cdf6cffeeGoW3oCpGCaTg6 于 lan-248 卡死(24h+无活动、cost=0、未 push)已中断,本会话接手同 worktree /sc-data/cfc/.worktrees/asset-library 续做并 commit+push feature/asset-library。", "generated_from": "manual-recovery", "recovered_from": "ses_e8e8cdf6cffeeGoW3oCpGCaTg6", "session_id": "ses_e8e680a53ffejn9lEv1p5BvFbp", "dispatched_at": "2026-10-25 13:46:24", "dispatched_to": "lan-248", "model": "axonhub/deepseek", "done_at": "2026-10-25 14:47:13" }, { "id": "T23", "title": "后台报告处理链路追踪 / 归因功能(report-trace)", "priority": "P1", "module": "fullstack", "instance": "会话已结束未回填,但分支有实质产出", "status": "done", "spec": "docs/superpowers/plans/2026-10-26-report-trace-design.md", "prompt": "实现后台「报告处理链路追踪 / 归因」功能。完整规格见仓库内设计文档 docs/superpowers/plans/2026-10-26-report-trace-design.md(请先读取该文档,按其 §四~§五 口径实现)。\n\n背景与根因(已源码确认):用户上传报告后小程序查不到、也无法对应到成员。根因有二——①链路 A(POST /api/report-parser/upload)建 HealthReportDraft 时 familyId=null、memberId=null,导致 ReportCollectService.insertReport 中 matchFamilyMemberByName(name, familyId) 因 familyId=null 恒返 null,健康报告落入 health_reports 时 family_id=null 且 subject_id=null,成为家庭成员维度不可见的孤儿报告;②现有后台 ReportParseAdminController 只查 health_report_drafts,看不到 DAN 上传(dan_report_uploads/dan_assessment_results)与未知上传(report_unknown_upload)的处理状态。\n\n范围(严格按文档):①后端新增 ReportTraceService + ReportTraceAdminController(/api/admin/report-trace 下 list/detail/retry/bind-member/unknown-list/stats 六接口),四表(health_report_drafts / health_reports / dan_report_uploads(+dan_assessment_results) / report_unknown_upload(+report_unknown_cluster))联查归一化为 TraceNode,展示解析服务(parseMethod/langgraph/opencode/dan_java/unknown_llm)、解析状态、是否已归因+原因、落地报告ID、解析数据摘要(指标数/菌群数/疾病风险数/综合分/items数);②健康报告孤儿(subject_id=null 或 family_id=null)可在后台手动归因:bind-member 调 HealthReportService.bindReportToMember + 回填 familyId + 刷新五维/食材推荐(复用 reassignReport 逻辑);③DAN/未知 重试路由:DAN→DanReportUploadService.reparseUpload,未知→重识别后入链;④前端 cfc-web/src/views/admin/ReportTrace.vue(筛选+表格+详情抽屉+重试/归因按钮),新增独立菜单项「报告链路追踪」,不动既有 report-parse 页。\n\n纪律:\n- git fetch origin cfclub → 基于 origin/cfclub 新建 feature/report-trace 分支(不要合并主干);\n- 只 git add 自己新增/修改的文件;不改动 ReportCollectService / DanReportUploadService / ReportParseAdminController 的公开行为(仅调用);\n- 先 mvn -pl cfc-backend -am compile 通过,再 cfc-web npm run build/lint 通过;\n- 不新增 DB 迁移(仅读现有表);\n- 完成后 git push -u origin feature/report-trace,回报 commit 哈希、改动文件清单、编译/构建结果;\n- 不要自行合并 cfclub;\n- 若指定规格文档在 checkout 中不存在,请停止并在回复中说明,不要凭空实现。\n- 关键源码落点(已核对):ReportCollectService.java:668-737(insertReport/matchFamilyMemberByName 调用)、HealthReportDraftService.java、HealthReportService.java:686(matchFamilyMemberByName)/1282(bindReportToMember)/1304(reassignReport)、DanReportUploadService.java:85(uploadAndParse)/296(reparseUpload)/184(confirmUpload)、ReportParseAdminController.java:43(list)、entity HealthReportDraft/HealthReport/DanReportUpload/ReportUnknownUpload/ReportUnknownCluster/ReportTypeRegistry。 | 判定=实质完成:分支 feature/report-trace @ eeea6c5d3,7 文件 +2412 行:ReportTraceService 1386 行 + ReportTraceAdminController 149 + cfc-web ReportTrace.vue 801(统计卡/7天趋势/筛选/表格/详情抽屉/归因弹窗/未知聚类)+ 路由 + API_REFERENCE 登记 6 个新接口。含重试路由(健康草稿异步重跑/DAN reparseUpload/未知指纹重识别重新入链)。未经独立核验。 | 独立核验已完成(2026-10-27): OK 6接口权限校验完备; OK 主链路不变(只读辅助层); OK 无N+1(批量查询); OK API文档一致; WARN 中风险: retryBySource 同步调用LLM无防重入/限流, 管理员频繁点击重试会并发触发, 可能打爆 LangGraph(9000), 合入主线前需加限流(synchronized 或令牌桶); WARN 前端构建/lint 未验证. 核验方违规在 feature/report-trace 多推了1个空commit 5bf862664(--allow-empty), 已核实未混入他人文件.", "generated_from": "manual", "generated_at": "2026-10-26", "session_id": "ses_e8e651be9ffe1nrAL6aVGk07bi", "dispatched_at": "2026-10-25 13:48:59", "dispatched_to": "local-45278", "model": "axonhub/deepseek" }, { "id": "T24", "title": "生产 bug:睡眠打卡 /complete 返回 500 + 双身份任务列表不同", "priority": "P0", "module": "fullstack", "instance": "", "status": "done", "spec": "docs/superpowers/plans/2026-10-25-task-complete-500-bug.md", "prompt": "修复生产环境(cfc.etotem.com.cn)两个关联 bug。完整诊断与证据链见 docs/superpowers/plans/2026-10-25-task-complete-500-bug.md,请先读取。根因一句话:睡眠打卡是每日进度型任务,POST /api/health/sleep/create 落库后由 HealthSleepController.create:76-86 以任务归属为准修正成员并调 TaskService.updateCheckinTaskProgress 自动置 completed(awardTaskCompletionRewards:918-921 真落库),但前端 cfc-frontend/pages/growth/sleep-checkin.vue:448-452 又冗余调 POST /api/tasks/{id}/complete(传 self.memberId);叠加双身份(family_members 同 user_id 存在多条「家长本人」重复记录,见 EnergyService:121/263;JwtInterceptor:177-182 用 LIMIT 1 非确定性解析),导致 /complete 命中 TaskService.completeTask:587(task.familyMemberId≠memberId)或 :591(已 completed)返回 null → TaskController:139 吐 500。\n\n分三块(按风险排序,逐一验收):\nA【后端热修·低危·必做】TaskService.completeTask(585-593) 对「本人已完成任务」幂等返回成功(复用既有 result 结构 pointsEarned=0/newBalance=当前积分/needReview=false/alreadyCompleted=true),不再返回 null→500;覆盖 587 与 591 两种触发。\nB【前端正本清源·低危·必做】删除 sleep-checkin.vue:448-452 冗余 /complete 调用(create 已自动完成);并全量排查 daily-checkin/diet-checkin/exercise-checkin/wealth-sub/checkin/emotion-checkin/body-detail/checkin 等打卡页是否存在「create 自动完成 + 再调 /complete」的同类冗余,一律移除或改为幂等。\nC【数据根治·双身份·中高危·需授权】先在备份/从库只读跑诊断 SQL(文档 §三 给出)确认受影响 (user_id, family_id) 重复行范围;再制定合并迁移方案(保留一条主成员、外键 tasks/task_executions/health_*/points_log 迁到保留行、删重复行、加 UNIQUE(user_id, family_id) 允许 user_id IS NULL 的 local 成员);JwtInterceptor:177-182 的 LIMIT 1 改为确定性取值(优先 status=active 且 userId 匹配的『主成员』);成员切换器(FamilyMemberVO.isSelf)对本人去重。\n\n纪律:git fetch origin cfclub → 基于 origin/cfclub 新建 feature/task-complete-500 分支(不要合并主干);只 git add 自己新增/修改的文件;先 mvn -pl cfc-backend -am compile 通过,再 cfc-web 与 cfc-frontend 各自 npm run build/lint 通过;A 不新增 DB 迁移,C 的迁移须在文档明确且经授权;任务完成后 git push -u origin feature/task-complete-500,回报 commit 哈希、改动文件清单、编译/构建结果;不要自行合并 cfclub;prod 部署(prod-etotem)属 manual_only,未经主理人显式授权不得 push 到 prod 分支或触发生产发布——本任务只完成代码与(若授权)迁移,生产发布单独拍板。", "generated_from": "manual", "generated_at": "2026-10-25", "session_id": "ses_e8e2fac76ffeHxTIZMUs8B1SN7", "dispatched_at": "2026-10-25 14:47:21", "dispatched_to": "lan-248", "model": "axonhub/deepseek", "done_at": "2026-10-25 17:01:01" }, { "id": "T25", "title": "统一成员选择器组件(去重双身份,覆盖所有成员选择页)", "priority": "P1", "module": "frontend", "instance": "", "status": "done", "spec": "docs/superpowers/plans/2026-10-25-unified-member-selector.md", "prompt": "实现「统一成员选择器」组件,消除所有页面把同一用户显示成「本人 + 本人所对应的成员」两项的问题。完整设计见 docs/superpowers/plans/2026-10-25-unified-member-selector.md,先读。\n\n核心约束(务必先读 §一.3):纯前端去重会丢数据——两条重复 family_members 行各自挂着不同任务外键,隐藏一行会导致该行业务数据不可达。因此本任务必须与 T24-C 数据合并(合并重复行 + 外键迁移 + UNIQUE(user_id,family_id))配套;在本任务中组件层只做防御性去重,真正消除重复靠数据层。\n\n范围(严格按文档):\n①新增 cfc-frontend/utils/memberNormalize.js:入参(原始成员数组, viewer)→ 折叠同 user_id 多行为一条,canonical memberId 取 isSelf→active→外键最多→id 最小;保证每用户至多一条且 isSelf 唯一;统一身份键为 familyMemberId(id),userId 仅作折叠依据。\n②新增 cfc-frontend/components/MemberSelector.vue,variant 支持 strip(替代 FamilyMemberStrip)/tabs(替代 DimensionMemberTabs)/minimal(替代 food-query 等内联 member-bar,含家庭总览/个人/各成员);内部先 memberNormalize 再渲染;emit select 带 canonical memberId。\n③P1(用户可见 bug 页,必做):food-query.vue 迁 userId→memberId 主键并改用 MemberSelector;tasks.vue 改用 MemberSelector;用 MemberSelector 替代 FamilyMemberStrip(parent-index/child-index/member-home-detail/action-detail) 与 DimensionMemberTabs(body-detail/wisdom-detail/wealth/index/mind-detail),完整保留 FamilyMemberStrip 长按操作菜单(移除/切换/编辑)逻辑。\n④P2(其余内联选择器,文档 §四清单)逐页替换为 MemberSelector,消除 userId 作主键写法。\n⑤后端配合:/api/food/recommendation/members 等返回 familyMemberId 字段;若未合并数据,列表接口应先按 user_id 折叠下发(同 user 多行→一行 canonical id),避免重复。\n\n纪律:git fetch origin cfclub → 基于 origin/cfclub 新建 feature/unified-member-selector 分支(不合并主干);只 git add 自己新增/修改文件;先 mvn -pl cfc-backend -am compile 通过,再 cfc-frontend node --check / npm run build 通过;不新增 DB 迁移(数据合并在 T24-C);完成后 git push -u origin feature/unified-member-selector,回报 commit 哈希、改动文件清单、编译/构建结果;不要自行合并 cfclub。prod 发布属 manual_only,未经授权不得 push prod 分支。", "generated_from": "manual", "generated_at": "2026-10-25", "session_id": "ses_e8e14dfa7ffeXQdvfhbTOXHCOb", "dispatched_at": "2026-10-25 15:16:36", "dispatched_to": "lan-248", "model": "axonhub/deepseek", "done_at": "2026-10-25 20:16:33" }, { "id": "A1", "title": "活动时间选择器:选择时即只显示 5 分钟粒度,删除「以 5 分钟为一个单元」提示文案", "priority": "P1", "module": "frontend", "instance": "", "status": "done", "spec": "docs/superpowers/plans/2026-10-26-activity-create-page-ux-and-audience-design.md", "prompt": "改造小程序「创建活动」页的时间选择器,让 5 分钟粒度在【选择过程中】生效,而不是选中后才被改写。完整设计与代码证据见 docs/superpowers/plans/2026-10-26-activity-create-page-ux-and-audience-design.md 的 §一 与 §零 0.1,请先读。\n\n背景(一句话):现在 3 处时间字段都用微信原生 ,原生时间选择器不支持步长,只能按 60 分钟逐项滚动,选中后再由 onStartTimeChange/onEndTimeChange/onRegTimeChange 调 normalizeTimeTo5Min 把分钟向下取整到 5 的倍数(14:07→14:05);为此页面上还重复写了 3 句提示「以 5 分钟为一个单元(如 14:00、14:05)」(create.vue:27/39/51,另有 CSS 注释 create.vue:677)。用户明确不想要这句话,也不想要「选了 07 分却变 05 分」。\n\n范围(唯一文件 cfc-frontend/pages/activity/create.vue,只做这一件事):\n①把 3 处 (行 24/36/48)改为原生 ,时列 ['00'..'23'] 共 24 项,分列严格只有 ['00','05','10','15','20','25','30','35','40','45','50','55'] 共 12 项,让用户在选择过程中就无法选中非 5 倍数分钟。\n②data 新增 hourOptions/minuteOptions 与 3 组时间各自的时/分索引(hourIdx/minuteIdx、endHourIdx/endMinuteIdx、regHourIdx/regMinuteIdx);新增 onStartTimeColChange/onEndTimeColChange/onRegTimeColChange(e) 取 e.detail.value(列索引数组)拼成 HH:MM 写入 timePart/endTimePart/regTimePart,再调用既有 syncStartTime/syncEndTime/syncRegDeadline。\n③日期逻辑完全不动:onStartDateChange/onEndDateChange/onRegDateChange → syncXxx 保持现状;提交串必须仍为 YYYY-MM-DDTHH:mm:00、秒恒 00。\n④删除 3 处 …(行 27/39/51);并删除行 677 那条「活动时间以 5 分钟为一个单元」的 CSS 注释。\n⑤索引与字符串必须双向同步:fmtTime 回填(create.vue:593-599)与 loadDetail 三处回填(create.vue:300-324)在 normalizeTimeTo5Min 之后要按 mi/5 反算分钟索引,否则 picker 会显示默认值 00:00。建议抽一个 applyTimeParts(timePart, hourIdxRef, minuteIdxRef) 供初始化与回填共用。\n⑥normalizeTimeTo5Min 必须保留作为兜底(历史脏数据、后台或接口写入非 5 倍数时仍能收敛),不要删。\n\n明确不做(超出范围,做了一定要停手汇报):不做结束时间≥开始时间、报名截止时间≤开始时间等业务校验(现状本来就没有);不动后台 cfc-web/src/views/admin/ActivityEdit.vue 的 element-ui datetime 面板(element-ui 2.x 不支持分钟步长,维持现状 @change 收敛);不动任何费用字段、不做适用人群(那是 A2/A3)。\n\n验收:①分列恰好 12 项且选择过程中无法选中非 5 倍数分钟;②grep \"以 5 分钟为一个单元\" cfc-frontend/pages/activity/create.vue 零命中(含 CSS 注释);③normalizeTimeTo5Min 1440 分钟全量扫描仍全部正确(可把