Prechádzať zdrojové kódy

【功能完善】审批时,流程表单可编辑字段,可修改。

jason 8 mesiacov pred
rodič
commit
0b6af855ac

+ 0 - 8
src/components/SimpleProcessDesignerV2/src/node.ts

@@ -15,7 +15,6 @@ import {
   AssignStartUserHandlerType,
   AssignEmptyHandlerType,
   FieldPermissionType,
-  ProcessVariableEnum
 } from './consts'
 import { parseFormFields } from '@/components/FormCreate/src/utils/index'
 export function useWatchNode(props: { flowNode: SimpleFlowNode }): Ref<SimpleFlowNode> {
@@ -37,13 +36,6 @@ const parseFormCreateFields = (formFields?: string[]) => {
       parseFormFields(JSON.parse(fieldStr), result)
     })
   }
-  // 固定添加发起人 ID 字段
-  result.unshift({
-    field: ProcessVariableEnum.START_USER_ID,
-    title: '发起人',
-    type: 'UserSelect',
-    required: true
-  })
   return result
 }
 

+ 16 - 3
src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue

@@ -102,7 +102,7 @@
                   <div class="mr-2">
                     <el-select style="width: 160px" v-model="rule.leftSide">
                       <el-option
-                        v-for="(item, index) in fieldsInfo"
+                        v-for="(item, index) in fieldOptions"
                         :key="index"
                         :label="item.title"
                         :value="item.field"
@@ -160,7 +160,8 @@ import {
   COMPARISON_OPERATORS,
   ConditionGroup,
   Condition,
-  ConditionRule
+  ConditionRule,
+  ProcessVariableEnum
 } from '../consts'
 import { getDefaultConditionNodeName } from '../utils'
 import { useFormFields } from '../node'
@@ -364,9 +365,21 @@ const addConditionRule = (condition: Condition, idx: number) => {
 const deleteConditionRule = (condition: Condition, idx: number) => {
   condition.rules.splice(idx, 1)
 }
-
 const fieldsInfo = useFormFields()
 
+/** 条件规则可选择的表单字段 */
+const fieldOptions = computed(() => {
+  const fieldsCopy = fieldsInfo.slice();
+  // 固定添加发起人 ID 字段
+  fieldsCopy.unshift({
+    field: ProcessVariableEnum.START_USER_ID,
+    title: '发起人',
+    required: true
+  })
+  return fieldsCopy
+})
+
+
 const getFieldTitle = (field: string) => {
   const item = fieldsInfo.find((item) => item.field === field)
   return item?.title

+ 9 - 1
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue

@@ -469,7 +469,8 @@ import {
   TimeoutHandlerType,
   ASSIGN_EMPTY_HANDLER_TYPES,
   AssignEmptyHandlerType,
-  FieldPermissionType
+  FieldPermissionType,
+  ProcessVariableEnum
 } from '../consts'
 
 import {
@@ -519,6 +520,13 @@ const { formType, fieldsPermissionConfig, formFieldOptions, getNodeConfigFormFie
   useFormFieldsPermission(FieldPermissionType.READ)
 // 表单内用户字段选项, 必须是必填和用户选择器
 const userFieldOnFormOptions = computed(() => {
+  // 固定添加发起人 ID 字段
+  formFieldOptions.unshift({
+    field: ProcessVariableEnum.START_USER_ID,
+    title: '发起人',
+    type: 'UserSelect',
+    required: true
+  })
   return formFieldOptions.filter((item) => item.type === 'UserSelect')
 })
 // 表单内部门字段选项, 必须是必填和部门选择器

+ 52 - 12
src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue

@@ -477,13 +477,12 @@ import { useUserStoreWithOut } from '@/store/modules/user'
 import { setConfAndFields2 } from '@/utils/formCreate'
 import * as TaskApi from '@/api/bpm/task'
 import * as ProcessInstanceApi from '@/api/bpm/processInstance'
-import { propTypes } from '@/utils/propTypes'
+import * as UserApi from '@/api/system/user'
 import {
   OperationButtonType,
   OPERATION_BUTTON_NAME
 } from '@/components/SimpleProcessDesignerV2/src/consts'
-import { BpmProcessInstanceStatus } from '@/utils/constants'
-
+import { BpmProcessInstanceStatus, BpmModelFormType } from '@/utils/constants'
 defineOptions({ name: 'ProcessInstanceBtnContainer' })
 
 const router = useRouter() // 路由
@@ -492,11 +491,15 @@ const { proxy } = getCurrentInstance() as any
 
 const userId = useUserStoreWithOut().getUser.id // 当前登录的编号
 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const props = defineProps({
-  processInstance: propTypes.object, // 流程实例信息
-  processDefinition: propTypes.object, // 流程定义信息
-  userOptions: propTypes.any
-})
+
+const props = defineProps< {
+  processInstance: any,  // 流程实例信息
+  processDefinition: any,  // 流程定义信息
+  userOptions: UserApi.UserVO[],
+  normalForm: any, // 流程表单 formCreate
+  normalFormApi: any, // 流程表单 formCreate Api
+  writableFields: string[] // 流程表单可以编辑的字段
+}>()
 
 const formLoading = ref(false) // 表单加载中
 const popOverVisible = ref({
@@ -554,6 +557,14 @@ const openReturnPopover = async () => {
 
 /** 弹出气泡卡 */
 const openPopover = async (type: string) => {
+  if (type === 'approve') {
+    // 校验流程表单
+     const valid = await validateNormalForm();
+     if (!valid) {
+      message.error('表单校验不通过,请先完善表单!!')
+      return;
+     }
+  }
   Object.keys(popOverVisible.value).forEach((item) => {
     popOverVisible.value[item] = item === type
   })
@@ -565,24 +576,29 @@ const openPopover = async (type: string) => {
 const handleAudit = async (pass: boolean) => {
   formLoading.value = true
   try {
+    // 校验审批表单
     const genericFormRef = proxy.$refs['formRef']
-    // 1.2 校验表单
     const elForm = unref(genericFormRef)
     if (!elForm) return
     const valid = await elForm.validate()
     if (!valid) return
-
-    // 2.1 提交审批
+    // 提交审批
     const data = {
       id: runningTask.value.id,
-      reason: genericForm.value.reason
+      reason: genericForm.value.reason,
     }
     if (pass) {
+       // 获取修改的流程变量, 暂时只支持流程表单
+      const variables = getUpdatedProcessInstanceVaiables();
+      // 审批通过, 把修改的字段值赋于流程实例变量
+      // @ts-ignore
+      data.variables = variables
       // 审批通过,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
       const formCreateApi = approveFormFApi.value
       if (Object.keys(formCreateApi)?.length > 0) {
         await formCreateApi.validate()
         // @ts-ignore
+        // TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突
         data.variables = approveForm.value.value
       }
       await TaskApi.approveTask(data)
@@ -855,6 +871,30 @@ const loadTodoTask = (task: any) => {
   }
 }
 
+/** 校验流程表单 */
+const validateNormalForm = async () => {
+  if (props.processDefinition?.formType === BpmModelFormType.NORMAL) {
+    let valid = true
+    try {
+      await props.normalFormApi?.validate()
+    } catch {
+      valid = false;
+    }
+    return valid;
+  } else {
+    return true;
+  }
+}
+/** 从可以编辑的流程表单字段,获取需要修改的流程实例的变量 */
+const getUpdatedProcessInstanceVaiables = ()=> {
+  const variables = {}
+  props.writableFields.forEach( (field) => {
+    const fieldValue = props.normalFormApi.getValue(field)
+    variables[field] = fieldValue;
+  })
+  return variables
+}
+
 defineExpose({ loadTodoTask })
 </script>
 

+ 16 - 7
src/views/bpm/processInstance/detail/index.vue

@@ -49,7 +49,7 @@
                       class="form-box flex flex-col mb-30px flex-1"
                     >
                       <!-- 情况一:流程表单 -->
-                      <el-col v-if="processDefinition?.formType === 10">
+                      <el-col v-if="processDefinition?.formType === BpmModelFormType.NORMAL">
                         <form-create
                           v-model="detailForm.value"
                           v-model:api="fApi"
@@ -58,7 +58,7 @@
                         />
                       </el-col>
                       <!-- 情况二:业务表单 -->
-                      <div v-if="processDefinition?.formType === 20">
+                      <div v-if="processDefinition?.formType === BpmModelFormType.CUSTOM">
                         <BusinessFormComponent :id="processInstance.businessKey" />
                       </div>
                     </div>
@@ -116,6 +116,9 @@
             :process-instance="processInstance"
             :process-definition="processDefinition"
             :userOptions="userOptions"
+            :normal-form ="detailForm"
+            :normal-form-api="fApi"
+            :writable-fields="writableFields"
             @success="refresh"
           />
         </div>
@@ -126,7 +129,7 @@
 <script lang="ts" setup>
 import { formatDate } from '@/utils/formatTime'
 import { DICT_TYPE } from '@/utils/dict'
-import { BpmModelType } from '@/utils/constants'
+import { BpmModelType,BpmModelFormType } from '@/utils/constants'
 import { setConfAndFields2 } from '@/utils/formCreate'
 import { registerComponent } from '@/utils/routerHelper'
 import type { ApiAttrs } from '@form-create/element-ui/types/config'
@@ -171,6 +174,9 @@ const detailForm = ref({
   value: {}
 }) // 流程实例的表单详情
 
+// 表单可以编辑的字段
+const writableFields : Array<string> = [];
+
 /** 获得详情 */
 const getDetail = () => {
   getApprovalDetail()
@@ -202,11 +208,12 @@ const getApprovalDetail = async () => {
     processDefinition.value = data.processDefinition
 
     // 设置表单信息
-    if (processDefinition.value.formType === 10) {
+    if (processDefinition.value.formType === BpmModelFormType.NORMAL) {
       // 获取表单字段权限
       const formFieldsPermission = data.formFieldsPermission
-
-      if (detailForm.value.rule.length > 0) {
+      // 清空可编辑字段为空
+      writableFields.splice(0)
+      if (detailForm.value.rule?.length > 0) {
         // 避免刷新 form-create 显示不了
         detailForm.value.value = processInstance.value.formVariables
       } else {
@@ -271,6 +278,8 @@ const setFieldPermission = (field: string, permission: string) => {
   if (permission === FieldPermissionType.WRITE) {
     //@ts-ignore
     fApi.value?.disabled(false, field)
+    // 加入可以编辑的字段
+    writableFields.push(field);
   }
   if (permission === FieldPermissionType.NONE) {
     //@ts-ignore
@@ -314,6 +323,7 @@ $process-header-height: 194px;
   overflow: auto;
 
   .form-scroll-area {
+    display: flex;
     height: calc(
       100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px -
         $process-header-height - 40px
@@ -323,7 +333,6 @@ $process-header-height: 194px;
         $process-header-height - 40px
     );
     overflow: auto;
-    display: flex;
     flex-direction: column;
 
     :deep(.box-card) {