Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 32 additions & 153 deletions web/src/components/ChartTabs.tsx

Large diffs are not rendered by default.

94 changes: 47 additions & 47 deletions web/src/components/TraderConfigModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export function TraderConfigModal({

const handleFetchCurrentBalance = async () => {
if (!isEditMode || !traderData?.trader_id) {
setBalanceFetchError('只有在编辑模式下才能获取当前余额')
setBalanceFetchError(t('fetchBalanceEditModeOnly', language))
return
}

Expand All @@ -142,13 +142,13 @@ export function TraderConfigModal({
const currentBalance =
result.data.total_equity || result.data.balance || 0
setFormData((prev) => ({ ...prev, initial_balance: currentBalance }))
toast.success('已获取当前余额')
toast.success(t('balanceFetched', language))
} else {
throw new Error(result.message || '获取余额失败')
throw new Error(result.message || t('balanceFetchFailed', language))
}
} catch (error) {
console.error('获取余额失败:', error)
setBalanceFetchError('获取余额失败,请检查网络连接')
console.error(t('balanceFetchFailed', language) + ':', error)
setBalanceFetchError(t('balanceFetchNetworkError', language))
} finally {
setIsFetchingBalance(false)
}
Expand All @@ -175,13 +175,13 @@ export function TraderConfigModal({
}

await toast.promise(onSave(saveData), {
loading: '正在保存…',
success: '保存成功',
error: '保存失败',
loading: t('saving', language),
success: t('saveSuccess', language),
error: t('saveFailed', language),
})
onClose()
} catch (error) {
console.error('保存失败:', error)
console.error(t('saveFailed', language) + ':', error)
} finally {
setIsSaving(false)
}
Expand All @@ -208,10 +208,10 @@ export function TraderConfigModal({
</div>
<div>
<h2 className="text-xl font-bold text-[#EAECEF]">
{isEditMode ? '修改交易员' : '创建交易员'}
{isEditMode ? t('editTrader', language) : t('createTrader', language)}
</h2>
<p className="text-sm text-[#848E9C] mt-1">
{isEditMode ? '修改交易员配置' : '选择策略并配置基础参数'}
{isEditMode ? t('editTraderConfig', language) : t('selectStrategyAndConfigParams', language)}
</p>
</div>
</div>
Expand All @@ -231,12 +231,12 @@ export function TraderConfigModal({
{/* Basic Info */}
<div className="bg-[#0B0E11] border border-[#2B3139] rounded-lg p-5">
<h3 className="text-lg font-semibold text-[#EAECEF] mb-5 flex items-center gap-2">
<span className="text-[#F0B90B]">1</span> 基础配置
<span className="text-[#F0B90B]">1</span> {t('basicConfig', language)}
</h3>
<div className="space-y-4">
<div>
<label className="text-sm text-[#EAECEF] block mb-2">
交易员名称 <span className="text-red-500">*</span>
{t('traderNameRequired', language)}
</label>
<input
type="text"
Expand All @@ -245,13 +245,13 @@ export function TraderConfigModal({
handleInputChange('trader_name', e.target.value)
}
className="w-full px-3 py-2 bg-[#0B0E11] border border-[#2B3139] rounded text-[#EAECEF] focus:border-[#F0B90B] focus:outline-none"
placeholder="请输入交易员名称"
placeholder={t('enterTraderNamePlaceholder', language)}
/>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm text-[#EAECEF] block mb-2">
AI模型 <span className="text-red-500">*</span>
{t('aiModelRequired', language)}
</label>
<select
value={formData.ai_model}
Expand All @@ -269,7 +269,7 @@ export function TraderConfigModal({
</div>
<div>
<label className="text-sm text-[#EAECEF] block mb-2">
交易所 <span className="text-red-500">*</span>
{t('exchangeRequired', language)}
</label>
<select
value={formData.exchange_id}
Expand Down Expand Up @@ -300,10 +300,10 @@ export function TraderConfigModal({
className="mt-2 inline-flex items-center gap-1.5 text-xs text-[#848E9C] hover:text-[#F0B90B] transition-colors"
>
<UserPlus className="w-3.5 h-3.5" />
<span>还没有交易所账号?点击注册</span>
<span>{t('noExchangeAccount', language)}</span>
{regLink.hasReferral && (
<span className="px-1.5 py-0.5 bg-[#F0B90B]/10 text-[#F0B90B] rounded text-[10px]">
折扣优惠
{t('discount', language)}
</span>
)}
<ExternalLink className="w-3 h-3" />
Expand All @@ -318,13 +318,13 @@ export function TraderConfigModal({
{/* Strategy Selection */}
<div className="bg-[#0B0E11] border border-[#2B3139] rounded-lg p-5">
<h3 className="text-lg font-semibold text-[#EAECEF] mb-5 flex items-center gap-2">
<span className="text-[#F0B90B]">2</span> 选择交易策略
<span className="text-[#F0B90B]">2</span> {t('selectTradingStrategy', language)}
<Sparkles className="w-4 h-4 text-[#F0B90B]" />
</h3>
<div className="space-y-4">
<div>
<label className="text-sm text-[#EAECEF] block mb-2">
使用策略
{t('useStrategy', language)}
</label>
<select
value={formData.strategy_id}
Expand All @@ -333,18 +333,18 @@ export function TraderConfigModal({
}
className="w-full px-3 py-2 bg-[#0B0E11] border border-[#2B3139] rounded text-[#EAECEF] focus:border-[#F0B90B] focus:outline-none"
>
<option value="">-- 不使用策略(手动配置)--</option>
<option value="">{t('noStrategyManual', language)}</option>
{strategies.map((strategy) => (
<option key={strategy.id} value={strategy.id}>
{strategy.name}
{strategy.is_active ? ' (当前激活)' : ''}
{strategy.is_default ? ' [默认]' : ''}
{selectedStrategy.name}
{selectedStrategy.is_active ? t('active', language) : ''}
{selectedStrategy.is_default ? t('default', language) : ''}
</option>
))}
</select>
{strategies.length === 0 && (
<p className="text-xs text-[#848E9C] mt-2">
暂无策略,请先在策略工作室创建策略
<p className="text-xs text-[#848E9C] mt-2">
{t('noStrategyHint', language)}
</p>
)}
</div>
Expand All @@ -354,25 +354,25 @@ export function TraderConfigModal({
<div className="mt-3 p-4 bg-[#1E2329] border border-[#2B3139] rounded-lg">
<div className="flex items-center gap-2 mb-2">
<span className="text-[#F0B90B] text-sm font-medium">
策略详情
{t('strategyDetails', language)}
</span>
{selectedStrategy.is_active && (
<span className="px-2 py-0.5 bg-green-500/20 text-green-400 text-xs rounded">
激活中
{t('activating', language)}
</span>
)}
</div>
<p className="text-sm text-[#848E9C] mb-2">
{selectedStrategy.description || '无描述'}
{selectedStrategy.description || (language === 'zh' ? '无描述' : 'No description')}
</p>
<div className="grid grid-cols-2 gap-2 text-xs text-[#848E9C]">
<div>
币种来源: {selectedStrategy.config.coin_source.source_type === 'static' ? '固定币种' :
{t('coinSource', language)}: {selectedStrategy.config.coin_source.source_type === 'static' ? '固定币种' :
selectedStrategy.config.coin_source.source_type === 'ai500' ? 'AI500' :
selectedStrategy.config.coin_source.source_type === 'oi_top' ? 'OI Top' : '混合'}
</div>
<div>
保证金上限: {((selectedStrategy.config.risk_control?.max_margin_usage || 0.9) * 100).toFixed(0)}%
{t('marginLimit', language)}: {((selectedStrategy.config.risk_control?.max_margin_usage || 0.9) * 100).toFixed(0)}%
</div>
</div>
</div>
Expand All @@ -383,13 +383,13 @@ export function TraderConfigModal({
{/* Trading Parameters */}
<div className="bg-[#0B0E11] border border-[#2B3139] rounded-lg p-5">
<h3 className="text-lg font-semibold text-[#EAECEF] mb-5 flex items-center gap-2">
<span className="text-[#F0B90B]">3</span> 交易参数
<span className="text-[#F0B90B]">3</span> {t('tradingParams', language)}
</h3>
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm text-[#EAECEF] block mb-2">
保证金模式
{t('marginMode', language)}
</label>
<div className="flex gap-2">
<button
Expand All @@ -401,7 +401,7 @@ export function TraderConfigModal({
: 'bg-[#0B0E11] text-[#848E9C] border border-[#2B3139]'
}`}
>
全仓
{t('crossMargin', language)}
</button>
<button
type="button"
Expand All @@ -414,7 +414,7 @@ export function TraderConfigModal({
: 'bg-[#0B0E11] text-[#848E9C] border border-[#2B3139]'
}`}
>
逐仓
{t('isolatedMargin', language)}
</button>
</div>
</div>
Expand Down Expand Up @@ -446,7 +446,7 @@ export function TraderConfigModal({
{/* Competition visibility */}
<div>
<label className="text-sm text-[#EAECEF] block mb-2">
竞技场显示
{t('competitionDisplay', language)}
</label>
<div className="flex gap-2">
<button
Expand All @@ -458,7 +458,7 @@ export function TraderConfigModal({
: 'bg-[#0B0E11] text-[#848E9C] border border-[#2B3139]'
}`}
>
显示
{t('show', language)}
</button>
<button
type="button"
Expand All @@ -469,11 +469,11 @@ export function TraderConfigModal({
: 'bg-[#0B0E11] text-[#848E9C] border border-[#2B3139]'
}`}
>
隐藏
{t('hide', language)}
</button>
</div>
<p className="text-xs text-[#848E9C] mt-1">
隐藏后将不在竞技场页面显示此交易员
<p className="text-xs text-[#848E9C] mt-1">
{t('hiddenInCompetition', language)}
</p>
</div>

Expand All @@ -482,15 +482,15 @@ export function TraderConfigModal({
<div>
<div className="flex items-center justify-between mb-2">
<label className="text-sm text-[#EAECEF]">
初始余额 ($)
{t('initialBalanceLabel', language)}
</label>
<button
type="button"
onClick={handleFetchCurrentBalance}
disabled={isFetchingBalance}
className="px-3 py-1 text-xs bg-[#F0B90B] text-black rounded hover:bg-[#E1A706] transition-colors disabled:bg-[#848E9C] disabled:cursor-not-allowed"
>
{isFetchingBalance ? '获取中...' : '获取当前余额'}
{isFetchingBalance ? t('fetching', language) : t('fetchCurrentBalance', language)}
</button>
</div>
<input
Expand All @@ -506,8 +506,8 @@ export function TraderConfigModal({
min="100"
step="0.01"
/>
<p className="text-xs text-[#848E9C] mt-1">
用于手动更新初始余额基准(例如充值/提现后)
<p className="text-xs text-[#848E9C] mt-1">
{t('balanceUpdateHint', language)}
</p>
{balanceFetchError && (
<p className="text-xs text-red-500 mt-1">
Expand Down Expand Up @@ -535,7 +535,7 @@ export function TraderConfigModal({
<line x1="12" x2="12.01" y1="16" y2="16" />
</svg>
<span className="text-sm text-[#848E9C]">
系统将自动获取您的账户净值作为初始余额
{t('autoFetchBalanceInfo', language)}
</span>
</div>
)}
Expand All @@ -550,7 +550,7 @@ export function TraderConfigModal({
onClick={onClose}
className="px-6 py-3 bg-[#2B3139] text-[#EAECEF] rounded-lg hover:bg-[#404750] transition-all duration-200 border border-[#404750]"
>
取消
{t('cancel', language)}
</button>
{onSave && (
<button
Expand All @@ -563,7 +563,7 @@ export function TraderConfigModal({
}
className="px-8 py-3 bg-gradient-to-r from-[#F0B90B] to-[#E1A706] text-black rounded-lg hover:from-[#E1A706] hover:to-[#D4951E] transition-all duration-200 disabled:bg-[#848E9C] disabled:cursor-not-allowed font-medium shadow-lg"
>
{isSaving ? '保存中...' : isEditMode ? '保存修改' : '创建交易员'}
{isSaving ? t('saving', language) : isEditMode ? t('editTrader', language) : t('createTraderButton', language)}
</button>
)}
</div>
Expand Down
Loading