feat: 完善跟单模板管理功能
- 更新需求文档:移除每日最大亏损限制、跟单延迟、轮询和WebSocket配置 - 跟单比例改为百分比格式(10%-1000%),只允许整数 - 所有USDC字段支持最多4位小数 - 固定金额和最小金额校验(必须>=1) - 模板名称支持编辑 - 复制模板改为Modal形式,可编辑后创建 - 模板列表按创建时间降序排序,显示创建时间 - 移动端适配:使用卡片式布局 - 合并跟单比例和固定金额列为跟单配置 - 支持卖出改为跟单卖出 - 菜单结构调整:跟单管理作为父菜单,包含跟单模板和跟单配置子菜单
This commit is contained in:
@@ -1,15 +1,18 @@
|
||||
import { useState } from 'react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { useNavigate, useLocation } from 'react-router-dom'
|
||||
import { Layout as AntLayout, Menu, Drawer, Button } from 'antd'
|
||||
import { useMediaQuery } from 'react-responsive'
|
||||
import {
|
||||
WalletOutlined,
|
||||
UserOutlined,
|
||||
SettingOutlined,
|
||||
UnorderedListOutlined,
|
||||
BarChartOutlined,
|
||||
MenuOutlined
|
||||
MenuOutlined,
|
||||
FileTextOutlined,
|
||||
LinkOutlined,
|
||||
AppstoreOutlined
|
||||
} from '@ant-design/icons'
|
||||
import type { MenuProps } from 'antd'
|
||||
import type { ReactNode } from 'react'
|
||||
|
||||
const { Header, Content, Sider } = AntLayout
|
||||
@@ -24,7 +27,31 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
|
||||
const isMobile = useMediaQuery({ maxWidth: 768 })
|
||||
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
|
||||
|
||||
const menuItems = [
|
||||
// 获取当前选中的菜单项
|
||||
const getSelectedKeys = (): string[] => {
|
||||
return [location.pathname]
|
||||
}
|
||||
|
||||
// 获取当前应该打开的父菜单
|
||||
const getInitialOpenKeys = (): string[] => {
|
||||
const path = location.pathname
|
||||
if (path.startsWith('/templates') || path.startsWith('/copy-trading')) {
|
||||
return ['/copy-trading-management']
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const [openKeys, setOpenKeys] = useState<string[]>(getInitialOpenKeys())
|
||||
|
||||
// 当路径变化时,自动打开对应的父菜单
|
||||
useEffect(() => {
|
||||
const path = location.pathname
|
||||
if (path.startsWith('/templates') || path.startsWith('/copy-trading')) {
|
||||
setOpenKeys(['/copy-trading-management'])
|
||||
}
|
||||
}, [location.pathname])
|
||||
|
||||
const menuItems: MenuProps['items'] = [
|
||||
{
|
||||
key: '/accounts',
|
||||
icon: <WalletOutlined />,
|
||||
@@ -36,9 +63,21 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
|
||||
label: 'Leader 管理'
|
||||
},
|
||||
{
|
||||
key: '/config',
|
||||
icon: <SettingOutlined />,
|
||||
label: '跟单配置'
|
||||
key: '/copy-trading-management',
|
||||
icon: <AppstoreOutlined />,
|
||||
label: '跟单管理',
|
||||
children: [
|
||||
{
|
||||
key: '/templates',
|
||||
icon: <FileTextOutlined />,
|
||||
label: '跟单模板'
|
||||
},
|
||||
{
|
||||
key: '/copy-trading',
|
||||
icon: <LinkOutlined />,
|
||||
label: '跟单配置'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: '/positions',
|
||||
@@ -52,13 +91,21 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
|
||||
}
|
||||
]
|
||||
|
||||
const handleMenuClick = (key: string) => {
|
||||
const handleMenuClick = ({ key }: { key: string }) => {
|
||||
// 如果是父菜单,不导航
|
||||
if (key === '/copy-trading-management') {
|
||||
return
|
||||
}
|
||||
navigate(key)
|
||||
if (isMobile) {
|
||||
setMobileMenuOpen(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOpenChange = (keys: string[]) => {
|
||||
setOpenKeys(keys)
|
||||
}
|
||||
|
||||
if (isMobile) {
|
||||
// 移动端布局
|
||||
return (
|
||||
@@ -96,9 +143,11 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
|
||||
>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={[location.pathname]}
|
||||
selectedKeys={getSelectedKeys()}
|
||||
openKeys={openKeys}
|
||||
onOpenChange={handleOpenChange}
|
||||
items={menuItems}
|
||||
onClick={({ key }) => handleMenuClick(key)}
|
||||
onClick={handleMenuClick}
|
||||
style={{ border: 'none' }}
|
||||
/>
|
||||
</Drawer>
|
||||
@@ -134,9 +183,11 @@ const Layout: React.FC<LayoutProps> = ({ children }) => {
|
||||
</div>
|
||||
<Menu
|
||||
mode="inline"
|
||||
selectedKeys={[location.pathname]}
|
||||
selectedKeys={getSelectedKeys()}
|
||||
openKeys={openKeys}
|
||||
onOpenChange={handleOpenChange}
|
||||
items={menuItems}
|
||||
onClick={({ key }) => handleMenuClick(key)}
|
||||
onClick={handleMenuClick}
|
||||
style={{
|
||||
height: 'calc(100vh - 64px)',
|
||||
borderRight: 0,
|
||||
|
||||
Reference in New Issue
Block a user