Skip to content

Commit 73ae3eb

Browse files
committed
fix: Correct the naming errors in the application topology graph API parameters and improve the code comments
1 parent 2186028 commit 73ae3eb

3 files changed

Lines changed: 48 additions & 6 deletions

File tree

ui-vue3/src/api/service/app.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,10 @@ export const updateAppGrayIsolation = (appName: string, graySets: Array<any>): P
177177
})
178178
}
179179

180-
export const getApplicationGraph = (serviceName: string): Promise<any> => {
180+
export const getApplicationGraph = (appName: string): Promise<any> => {
181181
return request({
182182
url: '/application/graph',
183183
method: 'get',
184-
params: { serviceName }
184+
params: { appName }
185185
})
186186
}

ui-vue3/src/views/resources/applications/tabs/topology.vue

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717
<template>
1818
<div class="__container_app_topology">
1919
<a-flex>
20-
<a-card class="topology-warpper"> <div id="topology"></div> </a-card>
20+
<a-card class="topology-warpper">
21+
<!-- G6 mount point (application topology) -->
22+
<div id="topology"></div>
23+
</a-card>
2124
</a-flex>
25+
<!-- Right drawer: show application details after node click -->
2226
<a-drawer v-model:open="detailDrawerOpen" :title="detailTitle" placement="right" width="520">
2327
<a-spin :spinning="detailLoading">
2428
<a-typography-text v-if="detailError" type="danger">{{ detailError }}</a-typography-text>
@@ -51,15 +55,18 @@ import { VueNode } from 'g6-extension-vue'
5155
5256
const route = useRoute()
5357
58+
// G6 graph instance for this view (resize/destroy lifecycle)
5459
const graphRef = shallowRef<Graph | null>(null)
5560
61+
// Right-side detail drawer state
5662
const detailDrawerOpen = ref(false)
5763
const detailLoading = ref(false)
5864
const detailError = ref('')
5965
const detailData = shallowRef<Record<string, unknown>>({})
6066
const currentDetailKey = ref('')
6167
const selectedNodeId = ref('')
6268
69+
// Clear selection when the drawer closes to avoid stale highlight
6370
const clearSelectedNode = () => {
6471
const id = selectedNodeId.value
6572
if (id && graphRef.value) {
@@ -82,6 +89,7 @@ type VueNodeViewData = {
8289
data?: Record<string, unknown>
8390
}
8491
92+
// Node renderer: render a TSX component into a G6 node via VueNode
8593
const StatefulNode = defineComponent({
8694
props: {
8795
data: { type: Object as PropType<VueNodeViewData>, required: true }
@@ -138,19 +146,23 @@ const StatefulNode = defineComponent({
138146
}
139147
})
140148
149+
// Register the VueNode extension type in G6
141150
register(ExtensionCategory.NODE, 'vue-node', VueNode)
142151
152+
// Drawer title: current node (application name)
143153
const detailTitle = computed(() => {
144154
return currentDetailKey.value ? `应用详情:${currentDetailKey.value}` : '应用详情'
145155
})
146156
157+
// Expand detail object into description entries and filter empty values
147158
const detailEntries = computed(() => {
148159
const data = detailData.value ?? {}
149160
return Object.entries(data)
150161
.filter(([, v]) => v !== undefined && v !== null && String(v) !== '')
151162
.map(([key, value]) => ({ key, value }))
152163
})
153164
165+
// Format values for display (primitives/arrays/objects)
154166
const formatValueForDisplay = (v: unknown): string => {
155167
if (v === null || v === undefined) return ''
156168
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v)
@@ -169,6 +181,7 @@ const formatValueForDisplay = (v: unknown): string => {
169181
return String(v)
170182
}
171183
184+
// Convert backend topology payload into G6 nodes/edges
172185
const buildGraphData = (raw: any) => {
173186
const nodes = Array.isArray(raw?.nodes)
174187
? raw.nodes.map((n: any) => ({
@@ -189,6 +202,7 @@ const buildGraphData = (raw: any) => {
189202
return { nodes, edges }
190203
}
191204
205+
// Render topology: create Graph, configure layout/styles/behaviors, bind node click
192206
const renderTopology = (graphData: any) => {
193207
const root = document.getElementById('topology')
194208
if (!root) return
@@ -232,6 +246,7 @@ const renderTopology = (graphData: any) => {
232246
]
233247
})
234248
249+
// On node click, fetch application detail and show it in the drawer
235250
const handleNodeClick = async (e: any) => {
236251
const rawId = e?.target?.id
237252
const appName = rawId == null ? '' : String(rawId)
@@ -268,13 +283,15 @@ const renderTopology = (graphData: any) => {
268283
let resizeHandler: (() => void) | null = null
269284
onMounted(async () => {
270285
try {
271-
const serviceName = String(route.params?.pathId ?? '')
272-
const res = await getApplicationGraph(serviceName)
286+
// Fetch application graph by route param and render with force layout
287+
const appName = String(route.params?.pathId ?? '')
288+
const res = await getApplicationGraph(appName)
273289
if (res?.code !== HTTP_STATUS.SUCCESS) return
274290
275291
const graphData = buildGraphData(res?.data)
276292
renderTopology(graphData)
277293
294+
// Resize canvas on window resize (keep container width responsive)
278295
resizeHandler = () => {
279296
const root = document.getElementById('topology')
280297
if (!root || !graphRef.value) return
@@ -286,6 +303,7 @@ onMounted(async () => {
286303
287304
onBeforeUnmount(() => {
288305
if (resizeHandler) window.removeEventListener('resize', resizeHandler)
306+
// Destroy Graph on unmount to release events/resources
289307
graphRef.value?.destroy()
290308
graphRef.value = null
291309
})

ui-vue3/src/views/resources/services/tabs/topology.vue

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,12 @@
1717
<template>
1818
<div class="__container_app_topology">
1919
<a-flex>
20-
<a-card class="topology-warpper"> <div id="topology"></div> </a-card>
20+
<a-card class="topology-warpper">
21+
<!-- G6 mount point (service call topology) -->
22+
<div id="topology"></div>
23+
</a-card>
2124
</a-flex>
25+
<!-- Right drawer: show service/application details after node click -->
2226
<a-drawer v-model:open="detailDrawerOpen" :title="detailTitle" placement="right" width="520">
2327
<a-spin :spinning="detailLoading">
2428
<a-typography-text v-if="detailError" type="danger">{{ detailError }}</a-typography-text>
@@ -52,17 +56,25 @@ import { useRoute } from 'vue-router'
5256
import { ExtensionCategory, register, Graph, NodeEvent } from '@antv/g6'
5357
const route = useRoute()
5458
59+
// G6 graph instance for this view (resize/destroy lifecycle)
5560
const graphRef = shallowRef<Graph | null>(null)
5661
register(ExtensionCategory.NODE, 'vue-node', VueNode)
62+
63+
// Right-side detail drawer state
5764
const detailDrawerOpen = ref(false)
5865
const detailLoading = ref(false)
5966
const detailError = ref('')
6067
const detailData = shallowRef<Record<string, unknown>>({})
68+
69+
// Detail cache to avoid refetching the same node
6170
const detailCache = new Map<string, Record<string, unknown>>()
71+
72+
// Current selected node info (for title and API selection)
6273
const currentDetailKey = ref('')
6374
const currentDetailType = ref('')
6475
const selectedNodeId = ref('')
6576
77+
// Clear selection when the drawer closes to avoid stale highlight
6678
const clearSelectedNode = () => {
6779
const id = selectedNodeId.value
6880
if (id && graphRef.value) {
@@ -94,6 +106,7 @@ const resolveNodeIconClass = (type: unknown) => {
94106
return 'icon-jiekouzhushou'
95107
}
96108
109+
// Node renderer: choose icon by type and highlight for selected/active state
97110
const StatefulNode = defineComponent({
98111
props: {
99112
data: { type: Object as PropType<VueNodeViewData>, required: true }
@@ -157,13 +170,15 @@ const detailTitle = computed(() => {
157170
return currentDetailKey.value ? `${base}:${currentDetailKey.value}` : base
158171
})
159172
173+
// Expand detail object into description entries and filter empty values
160174
const detailEntries = computed(() => {
161175
const data = detailData.value ?? {}
162176
return Object.entries(data)
163177
.filter(([, v]) => v !== undefined && v !== null && String(v) !== '')
164178
.map(([key, value]) => ({ key, value }))
165179
})
166180
181+
// Format values for display (primitives/arrays/objects)
167182
const formatValueForDisplay = (v: unknown) => {
168183
if (v === null || v === undefined) return ''
169184
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') return String(v)
@@ -182,6 +197,7 @@ const formatValueForDisplay = (v: unknown) => {
182197
return String(v)
183198
}
184199
200+
// Convert backend topology payload into G6 nodes/edges
185201
const buildGraphData = (raw: any) => {
186202
const nodes = Array.isArray(raw?.nodes)
187203
? raw.nodes.map((n: any) => ({
@@ -202,6 +218,8 @@ const buildGraphData = (raw: any) => {
202218
203219
return { nodes, edges }
204220
}
221+
222+
// Render topology: create Graph, configure layout/styles/behaviors, bind node click
205223
const renderTopology = (graphData: any) => {
206224
const root = document.getElementById('topology')
207225
if (!root) return
@@ -244,6 +262,7 @@ const renderTopology = (graphData: any) => {
244262
]
245263
})
246264
265+
// On node click, choose detail API by node type and show it in the drawer
247266
const handleNodeClick = async (e: any) => {
248267
const serviceName = String(e?.target?.id ?? '')
249268
const nodeData: any = serviceName ? graphRef.value?.getNodeData(serviceName) : undefined
@@ -260,6 +279,7 @@ const renderTopology = (graphData: any) => {
260279
: 'service'
261280
detailError.value = ''
262281
282+
// Return immediately on cache hit
263283
const cacheKey = `${serviceName}`
264284
const cached = detailCache.get(cacheKey)
265285
if (cached) {
@@ -271,6 +291,7 @@ const renderTopology = (graphData: any) => {
271291
detailLoading.value = true
272292
try {
273293
let res
294+
// application: use application detail API; service: split 'service:version:group' for service detail API
274295
if (nodeData.type === 'application') {
275296
res = await getApplicationDetail(nodeData.id)
276297
} else if (nodeData.type === 'service') {
@@ -311,13 +332,15 @@ watch(detailEntries, () => {
311332
})
312333
onMounted(async () => {
313334
try {
335+
// Fetch service graph by route param and render with force layout
314336
const serviceName = String(route.params?.pathId ?? '')
315337
console.log('topology', serviceName)
316338
const res = await getServiceGraph(serviceName)
317339
if (res?.code !== HTTP_STATUS.SUCCESS) return
318340
const graphData = buildGraphData(res?.data)
319341
renderTopology(graphData)
320342
343+
// Resize canvas on window resize (keep container width responsive)
321344
resizeHandler = () => {
322345
const root = document.getElementById('topology')
323346
if (!root || !graphRef.value) return
@@ -329,6 +352,7 @@ onMounted(async () => {
329352
330353
onBeforeUnmount(() => {
331354
if (resizeHandler) window.removeEventListener('resize', resizeHandler)
355+
// Destroy Graph on unmount to release events/resources
332356
graphRef.value?.destroy()
333357
graphRef.value = null
334358
})

0 commit comments

Comments
 (0)