|
@@ -0,0 +1,93 @@
|
|
|
|
|
+# 健康方案制定默认选当前用户 + 问卷代入自己 + 健康页健康阅卷入口(2026-11-07)
|
|
|
|
|
+
|
|
|
|
|
+> 主理人廖总提出 3 项功能需求。本设计基于对 cfclub 主线(HEAD 017042d8a)的只读核查,给出增量改动方案与验收标准。
|
|
|
|
|
+
|
|
|
|
|
+## 一、需求清单
|
|
|
|
|
+
|
|
|
|
|
+| # | 需求 | 产品语义 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| 1 | 进入方案制定时,默认应选择当前用户 | Step1 选服务对象:默认勾选「本人(isSelf)」而非列表第一个成员 |
|
|
|
|
|
+| 2 | 制定方案选完成员后,若没选自己,进入下一步问卷时自动代入**自己的数据**而非别人的 | Step2 健康问卷:预填数据源 = 当前登录用户自己(账号级),与被选成员解耦 |
|
|
|
|
|
+| 3 | 健康页增加「健康阅卷」填写入口,可多次填写、保存为多条记录,已填写过代入最后一次 | 健康主页新增入口;提交生成新记录(复用 `survey_records`),再进入时预填最后一条 |
|
|
|
|
|
+
|
|
|
|
|
+主理人拍板(2026-11-07):需求 3 问卷内容 = 复用现有健康问卷(ComprehensiveSurvey 8 模块);记录落库 = 复用 `survey_records`(加来源标识区分健康阅卷)。
|
|
|
|
|
+
|
|
|
|
|
+## 二、现状(只读核查结论,文件+行号)
|
|
|
|
|
+
|
|
|
|
|
+### 需求 1:方案制定默认选第一个成员,非当前用户
|
|
|
|
|
+
|
|
|
|
|
+- `cfc-frontend/pages/health/components/MemberChipPicker.vue`
|
|
|
|
|
+ - `applyList()` 行 148-157:`selectedIds.length === 0 && mapped.length > 0` → `selectedIds = [String(mapped[0].id)]`(**默认选第一个成员**)
|
|
|
|
|
+ - `mapped.push()`(行 138-146)**未保留 `isSelf` 字段** → 无法识别本人
|
|
|
|
|
+ - `loadMembers()`(行 164-192)经 `normalizeMembers(list, { userId })` 规范化,isSelf 行唯一(`utils/memberNormalize.js` canonical 优先级 isSelf 最高)
|
|
|
|
|
+- `cfc-frontend/pages/health/health-plan-summary.vue`
|
|
|
|
|
+ - `onLoad()` 行 393-400:`options.initialMemberIds` / `options.memberId` 均缺省时 `selectedMemberIds=[]` → 交由组件默认 `mapped[0]`
|
|
|
|
|
+ - 入口:`pages/health/plan-list.vue` `goCreatePlan()` → `/pages/health/health-plan-summary`(无参数)
|
|
|
|
|
+
|
|
|
|
|
+### 需求 2:问卷预填按选中成员
|
|
|
|
|
+
|
|
|
|
|
+- `cfc-frontend/pages/health/health-plan-summary.vue`
|
|
|
|
|
+ - `loadHealthForm(memberId)` 行 481-507:`getHealthStatus(mid || undefined)` —— `mid` = 选中成员 id → 后端 memberId 非空走**成员级**数据
|
|
|
|
|
+ - `loadDietForm(memberId)` 行 509-520:`getDietPreferences({ memberId: mid })` —— 同按选中成员
|
|
|
|
|
+ - 保存(`saveTaskForMember` 附近,行 750/757):`payload.memberId = mid` → 按选中成员保存(**本次不改**)
|
|
|
|
|
+- `cfc-backend/.../controller/HealthStatusController.java`
|
|
|
|
|
+ - `get()` 行 28-35:`memberId != null ? getByMemberId(userId, memberId) : getByUserId(userId)` —— memberId 空 = 账号级(自己)
|
|
|
|
|
+ - `HealthStatus` 实体:`userId` + `memberId` 双字段
|
|
|
|
|
+
|
|
|
|
|
+### 需求 3:健康页现状与 survey_records 能力
|
|
|
|
|
+
|
|
|
|
|
+- `cfc-frontend/pages/health-main/index.vue`
|
|
|
|
|
+ - 已有「15题五维健康自检」`goSelfTest()`(行 704-713)→ `/pages/health/health-survey`(保存 `health_status` **覆盖式单条**)
|
|
|
|
|
+ - 已有「待填调研」`loadPendingSurveys()`/`goSurveyFill()`(行 715-739)→ `survey-questionnaire`(`survey_records` **多条**)
|
|
|
|
|
+- `cfc-backend/.../controller/SurveyController.java`
|
|
|
|
|
+ - `submit()` 行 116-131:`submitSurvey(userId, memberId, templateId, answersJson, ps, pe, riskHits)` —— 每次插一条 `survey_records`
|
|
|
|
|
+ - `history()` 行 133-141:`getSurveyHistory(userId, memberId)` 返回列表
|
|
|
|
|
+- `cfc-backend/.../entity/SurveyRecord.java`:`@TableName("survey_records")`,字段 userId / memberId / periodStart / answersJson 等
|
|
|
|
|
+- `health-survey.vue`:ComprehensiveSurvey 8 模块,提交 `saveHealthStatus` + `saveDietPreferences`(health_status/diet_preferences,覆盖式)
|
|
|
|
|
+
|
|
|
|
|
+## 三、方案(改动点)
|
|
|
|
|
+
|
|
|
|
|
+### 需求 1 —— 默认选当前用户(前端 2 文件)
|
|
|
|
|
+
|
|
|
|
|
+1. **`MemberChipPicker.vue`**
|
|
|
|
|
+ - `applyList()`:`mapped.push()` 增加 `isSelf: !!m.isSelf`(及 `userId`)
|
|
|
|
|
+ - 默认选中逻辑:`selectedIds.length === 0 && mapped.length > 0` → 优先取 **isSelf 成员**,无则回退 `mapped[0]`
|
|
|
|
|
+2. **`health-plan-summary.vue`**
|
|
|
|
|
+ - `onLoad()`:无 `initialMemberIds`/`memberId` 参数时,不预设空,交由组件默认(组件已改为选 isSelf);如组件 loaded 后 `selectedMemberIds` 仍空且成员含 isSelf,补选 isSelf(防御)
|
|
|
|
|
+
|
|
|
|
|
+### 需求 2 —— 问卷预填代入自己(前端 1 文件)
|
|
|
|
|
+
|
|
|
|
|
+3. **`health-plan-summary.vue`**
|
|
|
|
|
+ - `loadHealthForm()`:`getHealthStatus()` **不传 memberId**(账号级 = 当前用户自己);快照 key 仍用选中成员 id(保存语义不变)
|
|
|
|
|
+ - `loadDietForm()`:`getDietPreferences({})`(账号级自己);快照 key 仍按成员
|
|
|
|
|
+ - 说明:预填数据源 = 当前登录用户自己;**保存仍按选中成员**(`payload.memberId = mid` 不动)。若后续主理人明确「保存也应归自己」,仅改保存处 memberId 取值即可,本设计按最小改动执行。
|
|
|
|
|
+
|
|
|
|
|
+### 需求 3 —— 健康阅卷(后端 + 前端)
|
|
|
|
|
+
|
|
|
|
|
+4. **后端 `SurveyRecord.java`**:新增 `source` 字段(String,如 `periodic`/`health_review`,默认 `periodic`)
|
|
|
|
|
+5. **后端 `DatabaseInitializer`**:迁移 —— `survey_records` ADD COLUMN `source VARCHAR(32) DEFAULT 'periodic'`(幂等)
|
|
|
|
|
+6. **后端 `SurveyService`**:
|
|
|
|
|
+ - `submitSurvey(...)` 支持 `source` 参数(透传落库)
|
|
|
|
|
+ - 新增 `getLastHealthReview(userId, memberId)`:查 `source='health_review'` 按 `created_at DESC LIMIT 1`
|
|
|
|
|
+7. **后端 `SurveyController`**:
|
|
|
|
|
+ - `submit()` 读取 `params.source` 透传
|
|
|
|
|
+ - 新增 `POST /api/survey/health-review/last`:返回最后一条健康阅卷(无则 null)
|
|
|
|
|
+8. **前端 `utils/api.js`**:新增 `submitSurvey(source=...)` 透传 source;`getLastHealthReview()`
|
|
|
|
|
+9. **前端 `health-main/index.vue`**:新增「健康阅卷」卡片入口 → `/pages/health/health-survey?source=health_review&entry=health_review`
|
|
|
|
|
+10. **前端 `health-survey.vue`**:
|
|
|
|
|
+ - `onLoad`:若 `source=health_review` → 调 `getLastHealthReview()`,将 `answersJson` 预填 `formSnapshot`/`dietSnapshot`
|
|
|
|
|
+ - `onSubmit`:若 `source=health_review` → `submitSurvey({source:'health_review', answersJson})`(仅写 survey_records,**不动 health_status**);否则走现有 `saveHealthStatus`+`saveDietPreferences` 逻辑
|
|
|
|
|
+
|
|
|
|
|
+## 四、验收标准
|
|
|
|
|
+
|
|
|
|
|
+1. 进入 `/pages/health/health-plan-summary`(无参数)→ Step1 默认勾选「本人(isSelf)」,成员 tab 高亮为本人
|
|
|
|
|
+2. 仅选孩子(不选自己)→ Step2 问卷预填显示**当前登录用户自己**的 health_status/diet_preferences 数据
|
|
|
|
|
+3. 健康主页出现「健康阅卷」入口;进入后可多次提交,每次生成一条 `survey_records`(source='health_review')记录;再次进入预填最后一条(以最后一次为准)
|
|
|
|
|
+4. 既有「15题五维健康自检」(health_status)与「定期调研」(survey_records periodic)行为不变(回归零破坏)
|
|
|
|
|
+5. 后端编译通过(`mvn -q -o compile`);前端 `mvn`/构建无新增报错
|
|
|
|
|
+
|
|
|
|
|
+## 五、范围与边界
|
|
|
|
|
+
|
|
|
|
|
+- 不改既有 `health_status` 覆盖式语义;不新建表(复用 `survey_records`);不改「定期调研」模板问卷流程
|
|
|
|
|
+- 需求 2 仅改预填源;保存归属维持选中成员(设计注记待主理人复核)
|
|
|
|
|
+- 涉及文件:前端 5(MemberChipPicker/health-plan-summary/health-main/health-survey/utils-api)+ 后端 5(SurveyRecord/DatabaseInitializer/SurveyService/SurveyController/schema.sql 若适用)
|