更新二维矩阵里的首列字段展示
This commit is contained in:
@@ -15,8 +15,7 @@ function GatewayConfigContent() {
|
|||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [infoData, setInfoData] = useState<GatewayInfo[]>([])
|
const [infoData, setInfoData] = useState<GatewayInfo[]>([])
|
||||||
const [totalCount, setTotalCount] = useState(0)
|
const [totalCount, setTotalCount] = useState(0)
|
||||||
const [matrixData, setMatrixData] = useState<{ city: string, devices: { [macaddr: string]: GatewayConfig[] } }[]>([])
|
const [matrixData, setMatrixData] = useState<{ inner_ip: string, devices: { [macaddr: string]: GatewayConfig[] } }[]>([])
|
||||||
const [cities, setCities] = useState<string[]>([])
|
|
||||||
const [macAddresses, setMacAddresses] = useState<string[]>([])
|
const [macAddresses, setMacAddresses] = useState<string[]>([])
|
||||||
const [currentTotal, setCurrentTotal] = useState(0)
|
const [currentTotal, setCurrentTotal] = useState(0)
|
||||||
// 缓存处理先保存初始MAC地址列表
|
// 缓存处理先保存初始MAC地址列表
|
||||||
@@ -161,51 +160,51 @@ function GatewayConfigContent() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const cityMinPortMap: { [city: string]: number } = {}
|
const allPortLines = Array.from(
|
||||||
Object.values(macConfigMap).forEach((configs) => {
|
|
||||||
configs.forEach((config) => {
|
|
||||||
const city = config.city
|
|
||||||
if (!city) return // 跳过无城市的配置
|
|
||||||
const currentPortLastOctet = getLastOctet(config.inner_ip)
|
|
||||||
if (!cityMinPortMap[city] || currentPortLastOctet < cityMinPortMap[city]) {
|
|
||||||
cityMinPortMap[city] = currentPortLastOctet
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
// 获取所有唯一的城市
|
|
||||||
const allCities = Array.from(
|
|
||||||
new Set(
|
new Set(
|
||||||
Object.values(macConfigMap)
|
Object.values(macConfigMap)
|
||||||
.flat()
|
.flat()
|
||||||
.map(item => item.city)
|
.map(item => item.inner_ip)// 获取端口和线路
|
||||||
.filter(Boolean),
|
.filter(Boolean),
|
||||||
),
|
),
|
||||||
).sort((cityA, cityB) => {
|
)
|
||||||
const portA = cityMinPortMap[cityA!] || 0
|
const portLineConfigMap: { [key: string]: GatewayConfig } = {}
|
||||||
const portB = cityMinPortMap[cityB!] || 0
|
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) => {
|
||||||
|
const portA = getLastOctet(a.split('|')[0])
|
||||||
|
const portB = getLastOctet(b.split('|')[0])
|
||||||
return portA - portB
|
return portA - portB
|
||||||
}) as string[]
|
})
|
||||||
|
|
||||||
// 构建矩阵数据
|
// 构建矩阵数据
|
||||||
const matrix = allCities.map((city) => {
|
const matrix = sortedPortLines.map((portLine) => {
|
||||||
|
const [inner_ip] = portLine.split('|')
|
||||||
|
const config = portLineConfigMap[portLine]
|
||||||
|
|
||||||
const row = {
|
const row = {
|
||||||
city,
|
inner_ip: inner_ip || '',
|
||||||
devices: {} as { [macaddr: string]: GatewayConfig[] },
|
devices: {} as { [macaddr: string]: GatewayConfig[] },
|
||||||
}
|
}
|
||||||
|
|
||||||
// 为每个MAC地址填充该城市的配置数据
|
// 为每个MAC地址填充该城市的配置数据
|
||||||
macList.forEach((mac) => {
|
macList.forEach((mac) => {
|
||||||
const configsForCity = macConfigMap[mac]
|
const configsForPortLine = macConfigMap[mac]
|
||||||
.filter(item => item.city === city)
|
.filter(item => item.inner_ip === inner_ip)
|
||||||
.sort(sortByInnerIp)
|
.sort(sortByInnerIp)
|
||||||
row.devices[mac] = configsForCity
|
row.devices[mac] = configsForPortLine
|
||||||
})
|
})
|
||||||
return row
|
return row
|
||||||
})
|
})
|
||||||
|
|
||||||
setMatrixData(matrix)
|
setMatrixData(matrix)
|
||||||
setCities(allCities)
|
|
||||||
setMacAddresses(macList)
|
setMacAddresses(macList)
|
||||||
setCurrentTotal(matrix.length)
|
setCurrentTotal(matrix.length)
|
||||||
|
|
||||||
@@ -228,6 +227,7 @@ function GatewayConfigContent() {
|
|||||||
try {
|
try {
|
||||||
// 获取网关基本信息
|
// 获取网关基本信息
|
||||||
const infoResult = await getGatewayInfo()
|
const infoResult = await getGatewayInfo()
|
||||||
|
|
||||||
if (!infoResult.success) {
|
if (!infoResult.success) {
|
||||||
throw new Error(infoResult.error || '查询网关信息失败')
|
throw new Error(infoResult.error || '查询网关信息失败')
|
||||||
}
|
}
|
||||||
@@ -429,13 +429,13 @@ function GatewayConfigContent() {
|
|||||||
<Table>
|
<Table>
|
||||||
<TableHeader>
|
<TableHeader>
|
||||||
<TableRow className="bg-gray-50">
|
<TableRow className="bg-gray-50">
|
||||||
<TableHead className="text-xs text-gray-500 uppercase tracking-wider sticky top-0 left-0 z-20 bg-gray-50 border-r min-w-[120px]">
|
<TableHead className="text-xs text-gray-500 bg-gray-50 uppercase tracking-wider sticky top-0 left-0 z-50 border-r min-w-[110px] shadow-md">
|
||||||
城市
|
端口
|
||||||
</TableHead>
|
</TableHead>
|
||||||
{macAddresses.map((macaddr, index) => (
|
{macAddresses.map((macaddr, index) => (
|
||||||
<TableHead
|
<TableHead
|
||||||
key={index}
|
key={index}
|
||||||
className="text-xs text-gray-500 uppercase tracking-wider sticky top-0 text-center min-w-[200px]"
|
className="text-xs text-gray-500 uppercase tracking-wider sticky top-0 z-30 bg-gray-50 text-center min-w-[110px] border-r"
|
||||||
>
|
>
|
||||||
{macaddr}
|
{macaddr}
|
||||||
</TableHead>
|
</TableHead>
|
||||||
@@ -444,18 +444,19 @@ function GatewayConfigContent() {
|
|||||||
</TableHeader>
|
</TableHeader>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{matrixData.map((row, rowIndex) => (
|
{matrixData.map((row, rowIndex) => (
|
||||||
<TableRow key={rowIndex}>
|
<TableRow key={rowIndex} className="border-b">
|
||||||
<TableCell className="px-4 py-2 font-medium sticky left-0 bg-inherit z-10 border-r">
|
<TableCell className="px-4 py-2 font-medium sticky left-0 z-40 border-r bg-white shadow-[2px_0_0_0_rgba(0,0,0,0.1)] min-w-[110px]">
|
||||||
{row.city}
|
<div className="flex justify-between items-center">
|
||||||
|
<span className="text-sm font-medium">{row.inner_ip || 'N/A'}</span>
|
||||||
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{macAddresses.map((macaddr, colIndex) => {
|
{macAddresses.map((macaddr, colIndex) => {
|
||||||
const configs = row.devices[macaddr] || []
|
const configs = row.devices[macaddr] || []
|
||||||
|
|
||||||
if (configs.length === 0) {
|
if (configs.length === 0) {
|
||||||
return (
|
return (
|
||||||
<TableCell
|
<TableCell
|
||||||
key={`${rowIndex}-${colIndex}`}
|
key={`${rowIndex}-${colIndex}`}
|
||||||
className="px-2 py-3 text-center min-w-[180px]"
|
className="px-2 py-3 text-center min-w-[110px] border-r"
|
||||||
>
|
>
|
||||||
<div className="text-gray-400 text-sm py-6">-</div>
|
<div className="text-gray-400 text-sm py-6">-</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@@ -465,7 +466,8 @@ function GatewayConfigContent() {
|
|||||||
return (
|
return (
|
||||||
<TableCell
|
<TableCell
|
||||||
key={`${rowIndex}-${colIndex}`}
|
key={`${rowIndex}-${colIndex}`}
|
||||||
className="p-2 min-w-[180px]"
|
// className="p-2 min-w-[110px] border-r text-center hover:bg-blue-50"
|
||||||
|
className="px-2 py-3 text-center min-w-[110px] border-r"
|
||||||
>
|
>
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{configs.map((item, itemIndex) => {
|
{configs.map((item, itemIndex) => {
|
||||||
@@ -479,13 +481,12 @@ function GatewayConfigContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={itemIndex} className="flex flex-col gap-1">
|
<div key={itemIndex} className="flex flex-col gap-1 transition-shadow">
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-sm font-medium">{item.public || 'N/A'}</span>
|
<span className="text-sm font-medium">{item.public || 'N/A'}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<span className="text-xs font-medium">{item.user || 'N/A'}</span>
|
<span className="text-xs font-medium">{item.city || 'N/A'}</span>
|
||||||
<span className="text-xs font-medium">{item.inner_ip || 'N/A'}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<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}`}>
|
<span className={`px-2 py-0.5 rounded text-xs font-medium ${statusConfig.ischange.bg} ${statusConfig.ischange.text}`}>
|
||||||
|
|||||||
Reference in New Issue
Block a user