BPM:优化 task 审批详情界面,增加开始时间、结束时间的展示

This commit is contained in:
YunaiV 2024-03-20 21:33:48 +08:00
parent d0f73344bf
commit d16194b794
12 changed files with 93 additions and 61 deletions

View File

@ -49,8 +49,8 @@ export const getFormPage = async (params) => {
} }
// 获得动态表单的精简列表 // 获得动态表单的精简列表
export const getSimpleFormList = async () => { export const getFormSimpleList = async () => {
return await request.get({ return await request.get({
url: '/bpm/form/list-all-simple' url: '/bpm/form/simple-list'
}) })
} }

View File

@ -2,7 +2,7 @@ import request from '@/config/axios'
export type LeaveVO = { export type LeaveVO = {
id: number id: number
result: number status: number
type: number type: number
reason: string reason: string
processInstanceId: string processInstanceId: string

View File

@ -194,6 +194,7 @@ const highlightDiagram = async () => {
}) })
} else if (n.$type === 'bpmn:StartEvent') { } else if (n.$type === 'bpmn:StartEvent') {
// //
canvas.addMarker(n.id, 'highlight')
n.outgoing?.forEach((nn) => { n.outgoing?.forEach((nn) => {
// outgoing bpmn:SequenceFlow线 // outgoing bpmn:SequenceFlow线
// 线 // 线
@ -223,40 +224,49 @@ const highlightDiagram = async () => {
canvas.addMarker(out.id, getResultCss(2)) canvas.addMarker(out.id, getResultCss(2))
}) })
} }
} else if (n.$type === 'bpmn:SequenceFlow') {
let targetActivity = activityList.find((m: any) => m.key === n.targetRef.id)
if (targetActivity) {
canvas.addMarker(n.id, getActivityHighlightCss(targetActivity))
}
} }
}) })
if (!isEmpty(removeTaskDefinitionKeyList)) { if (!isEmpty(removeTaskDefinitionKeyList)) {
// TODO .definitionKey
taskList.value = taskList.value.filter( taskList.value = taskList.value.filter(
(item) => !removeTaskDefinitionKeyList.includes(item.definitionKey) (item) => !removeTaskDefinitionKeyList.includes(item.taskDefinitionKey)
) )
} }
} }
const getActivityHighlightCss = (activity) => { const getActivityHighlightCss = (activity) => {
return activity.endTime ? 'highlight' : 'highlight-todo' return activity.endTime ? 'highlight' : 'highlight-todo'
} }
const getResultCss = (result) => {
if (result === 1) { const getResultCss = (status) => {
if (status === 1) {
// //
return 'highlight-todo' return 'highlight-todo'
} else if (result === 2) { } else if (status === 2) {
// //
return 'highlight' return 'highlight'
} else if (result === 3) { } else if (status === 3) {
// //
return 'highlight-reject' return 'highlight-reject'
} else if (result === 4) { } else if (status === 4) {
// //
return 'highlight-cancel' return 'highlight-cancel'
} else if (result === 5) { } else if (status === 5) {
// 退 // 退
return 'highlight-return' return 'highlight-return'
} else if (result === 6) { } else if (status === 6) {
// //
return 'highlight-return' return 'highlight-todo'
} else if (result === 7 || result === 8 || result === 9) { } else if (status === 7) {
// // //
return 'highlight-return' return 'highlight-todo'
} else if (status === 0) {
//
return 'highlight-todo'
} }
return '' return ''
} }
@ -297,10 +307,10 @@ const elementHover = (element) => {
!elementOverlayIds.value && (elementOverlayIds.value = {}) !elementOverlayIds.value && (elementOverlayIds.value = {})
!overlays.value && (overlays.value = bpmnModeler.get('overlays')) !overlays.value && (overlays.value = bpmnModeler.get('overlays'))
// //
console.log(activityLists.value, 'activityLists.value') // console.log(activityLists.value, 'activityLists.value')
console.log(element.value, 'element.value') // console.log(element.value, 'element.value')
const activity = activityLists.value.find((m) => m.key === element.value.id) const activity = activityLists.value.find((m) => m.key === element.value.id)
console.log(activity, 'activityactivityactivityactivity') // console.log(activity, 'activityactivityactivityactivity')
if (!activity) { if (!activity) {
return return
} }
@ -314,12 +324,11 @@ const elementHover = (element) => {
<p>部门${processInstance.value.startUser.deptName}</p> <p>部门${processInstance.value.startUser.deptName}</p>
<p>创建时间${formatDate(processInstance.value.createTime)}` <p>创建时间${formatDate(processInstance.value.createTime)}`
} else if (element.value.type === 'bpmn:UserTask') { } else if (element.value.type === 'bpmn:UserTask') {
// debugger
let task = taskList.value.find((m) => m.id === activity.taskId) // taskId let task = taskList.value.find((m) => m.id === activity.taskId) // taskId
if (!task) { if (!task) {
return return
} }
let optionData = getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT) let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS)
let dataResult = '' let dataResult = ''
optionData.forEach((element) => { optionData.forEach((element) => {
if (element.value == task.status) { if (element.value == task.status) {
@ -352,7 +361,7 @@ const elementHover = (element) => {
} }
console.log(html) console.log(html)
} else if (element.value.type === 'bpmn:EndEvent' && processInstance.value) { } else if (element.value.type === 'bpmn:EndEvent' && processInstance.value) {
let optionData = getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT) let optionData = getIntDictOptions(DICT_TYPE.BPM_TASK_STATUS)
let dataResult = '' let dataResult = ''
optionData.forEach((element) => { optionData.forEach((element) => {
if (element.value == processInstance.value.status) { if (element.value == processInstance.value.status) {
@ -375,6 +384,7 @@ const elementHover = (element) => {
}) })
} }
} }
// out // out
const elementOut = (element) => { const elementOut = (element) => {
toRaw(overlays.value).remove({ element }) toRaw(overlays.value).remove({ element })
@ -390,6 +400,7 @@ onMounted(() => {
// //
initModelListeners() initModelListeners()
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
// this.$once('hook:beforeDestroy', () => { // this.$once('hook:beforeDestroy', () => {
// }) // })
@ -428,7 +439,7 @@ watch(
) )
</script> </script>
<style> <style lang="scss">
/** 处理中 */ /** 处理中 */
.highlight-todo.djs-connection > .djs-visual > path { .highlight-todo.djs-connection > .djs-visual > path {
stroke: #1890ff !important; stroke: #1890ff !important;
@ -502,6 +513,10 @@ watch(
stroke: green !important; stroke: green !important;
} }
.djs-element.highlight > .djs-visual > path {
stroke: green !important;
}
/** 不通过 */ /** 不通过 */
.highlight-reject.djs-shape .djs-visual > :nth-child(1) { .highlight-reject.djs-shape .djs-visual > :nth-child(1) {
fill: red !important; fill: red !important;
@ -521,6 +536,7 @@ watch(
.highlight-reject.djs-connection > .djs-visual > path { .highlight-reject.djs-connection > .djs-visual > path {
stroke: red !important; stroke: red !important;
marker-end: url(#sequenceflow-end-white-success) !important;
} }
.highlight-reject:not(.djs-connection) .djs-visual > :nth-child(1) { .highlight-reject:not(.djs-connection) .djs-visual > :nth-child(1) {

View File

@ -461,7 +461,7 @@ const updateElementExtensions = () => {
const formList = ref([]) // const formList = ref([]) //
onMounted(async () => { onMounted(async () => {
formList.value = await FormApi.getSimpleFormList() formList.value = await FormApi.getFormSimpleList()
}) })
watch( watch(

View File

@ -139,7 +139,7 @@ export enum DICT_TYPE {
BPM_MODEL_FORM_TYPE = 'bpm_model_form_type', BPM_MODEL_FORM_TYPE = 'bpm_model_form_type',
BPM_TASK_CANDIDATE_STRATEGY = 'bpm_task_candidate_strategy', BPM_TASK_CANDIDATE_STRATEGY = 'bpm_task_candidate_strategy',
BPM_PROCESS_INSTANCE_STATUS = 'bpm_process_instance_status', BPM_PROCESS_INSTANCE_STATUS = 'bpm_process_instance_status',
BPM_PROCESS_INSTANCE_RESULT = 'bpm_process_instance_result', // TODO @芋艿:改名 BPM_TASK_STATUS = 'bpm_task_status',
BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type', BPM_OA_LEAVE_TYPE = 'bpm_oa_leave_type',
// ========== PAY 模块 ========== // ========== PAY 模块 ==========

View File

@ -173,7 +173,7 @@ const open = async (type: string, id?: number) => {
} }
} }
// //
formList.value = await FormApi.getSimpleFormList() formList.value = await FormApi.getFormSimpleList()
// //
categoryList.value = await CategoryApi.getCategorySimpleList() categoryList.value = await CategoryApi.getCategorySimpleList()
} }

View File

@ -109,6 +109,7 @@ const submitFormSuccess = async (response: any) => {
} }
// //
message.success('导入流程成功!请点击【设计流程】按钮,进行编辑保存后,才可以进行【发布流程】') message.success('导入流程成功!请点击【设计流程】按钮,进行编辑保存后,才可以进行【发布流程】')
dialogVisible.value = false
// //
emit('success') emit('success')
} }

View File

@ -36,10 +36,15 @@
value-format="YYYY-MM-DD HH:mm:ss" value-format="YYYY-MM-DD HH:mm:ss"
/> />
</el-form-item> </el-form-item>
<el-form-item label="结果" prop="result"> <el-form-item label="审批结果" prop="result">
<el-select v-model="queryParams.result" class="!w-240px" clearable placeholder="请选择结果"> <el-select
v-model="queryParams.result"
class="!w-240px"
clearable
placeholder="请选择审批结果"
>
<el-option <el-option
v-for="dict in getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)" v-for="dict in getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS)"
:key="dict.value" :key="dict.value"
:label="dict.label" :label="dict.label"
:value="dict.value" :value="dict.value"
@ -78,7 +83,7 @@
<el-table-column align="center" label="申请编号" prop="id" /> <el-table-column align="center" label="申请编号" prop="id" />
<el-table-column align="center" label="状态" prop="result"> <el-table-column align="center" label="状态" prop="result">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result" /> <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS" :value="scope.row.result" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column
@ -166,7 +171,7 @@ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
type: undefined, type: undefined,
result: undefined, status: undefined,
reason: undefined, reason: undefined,
createTime: [] createTime: []
}) })

View File

@ -7,14 +7,25 @@
<div class="block"> <div class="block">
<el-timeline> <el-timeline>
<el-timeline-item <el-timeline-item
v-for="(item, index) in tasks" v-if="processInstance.endTime"
:key="index" :type="getProcessInstanceTimelineItemType(processInstance)"
:icon="getTimelineItemIcon(item)"
:type="getTimelineItemType(item)"
> >
<p style="font-weight: 700"> <p style="font-weight: 700">
任务{{ item.name }} 结束流程 {{ formatDate(processInstance?.endTime) }} 结束
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="item.status" /> <dict-tag
:type="DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
:value="processInstance.status"
/>
</p>
</el-timeline-item>
<el-timeline-item
v-for="(item, index) in tasks"
:key="index"
:type="getTaskTimelineItemType(item)"
>
<p style="font-weight: 700">
审批任务{{ item.name }}
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="item.status" />
<el-button <el-button
class="ml-10px" class="ml-10px"
v-if="!isEmpty(item.children)" v-if="!isEmpty(item.children)"
@ -56,6 +67,12 @@
<p v-if="item.reason"> 审批建议{{ item.reason }} </p> <p v-if="item.reason"> 审批建议{{ item.reason }} </p>
</el-card> </el-card>
</el-timeline-item> </el-timeline-item>
<el-timeline-item type="success">
<p style="font-weight: 700">
发起流程{{ processInstance.startUser?.nickname }}
{{ formatDate(processInstance?.startTime) }} 发起 {{ processInstance.name }} 流程
</p>
</el-timeline-item>
</el-timeline> </el-timeline>
</div> </div>
</el-col> </el-col>
@ -86,33 +103,27 @@ defineOptions({ name: 'BpmProcessInstanceTaskList' })
defineProps({ defineProps({
loading: propTypes.bool, // loading: propTypes.bool, //
processInstance: propTypes.object, //
tasks: propTypes.arrayOf(propTypes.object) // tasks: propTypes.arrayOf(propTypes.object) //
}) })
/** 获得任务对应的 icon */ /** 获得流程实例对应的颜色 */
// TODO @ icon const getProcessInstanceTimelineItemType = (item: any) => {
const getTimelineItemIcon = (item) => {
if (item.status === 1) {
return 'el-icon-time'
}
if (item.status === 2) { if (item.status === 2) {
return 'el-icon-check' return 'success'
} }
if (item.status === 3) { if (item.status === 3) {
return 'el-icon-close' return 'danger'
} }
if (item.status === 4) { if (item.status === 4) {
return 'el-icon-remove-outline' return 'warning'
}
if (item.status === 5) {
return 'el-icon-back'
} }
return '' return ''
} }
/** 获得任务对应的颜色 */ /** 获得任务对应的颜色 */
const getTimelineItemType = (item: any) => { const getTaskTimelineItemType = (item: any) => {
if (item.status === 1) { if ([0, 1, 6, 7].includes(item.status)) {
return 'primary' return 'primary'
} }
if (item.status === 2) { if (item.status === 2) {
@ -127,12 +138,6 @@ const getTimelineItemType = (item: any) => {
if (item.status === 5) { if (item.status === 5) {
return 'warning' return 'warning'
} }
if (item.status === 6) {
return 'default'
}
if (item.status === 7 || item.status === 8) {
return 'warning'
}
return '' return ''
} }

View File

@ -27,7 +27,7 @@
</el-table-column> </el-table-column>
<el-table-column label="审批状态" prop="status" width="120"> <el-table-column label="审批状态" prop="status" width="120">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.status" /> <dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column <el-table-column

View File

@ -105,7 +105,12 @@
</el-card> </el-card>
<!-- 审批记录 --> <!-- 审批记录 -->
<ProcessInstanceTaskList :loading="tasksLoad" :tasks="tasks" @refresh="getTaskList" /> <ProcessInstanceTaskList
:loading="tasksLoad"
:process-instance="processInstance"
:tasks="tasks"
@refresh="getTaskList"
/>
<!-- 高亮流程图 --> <!-- 高亮流程图 -->
<ProcessInstanceBpmnViewer <ProcessInstanceBpmnViewer

View File

@ -77,7 +77,7 @@
/> />
<el-table-column align="center" label="审批状态" prop="status" width="120"> <el-table-column align="center" label="审批状态" prop="status" width="120">
<template #default="scope"> <template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.status" /> <dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="审批建议" prop="reason" min-width="180" /> <el-table-column align="center" label="审批建议" prop="reason" min-width="180" />