import { useState, useEffect } from 'react' import { Card, Table, Button, Space, Badge, message, Popconfirm, Tag, Switch } from 'antd' import { UpOutlined, DownOutlined, DeleteOutlined, ReloadOutlined, PlusOutlined, ApiOutlined } from '@ant-design/icons' import { apiService } from '../services/api' import type { RpcNodeConfig } from '../types' import AddRpcNodeModal from '../components/AddRpcNodeModal' import { useTranslation } from 'react-i18next' const RpcNodeSettings: React.FC = () => { const { t } = useTranslation() const [nodes, setNodes] = useState([]) const [loading, setLoading] = useState(false) const [checking, setChecking] = useState(false) const [modalVisible, setModalVisible] = useState(false) useEffect(() => { fetchNodes() }, []) const fetchNodes = async () => { setLoading(true) try { const response = await apiService.rpcNodes.list() if (response.data.code === 0 && response.data.data) { setNodes(response.data.data) } else { message.error(response.data.msg || t('rpcNodeSettings.fetchFailed')) } } catch (error: any) { message.error(error.message || t('rpcNodeSettings.fetchFailed')) } finally { setLoading(false) } } const handleCheckAllHealth = async () => { setChecking(true) try { const response = await apiService.rpcNodes.checkHealth({}) if (response.data.code === 0) { message.success(t('rpcNodeSettings.checkHealthSuccess')) fetchNodes() } else { message.error(response.data.msg || t('rpcNodeSettings.checkHealthFailed')) } } catch (error: any) { message.error(error.message || t('rpcNodeSettings.checkHealthFailed')) } finally { setChecking(false) } } const handleDelete = async (id: number) => { try { const response = await apiService.rpcNodes.delete({ id }) if (response.data.code === 0) { message.success(t('rpcNodeSettings.deleteSuccess')) fetchNodes() } else { message.error(response.data.msg || t('rpcNodeSettings.deleteFailed')) } } catch (error: any) { message.error(error.message || t('rpcNodeSettings.deleteFailed')) } } const handleMovePriority = async (id: number, direction: 'up' | 'down') => { const index = nodes.findIndex(n => n.id === id) if (index === -1) return if (direction === 'up' && index === 0) return if (direction === 'down' && index === nodes.length - 1) return const targetIndex = direction === 'up' ? index - 1 : index + 1 const newPriority = nodes[targetIndex].priority try { const response = await apiService.rpcNodes.updatePriority({ id, priority: newPriority }) if (response.data.code === 0) { // 同时更新另一个节点的优先级 await apiService.rpcNodes.updatePriority({ id: nodes[targetIndex].id, priority: nodes[index].priority }) message.success(t('rpcNodeSettings.adjustPrioritySuccess')) fetchNodes() } else { message.error(response.data.msg || t('rpcNodeSettings.adjustPriorityFailed')) } } catch (error: any) { message.error(error.message || t('rpcNodeSettings.adjustPriorityFailed')) } } const handleToggleEnabled = async (id: number, enabled: boolean) => { try { const response = await apiService.rpcNodes.update({ id, enabled }) if (response.data.code === 0) { message.success(enabled ? t('rpcNodeSettings.enableSuccess') : t('rpcNodeSettings.disableSuccess')) fetchNodes() } else { message.error(response.data.msg || t('rpcNodeSettings.updateFailed')) } } catch (error: any) { message.error(error.message || t('rpcNodeSettings.updateFailed')) } } const columns = [ { title: t('rpcNodeSettings.priority'), dataIndex: 'priority', width: 120, render: (_: any, record: RpcNodeConfig, index: number) => ( handleDelete(record.id)} okText={t('rpcNodeSettings.deleteConfirmOk')} cancelText={t('rpcNodeSettings.deleteConfirmCancel')} > ) } ] return ( {t('rpcNodeSettings.title')} } extra={ } > setModalVisible(false)} onSuccess={() => { setModalVisible(false) fetchNodes() }} /> ) } export default RpcNodeSettings