feat(topology): add device description support and polish UI layouts
- Topology: query /api/node-info on node select and display multi-line description
- Topology: widen device node cards and remove SID truncation for full display
- Topology: tune d3-force layout parameters (increased distance & repulsion)
- Topology: fix d3-force string ID matching error ("node not found: 0")
- Settings: switch device description field from Input to multi-line Textarea
- Overview: fix active lines count logic and broken badge layout
- Sidebar: remove redundant Live badge from overview navigation item
This commit is contained in:
+13
-10
@@ -49,28 +49,31 @@ function computeForceLayout(
|
||||
const positions = new Map<string, { x: number; y: number }>()
|
||||
if (topoNodes.length === 0) return positions
|
||||
|
||||
// 节点卡片较宽(~300px),初始环形半径与斥力需足够大以避免重叠
|
||||
const simNodes: LayoutNode[] = topoNodes.map((n, i) => ({
|
||||
...n,
|
||||
// 初始位置:环形分布避免重叠
|
||||
x: Math.cos((2 * Math.PI * i) / Math.max(topoNodes.length, 1)) * 250,
|
||||
y: Math.sin((2 * Math.PI * i) / Math.max(topoNodes.length, 1)) * 250,
|
||||
x: Math.cos((2 * Math.PI * i) / Math.max(topoNodes.length, 1)) * 450,
|
||||
y: Math.sin((2 * Math.PI * i) / Math.max(topoNodes.length, 1)) * 450,
|
||||
}))
|
||||
const nodeIndex = new Map(simNodes.map((n, i) => [n.id, i]))
|
||||
const nodeIds = new Set(simNodes.map((n) => n.id))
|
||||
|
||||
const simLinks = topoEdges
|
||||
.filter((e) => nodeIndex.has(e.source) && nodeIndex.has(e.target))
|
||||
.filter((e) => nodeIds.has(e.source) && nodeIds.has(e.target))
|
||||
.map((e) => {
|
||||
const cost = e.cost > 0 ? e.cost : e.delay
|
||||
// 延迟越高距离越远;基准距离 120px,按 ns 缩放
|
||||
const distance = Math.max(80, Math.min(400, 120 + Math.log10(Math.max(cost, 1)) * 20))
|
||||
return { source: nodeIndex.get(e.source)!, target: nodeIndex.get(e.target)!, distance }
|
||||
// 延迟越高距离越远;基准距离大于卡片宽度,保证相邻节点不挤压
|
||||
const distance = Math.max(280, Math.min(650, 300 + Math.log10(Math.max(cost, 1)) * 35))
|
||||
return { source: e.source, target: e.target, distance }
|
||||
})
|
||||
|
||||
const simulation = forceSimulation(simNodes)
|
||||
.force('charge', forceManyBody().strength(-600))
|
||||
.force('charge', forceManyBody().strength(-2200))
|
||||
.force(
|
||||
'link',
|
||||
forceLink(simLinks).id((d: SimulationNodeDatum) => (d as LayoutNode).id).distance((l: { distance: number }) => l.distance).strength(0.6)
|
||||
forceLink(simLinks)
|
||||
.id((d: SimulationNodeDatum) => (d as LayoutNode).id)
|
||||
.distance((l: any) => l.distance ?? 300)
|
||||
.strength(0.5)
|
||||
)
|
||||
.force('center', forceCenter(0, 0))
|
||||
.stop()
|
||||
|
||||
Reference in New Issue
Block a user