lsc 3 semanas atrás
pai
commit
7cfa8baff3

+ 1 - 1
dist/index.html

@@ -32,7 +32,7 @@
       width: 100%;
       background: #e6eaf0;
       font-family: '黑体';
-    }</style><link href=./static/css/app.e7aa43b13fd61845f312328738c416be.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3ad1d5771e9b13dbdad2.js></script><script type=text/javascript src=./static/js/vendor.4dce3a5441c732d84c44.js></script><script type=text/javascript src=./static/js/app.7dfb005875b23846097a.js></script></body></html><script>function stopSafari() {
+    }</style><link href=./static/css/app.abcb349fc1bb9bf441a18caf888a0e07.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=./static/js/manifest.3ad1d5771e9b13dbdad2.js></script><script type=text/javascript src=./static/js/vendor.4dce3a5441c732d84c44.js></script><script type=text/javascript src=./static/js/app.690dd5481e1f5f50ef41.js></script></body></html><script>function stopSafari() {
     //阻止safari浏览器双击放大功能
     let lastTouchEnd = 0  //更新手指弹起的时间
     document.documentElement.addEventListener("touchstart", function (event) {

Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/app.abcb349fc1bb9bf441a18caf888a0e07.css


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/app.abcb349fc1bb9bf441a18caf888a0e07.css.map


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/static/css/app.e7aa43b13fd61845f312328738c416be.css.map


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/app.690dd5481e1f5f50ef41.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/app.690dd5481e1f5f50ef41.js.map


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/app.7dfb005875b23846097a.js


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/app.7dfb005875b23846097a.js.map


Diferenças do arquivo suprimidas por serem muito extensas
+ 0 - 0
dist/static/js/manifest.3ad1d5771e9b13dbdad2.js.map


+ 131 - 16
src/components/pages/knowledge/components/graph.vue

@@ -1,15 +1,14 @@
 <template>
-    <div>
+    <div :class="['graph-container', { 'fullscreen': isFullscreen }]" ref="content">
         <div class="graph-toolbar">
             <button class="graph-btn" @click="zoomIn">放大</button>
             <button class="graph-btn" @click="zoomOut">缩小</button>
             <button class="graph-btn" @click="resetZoom">1:1</button>
+            <button class="graph-btn" @click="toggleFullscreen">{{ isFullscreen ? '退出全屏' : '全屏' }}</button>
             <input v-model="searchText" @keyup.enter="searchNode" placeholder="搜索节点" class="graph-input" />
             <button class="graph-btn graph-btn-primary" @click="searchNode">搜索</button>
         </div>
-        <div style="width: 100%; max-height: 600px; overflow: auto;padding-bottom: 10px;" class="content">
-            <div style="height:600px;position: relative;" ref="container"></div>
-        </div>
+        <div :style="{ height: isFullscreen ? '100vh' : '600px', position: 'relative' }" ref="container"></div>
     </div>
 </template>
 
@@ -22,6 +21,7 @@ export default {
         return {
             graph: null,
             searchText: '',
+            isFullscreen: false,
         }
     },
     mounted() {
@@ -31,9 +31,19 @@ export default {
             }
         });
         window.addEventListener('resize', this.handleResize);
+        // 添加全屏事件监听
+        document.addEventListener('fullscreenchange', this.handleFullscreenChange);
+        document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange);
+        document.addEventListener('mozfullscreenchange', this.handleFullscreenChange);
+        document.addEventListener('MSFullscreenChange', this.handleFullscreenChange);
     },
     beforeDestroy() {
         window.removeEventListener('resize', this.handleResize);
+        // 移除全屏事件监听
+        document.removeEventListener('fullscreenchange', this.handleFullscreenChange);
+        document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange);
+        document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange);
+        document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange);
         if (this.graph) {
             this.graph.destroy();
         }
@@ -94,6 +104,96 @@ export default {
                 this.$message && this.$message.warning('未找到该节点');
             }
         },
+        toggleFullscreen() {
+            if (!this.isFullscreen) {
+                this.enterFullscreen();
+            } else {
+                this.exitFullscreen();
+            }
+        },
+        enterFullscreen() {
+            const content = this.$refs.content;
+            if (content.requestFullscreen) {
+                content.requestFullscreen();
+            } else if (content.webkitRequestFullscreen) {
+                content.webkitRequestFullscreen();
+            } else if (content.mozRequestFullScreen) {
+                content.mozRequestFullScreen();
+            } else if (content.msRequestFullscreen) {
+                content.msRequestFullscreen();
+            }
+        },
+        exitFullscreen() {
+            if (document.exitFullscreen) {
+                document.exitFullscreen();
+            } else if (document.webkitExitFullscreen) {
+                document.webkitExitFullscreen();
+            } else if (document.mozCancelFullScreen) {
+                document.mozCancelFullScreen();
+            } else if (document.msExitFullscreen) {
+                document.msExitFullscreen();
+            }
+        },
+        handleFullscreenChange() {
+            this.isFullscreen = !!(
+                document.fullscreenElement ||
+                document.webkitFullscreenElement ||
+                document.mozFullScreenElement ||
+                document.msFullscreenElement
+            );
+            
+            // 全屏状态改变时重新调整图形大小
+            this.$nextTick(() => {
+                this.handleResize();
+            });
+        },
+        // 自定义分组布局函数
+        applyGroupLayout(data) {
+            const nodes = data.nodes;
+            // const edges = data.edges;
+            
+            // 按类别分组节点
+            const categoryGroups = {};
+            nodes.forEach(node => {
+                const category = node.category || 'default';
+                if (!categoryGroups[category]) {
+                    categoryGroups[category] = [];
+                }
+                categoryGroups[category].push(node);
+            });
+            
+            const categories = Object.keys(categoryGroups);
+            const groupSpacing = 400; // 组间距离
+            const nodeSpacing = 80; // 组内节点距离
+            
+            // 计算每个组的布局
+            categories.forEach((category, categoryIndex) => {
+                const groupNodes = categoryGroups[category];
+                const groupSize = Math.ceil(Math.sqrt(groupNodes.length));
+                
+                // 计算组的中心位置
+                const groupCenterX = (categoryIndex % 3) * groupSpacing - groupSpacing;
+                const groupCenterY = Math.floor(categoryIndex / 3) * groupSpacing;
+                
+                // 为组内每个节点分配位置
+                groupNodes.forEach((node, nodeIndex) => {
+                    const row = Math.floor(nodeIndex / groupSize);
+                    const col = nodeIndex % groupSize;
+                    
+                    const x = groupCenterX + (col - groupSize / 2) * nodeSpacing;
+                    const y = groupCenterY + (row - groupSize / 2) * nodeSpacing;
+                    
+                    // 更新节点位置
+                    const nodeData = data.nodes.find(n => n.id === node.id);
+                    if (nodeData) {
+                        nodeData.x = x;
+                        nodeData.y = y;
+                    }
+                });
+            });
+            
+            return data;
+        },
         showSeeksGraph(data) {
             if (this.graph) {
                 this.graph.destroy();
@@ -103,6 +203,9 @@ export default {
             const container = this.$refs.container;
             if (!container) return;
             
+            // 应用分组布局
+            const layoutData = this.applyGroupLayout(JSON.parse(JSON.stringify(data)));
+            
             this.graph = new G6.Graph({
                 container: container,
                 width: container.scrollWidth,
@@ -113,12 +216,13 @@ export default {
                     default: ['drag-canvas', 'zoom-canvas', 'drag-node'],
                 },
                 layout: {
-                    type: 'force',
-                    preventOverlap: true,
-                    nodeSpacing: 30,
-                    linkDistance: 200,
-                    nodeStrength: -60,
-                    edgeStrength: 0.1,
+                    // type: 'force',
+                    // preventOverlap: true,
+                    // nodeSpacing: 30,
+                    // linkDistance: 200,
+                    // nodeStrength: -60,
+                    // edgeStrength: 0.1,
+                    type: 'preset', // 使用预设布局,使用我们计算的位置
                 },
                 defaultNode: {
                     size: 40,
@@ -220,11 +324,11 @@ export default {
             });
 
 
-            const nodeIds = new Set(data.nodes.map(node => node.id));
+            const nodeIds = new Set(layoutData.nodes.map(node => node.id));
 
             // 统计每个节点的连线数量
             const linkCount = {};
-            data.edges.forEach(edge => {
+            layoutData.edges.forEach(edge => {
                 if (edge.source) linkCount[edge.source] = (linkCount[edge.source] || 0) + 1;
                 if (edge.target) linkCount[edge.target] = (linkCount[edge.target] || 0) + 1;
             });
@@ -257,7 +361,7 @@ export default {
             };
 
             const graphData = {
-                nodes: data.nodes.map(node => {
+                nodes: layoutData.nodes.map(node => {
                     const count = linkCount[node.id] || 0;
                     const size = 20 + count * 10; // 不封顶
                     const categoryColor = getCategoryColor(node.category);
@@ -271,13 +375,15 @@ export default {
                         ? fullLabel.substring(0, maxLength) + '...' 
                         : fullLabel;
                     
-                    // 保留 comboId 字段
+                    // 保留 comboId 字段和位置信息
                     const nodeData = {
                         id: node.id,
                         label: displayLabel, // 使用截断后的标签
                         fullLabel: fullLabel, // 保存完整标签用于tooltip
                         description: node.description,
                         size,
+                        x: node.x, // 保留计算的位置
+                        y: node.y, // 保留计算的位置
                         style: {
                             fill,
                             stroke: categoryColor,
@@ -287,7 +393,7 @@ export default {
                     if (node.comboId) nodeData.comboId = node.comboId;
                     return nodeData;
                 }),
-                edges: data.edges
+                edges: layoutData.edges
                     .filter(edge => {
                         const sourceExists = nodeIds.has(edge.source);
                         const targetExists = nodeIds.has(edge.target);
@@ -301,7 +407,7 @@ export default {
                         target: edge.target,
                         label: edge.predicate,
                 })),
-                combos: Array.isArray(data.combos) ? data.combos : undefined
+                combos: Array.isArray(layoutData.combos) ? layoutData.combos : undefined
             };
             console.log('graphData',graphData);
             
@@ -315,6 +421,7 @@ export default {
             this.graph.on('node:mouseleave', (e) => {
                 this.graph.setItemState(e.item, 'focus', false);
             });
+            this.handleResize();
         },
         handleResize() {
             if (!this.graph || this.graph.get('destroyed')) return;
@@ -370,4 +477,12 @@ export default {
     height: 30px;
     outline: none;
 }
+
+.graph-container{
+    width: 100%;
+    height: 100%;
+    background-color: #fff;
+    padding: 10px;
+    box-sizing: border-box;
+}
 </style>

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff