import { useEffect, useState } from 'react' import { useNavigate, useParams } from 'react-router-dom' import { Card, Form, Input, Button, Radio, InputNumber, Switch, message, Typography, Space, Divider } from 'antd' import { ArrowLeftOutlined, SaveOutlined } from '@ant-design/icons' import { apiService } from '../services/api' import type { CopyTradingTemplate } from '../types' import { useTranslation } from 'react-i18next' const { Title } = Typography const TemplateEdit: React.FC = () => { const { t } = useTranslation() const navigate = useNavigate() const { id } = useParams<{ id: string }>() const [form] = Form.useForm() const [loading, setLoading] = useState(false) const [fetching, setFetching] = useState(false) const [copyMode, setCopyMode] = useState<'RATIO' | 'FIXED'>('RATIO') useEffect(() => { if (id) { fetchTemplate(parseInt(id)) } }, [id]) const fetchTemplate = async (templateId: number) => { setFetching(true) try { const response = await apiService.templates.detail({ templateId }) if (response.data.code === 0 && response.data.data) { const template: CopyTradingTemplate = response.data.data setCopyMode(template.copyMode) form.setFieldsValue({ ...template, // 将小数转换为百分比:1.0 -> 100% copyRatio: template.copyRatio ? parseFloat(template.copyRatio) * 100 : 100, fixedAmount: template.fixedAmount ? parseFloat(template.fixedAmount) : undefined, maxOrderSize: template.maxOrderSize ? parseFloat(template.maxOrderSize) : undefined, minOrderSize: template.minOrderSize ? parseFloat(template.minOrderSize) : undefined, priceTolerance: parseFloat(template.priceTolerance), minOrderDepth: template.minOrderDepth ? parseFloat(template.minOrderDepth) : undefined, maxSpread: template.maxSpread ? parseFloat(template.maxSpread) : undefined, minPrice: template.minPrice ? parseFloat(template.minPrice) : undefined, maxPrice: template.maxPrice ? parseFloat(template.maxPrice) : undefined, pushFilteredOrders: template.pushFilteredOrders ?? false }) } else { message.error(response.data.msg || t('templateEdit.fetchFailed') || '获取模板详情失败') navigate('/templates') } } catch (error: any) { message.error(error.message || t('templateEdit.fetchFailed') || '获取模板详情失败') navigate('/templates') } finally { setFetching(false) } } const handleSubmit = async (values: any) => { if (!id) return // 前端校验:如果填写了 minOrderSize,必须 >= 1 if (values.copyMode === 'RATIO' && values.minOrderSize !== undefined && values.minOrderSize !== null && values.minOrderSize !== '' && Number(values.minOrderSize) < 1) { message.error(t('templateEdit.minOrderSizeError') || '最小金额必须 >= 1') return } // 前端校验:固定金额模式下,fixedAmount 必填且必须 >= 1 if (values.copyMode === 'FIXED') { const fixedAmount = values.fixedAmount if (fixedAmount === undefined || fixedAmount === null || fixedAmount === '') { message.error(t('templateEdit.fixedAmountRequired') || '请输入固定跟单金额') return } const amount = Number(fixedAmount) if (isNaN(amount)) { message.error(t('templateEdit.invalidNumber') || '请输入有效的数字') return } if (amount < 1) { message.error(t('templateEdit.fixedAmountError') || '固定金额必须 >= 1,请重新输入') return } } setLoading(true) try { const response = await apiService.templates.update({ templateId: parseInt(id), templateName: values.templateName, copyMode: values.copyMode, // 将百分比转换为小数:100% -> 1.0 copyRatio: values.copyMode === 'RATIO' && values.copyRatio ? (values.copyRatio / 100).toString() : undefined, fixedAmount: values.copyMode === 'FIXED' ? values.fixedAmount?.toString() : undefined, maxOrderSize: values.copyMode === 'RATIO' ? values.maxOrderSize?.toString() : undefined, minOrderSize: values.copyMode === 'RATIO' ? values.minOrderSize?.toString() : undefined, maxDailyOrders: values.maxDailyOrders, priceTolerance: values.priceTolerance?.toString(), supportSell: values.supportSell, minOrderDepth: values.minOrderDepth?.toString(), maxSpread: values.maxSpread?.toString(), minPrice: values.minPrice?.toString(), maxPrice: values.maxPrice?.toString(), pushFilteredOrders: values.pushFilteredOrders }) if (response.data.code === 0) { message.success(t('templateEdit.saveSuccess') || '更新模板成功') navigate('/templates') } else { message.error(response.data.msg || t('templateEdit.saveFailed') || '更新模板失败') } } catch (error: any) { message.error(error.message || t('templateEdit.saveFailed') || '更新模板失败') } finally { setLoading(false) } } return (