feat:【BPM 工作流】 完善流转记录列表
parent
e39e5a4ed8
commit
66ac3de5c1
|
@ -82,8 +82,10 @@ export const rejectTask = async (data: any) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 根据流程实例 ID 查询任务列表 */
|
/** 根据流程实例 ID 查询任务列表 */
|
||||||
export const getTaskListByProcessInstanceId = async (data: any) => {
|
export const getTaskListByProcessInstanceId = async (id: string) => {
|
||||||
return await requestClient.get('/bpm/task/list-by-process-instance-id', data);
|
return await requestClient.get(
|
||||||
|
`/bpm/task/list-by-process-instance-id?processInstanceId=${id}`,
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 获取所有可退回的节点 */
|
/** 获取所有可退回的节点 */
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import type { BpmProcessInstanceApi } from '#/api/bpm/processInstance';
|
import type { BpmProcessInstanceApi } from '#/api/bpm/processInstance';
|
||||||
import type { SystemUserApi } from '#/api/system/user';
|
import type { SystemUserApi } from '#/api/system/user';
|
||||||
|
|
||||||
import { nextTick, onMounted, ref } from 'vue';
|
import { nextTick, onMounted, ref, shallowRef, watch } from 'vue';
|
||||||
|
|
||||||
import { Page } from '@vben/common-ui';
|
import { Page } from '@vben/common-ui';
|
||||||
import { formatDateTime } from '@vben/utils';
|
import { formatDateTime } from '@vben/utils';
|
||||||
|
@ -39,6 +39,7 @@ import {
|
||||||
SvgBpmRunningIcon,
|
SvgBpmRunningIcon,
|
||||||
} from '#/views/bpm/processInstance/detail/modules/icons';
|
} from '#/views/bpm/processInstance/detail/modules/icons';
|
||||||
|
|
||||||
|
import BpmProcessInstanceTaskList from './modules/task-list.vue';
|
||||||
import ProcessInstanceTimeline from './modules/time-line.vue';
|
import ProcessInstanceTimeline from './modules/time-line.vue';
|
||||||
|
|
||||||
defineOptions({ name: 'BpmProcessInstanceDetail' });
|
defineOptions({ name: 'BpmProcessInstanceDetail' });
|
||||||
|
@ -99,7 +100,7 @@ const detailForm = ref({
|
||||||
const writableFields: Array<string> = []; // 表单可以编辑的字段
|
const writableFields: Array<string> = []; // 表单可以编辑的字段
|
||||||
|
|
||||||
/** 加载流程实例 */
|
/** 加载流程实例 */
|
||||||
const BusinessFormComponent = ref<any>(null); // 异步组件
|
const BusinessFormComponent = shallowRef<any>(null); // 异步组件
|
||||||
|
|
||||||
/** 获取详情 */
|
/** 获取详情 */
|
||||||
async function getDetail() {
|
async function getDetail() {
|
||||||
|
@ -221,6 +222,20 @@ const setFieldPermission = (field: string, permission: string) => {
|
||||||
|
|
||||||
/** 当前的Tab */
|
/** 当前的Tab */
|
||||||
const activeTab = ref('form');
|
const activeTab = ref('form');
|
||||||
|
const taskListRef = ref();
|
||||||
|
|
||||||
|
// 监听 Tab 切换,当切换到 "record" 标签时刷新任务列表
|
||||||
|
watch(
|
||||||
|
() => activeTab.value,
|
||||||
|
(newVal) => {
|
||||||
|
if (newVal === 'record') {
|
||||||
|
// 如果切换到流转记录标签,刷新任务列表
|
||||||
|
nextTick(() => {
|
||||||
|
taskListRef.value?.refresh();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
/** 初始化 */
|
/** 初始化 */
|
||||||
const userOptions = ref<SystemUserApi.User[]>([]); // 用户列表
|
const userOptions = ref<SystemUserApi.User[]>([]); // 用户列表
|
||||||
|
@ -332,7 +347,13 @@ onMounted(async () => {
|
||||||
</TabPane>
|
</TabPane>
|
||||||
|
|
||||||
<TabPane tab="流转记录" key="record">
|
<TabPane tab="流转记录" key="record">
|
||||||
<div>待开发</div>
|
<div class="h-full">
|
||||||
|
<BpmProcessInstanceTaskList
|
||||||
|
ref="taskListRef"
|
||||||
|
:loading="processInstanceLoading"
|
||||||
|
:id="id"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</TabPane>
|
</TabPane>
|
||||||
|
|
||||||
<!-- TODO 待开发 -->
|
<!-- TODO 待开发 -->
|
||||||
|
|
|
@ -0,0 +1,222 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import type { formCreate } from '@form-create/antd-designer';
|
||||||
|
|
||||||
|
import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
|
||||||
|
|
||||||
|
import type { BpmTaskApi } from '#/api/bpm/task';
|
||||||
|
|
||||||
|
import { nextTick, onMounted, ref, shallowRef } from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
|
import { Button } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import { useVbenVxeGrid } from '#/adapter/vxe-table';
|
||||||
|
import { getTaskListByProcessInstanceId } from '#/api/bpm/task';
|
||||||
|
import { DICT_TYPE, formatPast2, setConfAndFields2 } from '#/utils';
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'BpmProcessInstanceTaskList',
|
||||||
|
});
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: string;
|
||||||
|
loading: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
// 使用shallowRef减少不必要的深度响应
|
||||||
|
const columns = shallowRef([
|
||||||
|
{
|
||||||
|
field: 'name',
|
||||||
|
title: '审批节点',
|
||||||
|
minWidth: 150,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'approver',
|
||||||
|
title: '审批人',
|
||||||
|
slots: {
|
||||||
|
default: ({ row }: { row: BpmTaskApi.TaskManagerVO }) => {
|
||||||
|
return row.assigneeUser?.nickname || row.ownerUser?.nickname;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
minWidth: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'createTime',
|
||||||
|
title: '开始时间',
|
||||||
|
formatter: 'formatDateTime',
|
||||||
|
minWidth: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'endTime',
|
||||||
|
title: '结束时间',
|
||||||
|
formatter: 'formatDateTime',
|
||||||
|
minWidth: 180,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'status',
|
||||||
|
title: '审批状态',
|
||||||
|
minWidth: 150,
|
||||||
|
cellRender: {
|
||||||
|
name: 'CellDict',
|
||||||
|
props: { type: DICT_TYPE.BPM_TASK_STATUS },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'reason',
|
||||||
|
title: '审批建议',
|
||||||
|
slots: {
|
||||||
|
default: 'slot-reason',
|
||||||
|
},
|
||||||
|
minWidth: 200,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'durationInMillis',
|
||||||
|
title: '耗时',
|
||||||
|
minWidth: 180,
|
||||||
|
slots: {
|
||||||
|
default: ({ row }: { row: BpmTaskApi.TaskManagerVO }) => {
|
||||||
|
return formatPast2(row.durationInMillis);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Grid配置和API
|
||||||
|
const [Grid, gridApi] = useVbenVxeGrid({
|
||||||
|
gridOptions: {
|
||||||
|
columns: columns.value,
|
||||||
|
keepSource: true,
|
||||||
|
showFooter: true,
|
||||||
|
border: true,
|
||||||
|
height: 'auto',
|
||||||
|
proxyConfig: {
|
||||||
|
ajax: {
|
||||||
|
query: async () => {
|
||||||
|
return await getTaskListByProcessInstanceId(props.id);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rowConfig: {
|
||||||
|
keyField: 'id',
|
||||||
|
},
|
||||||
|
pagerConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
toolbarConfig: {
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
cellConfig: {
|
||||||
|
height: 60,
|
||||||
|
},
|
||||||
|
} as VxeTableGridOptions<BpmTaskApi.TaskVO>,
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新表格数据
|
||||||
|
*/
|
||||||
|
const refresh = (): void => {
|
||||||
|
gridApi.query();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 表单相关
|
||||||
|
interface TaskForm {
|
||||||
|
rule: any[];
|
||||||
|
option: Record<string, any>;
|
||||||
|
value: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定义表单组件引用类型
|
||||||
|
|
||||||
|
// 使用明确的类型定义
|
||||||
|
const formRef = ref<formCreate>();
|
||||||
|
const taskForm = ref<TaskForm>({
|
||||||
|
rule: [],
|
||||||
|
option: {},
|
||||||
|
value: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示表单详情
|
||||||
|
* @param row 任务数据
|
||||||
|
*/
|
||||||
|
async function showFormDetail(row: BpmTaskApi.TaskManagerVO): Promise<void> {
|
||||||
|
// 设置表单配置和表单字段
|
||||||
|
taskForm.value = {
|
||||||
|
rule: [],
|
||||||
|
option: {},
|
||||||
|
value: row,
|
||||||
|
};
|
||||||
|
|
||||||
|
setConfAndFields2(
|
||||||
|
taskForm,
|
||||||
|
row.formConf,
|
||||||
|
row.formFields || [],
|
||||||
|
row.formVariables || {},
|
||||||
|
);
|
||||||
|
|
||||||
|
// 打开弹窗
|
||||||
|
modalApi.open();
|
||||||
|
|
||||||
|
// 等待表单渲染
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// 获取表单API实例
|
||||||
|
const formApi = formRef.value?.fapi;
|
||||||
|
if (!formApi) return;
|
||||||
|
|
||||||
|
// 设置表单不可编辑
|
||||||
|
formApi.btn.show(false);
|
||||||
|
formApi.resetBtn.show(false);
|
||||||
|
formApi.disabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 表单查看模态框
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
title: '查看表单',
|
||||||
|
footer: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
refresh();
|
||||||
|
});
|
||||||
|
|
||||||
|
// 暴露刷新方法给父组件
|
||||||
|
defineExpose({
|
||||||
|
refresh,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex h-full flex-col">
|
||||||
|
<Grid>
|
||||||
|
<template #slot-reason="{ row }">
|
||||||
|
<div class="flex flex-wrap items-center justify-center">
|
||||||
|
<span v-if="row.reason">{{ row.reason }}</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
v-if="row.formId > 0"
|
||||||
|
type="primary"
|
||||||
|
@click="showFormDetail(row)"`
|
||||||
|
size="small"
|
||||||
|
ghost
|
||||||
|
class="ml-1"
|
||||||
|
>
|
||||||
|
<IconifyIcon icon="ep:document" />
|
||||||
|
<span class="!ml-[2px] text-[12px]">查看表单</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Grid>
|
||||||
|
<Modal class="w-[800px]">
|
||||||
|
<form-create
|
||||||
|
ref="formRef"
|
||||||
|
v-model="taskForm.value"
|
||||||
|
:option="taskForm.option"
|
||||||
|
:rule="taskForm.rule"
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
</template>
|
Loading…
Reference in New Issue