From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue | 470 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 470 insertions(+), 0 deletions(-)
diff --git a/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue b/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue
new file mode 100644
index 0000000..e4091b9
--- /dev/null
+++ b/src/components/bpmnProcessDesigner/package/penal/task/task-components/UserTask.vue
@@ -0,0 +1,470 @@
+<template>
+ <el-form label-width="120px">
+ <el-form-item label="瑙勫垯绫诲瀷" prop="candidateStrategy">
+ <el-select
+ v-model="userTaskForm.candidateStrategy"
+ clearable
+ style="width: 100%"
+ @change="changeCandidateStrategy"
+ >
+ <el-option
+ v-for="(dict, index) in CANDIDATE_STRATEGY"
+ :key="index"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item
+ v-if="userTaskForm.candidateStrategy == CandidateStrategy.ROLE"
+ 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 == CandidateStrategy.DEPT_MEMBER ||
+ userTaskForm.candidateStrategy == CandidateStrategy.DEPT_LEADER ||
+ userTaskForm.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER
+ "
+ 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
+ v-if="userTaskForm.candidateStrategy == CandidateStrategy.POST"
+ 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>
+ <el-form-item
+ v-if="userTaskForm.candidateStrategy == CandidateStrategy.USER"
+ 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 === CandidateStrategy.USER_GROUP"
+ 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 === CandidateStrategy.FORM_USER"
+ label="琛ㄥ崟鍐呯敤鎴峰瓧娈�"
+ prop="formUser"
+ >
+ <el-select
+ v-model="userTaskForm.candidateParam"
+ clearable
+ style="width: 100%"
+ @change="handleFormUserChange"
+ >
+ <el-option
+ v-for="(item, idx) in userFieldOnFormOptions"
+ :key="idx"
+ :label="item.title"
+ :value="item.field"
+ :disabled="!item.required"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item
+ v-if="userTaskForm.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER"
+ label="琛ㄥ崟鍐呴儴闂ㄥ瓧娈�"
+ prop="formDept"
+ >
+ <el-select
+ v-model="userTaskForm.candidateParam"
+ clearable
+ style="width: 100%"
+ @change="updateElementTask"
+ >
+ <el-option
+ v-for="(item, idx) in deptFieldOnFormOptions"
+ :key="idx"
+ :label="item.title"
+ :value="item.field"
+ :disabled="!item.required"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item
+ v-if="
+ userTaskForm.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER ||
+ userTaskForm.candidateStrategy == CandidateStrategy.START_USER_DEPT_LEADER ||
+ userTaskForm.candidateStrategy == CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER ||
+ userTaskForm.candidateStrategy == CandidateStrategy.FORM_DEPT_LEADER
+ "
+ :label="deptLevelLabel!"
+ prop="deptLevel"
+ span="24"
+ >
+ <el-select v-model="deptLevel" clearable @change="updateElementTask">
+ <el-option
+ v-for="(item, index) in MULTI_LEVEL_DEPT"
+ :key="index"
+ :label="item.label"
+ :value="item.value"
+ />
+ </el-select>
+ </el-form-item>
+ <el-form-item
+ v-if="userTaskForm.candidateStrategy === CandidateStrategy.EXPRESSION"
+ label="娴佺▼琛ㄨ揪寮�"
+ prop="candidateParam"
+ >
+ <el-input
+ type="textarea"
+ v-model="userTaskForm.candidateParam[0]"
+ clearable
+ style="width: 100%"
+ @change="updateElementTask"
+ />
+ <XButton
+ class="!w-1/1 mt-5px"
+ type="success"
+ preIcon="ep:select"
+ title="閫夋嫨琛ㄨ揪寮�"
+ size="small"
+ @click="openProcessExpressionDialog"
+ />
+ <!-- 閫夋嫨寮圭獥 -->
+ <ProcessExpressionDialog ref="processExpressionDialogRef" @select="selectProcessExpression" />
+ </el-form-item>
+
+ <el-form-item label="璺宠繃琛ㄨ揪寮�" prop="skipExpression">
+ <el-input
+ type="textarea"
+ v-model="userTaskForm.skipExpression"
+ clearable
+ style="width: 100%"
+ @change="updateSkipExpression"
+ />
+ </el-form-item>
+ </el-form>
+</template>
+
+<script lang="ts" setup>
+import {
+ CANDIDATE_STRATEGY,
+ CandidateStrategy,
+ FieldPermissionType,
+ MULTI_LEVEL_DEPT
+} from '@/components/SimpleProcessDesignerV2/src/consts'
+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'
+import { ProcessExpressionVO } from '@/api/bpm/processExpression'
+import { useFormFieldsPermission } from '@/components/SimpleProcessDesignerV2/src/node'
+
+defineOptions({ name: 'UserTask' })
+const props = defineProps({
+ id: String,
+ type: String
+})
+const prefix = inject('prefix')
+const userTaskForm = ref({
+ candidateStrategy: undefined, // 鍒嗛厤瑙勫垯
+ candidateParam: [], // 鍒嗛厤閫夐」
+ skipExpression: '' // 璺宠繃琛ㄨ揪寮�
+})
+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 { formFieldOptions } = useFormFieldsPermission(FieldPermissionType.READ)
+// 琛ㄥ崟鍐呯敤鎴峰瓧娈甸�夐」, 蹇呴』鏄繀濉拰鐢ㄦ埛閫夋嫨鍣�
+const userFieldOnFormOptions = computed(() => {
+ return formFieldOptions.filter((item) => item.type === 'UserSelect')
+})
+// 琛ㄥ崟鍐呴儴闂ㄥ瓧娈甸�夐」, 蹇呴』鏄繀濉拰閮ㄩ棬閫夋嫨鍣�
+const deptFieldOnFormOptions = computed(() => {
+ return formFieldOptions.filter((item) => item.type === 'DeptSelect')
+})
+
+const deptLevel = ref(1)
+const deptLevelLabel = computed(() => {
+ let label = '閮ㄩ棬璐熻矗浜烘潵婧�'
+ if (userTaskForm.value.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER) {
+ label = label + '(鎸囧畾閮ㄩ棬鍚戜笂)'
+ } else if (userTaskForm.value.candidateStrategy == CandidateStrategy.FORM_DEPT_LEADER) {
+ label = label + '(琛ㄥ崟鍐呴儴闂ㄥ悜涓�)'
+ } else {
+ label = label + '(鍙戣捣浜洪儴闂ㄥ悜涓�)'
+ }
+ return label
+})
+
+const otherExtensions = ref()
+
+const resetTaskForm = () => {
+ const businessObject = bpmnElement.value.businessObject
+ if (!businessObject) {
+ return
+ }
+
+ const extensionElements =
+ businessObject?.extensionElements ??
+ bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] })
+ userTaskForm.value.candidateStrategy = extensionElements.values?.filter(
+ (ex) => ex.$type === `${prefix}:CandidateStrategy`
+ )?.[0]?.value
+ const candidateParamStr = extensionElements.values?.filter(
+ (ex) => ex.$type === `${prefix}:CandidateParam`
+ )?.[0]?.value
+ if (candidateParamStr && candidateParamStr.length > 0) {
+ if (userTaskForm.value.candidateStrategy === CandidateStrategy.EXPRESSION) {
+ // 鐗规畩锛氭祦绋嬭〃杈惧紡锛屽彧鏈変竴涓� input 杈撳叆妗�
+ userTaskForm.value.candidateParam = [candidateParamStr]
+ } else if (userTaskForm.value.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER) {
+ // 鐗规畩锛氬绾т笉閮ㄩ棬璐熻矗浜猴紝闇�瑕侀�氳繃'|'鍒嗗壊
+ userTaskForm.value.candidateParam = candidateParamStr
+ .split('|')[0]
+ .split(',')
+ .map((item) => {
+ // 濡傛灉鏁板瓧瓒呭嚭浜嗘渶澶у畨鍏ㄦ暣鏁拌寖鍥达紝鍒欏皢鍏朵綔涓哄瓧绗︿覆澶勭悊
+ let num = Number(item)
+ return num > Number.MAX_SAFE_INTEGER || num < -Number.MAX_SAFE_INTEGER ? item : num
+ })
+ deptLevel.value = +candidateParamStr.split('|')[1]
+ } else if (
+ userTaskForm.value.candidateStrategy == CandidateStrategy.START_USER_DEPT_LEADER ||
+ userTaskForm.value.candidateStrategy == CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER
+ ) {
+ userTaskForm.value.candidateParam = +candidateParamStr
+ deptLevel.value = +candidateParamStr
+ } else if (userTaskForm.value.candidateStrategy == CandidateStrategy.FORM_DEPT_LEADER) {
+ userTaskForm.value.candidateParam = candidateParamStr.split('|')[0]
+ deptLevel.value = +candidateParamStr.split('|')[1]
+ } else {
+ userTaskForm.value.candidateParam = candidateParamStr.split(',').map((item) => {
+ // 濡傛灉鏁板瓧瓒呭嚭浜嗘渶澶у畨鍏ㄦ暣鏁拌寖鍥达紝鍒欏皢鍏朵綔涓哄瓧绗︿覆澶勭悊
+ let num = Number(item)
+ return num > Number.MAX_SAFE_INTEGER || num < -Number.MAX_SAFE_INTEGER ? item : num
+ })
+ }
+ } else {
+ userTaskForm.value.candidateParam = []
+ }
+
+ otherExtensions.value =
+ extensionElements.values?.filter(
+ (ex) => ex.$type !== `${prefix}:CandidateStrategy` && ex.$type !== `${prefix}:CandidateParam`
+ ) ?? []
+
+ // 璺宠繃琛ㄨ揪寮�
+ if (businessObject.skipExpression != undefined) {
+ userTaskForm.value.skipExpression = businessObject.skipExpression
+ } else {
+ userTaskForm.value.skipExpression = ''
+ }
+
+ // 鏀圭敤閫氳繃extensionElements鏉ュ瓨鍌ㄦ暟鎹�
+ 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 {
+ userTaskForm.value.candidateParam = businessObject.candidateParam
+ .split(',')
+ .map((item) => item)
+ }
+ } else {
+ userTaskForm.value.candidateParam = []
+ }
+}
+
+/** 鏇存柊 candidateStrategy 瀛楁鏃讹紝闇�瑕佹竻绌� candidateParam锛屽苟瑙﹀彂 bpmn 鍥炬洿鏂� */
+const changeCandidateStrategy = () => {
+ userTaskForm.value.candidateParam = []
+ deptLevel.value = 1
+ // 娉ㄩ噴 by 鑺嬭壙锛氳繖涓氦浜掑緢澶氱敤鎴峰弽棣堣垂瑙o紝https://t.zsxq.com/xNmas 鎵�浠ユ殏鏃跺睆钄�
+ // if (userTaskForm.value.candidateStrategy === CandidateStrategy.FORM_USER) {
+ // // 鐗规畩澶勭悊琛ㄥ崟鍐呯敤鎴峰瓧娈碉紝褰撳彧鏈夊彂璧蜂汉閫夐」鏃跺簲閫変腑鍙戣捣浜�
+ // if (!userFieldOnFormOptions.value || userFieldOnFormOptions.value.length <= 1) {
+ // userTaskForm.value.candidateStrategy = CandidateStrategy.START_USER
+ // }
+ // }
+ updateElementTask()
+}
+
+/** 閫変腑鏌愪釜 options 鏃跺�欙紝鏇存柊 bpmn 鍥� */
+const updateElementTask = () => {
+ let candidateParam =
+ userTaskForm.value.candidateParam instanceof Array
+ ? userTaskForm.value.candidateParam.join(',')
+ : userTaskForm.value.candidateParam
+
+ // 鐗规畩澶勭悊澶氱骇閮ㄩ棬鎯呭喌
+ if (
+ userTaskForm.value.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER ||
+ userTaskForm.value.candidateStrategy == CandidateStrategy.FORM_DEPT_LEADER
+ ) {
+ candidateParam += '|' + deptLevel.value
+ }
+ // 鐗规畩澶勭悊鍙戣捣浜洪儴闂ㄨ礋璐d汉銆佸彂璧蜂汉杩炵画閮ㄩ棬璐熻矗浜�
+ if (
+ userTaskForm.value.candidateStrategy == CandidateStrategy.START_USER_DEPT_LEADER ||
+ userTaskForm.value.candidateStrategy == CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER
+ ) {
+ candidateParam = deptLevel.value + ''
+ }
+
+ const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
+ values: [
+ ...otherExtensions.value,
+ bpmnInstances().moddle.create(`${prefix}:CandidateStrategy`, {
+ value: userTaskForm.value.candidateStrategy
+ }),
+ bpmnInstances().moddle.create(`${prefix}:CandidateParam`, {
+ value: candidateParam
+ })
+ ]
+ })
+ bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+ extensionElements: extensions
+ })
+
+ // 鏀圭敤閫氳繃extensionElements鏉ュ瓨鍌ㄦ暟鎹�
+ return
+ bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+ candidateStrategy: userTaskForm.value.candidateStrategy,
+ candidateParam: userTaskForm.value.candidateParam.join(',')
+ })
+}
+
+const updateSkipExpression = () => {
+ if (userTaskForm.value.skipExpression && userTaskForm.value.skipExpression !== '') {
+ bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+ skipExpression: userTaskForm.value.skipExpression
+ })
+ } else {
+ bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+ skipExpression: null
+ })
+ }
+}
+
+// 鎵撳紑鐩戝惉鍣ㄥ脊绐�
+const processExpressionDialogRef = ref()
+const openProcessExpressionDialog = async () => {
+ processExpressionDialogRef.value.open()
+}
+const selectProcessExpression = (expression: ProcessExpressionVO) => {
+ userTaskForm.value.candidateParam = [expression.expression]
+ updateElementTask()
+}
+
+const handleFormUserChange = (e) => {
+ if (e === 'PROCESS_START_USER_ID') {
+ userTaskForm.value.candidateParam = []
+ userTaskForm.value.candidateStrategy = CandidateStrategy.START_USER
+ }
+ updateElementTask()
+}
+
+watch(
+ () => props.id,
+ () => {
+ bpmnElement.value = bpmnInstances().bpmnElement
+ nextTick(() => {
+ resetTaskForm()
+ })
+ },
+ { 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
+})
+</script>
--
Gitblit v1.8.0