瀏覽代碼

feat: 发起流程-填写表单页面单独抽取子组件,总体布局调整与样式绘制

GoldenZqqq 9 月之前
父節點
當前提交
c1109e90c4

+ 247 - 0
src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue

@@ -0,0 +1,247 @@
+<template>
+  <ContentWrap :bodyStyle="{ padding: '10px 20px 0' }">
+    <div class="processInstance-wrap-main">
+      <el-scrollbar>
+        <div class="text-#878c93 h-15px">编号:{{ selectProcessDefinition.id }}</div>
+        <el-divider class="!my-8px" />
+
+        <div class="flex items-center justify-between gap-5 mb-10px h-40px">
+          <div class="text-26px font-bold mb-5px">{{ selectProcessDefinition.name }}</div>
+          <el-button style="float: right" type="primary" @click="handleCancel">
+            <Icon icon="ep:delete" /> 选择其它流程
+          </el-button>
+        </div>
+        <!-- 中间主要内容tab栏 -->
+        <el-tabs v-model="activeTab">
+          <!-- 表单信息 -->
+          <el-tab-pane label="表单填写" name="form">
+            <div class="form-scroll-area">
+              <el-scrollbar>
+                <el-row>
+                  <el-col :span="17">
+                    <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-col :span="7">
+                    <!-- 审批记录时间线 -->
+                    <!-- <ProcessInstanceTimeline ref="timelineRef" :approve-nodes="approveNodes" /> -->
+                  </el-col>
+                </el-row>
+              </el-scrollbar>
+            </div>
+          </el-tab-pane>
+          <!-- 流程图 -->
+          <el-tab-pane label="流程图" name="diagram">
+            <div class="form-scroll-area">
+              <!-- 流程图预览 -->
+              <ProcessInstanceBpmnViewer :bpmn-xml="bpmnXML" />
+            </div>
+          </el-tab-pane>
+        </el-tabs>
+
+        <!-- 底部操作栏 -->
+        <div class="b-t-solid border-t-1px border-[var(--el-border-color)]">
+          <!-- 操作栏按钮 -->
+          <div
+            class="h-50px bottom-10 text-14px flex items-center color-#32373c dark:color-#fff font-bold btn-container"
+          >
+            <el-button plain type="success" @click="submitForm">
+              <Icon icon="ep:select" />&nbsp; 发起
+            </el-button>
+            <el-button plain type="danger" @click="handleCancel">
+              <Icon icon="ep:close" />&nbsp; 取消
+            </el-button>
+          </div>
+        </div>
+      </el-scrollbar>
+    </div>
+  </ContentWrap>
+</template>
+<script lang="ts" setup>
+import { setConfAndFields2 } from '@/utils/formCreate'
+import ProcessInstanceBpmnViewer from '../detail/ProcessInstanceBpmnViewer.vue'
+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<{
+  selectProcessDefinition: any
+}>()
+const { push, currentRoute } = useRouter() // 路由
+const message = useMessage() // 消息弹窗
+const { delView } = useTagsViewStore() // 视图操作
+
+const detailForm: any = ref({
+  rule: [],
+  option: {},
+  value: {}
+}) // 流程表单详情
+const fApi = ref<ApiAttrs>()
+// 指定审批人
+const startUserSelectAssigneesFormRef = ref() // 发起人选择审批人的表单 Ref
+const startUserSelectTasks: any = ref([]) // 发起人需要选择审批人的用户任务列表
+const startUserSelectAssignees = ref({}) // 发起人选择审批人的数据
+const startUserSelectAssigneesFormRules = ref({}) // 发起人选择审批人的表单 Rules
+const userList = ref<any[]>([]) // 用户列表
+const bpmnXML: any = ref(null) // BPMN 数据
+
+/** 当前的Tab */
+const activeTab = ref('form')
+const emit = defineEmits(['cancel'])
+/** 处理选择流程的按钮操作 **/
+const initProcessInfo = async (row, formVariables?) => {
+  // 重置指定审批人
+  startUserSelectTasks.value = []
+  startUserSelectAssignees.value = {}
+  startUserSelectAssigneesFormRules.value = {}
+
+  // 情况一:流程表单
+  if (row.formType == 10) {
+    // 设置表单
+    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 || props.selectProcessDefinition) {
+    return
+  }
+  // 如果有指定审批人,需要校验
+  if (startUserSelectTasks.value?.length > 0) {
+    await startUserSelectAssigneesFormRef.value.validate()
+  }
+
+  // 提交请求
+  fApi.value.btn.loading(true)
+  try {
+    await ProcessInstanceApi.createProcessInstance({
+      processDefinitionId: props.selectProcessDefinition.id,
+      variables: formData || detailForm.value.value,
+      startUserSelectAssignees: startUserSelectAssignees.value
+    })
+    // 提示
+    message.success('发起流程成功')
+    // 跳转回去
+    delView(unref(currentRoute))
+    await push({
+      name: 'BpmProcessInstanceMy'
+    })
+  } finally {
+    fApi.value.btn.loading(false)
+  }
+}
+
+const handleCancel = () => {
+  emit('cancel')
+}
+
+defineExpose({ initProcessInfo })
+</script>
+
+<style lang="scss" scoped>
+$wrap-padding-height: 20px;
+$wrap-margin-height: 15px;
+$button-height: 51px;
+$process-header-height: 194px;
+
+.processInstance-wrap-main {
+  height: calc(
+    100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px
+  );
+  max-height: calc(
+    100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px
+  );
+  overflow: auto;
+
+  .form-scroll-area {
+    height: calc(
+      100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px -
+        $process-header-height - 40px
+    );
+    max-height: calc(
+      100vh - var(--top-tool-height) - var(--tags-view-height) - var(--app-footer-height) - 35px -
+        $process-header-height - 40px
+    );
+    overflow: auto;
+  }
+}
+
+.form-box {
+  :deep(.el-card) {
+    border: none;
+  }
+}
+</style>

+ 11 - 150
src/views/bpm/processInstance/create/index_new.vue

@@ -43,86 +43,31 @@
   </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" />
-  </ContentWrap>
+  <ProcessDefinitionDetail
+    v-else
+    ref="processDefinitionDetailRef"
+    :selectProcessDefinition="selectProcessDefinition"
+    @cancel="selectProcessDefinition = undefined"
+  />
 </template>
 
 <script lang="ts" setup>
 import * as DefinitionApi from '@/api/bpm/definition'
 import * as ProcessInstanceApi from '@/api/bpm/processInstance'
-import { 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'
+import ProcessDefinitionDetail from './ProcessDefinitionDetail.vue'
 import { categoryList as cl, processDefinitionList as pl } from './mock'
 
 defineOptions({ name: 'BpmProcessInstanceCreate' })
 
 const route = useRoute() // 路由
-const { push, currentRoute } = useRouter() // 路由
 const message = useMessage() // 消息
-const { delView } = useTagsViewStore() // 视图操作
 
 const processInstanceId: any = route.query.processInstanceId
 const loading = ref(true) // 加载中
 const categoryList: any = ref([]) // 分类的列表
 const categoryActive: any = ref({}) // 选中的分类
 const processDefinitionList = ref([]) // 流程定义的列表
-
 /** 查询列表 */
 const getList = async () => {
   loading.value = true
@@ -134,7 +79,6 @@ const getList = async () => {
     if (categoryList.value.length > 0) {
       categoryActive.value = categoryList.value[0]
     }
-    console.log('[ categoryActive.value ] >', categoryActive.value)
     // 流程定义
     processDefinitionList.value = await DefinitionApi.getProcessDefinitionList({
       suspensionState: 1
@@ -171,100 +115,17 @@ const categoryProcessDefinitionList: any = computed(() => {
 })
 
 // ========== 表单相关 ==========
-const fApi = ref<ApiAttrs>()
-const detailForm: any = ref({
-  rule: [],
-  option: {},
-  value: {}
-}) // 流程表单详情
 const selectProcessDefinition = ref() // 选择的流程定义
-
-// 指定审批人
-const bpmnXML: any = ref(null) // BPMN 数据
-const startUserSelectTasks: any = ref([]) // 发起人需要选择审批人的用户任务列表
-const startUserSelectAssignees = ref({}) // 发起人选择审批人的数据
-const startUserSelectAssigneesFormRef = ref() // 发起人选择审批人的表单 Ref
-const startUserSelectAssigneesFormRules = ref({}) // 发起人选择审批人的表单 Rules
-const userList = ref<any[]>([]) // 用户列表
+const processDefinitionDetailRef = ref()
 
 /** 处理选择流程的按钮操作 **/
 const handleSelect = async (row, formVariables?) => {
   // 设置选择的流程
   selectProcessDefinition.value = row
-
-  // 重置指定审批人
-  startUserSelectTasks.value = []
-  startUserSelectAssignees.value = {}
-  startUserSelectAssigneesFormRules.value = {}
-
-  // 情况一:流程表单
-  if (row.formType == 10) {
-    // 设置表单
-    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;
-  }
+  // 初始化流程定义详情
+  await nextTick()
+  processDefinitionDetailRef.value?.initProcessInfo(row, formVariables)
 }
-
-/** 提交按钮 */
-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)
-  }
-}
-
 // 左侧分类切换
 const handleCategoryClick = (val) => {
   categoryActive.value = val

+ 14 - 5
src/views/bpm/processInstance/create/mock.js

@@ -13,8 +13,12 @@ export const processDefinitionList = [
     category: 'approval',
     icon: 'https://picsum.photos/200?r=1',
     formType: 10,
-    formConf: {}, // 根据需要定义表单配置
-    formFields: [], // 根据需要定义表单字段
+    formConf:
+      '{"form":{"inline":false,"hideRequiredAsterisk":false,"labelPosition":"right","size":"default","labelWidth":"100px"},"resetBtn":{"show":false,"innerText":"重置"},"submitBtn":{"show":true,"innerText":"提交"}}',
+    formFields: [
+      '{"type":"input","field":"F1yrm2sosxgeabc","title":"请假原因","info":"","$required":false,"props":{"type":"text","placeholder":"请输入123"},"_fc_id":"id_Fhrbm2sosxgeacc","name":"ref_Festm2sosxgeadc","display":true,"hidden":false,"_fc_drag_tag":"input"}',
+      '{"type":"radio","field":"F9r3m2sp1b34aec","title":"请假类型","info":"","$required":false,"props":{"_optionType":2},"_fc_id":"id_F4nwm2sp1b34afc","name":"ref_Fkodm2sp1b34agc","display":true,"hidden":false,"_fc_drag_tag":"radio","options":[{"label":"事假","value":"1"},{"label":"婚假","value":"2"},{"label":"丧假","value":"3"}]}'
+    ],
     startUserSelectTasks: [
       { id: 'task1', name: '部门经理' },
       { id: 'task2', name: '人力资源' }
@@ -27,8 +31,12 @@ export const processDefinitionList = [
     category: 'approval',
     icon: 'https://picsum.photos/200?r=2',
     formType: 10,
-    formConf: {},
-    formFields: [],
+    formConf:
+      '{"form":{"inline":false,"hideRequiredAsterisk":false,"labelPosition":"right","size":"default","labelWidth":"100px"},"resetBtn":{"show":false,"innerText":"重置"},"submitBtn":{"show":true,"innerText":"提交"}}',
+    formFields: [
+      '{"type":"input","field":"F1yrm2sosxgeabc","title":"请假原因","info":"","$required":false,"props":{"type":"text","placeholder":"请输入123"},"_fc_id":"id_Fhrbm2sosxgeacc","name":"ref_Festm2sosxgeadc","display":true,"hidden":false,"_fc_drag_tag":"input"}',
+      '{"type":"radio","field":"F9r3m2sp1b34aec","title":"请假类型","info":"","$required":false,"props":{"_optionType":2},"_fc_id":"id_F4nwm2sp1b34afc","name":"ref_Fkodm2sp1b34agc","display":true,"hidden":false,"_fc_drag_tag":"radio","options":[{"label":"事假","value":"1"},{"label":"婚假","value":"2"},{"label":"丧假","value":"3"}]}'
+    ],
     startUserSelectTasks: [{ id: 'task3', name: '财务' }]
   },
   {
@@ -55,7 +63,8 @@ export const processDefinitionList = [
     formConf: {},
     formFields: [],
     startUserSelectTasks: [{ id: 'task3', name: '财务' }]
-  },{
+  },
+  {
     id: '5',
     key: 'process_1',
     name: '请假申请',