diff --git a/CLAUDE.md b/CLAUDE.md index ca270c0..8b26554 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -114,3 +114,9 @@ pnpm deploy:server # 部署后端到生产环境 - 新增迁移目录只放 migration.sql,测试沿用各模块 __tests__;部署配置与验收清单放 docs/member-care.md。 - 成长档案的两端共用 `components/MemberProgress.vue`,仅此跨端组件直接请求 progress API,避免主包引用 admin 分包 Store;馆主评价页面仍通过 admin Store 访问。 + +### 个人身体画像 +- 线上获客归属独立 `body-portrait` 模块,不是成长档案的一个页面。共享契约在 `packages/shared/src/types/body-portrait.ts`,规格在 `docs/body-portrait.md`。 +- 评分只在服务端规则引擎计算;匿名测评用访问令牌哈希,不用可枚举 ID 做权限。 +- 安全分流不计分。完整报告需登录认领,体验预约需手机号。现有 TRIAL 体验卡承接转化。 +- 馆主「今日经营助手」只展示待办,不做成通用 CRM。主包不得引用 admin store。 diff --git a/docs/body-portrait.md b/docs/body-portrait.md new file mode 100644 index 0000000..9eab6ab --- /dev/null +++ b/docs/body-portrait.md @@ -0,0 +1,118 @@ +# 个人身体画像增长系统 + +入口:小程序「3 分钟身体状态评估」、报告页、体验预约,以及管理中心「今日经营助手」。线上获客归属独立 `body-portrait` 模块;线下专业评估与改善计划复用成长档案口径,不把问卷结果写成医疗诊断。 + +## 产品口径 + +- 对外名称:**3 分钟身体状态评估 / 个人身体画像**。只使用「关注度、可能表现、建议进一步评估」。禁止「诊断、疾病检测、患病风险、准确率」。 +- 分数 0~100 只表示**问卷关注度**,不表示身体能力、疼痛程度或患病概率。 +- 陌生用户可匿名完成问卷。完成后先看摘要;微信登录并认领后看完整报告。点击体验预约时必须授权手机号。 +- 安全分流不计分。命中持续明显疼痛、近期受伤、手脚明显麻木、医生限制运动或医疗恢复期时,不展示动作建议和强销售 CTA。 +- 评分只在服务端用版本化规则引擎计算。客户端不得提交分数、画像类型或线索阶段。LLM 不决定结论。 +- 现有 `TRIAL` 体验卡就是「评估 + 普拉提体验」。画像只补来源关联,不新增商品类型。 +- 成长照片沿用私有 COS、短时签名和学员授权。馆主可见不等于可公开分享。 + +## 免责声明 + +各入口固定文案: + +> 本评估不是医疗诊断或体态疾病检测,仅用于运动训练参考。若你正处于明显疼痛、伤病或医生限制运动的阶段,请先由医生或相应专业人士确认运动条件。 + +保存说明:匿名未认领草稿默认 30 天后清理。认领后的健康相关数据仅用于训练评估与跟进;学员可申请删除,审计事件保留必要边界。 + +## 问卷版本 `portrait-q-v1` + +每屏一个决策,可多选的题目明确标注。不询问「骨盆前倾」等专业病名。 + +| 步骤 | ID | 题干 | 类型 | +| --- | --- | --- | --- | +| 1 | `concerns` | 最近身体哪里最困扰你? | 人体图多选 | +| 2 | `goal` | 如果训练有效果,你最希望看到什么变化? | 单选 | +| 3 | `sittingHours` | 每天坐多久? | 单选 | +| 4 | `exerciseFreq` | 平时运动频率? | 单选 | +| 5 | `workPosture` | 工作时最常见状态? | 单选 | +| 6 | `endOfDayFatigue` | 一天结束后,身体哪里最累? | 人体图多选 | +| 7 | `afterSitting` | 长时间坐着后,你会出现? | 多选 | +| 8 | `standingNotice` | 自然站立时,你有没有注意过? | 多选 | +| 9 | `safety` | 最近是否存在以下情况? | 多选,不计分 | + +部位:头颈 `neck`、肩 `shoulder`、上背 `upperBack`、腰 `lowBack`、骨盆 `pelvis`、髋 `hip`、膝 `knee`、腿 `leg`。 + +目标:看起来更挺拔 `posture`、肩颈没那么累 `neckRelief`、久坐更舒服 `backComfort`、腹部更有力量 `core`、身体线条更好 `shaping`、腿型/髋部状态改善 `hipLeg`、动作更稳定 `stability`、我有自己的目标 `other`。 + +## 五维与关注度 + +维度:肩颈状态 `cervicalShoulder`、脊柱活动 `spinalMobility`、核心控制 `coreControl`、髋骨盆状态 `hipPelvis`、下肢稳定 `lowerLimb`。 + +| 分数 | 关注度 | +| ---: | --- | +| 0~30 | 低关注 | +| 31~50 | 轻度关注 | +| 51~70 | 中度关注 | +| 71~85 | 高关注 | +| 86~100 | 重点关注 | + +规则版本 `portrait-r-v1`:先按答案累加,再把每一维 clamp 到 0~100。安全选项不加分。 + +## 画像模板(8 种) + +主类型 1 个,次类型最多 1 个。 + +| ID | 标签 | +| --- | --- | +| `sedentaryNeckTension` | 久坐肩颈紧张型 | +| `sedentaryCoreWeak` | 久坐核心弱化型 | +| `neckCompensation` | 肩颈代偿型 | +| `hipTight` | 髋部紧张型 | +| `upperLowerCross` | 上下交叉混合型 | +| `lowerLimbUnstable` | 下肢稳定不足型 | +| `mixedFatigue` | 全身疲劳累积型 | +| `lowOverallConcern` | 整体关注度较低型 | + +## 报告结构 + +1. 一句话结论 + 主/次类型 + 问卷依据(充分/一般,不是准确率) +2. 最多 3 个优先关注点,必须引用用户原话/选项 +3. 问题之间的关联(例如久坐 → 胸椎活动减少 → 肩颈承担更多) +4. 三条日常建议;安全分流不下发动作。动作建议含停止条件 +5. 线上局限 → 到店评估项目 → 现有体验卡 + +匹配度只展示「问卷依据:充分 / 一般」,由有效回答数和证据条数计算。 + +## 漏斗事件 + +服务端事实:`assessment_started` `assessment_completed` `assessment_claimed` `phone_bound` `trial_purchased` `trial_booked` `trial_attended` `plan_purchased`。 + +客户端可报但需幂等:`report_viewed` `advice_viewed` `trial_clicked` `report_shared`。 + +`trial_attended` 只由体验卡预约被核销(COMPLETED)产生,不等于自动完成,也不含补录。 + +渠道:`xhs` `wechat` `dianping` `member_share` `organic` `other`。分享链接只用邀请码/活动码,不暴露内部用户 ID。 + +## 线索阶段 + +只允许前进:`VISIT` → `STARTED` → `COMPLETED` → `CLAIMED` → `PHONE_BOUND` → `TRIAL_PURCHASED` → `TRIAL_BOOKED` → `TRIAL_ATTENDED` → `PLAN_PURCHASED` → `TRAINING` → `RENEWAL_DUE` → `RENEWED`。馆主可记跟进备注,不能把阶段任意倒退覆盖历史。 + +## 线下评估与改善计划(V2) + +到店 60 分钟:沟通目标 → 静态体态 → 活动度 → 动作控制 → 普拉提体验 → 解释结果。协议版本 `offline-v1`。operatorId 不是授课老师。 + +12 周计划三阶段:1–4 重新建立控制,5–8 改善活动能力,9–12 整合身体动作。卖的是改善计划,不是「20 节课」。 + +## 复测与分享(V3) + +默认可在第 4 / 8 / 12 节生成复测待办。对比必须同协议、同观察项。成长卡片默认不含照片;公开导出需学员单次确认。分享落地进入 `source=member_share` 的新测评。 + +## 部署 + +新增表见 `packages/server/prisma/migrations/20260911180000_body_portrait/migration.sql`。发布顺序:`prisma migrate deploy` → 后端 → 小程序。回退先回退应用,表可保留。 + +## 验收清单 + +- 匿名可完成、可续填;登录后同一会话只能认领一次。 +- 完整报告需登录;体验预约需手机号。 +- 安全分流不计分、无动作建议、无强销售。 +- 分数与画像只来自服务端快照。 +- 馆主今日待办能看到「测完未约 / 体验后未购 / 待复测」。 +- 漏斗按渠道聚合;补录不进入获客转化。 +- 照片与分享遵守成长档案隐私规则。 diff --git a/packages/app/src/components/BodySilhouette.vue b/packages/app/src/components/BodySilhouette.vue new file mode 100644 index 0000000..8dcd0a8 --- /dev/null +++ b/packages/app/src/components/BodySilhouette.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/packages/app/src/components/PortraitProgress.vue b/packages/app/src/components/PortraitProgress.vue new file mode 100644 index 0000000..a690c2d --- /dev/null +++ b/packages/app/src/components/PortraitProgress.vue @@ -0,0 +1,19 @@ + + + + + diff --git a/packages/app/src/components/PortraitRadar.vue b/packages/app/src/components/PortraitRadar.vue new file mode 100644 index 0000000..7e8ee17 --- /dev/null +++ b/packages/app/src/components/PortraitRadar.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/packages/app/src/components/ProfileMenu.vue b/packages/app/src/components/ProfileMenu.vue index b083c72..532c276 100644 --- a/packages/app/src/components/ProfileMenu.vue +++ b/packages/app/src/components/ProfileMenu.vue @@ -42,6 +42,8 @@ const emit = defineEmits<{ const menuItems = computed(() => { const items: MenuItem[] = [ { key: 'progress', type: 'item', title: '我的成长档案', path: '/pages/profile/progress', requireAuth: true }, + { key: 'portrait', type: 'item', title: '身体状态评估', path: '/pages/portrait/index' }, + { key: 'plan', type: 'item', title: '我的改善计划', path: '/pages/portrait/plan', requireAuth: true }, ...(props.isAdmin ? [{ key: 'teaching-schedule', diff --git a/packages/app/src/components/QuickEntry.vue b/packages/app/src/components/QuickEntry.vue index 6af3864..e5e3877 100644 --- a/packages/app/src/components/QuickEntry.vue +++ b/packages/app/src/components/QuickEntry.vue @@ -1,27 +1,14 @@