cfc-redesign-progressive-unlock.md 18 KB

浠艾福小程序改版:需求驱动 · 逐步解锁

阶段:实施计划 v1.0 | 分支:cfclub | 产品决策已确认(2026-08-13)

一、背景与目标

现状:小程序首页对所有用户一视同仁地堆内容(商品/活动/文章/任务),未区分用户需求深度,转化链路不清晰。

改版核心:从用户需求出发,先识别用户类型,按需求深度逐步解锁内容与功能,无关内容不展示。

三类用户:

  • A类 目标明确型:已接受平台理念,直接买 DAN测评 / 菌群检测 → 上传报告 → 出方案 → 生成任务 → 执行(方案任务需会员)
  • B类 观望型:登录看看 → 轻问卷 → 按答案开放相关科普内容
  • C类 问题导向型:带具体问题来(减肥/睡眠/便秘)→ 服务流程介绍 → 专项调研 → 匹配推荐套餐 → 购买 → 试剂盒寄送/样本寄回 → 报告完成系统通知 → 方案确认 → 任务分解执行 → 全部完成奖励 CF 值

已确认决策:

  1. 入口呈现:首次登录强制选择;已登录但从未选过的用户,下次进入也要弹出选择
  2. 问题域首版:减肥 / 睡眠 / 便秘 三个
  3. 会员任务边界:仅"方案生成"的任务需会员;未缴费用户可以自己创建任务自己完成(免费)
  4. 完成回馈奖励:主要奖励 CF 值(复用 PlatformPointsService)
  5. 实施优先级:C类优先 → A类会员任务解锁 → B类问卷引流

二、现状摸底结论(已核实)

模块 现状 结论
首页分流 pages/index-home/index.vue 内嵌登录/游客两态,游客看商品+活动+文章,登录看沙盘+动态+会员入口+快捷功能+任务+挑战+推荐 需重构为"旅程状态驱动"
测评链路 DanAssessmentController: order/create→pay→appointment→record→result→report 全链路已有 ★★★ 直接复用
报告解析 DanReportController: upload→edit→confirm→complete-analysis ★★★ 直接复用
菌群检测 BeijingNutritionController: bacteria/save + analysis + recommend;送会员走 TrialMembership ★★★ 直接复用
会员 FamilyMembership(FREE/BASIC/PROFESSIONAL/ENTERPRISE) + MembershipController(upgrade/trial/my/can-use/benefits) ★★★ 直接复用
问卷 SurveyTemplate(questionsJson 题目JSON) + SurveyRecord(answersJson) + ReportSurveyController(create/submit/status);前端 pages/health/survey-questionnaire.vue 通用渲染页已有 ★★ 扩展(题目JSON 加 resultMapping)
套餐 GuidePackage(price/validityDays) + TaskTemplatePackage(cycleDays/category/price) + AssessmentProduct(single/bundle) ★★ 需补"套餐→检测→任务模板"关联
任务 Task 有 sourceType/sourceId/dimensionCode,无会员字段 ★ 需加 member_only
CF值 PlatformPointsService.earn/spend/freeze/unfreeze + 家庭池 FamilyPlatformPointsServiceUnlockGateService 已实现关卡奖励发 CF 值(幂等) ★★★ 复用 earn() 发奖励
优惠券 Coupon/UserCoupon/CouponController(exchange/claim) ★★★ 备用
通知 NoticeController/list(GET,且不合规),无主动通知 ★ 需新建通知表+写入+列表接口

三、数据模型设计

3.1 新增 problem_domains(问题域表)

CREATE TABLE IF NOT EXISTS problem_domains (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  code VARCHAR(50) NOT NULL COMMENT '唯一编码: weight_loss/sleep/constipation',
  name VARCHAR(50) NOT NULL COMMENT '名称: 减肥/睡眠/便秘',
  icon VARCHAR(255) DEFAULT '' COMMENT '图标',
  description VARCHAR(500) DEFAULT '' COMMENT '一句话描述',
  flow_intro_json TEXT COMMENT '服务流程介绍(7步) JSON',
  survey_template_id BIGINT DEFAULT NULL COMMENT '专项调研问卷模板ID(SurveyTemplate.id)',
  content_tags VARCHAR(500) DEFAULT '' COMMENT '内容标签,逗号分隔(过滤文章/知识库)',
  recommended_product_ids VARCHAR(500) DEFAULT '' COMMENT '推荐产品ID,逗号分隔(Product.id)',
  task_template_package_ids VARCHAR(500) DEFAULT '' COMMENT '套餐绑定的任务模板包ID(TaskTemplatePackage.id)',
  reward_cf_value INT DEFAULT 0 COMMENT '全部完成奖励CF值',
  status TINYINT DEFAULT 1 COMMENT '1启用 0停用',
  sort_order INT DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_code (code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='问题域定义(改版v1)';

3.2 新增 user_intents(用户意图/旅程表)

CREATE TABLE IF NOT EXISTS user_intents (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT NOT NULL COMMENT '用户ID',
  intent_type VARCHAR(20) DEFAULT '' COMMENT 'A/B/C 用户类型',
  problem_domain_code VARCHAR(50) DEFAULT '' COMMENT '问题域编码(仅C类)',
  journey_stage INT DEFAULT 0 COMMENT '旅程阶段 0-7,语义见下方状态机',
  stage_updated_at DATETIME DEFAULT NULL COMMENT '最近阶段变化时间',
  survey_template_id BIGINT DEFAULT NULL COMMENT '最近作答问卷模板ID',
  survey_submitted_at DATETIME DEFAULT NULL COMMENT '最近问卷提交时间',
  survey_result_json TEXT COMMENT '问卷答案→推荐结果快照',
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  UNIQUE KEY uk_user (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户意图与服务旅程(改版v1)';

journey_stage 状态机(C类,0-7): | stage | 语义 | 进入条件 | 推进动作 | |-------|------|----------|----------| | 0 | 已选择问题域,未看流程 | 用户选择 C 类+问题域 | 打开流程介绍页 | | 1 | 已看流程介绍 | 流程介绍页曝光完成 | 提交调研 | | 2 | 调研已提交 | 调研提交成功 | 购买套餐 | | 3 | 已购买 | 支付回调成功 | 管理员发货 | | 4 | 试剂盒已发/样本已收 | 物流状态更新 | 报告生成 | | 5 | 报告已出 | completeAnalysis 完成 | 用户确认方案 | | 6 | 方案已确认,任务已生成 | 方案确认接口 | 任务全部完成 | | 7 | 任务完成,CF奖励已发 | 奖励发放成功 | —(终态,展示回馈) |

A类简化:0=已选A类,1=已购测评/检测,2=报告已出,3=方案确认,4=任务完成。B类简化:0=已选B类,1=问卷已答(此后首页按结果定向展示内容)。

3.2b 通知表与既有 notices 的边界

  • noticesNotice.java, @TableName("notices")):平台级公告,管理员发布(platform/activity/promotion),全员可见,NoticeController 仅 GET /list(遗留不合规,不动)。
  • user_notifications(新增):用户级主动通知,按 user_id 定向(报告完成/奖励到账/物流变化),带 ref_type/ref_id 可跳转。二者并存不冲突。

3.3 Task 表加会员字段

ALTER TABLE task ADD COLUMN member_only TINYINT DEFAULT 0 COMMENT '1=会员任务(方案生成),执行需会员';

3.4 新增 user_notifications(站内通知表)

CREATE TABLE IF NOT EXISTS user_notifications (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT NOT NULL COMMENT '接收用户ID',
  type VARCHAR(30) DEFAULT 'report_ready' COMMENT 'report_ready/reward_granted/system',
  title VARCHAR(200) NOT NULL,
  content VARCHAR(1000) DEFAULT '',
  ref_type VARCHAR(30) DEFAULT '' COMMENT '关联对象类型: report/package/task',
  ref_id BIGINT DEFAULT NULL COMMENT '关联对象ID',
  is_read TINYINT DEFAULT 0,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  INDEX idx_user_read (user_id, is_read)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='站内通知(改版v1)';

3.5 套餐/物流状态扩展(复用 PackageOrder / ProductOrder)

  • package_orders 表(entity/PackageOrder.java 已存在,含 userId/familyId/packageId/contactName/contactPhone/contactAddress)加:
    • logistics_status VARCHAR(20) DEFAULT 'none'(none/kit_shipped/kit_received/sample_shipped/sample_received)
    • tracking_no VARCHAR(100) DEFAULT ''

3.6 调研问卷 → 推荐结果映射

SurveyTemplate.questionsJson 题目结构扩展:每题的 option 支持 resultTags

[
  {"text": "您的睡眠问题持续多久了?", "options": [
    {"text": "1-3个月", "resultTags": "短期,轻中度"},
    {"text": "半年以上", "resultTags": "长期,重度"}
  ]}
]

后端提交问卷时汇总所有选中 option 的 resultTags + 问题域 code,返回推荐产品列表快照,存入 user_intents.survey_result_json

四、后端改动清单(cfc-backend)

阶段1:C类问题导向型闭环(优先交付)

# 文件 改动 验证
B1 entity/ProblemDomain.java 新实体(§3.1) compile
B2 mapper/ProblemDomainMapper.java 新 Mapper compile
B3 entity/UserIntent.java 新实体(§3.2) compile
B4 mapper/UserIntentMapper.java 新 Mapper compile
B5 entity/UserNotification.java 新实体(§3.4) compile
B6 mapper/UserNotificationMapper.java 新 Mapper compile
B7 entity/Task.java memberOnly 字段 compile
B8 config/DatabaseInitializer.java 迁移:3 张新表 + task.member_only + package_order 物流字段 compile
B9 resources/schema.sql 同步建表语句
B10 controller/ProblemDomainController.java 接口:POST /api/problem-domain/list(启用中,含问卷模板+推荐产品+任务模板) compile
B11 controller/UserIntentController.java 接口:POST /api/user-intent/get(当前意图) / POST /api/user-intent/choose(首次选择A/B/C) / POST /api/user-intent/update-stage(旅程推进) compile
B12 controller/UserNotificationController.java 接口:POST /api/notification/list / POST /api/notification/read compile
B13 controller/ProblemSurveyController.java 接口:POST /api/problem-survey/submit(提交调研→汇总resultTags→查推荐产品→存快照→返回推荐列表) compile
B14 controller/ProblemPackageController.java 接口:POST /api/problem-package/detail(套餐详情:介绍/使用方式/包含检测/任务模板/奖励说明) compile
B15 controller/TaskController.java 补会员校验:/{id}/complete/accept 时若 task.memberOnly==1 且非会员 → 拒绝(提示开通会员) compile
B16 service/DanReportService.completeAnalysis(报告确认处) 报告完成解析后:写 user_notifications(report_ready) + 更新 user_intents.journey_stage=5 compile
B17 service/ProblemCompletionService.java 新 Service:任务全部完成后发放 CF 值。奖励对象:家庭池(FamilyPlatformPointsService.earn,familyId 维度),金额=问题域配置 reward_cf_value;幂等:按 (familyId, problemDomainCode, 'completion') 查唯一发放记录;写通知(reward_granted) + 更新旅程 stage=7 compile
B18 entity/PackageOrder.java logisticsStatus / trackingNo(表 package_orders) compile
B19 controller/LogisticsController.java 接口:POST /api/logistics/update(管理端发货/收样) / POST /api/logistics/my(用户查状态) compile

阶段2:A类会员任务解锁

# 文件 改动
B20 service/TaskPlanService(任务实例生成处)+ TaskService.createSingleTask 方案/套餐确认生成任务实例时标记 memberOnly=1createSingleTask 从 DTO 透传 memberOnly
B21 service/RepeatTaskGenerator 重复任务复制模板时透传 memberOnly 字段(否则方案任务实例的会员标记丢失)
B22 TaskController.create 未缴费用户自建任务:memberOnly=0,不校验会员(确认现有 create 已放行)

阶段3:B类问卷引流

# 文件 改动
B23 SurveyTemplate 扩展 questionsJson 支持 resultTags;getActiveTemplates 支持按问题域过滤
B24 controller/ContentFilterController.java 接口:POST /api/content/by-tags(按 resultTags + 问题域 code 过滤文章/知识库/饮食推荐)

五、前端改动清单(cfc-frontend)

阶段1:C类闭环

# 文件 改动
F1 pages/index-home/index.vue 首页重构:登录后顶部"旅程状态卡"(进度+下一步);未选择过意图的用户弹"首次选择"层(A直达/B问卷/C问题域)
F2 components/intent-picker.vue(新) 首次选择弹层:三个入口卡片
F3 components/journey-card.vue(新) 旅程进度条 + 下一步动作按钮(按 user_intents 渲染)
F4 pages/problem/domain-list.vue(新) 问题域列表页(3个卡片)
F5 pages/problem/flow-intro.vue(新) 服务流程介绍页(7步,来自 flow_intro_json)
F6 pages/problem/survey.vue(新) 专项调研页(复用 survey-questionnaire 模式,提交走 problem-survey/submit)
F7 pages/problem/package-match.vue(新) 调研结果→推荐套餐列表(只显示相关)
F8 pages/problem/package-detail.vue(新) 套餐详情(介绍/使用方式/包含检测/任务模板/奖励)→ 购买按钮
F9 pages/problem/logistics.vue(新) 试剂盒寄送/样本寄回状态
F10 pages/problem/plan-confirm.vue(新) 报告出来后查看方案 → 确认 → 生成任务
F11 pages/notification/index.vue(新) 站内通知列表(报告完成/奖励到账)
F12 pages/tasks/tasks.vue 会员任务角标(memberOnly 显示🔒,点击提示开通会员)
F13 utils/api.js 新接口封装(problem-domain/user-intent/notification/problem-survey/problem-package/logistics)

阶段2:A类

# 文件 改动
F14 pages/index-home/index.vue 入口A直达"测评/检测选购页"
F15 方案确认页复用 F10 A类报告出方案→确认→生成任务(带 memberOnly)

阶段3:B类

# 文件 改动
F16 pages/problem/quick-survey.vue(新) 5-8题轻问卷
F17 pages/index-home/index.vue 按调研结果定向展示科普内容模块

六、管理端改动清单(cfc-web)

# 文件 改动
W1 views/admin/ProblemDomainManage.vue(新) 问题域 CRUD:编码/名称/图标/描述/流程介绍(7步编辑)/绑定问卷模板/内容标签/推荐产品/任务模板包/奖励CF值
W2 套餐管理增强 绑定检测项目、任务模板包、完成奖励CF值
W3 通知模板管理 report_ready / reward_granted 文案配置(可选)
W4 物流管理 试剂盒发货/样本签收状态更新(可选,后端接口已备)

七、实施顺序(里程碑)

里程碑 内容 验收标准
M1 数据层 B1-B9 mvn clean compile 通过;3 张新表 + task.member_only 迁移幂等
M2 C类后端接口 B10-B19 compile 通过;关键接口(survey submit→推荐、报告完成→通知+旅程推进、任务完成→CF奖励)逻辑可测
M3 C类前端闭环 F1-F13 + W1 用户在开发者工具可走通:选减肥→流程介绍→调研→套餐→购买→物流→通知→方案确认→任务→完成得CF值
M4 A类会员任务 B20-B21 + F14-F15 方案任务带锁,非会员执行被拦截;自建任务免费可用
M5 B类问卷引流 B22-B23 + F16-F17 观望用户填问卷后首页只显示相关内容

八、风险与注意事项

  1. 首次选择弹层:必须在登录后数据加载前弹出一次,且"跳过"不得导致下次不再弹出(storage 标记 intent_skipped,弹层关闭时写标记但 user_intents 未创建 → 下次仍弹)。决策1要求"未选过就要弹"。teacher(规划师)角色不弹(服务商不是 C 类客户,仅 parent/child 视角弹)。
  2. memberOnly 校验:校验点在 TaskController complete/accept,需同时覆盖规划师批量审核路径(GuideFamilyTaskController)与家长代完成路径(complete-parent)。
  3. CF 奖励幂等 + 归属:按 (familyId, problemDomainCode, 'completion') 唯一记录防重复发放(参照 UnlockGateService 已实现模式);奖励进家庭池(FamilyPlatformPointsService),不落个人池,避免"执行者是孩子、购买者是家长"的归属争议。
  4. 问卷 resultTags:老模板无 resultTags 时兼容(option 是纯字符串),解析器需双态处理。
  5. 小程序规范:新页面全部 Options API、禁止可选链、禁止 :key 表达式、日期用 parseDate、路由用 POST。
  6. 通知合规NoticeController 现有 /list 是 GET(不合规遗留),新建的 UserNotificationController 一律 POST;不动旧接口。
  7. 问卷模板 JSON 迁移:现有调研模板数据结构不含 resultTags,提交接口需对"无 resultTags"模板返回空推荐(不报错)。
  8. 物流状态:已确认 package_orders 表存在(PackageOrder.java),物流字段加其上;kit_shipped 即"试剂盒已寄出"。
  9. 会员判断复用:调 MembershipController.can-use 或直接查 FamilyMembership levelCode != FREE 且未过期。
  10. C类流程承载物:流程描述页/套餐详情页写死"菌群检测试剂盒"是错误的——套餐(TaskTemplatePackage/GuidePackage)是承载物,flow_intro_json 每步文案可配置,检测项目通过套餐绑定的 assessmentProduct 决定。减肥/睡眠/便秘各自的套餐与检测项在管理端配置,代码不写死。
  11. 新增 Controller 前置检查:新增 ProblemDomainController/UserIntentController 等前,先跑路由重复检查(AGENTS.md 工作流)与 Bean 名冲突检查。