工作流表单+模型代码提交

This commit is contained in:
2024-05-09 14:18:39 +08:00
parent eeef608ccd
commit 06611f527a
266 changed files with 18227 additions and 22039 deletions

View File

@@ -1,7 +1,6 @@
<template>
<div class="panel-tab__content">
<el-form size="small" label-width="90px">
<!-- add by 芋艿由于异步延续暂时用不到所以这里 display none -->
<el-form-item label="异步延续" style="display: none">
<el-checkbox
v-model="taskConfigForm.asyncBefore"
@@ -26,7 +25,6 @@ import UserTask from './task-components/UserTask.vue'
import ScriptTask from './task-components/ScriptTask.vue'
import ReceiveTask from './task-components/ReceiveTask.vue'
import { onMounted, reactive, ref, watch, onBeforeUnmount,toRaw,nextTick } from 'vue'
defineOptions({ name: 'ElementTaskConfig' })
const props = defineProps({

View File

@@ -1,65 +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>
<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 { onMounted, reactive, ref, watch, onBeforeUnmount } from 'vue'
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
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
}
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)
const select = async (row) => {
dialogVisible.value = false
// 发送操作成功的事件
emit('select', row)
}
</script>

View File

@@ -1,46 +1,58 @@
<template>
<div style="margin-top: 16px">
<el-form-item label="消息实例">
<div style="display: flex; align-items: center; justify-content: space-between; flex-wrap: nowrap">
<el-select v-model="bindMessageId" @change="updateTaskMessage">
<el-option
v-for="key in Object.keys(messageMap)"
:value="key"
:label="messageMap[key]"
:key="key"
/>
</el-select>
<el-button type="primary" icon="el-icon-Plus" style="margin-left: 8px" @click="openMessageModel" />
</div>
<div style="margin-top: 16px">
<el-form-item label="消息实例">
<div
style="
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: nowrap;
"
>
<el-select v-model="bindMessageId" @change="updateTaskMessage">
<el-option
v-for="key in Object.keys(messageMap)"
:value="key"
:label="messageMap[key]"
:key="key"
/>
</el-select>
<XButton
type="primary"
preIcon="ep:plus"
style="margin-left: 8px"
@click="openMessageModel"
/>
</div>
</el-form-item>
<el-dialog
v-model="messageModelVisible"
:close-on-click-modal="false"
title="创建新消息"
width="400px"
append-to-body
destroy-on-close
>
<el-form :model="newMessageForm" size="small" label-width="90px">
<el-form-item label="消息ID">
<el-input v-model="newMessageForm.id" clearable />
</el-form-item>
<el-dialog
v-model="messageModelVisible"
:close-on-click-modal="false"
title="创建新消息"
width="400px"
append-to-body
destroy-on-close
>
<el-form :model="newMessageForm" size="small" label-width="90px">
<el-form-item label="消息ID">
<el-input v-model="newMessageForm.id" clearable />
</el-form-item>
<el-form-item label="消息名称">
<el-input v-model="newMessageForm.name" clearable />
</el-form-item>
</el-form>
<template #footer>
<el-button size="small" type="primary" @click="createNewMessage"> </el-button>
</template>
</el-dialog>
</div>
<el-form-item label="消息名称">
<el-input v-model="newMessageForm.name" clearable />
</el-form-item>
</el-form>
<template #footer>
<el-button size="small" type="primary" @click="createNewMessage"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup>
defineOptions({ name: 'ReceiveTask' })
const props = defineProps({
id: String,
type: String
id: String,
type: String
})
const message = useMessage()
@@ -55,59 +67,59 @@ const bpmnRootElements = ref<any>()
const bpmnInstances = () => (window as any).bpmnInstances
const getBindMessage = () => {
bpmnElement.value = bpmnInstances().bpmnElement
bindMessageId.value = bpmnElement.value.businessObject?.messageRef?.id || '-1'
bpmnElement.value = bpmnInstances().bpmnElement
bindMessageId.value = bpmnElement.value.businessObject?.messageRef?.id || '-1'
}
const openMessageModel = () => {
messageModelVisible.value = true
newMessageForm.value = {}
messageModelVisible.value = true
newMessageForm.value = {}
}
const createNewMessage = () => {
if (messageMap.value[newMessageForm.value.id]) {
message.error('该消息已存在请修改id后重新保存')
return
}
const newMessage = bpmnInstances().moddle.create('bpmn:Message', newMessageForm.value)
bpmnRootElements.value.push(newMessage)
messageMap.value[newMessageForm.value.id] = newMessageForm.value.name
bpmnMessageRefsMap.value[newMessageForm.value.id] = newMessage
messageModelVisible.value = false
if (messageMap.value[newMessageForm.value.id]) {
message.error('该消息已存在请修改id后重新保存')
return
}
const newMessage = bpmnInstances().moddle.create('bpmn:Message', newMessageForm.value)
bpmnRootElements.value.push(newMessage)
messageMap.value[newMessageForm.value.id] = newMessageForm.value.name
bpmnMessageRefsMap.value[newMessageForm.value.id] = newMessage
messageModelVisible.value = false
}
const updateTaskMessage = messageId => {
if (messageId === '-1') {
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
messageRef: null
})
} else {
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
messageRef: bpmnMessageRefsMap.value[messageId]
})
}
const updateTaskMessage = (messageId) => {
if (messageId === '-1') {
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
messageRef: null
})
} else {
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
messageRef: bpmnMessageRefsMap.value[messageId]
})
}
}
onMounted(() => {
bpmnMessageRefsMap.value = Object.create(null)
bpmnRootElements.value = bpmnInstances().modeler.getDefinitions().rootElements
bpmnRootElements.value
.filter(el => el.$type === 'bpmn:Message')
.forEach(m => {
bpmnMessageRefsMap.value[m.id] = m
messageMap.value[m.id] = m.name
})
messageMap.value['-1'] = '无'
bpmnMessageRefsMap.value = Object.create(null)
bpmnRootElements.value = bpmnInstances().modeler.getDefinitions().rootElements
bpmnRootElements.value
.filter((el) => el.$type === 'bpmn:Message')
.forEach((m) => {
bpmnMessageRefsMap.value[m.id] = m
messageMap.value[m.id] = m.name
})
messageMap.value['-1'] = '无'
})
onBeforeUnmount(() => {
bpmnElement.value = null
bpmnElement.value = null
})
watch(
() => props.id,
() => {
// bpmnElement.value = bpmnInstances().bpmnElement
nextTick(() => {
getBindMessage()
})
},
{ immediate: true }
() => props.id,
() => {
// bpmnElement.value = bpmnInstances().bpmnElement
nextTick(() => {
getBindMessage()
})
},
{ immediate: true }
)
</script>

View File

@@ -1,182 +1,185 @@
<template>
<div>
<el-form label-width='100px'>
<el-form-item label='规则类型' prop='candidateStrategy'>
<el-select
v-model='userTaskForm.candidateStrategy'
clearable
style='width: 100%'
@change='changeCandidateStrategy'
>
<el-option
v-for='dict in RuleTypeList'
:key='dict.code'
:label='dict.name'
:value='dict.code'
/>
</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'
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>
<div v-if="dataType === 'ROLES'">
<el-select v-model='roleIds' :size='mini' placeholder='请选择 角色' @change='changeSelectRoles'>
<el-option
v-for='item in roleOptions'
:key='item.id'
:label='item.name'
:value='`ROLE${item.id}`'
>
</el-option>
</el-select>
</div>
</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.name'
:value='item.id'
/>
</el-select>
</el-form-item>
</el-form>
</template>
<script lang='ts' setup>
import { listAllUserByDeptId } from '@/api/user-boot/user'
import { onMounted, reactive, ref, watch, onBeforeUnmount, toRaw, nextTick } from 'vue'
import { defaultProps, handleTree } from '@/utils/tree'
import { useDictData } from '@/stores/dictData'
const dictData = useDictData()
const RuleTypeList = ref()
import { getRoleSimpleList } from '@/api/user-boot/role'
import { getUserSimpleList } from '@/api/user-boot/user'
interface UserTaskForm {
dataType: any,
assignee: any,
candidateUsers: any,
candidateGroups: any,
text: any
}
const userTaskForm: UserTaskForm = reactive({
dataType: '',
assignee: '',
candidateUsers: '',
candidateGroups: '',
text: []
// dueDate: '',
// followUpDate: '',
// priority: ''
})
const mini = ref('small')
const dataType = ref('ROLES')
const multiLoopType = ref('Null')
const roleIds = ref('')
const roleOptions = ref([{ id: '', name: '' }])
const bpmnElement = ref()
const isSequential = ref(false)
defineOptions({ name: 'UserTask' })
const props = defineProps({
id: String,
type: String
id: String,
type: String
})
const userTaskForm = ref({
candidateStrategy: '', // 分配规则
candidateParam: [] // 分配选项
})
const bpmnElement = ref()
const bpmnInstances = () => (window as any)?.bpmnInstances
const changeSelectRoles = (val: any) => {
let groups = null
let text = null
if (val && val.length > 0) {
userTaskForm.dataType = 'ROLES'
groups = val.join() || null
let textArr = roleOptions.value.filter(k => val.indexOf(`ROLE${k.id}`) >= 0)
text = textArr?.map(k => k.name).join() || null
} else {
userTaskForm.dataType = ''
multiLoopType.value = 'Null'
}
userTaskForm.candidateGroups = groups
userTaskForm.text = text
updateElementTask()
export interface optionVO {
id: string
name: string
}
/**
* 跟新节点数据
*/
const updateElementTask = () => {
const taskAttr = Object.create(null)
for (let key in userTaskForm) {
taskAttr[key] = userTaskForm[key]
}
bpmnInstances().modeling.updateProperties(bpmnElement.value, taskAttr)
}
const roleOptions = ref<optionVO[]>([]) // 角色列表
const userOptions = ref<optionVO[]>([]) // 用户列表
const deptTreeOptions = ref() // 部门树
const resetTaskForm = () => {
const bpmnElementObj = bpmnElement.value?.businessObject
if (!bpmnElementObj) {
return
const businessObject = bpmnElement.value.businessObject
if (!businessObject) {
return
}
if (businessObject.candidateStrategy != undefined) {
userTaskForm.value.candidateStrategy = businessObject.candidateStrategy
} else {
userTaskForm.value.candidateStrategy = undefined
}
if (businessObject.candidateParam && businessObject.candidateParam.length > 0) {
if (userTaskForm.value.candidateStrategy === 60) {
// 特殊:流程表达式,只有一个 input 输入框
userTaskForm.value.candidateParam = [businessObject.candidateParam]
} else {
userTaskForm.value.candidateParam = businessObject.candidateParam.split(',')
}
clearOptionsData()
getRoleOptions()
let roleIdData = bpmnElementObj['candidateGroups'] || []
if (roleIdData && roleIdData.length > 0) {
roleIds.value = roleIdData.split(',')
}
getElementLoop(bpmnElementObj)
} else {
userTaskForm.value.candidateParam = []
}
}
/**
* 清空选项数据
*/
const clearOptionsData = () => {
// this.selectedUser.ids = []
// this.selectedUser.text = []
roleIds.value = ''
/** 更新 candidateStrategy 字段时,需要清空 candidateParam并触发 bpmn 图更新 */
const changeCandidateStrategy = () => {
userTaskForm.value.candidateParam = []
updateElementTask()
}
const getRoleOptions = () => {
if (!roleOptions.value || roleOptions.value.length <= 0) {
listAllUserByDeptId('').then(res => {
roleOptions.value = res.data
//默认第一个
if (roleOptions.value.length > 0) {
roleIds.value = roleOptions.value[0].id
}
})
}
/** 选中某个 options 时候,更新 bpmn 图 */
const updateElementTask = () => {
bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
candidateStrategy: userTaskForm.value.candidateStrategy,
candidateParam: userTaskForm.value.candidateParam.join(',')
})
}
const getElementLoop = (businessObject: any) => {
if (!businessObject.loopCharacteristics) {
multiLoopType.value = 'Null'
return
}
isSequential.value = businessObject.loopCharacteristics.isSequential
if (businessObject.loopCharacteristics.completionCondition) {
if (businessObject.loopCharacteristics.completionCondition.body === '${nrOfCompletedInstances >= nrOfInstances}') {
multiLoopType.value = 'SequentialMultiInstance'
} else {
multiLoopType.value = 'ParallelMultiInstance'
}
}
// 打开监听器弹窗
const processExpressionDialogRef = ref()
const openProcessExpressionDialog = async () => {
processExpressionDialogRef.value.open()
}
const selectProcessExpression = (expression) => {
userTaskForm.value.candidateParam = [expression.expression]
}
watch(
() => props.id,
() => {
bpmnElement.value = bpmnInstances().bpmnElement
nextTick(() => {
resetTaskForm()
})
bpmnElement.value = bpmnInstances().bpmnElement
nextTick(() => {
resetTaskForm()
})
},
{ immediate: true }
)
onMounted(async () => {
// 获得角色列表
// roleOptions.value = await RoleApi.getSimpleRoleList()
// 获得用户列表
await listAllUserByDeptId('').then(res => {
roleOptions.value = res.data
})
// 获得角色列表
await getRoleSimpleList().then(res => {
roleOptions.value = res.data
})
// 获得用户列表
await getUserSimpleList().then(res => {
userOptions.value = res.data
})
//传入type的名称
RuleTypeList.value = dictData.getBasicData('rule_type')
//
// // 获得部门列表
// const deptOptions = await DeptApi.getSimpleDeptList()
// deptTreeOptions.value = handleTree(deptOptions, 'id')
})
onBeforeUnmount(() => {
bpmnElement.value = null
bpmnElement.value = null
})
</script>
<style scoped lang='scss'>
.el-row .el-radio-group {
margin-bottom: 15px;
.el-radio {
line-height: 28px;
}
}
.el-tag {
margin-bottom: 10px;
+ .el-tag {
margin-left: 10px;
}
}
.custom-label {
padding-left: 5px;
font-weight: 500;
font-size: 14px;
color: #606266;
}
</style>