├── src
├── App.vue
├── easy-process
│ ├── config
│ │ ├── provide-keys.js
│ │ ├── default-node-type.js
│ │ ├── event-keys.js
│ │ ├── gateway-type.js
│ │ ├── node-component.js
│ │ └── node-config.js
│ ├── assets
│ │ └── icons
│ │ │ ├── ep-subtract.svg
│ │ │ ├── ep-exclusive-gateway.svg
│ │ │ ├── ep-start.svg
│ │ │ ├── ep-close.svg
│ │ │ ├── ep-plus.svg
│ │ │ ├── ep-edit.svg
│ │ │ ├── ep-terminate.svg
│ │ │ ├── ep-left.svg
│ │ │ ├── ep-right.svg
│ │ │ ├── ep-condition.svg
│ │ │ ├── ep-tips.svg
│ │ │ ├── ep-task.svg
│ │ │ ├── ep-gateway.svg
│ │ │ ├── ep-parallel-gateway.svg
│ │ │ └── ep-setting.svg
│ ├── tools
│ │ ├── common-tools.js
│ │ ├── z-index-tools.js
│ │ ├── node-tools.js
│ │ ├── process-ctrl.js
│ │ └── validator.js
│ ├── components
│ │ ├── svg-icon
│ │ │ ├── index.js
│ │ │ └── ep-svg-icon.vue
│ │ ├── button
│ │ │ └── ep-button.vue
│ │ └── drawer
│ │ │ └── ep-drawer.vue
│ ├── node
│ │ ├── end
│ │ │ └── end-node.vue
│ │ ├── node-wrap.vue
│ │ ├── base
│ │ │ ├── base-drawer.vue
│ │ │ ├── add-node.vue
│ │ │ └── base-node.vue
│ │ └── gateway
│ │ │ └── gateway-node.vue
│ ├── index.js
│ └── ep-designer.vue
├── views
│ ├── node
│ │ ├── terminate
│ │ │ └── terminate-node.vue
│ │ ├── start
│ │ │ ├── start-drawer.vue
│ │ │ └── start-node.vue
│ │ ├── notify
│ │ │ ├── notify-drawer.vue
│ │ │ └── notify-node.vue
│ │ ├── task
│ │ │ ├── task-drawer.vue
│ │ │ └── task-node.vue
│ │ └── condition
│ │ │ ├── condition-drawer.vue
│ │ │ └── condition-node.vue
│ ├── test.vue
│ └── index.vue
├── router
│ └── index.js
└── main.js
├── vite
└── plugins
│ ├── setup-extend.js
│ ├── auto-import.js
│ ├── svg-icon.js
│ ├── copy.js
│ ├── index.js
│ └── compression.js
├── .gitignore
├── index.html
├── LICENSE
├── package.json
├── vite.config.js
├── public
└── mock
│ └── data.json
└── README.md
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/vite/plugins/setup-extend.js:
--------------------------------------------------------------------------------
1 | import setupExtend from 'vite-plugin-vue-setup-extend'
2 |
3 | export default function createSetupExtend() {
4 | return setupExtend()
5 | }
6 |
--------------------------------------------------------------------------------
/src/easy-process/config/provide-keys.js:
--------------------------------------------------------------------------------
1 | // 依赖注入数据的key
2 |
3 | // 流程控制器KEY
4 | export const KEY_PROCESS_CTRL = 'processCtrl'
5 |
6 | // 节点验证器KEY
7 | export const KEY_VALIDATOR = 'validator'
8 |
9 | // 流程数据KEY
10 | export const KEY_PROCESS_DATA = 'processData'
--------------------------------------------------------------------------------
/src/easy-process/config/default-node-type.js:
--------------------------------------------------------------------------------
1 | // 网关节点
2 | export const GATEWAY = 'gateway'
3 | // 条件节点
4 | export const CONDITION = 'condition'
5 | // 开始节点
6 | export const START = 'start'
7 | // 任务节点
8 | export const TASK = 'task'
9 | // 终止节点
10 | export const TERMINATE = 'terminate'
11 |
12 |
--------------------------------------------------------------------------------
/vite/plugins/auto-import.js:
--------------------------------------------------------------------------------
1 | import autoImport from 'unplugin-auto-import/vite'
2 |
3 | export default function createAutoImport() {
4 | return autoImport({
5 | imports: [
6 | 'vue',
7 | 'vue-router',
8 | 'pinia'
9 | ],
10 | dts: false
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | dist-lib
14 | *.local
15 |
16 |
17 | # Editor directories and files
18 | .vscode/*
19 | !.vscode/extensions.json
20 | .idea
21 | .DS_Store
22 | *.suo
23 | *.ntvs*
24 | *.njsproj
25 | *.sln
26 | *.sw?
27 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Easy Process
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-subtract.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/tools/common-tools.js:
--------------------------------------------------------------------------------
1 | import {v4 as uuidv4 } from 'uuid'
2 |
3 | /**
4 | * 获取UUID
5 | * @returns {*}
6 | */
7 | export const getUUID = () =>{
8 | return uuidv4()
9 | }
10 |
11 | /**
12 | * 复制对象(深拷贝)
13 | * @param source
14 | */
15 | export const copy = (source) => {
16 | if(source) {
17 | const str = JSON.stringify(source);
18 | return JSON.parse(str);
19 | }
20 | return null;
21 | }
--------------------------------------------------------------------------------
/vite/plugins/svg-icon.js:
--------------------------------------------------------------------------------
1 | import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
2 | import path from 'path'
3 |
4 | export default function createSvgIcon(isBuild) {
5 | return createSvgIconsPlugin({
6 | iconDirs: [path.resolve(process.cwd(), 'src/easy-process/assets/icons')],
7 | symbolId: 'icon-[dir]-[name]',
8 | customDomId: '__EASY_PROCESS_SVG_ICONS__',
9 | svgoOptions: isBuild
10 | })
11 | }
12 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-exclusive-gateway.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/components/svg-icon/index.js:
--------------------------------------------------------------------------------
1 | let iconPrefix = '#icon-'
2 |
3 |
4 | /**
5 | * 加载图标配置
6 | * @param iconConfig
7 | */
8 | export const loadIconConfig = (iconConfig) => {
9 | let {prefix} = iconConfig || {}
10 | setIconPrefix(prefix)
11 | }
12 |
13 | /**
14 | * 设置图标前缀
15 | * @param prefix
16 | */
17 | const setIconPrefix = (prefix) => {
18 | if (prefix) {
19 | iconPrefix = prefix
20 | }
21 | }
22 |
23 | /**
24 | * 获取图标前缀
25 | * @returns {string}
26 | */
27 | export const getIconPrefix = () => {
28 | return iconPrefix
29 | }
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-start.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/config/event-keys.js:
--------------------------------------------------------------------------------
1 | // 绑定事件的key
2 |
3 | // 设计器加载完毕KEY
4 | export const ON_DESIGNER_MOUNTED = 'on_designer_mounted'
5 | // 新增节点之前KEY
6 | export const ON_PRE_ADD_NODE = 'on_pre_add_node'
7 | // 新增节点之后KEY
8 | export const ON_AFTER_ADD_NODE = 'on_after_add_node'
9 | // 移除节点之前KEY
10 | export const ON_PRE_REMOVE_NODE = 'on_pre_remove_node'
11 | // 移除节点之后KEY
12 | export const ON_AFTER_REMOVE_NODE = 'on_after_remove_node'
13 | // 更新节点配置之前KEY
14 | export const ON_PRE_UPDATE_NODE_CONFIG = 'on_pre_update_node_config'
15 | // 更新节点配置之后KEY
16 | export const ON_AFTER_UPDATE_NODE_CONFIG = 'on_after_update_node_config'
17 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/node/terminate/terminate-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 流程驳回
5 |
6 |
7 |
8 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/vite/plugins/copy.js:
--------------------------------------------------------------------------------
1 | import copy from 'rollup-plugin-copy'
2 |
3 | export default function createCopy() {
4 | return copy({
5 | hook: 'closeBundle',
6 | targets: [
7 | { src: 'src/easy-process/assets/*', dest: 'dist/assets' },
8 | { src: 'src/easy-process/config/event-keys.js', dest: 'dist/config' },
9 | { src: 'src/easy-process/config/gateway-type.js', dest: 'dist/config' },
10 | { src: 'src/easy-process/config/default-node-type.js', dest: 'dist/config' },
11 | { src: 'src/easy-process/config/provide-keys.js', dest: 'dist/config' },
12 | ]
13 | })
14 | }
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/node/start/start-drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 发起人:
5 |
6 |
7 |
8 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/src/views/node/notify/notify-drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 抄送人:
5 |
6 |
7 |
8 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/src/views/node/task/task-drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 审核人:
5 |
6 |
7 |
8 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/src/views/node/condition/condition-drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 请假天数<
5 |
6 |
7 |
8 |
24 |
25 |
28 |
--------------------------------------------------------------------------------
/vite/plugins/index.js:
--------------------------------------------------------------------------------
1 | import vue from '@vitejs/plugin-vue'
2 |
3 | import createAutoImport from './auto-import'
4 | import createSvgIcon from './svg-icon'
5 | import createCompression from './compression'
6 | import createSetupExtend from './setup-extend'
7 | import createCopy from './copy'
8 |
9 | export default function createVitePlugins(viteEnv, isBuild = false) {
10 | const vitePlugins = [vue()]
11 | vitePlugins.push(createAutoImport())
12 | vitePlugins.push(createSetupExtend())
13 | vitePlugins.push(createSvgIcon(isBuild))
14 | vitePlugins.push(createCopy())
15 | isBuild && vitePlugins.push(...createCompression(viteEnv))
16 | return vitePlugins
17 | }
18 |
--------------------------------------------------------------------------------
/src/easy-process/config/gateway-type.js:
--------------------------------------------------------------------------------
1 | const EXCLUSIVE = 'exclusive'
2 | const PARALLEL = 'parallel'
3 |
4 | const GATEWAY_TYPE_LIST = [
5 | {
6 | type: EXCLUSIVE,
7 | name: '排他网关',
8 | icon: 'ep-exclusive-gateway',
9 | desc: '按照分支顺序(从左向右)进行计算,选择第一个条件计算为true的分支继续流程,未设置条件时默认通过。'
10 | },
11 | {
12 | type: PARALLEL,
13 | name: '并行网关',
14 | icon: 'ep-parallel-gateway',
15 | desc: '计算所有分支条件,符合条件的分支可并列执行,未设置条件时默认通过。'
16 | }
17 | ]
18 |
19 | const GATEWAY_TYPE_MAP = new Map()
20 | GATEWAY_TYPE_LIST.forEach(item => {
21 | GATEWAY_TYPE_MAP.set(item.type, item)
22 | })
23 |
24 | export {GATEWAY_TYPE_LIST, GATEWAY_TYPE_MAP, EXCLUSIVE, PARALLEL}
25 |
26 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-edit.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/tools/z-index-tools.js:
--------------------------------------------------------------------------------
1 | let zIndex = 2000
2 | let zIndexFunction = null
3 |
4 | /**
5 | * 加载zIndex配置
6 | */
7 | export const loadZIndexConfig = ({initZIndexValue, bindZIndexFunction}) => {
8 | if (bindZIndexFunction) {
9 | if (typeof bindZIndexFunction === 'function') {
10 | zIndexFunction = bindZIndexFunction
11 | } else {
12 | throw new Error('zIndexFunction must be a function')
13 | }
14 | } else if (initZIndexValue) {
15 | zIndex = initZIndexValue
16 | }
17 | }
18 |
19 | /**
20 | * 获取下一个zIndex
21 | */
22 | export const nextZIndex = () => {
23 | if (zIndexFunction && typeof zIndexFunction === 'function') {
24 | return zIndexFunction()
25 | }
26 | return zIndex++;
27 | }
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-terminate.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import { createWebHistory, createRouter } from 'vue-router'
2 |
3 | // 公共路由
4 | export const constantRoutes = [
5 | {
6 | path: '',
7 | redirect: '/index',
8 | children: [
9 | {
10 | path: '/index',
11 | component: () => import('@/views/index'),
12 | name: 'Index'
13 | }
14 | ]
15 | },
16 | {
17 | path: '/test',
18 | children: [
19 | {
20 | path: '/test',
21 | component: () => import('@/views/test'),
22 | name: 'Test'
23 | }
24 | ]
25 | },
26 | ]
27 |
28 | const router = createRouter({
29 | history: createWebHistory(),
30 | routes: constantRoutes,
31 | scrollBehavior(to, from, savedPosition) {
32 | if (savedPosition) {
33 | return savedPosition
34 | } else {
35 | return { top: 0 }
36 | }
37 | },
38 | });
39 |
40 | export default router;
41 |
--------------------------------------------------------------------------------
/src/views/node/start/start-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 发起人: {{node.config.name}}
5 |
6 |
7 |
8 |
34 |
35 |
38 |
--------------------------------------------------------------------------------
/src/views/node/notify/notify-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 抄送人: {{node.config.name}}
5 |
6 |
7 |
8 |
34 |
35 |
38 |
--------------------------------------------------------------------------------
/src/views/node/task/task-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 审批人: {{node.config.name}}
5 |
6 |
7 |
8 |
34 |
35 |
38 |
--------------------------------------------------------------------------------
/src/easy-process/tools/node-tools.js:
--------------------------------------------------------------------------------
1 | import {nodeConfig} from '../config/node-config.js'
2 | import {START, GATEWAY, CONDITION} from '../config/default-node-type.js'
3 | import {getUUID} from '../tools/common-tools.js'
4 |
5 | /**
6 | * 创建节点
7 | * @param nodeType
8 | */
9 | export const createNode = (nodeType = START) => {
10 | let config = nodeConfig[nodeType]
11 | let node = generateNodeObj(config)
12 | if (nodeType === GATEWAY) {
13 | let conditionConfig = nodeConfig[CONDITION]
14 | node.branchList = [generateNodeObj(conditionConfig), generateNodeObj(conditionConfig)]
15 | }
16 | return node
17 | }
18 |
19 | const generateNodeObj = (config) => {
20 | return {
21 | // 生成临时节点ID
22 | tmpNodeId: getUUID(),
23 | nodeName: config.nodeName,
24 | nodeType: config.nodeType,
25 | config: config.config || {},
26 | childNode: null
27 | }
28 | }
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-condition.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vite/plugins/compression.js:
--------------------------------------------------------------------------------
1 | import compression from 'vite-plugin-compression'
2 |
3 | export default function createCompression(env) {
4 | const { VITE_BUILD_COMPRESS } = env
5 | const plugin = []
6 | if (VITE_BUILD_COMPRESS) {
7 | const compressList = VITE_BUILD_COMPRESS.split(',')
8 | if (compressList.includes('gzip')) {
9 | // #使用gzip解压缩静态文件
10 | plugin.push(
11 | compression({
12 | ext: '.gz',
13 | deleteOriginFile: false
14 | })
15 | )
16 | }
17 | if (compressList.includes('brotli')) {
18 | plugin.push(
19 | compression({
20 | ext: '.br',
21 | algorithm: 'brotliCompress',
22 | deleteOriginFile: false
23 | })
24 | )
25 | }
26 | }
27 | return plugin
28 | }
29 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-tips.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/components/svg-icon/ep-svg-icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
34 |
35 |
44 |
--------------------------------------------------------------------------------
/src/easy-process/node/end/end-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
29 |
30 |
50 |
--------------------------------------------------------------------------------
/src/views/test.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
34 |
35 |
42 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-task.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 gaoyang
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/views/node/condition/condition-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 请假天数<{{node.config.days}}天
6 |
7 |
8 | 未设置条件
9 |
10 |
11 |
12 |
13 |
14 |
47 |
48 |
53 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "qx-easy-process",
3 | "private": false,
4 | "version": "3.0.10",
5 | "type": "module",
6 | "description": "easy-process流程设计器,基于vue3 + vite4实现,具备低代码、快速应用及扩展的特点。【工作流】【流程引擎】",
7 | "keywords": [
8 | "process",
9 | "process designer",
10 | "qx-easy-process",
11 | "流程引擎",
12 | "流程设计器",
13 | "工作流"
14 | ],
15 | "main": "dist/easy-process.umd.js",
16 | "module": "dist/easy-process.es.js",
17 | "files": [
18 | "dist"
19 | ],
20 | "license": "MIT",
21 | "author": {
22 | "name": "GaoYang",
23 | "email": "331607151@qq.com"
24 | },
25 | "scripts": {
26 | "dev": "vite",
27 | "build": "vite build",
28 | "preview": "vite preview"
29 | },
30 | "dependencies": {
31 | "fast-glob": "^3.3.3",
32 | "less": "^4.1.3",
33 | "less-loader": "^11.1.0",
34 | "uuid": "^9.0.0",
35 | "vue": "^3.2.47",
36 | "vue-router": "4.1.4"
37 | },
38 | "devDependencies": {
39 | "@vitejs/plugin-vue": "^4.1.0",
40 | "sass": "1.56.1",
41 | "unplugin-auto-import": "0.11.4",
42 | "vite": "^4.3.9",
43 | "vite-plugin-compression": "0.5.1",
44 | "vite-plugin-svg-icons": "2.0.1",
45 | "vite-plugin-vue-setup-extend": "0.4.0",
46 | "rollup-plugin-copy": "^3.5.0"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/easy-process/tools/process-ctrl.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * 流程控制器
4 | * @returns {{}}
5 | */
6 | export const createProcessCtrl = () => {
7 | let ctrl = {};
8 | // 节点信息
9 | ctrl.nodes = new Map()
10 | // 事件绑定
11 | ctrl.events = new Map()
12 |
13 | // 添加节点
14 | ctrl.addNode = (nodeId, nodeConfig) => {
15 | ctrl.nodes.set(nodeId, nodeConfig)
16 | }
17 |
18 | // 获取节点
19 | ctrl.getNode = (nodeId) => {
20 | return ctrl.nodes.get(nodeId)
21 | }
22 |
23 | // 移除节点
24 | ctrl.removeNode = (nodeId) => {
25 | ctrl.nodes.delete(nodeId)
26 | }
27 |
28 | // 绑定事件
29 | ctrl.bindEvent = (key, callback) => {
30 | if (key && callback && typeof callback === 'function') {
31 | ctrl.events.set(key, callback)
32 | }
33 | }
34 |
35 | // 解除绑定事件
36 | ctrl.unbindEvent = (key) => {
37 | ctrl.events.delete(key)
38 | }
39 |
40 | // 获取绑定事件
41 | ctrl.getBindEvent = (key) => {
42 | return ctrl.events.get(key)
43 | }
44 | // 触发事件
45 | ctrl.triggerEvent = (key, params) => {
46 | let f = ctrl.getBindEvent(key)
47 | if (f) {
48 | return f(params)
49 | }
50 | return null
51 | }
52 | // 触发事件结果是否为真
53 | ctrl.eventReturnIsTrue = (result) => {
54 | if (typeof result === 'boolean') {
55 | return result
56 | }
57 | return true
58 | }
59 |
60 | return ctrl
61 | }
62 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-gateway.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/config/node-component.js:
--------------------------------------------------------------------------------
1 | import { shallowRef, defineAsyncComponent } from 'vue'
2 | export const nodeComponents = shallowRef({});
3 | export const drawerComponents = shallowRef({});
4 |
5 | const nodePattern = /([^/]+)-node\.vue$/i
6 | const drawerPattern = /([^/]+)-drawer\.vue$/i
7 |
8 | export const initNodes = (extNodes) => {
9 | // 加载本地节点组件
10 | initComponents(import.meta.glob('../node/*/*.vue'))
11 | // 加载扩展节点组件
12 | if (extNodes) {
13 | initComponents(extNodes)
14 | }
15 | }
16 |
17 | const initComponents = (components) => {
18 | Object.keys(components).forEach(key => {
19 | loadNodeComponents(components, key);
20 | loadDrawerComponents(components, key);
21 | })
22 | }
23 |
24 | const loadNodeComponents = (components, key) => {
25 | let nodeType = getNodeType(nodePattern, key)
26 | if (nodeType) {
27 | let component = components[key]
28 | nodeComponents.value[nodeType] = defineAsyncComponent(component)
29 | }
30 | }
31 | const loadDrawerComponents = (components, key) => {
32 | let nodeType = getNodeType(drawerPattern, key)
33 | if (nodeType) {
34 | let component = components[key]
35 | drawerComponents.value[nodeType] = defineAsyncComponent(component)
36 | }
37 | }
38 |
39 | const getNodeType = (pattern, path) => {
40 | let result = pattern.exec(path)
41 | if (result !== null) {
42 | return result[1]
43 | }
44 | return null
45 | }
46 |
47 | export const getNodeComponent = () => {
48 |
49 | }
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-parallel-gateway.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/tools/validator.js:
--------------------------------------------------------------------------------
1 | import { reactive } from "vue";
2 | export const createValidator = () => {
3 | let validator = {};
4 | validator.nodeRules = new Map()
5 | validator.results = reactive(new Map())
6 |
7 | // 注册节点验证规则
8 | validator.register = (nodeId, validatorFun) => {
9 | if(validatorFun && validatorFun instanceof Function) {
10 | validator.nodeRules.set(nodeId, validatorFun)
11 | }
12 | }
13 |
14 | // 移除节点验证规则
15 | validator.remove = (nodeId) => {
16 | validator.nodeRules.delete(nodeId)
17 | validator.results.delete(nodeId)
18 | }
19 |
20 | // 验证节点
21 | validator.validate = () => {
22 | let valid = true
23 | let messages = []
24 | validator.nodeRules.forEach((value, key) => {
25 | let fun = value
26 | if(fun && fun instanceof Function) {
27 | let result = fun()
28 | if(!result.valid) {
29 | valid = false
30 | validator.results.set(key, result)
31 | messages.push(result.message)
32 | } else {
33 | validator.results.delete(key)
34 | }
35 | }
36 | })
37 | return {valid, messages}
38 | }
39 |
40 | // 获取指定节点的结果
41 | validator.getResult = (nodeId) => {
42 | let result = validator.results.get(nodeId)
43 | if(result) {
44 | return result
45 | }
46 | }
47 |
48 | return validator
49 | }
50 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 | import router from './router'
4 |
5 | // svg图标
6 | import 'virtual:svg-icons-register'
7 | // easy-process
8 | import ProcessDesigner from '@/easy-process/index'
9 |
10 | const app = createApp(App)
11 | app.use(router)
12 | app.use(ProcessDesigner, {
13 | nodeImplPath: import.meta.glob('@/views/node/**'),
14 | nodeConfig: [
15 | {
16 | "nodeType": "start",
17 | "nodeName": "发起人",
18 | "config": {
19 | name: '张三'
20 | },
21 | },
22 | {
23 | "nodeType": "task",
24 | "nodeName": "审批人",
25 | },
26 | {
27 | "nodeType": "terminate",
28 | "hasDrawer": false, // 禁用节点配置功能
29 | },
30 | {
31 | "nodeType": "notify",
32 | "nodeName": "抄送",
33 | "color": "#FFFFFF", // 节点标题颜色
34 | "bgColor": "#8225e4", // 节点标题背景颜色
35 | "hasDrawer": true, // 节点是否可以进行配置
36 | "icon": { // 图标
37 | "name": "ep-terminate", // 图标名
38 | "color": "#8225e4" // 颜色
39 | },
40 | "config": {
41 | name: '主管'
42 | },
43 | }
44 | ],
45 | zIndexConfig: {
46 | initZIndexValue: 1000,
47 | bindZIndexFunction: () => {
48 | if (!window.zIndex) {
49 | window.zIndex = 500
50 | }
51 | return window.zIndex++
52 | }
53 | },
54 | iconConfig: {
55 | prefix: '#icon-'
56 | }
57 | })
58 | app.mount('#app')
59 |
--------------------------------------------------------------------------------
/src/easy-process/components/button/ep-button.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
--------------------------------------------------------------------------------
/src/easy-process/index.js:
--------------------------------------------------------------------------------
1 | import {initNodes} from './config/node-component.js'
2 | import {loadNodeConfig} from './config/node-config.js'
3 | import {loadZIndexConfig} from './tools/z-index-tools.js'
4 | import {loadIconConfig} from './components/svg-icon/index.js'
5 |
6 | const requireGlobalComponent = import.meta.glob([
7 | './ep-designer.vue',
8 | './components/svg-icon/ep-svg-icon.vue',
9 | ], { eager: true });
10 |
11 | /**
12 | * 安装组件
13 | * @param app
14 | * @param options
15 | */
16 | const install = (app, options) => {
17 | console.log("run install")
18 | if (install.installed) {
19 | return;
20 | }
21 |
22 | install.installed;
23 |
24 | // 加载配置
25 | loadOptions(app, options)
26 |
27 | //注册全局组件
28 | registerGlobalComponent(app, options);
29 |
30 | };
31 |
32 | /**
33 | * 注册全局组件
34 | * @param app
35 | * @param options
36 | */
37 | const registerGlobalComponent = (app, options) => {
38 | Object.keys(requireGlobalComponent).forEach((fileName) => {
39 | const component = requireGlobalComponent[fileName];
40 | //获取组件名
41 | const componentName = component.default.name;
42 | app.component(componentName, component.default || component);
43 | });
44 | }
45 |
46 | /**
47 | * 加载配置
48 | * @param app
49 | * @param options
50 | */
51 | const loadOptions = (app, options) => {
52 | let {nodeImplPath, nodeConfig, zIndexConfig, iconConfig} = options;
53 | // 加载节点组件
54 | initNodes(nodeImplPath)
55 | // 加载节点配置
56 | loadNodeConfig(nodeConfig)
57 | // 加载z-index配置
58 | loadZIndexConfig(zIndexConfig)
59 | // 加载图标配置
60 | loadIconConfig(iconConfig)
61 | }
62 |
63 | //环境检测
64 | if (typeof window !== "undefined" && window.Vue) {
65 | install(window.Vue);
66 | }
67 |
68 | //对外暴露install方法
69 | export default {
70 | install,
71 | }
--------------------------------------------------------------------------------
/src/easy-process/node/node-wrap.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
67 |
68 |
71 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig, loadEnv } from 'vite'
2 | import path from 'path'
3 | import createVitePlugins from './vite/plugins'
4 |
5 | // https://vitejs.dev/config/
6 | export default defineConfig(({ mode, command }) => {
7 | const env = loadEnv(mode, process.cwd())
8 | const { VITE_APP_ENV } = env
9 | return {
10 | // 部署生产环境和开发环境下的URL。
11 | // 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
12 | // 例如 https://www.quxiou.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.quxiou.vip/admin/,则设置 baseUrl 为 /admin/。
13 | base: '/',
14 | plugins: createVitePlugins(env, command === 'build'),
15 | build: {
16 | outDir: "dist", // 打包输出目录
17 | lib: {
18 | // 指定库入口文件
19 | entry: path.resolve(__dirname, "src/easy-process/index.js"),
20 | // 指定库的名称
21 | name: "easy-process",
22 | fileName: (format) => `easy-process.${format}.js` // 输出文件名格式化函数。例如,'my-vue-plugin.es.js' 和 'my-vue-plugin.umd.js'。
23 | },
24 | rollupOptions: {
25 | external: ["vue"], // 防止将vue打包进库
26 | output: {
27 | globals: {
28 | vue: "Vue",
29 | },
30 | assetFileNames: (assetInfo) => {
31 | if (assetInfo.name.endsWith(".css")) {
32 | return "css/[name][extname]";
33 | }
34 | return "[name].[hash][extname]";
35 | },
36 | },
37 | },
38 | },
39 | resolve: {
40 | // https://cn.vitejs.dev/config/#resolve-alias
41 | alias: {
42 | // 设置路径
43 | '~': path.resolve(__dirname, './'),
44 | // 设置别名
45 | '@': path.resolve(__dirname, './src')
46 | },
47 | // https://cn.vitejs.dev/config/#resolve-extensions
48 | extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
49 | },
50 | // vite 相关配置
51 | server: {
52 | port: 80,
53 | host: true,
54 | open: true,
55 | },
56 | optimizeDeps: {
57 | exclude: ["fsevents"],
58 | },
59 | //fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
60 | css: {
61 | postcss: {
62 | plugins: [
63 | {
64 | postcssPlugin: 'internal:charset-removal',
65 | AtRule: {
66 | charset: (atRule) => {
67 | if (atRule.name === 'charset') {
68 | atRule.remove();
69 | }
70 | }
71 | }
72 | }
73 | ]
74 | }
75 | }
76 | }
77 | })
78 |
--------------------------------------------------------------------------------
/public/mock/data.json:
--------------------------------------------------------------------------------
1 | {
2 | "nodeConfig": {
3 | "tmpNodeId": "ab173ea9-d776-4b8a-8e84-ee6d6fe07b44",
4 | "nodeName": "发起人",
5 | "nodeType": "start",
6 | "config": {
7 | "name": "张三"
8 | },
9 | "childNode": {
10 | "tmpNodeId": "1632f624-8b04-4b62-93fc-7cef5b124189",
11 | "nodeName": "网关",
12 | "nodeType": "gateway",
13 | "config": { },
14 | "childNode": {
15 | "tmpNodeId": "c4787616-3666-406e-bb10-75eca8a72a86",
16 | "nodeName": "抄送",
17 | "nodeType": "notify",
18 | "config": {
19 | "name": "HR"
20 | },
21 | "childNode": null
22 | },
23 | "branchList": [
24 | {
25 | "tmpNodeId": "f34a892f-e3a5-4503-ac95-fadf8f72cd20",
26 | "nodeName": "条件",
27 | "nodeType": "condition",
28 | "config": {
29 | "days": "3"
30 | },
31 | "childNode": {
32 | "tmpNodeId": "6af25285-ad47-4b19-ba20-401d5660a49b",
33 | "nodeName": "审批人",
34 | "nodeType": "task",
35 | "config": {
36 | "name": "项目经理"
37 | },
38 | "childNode": null
39 | }
40 | },
41 | {
42 | "tmpNodeId": "46c9248b-64b4-491e-848c-b208ebb09d18",
43 | "nodeName": "条件",
44 | "nodeType": "condition",
45 | "config": {
46 | "days": "5"
47 | },
48 | "childNode": {
49 | "tmpNodeId": "3e83d699-7f9d-4814-83de-f073f05f0e7a",
50 | "nodeName": "审批人",
51 | "nodeType": "task",
52 | "config": {
53 | "name": "项目经理"
54 | },
55 | "childNode": {
56 | "tmpNodeId": "0d17edf9-1acb-4b35-a1a8-a049c0dea37d",
57 | "nodeName": "审批人",
58 | "nodeType": "task",
59 | "config": {
60 | "name": "总监"
61 | },
62 | "childNode": null
63 | }
64 | }
65 | },
66 | {
67 | "tmpNodeId": "80569c58-6b66-4bfc-bb4b-cee6ca376650",
68 | "nodeName": "条件",
69 | "nodeType": "condition",
70 | "config": { },
71 | "childNode": {
72 | "tmpNodeId": "8d0f7822-36df-49b0-8dcd-19d11fce6429",
73 | "nodeName": "终止",
74 | "nodeType": "terminate",
75 | "config": { },
76 | "childNode": null
77 | }
78 | }
79 | ],
80 | "gatewayType": "exclusive"
81 | }
82 | }
83 | }
--------------------------------------------------------------------------------
/src/easy-process/node/base/base-drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 取消
9 | 确定
10 |
11 |
12 |
13 |
14 |
80 |
81 |
87 |
--------------------------------------------------------------------------------
/src/views/index.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
82 |
83 |
124 |
--------------------------------------------------------------------------------
/src/easy-process/config/node-config.js:
--------------------------------------------------------------------------------
1 | import { GATEWAY, CONDITION, START, TASK, TERMINATE } from "./default-node-type.js"
2 | import {copy} from "@/easy-process/tools/common-tools.js";
3 |
4 | // 节点配置
5 | const nodeConfig = {}
6 |
7 | // 路由节点配置
8 | nodeConfig[GATEWAY] = {
9 | "nodeType": GATEWAY,
10 | "nodeName": "网关", // 节点标题
11 | "enable": true, // 节点是否可用
12 | "canAdd": true, // 节点是否可以增加
13 | "hasDrawer": false, // 节点是否可以进行配置
14 | "icon": { // 图标
15 | "name": "ep-gateway", // 图标名
16 | "color": "#3CB371" // 颜色
17 | },
18 | "branchList": []
19 | }
20 |
21 | // 条件节点配置
22 | nodeConfig[CONDITION] = {
23 | "nodeType": CONDITION,
24 | "nodeName": "条件", // 节点标题
25 | "color": "#FFFFFF", // 节点标题颜色
26 | "bgColor": "#3CB371", // 节点标题背景颜色
27 | "enable": true, // 节点是否可用
28 | "canAdd": false, // 节点是否可以增加
29 | "canRemoved": true, // 节点是否能够移除
30 | "hasDrawer": true, // 节点是否可以进行配置
31 | "icon": { // 图标
32 | "name": "ep-condition", // 图标名
33 | "color": "#3CB371" // 颜色
34 | }
35 | }
36 |
37 | // 开始节点配置
38 | nodeConfig[START] = {
39 | "nodeType": START,
40 | "nodeName": "开始", // 节点标题
41 | "color": "#FFFFFF", // 节点标题颜色
42 | "bgColor": "#1e83e9", // 节点标题背景颜色
43 | "enable": true, // 节点是否可用
44 | "canAdd": false, // 节点是否可以增加
45 | "canRemoved": false, // 节点是否能够移除
46 | "hasDrawer": true, // 节点是否可以进行配置
47 | "icon": { // 图标
48 | "name": "ep-start", // 图标名
49 | "color": "#1e83e9" // 颜色
50 | }
51 | }
52 |
53 | // 任务节点配置
54 | nodeConfig[TASK] = {
55 | "nodeType": TASK,
56 | "nodeName": "任务", // 节点标题
57 | "color": "#FFFFFF", // 节点标题颜色
58 | "bgColor": "#FF8C00", // 节点标题背景颜色
59 | "enable": true, // 节点是否可用
60 | "canAdd": true, // 节点是否可以增加
61 | "canRemoved": true, // 节点是否能够移除
62 | "hasDrawer": true, // 节点是否可以进行配置
63 | "icon": { // 图标
64 | "name": "ep-task", // 图标名
65 | "color": "#FF8C00" // 颜色
66 | }
67 | }
68 |
69 | // 终止节点配置
70 | nodeConfig[TERMINATE] = {
71 | "nodeType": TERMINATE,
72 | "nodeName": "终止", // 节点标题
73 | "color": "#FFFFFF", // 节点标题颜色
74 | "bgColor": "#F56C6C", // 节点标题背景颜色
75 | "enable": true, // 节点是否可用
76 | "canAdd": true, // 节点是否可以增加
77 | "canRemoved": true, // 节点是否能够移除
78 | "hasDrawer": true, // 节点是否可以进行配置
79 | "icon": { // 图标
80 | "name": "ep-terminate", // 图标名
81 | "color": "#F56C6C" // 颜色
82 | }
83 | }
84 |
85 | /**
86 | * 加载节点配置
87 | * @param externalConfig
88 | */
89 | const loadNodeConfig = (externalConfig) => {
90 | if (externalConfig && externalConfig.length > 0) {
91 | externalConfig.forEach(item => {
92 | if (!item.nodeType) {
93 | throw new Error('加载自定义配置:nodeType节点类型不能为空')
94 | }
95 | if (!nodeConfig[item.nodeType] && !item.nodeName) {
96 | throw new Error('加载自定义配置:nodeName节点类型不能为空')
97 | }
98 | let node = nodeConfig[item.nodeType] || copy(nodeDefaultValue)
99 | nodeConfig[item.nodeType] = { ...node, ...item}
100 | })
101 | }
102 | }
103 |
104 | // 默认节点值
105 | const nodeDefaultValue = {
106 | "enable": true, // 节点是否可用
107 | "color": "#FFFFFF", // 节点标题颜色
108 | "bgColor": "#8225e4", // 节点标题背景颜色
109 | "canAdd": true, // 节点是否可以增加
110 | "canRemoved": true, // 节点是否能够移除
111 | "hasDrawer": true, // 节点是否可以进行配置
112 | "icon": { // 图标
113 | "name": "task", // 图标名
114 | "color": "#8225e4" // 颜色
115 | }
116 | }
117 |
118 | export {nodeConfig, loadNodeConfig}
--------------------------------------------------------------------------------
/src/easy-process/components/drawer/ep-drawer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
84 |
85 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Easy Process V3
2 | Easy Process 流程设计器,基于vue3 + vite4 实现,提供易用的流程管理框架和组件,支持快速集成与定制,适用于多种应用场景。
3 |
4 |
5 | ## 开源许可协议
6 | - MIT
7 |
8 |
9 | ## 体验入口
10 | [http://process.uncode.vip](http://process.uncode.vip)
11 |
12 |
13 |
14 | ## 传送门
15 | **项目源码:**[easy-process](https://gitee.com/quxiu-code/easy-process)
16 |
17 | **示例源码:**[easy-process-demo](https://gitee.com/quxiu-code/easy-process-demo)
18 |
19 | **使用手册:** [http://docs.process.uncode.vip](http://docs.process.uncode.vip)
20 |
21 |
22 | ## 开发环境
23 |
24 | ```
25 | Node >= 14
26 | ```
27 |
28 | ## 技术选型
29 |
30 | - vue3
31 | - vite4
32 |
33 |
34 |
35 | ## 安装
36 |
37 |
38 |
39 | ### 安装qx-easy-process
40 |
41 | ```shell
42 | npm install qx-easy-process
43 | ```
44 |
45 |
46 |
47 | ### 安装vite-plugin-svg-icons
48 |
49 | ```shell
50 | npm install vite-plugin-svg-icons -D
51 | ```
52 |
53 |
54 |
55 |
56 |
57 | ## 快速开始
58 |
59 | ### 导入组件
60 |
61 | ```js
62 | // main.js
63 | import { createApp } from 'vue'
64 | import App from './App.vue'
65 |
66 | // easy-process
67 | import EasyProcess from 'qx-easy-process'
68 | import 'qx-easy-process/dist/css/style.css'
69 |
70 | // svg图标
71 | import 'virtual:svg-icons-register'
72 |
73 | const app = createApp(App)
74 |
75 | app.use(EasyProcess, {
76 | // 指定节点视图实现和节点配置实现目录
77 | nodeImplPath: import.meta.glob('src/views/node/**')
78 | })
79 | app.mount('#app')
80 | ```
81 |
82 |
83 |
84 | ### 配置vite-plugin-svg-icons
85 |
86 | ```js
87 | // vite.config.js
88 | import { defineConfig } from 'vite';
89 | import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
90 | import path from 'path';
91 |
92 | export default defineConfig({
93 | plugins: [
94 | createSvgIconsPlugin({
95 | // 指定qx-easy-process图标文件夹
96 | iconDirs: [path.resolve(process.cwd(), 'node_modules/qx-easy-process/dist/assets/icons')],
97 | // 指定symbolId格式
98 | symbolId: 'icon-[dir]-[name]',
99 | })
100 | ],
101 | });
102 | ```
103 |
104 |
105 |
106 | ### 实现节点组件
107 |
108 | 为了提高可扩展性,内置的各类型节点仅是定义了其存在,并未实现节点在流程设计器中展示的内容及配置内容,需要使用者自行实现。
109 |
110 | 注意:**网关节点** 为内置逻辑组件不需要对其实现节点视图和节点配置组件。
111 |
112 |
113 |
114 | #### 节点命名规范
115 |
116 | **节点视图组件文件格式:** [nodeType]-node.vue
117 |
118 | **节点配置组件文件格式:** [nodeType]-drawer.vue
119 |
120 |
121 |
122 | #### 实现节点视图组件
123 |
124 | 以**开始节点**为例,开始节点的**nodeType=start**,则在/src/views/node/start目录下创建start-node.vue文件, 内容如下:
125 |
126 | ```vue
127 | // start-node.vue
128 |
129 |
130 |
131 | 发起人: {{node.config.name}}
132 |
133 |
134 |
135 |
161 |
162 |
165 |
166 | ```
167 |
168 | #### 实现节点配置组件
169 |
170 | 以开始节点为例,开始节点的nodeType=start,则在/src/views/node/start目录下创建start-drawer.vue文件, 内容如下:
171 |
172 | ```vue
173 |
174 |
175 |
176 | 发起人:
177 |
178 |
179 |
180 |
196 |
197 |
200 |
201 | ```
202 |
203 |
204 |
205 | ### 使用组件
206 |
207 | ```vue
208 |
209 | ```
210 |
211 | processData:流程数据,为空时会默认创建一个开始节点
212 |
213 |
214 |
215 | ### 获取流程数据结果
216 |
217 | ```js
218 | import {getCurrentInstance} from "vue";
219 | const { proxy } = getCurrentInstance();
220 |
221 | let result = proxy.$refs.process.getResult();
222 | ```
223 |
224 |
225 |
226 | ## 截图
227 |
228 | 
229 |
230 | 
231 |
232 | 
233 |
234 | 
235 |
236 | 
237 |
238 |
239 |
240 |
--------------------------------------------------------------------------------
/src/easy-process/ep-designer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | {{ zoom }}%
14 |
15 |
16 |
17 |
18 |
19 |
176 |
219 |
--------------------------------------------------------------------------------
/src/easy-process/assets/icons/ep-setting.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/easy-process/node/gateway/gateway-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
11 |
12 |
13 |
14 | {{item.name}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
88 |
89 |
251 |
--------------------------------------------------------------------------------
/src/easy-process/node/base/add-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{item.nodeName}}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
116 |
117 |
241 |
--------------------------------------------------------------------------------
/src/easy-process/node/base/base-node.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
{{errorMsg}}
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
231 |
232 |
425 |
--------------------------------------------------------------------------------