Easy Process 流程设计器,基于vue3 + vite4 实现,具备低代码、快速应用及扩展的特点。
项目完全开源(永久),如果这个项目让你有所收获,记得 Star 关注哦,这对我是非常不错的鼓励与支持。
如果在使用过程中发现BUG,请提交Issues。
https://gitee.com/quxiou-code/easy-process
https://github.com/gy3135990/easy-process
http://process.uncodeshop.com
Node >= 14
计划 | 状态 | 备注 |
---|---|---|
基础功能 | 已完成 | |
节点校验功能 | 已完成 | 类似于表单校验功能,进行特殊样式的提示 |
提升可移植性 | 已完成 | 设计器组件的UI样式完全脱离第三方组件,提升可移植性 |
添加动画特效 | 已完成 | 添加动画特效,提升用户体验 |
优化逐级透传 | 已完成 | 部分功能使用Prop 逐级透传实现,这使代码非常不优雅,决定使用依赖注入方式重构此部分代码。 |
优化代码 | 进行中 |
# 安装依赖
npm install
# 运行项目
npm run dev
easy-process
├─ public
│ └─ mock // mock测试数据
├─ src
│ ├─ assets // 静态资源
│ ├─ components
│ │ ├─ Button
│ │ │ └─ Button.vue // 按钮组件
│ │ ├─ Drawer
│ │ │ └─ Drawer.vue // 抽屉组件
│ │ ├─ SvgIcon
│ │ │ └─ index.vue // svg图标组件
│ │ └─ EasyProcess // 流程设计器
│ │ ├─ ProcessDesigner.vue // 流程设计器组件(入口)
│ │ ├─ config // 流程设计器-配置文件
│ │ │ ├─ defaultConfig.js // 初始化时默认流程结构
│ │ │ ├─ nodeConfig.js // 各节点属性配置
│ │ │ ├─ nodeType.js // 节点类型
│ │ │ └─ keys.js // 定义KEY
│ │ └─ node // 流程设计器-节点组件
│ │ ├─ NodeWrap.vue // 用于递归生成流程节点的组件
│ │ ├─ base // 通用组件
│ │ │ ├─ BaseNode.vue // 通用节点组件(该组件只是节点的外壳,具体内容由各节点组件内部实现)
│ │ │ ├─ BaseDrawer.vue // 通用节点属性配置组件(该组件只是节点属性配置的外壳,具体内容由各节点组件内部实现)
│ │ │ └─ AddNode.vue // 添加节点组件
│ │ ├─ router // 路由节点
│ │ │ └─ routerNode.vue // 路由节点组件
│ │ ├─ condition // 条件节点
│ │ │ ├─ conditionNode.vue // 条件节点组件
│ │ │ └─ conditionDrawer.vue // 条件节点属性配置组件
│ │ ├─ start // 发起人节点
│ │ │ ├─ startNode.vue // 发起人节点组件
│ │ │ └─ startDrawer.vue // 发起人节点属性配置组件
│ │ ├─ approver // 审批人节点
│ │ │ ├─ approverNode.vue // 审批人节点组件
│ │ │ └─ approverDrawer.vue // 审批人节点属性配置组件
│ │ ├─ notify // 审批人节点
│ │ │ ├─ notifyNode.vue // 抄送人节点组件
│ │ │ └─ notifyDrawer.vue // 抄送人节点属性配置组件
│ │ ├─ end // 结束节点
│ │ │ └─ endNode.vue // 结束节点组件(仅用于展示,并没有实际意义)
│ │ └─ utils
│ │ └─ tools.js // 工具类
│ └─ views
│ └─ index.vue // demo
└─ README.md // 使用手册
导入流程设计器组件
import ProcessDesigner from "@/components/EasyProcess/ProcessDesigner";
使用组件
<ProcessDesigner ref="process" :data="processData"/>
获取流程设计结果
import {getCurrentInstance} from "vue";
const { proxy } = getCurrentInstance();
let result = proxy.$refs.process.getResult();
{
"processId": "流程ID",
"processName": "流程名称",
"nodeConfig": {
"nodeName": "节点名称",
"nodeType": "节点类型 start-发起人节点 approver-审批节点 router-路由节点 condition-条件节点 notify-抄送节点",
"config": {}, // 节点配置,根据需求可以自定义
"childNode": {}, // 下级节点
"conditionNodes": [ // 条件节点,节点类型为router时有效,至少会有两个条件节点
{
"nodeName": "条件",
"nodeType": "condition",
"isLastCondition": "true | false 是否为最后一个条件节点,最后一个条件节点不能设置任何条件,默认为通过",
"config": {},
"childNode": {}
}
]
}
}
注:以上数据结构除了nodeConfig字段内的结构是固定的外,使用者可以添加任意其他业务字段,获取数据方式见依赖注入章节。
节点的属性定义在config属性下,具体需要哪些属性请依据业务自行定义。
节点组件一般会由两个组件组成:
xxxNode.vue组件下会通过props.node传入当前节点数据
xxxDrawer.vue组件下会通过props.config传入当前节点属性配置的副本数据,因为是地址传递,所以可以直接对其内部的属性进行修改。在点击确定会将修改后的副本数据覆盖原来的数据。
传入组件的processData
数据可以通过以下方式,在
组件内的任意子组件中获取到。
import {inject} from "vue";
import { KEY_PROCESS_DATA } from "@/components/EasyProcess/config/keys"
// 获取流程数据,processData是一个被ref()包裹的响应式数据
const processData = inject(KEY_PROCESS_DATA)
在config/nodeConfig.js文件下维护各节点的默认配置,格式如下:
{
"title": "条件", // 节点标题
"color": "#FFFFFF", // 节点标题颜色
"bgColor": "#3CB371", // 节点标题背景颜色
"canAdd": false, // 节点是否可以增加
"canRemoved": true, // 节点是否能够移除
"hasDrawer": true, // 节点是否可以进行配置(点击后侧弹出属性配置抽屉)
"icon": { // 图标(使用的svg图标)
"name": "condition", // 图标名(svg图标的文件名,不包含后缀)
"color": "#3CB371" // 图标颜色(注:如果你导入的svg图标设置颜色不生效,请用IDE打开图标文件,找到并删除fill属性(可能存在多个)并保存即可)
},
"defaultNode": { // 默认节点结构,用于添加节点时
"nodeName": "条件",
"nodeType": "condition",
"isLastCondition": false,
"config": {},
"childNode": {}
},
}
1、在src/components/EasyProcess/node/*/xxxNode.vue文件中添加以下代码实现节点校验逻辑:
import { inject } from "vue"
import { KEY_VALIDATOR } from "../../config/keys"
const props = defineProps({
tempNodeId: { // 临时节点ID,该值是从BaseNode.vue组件中传入的
type: String
}
});
// 获取流程验证器实例
const validator = inject(KEY_VALIDATOR)
// 注册验证器
validator.register(props.tempNodeId, () => {
// 验证当前节点逻辑……
// 返回验证结果
return {
"valid": true, // true | false 是否验证通过
"message": "" // 当valid = false时的提示信息
}
})
2、获取验证结果
//
proxy.$refs.process.validate((valid, messages) => {
if(valid) {
// 验证通过,获取结果
let result = proxy.$refs.process.getResult();
} else {
// 验证未通过,messages为验证失败节点的提示信息,数组类型
}
})
1、在src/components/EasyProcess/config/nodeType.js文件下定义一个新的节点类型
export const NEWTYPE = 'newType'
2、在src/components/EasyProcess/config/nodeConfig.js文件下配置该节点的信息
// 引入新节点
import { NEWTYPE } from "./nodeType"
// 节点配置
nodeConfig[NEWTYPE] = {
"title": "新节点", // 节点标题
"color": "#FFFFFF", // 节点标题颜色
"bgColor": "#808000", // 节点标题背景颜色
"canAdd": true, // 节点是否可以增加
"canRemoved": true, // 节点是否能够移除
"hasDrawer": true, // 节点是否可以进行配置(点击后侧弹出属性配置抽屉)
"icon": { // 图标
"name": "notify", // 图标名,项目使用的是svg图标,请将图标文件放至src/assets/icons/svg目录下(注:如果你导入的svg图标设置颜色不生效,请用IDE打开图标文件,找到并删除fill属性(可能存在多个)并保存即可)
"color": "#808000" // 颜色
},
"defaultNode": { // 默认节点结构,用于添加节点时
"nodeName": "新节点",
"nodeType": "newType",
"config": {},
"childNode": null
}
}
3、在src/components/EasyProcess/node目录下创建一个文件夹,名称与节点类型一致
4、在该目录创建两个vue文件:xxxNode.vue和xxxDrawer.vue,其中xxx要与节点类型一致
xxxNode.vue
<template>
<div>
div>
template>
<script setup name="NewTypeNode">
import { getCurrentInstance, inject } from "vue"
import { KEY_VALIDATOR, KEY_PROCESS_DATA } from "../../config/keys"
const props = defineProps({
tempNodeId: { // 临时节点ID
type: String
},
node: { // 传入的流程配置数据
type: Object,
default: {}
}
});
// 获取流程数据
const processData = inject(KEY_PROCESS_DATA)
// 获取流程验证器实例
const validator = inject(KEY_VALIDATOR)
// 注册验证器
validator.register(props.tempNodeId, () => {
// 验证当前节点逻辑……
// 返回验证结果
return {
"valid": true, // true | false 是否验证通过
"message": "" // 当valid = false时的提示信息
}
})
script>
<style lang="less" scoped>
style>
xxxDrawer.vue
<template>
<div>
div>
template>
<script setup name="NewTypeDrawer">
import { getCurrentInstance, inject } from "vue";
import { KEY_PROCESS_DATA } from "../../config/keys"
const props = defineProps({
config: { // 传入的流程配置数据
type: Object,
default: {}
}
});
// 获取流程数据
const processData = inject(KEY_PROCESS_DATA)
script>
<style lang="less" scoped>
style>
5、如何定义节点,请看定义节点章节
6、运行项目进行测试