Browse Source

bpm:流程详情的时间轴

YunaiV 2 năm trước cách đây
mục cha
commit
0aa72b3200

+ 27 - 0
yudao-ui-admin-vue3/src/utils/formatTime.ts

@@ -147,3 +147,30 @@ export function formatAxis(param: Date): string {
   else if (hour < 22) return '晚上好'
   else return '夜里好'
 }
+
+/**
+ * 将毫秒,转换成时间字符串。例如说,xx 分钟
+ *
+ * @param ms 毫秒
+ * @returns {string} 字符串
+ */
+export function formatPast2(ms) {
+  const day = Math.floor(ms / (24 * 60 * 60 * 1000))
+  const hour = Math.floor(ms / (60 * 60 * 1000) - day * 24)
+  const minute = Math.floor(ms / (60 * 1000) - day * 24 * 60 - hour * 60)
+  const second = Math.floor(ms / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60)
+  if (day > 0) {
+    return day + '天' + hour + '小时' + minute + '分钟'
+  }
+  if (hour > 0) {
+    return hour + '小时' + minute + '分钟'
+  }
+  if (minute > 0) {
+    return minute + '分钟'
+  }
+  if (second > 0) {
+    return second + '秒'
+  } else {
+    return 0 + '秒'
+  }
+}

+ 137 - 2
yudao-ui-admin-vue3/src/views/bpm/processInstance/detail.vue

@@ -25,14 +25,63 @@
             processInstance.businessKey
           "
         >
-          <el-button type="primary">点击查看</el-button>
+          <XButton type="primary" preIcon="ep:view" title="点击查看" />
         </router-link>
       </div>
     </el-card>
+
+    <!-- 审批记录 -->
+    <el-card class="box-card" v-loading="tasksLoad">
+      <template #header>
+        <span class="el-icon-picture-outline">审批记录</span>
+      </template>
+      <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">
+                  {{ dayjs(item?.createTime).format('YYYY-MM-DD HH:mm:ss') }}
+                </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">
+                  {{ dayjs(item?.endTime).format('YYYY-MM-DD HH:mm:ss') }}
+                </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">
+                  {{ formatPast2(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>
   </ContentWrap>
 </template>
 <script setup lang="ts">
+import dayjs from 'dayjs'
 import * as ProcessInstanceApi from '@/api/bpm/processInstance'
+import * as TaskApi from '@/api/bpm/task'
+import { formatPast2 } from '@/utils/formatTime'
 
 const { query } = useRoute() // 查询参数
 const message = useMessage() // 消息弹窗
@@ -41,6 +90,11 @@ const message = useMessage() // 消息弹窗
 const id = query.id as unknown as number
 const processInstanceLoading = ref(false) // 流程实例的加载中
 const processInstance = ref({}) // 流程实例
+const runningTasks = ref([]) // 运行中的任务
+const auditForms = ref([]) // 审批任务的表单
+// const auditRule = reactive({
+//   reason: [{ required: true, message: '审批建议不能为空', trigger: 'blur' }]
+// })
 
 // ========== 申请信息 ==========
 import { setConfAndFields2 } from '@/utils/formCreate'
@@ -53,6 +107,41 @@ const detailForm = ref({
   value: {}
 })
 
+// ========== 审批记录 ==========
+const tasksLoad = ref(true)
+const tasks = ref([])
+
+const 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 ''
+}
+const 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 ''
+}
+
 // ========== 初始化 ==========
 onMounted(() => {
   // 1. 获得流程实例相关
@@ -88,7 +177,53 @@ onMounted(() => {
       processInstanceLoading.value = false
     })
 
-  // 2. TODO
+  // 2. 获得流程任务列表(审批记录)
+  tasksLoad.value = true
+  runningTasks.value = []
+  auditForms.value = []
+  TaskApi.getTaskListByProcessInstanceId(id)
+    .then((data) => {
+      // 审批记录
+      tasks.value = []
+      // 移除已取消的审批
+      data.forEach((task) => {
+        if (task.result !== 4) {
+          tasks.value.push(task)
+        }
+      })
+      // 排序,将未完成的排在前面,已完成的排在后面;
+      tasks.value.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: ''
+      //   })
+      // })
+    })
+    .finally(() => {
+      tasksLoad.value = false
+    })
 })
 </script>
 

+ 3 - 223
yudao-ui-admin-vue3/src/views/bpm/processInstance/detail2.vue

@@ -71,86 +71,8 @@
         </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">
@@ -209,21 +131,9 @@ import { getActivityList } from "@/api/bpm/activity"
 // 流程实例的详情页,可用于审批
 export default {
   name: "ProcessInstanceDetail",
-  components: {
-    Parser
-  },
   data () {
     return {
 
-      // 流程实例
-      id: undefined, // 流程实例的编号
-      processInstance: {},
-
-      // 流程表单详情
-      detailForm: {
-        fields: []
-      },
-
       // BPMN 数据
       bpmnXML: null,
       bpmnControlForm: {
@@ -231,17 +141,6 @@ export default {
       },
       activityList: [],
 
-      // 审批记录
-      tasksLoad: true,
-      tasks: [],
-
-      // 审批表单
-      runningTasks: [],
-      auditForms: [],
-      auditRule: {
-        reason: [{ required: true, message: "审批建议不能为空", trigger: "blur" }],
-      },
-
       // 转派审批人
       userOptions: [],
       updateAssignee: {
@@ -278,142 +177,23 @@ export default {
       // 获得流程实例相关
       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)

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

@@ -275,23 +275,6 @@ export default {
         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);
     },