vue-workflow-editor
Version:
在线工作流流程图编辑器,vue2+ts,基于G6
394 lines (365 loc) • 17.7 kB
HTML
<html>
<head>
<meta charset="utf-8">
<title>vue-flow-editor demo</title>
<link type="text/css" rel="stylesheet" href="http://martsforever-pot.gitee.io/vue-flow-editor/dist/vue-flow-editor.css">
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<style>
html, body {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
<div id="app">
</div>
<script src="http://martsforever-pot.gitee.io/vue-flow-editor/lib/g6.umd.min.js"></script>
<script src="http://martsforever-pot.gitee.io/vue-flow-editor/lib/vue.min.js"></script>
<script src="http://martsforever-pot.gitee.io/vue-flow-editor/lib/vue-composition-api.umd.js"></script>
<script src="http://martsforever-pot.gitee.io/vue-flow-editor/lib/element-ui.js"></script>
<script src="http://martsforever-pot.gitee.io/vue-flow-editor/dist/vue-flow-editor.js"></script>
<script>;
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
console.log(window);
Vue.use(window.vueCompositionApi.default);
Vue.use(window.VueFlowEditor);
var Ele = window.ELEMENT;
var G6 = window.G6.default;
var reactive = window.vueCompositionApi.reactive;
function delay(time) {
return new Promise(function (resolve) {
return setTimeout(resolve, time);
});
}
var AppData = {
"nodes": [{
"data": {},
"id": "start-node",
"label": "开始",
"shape": "ellipse",
"size": [120, 40],
"x": 380,
"y": 100
}, {
"data": {},
"id": "1588848310120",
"label": "主管审批",
"shape": "rect",
"size": [120, 40],
"x": 380,
"y": 180
}, {
"data": {},
"id": "1588848322179",
"label": "经理审批",
"shape": "rect",
"size": [120, 40],
"x": 380,
"y": 260
}, {
"data": {},
"id": "1588848338211",
"label": "金额>2万",
"shape": "diamond",
"size": [120, 40],
"x": 380,
"y": 340
}, {
"data": {},
"id": "1588848351476",
"label": "财务打款",
"shape": "rect",
"size": [120, 40],
"x": 380,
"y": 460
}, {
"data": {},
"id": "end-node",
"label": "结束",
"shape": "ellipse",
"size": [120, 40],
"x": 380,
"y": 540
}, {
"data": {},
"id": "1588848397511",
"label": "VIP审批",
"shape": "rect",
"size": [120, 40],
"x": 620,
"y": 340
}, {
"data": {},
"id": "1588848436694",
"label": "金额>10万",
"shape": "diamond",
"size": [120, 40],
"x": 780,
"y": 340
}, {
"data": {},
"id": "1588848449431",
"label": "CEO审批",
"shape": "rect",
"size": [120, 40],
"x": 980,
"y": 460
}],
"edges": [{
"shape": "flow-polyline-round",
"source": "start-node",
"sourceAnchor": 2,
"target": "1588848310120",
"targetAnchor": 0
}, {
"shape": "flow-polyline-round",
"source": "1588848310120",
"sourceAnchor": 2,
"target": "1588848322179",
"targetAnchor": 0
}, {
"shape": "flow-polyline-round",
"source": "1588848322179",
"sourceAnchor": 2,
"target": "1588848338211",
"targetAnchor": 0
}, {
"shape": "flow-polyline-round",
"source": "1588848338211",
"sourceAnchor": 2,
"target": "1588848351476",
"targetAnchor": 0,
"label": "否"
}, {
"shape": "flow-polyline-round",
"source": "1588848351476",
"sourceAnchor": 2,
"target": "end-node",
"targetAnchor": 0
}, {
"shape": "flow-polyline-round",
"source": "1588848338211",
"sourceAnchor": 3,
"target": "1588848397511",
"targetAnchor": 1,
"label": "是"
}, {
"shape": "flow-polyline-round",
"source": "1588848436694",
"sourceAnchor": 3,
"target": "1588848449431",
"targetAnchor": 0,
"label": "是"
}, {
"shape": "flow-polyline-round",
"source": "1588848449431",
"sourceAnchor": 1,
"target": "1588848351476",
"targetAnchor": 3
}, {
"shape": "flow-polyline-round",
"source": "1588848436694",
"sourceAnchor": 2,
"target": "1588848351476",
"targetAnchor": 3,
"label": "否"
}, {
"shape": "flow-polyline-round",
"source": "1588848397511",
"sourceAnchor": 3,
"target": "1588848436694",
"targetAnchor": 1
}]
};
new Vue({
el: '#app',
template: "\n <div class=\"app\" style=\"height: 100vh\">\n <vue-flow-editor\n ref=\"editor\"\n :data=\"state.data\"\n :grid=\"showGrid\"\n :miniMap=\"showMiniMap\"\n :onRef=\"onRef\"\n :multipleSelect=\"true\"\n :loading=\"state.editorLoading\"\n\n :disabledUndo=\"false\"\n :disabledDragEdge=\"true\"\n\n :beforeDelete=\"handleBeforeDelete\"\n :afterDelete=\"handleAfterDelete\"\n :beforeAdd=\"handleBeforeAdd\"\n :afterAdd=\"handleAfterAdd\"\n\n @dblclick-node=\"onDblclickNode\"\n @dblclick-edge=\"onDblClickEdge\"\n >\n <div slot=\"menu\">\n <vue-flow-edit-menu-group v-for=\"(group,groupIndex) in state.menuData\" :label=\"group.label\" :key=\"groupIndex\">\n <vue-flow-edit-menu v-for=\"(menu,menuIndex) in group.menus\" :key=\"menuIndex\" :model=\"menu\"/>\n </vue-flow-edit-menu-group>\n </div>\n <div slot=\"model\" style=\"padding: 16px\">\n <el-form v-if=\"!!state.detailModel\" ref=\"form\" :model=\"state.detailModel\" label-width=\"100px\">\n\n <el-form-item label=\"\u8282\u70B9\u540D\u79F0\" prop=\"label\">\n <el-input v-model=\"state.detailModel.label\"/>\n </el-form-item>\n\n <template v-if=\"state.detailModel.type !== 'edge'\">\n <el-form-item label=\"\u8282\u70B9\u80CC\u666F\u8272\" prop=\"style.fill\">\n <el-color-picker v-model=\"state.detailModel.style.fill\"/>\n </el-form-item>\n <el-form-item label=\"\u8282\u70B9\u8FB9\u6846\u8272\" prop=\"style.stroke\">\n <el-color-picker v-model=\"state.detailModel.style.stroke\"/>\n </el-form-item>\n <el-form-item label=\"\u8282\u70B9\u6587\u5B57\u8272\" prop=\"labelCfg.style.stroke\">\n <el-color-picker v-model=\"state.detailModel.labelCfg.style.fill\"/>\n </el-form-item>\n </template>\n\n </el-form>\n </div>\n\n <template slot=\"toolbar\">\n <el-tooltip content=\"\u6D4B\u8BD5\u5DE5\u5177\u680F\u63D2\u69FD\">\n <div class=\"vue-flow-editor-toolbar-item\">\n <i class=\"el-icon-search\"/>\n </div>\n </el-tooltip>\n </template>\n\n <template slot=\"foot\">\n <el-button type=\"primary\" @click=\"save\">\u4FDD\u5B58</el-button>\n <el-button @click=\"cancel\">\u53D6\u6D88</el-button>\n </template>\n </vue-flow-editor>\n </div>\n ",
setup: function setup() {
var state = reactive({
data: AppData,
detailModel: null,
editorLoading: false,
selectOptions: [{
label: '待确认',
value: '0'
}, {
label: '填写表单',
value: '1'
}, {
label: '部门负责人审批',
value: '2'
}, {
label: '总经理审批',
value: '3'
}],
menuData: [{
label: '流程节点',
menus: [{
label: '开始',
shape: 'ellipse',
id: 'start-node'
}, {
label: '结束',
shape: 'ellipse',
id: 'end-node'
}, {
label: '审批节点',
busType: '123'
}, {
label: '判断节点'
}]
}, {
label: '其他形状节点',
menus: [{
label: '矩形节点',
shape: 'rect'
}, {
label: '圆形节点',
shape: 'circle'
}, {
label: '椭圆节点',
shape: 'ellipse'
}, {
label: '菱形节点',
shape: 'diamond'
}, {
label: '三角形节点',
shape: 'triangle'
}, {
label: '星形节点',
shape: 'star'
}]
}]
});
var editor;
function onDblclickNode(e) {
var model = G6.Util.clone(e.item.get('model'));
model.style = model.style || {};
model.labelCfg = model.labelCfg || {
style: {}
};
state.detailModel = model;
editor.openModel();
}
function onDblClickEdge(e) {
var _e$item$get = e.item.get('model'),
source = _e$item$get.source,
target = _e$item$get.target,
style = _e$item$get.style,
labelCfg = _e$item$get.labelCfg,
label = _e$item$get.label;
var model = {
label: label,
source: source,
target: target,
style: style || {},
labelCfg: labelCfg || {
style: {}
},
type: null,
id: null
};
model.type = e.item.get('type');
model.id = e.item.get('id');
state.detailModel = model;
editor.openModel();
}
function cancel() {
editor.closeModel();
}
function save() {
editor.updateModel(state.detailModel);
editor.closeModel();
}
function handleBeforeDelete(_x, _x2) {
return _handleBeforeDelete.apply(this, arguments);
}
function _handleBeforeDelete() {
_handleBeforeDelete = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(model, type) {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (!(type === 'node')) {
_context.next = 8;
break;
}
if (!(model.label === '开始')) {
_context.next = 8;
break;
}
state.editorLoading = true;
_context.next = 5;
return delay(1000);
case 5:
state.editorLoading = false;
Ele.Notification.error('不可以删除【开始】节点');
return _context.abrupt("return", Promise.reject('reject'));
case 8:
case "end":
return _context.stop();
}
}
}, _callee);
}));
return _handleBeforeDelete.apply(this, arguments);
}
function handleAfterDelete(model, type) {
if (type === 'edge') {
console.log('delete edge');
} else {
console.log('after delete', model.label, _objectSpread({}, model));
}
}
function handleBeforeAdd(model, type) {
if (type === 'edge') {
if (model.source === 'end-node') {
Ele.Notification.error('结束节点不能输出连线其他节点');
return Promise.reject('reject');
}
}
if (type === 'node') {
if (model.id === 'start-node' || model.id === 'end-node') {
var data = editor.editorState.graph.save();
for (var i = 0; i < data.nodes.length; i++) {
var node = data.nodes[i];
if (node.id === model.id) {
Ele.Notification.error("\u53EA\u80FD\u6709\u4E00\u4E2A" + (model.id === 'start-node' ? '开始' : '结束') + "\u8282\u70B9");
return Promise.reject('reject');
}
}
}
}
}
function handleAfterAdd(model, type) {
if (type === 'edge') {
console.log("\u65B0\u589E\u8FDE\u63A5\u7EBF");
}
}
return {
state: state,
showGrid: true,
showMiniMap: false,
onDblclickNode: onDblclickNode,
onDblClickEdge: onDblClickEdge,
cancel: cancel,
save: save,
handleBeforeDelete: handleBeforeDelete,
handleAfterDelete: handleAfterDelete,
handleBeforeAdd: handleBeforeAdd,
handleAfterAdd: handleAfterAdd,
onRef: function onRef(e) {
return editor = e;
}
};
}
}).$mount();
</script>
</body>
</html>