Преглед на файлове

docs: update health dimensions design spec - add product-dimension integration section

Added Section 8: 商品与维度的联动设计
- Product list: ProductController/Service, DimensionProducts component
- AI recommendations: RecommendationService (tag-based LIKE), DifySyncService (TODO)
- Energy on purchase: NOT implemented - ProductOrder.pay() doesn't call awardEnergy()
- Proposed improvements documented in Section 8.2
Sisyphus преди 2 месеца
родител
ревизия
62e7da5760
променени са 1 файла, в които са добавени 102 реда и са изтрити 2 реда
  1. 102 2
      docs/superpowers/specs/2026-06-26-health-dimensions-design-spec.md

+ 102 - 2
docs/superpowers/specs/2026-06-26-health-dimensions-design-spec.md

@@ -390,16 +390,116 @@ CREATE TABLE health_norm_reference (
 
 ---
 
-## 8. 待确认问题
+## 8. 商品与维度的联动设计
+
+### 8.1 现有代码调研结论
+
+经过对后端/前端代码的全面探索,以下是当前商品模块的实际实现状态:
+
+#### 商品列表(已实现)
+
+| 层级 | 文件 | 说明 |
+|------|------|------|
+| 后端 | `ProductController.java` (`/api/product/*`) | 商品 CRUD、上下架、审核 |
+| 后端 | `ProductService.java` | 商品管理核心逻辑 |
+| 后端 | `ProductCategoryService.java` | 两级分类管理 |
+| 前端 | `pages/body/index.vue` → `loadDimensionProducts()` | 身体 Tab 调用 `getProductsByDomain('body', page, size)` |
+| 前端 | `DimensionProducts.vue` | 通用维度商品展示组件(2列卡片网格) |
+| 前端 | `pages/shop/index.vue` | 完整商城页(两级分类 + 分页加载) |
+| 前端 | `pages/discover/index.vue` | 发现页热门推荐(按 productType 筛选) |
+
+**数据结构**:`products` 表(status: pending/on_shelf/off_shelf/approved/rejected)+ `product_categories` 表(parent-child 自关联)
+
+#### AI 商品推荐(部分实现,待完善)
+
+| 组件 | 文件 | 现状 |
+|------|------|------|
+| 推荐引擎 | `RecommendationService.java` | 基于 `nutritionTags` 模糊搜索 `name`/`description`,非真正 AI 推荐 |
+| Dify 集成 | `DifySyncService.java` | 有 TODO 注释,实际未完成:`// 根据 dimensionCode 查找 product_dimension_config 中的 dify_dataset_id` |
+| 配置表 | `product_dimension_config` | 有 `difyDatasetId` 字段,但数据为空 |
+| 前端 | `pages/discover/product-detail/` | 有商品详情页,未接入 AI 推荐 |
+
+**推荐流程(当前)**:用户营养标签 → `RecommendationService.search()` → LIKE 模糊匹配商品 name/description → 返回 `RecommendationResult`(product/activity/article 三类)
+
+#### 购买后能量变化(**未实现**)
+
+| 数据模型 | 现状 |
+|----------|------|
+| `EnergyLog.sourceType` | 注释支持 "product" 类型,但代码中无触发路径 |
+| `EnergySourceConfig` | 表设计支持 `sourceType=product` + ratio 比例分配,需管理员预配置 |
+| `ProductDimensionConfig` | 有 `dimensionCode` + `dimensionType`,但无商品绑定数据 |
+
+**当前已实现的能量来源**:task、emotion_checkin、health_checkin、streak、game、article、appointment、activity、checkin
+
+**缺失**:商品支付成功后**未调用** `energyService.awardEnergy()`,能量系统对商品购买无感知。
+
+### 8.2 设计改进方案
+
+#### 改进1:商品购买后自动发放能量
+
+```
+用户支付成功(ProductOrder status: pending → paid)
+        │
+        ▼
+ProductOrderService.handlePaymentSuccess() / pay()
+        │
+        ├─ 检查 energy_source_config 中是否存在 sourceType=product, sourceId={商品ID} 的配置
+        ├─ 如有:按 ratio 比例分配能量至各维度
+        └─ 如无:使用商品默认能量值(由 ProductDimensionConfig.dimensionCode 决定基础维度)
+```
+
+**新增接口**:
+- `POST /api/energy/award-from-product` — 手动触发商品能量发放(用于补偿漏发场景)
+- `POST /api/admin/energy-source-config` — 管理员配置商品-维度-能量映射
+
+**Product 实体扩展**(可选):
+- 新增 `energyAmount` 字段:购买该商品赠送的能量值
+- 新增 `primaryDimension` 字段:主维度的 dimensionCode
+
+#### 改进2:Dify AI 商品推荐落地
+
+```
+用户进入身体 Tab → 加载7维健康数据
+        │
+        ▼
+获取营养缺乏标签(NutritionDeficiencyRecord)
+        │
+        ▼
+调用 Dify API(datasetId 来自 product_dimension_config)
+        │
+        ▼
+返回推荐的商品列表(排序:相关度 × 维度匹配度)
+        │
+        ▼
+前端 DimensionProducts 组件展示
+```
+
+**前提条件**:
+- `product_dimension_config` 表填充 `difyDatasetId`(目前为空)
+- Dify 中建立商品知识库,包含商品维度标签(growth/sleep/vision/immunity/nutrition/gut/exercise)
+
+### 8.3 现有代码文件索引
+
+| 功能 | 后端关键文件 | 前端关键文件 |
+|------|------------|------------|
+| 商品列表/分类 | `ProductController.java`, `ProductService.java`, `ProductMapper.java`, `ProductCategoryService.java` | `pages/shop/index.vue`, `pages/body/index.vue`, `DimensionProducts.vue` |
+| AI 推荐 | `RecommendationService.java`(推荐引擎), `DifySyncService.java`(Dify 集成) | `pages/discover/index.vue`, `pages/discover/product-detail/` |
+| 能量变化 | `EnergySourceConfig.java`(配置表), `ProductDimensionConfig.java`(维度配置), `EnergyLog.java`(流水) | 暂无前端入口 |
+
+---
+
+## 9. 待确认问题
 
 - [ ] 舌诊AI方案:自研基于颜色/纹理分类 vs 接入第三方API(如百度AI舌诊)
 - [ ] 体脂称:支持哪些品牌的屏幕布局,是否需要通用OCR适配层
 - [ ] 语音模型:用微信内置语音识别还是自建ASR
 - [ ] 常模数据:BMI百分位表是硬编码在代码中还是做成可配置表
+- [x] **商品能量触发**:当前 ProductOrder 支付成功后**未调用** awardEnergy,需在 ProductOrderService 中新增能量发放逻辑(见 8.2 改进方案)
+- [ ] **Dify 推荐落地**:`product_dimension_config.difyDatasetId` 为空,需填充实际数据集 ID 并完成 DifySyncService 调用链路
 
 ---
 
-## 9. 附录:7维与五维能量「身」的衔接
+## 10. 附录:7维与五维能量「身」的衔接
 
 ```
 五维「身」能量值 = Σ(7维子维度分 × 权重)