This commit is contained in:
limengnan 2026-01-13 17:39:09 +08:00
parent bd7292ccbe
commit b47a65bdc8
14 changed files with 226 additions and 193 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -17,6 +17,20 @@ import {
import insertCss from 'insert-css' import insertCss from 'insert-css'
import { updateProjects} from "@/api/business/project"; import { updateProjects} from "@/api/business/project";
import img1 from '@/assets/x6/1.png'
import img2 from '@/assets/x6/2.png'
import img3 from '@/assets/x6/3.png'
import img4 from '@/assets/x6/4.png'
import img5 from '@/assets/x6/5.png'
import img6 from '@/assets/x6/6.png'
import img7 from '@/assets/x6/7.png'
import line1 from '@/assets/x6/line1.png'
import line2 from '@/assets/x6/line2.png'
import line3 from '@/assets/x6/line3.png'
import line4 from '@/assets/x6/line4.png'
import line5 from '@/assets/x6/line5.png'
import line6 from '@/assets/x6/line6.png'
const emit = defineEmits([ 'closeAntvx6']); const emit = defineEmits([ 'closeAntvx6']);
const props = defineProps({ const props = defineProps({
projectInfo: { projectInfo: {
@ -64,6 +78,11 @@ let currentLineStyle = 'solid' // 默认实线
onMounted(() => { onMounted(() => {
preWork() preWork()
if(projectInfo.value.topology != null && projectInfo.value.topology != ''){
}
// #region // #region
graph = new Graph({ graph = new Graph({
container: document.getElementById('graph-container') as HTMLElement, container: document.getElementById('graph-container') as HTMLElement,
@ -127,7 +146,7 @@ onMounted(() => {
// #region 使 // #region 使
graph graph
.use( .use(
new Transform({ new Transform({
resizing: false, // resizing: false, //
rotating: true, // rotating: true, //
@ -172,9 +191,9 @@ onMounted(() => {
collapsable: false, collapsable: false,
title: '管线', title: '管线',
name: 'group3', name: 'group3',
graphHeight: 400, graphHeight: 400,
layoutOptions: { layoutOptions: {
rowHeight: 80, rowHeight: 120,
}, },
}, },
], ],
@ -184,21 +203,21 @@ onMounted(() => {
rowHeight: 100, rowHeight: 100,
}, },
}) })
graph.on('node:contextmenu', ({ e, node }) => { graph.on('node:contextmenu', ({ e, node }) => {
selectedNode.value = node selectedNode.value = node
e.preventDefault() e.preventDefault()
// //
const pos = node.position?.() || { x: 0, y: 0 } const pos = node.position?.() || { x: 0, y: 0 }
showContextMenu(pos.x, pos.y) showContextMenu(pos.x, pos.y)
}) })
function showContextMenu(x: number, y: number) { function showContextMenu(x: number, y: number) {
left.value = x + 260 left.value = x + 260
top.value = y - 50 top.value = y - 50
isMenuShow.value = true isMenuShow.value = true
// //
// //
} }
// StencilDnd // StencilDnd
stencil.on('dnd:start', (args:any) => { stencil.on('dnd:start', (args:any) => {
console.log('Stencil节点开始拖拽', args) console.log('Stencil节点开始拖拽', args)
@ -216,48 +235,48 @@ isMenuShow.value = true
?.appendChild(stencil.container as HTMLElement) ?.appendChild(stencil.container as HTMLElement)
// Graph // Graph
graph.on('node:added', (args) => { graph.on('node:added', (args) => {
console.log('节点已添加到画布', args) console.log('节点已添加到画布', args)
const { node } = args const { node } = args
// 线 // 线
if (node.data && node.data.lineStyle) { if (node.data && node.data.lineStyle) {
// 线线 // 线线
const lineStyle = node.data.lineStyle const lineStyle = node.data.lineStyle
graph.options.connecting.createEdge = () => { graph.options.connecting.createEdge = () => {
return new Shape.Edge({ return new Shape.Edge({
attrs: { attrs: {
line: { line: {
stroke: '#A2B1C3', stroke: '#A2B1C3',
strokeWidth: 2, strokeWidth: 2,
strokeDasharray: lineStyle.strokeDasharray, strokeDasharray: lineStyle.strokeDasharray,
targetMarker: lineStyle.targetMarker, targetMarker: lineStyle.targetMarker,
sourceMarker: lineStyle.sourceMarker sourceMarker: lineStyle.sourceMarker
} }
}, },
zIndex: 0 zIndex: 0
}) })
}
// 线
setTimeout(() => {
graph.removeNode(node)
}, 100)
} else {
//
node.size(160, 160)
//
node.attr('body/fill', 'none')
//
node.attr('image/refX', 0)
node.attr('image/refY', 0)
node.attr('image/width', 160) //
node.attr('image/height', 160) //
//
node.attr('text/text', '')
node.attr('label/text', '')
} }
// 线
setTimeout(() => {
graph.removeNode(node)
}, 100)
} else {
//
node.size(160, 160)
//
node.attr('body/fill', 'none')
//
node.attr('image/refX', 0)
node.attr('image/refY', 0)
node.attr('image/width', 160) //
node.attr('image/height', 160) //
//
node.attr('text/text', '')
node.attr('label/text', '')
}
}) })
// #endregion // #endregion
// #region // #region
@ -308,7 +327,6 @@ graph.on('node:added', (args) => {
// delete // delete
graph.bindKey('backspace', () => { graph.bindKey('backspace', () => {
debugger
const cells = graph.getSelectedCells() const cells = graph.getSelectedCells()
if (cells.length) { if (cells.length) {
graph.removeCells(cells) graph.removeCells(cells)
@ -476,40 +494,33 @@ graph.on('node:added', (args) => {
// stencil.load([r1, r2, r3, r4, r5, r6], 'group1') // stencil.load([r1, r2, r3, r4, r5, r6], 'group1')
const imageShapes = [ const imageShapes = [
{ {
label: '圆柱槽', label: '圆柱槽',
image: image: img1,
'http://localhost:3000/dev-api/avatar/1.png',
}, },
{ {
label: '扁平槽', label: '扁平槽',
image: image:img2,
'http://localhost:3000/dev-api/avatar/2.png',
}, },
{ {
label: '环形槽', label: '环形槽',
image: image:img3,
'http://localhost:3000/dev-api/avatar/3.png',
}, },
{ {
label: '管束槽', label: '管束槽',
image: image:img4,
'http://localhost:3000/dev-api/avatar/4.png',
}, },
{ {
label: '萃取柱', label: '萃取柱',
image: image:img5,
'http://localhost:3000/dev-api/avatar/5.png',
}, },
{ {
label: '流化床', label: '流化床',
image: image:img6,
'http://localhost:3000/dev-api/avatar/6.png',
},{ },{
label: '锥底环形槽', label: '锥底环形槽',
image: image:img7,
'http://localhost:3000/dev-api/avatar/7.png',
}, },
] ]
const imageNodes = imageShapes.map((item) => const imageNodes = imageShapes.map((item) =>
@ -523,22 +534,21 @@ graph.on('node:added', (args) => {
}, },
}), }),
) )
console.log(imageNodes)
stencil.load(imageNodes, 'group2') stencil.load(imageNodes, 'group2')
// 线 // 线
const lineShapes = [ const lineShapes = [
{ {
label: '实线', label: '实线',
image: image: line1,
'http://localhost:3000/dev-api/avatar/21.png',
targetMarker: null, targetMarker: null,
sourceMarker: null, sourceMarker: null,
strokeDasharray: 0 strokeDasharray: 0
}, },
{ {
label: '单箭头实线', label: '单箭头实线',
image: image: line2,
'http://localhost:3000/dev-api/avatar/22.png',
targetMarker: { targetMarker: {
name: 'block', name: 'block',
width: 12, width: 12,
@ -549,8 +559,7 @@ graph.on('node:added', (args) => {
}, },
{ {
label: '双箭头实线', label: '双箭头实线',
image: image: line3,
'http://localhost:3000/dev-api/avatar/23.png',
targetMarker: { targetMarker: {
name: 'block', name: 'block',
width: 12, width: 12,
@ -565,16 +574,14 @@ graph.on('node:added', (args) => {
}, },
{ {
label: '虚线', label: '虚线',
image: image: line4,
'http://localhost:3000/dev-api/avatar/24.png',
targetMarker: null, targetMarker: null,
sourceMarker: null, sourceMarker: null,
strokeDasharray: 5 strokeDasharray: 5
}, },
{ {
label: '单箭头虚线', label: '单箭头虚线',
image: image: line5,
'http://localhost:3000/dev-api/avatar/25.png',
targetMarker: { targetMarker: {
name: 'block', name: 'block',
width: 12, width: 12,
@ -585,8 +592,7 @@ graph.on('node:added', (args) => {
}, },
{ {
label: '双箭头虚线', label: '双箭头虚线',
image: image: line6,
'http://localhost:3000/dev-api/avatar/26.png',
targetMarker: { targetMarker: {
name: 'block', name: 'block',
width: 12, width: 12,
@ -602,32 +608,28 @@ graph.on('node:added', (args) => {
] ]
const lineNodes = lineShapes.map((item) => { const lineNodes = lineShapes.map((item) => {
// 线
// shape: 'custom-image',
// label: item.label,
// attrs: {
// image: {
// 'xlink:href': item.image,
// },
// },
// 线 // 线
const node = graph.createNode({ const node = graph.createNode({
shape: 'custom-image', shape: 'custom-image',
label: item.label, label: item.label,
width: 120, width: 130,
height: 60, height: 100,
attrs: { attrs: {
image: { image: {
'xlink:href': item.image, 'xlink:href': item.image,
width: 31,
height: 31,
refX: 50,
refY: 20
}, },
body: { body: {
stroke: 'transparent', stroke: 'transparent',
fill: 'transparent' fill: '#f8f8f8'
}, },
label: { label: {
text: item.label, text: item.label,
refX: 60, refX: 60,
refY: 50, refY: 65,
textAnchor: 'middle', textAnchor: 'middle',
fontSize: 12, fontSize: 12,
fill: '#666' fill: '#666'
@ -646,6 +648,11 @@ graph.on('node:added', (args) => {
}) })
stencil.load(lineNodes, 'group3') stencil.load(lineNodes, 'group3')
if (!graph || !projectInfo.value || !projectInfo.value.topology) return;
graph.clearCells();
const topology:any = JSON.parse(projectInfo.value.topology)
if(!topology.designData)return
graph.fromJSON(topology.designData);
// #endregion // #endregion
}) })
@ -749,8 +756,11 @@ function closeAntvx6() {
function saveDesign() { // function saveDesign() { //
try { try {
// JSON // JSON
const designData = graph.toJSON() const designData:any = graph.toJSON()
console.log('designData', designData) let cells = []
if(designData !=null && designData.cells.length>0){
cells = designData.cells
}
const topology = { const topology = {
projectId: projectInfo.value.projectId, projectId: projectInfo.value.projectId,
name: projectInfo.value.name, name: projectInfo.value.name,
@ -764,22 +774,23 @@ function saveDesign() { // 保存设计
material:{ material:{
showProperties:[] showProperties:[]
}, },
designData:designData
} },
designData:cells
} }
// //
const saveData = { const saveData = {
id: projectInfo.value.projectId, projectId: projectInfo.value.projectId,
topology: JSON.stringify(topology) topology: JSON.stringify(topology)
} }
updateProjects(saveData).then((res:any) => { updateProjects(saveData).then((res:any) => {
if(res.code === 200 || res.code === 200){ if(res === true){
ElMessage.success('保存成功') ElMessage({
type: "success",
message: "保存成功",
});
} }
}); });
//
console.log('保存的设计数据:', saveData)
// //
return saveData return saveData
} catch (error) { } catch (error) {
@ -787,6 +798,18 @@ function saveDesign() { // 保存设计
return null return null
} }
} }
function revokeClick(){
graph.undo()
}
function removeClick(){
graph.clearCells();
}
function bigClick(){
graph.zoom(0.1)
}
function smallClick(){
graph.zoom(-0.1)
}
</script> </script>
<template> <template>
@ -819,19 +842,19 @@ function saveDesign() { // 保存设计
</div> </div>
</div> </div>
<div class="header-content-box"> <div class="header-content-box">
<div class="operation-icon-box"> <div class="operation-icon-box" @click="revokeClick">
<img src="@/assets/x6/revoke.png"> <img src="@/assets/x6/revoke.png">
<div class="operation-icon-text">撤销</div> <div class="operation-icon-text">撤销</div>
</div> </div>
<div class="operation-icon-box"> <div class="operation-icon-box" @click="removeClick">
<img src="@/assets/x6/redo.png"> <img src="@/assets/x6/redo.png">
<div class="operation-icon-text">重做</div> <div class="operation-icon-text">重做</div>
</div> </div>
<div class="operation-icon-box"> <div class="operation-icon-box" @click="bigClick">
<img src="@/assets/x6/magnify.png"> <img src="@/assets/x6/magnify.png">
<div class="operation-icon-text">放大</div> <div class="operation-icon-text">放大</div>
</div> </div>
<div class="operation-icon-box"> <div class="operation-icon-box" @click="smallClick">
<img src="@/assets/x6/reduce.png"> <img src="@/assets/x6/reduce.png">
<div class="operation-icon-text">缩小</div> <div class="operation-icon-text">缩小</div>
</div> </div>
@ -871,7 +894,7 @@ function saveDesign() { // 保存设计
.app-layout { .app-layout {
position: fixed; position: fixed;
z-index: 9999; z-index: 10;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100vw; width: 100vw;
@ -999,7 +1022,8 @@ function saveDesign() { // 保存设计
background-color: #e6f7ff; background-color: #e6f7ff;
border: 2px dashed #1890ff; border: 2px dashed #1890ff;
} }
.context-menu{
.context-menu {
position: absolute; position: absolute;
z-index: 9999; z-index: 9999;
background-color: #fff; background-color: #fff;
@ -1014,73 +1038,82 @@ function saveDesign() { // 保存设计
} }
</style> </style>
<style> <style>
.x6-widget-stencil-content{ .x6-widget-stencil-content {
top:0px !important; top: 0px !important;
} }
.antvx6-header{
width: 100%; .antvx6-header {
height: 60px; width: 100%;
display: flex; height: 60px;
align-items: center; display: flex;
justify-content: space-between; align-items: center;
padding: 10px; justify-content: space-between;
background-color: #ffffff; padding: 10px;
border-bottom: 1px solid #e0e0e0; background-color: #ffffff;
} border-bottom: 1px solid #e0e0e0;
.header-left-box{ }
width: 400px;
height: 60px; .header-left-box {
display: flex; width: 400px;
align-items: center; height: 60px;
} display: flex;
.header-content-box{ align-items: center;
display: flex; }
align-items: center;
} .header-content-box {
.return-icon-box { display: flex;
width: 30px; align-items: center;
height: 30px; }
display:flex;
align-items:center; .return-icon-box {
justify-content: center; width: 30px;
cursor: pointer; height: 30px;
margin-right: 10px; display: flex;
} align-items: center;
.return-icon-box:hover{ justify-content: center;
background-color: #eeeeee; cursor: pointer;
border-radius: 4px; margin-right: 10px;
} }
.antvx6-header .project-name{
font-family: 'Arial Negreta', 'Arial Normal', 'Arial'; .return-icon-box:hover {
font-weight: 700; background-color: #eeeeee;
font-style: normal; border-radius: 4px;
font-size: 16px; }
color: #333333;
margin-right: 10px; .antvx6-header .project-name {
} font-family: 'Arial Negreta', 'Arial Normal', 'Arial';
.antvx6-header .operation-icon-box{ font-weight: 700;
width: 46px; font-style: normal;
height: 46px; font-size: 16px;
display:flex; color: #333333;
align-content:center; margin-right: 10px;
justify-content: center; }
flex-wrap: wrap;
cursor: pointer; .antvx6-header .operation-icon-box {
margin-right: 20px; width: 46px;
font-family: '微软雅黑'; height: 46px;
font-weight: 400; display: flex;
font-style: normal; align-content: center;
font-size: 12px; justify-content: center;
color: #4B4B4B; flex-wrap: wrap;
padding-top: 5px; cursor: pointer;
} margin-right: 20px;
.antvx6-header .operation-icon-box:hover{ font-family: '微软雅黑';
background-color: #eeeeee; font-weight: 400;
border-radius: 4px; font-style: normal;
} font-size: 12px;
.operation-icon-text{ color: #4B4B4B;
width: 100%; padding-top: 5px;
text-align: center; }
padding-top: 5px;
} .antvx6-header .operation-icon-box:hover {
background-color: #eeeeee;
border-radius: 4px;
}
.operation-icon-text {
width: 100%;
text-align: center;
padding-top: 5px;
}
</style> </style>