fix(approval): 待办支持全部待办开关与按任务改派、keywords 与报送人术语

- 有 approval:instance:assign 的用户可切换全租户待办(scope=all)
- 详情抽屉展示待办人员并按任务 id 改派
- 查询参数 keyword 改为 keywords;发起人统一为报送人
This commit is contained in:
2026-10-30 22:28:05 +08:00
parent bc94f04243
commit 56a2b96b3d
5 changed files with 75 additions and 16 deletions
+17 -2
View File
@@ -9,12 +9,12 @@ export interface ApprovalQueryParam extends PageParam {
// 单号
bizNo?: string;
// 关键词:单号、名称或标题、实施单位
keyword?: string;
keywords?: string;
// 报送部门id
reportOrgId?: number;
// 受理部门id
acceptOrgId?: number;
// 发起人id
// 报送人id
reporterId?: number;
// 单据状态
status?: string;
@@ -93,6 +93,18 @@ export interface ApprovalConfirm {
handleTime?: string;
}
/**
* 实例上的待办任务(PC 按任务改派)
*/
export interface ApprovalPendingTask {
id?: number;
nodeKey?: string;
nodeName?: string;
nodeType?: string;
assigneeId?: number;
assigneeName?: string;
}
/**
* 我的待处理任务
*/
@@ -144,6 +156,7 @@ export interface ApprovalInstance {
records?: ApprovalRecord[];
confirms?: ApprovalConfirm[];
myTask?: ApprovalMyTask | null;
pendingTasks?: ApprovalPendingTask[];
permissions?: Record<string, boolean>;
}
@@ -191,6 +204,8 @@ export interface ApprovalTodoParam extends PageParam {
status?: string;
// 单据类型
docType?: string;
// 查询范围:mine(默认本人待办)/all(全租户待办,需 assign 权限)
scope?: 'mine' | 'all';
// 关键词:单号、名称或标题、实施单位
keywords?: string;
}
@@ -29,7 +29,7 @@
<a-descriptions-item label="当前节点">
{{ data.currentNodeName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="发起人">
<a-descriptions-item label="报送人">
{{ data.reporterName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="报送部门">
@@ -131,7 +131,7 @@
prop:
| 'docType'
| 'bizNo'
| 'keyword'
| 'keywords'
| 'reportOrgId'
| 'acceptOrgId'
| 'reporterId'
@@ -140,10 +140,10 @@
}[] = [
{ prop: 'docType', label: '单据类型' },
{ prop: 'bizNo', label: '单号' },
{ prop: 'keyword', label: '标题或名称' },
{ prop: 'keywords', label: '标题或名称' },
{ prop: 'reportOrgId', label: '报送部门' },
{ prop: 'acceptOrgId', label: '受理部门' },
{ prop: 'reporterId', label: '发起人' },
{ prop: 'reporterId', label: '报送人' },
{ prop: 'status', label: '状态' }
];
@@ -167,7 +167,7 @@
const { form, resetFields } = useFormData<ApprovalQueryParam>({
docType: undefined,
bizNo: '',
keyword: '',
keywords: '',
reportOrgId: undefined,
acceptOrgId: undefined,
reporterId: undefined,
@@ -182,9 +182,9 @@
// 组织下拉选项
const organizationOptions = ref<{ label: string; value: number }[]>([]);
// 发起人下拉选项
// 报送人下拉选项
const userOptions = ref<{ label: string; value: number }[]>([]);
// 发起人请求状态
// 报送人请求状态
const userLoading = ref(false);
// 组织远程过滤
@@ -192,7 +192,7 @@
return (option?.label ?? '').toLowerCase().includes(input.toLowerCase());
};
// 远程搜索发起人
// 远程搜索报送人
const searchUsers = (keywords?: string) => {
userLoading.value = true;
searchApprovalUsers({ keywords })
@@ -76,7 +76,7 @@
<a-descriptions-item label="当前节点">
{{ detail.currentNodeName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="发起人">
<a-descriptions-item label="报送人">
{{ detail.reporterName }}
</a-descriptions-item>
<a-descriptions-item label="报送部门">
@@ -169,6 +169,14 @@
<a-descriptions-item label="节点">
{{ detail.currentNodeName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="待办人员">
<template v-if="pendingTasks.length">
<a-tag v-for="task in pendingTasks" :key="task.id" color="blue">
{{ task.nodeName }}·{{ task.assigneeName }}
</a-tag>
</template>
<span v-else>-</span>
</a-descriptions-item>
<a-descriptions-item label="存档确认">
<template v-if="confirms.length">
<a-tag
@@ -270,6 +278,13 @@
@ok="submitAssign"
>
<a-form layout="vertical">
<a-form-item v-if="pendingTasks.length" label="待办任务" required>
<a-select
v-model:value="assignTaskId"
:options="pendingTaskOptions"
placeholder="请选择需要改派的待办任务"
/>
</a-form-item>
<a-form-item label="改派对象" required>
<a-select
v-model:value="assignForm.targetUserId"
@@ -302,6 +317,7 @@
import type {
ApprovalAttachment,
ApprovalInstance,
ApprovalPendingTask,
ApprovalUser
} from '@/api/approval/instance/model';
import { getInstance } from '@/api/approval/instance';
@@ -346,6 +362,9 @@
);
const records = computed(() => detail.value?.records ?? []);
const confirms = computed(() => detail.value?.confirms ?? []);
const pendingTasks = computed<ApprovalPendingTask[]>(
() => detail.value?.pendingTasks ?? []
);
const load = async () => {
if (!props.instanceId) {
@@ -554,6 +573,13 @@
targetUserId: undefined,
reason: ''
});
const assignTaskId = ref<number | undefined>(undefined);
const pendingTaskOptions = computed(() =>
pendingTasks.value.map((task) => ({
value: task.id as number,
label: `${task.nodeName || task.nodeKey || ''}·${task.assigneeName || ''}`
}))
);
let searchTimer: ReturnType<typeof setTimeout> | undefined;
const doSearchUsers = async (keywords?: string) => {
@@ -585,14 +611,15 @@
const openAssign = () => {
assignForm.targetUserId = undefined;
assignForm.reason = '';
assignTaskId.value = detail.value?.myTask?.id ?? pendingTasks.value[0]?.id;
assignVisible.value = true;
doSearchUsers();
};
const submitAssign = async () => {
const taskId = detail.value?.myTask?.id;
const taskId = assignTaskId.value;
if (!taskId) {
message.error('待办任务不存在,请刷新');
message.error('请选择待办任务');
return;
}
if (!assignForm.targetUserId) {
@@ -613,8 +640,12 @@
message.success('改派成功');
assignVisible.value = false;
emit('done');
// 改派后待办不再属于当前用户,关闭抽屉
updateVisible(false);
if (detail.value?.myTask?.id === taskId) {
// 改派的是当前用户的待办,关闭抽屉回到列表
updateVisible(false);
} else {
await load();
}
} catch (e: any) {
message.error(e.message);
} finally {
+14 -1
View File
@@ -31,6 +31,13 @@
@pressEnter="reload"
@search="reload"
/>
<a-checkbox
v-if="canAssign"
v-model:checked="allScope"
@change="reload"
>
全部待办
</a-checkbox>
<a-button @click="resetSearch">重置</a-button>
</a-space>
</template>
@@ -68,6 +75,7 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import useSearch from '@/utils/use-search';
import { hasPermission } from '@/utils/permission';
import type {
ApprovalItem,
ApprovalTodoParam
@@ -82,6 +90,9 @@
const showDetail = ref(false);
// 当前单据id
const currentId = ref<number | null>(null);
// 是否查看全租户待办(仅 assign 权限)
const allScope = ref(false);
const canAssign = hasPermission('approval:instance:assign');
// 搜索条件
const { where, resetFields } = useSearch<ApprovalTodoParam>({
@@ -122,7 +133,7 @@
ellipsis: true
},
{
title: '发起人',
title: '报送人',
dataIndex: 'reporterName',
key: 'reporterName',
width: 120,
@@ -171,6 +182,7 @@
return pageApprovalTodo({
status: where.status,
keywords: where.keywords?.trim() || undefined,
scope: allScope.value ? 'all' : undefined,
page,
limit
});
@@ -184,6 +196,7 @@
// 重置搜索
const resetSearch = () => {
resetFields();
allScope.value = false;
reload();
};