import { useCallback, useMemo, useState, type Key } from 'react'; import { useTranslation } from 'react-i18next'; import { Button, Card, Checkbox, Dropdown, Space, Switch, Table, Tag, Tooltip, type MenuProps, } from 'antd'; import { PlusOutlined, MenuOutlined, MoreOutlined, ExportOutlined, ImportOutlined, ReloadOutlined, InfoCircleOutlined, DeleteOutlined, } from '@ant-design/icons'; import { HttpUtil } from '@/utils'; import { buildRowActionsMenu } from './RowActions'; import { useInboundColumns } from './useInboundColumns'; import InboundStatsModal from './InboundStatsModal'; import type { DBInboundRecord, GeneralAction, InboundListProps, RowAction } from './types'; import './InboundList.css'; export default function InboundList({ dbInbounds, clientCount, lastOnlineMap: _lastOnlineMap, expireDiff, trafficDiff, pageSize, isMobile, subEnable, nodesById, hasActiveNode, onAddInbound, onGeneralAction, onRowAction, onBulkDelete, }: InboundListProps) { const { t } = useTranslation(); const [statsRecord, setStatsRecord] = useState(null); const [selectedRowKeys, setSelectedRowKeys] = useState([]); const onSwitchEnable = useCallback(async (dbInbound: DBInboundRecord, next: boolean) => { const previous = dbInbound.enable; dbInbound.enable = next; try { const formData = new FormData(); formData.append('enable', String(next)); const msg = await HttpUtil.post(`/panel/api/inbounds/setEnable/${dbInbound.id}`, formData); if (!msg?.success) dbInbound.enable = previous; } catch { dbInbound.enable = previous; } }, []); const hasAnyRemark = useMemo( () => dbInbounds.some((i) => typeof i.remark === 'string' && i.remark.trim() !== ''), [dbInbounds], ); const toggleSelect = useCallback((id: number, checked: boolean) => { setSelectedRowKeys((prev) => { const next = new Set(prev); if (checked) next.add(id); else next.delete(id); return Array.from(next); }); }, []); const selectAll = useCallback((checked: boolean) => { setSelectedRowKeys(checked ? dbInbounds.map((i) => i.id) : []); }, [dbInbounds]); const allSelected = dbInbounds.length > 0 && selectedRowKeys.length === dbInbounds.length; const someSelected = selectedRowKeys.length > 0 && selectedRowKeys.length < dbInbounds.length; const handleBulkDelete = useCallback(async () => { const ok = await onBulkDelete(selectedRowKeys); if (ok) setSelectedRowKeys([]); }, [onBulkDelete, selectedRowKeys]); const columns = useInboundColumns({ hasAnyRemark, hasActiveNode, nodesById, clientCount, subEnable, expireDiff, trafficDiff, onRowAction, onSwitchEnable, }); const paginationFor = (rows: DBInboundRecord[]) => { const size = pageSize > 0 ? pageSize : rows.length || 1; return { pageSize: size, showSizeChanger: false, hideOnSinglePage: true }; }; const generalActionsMenu: MenuProps = { items: [ { key: 'import', icon: , label: t('pages.inbounds.importInbound') }, { key: 'export', icon: , label: t('pages.inbounds.export') }, ...(subEnable ? [{ key: 'subs', icon: , label: `${t('pages.inbounds.export')} — ${t('pages.settings.subSettings')}` }] : []), { key: 'resetInbounds', icon: , label: t('pages.inbounds.resetAllTraffic') }, ], onClick: ({ key }) => onGeneralAction(key as GeneralAction), }; return ( {selectedRowKeys.length > 0 && ( <> setSelectedRowKeys([])} style={{ marginInlineEnd: 0 }}> {t('pages.inbounds.selectedCount', { count: selectedRowKeys.length })} )} )} > {isMobile ? (
{dbInbounds.length === 0 ? (
{t('noData')}
) : ( <>
selectAll(e.target.checked)} > {t('pages.inbounds.selectAll')} {selectedRowKeys.length > 0 && ( {selectedRowKeys.length} )}
{dbInbounds.map((record) => (
toggleSelect(record.id, e.target.checked)} /> #{record.id} {record.remark}
e.stopPropagation()}> setStatsRecord(record)} /> onSwitchEnable(record, next)} /> 0 }), onClick: ({ key }) => onRowAction({ key: key as RowAction, dbInbound: record }), }} > e.preventDefault()} />
))} )}
) : ( r.id} rowSelection={{ selectedRowKeys, onChange: (keys: Key[]) => setSelectedRowKeys(keys as number[]), }} pagination={paginationFor(dbInbounds)} scroll={{ x: 1000 }} style={{ marginTop: 10 }} size="small" locale={{ emptyText: (
{t('noData')}
), }} /> )} setStatsRecord(null)} /> ); }