mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-06-06 05:51:19 +08:00
Resolved front-end linting issues. (#533)
This commit is contained in:
17
web/package-lock.json
generated
17
web/package-lock.json
generated
@@ -84,7 +84,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz",
|
||||
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
"@babel/generator": "^7.28.5",
|
||||
@@ -1549,7 +1548,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz",
|
||||
"integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
|
||||
"devOptional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"csstype": "^3.0.2"
|
||||
@@ -1600,7 +1598,6 @@
|
||||
"integrity": "sha512-6m1I5RmHBGTnUGS113G04DMu3CpSdxCAU/UvtjNWL4Nuf3MW9tQhiJqRlHzChIkhy6kZSAQmc+I1bcGjE3yNKg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.46.3",
|
||||
"@typescript-eslint/types": "8.46.3",
|
||||
@@ -1839,7 +1836,6 @@
|
||||
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
@@ -2214,7 +2210,6 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"baseline-browser-mapping": "^2.8.19",
|
||||
"caniuse-lite": "^1.0.30001751",
|
||||
@@ -3107,7 +3102,6 @@
|
||||
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.8.0",
|
||||
"@eslint-community/regexpp": "^4.12.1",
|
||||
@@ -3168,7 +3162,6 @@
|
||||
"integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"eslint-config-prettier": "bin/cli.js"
|
||||
},
|
||||
@@ -4553,7 +4546,6 @@
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
|
||||
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"jiti": "bin/jiti.js"
|
||||
}
|
||||
@@ -5408,7 +5400,6 @@
|
||||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
@@ -5562,7 +5553,6 @@
|
||||
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
@@ -5635,7 +5625,6 @@
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
|
||||
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
},
|
||||
@@ -5647,7 +5636,6 @@
|
||||
"version": "18.3.1",
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
"scheduler": "^0.23.2"
|
||||
@@ -6611,7 +6599,6 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -6752,7 +6739,6 @@
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -6860,7 +6846,6 @@
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
|
||||
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.4",
|
||||
@@ -6952,7 +6937,6 @@
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -7203,7 +7187,6 @@
|
||||
"integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
||||
@@ -1039,12 +1039,17 @@ function DecisionCard({
|
||||
保证金率: {decision.account_state.margin_used_pct.toFixed(1)}%
|
||||
</span>
|
||||
<span>持仓: {decision.account_state.position_count}</span>
|
||||
<span style={{
|
||||
color: decision.candidate_coins && decision.candidate_coins.length === 0
|
||||
? '#F6465D'
|
||||
: '#848E9C'
|
||||
}}>
|
||||
{t('candidateCoins', language)}: {decision.candidate_coins?.length || 0}
|
||||
<span
|
||||
style={{
|
||||
color:
|
||||
decision.candidate_coins &&
|
||||
decision.candidate_coins.length === 0
|
||||
? '#F6465D'
|
||||
: '#848E9C',
|
||||
}}
|
||||
>
|
||||
{t('candidateCoins', language)}:{' '}
|
||||
{decision.candidate_coins?.length || 0}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -1056,12 +1061,14 @@ function DecisionCard({
|
||||
style={{
|
||||
background: 'rgba(246, 70, 93, 0.1)',
|
||||
border: '1px solid rgba(246, 70, 93, 0.3)',
|
||||
color: '#F6465D'
|
||||
color: '#F6465D',
|
||||
}}
|
||||
>
|
||||
<AlertTriangle size={16} className="flex-shrink-0 mt-0.5" />
|
||||
<div className="flex-1">
|
||||
<div className="font-semibold mb-1">⚠️ {t('candidateCoinsZeroWarning', language)}</div>
|
||||
<div className="font-semibold mb-1">
|
||||
⚠️ {t('candidateCoinsZeroWarning', language)}
|
||||
</div>
|
||||
<div className="text-xs space-y-1" style={{ color: '#848E9C' }}>
|
||||
<div>{t('possibleReasons', language)}</div>
|
||||
<ul className="list-disc list-inside space-y-0.5 ml-2">
|
||||
|
||||
@@ -113,9 +113,12 @@ export function EquityChart({ traderId }: EquityChartProps) {
|
||||
: validHistory
|
||||
|
||||
// 计算初始余额(优先从 account 获取配置的初始余额,备选从历史数据反推)
|
||||
const initialBalance = account?.initial_balance // 从交易员配置读取真实初始余额
|
||||
|| (validHistory[0] ? validHistory[0].total_equity - validHistory[0].pnl : undefined) // 备选:淨值 - 盈亏
|
||||
|| 1000; // 默认值(与创建交易员时的默认配置一致)
|
||||
const initialBalance =
|
||||
account?.initial_balance || // 从交易员配置读取真实初始余额
|
||||
(validHistory[0]
|
||||
? validHistory[0].total_equity - validHistory[0].pnl
|
||||
: undefined) || // 备选:淨值 - 盈亏
|
||||
1000 // 默认值(与创建交易员时的默认配置一致)
|
||||
|
||||
// 转换数据格式
|
||||
const chartData = displayHistory.map((point) => {
|
||||
|
||||
@@ -102,7 +102,7 @@ export function TraderConfigModal({
|
||||
}
|
||||
// 确保旧数据也有默认的 system_prompt_template
|
||||
if (traderData && traderData.system_prompt_template === undefined) {
|
||||
setFormData(prev => ({
|
||||
setFormData((prev) => ({
|
||||
...prev,
|
||||
system_prompt_template: 'default',
|
||||
}))
|
||||
@@ -186,42 +186,45 @@ export function TraderConfigModal({
|
||||
|
||||
const handleFetchCurrentBalance = async () => {
|
||||
if (!isEditMode || !traderData?.trader_id) {
|
||||
setBalanceFetchError('只有在编辑模式下才能获取当前余额');
|
||||
return;
|
||||
setBalanceFetchError('只有在编辑模式下才能获取当前余额')
|
||||
return
|
||||
}
|
||||
|
||||
setIsFetchingBalance(true);
|
||||
setBalanceFetchError('');
|
||||
setIsFetchingBalance(true)
|
||||
setBalanceFetchError('')
|
||||
|
||||
try {
|
||||
const token = localStorage.getItem('token');
|
||||
const response = await fetch(`/api/account?trader_id=${traderData.trader_id}`, {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${token}`
|
||||
const token = localStorage.getItem('token')
|
||||
const response = await fetch(
|
||||
`/api/account?trader_id=${traderData.trader_id}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
});
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('获取账户余额失败');
|
||||
throw new Error('获取账户余额失败')
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
const data = await response.json()
|
||||
|
||||
// total_equity = 当前账户净值(包含未实现盈亏)
|
||||
// 这应该作为新的初始余额
|
||||
const currentBalance = data.total_equity || data.balance || 0;
|
||||
const currentBalance = data.total_equity || data.balance || 0
|
||||
|
||||
setFormData(prev => ({ ...prev, initial_balance: currentBalance }));
|
||||
setFormData((prev) => ({ ...prev, initial_balance: currentBalance }))
|
||||
|
||||
// 显示成功提示
|
||||
console.log('已获取当前余额:', currentBalance);
|
||||
console.log('已获取当前余额:', currentBalance)
|
||||
} catch (error) {
|
||||
console.error('获取余额失败:', error);
|
||||
setBalanceFetchError('获取余额失败,请检查网络连接');
|
||||
console.error('获取余额失败:', error)
|
||||
setBalanceFetchError('获取余额失败,请检查网络连接')
|
||||
} finally {
|
||||
setIsFetchingBalance(false);
|
||||
setIsFetchingBalance(false)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!onSave) return
|
||||
@@ -390,7 +393,9 @@ export function TraderConfigModal({
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<label className="text-sm text-[#EAECEF]">
|
||||
初始余额 ($)
|
||||
{!isEditMode && <span className="text-[#F0B90B] ml-1">*</span>}
|
||||
{!isEditMode && (
|
||||
<span className="text-[#F0B90B] ml-1">*</span>
|
||||
)}
|
||||
</label>
|
||||
{isEditMode && (
|
||||
<button
|
||||
@@ -418,7 +423,20 @@ export function TraderConfigModal({
|
||||
/>
|
||||
{!isEditMode && (
|
||||
<p className="text-xs text-[#F0B90B] mt-1 flex items-center gap-1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="w-3.5 h-3.5" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z"/><line x1="12" x2="12" y1="9" y2="13"/><line x1="12" x2="12.01" y1="17" y2="17"/></svg>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-3.5 h-3.5"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z" />
|
||||
<line x1="12" x2="12" y1="9" y2="13" />
|
||||
<line x1="12" x2="12.01" y1="17" y2="17" />
|
||||
</svg>
|
||||
请输入您交易所账户的当前实际余额。如果输入不准确,P&L统计将会错误。
|
||||
</p>
|
||||
)}
|
||||
@@ -428,7 +446,9 @@ export function TraderConfigModal({
|
||||
</p>
|
||||
)}
|
||||
{balanceFetchError && (
|
||||
<p className="text-xs text-red-500 mt-1">{balanceFetchError}</p>
|
||||
<p className="text-xs text-red-500 mt-1">
|
||||
{balanceFetchError}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -483,15 +483,19 @@ export const translations = {
|
||||
candidateCoins: 'Candidate Coins',
|
||||
candidateCoinsZeroWarning: 'Candidate Coins Count is 0',
|
||||
possibleReasons: 'Possible Reasons:',
|
||||
coinPoolApiNotConfigured: 'Coin pool API not configured or inaccessible (check signal source settings)',
|
||||
coinPoolApiNotConfigured:
|
||||
'Coin pool API not configured or inaccessible (check signal source settings)',
|
||||
apiConnectionTimeout: 'API connection timeout or returned empty data',
|
||||
noCustomCoinsAndApiFailed: 'No custom coins configured and API fetch failed',
|
||||
noCustomCoinsAndApiFailed:
|
||||
'No custom coins configured and API fetch failed',
|
||||
solutions: 'Solutions:',
|
||||
setCustomCoinsInConfig: 'Set custom coin list in trader configuration',
|
||||
orConfigureCorrectApiUrl: 'Or configure correct coin pool API address',
|
||||
orDisableCoinPoolOptions: 'Or disable "Use Coin Pool" and "Use OI Top" options',
|
||||
orDisableCoinPoolOptions:
|
||||
'Or disable "Use Coin Pool" and "Use OI Top" options',
|
||||
signalSourceNotConfigured: 'Signal Source Not Configured',
|
||||
signalSourceWarningMessage: 'You have traders that enabled "Use Coin Pool" or "Use OI Top", but signal source API address is not configured yet. This will cause candidate coins count to be 0, and traders cannot work properly.',
|
||||
signalSourceWarningMessage:
|
||||
'You have traders that enabled "Use Coin Pool" or "Use OI Top", but signal source API address is not configured yet. This will cause candidate coins count to be 0, and traders cannot work properly.',
|
||||
configureSignalSourceNow: 'Configure Signal Source Now',
|
||||
},
|
||||
zh: {
|
||||
@@ -948,7 +952,8 @@ export const translations = {
|
||||
orConfigureCorrectApiUrl: '或者配置正确的币种池API地址',
|
||||
orDisableCoinPoolOptions: '或者禁用"使用币种池"和"使用OI Top"选项',
|
||||
signalSourceNotConfigured: '信号源未配置',
|
||||
signalSourceWarningMessage: '您有交易员启用了"使用币种池"或"使用OI Top",但尚未配置信号源API地址。这将导致候选币种数量为0,交易员无法正常工作。',
|
||||
signalSourceWarningMessage:
|
||||
'您有交易员启用了"使用币种池"或"使用OI Top",但尚未配置信号源API地址。这将导致候选币种数量为0,交易员无法正常工作。',
|
||||
configureSignalSourceNow: '立即配置信号源',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -330,13 +330,13 @@ export const api = {
|
||||
|
||||
// 获取服务器IP(需要认证,用于白名单配置)
|
||||
async getServerIP(): Promise<{
|
||||
public_ip: string;
|
||||
message: string;
|
||||
public_ip: string
|
||||
message: string
|
||||
}> {
|
||||
const res = await fetch(`${API_BASE}/server-ip`, {
|
||||
headers: getAuthHeaders(),
|
||||
});
|
||||
if (!res.ok) throw new Error('获取服务器IP失败');
|
||||
return res.json();
|
||||
})
|
||||
if (!res.ok) throw new Error('获取服务器IP失败')
|
||||
return res.json()
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user