import { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { Button, Card, Popover, Space, Switch, Table, Tag, Tooltip } from 'antd'; import type { ColumnsType } from 'antd/es/table'; import { ArrowDownOutlined, ArrowUpOutlined, DeleteOutlined, EditOutlined, GlobalOutlined, PlusOutlined, } from '@ant-design/icons'; import type { HostRecord } from '@/api/queries/useHostsQuery'; import type { InboundOption } from '@/schemas/client'; import './HostList.css'; interface HostListProps { hosts: HostRecord[]; inboundOptions: InboundOption[]; loading?: boolean; isMobile?: boolean; selectedGroupIds: string[]; onSelectionChange: (groupIds: string[]) => void; onAdd: () => void; onEdit: (host: HostRecord) => void; onDelete: (host: HostRecord) => void; onToggleEnable: (host: HostRecord, next: boolean) => void; onMove: (host: HostRecord, dir: 'up' | 'down') => void; onBulkEnable: (enable: boolean) => void; onBulkDelete: () => void; } const INBOUND_PROTOCOL_COLORS: Record = { vless: 'blue', vmess: 'geekblue', trojan: 'volcano', shadowsocks: 'magenta', hysteria: 'cyan', hysteria2: 'green', wireguard: 'gold', http: 'purple', mixed: 'lime', tunnel: 'orange', }; export function sortHosts(hosts: HostRecord[]): HostRecord[] { return [...hosts].sort((a, b) => { const sa = a.sortOrder ?? 0; const sb = b.sortOrder ?? 0; if (sa !== sb) return sa - sb; return (a.remark || '').localeCompare(b.remark || ''); }); } export default function HostList(props: HostListProps) { const { t } = useTranslation(); const { hosts, inboundOptions, loading, isMobile, selectedGroupIds, onSelectionChange, onAdd, onEdit, onDelete, onToggleEnable, onMove, onBulkEnable, onBulkDelete, } = props; const inboundsMap = useMemo(() => { const map = new Map(); for (const ib of inboundOptions) map.set(ib.id, ib); return map; }, [inboundOptions]); const sorted = useMemo(() => sortHosts(hosts), [hosts]); const columns: ColumnsType = [ { title: t('pages.hosts.fields.actions'), key: 'actions', width: 168, render: (_, h, idx) => { const count = sorted.length; return ( ) : ( <> onSelectionChange([])} style={{ marginInlineEnd: 0, padding: '4px 8px', fontSize: 13 }} > {t('pages.hosts.selectedCount', { count: selectedGroupIds.length })} )} ); return ( rowKey="groupId" size="small" loading={loading} columns={columns} dataSource={sorted} pagination={false} scroll={{ x: 'max-content', y: 'calc(100vh - 280px)' }} virtual rowSelection={{ selectedRowKeys: selectedGroupIds, onChange: (keys) => onSelectionChange(keys as string[]), }} locale={{ emptyText: (
{t('noData')}
), }} />
); }