CN-1548 feat: 修复关系图临时节点不对的问题

This commit is contained in:
chenjinsong
2024-06-14 15:27:43 +08:00
parent a73c9f18cd
commit 01d83c4b4a
3 changed files with 63 additions and 75 deletions

View File

@@ -67,7 +67,6 @@ export default {
debounceFunc: null, debounceFunc: null,
center: {}, center: {},
initialData: null, // 初始化数据,用于重置 initialData: null, // 初始化数据,用于重置
currentNodeData: [],
nodes: [], nodes: [],
links: [], links: [],
graph: shallowRef(null), graph: shallowRef(null),
@@ -81,11 +80,11 @@ export default {
methods: { methods: {
async init () { async init () {
try { try {
this.currentNodeData = await this.generateInitialData() const initialData = await this.generateInitialData()
this.initialData = _.cloneDeep(this.currentNodeData) // 初始化数据 this.initialData = _.cloneDeep(initialData) // 初始化数据
let hoverNode = null let hoverNode = null
this.graph = ForceGraph()(document.getElementById('entityGraph')) this.graph = ForceGraph()(document.getElementById('entityGraph'))
.graphData(this.currentNodeData) .graphData(initialData)
.nodeCanvasObject((node, ctx) => { .nodeCanvasObject((node, ctx) => {
const nodeStyle = this.getNodeStyle(node.type, node.data.entityType) const nodeStyle = this.getNodeStyle(node.type, node.data.entityType)
const iconWidth = nodeStyle.iconWidth / 2 const iconWidth = nodeStyle.iconWidth / 2
@@ -224,35 +223,35 @@ export default {
} }
}) })
.centerAt(0, 30)// 设置中心节点位置 .centerAt(0, 30)// 设置中心节点位置
.onNodeClick(async (nodeModel, e) => { .onNodeClick(async (node, e) => {
this.clickNode = nodeModel || null this.clickNode = node || null
if (nodeModel.type !== 'tempNode') { if (node.type !== 'tempNode') {
this.rightBox.show = true this.rightBox.show = true
this.cleanTempItems() this.cleanTempItems()
// 点击entityNode查询数据并根据数据生成tempNode // 点击entityNode查询数据并根据数据生成tempNode
if (nodeModel.type === nodeType.entityNode) { if (node.type === nodeType.entityNode) {
this.rightBox.loading = true this.rightBox.loading = true
try { try {
// 若已查过数据,不重复查询 // 若已查过数据,不重复查询
if (!nodeModel.data.relatedEntities) { if (!node.data.relatedEntities) {
await nodeModel.queryDetailData() await node.queryDetailData()
} }
let change = false const toAddNodes = []
Object.keys(nodeModel.data.relatedEntities).forEach(k => { const toAddLinks = []
if (nodeModel.data.relatedEntities[k].total) { Object.keys(node.data.relatedEntities).forEach(k => {
if (node.data.relatedEntities[k].total) {
// 若已有同级同类型的listNode不生成此tempNode // 若已有同级同类型的listNode不生成此tempNode
const neighbors = nodeModel.getNeighbors(this.currentNodeData) const neighbors = node.getNeighbors(this.graph.graphData())
const hasListNode = neighbors.nodes.some(b => b.data.entityType === k) const hasListNode = neighbors.nodes.some(b => b.data.entityType === k)
if (!hasListNode) { if (!hasListNode) {
change = true
const tempNode = new Node( const tempNode = new Node(
nodeType.tempNode, nodeType.tempNode,
`${nodeModel.id}__${k}__temp`, `${node.id}__${k}__temp`,
{ {
entityType: k, entityType: k,
...this.generateTempNodeCoordinate(nodeModel.getSourceNode(this.currentNodeData), e) ...this.generateTempNodeCoordinate(node.getSourceNode(this.graph.graphData()), e)
}, },
nodeModel, node,
this.defaultChargeStrength, this.defaultChargeStrength,
this.getIconUrl(k, false, false) this.getIconUrl(k, false, false)
) )
@@ -261,15 +260,16 @@ export default {
tempNode.fy = tempNode.y tempNode.fy = tempNode.y
}) })
const tempEdge = new Link(nodeModel, tempNode, 'temp', this.defaultLinkDistance, 3) const tempLink = new Link(node, tempNode, 'temp', this.defaultLinkDistance, 3)
this.currentNodeData.nodes.push(tempNode) toAddNodes.push(tempNode)
this.currentNodeData.links.push(tempEdge) toAddLinks.push(tempLink)
this.graph.graphData(this.currentNodeData)
} }
} }
}) })
// change && this.graph.layout()//????????????? if (toAddNodes.length || toAddLinks.length) {
this.rightBox.node = _.cloneDeep(nodeModel) this.addItems(toAddNodes, toAddLinks)
}
this.rightBox.node = _.cloneDeep(node)
this.rightBox.mode = 'detail' this.rightBox.mode = 'detail'
} catch (e) { } catch (e) {
console.error(e) console.error(e)
@@ -277,11 +277,11 @@ export default {
} finally { } finally {
this.rightBox.loading = false this.rightBox.loading = false
} }
} else if (nodeModel.type === nodeType.listNode) { } else if (node.type === nodeType.listNode) {
this.rightBox.node = _.cloneDeep(nodeModel) this.rightBox.node = _.cloneDeep(node)
this.rightBox.mode = 'list' this.rightBox.mode = 'list'
} else if (nodeModel.type === nodeType.rootNode) { } else if (node.type === nodeType.rootNode) {
this.rightBox.node = _.cloneDeep(nodeModel) this.rightBox.node = _.cloneDeep(node)
this.rightBox.mode = 'detail' this.rightBox.mode = 'detail'
} }
} else { } else {
@@ -289,18 +289,18 @@ export default {
// 若已达第六层则只生成listNode不再展开entityNode // 若已达第六层则只生成listNode不再展开entityNode
const nodes = [] const nodes = []
const edges = [] const edges = []
const sourceNode = nodeModel.getSourceNode(this.currentNodeData) const sourceNode = node.getSourceNode(this.graph.graphData())
const listNode = new Node( const listNode = new Node(
nodeType.listNode, nodeType.listNode,
`${sourceNode.id}__${nodeModel.data.entityType}-list`, `${sourceNode.id}__${node.data.entityType}-list`,
{ {
entityType: nodeModel.data.entityType, entityType: node.data.entityType,
x: nodeModel.x, x: node.x,
y: nodeModel.y y: node.y
}, },
sourceNode, sourceNode,
this.defaultChargeStrength, this.defaultChargeStrength,
this.getIconUrl(nodeModel.data.entityType, false, false) this.getIconUrl(node.data.entityType, false, false)
) )
nodes.push(listNode) nodes.push(listNode)
edges.push(new Link(sourceNode, listNode, null, this.defaultLinkDistance, 2)) edges.push(new Link(sourceNode, listNode, null, this.defaultLinkDistance, 2))
@@ -432,13 +432,7 @@ export default {
} else if (code === 'zoomIn') { } else if (code === 'zoomIn') {
this.graph.zoom(this.graph.zoom() - 0.2) this.graph.zoom(this.graph.zoom() - 0.2)
} else { } else {
// this.graph = null
// this.currentNodeData = []
// this.nodes = []
// this.links = []
this.clickNode = this.rootNode this.clickNode = this.rootNode
// this.init()
this.graph.graphData(this.initialData).centerAt(0, 30) this.graph.graphData(this.initialData).centerAt(0, 30)
} }
}, },
@@ -878,7 +872,7 @@ export default {
// 移除 tempNode 和 tempEdge // 移除 tempNode 和 tempEdge
this.cleanTempItems() this.cleanTempItems()
const neighbors = this.getNeighborItems(node) const neighbors = node.getNeighbors(this.graph.graphData())
let listNode = neighbors.targetNodes.find(n => n.data.entityType === expandType) let listNode = neighbors.targetNodes.find(n => n.data.entityType === expandType)
if (!listNode) { if (!listNode) {
listNode = new Node(nodeType.listNode, `${node.id}__${expandType}-list`, { entityType: expandType }, node, this.defaultChargeStrength, this.getIconUrl(expandType, false, false)) listNode = new Node(nodeType.listNode, `${node.id}__${expandType}-list`, { entityType: expandType }, node, this.defaultChargeStrength, this.getIconUrl(expandType, false, false))
@@ -919,36 +913,6 @@ export default {
const img = new Image() const img = new Image()
img.src = require(`@/assets/img/entity-symbol2/${entityType}${suffix}.svg`) img.src = require(`@/assets/img/entity-symbol2/${entityType}${suffix}.svg`)
return img return img
},
getNeighborItems (node) {
const { links } = this.graph.graphData()
const neighboringNodes = []
const neighboringTargetNodes = []
const neighboringSourceNodes = []
const neighboringTargetLinks = []
const neighboringSourceLinks = []
const neighboringLinks = links.filter(l => {
if (l.target === node || l.source === node) {
neighboringNodes.push(l.target === node ? l.source : l.target)
if (l.target === node) {
neighboringSourceNodes.push(l.source)
neighboringSourceLinks.push(l)
} else {
neighboringTargetNodes.push(l.target)
neighboringTargetLinks.push(l)
}
return true
}
return false
})
return {
nodes: neighboringNodes,
targetNodes: neighboringTargetNodes,
sourceNodes: neighboringSourceNodes,
links: neighboringLinks,
targetLinks: neighboringTargetLinks,
sourceLinks: neighboringSourceLinks
}
} }
}, },
watch: { watch: {

View File

@@ -176,7 +176,6 @@ export default {
node: { node: {
deep: true, deep: true,
handler (n) { handler (n) {
console.info(n)
this.handleDetailData(n) this.handleDetailData(n)
} }
} }

View File

@@ -53,9 +53,34 @@ export default class Node {
} }
getNeighbors (gData) { getNeighbors (gData) {
const links = gData.links.filter(l => l.source.id === this.id || l.target.id === this.id) const { links } = gData
const nodes = gData.nodes.filter(n => links.some(l => l.source.id === n.id || l.target.id === n.id)) const neighboringNodes = []
return { links, nodes } const neighboringTargetNodes = []
const neighboringSourceNodes = []
const neighboringTargetLinks = []
const neighboringSourceLinks = []
const neighboringLinks = links.filter(l => {
if (l.target === this || l.source === this) {
neighboringNodes.push(l.target === this ? l.source : l.target)
if (l.target === this) {
neighboringSourceNodes.push(l.source)
neighboringSourceLinks.push(l)
} else {
neighboringTargetNodes.push(l.target)
neighboringTargetLinks.push(l)
}
return true
}
return false
})
return {
nodes: neighboringNodes,
targetNodes: neighboringTargetNodes,
sourceNodes: neighboringSourceNodes,
links: neighboringLinks,
targetLinks: neighboringTargetLinks,
sourceLinks: neighboringSourceLinks
}
} }
// 获取唯一sourcelistNode和tempNode专用因为entityNode的source可能有多个rootNode无source // 获取唯一sourcelistNode和tempNode专用因为entityNode的source可能有多个rootNode无source