|
@@ -1373,16 +1373,17 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
"关键点": "#9b59b6"
|
|
"关键点": "#9b59b6"
|
|
|
}};
|
|
}};
|
|
|
|
|
|
|
|
- // 获取节点的层级编号(三层结构)
|
|
|
|
|
|
|
+ // 获取节点的层级编号(四层结构)
|
|
|
function getNodeLayer(d) {{
|
|
function getNodeLayer(d) {{
|
|
|
if (d.source === "帖子") {{
|
|
if (d.source === "帖子") {{
|
|
|
return d.节点类型 === "点" ? 0 : 1; // 点=0, 标签=1
|
|
return d.节点类型 === "点" ? 0 : 1; // 点=0, 标签=1
|
|
|
}}
|
|
}}
|
|
|
- return 2; // 人设(标签+分类)都在层2
|
|
|
|
|
|
|
+ // 人设节点:根据是否扩展分成两层
|
|
|
|
|
+ return d.是否扩展 ? 3 : 2; // 直接匹配=2, 扩展=3
|
|
|
}}
|
|
}}
|
|
|
|
|
|
|
|
- // 统计每层节点数量(三层结构)
|
|
|
|
|
- const layerCounts = {{0: 0, 1: 0, 2: 0}};
|
|
|
|
|
|
|
+ // 统计每层节点数量(四层结构)
|
|
|
|
|
+ const layerCounts = {{0: 0, 1: 0, 2: 0, 3: 0}};
|
|
|
nodes.forEach(n => {{
|
|
nodes.forEach(n => {{
|
|
|
const layer = getNodeLayer(n);
|
|
const layer = getNodeLayer(n);
|
|
|
layerCounts[layer]++;
|
|
layerCounts[layer]++;
|
|
@@ -1403,10 +1404,17 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
return Math.max(minRadius, Math.min(maxRadius, r));
|
|
return Math.max(minRadius, Math.min(maxRadius, r));
|
|
|
}}
|
|
}}
|
|
|
|
|
|
|
|
|
|
+ // 左列3层统一大小(取最大值)
|
|
|
|
|
+ const leftColRadius = Math.max(
|
|
|
|
|
+ calcRadius(layerCounts[1]),
|
|
|
|
|
+ calcRadius(layerCounts[2]),
|
|
|
|
|
+ calcRadius(layerCounts[3])
|
|
|
|
|
+ );
|
|
|
const layerRadius = {{
|
|
const layerRadius = {{
|
|
|
0: calcRadius(layerCounts[0]), // 帖子点(右列)
|
|
0: calcRadius(layerCounts[0]), // 帖子点(右列)
|
|
|
- 1: calcRadius(layerCounts[1]), // 帖子标签(左上)
|
|
|
|
|
- 2: calcRadius(layerCounts[2]) // 人设匹配(左下)
|
|
|
|
|
|
|
+ 1: leftColRadius, // 帖子标签(左上)
|
|
|
|
|
+ 2: leftColRadius, // 人设匹配1层(左中)
|
|
|
|
|
+ 3: leftColRadius // 人设匹配2层(左下)
|
|
|
}};
|
|
}};
|
|
|
console.log("每层半径:", layerRadius);
|
|
console.log("每层半径:", layerRadius);
|
|
|
|
|
|
|
@@ -1419,9 +1427,9 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
const egoRadius = 180;
|
|
const egoRadius = 180;
|
|
|
const egoAreaHeight = egoRadius * 2 + 80;
|
|
const egoAreaHeight = egoRadius * 2 + 80;
|
|
|
|
|
|
|
|
- // 计算布局:左列(帖子标签+人设匹配),右列(帖子点)
|
|
|
|
|
- const layerPadding = 40;
|
|
|
|
|
- const leftColHeight = layerRadius[1] * 2 + layerPadding + layerRadius[2] * 2 + layerPadding;
|
|
|
|
|
|
|
+ // 计算布局:左列(帖子标签+人设匹配1层+人设匹配2层),右列(帖子点)
|
|
|
|
|
+ const layerPadding = 30;
|
|
|
|
|
+ const leftColHeight = layerRadius[1] * 2 + layerPadding + layerRadius[2] * 2 + layerPadding + layerRadius[3] * 2 + layerPadding;
|
|
|
const circleHeight = leftColHeight;
|
|
const circleHeight = leftColHeight;
|
|
|
const height = Math.max(circleHeight + 80, treeHeight + 80, container.clientHeight);
|
|
const height = Math.max(circleHeight + 80, treeHeight + 80, container.clientHeight);
|
|
|
|
|
|
|
@@ -1431,13 +1439,15 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
|
|
|
|
|
// 左列居中显示,右列在旁边
|
|
// 左列居中显示,右列在旁边
|
|
|
const leftColX = circleAreaCenterX; // 左列居中
|
|
const leftColX = circleAreaCenterX; // 左列居中
|
|
|
- const rightColX = leftColX + Math.max(layerRadius[1], layerRadius[2]) + layerPadding + layerRadius[0] + 30; // 右列在右边
|
|
|
|
|
|
|
+ const rightColX = leftColX + Math.max(layerRadius[1], layerRadius[2], layerRadius[3]) + layerPadding + layerRadius[0] + 30; // 右列在右边
|
|
|
|
|
|
|
|
- // 左列:帖子标签(上)+ 人设匹配(下)
|
|
|
|
|
|
|
+ // 左列:帖子标签(上)+ 人设匹配1层(中)+ 人设匹配2层(下)
|
|
|
layerCenterX[1] = leftColX;
|
|
layerCenterX[1] = leftColX;
|
|
|
layerCenterY[1] = layerRadius[1] + layerPadding / 2 + 20;
|
|
layerCenterY[1] = layerRadius[1] + layerPadding / 2 + 20;
|
|
|
layerCenterX[2] = leftColX;
|
|
layerCenterX[2] = leftColX;
|
|
|
layerCenterY[2] = layerCenterY[1] + layerRadius[1] + layerPadding + layerRadius[2];
|
|
layerCenterY[2] = layerCenterY[1] + layerRadius[1] + layerPadding + layerRadius[2];
|
|
|
|
|
+ layerCenterX[3] = leftColX;
|
|
|
|
|
+ layerCenterY[3] = layerCenterY[2] + layerRadius[2] + layerPadding + layerRadius[3];
|
|
|
|
|
|
|
|
// 右列:帖子点(与帖子标签同一行开始)
|
|
// 右列:帖子点(与帖子标签同一行开始)
|
|
|
layerCenterX[0] = rightColX;
|
|
layerCenterX[0] = rightColX;
|
|
@@ -1558,7 +1568,7 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
|
|
|
|
|
function force(alpha) {{
|
|
function force(alpha) {{
|
|
|
// 按层分组(三层)
|
|
// 按层分组(三层)
|
|
|
- const layerNodes = {{0: [], 1: [], 2: []}};
|
|
|
|
|
|
|
+ const layerNodes = {{0: [], 1: [], 2: [], 3: []}};
|
|
|
nodes.forEach(node => {{
|
|
nodes.forEach(node => {{
|
|
|
const layer = getNodeLayer(node);
|
|
const layer = getNodeLayer(node);
|
|
|
layerNodes[layer].push(node);
|
|
layerNodes[layer].push(node);
|
|
@@ -1676,7 +1686,8 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
const layerConfig = [
|
|
const layerConfig = [
|
|
|
{{ name: "帖子点", layer: 0, color: "rgba(243, 156, 18, 0.08)", stroke: "rgba(243, 156, 18, 0.3)" }},
|
|
{{ name: "帖子点", layer: 0, color: "rgba(243, 156, 18, 0.08)", stroke: "rgba(243, 156, 18, 0.3)" }},
|
|
|
{{ name: "帖子标签", layer: 1, color: "rgba(52, 152, 219, 0.08)", stroke: "rgba(52, 152, 219, 0.3)" }},
|
|
{{ name: "帖子标签", layer: 1, color: "rgba(52, 152, 219, 0.08)", stroke: "rgba(52, 152, 219, 0.3)" }},
|
|
|
- {{ name: "人设匹配", layer: 2, color: "rgba(155, 89, 182, 0.08)", stroke: "rgba(155, 89, 182, 0.3)" }}
|
|
|
|
|
|
|
+ {{ name: "人设匹配", layer: 2, color: "rgba(155, 89, 182, 0.08)", stroke: "rgba(155, 89, 182, 0.3)" }},
|
|
|
|
|
+ {{ name: "人设扩展", layer: 3, color: "rgba(46, 204, 113, 0.08)", stroke: "rgba(46, 204, 113, 0.3)" }}
|
|
|
];
|
|
];
|
|
|
|
|
|
|
|
// 绘制三层圆形背景
|
|
// 绘制三层圆形背景
|
|
@@ -1980,16 +1991,33 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
linkHitarea.on("click", (event, d, i) => {{
|
|
linkHitarea.on("click", (event, d, i) => {{
|
|
|
event.stopPropagation();
|
|
event.stopPropagation();
|
|
|
const linkIndex = links.indexOf(d);
|
|
const linkIndex = links.indexOf(d);
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 力导向图高亮(highlightEdge 处理所有路径高亮逻辑)
|
|
|
highlightEdge(d, linkIndex);
|
|
highlightEdge(d, linkIndex);
|
|
|
showEdgeInfo(d);
|
|
showEdgeInfo(d);
|
|
|
- // 边联动:如果边涉及人设节点,联动人设树和关系图
|
|
|
|
|
- const sourceNode = typeof d.source === "object" ? d.source : nodes.find(n => n.id === d.source);
|
|
|
|
|
- const targetNode = typeof d.target === "object" ? d.target : nodes.find(n => n.id === d.target);
|
|
|
|
|
- if (sourceNode && sourceNode.source === "人设") {{
|
|
|
|
|
- handleNodeClick(sourceNode.节点ID, sourceNode.节点名称);
|
|
|
|
|
- }} else if (targetNode && targetNode.source === "人设") {{
|
|
|
|
|
- handleNodeClick(targetNode.节点ID, targetNode.节点名称);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 确定要在人设树和关系图中展示的人设边
|
|
|
|
|
+ const edgeDetail = d.边详情 || {{}};
|
|
|
|
|
+ const isMirrorEdge = d.type.startsWith("镜像_") || d.type.startsWith("二阶_");
|
|
|
|
|
+
|
|
|
|
|
+ let personaSrcId, personaTgtId, edgeType;
|
|
|
|
|
+
|
|
|
|
|
+ if (isMirrorEdge && edgeDetail.源人设节点 && edgeDetail.目标人设节点) {{
|
|
|
|
|
+ // 镜像边:使用对应的人设节点
|
|
|
|
|
+ personaSrcId = edgeDetail.源人设节点;
|
|
|
|
|
+ personaTgtId = edgeDetail.目标人设节点;
|
|
|
|
|
+ edgeType = edgeDetail.原始边类型 || d.type.replace("镜像_", "").replace("二阶_", "");
|
|
|
|
|
+ }} else {{
|
|
|
|
|
+ // 普通边:使用边的两端节点
|
|
|
|
|
+ const sourceNode = typeof d.source === "object" ? d.source : nodes.find(n => n.id === d.source);
|
|
|
|
|
+ const targetNode = typeof d.target === "object" ? d.target : nodes.find(n => n.id === d.target);
|
|
|
|
|
+ personaSrcId = sourceNode ? sourceNode.id : d.source;
|
|
|
|
|
+ personaTgtId = targetNode ? targetNode.id : d.target;
|
|
|
|
|
+ edgeType = d.type;
|
|
|
}}
|
|
}}
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 同步人设树高亮和关系图展示
|
|
|
|
|
+ syncTreeAndRelationGraph(personaSrcId, personaTgtId, edgeType);
|
|
|
}})
|
|
}})
|
|
|
.on("mouseover", function(event, d) {{
|
|
.on("mouseover", function(event, d) {{
|
|
|
d3.select(this.parentNode).select(".link")
|
|
d3.select(this.parentNode).select(".link")
|
|
@@ -2306,6 +2334,38 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
}}
|
|
}}
|
|
|
}});
|
|
}});
|
|
|
}}
|
|
}}
|
|
|
|
|
+ // 如果是人设边(两端都不是帖子节点),找对应的镜像边
|
|
|
|
|
+ else if (!sourceId.startsWith("帖子_") && !targetId.startsWith("帖子_")) {{
|
|
|
|
|
+ // 收集路径节点
|
|
|
|
|
+ const pathNodes = new Set([sourceId, targetId]);
|
|
|
|
|
+
|
|
|
|
|
+ // 找匹配的镜像边,读取其路径节点
|
|
|
|
|
+ links.forEach((link, i) => {{
|
|
|
|
|
+ const detail = link.边详情 || {{}};
|
|
|
|
|
+ if ((link.type.startsWith("镜像_") || link.type.startsWith("二阶_")) && detail.源人设节点 && detail.目标人设节点) {{
|
|
|
|
|
+ const matches = (detail.源人设节点 === sourceId && detail.目标人设节点 === targetId) ||
|
|
|
|
|
+ (detail.源人设节点 === targetId && detail.目标人设节点 === sourceId);
|
|
|
|
|
+ if (matches) {{
|
|
|
|
|
+ highlightLinkIndices.add(i);
|
|
|
|
|
+ // 直接使用预存的路径节点
|
|
|
|
|
+ (detail.路径节点 || []).forEach(n => pathNodes.add(n));
|
|
|
|
|
+ }}
|
|
|
|
|
+ }}
|
|
|
|
|
+ }});
|
|
|
|
|
+
|
|
|
|
|
+ // 高亮路径上的所有节点
|
|
|
|
|
+ pathNodes.forEach(n => highlightNodeIds.add(n));
|
|
|
|
|
+
|
|
|
|
|
+ // 高亮连接路径节点的边
|
|
|
|
|
+ links.forEach((link, i) => {{
|
|
|
|
|
+ const lSrc = typeof link.source === "object" ? link.source.id : link.source;
|
|
|
|
|
+ const lTgt = typeof link.target === "object" ? link.target.id : link.target;
|
|
|
|
|
+ // 两端都在路径上的边
|
|
|
|
|
+ if (pathNodes.has(lSrc) && pathNodes.has(lTgt)) {{
|
|
|
|
|
+ highlightLinkIndices.add(i);
|
|
|
|
|
+ }}
|
|
|
|
|
+ }});
|
|
|
|
|
+ }}
|
|
|
|
|
|
|
|
// 高亮相关的节点和边
|
|
// 高亮相关的节点和边
|
|
|
highlightElements(highlightNodeIds, highlightLinkIndices);
|
|
highlightElements(highlightNodeIds, highlightLinkIndices);
|
|
@@ -2756,15 +2816,15 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
}}
|
|
}}
|
|
|
}}
|
|
}}
|
|
|
|
|
|
|
|
- // 共享的边点击处理函数(人设树和关系图复用)
|
|
|
|
|
- function handleEdgeClick(srcNodeId, tgtNodeId, edgeType) {{
|
|
|
|
|
|
|
+ // 同步人设树高亮和关系图展示(职责单一:不处理力导向图)
|
|
|
|
|
+ function syncTreeAndRelationGraph(srcNodeId, tgtNodeId, edgeType) {{
|
|
|
// 动态获取树相关元素
|
|
// 动态获取树相关元素
|
|
|
const treeGroup = d3.select(".persona-tree");
|
|
const treeGroup = d3.select(".persona-tree");
|
|
|
if (treeGroup.empty()) return;
|
|
if (treeGroup.empty()) return;
|
|
|
|
|
|
|
|
const treeEdges = treeGroup.selectAll(".tree-edge");
|
|
const treeEdges = treeGroup.selectAll(".tree-edge");
|
|
|
|
|
|
|
|
- // 先重置所有高亮状态
|
|
|
|
|
|
|
+ // 重置人设树高亮状态
|
|
|
treeGroup.selectAll(".tree-node")
|
|
treeGroup.selectAll(".tree-node")
|
|
|
.classed("tree-dimmed", false)
|
|
.classed("tree-dimmed", false)
|
|
|
.classed("tree-highlighted", false);
|
|
.classed("tree-highlighted", false);
|
|
@@ -2778,10 +2838,6 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
.attr("fill", d => (d.data.isRoot || d.data.isDimension) ? getTreeNodeColor(d) : "#bbb")
|
|
.attr("fill", d => (d.data.isRoot || d.data.isDimension) ? getTreeNodeColor(d) : "#bbb")
|
|
|
.attr("opacity", 1);
|
|
.attr("opacity", 1);
|
|
|
treeEdges.attr("stroke-opacity", 0.3).attr("stroke-width", 1);
|
|
treeEdges.attr("stroke-opacity", 0.3).attr("stroke-width", 1);
|
|
|
- if (g) {{
|
|
|
|
|
- g.selectAll(".node").classed("dimmed", false).classed("highlighted", false);
|
|
|
|
|
- g.selectAll(".link-group").classed("dimmed", false).classed("highlighted", false);
|
|
|
|
|
- }}
|
|
|
|
|
|
|
|
|
|
// 构建节点ID到D3节点的映射
|
|
// 构建节点ID到D3节点的映射
|
|
|
const treeNodeById = {{}};
|
|
const treeNodeById = {{}};
|
|
@@ -2799,29 +2855,35 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
return isThisEdge ? 1 : 0.1;
|
|
return isThisEdge ? 1 : 0.1;
|
|
|
}});
|
|
}});
|
|
|
|
|
|
|
|
- // 高亮相关节点
|
|
|
|
|
- const connectedNodes = new Set();
|
|
|
|
|
- if (sourceTreeNode) connectedNodes.add(sourceTreeNode);
|
|
|
|
|
- if (targetTreeNode) connectedNodes.add(targetTreeNode);
|
|
|
|
|
|
|
+ // 高亮相关节点(使用节点ID集合判断)
|
|
|
|
|
+ const connectedNodeIds = new Set([srcNodeId, tgtNodeId]);
|
|
|
|
|
|
|
|
- treeGroup.selectAll(".tree-node .tree-shape")
|
|
|
|
|
- .attr("fill", n => connectedNodes.has(n) ? getTreeNodeColor(n) : "#555")
|
|
|
|
|
- .attr("opacity", 1);
|
|
|
|
|
-
|
|
|
|
|
- treeGroup.selectAll(".tree-node text")
|
|
|
|
|
- .attr("fill", n => connectedNodes.has(n) ?
|
|
|
|
|
- ((n.data.isRoot || n.data.isDimension) ? getTreeNodeColor(n) : "#bbb") : "#555")
|
|
|
|
|
- .attr("opacity", 1);
|
|
|
|
|
|
|
+ treeGroup.selectAll(".tree-node").each(function(n) {{
|
|
|
|
|
+ const nodeId = n.data.节点ID;
|
|
|
|
|
+ const isConnected = connectedNodeIds.has(nodeId);
|
|
|
|
|
+ d3.select(this).select(".tree-shape")
|
|
|
|
|
+ .attr("fill", isConnected ? getTreeNodeColor(n) : "#555")
|
|
|
|
|
+ .attr("opacity", 1);
|
|
|
|
|
+ d3.select(this).select("text")
|
|
|
|
|
+ .attr("fill", isConnected ?
|
|
|
|
|
+ ((n.data.isRoot || n.data.isDimension) ? getTreeNodeColor(n) : "#bbb") : "#555")
|
|
|
|
|
+ .attr("opacity", 1);
|
|
|
|
|
+ }});
|
|
|
|
|
|
|
|
// 显示边详情
|
|
// 显示边详情
|
|
|
const panel = document.getElementById("detailPanel");
|
|
const panel = document.getElementById("detailPanel");
|
|
|
panel.classList.add("active");
|
|
panel.classList.add("active");
|
|
|
document.getElementById("detailTitle").textContent = "🔗 边详情";
|
|
document.getElementById("detailTitle").textContent = "🔗 边详情";
|
|
|
|
|
|
|
|
- const srcNode = personaTreeData.nodes.find(n => n.节点ID === srcNodeId);
|
|
|
|
|
- const tgtNode = personaTreeData.nodes.find(n => n.节点ID === tgtNodeId);
|
|
|
|
|
- const srcName = sourceTreeNode ? (sourceTreeNode.data.节点名称 || sourceTreeNode.data.name) : (srcNode?.节点名称 || srcNodeId);
|
|
|
|
|
- const tgtName = targetTreeNode ? (targetTreeNode.data.节点名称 || targetTreeNode.data.name) : (tgtNode?.节点名称 || tgtNodeId);
|
|
|
|
|
|
|
+ // 从 personaTreeData 中获取节点数据(即使不在可视化树中)
|
|
|
|
|
+ const srcNodeData = personaTreeData.nodes.find(n => n.节点ID === srcNodeId);
|
|
|
|
|
+ const tgtNodeData = personaTreeData.nodes.find(n => n.节点ID === tgtNodeId);
|
|
|
|
|
+
|
|
|
|
|
+ // 构造显示用的节点名称
|
|
|
|
|
+ const srcName = sourceTreeNode ? (sourceTreeNode.data.节点名称 || sourceTreeNode.data.name) :
|
|
|
|
|
+ (srcNodeData?.节点名称 || srcNodeId);
|
|
|
|
|
+ const tgtName = targetTreeNode ? (targetTreeNode.data.节点名称 || targetTreeNode.data.name) :
|
|
|
|
|
+ (tgtNodeData?.节点名称 || tgtNodeId);
|
|
|
|
|
|
|
|
let html = `
|
|
let html = `
|
|
|
<p><span class="label">边类型:</span> <strong>${{edgeType}}</strong></p>
|
|
<p><span class="label">边类型:</span> <strong>${{edgeType}}</strong></p>
|
|
@@ -2830,41 +2892,17 @@ HTML_TEMPLATE = '''<!DOCTYPE html>
|
|
|
`;
|
|
`;
|
|
|
document.getElementById("detailContent").innerHTML = html;
|
|
document.getElementById("detailContent").innerHTML = html;
|
|
|
|
|
|
|
|
- // 高亮右侧人设匹配区域
|
|
|
|
|
- if (g) {{
|
|
|
|
|
- const relatedNodeIds = new Set([srcNodeId, tgtNodeId]);
|
|
|
|
|
- const hasRelatedNodes = g.selectAll(".node").filter(n => relatedNodeIds.has(n.id)).size() > 0;
|
|
|
|
|
-
|
|
|
|
|
- if (hasRelatedNodes) {{
|
|
|
|
|
- // 高亮相关节点
|
|
|
|
|
- g.selectAll(".node")
|
|
|
|
|
- .classed("dimmed", n => !relatedNodeIds.has(n.id))
|
|
|
|
|
- .classed("highlighted", n => relatedNodeIds.has(n.id));
|
|
|
|
|
- // 高亮相关边
|
|
|
|
|
- g.selectAll(".link-group").each(function(d) {{
|
|
|
|
|
- const sid = typeof d.source === "object" ? d.source.id : d.source;
|
|
|
|
|
- const tid = typeof d.target === "object" ? d.target.id : d.target;
|
|
|
|
|
- const isRelated = (sid === srcNodeId && tid === tgtNodeId) ||
|
|
|
|
|
- (sid === tgtNodeId && tid === srcNodeId) ||
|
|
|
|
|
- relatedNodeIds.has(sid) || relatedNodeIds.has(tid);
|
|
|
|
|
- d3.select(this)
|
|
|
|
|
- .classed("dimmed", !isRelated)
|
|
|
|
|
- .classed("highlighted", isRelated);
|
|
|
|
|
- }});
|
|
|
|
|
- }} else {{
|
|
|
|
|
- // 全部变灰
|
|
|
|
|
- g.selectAll(".node").classed("dimmed", true).classed("highlighted", false);
|
|
|
|
|
- g.selectAll(".link-group").classed("dimmed", true).classed("highlighted", false);
|
|
|
|
|
- }}
|
|
|
|
|
- }}
|
|
|
|
|
-
|
|
|
|
|
// 在关系图中展示这条边和两个节点
|
|
// 在关系图中展示这条边和两个节点
|
|
|
|
|
+ // 构造节点对象(优先使用树节点,否则使用 personaTreeData 中的数据)
|
|
|
|
|
+ const srcForEgo = sourceTreeNode || (srcNodeData ? {{ data: srcNodeData }} : null);
|
|
|
|
|
+ const tgtForEgo = targetTreeNode || (tgtNodeData ? {{ data: tgtNodeData }} : null);
|
|
|
|
|
+
|
|
|
const edgeData = {{
|
|
const edgeData = {{
|
|
|
边类型: edgeType,
|
|
边类型: edgeType,
|
|
|
源节点ID: srcNodeId,
|
|
源节点ID: srcNodeId,
|
|
|
目标节点ID: tgtNodeId
|
|
目标节点ID: tgtNodeId
|
|
|
}};
|
|
}};
|
|
|
- renderEgoGraphEdge(edgeData, sourceTreeNode, targetTreeNode);
|
|
|
|
|
|
|
+ renderEgoGraphEdge(edgeData, srcForEgo, tgtForEgo);
|
|
|
}}
|
|
}}
|
|
|
|
|
|
|
|
// 关系子图(Ego Graph)- 在画布第四层显示
|
|
// 关系子图(Ego Graph)- 在画布第四层显示
|
|
@@ -3672,7 +3710,8 @@ def main():
|
|
|
"postTitle": match_graph_data["说明"].get("帖子标题", ""),
|
|
"postTitle": match_graph_data["说明"].get("帖子标题", ""),
|
|
|
"stats": match_graph_data["说明"]["统计"],
|
|
"stats": match_graph_data["说明"]["统计"],
|
|
|
"nodes": match_graph_data["节点列表"],
|
|
"nodes": match_graph_data["节点列表"],
|
|
|
- "edges": match_graph_data["边列表"]
|
|
|
|
|
|
|
+ "edges": match_graph_data["边列表"],
|
|
|
|
|
+ "personaEdgeToMirrorEdges": match_graph_data.get("人设边到镜像边映射", {})
|
|
|
}
|
|
}
|
|
|
all_graph_data.append(graph_data)
|
|
all_graph_data.append(graph_data)
|
|
|
|
|
|