This commit is contained in:
薇薇安 2026-01-26 21:00:43 +08:00
parent 1eb5c618eb
commit 3057ce0e8b
3 changed files with 36 additions and 28 deletions

View File

@ -732,9 +732,11 @@ class ConfigManager:
except Exception: except Exception:
value = self.get(key, default) value = self.get(key, default)
# ⚠️ 关键修复:百分比配置值格式转换 # ⚠️ 临时兼容性处理:百分比配置值格式转换
# 如果配置值是百分比形式(>1转换为比例形式除以100 # 如果配置值是百分比形式(>1转换为比例形式除以100
# 兼容数据库中存储的百分比形式如30表示30%和比例形式如0.30表示30% # 兼容数据库中可能存在的旧数据百分比形式如30表示30%
# 数据迁移完成后,可以移除此逻辑
# 统一格式数据库、前端、后端都使用比例形式0.30表示30%
if isinstance(value, (int, float)) and value is not None: if isinstance(value, (int, float)) and value is not None:
# 需要转换的百分比配置项 # 需要转换的百分比配置项
percent_keys = [ percent_keys = [
@ -752,10 +754,11 @@ class ConfigManager:
] ]
if key in percent_keys: if key in percent_keys:
# 如果值>1认为是百分比形式转换为比例形式 # 如果值>1认为是百分比形式旧数据转换为比例形式
# 数据迁移完成后,所有值都应该<=1此逻辑可以移除
if value > 1: if value > 1:
value = value / 100.0 value = value / 100.0
logger.debug(f"配置值格式转换: {key} = {value*100:.2f}% (从百分比形式转换为比例形式)") logger.warning(f"配置值格式转换(临时兼容): {key} = {value*100:.2f}% (从百分比形式转换为比例形式,建议执行数据迁移)")
return value return value

View File

@ -1503,15 +1503,14 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
if (isNaN(numVal)) { if (isNaN(numVal)) {
return '' return ''
} }
// // 0.300.30
// 1) STOP_LOSS_PERCENT=0.08 8% // >1
// 2) pct-like LIMIT_ORDER_OFFSET_PCT=0.5 0.5% 0.5%
if (isPctLike) { if (isPctLike) {
const pctNum = numVal <= 0.05 ? numVal * 100 : numVal // pct-like""<=1<=1%
return formatPercent(pctNum) return formatPercent(numVal <= 0.05 ? numVal * 100 : numVal)
} }
const percent = numVal <= 1 ? numVal * 100 : numVal // 0.30>1
return formatPercent(percent) return formatPercent(numVal <= 1 ? numVal : numVal / 100)
} }
return val === null || val === undefined ? '' : val return val === null || val === undefined ? '' : val
} }
@ -1555,7 +1554,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
} else if (localValue === '.' || localValue === '-.') { } else if (localValue === '.' || localValue === '-.') {
// "." "-." // "." "-."
const restoreValue = isPercentKey const restoreValue = isPercentKey
? (typeof value === 'number' ? formatPercent((value <= 1 ? value * 100 : value)) : value) ? (typeof value === 'number' ? formatPercent(value <= 1 ? value : value / 100) : value)
: value : value
setLocalValue(restoreValue) setLocalValue(restoreValue)
return return
@ -1569,7 +1568,7 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
if (isNaN(numValue)) { if (isNaN(numValue)) {
// //
const restoreValue = isPercentKey const restoreValue = isPercentKey
? (typeof value === 'number' ? formatPercent((value <= 1 ? value * 100 : value)) : value) ? (typeof value === 'number' ? formatPercent(value <= 1 ? value : value / 100) : value)
: value : value
setLocalValue(restoreValue) setLocalValue(restoreValue)
return return
@ -1586,11 +1585,12 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
} }
} else { } else {
// 0~100 0~1 // 0~100 0~1
if (processedValue < 0 || processedValue > 100) { if (processedValue < 0 || processedValue > 1) {
setLocalValue(getInitialDisplayValue(value)) setLocalValue(getInitialDisplayValue(value))
return return
} }
processedValue = processedValue / 100 // 使0.30
// processedValue = processedValue / 100 //
} }
} }
} else if (config.type === 'boolean') { } else if (config.type === 'boolean') {
@ -1742,11 +1742,10 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
// return // return
// } // }
// 0-100 // 0-1
if (isPercentKey) { if (isPercentKey) {
const numValue = parseFloat(newValue) const numValue = parseFloat(newValue)
const maxAllowed = isPctLike ? 1 : 100 if (newValue !== '' && !isNaN(numValue) && (numValue < 0 || numValue > 1)) {
if (newValue !== '' && !isNaN(numValue) && (numValue < 0 || numValue > maxAllowed)) {
// //
return return
} }

View File

@ -32,12 +32,14 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
if (isNaN(numVal)) { if (isNaN(numVal)) {
return '' return ''
} }
// 0.300.30
// >1
if (isPctLike) { if (isPctLike) {
const pctNum = numVal <= 0.05 ? numVal * 100 : numVal // pct-like""<=1<=1%
return formatPercent(pctNum) return formatPercent(numVal <= 0.05 ? numVal * 100 : numVal)
} }
const percent = numVal <= 1 ? numVal * 100 : numVal // 0.30>1
return formatPercent(percent) return formatPercent(numVal <= 1 ? numVal : numVal / 100)
} }
return val === null || val === undefined ? '' : val return val === null || val === undefined ? '' : val
} }
@ -68,11 +70,15 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
setIsEditing(false) setIsEditing(false)
return return
} }
if (isPctLike) { // 0.30
finalValue = numVal <= 1 ? numVal / 100 : numVal / 100 // 0-1
} else { if (numVal < 0 || numVal > 1) {
finalValue = numVal <= 100 ? numVal / 100 : numVal / 100 setLocalValue(getInitialDisplayValue(config.value))
setIsEditing(false)
return
} }
// 使0.30
finalValue = numVal
} else { } else {
finalValue = parseFloat(localValue) finalValue = parseFloat(localValue)
if (isNaN(finalValue)) { if (isNaN(finalValue)) {
@ -121,8 +127,8 @@ const ConfigItem = ({ label, config, onUpdate, disabled }) => {
if (config.type === 'number') { if (config.type === 'number') {
if (isPercentKey) { if (isPercentKey) {
const numValue = parseFloat(newValue) const numValue = parseFloat(newValue)
const maxAllowed = isPctLike ? 1 : 100 // 0-1
if (newValue !== '' && !isNaN(numValue) && (numValue < 0 || numValue > maxAllowed)) { if (newValue !== '' && !isNaN(numValue) && (numValue < 0 || numValue > 1)) {
return return
} }
} }