diff --git a/cypher-executor/src/routes/portal-ui.ts b/cypher-executor/src/routes/portal-ui.ts index 99c79b9..99b2aa6 100644 --- a/cypher-executor/src/routes/portal-ui.ts +++ b/cypher-executor/src/routes/portal-ui.ts @@ -749,11 +749,23 @@ function renderPortalHtml(brand: string, sourceWebBase = ''): string { if (!x.ok) { $('se-count').innerHTML = '' + esc(x.d.error || ('關聯查詢失敗(HTTP ' + x.status + ')')) + ''; renderGraphEmpty(x.d.error || '關聯查詢失敗'); return; } var neighbors = x.d.neighbors || []; var edges = x.d.edges || []; - $('se-count').textContent = '節點「' + name + '」・鄰居 ' + neighbors.length + '・關聯 ' + edges.length; - if (!neighbors.length) { renderGraphEmpty('尚無關聯資料——這個名字還沒有連進知識圖譜。'); return; } - renderGraph(name, neighbors.slice(0, 10)); + // 形狀相容(Arcrun#57 家族):plugin 版 neighbors 是字串、workflow 版是 + // { node, predicate, from, depth } 物件——不正規化會渲染成 [object Object]。 + var names = neighbors.map(function (nb) { + if (typeof nb === 'string') return nb; + return (nb && (nb.node || nb.name)) || ''; + }).filter(Boolean); + // workflow 版 edges 恆空,但 neighbor 物件本身就是一條邊(from --predicate--> node)→ 導出。 + if (!edges.length) { + edges = neighbors.filter(function (nb) { return nb && typeof nb === 'object' && nb.predicate; }) + .map(function (nb) { return { subject: nb.from || name, predicate: nb.predicate, object: nb.node }; }); + } + $('se-count').textContent = '節點「' + name + '」・鄰居 ' + names.length + '・關聯 ' + edges.length; + if (!names.length) { renderGraphEmpty('尚無關聯資料——這個名字還沒有連進知識圖譜。'); return; } + renderGraph(name, names.slice(0, 10)); $('gr-edges').innerHTML = edges.slice(0, 12).map(function (t) { - var other = t.subject === name ? t.object : t.subject; + // 大小寫不敏感比對(graph 查詢已正規化:搜 rag 會命中節點 RAG) + var other = String(t.subject).toLowerCase() === String(name).toLowerCase() ? t.object : t.subject; return '