Procházet zdrojové kódy

Vue3 重构:流程模型的列表和新增、修改

YunaiV před 2 roky
rodič
revize
1854b85b40

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

@@ -25,7 +25,7 @@ export type ModelVO = {
   bpmnXml: string
 }
 
-export const getModelPageApi = async (params) => {
+export const getModelPage = async (params) => {
   return await request.get({ url: '/bpm/model/page', params })
 }
 
@@ -33,7 +33,7 @@ export const getModel = async (id: number) => {
   return await request.get({ url: '/bpm/model/get?id=' + id })
 }
 
-export const updateModelApi = async (data: ModelVO) => {
+export const updateModel = async (data: ModelVO) => {
   return await request.put({ url: '/bpm/model/update', data: data })
 }
 
@@ -46,7 +46,7 @@ export const updateModelStateApi = async (id: number, state: number) => {
   return await request.put({ url: '/bpm/model/update-state', data: data })
 }
 
-export const createModelApi = async (data: ModelVO) => {
+export const createModel = async (data: ModelVO) => {
   return await request.post({ url: '/bpm/model/create', data: data })
 }
 

+ 1 - 1
src/components/DictTag/src/DictTag.vue

@@ -34,7 +34,7 @@ export default defineComponent({
         return null
       }
       // 解决自定义字典标签值为零时标签不渲染的问题
-      if (props.value === undefined) {
+      if (props.value === undefined || props.value === null) {
         return null
       }
       getDictObj(props.type, props.value.toString())

+ 219 - 0
src/views/bpm/model/ModelForm.vue

@@ -0,0 +1,219 @@
+<template>
+  <Dialog :title="modelTitle" v-model="modelVisible" width="600">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      :rules="formRules"
+      label-width="110px"
+      v-loading="formLoading"
+    >
+      <el-form-item label="流程标识" prop="key">
+        <el-input
+          v-model="formData.key"
+          placeholder="请输入流标标识"
+          style="width: 330px"
+          :disabled="!!formData.id"
+        />
+        <el-tooltip
+          v-if="!formData.id"
+          class="item"
+          effect="light"
+          content="新建后,流程标识不可修改!"
+          placement="top"
+        >
+          <i style="padding-left: 5px" class="el-icon-question"></i>
+        </el-tooltip>
+        <el-tooltip v-else class="item" effect="light" content="流程标识不可修改!" placement="top">
+          <i style="padding-left: 5px" class="el-icon-question"></i>
+        </el-tooltip>
+      </el-form-item>
+      <el-form-item label="流程名称" prop="name">
+        <el-input
+          v-model="formData.name"
+          placeholder="请输入流程名称"
+          :disabled="!!formData.id"
+          clearable
+        />
+      </el-form-item>
+      <el-form-item v-if="formData.id" label="流程分类" prop="category">
+        <el-select
+          v-model="formData.category"
+          placeholder="请选择流程分类"
+          clearable
+          style="width: 100%"
+        >
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.BPM_MODEL_CATEGORY)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="流程描述" prop="description">
+        <el-input type="textarea" v-model="formData.description" clearable />
+      </el-form-item>
+      <div v-if="formData.id">
+        <el-form-item label="表单类型" prop="formType">
+          <el-radio-group v-model="formData.formType">
+            <el-radio
+              v-for="dict in getIntDictOptions(DICT_TYPE.BPM_MODEL_FORM_TYPE)"
+              :key="dict.value"
+              :label="dict.value"
+            >
+              {{ dict.label }}
+            </el-radio>
+          </el-radio-group>
+        </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-select>
+        </el-form-item>
+        <el-form-item
+          v-if="formData.formType === 20"
+          label="表单提交路由"
+          prop="formCustomCreatePath"
+        >
+          <el-input
+            v-model="formData.formCustomCreatePath"
+            placeholder="请输入表单提交路由"
+            style="width: 330px"
+          />
+          <el-tooltip
+            class="item"
+            effect="light"
+            content="自定义表单的提交路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/create"
+            placement="top"
+          >
+            <i style="padding-left: 5px" class="el-icon-question"></i>
+          </el-tooltip>
+        </el-form-item>
+        <el-form-item
+          v-if="formData.formType === 20"
+          label="表单查看路由"
+          prop="formCustomViewPath"
+        >
+          <el-input
+            v-model="formData.formCustomViewPath"
+            placeholder="请输入表单查看路由"
+            style="width: 330px"
+          />
+          <el-tooltip
+            class="item"
+            effect="light"
+            content="自定义表单的查看路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/view"
+            placement="top"
+          >
+            <i style="padding-left: 5px" class="el-icon-question"></i>
+          </el-tooltip>
+        </el-form-item>
+      </div>
+    </el-form>
+    <template #footer>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="modelVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script setup lang="ts">
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { ElMessageBox } from 'element-plus'
+import * as ModelApi from '@/api/bpm/model'
+
+const { t } = useI18n() // 国际化
+const message = useMessage() // 消息弹窗
+
+const modelVisible = ref(false) // 弹窗的是否展示
+const modelTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  formType: 10,
+  name: '',
+  category: undefined,
+  description: '',
+  formId: '',
+  formCustomCreatePath: '',
+  formCustomViewPath: ''
+})
+const formRules = reactive({
+  category: [{ required: true, message: '参数分类不能为空', trigger: 'blur' }],
+  name: [{ required: true, message: '参数名称不能为空', trigger: 'blur' }],
+  key: [{ required: true, message: '参数键名不能为空', trigger: 'blur' }],
+  value: [{ required: true, message: '参数键值不能为空', trigger: 'blur' }],
+  visible: [{ required: true, message: '是否可见不能为空', trigger: 'blur' }]
+})
+const formRef = ref() // 表单 Ref
+
+/** 打开弹窗 */
+const open = async (type: string, id?: number) => {
+  modelVisible.value = true
+  modelTitle.value = t('action.' + type)
+  formType.value = type
+  resetForm()
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await ModelApi.getModel(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
+const submitForm = async () => {
+  // 校验表单
+  if (!formRef) return
+  const valid = await formRef.value.validate()
+  if (!valid) return
+  // 提交请求
+  formLoading.value = true
+  try {
+    const data = formData.value as unknown as ModelApi.ModelVO
+    if (formType.value === 'create') {
+      await ModelApi.createModel(data)
+      // 提示,引导用户做后续的操作
+      await ElMessageBox.alert(
+        '<strong>新建模型成功!</strong>后续需要执行如下 4 个步骤:' +
+          '<div>1. 点击【修改流程】按钮,配置流程的分类、表单信息</div>' +
+          '<div>2. 点击【设计流程】按钮,绘制流程图</div>' +
+          '<div>3. 点击【分配规则】按钮,设置每个用户任务的审批人</div>' +
+          '<div>4. 点击【发布流程】按钮,完成流程的最终发布</div>' +
+          '另外,每次流程修改后,都需要点击【发布流程】按钮,才能正式生效!!!',
+        '重要提示',
+        {
+          dangerouslyUseHTMLString: true,
+          type: 'success'
+        }
+      )
+    } else {
+      await ModelApi.updateModel(data)
+      message.success(t('common.updateSuccess'))
+    }
+    modelVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+/** 重置表单 */
+const resetForm = () => {
+  formData.value = {
+    formType: 10,
+    name: '',
+    category: undefined,
+    description: '',
+    formId: '',
+    formCustomCreatePath: '',
+    formCustomViewPath: ''
+  }
+  formRef.value?.resetFields()
+}
+</script>

+ 2 - 2
src/views/bpm/model/editor/index.vue

@@ -62,10 +62,10 @@ const save = async (bpmnXml) => {
   } as unknown as ModelApi.ModelVO
   // 提交
   if (data.id) {
-    await ModelApi.updateModelApi(data)
+    await ModelApi.updateModel(data)
     message.success('修改成功')
   } else {
-    await ModelApi.createModelApi(data)
+    await ModelApi.createModel(data)
     message.success('新增成功')
   }
   // 跳转回去

+ 218 - 564
src/views/bpm/model/index.vue

@@ -1,595 +1,249 @@
 <template>
   <ContentWrap>
-    <!-- 列表 -->
-    <XTable @register="registerTable">
-      <template #toolbar_buttons>
-        <!-- 操作:新增 -->
-        <XButton
-          type="primary"
-          preIcon="ep:zoom-in"
-          title="新建流程"
-          v-hasPermi="['bpm:model:create']"
-          @click="handleCreate"
-        />
-        <!-- 操作:导入 -->
-        <XButton
-          type="warning"
-          preIcon="ep:upload"
-          :title="'导入流程'"
-          @click="handleImport"
-          style="margin-left: 10px"
-        />
-      </template>
-      <!-- 流程名称 -->
-      <template #name_default="{ row }">
-        <XTextButton :title="row.name" @click="handleBpmnDetail(row.id)" />
-      </template>
-      <!-- 流程分类 -->
-      <template #category_default="{ row }">
-        <DictTag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="Number(row?.category)" />
-      </template>
-      <!-- 表单信息 -->
-      <template #formId_default="{ row }">
-        <XTextButton
-          v-if="row.formType === 10"
-          :title="forms.find((form) => form.id === row.formId)?.name || row.formId"
-          @click="handleFormDetail(row)"
-        />
-        <XTextButton v-else :title="row.formCustomCreatePath" @click="handleFormDetail(row)" />
-      </template>
-      <!-- 流程版本 -->
-      <template #version_default="{ row }">
-        <el-tag v-if="row.processDefinition">v{{ row.processDefinition.version }}</el-tag>
-        <el-tag type="warning" v-else>未部署</el-tag>
-      </template>
-      <!-- 激活状态 -->
-      <template #status_default="{ row }">
-        <el-switch
-          v-if="row.processDefinition"
-          v-model="row.processDefinition.suspensionState"
-          :active-value="1"
-          :inactive-value="2"
-          @change="handleChangeState(row)"
-        />
-      </template>
-      <!-- 操作 -->
-      <template #actionbtns_default="{ row }">
-        <XTextButton
-          preIcon="ep:edit"
-          title="修改流程"
-          v-hasPermi="['bpm:model:update']"
-          @click="handleUpdate(row.id)"
-        />
-        <XTextButton
-          preIcon="ep:setting"
-          title="设计流程"
-          v-hasPermi="['bpm:model:update']"
-          @click="handleDesign(row)"
-        />
-        <XTextButton
-          preIcon="ep:user"
-          title="分配规则"
-          v-hasPermi="['bpm:task-assign-rule:query']"
-          @click="handleAssignRule(row)"
-        />
-        <XTextButton
-          preIcon="ep:position"
-          title="发布流程"
-          v-hasPermi="['bpm:model:deploy']"
-          @click="handleDeploy(row)"
-        />
-        <XTextButton
-          preIcon="ep:aim"
-          title="流程定义"
-          v-hasPermi="['bpm:process-definition:query']"
-          @click="handleDefinitionList(row)"
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="流程标识" prop="key">
+        <el-input
+          v-model="queryParams.key"
+          placeholder="请输入流程标识"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
         />
-        <!-- 操作:删除 -->
-        <XTextButton
-          preIcon="ep:delete"
-          :title="t('action.del')"
-          v-hasPermi="['bpm:model:delete']"
-          @click="handleDelete(row.id)"
+      </el-form-item>
+      <el-form-item label="流程名称" prop="name">
+        <el-input
+          v-model="queryParams.name"
+          placeholder="请输入流程名称"
+          clearable
+          @keyup.enter="handleQuery"
+          class="!w-240px"
         />
-      </template>
-    </XTable>
-
-    <!-- 对话框(添加 / 修改流程) -->
-    <XModal v-model="dialogVisible" :title="dialogTitle" width="600">
-      <el-form
-        :loading="dialogLoading"
-        el-form
-        ref="saveFormRef"
-        :model="saveForm"
-        :rules="rules"
-        label-width="110px"
-      >
-        <el-form-item label="流程标识" prop="key">
-          <el-input
-            v-model="saveForm.key"
-            placeholder="请输入流标标识"
-            style="width: 330px"
-            :disabled="!!saveForm.id"
-          />
-          <el-tooltip
-            v-if="!saveForm.id"
-            class="item"
-            effect="light"
-            content="新建后,流程标识不可修改!"
-            placement="top"
-          >
-            <i style="padding-left: 5px" class="el-icon-question"></i>
-          </el-tooltip>
-          <el-tooltip
-            v-else
-            class="item"
-            effect="light"
-            content="流程标识不可修改!"
-            placement="top"
-          >
-            <i style="padding-left: 5px" class="el-icon-question"></i>
-          </el-tooltip>
-        </el-form-item>
-        <el-form-item label="流程名称" prop="name">
-          <el-input
-            v-model="saveForm.name"
-            placeholder="请输入流程名称"
-            :disabled="!!saveForm.id"
-            clearable
+      </el-form-item>
+      <el-form-item label="流程分类" prop="category">
+        <el-select
+          v-model="queryParams.category"
+          placeholder="请选择流程分类"
+          clearable
+          class="!w-240px"
+        >
+          <el-option
+            v-for="dict in getIntDictOptions(DICT_TYPE.BPM_MODEL_CATEGORY)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
           />
-        </el-form-item>
-        <el-form-item v-if="saveForm.id" label="流程分类" prop="category">
-          <el-select
-            v-model="saveForm.category"
-            placeholder="请选择流程分类"
-            clearable
-            style="width: 100%"
-          >
-            <el-option
-              v-for="dict in getDictOptions(DICT_TYPE.BPM_MODEL_CATEGORY)"
-              :key="dict.value"
-              :label="dict.label"
-              :value="dict.value"
-            />
-          </el-select>
-        </el-form-item>
-        <el-form-item label="流程描述" prop="description">
-          <el-input type="textarea" v-model="saveForm.description" clearable />
-        </el-form-item>
-        <div v-if="saveForm.id">
-          <el-form-item label="表单类型" prop="formType">
-            <el-radio-group v-model="saveForm.formType">
-              <el-radio
-                v-for="dict in getDictOptions(DICT_TYPE.BPM_MODEL_FORM_TYPE)"
-                :key="parseInt(dict.value)"
-                :label="parseInt(dict.value)"
-              >
-                {{ dict.label }}
-              </el-radio>
-            </el-radio-group>
-          </el-form-item>
-          <el-form-item v-if="saveForm.formType === 10" label="流程表单" prop="formId">
-            <el-select v-model="saveForm.formId" clearable style="width: 100%">
-              <el-option v-for="form in forms" :key="form.id" :label="form.name" :value="form.id" />
-            </el-select>
-          </el-form-item>
-          <el-form-item
-            v-if="saveForm.formType === 20"
-            label="表单提交路由"
-            prop="formCustomCreatePath"
-          >
-            <el-input
-              v-model="saveForm.formCustomCreatePath"
-              placeholder="请输入表单提交路由"
-              style="width: 330px"
-            />
-            <el-tooltip
-              class="item"
-              effect="light"
-              content="自定义表单的提交路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/create"
-              placement="top"
-            >
-              <i style="padding-left: 5px" class="el-icon-question"></i>
-            </el-tooltip>
-          </el-form-item>
-          <el-form-item
-            v-if="saveForm.formType === 20"
-            label="表单查看路由"
-            prop="formCustomViewPath"
-          >
-            <el-input
-              v-model="saveForm.formCustomViewPath"
-              placeholder="请输入表单查看路由"
-              style="width: 330px"
-            />
-            <el-tooltip
-              class="item"
-              effect="light"
-              content="自定义表单的查看路径,使用 Vue 的路由地址,例如说:bpm/oa/leave/view"
-              placement="top"
-            >
-              <i style="padding-left: 5px" class="el-icon-question"></i>
-            </el-tooltip>
-          </el-form-item>
-        </div>
-      </el-form>
-      <template #footer>
-        <!-- 按钮:保存 -->
-        <XButton
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
           type="primary"
-          :loading="dialogLoading"
-          @click="submitForm"
-          :title="t('action.save')"
-        />
-        <!-- 按钮:关闭 -->
-        <XButton
-          :loading="dialogLoading"
-          @click="dialogVisible = false"
-          :title="t('dialog.close')"
-        />
-      </template>
-    </XModal>
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['bpm:model:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新建流程
+        </el-button>
+        <el-button type="success" plain @click="handleImport()" v-hasPermi="['bpm:model:import']">
+          <Icon icon="ep:upload" class="mr-5px" /> 导入流程
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
 
-    <!-- 导入流程 -->
-    <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"
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list">
+      <el-table-column label="流程标识" align="center" prop="key" />
+      <el-table-column label="流程名称" align="center" prop="name" width="200">
+        <template #default="scope">
+          <el-button type="text" @click="handleBpmnDetail(scope.row)">
+            <span>{{ scope.row.name }}</span>
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="流程分类" align="center" prop="category" width="100">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="scope.row.category" />
+        </template>
+      </el-table-column>
+      <el-table-column label="表单信息" align="center" prop="formType" width="200">
+        <template #default="scope">
+          <el-button v-if="scope.row.formId" type="text" @click="handleFormDetail(scope.row)">
+            <span>{{ scope.row.formName }}</span>
+          </el-button>
+          <el-button
+            v-else-if="scope.row.formCustomCreatePath"
+            type="text"
+            @click="handleFormDetail(scope.row)"
+          >
+            <span>{{ scope.row.formCustomCreatePath }}</span>
+          </el-button>
+          <label v-else>暂无表单</label>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+      />
+      <el-table-column label="最新部署的流程定义" align="center">
+        <el-table-column
+          label="流程版本"
+          align="center"
+          prop="processDefinition.version"
+          width="100"
         >
-          <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 #default="scope">
+            <el-tag v-if="scope.row.processDefinition">
+              v{{ scope.row.processDefinition.version }}
+            </el-tag>
+            <el-tag v-else type="warning">未部署</el-tag>
           </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>
+        </el-table-column>
+        <el-table-column
+          label="激活状态"
+          align="center"
+          prop="processDefinition.version"
+          width="80"
+        >
+          <template #default="scope">
+            <el-switch
+              v-if="scope.row.processDefinition"
+              v-model="scope.row.processDefinition.suspensionState"
+              :active-value="1"
+              :inactive-value="2"
+              @change="handleChangeState(scope.row)"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column label="部署时间" align="center" prop="deploymentTime" width="180">
+          <template #default="scope">
+            <span v-if="scope.row.processDefinition">
+              {{ formatDate(scope.row.processDefinition.deploymentTime) }}
+            </span>
+          </template>
+        </el-table-column>
+      </el-table-column>
+      <el-table-column label="操作" align="center" fixed="right" class-name="fixed-width">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['bpm:model:update']"
+          >
+            修改流程
+          </el-button>
+          <!-- TODO tailow 了-->
+          <el-button link @click="openDetail(scope.row.id)" v-hasPermi="['bpm:form:query']">
+            详情
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['bpm:form:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
 
-    <!-- 表单详情的弹窗 -->
-    <XModal v-model="formDetailVisible" width="800" title="表单详情" :show-footer="false">
-      <form-create
-        :rule="formDetailPreview.rule"
-        :option="formDetailPreview.option"
-        v-if="formDetailVisible"
-      />
-    </XModal>
+  <!-- 表单弹窗:添加/修改 -->
+  <ModelForm ref="formRef" @success="getList" />
 
-    <!-- 流程模型图的预览 -->
-    <XModal title="流程图" v-model="showBpmnOpen" width="80%" height="90%">
-      <my-process-viewer
-        key="designer"
-        v-model="bpmnXML"
-        :value="bpmnXML"
-        v-bind="bpmnControlForm"
-        :prefix="bpmnControlForm.prefix"
-      />
-    </XModal>
-  </ContentWrap>
+  <!-- 表单详情的弹窗 -->
+  <Dialog title="表单详情" v-model="detailVisible" width="800">
+    <form-create :rule="detailData.rule" :option="detailData.option" />
+  </Dialog>
 </template>
 
-<script setup lang="ts">
-// 全局相关的 import
-import { DICT_TYPE, getDictOptions } from '@/utils/dict'
-import { FormInstance, UploadInstance } from 'element-plus'
-
-// 业务相关的 import
-import { getAccessToken, getTenantId } from '@/utils/auth'
-import * as FormApi from '@/api/bpm/form'
+<script setup lang="ts" name="Form">
+import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
+import { dateFormatter, formatDate } from '@/utils/formatTime'
 import * as ModelApi from '@/api/bpm/model'
-import { allSchemas, rules } from './model.data'
-import { setConfAndFields2 } from '@/utils/formCreate'
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-const router = useRouter() // 路由
-
-const showBpmnOpen = ref(false)
-const bpmnXML = ref(null)
-const bpmnControlForm = ref({
-  prefix: 'flowable'
-})
-// ========== 列表相关 ==========
-const [registerTable, { reload }] = useXTable({
-  allSchemas: allSchemas,
-  getListApi: ModelApi.getModelPageApi
-})
-const forms = ref() // 流程表单的下拉框的数据
-
-// 设计流程
-const handleDesign = (row) => {
-  console.log(row, '设计流程')
-  router.push({
-    name: 'modelEditor',
-    query: {
-      modelId: row.id
-    }
-  })
-}
-
-// 跳转到指定流程定义列表
-const handleDefinitionList = (row) => {
-  router.push({
-    name: 'BpmProcessDefinitionList',
-    query: {
-      key: row.key
-    }
-  })
-}
-
-// 流程表单的详情按钮操作
-const formDetailVisible = ref(false)
-const formDetailPreview = ref({
-  rule: [],
-  option: {}
+import ModelForm from './ModelForm.vue'
+// import { setConfAndFields2 } from '@/utils/formCreate'
+// const message = useMessage() // 消息弹窗
+// const { t } = useI18n() // 国际化
+// const { push } = useRouter() // 路由
+
+const loading = ref(true) // 列表的加载中
+const total = ref(0) // 列表的总页数
+const list = ref([]) // 列表的数据
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  key: undefined,
+  name: undefined,
+  category: undefined
 })
-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 router.push({
-      path: row.formCustomCreatePath
-    })
-  }
-}
-
-// 流程图的详情按钮操作
-const handleBpmnDetail = (row) => {
-  // TODO 芋艿:流程组件开发中
-  console.log(row)
-  ModelApi.getModel(row).then((response) => {
-    console.log(response, 'response')
-    bpmnXML.value = response.bpmnXml
-    // 弹窗打开
-    showBpmnOpen.value = true
-  })
-  // message.success('流程组件开发中,预计 2 月底完成')
-}
-
-// 点击任务分配按钮
-const handleAssignRule = (row) => {
-  router.push({
-    name: 'BpmTaskAssignRuleList',
-    query: {
-      modelId: row.id
-    }
-  })
-}
-
-// ========== 新建/修改流程 ==========
-const dialogVisible = ref(false)
-const dialogTitle = ref('新建模型')
-const dialogLoading = ref(false)
-const saveForm = ref()
-const saveFormRef = ref<FormInstance>()
-
-// 设置标题
-const setDialogTile = async (type: string) => {
-  dialogTitle.value = t('action.' + type)
-  dialogVisible.value = true
-}
-
-// 新增操作
-const handleCreate = async () => {
-  resetForm()
-  await setDialogTile('create')
-}
-
-// 修改操作
-const handleUpdate = async (rowId: number) => {
-  resetForm()
-  await setDialogTile('edit')
-  // 设置数据
-  saveForm.value = await ModelApi.getModel(rowId)
-  if (saveForm.value.category == null) {
-    saveForm.value.category = 1
-  } else {
-    saveForm.value.category = Number(saveForm.value.category)
-  }
-}
-
-// 提交按钮
-const submitForm = async () => {
-  // 参数校验
-  const elForm = unref(saveFormRef)
-  if (!elForm) return
-  const valid = await elForm.validate()
-  if (!valid) return
+const queryFormRef = ref() // 搜索的表单
 
-  // 提交请求
-  dialogLoading.value = true
+/** 查询参数列表 */
+const getList = async () => {
+  loading.value = true
   try {
-    const data = saveForm.value as ModelApi.ModelVO
-    if (!data.id) {
-      await ModelApi.createModelApi(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await ModelApi.updateModelApi(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
+    const data = await ModelApi.getModelPage(queryParams)
+    list.value = data.list
+    total.value = data.total
   } finally {
-    // 刷新列表
-    await reload()
-    dialogLoading.value = false
+    loading.value = false
   }
 }
 
-// 重置表单
-const resetForm = () => {
-  saveForm.value = {
-    formType: 10,
-    name: '',
-    courseSort: '',
-    description: '',
-    formId: '',
-    formCustomCreatePath: '',
-    formCustomViewPath: ''
-  }
-  saveFormRef.value?.resetFields()
-}
-
-// ========== 删除 / 更新状态 / 发布流程 ==========
-// 删除流程
-const handleDelete = (rowId) => {
-  message.delConfirm('是否删除该流程!!').then(async () => {
-    await ModelApi.deleteModelApi(rowId)
-    message.success(t('common.delSuccess'))
-    // 刷新列表
-    reload()
-  })
-}
-
-// 更新状态操作
-const handleChangeState = (row) => {
-  const id = row.id
-  const state = row.processDefinition.suspensionState
-  const statusState = state === 1 ? '激活' : '挂起'
-  const content = '是否确认' + statusState + '流程名字为"' + row.name + '"的数据项?'
-  message
-    .confirm(content)
-    .then(async () => {
-      await ModelApi.updateModelStateApi(id, state)
-      message.success(t('部署成功'))
-      // 刷新列表
-      reload()
-    })
-    .catch(() => {
-      // 取消后,进行恢复按钮
-      row.processDefinition.suspensionState = state === 1 ? 2 : 1
-    })
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
 }
 
-// 发布流程
-const handleDeploy = (row) => {
-  message.confirm('是否部署该流程!!').then(async () => {
-    await ModelApi.deployModelApi(row.id)
-    message.success(t('部署成功'))
-    // 刷新列表
-    reload()
-  })
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
 }
 
-// ========== 导入流程 ==========
-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 formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
 }
 
-// 提交文件上传
-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()
-}
+/** 删除按钮操作 */
+// const handleDelete = async (id: number) => {
+//   try {
+//     // 删除的二次确认
+//     await message.delConfirm()
+//     // 发起删除
+//     await FormApi.deleteForm(id)
+//     message.success(t('common.delSuccess'))
+//     // 刷新列表
+//     await getList()
+//   } catch {}
+// }
 
-// ========== 初始化 ==========
+/** 初始化 **/
 onMounted(() => {
-  // 获得流程表单的下拉框的数据
-  FormApi.getSimpleFormList().then((data) => {
-    forms.value = data
-  })
+  getList()
 })
 </script>

+ 0 - 106
src/views/bpm/model/model.data.ts

@@ -1,106 +0,0 @@
-import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
-
-const { t } = useI18n() // 国际化
-
-// 表单校验
-export const rules = reactive({
-  key: [required],
-  name: [required],
-  category: [required],
-  formType: [required],
-  formId: [required],
-  formCustomCreatePath: [required],
-  formCustomViewPath: [required]
-})
-
-// CrudSchema
-const crudSchemas = reactive<VxeCrudSchema>({
-  primaryKey: 'key',
-  primaryType: null,
-  action: true,
-  actionWidth: '540px',
-  columns: [
-    {
-      title: '流程标识',
-      field: 'key',
-      isSearch: true,
-      table: {
-        width: 120
-      }
-    },
-    {
-      title: '流程名称',
-      field: 'name',
-      isSearch: true,
-      table: {
-        width: 120,
-        slots: {
-          default: 'name_default'
-        }
-      }
-    },
-    {
-      title: '流程分类',
-      field: 'category',
-      dictType: DICT_TYPE.BPM_MODEL_CATEGORY,
-      dictClass: 'number',
-      isSearch: true,
-      table: {
-        slots: {
-          default: 'category_default'
-        }
-      }
-    },
-    {
-      title: '表单信息',
-      field: 'formId',
-      table: {
-        width: 180,
-        slots: {
-          default: 'formId_default'
-        }
-      }
-    },
-    {
-      title: '最新部署的流程定义',
-      field: 'processDefinition',
-      isForm: false,
-      table: {
-        children: [
-          {
-            title: '流程版本',
-            field: 'version',
-            slots: {
-              default: 'version_default'
-            },
-            width: 80
-          },
-          {
-            title: '激活状态',
-            field: 'status',
-            slots: {
-              default: 'status_default'
-            },
-            width: 80
-          },
-          {
-            title: '部署时间',
-            field: 'processDefinition.deploymentTime',
-            formatter: 'formatDate',
-            width: 180
-          }
-        ]
-      }
-    },
-    {
-      title: t('common.createTime'),
-      field: 'createTime',
-      isForm: false,
-      formatter: 'formatDate',
-      table: {
-        width: 180
-      }
-    }
-  ]
-})
-export const { allSchemas } = useVxeCrudSchemas(crudSchemas)