Переглянути джерело

Vue3 重构:流程模型的各种操作

YunaiV 2 роки тому
батько
коміт
e83d5914f0

+ 3 - 3
src/api/bpm/model/index.ts

@@ -38,7 +38,7 @@ export const updateModel = async (data: ModelVO) => {
 }
 
 // 任务状态修改
-export const updateModelStateApi = async (id: number, state: number) => {
+export const updateModelState = async (id: number, state: number) => {
   const data = {
     id: id,
     state: state
@@ -50,10 +50,10 @@ export const createModel = async (data: ModelVO) => {
   return await request.post({ url: '/bpm/model/create', data: data })
 }
 
-export const deleteModelApi = async (id: number) => {
+export const deleteModel = async (id: number) => {
   return await request.delete({ url: '/bpm/model/delete?id=' + id })
 }
 
-export const deployModelApi = async (id: number) => {
+export const deployModel = async (id: number) => {
   return await request.post({ url: '/bpm/model/deploy?id=' + id })
 }

+ 10 - 2
src/views/bpm/model/ModelForm.vue

@@ -67,7 +67,12 @@
         </el-form-item>
         <el-form-item v-if="formData.formType === 10" label="流程表单" prop="formId">
           <el-select v-model="formData.formId" clearable style="width: 100%">
-            <el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id" />
+            <el-option
+              v-for="form in formList"
+              :key="form.id"
+              :label="form.name"
+              :value="form.id"
+            />
           </el-select>
         </el-form-item>
         <el-form-item
@@ -120,7 +125,7 @@
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import { ElMessageBox } from 'element-plus'
 import * as ModelApi from '@/api/bpm/model'
-
+import * as FormApi from '@/api/bpm/form'
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
 
@@ -145,6 +150,7 @@ const formRules = reactive({
   visible: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }]
 })
 const formRef = ref() // 表单 Ref
+const formList = ref([]) // 流程表单的下拉框的数据
 
 /** 打开弹窗 */
 const open = async (type: string, id?: number) => {
@@ -161,6 +167,8 @@ const open = async (type: string, id?: number) => {
       formLoading.value = false
     }
   }
+  // 获得流程表单的下拉框的数据
+  formList.value = await FormApi.getSimpleFormList()
 }
 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 

+ 153 - 0
src/views/bpm/model/ModelImportForm.vue

@@ -0,0 +1,153 @@
+<template>
+  <ContentWrap>
+    <!-- 列表 -->
+    <XTable @register="registerTable">
+      <template #toolbar_buttons>
+        <!-- 操作:导入 -->
+        <XButton
+          type="warning"
+          preIcon="ep:upload"
+          :title="'导入流程'"
+          @click="handleImport"
+          style="margin-left: 10px"
+        />
+      </template>
+    </XTable>
+
+    <!-- 导入流程 -->
+    <XModal v-model="importDialogVisible" width="400" title="导入流程">
+      <div>
+        <el-upload
+          ref="uploadRef"
+          :action="importUrl"
+          :headers="uploadHeaders"
+          :drag="true"
+          :limit="1"
+          :multiple="true"
+          :show-file-list="true"
+          :disabled="uploadDisabled"
+          :on-exceed="handleExceed"
+          :on-success="handleFileSuccess"
+          :on-error="excelUploadError"
+          :auto-upload="false"
+          accept=".bpmn, .xml"
+          name="bpmnFile"
+          :data="importForm"
+        >
+          <Icon class="el-icon--upload" icon="ep:upload-filled" />
+          <div class="el-upload__text"> 将文件拖到此处,或 <em>点击上传</em> </div>
+          <template #tip>
+            <div class="el-upload__tip" style="color: red">
+              提示:仅允许导入“bpm”或“xml”格式文件!
+            </div>
+            <div>
+              <el-form
+                ref="importFormRef"
+                :model="importForm"
+                :rules="rules"
+                label-width="120px"
+                status-icon
+              >
+                <el-form-item label="流程标识" prop="key">
+                  <el-input
+                    v-model="importForm.key"
+                    placeholder="请输入流标标识"
+                    style="width: 250px"
+                  />
+                </el-form-item>
+                <el-form-item label="流程名称" prop="name">
+                  <el-input v-model="importForm.name" placeholder="请输入流程名称" clearable />
+                </el-form-item>
+                <el-form-item label="流程描述" prop="description">
+                  <el-input type="textarea" v-model="importForm.description" clearable />
+                </el-form-item>
+              </el-form>
+            </div>
+          </template>
+        </el-upload>
+      </div>
+      <template #footer>
+        <!-- 按钮:保存 -->
+        <XButton
+          type="warning"
+          preIcon="ep:upload-filled"
+          :title="t('action.save')"
+          @click="submitFileForm"
+        />
+        <XButton title="取 消" @click="uploadClose" />
+      </template>
+    </XModal>
+
+  </ContentWrap>
+</template>
+
+<script setup lang="ts">
+import { getAccessToken, getTenantId } from '@/utils/auth'
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+const router = useRouter() // 路由
+
+// ========== 导入流程 ==========
+const uploadRef = ref<UploadInstance>()
+let importUrl = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/bpm/model/import'
+const uploadHeaders = ref()
+const importDialogVisible = ref(false)
+const uploadDisabled = ref(false)
+const importFormRef = ref<FormInstance>()
+const importForm = ref({
+  key: '',
+  name: '',
+  description: ''
+})
+
+// 导入流程弹窗显示
+const handleImport = () => {
+  importDialogVisible.value = true
+}
+// 文件数超出提示
+const handleExceed = (): void => {
+  message.error('最多只能上传一个文件!')
+}
+// 上传错误提示
+const excelUploadError = (): void => {
+  message.error('导入流程失败,请您重新上传!')
+}
+
+// 提交文件上传
+const submitFileForm = () => {
+  uploadHeaders.value = {
+    Authorization: 'Bearer ' + getAccessToken(),
+    'tenant-id': getTenantId()
+  }
+  uploadDisabled.value = true
+  uploadRef.value!.submit()
+}
+// 文件上传成功
+const handleFileSuccess = async (response: any): Promise<void> => {
+  if (response.code !== 0) {
+    message.error(response.msg)
+    return
+  }
+  // 重置表单
+  uploadClose()
+  // 提示,并刷新
+  message.success('导入流程成功!请点击【设计流程】按钮,进行编辑保存后,才可以进行【发布流程】')
+  await reload()
+}
+// 关闭文件上传
+const uploadClose = () => {
+  // 关闭弹窗
+  importDialogVisible.value = false
+  // 重置上传状态和文件
+  uploadDisabled.value = false
+  uploadRef.value!.clearFiles()
+  // 重置表单
+  importForm.value = {
+    key: '',
+    name: '',
+    description: ''
+  }
+  importFormRef.value?.resetFields()
+}
+</script>

+ 156 - 22
src/views/bpm/model/index.vue

@@ -144,15 +144,43 @@
           >
             修改流程
           </el-button>
-          <!-- TODO tailow 了-->
-          <el-button link @click="openDetail(scope.row.id)" v-hasPermi="['bpm:form:query']">
-            详情
+          <el-button
+            link
+            type="primary"
+            @click="handleDesign(scope.row)"
+            v-hasPermi="['bpm:model:update']"
+          >
+            设计流程
+          </el-button>
+          <el-button
+            link
+            type="primary"
+            @click="handleAssignRule(scope.row)"
+            v-hasPermi="['bpm:task-assign-rule:query']"
+          >
+            分配规则
+          </el-button>
+          <el-button
+            link
+            type="primary"
+            @click="handleDeploy(scope.row)"
+            v-hasPermi="['bpm:model:deploy']"
+          >
+            发布流程
+          </el-button>
+          <el-button
+            link
+            type="primary"
+            v-hasPermi="['bpm:process-definition:query']"
+            @click="handleDefinitionList(scope.row)"
+          >
+            流程定义
           </el-button>
           <el-button
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
-            v-hasPermi="['bpm:form:delete']"
+            v-hasPermi="['bpm:model:delete']"
           >
             删除
           </el-button>
@@ -171,9 +199,20 @@
   <!-- 表单弹窗:添加/修改 -->
   <ModelForm ref="formRef" @success="getList" />
 
-  <!-- 表单详情的弹窗 -->
-  <Dialog title="表单详情" v-model="detailVisible" width="800">
-    <form-create :rule="detailData.rule" :option="detailData.option" />
+  <!-- 弹窗:表单详情 -->
+  <Dialog title="表单详情" v-model="formDetailVisible" width="800">
+    <form-create :rule="formDetailPreview.rule" :option="formDetailPreview.option" />
+  </Dialog>
+
+  <!-- 弹窗:流程模型图的预览 -->
+  <Dialog title="流程图" v-model="bpmnDetailVisible" width="800">
+    <my-process-viewer
+      key="designer"
+      v-model="bpmnXML"
+      :value="bpmnXML"
+      v-bind="bpmnControlForm"
+      :prefix="bpmnControlForm.prefix"
+    />
   </Dialog>
 </template>
 
@@ -181,11 +220,12 @@
 import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 import { dateFormatter, formatDate } from '@/utils/formatTime'
 import * as ModelApi from '@/api/bpm/model'
+import * as FormApi from '@/api/bpm/form'
 import ModelForm from './ModelForm.vue'
-// import { setConfAndFields2 } from '@/utils/formCreate'
-// const message = useMessage() // 消息弹窗
-// const { t } = useI18n() // 国际化
-// const { push } = useRouter() // 路由
+import { setConfAndFields2 } from '@/utils/formCreate'
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+const { push } = useRouter() // 路由
 
 const loading = ref(true) // 列表的加载中
 const total = ref(0) // 列表的总页数
@@ -230,17 +270,111 @@ const openForm = (type: string, id?: number) => {
 }
 
 /** 删除按钮操作 */
-// const handleDelete = async (id: number) => {
-//   try {
-//     // 删除的二次确认
-//     await message.delConfirm()
-//     // 发起删除
-//     await FormApi.deleteForm(id)
-//     message.success(t('common.delSuccess'))
-//     // 刷新列表
-//     await getList()
-//   } catch {}
-// }
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await ModelApi.deleteModel(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 更新状态操作 */
+const handleChangeState = async (row) => {
+  const state = row.processDefinition.suspensionState
+  try {
+    // 修改状态的二次确认
+    const id = row.id
+    const statusState = state === 1 ? '激活' : '挂起'
+    const content = '是否确认' + statusState + '流程名字为"' + row.name + '"的数据项?'
+    await message.confirm(content)
+    // 发起修改状态
+    await ModelApi.updateModelState(id, state)
+    // 刷新列表
+    await getList()
+  } catch {
+    // 取消后,进行恢复按钮
+    row.processDefinition.suspensionState = state === 1 ? 2 : 1
+  }
+}
+
+/** 设计流程 */
+const handleDesign = (row) => {
+  push({
+    name: 'modelEditor',
+    query: {
+      modelId: row.id
+    }
+  })
+}
+
+/** 发布流程 */
+const handleDeploy = async (row) => {
+  try {
+    // 删除的二次确认
+    await message.confirm('是否部署该流程!!')
+    // 发起部署
+    await ModelApi.deployModel(row.id)
+    message.success(t('部署成功'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 点击任务分配按钮 */
+const handleAssignRule = (row) => {
+  push({
+    name: 'BpmTaskAssignRuleList',
+    query: {
+      modelId: row.id
+    }
+  })
+}
+
+/** 跳转到指定流程定义列表 */
+const handleDefinitionList = (row) => {
+  push({
+    name: 'BpmProcessDefinitionList',
+    query: {
+      key: row.key
+    }
+  })
+}
+
+/** 流程表单的详情按钮操作 */
+const formDetailVisible = ref(false)
+const formDetailPreview = ref({
+  rule: [],
+  option: {}
+})
+const handleFormDetail = async (row) => {
+  if (row.formType == 10) {
+    // 设置表单
+    const data = await FormApi.getForm(row.formId)
+    setConfAndFields2(formDetailPreview, data.conf, data.fields)
+    // 弹窗打开
+    formDetailVisible.value = true
+  } else {
+    await push({
+      path: row.formCustomCreatePath
+    })
+  }
+}
+
+/** 流程图的详情按钮操作 */
+const bpmnDetailVisible = ref(false)
+const bpmnXML = ref(null)
+const bpmnControlForm = ref({
+  prefix: 'flowable'
+})
+const handleBpmnDetail = async (row) => {
+  const data = await ModelApi.getModel(row.id)
+  bpmnXML.value = data.bpmnXml || ''
+  bpmnDetailVisible.value = true
+}
 
 /** 初始化 **/
 onMounted(() => {