Przeglądaj źródła

bpm:初始化流程实例的代码

YunaiV 2 lat temu
rodzic
commit
e6fadf073a

+ 133 - 0
yudao-ui-admin-vue3/src/views/bpm/processInstance/create.vue

@@ -0,0 +1,133 @@
+<template>
+  <div class="app-container">
+    <!-- 第一步,通过流程定义的列表,选择对应的流程 -->
+    <div v-if="!selectProcessInstance">
+      <XTable @register="registerTable">
+        <template #version_default="{ row }">
+          <el-tag v-if="row">v{{ row.version }}</el-tag>
+        </template>
+        <template #actionbtns_default="{ row }">
+          <el-button type="text" size="small" icon="el-icon-plus" @click="handleSelect(row)"
+            >选择</el-button
+          >
+        </template>
+      </XTable>
+    </div>
+    <!-- 第二步,填写表单,进行流程的提交 -->
+    <div v-else>
+      <el-card class="box-card">
+        <div class="clearfix">
+          <span class="el-icon-document">申请信息【{{ selectProcessInstance.name }}】</span>
+          <el-button style="float: right" type="primary" @click="selectProcessInstance = undefined"
+            >选择其它流程</el-button
+          >
+        </div>
+        <el-col :span="16" :offset="6">
+          <div>
+            <!-- <parser :key="new Date().getTime()" :form-conf="detailForm" @submit="submitForm" /> -->
+          </div>
+        </el-col>
+      </el-card>
+      <el-card class="box-card">
+        <div class="clearfix">
+          <span class="el-icon-picture-outline">流程图</span>
+        </div>
+        <!-- <my-process-viewer key="designer" v-model="bpmnXML" v-bind="bpmnControlForm" /> -->
+      </el-card>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { reactive, ref } from 'vue'
+import { useXTable } from '@/hooks/web/useXTable'
+import * as definitionApi from '@/api/bpm/definition'
+// import {DICT_TYPE, getDictDatas} from "@/utils/dict";
+import { decodeFields } from '@/utils/formGenerator'
+// import Parser from '@/components/parser/Parser'
+// import * as processInstanceApi from "@/api/bpm/processInstance";
+import { allSchemas } from './process.create'
+import { useRouter } from 'vue-router'
+const router = useRouter()
+
+const queryParams = reactive({
+  suspensionState: 1
+})
+const [registerTable] = useXTable({
+  allSchemas: allSchemas,
+  params: queryParams,
+  getListApi: definitionApi.getProcessDefinitionListApi
+})
+
+// 流程表单详情
+const detailForm = ref({
+  fields: []
+})
+
+// // BPMN 数据
+const bpmnXML = ref(null)
+// const bpmnControlForm=ref( {
+//   prefix: "flowable"
+// })
+
+// 流程表单
+const selectProcessInstance = ref(undefined) // 选择的流程实例
+/** 处理选择流程的按钮操作 **/
+const handleSelect = (row) => {
+  // 设置选择的流程
+  selectProcessInstance.value = row
+
+  // 流程表单
+  if (row.formId) {
+    // 设置对应的表单
+    detailForm.value = {
+      ...JSON.parse(row.formConf),
+      fields: decodeFields([], row.formFields)
+    }
+
+    // 加载流程图
+    definitionApi.getProcessDefinitionBpmnXMLApi(row.id).then((response) => {
+      bpmnXML.value = response.data
+    })
+  } else if (row.formCustomCreatePath) {
+    router.push({ path: row.formCustomCreatePath })
+    // 这里暂时无需加载流程图,因为跳出到另外个 Tab;
+  }
+}
+/** 提交按钮 */
+//  const submitForm=(params)=> {
+//     if (!params) {
+//       return;
+//     }
+//     // 设置表单禁用
+//     const conf = params.conf;
+//     conf.disabled = true; // 表单禁用
+//     conf.formBtns = false; // 按钮隐藏
+
+//     // 提交表单,创建流程
+//     const variables = params.values;
+//   await  processInstanceApi.createProcessInstanceApi({
+//       processDefinitionId: this.selectProcessInstance.id,
+//       variables: variables
+//     }).then(response => {
+//       this.$modal.msgSuccess("发起流程成功");
+//       // 关闭当前窗口
+//       this.$tab.closeOpenPage();
+//       this.$router.go(-1);
+//     }).catch(() => {
+//       conf.disabled = false; // 表单开启
+//       conf.formBtns = true; // 按钮展示
+//     })
+//   }
+</script>
+
+<style lang="scss">
+.my-process-designer {
+  height: calc(100vh - 200px);
+}
+
+.box-card {
+  width: 100%;
+  margin-bottom: 20px;
+}
+</style>

+ 506 - 0
yudao-ui-admin-vue3/src/views/bpm/processInstance/detail.vue

@@ -0,0 +1,506 @@
+<template>
+  <div class="app-container">
+    <!-- 审批信息 -->
+    <el-card
+      class="box-card"
+      v-loading="processInstanceLoading"
+      v-for="(item, index) in runningTasks"
+      :key="index"
+    >
+      <div slot="header" class="clearfix">
+        <span class="el-icon-picture-outline">审批任务【{{ item.name }}】</span>
+      </div>
+      <el-col :span="16" :offset="6">
+        <el-form
+          :ref="'form' + index"
+          :model="auditForms[index]"
+          :rules="auditRule"
+          label-width="100px"
+        >
+          <el-form-item label="流程名" v-if="processInstance && processInstance.name">
+            {{ processInstance.name }}
+          </el-form-item>
+          <el-form-item label="流程发起人" v-if="processInstance && processInstance.startUser">
+            {{ processInstance.startUser.nickname }}
+            <el-tag type="info" size="mini">{{ processInstance.startUser.deptName }}</el-tag>
+          </el-form-item>
+          <el-form-item label="审批建议" prop="reason">
+            <el-input
+              type="textarea"
+              v-model="auditForms[index].reason"
+              placeholder="请输入审批建议"
+            />
+          </el-form-item>
+        </el-form>
+        <div style="margin-left: 10%; margin-bottom: 20px; font-size: 14px">
+          <el-button
+            icon="el-icon-edit-outline"
+            type="success"
+            size="mini"
+            @click="handleAudit(item, true)"
+            >通过</el-button
+          >
+          <el-button
+            icon="el-icon-circle-close"
+            type="danger"
+            size="mini"
+            @click="handleAudit(item, false)"
+            >不通过</el-button
+          >
+          <el-button
+            icon="el-icon-edit-outline"
+            type="primary"
+            size="mini"
+            @click="handleUpdateAssignee(item)"
+            >转办</el-button
+          >
+          <el-button
+            icon="el-icon-edit-outline"
+            type="primary"
+            size="mini"
+            @click="handleDelegate(item)"
+            >委派</el-button
+          >
+          <el-button
+            icon="el-icon-refresh-left"
+            type="warning"
+            size="mini"
+            @click="handleBack(item)"
+            >退回</el-button
+          >
+        </div>
+      </el-col>
+    </el-card>
+    <!-- 申请信息 -->
+    <el-card class="box-card" v-loading="processInstanceLoading">
+      <div slot="header" class="clearfix">
+        <span class="el-icon-document">申请信息【{{ processInstance.name }}】</span>
+      </div>
+      <el-col
+        v-if="
+          this.processInstance.processDefinition &&
+          this.processInstance.processDefinition.formType === 10
+        "
+        :span="16"
+        :offset="6"
+      >
+        <div>
+          <parser :key="new Date().getTime()" :form-conf="detailForm" />
+        </div>
+      </el-col>
+      <div
+        v-if="
+          this.processInstance.processDefinition &&
+          this.processInstance.processDefinition.formType === 20
+        "
+      >
+        <router-link
+          :to="
+            this.processInstance.processDefinition.formCustomViewPath +
+            '?id=' +
+            this.processInstance.businessKey
+          "
+        >
+          <el-button type="primary">点击查看</el-button>
+        </router-link>
+      </div>
+    </el-card>
+
+    <!-- 审批记录 -->
+    <el-card class="box-card" v-loading="tasksLoad">
+      <div slot="header" class="clearfix">
+        <span class="el-icon-picture-outline">审批记录</span>
+      </div>
+      <el-col :span="16" :offset="4">
+        <div class="block">
+          <el-timeline>
+            <el-timeline-item
+              v-for="(item, index) in tasks"
+              :key="index"
+              :icon="getTimelineItemIcon(item)"
+              :type="getTimelineItemType(item)"
+            >
+              <p style="font-weight: 700">任务:{{ item.name }}</p>
+              <el-card :body-style="{ padding: '10px' }">
+                <label v-if="item.assigneeUser" style="font-weight: normal; margin-right: 30px">
+                  审批人:{{ item.assigneeUser.nickname }}
+                  <el-tag type="info" size="mini">{{ item.assigneeUser.deptName }}</el-tag>
+                </label>
+                <label style="font-weight: normal" v-if="item.createTime">创建时间:</label>
+                <label style="color: #8a909c; font-weight: normal">{{
+                  parseTime(item.createTime)
+                }}</label>
+                <label v-if="item.endTime" style="margin-left: 30px; font-weight: normal"
+                  >审批时间:</label
+                >
+                <label v-if="item.endTime" style="color: #8a909c; font-weight: normal">
+                  {{ parseTime(item.endTime) }}</label
+                >
+                <label v-if="item.durationInMillis" style="margin-left: 30px; font-weight: normal"
+                  >耗时:</label
+                >
+                <label v-if="item.durationInMillis" style="color: #8a909c; font-weight: normal">
+                  {{ getDateStar(item.durationInMillis) }}
+                </label>
+                <p v-if="item.reason">
+                  <el-tag :type="getTimelineItemType(item)">{{ item.reason }}</el-tag>
+                </p>
+              </el-card>
+            </el-timeline-item>
+          </el-timeline>
+        </div>
+      </el-col>
+    </el-card>
+
+    <!-- 高亮流程图 -->
+    <el-card class="box-card" v-loading="processInstanceLoading">
+      <div slot="header" class="clearfix">
+        <span class="el-icon-picture-outline">流程图</span>
+      </div>
+      <my-process-viewer
+        key="designer"
+        v-model="bpmnXML"
+        v-bind="bpmnControlForm"
+        :activityData="activityList"
+        :processInstanceData="processInstance"
+        :taskData="tasks"
+      />
+    </el-card>
+
+    <!-- 对话框(转派审批人) -->
+    <el-dialog title="转派审批人" :visible.sync="updateAssignee.open" width="500px" append-to-body>
+      <el-form
+        ref="updateAssigneeForm"
+        :model="updateAssignee.form"
+        :rules="updateAssignee.rules"
+        label-width="110px"
+      >
+        <el-form-item label="新审批人" prop="assigneeUserId">
+          <el-select v-model="updateAssignee.form.assigneeUserId" clearable style="width: 100%">
+            <el-option
+              v-for="item in userOptions"
+              :key="parseInt(item.id)"
+              :label="item.nickname"
+              :value="parseInt(item.id)"
+            />
+          </el-select>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitUpdateAssigneeForm">确 定</el-button>
+        <el-button @click="cancelUpdateAssigneeForm">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { getProcessDefinitionBpmnXML } from "@/api/bpm/definition"
+import { DICT_TYPE, getDictOptions } from "@/utils/dict"
+import store from "@/store"
+import { decodeFields } from "@/utils/formGenerator"
+import Parser from '@/components/parser/Parser'
+import { getProcessInstanceApi } from "@/api/bpm/processInstance"
+import { approveTask, getTaskListByProcessInstanceId, rejectTask, updateTaskAssignee } from "@/api/bpm/task"
+import { getDate } from "@/utils/dateUtils"
+import { getListSimpleUsersApi } from "@/api/system/user"
+import { getActivityList } from "@/api/bpm/activity"
+
+// 流程实例的详情页,可用于审批
+export default {
+  name: "ProcessInstanceDetail",
+  components: {
+    Parser
+  },
+  data () {
+    return {
+      // 遮罩层
+      processInstanceLoading: true,
+      // 流程实例
+      id: undefined, // 流程实例的编号
+      processInstance: {},
+
+      // 流程表单详情
+      detailForm: {
+        fields: []
+      },
+
+      // BPMN 数据
+      bpmnXML: null,
+      bpmnControlForm: {
+        prefix: "flowable"
+      },
+      activityList: [],
+
+      // 审批记录
+      tasksLoad: true,
+      tasks: [],
+
+      // 审批表单
+      runningTasks: [],
+      auditForms: [],
+      auditRule: {
+        reason: [{ required: true, message: "审批建议不能为空", trigger: "blur" }],
+      },
+
+      // 转派审批人
+      userOptions: [],
+      updateAssignee: {
+        open: false,
+        form: {
+          assigneeUserId: undefined,
+        },
+        rules: {
+          assigneeUserId: [{ required: true, message: "新审批人不能为空", trigger: "change" }],
+        }
+      },
+
+      // 数据字典
+      categoryDictDatas: getDictDatas(DICT_TYPE.BPM_MODEL_CATEGORY),
+    }
+  },
+  created () {
+    this.id = this.$route.query.id
+    if (!this.id) {
+      this.$message.error('未传递 id 参数,无法查看流程信息')
+      return
+    }
+    this.getDetail()
+
+    // 获得用户列表
+    this.userOptions = []
+    getListSimpleUsersApi().then(response => {
+      this.userOptions.push(...response.data)
+    })
+  },
+  methods: {
+    /** 获得流程实例 */
+    getDetail () {
+      // 获得流程实例相关
+      this.processInstanceLoading = true
+      getProcessInstanceApi(this.id).then(response => {
+        if (!response.data) {
+          this.$message.error('查询不到流程信息!')
+          return
+        }
+        // 设置流程信息
+        this.processInstance = response.data
+
+        // 设置表单信息
+        if (this.processInstance.processDefinition.formType === 10) {
+          this.detailForm = {
+            ...JSON.parse(this.processInstance.processDefinition.formConf),
+            disabled: true, // 表单禁用
+            formBtns: false, // 按钮隐藏
+            fields: decodeFields(this.processInstance.processDefinition.formFields)
+          }
+          // 设置表单的值
+          this.detailForm.fields.forEach(item => {
+            const val = this.processInstance.formVariables[item.__vModel__]
+            if (val) {
+              item.__config__.defaultValue = val
+            }
+          })
+        }
+
+        // 加载流程图
+        getProcessDefinitionBpmnXML(this.processInstance.processDefinition.id).then(response => {
+          this.bpmnXML = response.data
+        })
+        // 加载活动列表
+        getActivityList({
+          processInstanceId: this.processInstance.id
+        }).then(response => {
+          this.activityList = response.data
+        })
+
+        // 取消加载中
+        this.processInstanceLoading = false
+      })
+
+      // 获得流程任务列表(审批记录)
+      this.tasksLoad = true
+      this.runningTasks = []
+      this.auditForms = []
+      getTaskListByProcessInstanceId(this.id).then(response => {
+        // 审批记录
+        this.tasks = []
+        // 移除已取消的审批
+        response.data.forEach(task => {
+          if (task.result !== 4) {
+            this.tasks.push(task)
+          }
+        })
+        // 排序,将未完成的排在前面,已完成的排在后面;
+        this.tasks.sort((a, b) => {
+          // 有已完成的情况,按照完成时间倒序
+          if (a.endTime && b.endTime) {
+            return b.endTime - a.endTime
+          } else if (a.endTime) {
+            return 1
+          } else if (b.endTime) {
+            return -1
+            // 都是未完成,按照创建时间倒序
+          } else {
+            return b.createTime - a.createTime
+          }
+        })
+
+        // 需要审核的记录
+        const userId = store.getters.userId
+        this.tasks.forEach(task => {
+          if (task.result !== 1) { // 只有待处理才需要
+            return
+          }
+          if (!task.assigneeUser || task.assigneeUser.id !== userId) { // 自己不是处理人
+            return
+          }
+          this.runningTasks.push({ ...task })
+          this.auditForms.push({
+            reason: ''
+          })
+        })
+
+        // 取消加载中
+        this.tasksLoad = false
+      })
+    },
+    /** 处理选择流程的按钮操作 **/
+    handleSelect (row) {
+      // 设置选择的流程
+      this.selectProcessInstance = row
+
+      // 流程表单
+      if (row.formId) {
+        // 设置对应的表单
+        this.detailForm = {
+          ...JSON.parse(row.formConf),
+          fields: decodeFields(row.formFields)
+        }
+      } else if (row.formCustomCreatePath) {
+        this.$router.push({ path: row.formCustomCreatePath })
+        // 这里暂时无需加载流程图,因为跳出到另外个 Tab;
+      }
+    },
+    getDateStar (ms) {
+      return getDate(ms)
+    },
+    getTimelineItemIcon (item) {
+      if (item.result === 1) {
+        return 'el-icon-time'
+      }
+      if (item.result === 2) {
+        return 'el-icon-check'
+      }
+      if (item.result === 3) {
+        return 'el-icon-close'
+      }
+      if (item.result === 4) {
+        return 'el-icon-remove-outline'
+      }
+      return ''
+    },
+    getTimelineItemType (item) {
+      if (item.result === 1) {
+        return 'primary'
+      }
+      if (item.result === 2) {
+        return 'success'
+      }
+      if (item.result === 3) {
+        return 'danger'
+      }
+      if (item.result === 4) {
+        return 'info'
+      }
+      return ''
+    },
+    /** 处理审批通过和不通过的操作 */
+    handleAudit (task, pass) {
+      const index = this.runningTasks.indexOf(task)
+      this.$refs['form' + index][0].validate(valid => {
+        if (!valid) {
+          return
+        }
+        const data = {
+          id: task.id,
+          reason: this.auditForms[index].reason
+        }
+        if (pass) {
+          approveTask(data).then(response => {
+            this.$modal.msgSuccess("审批通过成功!")
+            this.getDetail() // 获得最新详情
+          })
+        } else {
+          rejectTask(data).then(response => {
+            this.$modal.msgSuccess("审批不通过成功!")
+            this.getDetail() // 获得最新详情
+          })
+        }
+      })
+    },
+    /** 处理转派审批人 */
+    handleUpdateAssignee (task) {
+      // 设置表单
+      this.resetUpdateAssigneeForm()
+      this.updateAssignee.form.id = task.id
+      // 设置为打开
+      this.updateAssignee.open = true
+    },
+    /** 提交转派审批人 */
+    submitUpdateAssigneeForm () {
+      this.$refs['updateAssigneeForm'].validate(valid => {
+        if (!valid) {
+          return
+        }
+        updateTaskAssignee(this.updateAssignee.form).then(response => {
+          this.$modal.msgSuccess("转派任务成功!")
+          this.updateAssignee.open = false
+          this.getDetail() // 获得最新详情
+        })
+      })
+    },
+    /** 取消转派审批人 */
+    cancelUpdateAssigneeForm () {
+      this.updateAssignee.open = false
+      this.resetUpdateAssigneeForm()
+    },
+    /** 重置转派审批人 */
+    resetUpdateAssigneeForm () {
+      this.updateAssignee.form = {
+        id: undefined,
+        assigneeUserId: undefined,
+      }
+      this.resetForm("updateAssigneeForm")
+    },
+    /** 处理审批退回的操作 */
+    handleDelegate (task) {
+      this.$modal.msgError("暂不支持【委派】功能,可以使用【转派】替代!")
+    },
+    /** 处理审批退回的操作 */
+    handleBack (task) {
+      this.$modal.msgError("暂不支持【退回】功能!")
+      // 可参考 http://blog.wya1.com/article/636697030/details/7296
+      // const data = {
+      //   id: task.id,
+      //   assigneeUserId: 1
+      // }
+      // backTask(data).then(response => {
+      //   this.$modal.msgSuccess("回退成功!");
+      //   this.getDetail(); // 获得最新详情
+      // });
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+.my-process-designer {
+  height: calc(100vh - 200px);
+}
+
+.box-card {
+  width: 100%;
+  margin-bottom: 20px;
+}
+</style>

+ 97 - 100
yudao-ui-admin-vue3/src/views/bpm/processInstance/index.vue

@@ -1,113 +1,110 @@
-<script setup lang="ts" name="ProcessInstance">
-import dayjs from 'dayjs'
-import { DICT_TYPE } from '@/utils/dict'
-import { useTable } from '@/hooks/web/useTable'
-import type { ProcessInstanceVO } from '@/api/bpm/processInstance/types'
-import { allSchemas } from './process.data'
+<template>
+  <ContentWrap>
+    <!-- 列表 -->
+    <XTable @register="registerTable">
+      <template #toolbar_buttons>
+        <!-- 操作:新增 -->
+        <XButton
+          type="primary"
+          preIcon="ep:zoom-in"
+          title="新建流程"
+          v-hasPermi="['bpm:process-instance:query']"
+          @click="handleCreate"
+        />
+      </template>
+      <!-- 当前审批任务 -->
+      <template #tasks_default="{ row }">
+        <el-button
+          v-for="task in row.tasks"
+          :key="task.id"
+          type="text"
+          @click="handleFormDetail(task.id)"
+        >
+          <span>{{ task.name }}</span>
+        </el-button>
+      </template>
+      <!-- 操作 -->
+      <template #actionbtns_default="{ row }">
+        <XButton
+          type="primary"
+          title="取消"
+          v-if="row.result === 1"
+          preIcon="ep:delete"
+          @click="handleCancel(row)"
+        />
+        <XButton type="primary" title="详情" preIcon="ep:edit-pen" @click="handleDetail(row)" />
+      </template>
+    </XTable>
+  </ContentWrap>
+</template>
+<script setup lang="ts">
+// 全局相关的 import
+import { ref } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { useXTable } from '@/hooks/web/useXTable'
+import { useRouter } from 'vue-router'
+
+// 业务相关的 import
 import * as ProcessInstanceApi from '@/api/bpm/processInstance'
-import { ElMessageBox } from 'element-plus'
-const { t } = useI18n() // 国际化
-const message = useMessage()
+// import { decodeFields } from '@/utils/formGenerator' // TODO 芋艿:后续根据情况清理
+import { allSchemas } from './process.data'
+
+const router = useRouter() // 路由
 
 // ========== 列表相关 ==========
-const { register, tableObject, methods } = useTable<ProcessInstanceVO>({
+const [registerTable] = useXTable({
+  allSchemas: allSchemas,
   getListApi: ProcessInstanceApi.getMyProcessInstancePageApi
 })
-const { getList, setSearchParams } = methods
+// 流程表单的弹出框
+const detailOpen = ref(false)
+const detailForm = ref()
+/** 发起流程操作 **/
+const handleCreate = () => {
+  router.push({
+    name: 'BpmProcessInstanceCreate'
+  })
+}
+/** 流程表单的详情按钮操作 */
+const handleFormDetail = (row) => {
+  // 情况一:使用流程表单
+  if (row.formId) {
+    // 设置值 TODO 芋艿:动态表单做完后,需要测试下
+    detailForm.value = {
+      ...JSON.parse(row.formConf),
+      fields: decodeFields([], row.formFields)
+    }
+    // 弹窗打开
+    detailOpen.value = true
+    // 情况二:使用业务表单
+  } else if (row.formCustomCreatePath) {
+    router.push({ path: row.formCustomCreatePath })
+  }
+}
 
-// ========== CRUD 相关 ==========
-const dialogVisible = ref(false) // 是否显示弹出层
-// 发起流程
-const handleAdd = () => {
-  console.info('add')
+// 列表操作
+const handleDetail = (row) => {
+  console.log(row, 'row')
+  router.push({ path: '/process-instance/detail', query: { id: row.id } })
 }
-// 取消操作
-const handleCancel = (row: ProcessInstanceVO) => {
+/** 取消按钮操作 */
+const handleCancel = (row) => {
+  const id = row.id
   ElMessageBox.prompt('请输入取消原因?', '取消流程', {
-    confirmButtonText: t('common.ok'),
-    cancelButtonText: t('common.cancel'),
     type: 'warning',
-    inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/, // 判断非空,且非空格
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    inputPattern: /^[\s\S]*.*\S[\s\S]*$/, // 判断非空,且非空格
     inputErrorMessage: '取消原因不能为空'
-  }).then(async ({ value }) => {
-    await ProcessInstanceApi.cancelProcessInstanceApi(row.id, value)
-    message.success('取消成功')
-    getList()
   })
+    .then(({ value }) => {
+      return ProcessInstanceApi.cancelProcessInstanceApi(id, value)
+    })
+    .then(() => {
+      ElMessage({
+        message: '取消成功',
+        type: 'success'
+      })
+    })
 }
-
-// ========== 详情相关 ==========
-const detailData = ref() // 详情 Ref
-
-// 详情操作
-const handleDetail = async (row: ProcessInstanceVO) => {
-  // 设置数据
-  detailData.value = row
-  dialogVisible.value = true
-}
-
-// ========== 初始化 ==========
-getList()
 </script>
-
-<template>
-  <!-- 搜索工作区 -->
-  <ContentWrap>
-    <Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
-  </ContentWrap>
-  <ContentWrap>
-    <!-- 操作工具栏 -->
-    <div class="mb-10px">
-      <el-button type="primary" v-hasPermi="['bpm:process-instance:query']" @click="handleAdd">
-        <Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }}
-      </el-button>
-    </div>
-    <!-- 列表 -->
-    <Table
-      :columns="allSchemas.tableColumns"
-      :selection="false"
-      :data="tableObject.tableList"
-      :loading="tableObject.loading"
-      :pagination="{
-        total: tableObject.total
-      }"
-      v-model:pageSize="tableObject.pageSize"
-      v-model:currentPage="tableObject.currentPage"
-      @register="register"
-    >
-      <template #status="{ row }">
-        <DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
-      </template>
-      <template #createTime="{ row }">
-        <span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
-      </template>
-      <template #action="{ row }">
-        <el-button
-          link
-          type="primary"
-          v-hasPermi="['bpm:process-instance:query']"
-          @click="handleDetail(row)"
-        >
-          <Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}
-        </el-button>
-        <el-button
-          link
-          type="primary"
-          v-hasPermi="['bpm:process-instance:cancel']"
-          @click="handleCancel(row)"
-        >
-          <Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}
-        </el-button>
-      </template>
-    </Table>
-  </ContentWrap>
-
-  <XModal v-model="dialogVisible" :title="t('action.detail')">
-    <!-- 对话框(详情) -->
-    <Descriptions :schema="allSchemas.detailSchema" :data="detailData" />
-    <!-- 操作按钮 -->
-    <template #footer>
-      <el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>
-    </template>
-  </XModal>
-</template>

+ 36 - 0
yudao-ui-admin-vue3/src/views/bpm/processInstance/process.create.ts

@@ -0,0 +1,36 @@
+import { reactive } from 'vue'
+// import { useI18n } from '@/hooks/web/useI18n'
+import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
+import { DICT_TYPE } from '@/utils/dict'
+// const { t } = useI18n() // 国际化
+
+// CrudSchema
+const crudSchemas = reactive<VxeCrudSchema>({
+  primaryKey: 'id',
+  primaryType: 'id',
+  primaryTitle: '流程名称',
+  action: true,
+  actionWidth: '200px',
+  columns: [
+    {
+      title: '流程分类',
+      field: 'category',
+      dictType: DICT_TYPE.BPM_MODEL_CATEGORY,
+      dictClass: 'number'
+    },
+    {
+      title: '流程版本',
+      field: 'processDefinition.version',
+      table: {
+        slots: {
+          default: 'version_default'
+        }
+      }
+    },
+    {
+      title: '流程描述',
+      field: 'description'
+    }
+  ]
+})
+export const { allSchemas } = useVxeCrudSchemas(crudSchemas)

+ 84 - 77
yudao-ui-admin-vue3/src/views/bpm/processInstance/process.data.ts

@@ -1,84 +1,91 @@
-import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
+import { reactive } from 'vue'
+import { useI18n } from '@/hooks/web/useI18n'
+import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
+import { DICT_TYPE } from '@/utils/dict'
 const { t } = useI18n() // 国际化
 
 // CrudSchema
-const crudSchemas = reactive<CrudSchema[]>([
-  {
-    label: t('common.index'),
-    field: 'id',
-    type: 'index',
-    form: {
-      show: false
+const crudSchemas = reactive<VxeCrudSchema>({
+  primaryKey: 'id',
+  primaryType: null,
+  primaryTitle: '编号',
+  action: true,
+  actionWidth: '200px',
+  columns: [
+    {
+      title: '编号',
+      field: 'id',
+      table: {
+        width: 320
+      }
     },
-    detail: {
-      show: false
-    }
-  },
-  {
-    label: '流程名',
-    field: 'name',
-    search: {
-      show: true
-    }
-  },
-  {
-    label: '流程分类',
-    field: 'category',
-    dictType: DICT_TYPE.BPM_MODEL_CATEGORY,
-    dictClass: 'number',
-    search: {
-      show: true
-    }
-  },
-  {
-    label: '当前审批任务',
-    field: 'tasks'
-  },
-  {
-    label: t('common.status'),
-    field: 'status',
-    dictType: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS,
-    dictClass: 'number',
-    search: {
-      show: true
-    }
-  },
-  {
-    label: '结果',
-    field: 'result',
-    dictType: DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
-    dictClass: 'number',
-    search: {
-      show: true
-    }
-  },
-  {
-    label: '提交时间',
-    field: 'createTime',
-    form: {
-      show: false
+    {
+      title: '流程名',
+      field: 'name',
+      isSearch: true
     },
-    search: {
-      show: true
-    }
-  },
-  {
-    label: '结束时间',
-    field: 'endTime',
-    form: {
-      show: false
-    }
-  },
-  {
-    label: t('table.action'),
-    field: 'action',
-    width: '240px',
-    form: {
-      show: false
+    {
+      title: '所属流程',
+      field: 'processDefinitionId',
+      isSearch: true,
+      isTable: false
+    },
+    {
+      title: '流程分类',
+      field: 'category',
+      dictType: DICT_TYPE.BPM_MODEL_CATEGORY,
+      dictClass: 'number',
+      isSearch: true
+    },
+    {
+      title: '当前审批任务',
+      field: 'tasks',
+      table: {
+        width: 100,
+        slots: {
+          default: 'tasks_default'
+        }
+      }
+    },
+    {
+      title: t('common.status'),
+      field: 'status',
+      dictType: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS,
+      dictClass: 'number',
+      isSearch: true
+    },
+    {
+      title: '结果',
+      field: 'result',
+      dictType: DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
+      dictClass: 'number',
+      isSearch: true
+    },
+    {
+      title: '提交时间',
+      field: 'createTime',
+      formatter: 'formatDate',
+      table: {
+        width: 180
+      },
+      isForm: false,
+      isSearch: true,
+      search: {
+        show: true,
+        itemRender: {
+          name: 'XDataTimePicker'
+        }
+      }
     },
-    detail: {
-      show: false
+    {
+      title: '结束时间',
+      field: 'endTime',
+      formatter: 'formatDate',
+      table: {
+        width: 180
+      },
+      isForm: false
     }
-  }
-])
-export const { allSchemas } = useCrudSchemas(crudSchemas)
+  ]
+})
+export const { allSchemas } = useVxeCrudSchemas(crudSchemas)

+ 36 - 0
yudao-ui-admin-vue3/src/views/bpm/processInstance/process.detail.ts

@@ -0,0 +1,36 @@
+import { reactive } from 'vue'
+// import { useI18n } from '@/hooks/web/useI18n'
+import { VxeCrudSchema, useVxeCrudSchemas } from '@/hooks/web/useVxeCrudSchemas'
+import { DICT_TYPE } from '@/utils/dict'
+// const { t } = useI18n() // 国际化
+
+// CrudSchema
+const crudSchemas = reactive<VxeCrudSchema>({
+  primaryKey: 'id',
+  primaryType: 'id',
+  primaryTitle: '流程名称',
+  action: true,
+  actionWidth: '200px',
+  columns: [
+    {
+      title: '流程分类',
+      field: 'category',
+      dictType: DICT_TYPE.BPM_MODEL_CATEGORY,
+      dictClass: 'number'
+    },
+    {
+      title: '流程版本',
+      field: 'processDefinition.version',
+      table: {
+        slots: {
+          default: 'version_default'
+        }
+      }
+    },
+    {
+      title: '流程描述',
+      field: 'description'
+    }
+  ]
+})
+export const { allSchemas } = useVxeCrudSchemas(crudSchemas)