diff --git a/src/components/UserSelectForm/index.vue b/src/components/UserSelectForm/index.vue new file mode 100644 index 00000000..d4cf6f2b --- /dev/null +++ b/src/components/UserSelectForm/index.vue @@ -0,0 +1,100 @@ + + + + + + + + + + + + 确 定 + 取 消 + + + + diff --git a/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue b/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue index 203ec25b..bdd8e3f0 100644 --- a/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue +++ b/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue @@ -19,40 +19,7 @@ v-model="detailForm.value" :option="detailForm.option" @submit="submitForm" - > - - - - 指定审批人 - - - - - - - - - - - + /> @@ -61,7 +28,9 @@ ref="timelineRef" :activity-nodes="activityNodes" :show-status-icon="false" - candidateField="candidateUserList" + :startUserSelectTasks="startUserSelectTasks" + :startUserSelectAssignees="startUserSelectAssignees" + @select-user-confirm="selectUserConfirm" /> @@ -72,15 +41,15 @@ - - @@ -115,7 +84,6 @@ import type { ApiAttrs } from '@form-create/element-ui/types/config' import { useTagsViewStore } from '@/store/modules/tagsView' import * as ProcessInstanceApi from '@/api/bpm/processInstance' import * as DefinitionApi from '@/api/bpm/definition' -import * as UserApi from '@/api/system/user' defineOptions({ name: 'ProcessDefinitionDetail' }) const props = defineProps<{ @@ -132,11 +100,8 @@ const detailForm: any = ref({ }) // 流程表单详情 const fApi = ref() // 指定审批人 -const startUserSelectAssigneesFormRef = ref() // 发起人选择审批人的表单 Ref const startUserSelectTasks: any = ref([]) // 发起人需要选择审批人的用户任务列表 const startUserSelectAssignees = ref({}) // 发起人选择审批人的数据 -const startUserSelectAssigneesFormRules = ref({}) // 发起人选择审批人的表单 Rules -const userList = ref([]) // 用户列表 const bpmnXML: any = ref(null) // BPMN 数据 const simpleJson = ref() // Simple 设计器数据 json 格式 /** 当前的Tab */ @@ -150,7 +115,6 @@ const initProcessInfo = async (row: any, formVariables?: any) => { // 重置指定审批人 startUserSelectTasks.value = [] startUserSelectAssignees.value = {} - startUserSelectAssigneesFormRules.value = {} // 情况一:流程表单 if (row.formType == 10) { @@ -176,24 +140,12 @@ const initProcessInfo = async (row: any, formVariables?: any) => { bpmnXML.value = processDefinitionDetail.bpmnXml simpleJson.value = processDefinitionDetail.simpleModel startUserSelectTasks.value = processDefinitionDetail.startUserSelectTasks - // 设置指定审批人 if (startUserSelectTasks.value?.length > 0) { - detailForm.value.rule.push({ - type: 'startUserSelect', - props: { - title: '指定审批人' - } - }) - // 设置校验规则 for (const userTask of startUserSelectTasks.value) { + // 初始化数据 startUserSelectAssignees.value[userTask.id] = [] - startUserSelectAssigneesFormRules.value[userTask.id] = [ - { required: true, message: '请选择审批人', trigger: 'blur' } - ] } - // 加载用户列表 - userList.value = await UserApi.getSimpleUserList() } } // 情况二:业务表单 @@ -223,13 +175,19 @@ const getApprovalDetail = async (row: any) => { } /** 提交按钮 */ -const submitForm = async (formData: any) => { +const submitForm = async () => { if (!fApi.value || !props.selectProcessDefinition) { return } // 如果有指定审批人,需要校验 if (startUserSelectTasks.value?.length > 0) { - await startUserSelectAssigneesFormRef.value.validate() + for (const userTask of startUserSelectTasks.value) { + if ( + Array.isArray(startUserSelectAssignees.value[userTask.id]) && + startUserSelectAssignees.value[userTask.id].length === 0 + ) + return message.warning(`请选择${userTask.name}的审批人`) + } } // 提交请求 @@ -237,7 +195,7 @@ const submitForm = async (formData: any) => { try { await ProcessInstanceApi.createProcessInstance({ processDefinitionId: props.selectProcessDefinition.id, - variables: formData || detailForm.value.value, + variables: detailForm.value.value, startUserSelectAssignees: startUserSelectAssignees.value }) // 提示 @@ -256,6 +214,10 @@ const handleCancel = () => { emit('cancel') } +const selectUserConfirm = (id, userList) => { + startUserSelectAssignees.value[id] = userList?.map((item) => item.id) +} + defineExpose({ initProcessInfo }) @@ -263,7 +225,7 @@ defineExpose({ initProcessInfo }) $wrap-padding-height: 20px; $wrap-margin-height: 15px; $button-height: 51px; -$process-header-height: 194px; +$process-header-height: 105px; .processInstance-wrap-main { height: calc( diff --git a/src/views/bpm/processInstance/create/index.vue b/src/views/bpm/processInstance/create/index.vue index 9e6fcb48..5daa22d8 100644 --- a/src/views/bpm/processInstance/create/index.vue +++ b/src/views/bpm/processInstance/create/index.vue @@ -1,46 +1,74 @@ - - - - - - {{ category.name }} + + + + + + + + + + + + {{ category.name }} + - - - - {{ categoryActive.name }} - - - - - - {{ definition.name }} + + + + + {{ title }} + + + + + + + {{ definition.name }} + + + + - - - - - - - + + + + + + + { loading.value = true try { - // 流程分类 - categoryList.value = await CategoryApi.getCategorySimpleList() - if (categoryList.value.length > 0) { - categoryActive.value = categoryList.value[0] - } - // 流程定义 - processDefinitionList.value = await DefinitionApi.getProcessDefinitionList({ - suspensionState: 1 - }) + // 所有流程分类数据 + await getCategoryList() + // 所有流程定义数据 + await getDefinitionList() // 如果 processInstanceId 非空,说明是重新发起 if (processInstanceId?.length > 0) { @@ -102,11 +127,55 @@ const getList = async () => { } } -/** 选中分类对应的流程定义列表 */ -const categoryProcessDefinitionList: any = computed(() => { - return processDefinitionList.value.filter( - (item: any) => item.category == categoryActive.value.code - ) +// 获取所有流程分类数据 +const getCategoryList = async () => { + try { + // 流程分类 + categoryList.value = await CategoryApi.getCategorySimpleList() + if (categoryList.value.length > 0) { + categoryActive.value = categoryList.value[0] + } + } finally { + } +} + +// 获取所有流程定义数据 +const getDefinitionList = async () => { + try { + // 流程定义 + processDefinitionList.value = await DefinitionApi.getProcessDefinitionList({ + suspensionState: 1 + }) + // 初始化过滤列表为全部流程定义 + filteredProcessDefinitionList.value = processDefinitionList.value + } finally { + } +} + +const filteredProcessDefinitionList = ref([]) // 用于存储搜索过滤后的流程定义 +// 直接进行前端搜索 +const handleQuery = () => { + if (currentSearchKey.value.trim()) { + // 如果有搜索关键字,进行过滤 + filteredProcessDefinitionList.value = processDefinitionList.value.filter( + (definition: any) => + definition.name.toLowerCase().includes(currentSearchKey.value.toLowerCase()) // 假设搜索依据是流程定义的名称 + ) + } else { + // 如果没有搜索关键字,恢复所有数据 + filteredProcessDefinitionList.value = processDefinitionList.value + } +} + +// 监听input `clearable` 事件 +const handleClear = () => { + filteredProcessDefinitionList.value = processDefinitionList.value +} + +// 流程定义的分组 +const processDefinitionGroup: any = computed(() => { + if (!processDefinitionList.value?.length) return {} + return groupBy(filteredProcessDefinitionList.value, 'categoryName') }) // ========== 表单相关 ========== @@ -122,8 +191,16 @@ const handleSelect = async (row, formVariables?) => { processDefinitionDetailRef.value?.initProcessInfo(row, formVariables) } // 左侧分类切换 -const handleCategoryClick = (val: number) => { - categoryActive.value = val +const handleCategoryClick = (category) => { + categoryActive.value = category + const categoryRef = proxy.$refs[`category-${category.name}`] // 获取点击分类对应的 DOM 元素 + if (categoryRef?.length) { + const scrollWrapper = proxy.$refs.scrollWrapper // 获取右侧滚动容器 + const categoryOffsetTop = categoryRef[0].offsetTop + + // 滚动到对应位置 + scrollWrapper.scrollTo({ top: categoryOffsetTop, behavior: 'smooth' }) + } } /** 初始化 */ diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue index 9df395f6..d770452f 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue @@ -24,7 +24,7 @@ - + {{ activity.name }} @@ -36,53 +36,79 @@ {{ getApprovalNodeTime(activity) }} - + + + + + + + + + + {{ user.nickname.substring(0, 1) }} + + {{ user.nickname }} + + + - - + + + - + + + + {{ task.assigneeUser?.nickname.substring(0, 1) }} + + {{ task.assigneeUser?.nickname }} + + + + + {{ task.ownerUser?.nickname.substring(0, 1) }} + + {{ task.ownerUser?.nickname }} + + - - - - {{ task.assigneeUser?.nickname.substring(0, 1) }} - - {{ task.assigneeUser?.nickname }} - - - - - {{ task.ownerUser?.nickname.substring(0, 1) }} - - {{ task.ownerUser?.nickname }} - - - - - + + +