网关配置的表格添加内网IP的inner_ip字段的筛选条件

This commit is contained in:
wmp
2025-10-20 17:15:10 +08:00
parent 8c05d0b332
commit 9fff300a22
3 changed files with 145 additions and 141 deletions

View File

@@ -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<typeof filterSchema>
// 初始化表单
const form = useForm<FilterFormValues>({
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() {
</Button>
</form>
</Form>
<div className="flex gap-6 p-2 items-center justify-between text-sm">
<div className="flex gap-2">
<div className="flex items-center gap-2">
@@ -414,15 +424,17 @@ function GatewayConfigContent() {
</div>
</div>
</div>
<Table>
<TableHeader>
<TableRow>
<TableHead>
</TableHead>
{macAddresses.map((macaddr, index) => (
<TableHead className="border-r sticky left-0 bg-white z-10"></TableHead>
{gatewayPairs.map((pair, index) => (
<TableHead key={index} className="border-r">
{macaddr}
<div className="flex flex-col items-center">
<div className="font-medium">{pair.macaddr}</div>
<div className="text-xs text-gray-500 mt-1">{pair.inner_ip}</div>
</div>
</TableHead>
))}
</TableRow>
@@ -430,33 +442,28 @@ function GatewayConfigContent() {
<TableBody>
{matrixData.map((row, rowIndex) => (
<TableRow key={rowIndex}>
<TableCell className="border-r">{row.inner_ip}</TableCell>
{macAddresses.map((macaddr, colIndex) => {
const configs = row.devices[macaddr] || []
<TableCell className="border-r sticky left-0 bg-white z-10">{row.inner_ip}</TableCell>
{gatewayPairs.map((pair, colIndex) => {
const configs = row.devices[pair.macaddr] || []
return (
<TableCell key={`${rowIndex}-${colIndex}`} className="border-r">
{ configs.length === 0 ? (
{configs.length === 0 ? (
<div className="text-center">-</div>
) : (
<div className="space-y-2">
{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 (
<div key={itemIndex} className="flex flex-col gap-1 transition-shadow">
<div className="flex justify-between items-center">
<span className="text-sm font-medium">{item.public || 'N/A'}</span>
</div>
<div className="flex justify-between items-center">
<span className="text-xs font-medium">{item.city || 'N/A'}</span>
</div>
<div key={itemIndex} className="flex flex-col gap-1">
<div className="text-sm font-medium">{item.public || 'N/A'}</div>
<div className="text-xs font-medium">{item.city || 'N/A'}</div>
<div className="flex justify-between items-center">
<span className={`px-2 py-0.5 rounded text-xs font-medium ${statusConfig.ischange.bg} ${statusConfig.ischange.text}`}>
{statusConfig.ischange.label}

View File

@@ -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

View File

@@ -261,7 +261,6 @@ export default function Settings() {
/>
</div>
<div className="border rounded-lg">
<DataTable
data={newData}
columns={[
@@ -291,7 +290,6 @@ export default function Settings() {
]}
/>
</div>
</div>
<Toaster richColors />
</Page>
)