Skip to content

Commit 0eb10b4

Browse files
the-dev-zclaude
andcommitted
feat(web): improve trader config UX for initial balance and prompt templates (#629 #630)
**問題:** - 輸入框有 `min="100"` 和 `step="100"` - 用戶可以手動輸入 50(HTML min 不強制) - 點擊上下箭頭時,因為 min="100" 會強制跳到 100 - 導致用戶輸入被覆蓋,體驗不佳 **解決方案:** 1. 添加 `onBlur` 事件處理:失焦時自動調整低於 100 的值 2. 保留 `onChange` 自由輸入能力 3. 添加提示文字說明最小值規則 **效果:** - ✅ 用戶可以正常輸入(不會即時被覆蓋) - ✅ 失焦時自動調整到最小值 100 - ✅ 箭頭調整行為與手動輸入一致 - ✅ 清晰的提示文字說明規則 --- **問題:** - 下拉框只顯示模板名稱(default, aggressive 等) - 無說明每個模板的風格、特色 - 新手不知道該選擇哪個 **解決方案:** 1. 為每個模板添加中文友好名稱和 Emoji 圖標 2. 在下拉框下方添加動態描述區域 3. 根據選擇的模板實時顯示詳細說明 **模板描述映射:** - `default`: 📊 默認穩健策略 - 最大化夏普比率,適合新手 - `adaptive`: 🛡️ 保守策略 - 嚴格風控,BTC 強制確認 - `adaptive_moderate`: ⚖️ 平衡策略 - 平衡風控與頻率 - `adaptive_relaxed`: ⚡ 激進策略 - 高頻交易,追求機會 - `adaptive_altcoin`: 🪙 山寨幣專用 - 專注 Altcoin 交易 - `Hansen`: 🎯 Hansen 策略 - 專業交易者專用 - `nof1`: 🌐 NoF1 英文框架 - Hyperliquid 專用 - `taro_long_prompts`: 📈 Taro 長倉策略 - 數據驅動 **效果:** - ✅ 清晰的模板名稱和圖標 - ✅ 動態顯示當前選擇的模板描述 - ✅ 新手友好,易於選擇 Fixes #629 Fixes #630 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 4f2177a commit 0eb10b4

File tree

1 file changed

+121
-19
lines changed

1 file changed

+121
-19
lines changed

web/src/components/TraderConfigModal.tsx

Lines changed: 121 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,17 @@ export function TraderConfigModal({
411411
<input
412412
type="number"
413413
value={formData.initial_balance}
414-
onChange={(e) =>
415-
handleInputChange(
416-
'initial_balance',
417-
Number(e.target.value)
418-
)
419-
}
414+
onChange={(e) => {
415+
const value = Number(e.target.value)
416+
handleInputChange('initial_balance', value)
417+
}}
418+
onBlur={(e) => {
419+
// 失焦時強制最小值,統一箭頭調整和手動輸入的行為
420+
const value = Number(e.target.value)
421+
if (value < 100) {
422+
handleInputChange('initial_balance', 100)
423+
}
424+
}}
420425
className="w-full px-3 py-2 bg-[#0B0E11] border border-[#2B3139] rounded text-[#EAECEF] focus:border-[#F0B90B] focus:outline-none"
421426
min="100"
422427
step="0.01"
@@ -445,6 +450,9 @@ export function TraderConfigModal({
445450
点击"获取当前余额"按钮可自动获取您交易所账户的当前净值
446451
</p>
447452
)}
453+
<p className="text-xs text-[#848E9C] mt-1">
454+
最小金额 100 USDT(与步进值一致,输入低于 100 将自动调整)
455+
</p>
448456
{balanceFetchError && (
449457
<p className="text-xs text-red-500 mt-1">
450458
{balanceFetchError}
@@ -626,20 +634,114 @@ export function TraderConfigModal({
626634
}
627635
className="w-full px-3 py-2 bg-[#0B0E11] border border-[#2B3139] rounded text-[#EAECEF] focus:border-[#F0B90B] focus:outline-none"
628636
>
629-
{promptTemplates.map((template) => (
630-
<option key={template.name} value={template.name}>
631-
{template.name === 'default'
632-
? 'Default (默认稳健)'
633-
: template.name === 'aggressive'
634-
? 'Aggressive (激进)'
635-
: template.name.charAt(0).toUpperCase() +
636-
template.name.slice(1)}
637-
</option>
638-
))}
637+
{promptTemplates.map((template) => {
638+
// 模板名称映射
639+
const getTemplateName = (name: string) => {
640+
const names: Record<string, string> = {
641+
default: '默认稳健',
642+
adaptive: '保守策略',
643+
adaptive_moderate: '平衡策略',
644+
adaptive_relaxed: '激进策略',
645+
adaptive_altcoin: '山寨币专用',
646+
Hansen: 'Hansen 策略',
647+
nof1: 'NoF1 英文框架',
648+
taro_long_prompts: 'Taro 长仓',
649+
}
650+
return (
651+
names[name] ||
652+
name.charAt(0).toUpperCase() + name.slice(1)
653+
)
654+
}
655+
656+
return (
657+
<option key={template.name} value={template.name}>
658+
{getTemplateName(template.name)}
659+
</option>
660+
)
661+
})}
639662
</select>
640-
<p className="text-xs text-[#848E9C] mt-1">
641-
选择预设的交易策略模板(包含交易哲学、风控原则等)
642-
</p>
663+
664+
{/* 動態描述區域 */}
665+
<div className="mt-2 p-3 rounded" style={{ background: 'rgba(240, 185, 11, 0.05)', border: '1px solid rgba(240, 185, 11, 0.15)' }}>
666+
<div className="text-xs font-semibold mb-1" style={{ color: '#F0B90B' }}>
667+
{(() => {
668+
const desc: Record<string, { title: string; content: string }> = {
669+
'default': {
670+
title: '📊 默認穩健策略',
671+
content: '最大化夏普比率,平衡風險收益,適合新手和長期穩定交易'
672+
},
673+
'adaptive': {
674+
title: '🛡️ 保守策略 (v6.0.0)',
675+
content: '嚴格風控,BTC 強制確認,高勝率優先,適合保守型交易者'
676+
},
677+
'adaptive_moderate': {
678+
title: '⚖️ 平衡策略 (v6.0.0)',
679+
content: '平衡風控與頻率,BTC 建議確認,適合常規市場環境'
680+
},
681+
'adaptive_relaxed': {
682+
title: '⚡ 激進策略 (v6.0.0)',
683+
content: '高頻交易,BTC 可選確認,追求交易機會,適合波動市場'
684+
},
685+
'adaptive_altcoin': {
686+
title: '🪙 山寨幣專用 (v6.0.0)',
687+
content: '專注山寨幣交易,BTC 僅作參考不阻止開倉,適合 Altcoin 交易'
688+
},
689+
'Hansen': {
690+
title: '🎯 Hansen 策略',
691+
content: 'Hansen 定制策略,最大化夏普比率,專業交易者專用'
692+
},
693+
'nof1': {
694+
title: '🌐 NoF1 英文框架',
695+
content: 'Hyperliquid 交易所專用,英文提示詞,風險調整回報最大化'
696+
},
697+
'taro_long_prompts': {
698+
title: '📈 Taro 長倉策略',
699+
content: '數據驅動決策,多維度驗證,持續學習進化,長倉專用'
700+
},
701+
};
702+
return desc[formData.system_prompt_template]?.title || '策略描述';
703+
})()}
704+
</div>
705+
<div className="text-xs" style={{ color: '#848E9C' }}>
706+
{(() => {
707+
const desc: Record<string, { title: string; content: string }> = {
708+
'default': {
709+
title: '📊 默認穩健策略',
710+
content: '最大化夏普比率,平衡風險收益,適合新手和長期穩定交易'
711+
},
712+
'adaptive': {
713+
title: '🛡️ 保守策略 (v6.0.0)',
714+
content: '嚴格風控,BTC 強制確認,高勝率優先,適合保守型交易者'
715+
},
716+
'adaptive_moderate': {
717+
title: '⚖️ 平衡策略 (v6.0.0)',
718+
content: '平衡風控與頻率,BTC 建議確認,適合常規市場環境'
719+
},
720+
'adaptive_relaxed': {
721+
title: '⚡ 激進策略 (v6.0.0)',
722+
content: '高頻交易,BTC 可選確認,追求交易機會,適合波動市場'
723+
},
724+
'adaptive_altcoin': {
725+
title: '🪙 山寨幣專用 (v6.0.0)',
726+
content: '專注山寨幣交易,BTC 僅作參考不阻止開倉,適合 Altcoin 交易'
727+
},
728+
'Hansen': {
729+
title: '🎯 Hansen 策略',
730+
content: 'Hansen 定制策略,最大化夏普比率,專業交易者專用'
731+
},
732+
'nof1': {
733+
title: '🌐 NoF1 英文框架',
734+
content: 'Hyperliquid 交易所專用,英文提示詞,風險調整回報最大化'
735+
},
736+
'taro_long_prompts': {
737+
title: '📈 Taro 長倉策略',
738+
content: '數據驅動決策,多維度驗證,持續學習進化,長倉專用'
739+
},
740+
};
741+
return desc[formData.system_prompt_template]?.content || '包含交易哲學、風控原則等';
742+
})()}
743+
</div>
744+
</div>
643745
</div>
644746

645747
<div className="flex items-center gap-3">

0 commit comments

Comments
 (0)