|
@@ -0,0 +1,588 @@
|
|
|
+<template>
|
|
|
+ <div>
|
|
|
+ <button @mousedown="startDrag('Start', $event)">开始节点</button>
|
|
|
+ <button @mousedown="startDrag('End', $event)">结束节点</button>
|
|
|
+ <button @mousedown="startDrag('Circle', $event)">循环节点</button>
|
|
|
+ <button @mousedown="startDrag('Rect', $event)">任务节点</button>
|
|
|
+ <button @mousedown="startDrag('polygon', $event)">条件节点</button>
|
|
|
+ <button @click="deleteNode()">删除</button>
|
|
|
+ <button @click="onUndo">撤销</button>
|
|
|
+ <button @click="onRedo">重做</button>
|
|
|
+ <button @click="savePic">生成图片</button>
|
|
|
+ <button @click="saveFlow">保存流程图并生成java代码</button>
|
|
|
+ <button @click="getJson">getJson</button>
|
|
|
+ <div class="graph-drawer-box">
|
|
|
+ <div ref="graphContainer"></div>
|
|
|
+ <RightDrawer ref="rightDrawer"
|
|
|
+ :drawerType="type" :selectCellNum="selectCellNum" :selectCell="selectCell"
|
|
|
+ :graph="graph" :grid="grid" @deleteNode="deleteNode"></RightDrawer>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <script>
|
|
|
+ import { Graph, Shape, FunctionExt, DataUri } from '@antv/x6';
|
|
|
+ // import insertCss from 'insert-css';
|
|
|
+ // 添加 Dnd 导入
|
|
|
+import { Dnd } from '@antv/x6-plugin-dnd';
|
|
|
+ import data from './nodes/data.js'
|
|
|
+ import { startDragToGraph } from './nodes/methods.js';
|
|
|
+ import RightDrawer from './nodes/right-drawer';
|
|
|
+ export default {
|
|
|
+ name: 'index2Page',
|
|
|
+ components: {
|
|
|
+ RightDrawer
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ selectCellNum: 0,
|
|
|
+ contentWidth: 0,
|
|
|
+ contentHeight: 0,
|
|
|
+ graph: null,
|
|
|
+ type: 'grid',
|
|
|
+ selectCell: '',
|
|
|
+ connectEdgeType: { //连线方式
|
|
|
+ connector: 'normal',
|
|
|
+ router: {
|
|
|
+ // name: ''
|
|
|
+ name: 'normal'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ grid: { // 网格设置
|
|
|
+ showGrid: true,
|
|
|
+ size: 10, // 网格大小 10px
|
|
|
+ visible: true, // 渲染网格背景
|
|
|
+ type: 'mesh',
|
|
|
+ args: {
|
|
|
+ color: '#D0D0D0',
|
|
|
+ thickness: 1, // 网格线宽度/网格点大小
|
|
|
+ factor: 10,
|
|
|
+ },
|
|
|
+ },
|
|
|
+ canUndo: false,
|
|
|
+ canRedo: false,
|
|
|
+ haveStart: false, //已有开始或结束
|
|
|
+ haveEnd: false,
|
|
|
+ }
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ // 在初始化图形之前注册插件
|
|
|
+ Graph.use(['dnd']);
|
|
|
+ this.initX6()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // initGraph() {
|
|
|
+ // this.graph = new Graph({
|
|
|
+ // container: document.getElementById('container'),
|
|
|
+ // width: 800,
|
|
|
+ // height: 600,
|
|
|
+ // background: {
|
|
|
+ // color: '#F2F7FA'
|
|
|
+ // }
|
|
|
+ // })
|
|
|
+ // console.log(dataJSON)
|
|
|
+ // this.graph.fromJSON(dataJSON) // 渲染元素 this.graph.centerContent() // 居中显示
|
|
|
+ // },
|
|
|
+ // 计算main主体高度
|
|
|
+ getMainHeight(e) {
|
|
|
+ /* this.contentHeight = Math.max(window.innerHeight - 60, 400);
|
|
|
+ this.contentWidth = window.innerWidth - 250;
|
|
|
+ if (e) {
|
|
|
+ //画布调整大小
|
|
|
+ this.graph.resize(this.contentWidth, this.contentHeight);
|
|
|
+ } */
|
|
|
+ this.contentWidth = this.$refs['graphContainer'].parentNode.offsetWidth;
|
|
|
+ this.contentHeight = 910;
|
|
|
+ },
|
|
|
+ initX6() {
|
|
|
+ this.type = 'grid';
|
|
|
+ this.selectCell = '';
|
|
|
+ let _that = this;
|
|
|
+ // window.addEventListener('resize', this.debounceHeight);
|
|
|
+ this.graph = new Graph({
|
|
|
+ container: this.$refs['graphContainer'],
|
|
|
+ width: 1200,
|
|
|
+ height: 600,
|
|
|
+ grid: this.grid,
|
|
|
+ panning: {
|
|
|
+ enabled: true,
|
|
|
+ modifiers: 'shift'
|
|
|
+ }, //平移
|
|
|
+ resizing: { //调整节点宽高
|
|
|
+ enabled: true,
|
|
|
+ orthogonal: false,
|
|
|
+ },
|
|
|
+ selecting: true, //可选
|
|
|
+ snapline: true,
|
|
|
+ interacting: {
|
|
|
+ edgeLabelMovable: true
|
|
|
+ },
|
|
|
+ connecting: { // 节点连接
|
|
|
+ anchor: 'center',
|
|
|
+ connectionPoint: 'anchor',
|
|
|
+ allowBlank: false,
|
|
|
+ snap: true,
|
|
|
+ createEdge() {
|
|
|
+ return new Shape.Edge({
|
|
|
+ attrs: {
|
|
|
+ line: {
|
|
|
+ stroke: '#1890ff',
|
|
|
+ strokeWidth: 1,
|
|
|
+ targetMarker: {
|
|
|
+ name: 'classic',
|
|
|
+ size: 8
|
|
|
+ },
|
|
|
+ strokeDasharray: 0, //虚线
|
|
|
+ style: {
|
|
|
+ animation: 'ant-line 30s infinite linear',
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ label: {
|
|
|
+ text: ''
|
|
|
+ },
|
|
|
+ connector: _that.connectEdgeType.connector,
|
|
|
+ router: {
|
|
|
+ name: _that.connectEdgeType.router.name || ''
|
|
|
+ },
|
|
|
+ zIndex: 0
|
|
|
+ })
|
|
|
+ },
|
|
|
+ },
|
|
|
+ highlighting: {
|
|
|
+ magnetAvailable: {
|
|
|
+ name: 'stroke',
|
|
|
+ args: {
|
|
|
+ padding: 4,
|
|
|
+ attrs: {
|
|
|
+ strokeWidth: 4,
|
|
|
+ stroke: '#6a6c8a'
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //滚动
|
|
|
+ scroller: {
|
|
|
+ enabled: false
|
|
|
+ },
|
|
|
+ //小地图
|
|
|
+ minimap: {
|
|
|
+ enabled: !this.readonly,
|
|
|
+ container: !this.readonly ? this.$refs['rightDrawer'].$refs['miniMap'] : '',
|
|
|
+ width: 300,
|
|
|
+ height: 150,
|
|
|
+ padding: 5
|
|
|
+ },
|
|
|
+ //缩放
|
|
|
+ mousewheel: {
|
|
|
+ enabled: true,
|
|
|
+ modifiers: ['ctrl', 'meta'],
|
|
|
+ },
|
|
|
+ // 历史
|
|
|
+ history: {
|
|
|
+ enabled: true,
|
|
|
+ },
|
|
|
+ //框选
|
|
|
+ selecting: {
|
|
|
+ enabled: true,
|
|
|
+ rubberband: true
|
|
|
+ },
|
|
|
+ });
|
|
|
+ // insertCss(`
|
|
|
+ // @keyframes ant-line {
|
|
|
+ // to {
|
|
|
+ // stroke-dashoffset: -1000
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // `)
|
|
|
+ this.graph.fromJSON(data);
|
|
|
+ this.graph.history.redo();
|
|
|
+ this.graph.history.undo();
|
|
|
+ // 鼠标移入移出节点
|
|
|
+ this.graph.on('node:mouseenter', FunctionExt.debounce(() => {
|
|
|
+ const container = this.$refs['graphContainer']
|
|
|
+ const ports = container.querySelectorAll('.x6-port-body')
|
|
|
+ this.showPorts(ports, true)
|
|
|
+ }), 500);
|
|
|
+ this.graph.on('node:mouseleave', () => {
|
|
|
+ const container = this.$refs['graphContainer']
|
|
|
+ const ports = container.querySelectorAll('.x6-port-body')
|
|
|
+ this.showPorts(ports, false)
|
|
|
+ });
|
|
|
+ this.graph.on('blank:click', () => {
|
|
|
+ this.type = 'grid';
|
|
|
+ //选中网格需清空选中节点的数据
|
|
|
+ this.selectCell = '';
|
|
|
+ console.log('blank:click')
|
|
|
+ });
|
|
|
+ this.graph.on('cell:click', ({ cell }) => {
|
|
|
+ this.type = cell.isNode() ? 'node' : 'edge';
|
|
|
+ this.$emit('cellClick', cell);
|
|
|
+ console.log('cell:click', cell, cell.isNode(), cell.attrs.nodeData, cell)
|
|
|
+ });
|
|
|
+ //监听框选
|
|
|
+ this.graph.on('selection:changed', args => {
|
|
|
+ //记录当前选中的数量
|
|
|
+ this.selectCellNum = args.selected.length;
|
|
|
+ if (this.selectCellNum > 1) {
|
|
|
+ //只有选中一个节点时才允许修改节点信息
|
|
|
+ this.type = 'grid';
|
|
|
+ this.selectCell = '';
|
|
|
+ } else {
|
|
|
+ this.selectCell = args.added[0];
|
|
|
+ }
|
|
|
+ args.added.forEach(cell => {
|
|
|
+ // this.selectCell = cell
|
|
|
+ if (cell.isEdge()) {
|
|
|
+ cell.isEdge() && cell.attr('line/strokeDasharray', 5) //虚线蚂蚁线
|
|
|
+ cell.addTools([
|
|
|
+ {
|
|
|
+ name: 'vertices',
|
|
|
+ args: {
|
|
|
+ padding: 4,
|
|
|
+ attrs: {
|
|
|
+ strokeWidth: 0.1,
|
|
|
+ stroke: '#2d8cf0',
|
|
|
+ fill: '#ffffff',
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ ])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ args.removed.forEach(cell => {
|
|
|
+ cell.isEdge() && cell.attr('line/strokeDasharray', 0); //正常线
|
|
|
+ cell.removeTools();
|
|
|
+ })
|
|
|
+ });
|
|
|
+ /**
|
|
|
+ * 处理history
|
|
|
+ */
|
|
|
+ //监听撤销
|
|
|
+ this.graph.history.on('undo', args => {
|
|
|
+ // code here
|
|
|
+ this.$emit('historyUndo', args);
|
|
|
+ });
|
|
|
+ //监听重做
|
|
|
+ this.graph.history.on('redo', args => {
|
|
|
+ // code here
|
|
|
+ this.$emit('historyRedo', args);
|
|
|
+ });
|
|
|
+ this.graph.history.on('change', () => {
|
|
|
+ this.historyChange();
|
|
|
+ });
|
|
|
+ // 监听节点新增
|
|
|
+ this.graph.on('node:added', args => {
|
|
|
+ const { cell } = args;
|
|
|
+ // 检查禁用情况
|
|
|
+ this.checkNode();
|
|
|
+ //选中
|
|
|
+ this.graph.resetSelection(cell);
|
|
|
+ this.type = 'node';
|
|
|
+ const data = cell.store.data;
|
|
|
+ switch (data.attrs.nodeData.type) {
|
|
|
+ case 'Start':
|
|
|
+ //开始
|
|
|
+ this.haveStart = true;
|
|
|
+ break;
|
|
|
+ case 'End':
|
|
|
+ //结束
|
|
|
+ this.haveEnd = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ //监听节点删除
|
|
|
+ this.graph.on('node:removed', args => {
|
|
|
+ const { cell } = args;
|
|
|
+ const data = cell.store.data;
|
|
|
+ // 检查禁用情况
|
|
|
+ this.checkNode();
|
|
|
+ switch (data.attrs.nodeData.type) {
|
|
|
+ case 'Start':
|
|
|
+ //开始
|
|
|
+ this.haveStart = false;
|
|
|
+ break;
|
|
|
+ case 'End':
|
|
|
+ //结束
|
|
|
+ this.haveEnd = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ //边连接
|
|
|
+ this.graph.on('edge:connected', args => {
|
|
|
+ //选中节点
|
|
|
+ this.graph.resetSelection(args.edge);
|
|
|
+ this.type = 'edge';
|
|
|
+ console.log('edge:connected', args.edge)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ showPorts(ports, show) {
|
|
|
+ for (let i = 0, len = ports.length; i < len; i = i + 1) {
|
|
|
+ ports[i].style.visibility = show ? 'visible' : 'hidden'
|
|
|
+ }
|
|
|
+ }, // 拖拽生成正方���或者圆形
|
|
|
+ startDrag(type, e) {
|
|
|
+ if (this.disabled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //只能有一个开始和结束
|
|
|
+ if (type === 'Start') {
|
|
|
+ if (this.haveStart) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ } else if (type === 'End') {
|
|
|
+ if (this.haveEnd) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ startDragToGraph(this.graph, type, e);
|
|
|
+ },
|
|
|
+ // 删除节点
|
|
|
+ deleteNode() {
|
|
|
+ if (this.disabled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const cell = this.graph.getSelectedCells();
|
|
|
+ this.graph.removeCells(cell);
|
|
|
+ this.type = 'grid';
|
|
|
+ },
|
|
|
+ // 保存png
|
|
|
+ savePic() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.graph.toPNG(dataUri => {
|
|
|
+ // 下载
|
|
|
+ DataUri.downloadDataUri(dataUri, this.title + '.png');
|
|
|
+ }, {
|
|
|
+ backgroundColor: 'white',
|
|
|
+ padding: {
|
|
|
+ top: 50,
|
|
|
+ right: 50,
|
|
|
+ bottom: 50,
|
|
|
+ left: 50
|
|
|
+ },
|
|
|
+ quality: 1,
|
|
|
+ copyStyles: false
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 检查是否可以禁用关联模型
|
|
|
+ * 当节点中存在非开始和结束节点时不允许编辑
|
|
|
+ */
|
|
|
+ checkNode(checkStartAndEnd) {
|
|
|
+ const node = this.graph.getNodes();
|
|
|
+ const ignores = ['Start', 'End'];
|
|
|
+ let diabledEntity = false;
|
|
|
+ console.log('node', node)
|
|
|
+ for (let i = node.length - 1; i > -1; i--) {
|
|
|
+ if (ignores.indexOf(node[i].attrs.nodeData.type) < 0) {
|
|
|
+ diabledEntity = true;
|
|
|
+ if (!checkStartAndEnd) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else if (checkStartAndEnd) {
|
|
|
+ if (node[i].attrs.nodeData.type === 'Start') {
|
|
|
+ this.haveStart = true;
|
|
|
+ } else {
|
|
|
+ this.haveEnd = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.diabledEntity = diabledEntity;
|
|
|
+ },
|
|
|
+ //流程图完整性校验
|
|
|
+ checkFlow() {
|
|
|
+ const graphToJson = this.graph.toJSON();
|
|
|
+ const { cells } = graphToJson;
|
|
|
+ /**
|
|
|
+ * 1、完整的流程图必需包含开始节点和结束节点且仅有一个
|
|
|
+ * 2、每个节点必定有至少一条与其他节点的连接线;
|
|
|
+ * 3、开始节点只能是连接线起点
|
|
|
+ * 4、结束节点只能是连接线终点
|
|
|
+ */
|
|
|
+ let errs = [], //错误消息集合
|
|
|
+ nodeList = [],
|
|
|
+ edgeList = [],
|
|
|
+ startNum = 0,
|
|
|
+ endNum = 0,
|
|
|
+ len = cells.length,
|
|
|
+ alls = [], //所有节点
|
|
|
+ edges = []; //与其他节点有连接关系的节点集合(不包含自己与自己连接的)
|
|
|
+ if (len === 0) {
|
|
|
+ errs.push('画布不能为空');
|
|
|
+ } else {
|
|
|
+ for (let i = 0; i < len; i++) {
|
|
|
+ //非连线(节点)
|
|
|
+ if (cells[i].shape !== 'edge') {
|
|
|
+ //节点数据
|
|
|
+ const nodeData = cells[i].attrs.nodeData;
|
|
|
+ //节点名称
|
|
|
+ const nodeText = cells[i].attrs.label.text;
|
|
|
+ const flowNode = nodeData.flowNode;
|
|
|
+ if (nodeData.type === 'Start') {
|
|
|
+ startNum++;
|
|
|
+ } else if (nodeData.type === 'End') {
|
|
|
+ endNum++;
|
|
|
+ } else if (nodeData.type === 'Rect') {
|
|
|
+ let errTxt = '任务节点【' + nodeText + '】';
|
|
|
+ switch (flowNode.flowNodeType) {
|
|
|
+ case '':
|
|
|
+ errs.push(errTxt + '未选择节点类型');
|
|
|
+ break;
|
|
|
+ case '2':
|
|
|
+ //执行规则组
|
|
|
+ if (flowNode.groupIdentify === '') {
|
|
|
+ errs.push(errTxt + '未选择执行规则组');
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case '6':
|
|
|
+ //子流程
|
|
|
+ if (flowNode.childFlowIdentify === '') {
|
|
|
+ errs.push(errTxt + '未选择子流程');
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case '7':
|
|
|
+ //源码节点
|
|
|
+ if (flowNode.methodName === '') {
|
|
|
+ errs.push(errTxt + '未选择方法');
|
|
|
+ } else if (flowNode.hasMethodParams && flowNode.methodParams === '') {
|
|
|
+ errs.push(errTxt + '方法未输入参数');
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else if (nodeData.type === 'polygon') {
|
|
|
+ const errTxt = '条件节点【' + nodeText + '】';
|
|
|
+ //处理条件节点的边
|
|
|
+ let conditionEdges = this.graph.getOutgoingEdges(cells[i].id);
|
|
|
+ console.log('conditionEdges', conditionEdges)
|
|
|
+ if (conditionEdges) {
|
|
|
+ conditionEdges = conditionEdges.filter(item => {
|
|
|
+ return item.source.cell !== item.target.cell;
|
|
|
+ });
|
|
|
+ let trueNum = 0,
|
|
|
+ falseNum = 0;
|
|
|
+ conditionEdges.forEach(item => {
|
|
|
+ console.log('item', item)
|
|
|
+ let labelText = item.store.data.labels ? item.store.data.labels[0].text != undefined ? item.store.data.labels[0].text : item.store.data.labels[0].attrs.label.text : '';
|
|
|
+ if (labelText === '是') {
|
|
|
+ trueNum++;
|
|
|
+ } else if (labelText === '否') {
|
|
|
+ falseNum++;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ if (trueNum < 1) {
|
|
|
+ errs.push(errTxt + '缺少是判断的连线');
|
|
|
+ } else if (trueNum > 1) {
|
|
|
+ errs.push(errTxt + '过多是判断的连线');
|
|
|
+ }
|
|
|
+ if (falseNum < 1) {
|
|
|
+ errs.push(errTxt + '缺少否判断的连线');
|
|
|
+ } else if (falseNum > 1) {
|
|
|
+ errs.push(errTxt + '过多否判断的连线');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ //校验条件表单
|
|
|
+ if (flowNode.flowJudges.length < 1) {
|
|
|
+ errs.push(errTxt + '未选择判断条件');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ alls.push({
|
|
|
+ id: cells[i].id,
|
|
|
+ type: cells[i].attrs.nodeData.type
|
|
|
+ });
|
|
|
+ nodeList.push(cells[i]);
|
|
|
+ } else {
|
|
|
+ //连接线
|
|
|
+ if (cells[i].source.cell !== cells[i].target.cell) {
|
|
|
+ edges.push({
|
|
|
+ source: cells[i].source.cell,
|
|
|
+ target: cells[i].target.cell
|
|
|
+ });
|
|
|
+ }
|
|
|
+ edgeList.push(cells[i]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (startNum !== 1) {
|
|
|
+ errs.push('开始节点必需存在,且仅有一个');
|
|
|
+ }
|
|
|
+ if (endNum !== 1) {
|
|
|
+ errs.push('结束节点必需存在,且仅有一个');
|
|
|
+ }
|
|
|
+
|
|
|
+ let startEdgeErr = false,
|
|
|
+ endEdgeErr = false,
|
|
|
+ edgeErr = false;
|
|
|
+ //遍历所有节点
|
|
|
+ alls.forEach(item => {
|
|
|
+ let hasEdge = false;
|
|
|
+ for (let i = 0, len = edges.length; i < len; i++) {
|
|
|
+ if (item.id === edges[i].source || item.id === edges[i].target) {
|
|
|
+ hasEdge = true;
|
|
|
+ }
|
|
|
+ if (item.type === 'Start') {
|
|
|
+ if (item.id === edges[i].target && !startEdgeErr) {
|
|
|
+ startEdgeErr = true;
|
|
|
+ errs.push('开始节点不能为连线终点');
|
|
|
+ }
|
|
|
+ } else if (item.type === 'End') {
|
|
|
+ if (item.id === edges[i].source && !endEdgeErr) {
|
|
|
+ endEdgeErr = true;
|
|
|
+ errs.push('结束节点不能为连线起点');
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!hasEdge && !edgeErr) {
|
|
|
+ edgeErr = true;
|
|
|
+ errs.push('节点间必需有连接线关联');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ graphToJson,
|
|
|
+ nodeList,
|
|
|
+ edgeList,
|
|
|
+ errs
|
|
|
+ };
|
|
|
+ },
|
|
|
+ //保存流程图
|
|
|
+ saveFlow() {
|
|
|
+ // 先取消所有选中的节点和边, 防止把选中状态一起保存了
|
|
|
+ this.graph.cleanSelection();
|
|
|
+ const { errs, nodeList, edgeList, graphToJson } = this.checkFlow();
|
|
|
+ console.log('nodeList', nodeList)
|
|
|
+ console.log('edgeList', edgeList)
|
|
|
+ console.log('saveData', {
|
|
|
+ nodes: nodeList,
|
|
|
+ edges: edgeList
|
|
|
+ })
|
|
|
+ },
|
|
|
+ //历史状态改变
|
|
|
+ historyChange() {
|
|
|
+ this.canUndo = this.graph.history.canUndo();
|
|
|
+ this.canRedo = this.graph.history.canRedo();
|
|
|
+ },
|
|
|
+ //撤销
|
|
|
+ onUndo() {
|
|
|
+ if (this.disabled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.graph.history.undo();
|
|
|
+ },
|
|
|
+ //重做
|
|
|
+ onRedo() {
|
|
|
+ if (this.disabled) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.graph.history.redo();
|
|
|
+ },
|
|
|
+ getJson() {
|
|
|
+ console.log(this.graph.toJSON());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </script>
|
|
|
+ <style lang="scss" scoped>
|
|
|
+ .graph-drawer-box{
|
|
|
+ display: flex;
|
|
|
+ }
|
|
|
+ </style>
|