日期: 2026-06-05 状态: 已确认,待实施 分支: cfclub
本项目服务于身、心、智、行、富五个维度,服务内容包括活动、课程、商品、任务、咨询五大类。每个服务实例可影响多个维度,能量值按比例分配。能量系统为全新独立系统,与现有积分系统并行但解耦。
| 决策项 | 结论 |
|---|---|
| 维度比例配置方式 | 按服务实例配置(每个具体任务/课程/商品创建时可指定维度比例) |
| 能量值性质 | 可消耗值(类似积分,可增可减) |
| 健康指数算法 | 待定,先搭框架返回0占位 |
| 与积分系统关系 | 全新独立系统,不复用积分 |
| 架构方案 | 方案B:维度定义表+流水表+余额表 |
| 列名 | 类型 | 说明 |
|---|---|---|
| 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 |
| 列名 | 类型 | 说明 |
|---|---|---|
| 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行记录。
| 列名 | 类型 | 说明 |
|---|---|---|
| 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)
| 列名 | 类型 | 说明 |
|---|---|---|
| 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)
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。
| 文件 | 位置 | 职责 |
|---|---|---|
| EnergyDimension | entity/ | 维度定义实体 |
| EnergySourceConfig | entity/ | 服务-维度比例配置实体 |
| EnergyLog | entity/ | 能量流水实体 |
| EnergyBalance | entity/ | 维度余额实体 |
| EnergyDimensionMapper | mapper/ | 维度CRUD |
| EnergySourceConfigMapper | mapper/ | 比例配置CRUD |
| EnergyLogMapper | mapper/ | 流水查询 |
| EnergyBalanceMapper | mapper/ | 余额查询/更新 |
| EnergyService | service/ | 核心业务:发放/扣除能量、查余额、算指数 |
| EnergyController | controller/energy/ | API入口:概览、流水、配置 |
/**
* 发放能量 — 指定source_type+source_id,自动查比例配置,按比例分配到各维度
* @return 各维度实际发放量 Map<dimensionCode, amount>
*/
Map<String, Integer> 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<String, Object> getOverview(Long childId)
/**
* 查询流水 — 按维度筛选,分页
*/
Page<EnergyLog> 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<Map<String, Object>> ratios)
| 业务场景 | 调用位置 | 调用方式 |
|---|---|---|
| 完成任务 | 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只负责按比例分配。
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. 返回各维度实际发放量
顶: 心·火
左上: 行·木 右上: 富·水
左下: 智·金 右下: 身·土
外层 — 维度角(五角形顶点) 每个角显示:
320中层 — 健康指数扇区(角底边→中心的三角形区域) 每个维度的三角形区域外围显示该维度的健康指数:
78内层 — 中心圆 中央圆形区域显示:
152075props: {
mode: String, // 'preview' | 'parent' | 'child'
dimensions: { // API返回的维度数据
type: Array,
default: () => []
},
totalEnergy: {
type: Number,
default: 0
},
totalHealthIndex: {
type: Number,
default: 0
}
}
dimensions 数组元素结构:
{ "code": "body", "name": "身", "icon": "🌏", "element": "土", "energy": 320, "healthIndex": 0 }
| 页面 | 路径 | 说明 |
|---|---|---|
| 维度详情页 | pages/energy/detail.vue | 某维度能量值、流水记录、提升建议 |
在 pages.json 中注册(非TabBar页),从沙盘点位点击 navigateTo 进入。
// utils/api.js 新增
getEnergyOverview(childId) // POST /api/energy/overview
getEnergyLogs(childId, dimensionCode, page, size) // POST /api/energy/logs
| 页面 | 当前用法 | 更新为 |
|---|---|---|
| parent-index.vue | <wuxing-sandbox mode="parent" badgeText="综合成长力 0%" /> |
传入从API获取的 dimensions/totalEnergy/totalHealthIndex |
| child-index.vue | <wuxing-sandbox mode="child" badgeText="综合 0%" /> |
同上 |
| discover/index.vue | <wuxing-sandbox mode="preview" badgeText="登录查看完整报告" /> |
保持预览模式,用空数据 |
| 项目 | 处理方式 |
|---|---|
| 积分系统(PointsService) | 完全不动,能量系统独立运行 |
| TaskService.completeTask() | 新增一行 energyService.awardEnergy(...) 调用,积分和能量并行发放 |
| Product.domain 字段 | 保留不删除,作为无 energy_source_config 时的 fallback |
| wuxing-sandbox.vue | 组件接口从硬编码改为接收 props 数据 |
| 前端3处引用 | parent-index/child-index/discover 传入实际数据 |
1. 查 energy_source_config → 有 → 使用配置比例
2. 无 → source_type 为 "product" 时查 Product.domain → 有 → 单维度100%
3. 无 → 默认分配到"行"维度100%
| 事项 | 说明 | 影响 |
|---|---|---|
| 健康指数算法 | 各维度健康指数 + 总体健康指数的计算公式 | API返回0占位,不影响数据结构 |
| 能量过期/衰减 | 是否需要能量值过期机制 | 暂不实现,energy_log.created_at 可支撑后续时间窗口计算 |
| Web管理端 | 管理端维度比例配置页面 | 本次只做后端API,管理端UI后续迭代 |
| 能量兑换/消耗 | 扣除能量的具体业务场景 | deductEnergy 方法已预留,具体场景待定 |