# 能量配置管理系统设计 ## 当前问题 1. **能量来源分散**:19个来源的能能量值硬编码在 Java 代码中,修改需要改代码+重新部署 2. **维度分配单一**:所有来源默认全部归入 action(行)维度,其他维度几乎没有能量流入 3. **缺少配置管理**:无法通过管理后台动态调整能量发放规则 4. **消费体系不完整**:目前只有心愿兑换扣减和未报名签到惩罚两种消耗 ## 设计目标 | 目标 | 说明 | |------|------| | 可配置 | 管理员通过后台配置每种行为给多少能量、分到哪些维度 | | 维度均衡 | 不同行为分配到不同维度,五维都有能量流入 | | 消费闭环 | 每种能量有对应的消费场景,消费后可转化为其他能量或权益 | | 实时生效 | 配置变更后即时生效,无需重启 | ## 一、能量来源配置(energy_source_config 增强) ### 当前表结构(不完整) ```sql CREATE TABLE energy_source_config ( id BIGINT AUTO_INCREMENT PRIMARY KEY, source_type VARCHAR(32) NOT NULL COMMENT '来源类型: task/game/activity/...', source_id BIGINT COMMENT '来源ID(0=全局配置)', dimension_id BIGINT NOT NULL COMMENT '维度ID', ratio INT NOT NULL COMMENT '分配比例(10000=100%)', created_at DATETIME ); ``` ### 增强后的表结构 ```sql CREATE TABLE energy_behavior_config ( id BIGINT AUTO_INCREMENT PRIMARY KEY, behavior_code VARCHAR(32) NOT NULL UNIQUE COMMENT '行为编码: task_complete/game_finish/...', behavior_name VARCHAR(50) NOT NULL COMMENT '行为名称: 完成任务/完成游戏/...', description VARCHAR(200) COMMENT '行为描述', default_amount INT NOT NULL DEFAULT 5 COMMENT '默认能量值', amount_source VARCHAR(32) DEFAULT 'fixed' COMMENT '能量值来源: fixed(固定)/points(跟随积分)/order_amount(跟随金额)/config(从配置表读取)', dimension_assign JSON NOT NULL COMMENT '维度分配: [{"dim":"body","ratio":50},{"dim":"action","ratio":50}]', daily_limit INT DEFAULT 0 COMMENT '每日上限(0=不限制)', cooldown_seconds INT DEFAULT 0 COMMENT '冷却时间(秒,0=无冷却)', expire_days INT DEFAULT 0 COMMENT '过期天数(0=永久)', enabled TINYINT DEFAULT 1 COMMENT '是否启用', created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_behavior_code (behavior_code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='能量行为配置表'; ``` ### 预置行为配置 | behavior_code | behavior_name | 默认值 | 维度分配 | 说明 | |--------------|---------------|--------|---------|------| | `task_complete` | 完成任务 | =积分 | body:0, mind:0, wisdom:0, action:100, wealth:0 | 任务奖励归行 | | `game_finish` | 完成游戏 | =积分 | body:0, mind:30, wisdom:50, action:20, wealth:0 | 游戏益智归智+心 | | `activity_checkin` | 活动签到 | 5 | body:30, mind:0, wisdom:0, action:70, wealth:0 | 活动归行+身 | | `article_read` | 阅读文章 | =积分 | body:0, mind:30, wisdom:50, action:20, wealth:0 | 阅读归智+心 | | `product_purchase` | 商品购买 | =金额 | body:0, mind:0, wisdom:0, action:0, wealth:100 | 消费归富 | | `health_checkin` | 健康打卡 | 5 | body:100, mind:0, wisdom:0, action:0, wealth:0 | 健康归身 | | `finance_checkin` | 理财打卡 | 5 | body:0, mind:0, wisdom:0, action:0, wealth:100 | 理财归富 | | `emotion_checkin` | 情绪打卡 | 5 | body:0, mind:100, wisdom:0, action:0, wealth:0 | 情绪归心 | | `appointment_submit` | 提交测评预约 | 10 | body:0, mind:0, wisdom:0, action:100, wealth:0 | 预约归行 | | `appointment_complete` | 完成测评 | 30 | body:0, mind:50, wisdom:50, action:0, wealth:0 | 测评归心+智 | | `streak_daily` | 连续打卡每日 | 5 | body:30, mind:20, wisdom:0, action:50, wealth:0 | 坚持归行+身 | | `streak_milestone` | 打卡里程碑 | 配置值 | body:30, mind:20, wisdom:0, action:50, wealth:0 | 里程碑归行+身 | | `growth_task` | 成长任务 | 配置值 | 按任务维度 | 跟随任务配置 | | `micro_action` | 微行动 | 1 | body:0, mind:0, wisdom:0, action:100, wealth:0 | 微行动归行 | | `onboarding` | 新手引导 | 配置值 | body:20, mind:20, wisdom:20, action:20, wealth:20 | 引导均衡分配 | | `invite_milestone` | 邀请里程碑 | 配置值 | body:0, mind:20, wisdom:0, action:40, wealth:40 | 邀请归行+富 | | `dimension_sync` | 维度同步 | 计算值 | 按评分维度 | 跟随评分 | | **`invite_friend`** | **邀请好友加入** | **20** | **body:0, mind:0, wisdom:0, action:50, wealth:50** | **新增: 邀请好友归行+富** | | **`invite_family`** | **邀请家庭成员** | **10** | **body:0, mind:30, wisdom:0, action:40, wealth:0** | **新增: 邀家人归行+心** | | **`report_upload`** | **上传体检报告** | **30** | **body:100, mind:0, wisdom:0, action:0, wealth:0** | **新增: 体检归身** | | **`plan_complete`** | **完成规划计划** | **20** | **按计划维度** | **新增: 跟随计划维度** | | **`wisdom_report`** | **上传智测评报告** | **30** | **body:0, mind:0, wisdom:100, action:0, wealth:0** | **新增: 智测评归智** | ## 二、能量消费配置 ### 消费表结构 ```sql CREATE TABLE energy_consumption_config ( id BIGINT AUTO_INCREMENT PRIMARY KEY, consumption_code VARCHAR(32) NOT NULL UNIQUE COMMENT '消费编码: coupon_exchange/wish_redeem/...', consumption_name VARCHAR(50) NOT NULL COMMENT '消费名称: 兑换优惠券/心愿兑换/...', source_dimension VARCHAR(20) NOT NULL COMMENT '消耗维度: wealth/action/body/mind/wisdom', amount INT NOT NULL COMMENT '消耗数量', target_type VARCHAR(32) NOT NULL COMMENT '目标类型: coupon(优惠券)/energy(能量转换)/points(积分)/...', target_id BIGINT COMMENT '目标ID(如优惠券ID,0=通用)', convert_dimension VARCHAR(20) COMMENT '转换目标维度(当target_type=energy时)', convert_ratio INT DEFAULT 100 COMMENT '转换比例(100=100%, 消耗N获得N)', min_balance INT DEFAULT 0 COMMENT '最低余额要求', description VARCHAR(200) COMMENT '消费描述', enabled TINYINT DEFAULT 1, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, INDEX idx_consumption_code (consumption_code) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='能量消费配置表'; ``` ### 预置消费配置 | consumption_code | 消耗维度 | 消耗量 | 目标类型 | 转换/结果 | 说明 | |-----------------|---------|--------|---------|-----------|------| | `coupon_exchange` | wealth(富) | 100 | coupon | 兑换10元优惠券 | 消耗富能量得优惠券 | | `wish_redeem` | action(行) | 变量 | wish | 完成心愿兑换 | 消耗行能量兑换心愿 | | `energy_convert_wealth_to_action` | wealth(富) | 变量 | energy→action | 1:1 转为行动能量 | 富→行转换 | | `energy_convert_action_to_body` | action(行) | 变量 | energy→body | 1:1 转为身体能量 | 行→身转换 | | `energy_convert_wealth_to_wisdom` | wealth(富) | 变量 | energy→wisdom | 2:1 转为智慧能量 | 富→智转换(损耗) | | `activity_penalty` | 活动维度 | 变量 | penalty | 未报名签到扣减 | 惩罚扣减 | ## 三、能量转换规则 ### 五维相生转换 ``` 身(body) → 可通过运动/健康行为获得 心(mind) → 可通过情绪管理/心理活动获得 智(wisdom) → 可通过学习/测评/阅读获得 行(action) → 可通过任务/活动/坚持获得 富(wealth) → 可通过消费/推广/理财获得 ``` ### 允许的转换(消耗一种能量,获得另一种) | 转换 | 消耗 | 获得 | 比例 | 场景 | |------|------|------|------|------| | 富→行 | 100 富 | 100 行 | 1:1 | 财富能量兑换优惠券时触发 | | 富→智 | 200 富 | 100 智 | 2:1 | 购买课程/学习资源 | | 行→身 | 50 行 | 50 身 | 1:1 | 运动消耗转化 | | 行→心 | 50 行 | 50 心 | 1:1 | 社交活动转化 | | 心→智 | 30 心 | 30 智 | 1:1 | 情绪稳定后学习效率提升 | | 身→行 | 30 身 | 30 行 | 1:1 | 身体健康后行动力提升 | ## 四、管理后台界面设计 ### 4.1 能量行为配置页 ``` ┌─────────────────────────────────────────────────────┐ │ 能量行为配置 │ │ ┌──────┬────────┬──────┬────────────┬───────────┐ │ │ │ 行为 │ 默认值 │ 维度分配 │ 每日上限 │ 操作 │ │ │ ├──────┼────────┼──────┼────────────┼───────────┤ │ │ │完成任务│ =积分 │ 行100% │ 200 │ ✏️ ⛔ │ │ │ │完成游戏│ =积分 │ 智50% │ 200 │ ✏️ ⛔ │ │ │ │健康打卡│ 5 │ 身100% │ 50 │ ✏️ ⛔ │ │ │ │ ... │ ... │ ... │ ... │ ... │ │ │ └──────┴────────┴──────┴────────────┴───────────┘ │ │ [+ 新增行为] │ └─────────────────────────────────────────────────────┘ ``` ### 4.2 能量消费配置页 ``` ┌─────────────────────────────────────────────────────┐ │ 能量消费配置 │ │ ┌──────────┬────────┬──────┬────────┬───────────┐ │ │ │ 消费场景 │ 消耗维度 │ 数量 │ 获得 │ 操作 │ │ │ ├──────────┼────────┼──────┼────────┼───────────┤ │ │ │兑换优惠券│ 富 │ 100 │ 10元券 │ ✏️ ⛔ │ │ │ │富→行转换 │ 富 │ 变量 │ 行1:1 │ ✏️ ⛔ │ │ │ │ ... │ ... │ ... │ ... │ ... │ │ │ └──────────┴────────┴──────┴────────┴───────────┘ │ │ [+ 新增消费] │ └─────────────────────────────────────────────────────┘ ``` ## 五、后端实现方案 ### 5.1 能量发放流程改造 ``` 当前流程: Hardcode: awardEnergy(childId, "task", taskId, points, "描述", null) ↓ 改造后流程: EnergyBehaviorConfig config = getConfig("task_complete"); if (config != null && config.enabled) { int amount = resolveAmount(config, context); // 从配置或上下文计算 Map dimMap = config.getDimensionAssign(); awardEnergyByDim(childId, dimMap, amount, "task", taskId, "描述"); } else { // 无配置时使用默认行为(保持兼容) awardEnergy(childId, "task", taskId, points, "描述", null); } ``` ### 5.2 维度分配发放 ```java public void awardEnergyByDim(Long childId, Map dimRatios, Integer totalAmount, String sourceType, Long sourceId, String description) { // 按比例分配到各维度 for (Map.Entry entry : dimRatios.entrySet()) { String dimCode = entry.getKey(); int ratio = entry.getValue(); // 如 50 表示50% int dimAmount = totalAmount * ratio / 100; if (dimAmount > 0) { awardEnergyByDimCode(childId, dimCode, dimAmount, sourceType, sourceId, description); } } } ``` ### 5.3 消费/转换流程 ```java @Transactional public Result consumeEnergy(Long childId, String consumptionCode, Map params) { EnergyConsumptionConfig config = getConsumptionConfig(consumptionCode); if (config == null || !config.enabled) return Result.error("消费配置不存在"); // 1. 校验余额 int balance = energyService.getBalance(childId, config.getSourceDimension()); if (balance < config.getAmount()) return Result.error("能量不足"); // 2. 扣除能量 energyService.deductEnergyByCode(childId, config.getSourceDimension(), config.getAmount(), config.getDescription()); // 3. 执行目标操作 switch (config.getTargetType()) { case "coupon": // 发放优惠券 couponService.issueToUser(config.getTargetId(), userId); break; case "energy": // 转换为其他维度能量 int convertAmount = config.getAmount() * config.getConvertRatio() / 100; energyService.awardEnergyByDimCode(childId, config.getConvertDimension(), convertAmount, "energy_convert", 0L, "能量转换"); break; case "wish": // 心愿兑换 break; } return Result.success("消费成功"); } ``` ## 六、实施路线图 | 阶段 | 内容 | 涉及 | |------|------|------| | **P0** | 新增 missing 能量来源代码实现 | 邀请好友/家人、上传报告、完成计划等 | | **P1** | 创建 `energy_behavior_config` 表 + 管理后台CRUD | 后端 + 管理端 | | **P1** | 改造 `awardEnergy()` 调用改为从配置读取 | 后端重构 | | **P2** | 创建 `energy_consumption_config` 表 + 管理后台CRUD | 后端 + 管理端 | | **P2** | 实现能量转换引擎 | 后端 | | **P3** | 迁移旧数据到新配置表 | 数据迁移 | | **P3** | 废弃旧的 `energy_source_config` 表 | 清理 |