diff --git a/gyxtp/src/view/graphPageCopy0926.vue b/gyxtp/src/view/graphPageCopy0926.vue index 57028c6..8fbcc15 100644 --- a/gyxtp/src/view/graphPageCopy0926.vue +++ b/gyxtp/src/view/graphPageCopy0926.vue @@ -191,18 +191,54 @@ + +
+
+ +
+ +
展示层级{{i}}
+
+
+
+ +
-
+
+ > + + +
+
对这个节点进行操作:
+
查看节点
+
{{currentNode.expanded?'收回':'扩展'}}
+ +
+
@@ -261,6 +297,9 @@ export default { }, data() { return { + isShowCodePanel: false, + isShowNodeMenuPanel: false, + nodeMenuPanelPosition: { x: 0, y: 0 }, currentGroup:1, direction: "rtl", // visGraph实例对象 @@ -290,12 +329,6 @@ export default { data: [] //提示内部的数据 }, graphOptions: { - // 启用展开/折叠按钮 - defaultExpandHolderPosition: 'right', // 按钮显示位置:'left' 或 'right' - defaultExpandHolderSize: 16, - defaultExpandHolderColor: '#fff', - defaultExpandHolderBorder: '1px solid #00d7e0', - isMoveByParentNode: true, allowSwitchLineShape: true, allowSwitchJunctionPoint: true, defaultLineColor: '#2E74B5', @@ -317,15 +350,8 @@ export default { // 布局核心:使用 center 布局实现环形 layout: { layoutName: 'center', // 关键:使用 center 布局 - from: 'center', // 从中心向外扩展 - levelDistance: '700,700,900,900,1000,1000,1000,1000', // 每一层的半径(可动态修改) - nodeDistance: 20, // 同一层节点间的最小角度间距(影响密度) - min_per_width: 300, // 最小水平间隔(角度相关) - max_per_width: 500, - clockwise: true, // 是否顺时针排列 + levelDistance: '1000,1000,1000,1000,3000,3000,3000,3000', // 每一层的半径(可动态修改) startAngle: -Math.PI / 2, // 起始角度(-90°,顶部开始) - preventOverlap: true, // 防止重叠 - distance_coefficient: 5, } }, currentNode: {}, // 选中的节点对象 @@ -401,22 +427,49 @@ export default { level: 'titleLevel', docLevel: 'docLevel', }, - heightlightTable:[] + heightlightTable:[], + currentShowLeve:1, } }, methods: { - changeGroup(groupId){ - this.currentGroup = groupId - this.getInfo() + showNodeMenus(nodeObject, $event) { + this.currentNode = nodeObject; + const _base_position = this.$refs.myPage.getBoundingClientRect(); + this.isShowNodeMenuPanel = true; + this.nodeMenuPanelPosition.x = $event.clientX - _base_position.x; + this.nodeMenuPanelPosition.y = $event.clientY - _base_position.y; }, - onNodeCollapse(node, e) { - this.$refs.graphRef.refresh(); + showOrHide(){ + this.currentNode.expanded = !this.currentNode.expanded + const graphInstance = this.$refs.graphRef.getInstance(); + graphInstance.doLayout() }, + toNodeInfo() { + let nodeObject = this.currentNode + console.log(nodeObject) + const data = { + 'id': nodeObject.data.docId, + 'docTitle': nodeObject.text, + } + getDocInfo(data).then((res) => { + localStorage.setItem("docUrl", res.data.docUrl) + this.$router.push({ + name: 'docInfo', + query: { + title: res.data.docTitle, + level: res.data.docLevel, + keyword: res.data.docTitle, + docId: res.data.id + } + }) + }); - // 节点展开时触发 - onNodeExpand(node, e) { - this.$refs.graphRef.refresh(); + this.isShowNodeMenuPanel = false; + }, + changeGroup(groupId){ + this.currentGroup = groupId + this.getInfo() }, handleNodeClick(node) { console.log(node); @@ -538,8 +591,8 @@ export default { data.g13["docTitle"] = data.g13["name"] data.g14["level"] = 1 data.g14["docTitle"] = data.g14["name"] - // data.g15["level"] = 1 - // data.g15["docTitle"] = data.g15["name"] + data.g15["level"] = 1 + data.g15["docTitle"] = data.g15["name"] data.g21["level"] = 1 data.g21["docTitle"] = data.g21["name"] data.g22["level"] = 1 @@ -553,7 +606,7 @@ export default { this.data1.push(data.g12) this.data1.push(data.g13) this.data1.push(data.g14) - // this.data1.push(data.g15) + this.data1.push(data.g15) this.data1.push(data.g21) this.data1.push(data.g22) }) @@ -661,7 +714,6 @@ export default { return found ? 'nodeclass' : 'nodeclassnormal'; }, getLinesClass(mergedDbIds) { - console.log("44444444444444") const lines = this.heightLight.links; if (lines == undefined){ return "" @@ -723,9 +775,46 @@ export default { // line.sourceAsMap.data this.drawer = true; }, - //整理图谱数据 - //整理图谱数据 - //整理图谱数据 + getNodeColor(leve){ + let color = "" + switch (leve) { + case "0": + color = '#ffd602'; + break; + case "1": + color = 'rgb(64, 158, 255)'; + break; + case "2": + color = '#ff8c00'; + break; + case "3": + color = '#67c23a'; + break; + case "4": + color = 'rgb(248,143,248)'; + break; + case "5": + color = 'rgb(65,154,255)'; + break; + case "6": + color = 'rgb(0,228,255)'; + break; + default: + color = 'rgba(255, 255, 255, 0.6)'; + } + console.log(color) + return color; + }, + getExpanded(leve){ + if (leve { - nodeMap[node.id] = node; - }); - // 找出有连接的节点 const connectedNodeIds = new Set(); lineList.forEach(line => { @@ -746,423 +829,74 @@ export default { connectedNodeIds.add(line.target); }); - // 按层级和组别分组孤立节点 - const isolatedNodesByGroupAndLevel = {}; - nodeList.forEach(node => { - if (!connectedNodeIds.has(node.id)) { - const groupId = node.groupId || '1'; - const level = node.docLeve || '0'; - if (!isolatedNodesByGroupAndLevel[groupId]) { - isolatedNodesByGroupAndLevel[groupId] = {}; + + // 在遍历前先按 docLeve 分组统计数量 + const nodesByLevel = {}; + for (let i = 0; i < nodeList.length; i++) { + const node = nodeList[i]; + if (node.groupId == this.currentGroup || node.docLeve == "0") { + // 仅孤立节点判断,超出层级不展示 + if (Number(node.docLeve) > this.currentShowLeve) { + if (!connectedNodeIds.has(node.id)) { + continue; + } } - if (!isolatedNodesByGroupAndLevel[groupId][level]) { - isolatedNodesByGroupAndLevel[groupId][level] = []; + + const level = Number(node.docLeve); + if (!nodesByLevel[level]) { + nodesByLevel[level] = []; } - isolatedNodesByGroupAndLevel[groupId][level].push(node); + nodesByLevel[level].push(node); } - }); + } - // 存储每个层级每个组别的节点位置信息 - const levelGroupPositions = {}; - - // 处理有连接的节点 - if (nodeList != undefined) { - // 按组别分组处理有连接的节点 - const groupedNodes = { - '0': {levels: {}}, - '1': {levels: {}}, - '2': {levels: {}} - }; - - // 按组别和层级分类节点 - nodeList.forEach(node => { - if (connectedNodeIds.has(node.id)) { - const groupId = node.groupId || '1'; - const level = node.docLeve || '1'; - if (!groupedNodes[groupId]) groupedNodes[groupId] = {levels: {}}; - if (!groupedNodes[groupId].levels[level]) groupedNodes[groupId].levels[level] = []; - groupedNodes[groupId].levels[level].push(node); - } - }); +// 配置参数 + const baseRadius = 1200; // 每层之间的半径差 + const centerX = 0, centerY = 0; - // 定义组别的位置偏移 - const groupOffsets = { - '0': -10200, // 左侧区域 - '1': 0, // 中间区域 - '2': 10200 // 右侧区域 - }; - - // 处理每个组别的节点 - Object.keys(groupedNodes).forEach(groupId => { - const groupData = groupedNodes[groupId]; - const groupOffsetX = groupOffsets[groupId] || 0; - - // 处理每个层级的节点 - Object.keys(groupData.levels).sort().forEach(level => { - const levelNodes = groupData.levels[level].sort((a, b) => a.docId - b.docId); - const levelNum = parseInt(level); - - // 计算该层级节点的起始X位置(考虑组别偏移) - const startX = groupOffsetX - (levelNodes.length * 200) / 2; - - // 初始化该层级该组别的位置信息 - const levelGroupKey = `${levelNum}_${groupId}`; - if (!levelGroupPositions[levelGroupKey]) { - levelGroupPositions[levelGroupKey] = { - minX: startX, - maxX: startX + levelNodes.length * 200, - leftAvailableX: startX - 200, // 左侧可用位置 - rightAvailableX: startX + 200, // 右侧可用位置 - hasConnectedNodes: levelNodes.length > 0 - }; - } +// 遍历每一层进行布局 + Object.keys(nodesByLevel).forEach(levelStr => { + const level = Number(levelStr); + const levelNodes = nodesByLevel[level]; + const total = levelNodes.length; + const radius = level === 0 ? 0 : level * baseRadius; // level 0 放中心 + + levelNodes.forEach((node, index) => { + let x, y; - levelNodes.forEach((node, index) => { - if (levelNum === 0) this.rootId = node.id; - - // 根据层级设置节点样式 - let color, fontSize, fontColor; - switch (levelNum) { - case 0: - color = 'rgb(227,203,0)'; - fontSize = '30px'; - fontColor = 'rgb(255,255,255)'; - break; - case 1: - color = 'rgb(47,47,230)'; - fontSize = '30px'; - fontColor = 'rgb(255,255,255)'; - break; - case 2: - color = 'rgb(255,138,0)'; - fontSize = '30px'; - fontColor = 'rgb(255,255,255)'; - break; - case 3: - color = 'rgb(30,255,0)'; - fontSize = '30px'; - fontColor = 'rgb(0,0,0)'; - break; - case 4: - color = 'rgb(248,143,248)'; - fontSize = '30px'; - fontColor = 'rgb(255,255,255)'; - break; - case 5: - color = 'rgb(65,154,255)'; - fontSize = '30px'; - fontColor = 'rgb(255,255,255)'; - break; - case 6: - color = 'rgb(0,228,255)'; - fontSize = '30px'; - fontColor = 'rgb(0,0,0)'; - break; - default: - color = 'rgb(200,200,200)'; - fontSize = '30px'; - fontColor = 'rgb(255,255,255)'; - } - - const x = startX + index * 200; - // 修改点:当 groupId 为 '1' 时,Y 值反向 - const y = groupId === '1' ? levelNum * -1400 : levelNum * 1400; - - - if (node.groupId==this.currentGroup || node.docLeve=="0"){ - // 添加节点 - nodes.push({ - fontSize:100, - id: node.id, - text: node.name, - data: { - docId: node.docId, - group: node.groupId - }, - level: levelNum, - // x: x, - // y: y, - // fixed: true, - width: 220, - height: 220, - color: color, - font: `normal ${fontSize} Arial`, - // html:"
"+node.name+"
", - fontColor: fontColor, - expandHolderPosition: 'right', - expanded: true, - styleClass:this.getNodeClass(node.name), - }); - } - - }); + if (level === 0) { + // 中心节点放在原点 + x = 0; + y = 0; + } else { + // 计算极角 + const angle = (2 * Math.PI / total) * index; // 均匀分布 + x = centerX + radius * Math.cos(angle); + y = centerY + radius * Math.sin(angle); + } + + nodes.push({ + id: node.id, + text: node.name, + data: { + docId: node.docId, + group: node.groupId + }, + level: node.docLeve, + x: x, + y: y, + fixed: true, // 锁定位置 + width: 250, + height: 250, + color: this.getNodeColor(node.docLeve), + expandHolderPosition: 'right', + expanded: this.getExpanded(node.docLeve), + styleClass: this.getNodeClass(node.name), }); }); - } + }); + - // 处理孤立节点 - 放置在有连线节点的两侧 - // Object.keys(isolatedNodesByGroupAndLevel).sort().forEach(groupId => { - // const groupData = isolatedNodesByGroupAndLevel[groupId]; - // const groupOffsetX = groupId === '0' ? -10200 : groupId === '1' ? 0 : 10200; - // - // Object.keys(groupData).sort().forEach(level => { - // const levelNodes = groupData[level]; - // const levelNum = parseInt(level); - // - // // 确定孤立节点的Y坐标(与有连接节点保持一致) - // const y = groupId === '1' ? levelNum * -1400 : levelNum * 1400; - // - // // 获取或创建该层级该组别的位置信息 - // const levelGroupKey = `${levelNum}_${groupId}`; - // - // // 先按docId排序孤立节点 - // const sortedIsolatedNodes = levelNodes.sort((a, b) => a.docId - b.docId); - // - // if (!levelGroupPositions[levelGroupKey] || !levelGroupPositions[levelGroupKey].hasConnectedNodes) { - // // 如果没有有连接的节点,居中展示孤立节点 - // const totalWidth = sortedIsolatedNodes.length * 200; - // const startX = groupOffsetX - totalWidth / 2; - // - // // 放置孤立节点(居中排列) - // sortedIsolatedNodes.forEach((node, index) => { - // // 根据层级设置节点样式 - // let color, fontSize, fontColor; - // switch (levelNum) { - // case 0: - // color = 'rgb(227,203,0)'; - // fontSize = '70px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 1: - // color = 'rgb(47,47,230)'; - // fontSize = '68px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 2: - // color = 'rgb(255,138,0)'; - // fontSize = '50px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 3: - // color = 'rgb(30,255,0)'; - // fontSize = '40px'; - // fontColor = 'rgb(0,0,0)'; - // break; - // case 4: - // color = 'rgb(248,143,248)'; - // fontSize = '32px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 5: - // color = 'rgb(65,154,255)'; - // fontSize = '30px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 6: - // color = 'rgb(0,228,255)'; - // fontSize = '28px'; - // fontColor = 'rgb(0,0,0)'; - // break; - // default: - // color = 'rgb(200,200,200)'; - // fontSize = '24px'; - // fontColor = 'rgb(255,255,255)'; - // } - // - // const x = startX + index * 200; - // - // if (node.groupId==this.currentGroup || node.docLeve=="0"){ - // // 添加节点 - // nodes.push({ - // id: node.id, - // text: node.name, - // data: { - // docId: node.docId, - // group: node.groupId - // }, - // level: levelNum, - // // x: x, - // // y: y, - // // fixed: true, - // width: 150, - // height: 150, - // color: color, - // font: `normal ${fontSize} Arial`, - // fontColor: fontColor, - // expandHolderPosition: 'right', - // expanded: true, - // styleClass:this.getNodeClass(node.name), - // }); - // } - // }); - // } else { - // // 如果有有连接的节点,在两侧放置孤立节点 - // const positionInfo = levelGroupPositions[levelGroupKey]; - // - // // 将孤立节点分成两组:左侧和右侧 - // const leftNodes = []; - // const rightNodes = []; - // - // sortedIsolatedNodes.forEach((node, index) => { - // if (index % 2 === 0) { - // leftNodes.push(node); // 偶数索引放左侧 - // } else { - // rightNodes.push(node); // 奇数索引放右侧 - // } - // }); - // - // // 放置左侧孤立节点(从右往左排列) - // let currentLeftX = positionInfo.leftAvailableX; - // for (let i = leftNodes.length - 1; i >= 0; i--) { - // const node = leftNodes[i]; - // - // // 根据层级设置节点样式 - // let color, fontSize, fontColor; - // switch (levelNum) { - // case 0: - // color = 'rgb(227,203,0)'; - // fontSize = '70px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 1: - // color = 'rgb(47,47,230)'; - // fontSize = '68px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 2: - // color = 'rgb(255,138,0)'; - // fontSize = '50px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 3: - // color = 'rgb(30,255,0)'; - // fontSize = '40px'; - // fontColor = 'rgb(0,0,0)'; - // break; - // case 4: - // color = 'rgb(248,143,248)'; - // fontSize = '32px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 5: - // color = 'rgb(65,154,255)'; - // fontSize = '30px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 6: - // color = 'rgb(0,228,255)'; - // fontSize = '28px'; - // fontColor = 'rgb(0,0,0)'; - // break; - // default: - // color = 'rgb(200,200,200)'; - // fontSize = '24px'; - // fontColor = 'rgb(255,255,255)'; - // } - // - // if (node.groupId==this.currentGroup || node.docLeve=="0"){ - // // 添加节点 - // nodes.push({ - // id: node.id, - // text: node.name, - // data: { - // docId: node.docId, - // group: node.groupId - // }, - // level: levelNum, - // // x: x, - // // y: y, - // // fixed: true, - // width: 150, - // height: 150, - // color: color, - // font: `normal ${fontSize} Arial`, - // fontColor: fontColor, - // expandHolderPosition: 'right', - // expanded: true, - // styleClass:this.getNodeClass(node.name), - // }); - // } - // - // currentLeftX -= 200; - // } - // - // // 放置右侧孤立节点(从左往右排列) - // let currentRightX = positionInfo.rightAvailableX; - // rightNodes.forEach(node => { - // // 根据层级设置节点样式 - // let color, fontSize, fontColor; - // switch (levelNum) { - // case 0: - // color = 'rgb(227,203,0)'; - // fontSize = '70px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 1: - // color = 'rgb(47,47,230)'; - // fontSize = '68px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 2: - // color = 'rgb(255,138,0)'; - // fontSize = '50px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 3: - // color = 'rgb(30,255,0)'; - // fontSize = '40px'; - // fontColor = 'rgb(0,0,0)'; - // break; - // case 4: - // color = 'rgb(248,143,248)'; - // fontSize = '32px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 5: - // color = 'rgb(65,154,255)'; - // fontSize = '30px'; - // fontColor = 'rgb(255,255,255)'; - // break; - // case 6: - // color = 'rgb(0,228,255)'; - // fontSize = '28px'; - // fontColor = 'rgb(0,0,0)'; - // break; - // default: - // color = 'rgb(200,200,200)'; - // fontSize = '24px'; - // fontColor = 'rgb(255,255,255)'; - // } - // - // if (node.groupId==this.currentGroup || node.docLeve=="0"){ - // // 添加节点 - // nodes.push({ - // id: node.id, - // text: node.name, - // data: { - // docId: node.docId, - // group: node.groupId - // }, - // level: levelNum, - // // x: x, - // // y: y, - // // fixed: true, - // width: 150, - // height: 150, - // color: color, - // font: `normal ${fontSize} Arial`, - // fontColor: fontColor, - // expandHolderPosition: 'right', - // expanded: true, - // styleClass:this.getNodeClass(node.name), - // }); - // } - // - // currentRightX += 200; - // }); - // } - // }); - // }); // 处理连线 lineList.forEach(line => { @@ -1172,15 +906,18 @@ export default { style=this.getLinesClass(line.DbId) num=10 } + + // 查询父节点是否是展示状态 + links.push({ id:line.DbId, from: line.source, to: line.target, text: line.relate || '相关', color: - line.num <= 5 ? '#fff' : // 白色 - line.num <= 10 ? '#0f0' : // 绿色 - line.num <= 15 ? '#ff0' : // 黄色 + line.num <= 5 ? 'rgb(255, 255, 255)' : // 白色 + line.num <= 10 ? 'rgb(0, 255, 0)' : // 绿色 + line.num <= 15 ? 'rgb(255, 255, 0)' : // 黄色 'rgb(178,246,255)', // 红色(包含line.num <= 20和超过20的情况) lineWidth:num, lineShape: 1, @@ -1213,23 +950,18 @@ export default { }) }, onNodeClick(nodeObject, $event) { - console.log(nodeObject) - const data = { - 'id': nodeObject.data.docId, - 'docTitle': nodeObject.text, + console.log(nodeObject.id) + const graphInstance = this.$refs.graphRef.getInstance(); + let node = graphInstance.getNodeById(nodeObject.id) + let relinks = graphInstance.getLinesByNode(node); + + for (let i=0;i { - localStorage.setItem("docUrl", res.data.docUrl) - this.$router.push({ - name: 'docInfo', - query: { - title: res.data.docTitle, - level: res.data.docLevel, - keyword: res.data.docTitle, - docId: res.data.id - } - }) - }); } }, created() { @@ -1849,7 +1581,7 @@ tr { stroke: white !important; stroke-width: 3 !important; stroke-opacity: 1 !important; - + font-size: 20px !important; /* 多层光晕:内层青色,外层白色 */ filter: drop-shadow(0 0 20px rgba(0, 255, 255, 1)) /* 内层青色光晕 */ @@ -1861,7 +1593,7 @@ tr { paint-order: stroke fill !important; } .nodeclassnormal{ - font-size: 30px !important; + font-size: 20px !important; } .el-table .warning-row { background: oldlace; @@ -1909,7 +1641,4 @@ tr { .flow-tree:hover { background-color: rgba(255, 255, 255, 0.1); } -.c-node-text{ - -} \ No newline at end of file