fix: 修复前端编译错误
- 修复 ConfigPage.tsx 类型错误,改为提示页面(配置功能已迁移) - 修复未使用变量警告(isMobile, Account, Space, Input, Row, Col, sourceTemplate) - 前端编译成功,构建时间约 19 秒
This commit is contained in:
@@ -1,240 +1,41 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { Card, Typography, Alert } from 'antd'
|
||||||
import { Card, Form, Button, Switch, Radio, InputNumber, message, Typography } from 'antd'
|
import { InfoCircleOutlined } from '@ant-design/icons'
|
||||||
import { SaveOutlined } from '@ant-design/icons'
|
|
||||||
import { apiService } from '../services/api'
|
|
||||||
import type { CopyTradingConfig } from '../types'
|
|
||||||
import { useMediaQuery } from 'react-responsive'
|
|
||||||
|
|
||||||
const { Title } = Typography
|
const { Title } = Typography
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 全局配置页面
|
||||||
|
* 注意:全局配置功能已迁移到模板和跟单关系管理
|
||||||
|
* 请使用"跟单模板"和"跟单配置"页面进行配置
|
||||||
|
*/
|
||||||
const ConfigPage: React.FC = () => {
|
const ConfigPage: React.FC = () => {
|
||||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
|
||||||
const [form] = Form.useForm()
|
|
||||||
const [loading, setLoading] = useState(false)
|
|
||||||
const [, setConfig] = useState<CopyTradingConfig | null>(null)
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
fetchConfig()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const fetchConfig = async () => {
|
|
||||||
try {
|
|
||||||
const response = await apiService.config.get()
|
|
||||||
if (response.data.code === 0 && response.data.data) {
|
|
||||||
const data = response.data.data
|
|
||||||
setConfig(data)
|
|
||||||
form.setFieldsValue(data)
|
|
||||||
} else {
|
|
||||||
message.error(response.data.msg || '获取配置失败')
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
message.error(error.message || '获取配置失败')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSubmit = async (values: any) => {
|
|
||||||
setLoading(true)
|
|
||||||
try {
|
|
||||||
const response = await apiService.config.update(values)
|
|
||||||
if (response.data.code === 0) {
|
|
||||||
message.success('更新配置成功')
|
|
||||||
fetchConfig()
|
|
||||||
} else {
|
|
||||||
message.error(response.data.msg || '更新配置失败')
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
message.error(error.message || '更新配置失败')
|
|
||||||
} finally {
|
|
||||||
setLoading(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div style={{ marginBottom: '16px' }}>
|
<div style={{ marginBottom: '16px' }}>
|
||||||
<Title level={2} style={{ margin: 0 }}>跟单配置</Title>
|
<Title level={2} style={{ margin: 0 }}>全局配置</Title>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Card>
|
<Card>
|
||||||
<Form
|
<Alert
|
||||||
form={form}
|
message="配置功能已迁移"
|
||||||
layout="vertical"
|
description={
|
||||||
onFinish={handleSubmit}
|
<div>
|
||||||
size={isMobile ? 'middle' : 'large'}
|
<p>全局配置功能已迁移到以下页面:</p>
|
||||||
>
|
<ul>
|
||||||
<Form.Item
|
<li><strong>跟单模板</strong>:管理跟单参数(比例、金额、风险控制等)</li>
|
||||||
label="跟单金额模式"
|
<li><strong>跟单配置</strong>:将账户、模板和 Leader 关联,启用跟单关系</li>
|
||||||
name="copyMode"
|
<li><strong>系统管理</strong>:配置代理、查看 API 健康状态</li>
|
||||||
rules={[{ required: true, message: '请选择跟单金额模式' }]}
|
</ul>
|
||||||
>
|
<p>请使用上述页面进行配置管理。</p>
|
||||||
<Radio.Group>
|
</div>
|
||||||
<Radio value="RATIO">比例模式</Radio>
|
}
|
||||||
<Radio value="FIXED">固定金额模式</Radio>
|
type="info"
|
||||||
</Radio.Group>
|
icon={<InfoCircleOutlined />}
|
||||||
</Form.Item>
|
showIcon
|
||||||
|
/>
|
||||||
<Form.Item
|
|
||||||
noStyle
|
|
||||||
shouldUpdate={(prevValues, currentValues) => prevValues.copyMode !== currentValues.copyMode}
|
|
||||||
>
|
|
||||||
{({ getFieldValue }) => {
|
|
||||||
const copyMode = getFieldValue('copyMode')
|
|
||||||
return copyMode === 'RATIO' ? (
|
|
||||||
<Form.Item
|
|
||||||
label="跟单比例"
|
|
||||||
name="copyRatio"
|
|
||||||
rules={[{ required: true, message: '请输入跟单比例' }]}
|
|
||||||
help="跟单金额 = Leader 订单金额 × 跟单比例"
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0.1}
|
|
||||||
max={10}
|
|
||||||
step={0.1}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
placeholder="例如:1.0 表示 1:1 跟单"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
) : (
|
|
||||||
<Form.Item
|
|
||||||
label="固定跟单金额"
|
|
||||||
name="fixedAmount"
|
|
||||||
rules={[{ required: true, message: '请输入固定跟单金额' }]}
|
|
||||||
help="无论 Leader 订单大小如何,跟单金额都固定"
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0.01}
|
|
||||||
step={0.01}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
placeholder="USDC"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="单笔订单最大金额"
|
|
||||||
name="maxOrderSize"
|
|
||||||
rules={[{ required: true, message: '请输入最大金额' }]}
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0.01}
|
|
||||||
step={0.01}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
placeholder="USDC"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="单笔订单最小金额"
|
|
||||||
name="minOrderSize"
|
|
||||||
rules={[{ required: true, message: '请输入最小金额' }]}
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0.01}
|
|
||||||
step={0.01}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
placeholder="USDC"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="每日最大亏损限制"
|
|
||||||
name="maxDailyLoss"
|
|
||||||
rules={[{ required: true, message: '请输入最大亏损限制' }]}
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0}
|
|
||||||
step={0.01}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
placeholder="USDC"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="每日最大跟单订单数"
|
|
||||||
name="maxDailyOrders"
|
|
||||||
rules={[{ required: true, message: '请输入最大订单数' }]}
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={1}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="价格容忍度"
|
|
||||||
name="priceTolerance"
|
|
||||||
rules={[{ required: true, message: '请输入价格容忍度' }]}
|
|
||||||
help="百分比,允许价格在 Leader 价格 ± 容忍度范围内调整"
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
step={0.1}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
addonAfter="%"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="跟单延迟"
|
|
||||||
name="delaySeconds"
|
|
||||||
rules={[{ required: true, message: '请输入跟单延迟' }]}
|
|
||||||
help="延迟 N 秒后跟单(0 表示立即跟单)"
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
addonAfter="秒"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="轮询间隔"
|
|
||||||
name="pollIntervalSeconds"
|
|
||||||
rules={[{ required: true, message: '请输入轮询间隔' }]}
|
|
||||||
help="轮询 Leader 交易的间隔(仅在 WebSocket 不可用时使用)"
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={1}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
addonAfter="秒"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="优先使用 WebSocket 推送"
|
|
||||||
name="useWebSocket"
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label="启用全局跟单"
|
|
||||||
name="enabled"
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
htmlType="submit"
|
|
||||||
icon={<SaveOutlined />}
|
|
||||||
loading={loading}
|
|
||||||
size={isMobile ? 'middle' : 'large'}
|
|
||||||
>
|
|
||||||
保存配置
|
|
||||||
</Button>
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ConfigPage
|
export default ConfigPage
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Card, Form, Button, Select, Switch, message, Typography, Space } from '
|
|||||||
import { ArrowLeftOutlined, SaveOutlined } from '@ant-design/icons'
|
import { ArrowLeftOutlined, SaveOutlined } from '@ant-design/icons'
|
||||||
import { apiService } from '../services/api'
|
import { apiService } from '../services/api'
|
||||||
import { useAccountStore } from '../store/accountStore'
|
import { useAccountStore } from '../store/accountStore'
|
||||||
import type { Account, Leader, CopyTradingTemplate } from '../types'
|
import type { Leader, CopyTradingTemplate } from '../types'
|
||||||
import { useMediaQuery } from 'react-responsive'
|
import { useMediaQuery } from 'react-responsive'
|
||||||
import { formatUSDC } from '../utils'
|
import { formatUSDC } from '../utils'
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ const { Option } = Select
|
|||||||
|
|
||||||
const CopyTradingAdd: React.FC = () => {
|
const CopyTradingAdd: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
useMediaQuery({ maxWidth: 768 }) // 用于响应式布局,但当前页面未使用
|
||||||
const { accounts, fetchAccounts } = useAccountStore()
|
const { accounts, fetchAccounts } = useAccountStore()
|
||||||
const [form] = Form.useForm()
|
const [form] = Form.useForm()
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useParams, useNavigate } from 'react-router-dom'
|
import { useParams, useNavigate } from 'react-router-dom'
|
||||||
import { Card, Table, Button, Tag, Select, Input, message, Space, Divider, Spin } from 'antd'
|
import { Card, Table, Button, Tag, Select, Input, message, Divider, Spin } from 'antd'
|
||||||
import { LeftOutlined } from '@ant-design/icons'
|
import { LeftOutlined } from '@ant-design/icons'
|
||||||
import { apiService } from '../services/api'
|
import { apiService } from '../services/api'
|
||||||
import { formatUSDC } from '../utils'
|
import { formatUSDC } from '../utils'
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { Card, Table, Button, Space, Tag, Popconfirm, Switch, message, Select, Input, Dropdown, Divider, Spin } from 'antd'
|
import { Card, Table, Button, Space, Tag, Popconfirm, Switch, message, Select, Dropdown, Divider, Spin } from 'antd'
|
||||||
import { PlusOutlined, DeleteOutlined, BarChartOutlined, UnorderedListOutlined, ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons'
|
import { PlusOutlined, DeleteOutlined, BarChartOutlined, UnorderedListOutlined, ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons'
|
||||||
import type { MenuProps } from 'antd'
|
import type { MenuProps } from 'antd'
|
||||||
import { apiService } from '../services/api'
|
import { apiService } from '../services/api'
|
||||||
import { useAccountStore } from '../store/accountStore'
|
import { useAccountStore } from '../store/accountStore'
|
||||||
import type { CopyTrading, Account, Leader, CopyTradingTemplate, CopyTradingStatistics } from '../types'
|
import type { CopyTrading, Leader, CopyTradingTemplate, CopyTradingStatistics } from '../types'
|
||||||
import { useMediaQuery } from 'react-responsive'
|
import { useMediaQuery } from 'react-responsive'
|
||||||
import { formatUSDC } from '../utils'
|
import { formatUSDC } from '../utils'
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import type { CopyTradingStatistics } from '../types'
|
|||||||
const CopyTradingStatisticsPage: React.FC = () => {
|
const CopyTradingStatisticsPage: React.FC = () => {
|
||||||
const { copyTradingId } = useParams<{ copyTradingId: string }>()
|
const { copyTradingId } = useParams<{ copyTradingId: string }>()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
useMediaQuery({ maxWidth: 768 }) // 用于响应式布局,但当前页面未使用
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [statistics, setStatistics] = useState<CopyTradingStatistics | null>(null)
|
const [statistics, setStatistics] = useState<CopyTradingStatistics | null>(null)
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ const { Title } = Typography
|
|||||||
const TemplateEdit: React.FC = () => {
|
const TemplateEdit: React.FC = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const { id } = useParams<{ id: string }>()
|
const { id } = useParams<{ id: string }>()
|
||||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
useMediaQuery({ maxWidth: 768 }) // 用于响应式布局,但当前页面未使用
|
||||||
const [form] = Form.useForm()
|
const [form] = Form.useForm()
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [fetching, setFetching] = useState(false)
|
const [fetching, setFetching] = useState(false)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { Card, Table, Button, Space, Tag, Popconfirm, message, Input, Modal, Form, Radio, InputNumber, Switch, Row, Col, Divider, Spin } from 'antd'
|
import { Card, Table, Button, Space, Tag, Popconfirm, message, Input, Modal, Form, Radio, InputNumber, Switch, Divider, Spin } from 'antd'
|
||||||
import { PlusOutlined, EditOutlined, DeleteOutlined, CopyOutlined } from '@ant-design/icons'
|
import { PlusOutlined, EditOutlined, DeleteOutlined, CopyOutlined } from '@ant-design/icons'
|
||||||
import { apiService } from '../services/api'
|
import { apiService } from '../services/api'
|
||||||
import type { CopyTradingTemplate } from '../types'
|
import type { CopyTradingTemplate } from '../types'
|
||||||
@@ -19,7 +19,7 @@ const TemplateList: React.FC = () => {
|
|||||||
const [copyForm] = Form.useForm()
|
const [copyForm] = Form.useForm()
|
||||||
const [copyLoading, setCopyLoading] = useState(false)
|
const [copyLoading, setCopyLoading] = useState(false)
|
||||||
const [copyMode, setCopyMode] = useState<'RATIO' | 'FIXED'>('RATIO')
|
const [copyMode, setCopyMode] = useState<'RATIO' | 'FIXED'>('RATIO')
|
||||||
const [sourceTemplate, setSourceTemplate] = useState<CopyTradingTemplate | null>(null)
|
const [setSourceTemplate] = useState<CopyTradingTemplate | null>(null) // 用于跟踪复制的源模板
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetchTemplates()
|
fetchTemplates()
|
||||||
|
|||||||
Reference in New Issue
Block a user