话术流程图

This commit is contained in:
shidongli 2024-06-14 08:59:44 +08:00
parent 6f8b41e941
commit 8bf76511f5
12 changed files with 2082 additions and 0 deletions

View File

@ -36,10 +36,18 @@
"url": "https://gitee.com/y_project/xinelu-Vue.git"
},
"dependencies": {
"@antv/g6-editor": "^1.2.0",
"@babel/preset-react": "^7.24.7",
"@fortawesome/fontawesome-svg-core": "^6.5.2",
"@fortawesome/free-brands-svg-icons": "^6.5.2",
"@fortawesome/free-regular-svg-icons": "^6.5.2",
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/vue-fontawesome": "^2.0.10",
"@riophae/vue-treeselect": "0.4.0",
"@wangeditor/editor": "^5.1.23",
"@wangeditor/editor-for-vue": "^1.0.2",
"axios": "0.24.0",
"butterfly-dag": "^5.1.0-beta.38",
"clipboard": "2.0.8",
"core-js": "3.19.1",
"echarts": "4.9.0",
@ -50,6 +58,8 @@
"js-beautify": "1.13.0",
"js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1",
"less": "^4.2.0",
"netflix-conductor-json-tree": "^0.0.4",
"nprogress": "0.2.0",
"quill": "1.3.7",
"screenfull": "5.0.2",
@ -74,6 +84,7 @@
"connect": "3.6.6",
"eslint": "7.15.0",
"eslint-plugin-vue": "7.2.0",
"less-loader": "^7.3.0",
"lint-staged": "10.5.3",
"runjs": "4.4.2",
"sass": "1.32.13",

18
src/api/system/preview.js Normal file
View File

@ -0,0 +1,18 @@
import request from '@/utils/request'
//新增
export function insertScriptEdgeNode(data) {
return request({
url: '/manage/script/updateScriptEdgeNode',
method: 'post',
data: data
})
}
// 话术列表
export function selectScriptEdgeNode(id) {
return request({
url: `/manage/script/selectScriptEdgeNode?id=${id}`,
method: 'get'
})
}

View File

@ -1,4 +1,9 @@
import Vue from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { fas } from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
import { fab } from '@fortawesome/free-brands-svg-icons'
import Cookies from 'js-cookie'
@ -38,6 +43,7 @@ import VueMeta from 'vue-meta'
// 字典数据组件
import DictData from '@/components/DictData'
import echarts from "echarts";
library.add(fas,far, fab)
Vue.prototype.$echarts = echarts;
// 全局方法挂载
@ -52,6 +58,8 @@ Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
// 全局组件挂载
Vue.component('font-awesome-icon', FontAwesomeIcon)
Vue.component('DictTag', DictTag)
Vue.component('Pagination', Pagination)
Vue.component('RightToolbar', RightToolbar)

View File

@ -0,0 +1,902 @@
<template>
<div id="vue-g6-editor">
<el-row>
<el-col :span="24">
<!-- <header>vue-g6-editor</header> -->
</el-col>
</el-row>
<!-- 工具栏 -->
<el-row>
<el-col :span="24">
<div id="toolbar">
<!-- <font-awesome-icon icon="fa fa-history" />
<font-awesome-icon icon="heart" />
<font-awesome-icon icon="clock" />
<font-awesome-icon icon="clock" style="color: #476151" />
<i
class="el-icon-edit"
data-command="save"
title="保存"
@click="submitForm"
>保存</i
> -->
<!-- <font-awesome-icon icon="heart" /> -->
<!-- <FontAwesomeIcon icon="far fa-copy" /> -->
<font-awesome-icon
data-command="save"
class="command fa fa-floppy-o"
icon="command far far fa-copy"
title="保存"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-reply-all"
title="历史数据"
@click="readHistoryData"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
class="fa fa-hdd-o"
icon="fas fa-file"
title="上传数据"
@click="readUploadData"
></font-awesome-icon>
<font-awesome-icon
icon="fas fa-download"
style="margin-left: 10px"
title="另存为文件"
@click="saveAsFile"
>文件</font-awesome-icon
>
<!-- <FontAwesomeIcon icon="fas fa-image" /> -->
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-image"
title="另存为图片"
@click="openSaveAsImageDialog"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="undo"
icon="fas fa-undo"
class="command fa fa-undo"
title="撤销"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="redo"
class="command fa fa-repeat"
icon="fas fa-repeat"
title="重做"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="delete"
class="command fa fa-trash-o"
icon="fas fa-trash-alt"
title="删除"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="zoomOut"
class="command fa fa-search-minus"
icon="fas fa-search-minus"
title="缩小"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="zoomIn"
icon="fas fa-search-plus"
class="command fa fa-search-plus"
title="放大"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-eraser"
data-command="clear"
class="command fa fa-eraser"
title="清除画布"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-arrow-up"
data-command="toFront"
class="command fa fa-arrow-up"
title="提升层级"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-arrow-down"
data-command="toBack"
class="command fa fa-arrow-down"
title="下降层级"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-check-square"
data-command="selectAll"
class="command fa fa-check-square-o"
title="全选"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="far fa-copy"
data-command="copy"
class="command fa fa-files-o"
title="复制"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-clone"
data-command="paste"
class="command fa fa-clipboard"
title="粘贴"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-expand"
data-command="autoZoom"
class="command fa fa-expand"
title="实际大小"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-compress"
data-command="resetZoom"
class="command fa fa-compress"
title="适应页面"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-object-group"
data-command="addGroup"
class="command fa fa-object-group"
title="组合"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-object-ungroup"
data-command="unGroup"
class="command fa fa-object-ungroup"
title="取消组合"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-crop"
data-command="multiSelect"
class="command fa fa fa-crop"
title="多选"
></font-awesome-icon>
</div>
</el-col>
</el-row>
<!-- 元素面板 + 画布 + 属性栏 -->
<el-row>
<!-- 元素面板 -->
<el-col :span="2">
<!-- <div id="itempannel">
</div> -->
</el-col>
<!-- 画布 -->
<el-col :span="20">
<el-col :span="24">
<div id="page"></div>
</el-col>
</el-col>
<!-- 属性栏 -->
<el-col :span="4">
<section class="right-part">
<!-- 缩略图 -->
<div id="minimap">
<div class="title">缩略图</div>
</div>
</section>
</el-col>
</el-row>
<!-- 弹窗 -->
<article>
<!-- 下载图片 -->
<section class="save-as-image-dialog">
<el-dialog
title="下载图片"
:visible.sync="saveAsImageDialogVisible"
width="360px"
>
<el-form label-width="100px" label-position="top">
<el-form-item label="选择图片格式">
<el-select v-model="saveAsImageFormat">
<el-option label="jpg" value="jpg">
<span style="float: left">jpg</span>
<span style="float: right; color: #8492a6; font-size: 13px"
>白色背景</span
>
</el-option>
<el-option label="png" value="png">
<span style="float: left">png</span>
<span style="float: right; color: #8492a6; font-size: 13px"
>透明背景</span
>
</el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="saveAsImageDialogVisible = false"
> </el-button
>
<el-button type="primary" @click="saveAsImage"> </el-button>
</span>
</el-dialog>
</section>
</article>
<!-- 右键菜单 -->
<section>
<div id="contextmenu">
<div data-status="node-selected" class="menu">
<el-button data-command="copy" class="command">复制</el-button>
<el-button data-command="paste" class="command">粘贴</el-button>
<el-button data-command="delete" class="command">删除</el-button>
</div>
<div data-status="edge-selected" class="menu">
<el-button data-command="delete" class="command">删除</el-button>
</div>
<div data-status="group-selected" class="menu">
<el-button data-command="copy" class="command">复制</el-button>
<el-button data-command="paste" class="command">粘贴</el-button>
<el-button data-command="unGroup" class="command">取消组合</el-button>
<el-button data-command="delete" class="command">删除</el-button>
</div>
<div data-status="canvas-selected" class="menu">
<el-button data-command="undo" class="command">撤销</el-button>
<el-button data-command="redo" class="command disable"
>重做</el-button
>
</div>
<div data-status="multi-selected" class="menu">
<el-button data-command="copy" class="command">复制</el-button>
<el-button data-command="paste" class="command">粘贴</el-button>
<el-button data-command="addGroup" class="command">组合</el-button>
</div>
</div>
</section>
</div>
</template>
<script>
import G6Editor from "@antv/g6-editor";
import mixin from "../mianview/mixin";
import { selectScriptEdgeNode } from "@/api/system/preview";
import { construct } from "netflix-conductor-json-tree/dist/index";
import Cookies from 'js-cookie'
export default {
name: "VueG6Editor",
mixins: [mixin],
data() {
return {
form: {
scriptInfoId: null,
flowScheme: null,
nodes: [],
edges: [],
},
// form: {
// nodes: [{
// color
// :
// "#FA8C16",
// id
// :
// "655c5165",
// index
// :
// 0,
// label
// :
// "",
// nodetype
// :
// "startNode",
// shape
// :
// "flow-circle",
// size
// :
// "72*72",
// type
// :
// "node",
// x
// :
// 441.5124969482422,
// y
// :
// 60.79999542236328,
// }, {
// color
// :
// "#1890ff",
// id
// :
// "8660695d",
// index
// :
// 1,
// label
// :
// "",
// size
// :
// "100*50",
// type
// :
// "node",
// x
// :
// 242.5124969482422,
// y
// :
// 183.5999984741211,
// },
// {
// color
// :
// "#1890ff",
// id
// :
// "59c9ceed",
// index
// :
// 2,
// label
// :
// "",
// size
// :
// "100*50",
// type
// :
// "node",
// x
// :
// 606.5124969482422,
// y
// :
// 187.5999984741211,
// }, {
// color
// :
// "#722ED1",
// id
// :
// "16f4c8ba",
// index
// :
// 5,
// label
// :
// "##",
// shape
// :
// "flow-capsule",
// size
// :
// "200*48",
// type
// :
// "node",
// x
// :
// 433.5124969482422,
// y
// :
// 125.5999984741211,
// }, {
// color
// :
// "#722ED1",
// id
// :
// "e4839dcc",
// index
// :
// 6,
// label
// :
// "",
// shape
// :
// "flow-capsule",
// size
// :
// "80*48",
// type
// :
// "node",
// x
// :
// 233.5124969482422,
// y
// :
// 251.5999984741211,
// }, {
// color
// :
// "#1890ff",
// id
// :
// "392ca0b8",
// index
// :
// 7,
// label
// :
// "",
// size
// :
// "100*50",
// type
// :
// "node",
// x
// :
// 55.51249694824219,
// y
// :
// 299.5999984741211
// }, {
// color
// :
// "#1890ff",
// id
// :
// "6bcab22d",
// index
// :
// 8,
// label
// :
// "",
// size
// :
// "100*50",
// type
// :
// "node",
// x
// :
// 384.5124969482422,
// y
// :
// 307.5999984741211
// },
// {
// color
// :
// "#722ED1",
// id
// :
// "dc5de91f",
// index
// :
// 11,
// label
// :
// " ",
// shape
// :
// "flow-capsule",
// size
// :
// "200*48",
// type
// :
// "node",
// x
// :
// 55.51249694824219,
// y
// :
// 366.5
// }],
// edges: [{
// id: "b04d23c7",
// index
// :
// 3,
// label
// :
// "",
// shape
// :
// "flow-polyline-round",
// source
// :
// "655c5165",
// sourceAnchor
// :
// 1,
// target
// :
// "59c9ceed",
// targetAnchor
// :
// 0,
// }, {
// id
// :
// "7894068d",
// index
// :
// 4,
// label
// :
// "",
// shape
// :
// "flow-polyline-round",
// source
// :
// "655c5165",
// sourceAnchor
// :
// 3,
// target
// :
// "8660695d",
// targetAnchor
// :
// 0,
// }, {
// id
// :
// "6aa429cc",
// index
// :
// 9,
// label
// :
// "",
// shape
// :
// "flow-polyline-round",
// source
// :
// "8660695d",
// sourceAnchor
// :
// 3,
// target
// :
// "392ca0b8",
// targetAnchor
// :
// 0,
// },
// {
// id
// :
// "02bfc4d0",
// index
// :
// 10,
// label
// :
// "",
// shape
// :
// "flow-polyline-round",
// source
// :
// "8660695d",
// sourceAnchor
// :
// 1,
// target
// :
// "6bcab22d",
// targetAnchor
// :
// 0
// }
// ]
// },
//
nodeAttributeForm: {
label: "",
width: "",
height: ""
},
//
edgeAttributeForm: {
label: ""
},
//
canvasAttributeForm: {
grid: true,
cell: 20
},
// SVGURL
startNodeSVGUrl: require("../mianview/start-node.svg"),
endNodeSVGUrl: require("../mianview/end-node.svg"),
regularNodeSVGUrl: require("../mianview/regular-node.svg"),
conditionNodeSVGUrl: require("../mianview/condition-node.svg"),
nNodeSVGUrl: "https://gw.alipayobjects.com/zos/rmsportal/rQMUhHHSqwYsPwjXxcfP.svg",
modelNodeSVGUrl: "https://gw.alipayobjects.com/zos/rmsportal/rQMUhHHSqwYsPwjXxcfP.svg",
//
editor: null,
saveAsImageDialogVisible: false,
saveAsImageFormat: "jpg"
};
},
mounted() {
this.initG6Editor();
this.getlist();
// this.editor.getCurrentPage().save()
this.editor.getCurrentPage().hideGrid();
this.editor.getCurrentPage().read(this.form);
},
methods: {
getlist(){
selectScriptEdgeNode(Cookies.get('id')).then(res=>{
this.form=JSON.parse(res.data.flowScheme)
this.editor.getCurrentPage().read(this.form);
// console.log(this.form,'this.form')
})
},
//
initG6Editor() {
const _this = this;
const editor = new G6Editor();
this.editor = editor;
G6Editor.track(false);
const Command = G6Editor.Command;
// save
Command.registerCommand("save", {
//
queue: false,
//
enable: (editor) => {
return true;
},
//
execute(editor) {
let needSaveData = editor.getCurrentPage().save();
console.log(needSaveData, 'needSaveData');
// JSON.parse(JSON.stringify(needSaveData))
// console.log(JSON.stringify(needSaveData), 'text1111');
const text =JSON.stringify(needSaveData)
console.log(JSON.parse(JSON.stringify(text)), 'text');
localStorage.setItem("flowData", JSON.stringify(needSaveData));
_this.save(needSaveData);
_this.$message.success("数据已保存1111");
},
//
back(editor) {
console.log("反向命令");
console.log(editor);
},
// Ctrl + S
shortcutCodes: [
["metaKey", "s"],
["ctrlKey", "s"]
]
});
//
const flow = new G6Editor.Flow({
graph: {
container: "page"
},
align: {
line: {
// 线
stroke: "#FA8C16",
// 线
lineWidth: 1
},
//
item: true,
//
grid: true
},
grid: {
//
cell: 18
},
shortcut: {
//
save: true
}
});
window.flow = flow;
//
flow.getGraph().edge({
shape: "flow-polyline"
});
//
const itempannel = new G6Editor.Itempannel({
container: "itempannel"
});
//
const toolbar = new G6Editor.Toolbar({
container: "toolbar"
});
//
// const detailpannel = new G6Editor.Detailpannel({
// container: "detailpannel"
// });
//
let minimapWidth = getComputedStyle(document.querySelector(".right-part")).width;
minimapWidth = Number(minimapWidth.replace(/px$/, ""));
const minimap = new G6Editor.Minimap({
container: "minimap",
width: minimapWidth,
height: 200
});
//
const contextmenu = new G6Editor.Contextmenu({
container: "contextmenu"
});
// Editor
editor.add(flow);
editor.add(itempannel);
editor.add(toolbar);
// editor.add(detailpannel);
editor.add(minimap);
editor.add(contextmenu);
// window便
window.editor = editor;
//
const currentPage = editor.getCurrentPage();
currentPage.on("afterchange", (e) => {
if (e.action === "add") {
if (e.model.nodetype === "startNode" || e.model.nodetype === "endNode") {
let nodes = this.editor.getCurrentPage().getNodes();
for (const item of nodes) {
if (item.model.nodetype === e.model.nodetype && item.model.id !== e.model.id) {
this.editor.getCurrentPage().remove(e.item);
this.$message.warning("只能有一个开始节点或结束节点");
}
}
}
}
});
//
currentPage.on("afteritemselected", (ev) => {
console.log("打印所选对象属性", ev.item);
console.log("打印所选对象数据模型", ev.item.model);
const selectedItemDataModel = ev.item.model;
//
if (ev.item.isNode) {
this.nodeAttributeForm.label = selectedItemDataModel.label;
this.nodeAttributeForm.width = selectedItemDataModel.size.split("*")[0];
this.nodeAttributeForm.height = selectedItemDataModel.size.split("*")[1];
this.nodeAttributeForm.color = selectedItemDataModel.color;
}
//
if (ev.item.isEdge) {
ev.item.graph.edge({
shape: "flow-polyline-round"
});
this.edgeAttributeForm.label = selectedItemDataModel.label;
this.edgeAttributeForm.shape = selectedItemDataModel.shape;
}
});
//
currentPage.on("afterdelete", (ev) => { });
},
//
openSaveAsImageDialog() {
this.saveAsImageDialogVisible = true;
},
// /
toggleGridShowStatus(value) {
if (value) {
this.editor.getCurrentPage().showGrid();
} else {
this.editor.getCurrentPage().hideGrid();
}
},
//
saveAsImage() {
let newCanvas;
if (this.saveAsImageFormat === "jpg") {
let canvas = this.editor.getCurrentPage().saveImage();
newCanvas = document.createElement("canvas");
newCanvas.width = canvas.width;
newCanvas.height = canvas.height;
let newContext = newCanvas.getContext("2d");
newContext.fillStyle = "#fff";
newContext.fillRect(0, 0, newCanvas.width, newCanvas.height);
newContext.drawImage(canvas, 0, 0);
}
if (this.saveAsImageFormat === "png") {
newCanvas = this.editor.getCurrentPage().saveImage();
}
let imageDataURL = newCanvas.toDataURL();
let downloadLink = document.createElement("a");
downloadLink.download = "图片.jpg";
downloadLink.href = imageDataURL;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
this.saveAsImageDialogVisible = false;
},
//
submitForm() {
const _this = this;
let needSaveData = editor.getCurrentPage().save();
console.log(needSaveData, 'needSaveData');
localStorage.setItem("flowData", JSON.stringify(needSaveData));
_this.save(needSaveData);
_this.$message.success("数据已保存");
},
//
saveAsFile() {
let sub = this.editor.getCurrentPage().save()
console.log(sub, 'sub')
let jsonString = JSON.stringify(this.editor.getCurrentPage().save());
let blob = new Blob([jsonString]);
let blobURL = URL.createObjectURL(blob);
let downloadLink = document.createElement("a");
downloadLink.download = "数据.json";
downloadLink.href = blobURL;
document.body.appendChild(downloadLink);
downloadLink.click();
URL.revokeObjectURL(blobURL);
document.body.removeChild(downloadLink);
},
//
readHistoryData() {
let stringData = localStorage.getItem("flowData");
if (stringData === "" || stringData === "{}" || stringData === null) {
this.$message.warning("无历史数据");
return;
}
let jsonData = JSON.parse(stringData);
this.editor.getCurrentPage().read(jsonData);
},
//
readUploadData() {
let uploadButton = document.createElement("input");
uploadButton.setAttribute("type", "file");
uploadButton.setAttribute("accept", ".json");
uploadButton.addEventListener("change", (e) => {
console.dir(uploadButton);
let file = uploadButton.files[0];
let fileReader = new FileReader();
fileReader.onload = (event) => {
console.log(event);
let text = JSON.parse(event.target.result);
console.log(text);
this.editor.getCurrentPage().read(text);
};
fileReader.readAsText(file);
});
uploadButton.click();
},
//
save(source) {
let edges = source.edges;
let nodes = source.nodes;
console.log(construct);
let res = construct(source);
console.log(JSON.stringify(res, null, 2));
}
}
};
</script>
<style lang="less">
@import url("../mianview/index.less");
</style>

View File

@ -0,0 +1,17 @@
<svg width="80" height="80" xmlns="http://www.w3.org/2000/svg">
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
<g>
<title>background</title>
<rect x="-1" y="-1" width="82" height="82" id="canvas_background" fill="none"/>
<g id="canvasGrid" display="none">
<rect id="svg_4" width="80" height="400" x="1" y="1" stroke-width="0" fill="url(#gridpattern)"/>
</g>
</g>
<g>
<title>Layer 1</title>
<ellipse fill="#fff" stroke="#000" stroke-width="1.5" cx="139.5" cy="166.4375" id="svg_2"/>
<rect stroke="#5cdbd3" 高度="56" transform="rotate(45 40.04504776000976,40.213043212890625) " 宽度="55" id="svg_5" height="55.386692" width="55.38669" y="12.519695" x="12.351704" stroke-width="null" fill="#e8fffb"/>
<text xml:space="preserve" text-anchor="start" font-family="Arvo, sans-serif" font-size="14" id="svg_6" y="45.754652" x="12.013331" stroke-width="0" stroke="#5cdbd3" fill="#000000">条件节点</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 968 B

View File

@ -0,0 +1,17 @@
<svg width="80" height="80" xmlns="http://www.w3.org/2000/svg">
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
<g>
<title>background</title>
<rect x="-1" y="-1" width="82" height="82" id="canvas_background" fill="none"/>
<g id="canvasGrid" display="none">
<rect id="svg_4" width="80" height="400" x="1" y="1" stroke-width="0" fill="url(#gridpattern)"/>
</g>
</g>
<g>
<title>Layer 1</title>
<ellipse stroke="#ffc371" fill="#fff3ea" cx="40.000001" cy="39.999998" id="svg_1" rx="39" ry="39"/>
<ellipse fill="#fff" stroke="#000" stroke-width="1.5" cx="139.5" cy="166.4375" id="svg_2"/>
<text fill="#000000" stroke="#ffc371" stroke-width="0" stroke-opacity="null" fill-opacity="null" x="12.013936" y="45.567568" id="svg_3" font-size="14" font-family="Arvo, sans-serif" text-anchor="start" xml:space="preserve" font-weight="normal">结束节点</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 911 B

View File

@ -0,0 +1,146 @@
@backgroundColor: #fbfbfb;
@borderColor: #dadce0;
@itempannelAndPageBorder: 1px solid #ccc;
@pageHeight: calc(100vh - 41px - 37px);
body {
margin: 0;
overflow: hidden;
}
#vue-g6-editor {
header:nth-of-type(1) {
background: @backgroundColor;
line-height: 40px;
padding-left: 20px;
border-bottom: 1px solid @borderColor;
box-sizing: border-box;
}
// 工具栏
#toolbar {
background: @backgroundColor;
border-bottom: 1px solid @borderColor;
padding: 4px 14px;
i {
font-size: 18px;
padding: 4px;
margin-right: 8px;
color: #999999;
&:hover {
cursor: pointer;
background-color: #eeeeee;
color: #5cb6ff;
}
}
}
// 元素面板
#itempannel {
box-sizing: border-box;
background-color: @backgroundColor;
border-right: 1px solid @borderColor;
height: @pageHeight;
padding-top: 10px;
overflow: hidden;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
align-content: flex-start;
.getItem {
cursor: move;
width: 80px;
height: 80px;
margin-bottom: 20px;
display: flex;
justify-content: center;
align-items: center;
img {
width: 100%;
}
}
}
// 主画布
#page {
height: @pageHeight;
canvas {
// 去除canvas底部间隙
display: block;
width: 100%;
}
}
// 右侧部分(属性栏 + 缩略图)
.right-part {
height: @pageHeight;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
// 属性栏
#detailpannel {
flex-grow: 1;
background-color: @backgroundColor;
border-left: 1px solid @borderColor;
overflow-y: scroll;
#nodeAttributeBar,
#edgeAttributeBar,
#groupAttributeBar,
#canvasAttributeBar,
#multiAttributeBar {
.title {
height: 34px;
line-height: 34px;
text-align: center;
box-sizing: border-box;
font-weight: bold;
font-size: 13px;
border-width: 0 0 1px 0;
border-style: solid;
border-color: @borderColor;
}
.main {
padding: 10px;
}
}
}
// 缩略图
#minimap {
background-color: @backgroundColor;
border-top: 1px solid #ccc;
border-left: 1px solid #ccc;
.title {
height: 34px;
line-height: 34px;
text-align: center;
box-sizing: border-box;
font-weight: bold;
font-size: 13px;
border-width: 0 0 1px 0;
border-style: solid;
border-color: @borderColor;
}
}
// 右键菜单
#contextmenu {
display: none;
.menu {
/deep/ .el-button {
width: 100%;
display: block;
margin-left: 0;
border-radius: 0 !important;
border-bottom: none;
&:nth-last-of-type(1) {
border-bottom: 1px solid #dcdfe6;
}
}
}
}
// 下载图片弹窗
.save-as-image-dialog {
/deep/ .el-select {
display: block;
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,39 @@
export default {
methods: {
// 保存节点属性
saveNodeAttribute() {
this.editor.executeCommand(() => {
// 获取画布
const page = this.editor.getCurrentPage();
// 获取所选对象
const selectedItem = page.getSelected()[0];
page.update(selectedItem.id, {
label: this.nodeAttributeForm.label,
size: this.nodeAttributeForm.width + "*" + this.nodeAttributeForm.height,
color: this.nodeAttributeForm.color
});
});
},
// 保存边属性
saveEdgeAttribute() {
this.editor.executeCommand(() => {
// 获取画布
const page = this.editor.getCurrentPage();
// 获取所选对象
const selectedItem = page.getSelected()[0];
console.log(this.edgeAttributeForm);
if(this.edgeAttributeForm.keyword){
this.edgeAttributeForm.label = {
text: this.edgeAttributeForm.label,
fill: 'red'
}
}
page.update(selectedItem.id, {
label: this.edgeAttributeForm.label,
shape: this.edgeAttributeForm.shape,
keyword: this.edgeAttributeForm.keyword
});
});
}
}
};

View File

@ -0,0 +1,18 @@
<svg width="80" height="49" xmlns="http://www.w3.org/2000/svg">
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
<g>
<title>background</title>
<rect x="-1" y="-1" width="82" height="51" id="canvas_background" fill="none"/>
<g id="canvasGrid" display="none">
<rect id="svg_4" width="80" height="400" x="3" y="3" stroke-width="0" fill="url(#gridpattern)"/>
</g>
</g>
<g>
<title>Layer 1</title>
<ellipse fill="#fff" stroke="#000" stroke-width="1.5" cx="141.5" cy="168.4375" id="svg_2"/>
<rect rx="4" stroke="#5bb1ff" 高度="48" 宽度="78" id="svg_7" height="48.227116" width="79.60015" y="0.56203" x="0.26445" stroke-width="NaN" fill="#e8f8ff"/>
<rect id="svg_8" height="0" width="2.400004" y="52.175019" x="95.400098" fill-opacity="null" stroke-opacity="null" stroke-width="null" stroke="#5cdbd3" fill="#e8fffb"/>
<text xml:space="preserve" text-anchor="start" font-family="'Courier New', Courier, monospace" font-size="13" id="svg_9" y="28.056967" x="14.021708" stroke-width="0" stroke="#5bb1ff" fill="#000000">常规节点</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,17 @@
<svg width="80" height="80" xmlns="http://www.w3.org/2000/svg">
<!-- Created with Method Draw - http://github.com/duopixel/Method-Draw/ -->
<g>
<title>background</title>
<rect x="-1" y="-1" width="82" height="82" id="canvas_background" fill="none"/>
<g id="canvasGrid" display="none">
<rect id="svg_4" width="80" height="400" x="1" y="1" stroke-width="0" fill="url(#gridpattern)"/>
</g>
</g>
<g>
<title>Layer 1</title>
<ellipse stroke="#ffc371" fill="#fff3ea" cx="40.000001" cy="39.999998" id="svg_1" rx="39" ry="39"/>
<ellipse fill="#fff" stroke="#000" stroke-width="1.5" cx="139.5" cy="166.4375" id="svg_2"/>
<text style="cursor: move;" fill="#000000" stroke="#ffc371" stroke-width="0" stroke-opacity="null" fill-opacity="null" x="12.013936" y="45.567568" id="svg_3" font-size="14" font-family="Arvo, sans-serif" text-anchor="start" xml:space="preserve" font-weight="normal">开始节点</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 933 B

View File

@ -0,0 +1,889 @@
<template>
<div id="vue-g6-editor">
<el-row>
<el-col :span="24">
<!-- <header>vue-g6-editor</header> -->
</el-col>
</el-row>
<!-- 工具栏 -->
<el-row>
<el-col :span="24">
<div id="toolbar">
<!-- <font-awesome-icon icon="fa fa-history" />
<font-awesome-icon icon="heart" />
<font-awesome-icon icon="clock" />
<font-awesome-icon icon="clock" style="color: #476151" />
<i
class="el-icon-edit"
data-command="save"
title="保存"
@click="submitForm"
>保存</i
> -->
<!-- <font-awesome-icon icon="heart" /> -->
<!-- <FontAwesomeIcon icon="far fa-copy" /> -->
<font-awesome-icon
data-command="save"
class="command fa fa-floppy-o"
icon="command far far fa-copy"
title="保存"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-reply-all"
title="历史数据"
@click="readHistoryData"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
class="fa fa-hdd-o"
icon="fas fa-file"
title="上传数据"
@click="readUploadData"
></font-awesome-icon>
<font-awesome-icon
icon="fas fa-download"
style="margin-left: 10px"
title="另存为文件"
@click="saveAsFile"
>文件</font-awesome-icon
>
<!-- <FontAwesomeIcon icon="fas fa-image" /> -->
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-image"
title="另存为图片"
@click="openSaveAsImageDialog"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="undo"
icon="fas fa-undo"
class="command fa fa-undo"
title="撤销"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="redo"
class="command fa fa-repeat"
icon="fas fa-repeat"
title="重做"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="delete"
class="command fa fa-trash-o"
icon="fas fa-trash-alt"
title="删除"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="zoomOut"
class="command fa fa-search-minus"
icon="fas fa-search-minus"
title="缩小"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
data-command="zoomIn"
icon="fas fa-search-plus"
class="command fa fa-search-plus"
title="放大"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-eraser"
data-command="clear"
class="command fa fa-eraser"
title="清除画布"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-arrow-up"
data-command="toFront"
class="command fa fa-arrow-up"
title="提升层级"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-arrow-down"
data-command="toBack"
class="command fa fa-arrow-down"
title="下降层级"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-check-square"
data-command="selectAll"
class="command fa fa-check-square-o"
title="全选"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="far fa-copy"
data-command="copy"
class="command fa fa-files-o"
title="复制"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-clone"
data-command="paste"
class="command fa fa-clipboard"
title="粘贴"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-expand"
data-command="autoZoom"
class="command fa fa-expand"
title="实际大小"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-compress"
data-command="resetZoom"
class="command fa fa-compress"
title="适应页面"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-object-group"
data-command="addGroup"
class="command fa fa-object-group"
title="组合"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-object-ungroup"
data-command="unGroup"
class="command fa fa-object-ungroup"
title="取消组合"
></font-awesome-icon>
<font-awesome-icon
style="margin-left: 10px"
icon="fas fa-crop"
data-command="multiSelect"
class="command fa fa fa-crop"
title="多选"
></font-awesome-icon>
</div>
</el-col>
</el-row>
<!-- 元素面板 + 画布 + 属性栏 -->
<el-row>
<!-- 元素面板 -->
<el-col :span="2">
<div id="itempannel">
<!-- 开始节点 -->
<div
id="startNode"
class="getItem"
data-type="node"
data-shape="flow-circle"
data-size="72*72"
data-label="开始节点"
data-color="#FA8C16"
data-nodeType="startNode"
>
<img draggable="false" :src="startNodeSVGUrl" alt srcset />
</div>
<!-- 常规节点 -->
<div
id="regularNode"
class="getItem"
data-type="node"
data-size="100*50"
data-label="常规节点"
data-color="#1890ff"
>
<img draggable="false" :src="regularNodeSVGUrl" alt srcset />
</div>
<!-- 条件节点 -->
<div
id="judgeNode"
class="getItem"
data-type="node"
data-shape="flow-rhombus"
data-size="80*80"
data-label="条件节点"
data-color="#13C2C2"
>
<img draggable="false" :src="conditionNodeSVGUrl" />
</div>
<!-- 自定义节点 -->
<div
class="getItem"
data-type="node"
data-shape="customNode"
data-size="80*48"
data-labeltitle=""
data-labelconcent=""
data-color="#722ED1"
>
<img draggable="false" :src="nNodeSVGUrl" />
</div>
<!-- 结束节点 -->
<div
id="endNode"
class="getItem"
data-type="node"
data-shape="flow-circle"
data-size="80*80"
data-label="结束节点"
data-color="#FA8C16"
data-nodeType="endNode"
>
<img draggable="false" :src="endNodeSVGUrl" />
</div>
</div>
</el-col>
<!-- 画布 -->
<el-col :span="18">
<el-col :span="24">
<div id="page"></div>
</el-col>
</el-col>
<!-- 属性栏 -->
<el-col :span="4">
<section class="right-part">
<div id="detailpannel">
<!-- 节点属性栏 -->
<div
id="nodeAttributeBar"
class="pannel"
data-status="node-selected"
>
<div class="title">节点属性</div>
<div class="main">
<el-form
:model="nodeAttributeForm"
label-position="top"
label-width="80px"
>
<el-form-item label="节点文本" v-if="type != 'customNode'">
<el-input
v-model="nodeAttributeForm.label"
@change="saveNodeAttribute"
></el-input>
</el-form-item>
<el-form-item label="标题" v-if="type == 'customNode'">
<el-input
type="textarea"
v-model="nodeAttributeForm.labeltitle"
@change="saveNodeAttribute"
></el-input>
</el-form-item>
<el-form-item label="内容" v-if="type == 'customNode'">
<el-input
type="textarea"
v-model="nodeAttributeForm.labelconcent"
@change="saveNodeAttribute"
></el-input>
</el-form-item>
<el-form-item label="宽度">
<el-input
v-model="nodeAttributeForm.width"
@change="saveNodeAttribute"
></el-input>
</el-form-item>
<el-form-item label="高度">
<el-input
v-model="nodeAttributeForm.height"
@change="saveNodeAttribute"
></el-input>
</el-form-item>
<el-form-item label="颜色">
<el-color-picker
v-model="nodeAttributeForm.color"
@change="saveNodeAttribute"
></el-color-picker>
</el-form-item>
</el-form>
</div>
</div>
<!-- 边属性栏 -->
<div
id="edgeAttributeBar"
class="pannel"
data-status="edge-selected"
>
<div class="title">边属性</div>
<div class="main">
<el-form
:model="edgeAttributeForm"
label-position="top"
label-width="80px"
>
<el-form-item label="边文本">
<el-input
v-model="edgeAttributeForm.label"
@change="saveEdgeAttribute"
></el-input>
</el-form-item>
<el-form-item label="关键字">
<el-input
type="textarea"
v-model="edgeAttributeForm.keyword"
@change="saveEdgeAttribute"
></el-input>
</el-form-item>
<!-- <el-form-item label="边文本">
<el-select
v-model="edgeAttributeForm.shape"
@change="saveEdgeAttribute"
>
<el-option
label="流程图折线"
value="flow-polyline"
></el-option>
<el-option
label="流程图圆⻆折线"
value="flow-polyline-round"
></el-option>
<el-option
label="流程图曲线"
value="flow-smooth"
></el-option>
</el-select>
</el-form-item> -->
</el-form>
</div>
</div>
<div
id="groupAttributeBar"
class="pannel"
data-status="group-selected"
>
<div class="title">群组属性栏</div>
</div>
<div
id="canvasAttributeBar"
class="pannel"
data-status="canvas-selected"
>
<div class="title">画布属性栏</div>
<div class="main">
<el-form label-width="80px" label-position="right">
<el-form-item label="网格对齐">
<el-checkbox
v-model="canvasAttributeForm.grid"
@change="toggleGridShowStatus"
></el-checkbox>
</el-form-item>
</el-form>
</div>
</div>
<div
id="multiAttributeBar"
class="pannel"
data-status="multi-selected"
>
<div class="title">多选时属性栏</div>
</div>
</div>
<!-- 缩略图 -->
<div id="minimap">
<div class="title">缩略图</div>
</div>
</section>
</el-col>
</el-row>
<!-- 弹窗 -->
<article>
<!-- 下载图片 -->
<section class="save-as-image-dialog">
<el-dialog
title="下载图片"
:visible.sync="saveAsImageDialogVisible"
width="360px"
>
<el-form label-width="100px" label-position="top">
<el-form-item label="选择图片格式">
<el-select v-model="saveAsImageFormat">
<el-option label="jpg" value="jpg">
<span style="float: left">jpg</span>
<span style="float: right; color: #8492a6; font-size: 13px"
>白色背景</span
>
</el-option>
<el-option label="png" value="png">
<span style="float: left">png</span>
<span style="float: right; color: #8492a6; font-size: 13px"
>透明背景</span
>
</el-option>
</el-select>
</el-form-item>
</el-form>
<span slot="footer">
<el-button @click="saveAsImageDialogVisible = false"
> </el-button
>
<el-button type="primary" @click="saveAsImage"> </el-button>
</span>
</el-dialog>
</section>
</article>
<!-- 右键菜单 -->
<section>
<div id="contextmenu">
<div data-status="node-selected" class="menu">
<el-button data-command="copy" class="command">复制</el-button>
<el-button data-command="paste" class="command">粘贴</el-button>
<el-button data-command="delete" class="command">删除</el-button>
</div>
<div data-status="edge-selected" class="menu">
<el-button data-command="delete" class="command">删除</el-button>
</div>
<div data-status="group-selected" class="menu">
<el-button data-command="copy" class="command">复制</el-button>
<el-button data-command="paste" class="command">粘贴</el-button>
<el-button data-command="unGroup" class="command">取消组合</el-button>
<el-button data-command="delete" class="command">删除</el-button>
</div>
<div data-status="canvas-selected" class="menu">
<el-button data-command="undo" class="command">撤销</el-button>
<el-button data-command="redo" class="command disable"
>重做</el-button
>
</div>
<div data-status="multi-selected" class="menu">
<el-button data-command="copy" class="command">复制</el-button>
<el-button data-command="paste" class="command">粘贴</el-button>
<el-button data-command="addGroup" class="command">组合</el-button>
</div>
</div>
</section>
</div>
</template>
<script>
import G6Editor from "@antv/g6-editor";
import mixin from "../mianview/mixin";
import { insertScriptEdgeNode,selectScriptEdgeNode } from "@/api/system/preview";
import Cookies from 'js-cookie'
import { construct } from "netflix-conductor-json-tree/dist/index";
export default {
name: "VueG6Editor",
mixins: [mixin],
data() {
return {
type: '',
state: {
edgeTextColor: '#000' //
},
form: {
scriptInfoId: null,
flowScheme: null,
nodes: [],
edges: [],
},
//
nodeAttributeForm: {
// title:"",
// contont:"",
labeltitle: "",
label: "",
labelconcent: "",
width: "",
height: ""
},
//
edgeAttributeForm: {
keyword: '',
label: ""
},
//
canvasAttributeForm: {
grid: true,
cell: 20
},
// SVGURL
startNodeSVGUrl: require("../mianview/start-node.svg"),
endNodeSVGUrl: require("../mianview/end-node.svg"),
regularNodeSVGUrl: require("../mianview/regular-node.svg"),
conditionNodeSVGUrl: require("../mianview/condition-node.svg"),
nNodeSVGUrl: "https://gw.alipayobjects.com/zos/rmsportal/rQMUhHHSqwYsPwjXxcfP.svg",
// modelNodeSVGUrl: "https://gw.alipayobjects.com/zos/rmsportal/rQMUhHHSqwYsPwjXxcfP.svg",
//
editor: null,
saveAsImageDialogVisible: false,
saveAsImageFormat: "jpg"
};
},
watch: {
nodeAttributeForm: {
handler(newVal, oldVal) {
if (newVal.labeltitle || newVal.labelconcent) {
this.$set(this.nodeAttributeForm, 'labelconcent', newVal.labelconcent)
this.$set(this.nodeAttributeForm, 'labeltitle', newVal.labeltitle)
// this.nodeAttributeForm.labelconcent=newVal.labelconcent
// this.nodeAttributeForm.labeltitle=newVal.labeltitle
this.nodeAttributeForm.label = newVal.labeltitle + '\n' + newVal.labelconcent;
// console.log('this.nodeAttributeForm.label', this.nodeAttributeForm.label)
} else {
this.nodeAttributeForm.label = newVal.label
}
console.log('obj发生了变化', newVal, oldVal)
},
deep: true
}
},
mounted() {
this.initG6Editor();
this.getlist()
this.form.edges.forEach(e => {
if (e.keyword) {
// e.label=e.label
e.label = {
text: e.label,
fill: 'red'
}
}
})
// this.editor.getCurrentPage().save()
// this.editor.getCurrentPage().read(this.form);
},
created() {
},
methods: {
getlist(){
selectScriptEdgeNode(Cookies.get('id')).then(res=>{
this.form=JSON.parse(res.data.flowScheme)
this.editor.getCurrentPage().read(this.form);
// console.log(this.form,'this.form')
})
},
//
initG6Editor() {
const _this = this;
const editor = new G6Editor();
this.editor = editor;
G6Editor.track(false);
const Command = G6Editor.Command;
// save
Command.registerCommand("save", {
//
queue: false,
//
enable: (editor) => {
return true;
},
//
execute(editor) {
let needSaveData = editor.getCurrentPage().save();
let newObj = JSON.parse(JSON.stringify(needSaveData))
newObj.scriptInfoId = Cookies.get('id')
newObj.flowScheme = JSON.stringify(needSaveData)
newObj.edges.forEach(e => {
if (e.keyword) {
// e.label=e.label
e.label = e.label.text
}
e.code = e.id
delete e.id
})
newObj.nodes.forEach(e => {
e.code = e.id
delete e.id
})
console.log(newObj, 'newObj');
// this.form.nodes=newObj.nodes
// this.form.edges=newObj.edges
// newObj.edges.forEach(e => {
// if (e.keyword) {
// // e.label=e.label
// e.label = e.label.text
// }
// })
insertScriptEdgeNode(newObj).then(res => {
if (res.code == 200) {
_this.$message.success("数据保存成功");
this.getlist()
} else {
_this.$modal.msgError(res.msg);
}
})
// newObj.nodes.forEach(e => {
// var text = e.label.replace(/\n/g, ",");
// var concet = text.split(',')
// console.log(concet, 'text')
// e.labeltitle = concet[0]
// e.labelconcent = concet[1]
// })
let testcs = JSON.stringify(needSaveData)
let test = JSON.parse(testcs)
console.log(testcs, 'JSON.stringify(needSaveData)');
console.log(test, 'test');
localStorage.setItem("flowData", JSON.stringify(needSaveData));
_this.save(needSaveData);
},
//
back(editor) {
console.log("反向命令");
},
// Ctrl + S
shortcutCodes: [
["metaKey", "s"],
["ctrlKey", "s"]
]
});
//
const flow = new G6Editor.Flow({
graph: {
container: "page"
},
align: {
line: {
// 线
stroke: "#FA8C16",
// 线
lineWidth: 1
},
//
item: true,
//
grid: true
},
grid: {
//
cell: 18
},
shortcut: {
//
save: true
}
});
window.flow = flow;
//
flow.getGraph().edge({
shape: "flow-polyline"
});
//
const itempannel = new G6Editor.Itempannel({
container: "itempannel"
});
//
const toolbar = new G6Editor.Toolbar({
container: "toolbar"
});
//
const detailpannel = new G6Editor.Detailpannel({
container: "detailpannel"
});
//
let minimapWidth = getComputedStyle(document.querySelector(".right-part")).width;
minimapWidth = Number(minimapWidth.replace(/px$/, ""));
const minimap = new G6Editor.Minimap({
container: "minimap",
width: minimapWidth,
height: 200
});
//
const contextmenu = new G6Editor.Contextmenu({
container: "contextmenu"
});
// Editor
editor.add(flow);
editor.add(itempannel);
editor.add(toolbar);
editor.add(detailpannel);
editor.add(minimap);
editor.add(contextmenu);
// window便
window.editor = editor;
//
const currentPage = editor.getCurrentPage();
currentPage.on("afterchange", (e) => {
if (e.action === "add") {
if (e.model.nodetype === "startNode" || e.model.nodetype === "endNode") {
let nodes = this.editor.getCurrentPage().getNodes();
for (const item of nodes) {
if (item.model.nodetype === e.model.nodetype && item.model.id !== e.model.id) {
this.editor.getCurrentPage().remove(e.item);
this.$message.warning("只能有一个开始节点或结束节点");
}
}
}
}
});
//
currentPage.on("afteritemselected", (ev) => {
console.log("打印所选对象属性", ev.item);
console.log("打印所选对象数据模型", ev.item.model);
const selectedItemDataModel = ev.item.model
//
if (ev.item.isNode) {
this.type = selectedItemDataModel.shape
if (selectedItemDataModel.label && selectedItemDataModel.labelconcent=='' && selectedItemDataModel.labeltitle=='') {
var text = selectedItemDataModel.label.replace(/\n/g, ",");
var concet = text.split(',')
console.log(concet, 'text')
if (concet.length == 2) {
this.nodeAttributeForm.labeltitle = concet[0]
this.nodeAttributeForm.labelconcent = concet[1]
} else if (concet.length == 1) {
this.nodeAttributeForm.label = concet[0];
}
} else {
this.nodeAttributeForm.labelconcent = selectedItemDataModel.labelconcent;
this.nodeAttributeForm.labeltitle = selectedItemDataModel.labeltitle;
}
if(!this.nodeAttributeForm.labelconcent && !this.nodeAttributeForm.labeltitle){
this.nodeAttributeForm.label = selectedItemDataModel.label;
}
// this.nodeAttributeForm.labelconcent = selectedItemDataModel.labelconcent;
// this.nodeAttributeForm.labeltitle = selectedItemDataModel.labeltitle;
this.nodeAttributeForm.width = selectedItemDataModel.size.split("*")[0];
this.nodeAttributeForm.height = selectedItemDataModel.size.split("*")[1];
this.nodeAttributeForm.color = selectedItemDataModel.color;
}
//
if (ev.item.isEdge) {
ev.item.graph.edge({
shape: "flow-polyline-round"
});
let newObj = JSON.parse(JSON.stringify(selectedItemDataModel))
if (newObj.keyword) {
console.log(newObj, '1111111')
this.edgeAttributeForm.label = newObj.label.text;
} else {
this.edgeAttributeForm.label = selectedItemDataModel.label;
}
this.edgeAttributeForm.shape = selectedItemDataModel.shape;
this.edgeAttributeForm.keyword = selectedItemDataModel.keyword;
// this.edgeAttributeForm.keyword = '00';
}
});
//
currentPage.on("afterdelete", (ev) => { });
},
//
openSaveAsImageDialog() {
this.saveAsImageDialogVisible = true;
},
// /
toggleGridShowStatus(value) {
if (value) {
this.editor.getCurrentPage().showGrid();
} else {
this.editor.getCurrentPage().hideGrid();
}
},
//
saveAsImage() {
let newCanvas;
if (this.saveAsImageFormat === "jpg") {
let canvas = this.editor.getCurrentPage().saveImage();
newCanvas = document.createElement("canvas");
newCanvas.width = canvas.width;
newCanvas.height = canvas.height;
let newContext = newCanvas.getContext("2d");
newContext.fillStyle = "#fff";
newContext.fillRect(0, 0, newCanvas.width, newCanvas.height);
newContext.drawImage(canvas, 0, 0);
}
if (this.saveAsImageFormat === "png") {
newCanvas = this.editor.getCurrentPage().saveImage();
}
let imageDataURL = newCanvas.toDataURL();
let downloadLink = document.createElement("a");
downloadLink.download = "图片.jpg";
downloadLink.href = imageDataURL;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
this.saveAsImageDialogVisible = false;
},
//
// submitForm() {
// const _this = this;
// let needSaveData = editor.getCurrentPage().save();
// console.log(needSaveData, 'needSaveData');
// localStorage.setItem("flowData", JSON.stringify(needSaveData));
// _this.save(needSaveData);
// _this.$message.success("");
// },
//
saveAsFile() {
let sub = this.editor.getCurrentPage().save()
console.log(sub, 'sub')
let jsonString = JSON.stringify(this.editor.getCurrentPage().save());
let blob = new Blob([jsonString]);
let blobURL = URL.createObjectURL(blob);
let downloadLink = document.createElement("a");
downloadLink.download = "数据.json";
downloadLink.href = blobURL;
document.body.appendChild(downloadLink);
downloadLink.click();
URL.revokeObjectURL(blobURL);
document.body.removeChild(downloadLink);
},
//
readHistoryData() {
let stringData = localStorage.getItem("flowData");
if (stringData === "" || stringData === "{}" || stringData === null) {
this.$message.warning("无历史数据");
return;
}
let jsonData = JSON.parse(stringData);
this.editor.getCurrentPage().read(jsonData);
},
//
readUploadData() {
let uploadButton = document.createElement("input");
uploadButton.setAttribute("type", "file");
uploadButton.setAttribute("accept", ".json");
uploadButton.addEventListener("change", (e) => {
console.dir(uploadButton);
let file = uploadButton.files[0];
let fileReader = new FileReader();
fileReader.onload = (event) => {
console.log(event);
let text = JSON.parse(event.target.result);
console.log(text);
this.editor.getCurrentPage().read(text);
};
fileReader.readAsText(file);
});
uploadButton.click();
},
//
save(source) {
let edges = source.edges;
let nodes = source.nodes;
console.log(construct);
let res = construct(source);
console.log(JSON.stringify(res, null, 2));
}
}
};
</script>
<style lang="less">
@import url("../mianview/index.less");
</style>