mirror of
https://gitee.com/yudaocode/yudao-ui-admin-vben.git
synced 2025-12-30 02:22:25 +00:00
feat: [bpm][ele] bpm 迁移优化
This commit is contained in:
@@ -8,26 +8,15 @@ export namespace BpmTaskApi {
|
||||
/** 流程任务 */
|
||||
export interface Task {
|
||||
id: number; // 编号
|
||||
name: string; // 监听器名字
|
||||
type: string; // 监听器类型
|
||||
status: number; // 监听器状态
|
||||
event: string; // 监听事件
|
||||
valueType: string; // 监听器值类型
|
||||
processInstance?: BpmProcessInstanceApi.ProcessInstance; // 流程实例
|
||||
}
|
||||
|
||||
// 流程任务
|
||||
export interface TaskManager {
|
||||
id: string; // 编号
|
||||
name: string; // 任务名称
|
||||
name: string; // 任务名字
|
||||
status: number; // 任务状态
|
||||
createTime: number; // 创建时间
|
||||
endTime: number; // 结束时间
|
||||
durationInMillis: number; // 持续时间
|
||||
status: number; // 状态
|
||||
reason: string; // 原因
|
||||
reason: string; // 审批理由
|
||||
ownerUser: any; // 负责人
|
||||
assigneeUser: any; // 处理人
|
||||
taskDefinitionKey: string; // 任务定义key
|
||||
taskDefinitionKey: string; // 任务定义的标识
|
||||
processInstanceId: string; // 流程实例id
|
||||
processInstance: BpmProcessInstanceApi.ProcessInstance; // 流程实例
|
||||
parentTaskId: any; // 父任务id
|
||||
|
||||
@@ -9,24 +9,6 @@ const routes: RouteRecordRaw[] = [
|
||||
hideInMenu: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'task',
|
||||
name: 'BpmTask',
|
||||
meta: {
|
||||
title: '审批中心',
|
||||
icon: 'ant-design:history-outlined',
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'my',
|
||||
name: 'BpmTaskMy',
|
||||
component: () => import('#/views/bpm/processInstance/index.vue'),
|
||||
meta: {
|
||||
title: '我的流程',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: 'process-instance/detail',
|
||||
component: () => import('#/views/bpm/processInstance/detail/index.vue'),
|
||||
|
||||
@@ -259,6 +259,7 @@ async function validateAllSteps() {
|
||||
return true;
|
||||
}
|
||||
|
||||
const saveLoading = ref<boolean>(false);
|
||||
/** 保存操作 */
|
||||
async function handleSave() {
|
||||
try {
|
||||
@@ -272,7 +273,7 @@ async function handleSave() {
|
||||
const modelData = {
|
||||
...formData.value,
|
||||
};
|
||||
|
||||
saveLoading.value = true;
|
||||
switch (actionType) {
|
||||
case 'copy': {
|
||||
// 情况三:复制场景
|
||||
@@ -309,9 +310,12 @@ async function handleSave() {
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('保存失败:', error);
|
||||
} finally {
|
||||
saveLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 发布加载中状态
|
||||
const deployLoading = ref<boolean>(false);
|
||||
/** 发布操作 */
|
||||
async function handleDeploy() {
|
||||
try {
|
||||
@@ -322,6 +326,8 @@ async function handleDeploy() {
|
||||
// 1.2 校验所有步骤
|
||||
await validateAllSteps();
|
||||
|
||||
deployLoading.value = true;
|
||||
|
||||
// 2.1 更新表单数据
|
||||
const modelData = {
|
||||
...formData.value,
|
||||
@@ -342,6 +348,8 @@ async function handleDeploy() {
|
||||
} catch (error: any) {
|
||||
console.error('发布失败:', error);
|
||||
ElMessage.warning(error.message || '发布失败');
|
||||
} finally {
|
||||
deployLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,11 +456,12 @@ onBeforeUnmount(() => {
|
||||
<ElButton
|
||||
v-if="actionType === 'update'"
|
||||
type="primary"
|
||||
:loading="deployLoading"
|
||||
@click="handleDeploy"
|
||||
>
|
||||
发 布
|
||||
</ElButton>
|
||||
<ElButton type="primary" @click="handleSave">
|
||||
<ElButton type="primary" @click="handleSave" :loading="saveLoading">
|
||||
<span v-if="actionType === 'definition'">恢 复</span>
|
||||
<span v-else>保 存</span>
|
||||
</ElButton>
|
||||
|
||||
@@ -234,9 +234,10 @@ onMounted(() => {
|
||||
>
|
||||
<ElCard
|
||||
shadow="hover"
|
||||
class="definition-item-card w-full cursor-pointer"
|
||||
class="w-full cursor-pointer"
|
||||
:class="{
|
||||
'search-match': searchName.trim().length > 0,
|
||||
'animate-bounce-once !bg-[rgb(63_115_247_/_10%)]':
|
||||
searchName.trim().length > 0,
|
||||
}"
|
||||
:body-style="{
|
||||
width: '100%',
|
||||
@@ -247,10 +248,13 @@ onMounted(() => {
|
||||
<img
|
||||
v-if="definition.icon"
|
||||
:src="definition.icon"
|
||||
class="flow-icon-img object-contain"
|
||||
class="size-12 rounded object-contain"
|
||||
alt="流程图标"
|
||||
/>
|
||||
<div v-else class="flow-icon flex-shrink-0">
|
||||
<div
|
||||
v-else
|
||||
class="flex size-12 flex-shrink-0 items-center justify-center rounded bg-primary"
|
||||
>
|
||||
<span class="text-xs text-white">
|
||||
{{ definition.name?.slice(0, 2) }}
|
||||
</span>
|
||||
@@ -301,31 +305,8 @@ onMounted(() => {
|
||||
}
|
||||
}
|
||||
|
||||
.process-definition-container {
|
||||
.definition-item-card {
|
||||
.flow-icon-img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.flow-icon {
|
||||
@apply bg-primary;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
&.search-match {
|
||||
background-color: rgb(63 115 247 / 10%);
|
||||
border: 1px solid var(--primary);
|
||||
animation: bounce 0.5s ease;
|
||||
}
|
||||
}
|
||||
.animate-bounce-once {
|
||||
animation: bounce 0.5s ease;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__content) {
|
||||
|
||||
@@ -112,7 +112,7 @@ async function submitForm() {
|
||||
// 关闭并提示
|
||||
ElMessage.success('发起流程成功');
|
||||
await closeCurrentTab();
|
||||
await router.push({ name: 'BpmTaskMy' });
|
||||
await router.push({ name: 'BpmProcessInstanceMy' });
|
||||
} finally {
|
||||
processInstanceStartLoading.value = false;
|
||||
}
|
||||
|
||||
@@ -220,17 +220,22 @@ watch(
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const loading = ref(false);
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
await getDetail();
|
||||
// 获得用户列表
|
||||
userOptions.value = await getSimpleUserList();
|
||||
loading.value = true;
|
||||
try {
|
||||
await getDetail();
|
||||
// 获得用户列表
|
||||
userOptions.value = await getSimpleUserList();
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Page auto-content-height>
|
||||
<Page auto-content-height v-loading="loading">
|
||||
<ElCard
|
||||
class="flex h-full flex-col"
|
||||
:body-style="{
|
||||
|
||||
@@ -275,7 +275,7 @@ async function openPopover(type: string) {
|
||||
}
|
||||
}
|
||||
Object.keys(popOverVisible.value).forEach((item) => {
|
||||
if (popOverVisible.value[item]) popOverVisible.value[item] = item === type;
|
||||
popOverVisible.value[item] = item === type;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -704,14 +704,6 @@ function handleSignFinish(url: string) {
|
||||
approveFormRef.value?.validateField('signPicUrl');
|
||||
}
|
||||
|
||||
/** 处理弹窗可见性 */
|
||||
function handlePopoverVisible(visible: boolean) {
|
||||
if (!visible) {
|
||||
// 拦截关闭事件
|
||||
popOverVisible.value.approve = true;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ loadTodoTask });
|
||||
</script>
|
||||
<template>
|
||||
@@ -720,11 +712,10 @@ defineExpose({ loadTodoTask });
|
||||
<!-- z-index 设置为300 避免覆盖签名弹窗 -->
|
||||
<ElSpace size="default">
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.approve"
|
||||
:visible="popOverVisible.approve"
|
||||
placement="top"
|
||||
:popper-style="{ minWidth: '400px', zIndex: 300 }"
|
||||
trigger="click"
|
||||
@open-change="handlePopoverVisible"
|
||||
v-if="
|
||||
runningTask &&
|
||||
isHandleTaskStatus() &&
|
||||
@@ -825,7 +816,7 @@ defineExpose({ loadTodoTask });
|
||||
|
||||
<!-- 【拒绝】按钮 -->
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.reject"
|
||||
:visible="popOverVisible.reject"
|
||||
placement="top"
|
||||
:popper-style="{ minWidth: '400px' }"
|
||||
trigger="click"
|
||||
@@ -885,7 +876,7 @@ defineExpose({ loadTodoTask });
|
||||
|
||||
<!-- 【抄送】按钮 -->
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.copy"
|
||||
:visible="popOverVisible.copy"
|
||||
placement="top"
|
||||
:popper-style="{ width: '400px' }"
|
||||
trigger="click"
|
||||
@@ -960,7 +951,7 @@ defineExpose({ loadTodoTask });
|
||||
|
||||
<!-- 【转办】按钮 -->
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.transfer"
|
||||
:visible="popOverVisible.transfer"
|
||||
placement="top"
|
||||
:popper-style="{ width: '400px' }"
|
||||
trigger="click"
|
||||
@@ -1036,7 +1027,7 @@ defineExpose({ loadTodoTask });
|
||||
|
||||
<!-- 【委派】按钮 -->
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.delegate"
|
||||
:visible="popOverVisible.delegate"
|
||||
placement="top"
|
||||
:popper-style="{ width: '400px' }"
|
||||
trigger="click"
|
||||
@@ -1112,7 +1103,7 @@ defineExpose({ loadTodoTask });
|
||||
|
||||
<!-- 【加签】按钮 当前任务审批人为A,向前加签选了一个C,则需要C先审批,然后再是A审批,向后加签B,A审批完,需要B再审批完,才算完成这个任务节点 -->
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.addSign"
|
||||
:visible="popOverVisible.addSign"
|
||||
placement="top"
|
||||
:popper-style="{ width: '400px' }"
|
||||
trigger="click"
|
||||
@@ -1200,7 +1191,7 @@ defineExpose({ loadTodoTask });
|
||||
|
||||
<!-- 【减签】按钮 -->
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.deleteSign"
|
||||
:visible="popOverVisible.deleteSign"
|
||||
placement="top"
|
||||
:popper-style="{ width: '400px' }"
|
||||
trigger="click"
|
||||
@@ -1268,7 +1259,7 @@ defineExpose({ loadTodoTask });
|
||||
|
||||
<!-- 【退回】按钮 -->
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.return"
|
||||
:visible="popOverVisible.return"
|
||||
placement="top"
|
||||
:popper-style="{ width: '400px' }"
|
||||
trigger="click"
|
||||
@@ -1342,7 +1333,7 @@ defineExpose({ loadTodoTask });
|
||||
|
||||
<!--【取消】按钮 这个对应发起人的取消, 只有发起人可以取消 -->
|
||||
<ElPopover
|
||||
v-model:visible="popOverVisible.cancel"
|
||||
:visible="popOverVisible.cancel"
|
||||
placement="top"
|
||||
:popper-style="{ width: '460px' }"
|
||||
trigger="click"
|
||||
|
||||
@@ -35,30 +35,30 @@ const [Modal, modalApi] = useVbenModal({
|
||||
|
||||
<template>
|
||||
<Modal title="流程签名" class="w-3/5">
|
||||
<div class="mb-2 flex justify-end">
|
||||
<ElSpace>
|
||||
<div class="flex h-[50vh] flex-col">
|
||||
<div class="mb-2 flex justify-end">
|
||||
<ElTooltip content="撤销上一步操作">
|
||||
<ElButton @click="signature?.undo()">
|
||||
<ElButton @click="signature?.undo()" size="small">
|
||||
<template #icon>
|
||||
<IconifyIcon icon="lucide:undo" class="mb-1 size-4" />
|
||||
<IconifyIcon icon="lucide:undo" class="size-4" />
|
||||
</template>
|
||||
撤销
|
||||
</ElButton>
|
||||
</ElTooltip>
|
||||
<ElTooltip content="清空画布">
|
||||
<ElButton @click="signature?.clear()">
|
||||
<ElButton @click="signature?.clear()" size="small">
|
||||
<template #icon>
|
||||
<IconifyIcon icon="lucide:trash" class="mb-1 size-4" />
|
||||
<IconifyIcon icon="lucide:trash" class="size-4" />
|
||||
</template>
|
||||
<span>清除</span>
|
||||
</ElButton>
|
||||
</ElTooltip>
|
||||
</ElSpace>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Vue3Signature
|
||||
class="mx-auto !h-80 border border-solid border-gray-300"
|
||||
ref="signature"
|
||||
/>
|
||||
<Vue3Signature
|
||||
class="h-full flex-1 border border-solid border-gray-300"
|
||||
ref="signature"
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
@@ -42,7 +42,7 @@ function useGridColumns(): VxeTableGridOptions['columns'] {
|
||||
field: 'approver',
|
||||
title: '审批人',
|
||||
slots: {
|
||||
default: ({ row }: { row: BpmTaskApi.TaskManager }) => {
|
||||
default: ({ row }: { row: BpmTaskApi.Task }) => {
|
||||
return row.assigneeUser?.nickname || row.ownerUser?.nickname;
|
||||
},
|
||||
},
|
||||
@@ -104,7 +104,7 @@ function handleRefresh() {
|
||||
}
|
||||
|
||||
/** 显示表单详情 */
|
||||
async function handleShowFormDetail(row: BpmTaskApi.TaskManager) {
|
||||
async function handleShowFormDetail(row: BpmTaskApi.Task) {
|
||||
// 设置表单配置和表单字段
|
||||
taskForm.value = {
|
||||
rule: [],
|
||||
@@ -156,7 +156,7 @@ const [Grid, gridApi] = useVbenVxeGrid({
|
||||
toolbarConfig: {
|
||||
enabled: false,
|
||||
},
|
||||
} as VxeTableGridOptions<BpmTaskApi.TaskManager>,
|
||||
} as VxeTableGridOptions<BpmTaskApi.Task>,
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
@@ -186,7 +186,7 @@ defineExpose({
|
||||
</template>
|
||||
</Grid>
|
||||
</div>
|
||||
<Modal class="w-[800px]">
|
||||
<Modal class="w-3/5">
|
||||
<FormCreate
|
||||
ref="formRef"
|
||||
v-model="taskForm.value"
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useGridColumns, useGridFormSchema } from './data';
|
||||
defineOptions({ name: 'BpmManagerTask' });
|
||||
|
||||
/** 查看历史 */
|
||||
function handleHistory(row: BpmTaskApi.TaskManager) {
|
||||
function handleHistory(row: BpmTaskApi.Task) {
|
||||
router.push({
|
||||
name: 'BpmProcessInstanceDetail',
|
||||
query: {
|
||||
|
||||
Reference in New Issue
Block a user