31 KiB
代理配置表分析和优化建议
一、当前配置表结构分析
1.1 数据库表结构
表名: agent_config
CREATE TABLE `agent_config` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`config_key` varchar(100) NOT NULL COMMENT '配置键(唯一)',
`config_value` varchar(500) NOT NULL COMMENT '配置值',
`config_type` varchar(50) NOT NULL COMMENT '配置类型:price=价格,bonus=等级加成,upgrade=升级费用,rebate=返佣,tax=税费',
`description` varchar(500) DEFAULT NULL COMMENT '配置描述',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`delete_time` datetime DEFAULT NULL,
`del_state` tinyint NOT NULL DEFAULT 0,
`version` bigint NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_config_key` (`config_key`),
KEY `idx_config_type` (`config_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
1.2 配置表设计评估
优点:
✅ 键值对存储灵活:使用 config_key 和 config_value 的键值对模式,易于扩展新配置项
✅ 类型分类清晰:config_type 字段将配置分为 price、bonus、upgrade、rebate、tax 等类型,便于管理
✅ 唯一索引合理:config_key 的唯一索引确保配置键不重复
✅ 版本控制:包含 version 字段支持乐观锁,适合配置更新场景
✅ 软删除支持:支持软删除,保留历史配置记录
缺点/问题:
❌ 配置值类型限制:config_value 为 varchar(500),所有值都存储为字符串,需要在使用时转换
❌ 缺少验证机制:数据库层面无法验证配置值的格式和范围
❌ 配置值长度限制:对于复杂配置(如JSON对象),500字符可能不够
二、当前配置项清单
2.1 SQL初始化脚本中的配置项
根据 agent_system_migration.sql 文件,当前初始化的配置项:
| 配置键 | 配置值 | 类型 | 说明 |
|---|---|---|---|
base_price |
0.00 | price | 系统基础底价 |
system_max_price |
9999.99 | price | 系统价格上限 |
price_threshold |
0.00 | price | 提价标准阈值 |
price_fee_rate |
0.0000 | price | 提价手续费比例 |
level_bonus_normal |
6.00 | bonus | 普通代理等级加成 |
level_bonus_gold |
3.00 | bonus | 黄金代理等级加成 |
level_bonus_diamond |
0.00 | bonus | 钻石代理等级加成 |
upgrade_fee_normal_to_gold |
199.00 | upgrade | 普通→黄金升级费用 |
upgrade_fee_to_diamond |
980.00 | upgrade | 升级为钻石费用 |
upgrade_rebate_normal_to_gold |
139.00 | upgrade | 普通→黄金返佣金额 |
upgrade_rebate_to_diamond |
680.00 | upgrade | 升级为钻石返佣金额 |
direct_parent_amount_diamond |
6.00 | rebate | 直接上级是钻石的返佣金额 |
direct_parent_amount_gold |
3.00 | rebate | 直接上级是黄金的返佣金额 |
direct_parent_amount_normal |
2.00 | rebate | 直接上级是普通的返佣金额 |
max_gold_rebate_amount |
3.00 | rebate | 黄金代理最大返佣金额 |
tax_rate |
0.0600 | tax | 提现税率(6%) |
共15个配置项
2.2 代码中使用的配置键
2.2.1 AgentService 中使用的配置键
base_price- 基础底价 ✅price_threshold- 提价标准阈值 ✅price_fee_rate- 提价手续费比例 ✅level_bonus- 硬编码,未从配置表读取 ❌
2.2.2 AdminGetAgentConfigLogic 中使用的配置键
level_1_bonus- 普通代理等级加成 ❌ 配置键不匹配level_2_bonus- 黄金代理等级加成 ❌ 配置键不匹配level_3_bonus- 钻石代理等级加成 ❌ 配置键不匹配upgrade_to_gold_fee- 升级为黄金费用 ❌ 配置键不匹配upgrade_to_diamond_fee- 升级为钻石费用 ❌ 配置键不匹配upgrade_to_gold_rebate- 升级为黄金返佣 ❌ 配置键不匹配upgrade_to_diamond_rebate- 升级为钻石返佣 ❌ 配置键不匹配tax_rate- 税率 ✅tax_exemption_amount- 免税额度 ❌ 配置项缺失
三、发现的问题
3.1 🔴 严重问题:价格配置不应在系统配置表中
问题描述:
价格相关配置(底价、上限、提价阈值、手续费比例)应该按产品配置,而不是全局系统配置。当前这些配置同时存在于 agent_config 和 agent_product_config 表中,但代码只从系统配置表读取,没有实现产品级别的配置覆盖。
问题影响:
- ❌ 不同产品无法设置不同的底价和价格策略
- ❌ 代码中只读取系统配置,忽略了产品配置(
AgentService.AgentProcess、PaymentLogic) - ❌ 产品配置表虽然存在,但在订单处理逻辑中未被使用
应该移除的系统配置项:
base_price- 应该只在产品配置表中system_max_price- 应该只在产品配置表中price_threshold- 应该只在产品配置表中(可选)price_fee_rate- 应该只在产品配置表中(可选)
正确的设计:
- ✅ 所有价格相关配置都应该在
agent_product_config表中按产品配置 - ✅ 系统配置表只保留全局配置(等级加成、升级费用、税费等)
- ✅ 代码应该优先从产品配置读取,如果产品未配置,则使用默认值
3.2 🔴 严重问题:配置键命名不一致
问题描述: SQL初始化脚本和代码逻辑中使用的配置键命名不一致,导致配置无法正确读取。
具体情况:
| 配置项 | SQL初始化脚本 | 代码逻辑期望 | 状态 |
|---|---|---|---|
| 普通代理等级加成 | level_bonus_normal |
level_1_bonus |
❌ 不匹配 |
| 黄金代理等级加成 | level_bonus_gold |
level_2_bonus |
❌ 不匹配 |
| 钻石代理等级加成 | level_bonus_diamond |
level_3_bonus |
❌ 不匹配 |
| 升级为黄金费用 | upgrade_fee_normal_to_gold |
upgrade_to_gold_fee |
❌ 不匹配 |
| 升级为钻石费用 | upgrade_fee_to_diamond |
upgrade_to_diamond_fee |
❌ 不匹配 |
| 升级为黄金返佣 | upgrade_rebate_normal_to_gold |
upgrade_to_gold_rebate |
❌ 不匹配 |
| 升级为钻石返佣 | upgrade_rebate_to_diamond |
upgrade_to_diamond_rebate |
❌ 不匹配 |
影响:
- 后台管理系统无法正确读取和显示配置值
- 配置更新可能无法正常工作
3.3 🔴 严重问题:代码中硬编码等级加成
问题位置:
// agentService.go:144-155
func (s *AgentService) getLevelBonus(level int64) int64 {
switch level {
case 1: // 普通
return 6 // ❌ 硬编码,应该从配置表读取
case 2: // 黄金
return 3 // ❌ 硬编码,应该从配置表读取
case 3: // 钻石
return 0 // ❌ 硬编码,应该从配置表读取
default:
return 0
}
}
问题影响:
- 等级加成值无法通过后台配置动态调整
- 必须修改代码才能更改等级加成
- 违反了配置化的设计原则
3.4 🟡 中等问题:缺少配置项
缺失的配置项:
tax_exemption_amount- 免税额度(前端接口需要,但SQL初始化脚本中未包含)upgrade_fee_gold_to_diamond- 黄金→钻石升级费用(如果独立配置)
3.5 🟡 中等问题:配置键命名规范不统一
当前问题:
- 部分使用下划线分隔:
level_bonus_normal - 部分使用数字后缀:
level_1_bonus - 部分使用驼峰式:
upgrade_fee_normal_to_gold
建议:统一命名规范
3.6 🟢 轻微问题:配置值存储方式
当前方式:所有配置值以字符串形式存储,需要在使用时转换
strconv.ParseFloat()转换为浮点数strconv.ParseInt()转换为整数
影响:每次读取都需要类型转换,性能影响较小,但容易出错
四、配置使用情况分析
4.1 实际使用的配置项
在业务逻辑中使用的配置:
- ✅
base_price- 订单处理时使用 - ✅
price_threshold- 计算提价成本时使用 - ✅
price_fee_rate- 计算提价成本时使用 - ❌
level_bonus_*- 未使用,代码中硬编码
在后台管理中使用的配置:
- ❌
level_1_bonus- 读取配置(但键名不匹配) - ❌
level_2_bonus- 读取配置(但键名不匹配) - ❌
level_3_bonus- 读取配置(但键名不匹配) - ❌
upgrade_to_gold_fee- 读取配置(但键名不匹配) - ❌
upgrade_to_diamond_fee- 读取配置(但键名不匹配) - ❌
upgrade_to_gold_rebate- 读取配置(但键名不匹配) - ❌
upgrade_to_diamond_rebate- 读取配置(但键名不匹配) - ✅
tax_rate- 读取配置 - ❌
tax_exemption_amount- 读取配置(但配置项缺失)
4.2 未使用的配置项
以下配置项在SQL中初始化了,但在代码中似乎未使用:
direct_parent_amount_diamond- 直接上级是钻石的返佣金额direct_parent_amount_gold- 直接上级是黄金的返佣金额direct_parent_amount_normal- 直接上级是普通的返佣金额max_gold_rebate_amount- 黄金代理最大返佣金额
说明:这些配置项可能被硬编码在 distributeNormalAgentBonus 等函数中,需要确认是否需要配置化。
五、优化建议
5.1 🔴 立即修复:移除系统配置表中的价格配置
问题:
价格相关配置(base_price、system_max_price、price_threshold、price_fee_rate)应该完全由产品配置表管理,系统配置表中不应该存在这些配置。
修复步骤:
- 从系统配置表中删除价格相关配置:
-- 删除系统配置表中的价格相关配置
DELETE FROM `agent_config` WHERE `config_key` IN (
'base_price',
'system_max_price',
'price_threshold',
'price_fee_rate'
);
- 修改订单处理逻辑,从产品配置表读取:
需要修改的文件:
app/main/api/internal/service/agentService.go-AgentProcess方法app/main/api/internal/logic/pay/paymentlogic.go- 创建订单时的价格计算
示例代码修改(agentService.go):
// AgentProcess 处理代理订单(新系统)
func (s *AgentService) AgentProcess(ctx context.Context, order *model.Order) error {
// ... 前面的代码不变 ...
// 4. 获取产品配置(优先使用产品配置,如果不存在则使用默认值)
productConfig, err := s.AgentProductConfigModel.FindOneByProductId(ctx, order.ProductId)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return errors.Wrapf(err, "查询产品配置失败, productId: %d", order.ProductId)
}
// 使用产品配置的底价,如果产品未配置则使用默认值0
basePrice := 0.0
if productConfig != nil {
basePrice = productConfig.BasePrice
}
// ... 使用basePrice计算实际底价 ...
// 6.2 计算提价成本(使用产品配置)
priceThreshold := 0.0
priceFeeRate := 0.0
if productConfig != nil {
if productConfig.PriceThreshold.Valid {
priceThreshold = productConfig.PriceThreshold.Float64
}
if productConfig.PriceFeeRate.Valid {
priceFeeRate = productConfig.PriceFeeRate.Float64
}
}
priceCost := s.calculatePriceCost(agentOrder.SetPrice, priceThreshold, priceFeeRate)
// ... 后续代码 ...
}
- 更新后台管理系统:
- 移除系统配置页面中的价格相关配置项
- 确保产品配置页面可以正确配置这些价格参数
5.2 🔴 立即修复:统一配置键命名
方案一:修改SQL初始化脚本,使用代码期望的键名
-- 修改等级加成配置键
UPDATE `agent_config` SET `config_key` = 'level_1_bonus' WHERE `config_key` = 'level_bonus_normal';
UPDATE `agent_config` SET `config_key` = 'level_2_bonus' WHERE `config_key` = 'level_bonus_gold';
UPDATE `agent_config` SET `config_key` = 'level_3_bonus' WHERE `config_key` = 'level_bonus_diamond';
-- 修改升级费用配置键
UPDATE `agent_config` SET `config_key` = 'upgrade_to_gold_fee' WHERE `config_key` = 'upgrade_fee_normal_to_gold';
UPDATE `agent_config` SET `config_key` = 'upgrade_to_diamond_fee' WHERE `config_key` = 'upgrade_fee_to_diamond';
-- 修改升级返佣配置键
UPDATE `agent_config` SET `config_key` = 'upgrade_to_gold_rebate' WHERE `config_key` = 'upgrade_rebate_normal_to_gold';
UPDATE `agent_config` SET `config_key` = 'upgrade_to_diamond_rebate' WHERE `config_key` = 'upgrade_rebate_to_diamond';
方案二:修改代码逻辑,使用SQL中的键名
需要修改的文件:
app/main/api/internal/logic/admin_agent/admingetagentconfiglogic.goapp/main/api/internal/logic/admin_agent/adminupdateagentconfiglogic.go
推荐方案一,因为:
- 代码中的命名更清晰(
level_1_bonus比level_bonus_normal更直观) - 数字后缀与等级数字(1/2/3)对应,易于理解
5.3 🔴 立即修复:从配置表读取等级加成
修改 agentService.go 中的 getLevelBonus 函数:
// getLevelBonus 获取等级加成(从配置表读取)
func (s *AgentService) getLevelBonus(ctx context.Context, level int64) (int64, error) {
var configKey string
switch level {
case 1:
configKey = "level_1_bonus"
case 2:
configKey = "level_2_bonus"
case 3:
configKey = "level_3_bonus"
default:
return 0, nil
}
bonus, err := s.getConfigFloat(ctx, configKey)
if err != nil {
// 配置不存在时返回默认值
switch level {
case 1:
return 6, nil
case 2:
return 3, nil
case 3:
return 0, nil
}
return 0, nil
}
return int64(bonus), nil
}
修改调用处:
// agentService.go:108
levelBonus, err := s.getLevelBonus(ctx, agent.Level)
if err != nil {
return errors.Wrapf(err, "获取等级加成配置失败")
}
actualBasePrice := basePrice + float64(levelBonus)
5.4 🟡 补充缺失的配置项
添加 tax_exemption_amount 配置:
INSERT INTO `agent_config` (`config_key`, `config_value`, `config_type`, `description`)
VALUES ('tax_exemption_amount', '0.00', 'tax', '提现免税额度(元,默认0)');
5.5 🟡 规范化配置键命名
建议统一使用以下命名规范:
{类型}_{编号/级别}_{属性}
示例:
- ✅
level_1_bonus- 等级1的加成 - ✅
level_2_bonus- 等级2的加成 - ✅
level_3_bonus- 等级3的加成 - ✅
upgrade_to_gold_fee- 升级到黄金的费用 - ✅
upgrade_to_diamond_fee- 升级到钻石的费用 - ✅
upgrade_to_gold_rebate- 升级到黄金的返佣 - ✅
upgrade_to_diamond_rebate- 升级到钻石的返佣
5.6 🟢 优化建议:添加配置验证
在更新配置时添加验证逻辑:
// 验证配置值的合理性
func validateConfigValue(key string, value float64) error {
switch key {
case "tax_rate":
if value < 0 || value > 1 {
return errors.New("税率必须在0-1之间")
}
case "price_fee_rate":
if value < 0 || value > 1 {
return errors.New("提价费率必须在0-1之间")
}
case "base_price", "system_max_price":
if value < 0 {
return errors.New("价格配置不能为负数")
}
}
return nil
}
六、配置项完整清单(修正后)
6.1 价格相关配置(应移除,改为产品配置)
⚠️ 重要说明:以下配置项应该从系统配置表(agent_config)中移除,改为在产品配置表(agent_product_config)中按产品配置。
| 配置键 | 说明 | 配置位置 |
|---|---|---|
base_price |
✅ 应在 agent_product_config |
|
system_max_price |
✅ 应在 agent_product_config |
|
price_threshold |
✅ 应在 agent_product_config |
|
price_fee_rate |
✅ 应在 agent_product_config |
产品配置表结构(agent_product_config):
base_price- 产品基础底价(必填)system_max_price- 产品价格上限(必填)price_threshold- 提价标准阈值(可选,NULL时表示不设阈值)price_fee_rate- 提价手续费比例(可选,NULL时表示不收费)
6.2 等级加成配置(bonus类型)
| 配置键 | 默认值 | 说明 |
|---|---|---|
level_1_bonus |
6.00 | 普通代理等级加成(元) |
level_2_bonus |
3.00 | 黄金代理等级加成(元) |
level_3_bonus |
0.00 | 钻石代理等级加成(元) |
6.3 升级费用配置(upgrade类型)
| 配置键 | 默认值 | 说明 |
|---|---|---|
upgrade_to_gold_fee |
199.00 | 普通→黄金升级费用(元) |
upgrade_to_diamond_fee |
980.00 | 升级为钻石费用(元) |
upgrade_to_gold_rebate |
139.00 | 普通→黄金返佣金额(元) |
upgrade_to_diamond_rebate |
680.00 | 升级为钻石返佣金额(元) |
注意:gold_to_diamond 的费用和返佣可以通过计算得出:
- 费用:
upgrade_to_diamond_fee - upgrade_to_gold_fee = 980 - 199 = 781元 - 返佣:可以通过前端或后端计算,不单独存储
6.4 返佣规则配置(rebate类型)
| 配置键 | 默认值 | 说明 |
|---|---|---|
direct_parent_amount_diamond |
6.00 | 直接上级是钻石的返佣金额(元) |
direct_parent_amount_gold |
3.00 | 直接上级是黄金的返佣金额(元) |
direct_parent_amount_normal |
2.00 | 直接上级是普通的返佣金额(元) |
max_gold_rebate_amount |
3.00 | 黄金代理最大返佣金额(元) |
建议:这些配置项目前在代码中硬编码,建议配置化。
6.5 税费配置(tax类型)
| 配置键 | 默认值 | 说明 |
|---|---|---|
tax_rate |
0.0600 | 提现税率(6%,即0.06) |
tax_exemption_amount |
0.00 | 免税额度(元,默认0) |
七、配置表的合理性评估
7.1 表结构设计
| 评估项 | 评分 | 说明 |
|---|---|---|
| 灵活性 | ⭐⭐⭐⭐⭐ | 键值对设计非常灵活,易于扩展 |
| 可维护性 | ⭐⭐⭐⭐ | 类型分类清晰,便于管理 |
| 性能 | ⭐⭐⭐⭐ | 唯一索引优化查询,缓存支持 |
| 类型安全 | ⭐⭐⭐ | 所有值都是字符串,需要转换 |
| 验证机制 | ⭐⭐ | 缺少数据库层面的验证 |
7.2 总体评价
设计优点: ✅ 采用键值对存储,扩展性强 ✅ 类型分类清晰,便于管理 ✅ 支持版本控制和软删除
存在的问题: ❌ 价格配置应该在产品配置表,而不是系统配置表(严重设计问题) ❌ 配置键命名不一致(严重) ❌ 部分配置硬编码(严重) ❌ 缺少部分配置项(中等) ❌ 缺少配置验证机制(中等)
总体评分:⭐⭐⭐(3/5)
结论:配置表的设计思路基本合理,但存在价格配置位置设计错误的严重问题。价格相关配置应该完全由产品配置表管理,系统配置表只应该包含全局配置(等级加成、升级费用、税费等)。修复这些问题后,配置表设计将更加完善和符合项目规范。
八、修复后的完整配置SQL
-- ============================================
-- 代理系统配置初始化(修正版)
-- ============================================
-- 删除价格相关配置(应该在产品配置表中)
DELETE FROM `agent_config` WHERE `config_key` IN (
'base_price',
'system_max_price',
'price_threshold',
'price_fee_rate'
);
-- 删除旧的不一致配置(如果存在)
DELETE FROM `agent_config` WHERE `config_key` IN (
'level_bonus_normal',
'level_bonus_gold',
'level_bonus_diamond',
'upgrade_fee_normal_to_gold',
'upgrade_fee_to_diamond',
'upgrade_rebate_normal_to_gold',
'upgrade_rebate_to_diamond'
);
-- 插入修正后的配置项
INSERT INTO `agent_config` (`config_key`, `config_value`, `config_type`, `description`) VALUES
-- 注意:价格相关配置(base_price, system_max_price, price_threshold, price_fee_rate)
-- 已从系统配置表中移除,改为在产品配置表(agent_product_config)中按产品配置
-- 等级加成配置(修正键名)
('level_1_bonus', '6.00', 'bonus', '普通代理等级加成(6元)'),
('level_2_bonus', '3.00', 'bonus', '黄金代理等级加成(3元)'),
('level_3_bonus', '0.00', 'bonus', '钻石代理等级加成(0元)'),
-- 升级费用配置(修正键名)
('upgrade_to_gold_fee', '199.00', 'upgrade', '普通→黄金升级费用(199元)'),
('upgrade_to_diamond_fee', '980.00', 'upgrade', '升级为钻石费用(980元)'),
-- 升级返佣配置(修正键名)
('upgrade_to_gold_rebate', '139.00', 'upgrade', '普通→黄金返佣金额(139元)'),
('upgrade_to_diamond_rebate', '680.00', 'upgrade', '升级为钻石返佣金额(680元)'),
-- 返佣规则配置
('direct_parent_amount_diamond', '6.00', 'rebate', '直接上级是钻石的返佣金额(6元)'),
('direct_parent_amount_gold', '3.00', 'rebate', '直接上级是黄金的返佣金额(3元)'),
('direct_parent_amount_normal', '2.00', 'rebate', '直接上级是普通的返佣金额(2元)'),
('max_gold_rebate_amount', '3.00', 'rebate', '黄金代理最大返佣金额(3元)'),
-- 税费配置
('tax_rate', '0.0600', 'tax', '提现税率(6%,即0.06)'),
('tax_exemption_amount', '0.00', 'tax', '提现免税额度(元,默认0)')
ON DUPLICATE KEY UPDATE
`config_value` = VALUES(`config_value`),
`update_time` = NOW();
九、建议的改进方案
方案A:保持当前键值对设计(推荐)
优点:
- 灵活性强,易于扩展
- 不需要修改表结构
- 符合项目当前架构
需要做的修改:
- 统一配置键命名
- 修复代码硬编码问题
- 补充缺失的配置项
- 添加配置验证逻辑
方案B:改为结构化JSON配置(可选)
如果配置项继续增长,可以考虑:
- 将相关配置组合成JSON对象存储在
config_value中 - 例如:
level_bonus_config存储{"1": 6, "2": 3, "3": 0}
缺点:
- 需要修改所有读取配置的代码
- 不利于单个配置项的独立更新
建议:当前配置项数量不多(约15个),保持键值对设计更合适。
十、总结
当前状态
- ✅ 配置表设计思路合理
- ❌ 价格配置设计错误(应该在产品配置表,不在系统配置表)
- ❌ 配置键命名不一致(需要立即修复)
- ❌ 部分配置硬编码(需要立即修复)
- ⚠️ 缺少部分配置项(需要补充)
修复优先级
- P0(紧急):移除系统配置表中的价格配置,改为完全由产品配置表管理
- P0(紧急):修改订单处理逻辑,从产品配置表读取价格参数
- P0(紧急):统一配置键命名,修复不一致问题
- P0(紧急):修改代码,从配置表读取等级加成,移除硬编码
- P1(重要):补充缺失的配置项(
tax_exemption_amount) - P2(建议):添加配置验证逻辑
- P2(建议):将返佣规则配置化(当前硬编码)
是否符合项目
配置表设计:✅ 基本符合,但价格配置的位置设计错误
存在的问题:
- ❌ 价格配置应该在产品配置表中,而不是系统配置表(严重设计问题)
- ❌ 配置键命名不一致
- ❌ 部分配置硬编码
- ⚠️ 缺少部分配置项
结论:需要修复上述问题后才能完全符合项目的配置化设计理念。最重要的是将价格配置从系统配置表移除,改为完全由产品配置表管理。
十一、产品配置表使用规范
11.1 产品配置表结构
表名: agent_product_config
每个产品都应该有对应的配置记录,包含以下字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
product_id |
bigint | ✅ 是 | 产品ID(唯一) |
product_name |
varchar(100) | ✅ 是 | 产品名称 |
base_price |
decimal(10,2) | ✅ 是 | 产品基础底价 |
system_max_price |
decimal(10,2) | ✅ 是 | 产品价格上限 |
price_threshold |
decimal(10,2) | ❌ 否 | 提价标准阈值(NULL表示不设阈值) |
price_fee_rate |
decimal(5,4) | ❌ 否 | 提价手续费比例(NULL表示不收费,0-1之间) |
11.2 配置优先级和默认值
规则:
- 所有价格参数必须从产品配置表读取
- 如果产品配置记录不存在,应该报错或使用合理的默认值(建议报错,强制每个产品必须配置)
- 可选字段(
price_threshold、price_fee_rate)如果为NULL,表示不启用该功能price_threshold = NULL→ 不设提价阈值price_fee_rate = NULL→ 不收取提价手续费
11.3 代码修改示例
修改 AgentService.AgentProcess 方法
// AgentProcess 处理代理订单(新系统)
func (s *AgentService) AgentProcess(ctx context.Context, order *model.Order) error {
// 1-3. 前面的代码不变...
// 4. 获取产品配置(必须存在)
productConfig, err := s.AgentProductConfigModel.FindOneByProductId(ctx, order.ProductId)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return errors.Wrapf(err, "产品配置不存在, productId: %d,请先在后台配置产品价格参数", order.ProductId)
}
return errors.Wrapf(err, "查询产品配置失败, productId: %d", order.ProductId)
}
// 使用产品配置的底价
basePrice := productConfig.BasePrice
// 6. 使用事务处理订单
return s.AgentWalletModel.Trans(ctx, func(transCtx context.Context, session sqlx.Session) error {
// 6.1 计算实际底价和代理收益
levelBonus, err := s.getLevelBonus(ctx, agent.Level)
if err != nil {
return errors.Wrapf(err, "获取等级加成配置失败")
}
actualBasePrice := basePrice + float64(levelBonus)
// 6.2 计算提价成本(使用产品配置)
priceThreshold := 0.0
priceFeeRate := 0.0
if productConfig.PriceThreshold.Valid {
priceThreshold = productConfig.PriceThreshold.Float64
}
if productConfig.PriceFeeRate.Valid {
priceFeeRate = productConfig.PriceFeeRate.Float64
}
priceCost := s.calculatePriceCost(agentOrder.SetPrice, priceThreshold, priceFeeRate)
// 6.3 计算代理收益
agentProfit := agentOrder.SetPrice - actualBasePrice - priceCost
// ... 后续代码不变 ...
})
}
修改 PaymentLogic 创建订单时的价格计算
// 如果是代理推广订单,创建完整的代理订单记录
if data.AgentIdentifier != "" && agentLinkModel != nil {
// ... 获取代理信息 ...
// 获取产品配置(必须存在)
productConfig, err := l.svcCtx.AgentProductConfigModel.FindOneByProductId(l.ctx, product.Id)
if err != nil {
if errors.Is(err, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"生成订单失败,产品配置不存在, productId: %d,请先在后台配置产品价格参数", product.Id)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR),
"生成订单, 查询产品配置失败: %+v", err)
}
// 使用产品配置的底价
basePrice := productConfig.BasePrice
// 计算实际底价(基础底价+等级加成)
levelBonus, _ := l.getLevelBonus(agent.Level)
actualBasePrice := basePrice + float64(levelBonus)
// 计算提价成本(使用产品配置)
priceThreshold := 0.0
priceFeeRate := 0.0
if productConfig.PriceThreshold.Valid {
priceThreshold = productConfig.PriceThreshold.Float64
}
if productConfig.PriceFeeRate.Valid {
priceFeeRate = productConfig.PriceFeeRate.Float64
}
priceCost := 0.0
if agentLinkModel.SetPrice > priceThreshold {
priceCost = (agentLinkModel.SetPrice - priceThreshold) * priceFeeRate
}
// 计算代理收益
agentProfit := agentLinkModel.SetPrice - actualBasePrice - priceCost
// ... 创建代理订单记录 ...
}
11.4 需要修改的文件清单
需要修改以支持产品配置的代码文件:
-
app/main/api/internal/service/agentService.goAgentProcess()方法:从产品配置表读取价格参数
-
app/main/api/internal/logic/pay/paymentlogic.go- 创建订单时的价格计算:从产品配置表读取价格参数
-
app/main/api/internal/logic/agent/getagentproductconfiglogic.go- 移除从系统配置表读取价格参数的逻辑(只保留从产品配置表读取)
-
app/main/api/internal/logic/admin_agent/admingetagentconfiglogic.go- 移除价格相关配置项的返回
-
app/main/api/internal/logic/admin_agent/adminupdateagentconfiglogic.go- 移除价格相关配置项的更新逻辑
-
后台管理系统前端
- 系统配置页面:移除价格相关配置项
- 产品配置页面:确保可以正确配置所有价格参数