diff --git a/src/app/(root)/gatewayMonitor/page.tsx b/src/app/(root)/gatewayMonitor/page.tsx index ecce44c..a53159b 100644 --- a/src/app/(root)/gatewayMonitor/page.tsx +++ b/src/app/(root)/gatewayMonitor/page.tsx @@ -25,7 +25,10 @@ function GatewayConfigContent() { const [initialConfigData, setInitialConfigData] = useState<{ [mac: string]: GatewayConfig[] }>({}) // 初始数据是否已加载完成 const [isInitialDataLoaded, setIsInitialDataLoaded] = useState(false) - // 定义表单验证规则 + // MAC 地址 - 内网 IP + const [gatewayPairs, setGatewayPairs] = useState<{ macaddr: string, inner_ip: string }[]>([]) + + // 表单验证规则 const filterSchema = z.object({ macaddr: z.string().optional(), public: z.string().optional(), @@ -33,10 +36,7 @@ function GatewayConfigContent() { inner_ip: z.string().optional(), user: z.string().optional(), }) - type FilterFormValues = z.infer - - // 初始化表单 const form = useForm({ resolver: zodResolver(filterSchema), defaultValues: { @@ -62,6 +62,8 @@ function GatewayConfigContent() { return processedItem }) } + + // 获取IP最后一段用于排序 const getLastOctet = (ip: string | undefined): number => { if (!ip) return 0 const parts = ip.split('.') @@ -70,14 +72,14 @@ function GatewayConfigContent() { return isNaN(last) ? 0 : last } - // 端口排序函数 + // 按内网IP排序配置 const sortByInnerIp = (a: GatewayConfig, b: GatewayConfig): number => { const lastOctetA = getLastOctet(a.inner_ip) const lastOctetB = getLastOctet(b.inner_ip) return lastOctetA - lastOctetB } - // 为每个MAC地址获取配置数据的函数 + // 为单个MAC获取配置数据 const fetchConfigForMac = async (mac: string, filters: { mac?: string | undefined public?: string | undefined @@ -90,16 +92,17 @@ function GatewayConfigContent() { const result = await getGatewayConfig(1, queryParams) if (result.success) { const processedData = processCityNames(result.data.items) - const sortedData = [...processedData].sort(sortByInnerIp) - return sortedData + return [...processedData].sort(sortByInnerIp) } return [] } catch (error) { - console.error(`获取MAC地址 ${mac} 的配置失败:`, error) + console.error(`获取MAC ${mac} 配置失败:`, error) return [] } } + + // 本地筛选数据 const filterLocalData = (filters: { mac?: string public?: string @@ -108,18 +111,26 @@ function GatewayConfigContent() { inner_ip?: string }) => { const { mac, public: publicIp, city, user, inner_ip } = filters - // 筛选MAC地址 - let filteredMacs = initialMacAddresses + let filteredPairs = [...gatewayPairs] + + // 按MAC筛选 if (mac) { - filteredMacs = filteredMacs.filter(macAddr => - macAddr.toLowerCase().includes(mac.toLowerCase()), + filteredPairs = filteredPairs.filter(pair => + pair.macaddr.toLowerCase().includes(mac.toLowerCase()), ) } - // 筛选每个MAC地址对应的配置数据 - const filteredConfigs: { [mac: string]: GatewayConfig[] } = {} - filteredMacs.forEach((macAddr) => { - const configs = initialConfigData[macAddr] || [] + // 按内网IP筛选 + if (inner_ip) { + filteredPairs = filteredPairs.filter(pair => + pair.inner_ip.includes(inner_ip), + ) + } + + // 筛选配置数据 + const filteredConfigs: { [mac: string]: GatewayConfig[] } = {} + filteredPairs.forEach((pair) => { + const configs = initialConfigData[pair.macaddr] || [] const filtered = configs.filter((config) => { // 按各个字段筛选 const matchPublic = !publicIp || (config.public && config.public.includes(publicIp)) @@ -128,24 +139,35 @@ function GatewayConfigContent() { const matchInnerIp = !inner_ip || (config.inner_ip && config.inner_ip.includes(inner_ip)) return matchPublic && matchCity && matchUser && matchInnerIp }) - if (filtered.length > 0) { - filteredConfigs[macAddr] = filtered + filteredConfigs[pair.macaddr] = filtered } }) - return { filteredMacs: Object.keys(filteredConfigs), filteredConfigs } + + // 筛选后按内网IP重新排序,确保表头与列顺序一致 + const sortedFilteredPairs = filteredPairs + .filter(pair => filteredConfigs[pair.macaddr]?.length > 0) + .sort((a, b) => { + const lastOctetA = getLastOctet(a.inner_ip) + const lastOctetB = getLastOctet(b.inner_ip) + return lastOctetA - lastOctetB + }) + + return { filteredPairs: sortedFilteredPairs, filteredConfigs } } - // 矩阵数据构建函数 + // 构建矩阵数据 const buildMatrixData = async ( - macList: string[], + gatewayPairsList: { macaddr: string, inner_ip: string }[], configData: { [mac: string]: GatewayConfig[] } = {}, useLocalData: boolean = false, ) => { setLoading(true) try { let macConfigMap: { [mac: string]: GatewayConfig[] } = {} + const macList = gatewayPairsList.map(pair => pair.macaddr) + // 加载配置数据 if (useLocalData) { // 使用本地数据 macConfigMap = configData @@ -161,96 +183,91 @@ function GatewayConfigContent() { }) } + // 获取所有端口并排序 const allPortLines = Array.from( new Set( Object.values(macConfigMap) .flat() - .map(item => item.inner_ip)// 获取端口和线路 + .map(item => item.inner_ip) .filter(Boolean), ), - ) - const portLineConfigMap: { [key: string]: GatewayConfig } = {} - Object.values(macConfigMap).forEach((configs) => { - configs.forEach((config) => { - const key = config.inner_ip - if (!portLineConfigMap[key]) { - portLineConfigMap[key] = config - } - }) - }) - // 按端口号排序 - const sortedPortLines = allPortLines.sort((a, b) => { + ).sort((a, b) => { const portA = getLastOctet(a.split('|')[0]) const portB = getLastOctet(b.split('|')[0]) return portA - portB }) - // 构建矩阵数据 - const matrix = sortedPortLines.map((portLine) => { + // 构建矩阵 + const matrix = allPortLines.map((portLine) => { const [inner_ip] = portLine.split('|') - const config = portLineConfigMap[portLine] + const row = { inner_ip: inner_ip || '', devices: {} as { [macaddr: string]: GatewayConfig[] } } - const row = { - inner_ip: inner_ip || '', - devices: {} as { [macaddr: string]: GatewayConfig[] }, - } - - // 为每个MAC地址填充该城市的配置数据 - macList.forEach((mac) => { - const configsForPortLine = macConfigMap[mac] - .filter(item => item.inner_ip === inner_ip) + // 遍历排序后的网关对,双重校验配置归属 + gatewayPairsList.forEach((pair) => { + const configsForPortLine = macConfigMap[pair.macaddr] + .filter(item => item.inner_ip === inner_ip) // 匹配当前行端口 .sort(sortByInnerIp) - row.devices[mac] = configsForPortLine + row.devices[pair.macaddr] = configsForPortLine }) + return row }) + // 更新状态 setMatrixData(matrix) - setMacAddresses(macList) + setGatewayPairs(gatewayPairsList) setCurrentTotal(matrix.length) - - // 计算总记录数 - const total = Object.values(macConfigMap).reduce((sum, configs) => sum + configs.length, 0) - setTotalCount(total) + setTotalCount(Object.values(macConfigMap).reduce((sum, configs) => sum + configs.length, 0)) + console.log('矩阵构建完成:', { 表头列数: gatewayPairsList.length, 矩阵行数: matrix.length }) } catch (error) { toast.error('构建矩阵数据失败') - console.error('构建矩阵数据错误:', error) + console.error('矩阵构建错误:', error) } finally { setLoading(false) } } - // 初始化调用 + + // 初始化数据 useEffect(() => { const initData = async () => { setLoading(true) try { // 获取网关基本信息 const infoResult = await getGatewayInfo() - - if (!infoResult.success) { - throw new Error(infoResult.error || '查询网关信息失败') - } + if (!infoResult.success) throw new Error(infoResult.error || '查询网关信息失败') setInfoData(infoResult.data) - // 获取所有MAC地址 - const allMacAddresses = Array.from( - new Set(infoResult.data.map(item => item.macaddr).filter(Boolean)), - ).sort() as string[] - setInitialMacAddresses(allMacAddresses) - setMacAddresses(allMacAddresses) - const configPromises = allMacAddresses.map(mac => fetchConfigForMac(mac, {})) - const configResults = await Promise.all(configPromises) + // 构建排序后的网关对(MAC+内网IP) + const sortedGatewayPairs = infoResult.data + .filter(item => item.macaddr && item.inner_ip) + .sort((a, b) => { + const lastOctetA = getLastOctet(a.inner_ip) + const lastOctetB = getLastOctet(b.inner_ip) + return lastOctetA - lastOctetB + }) + .map(item => ({ macaddr: item.macaddr!, inner_ip: item.inner_ip! })) + + // 加载初始配置 + setGatewayPairs(sortedGatewayPairs)// 表头数据 + const sortedMacAddresses = sortedGatewayPairs.map(pair => pair.macaddr) + + setInitialMacAddresses(sortedMacAddresses) + setMacAddresses(sortedMacAddresses) + + const configPromises = sortedMacAddresses.map(mac => fetchConfigForMac(mac, {})) + const configResults = await Promise.all(configPromises) const initialConfig: { [mac: string]: GatewayConfig[] } = {} - allMacAddresses.forEach((mac, index) => { + sortedMacAddresses.forEach((mac, index) => { initialConfig[mac] = configResults[index] || [] }) setInitialConfigData(initialConfig) setIsInitialDataLoaded(true) - // 每个MAC地址调用接口 - await buildMatrixData(allMacAddresses, initialConfig, true) + + // 构建初始矩阵 + await buildMatrixData(sortedGatewayPairs, initialConfig, true) } catch (error) { toast.error((error as Error).message || '获取数据失败') @@ -259,11 +276,10 @@ function GatewayConfigContent() { setLoading(false) } } - initData() }, []) - // 网关配置数据查询函数(用于表单查询) + // 查询数据表单查询 const fetchData = async (filters: { mac?: string public?: string @@ -275,34 +291,26 @@ function GatewayConfigContent() { try { // 如果有初始数据,就本地筛选 if (isInitialDataLoaded) { - const { filteredMacs, filteredConfigs } = filterLocalData(filters) - - // 更新表格数据(扁平化所有配置数据) - const allFilteredData = Object.values(filteredConfigs).flat() - setData(allFilteredData) - setTotalCount(allFilteredData.length) - - // 构建矩阵数据 - await buildMatrixData(filteredMacs, filteredConfigs, true) + const { filteredPairs, filteredConfigs } = filterLocalData(filters) + setData(Object.values(filteredConfigs).flat()) + setTotalCount(Object.values(filteredConfigs).flat().length) + await buildMatrixData(filteredPairs, filteredConfigs, true) } else { // 如果没有初始数据,就接口查询 const result = await getGatewayConfig(page, filters) - - if (!result.success) { - throw new Error(result.error || '查询网关配置失败') - } + if (!result.success) throw new Error(result.error || '查询网关配置失败') const processedData = processCityNames(result.data.items) const sortedData = [...processedData].sort(sortByInnerIp) - setData(sortedData) setTotalCount(result.data.total) - const filteredMacs = Array.from( - new Set(sortedData.map(item => item.edge).filter(Boolean)), - ).sort() as string[] + const filteredMacs = Array.from(new Set(sortedData.map(item => item.edge).filter(Boolean))).sort() as string[] + const temporaryGatewayPairs = filteredMacs + .map(mac => ({ macaddr: mac, inner_ip: '' })) + .sort((a, b) => a.macaddr.localeCompare(b.macaddr)) - await buildMatrixData(filteredMacs, {}, false) + await buildMatrixData(temporaryGatewayPairs, {}, false) } } catch (error) { @@ -313,6 +321,7 @@ function GatewayConfigContent() { } } + // 提交查询 const onSubmit = async (formData: FilterFormValues) => { const filters = { mac: formData.macaddr || '', @@ -382,6 +391,7 @@ function GatewayConfigContent() { +
@@ -414,15 +424,17 @@ function GatewayConfigContent() {
+ - - 端口 - - {macAddresses.map((macaddr, index) => ( + 端口 + {gatewayPairs.map((pair, index) => ( - {macaddr} +
+
{pair.macaddr}
+
{pair.inner_ip}
+
))}
@@ -430,33 +442,28 @@ function GatewayConfigContent() { {matrixData.map((row, rowIndex) => ( - {row.inner_ip} - {macAddresses.map((macaddr, colIndex) => { - const configs = row.devices[macaddr] || [] + {row.inner_ip} + {gatewayPairs.map((pair, colIndex) => { + const configs = row.devices[pair.macaddr] || [] return ( - { configs.length === 0 ? ( + {configs.length === 0 ? (
-
) : (
{configs.map((item, itemIndex) => { const statusConfig = { ischange: item.ischange === 0 - ? { bg: 'bg-green-100', border: 'border-green-200', text: 'text-green-800', label: '正常' } - : { bg: 'bg-yellow-100', border: 'border-yellow-200', text: 'text-yellow-800', label: '更新' }, + ? { bg: 'bg-green-100', text: 'text-green-800', label: '正常' } + : { bg: 'bg-yellow-100', text: 'text-yellow-800', label: '更新' }, isonline: item.isonline === 0 - ? { bg: 'bg-green-100', border: 'border-green-200', text: 'text-green-800', label: '空闲' } - : { bg: 'bg-blue-100', border: 'border-blue-200', text: 'text-blue-800', label: '在用' }, + ? { bg: 'bg-green-100', text: 'text-green-800', label: '空闲' } + : { bg: 'bg-blue-100', text: 'text-blue-800', label: '在用' }, } - return ( -
-
- {item.public || 'N/A'} -
-
- {item.city || 'N/A'} -
+
+
{item.public || 'N/A'}
+
{item.city || 'N/A'}
{statusConfig.ischange.label} diff --git a/src/app/(root)/gatewayinfo/page.tsx b/src/app/(root)/gatewayinfo/page.tsx index 6b4ecb6..4c87ca0 100644 --- a/src/app/(root)/gatewayinfo/page.tsx +++ b/src/app/(root)/gatewayinfo/page.tsx @@ -120,7 +120,6 @@ export default function Gatewayinfo() { setLoading(true) setError('') const result = await getGatewayInfo() - console.log(result.data) setData(result.data) setFilteredData(result.data) // 初始化时设置filteredData diff --git a/src/app/(root)/settings/page.tsx b/src/app/(root)/settings/page.tsx index 97738a9..c85a769 100644 --- a/src/app/(root)/settings/page.tsx +++ b/src/app/(root)/settings/page.tsx @@ -261,36 +261,34 @@ export default function Settings() { />
-
- { + return ( + + ) }, - { - label: '创建时间', - props: 'createdAt', - }, - { - label: '操作', - render: (val) => { - return ( - - ) - }, - }, - ]} - /> -
+ }, + ]} + />