|
@@ -0,0 +1,847 @@
|
|
|
|
|
+# 7维健康体系增量实施计划
|
|
|
|
|
+
|
|
|
|
|
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
|
|
+
|
|
|
|
|
+**Goal:** 完成7维健康评分系统与设计规范的差距填补,覆盖商品→能量奖励、Dify AI推荐、维度详情页、问卷前端、trend计算、body首页入口、管理端配置和测试。
|
|
|
|
|
+
|
|
|
|
|
+**Architecture:** 后端Spring Boot 2.7.18 + MyBatis-Plus,前端uni-app Vue 2(微信小程序),Web管理端Vue 2 + Element UI。7维评分核心已实现(Controller+Service+DTO+Entity+DB),剩余为增量衔接工作。
|
|
|
|
|
+
|
|
|
|
|
+**Tech Stack:** Java 8, Spring Boot 2.7.18, MyBatis-Plus, MySQL 8.0, uni-app Vue 2, Element UI Vue 2
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## TL;DR
|
|
|
|
|
+
|
|
|
|
|
+> **Quick Summary**: 填补7维健康体系与设计规范的10项差距:后端4项(商品能量、Dify推荐、趋势计算、身能量集成)、前端3项(详情页、问卷页、入口导航)、管理端2项(维度配置、数据源管理)、测试1项。核心评分引擎无需改动。
|
|
|
|
|
+>
|
|
|
|
|
+> **Deliverables**:
|
|
|
|
|
+> - 商品购买成功后自动奖励五维能量
|
|
|
|
|
+> - Dify AI智能推荐替代LIKE搜索
|
|
|
|
|
+> - 7个维度各自的详情页(历史趋势+建议+推荐商品)
|
|
|
|
|
+> - 维度问卷专用前端页面
|
|
|
|
|
+> - 趋势计算从硬编码改为基于历史数据
|
|
|
|
|
+> - body首页导航入口
|
|
|
|
|
+> - 管理端维度常模CRUD + 数据源CRUD
|
|
|
|
|
+> - 后端服务单元测试
|
|
|
|
|
+>
|
|
|
|
|
+> **Estimated Effort**: Medium (10 tasks)
|
|
|
|
|
+> **Parallel Execution**: YES - 4 waves, max 4 parallel
|
|
|
|
|
+> **Critical Path**: Task 1 (trend) → independent | Task 4 (身能量) → independent
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Context
|
|
|
|
|
+
|
|
|
|
|
+### Original Request
|
|
|
|
|
+根据设计规范(`.sisyphus/drafts/health-dimensions-design.md`)制定7维健康体系的完整实施计划。
|
|
|
|
|
+
|
|
|
|
|
+### Codebase State Summary
|
|
|
|
|
+经过全面探索,7维健康评分框架**核心已完全实现**:
|
|
|
|
|
+- **后端**:`HealthDimensionController` + `DimensionScoreServiceImpl` + DTOs + Entity + Mapper + DB表 — 100%
|
|
|
|
|
+- **前端**:`health-dimensions.vue`(健康指数环+雷达图+维度卡片+上传弹窗)— 100%
|
|
|
|
|
+- **剩余**:10项增量差距
|
|
|
|
|
+
|
|
|
|
|
+### Key Decisions Made
|
|
|
|
|
+- 范围:全部差距项(10项),用户确认
|
|
|
|
|
+- 测试:包含后端单元测试
|
|
|
|
|
+- 保存:`.sisyphus/plans/` + 拷贝到 `docs/superpowers/plans/` 提交
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Work Objectives
|
|
|
|
|
+
|
|
|
|
|
+### Core Objective
|
|
|
|
|
+完成7维健康体系剩余10项增量功能的实施,覆盖后端增强、前端页面、管理端配置和测试。
|
|
|
|
|
+
|
|
|
|
|
+### Concrete Deliverables
|
|
|
|
|
+- `ProductOrderService.java` - 支付成功后触发能量奖励
|
|
|
|
|
+- `DifySyncService.java` - 完整的Dify API调用实现
|
|
|
|
|
+- `RecommendationService.java` - 集成Dify AI推荐
|
|
|
|
|
+- `DimensionScoreServiceImpl.java` - 趋势计算修正
|
|
|
|
|
+- `EnergyService.java` - 读取维度分数影响身能量
|
|
|
|
|
+- 7个维度详情页 (`pages/body/dimension-detail/`)
|
|
|
|
|
+- 问卷前端页 (`pages/body/dimension-questionnaire.vue`)
|
|
|
|
|
+- `body/index.vue` - 添加维度入口链接
|
|
|
|
|
+- Web管理端维度常模管理页
|
|
|
|
|
+- Web管理端数据源管理页
|
|
|
|
|
+- 后端JUnit测试
|
|
|
|
|
+
|
|
|
|
|
+### Definition of Done
|
|
|
|
|
+- [ ] `mvn clean compile` 通过
|
|
|
|
|
+- [ ] 所有新增/修改的后端逻辑可编译
|
|
|
|
|
+- [ ] 前端页面在pages.json注册且路径可访问
|
|
|
|
|
+- [ ] 单元测试通过(覆盖率≥60%新增代码)
|
|
|
|
|
+
|
|
|
|
|
+### Must Have
|
|
|
|
|
+- 商品购买成功→能量奖励:`ProductOrderService.pay()` + `handlePaymentSuccess()` 调用 `EnergyService.awardEnergy()`
|
|
|
|
|
+- Dify同步:`DifySyncService` 实现 REST API 调用(POST/PUT/DELETE文档到Dify Dataset)
|
|
|
|
|
+- AI推荐:`RecommendationService` 在关键词搜索无结果时调用 Dify 推荐
|
|
|
|
|
+- 趋势:`DimensionScoreServiceImpl` 基于最近2次评分计算 up/down/stable
|
|
|
|
|
+- 身能量联动:`EnergyService` 或新Service读取7维评分并影响body维度能量
|
|
|
|
|
+- 维度详情页:7个维度各自的页面,含历史折线图、建议、关联商品
|
|
|
|
|
+- 问卷页:专用问卷页调用 `/api/dimension/questionnaire`
|
|
|
|
|
+- body首页:添加"健康维度"入口按钮
|
|
|
|
|
+- 管理端:维度常模CRUD + 数据源CRUD
|
|
|
|
|
+
|
|
|
|
|
+### Must NOT Have (Guardrails)
|
|
|
|
|
+- 不改动7维评分核心聚合逻辑(`DimensionScoreServiceImpl.getHealthDimension()` 的7维聚合)
|
|
|
|
|
+- 不改动前端已实现的 `health-dimensions.vue` 核心结构(雷达图、维度卡片等)
|
|
|
|
|
+- 不改动数据库已有表结构(仅可能新增索引或数据行)
|
|
|
|
|
+- 不重写 `ProductOrderService` 的订单流程,仅在支付成功后插入能量奖励调用
|
|
|
|
|
+- 不引入新依赖/库
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Verification Strategy
|
|
|
|
|
+
|
|
|
|
|
+> **ZERO HUMAN INTERVENTION** - ALL verification is agent-executed. No exceptions.
|
|
|
|
|
+
|
|
|
|
|
+### Test Decision
|
|
|
|
|
+- **Infrastructure exists**: YES (后端有JUnit/Spring Boot Test支持)
|
|
|
|
|
+- **Automated tests**: YES (Tests after) - 为新增/修改的后端逻辑编写单元测试
|
|
|
|
|
+- **Framework**: JUnit 5 + Spring Boot Test + Mockito
|
|
|
|
|
+
|
|
|
|
|
+### QA Policy
|
|
|
|
|
+Every task MUST include agent-executed QA scenarios. Evidence saved to `.sisyphus/evidence/task-{N}-{scenario-slug}.{ext}`.
|
|
|
|
|
+
|
|
|
|
|
+- **Backend changes**: Use Bash (mvn test / curl API endpoints)
|
|
|
|
|
+- **Frontend pages**: Use Playwright (navigate, assert DOM)
|
|
|
|
|
+- **Admin UI**: Use Playwright (navigate, fill forms, assert)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Execution Strategy
|
|
|
|
|
+
|
|
|
|
|
+### Parallel Execution Waves
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+Wave 1 (Backend Core - Start Immediately):
|
|
|
|
|
+├── Task 1: Trend calculation fix [quick]
|
|
|
|
|
+├── Task 2: Product→Energy reward [quick]
|
|
|
|
|
+├── Task 3: Dify AI sync + integration [unspecified-high]
|
|
|
|
|
+└── Task 4: 7-dimension → body energy integration [quick]
|
|
|
|
|
+
|
|
|
|
|
+Wave 2 (Frontend Pages):
|
|
|
|
|
+├── Task 5: Body index → dimensions entry [quick]
|
|
|
|
|
+├── Task 6: Questionnaire frontend page [visual-engineering]
|
|
|
|
|
+└── Task 7: Dimension detail pages (7 pages) [visual-engineering]
|
|
|
|
|
+
|
|
|
|
|
+Wave 3 (Admin UI + Testing):
|
|
|
|
|
+├── Task 8: Dimension config management (Web admin) [quick]
|
|
|
|
|
+├── Task 9: Data source management (Web admin) [quick]
|
|
|
|
|
+└── Task 10: Unit tests [quick]
|
|
|
|
|
+
|
|
|
|
|
+Wave FINAL (Verification):
|
|
|
|
|
+├── F1: Plan compliance audit (oracle)
|
|
|
|
|
+├── F2: Code quality review (unspecified-high)
|
|
|
|
|
+├── F3: Real manual QA (unspecified-high + playwright)
|
|
|
|
|
+└── F4: Scope fidelity check (deep)
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## TODOs
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 1. Trend Calculation — 基于历史数据计算趋势
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 在 `DimensionScoreServiceImpl.java` 中找到 `item.setTrend("stable")` 行(约第78行)
|
|
|
|
|
+ - 将趋势计算改为基于最近2次评分的历史比较
|
|
|
|
|
+ - 逻辑:比较当前评分与上一次评分,若差异≥5分则判定up/down,否则stable
|
|
|
|
|
+ - 使用 `HistoryScores(memberId, dimension, 2)` 获取最近2条记录
|
|
|
|
|
+ - 修改 `getHealthDimension()` 方法中构建 DimensionItem 的部分
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不改动 `getHealthDimension()` 的整体结构
|
|
|
|
|
+ - 不改动其他方法
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `quick`
|
|
|
|
|
+ - Reason: Single simple logic change, low complexity
|
|
|
|
|
+ - **Skills**: [] (no special skills needed)
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 1 (with Tasks 2, 3, 4)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None (can start immediately)
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/impl/DimensionScoreServiceImpl.java:52-98` — `getHealthDimension()` 方法,第78行硬编码 `"stable"`
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/impl/DimensionScoreServiceImpl.java:143-160` — `getDimensionHistory()` 方法,用作参考
|
|
|
|
|
+ - `.sisyphus/drafts/health-dimensions-design.md` — 设计规范§7.1 趋势定义
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] 当最近2次评分差≥5分时,trend返回"up"或"down"
|
|
|
|
|
+ - [ ] 当评分差<5分或无历史数据时,trend返回"stable"
|
|
|
|
|
+ - [ ] `mvn clean compile` 通过
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: Trend shows "up" when score increased by ≥5
|
|
|
|
|
+ Tool: Bash (curl)
|
|
|
|
|
+ Preconditions: Member has score 70 on day-1 and 80 on day-2 for "growth" dimension
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. POST /api/dimension/overview { memberId: 1 }
|
|
|
|
|
+ 2. Find "growth" dimension item in response
|
|
|
|
|
+ Expected Result: growth.trend === "up"
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-1-trend-up.json
|
|
|
|
|
+
|
|
|
|
|
+ Scenario: Trend shows "stable" with no history
|
|
|
|
|
+ Tool: Bash (curl)
|
|
|
|
|
+ Preconditions: Member has only 1 score record for "sleep" dimension
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. POST /api/dimension/overview { memberId: 2 }
|
|
|
|
|
+ 2. Find "sleep" dimension item
|
|
|
|
|
+ Expected Result: sleep.trend === "stable"
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-1-trend-stable.json
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `fix(dimension): calculate trend from score history instead of hardcoding`
|
|
|
|
|
+ - Files: `cfc-backend/src/main/java/com/etotem/cfc/service/impl/DimensionScoreServiceImpl.java`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 2. Product→Energy Reward — 商品购买后自动奖励能量
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 在 `ProductOrderService.java` 中:
|
|
|
|
|
+ - 注入 `EnergyService` (使用 `@Resource`)
|
|
|
|
|
+ - 在 `pay()` 方法中,在 `order.setStatus("paid")` 和 `orderMapper.updateById(order)` 之后,调用 `energyService.awardEnergy()`
|
|
|
|
|
+ - 在 `handlePaymentSuccess()` 方法中,同样的位置插入能量奖励
|
|
|
|
|
+ - 能量值:使用固定值 10(或根据商品价格计算,如 `totalAmount / 100`,以分为单位)
|
|
|
|
|
+ - sourceType 使用 `"product"`
|
|
|
|
|
+ - 确定 `childId`:从订单的 `buyerId` 对应的 `User.familyId` 中查找 children(可选:或直接使用 buyerId 作为 childId)
|
|
|
|
|
+ - 如果 buyer 不是 child 角色,则需要通过 `UserService` 查找该 buyer 家庭下的 child
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不改动订单支付流程的现有逻辑
|
|
|
|
|
+ - 不改变 `pay()` 方法的返回结构
|
|
|
|
|
+ - 不阻塞支付流程(能量奖励失败不应影响订单状态)
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `quick`
|
|
|
|
|
+ - Reason: Simple insertion of existing pattern (copy from `HealthCheckinService`)
|
|
|
|
|
+ - **Skills**: [] (no special skills needed)
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 1 (with Tasks 1, 3, 4)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java:140-168` — `pay()` 方法,在 `updateById` 后插入
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java:170-187` — `handlePaymentSuccess()` 方法
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/HealthCheckinService.java:161` — 调用 `energyService.awardEnergy()` 的模式参考
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/EnergyService.java:591-593` — `awardEnergy()` 方法签名
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/entity/EnergySourceConfig.java:19` — sourceType 枚举含 "product"
|
|
|
|
|
+ - `.sisyphus/drafts/health-dimensions-design.md` §8.2 — 改进方案
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] `pay()` 方法中支付成功后调用 `energyService.awardEnergy()`
|
|
|
|
|
+ - [ ] `handlePaymentSuccess()` 方法中也调用能量奖励
|
|
|
|
|
+ - [ ] 能量奖励失败不阻断支付返回
|
|
|
|
|
+ - [ ] `mvn clean compile` 通过
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: Product purchase awards energy on payment success
|
|
|
|
|
+ Tool: Bash (curl)
|
|
|
|
|
+ Preconditions: A product with id=1, a user with token
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. POST /api/product/order/pay { orderNo: "PO1234567890" }
|
|
|
|
|
+ 2. Check response status === 200
|
|
|
|
|
+ 3. POST /api/energy/balance { childId: 1 }
|
|
|
|
|
+ 4. Verify body dimension energy has increased
|
|
|
|
|
+ Expected Result: Energy balance shows product-purchase energy
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-2-energy-awarded.json
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `feat(product): award energy on successful payment`
|
|
|
|
|
+ - Files: `cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 3. Dify AI Sync and Recommendation — 实现Dify知识库同步和AI推荐
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 完成 `DifySyncService.java` 中的 TODO:
|
|
|
|
|
+ - `syncToDify()`: 根据 `dimensionCodes` 查询 `ProductDimensionConfigMapper` 获取 `difyDatasetId`,调用Dify REST API上传文档
|
|
|
|
|
+ - `removeFromDify()`: 调用Dify REST API删除文档
|
|
|
|
|
+ - 使用 Spring `RestTemplate` 发送 HTTP 请求到 `{difyBaseUrl}/datasets/{datasetId}/documents`
|
|
|
|
|
+ - 修改 `RecommendationService.java`:
|
|
|
|
|
+ - 当关键词LIKE搜索无结果或结果不足时,调用 Dify API 获取AI推荐
|
|
|
|
|
+ - 解析Dify返回结果,映射到商品ID
|
|
|
|
|
+ - 回退逻辑:Dify失败时继续使用原有LIKE搜索
|
|
|
|
|
+ - 添加 `product_dimension_config` 的 `difyDatasetId` 配置更新
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不阻塞主流程(Dify失败仅记录日志)
|
|
|
|
|
+ - 不改动 `RecommendationService` 的现有搜索逻辑(仅作为补充)
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `unspecified-high`
|
|
|
|
|
+ - Reason: Multiple integration points (REST API calls, data mapping, fallback logic)
|
|
|
|
|
+ - **Skills**: [] (no special skills needed)
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 1 (with Tasks 1, 2, 4)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None (Dify API integration is standalone)
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/DifySyncService.java` — TODO实现
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/entity/ProductDimensionConfig.java` — 含 `difyDatasetId` 字段
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/mapper/ProductDimensionConfigMapper.java` — 查询维度配置
|
|
|
|
|
+ - `cfc-backend/src/main/resources/application.yml:79-82` — Dify配置(base-url, api-key, nutrition-api-key)
|
|
|
|
|
+ - Dify API 文档: `POST /v1/datasets/{dataset_id}/documents` — 上传文档
|
|
|
|
|
+ - Dify API 文档: `DELETE /v1/datasets/{dataset_id}/documents/{doc_id}` — 删除文档
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] `syncToDify()` 成功发起HTTP POST请求到Dify API
|
|
|
|
|
+ - [ ] `removeFromDify()` 成功发起HTTP DELETE请求
|
|
|
|
|
+ - [ ] Dify API调用失败仅记录error log,不阻塞主流程
|
|
|
|
|
+ - [ ] `RecommendationService` 在LIKE搜索无结果时使用Dify推荐
|
|
|
|
|
+ - [ ] `mvn clean compile` 通过
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: Dify sync sends HTTP request
|
|
|
|
|
+ Tool: Bash (curl mock)
|
|
|
|
|
+ Preconditions: Dify API is configured, a knowledge base item exists
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Trigger knowledge base save
|
|
|
|
|
+ 2. Check log for "同步知识点" message
|
|
|
|
|
+ Expected Result: DifySyncService.syncToDify() called without error
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-3-dify-sync.log
|
|
|
|
|
+
|
|
|
|
|
+ Scenario: Recommendation falls back to LIKE search on Dify failure
|
|
|
|
|
+ Tool: Bash (curl)
|
|
|
|
|
+ Preconditions: Dify API returns error
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. POST /api/product/recommend { dimension: "gut", keyword: "益生菌" }
|
|
|
|
|
+ 2. Check response has data even if Dify fails
|
|
|
|
|
+ Expected Result: Returns products from LIKE search (existing behavior preserved)
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-3-recommend-fallback.json
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `feat(dify): implement knowledge sync API and AI recommendation`
|
|
|
|
|
+ - Files: `cfc-backend/src/main/java/com/etotem/cfc/service/DifySyncService.java`, `cfc-backend/src/main/java/com/etotem/cfc/service/RecommendationService.java`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 4. 7-Dimension → Body Energy Integration — 7维评分影响身能量
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 创建新的Service(或修改现有 `EnergyService`)来建立7维评分到五维「身」能量的映射
|
|
|
|
|
+ - 逻辑:读取 `health_dimension_scores` 表中某个 child 的最新7维评分,综合计算一个「身」能量加成值
|
|
|
|
|
+ - 在 `EnergyService.recalculateDimensionEnergy()` 或类似方法中集成
|
|
|
|
|
+ - 或创建 `DimensionEnergySyncService` 新 Service,供 `DimensionScoreServiceImpl` 在评分更新后调用
|
|
|
|
|
+ - 能量加成规则:7维平均分 × 系数(如 0.5)+ 基础值(简化方案)
|
|
|
|
|
+ - 在 `DimensionScoreServiceImpl` 的 `uploadScore()` 和 `submitQuestionnaire()` 成功后自动调用
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不改动七维评分核心逻辑
|
|
|
|
|
+ - 不改造 `EnergyService` 能量分配的核心算法
|
|
|
|
|
+ - 不引入循环依赖
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `quick`
|
|
|
|
|
+ - Reason: Simple data read + write, follows existing awardEnergy pattern
|
|
|
|
|
+ - **Skills**: [] (no special skills needed)
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 1 (with Tasks 1, 2, 3)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `.sisyphus/drafts/health-dimensions-design.md` §10 — 7维→五维「身」衔接逻辑
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/impl/DimensionScoreServiceImpl.java:100-116` — `uploadScore()` 方法
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/EnergyService.java:591-593` — `awardEnergy()` 方法
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/HealthDimensionScoreService.java` — 查询维度评分
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] 维度评分更新(upload/questionnaire)后自动触发身能量更新
|
|
|
|
|
+ - [ ] 7维平均分映射为body维度能量值
|
|
|
|
|
+ - [ ] `mvn clean compile` 通过
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: Body energy updates after dimension score upload
|
|
|
|
|
+ Tool: Bash (curl)
|
|
|
|
|
+ Preconditions: Member has 5 dimension scores
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. POST /api/dimension/upload { memberId: 1, dimension: "growth", score: 80, sourceType: "MANUAL" }
|
|
|
|
|
+ 2. POST /api/energy/overview { childId: 1 }
|
|
|
|
|
+ 3. Check body dimension energy value
|
|
|
|
|
+ Expected Result: Body energy reflects new dimension scores
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-4-body-energy.json
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `feat(dimension): integrate 7-dimension scores into body energy`
|
|
|
|
|
+ - Files: `cfc-backend/src/main/java/com/etotem/cfc/service/impl/DimensionScoreServiceImpl.java`, `cfc-backend/src/main/java/com/etotem/cfc/service/impl/DimensionEnergySyncService.java` (new)
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 5. Body Index → Dimensions Entry — 身体首页添加维度入口导航
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 在 `body/index.vue` 中找到功能入口区域(约第48-57行 `func-section`)
|
|
|
|
|
+ - 添加一个新的功能入口项,跳转到 `health-dimensions.vue`
|
|
|
|
|
+ - 图标使用 `📊` 或 `💚`,文案使用 "健康维度"
|
|
|
|
|
+ - 导航使用 `uni.navigateTo({ url: '/pages/body/dimension-overview?childId=...' })`
|
|
|
|
|
+ - 在 `onFuncClick` 方法中处理新入口
|
|
|
|
|
+ - 如果 `health-dimensions.vue` 不在首页直接可见,添加入口是必须的
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不改变现有功能入口的结构
|
|
|
|
|
+ - 不修改其他功能入口的行为
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `quick`
|
|
|
|
|
+ - Reason: Simple UI modification, add 1 entry to existing list
|
|
|
|
|
+ - **Skills**: []
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 2 (with Tasks 6, 7)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-frontend/pages/body/index.vue:279-284` — 现有功能入口列表 `funcList`
|
|
|
|
|
+ - `cfc-frontend/pages/body/index.vue:497-509` — `onFuncClick` 处理方法
|
|
|
|
|
+ - `cfc-frontend/pages/body/health-dimensions.vue` — 目标页面
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] body首页显示"健康维度"功能入口
|
|
|
|
|
+ - [ ] 点击后导航到健康维度页面
|
|
|
|
|
+ - [ ] 未登录时显示登录引导
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: Click health-dimensions entry navigates to dimensions page
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: User logged in, on body/index page
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Locate element with text "健康维度" in func-grid
|
|
|
|
|
+ 2. Click it
|
|
|
|
|
+ 3. Wait for navigation
|
|
|
|
|
+ Expected Result: Page URL contains "health-dimensions" or "dimension-overview"
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-5-navigation.png
|
|
|
|
|
+
|
|
|
|
|
+ Scenario: Unauthenticated user sees login prompt
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: User not logged in
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Click "健康维度" entry
|
|
|
|
|
+ Expected Result: Login modal appears
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-5-login-prompt.png
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `feat(body): add health-dimensions navigation entry`
|
|
|
|
|
+ - Files: `cfc-frontend/pages/body/index.vue`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 6. Dimension Questionnaire Page — 维度问卷前端页面
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 创建新页面 `cfc-frontend/pages/body/dimension-questionnaire.vue`
|
|
|
|
|
+ - 页面功能:选择维度 → 回答该维度的标准化问题 → 提交评分
|
|
|
|
|
+ - 调用后端 API: `POST /api/dimension/questionnaire`
|
|
|
|
|
+ - 问题数据:前端预定义问题列表,每维度3-5个问题,选择题(单选)
|
|
|
|
|
+ - 提交成功后显示评分结果并跳转回维度全景页
|
|
|
|
|
+ - 在 `pages.json` 中注册新页面
|
|
|
|
|
+ - 添加 API 函数 `submitDimensionQuestionnaire` 到 `utils/api.js`
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不替换已有的手动上传弹窗
|
|
|
|
|
+ - 不引入复杂状态管理
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `visual-engineering`
|
|
|
|
|
+ - Reason: Needs UI design + API integration, moderate complexity
|
|
|
|
|
+ - **Skills**: []
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 2 (with Tasks 5, 7)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-frontend/pages/body/health-dimensions.vue` — UI样式参考
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/controller/HealthDimensionController.java:49-59` — 后端问卷API
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/dto/HealthDimensionQuestionnaireVO.java` — DTO结构
|
|
|
|
|
+ - `cfc-frontend/utils/api.js` — 需要添加 `submitDimensionQuestionnaire`
|
|
|
|
|
+ - `cfc-frontend/pages.json` — 注册新页面
|
|
|
|
|
+ - `.sisyphus/drafts/health-dimensions-design.md` §6.2 — 问卷维度映射
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] 页面可选维度
|
|
|
|
|
+ - [ ] 每维度3-5个标准化问题
|
|
|
|
|
+ - [ ] 提交后调用 `/api/dimension/questionnaire`
|
|
|
|
|
+ - [ ] 提交成功后有反馈并跳转
|
|
|
|
|
+ - [ ] 页面在 `pages.json` 注册
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: Submit questionnaire for sleep dimension
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: User logged in, member exists
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Navigate to dimension-questionnaire page
|
|
|
|
|
+ 2. Select "睡眠质量" dimension
|
|
|
|
|
+ 3. Answer 3 questions (select options)
|
|
|
|
|
+ 4. Click submit
|
|
|
|
|
+ Expected Result: API returns success, redirect to dimensions page
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-6-questionnaire-submit.png
|
|
|
|
|
+
|
|
|
|
|
+ Scenario: Validation - no dimension selected
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: User on questionnaire page
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Click submit without selecting dimension
|
|
|
|
|
+ Expected Result: Toast shows "请选择维度"
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-6-validation.png
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `feat(body): add dimension questionnaire page`
|
|
|
|
|
+ - Files: `cfc-frontend/pages/body/dimension-questionnaire.vue` (new), `cfc-frontend/pages.json`, `cfc-frontend/utils/api.js`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 7. Dimension Detail Pages — 7个维度的详情页
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 创建新页面 `cfc-frontend/pages/body/dimension-detail.vue`(单页面+路由参数区分维度)
|
|
|
|
|
+ - 路由参数: `dimension` (code: growth/sleep/vision/immunity/nutrition/gut/exercise)
|
|
|
|
|
+ - 页面内容:
|
|
|
|
|
+ - 维度标题和当前评分(大号显示+等级颜色)
|
|
|
|
|
+ - 历史评分趋势折线图(Canvas或CSS实现,无需第三方库)
|
|
|
|
|
+ - 当前评分在常模中的百分位展示
|
|
|
|
|
+ - 该维度的改善建议(预置文本,每维度3-5条)
|
|
|
|
|
+ - 关联商品推荐(调用 `getProductsByDomain('body')` 并过滤)
|
|
|
|
|
+ - 调用后端API: `POST /api/dimension/history { memberId, dimension, limit: 10 }`
|
|
|
|
|
+ - 从 `health-dimensions.vue` 的维度卡片点击可导航至此详情页
|
|
|
|
|
+ - 在 `pages.json` 中注册新页面
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不删除已有的 `health-dimensions.vue` 全览页面
|
|
|
|
|
+ - 不引入第三方图表库
|
|
|
|
|
+ - 不包含实际医疗建议
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `visual-engineering`
|
|
|
|
|
+ - Reason: Complex UI with history chart, multiple sections, API integration
|
|
|
|
|
+ - **Skills**: []
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 2 (with Tasks 5, 6)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/controller/HealthDimensionController.java:61-76` — `/api/dimension/history` API
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/dto/HealthDimensionVO.java` — DimensionItem结构
|
|
|
|
|
+ - `cfc-frontend/pages/body/health-dimensions.vue` — UI样式参考
|
|
|
|
|
+ - `cfc-frontend/utils/api.js` — API函数
|
|
|
|
|
+ - `cfc-frontend/pages.json` — 注册新页面
|
|
|
|
|
+ - `.sisyphus/drafts/health-dimensions-design.md` §7.2 — 维度详情页要求
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] 7个维度共享同一详情页组件,通过参数区分
|
|
|
|
|
+ - [ ] 显示维度名称、当前评分、等级颜色
|
|
|
|
|
+ - [ ] 历史趋势折线图(至少最近5次评分)
|
|
|
|
|
+ - [ ] 百分位展示
|
|
|
|
|
+ - [ ] 3-5条改善建议
|
|
|
|
|
+ - [ ] 关联商品列表
|
|
|
|
|
+ - [ ] 在 `pages.json` 注册
|
|
|
|
|
+ - [ ] 从维度全景页可点击进入详情
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: View dimension detail for gut health
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: Member has gut dimension history
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Navigate to /pages/body/dimension-detail?dimension=gut&childId=1
|
|
|
|
|
+ 2. Verify shows "肠胃健康" title
|
|
|
|
|
+ 3. Verify score displayed with level color
|
|
|
|
|
+ 4. Verify history chart has data points
|
|
|
|
|
+ Expected Result: All sections render correctly
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-7-dimension-detail.png
|
|
|
|
|
+
|
|
|
|
|
+ Scenario: Empty state - no history data
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: Member has no history for "vision"
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Navigate to /pages/body/dimension-detail?dimension=vision&childId=2
|
|
|
|
|
+ Expected Result: Shows "暂无历史数据" empty state
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-7-empty-state.png
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `feat(body): add 7 dimension detail pages`
|
|
|
|
|
+ - Files: `cfc-frontend/pages/body/dimension-detail.vue` (new), `cfc-frontend/pages.json`, `cfc-frontend/pages/body/health-dimensions.vue`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 8. Dimension Config Management (Web Admin) — 管理端维度常模配置
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 在 `cfc-web/` 中创建新视图页面 `src/views/admin/dimension-config.vue`
|
|
|
|
|
+ - 功能:
|
|
|
|
|
+ - 列出 `health_norm_reference` 表中的所有维度常模数据
|
|
|
|
|
+ - 编辑:修改某个维度/年龄段/性别的百分位阈值(p5/p15/p25/p50/p75/p85/p95)
|
|
|
|
|
+ - 新增:添加新的常模行
|
|
|
|
|
+ - 删除:删除常模行(带确认弹窗)
|
|
|
|
|
+ - 使用 Element UI 组件:el-table, el-form, el-dialog, el-input-number, el-button
|
|
|
|
|
+ - 调用后端API:
|
|
|
|
|
+ - 后端需新增 `HealthNormController`(或复用现有 admin controller)
|
|
|
|
|
+ - API: POST /api/admin/dimension/norm/list, /api/admin/dimension/norm/save, /api/admin/dimension/norm/delete
|
|
|
|
|
+ - 在 `router/index.js` 中添加路由: `/admin/dimension-config`
|
|
|
|
|
+ - 在 `store/` 中添加对应的 API 封装(或直接使用 axios)
|
|
|
|
|
+ - 从 `cfc-backend/` 中创建对应的 Controller:
|
|
|
|
|
+ - `controller/admin/DimensionAdminController.java`
|
|
|
|
|
+ - 注入 `HealthNormReferenceMapper` 进行 CRUD 操作
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不修改已有维度评分数据
|
|
|
|
|
+ - 不改动前端已有页面
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `quick`
|
|
|
|
|
+ - Reason: Standard CRUD admin panel, follows existing patterns
|
|
|
|
|
+ - **Skills**: []
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 3 (with Tasks 9, 10)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/entity/HealthNormReference.java` — 常模实体(dimension, gender, age, percentile5/15/25/50/75/85/95)
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/mapper/HealthNormReferenceMapper.java` — 已有 Mapper(含 `selectNorm` 方法)
|
|
|
|
|
+ - `cfc-web/src/views/admin/` — 其他管理端页面作为样式/模式参考
|
|
|
|
|
+ - `cfc-web/src/router/index.js` — 路由配置
|
|
|
|
|
+ - `.sisyphus/drafts/health-dimensions-design.md` §7.3 — 维度配置管理要求
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] 管理端可查看所有维度的常模列表
|
|
|
|
|
+ - [ ] 可编辑常模的百分位阈值
|
|
|
|
|
+ - [ ] 可新增常模行
|
|
|
|
|
+ - [ ] 可删除常模行(带确认)
|
|
|
|
|
+ - [ ] 后端API通过 `mvn clean compile`
|
|
|
|
|
+ - [ ] 路由 `/admin/dimension-config` 可访问
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: View and edit dimension norm
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: Admin is logged in to web admin
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Navigate to /admin/dimension-config
|
|
|
|
|
+ 2. Verify table shows dimension norms with all percentile columns
|
|
|
|
|
+ 3. Click edit on first row
|
|
|
|
|
+ 4. Change p95 value
|
|
|
|
|
+ 5. Click save
|
|
|
|
|
+ Expected Result: Norm value updated successfully
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-8-norm-edit.png
|
|
|
|
|
+
|
|
|
|
|
+ Scenario: Delete norm with confirmation
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: Admin on dimension-config page
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Click delete on a row
|
|
|
|
|
+ 2. Confirm deletion dialog
|
|
|
|
|
+ Expected Result: Row removed from table
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-8-norm-delete.png
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `feat(admin): add dimension config management`
|
|
|
|
|
+ - Files: `cfc-web/src/views/admin/dimension-config.vue` (new), `cfc-web/src/router/index.js`, `cfc-backend/src/main/java/com/etotem/cfc/controller/admin/DimensionAdminController.java` (new), `cfc-backend/src/main/resources/mapper/HealthNormReferenceMapper.xml` (if new queries needed)
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 9. Data Source Management (Web Admin) — 管理端数据源管理
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 在 `cfc-web/` 中创建新视图页面 `src/views/admin/data-source-config.vue`
|
|
|
|
|
+ - 功能:
|
|
|
|
|
+ - 列出 `health_data_sources` 表的所有数据源配置
|
|
|
|
|
+ - 编辑/新增/删除数据源行
|
|
|
|
|
+ - 使用 Element UI 组件
|
|
|
|
|
+ - 调用后端API:
|
|
|
|
|
+ - 后端新增 Controller: `POST /api/admin/dimension/data-source/list`, `/save`, `/delete`
|
|
|
|
|
+ - 可使用 `DimensionAdminController` 合并同类端点
|
|
|
|
|
+ - 在路由中添加 `/admin/data-source-config`
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不修改已有数据源数据
|
|
|
|
|
+ - 不重复造轮子(与Task 8共享Controller)
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `quick`
|
|
|
|
|
+ - Reason: Standard CRUD, essentially same pattern as Task 8
|
|
|
|
|
+ - **Skills**: []
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 3 (with Tasks 8, 10)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: None
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/entity/HealthDataSourceRecord.java` — 数据源实体
|
|
|
|
|
+ - Task 8 创建的 `DimensionAdminController.java` — 可复用同类端点
|
|
|
|
|
+ - `cfc-web/src/router/index.js`
|
|
|
|
|
+ - `.sisyphus/drafts/health-dimensions-design.md` §7.3 — 数据源配置要求
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] 管理端可查看所有数据源
|
|
|
|
|
+ - [ ] 可编辑/新增/删除数据源
|
|
|
|
|
+ - [ ] 后端API编译通过
|
|
|
|
|
+ - [ ] 路由 `/admin/data-source-config` 可访问
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: List and add data source
|
|
|
|
|
+ Tool: Playwright
|
|
|
|
|
+ Preconditions: Admin logged in
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. Navigate to /admin/data-source-config
|
|
|
|
|
+ 2. Verify table shows data sources
|
|
|
|
|
+ 3. Click "新增" button
|
|
|
|
|
+ 4. Fill form: name="测试源", type="MANUAL"
|
|
|
|
|
+ 5. Click save
|
|
|
|
|
+ Expected Result: New data source appears in table
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-9-datasource-add.png
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `feat(admin): add data source management`
|
|
|
|
|
+ - Files: `cfc-web/src/views/admin/data-source-config.vue` (new), `cfc-web/src/router/index.js`, `cfc-backend/src/main/java/com/etotem/cfc/controller/admin/DimensionAdminController.java`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 10. Unit Tests — 后端服务单元测试
|
|
|
|
|
+
|
|
|
|
|
+ **What to do**:
|
|
|
|
|
+ - 为以下后端服务编写JUnit + Mockito单元测试:
|
|
|
|
|
+ - `DimensionScoreServiceImpl` — 测试聚合逻辑、趋势计算、百分位计算、等级分类
|
|
|
|
|
+ - `ProductOrderService` — 测试支付成功后能量奖励调用(使用Mock验证)
|
|
|
|
|
+ - `DifySyncService` — 测试API调用(使用Mock RestTemplate)
|
|
|
|
|
+ - 测试结构:
|
|
|
|
|
+ - `cfc-backend/src/test/java/com/etotem/cfc/service/impl/DimensionScoreServiceImplTest.java`
|
|
|
|
|
+ - `cfc-backend/src/test/java/com/etotem/cfc/service/ProductOrderServiceTest.java`
|
|
|
|
|
+ - `cfc-backend/src/test/java/com/etotem/cfc/service/DifySyncServiceTest.java`
|
|
|
|
|
+ - 使用 `@SpringBootTest` 或直接 `MockitoExtension` + `@InjectMocks` + `@Mock`
|
|
|
|
|
+ - 使用 `MockMvc` 或直接调用 Service 方法
|
|
|
|
|
+ - 至少覆盖:
|
|
|
|
|
+ - DimensionScoreServiceImpl: 健康指数计算(全维度/部分维度)、趋势判定(up/down/stable)、百分位、等级
|
|
|
|
|
+ - ProductOrderService: pay()调用energyService、handlePaymentSuccess()调用energyService
|
|
|
|
|
+ - DifySyncService: syncToDify() send request、异常不传播
|
|
|
|
|
+
|
|
|
|
|
+ **Must NOT do**:
|
|
|
|
|
+ - 不编写集成测试(只写单元测试)
|
|
|
|
|
+ - 不测试已存在的前端页面(只测试新增/修改代码)
|
|
|
|
|
+ - 不过度Mock(只Mock外部依赖)
|
|
|
|
|
+
|
|
|
|
|
+ **Recommended Agent Profile**:
|
|
|
|
|
+ - **Category**: `quick`
|
|
|
|
|
+ - Reason: Standard unit test patterns
|
|
|
|
|
+ - **Skills**: []
|
|
|
|
|
+ - **Skills Evaluated but Omitted**: n/a
|
|
|
|
|
+
|
|
|
|
|
+ **Parallelization**:
|
|
|
|
|
+ - **Can Run In Parallel**: YES
|
|
|
|
|
+ - **Parallel Group**: Wave 3 (with Tasks 8, 9)
|
|
|
|
|
+ - **Blocks**: None
|
|
|
|
|
+ - **Blocked By**: Tasks 1-4 (需要实现完成才能测试)
|
|
|
|
|
+
|
|
|
|
|
+ **References**:
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/impl/DimensionScoreServiceImpl.java` — 被测类
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java` — 被测类
|
|
|
|
|
+ - `cfc-backend/src/main/java/com/etotem/cfc/service/DifySyncService.java` — 被测类
|
|
|
|
|
+ - `cfc-backend/pom.xml` — 测试依赖(Spring Boot Starter Test 应已有)
|
|
|
|
|
+
|
|
|
|
|
+ **Acceptance Criteria**:
|
|
|
|
|
+ - [ ] DimensionScoreServiceImplTest: 5个测试方法通过
|
|
|
|
|
+ - [ ] ProductOrderServiceTest: 2个测试方法通过
|
|
|
|
|
+ - [ ] DifySyncServiceTest: 2个测试方法通过
|
|
|
|
|
+ - [ ] `mvn test` 全部通过
|
|
|
|
|
+
|
|
|
|
|
+ **QA Scenarios**:
|
|
|
|
|
+ ```
|
|
|
|
|
+ Scenario: Run all unit tests
|
|
|
|
|
+ Tool: Bash
|
|
|
|
|
+ Preconditions: All backend implementation completed
|
|
|
|
|
+ Steps:
|
|
|
|
|
+ 1. cd cfc-backend
|
|
|
|
|
+ 2. mvn test
|
|
|
|
|
+ Expected Result: BUILD SUCCESS, all 9+ tests pass
|
|
|
|
|
+ Evidence: .sisyphus/evidence/task-10-test-results.log
|
|
|
|
|
+ ```
|
|
|
|
|
+
|
|
|
|
|
+ **Commit**: YES
|
|
|
|
|
+ - Message: `test(dimension): add unit tests for dimension services`
|
|
|
|
|
+ - Files: `cfc-backend/src/test/java/com/etotem/cfc/service/impl/DimensionScoreServiceImplTest.java` (new), `cfc-backend/src/test/java/com/etotem/cfc/service/ProductOrderServiceTest.java` (new), `cfc-backend/src/test/java/com/etotem/cfc/service/DifySyncServiceTest.java` (new)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Final Verification Wave (MANDATORY)
|
|
|
|
|
+
|
|
|
|
|
+> 4 review agents run in PARALLEL. ALL must APPROVE.
|
|
|
|
|
+
|
|
|
|
|
+- [ ] F1. **Plan Compliance Audit** — `oracle`
|
|
|
|
|
+ Read the plan end-to-end. For each "Must Have": verify implementation exists. For each "Must NOT Have": search codebase for forbidden patterns. Check evidence files exist. Compare deliverables against plan.
|
|
|
|
|
+ Output: `Must Have [N/N] | Must NOT Have [N/N] | Tasks [N/N] | VERDICT: APPROVE/REJECT`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] F2. **Code Quality Review** — `unspecified-high`
|
|
|
|
|
+ Run `mvn clean compile` + linter check. Review all changed files for: `as any`/`@SuppressWarnings`, empty catches, console.log in prod, commented-out code, unused imports.
|
|
|
|
|
+ Output: `Build [PASS/FAIL] | Files [N clean/N issues] | VERDICT`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] F3. **Real Manual QA** — `unspecified-high` (+ `playwright` skill if UI)
|
|
|
|
|
+ Execute EVERY QA scenario from EVERY task. Test cross-task integration. Test edge cases: empty state, invalid input.
|
|
|
|
|
+ Output: `Scenarios [N/N pass] | Integration [N/N] | VERDICT`
|
|
|
|
|
+
|
|
|
|
|
+- [ ] F4. **Scope Fidelity Check** — `deep`
|
|
|
|
|
+ For each task: read "What to do", read actual diff (git log/diff). Verify 1:1 compliance. Check "Must NOT do" compliance.
|
|
|
|
|
+ Output: `Tasks [N/N compliant] | Contamination [CLEAN/N issues] | VERDICT`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Commit Strategy
|
|
|
|
|
+
|
|
|
|
|
+- **Task 1**: `fix(dimension): calculate trend from score history instead of hardcoding`
|
|
|
|
|
+- **Task 2**: `feat(product): award energy on successful payment`
|
|
|
|
|
+- **Task 3**: `feat(dify): implement knowledge sync API and AI recommendation`
|
|
|
|
|
+- **Task 4**: `feat(dimension): integrate 7-dimension scores into body energy`
|
|
|
|
|
+- **Task 5**: `feat(body): add health-dimensions navigation entry`
|
|
|
|
|
+- **Task 6**: `feat(body): add dimension questionnaire page`
|
|
|
|
|
+- **Task 7**: `feat(body): add 7 dimension detail pages`
|
|
|
|
|
+- **Task 8**: `feat(admin): add dimension config management`
|
|
|
|
|
+- **Task 9**: `feat(admin): add data source management`
|
|
|
|
|
+- **Task 10**: `test(dimension): add unit tests for dimension services`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## Success Criteria
|
|
|
|
|
+
|
|
|
|
|
+### Verification Commands
|
|
|
|
|
+```bash
|
|
|
|
|
+cd cfc-backend && mvn clean compile # Expected: BUILD SUCCESS
|
|
|
|
|
+cd cfc-backend && mvn test # Expected: Tests pass
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### Final Checklist
|
|
|
|
|
+- [ ] All 10 "Must Have" present
|
|
|
|
|
+- [ ] All "Must NOT Have" absent
|
|
|
|
|
+- [ ] All tests pass
|
|
|
|
|
+- [ ] No regression in existing dimension functionality
|