仿钉钉设计流程:增加抄送人节点

This commit is contained in:
jason 2024-04-05 13:04:12 +08:00
parent 4f839136c7
commit f79c29d168
10 changed files with 391 additions and 120 deletions

View File

@ -24,6 +24,12 @@
<p>条件分支</p> <p>条件分支</p>
</a> </a>
--> -->
<a class="add-node-popover-item notifier" @click="addType(2)">
<div class="item-wrapper">
<span class="iconfont"></span>
</div>
<p>抄送人</p>
</a>
<a class="add-node-popover-item condition" @click="addType(4)"> <a class="add-node-popover-item condition" @click="addType(4)">
<div class="item-wrapper"> <div class="item-wrapper">
<span class="iconfont"></span> <span class="iconfont"></span>
@ -86,9 +92,13 @@ const addType = (type) => {
data = { data = {
name: '抄送人', name: '抄送人',
type: 2, type: 2,
ccSelfSelectFlag: 1, error: true,
childNode: props.childNodeP, //
nodeUserList: [] attributes : {
candidateStrategy: undefined,
candidateParam: undefined
},
childNode: props.childNodeP
} }
} }
emits('update:childNodeP', data) emits('update:childNodeP', data)

View File

@ -2,7 +2,6 @@
<el-drawer <el-drawer
:append-to-body="true" :append-to-body="true"
v-model="visible" v-model="visible"
class="set_promoter"
:show-close="false" :show-close="false"
:size="550" :size="550"
:before-close="saveConfig" :before-close="saveConfig"
@ -165,12 +164,7 @@ import * as DeptApi from '@/api/system/dept'
import * as PostApi from '@/api/system/post' import * as PostApi from '@/api/system/post'
import * as UserApi from '@/api/system/user' import * as UserApi from '@/api/system/user'
import * as UserGroupApi from '@/api/bpm/userGroup' import * as UserGroupApi from '@/api/bpm/userGroup'
defineProps({
directorMaxLevel: {
type: Number,
default: 0
}
})
const roleOptions = ref<RoleApi.RoleVO[]>([]) // const roleOptions = ref<RoleApi.RoleVO[]>([]) //
const postOptions = ref<PostApi.PostVO[]>([]) // const postOptions = ref<PostApi.PostVO[]>([]) //
const userOptions = ref<UserApi.UserVO[]>([]) // const userOptions = ref<UserApi.UserVO[]>([]) //
@ -183,7 +177,7 @@ const candidateConfig = ref({
}) })
let approverConfig = ref({}) let approverConfig = ref({})
let store = useWorkFlowStoreWithOut() let store = useWorkFlowStoreWithOut()
let { setApprover, setUserTaskConfig } = store let { setApproverDrawer, setUserTaskConfig } = store
let approverConfig1 = computed(() => store.approverConfig1) let approverConfig1 = computed(() => store.approverConfig1)
let approverDrawer = computed(() => store.approverDrawer) let approverDrawer = computed(() => store.approverDrawer)
const userTaskConfig = computed(() => store.userTaskConfig) const userTaskConfig = computed(() => store.userTaskConfig)
@ -233,32 +227,16 @@ const saveConfig = () => {
// flag: true, // flag: true,
// id: approverConfig1.value.id // id: approverConfig1.value.id
// }) // })
const showText = getApproverShowText()
setUserTaskConfig({ setUserTaskConfig({
value: rawConfig.value, value: rawConfig.value,
flag: true, flag: true,
id: userTaskConfig.value.id, id: userTaskConfig.value.id,
showText
}) })
console.log('after is userTaskConfig', userTaskConfig.value)
closeDrawer() closeDrawer()
} }
const getApproverShowText = () => {
let appoveMethodText = ''
approveMethods.forEach((item) => {
if (item.value == candidateConfig.value.approveMethod) {
appoveMethodText = item.label
}
})
const strategyText = getDictLabel(
DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY,
candidateConfig.value.candidateStrategy
)
return `审批方式:${appoveMethodText} <br/>
审批人规则类型按${strategyText}`
}
const closeDrawer = () => { const closeDrawer = () => {
setApprover(false) setApproverDrawer(false)
} }
const changecandidateStrategy = () => { const changecandidateStrategy = () => {
candidateConfig.value.candidateParam = [] candidateConfig.value.candidateParam = []

View File

@ -0,0 +1,246 @@
<template>
<el-drawer
:append-to-body="true"
v-model="visible"
:show-close="false"
:size="550"
:before-close="saveConfig"
>
<template #header>
<div class="copy-task-header">抄送人设置</div>
</template>
<div>
<el-form label-position="top" label-width="100px">
<el-form-item label="选择抄送人" prop="candidateStrategy">
<el-select v-model="candidateConfig.candidateStrategy" style="width: 100%" clearable @change="changecandidateStrategy">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy == 10"
label="指定角色"
prop="candidateParam"
>
<el-select
v-model="candidateConfig.candidateParam"
clearable
multiple
style="width: 100%"
>
<el-option
v-for="item in roleOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy == 20 || candidateConfig.candidateStrategy == 21"
label="指定部门"
prop="candidateParam"
span="24"
>
<el-tree-select
ref="treeRef"
v-model="candidateConfig.candidateParam"
:data="deptTreeOptions"
:props="defaultProps"
empty-text="加载中,请稍后"
multiple
node-key="id"
style="width: 100%"
show-checkbox
/>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy == 22"
label="指定岗位"
prop="candidateParam"
span="24"
>
<el-select
v-model="candidateConfig.candidateParam"
clearable
multiple
style="width: 100%"
>
<el-option
v-for="item in postOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="
candidateConfig.candidateStrategy == 30 ||
candidateConfig.candidateStrategy == 31 ||
candidateConfig.candidateStrategy == 32
"
label="指定用户"
prop="candidateParam"
span="24"
>
<el-select
v-model="candidateConfig.candidateParam"
clearable
multiple
style="width: 100%"
>
<el-option
v-for="item in userOptions"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy === 40"
label="指定用户组"
prop="candidateParam"
>
<el-select
v-model="candidateConfig.candidateParam"
clearable
multiple
style="width: 100%"
>
<el-option
v-for="item in userGroupOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="candidateConfig.candidateStrategy === 60"
label="流程表达式"
prop="candidateParam"
>
<el-input
type="textarea"
v-model="candidateConfig.candidateParam[0]"
clearable
style="width: 100%"
/>
</el-form-item>
</el-form>
</div>
<div class="demo-drawer__footer clear">
<el-button type="primary" @click="saveConfig"> </el-button>
<el-button @click="closeDrawer"> </el-button>
</div>
</el-drawer>
</template>
<script lang="ts" setup>
import { ref, watch, computed, toRaw } from 'vue'
import { useWorkFlowStoreWithOut } from '@/store/modules/simpleWorkflow'
import { DICT_TYPE, getIntDictOptions, getDictLabel } from '@/utils/dict'
import { defaultProps, handleTree } from '@/utils/tree'
import * as RoleApi from '@/api/system/role'
import * as DeptApi from '@/api/system/dept'
import * as PostApi from '@/api/system/post'
import * as UserApi from '@/api/system/user'
import * as UserGroupApi from '@/api/bpm/userGroup'
const roleOptions = ref<RoleApi.RoleVO[]>([]) //
const postOptions = ref<PostApi.PostVO[]>([]) //
const userOptions = ref<UserApi.UserVO[]>([]) //
const deptTreeOptions = ref() //
const userGroupOptions = ref<UserGroupApi.UserGroupVO[]>([]) //
const candidateConfig = ref({
candidateStrategy: undefined,
candidateParam: [],
})
const store = useWorkFlowStoreWithOut()
const { setCopyerDrawer, setCopyerConfig } = store
const copyerDrawer = computed(() => store.copyerDrawer)
const copyerConfig = computed(() => store.copyerConfig)
const visible = computed({
get() {
return copyerDrawer.value
},
set() {
closeDrawer()
}
})
watch(copyerConfig, (val) => {
if (val.value.attributes) {
console.log('val.value.attributes', val.value.attributes);
candidateConfig.value.candidateStrategy = val.value.attributes.candidateStrategy
const candidateParamStr = val.value.attributes.candidateParam;
if(val.value.attributes.candidateStrategy === 60) {
candidateConfig.value.candidateParam = [candidateParamStr]
} else {
if(candidateParamStr){
candidateConfig.value.candidateParam = candidateParamStr.split(',').map((item) => +item)
}
}
// candidateConfig.value = val.value.attributes
}
})
const saveConfig = () => {
const rawConfig = toRaw(copyerConfig.value)
const { candidateStrategy , candidateParam} = toRaw(candidateConfig.value);
const candidateParamStr = candidateParam.join(',')
rawConfig.value.attributes = {
candidateStrategy,
candidateParam: candidateParamStr
}
rawConfig.flag = true
// TODO
// setApproverConfig({
// value: approverConfig.value,
// flag: true,
// id: approverConfig1.value.id
// })
setCopyerConfig({
value: rawConfig.value,
flag: true,
id: copyerConfig.value.id,
})
console.log('after is copyerConfig', copyerConfig.value)
closeDrawer()
}
const closeDrawer = () => {
setCopyerDrawer(false)
}
const changecandidateStrategy = () => {
candidateConfig.value.candidateParam = []
}
onMounted(async () => {
//
roleOptions.value = await RoleApi.getSimpleRoleList()
postOptions.value = await PostApi.getSimplePostList()
//
userOptions.value = await UserApi.getSimpleUserList()
//
const deptOptions = await DeptApi.getSimpleDeptList()
deptTreeOptions.value = handleTree(deptOptions, 'id')
//
userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList()
})
</script>
<style lang="scss" scoped>
.copy-task-header {
font-size: 16px !important;
}
</style>

View File

@ -22,12 +22,13 @@
v-if="isInput" v-if="isInput"
type="text" type="text"
class="ant-input editable-title-input" class="ant-input editable-title-input"
@blur="blurEvent()" @blur="blurEvent(-1)"
@focus="$event.currentTarget.select()" @focus="$event.currentTarget?.select()"
v-mountedFoucs
v-model="nodeConfig.name" v-model="nodeConfig.name"
:placeholder="defaultText" :placeholder="defaultText"
/> />
<span v-else class="editable-title" @click="clickEvent()">{{ nodeConfig.name }}</span> <span v-else class="editable-title" @click="clickEvent(-1)">{{ nodeConfig.name }}</span>
<i class="anticon anticon-close close" @click="delNode"></i> <i class="anticon anticon-close close" @click="delNode"></i>
</template> </template>
</div> </div>
@ -60,7 +61,8 @@
type="text" type="text"
class="ant-input editable-title-input" class="ant-input editable-title-input"
@blur="blurEvent(index)" @blur="blurEvent(index)"
@focus="$event.currentTarget.select()" @focus="$event.currentTarget?.select()"
v-mountedFoucs
v-model="item.name" v-model="item.name"
/> />
<span v-else class="editable-title" @click="clickEvent(index)">{{ <span v-else class="editable-title" @click="clickEvent(index)">{{
@ -135,9 +137,8 @@ let props = defineProps({
let defaultText = computed(() => { let defaultText = computed(() => {
return placeholderList[props.nodeConfig.type] return placeholderList[props.nodeConfig.type]
}) })
const isInputList = ref<boolean[]>([])
let isInputList = ref([]) const isInput = ref<boolean>(false)
let isInput = ref(false)
const resetConditionNodesErr = () => { const resetConditionNodesErr = () => {
for (var i = 0; i < props.nodeConfig.conditionNodes.length; i++) { for (var i = 0; i < props.nodeConfig.conditionNodes.length; i++) {
// eslint-disable-next-line vue/no-mutating-props // eslint-disable-next-line vue/no-mutating-props
@ -160,20 +161,20 @@ onMounted(() => {
let emits = defineEmits(['update:nodeConfig']) let emits = defineEmits(['update:nodeConfig'])
let store = useWorkFlowStoreWithOut() let store = useWorkFlowStoreWithOut()
let { let {
setPromoter, setApproverDrawer,
setApprover, setCopyerDrawer,
setCopyer, // setCondition,
setCondition,
setCopyerConfig, setCopyerConfig,
setConditionsConfig, // setConditionsConfig,
setUserTaskConfig setUserTaskConfig
} = store } = store
// ???
const isTried = computed(() => store.isTried)
// //
const userTaskConfig = computed(() => store.userTaskConfig) const userTaskConfig = computed(() => store.userTaskConfig)
let isTried = computed(() => store.isTried) //
let approverConfig1 = computed(() => store.approverConfig1) const copyerConfig = computed(() => store.copyerConfig)
let copyerConfig1 = computed(() => store.copyerConfig1) // let conditionsConfig1 = computed(() => store.conditionsConfig1)
let conditionsConfig1 = computed(() => store.conditionsConfig1)
const showText = computed(() => { const showText = computed(() => {
if (props.nodeConfig.type == 0) return '发起人' if (props.nodeConfig.type == 0) return '发起人'
if (props.nodeConfig.type == 1) { if (props.nodeConfig.type == 1) {
@ -186,42 +187,49 @@ const showText = computed(() => {
return '' return ''
} }
} }
return copyerStr(props.nodeConfig) if(props.nodeConfig.type === 2) {
if(props.nodeConfig.attributes) {
return copyerStr( props.nodeConfig.attributes.candidateStrategy)
} else {
return ''
}
}
return ''
}) })
watch(userTaskConfig, (approver) => { watch(userTaskConfig, (approver) => {
if (approver.flag && approver.id === _uid) { if (approver.flag && approver.id === _uid) {
emits('update:nodeConfig', approver.value) emits('update:nodeConfig', approver.value)
} }
}) })
watch(approverConfig1, (approver) => { watch(copyerConfig, (copyer) => {
if (approver.flag && approver.id === _uid) { console.log('copyer',copyer)
emits('update:nodeConfig', approver.value)
}
})
watch(copyerConfig1, (copyer) => {
if (copyer.flag && copyer.id === _uid) { if (copyer.flag && copyer.id === _uid) {
console.log('copyer id is equal',copyer)
emits('update:nodeConfig', copyer.value) emits('update:nodeConfig', copyer.value)
} }
}) })
watch(conditionsConfig1, (condition) => {
if (condition.flag && condition.id === _uid) { // watch(conditionsConfig1, (condition) => {
emits('update:nodeConfig', condition.value) // if (condition.flag && condition.id === _uid) {
} // emits('update:nodeConfig', condition.value)
}) // }
// })
const clickEvent = (index) => { const clickEvent = (index) => {
if (index || index === 0) { if (index >= 0) {
isInputList.value[index] = true isInputList.value[index] = true
} else { } else {
isInput.value = true isInput.value = true
} }
} }
const blurEvent = (index) => { const blurEvent = (index) => {
if (index || index === 0) { if (index >= 0) {
isInputList.value[index] = false isInputList.value[index] = false
// eslint-disable-next-line vue/no-mutating-props // eslint-disable-next-line vue/no-mutating-props
props.nodeConfig.conditionNodes[index].name = props.nodeConfig.conditionNodes[index].name =
props.nodeConfig.conditionNodes[index].name || '条件' props.nodeConfig.conditionNodes[index].name || '条件'
} else { } else {
isInput.value = false isInput.value = false
// eslint-disable-next-line vue/no-mutating-props // eslint-disable-next-line vue/no-mutating-props
@ -278,42 +286,45 @@ const reData = (data, addData) => {
} }
} }
const setPerson = (priorityLevel) => { const setPerson = (priorityLevel) => {
var { type } = props.nodeConfig console.log('priorityLevel',priorityLevel)
const { type } = props.nodeConfig
console.log('type',type)
if (type == 0) { if (type == 0) {
setPromoter(true) // setPromoter(true)
} else if (type == 1) { } else if (type == 1) {
setApprover(true) setApproverDrawer(true)
let showText = undefined // if (_uid === userTaskConfig.value.id) {
if (_uid === userTaskConfig.value.id) { // showText = userTaskConfig.value.showText
showText = userTaskConfig.value.showText // }
}
setUserTaskConfig({ setUserTaskConfig({
value: { value: {
...JSON.parse(JSON.stringify(props.nodeConfig)), ...JSON.parse(JSON.stringify(props.nodeConfig)),
id: 'Activity_' + _uid id: 'Activity_' + _uid
}, },
flag: false, flag: false,
id: _uid, id: _uid
showText
}) })
} else if (type == 2) { } else if (type == 2) {
setCopyer(true) setCopyerDrawer(true)
setCopyerConfig({ setCopyerConfig({
value: JSON.parse(JSON.stringify(props.nodeConfig)), value: {
...JSON.parse(JSON.stringify(props.nodeConfig)),
id: 'Activity_' + _uid
},
flag: false, flag: false,
id: _uid id: _uid
}) })
} else { } else {
setCondition(true) // setCondition(true)
setConditionsConfig({ // setConditionsConfig({
value: { // value: {
...JSON.parse(JSON.stringify(props.nodeConfig)), // ...JSON.parse(JSON.stringify(props.nodeConfig)),
id: 'Gateway_' + _uid // id: 'Gateway_' + _uid
}, // },
priorityLevel, // priorityLevel,
flag: false, // flag: false,
id: _uid // id: _uid
}) // })
} }
} }
// const arrTransfer = (index, type = 1) => { // const arrTransfer = (index, type = 1) => {

View File

@ -80,13 +80,24 @@ export const getApproverShowText = (approveMethod :number, candidateStrategy: nu
} }
} }
export const copyerStr = (nodeConfig: any) => { export const copyerStr = ( candidateStrategy: number) => {
if (nodeConfig.nodeUserList.length != 0) { // if (nodeConfig.nodeUserList.length != 0) {
return arrToStr(nodeConfig.nodeUserList) // return arrToStr(nodeConfig.nodeUserList)
// } else {
// if (nodeConfig.ccSelfSelectFlag == 1) {
// return '发起人自选'
// }
// }
console.log('candidateStrategy', candidateStrategy);
if(candidateStrategy) {
const strategyText = getDictLabel(
DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY,
candidateStrategy
)
return `抄送人类型:按${strategyText}`
} else { } else {
if (nodeConfig.ccSelfSelectFlag == 1) { return ''
return '发起人自选'
}
} }
} }
export const conditionStr = (nodeConfig, index) => { export const conditionStr = (nodeConfig, index) => {

View File

@ -1163,11 +1163,7 @@ html {
box-shadow: 0 0 6px 0 rgba(50, 150, 250, .3) box-shadow: 0 0 6px 0 rgba(50, 150, 250, .3)
} }
.dingflow-design .auto-judge.active .close,
.dingflow-design .auto-judge:active .close,
.dingflow-design .auto-judge:hover .close {
display: block
}
.dingflow-design .auto-judge.error:after { .dingflow-design .auto-judge.error:after {
border: 1px solid #f25643; border: 1px solid #f25643;
@ -1183,6 +1179,7 @@ html {
line-height: 24px; line-height: 24px;
width: 258px; width: 258px;
} */ } */
.dingflow-design .title-wrapper { .dingflow-design .title-wrapper {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -1195,18 +1192,39 @@ html {
line-height: 24px; line-height: 24px;
width: 220px; width: 220px;
color: #fff; color: #fff;
padding-right: 10px;
padding-left: 10px;
} }
.dingflow-design .title-wrapper .editable-title { .dingflow-design .title-wrapper .editable-title {
max-width: 120px; max-width: 120px;
padding-left: 10px;
overflow: hidden; overflow: hidden;
white-space: nowrap; white-space: nowrap;
text-overflow: ellipsis text-overflow: ellipsis
} }
.dingflow-design .title-wrapper .close {
padding-right: 10px; .dingflow-design .title-wrapper .close {
display: none;
position: absolute;
right: 10px;
top: 2px;
width: 20px;
height: 20px;
font-size: 14px;
color:#fff;
border-radius: 50%;
text-align: center;
line-height: 20px;
z-index: 2
} }
.dingflow-design .title-wrapper:hover .close {
display: block
}
/* .dingflow-design .title-wrapper .close {
padding-right: 2px;
} */
/* .dingflow-design .title-wrapper .priority-title { /* .dingflow-design .title-wrapper .priority-title {
display: inline-block; display: inline-block;
float: right; float: right;
@ -1233,21 +1251,6 @@ html {
color: #bfbfbf color: #bfbfbf
} }
.dingflow-design .auto-judge .close {
display: none;
position: absolute;
right: -10px;
top: -10px;
width: 20px;
height: 20px;
font-size: 14px;
color: rgba(0, 0, 0, .25);
border-radius: 50%;
text-align: center;
line-height: 20px;
z-index: 2
}
.dingflow-design .auto-judge .content { .dingflow-design .auto-judge .content {
font-size: 14px; font-size: 14px;
color: #191f25; color: #191f25;

View File

@ -10,4 +10,16 @@ import { hasPermi } from './permission/hasPermi'
export const setupAuth = (app: App<Element>) => { export const setupAuth = (app: App<Element>) => {
hasRole(app) hasRole(app)
hasPermi(app) hasPermi(app)
}
/**
* v-mountedFoucs
*/
export const setupMountedFoucs= (app: App<Element>) => {
app.directive('mountedFoucs', {
mounted(el) {
el.focus();
}
})
} }

View File

@ -28,8 +28,8 @@ import '@/plugins/animate.css'
// 路由 // 路由
import router, { setupRouter } from '@/router' import router, { setupRouter } from '@/router'
// 权限 // 其它指令
import { setupAuth } from '@/directives' import { setupAuth, setupMountedFoucs } from '@/directives'
import { createApp } from 'vue' import { createApp } from 'vue'
@ -60,6 +60,8 @@ const setupAll = async () => {
setupAuth(app) setupAuth(app)
setupMountedFoucs(app)
await router.isReady() await router.isReady()
app.use(VueDOMPurifyHTML) app.use(VueDOMPurifyHTML)

View File

@ -6,11 +6,10 @@ export const useWorkFlowStore = defineStore('simpleWorkflow', {
tableId: '', tableId: '',
isTried: false, isTried: false,
promoterDrawer: false, promoterDrawer: false,
flowPermission1: {},
approverDrawer: false, approverDrawer: false,
approverConfig1: {}, approverConfig1: {},
copyerDrawer: false, copyerDrawer: false,
copyerConfig1: {}, copyerConfig: {},
conditionDrawer: false, conditionDrawer: false,
conditionsConfig1: { conditionsConfig1: {
conditionNodes: [] conditionNodes: []
@ -27,20 +26,17 @@ export const useWorkFlowStore = defineStore('simpleWorkflow', {
setPromoter(payload) { setPromoter(payload) {
this.promoterDrawer = payload this.promoterDrawer = payload
}, },
setFlowPermission(payload) { setApproverDrawer(payload) {
this.flowPermission1 = payload
},
setApprover(payload) {
this.approverDrawer = payload this.approverDrawer = payload
}, },
setApproverConfig(payload) { setApproverConfig(payload) {
this.approverConfig1 = payload this.approverConfig1 = payload
}, },
setCopyer(payload) { setCopyerDrawer(payload) {
this.copyerDrawer = payload this.copyerDrawer = payload
}, },
setCopyerConfig(payload) { setCopyerConfig(payload) {
this.copyerConfig1 = payload this.copyerConfig = payload
}, },
setCondition(payload) { setCondition(payload) {
this.conditionDrawer = payload this.conditionDrawer = payload

View File

@ -24,10 +24,12 @@
</section> </section>
</div> </div>
<approverDrawer /> <approverDrawer />
<copyerDrawer />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import nodeWrap from '@/components/SimpleProcessDesigner/src/nodeWrap.vue' import nodeWrap from '@/components/SimpleProcessDesigner/src/nodeWrap.vue'
import approverDrawer from '@/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue' import approverDrawer from '@/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue'
import copyerDrawer from '@/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue'
import { WorkFlowNode } from '@/components/SimpleProcessDesigner/src/consts' import { WorkFlowNode } from '@/components/SimpleProcessDesigner/src/consts'
import { ref } from 'vue' import { ref } from 'vue'
import { saveBpmSimpleModel, getBpmSimpleModel } from '@/api/bpm/simple' import { saveBpmSimpleModel, getBpmSimpleModel } from '@/api/bpm/simple'