fix(知识图谱): 修复边点击不显示问题并优化面板布局
改进边数据查找逻辑,增加多种ID格式匹配方式 调整边面板位置逻辑,避免与节点面板重叠 增加边点击容差和悬停容差,提升交互体验 添加调试日志和错误处理,便于问题排查
This commit is contained in:
parent
7fc1673d11
commit
921c8d6640
@ -5,7 +5,7 @@
|
|||||||
- [ ] 添加对于上传文件的支持:这里的复杂的地方就在于如何和历史记录结合在一起(v0.2.3 版本实现,放在记忆管理后面)
|
- [ ] 添加对于上传文件的支持:这里的复杂的地方就在于如何和历史记录结合在一起(v0.2.3 版本实现,放在记忆管理后面)
|
||||||
|
|
||||||
🐛**BUGs**
|
🐛**BUGs**
|
||||||
- [ ] LlightRAG 知识库中,点击边,没有显示,但是在全屏的时候却又能够显示出来。
|
- [x] LlightRAG 知识库中,点击边,没有显示,但是在全屏的时候却又能够显示出来。
|
||||||
|
|
||||||
💯 **More**:
|
💯 **More**:
|
||||||
|
|
||||||
|
|||||||
@ -136,7 +136,7 @@
|
|||||||
<div
|
<div
|
||||||
v-if="selectedEdgeData"
|
v-if="selectedEdgeData"
|
||||||
class="detail-panel edge-panel"
|
class="detail-panel edge-panel"
|
||||||
:style="{ transform: `translate(${edgePanelPosition.x}px, ${edgePanelPosition.y}px)` }"
|
:style="{ transform: `translate(${intelligentEdgePanelPosition.x}px, ${intelligentEdgePanelPosition.y}px)` }"
|
||||||
@mousedown="startDragPanel('edge', $event)"
|
@mousedown="startDragPanel('edge', $event)"
|
||||||
>
|
>
|
||||||
<div class="detail-header">
|
<div class="detail-header">
|
||||||
@ -284,7 +284,7 @@ const loadingMessage = ref('加载图数据中...')
|
|||||||
|
|
||||||
// 面板拖拽相关
|
// 面板拖拽相关
|
||||||
const nodePanelPosition = ref({ x: 12, y: 60 })
|
const nodePanelPosition = ref({ x: 12, y: 60 })
|
||||||
const edgePanelPosition = ref({ x: 12, y: 320 })
|
const edgePanelPosition = ref({ x: 12, y: 150 }) // 降低初始Y位置以适应紧凑模式
|
||||||
const dragging = ref({ active: false, type: '', startX: 0, startY: 0, initialX: 0, initialY: 0 })
|
const dragging = ref({ active: false, type: '', startX: 0, startY: 0, initialX: 0, initialY: 0 })
|
||||||
|
|
||||||
// 数据库相关状态
|
// 数据库相关状态
|
||||||
@ -309,6 +309,29 @@ const stats = computed(() => graphStore.stats)
|
|||||||
const selectedNodeData = computed(() => graphStore.selectedNodeData)
|
const selectedNodeData = computed(() => graphStore.selectedNodeData)
|
||||||
const selectedEdgeData = computed(() => graphStore.selectedEdgeData)
|
const selectedEdgeData = computed(() => graphStore.selectedEdgeData)
|
||||||
|
|
||||||
|
// 智能边面板位置 - 确保在紧凑模式下也能正确显示
|
||||||
|
const intelligentEdgePanelPosition = computed(() => {
|
||||||
|
if (!sigmaContainer.value) return edgePanelPosition.value
|
||||||
|
|
||||||
|
const containerHeight = sigmaContainer.value.clientHeight
|
||||||
|
const panelHeight = 200 // 估计的面板高度
|
||||||
|
const nodePanelBottom = selectedNodeData.value ? nodePanelPosition.value.y + 200 : 0
|
||||||
|
|
||||||
|
// 如果有节点面板显示,将边面板放在节点面板下方
|
||||||
|
if (selectedNodeData.value) {
|
||||||
|
return {
|
||||||
|
x: edgePanelPosition.value.x + 260, // 在节点面板右侧
|
||||||
|
y: Math.min(nodePanelPosition.value.y, containerHeight - panelHeight - 20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保边面板在容器范围内
|
||||||
|
return {
|
||||||
|
x: edgePanelPosition.value.x,
|
||||||
|
y: Math.min(edgePanelPosition.value.y, Math.max(60, containerHeight - panelHeight - 20))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 获取节点显示名称
|
// 获取节点显示名称
|
||||||
const getNodeDisplayName = (node) => {
|
const getNodeDisplayName = (node) => {
|
||||||
if (node.properties?.entity_id) {
|
if (node.properties?.entity_id) {
|
||||||
@ -425,11 +448,11 @@ const sigmaSettings = {
|
|||||||
edgeLabelColor: {
|
edgeLabelColor: {
|
||||||
color: '#666'
|
color: '#666'
|
||||||
},
|
},
|
||||||
minEdgeThickness: 3, // 增加最小边厚度,提高点击性
|
minEdgeThickness: 4, // 增加最小边厚度,提高点击性
|
||||||
maxEdgeThickness: 8, // 增加最大边厚度
|
maxEdgeThickness: 10, // 增加最大边厚度
|
||||||
// 添加边点击相关配置
|
// 添加边点击相关配置
|
||||||
edgeClickTolerance: 10, // 边点击容差,增加点击检测区域
|
edgeClickTolerance: 15, // 增加边点击容差,增加点击检测区域
|
||||||
edgeHoverTolerance: 8, // 边悬停容差
|
edgeHoverTolerance: 12, // 增加边悬停容差
|
||||||
zoomToSizeRatioFunction: (x) => x, // 确保缩放时边的厚度保持合理
|
zoomToSizeRatioFunction: (x) => x, // 确保缩放时边的厚度保持合理
|
||||||
eventListenerOptions: {
|
eventListenerOptions: {
|
||||||
wheel: { passive: true },
|
wheel: { passive: true },
|
||||||
@ -522,18 +545,45 @@ const registerEvents = () => {
|
|||||||
// 边点击事件
|
// 边点击事件
|
||||||
sigmaInstance.on('clickEdge', ({ edge }) => {
|
sigmaInstance.on('clickEdge', ({ edge }) => {
|
||||||
try {
|
try {
|
||||||
console.log('边被点击:', edge)
|
console.log('边被点击 - Sigma边ID:', edge)
|
||||||
const graph = sigmaInstance.getGraph()
|
const graph = sigmaInstance.getGraph()
|
||||||
if (graph.hasEdge(edge)) {
|
if (graph.hasEdge(edge)) {
|
||||||
|
// 获取Sigma边的属性,其中包含原始数据
|
||||||
|
const sigmaEdgeData = graph.getEdgeAttributes(edge)
|
||||||
|
console.log('Sigma边属性:', sigmaEdgeData)
|
||||||
|
|
||||||
|
// 立即设置选中的边 - 使用Sigma边ID
|
||||||
graphStore.setSelectedEdge(edge)
|
graphStore.setSelectedEdge(edge)
|
||||||
const edgeData = graph.getEdgeAttributes(edge)
|
|
||||||
console.log('边数据:', edgeData)
|
// 确保边面板显示
|
||||||
message.success(`已选中边: ${edge}`)
|
nextTick(() => {
|
||||||
|
if (selectedEdgeData.value) {
|
||||||
|
console.log('边面板应该显示:', selectedEdgeData.value)
|
||||||
|
message.success(`已选中边: ${getEdgeDisplayName(selectedEdgeData.value)}`)
|
||||||
|
} else {
|
||||||
|
console.warn('selectedEdgeData为空,尝试使用Sigma边数据')
|
||||||
|
// 如果无法从rawGraph中找到,直接使用Sigma边的原始数据
|
||||||
|
const fallbackData = sigmaEdgeData.originalData || {
|
||||||
|
id: edge,
|
||||||
|
source: graph.source(edge),
|
||||||
|
target: graph.target(edge),
|
||||||
|
properties: {
|
||||||
|
keywords: sigmaEdgeData.label || '',
|
||||||
|
description: sigmaEdgeData.label || '',
|
||||||
|
weight: sigmaEdgeData.originalWeight || 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('使用回退边数据:', fallbackData)
|
||||||
|
message.success(`已选中边: ${getEdgeDisplayName(fallbackData)}`)
|
||||||
|
}
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
console.warn('点击的边不存在于图中:', edge)
|
console.warn('点击的边不存在于图中:', edge)
|
||||||
|
message.warning('点击的边不存在于图中')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('处理边点击事件时出错:', error)
|
console.error('处理边点击事件时出错:', error)
|
||||||
|
message.error('处理边点击事件时出错')
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1029,6 +1079,14 @@ watch(() => graphStore.selectedNodeData, (nodeData) => {
|
|||||||
console.log('Selected node data changed:', nodeData)
|
console.log('Selected node data changed:', nodeData)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 监听选中边数据变化,用于调试和确保面板显示
|
||||||
|
watch(() => graphStore.selectedEdgeData, (edgeData) => {
|
||||||
|
console.log('Selected edge data changed:', edgeData)
|
||||||
|
if (edgeData) {
|
||||||
|
console.log('边面板应该显示,当前位置:', intelligentEdgePanelPosition.value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// 监听选中节点变化,移动相机
|
// 监听选中节点变化,移动相机
|
||||||
watch(() => graphStore.selectedNode, (nodeId) => {
|
watch(() => graphStore.selectedNode, (nodeId) => {
|
||||||
if (nodeId && graphStore.moveToSelectedNode && sigmaInstance) {
|
if (nodeId && graphStore.moveToSelectedNode && sigmaInstance) {
|
||||||
|
|||||||
@ -159,7 +159,7 @@ const dislikeThisResponse = (msg) => {
|
|||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
background: var(--gray-100);
|
background: var(--gray-50);
|
||||||
color: var(--gray-700);
|
color: var(--gray-700);
|
||||||
padding: 2px 8px;
|
padding: 2px 8px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
@ -169,10 +169,10 @@ const dislikeThisResponse = (msg) => {
|
|||||||
&.btn {
|
&.btn {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: var(--gray-200);
|
background: var(--gray-100);
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
background: var(--gray-300);
|
background: var(--gray-200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,23 +44,53 @@ export const useGraphStore = defineStore('graph', {
|
|||||||
// 获取选中边的详细信息
|
// 获取选中边的详细信息
|
||||||
selectedEdgeData: (state) => {
|
selectedEdgeData: (state) => {
|
||||||
if (!state.selectedEdge || !state.rawGraph) return null
|
if (!state.selectedEdge || !state.rawGraph) return null
|
||||||
// 首先尝试通过dynamicId匹配
|
|
||||||
|
console.log('查找边数据,选中边ID:', state.selectedEdge)
|
||||||
|
|
||||||
|
// 首先尝试通过dynamicId匹配(Sigma使用的ID格式)
|
||||||
let foundEdge = state.rawGraph.edges.find(edge => edge.dynamicId === state.selectedEdge)
|
let foundEdge = state.rawGraph.edges.find(edge => edge.dynamicId === state.selectedEdge)
|
||||||
if (foundEdge) return foundEdge
|
if (foundEdge) {
|
||||||
|
console.log('通过dynamicId找到边:', foundEdge)
|
||||||
|
return foundEdge
|
||||||
|
}
|
||||||
|
|
||||||
// 如果没找到,尝试通过原始ID匹配
|
// 如果没找到,尝试通过原始ID匹配
|
||||||
foundEdge = state.rawGraph.edges.find(edge => edge.id === state.selectedEdge)
|
foundEdge = state.rawGraph.edges.find(edge => edge.id === state.selectedEdge)
|
||||||
if (foundEdge) return foundEdge
|
if (foundEdge) {
|
||||||
|
console.log('通过id找到边:', foundEdge)
|
||||||
|
return foundEdge
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对于格式为 source-target-index 的dynamicId,也尝试解析
|
||||||
|
const dynamicIdPattern = /^(.+)-(.+)-(\d+)$/
|
||||||
|
const match = state.selectedEdge.match(dynamicIdPattern)
|
||||||
|
if (match) {
|
||||||
|
const [, source, target, index] = match
|
||||||
|
foundEdge = state.rawGraph.edges.find(edge =>
|
||||||
|
edge.source === source && edge.target === target
|
||||||
|
)
|
||||||
|
if (foundEdge) {
|
||||||
|
console.log('通过解析dynamicId找到边:', foundEdge)
|
||||||
|
return foundEdge
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 最后尝试通过source->target格式匹配
|
// 最后尝试通过source->target格式匹配
|
||||||
const [source, target] = state.selectedEdge.split('->')
|
const arrowPattern = /^(.+)->(.+)$/
|
||||||
if (source && target) {
|
const arrowMatch = state.selectedEdge.match(arrowPattern)
|
||||||
|
if (arrowMatch) {
|
||||||
|
const [, source, target] = arrowMatch
|
||||||
foundEdge = state.rawGraph.edges.find(edge =>
|
foundEdge = state.rawGraph.edges.find(edge =>
|
||||||
edge.source === source.trim() && edge.target === target.trim()
|
edge.source === source.trim() && edge.target === target.trim()
|
||||||
)
|
)
|
||||||
|
if (foundEdge) {
|
||||||
|
console.log('通过箭头格式找到边:', foundEdge)
|
||||||
|
return foundEdge
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundEdge || null
|
console.warn('未找到匹配的边数据,选中边ID:', state.selectedEdge)
|
||||||
|
return null
|
||||||
},
|
},
|
||||||
|
|
||||||
// 检查图是否为空
|
// 检查图是否为空
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user