|
|
@@ -135,13 +135,18 @@
|
|
|
<div class="flex items-center gap-1.5">
|
|
|
<!-- hover 标识 -->
|
|
|
<span v-if="store.hoverNode" class="text-[9px] text-warning/60">[hover]</span>
|
|
|
- <!-- 节点样式:空心(帖子域)或实心(人设域) -->
|
|
|
+ <!-- 节点样式:空心(帖子域)或实心(人设域),激活状态有发光效果 -->
|
|
|
<span
|
|
|
class="w-2 h-2 shrink-0"
|
|
|
:class="displayNodeStyle.shape === 'rect' ? 'rounded-sm' : 'rounded-full'"
|
|
|
- :style="displayNodeStyle.hollow
|
|
|
- ? { backgroundColor: 'transparent', border: '2px solid ' + displayNodeStyle.color }
|
|
|
- : { backgroundColor: displayNodeStyle.color }"
|
|
|
+ :style="{
|
|
|
+ ...(displayNodeStyle.hollow
|
|
|
+ ? { backgroundColor: 'transparent', border: '2px solid ' + displayNodeStyle.color }
|
|
|
+ : { backgroundColor: displayNodeStyle.color }),
|
|
|
+ ...(store.selectedNode && !store.hoverNode
|
|
|
+ ? { filter: 'brightness(1.2)', boxShadow: '0 0 4px ' + displayNodeStyle.color }
|
|
|
+ : {})
|
|
|
+ }"
|
|
|
></span>
|
|
|
<span class="text-primary font-medium text-[11px] break-all">{{ displayNode.name }}</span>
|
|
|
</div>
|
|
|
@@ -1821,10 +1826,9 @@ function applyPathHighlightWithEdges(pathNodes, pathEdges) {
|
|
|
const allLinks = svg.selectAll('.tree-link, .match-link, .walked-link')
|
|
|
const allLabels = svg.selectAll('.match-score, .walked-score')
|
|
|
|
|
|
- // 先清除所有残留的高亮类
|
|
|
+ // 先清除所有残留的高亮类(但保留 selected 类给选中节点)
|
|
|
allNodes
|
|
|
.classed('highlighted', false)
|
|
|
- .classed('selected', false)
|
|
|
.classed('locked-path', false)
|
|
|
allLinks
|
|
|
.classed('highlighted', false)
|
|
|
@@ -1833,11 +1837,17 @@ function applyPathHighlightWithEdges(pathNodes, pathEdges) {
|
|
|
.classed('highlighted', false)
|
|
|
.classed('locked-path', false)
|
|
|
|
|
|
- // 节点高亮
|
|
|
- allNodes.classed('dimmed', function(d) {
|
|
|
- const nodeId = d.data?.id || d.id
|
|
|
- return !pathNodes.has(nodeId)
|
|
|
- })
|
|
|
+ // 节点高亮(保持选中节点的 selected 样式)
|
|
|
+ const activeNodeId = store.selectedNodeId
|
|
|
+ allNodes
|
|
|
+ .classed('dimmed', function(d) {
|
|
|
+ const nodeId = d.data?.id || d.id
|
|
|
+ return !pathNodes.has(nodeId)
|
|
|
+ })
|
|
|
+ .classed('selected', function(d) {
|
|
|
+ const nodeId = d.data?.id || d.id
|
|
|
+ return nodeId === activeNodeId
|
|
|
+ })
|
|
|
|
|
|
// 边高亮(基于边集合判断)
|
|
|
allLinks.each(function(d) {
|
|
|
@@ -1890,7 +1900,7 @@ watch([() => store.hoverPathNodes.size, () => store.hoverNodeId], () => {
|
|
|
const allLinks = svg.selectAll('.tree-link, .match-link, .walked-link')
|
|
|
const allLabels = svg.selectAll('.match-score, .walked-score')
|
|
|
const lockedPath = store.lockedHoverPathNodes.size > 0 ? store.lockedHoverPathNodes : null
|
|
|
- applyHoverHighlight(allNodes, allLinks, allLabels, store.hoverPathNodes, lockedPath)
|
|
|
+ applyHoverHighlight(allNodes, allLinks, allLabels, store.hoverPathNodes, lockedPath, store.selectedNodeId)
|
|
|
|
|
|
if (store.hoverNodeId) {
|
|
|
const nodeInfo = nodeElements[store.hoverNodeId]
|
|
|
@@ -1975,10 +1985,10 @@ function restoreLockedHover() {
|
|
|
const allLinks = svg.selectAll('.tree-link, .match-link, .walked-link')
|
|
|
const allLabels = svg.selectAll('.match-score, .walked-score')
|
|
|
|
|
|
- // 恢复高亮效果(传入锁定路径)
|
|
|
+ // 恢复高亮效果(传入锁定路径和选中节点)
|
|
|
if (store.hoverPathNodes.size > 0) {
|
|
|
const lockedPath = store.lockedHoverPathNodes.size > 0 ? store.lockedHoverPathNodes : null
|
|
|
- applyHoverHighlight(allNodes, allLinks, allLabels, store.hoverPathNodes, lockedPath)
|
|
|
+ applyHoverHighlight(allNodes, allLinks, allLabels, store.hoverPathNodes, lockedPath, store.selectedNodeId)
|
|
|
}
|
|
|
|
|
|
// 恢复锁定按钮
|