bpm:流程详情的时间轴

This commit is contained in:
YunaiV 2023-01-24 09:20:30 +08:00
parent 2774671a88
commit 0aa72b3200
4 changed files with 167 additions and 242 deletions

View File

@ -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 + '秒'
}
}

View File

@ -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>

View File

@ -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)

View File

@ -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);
},