postdischarge-ui/src/views/system/Scriptpreview/index.vue
2024-06-14 08:59:44 +08:00

902 lines
27 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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
},
// SVG节点图片URL地址
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>