5.6 KiB
5.6 KiB
配置值格式统一 - 最终方案
🎯 统一原则
核心原则:前端和后端使用相同的值(比例形式),只在显示时转换
数据格式统一
| 位置 | 格式 | 示例 | 说明 |
|---|---|---|---|
| 数据库存储 | 比例形式 | 0.30 | 表示30% |
| 前端显示 | 百分比形式 | 30% | 用户看到30% |
| 前端存储 | 比例形式 | 0.30 | 用户输入30,转换为0.30存储 |
| 后端使用 | 比例形式 | 0.30 | 直接使用,不需要转换 |
🔧 当前实现
前端逻辑(ConfigPanel.jsx & GlobalConfig.jsx)
显示逻辑:
// 从数据库读取0.30,显示为30%(用户看到)
const percent = numVal <= 1 ? numVal * 100 : numVal
return formatPercent(percent) // 显示30
存储逻辑:
// 用户输入30,转换为0.30存储(与后端使用相同的值)
if (processedValue < 0 || processedValue > 100) {
return
}
processedValue = processedValue / 100 // 30 -> 0.30
onUpdate(processedValue) // 存储0.30到数据库
结论:✅ 前端逻辑正确,用户输入30,存储0.30,与后端使用相同的值
后端逻辑(config_manager.py)
当前实现:
# ⚠️ 临时兼容性处理:如果值>1,转换为比例形式
if value > 1:
value = value / 100.0 # 30 -> 0.30
说明:
- ✅ 作为临时兼容性处理,处理旧数据
- ⚠️ 数据迁移完成后,可以移除此逻辑
后端验证(config.py)
当前实现:
# 特殊验证:百分比配置应该在0-1之间
if ('PERCENT' in key or 'PCT' in key) and config_type == 'number':
if not (0 <= float(item.value) <= 1):
raise HTTPException(
status_code=400,
detail=f"{key} must be between 0 and 1 (0% to 100%)"
)
说明:✅ 后端验证正确,只接受0-1之间的值
✅ 实施步骤
步骤1:执行数据迁移(必须)
目的:将数据库中的百分比形式(30)转换为比例形式(0.30)
脚本:backend/database/migrate_percent_configs_to_ratio.sql
执行:
# 执行SQL迁移脚本
mysql -u username -p database_name < backend/database/migrate_percent_configs_to_ratio.sql
结果:
- 数据库统一存储比例形式(0.30)
- 前端显示为30%(用户看到)
- 前端存储为0.30(直接存储)
- 后端使用0.30(直接使用)
步骤2:清除Redis缓存
# 清除Redis缓存,让系统重新加载配置
redis-cli DEL "config:trading_config:*"
redis-cli DEL "config:global_strategy_config:*"
步骤3:验证数据格式
-- 验证:所有百分比配置项应该在0-1之间
SELECT config_key, config_value
FROM trading_config
WHERE config_key IN (
'TRAILING_STOP_ACTIVATION',
'TRAILING_STOP_PROTECT',
'MIN_VOLATILITY',
'TAKE_PROFIT_PERCENT',
'STOP_LOSS_PERCENT'
)
AND config_type = 'number'
AND (CAST(config_value AS DECIMAL(10, 4)) < 0 OR CAST(config_value AS DECIMAL(10, 4)) > 1);
-- 应该返回0行
步骤4:保留格式转换作为兼容性处理(可选)
建议:数据迁移完成后,保留格式转换逻辑作为兼容性处理,但标记为临时方案
代码位置:backend/config_manager.py:735-758
说明:
- 作为临时兼容性处理,处理可能存在的旧数据
- 数据迁移完成后,所有值都应该<=1,此逻辑可以移除
- 但为了安全,建议保留一段时间
📊 数据流对比
当前流程(有格式转换)
用户输入30
↓
前端转换:30 -> 0.30
↓
存储到数据库:0.30
↓
后端读取:0.30(如果旧数据可能是30)
↓
代码中格式转换:30 -> 0.30(如果>1才转换)
↓
使用:0.30
统一后流程(无格式转换)
用户输入30
↓
前端转换:30 -> 0.30(仅前端输入时转换)
↓
存储到数据库:0.30
↓
后端读取:0.30(数据迁移后,统一为0.30)
↓
直接使用:0.30(不需要转换)
✅ 总结
统一方案
- 数据库存储:比例形式(0.30表示30%)
- 前端显示:百分比形式(30%,用户看到)
- 前端存储:比例形式(0.30,直接存储)
- 后端使用:比例形式(0.30,直接使用)
优势
- ✅ 数据格式统一:数据库、前端、后端都是0.30
- ✅ 代码逻辑简单:不需要到处做格式转换
- ✅ 减少出错:避免格式不一致导致的bug
- ✅ 易于维护:统一的格式,更容易理解和维护
实施建议
- 立即执行数据迁移:统一数据格式
- 保留格式转换作为兼容性处理:标记为临时方案
- 后续可以移除格式转换:数据格式统一后,可以移除
前端逻辑
- ✅ 显示时转换:0.30 -> 30%(用户看到)
- ✅ 输入时转换:30 -> 0.30(存储)
- ✅ 存储值统一:0.30(与后端使用相同的值)
后端逻辑
- ✅ 直接使用:0.30(不需要转换)
- ⚠️ 临时兼容:如果值>1,转换为0.30(处理旧数据)
- ✅ 验证正确:只接受0-1之间的值
🎯 最终结论
前端和后端使用相同的值(比例形式0.30):
- ✅ 前端输入时转换:30 -> 0.30(用户输入30,存储0.30)
- ✅ 前端显示时转换:0.30 -> 30%(用户看到30%)
- ✅ 后端直接使用:0.30(不需要转换)
- ✅ 数据格式统一:数据库、前端、后端都是0.30
优势:
- ✅ 避免中间转换出问题
- ✅ 代码逻辑简单
- ✅ 易于维护