# 五维能量系统设计 **日期:** 2026-06-05 **状态:** 已确认,待实施 **分支:** cfclub ## 概述 本项目服务于身、心、智、行、富五个维度,服务内容包括活动、课程、商品、任务、咨询五大类。每个服务实例可影响多个维度,能量值按比例分配。能量系统为全新独立系统,与现有积分系统并行但解耦。 ### 关键决策 | 决策项 | 结论 | |--------|------| | 维度比例配置方式 | 按服务实例配置(每个具体任务/课程/商品创建时可指定维度比例) | | 能量值性质 | 可消耗值(类似积分,可增可减) | | 健康指数算法 | 待定,先搭框架返回0占位 | | 与积分系统关系 | 全新独立系统,不复用积分 | | 架构方案 | 方案B:维度定义表+流水表+余额表 | ## 1. 数据模型 ### 1.1 energy_dimension — 维度定义表 | 列名 | 类型 | 说明 | |------|------|------| | id | BIGINT AUTO_INCREMENT PK | | | code | VARCHAR(16) UNIQUE | body/mind/wisdom/action/wealth | | name | VARCHAR(20) | 身/心/智/行/富 | | icon | VARCHAR(16) | 🌏/🔥/⚔️/🌿/💧 | | element | VARCHAR(10) | 土/火/金/木/水 | | sort_order | INT | 显示顺序 | | status | TINYINT DEFAULT 1 | 1启用/0禁用 | 种子数据: | code | name | icon | element | sort_order | |------|------|------|---------|------------| | mind | 心 | 🔥 | 火 | 1 | | action | 行 | 🌿 | 木 | 2 | | wealth | 富 | 💧 | 水 | 3 | | wisdom | 智 | ⚔️ | 金 | 4 | | body | 身 | 🌏 | 土 | 5 | ### 1.2 energy_source_config — 服务-维度比例配置表 | 列名 | 类型 | 说明 | |------|------|------| | id | BIGINT AUTO_INCREMENT PK | | | source_type | VARCHAR(32) | task/activity/course/product/consultation | | source_id | BIGINT | 对应业务表ID | | source_name | VARCHAR(200) | 冗余名称,方便展示 | | dimension_id | BIGINT | 维度ID | | ratio | DECIMAL(5,4) | 该维度占比,如0.6000=60% | | created_at | DATETIME DEFAULT CURRENT_TIMESTAMP | | 约束:同一 source_type+source_id 的所有 ratio 之和应 = 1.0。一个服务实例配多行记录。 示例:任务#42 → 行60%+心40% = 2行记录。 ### 1.3 energy_log — 能量流水表 | 列名 | 类型 | 说明 | |------|------|------| | id | BIGINT AUTO_INCREMENT PK | | | child_id | BIGINT | 孩子ID | | dimension_id | BIGINT | 维度ID | | amount | INT | 变动量(正=获得,负=消耗) | | balance_after | INT | 变动后该维度余额 | | source_type | VARCHAR(32) | 来源类型 | | source_id | BIGINT | 来源ID | | description | VARCHAR(500) | 描述 | | created_at | DATETIME DEFAULT CURRENT_TIMESTAMP | | 索引:`idx_child_dim (child_id, dimension_id)`,`idx_created (created_at)` ### 1.4 energy_balance — 各维度当前余额表 | 列名 | 类型 | 说明 | |------|------|------| | id | BIGINT AUTO_INCREMENT PK | | | child_id | BIGINT | 孩子ID | | dimension_id | BIGINT | 维度ID | | balance | INT DEFAULT 0 | 当前能量值 | | total_earned | INT DEFAULT 0 | 累计获得 | | total_spent | INT DEFAULT 0 | 累计消耗 | | updated_at | DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | | UNIQUE(child_id, dimension_id) ### 1.5 API 响应结构 ```json GET /api/energy/overview?childId=123 { "code": 0, "data": { "dimensions": [ { "code": "mind", "name": "心", "icon": "🔥", "element": "火", "energy": 280, "healthIndex": 0 }, { "code": "action", "name": "行", "icon": "🌿", "element": "木", "energy": 350, "healthIndex": 0 }, { "code": "wealth", "name": "富", "icon": "💧", "element": "水", "energy": 200, "healthIndex": 0 }, { "code": "wisdom", "name": "智", "icon": "⚔️", "element": "金", "energy": 310, "healthIndex": 0 }, { "code": "body", "name": "身", "icon": "🌏", "element": "土", "energy": 380, "healthIndex": 0 } ], "totalEnergy": 1520, "totalHealthIndex": 0 } } ``` healthIndex 和 totalHealthIndex 算法待定,先返回0。 ## 2. 后端服务架构 ### 2.1 新增文件清单 | 文件 | 位置 | 职责 | |------|------|------| | EnergyDimension | entity/ | 维度定义实体 | | EnergySourceConfig | entity/ | 服务-维度比例配置实体 | | EnergyLog | entity/ | 能量流水实体 | | EnergyBalance | entity/ | 维度余额实体 | | EnergyDimensionMapper | mapper/ | 维度CRUD | | EnergySourceConfigMapper | mapper/ | 比例配置CRUD | | EnergyLogMapper | mapper/ | 流水查询 | | EnergyBalanceMapper | mapper/ | 余额查询/更新 | | EnergyService | service/ | 核心业务:发放/扣除能量、查余额、算指数 | | EnergyController | controller/energy/ | API入口:概览、流水、配置 | ### 2.2 EnergyService 核心方法 ```java /** * 发放能量 — 指定source_type+source_id,自动查比例配置,按比例分配到各维度 * @return 各维度实际发放量 Map */ Map awardEnergy(Long childId, String sourceType, Long sourceId, Integer totalAmount, String description) /** * 扣除能量 — 指定维度,检查余额,余额不足返回-1 * @return 扣除后余额,-1表示余额不足 */ int deductEnergy(Long childId, Long dimensionId, Integer amount, String reason) /** * 查询概览 — 返回5维度能量值+健康指数+总能量+总指数 */ Map getOverview(Long childId) /** * 查询流水 — 按维度筛选,分页 */ Page getLogs(Long childId, String dimensionCode, Integer page, Integer size) /** * 配置比例 — 为某服务实例设置维度比例 * ratios: [{dimensionCode:"action", ratio:0.6}, {dimensionCode:"mind", ratio:0.4}] */ void configureSourceRatios(String sourceType, Long sourceId, String sourceName, List> ratios) ``` ### 2.3 与现有系统的集成点 | 业务场景 | 调用位置 | 调用方式 | |----------|----------|----------| | 完成任务 | TaskService.completeTask() | energyService.awardEnergy(childId, "task", taskId, energyAmount, "完成任务: "+title) | | 购买商品 | 商品订单支付成功回调 | energyService.awardEnergy(childId, "product", productId, energyAmount, "购买商品: "+name) | | 参加活动 | 活动报名/签到 | energyService.awardEnergy(childId, "activity", activityId, energyAmount, "参加活动: "+title) | | 课程学习 | 课程完成/打卡 | energyService.awardEnergy(childId, "course", courseId, energyAmount, "完成课程: "+title) | | 咨询完成 | 咨询结束后 | energyService.awardEnergy(childId, "consultation", consultId, energyAmount, "完成咨询") | 能量发放额度由各业务方自行决定,EnergyService只负责按比例分配。 ### 2.4 awardEnergy 核心流程 ``` 1. 根据 sourceType+sourceId 查 energy_source_config 获取比例列表 2. 若无配置,查 Product.domain 作为 fallback(单维度100%) 3. 若仍无配置,默认分配到"行"维度100% 4. 按 ratio * totalAmount 计算各维度发放量(整数,余数加到最大比例维度) 5. 对每个维度: a. 查 energy_balance 获取当前余额 b. 计算新余额 c. 更新 energy_balance d. 写入 energy_log 6. 返回各维度实际发放量 ``` ## 3. 前端可视化设计 ### 3.1 五角形布局(从顶点顺时针) ``` 顶: 心·火 左上: 行·木 右上: 富·水 左下: 智·金 右下: 身·土 ``` ### 3.2 三层视觉结构 **外层 — 维度角(五角形顶点)** 每个角显示: - 图标 + 名称(如 🔥心·火) - 能量值:绝对数字,如 `320` - 点击可跳转该维度详情页 **中层 — 健康指数扇区(角底边→中心的三角形区域)** 每个维度的三角形区域外围显示该维度的健康指数: - 数字显示,如 `78` - 背景色按指数高低渐变(绿→黄→红) - 指数算法待定,先显示0占位 **内层 — 中心圆** 中央圆形区域显示: - 总体能量值:五维度能量值之和,如 `1520` - 总体健康指数:综合指数,如 `75` - 算法待定,先显示0占位 ### 3.3 wuxing-sandbox.vue Props 接口 ```js props: { mode: String, // 'preview' | 'parent' | 'child' dimensions: { // API返回的维度数据 type: Array, default: () => [] }, totalEnergy: { type: Number, default: 0 }, totalHealthIndex: { type: Number, default: 0 } } ``` dimensions 数组元素结构: ```json { "code": "body", "name": "身", "icon": "🌏", "element": "土", "energy": 320, "healthIndex": 0 } ``` ### 3.4 新增页面 | 页面 | 路径 | 说明 | |------|------|------| | 维度详情页 | pages/energy/detail.vue | 某维度能量值、流水记录、提升建议 | 在 pages.json 中注册(非TabBar页),从沙盘点位点击 navigateTo 进入。 ### 3.5 API 调用 ```js // utils/api.js 新增 getEnergyOverview(childId) // POST /api/energy/overview getEnergyLogs(childId, dimensionCode, page, size) // POST /api/energy/logs ``` ### 3.6 现有引用更新 | 页面 | 当前用法 | 更新为 | |------|----------|--------| | parent-index.vue | `` | 传入从API获取的 dimensions/totalEnergy/totalHealthIndex | | child-index.vue | `` | 同上 | | discover/index.vue | `` | 保持预览模式,用空数据 | ## 4. 数据库迁移与兼容性 ### 4.1 DatabaseInitializer 迁移步骤 1. 创建4张新表(IF NOT EXISTS) 2. 插入5条维度种子数据 3. 为现有Product种子数据插入默认 energy_source_config(1:1单维度映射,与当前Product.domain一致) 4. 为任务模板插入默认比例配置(任务默认→行100%) ### 4.2 现有系统兼容 | 项目 | 处理方式 | |------|----------| | 积分系统(PointsService) | 完全不动,能量系统独立运行 | | TaskService.completeTask() | 新增一行 energyService.awardEnergy(...) 调用,积分和能量并行发放 | | Product.domain 字段 | 保留不删除,作为无 energy_source_config 时的 fallback | | wuxing-sandbox.vue | 组件接口从硬编码改为接收 props 数据 | | 前端3处引用 | parent-index/child-index/discover 传入实际数据 | ### 4.3 无比例配置时的 Fallback 链 ``` 1. 查 energy_source_config → 有 → 使用配置比例 2. 无 → source_type 为 "product" 时查 Product.domain → 有 → 单维度100% 3. 无 → 默认分配到"行"维度100% ``` ## 5. 待定事项 | 事项 | 说明 | 影响 | |------|------|------| | 健康指数算法 | 各维度健康指数 + 总体健康指数的计算公式 | API返回0占位,不影响数据结构 | | 能量过期/衰减 | 是否需要能量值过期机制 | 暂不实现,energy_log.created_at 可支撑后续时间窗口计算 | | Web管理端 | 管理端维度比例配置页面 | 本次只做后端API,管理端UI后续迭代 | | 能量兑换/消耗 | 扣除能量的具体业务场景 | deductEnergy 方法已预留,具体场景待定 |