Browse Source

【功能优化】BPM:待审批、已审批的所属流程的筛选

YunaiV 5 tháng trước cách đây
mục cha
commit
20564ed803

+ 6 - 0
src/api/bpm/definition/index.ts

@@ -20,3 +20,9 @@ export const getProcessDefinitionList = async (params) => {
     params
   })
 }
+
+export const getSimpleProcessDefinitionList = async () => {
+  return await request.get({
+    url: '/bpm/process-definition/simple-list'
+  })
+}

+ 0 - 267
src/views/bpm/processInstance/create/index_old.vue

@@ -1,267 +0,0 @@
-<template>
-  <doc-alert title="流程发起、取消、重新发起" url="https://doc.iocoder.cn/bpm/process-instance/" />
-
-  <!-- 第一步,通过流程定义的列表,选择对应的流程 -->
-  <ContentWrap v-if="!selectProcessDefinition" v-loading="loading">
-    <el-tabs tab-position="left" v-model="categoryActive">
-      <el-tab-pane
-        :label="category.name"
-        :name="category.code"
-        :key="category.code"
-        v-for="category in categoryList"
-      >
-        <el-row :gutter="20">
-          <el-col
-            :lg="6"
-            :sm="12"
-            :xs="24"
-            v-for="definition in categoryProcessDefinitionList"
-            :key="definition.id"
-          >
-            <el-card
-              shadow="hover"
-              class="mb-20px cursor-pointer"
-              @click="handleSelect(definition)"
-            >
-              <template #default>
-                <div class="flex">
-                  <el-image :src="definition.icon" class="w-32px h-32px" />
-                  <el-text class="!ml-10px" size="large">{{ definition.name }}</el-text>
-                </div>
-              </template>
-            </el-card>
-          </el-col>
-        </el-row>
-      </el-tab-pane>
-    </el-tabs>
-  </ContentWrap>
-
-  <!-- 第二步,填写表单,进行流程的提交 -->
-  <ContentWrap v-else>
-    <el-card class="box-card">
-      <div class="clearfix">
-        <span class="el-icon-document">申请信息【{{ selectProcessDefinition.name }}】</span>
-        <el-button style="float: right" type="primary" @click="selectProcessDefinition = undefined">
-          <Icon icon="ep:delete" /> 选择其它流程
-        </el-button>
-      </div>
-      <el-col :span="16" :offset="6" style="margin-top: 20px">
-        <form-create
-          :rule="detailForm.rule"
-          v-model:api="fApi"
-          v-model="detailForm.value"
-          :option="detailForm.option"
-          @submit="submitForm"
-        >
-          <template #type-startUserSelect>
-            <el-col :span="24">
-              <el-card class="mb-10px">
-                <template #header>指定审批人</template>
-                <el-form
-                  :model="startUserSelectAssignees"
-                  :rules="startUserSelectAssigneesFormRules"
-                  ref="startUserSelectAssigneesFormRef"
-                >
-                  <el-form-item
-                    v-for="userTask in startUserSelectTasks"
-                    :key="userTask.id"
-                    :label="`任务【${userTask.name}】`"
-                    :prop="userTask.id"
-                  >
-                    <el-select
-                      v-model="startUserSelectAssignees[userTask.id]"
-                      multiple
-                      placeholder="请选择审批人"
-                    >
-                      <el-option
-                        v-for="user in userList"
-                        :key="user.id"
-                        :label="user.nickname"
-                        :value="user.id"
-                      />
-                    </el-select>
-                  </el-form-item>
-                </el-form>
-              </el-card>
-            </el-col>
-          </template>
-        </form-create>
-      </el-col>
-    </el-card>
-    <!-- 流程图预览 -->
-    <ProcessInstanceBpmnViewer :bpmn-xml="bpmnXML as any" />
-  </ContentWrap>
-</template>
-<script lang="ts" setup>
-import * as DefinitionApi from '@/api/bpm/definition'
-import * as ProcessInstanceApi from '@/api/bpm/processInstance'
-import { decodeFields, setConfAndFields2 } from '@/utils/formCreate'
-import type { ApiAttrs } from '@form-create/element-ui/types/config'
-import ProcessInstanceBpmnViewer from '../detail/ProcessInstanceBpmnViewer.vue'
-import { CategoryApi } from '@/api/bpm/category'
-import { useTagsViewStore } from '@/store/modules/tagsView'
-import * as UserApi from '@/api/system/user'
-
-defineOptions({ name: 'BpmProcessInstanceCreate' })
-
-const route = useRoute() // 路由
-const { push, currentRoute } = useRouter() // 路由
-const message = useMessage() // 消息
-const { delView } = useTagsViewStore() // 视图操作
-
-const processInstanceId = route.query.processInstanceId
-const loading = ref(true) // 加载中
-const categoryList = ref([]) // 分类的列表
-const categoryActive = ref('') // 选中的分类
-const processDefinitionList = ref([]) // 流程定义的列表
-
-/** 查询列表 */
-const getList = async () => {
-  loading.value = true
-  try {
-    // 流程分类
-    categoryList.value = await CategoryApi.getCategorySimpleList()
-    if (categoryList.value.length > 0) {
-      categoryActive.value = categoryList.value[0].code
-    }
-    // 流程定义
-    processDefinitionList.value = await DefinitionApi.getProcessDefinitionList({
-      suspensionState: 1
-    })
-
-    // 如果 processInstanceId 非空,说明是重新发起
-    if (processInstanceId?.length > 0) {
-      const processInstance = await ProcessInstanceApi.getProcessInstance(processInstanceId)
-      if (!processInstance) {
-        message.error('重新发起流程失败,原因:流程实例不存在')
-        return
-      }
-      const processDefinition = processDefinitionList.value.find(
-        (item) => item.key == processInstance.processDefinition?.key
-      )
-      if (!processDefinition) {
-        message.error('重新发起流程失败,原因:流程定义不存在')
-        return
-      }
-      await handleSelect(processDefinition, processInstance.formVariables)
-    }
-  } finally {
-    loading.value = false
-  }
-}
-
-/** 选中分类对应的流程定义列表 */
-const categoryProcessDefinitionList = computed(() => {
-  return processDefinitionList.value.filter((item) => item.category == categoryActive.value)
-})
-
-// ========== 表单相关 ==========
-const fApi = ref<ApiAttrs>()
-const detailForm = ref({
-  rule: [],
-  option: {},
-  value: {}
-}) // 流程表单详情
-const selectProcessDefinition = ref() // 选择的流程定义
-
-// 指定审批人
-const bpmnXML = ref(null) // BPMN 数据
-const startUserSelectTasks = ref([]) // 发起人需要选择审批人的用户任务列表
-const startUserSelectAssignees = ref({}) // 发起人选择审批人的数据
-const startUserSelectAssigneesFormRef = ref() // 发起人选择审批人的表单 Ref
-const startUserSelectAssigneesFormRules = ref({}) // 发起人选择审批人的表单 Rules
-const userList = ref<any[]>([]) // 用户列表
-
-/** 处理选择流程的按钮操作 **/
-const handleSelect = async (row, formVariables) => {
-  // 设置选择的流程
-  selectProcessDefinition.value = row
-
-  // 重置指定审批人
-  startUserSelectTasks.value = []
-  startUserSelectAssignees.value = {}
-  startUserSelectAssigneesFormRules.value = {}
-
-  // 情况一:流程表单
-  if (row.formType == 10) {
-    // 设置表单
-    // 注意:需要从 formVariables 中,移除不在 row.formFields 的值。
-    // 原因是:后端返回的 formVariables 里面,会有一些非表单的信息。例如说,某个流程节点的审批人。
-    //        这样,就可能导致一个流程被审批不通过后,重新发起时,会直接后端报错!!!
-    const allowedFields = decodeFields(row.formFields).map((fieldObj: any) => fieldObj.field)
-    for (const key in formVariables) {
-      if (!allowedFields.includes(key)) {
-        delete formVariables[key]
-      }
-    }
-    setConfAndFields2(detailForm, row.formConf, row.formFields, formVariables)
-
-    // 加载流程图
-    const processDefinitionDetail = await DefinitionApi.getProcessDefinition(row.id)
-    if (processDefinitionDetail) {
-      bpmnXML.value = processDefinitionDetail.bpmnXml
-      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()
-      }
-    }
-    // 情况二:业务表单
-  } else if (row.formCustomCreatePath) {
-    await push({
-      path: row.formCustomCreatePath
-    })
-    // 这里暂时无需加载流程图,因为跳出到另外个 Tab;
-  }
-}
-
-/** 提交按钮 */
-const submitForm = async (formData) => {
-  if (!fApi.value || !selectProcessDefinition.value) {
-    return
-  }
-  // 如果有指定审批人,需要校验
-  if (startUserSelectTasks.value?.length > 0) {
-    await startUserSelectAssigneesFormRef.value.validate()
-  }
-
-  // 提交请求
-  fApi.value.btn.loading(true)
-  try {
-    await ProcessInstanceApi.createProcessInstance({
-      processDefinitionId: selectProcessDefinition.value.id,
-      variables: formData,
-      startUserSelectAssignees: startUserSelectAssignees.value
-    })
-    // 提示
-    message.success('发起流程成功')
-    // 跳转回去
-    delView(unref(currentRoute))
-    await push({
-      name: 'BpmProcessInstanceMy'
-    })
-  } finally {
-    fApi.value.btn.loading(false)
-  }
-}
-
-/** 初始化 */
-onMounted(() => {
-  getList()
-})
-</script>

+ 15 - 6
src/views/bpm/processInstance/index.vue

@@ -40,7 +40,6 @@
           />
         </el-select>
       </el-form-item>
-
       <el-form-item label="" prop="status" class="absolute right-[130px]">
         <el-select
           v-model="queryParams.status"
@@ -78,13 +77,20 @@
             label-position="top"
             prop="processDefinitionKey"
           >
-            <el-input
+            <el-select
               v-model="queryParams.processDefinitionKey"
-              placeholder="请输入流程定义的标识"
+              placeholder="请选择流程定义"
               clearable
-              @keyup.enter="handleQuery"
               class="!w-390px"
-            />
+              @change="handleQuery"
+            >
+              <el-option
+                v-for="item in processDefinitionList"
+                :key="item.key"
+                :label="item.name"
+                :value="item.key"
+              />
+            </el-select>
           </el-form-item>
           <el-form-item label="发起时间" class="font-bold" label-position="top" prop="createTime">
             <el-date-picker
@@ -113,7 +119,7 @@
   <ContentWrap>
     <el-table v-loading="loading" :data="list">
       <el-table-column label="流程名称" align="center" prop="name" min-width="200px" fixed="left" />
-      <el-table-column label="摘要" prop="summary" min-width="180" fixed="left">
+      <el-table-column label="摘要" prop="summary" width="180" fixed="left">
         <template #default="scope">
           <div class="flex flex-col" v-if="scope.row.summary && scope.row.summary.length > 0">
             <div v-for="(item, index) in scope.row.summary" :key="index">
@@ -229,6 +235,7 @@ const { t } = useI18n() // 国际化
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
+const processDefinitionList = ref<any[]>([]) // 流程定义列表
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
@@ -320,5 +327,7 @@ onActivated(() => {
 onMounted(async () => {
   await getList()
   categoryList.value = await CategoryApi.getCategorySimpleList()
+  // 获取流程定义列表
+  processDefinitionList.value = await DefinitionApi.getSimpleProcessDefinitionList()
 })
 </script>

+ 33 - 16
src/views/bpm/task/done/index.vue

@@ -76,26 +76,31 @@
           placement="bottom-end"
         >
           <template #reference>
-            <el-button @click="showPopover = !showPopover" >
+            <el-button @click="showPopover = !showPopover">
               <Icon icon="ep:plus" class="mr-5px" />高级筛选
             </el-button>
-
           </template>
-          <!-- <el-form-item label="流程发起人" class="bold-label" label-position="top" prop="category">
+          <el-form-item
+            label="所属流程"
+            class="font-bold"
+            label-position="top"
+            prop="processDefinitionKey"
+          >
             <el-select
-              v-model="queryParams.category"
-              placeholder="请选择流程发起人"
+              v-model="queryParams.processDefinitionKey"
+              placeholder="请选择流程定义"
               clearable
+              @change="handleQuery"
               class="!w-390px"
             >
               <el-option
-                v-for="category in categoryList"
-                :key="category.code"
-                :label="category.name"
-                :value="category.code"
+                v-for="item in processDefinitionList"
+                :key="item.key"
+                :label="item.name"
+                :value="item.key"
               />
             </el-select>
-          </el-form-item> -->
+          </el-form-item>
           <el-form-item label="发起时间" class="bold-label" label-position="top" prop="createTime">
             <el-date-picker
               v-model="queryParams.createTime"
@@ -111,10 +116,9 @@
             <el-button @click="handleQuery"> 确认</el-button>
             <el-button @click="showPopover = false"> 取消</el-button>
             <el-button @click="resetQuery"> 清空</el-button>
-        </el-form-item>
+          </el-form-item>
         </el-popover>
       </el-form-item>
-
     </el-form>
   </ContentWrap>
 
@@ -122,9 +126,12 @@
   <ContentWrap>
     <el-table v-loading="loading" :data="list">
       <el-table-column align="center" label="流程" prop="processInstance.name" width="180" />
-      <el-table-column label="摘要" prop="processInstance.summary" min-width="180">
+      <el-table-column label="摘要" prop="processInstance.summary" width="180">
         <template #default="scope">
-          <div class="flex flex-col" v-if="scope.row.processInstance.summary && scope.row.processInstance.summary.length > 0">
+          <div
+            class="flex flex-col"
+            v-if="scope.row.processInstance.summary && scope.row.processInstance.summary.length > 0"
+          >
             <div v-for="(item, index) in scope.row.processInstance.summary" :key="index">
               <el-text type="info"> {{ item.key }} : {{ item.value }} </el-text>
             </div>
@@ -170,7 +177,12 @@
           {{ formatPast2(scope.row.durationInMillis) }}
         </template>
       </el-table-column>
-      <el-table-column align="center" label="流程编号" prop="processInstanceId" :show-overflow-tooltip="true" />
+      <el-table-column
+        align="center"
+        label="流程编号"
+        prop="processInstanceId"
+        :show-overflow-tooltip="true"
+      />
       <el-table-column align="center" label="任务编号" prop="id" :show-overflow-tooltip="true" />
       <el-table-column align="center" label="操作" fixed="right" width="80">
         <template #default="scope">
@@ -192,6 +204,7 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import { dateFormatter, formatPast2 } from '@/utils/formatTime'
 import * as TaskApi from '@/api/bpm/task'
 import { CategoryApi, CategoryVO } from '@/api/bpm/category'
+import * as DefinitionApi from '@/api/bpm/definition'
 
 defineOptions({ name: 'BpmDoneTask' })
 
@@ -200,17 +213,19 @@ const { push } = useRouter() // 路由
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
+const processDefinitionList = ref<any[]>([]) // 流程定义列表
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
   name: '',
   category: undefined,
   status: undefined,
+  processDefinitionKey: '',
   createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
 const categoryList = ref<CategoryVO[]>([]) // 流程分类列表
-const showPopover = ref(false)
+const showPopover = ref(false) // 高级筛选是否展示
 
 /** 查询任务列表 */
 const getList = async () => {
@@ -251,5 +266,7 @@ const handleAudit = (row: any) => {
 onMounted(async () => {
   await getList()
   categoryList.value = await CategoryApi.getCategorySimpleList()
+  // 获取流程定义列表
+  processDefinitionList.value = await DefinitionApi.getSimpleProcessDefinitionList()
 })
 </script>

+ 43 - 27
src/views/bpm/task/todo/index.vue

@@ -31,8 +31,7 @@
           搜索
         </el-button>
       </el-form-item>
-
-      <el-form-item label="" prop="category" :style="{ position: 'absolute', right: '130px' }">
+      <el-form-item label="" prop="category" class="absolute right-130px">
         <el-select
           v-model="queryParams.category"
           placeholder="请选择流程分类"
@@ -48,9 +47,8 @@
           />
         </el-select>
       </el-form-item>
-
       <!-- 高级筛选 -->
-      <el-form-item :style="{ position: 'absolute', right: '0px' }">
+      <el-form-item class="absolute right-0">
         <el-popover
           :visible="showPopover"
           persistent
@@ -59,27 +57,32 @@
           placement="bottom-end"
         >
           <template #reference>
-            <el-button @click="showPopover = !showPopover" >
+            <el-button @click="showPopover = !showPopover">
               <Icon icon="ep:plus" class="mr-5px" />高级筛选
             </el-button>
-
           </template>
-          <!-- <el-form-item label="流程发起人" class="bold-label" label-position="top" prop="category">
+          <el-form-item
+            label="所属流程"
+            class="font-bold"
+            label-position="top"
+            prop="processDefinitionKey"
+          >
             <el-select
-              v-model="queryParams.category"
-              placeholder="请选择流程发起人"
+              v-model="queryParams.processDefinitionKey"
+              placeholder="请选择流程定义"
               clearable
+              @change="handleQuery"
               class="!w-390px"
             >
               <el-option
-                v-for="category in categoryList"
-                :key="category.code"
-                :label="category.name"
-                :value="category.code"
+                v-for="item in processDefinitionList"
+                :key="item.key"
+                :label="item.name"
+                :value="item.key"
               />
             </el-select>
-          </el-form-item> -->
-          <el-form-item label="发起时间" class="bold-label" label-position="top" prop="createTime">
+          </el-form-item>
+          <el-form-item label="发起时间" class="font-bold" label-position="top" prop="createTime">
             <el-date-picker
               v-model="queryParams.createTime"
               value-format="YYYY-MM-DD HH:mm:ss"
@@ -87,17 +90,18 @@
               start-placeholder="开始日期"
               end-placeholder="结束日期"
               :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-              class="!w-240px"
+              class="w-240px!"
             />
           </el-form-item>
-          <el-form-item class="bold-label" label-position="top">
-            <el-button @click="handleQuery"> 确认</el-button>
-            <el-button @click="showPopover = false"> 取消</el-button>
-            <el-button @click="resetQuery"> 清空</el-button>
-        </el-form-item>
+          <el-form-item class="font-bold" label-position="top">
+            <div class="flex justify-end w-full">
+              <el-button @click="resetQuery">清空</el-button>
+              <el-button @click="showPopover = false">取消</el-button>
+              <el-button type="primary" @click="handleQuery">确认</el-button>
+            </div>
+          </el-form-item>
         </el-popover>
       </el-form-item>
-
     </el-form>
   </ContentWrap>
 
@@ -105,9 +109,12 @@
   <ContentWrap>
     <el-table v-loading="loading" :data="list">
       <el-table-column align="center" label="流程" prop="processInstance.name" width="180" />
-      <el-table-column label="摘要" prop="processInstance.summary" min-width="180">
+      <el-table-column label="摘要" prop="processInstance.summary" width="180">
         <template #default="scope">
-          <div class="flex flex-col" v-if="scope.row.processInstance.summary && scope.row.processInstance.summary.length > 0">
+          <div
+            class="flex flex-col"
+            v-if="scope.row.processInstance.summary && scope.row.processInstance.summary.length > 0"
+          >
             <div v-for="(item, index) in scope.row.processInstance.summary" :key="index">
               <el-text type="info"> {{ item.key }} : {{ item.value }} </el-text>
             </div>
@@ -135,7 +142,12 @@
         prop="createTime"
         width="180"
       />
-      <el-table-column align="center" label="流程编号" prop="processInstanceId" :show-overflow-tooltip="true" />
+      <el-table-column
+        align="center"
+        label="流程编号"
+        prop="processInstanceId"
+        :show-overflow-tooltip="true"
+      />
       <el-table-column align="center" label="任务编号" prop="id" :show-overflow-tooltip="true" />
       <el-table-column align="center" label="操作" fixed="right" width="80">
         <template #default="scope">
@@ -157,6 +169,7 @@
 import { dateFormatter } from '@/utils/formatTime'
 import * as TaskApi from '@/api/bpm/task'
 import { CategoryApi, CategoryVO } from '@/api/bpm/category'
+import * as DefinitionApi from '@/api/bpm/definition'
 
 defineOptions({ name: 'BpmTodoTask' })
 
@@ -165,15 +178,18 @@ const { push } = useRouter() // 路由
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
 const list = ref([]) // 列表的数据
+const processDefinitionList = ref<any[]>([]) // 流程定义列表
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
   name: '',
   category: undefined,
+  processDefinitionKey: '',
   createTime: []
 })
 const queryFormRef = ref() // 搜索的表单
 const categoryList = ref<CategoryVO[]>([]) // 流程分类列表
+const showPopover = ref(false) // 高级筛选是否展示
 
 /** 查询任务列表 */
 const getList = async () => {
@@ -187,8 +203,6 @@ const getList = async () => {
   }
 }
 
-const showPopover = ref(false)
-
 /** 搜索按钮操作 */
 const handleQuery = () => {
   queryParams.pageNo = 1
@@ -216,5 +230,7 @@ const handleAudit = (row: any) => {
 onMounted(async () => {
   await getList()
   categoryList.value = await CategoryApi.getCategorySimpleList()
+  // 获取流程定义列表
+  processDefinitionList.value = await DefinitionApi.getSimpleProcessDefinitionList()
 })
 </script>