mirror of
https://gitee.com/hhyykk/ipms-sjy-ui.git
synced 2025-07-14 02:45:06 +08:00
Merge branch 'master' of https://gitee.com/yudaocode/yudao-ui-admin-vue3 into dev
# Conflicts: # package.json
This commit is contained in:
@ -25,6 +25,9 @@ defineProps({
|
||||
</template>
|
||||
<Icon :size="14" class="ml-5px" icon="ep:question-filled" />
|
||||
</ElTooltip>
|
||||
<div class="flex flex-grow pl-20px">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
|
@ -180,12 +180,12 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="z-99 border-1 border-[var(--el-border-color)] border-solid">
|
||||
<div class="border-1 border-solid border-[var(--tags-view-border-color)] z-10">
|
||||
<!-- 工具栏 -->
|
||||
<Toolbar
|
||||
:editor="editorRef"
|
||||
:editorId="editorId"
|
||||
class="border-0 b-b-1 border-[var(--el-border-color)] border-solid"
|
||||
class="border-0 b-b-1 border-solid border-[var(--tags-view-border-color)]"
|
||||
/>
|
||||
<!-- 编辑器 -->
|
||||
<Editor
|
||||
|
@ -12,7 +12,7 @@ export function createImageViewer(options: ImageViewerProps) {
|
||||
initialIndex = 0,
|
||||
infinite = true,
|
||||
hideOnClickModal = false,
|
||||
appendToBody = false,
|
||||
teleported = false,
|
||||
zIndex = 2000,
|
||||
show = true
|
||||
} = options
|
||||
@ -23,7 +23,7 @@ export function createImageViewer(options: ImageViewerProps) {
|
||||
propsData.initialIndex = initialIndex
|
||||
propsData.infinite = infinite
|
||||
propsData.hideOnClickModal = hideOnClickModal
|
||||
propsData.appendToBody = appendToBody
|
||||
propsData.teleported = teleported
|
||||
propsData.zIndex = zIndex
|
||||
propsData.show = show
|
||||
|
||||
|
@ -13,7 +13,7 @@ const props = defineProps({
|
||||
initialIndex: propTypes.number.def(0),
|
||||
infinite: propTypes.bool.def(true),
|
||||
hideOnClickModal: propTypes.bool.def(false),
|
||||
appendToBody: propTypes.bool.def(false),
|
||||
teleported: propTypes.bool.def(false),
|
||||
show: propTypes.bool.def(false)
|
||||
})
|
||||
|
||||
|
@ -4,6 +4,6 @@ export interface ImageViewerProps {
|
||||
initialIndex?: number
|
||||
infinite?: boolean
|
||||
hideOnClickModal?: boolean
|
||||
appendToBody?: boolean
|
||||
teleported?: boolean
|
||||
show?: boolean
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ const props = defineProps({
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:page', 'update:limit', 'pagination', 'pagination'])
|
||||
const emit = defineEmits(['update:page', 'update:limit', 'pagination'])
|
||||
const currentPage = computed({
|
||||
get() {
|
||||
return props.page
|
||||
|
@ -26,7 +26,7 @@
|
||||
placeholder="请输入菜单内容"
|
||||
:remote-method="remoteMethod"
|
||||
class="overflow-hidden transition-all-600"
|
||||
:class="showTopSearch ? 'w-220px ml2' : 'w-0'"
|
||||
:class="showTopSearch ? '!w-220px ml2' : '!w-0'"
|
||||
@change="handleChange"
|
||||
>
|
||||
<el-option
|
||||
|
237
src/components/SimpleProcessDesigner/src/addNode.vue
Normal file
237
src/components/SimpleProcessDesigner/src/addNode.vue
Normal file
@ -0,0 +1,237 @@
|
||||
/* stylelint-disable order/properties-order */
|
||||
<template>
|
||||
<div class="add-node-btn-box">
|
||||
<div class="add-node-btn">
|
||||
<el-popover placement="right-start" v-model="visible" width="auto">
|
||||
<div class="add-node-popover-body">
|
||||
<a class="add-node-popover-item approver" @click="addType(1)">
|
||||
<div class="item-wrapper">
|
||||
<span class="iconfont"></span>
|
||||
</div>
|
||||
<p>审批人</p>
|
||||
</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)">
|
||||
<div class="item-wrapper">
|
||||
<span class="iconfont"></span>
|
||||
</div>
|
||||
<p>条件分支</p>
|
||||
</a>
|
||||
</div>
|
||||
<template #reference>
|
||||
<button class="btn" type="button">
|
||||
<span class="iconfont"></span>
|
||||
</button>
|
||||
</template>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
let props = defineProps({
|
||||
childNodeP: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
})
|
||||
let emits = defineEmits(['update:childNodeP'])
|
||||
let visible = ref(false)
|
||||
const addType = (type) => {
|
||||
visible.value = false
|
||||
if (type != 4) {
|
||||
var data
|
||||
if (type == 1) {
|
||||
data = {
|
||||
nodeName: '审核人',
|
||||
error: true,
|
||||
type: 1,
|
||||
settype: 1,
|
||||
selectMode: 0,
|
||||
selectRange: 0,
|
||||
directorLevel: 1,
|
||||
examineMode: 1,
|
||||
noHanderAction: 1,
|
||||
examineEndDirectorLevel: 0,
|
||||
childNode: props.childNodeP,
|
||||
nodeUserList: []
|
||||
}
|
||||
} else if (type == 2) {
|
||||
data = {
|
||||
nodeName: '抄送人',
|
||||
type: 2,
|
||||
ccSelfSelectFlag: 1,
|
||||
childNode: props.childNodeP,
|
||||
nodeUserList: []
|
||||
}
|
||||
}
|
||||
emits('update:childNodeP', data)
|
||||
} else {
|
||||
emits('update:childNodeP', {
|
||||
nodeName: '路由',
|
||||
type: 4,
|
||||
childNode: null,
|
||||
conditionNodes: [
|
||||
{
|
||||
nodeName: '条件1',
|
||||
error: true,
|
||||
type: 3,
|
||||
priorityLevel: 1,
|
||||
conditionList: [],
|
||||
nodeUserList: [],
|
||||
childNode: props.childNodeP
|
||||
},
|
||||
{
|
||||
nodeName: '条件2',
|
||||
type: 3,
|
||||
priorityLevel: 2,
|
||||
conditionList: [],
|
||||
nodeUserList: [],
|
||||
childNode: null
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.add-node-btn-box {
|
||||
width: 240px;
|
||||
display: inline-flex;
|
||||
-ms-flex-negative: 0;
|
||||
flex-shrink: 0;
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex-positive: 1;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: -1;
|
||||
margin: auto;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background-color: #cacaca;
|
||||
}
|
||||
|
||||
.add-node-btn {
|
||||
user-select: none;
|
||||
width: 240px;
|
||||
padding: 20px 0 32px;
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
-webkit-box-flex: 1;
|
||||
flex-grow: 1;
|
||||
|
||||
.btn {
|
||||
outline: none;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: #3296fa;
|
||||
border-radius: 50%;
|
||||
position: relative;
|
||||
border: none;
|
||||
line-height: 30px;
|
||||
-webkit-transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
.iconfont {
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.3);
|
||||
box-shadow: 0 13px 27px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: none;
|
||||
background: #1e83e9;
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-node-popover-body {
|
||||
display: flex;
|
||||
|
||||
.add-node-popover-item {
|
||||
margin-right: 10px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
flex: 1;
|
||||
color: #191f25 !important;
|
||||
|
||||
.item-wrapper {
|
||||
user-select: none;
|
||||
display: inline-block;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-bottom: 5px;
|
||||
background: #fff;
|
||||
border: 1px solid #e2e2e2;
|
||||
border-radius: 50%;
|
||||
transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
.iconfont {
|
||||
font-size: 35px;
|
||||
line-height: 80px;
|
||||
}
|
||||
}
|
||||
|
||||
&.approver {
|
||||
.item-wrapper {
|
||||
color: #ff943e;
|
||||
}
|
||||
}
|
||||
|
||||
&.notifier {
|
||||
.item-wrapper {
|
||||
color: #3296fa;
|
||||
}
|
||||
}
|
||||
|
||||
&.condition {
|
||||
.item-wrapper {
|
||||
color: #15bc83;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.item-wrapper {
|
||||
background: #3296fa;
|
||||
box-shadow: 0 10px 20px 0 rgba(50, 150, 250, 0.4);
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&:active {
|
||||
.item-wrapper {
|
||||
box-shadow: none;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
297
src/components/SimpleProcessDesigner/src/nodeWrap.vue
Normal file
297
src/components/SimpleProcessDesigner/src/nodeWrap.vue
Normal file
@ -0,0 +1,297 @@
|
||||
<!-- eslint-disable vue/no-mutating-props -->
|
||||
<!--
|
||||
* @Date: 2022-09-21 14:41:53
|
||||
* @LastEditors: StavinLi 495727881@qq.com
|
||||
* @LastEditTime: 2023-05-24 15:20:24
|
||||
* @FilePath: /Workflow-Vue3/src/components/nodeWrap.vue
|
||||
-->
|
||||
<template>
|
||||
<div class="node-wrap" v-if="nodeConfig.type < 3">
|
||||
<div class="node-wrap-box" :class="(nodeConfig.type == 0 ? 'start-node ' : '') +(isTried && nodeConfig.error ? 'active error' : '')">
|
||||
<div class="title" :style="`background: rgb(${bgColors[nodeConfig.type]});`">
|
||||
<span v-if="nodeConfig.type == 0">{{ nodeConfig.nodeName }}</span>
|
||||
<template v-else>
|
||||
<span class="iconfont">{{nodeConfig.type == 1?'':''}}</span>
|
||||
<input
|
||||
v-if="isInput"
|
||||
type="text"
|
||||
class="ant-input editable-title-input"
|
||||
@blur="blurEvent()"
|
||||
@focus="$event.currentTarget.select()"
|
||||
v-focus
|
||||
v-model="nodeConfig.nodeName"
|
||||
:placeholder="defaultText"
|
||||
/>
|
||||
<span v-else class="editable-title" @click="clickEvent()">{{ nodeConfig.nodeName }}</span>
|
||||
<i class="anticon anticon-close close" @click="delNode"></i>
|
||||
</template>
|
||||
</div>
|
||||
<div class="content" @click="setPerson">
|
||||
<div class="text">
|
||||
<span class="placeholder" v-if="!showText">请选择{{defaultText}}</span>
|
||||
{{showText}}
|
||||
</div>
|
||||
<i class="anticon anticon-right arrow"></i>
|
||||
</div>
|
||||
<div class="error_tip" v-if="isTried && nodeConfig.error">
|
||||
<i class="anticon anticon-exclamation-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<addNode v-model:childNodeP="nodeConfig.childNode" />
|
||||
</div>
|
||||
<div class="branch-wrap" v-if="nodeConfig.type == 4">
|
||||
<div class="branch-box-wrap">
|
||||
<div class="branch-box">
|
||||
<button class="add-branch" @click="addTerm">添加条件</button>
|
||||
<div class="col-box" v-for="(item, index) in nodeConfig.conditionNodes" :key="index">
|
||||
<div class="condition-node">
|
||||
<div class="condition-node-box">
|
||||
<div class="auto-judge" :class="isTried && item.error ? 'error active' : ''">
|
||||
<div class="sort-left" v-if="index != 0" @click="arrTransfer(index, -1)"><</div>
|
||||
<div class="title-wrapper">
|
||||
<input
|
||||
v-if="isInputList[index]"
|
||||
type="text"
|
||||
class="ant-input editable-title-input"
|
||||
@blur="blurEvent(index)"
|
||||
@focus="$event.currentTarget.select()"
|
||||
v-model="item.nodeName"
|
||||
/>
|
||||
<span v-else class="editable-title" @click="clickEvent(index)">{{ item.nodeName }}</span>
|
||||
<span class="priority-title" @click="setPerson(item.priorityLevel)">优先级{{ item.priorityLevel }}</span>
|
||||
<i class="anticon anticon-close close" @click="delTerm(index)"></i>
|
||||
</div>
|
||||
<div class="sort-right" v-if="index != nodeConfig.conditionNodes.length - 1" @click="arrTransfer(index)">></div>
|
||||
<div class="content" @click="setPerson(item.priorityLevel)">{{ conditionStr(nodeConfig, index) }}</div>
|
||||
<div class="error_tip" v-if="isTried && item.error">
|
||||
<i class="anticon anticon-exclamation-circle"></i>
|
||||
</div>
|
||||
</div>
|
||||
<addNode v-model:childNodeP="item.childNode" />
|
||||
</div>
|
||||
</div>
|
||||
<nodeWrap v-if="item.childNode" v-model:nodeConfig="item.childNode" />
|
||||
<template v-if="index == 0">
|
||||
<div class="top-left-cover-line"></div>
|
||||
<div class="bottom-left-cover-line"></div>
|
||||
</template>
|
||||
<template v-if="index == nodeConfig.conditionNodes.length - 1">
|
||||
<div class="top-right-cover-line"></div>
|
||||
<div class="bottom-right-cover-line"></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<addNode v-model:childNodeP="nodeConfig.childNode" />
|
||||
</div>
|
||||
</div>
|
||||
<nodeWrap v-if="nodeConfig.childNode" v-model:nodeConfig="nodeConfig.childNode" />
|
||||
</template>
|
||||
<script setup>
|
||||
import addNode from './addNode.vue'
|
||||
import { onMounted, ref, watch, getCurrentInstance, computed } from 'vue'
|
||||
import {
|
||||
arrToStr,
|
||||
conditionStr,
|
||||
setApproverStr,
|
||||
copyerStr,
|
||||
bgColors,
|
||||
placeholderList
|
||||
} from './util'
|
||||
import { useWorkFlowStoreWithOut } from '@/store/modules/simpleWorkflow'
|
||||
let _uid = getCurrentInstance().uid
|
||||
|
||||
let props = defineProps({
|
||||
nodeConfig: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
flowPermission: {
|
||||
type: Object,
|
||||
// eslint-disable-next-line vue/require-valid-default-prop
|
||||
default: () => []
|
||||
}
|
||||
})
|
||||
|
||||
let defaultText = computed(() => {
|
||||
return placeholderList[props.nodeConfig.type]
|
||||
})
|
||||
let showText = computed(() => {
|
||||
if (props.nodeConfig.type == 0) return arrToStr(props.flowPermission) || '所有人'
|
||||
if (props.nodeConfig.type == 1) return setApproverStr(props.nodeConfig)
|
||||
return copyerStr(props.nodeConfig)
|
||||
})
|
||||
|
||||
let isInputList = ref([])
|
||||
let isInput = ref(false)
|
||||
const resetConditionNodesErr = () => {
|
||||
for (var i = 0; i < props.nodeConfig.conditionNodes.length; i++) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes[i].error =
|
||||
conditionStr(props.nodeConfig, i) == '请设置条件' &&
|
||||
i != props.nodeConfig.conditionNodes.length - 1
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
if (props.nodeConfig.type == 1) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.error = !setApproverStr(props.nodeConfig)
|
||||
} else if (props.nodeConfig.type == 2) {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.error = !copyerStr(props.nodeConfig)
|
||||
} else if (props.nodeConfig.type == 4) {
|
||||
resetConditionNodesErr()
|
||||
}
|
||||
})
|
||||
let emits = defineEmits(['update:flowPermission', 'update:nodeConfig'])
|
||||
let store = useWorkFlowStoreWithOut()
|
||||
let {
|
||||
setPromoter,
|
||||
setApprover,
|
||||
setCopyer,
|
||||
setCondition,
|
||||
setFlowPermission,
|
||||
setApproverConfig,
|
||||
setCopyerConfig,
|
||||
setConditionsConfig
|
||||
} = store
|
||||
let isTried = computed(() => store.isTried)
|
||||
let flowPermission1 = computed(() => store.flowPermission1)
|
||||
let approverConfig1 = computed(() => store.approverConfig1)
|
||||
let copyerConfig1 = computed(() => store.copyerConfig1)
|
||||
let conditionsConfig1 = computed(() => store.conditionsConfig1)
|
||||
watch(flowPermission1, (flow) => {
|
||||
if (flow.flag && flow.id === _uid) {
|
||||
emits('update:flowPermission', flow.value)
|
||||
}
|
||||
})
|
||||
watch(approverConfig1, (approver) => {
|
||||
if (approver.flag && approver.id === _uid) {
|
||||
emits('update:nodeConfig', approver.value)
|
||||
}
|
||||
})
|
||||
watch(copyerConfig1, (copyer) => {
|
||||
if (copyer.flag && copyer.id === _uid) {
|
||||
emits('update:nodeConfig', copyer.value)
|
||||
}
|
||||
})
|
||||
watch(conditionsConfig1, (condition) => {
|
||||
if (condition.flag && condition.id === _uid) {
|
||||
emits('update:nodeConfig', condition.value)
|
||||
}
|
||||
})
|
||||
|
||||
const clickEvent = (index) => {
|
||||
if (index || index === 0) {
|
||||
isInputList.value[index] = true
|
||||
} else {
|
||||
isInput.value = true
|
||||
}
|
||||
}
|
||||
const blurEvent = (index) => {
|
||||
if (index || index === 0) {
|
||||
isInputList.value[index] = false
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes[index].nodeName =
|
||||
props.nodeConfig.conditionNodes[index].nodeName || '条件'
|
||||
} else {
|
||||
isInput.value = false
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.nodeName = props.nodeConfig.nodeName || defaultText
|
||||
}
|
||||
}
|
||||
const delNode = () => {
|
||||
emits('update:nodeConfig', props.nodeConfig.childNode)
|
||||
}
|
||||
const addTerm = () => {
|
||||
let len = props.nodeConfig.conditionNodes.length + 1
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes.push({
|
||||
nodeName: '条件' + len,
|
||||
type: 3,
|
||||
priorityLevel: len,
|
||||
conditionList: [],
|
||||
nodeUserList: [],
|
||||
childNode: null
|
||||
})
|
||||
resetConditionNodesErr()
|
||||
emits('update:nodeConfig', props.nodeConfig)
|
||||
}
|
||||
const delTerm = (index) => {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes.splice(index, 1)
|
||||
props.nodeConfig.conditionNodes.map((item, index) => {
|
||||
item.priorityLevel = index + 1
|
||||
item.nodeName = `条件${index + 1}`
|
||||
})
|
||||
resetConditionNodesErr()
|
||||
emits('update:nodeConfig', props.nodeConfig)
|
||||
if (props.nodeConfig.conditionNodes.length == 1) {
|
||||
if (props.nodeConfig.childNode) {
|
||||
if (props.nodeConfig.conditionNodes[0].childNode) {
|
||||
reData(props.nodeConfig.conditionNodes[0].childNode, props.nodeConfig.childNode)
|
||||
} else {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes[0].childNode = props.nodeConfig.childNode
|
||||
}
|
||||
}
|
||||
emits('update:nodeConfig', props.nodeConfig.conditionNodes[0].childNode)
|
||||
}
|
||||
}
|
||||
const reData = (data, addData) => {
|
||||
if (!data.childNode) {
|
||||
data.childNode = addData
|
||||
} else {
|
||||
reData(data.childNode, addData)
|
||||
}
|
||||
}
|
||||
const setPerson = (priorityLevel) => {
|
||||
var { type } = props.nodeConfig
|
||||
if (type == 0) {
|
||||
setPromoter(true)
|
||||
setFlowPermission({
|
||||
value: props.flowPermission,
|
||||
flag: false,
|
||||
id: _uid
|
||||
})
|
||||
} else if (type == 1) {
|
||||
setApprover(true)
|
||||
setApproverConfig({
|
||||
value: {
|
||||
...JSON.parse(JSON.stringify(props.nodeConfig)),
|
||||
...{ settype: props.nodeConfig.settype ? props.nodeConfig.settype : 1 }
|
||||
},
|
||||
flag: false,
|
||||
id: _uid
|
||||
})
|
||||
} else if (type == 2) {
|
||||
setCopyer(true)
|
||||
setCopyerConfig({
|
||||
value: JSON.parse(JSON.stringify(props.nodeConfig)),
|
||||
flag: false,
|
||||
id: _uid
|
||||
})
|
||||
} else {
|
||||
setCondition(true)
|
||||
setConditionsConfig({
|
||||
value: JSON.parse(JSON.stringify(props.nodeConfig)),
|
||||
priorityLevel,
|
||||
flag: false,
|
||||
id: _uid
|
||||
})
|
||||
}
|
||||
}
|
||||
const arrTransfer = (index, type = 1) => {
|
||||
//向左-1,向右1
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
props.nodeConfig.conditionNodes[index] = props.nodeConfig.conditionNodes.splice(
|
||||
index + type,
|
||||
1,
|
||||
props.nodeConfig.conditionNodes[index]
|
||||
)[0]
|
||||
props.nodeConfig.conditionNodes.map((item, index) => {
|
||||
item.priorityLevel = index + 1
|
||||
})
|
||||
resetConditionNodesErr()
|
||||
emits('update:nodeConfig', props.nodeConfig)
|
||||
}
|
||||
</script>
|
165
src/components/SimpleProcessDesigner/src/util.ts
Normal file
165
src/components/SimpleProcessDesigner/src/util.ts
Normal file
@ -0,0 +1,165 @@
|
||||
/**
|
||||
* todo
|
||||
*/
|
||||
export const arrToStr = (arr?: [{ name: string }]) => {
|
||||
if (arr) {
|
||||
return arr
|
||||
.map((item) => {
|
||||
return item.name
|
||||
})
|
||||
.toString()
|
||||
}
|
||||
}
|
||||
|
||||
export const setApproverStr = (nodeConfig: any) => {
|
||||
if (nodeConfig.settype == 1) {
|
||||
if (nodeConfig.nodeUserList.length == 1) {
|
||||
return nodeConfig.nodeUserList[0].name
|
||||
} else if (nodeConfig.nodeUserList.length > 1) {
|
||||
if (nodeConfig.examineMode == 1) {
|
||||
return arrToStr(nodeConfig.nodeUserList)
|
||||
} else if (nodeConfig.examineMode == 2) {
|
||||
return nodeConfig.nodeUserList.length + '人会签'
|
||||
}
|
||||
}
|
||||
} else if (nodeConfig.settype == 2) {
|
||||
const level =
|
||||
nodeConfig.directorLevel == 1 ? '直接主管' : '第' + nodeConfig.directorLevel + '级主管'
|
||||
if (nodeConfig.examineMode == 1) {
|
||||
return level
|
||||
} else if (nodeConfig.examineMode == 2) {
|
||||
return level + '会签'
|
||||
}
|
||||
} else if (nodeConfig.settype == 4) {
|
||||
if (nodeConfig.selectRange == 1) {
|
||||
return '发起人自选'
|
||||
} else {
|
||||
if (nodeConfig.nodeUserList.length > 0) {
|
||||
if (nodeConfig.selectRange == 2) {
|
||||
return '发起人自选'
|
||||
} else {
|
||||
return '发起人从' + nodeConfig.nodeUserList[0].name + '中自选'
|
||||
}
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
} else if (nodeConfig.settype == 5) {
|
||||
return '发起人自己'
|
||||
} else if (nodeConfig.settype == 7) {
|
||||
return '从直接主管到通讯录中级别最高的第' + nodeConfig.examineEndDirectorLevel + '个层级主管'
|
||||
}
|
||||
}
|
||||
|
||||
export const copyerStr = (nodeConfig: any) => {
|
||||
if (nodeConfig.nodeUserList.length != 0) {
|
||||
return arrToStr(nodeConfig.nodeUserList)
|
||||
} else {
|
||||
if (nodeConfig.ccSelfSelectFlag == 1) {
|
||||
return '发起人自选'
|
||||
}
|
||||
}
|
||||
}
|
||||
export const conditionStr = (nodeConfig, index) => {
|
||||
const { conditionList, nodeUserList } = nodeConfig.conditionNodes[index]
|
||||
if (conditionList.length == 0) {
|
||||
return index == nodeConfig.conditionNodes.length - 1 &&
|
||||
nodeConfig.conditionNodes[0].conditionList.length != 0
|
||||
? '其他条件进入此流程'
|
||||
: '请设置条件'
|
||||
} else {
|
||||
let str = ''
|
||||
for (let i = 0; i < conditionList.length; i++) {
|
||||
const {
|
||||
columnId,
|
||||
columnType,
|
||||
showType,
|
||||
showName,
|
||||
optType,
|
||||
zdy1,
|
||||
opt1,
|
||||
zdy2,
|
||||
opt2,
|
||||
fixedDownBoxValue
|
||||
} = conditionList[i]
|
||||
if (columnId == 0) {
|
||||
if (nodeUserList.length != 0) {
|
||||
str += '发起人属于:'
|
||||
str +=
|
||||
nodeUserList
|
||||
.map((item) => {
|
||||
return item.name
|
||||
})
|
||||
.join('或') + ' 并且 '
|
||||
}
|
||||
}
|
||||
if (columnType == 'String' && showType == '3') {
|
||||
if (zdy1) {
|
||||
str += showName + '属于:' + dealStr(zdy1, JSON.parse(fixedDownBoxValue)) + ' 并且 '
|
||||
}
|
||||
}
|
||||
if (columnType == 'Double') {
|
||||
if (optType != 6 && zdy1) {
|
||||
const optTypeStr = ['', '<', '>', '≤', '=', '≥'][optType]
|
||||
str += `${showName} ${optTypeStr} ${zdy1} 并且 `
|
||||
} else if (optType == 6 && zdy1 && zdy2) {
|
||||
str += `${zdy1} ${opt1} ${showName} ${opt2} ${zdy2} 并且 `
|
||||
}
|
||||
}
|
||||
}
|
||||
return str ? str.substring(0, str.length - 4) : '请设置条件'
|
||||
}
|
||||
}
|
||||
|
||||
export const dealStr = (str: string, obj) => {
|
||||
const arr = []
|
||||
const list = str.split(',')
|
||||
for (const elem in obj) {
|
||||
list.map((item) => {
|
||||
if (item == elem) {
|
||||
arr.push(obj[elem].value)
|
||||
}
|
||||
})
|
||||
}
|
||||
return arr.join('或')
|
||||
}
|
||||
|
||||
export const removeEle = (arr, elem, key = 'id') => {
|
||||
let includesIndex
|
||||
arr.map((item, index) => {
|
||||
if (item[key] == elem[key]) {
|
||||
includesIndex = index
|
||||
}
|
||||
})
|
||||
arr.splice(includesIndex, 1)
|
||||
}
|
||||
|
||||
export const bgColors = ['87, 106, 149', '255, 148, 62', '50, 150, 250']
|
||||
export const placeholderList = ['发起人', '审核人', '抄送人']
|
||||
export const setTypes = [
|
||||
{ value: 1, label: '指定成员' },
|
||||
{ value: 2, label: '主管' },
|
||||
{ value: 4, label: '发起人自选' },
|
||||
{ value: 5, label: '发起人自己' },
|
||||
{ value: 7, label: '连续多级主管' }
|
||||
]
|
||||
|
||||
export const selectModes = [
|
||||
{ value: 1, label: '选一个人' },
|
||||
{ value: 2, label: '选多个人' }
|
||||
]
|
||||
|
||||
export const selectRanges = [
|
||||
{ value: 1, label: '全公司' },
|
||||
{ value: 2, label: '指定成员' },
|
||||
{ value: 3, label: '指定角色' }
|
||||
]
|
||||
|
||||
export const optTypes = [
|
||||
{ value: '1', label: '小于' },
|
||||
{ value: '2', label: '大于' },
|
||||
{ value: '3', label: '小于等于' },
|
||||
{ value: '4', label: '等于' },
|
||||
{ value: '5', label: '大于等于' },
|
||||
{ value: '6', label: '介于两个数之间' }
|
||||
]
|
1292
src/components/SimpleProcessDesigner/theme/workflow.css
Normal file
1292
src/components/SimpleProcessDesigner/theme/workflow.css
Normal file
File diff suppressed because it is too large
Load Diff
@ -436,7 +436,7 @@ const initBpmnModeler = () => {
|
||||
|
||||
// bpmnModeler.createDiagram()
|
||||
|
||||
console.log(bpmnModeler, 'bpmnModeler111111')
|
||||
// console.log(bpmnModeler, 'bpmnModeler111111')
|
||||
emit('init-finished', bpmnModeler)
|
||||
initModelListeners()
|
||||
}
|
||||
@ -666,10 +666,10 @@ const previewProcessJson = () => {
|
||||
}
|
||||
/* ------------------------------------------------ 芋道源码 methods ------------------------------------------------------ */
|
||||
const processSave = async () => {
|
||||
console.log(bpmnModeler, 'bpmnModelerbpmnModelerbpmnModelerbpmnModeler')
|
||||
// console.log(bpmnModeler, 'bpmnModelerbpmnModelerbpmnModelerbpmnModeler')
|
||||
const { err, xml } = await bpmnModeler.saveXML()
|
||||
console.log(err, 'errerrerrerrerr')
|
||||
console.log(xml, 'xmlxmlxmlxmlxml')
|
||||
// console.log(err, 'errerrerrerrerr')
|
||||
// console.log(xml, 'xmlxmlxmlxmlxml')
|
||||
// 读取异常时抛出异常
|
||||
if (err) {
|
||||
// this.$modal.msgError('保存模型失败,请重试!')
|
||||
|
@ -115,19 +115,19 @@ const highlightDiagram = async () => {
|
||||
if (!task) {
|
||||
return
|
||||
}
|
||||
//进行中的任务已经高亮过了,则不高亮后面的任务了
|
||||
// 进行中的任务已经高亮过了,则不高亮后面的任务了
|
||||
if (findProcessTask) {
|
||||
removeTaskDefinitionKeyList.push(n.id)
|
||||
return
|
||||
}
|
||||
// 高亮任务
|
||||
canvas.addMarker(n.id, getResultCss(task.result))
|
||||
canvas.addMarker(n.id, getResultCss(task.status))
|
||||
//标记是否高亮了进行中任务
|
||||
if (task.result === 1) {
|
||||
if (task.status === 1) {
|
||||
findProcessTask = true
|
||||
}
|
||||
// 如果非通过,就不走后面的线条了
|
||||
if (task.result !== 2) {
|
||||
if (task.status !== 2) {
|
||||
return
|
||||
}
|
||||
// 处理 outgoing 出线
|
||||
@ -194,6 +194,7 @@ const highlightDiagram = async () => {
|
||||
})
|
||||
} else if (n.$type === 'bpmn:StartEvent') {
|
||||
// 开始节点
|
||||
canvas.addMarker(n.id, 'highlight')
|
||||
n.outgoing?.forEach((nn) => {
|
||||
// outgoing 例如说【bpmn:SequenceFlow】连线
|
||||
// 获得连线是否有指向目标。如果有,则进行高亮
|
||||
@ -205,10 +206,10 @@ const highlightDiagram = async () => {
|
||||
})
|
||||
} else if (n.$type === 'bpmn:EndEvent') {
|
||||
// 结束节点
|
||||
if (!processInstance.value || processInstance.value.result === 1) {
|
||||
if (!processInstance.value || processInstance.value.status === 1) {
|
||||
return
|
||||
}
|
||||
canvas.addMarker(n.id, getResultCss(processInstance.value.result))
|
||||
canvas.addMarker(n.id, getResultCss(processInstance.value.status))
|
||||
} else if (n.$type === 'bpmn:ServiceTask') {
|
||||
//服务任务
|
||||
if (activity.startTime > 0 && activity.endTime === 0) {
|
||||
@ -223,39 +224,49 @@ const highlightDiagram = async () => {
|
||||
canvas.addMarker(out.id, getResultCss(2))
|
||||
})
|
||||
}
|
||||
} else if (n.$type === 'bpmn:SequenceFlow') {
|
||||
let targetActivity = activityList.find((m: any) => m.key === n.targetRef.id)
|
||||
if (targetActivity) {
|
||||
canvas.addMarker(n.id, getActivityHighlightCss(targetActivity))
|
||||
}
|
||||
}
|
||||
})
|
||||
if (!isEmpty(removeTaskDefinitionKeyList)) {
|
||||
taskList.value = taskList.value.filter(
|
||||
(item) => !removeTaskDefinitionKeyList.includes(item.definitionKey)
|
||||
(item) => !removeTaskDefinitionKeyList.includes(item.taskDefinitionKey)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const getActivityHighlightCss = (activity) => {
|
||||
return activity.endTime ? 'highlight' : 'highlight-todo'
|
||||
}
|
||||
const getResultCss = (result) => {
|
||||
if (result === 1) {
|
||||
|
||||
const getResultCss = (status) => {
|
||||
if (status === 1) {
|
||||
// 审批中
|
||||
return 'highlight-todo'
|
||||
} else if (result === 2) {
|
||||
} else if (status === 2) {
|
||||
// 已通过
|
||||
return 'highlight'
|
||||
} else if (result === 3) {
|
||||
} else if (status === 3) {
|
||||
// 不通过
|
||||
return 'highlight-reject'
|
||||
} else if (result === 4) {
|
||||
} else if (status === 4) {
|
||||
// 已取消
|
||||
return 'highlight-cancel'
|
||||
} else if (result === 5) {
|
||||
} else if (status === 5) {
|
||||
// 退回
|
||||
return 'highlight-return'
|
||||
} else if (result === 6) {
|
||||
} else if (status === 6) {
|
||||
// 委派
|
||||
return 'highlight-return'
|
||||
} else if (result === 7 || result === 8 || result === 9) {
|
||||
// 待后加签任务完成/待前加签任务完成/待前置任务完成
|
||||
return 'highlight-return'
|
||||
return 'highlight-todo'
|
||||
} else if (status === 7) {
|
||||
// 审批通过中
|
||||
return 'highlight-todo'
|
||||
} else if (status === 0) {
|
||||
// 待审批
|
||||
return 'highlight-todo'
|
||||
}
|
||||
return ''
|
||||
}
|
||||
@ -296,10 +307,10 @@ const elementHover = (element) => {
|
||||
!elementOverlayIds.value && (elementOverlayIds.value = {})
|
||||
!overlays.value && (overlays.value = bpmnModeler.get('overlays'))
|
||||
// 展示信息
|
||||
console.log(activityLists.value, 'activityLists.value')
|
||||
console.log(element.value, 'element.value')
|
||||
// console.log(activityLists.value, 'activityLists.value')
|
||||
// console.log(element.value, 'element.value')
|
||||
const activity = activityLists.value.find((m) => m.key === element.value.id)
|
||||
console.log(activity, 'activityactivityactivityactivity')
|
||||
// console.log(activity, 'activityactivityactivityactivity')
|
||||
if (!activity) {
|
||||
return
|
||||
}
|
||||
@ -313,15 +324,14 @@ const elementHover = (element) => {
|
||||
<p>部门:${processInstance.value.startUser.deptName}</p>
|
||||
<p>创建时间:${formatDate(processInstance.value.createTime)}`
|
||||
} else if (element.value.type === 'bpmn:UserTask') {
|
||||
// debugger
|
||||
let task = taskList.value.find((m) => m.id === activity.taskId) // 找到活动对应的 taskId
|
||||
if (!task) {
|
||||
return
|
||||
}
|
||||
let optionData = getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)
|
||||
let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS)
|
||||
let dataResult = ''
|
||||
optionData.forEach((element) => {
|
||||
if (element.value == task.result) {
|
||||
if (element.value == task.status) {
|
||||
dataResult = element.label
|
||||
}
|
||||
})
|
||||
@ -333,7 +343,7 @@ const elementHover = (element) => {
|
||||
// <p>部门:${task.assigneeUser.deptName}</p>
|
||||
// <p>结果:${getIntDictOptions(
|
||||
// DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
|
||||
// task.result
|
||||
// task.status
|
||||
// )}</p>
|
||||
// <p>创建时间:${formatDate(task.createTime)}</p>`
|
||||
if (task.endTime) {
|
||||
@ -351,29 +361,30 @@ const elementHover = (element) => {
|
||||
}
|
||||
console.log(html)
|
||||
} else if (element.value.type === 'bpmn:EndEvent' && processInstance.value) {
|
||||
let optionData = getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)
|
||||
let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS)
|
||||
let dataResult = ''
|
||||
optionData.forEach((element) => {
|
||||
if (element.value == processInstance.value.result) {
|
||||
if (element.value == processInstance.value.status) {
|
||||
dataResult = element.label
|
||||
}
|
||||
})
|
||||
html = `<p>结果:${dataResult}</p>`
|
||||
// html = `<p>结果:${getIntDictOptions(
|
||||
// DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
|
||||
// processInstance.value.result
|
||||
// processInstance.value.status
|
||||
// )}</p>`
|
||||
if (processInstance.value.endTime) {
|
||||
html += `<p>结束时间:${formatDate(processInstance.value.endTime)}</p>`
|
||||
}
|
||||
}
|
||||
console.log(html, 'html111111111111111')
|
||||
// console.log(html, 'html111111111111111')
|
||||
elementOverlayIds.value[element.value.id] = toRaw(overlays.value)?.add(element.value, {
|
||||
position: { left: 0, bottom: 0 },
|
||||
html: `<div class="element-overlays">${html}</div>`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 流程图的元素被 out
|
||||
const elementOut = (element) => {
|
||||
toRaw(overlays.value).remove({ element })
|
||||
@ -389,6 +400,7 @@ onMounted(() => {
|
||||
// 初始模型的监听器
|
||||
initModelListeners()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
// this.$once('hook:beforeDestroy', () => {
|
||||
// })
|
||||
@ -427,7 +439,7 @@ watch(
|
||||
)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
<style lang="scss">
|
||||
/** 处理中 */
|
||||
.highlight-todo.djs-connection > .djs-visual > path {
|
||||
stroke: #1890ff !important;
|
||||
@ -501,6 +513,10 @@ watch(
|
||||
stroke: green !important;
|
||||
}
|
||||
|
||||
.djs-element.highlight > .djs-visual > path {
|
||||
stroke: green !important;
|
||||
}
|
||||
|
||||
/** 不通过 */
|
||||
.highlight-reject.djs-shape .djs-visual > :nth-child(1) {
|
||||
fill: red !important;
|
||||
@ -520,6 +536,7 @@ watch(
|
||||
|
||||
.highlight-reject.djs-connection > .djs-visual > path {
|
||||
stroke: red !important;
|
||||
marker-end: url(#sequenceflow-end-white-success) !important;
|
||||
}
|
||||
|
||||
.highlight-reject:not(.djs-connection) .djs-visual > :nth-child(1) {
|
||||
|
@ -332,6 +332,16 @@
|
||||
"name": "multiinstance_condition",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateStrategy",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateParam",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -319,6 +319,16 @@
|
||||
"name": "priority",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateStrategy",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateParam",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -319,6 +319,16 @@
|
||||
"name": "priority",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateStrategy",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
},
|
||||
{
|
||||
"name": "candidateParam",
|
||||
"isAttr": true,
|
||||
"type": "String"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -24,15 +24,10 @@
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="condition" v-if="formVisible" key="form">
|
||||
<template #title><Icon icon="ep:list" />表单</template>
|
||||
<!-- <element-form :id="elementId" :type="elementType" /> -->
|
||||
友情提示:使用
|
||||
<router-link :to="{ path: '/bpm/manager/form' }"
|
||||
><el-link type="danger">流程表单</el-link>
|
||||
</router-link>
|
||||
替代,提供更好的表单设计功能
|
||||
<element-form :id="elementId" :type="elementType" />
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="task" v-if="elementType.indexOf('Task') !== -1" key="task">
|
||||
<template #title><Icon icon="ep:checked" />任务</template>
|
||||
<template #title><Icon icon="ep:checked" />任务(审批人)</template>
|
||||
<element-task :id="elementId" :type="elementType" />
|
||||
</el-collapse-item>
|
||||
<el-collapse-item
|
||||
@ -40,7 +35,7 @@
|
||||
v-if="elementType.indexOf('Task') !== -1"
|
||||
key="multiInstance"
|
||||
>
|
||||
<template #title><Icon icon="ep:help-filled" />多实例</template>
|
||||
<template #title><Icon icon="ep:help-filled" />多实例(会签配置)</template>
|
||||
<element-multi-instance :business-object="elementBusinessObject" :type="elementType" />
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="listeners" key="listeners">
|
||||
|
@ -3,13 +3,6 @@
|
||||
<el-form label-width="90px" :model="needProps" :rules="rules">
|
||||
<div v-if="needProps.type == 'bpmn:Process'">
|
||||
<!-- 如果是 Process 信息的时候,使用自定义表单 -->
|
||||
<el-link
|
||||
href="https://doc.iocoder.cn/bpm/#_3-%E6%B5%81%E7%A8%8B%E5%9B%BE%E7%A4%BA%E4%BE%8B"
|
||||
type="danger"
|
||||
target="_blank"
|
||||
>
|
||||
如何实现实现会签、或签?
|
||||
</el-link>
|
||||
<el-form-item label="流程标识" prop="id">
|
||||
<el-input
|
||||
v-model="needProps.id"
|
||||
@ -68,13 +61,13 @@ const resetBaseInfo = () => {
|
||||
console.log(bpmnElement.value, 'bpmnElement')
|
||||
|
||||
bpmnElement.value = bpmnInstances()?.bpmnElement
|
||||
console.log(bpmnElement.value, 'resetBaseInfo11111111111')
|
||||
// console.log(bpmnElement.value, 'resetBaseInfo11111111111')
|
||||
elementBaseInfo.value = bpmnElement.value.businessObject
|
||||
needProps.value['type'] = bpmnElement.value.businessObject.$type
|
||||
// elementBaseInfo.value['typess'] = bpmnElement.value.businessObject.$type
|
||||
|
||||
// elementBaseInfo.value = JSON.parse(JSON.stringify(bpmnElement.value.businessObject))
|
||||
console.log(elementBaseInfo.value, 'elementBaseInfo22222222222')
|
||||
// console.log(elementBaseInfo.value, 'elementBaseInfo22222222222')
|
||||
}
|
||||
const handleKeyUpdate = (value) => {
|
||||
// 校验 value 的值,只有 XML NCName 通过的情况下,才进行赋值。否则,会导致流程图报错,无法绘制的问题
|
||||
@ -121,11 +114,11 @@ const updateBaseInfo = (key) => {
|
||||
// id: elementBaseInfo.value[key]
|
||||
// // di: { id: `${elementBaseInfo.value[key]}_di` }
|
||||
// }
|
||||
console.log(elementBaseInfo, 'elementBaseInfo11111111111')
|
||||
// console.log(elementBaseInfo, 'elementBaseInfo11111111111')
|
||||
needProps.value = { ...elementBaseInfo.value, ...needProps.value }
|
||||
|
||||
if (key === 'id') {
|
||||
console.log('jinru')
|
||||
// console.log('jinru')
|
||||
console.log(window, 'window')
|
||||
console.log(bpmnElement.value, 'bpmnElement')
|
||||
console.log(toRaw(bpmnElement.value), 'bpmnElement')
|
||||
@ -138,20 +131,11 @@ const updateBaseInfo = (key) => {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), attrObj)
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
// 针对上传的 bpmn 流程图时,需要延迟 1 秒的时间,保证 key 和 name 的更新
|
||||
setTimeout(() => {
|
||||
console.log(props.model, 'props.model')
|
||||
handleKeyUpdate(props.model.key)
|
||||
handleNameUpdate(props.model.name)
|
||||
console.log(props, 'propsssssssssssssssssssss')
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.businessObject,
|
||||
(val) => {
|
||||
console.log(val, 'val11111111111111111111')
|
||||
// console.log(val, 'val11111111111111111111')
|
||||
if (val) {
|
||||
// nextTick(() => {
|
||||
resetBaseInfo()
|
||||
@ -159,6 +143,18 @@ watch(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.model?.key,
|
||||
(val) => {
|
||||
// 针对上传的 bpmn 流程图时,保证 key 和 name 的更新
|
||||
if (val) {
|
||||
handleKeyUpdate(props.model.key)
|
||||
handleNameUpdate(props.model.name)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// watch(
|
||||
// () => ({ ...props }),
|
||||
// (oldVal, newVal) => {
|
||||
|
@ -1,228 +1,233 @@
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<el-form label-width="80px">
|
||||
<el-form-item label="表单标识">
|
||||
<el-input v-model="formKey" clearable @change="updateElementFormKey" />
|
||||
</el-form-item>
|
||||
<el-form-item label="业务标识">
|
||||
<el-select v-model="businessKey" @change="updateElementBusinessKey">
|
||||
<el-option v-for="i in fieldList" :key="i.id" :value="i.id" :label="i.label" />
|
||||
<el-option label="无" value="" />
|
||||
<el-form-item label="流程表单">
|
||||
<!-- <el-input v-model="formKey" clearable @change="updateElementFormKey" />-->
|
||||
<el-select v-model="formKey" clearable @change="updateElementFormKey">
|
||||
<el-option v-for="form in formList" :key="form.id" :label="form.name" :value="form.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="业务标识">-->
|
||||
<!-- <el-select v-model="businessKey" @change="updateElementBusinessKey">-->
|
||||
<!-- <el-option v-for="i in fieldList" :key="i.id" :value="i.id" :label="i.label" />-->
|
||||
<!-- <el-option label="无" value="" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
</el-form>
|
||||
|
||||
<!--字段列表-->
|
||||
<div class="element-property list-property">
|
||||
<el-divider><Icon icon="ep:coin" /> 表单字段</el-divider>
|
||||
<el-table :data="fieldList" max-height="240" fit border>
|
||||
<el-table-column label="序号" type="index" width="50px" />
|
||||
<el-table-column label="字段名称" prop="label" min-width="80px" show-overflow-tooltip />
|
||||
<el-table-column
|
||||
label="字段类型"
|
||||
prop="type"
|
||||
min-width="80px"
|
||||
:formatter="(row) => fieldType[row.type] || row.type"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
label="默认值"
|
||||
prop="defaultValue"
|
||||
min-width="80px"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column label="操作" width="90px">
|
||||
<template #default="scope">
|
||||
<el-button type="primary" link @click="openFieldForm(scope, scope.$index)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeField(scope, scope.$index)"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="element-drawer__button">
|
||||
<XButton type="primary" proIcon="ep:plus" title="添加字段" @click="openFieldForm(null, -1)" />
|
||||
</div>
|
||||
<!-- <div class="element-property list-property">-->
|
||||
<!-- <el-divider><Icon icon="ep:coin" /> 表单字段</el-divider>-->
|
||||
<!-- <el-table :data="fieldList" max-height="240" fit border>-->
|
||||
<!-- <el-table-column label="序号" type="index" width="50px" />-->
|
||||
<!-- <el-table-column label="字段名称" prop="label" min-width="80px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- label="字段类型"-->
|
||||
<!-- prop="type"-->
|
||||
<!-- min-width="80px"-->
|
||||
<!-- :formatter="(row) => fieldType[row.type] || row.type"-->
|
||||
<!-- show-overflow-tooltip-->
|
||||
<!-- />-->
|
||||
<!-- <el-table-column-->
|
||||
<!-- label="默认值"-->
|
||||
<!-- prop="defaultValue"-->
|
||||
<!-- min-width="80px"-->
|
||||
<!-- show-overflow-tooltip-->
|
||||
<!-- />-->
|
||||
<!-- <el-table-column label="操作" width="90px">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button type="primary" link @click="openFieldForm(scope, scope.$index)"-->
|
||||
<!-- >编辑</el-button-->
|
||||
<!-- >-->
|
||||
<!-- <el-divider direction="vertical" />-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- style="color: #ff4d4f"-->
|
||||
<!-- @click="removeField(scope, scope.$index)"-->
|
||||
<!-- >移除</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="element-drawer__button">-->
|
||||
<!-- <XButton type="primary" proIcon="ep:plus" title="添加字段" @click="openFieldForm(null, -1)" />-->
|
||||
<!-- </div>-->
|
||||
|
||||
<!--字段配置侧边栏-->
|
||||
<el-drawer
|
||||
v-model="fieldModelVisible"
|
||||
title="字段配置"
|
||||
:size="`${width}px`"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form :model="formFieldForm" label-width="90px">
|
||||
<el-form-item label="字段ID">
|
||||
<el-input v-model="formFieldForm.id" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="类型">
|
||||
<el-select
|
||||
v-model="formFieldForm.typeType"
|
||||
placeholder="请选择字段类型"
|
||||
clearable
|
||||
@change="changeFieldTypeType"
|
||||
>
|
||||
<el-option v-for="(value, key) of fieldType" :label="value" :value="key" :key="key" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="类型名称" v-if="formFieldForm.typeType === 'custom'">
|
||||
<el-input v-model="formFieldForm.type" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称">
|
||||
<el-input v-model="formFieldForm.label" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="时间格式" v-if="formFieldForm.typeType === 'date'">
|
||||
<el-input v-model="formFieldForm.datePattern" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="默认值">
|
||||
<el-input v-model="formFieldForm.defaultValue" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- <el-drawer-->
|
||||
<!-- v-model="fieldModelVisible"-->
|
||||
<!-- title="字段配置"-->
|
||||
<!-- :size="`${width}px`"-->
|
||||
<!-- append-to-body-->
|
||||
<!-- destroy-on-close-->
|
||||
<!-- >-->
|
||||
<!-- <el-form :model="formFieldForm" label-width="90px">-->
|
||||
<!-- <el-form-item label="字段ID">-->
|
||||
<!-- <el-input v-model="formFieldForm.id" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="类型">-->
|
||||
<!-- <el-select-->
|
||||
<!-- v-model="formFieldForm.typeType"-->
|
||||
<!-- placeholder="请选择字段类型"-->
|
||||
<!-- clearable-->
|
||||
<!-- @change="changeFieldTypeType"-->
|
||||
<!-- >-->
|
||||
<!-- <el-option v-for="(value, key) of fieldType" :label="value" :value="key" :key="key" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="类型名称" v-if="formFieldForm.typeType === 'custom'">-->
|
||||
<!-- <el-input v-model="formFieldForm.type" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="名称">-->
|
||||
<!-- <el-input v-model="formFieldForm.label" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="时间格式" v-if="formFieldForm.typeType === 'date'">-->
|
||||
<!-- <el-input v-model="formFieldForm.datePattern" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="默认值">-->
|
||||
<!-- <el-input v-model="formFieldForm.defaultValue" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-form>-->
|
||||
|
||||
<!-- 枚举值设置 -->
|
||||
<template v-if="formFieldForm.type === 'enum'">
|
||||
<el-divider key="enum-divider" />
|
||||
<p class="listener-filed__title" key="enum-title">
|
||||
<span><Icon icon="ep:menu" />枚举值列表:</span>
|
||||
<el-button type="primary" @click="openFieldOptionForm(null, -1, 'enum')"
|
||||
>添加枚举值</el-button
|
||||
>
|
||||
</p>
|
||||
<el-table :data="fieldEnumList" key="enum-table" max-height="240" fit border>
|
||||
<el-table-column label="序号" width="50px" type="index" />
|
||||
<el-table-column label="枚举值编号" prop="id" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="枚举值名称" prop="name" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="90px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="openFieldOptionForm(scope, scope.$index, 'enum')"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'enum')"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</template>
|
||||
<!-- <!– 枚举值设置 –>-->
|
||||
<!-- <template v-if="formFieldForm.type === 'enum'">-->
|
||||
<!-- <el-divider key="enum-divider" />-->
|
||||
<!-- <p class="listener-filed__title" key="enum-title">-->
|
||||
<!-- <span><Icon icon="ep:menu" />枚举值列表:</span>-->
|
||||
<!-- <el-button type="primary" @click="openFieldOptionForm(null, -1, 'enum')"-->
|
||||
<!-- >添加枚举值</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </p>-->
|
||||
<!-- <el-table :data="fieldEnumList" key="enum-table" max-height="240" fit border>-->
|
||||
<!-- <el-table-column label="序号" width="50px" type="index" />-->
|
||||
<!-- <el-table-column label="枚举值编号" prop="id" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="枚举值名称" prop="name" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="操作" width="90px">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- @click="openFieldOptionForm(scope, scope.$index, 'enum')"-->
|
||||
<!-- >编辑</el-button-->
|
||||
<!-- >-->
|
||||
<!-- <el-divider direction="vertical" />-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- style="color: #ff4d4f"-->
|
||||
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'enum')"-->
|
||||
<!-- >移除</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
<!-- </template>-->
|
||||
|
||||
<!-- 校验规则 -->
|
||||
<el-divider key="validation-divider" />
|
||||
<p class="listener-filed__title" key="validation-title">
|
||||
<span><Icon icon="ep:menu" />约束条件列表:</span>
|
||||
<el-button type="primary" @click="openFieldOptionForm(null, -1, 'constraint')"
|
||||
>添加约束</el-button
|
||||
>
|
||||
</p>
|
||||
<el-table :data="fieldConstraintsList" key="validation-table" max-height="240" fit border>
|
||||
<el-table-column label="序号" width="50px" type="index" />
|
||||
<el-table-column label="约束名称" prop="name" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="约束配置" prop="config" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="90px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="openFieldOptionForm(scope, scope.$index, 'constraint')"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'constraint')"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- <!– 校验规则 –>-->
|
||||
<!-- <el-divider key="validation-divider" />-->
|
||||
<!-- <p class="listener-filed__title" key="validation-title">-->
|
||||
<!-- <span><Icon icon="ep:menu" />约束条件列表:</span>-->
|
||||
<!-- <el-button type="primary" @click="openFieldOptionForm(null, -1, 'constraint')"-->
|
||||
<!-- >添加约束</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </p>-->
|
||||
<!-- <el-table :data="fieldConstraintsList" key="validation-table" max-height="240" fit border>-->
|
||||
<!-- <el-table-column label="序号" width="50px" type="index" />-->
|
||||
<!-- <el-table-column label="约束名称" prop="name" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="约束配置" prop="config" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="操作" width="90px">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- @click="openFieldOptionForm(scope, scope.$index, 'constraint')"-->
|
||||
<!-- >编辑</el-button-->
|
||||
<!-- >-->
|
||||
<!-- <el-divider direction="vertical" />-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- style="color: #ff4d4f"-->
|
||||
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'constraint')"-->
|
||||
<!-- >移除</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
|
||||
<!-- 表单属性 -->
|
||||
<el-divider key="property-divider" />
|
||||
<p class="listener-filed__title" key="property-title">
|
||||
<span><Icon icon="ep:menu" />字段属性列表:</span>
|
||||
<el-button type="primary" @click="openFieldOptionForm(null, -1, 'property')"
|
||||
>添加属性</el-button
|
||||
>
|
||||
</p>
|
||||
<el-table :data="fieldPropertiesList" key="property-table" max-height="240" fit border>
|
||||
<el-table-column label="序号" width="50px" type="index" />
|
||||
<el-table-column label="属性编号" prop="id" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="属性值" prop="value" min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="90px">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@click="openFieldOptionForm(scope, scope.$index, 'property')"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-divider direction="vertical" />
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
style="color: #ff4d4f"
|
||||
@click="removeFieldOptionItem(scope, scope.$index, 'property')"
|
||||
>移除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- <!– 表单属性 –>-->
|
||||
<!-- <el-divider key="property-divider" />-->
|
||||
<!-- <p class="listener-filed__title" key="property-title">-->
|
||||
<!-- <span><Icon icon="ep:menu" />字段属性列表:</span>-->
|
||||
<!-- <el-button type="primary" @click="openFieldOptionForm(null, -1, 'property')"-->
|
||||
<!-- >添加属性</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </p>-->
|
||||
<!-- <el-table :data="fieldPropertiesList" key="property-table" max-height="240" fit border>-->
|
||||
<!-- <el-table-column label="序号" width="50px" type="index" />-->
|
||||
<!-- <el-table-column label="属性编号" prop="id" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="属性值" prop="value" min-width="100px" show-overflow-tooltip />-->
|
||||
<!-- <el-table-column label="操作" width="90px">-->
|
||||
<!-- <template #default="scope">-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- @click="openFieldOptionForm(scope, scope.$index, 'property')"-->
|
||||
<!-- >编辑</el-button-->
|
||||
<!-- >-->
|
||||
<!-- <el-divider direction="vertical" />-->
|
||||
<!-- <el-button-->
|
||||
<!-- type="primary"-->
|
||||
<!-- link-->
|
||||
<!-- style="color: #ff4d4f"-->
|
||||
<!-- @click="removeFieldOptionItem(scope, scope.$index, 'property')"-->
|
||||
<!-- >移除</el-button-->
|
||||
<!-- >-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<!-- </el-table>-->
|
||||
|
||||
<!-- 底部按钮 -->
|
||||
<div class="element-drawer__button">
|
||||
<el-button>取 消</el-button>
|
||||
<el-button type="primary" @click="saveField">保 存</el-button>
|
||||
</div>
|
||||
</el-drawer>
|
||||
<!-- <!– 底部按钮 –>-->
|
||||
<!-- <div class="element-drawer__button">-->
|
||||
<!-- <el-button>取 消</el-button>-->
|
||||
<!-- <el-button type="primary" @click="saveField">保 存</el-button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </el-drawer>-->
|
||||
|
||||
<el-dialog
|
||||
v-model="fieldOptionModelVisible"
|
||||
:title="optionModelTitle"
|
||||
width="600px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
>
|
||||
<el-form :model="fieldOptionForm" label-width="96px">
|
||||
<el-form-item label="编号/ID" v-if="fieldOptionType !== 'constraint'" key="option-id">
|
||||
<el-input v-model="fieldOptionForm.id" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="名称" v-if="fieldOptionType !== 'property'" key="option-name">
|
||||
<el-input v-model="fieldOptionForm.name" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="配置" v-if="fieldOptionType === 'constraint'" key="option-config">
|
||||
<el-input v-model="fieldOptionForm.config" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="值" v-if="fieldOptionType === 'property'" key="option-value">
|
||||
<el-input v-model="fieldOptionForm.value" clearable />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="fieldOptionModelVisible = false">取 消</el-button>
|
||||
<el-button type="primary" @click="saveFieldOption">确 定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- <el-dialog-->
|
||||
<!-- v-model="fieldOptionModelVisible"-->
|
||||
<!-- :title="optionModelTitle"-->
|
||||
<!-- width="600px"-->
|
||||
<!-- append-to-body-->
|
||||
<!-- destroy-on-close-->
|
||||
<!-- >-->
|
||||
<!-- <el-form :model="fieldOptionForm" label-width="96px">-->
|
||||
<!-- <el-form-item label="编号/ID" v-if="fieldOptionType !== 'constraint'" key="option-id">-->
|
||||
<!-- <el-input v-model="fieldOptionForm.id" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="名称" v-if="fieldOptionType !== 'property'" key="option-name">-->
|
||||
<!-- <el-input v-model="fieldOptionForm.name" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="配置" v-if="fieldOptionType === 'constraint'" key="option-config">-->
|
||||
<!-- <el-input v-model="fieldOptionForm.config" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="值" v-if="fieldOptionType === 'property'" key="option-value">-->
|
||||
<!-- <el-input v-model="fieldOptionForm.value" clearable />-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- </el-form>-->
|
||||
<!-- <template #footer>-->
|
||||
<!-- <el-button @click="fieldOptionModelVisible = false">取 消</el-button>-->
|
||||
<!-- <el-button type="primary" @click="saveFieldOption">确 定</el-button>-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-dialog>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as FormApi from '@/api/bpm/form'
|
||||
|
||||
defineOptions({ name: 'ElementForm' })
|
||||
|
||||
const props = defineProps({
|
||||
@ -263,6 +268,9 @@ const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
const resetFormList = () => {
|
||||
bpmnELement.value = bpmnInstances().bpmnElement
|
||||
formKey.value = bpmnELement.value.businessObject.formKey
|
||||
if (formKey.value?.length > 0) {
|
||||
formKey.value = parseInt(formKey.value)
|
||||
}
|
||||
// 获取元素扩展属性 或者 创建扩展属性
|
||||
elExtensionElements.value =
|
||||
bpmnELement.value.businessObject.get('extensionElements') ||
|
||||
@ -421,7 +429,7 @@ const saveField = () => {
|
||||
|
||||
// 移除某个 字段的 配置项
|
||||
const removeFieldOptionItem = (option, index, type) => {
|
||||
console.log(option, 'option')
|
||||
// console.log(option, 'option')
|
||||
if (type === 'property') {
|
||||
fieldPropertiesList.value.splice(index, 1)
|
||||
return
|
||||
@ -451,6 +459,11 @@ const updateElementExtensions = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const formList = ref([]) // 流程表单的下拉框的数据
|
||||
onMounted(async () => {
|
||||
formList.value = await FormApi.getFormSimpleList()
|
||||
})
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
(val) => {
|
||||
|
@ -26,8 +26,16 @@
|
||||
type="primary"
|
||||
preIcon="ep:plus"
|
||||
title="添加监听器"
|
||||
size="small"
|
||||
@click="openListenerForm(null)"
|
||||
/>
|
||||
<XButton
|
||||
type="success"
|
||||
preIcon="ep:select"
|
||||
title="选择监听器"
|
||||
size="small"
|
||||
@click="openProcessListenerDialog"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 监听器 编辑/创建 部分 -->
|
||||
@ -240,11 +248,21 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<!-- 选择弹窗 -->
|
||||
<ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { createListenerObject, updateElementExtensions } from '../../utils'
|
||||
import { initListenerType, initListenerForm, listenerType, fieldType } from './utilSelf'
|
||||
import {
|
||||
initListenerType,
|
||||
initListenerForm,
|
||||
listenerType,
|
||||
fieldType,
|
||||
initListenerForm2
|
||||
} from './utilSelf'
|
||||
import ProcessListenerDialog from './ProcessListenerDialog.vue'
|
||||
|
||||
defineOptions({ name: 'ElementListeners' })
|
||||
|
||||
@ -284,6 +302,7 @@ const resetListenersList = () => {
|
||||
}
|
||||
// 打开 监听器详情 侧边栏
|
||||
const openListenerForm = (listener, index?) => {
|
||||
// debugger
|
||||
if (listener) {
|
||||
listenerForm.value = initListenerForm(listener)
|
||||
editingListenerIndex.value = index
|
||||
@ -321,6 +340,7 @@ const openListenerFieldForm = (field, index?) => {
|
||||
}
|
||||
// 保存监听器注入字段
|
||||
const saveListenerFiled = async () => {
|
||||
// debugger
|
||||
let validateStatus = await listenerFieldFormRef.value.validate()
|
||||
if (!validateStatus) return // 验证不通过直接返回
|
||||
if (editingListenerFieldIndex.value === -1) {
|
||||
@ -337,6 +357,7 @@ const saveListenerFiled = async () => {
|
||||
}
|
||||
// 移除监听器字段
|
||||
const removeListenerField = (index) => {
|
||||
// debugger
|
||||
ElMessageBox.confirm('确认移除该字段吗?', '提示', {
|
||||
confirmButtonText: '确 认',
|
||||
cancelButtonText: '取 消'
|
||||
@ -349,6 +370,7 @@ const removeListenerField = (index) => {
|
||||
}
|
||||
// 移除监听器
|
||||
const removeListener = (index) => {
|
||||
debugger
|
||||
ElMessageBox.confirm('确认移除该监听器吗?', '提示', {
|
||||
confirmButtonText: '确 认',
|
||||
cancelButtonText: '取 消'
|
||||
@ -365,6 +387,7 @@ const removeListener = (index) => {
|
||||
}
|
||||
// 保存监听器配置
|
||||
const saveListenerConfig = async () => {
|
||||
// debugger
|
||||
let validateStatus = await listenerFormRef.value.validate()
|
||||
if (!validateStatus) return // 验证不通过直接返回
|
||||
const listenerObject = createListenerObject(listenerForm.value, false, prefix)
|
||||
@ -389,6 +412,28 @@ const saveListenerConfig = async () => {
|
||||
listenerForm.value = {}
|
||||
}
|
||||
|
||||
// 打开监听器弹窗
|
||||
const processListenerDialogRef = ref()
|
||||
const openProcessListenerDialog = async () => {
|
||||
processListenerDialogRef.value.open('execution')
|
||||
}
|
||||
const selectProcessListener = (listener) => {
|
||||
const listenerForm = initListenerForm2(listener)
|
||||
const listenerObject = createListenerObject(listenerForm, false, prefix)
|
||||
bpmnElementListeners.value.push(listenerObject)
|
||||
elementListenersList.value.push(listenerForm)
|
||||
|
||||
// 保存其他配置
|
||||
otherExtensionList.value =
|
||||
bpmnElement.value.businessObject?.extensionElements?.values?.filter(
|
||||
(ex) => ex.$type !== `${prefix}:ExecutionListener`
|
||||
) ?? []
|
||||
updateElementExtensions(
|
||||
bpmnElement.value,
|
||||
otherExtensionList.value.concat(bpmnElementListeners.value)
|
||||
)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
(val) => {
|
||||
|
@ -0,0 +1,83 @@
|
||||
<!-- 执行器选择 -->
|
||||
<template>
|
||||
<Dialog title="请选择监听器" v-model="dialogVisible" width="1024px">
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="类型" align="center" prop="type">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.BPM_PROCESS_LISTENER_TYPE" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="事件" align="center" prop="event" />
|
||||
<el-table-column label="值类型" align="center" prop="valueType">
|
||||
<template #default="scope">
|
||||
<dict-tag
|
||||
:type="DICT_TYPE.BPM_PROCESS_LISTENER_VALUE_TYPE"
|
||||
:value="scope.row.valueType"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="值" align="center" prop="value" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="select(scope.row)"> 选择 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { ProcessListenerApi, ProcessListenerVO } from '@/api/bpm/processListener'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
|
||||
/** BPM 流程 表单 */
|
||||
defineOptions({ name: 'ProcessListenerDialog' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<ProcessListenerVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
type: undefined,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
})
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string) => {
|
||||
dialogVisible.value = true
|
||||
loading.value = true
|
||||
try {
|
||||
queryParams.pageNo = 1
|
||||
queryParams.type = type
|
||||
const data = await ProcessListenerApi.getProcessListenerPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const select = async (row) => {
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('select', row)
|
||||
}
|
||||
</script>
|
@ -39,6 +39,13 @@
|
||||
title="添加监听器"
|
||||
@click="openListenerForm(null)"
|
||||
/>
|
||||
<XButton
|
||||
type="success"
|
||||
preIcon="ep:select"
|
||||
title="选择监听器"
|
||||
size="small"
|
||||
@click="openProcessListenerDialog"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 监听器 编辑/创建 部分 -->
|
||||
@ -286,11 +293,22 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<!-- 选择弹窗 -->
|
||||
<ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { createListenerObject, updateElementExtensions } from '../../utils'
|
||||
import { initListenerForm, initListenerType, eventType, listenerType, fieldType } from './utilSelf'
|
||||
import {
|
||||
initListenerForm,
|
||||
initListenerType,
|
||||
eventType,
|
||||
listenerType,
|
||||
fieldType,
|
||||
initListenerForm2
|
||||
} from './utilSelf'
|
||||
import ProcessListenerDialog from '@/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue'
|
||||
|
||||
defineOptions({ name: 'UserTaskListeners' })
|
||||
|
||||
@ -437,6 +455,28 @@ const removeListenerField = (field, index) => {
|
||||
.catch(() => console.info('操作取消'))
|
||||
}
|
||||
|
||||
// 打开监听器弹窗
|
||||
const processListenerDialogRef = ref()
|
||||
const openProcessListenerDialog = async () => {
|
||||
processListenerDialogRef.value.open('task')
|
||||
}
|
||||
const selectProcessListener = (listener) => {
|
||||
const listenerForm = initListenerForm2(listener)
|
||||
const listenerObject = createListenerObject(listenerForm, true, prefix)
|
||||
bpmnElementListeners.value.push(listenerObject)
|
||||
elementListenersList.value.push(listenerForm)
|
||||
|
||||
// 保存其他配置
|
||||
otherExtensionList.value =
|
||||
bpmnElement.value.businessObject?.extensionElements?.values?.filter(
|
||||
(ex) => ex.$type !== `${prefix}:TaskListener`
|
||||
) ?? []
|
||||
updateElementExtensions(
|
||||
bpmnElement.value,
|
||||
otherExtensionList.value.concat(bpmnElementListeners.value)
|
||||
)
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.id,
|
||||
(val) => {
|
||||
|
@ -40,6 +40,33 @@ export function initListenerType(listener) {
|
||||
}
|
||||
}
|
||||
|
||||
/** 将 ProcessListenerDO 转换成 initListenerForm 想同的 Form 对象 */
|
||||
export function initListenerForm2(processListener) {
|
||||
if (processListener.valueType === 'class') {
|
||||
return {
|
||||
listenerType: 'classListener',
|
||||
class: processListener.value,
|
||||
event: processListener.event,
|
||||
fields: []
|
||||
}
|
||||
} else if (processListener.valueType === 'expression') {
|
||||
return {
|
||||
listenerType: 'expressionListener',
|
||||
expression: processListener.value,
|
||||
event: processListener.event,
|
||||
fields: []
|
||||
}
|
||||
} else if (processListener.valueType === 'delegateExpression') {
|
||||
return {
|
||||
listenerType: 'delegateExpressionListener',
|
||||
delegateExpression: processListener.value,
|
||||
event: processListener.event,
|
||||
fields: []
|
||||
}
|
||||
}
|
||||
throw new Error('未知的监听器类型')
|
||||
}
|
||||
|
||||
export const listenerType = {
|
||||
classListener: 'Java 类',
|
||||
expressionListener: '表达式',
|
||||
|
@ -1,11 +1,15 @@
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<el-form label-width="90px">
|
||||
<el-form-item label="回路特性">
|
||||
<el-form-item label="快捷配置">
|
||||
<el-button size="small" @click="changeConfig('依次审批')">依次审批</el-button>
|
||||
<el-button size="small" @click="changeConfig('会签')">会签</el-button>
|
||||
<el-button size="small" @click="changeConfig('或签')">或签</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="会签类型">
|
||||
<el-select v-model="loopCharacteristics" @change="changeLoopCharacteristicsType">
|
||||
<el-option label="并行多重事件" value="ParallelMultiInstance" />
|
||||
<el-option label="时序多重事件" value="SequentialMultiInstance" />
|
||||
<el-option label="循环事件" value="StandardLoop" />
|
||||
<el-option label="无" value="Null" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@ -15,7 +19,7 @@
|
||||
loopCharacteristics === 'SequentialMultiInstance'
|
||||
"
|
||||
>
|
||||
<el-form-item label="循环基数" key="loopCardinality">
|
||||
<el-form-item label="循环数量" key="loopCardinality">
|
||||
<el-input
|
||||
v-model="loopInstanceForm.loopCardinality"
|
||||
clearable
|
||||
@ -25,7 +29,8 @@
|
||||
<el-form-item label="集合" key="collection" v-show="false">
|
||||
<el-input v-model="loopInstanceForm.collection" clearable @change="updateLoopBase" />
|
||||
</el-form-item>
|
||||
<el-form-item label="元素变量" key="elementVariable">
|
||||
<!-- add by 芋艿:由于「元素变量」暂时用不到,所以这里 display 为 none -->
|
||||
<el-form-item label="元素变量" key="elementVariable" style="display: none">
|
||||
<el-input v-model="loopInstanceForm.elementVariable" clearable @change="updateLoopBase" />
|
||||
</el-form-item>
|
||||
<el-form-item label="完成条件" key="completionCondition">
|
||||
@ -35,7 +40,8 @@
|
||||
@change="updateLoopCondition"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="异步状态" key="async">
|
||||
<!-- add by 芋艿:由于「异步状态」暂时用不到,所以这里 display 为 none -->
|
||||
<el-form-item label="异步状态" key="async" style="display: none">
|
||||
<el-checkbox
|
||||
v-model="loopInstanceForm.asyncBefore"
|
||||
label="异步前"
|
||||
@ -124,6 +130,7 @@ const getElementLoop = (businessObject) => {
|
||||
businessObject.loopCharacteristics.extensionElements.values[0].body
|
||||
}
|
||||
}
|
||||
|
||||
const changeLoopCharacteristicsType = (type) => {
|
||||
// this.loopInstanceForm = { ...this.defaultLoopInstanceForm }; // 切换类型取消原表单配置
|
||||
// 取消多实例配置
|
||||
@ -160,6 +167,7 @@ const changeLoopCharacteristicsType = (type) => {
|
||||
loopCharacteristics: toRaw(multiLoopInstance.value)
|
||||
})
|
||||
}
|
||||
|
||||
// 循环基数
|
||||
const updateLoopCardinality = (cardinality) => {
|
||||
let loopCardinality = null
|
||||
@ -176,6 +184,7 @@ const updateLoopCardinality = (cardinality) => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 完成条件
|
||||
const updateLoopCondition = (condition) => {
|
||||
let completionCondition = null
|
||||
@ -192,6 +201,7 @@ const updateLoopCondition = (condition) => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 重试周期
|
||||
const updateLoopTimeCycle = (timeCycle) => {
|
||||
const extensionElements = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
|
||||
@ -209,6 +219,7 @@ const updateLoopTimeCycle = (timeCycle) => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 直接更新的基础信息
|
||||
const updateLoopBase = () => {
|
||||
bpmnInstances().modeling.updateModdleProperties(
|
||||
@ -220,6 +231,7 @@ const updateLoopBase = () => {
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// 各异步状态
|
||||
const updateLoopAsync = (key) => {
|
||||
const { asyncBefore, asyncAfter } = loopInstanceForm.value
|
||||
@ -238,6 +250,20 @@ const updateLoopAsync = (key) => {
|
||||
)
|
||||
}
|
||||
|
||||
const changeConfig = (config) => {
|
||||
if (config === '依次审批') {
|
||||
changeLoopCharacteristicsType('SequentialMultiInstance')
|
||||
updateLoopCardinality('1')
|
||||
updateLoopCondition('${ nrOfCompletedInstances >= nrOfInstances }')
|
||||
} else if (config === '会签') {
|
||||
changeLoopCharacteristicsType('ParallelMultiInstance')
|
||||
updateLoopCondition('${ nrOfCompletedInstances >= nrOfInstances }')
|
||||
} else if (config === '或签') {
|
||||
changeLoopCharacteristicsType('ParallelMultiInstance')
|
||||
updateLoopCondition('${ nrOfCompletedInstances > 0 }')
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
multiLoopInstance.value = null
|
||||
bpmnElement.value = null
|
||||
|
@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="panel-tab__content">
|
||||
<el-form size="small" label-width="90px">
|
||||
<el-form-item label="异步延续">
|
||||
<!-- add by 芋艿:由于「异步延续」暂时用不到,所以这里 display 为 none -->
|
||||
<el-form-item label="异步延续" style="display: none">
|
||||
<el-checkbox
|
||||
v-model="taskConfigForm.asyncBefore"
|
||||
label="异步前"
|
||||
|
@ -0,0 +1,68 @@
|
||||
<!-- 表达式选择 -->
|
||||
<template>
|
||||
<Dialog title="请选择表达式" v-model="dialogVisible" width="1024px">
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="名字" align="center" prop="name" />
|
||||
<el-table-column label="表达式" align="center" prop="expression" />
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="select(scope.row)"> 选择 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { CommonStatusEnum } from '@/utils/constants'
|
||||
import { ProcessExpressionApi, ProcessExpressionVO } from '@/api/bpm/processExpression'
|
||||
|
||||
/** BPM 流程 表单 */
|
||||
defineOptions({ name: 'ProcessExpressionDialog' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<ProcessExpressionVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
type: undefined,
|
||||
status: CommonStatusEnum.ENABLE
|
||||
})
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string) => {
|
||||
dialogVisible.value = true
|
||||
loading.value = true
|
||||
try {
|
||||
queryParams.pageNo = 1
|
||||
queryParams.type = type
|
||||
const data = await ProcessExpressionApi.getProcessExpressionPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const select = async (row) => {
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('select', row)
|
||||
}
|
||||
</script>
|
@ -1,85 +1,204 @@
|
||||
<template>
|
||||
<div style="margin-top: 16px">
|
||||
<!-- <el-form-item label="处理用户">-->
|
||||
<!-- <el-select v-model="userTaskForm.assignee" @change="updateElementTask('assignee')">-->
|
||||
<!-- <el-option v-for="ak in mockData" :key="'ass-' + ak" :label="`用户${ak}`" :value="`user${ak}`" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="候选用户">-->
|
||||
<!-- <el-select v-model="userTaskForm.candidateUsers" multiple collapse-tags @change="updateElementTask('candidateUsers')">-->
|
||||
<!-- <el-option v-for="uk in mockData" :key="'user-' + uk" :label="`用户${uk}`" :value="`user${uk}`" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<!-- <el-form-item label="候选分组">-->
|
||||
<!-- <el-select v-model="userTaskForm.candidateGroups" multiple collapse-tags @change="updateElementTask('candidateGroups')">-->
|
||||
<!-- <el-option v-for="gk in mockData" :key="'ass-' + gk" :label="`分组${gk}`" :value="`group${gk}`" />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- </el-form-item>-->
|
||||
<el-form-item label="到期时间">
|
||||
<el-input v-model="userTaskForm.dueDate" clearable @change="updateElementTask('dueDate')" />
|
||||
</el-form-item>
|
||||
<el-form-item label="跟踪时间">
|
||||
<el-input
|
||||
v-model="userTaskForm.followUpDate"
|
||||
<el-form label-width="100px">
|
||||
<el-form-item label="规则类型" prop="candidateStrategy">
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateStrategy"
|
||||
clearable
|
||||
@change="updateElementTask('followUpDate')"
|
||||
style="width: 100%"
|
||||
@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="userTaskForm.candidateStrategy == 10"
|
||||
label="指定角色"
|
||||
prop="candidateParam"
|
||||
>
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateParam"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<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="userTaskForm.candidateStrategy == 20 || userTaskForm.candidateStrategy == 21"
|
||||
label="指定部门"
|
||||
prop="candidateParam"
|
||||
span="24"
|
||||
>
|
||||
<el-tree-select
|
||||
ref="treeRef"
|
||||
v-model="userTaskForm.candidateParam"
|
||||
:data="deptTreeOptions"
|
||||
:props="defaultProps"
|
||||
empty-text="加载中,请稍后"
|
||||
multiple
|
||||
node-key="id"
|
||||
show-checkbox
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="优先级">
|
||||
<el-input v-model="userTaskForm.priority" clearable @change="updateElementTask('priority')" />
|
||||
<el-form-item
|
||||
v-if="userTaskForm.candidateStrategy == 22"
|
||||
label="指定岗位"
|
||||
prop="candidateParam"
|
||||
span="24"
|
||||
>
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateParam"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<el-option v-for="item in postOptions" :key="item.id" :label="item.name" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
友情提示:任务的分配规则,使用
|
||||
<router-link target="_blank" :to="{ path: '/bpm/manager/model' }"
|
||||
><el-link type="danger">流程模型</el-link>
|
||||
</router-link>
|
||||
下的【分配规则】替代,提供指定角色、部门负责人、部门成员、岗位、工作组、自定义脚本等 7
|
||||
种维护的任务分配维度,更加灵活!
|
||||
</div>
|
||||
<el-form-item
|
||||
v-if="userTaskForm.candidateStrategy == 30"
|
||||
label="指定用户"
|
||||
prop="candidateParam"
|
||||
span="24"
|
||||
>
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateParam"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<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="userTaskForm.candidateStrategy === 40"
|
||||
label="指定用户组"
|
||||
prop="candidateParam"
|
||||
>
|
||||
<el-select
|
||||
v-model="userTaskForm.candidateParam"
|
||||
clearable
|
||||
multiple
|
||||
style="width: 100%"
|
||||
@change="updateElementTask"
|
||||
>
|
||||
<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="userTaskForm.candidateStrategy === 60"
|
||||
label="流程表达式"
|
||||
prop="candidateParam"
|
||||
>
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="userTaskForm.candidateParam[0]"
|
||||
clearable
|
||||
style="width: 72%"
|
||||
@change="updateElementTask"
|
||||
/>
|
||||
<el-button class="ml-5px" size="small" type="success" @click="openProcessExpressionDialog"
|
||||
>选择表达式</el-button
|
||||
>
|
||||
<!-- 选择弹窗 -->
|
||||
<ProcessExpressionDialog ref="processExpressionDialogRef" @select="selectProcessExpression" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { DICT_TYPE, getIntDictOptions } 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'
|
||||
import ProcessExpressionDialog from './ProcessExpressionDialog.vue'
|
||||
|
||||
defineOptions({ name: 'UserTask' })
|
||||
const props = defineProps({
|
||||
id: String,
|
||||
type: String
|
||||
})
|
||||
const defaultTaskForm = ref({
|
||||
assignee: '',
|
||||
candidateUsers: [],
|
||||
candidateGroups: [],
|
||||
dueDate: '',
|
||||
followUpDate: '',
|
||||
priority: ''
|
||||
const userTaskForm = ref({
|
||||
candidateStrategy: undefined, // 分配规则
|
||||
candidateParam: [] // 分配选项
|
||||
})
|
||||
const userTaskForm = ref<any>({})
|
||||
// const mockData=ref([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
|
||||
const bpmnElement = ref()
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
|
||||
const roleOptions = ref<RoleApi.RoleVO[]>([]) // 角色列表
|
||||
const deptTreeOptions = ref() // 部门树
|
||||
const postOptions = ref<PostApi.PostVO[]>([]) // 岗位列表
|
||||
const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
const userGroupOptions = ref<UserGroupApi.UserGroupVO[]>([]) // 用户组列表
|
||||
|
||||
const resetTaskForm = () => {
|
||||
for (let key in defaultTaskForm.value) {
|
||||
let value
|
||||
if (key === 'candidateUsers' || key === 'candidateGroups') {
|
||||
value = bpmnElement.value?.businessObject[key]
|
||||
? bpmnElement.value.businessObject[key].split(',')
|
||||
: []
|
||||
const businessObject = bpmnElement.value.businessObject
|
||||
if (!businessObject) {
|
||||
return
|
||||
}
|
||||
if (businessObject.candidateStrategy != undefined) {
|
||||
userTaskForm.value.candidateStrategy = parseInt(businessObject.candidateStrategy) as any
|
||||
} else {
|
||||
userTaskForm.value.candidateStrategy = undefined
|
||||
}
|
||||
if (businessObject.candidateParam && businessObject.candidateParam.length > 0) {
|
||||
if (userTaskForm.value.candidateStrategy === 60) {
|
||||
// 特殊:流程表达式,只有一个 input 输入框
|
||||
userTaskForm.value.candidateParam = [businessObject.candidateParam]
|
||||
} else {
|
||||
value = bpmnElement.value?.businessObject[key] || defaultTaskForm.value[key]
|
||||
userTaskForm.value.candidateParam = businessObject.candidateParam
|
||||
.split(',')
|
||||
.map((item) => +item)
|
||||
}
|
||||
userTaskForm.value[key] = value
|
||||
} else {
|
||||
userTaskForm.value.candidateParam = []
|
||||
}
|
||||
}
|
||||
const updateElementTask = (key) => {
|
||||
const taskAttr = Object.create(null)
|
||||
if (key === 'candidateUsers' || key === 'candidateGroups') {
|
||||
taskAttr[key] =
|
||||
userTaskForm.value[key] && userTaskForm.value[key].length
|
||||
? userTaskForm.value[key].join()
|
||||
: null
|
||||
} else {
|
||||
taskAttr[key] = userTaskForm.value[key] || null
|
||||
}
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), taskAttr)
|
||||
|
||||
/** 更新 candidateStrategy 字段时,需要清空 candidateParam,并触发 bpmn 图更新 */
|
||||
const changeCandidateStrategy = () => {
|
||||
userTaskForm.value.candidateParam = []
|
||||
updateElementTask()
|
||||
}
|
||||
|
||||
/** 选中某个 options 时候,更新 bpmn 图 */
|
||||
const updateElementTask = () => {
|
||||
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
|
||||
candidateStrategy: userTaskForm.value.candidateStrategy,
|
||||
candidateParam: userTaskForm.value.candidateParam.join(',')
|
||||
})
|
||||
}
|
||||
|
||||
// 打开监听器弹窗
|
||||
const processExpressionDialogRef = ref()
|
||||
const openProcessExpressionDialog = async () => {
|
||||
processExpressionDialogRef.value.open()
|
||||
}
|
||||
const selectProcessExpression = (expression) => {
|
||||
userTaskForm.value.candidateParam = [expression.expression]
|
||||
}
|
||||
|
||||
watch(
|
||||
@ -92,6 +211,21 @@ watch(
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
// 获得角色列表
|
||||
roleOptions.value = await RoleApi.getSimpleRoleList()
|
||||
// 获得部门列表
|
||||
const deptOptions = await DeptApi.getSimpleDeptList()
|
||||
deptTreeOptions.value = handleTree(deptOptions, 'id')
|
||||
// 获得岗位列表
|
||||
postOptions.value = await PostApi.getSimplePostList()
|
||||
// 获得用户列表
|
||||
userOptions.value = await UserApi.getSimpleUserList()
|
||||
// 获得用户组列表
|
||||
userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList()
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
bpmnElement.value = null
|
||||
})
|
||||
|
@ -2,6 +2,7 @@ import { toRaw } from 'vue'
|
||||
const bpmnInstances = () => (window as any)?.bpmnInstances
|
||||
// 创建监听器实例
|
||||
export function createListenerObject(options, isTask, prefix) {
|
||||
debugger
|
||||
const listenerObj = Object.create(null)
|
||||
listenerObj.event = options.event
|
||||
isTask && (listenerObj.id = options.id) // 任务监听器特有的 id 字段
|
||||
|
Reference in New Issue
Block a user