yxk-20260610-审批历史页面
在审批历史页面增加独立开关 仅看本部门,与现有节点名称 checkbox 筛选叠加。当前登录人的部门信息从 useUserStore().getUserInfo 获取,按用户全部部门口径解析 departIds,再通过部门接口补齐部门编码和名称,用于前端本地过滤审批历史。
This commit is contained in:
@@ -278,7 +278,7 @@
|
|||||||
const feedbackBaseColumns = [
|
const feedbackBaseColumns = [
|
||||||
{ title: '责任部门名称', dataIndex: 'responDeptname', align: 'center', width: 160 },
|
{ title: '责任部门名称', dataIndex: 'responDeptname', align: 'center', width: 160 },
|
||||||
{ title: '反馈人姓名', dataIndex: 'responPersonname', align: 'center', width: 140 },
|
{ title: '反馈人姓名', dataIndex: 'responPersonname', align: 'center', width: 140 },
|
||||||
{ title: '实际执行情况', dataIndex: 'actualExect', align: 'left', width: 280 },
|
{ title: '实际执行情况', dataIndex: 'actualExect', align: 'center', width: 280 },
|
||||||
{ title: '实际完成时间', dataIndex: 'actualTime', align: 'center', width: 180 },
|
{ title: '实际完成时间', dataIndex: 'actualTime', align: 'center', width: 180 },
|
||||||
{ title: '完成状态', dataIndex: 'bpmStatus', align: 'center', width: 120, customRender: ({ record }) => record?.bpmStatus_dictText || record?.bpmStatus },
|
{ title: '完成状态', dataIndex: 'bpmStatus', align: 'center', width: 120, customRender: ({ record }) => record?.bpmStatus_dictText || record?.bpmStatus },
|
||||||
{ title: '附件', dataIndex: 'id', key: 'attachments', align: 'left', width: 340 },
|
{ title: '附件', dataIndex: 'id', key: 'attachments', align: 'left', width: 340 },
|
||||||
|
|||||||
+162
-8
@@ -1,6 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="approval-history-pane">
|
<div class="approval-history-pane">
|
||||||
<div v-if="taskNameOptions.length > 0" class="approval-history-filter">
|
<div v-if="taskNameOptions.length > 0" class="approval-history-filter">
|
||||||
|
<div class="approval-history-filter__main">
|
||||||
<span class="approval-history-filter__label">节点名称:</span>
|
<span class="approval-history-filter__label">节点名称:</span>
|
||||||
<a-checkbox-group v-model:value="selectedTaskNames" class="approval-history-filter__checkboxes" @change="handleTaskNameChange">
|
<a-checkbox-group v-model:value="selectedTaskNames" class="approval-history-filter__checkboxes" @change="handleTaskNameChange">
|
||||||
<a-checkbox v-for="taskName in taskNameOptions" :key="taskName" :value="taskName">
|
<a-checkbox v-for="taskName in taskNameOptions" :key="taskName" :value="taskName">
|
||||||
@@ -8,10 +9,17 @@
|
|||||||
</a-checkbox>
|
</a-checkbox>
|
||||||
</a-checkbox-group>
|
</a-checkbox-group>
|
||||||
<div class="approval-history-filter__actions">
|
<div class="approval-history-filter__actions">
|
||||||
<a-button type="link" size="small" :disabled="selectedTaskNames.length === taskNameOptions.length" @click="selectAllTaskNames">全选</a-button>
|
<a-button type="link" size="small" :disabled="selectedTaskNames.length === taskNameOptions.length" @click="selectAllTaskNames"
|
||||||
|
>全选</a-button
|
||||||
|
>
|
||||||
<a-button type="link" size="small" :disabled="selectedTaskNames.length === 0" @click="clearTaskNames">清空</a-button>
|
<a-button type="link" size="small" :disabled="selectedTaskNames.length === 0" @click="clearTaskNames">清空</a-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="approval-history-filter__dept">
|
||||||
|
<a-switch v-model:checked="onlyCurrentDept" :disabled="currentUserDeptList.length === 0" @change="handleCurrentDeptChange" />
|
||||||
|
<span class="approval-history-filter__dept-text">仅看本部门审批历史</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<BasicTable @register="registerTable" />
|
<BasicTable @register="registerTable" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -24,11 +32,22 @@
|
|||||||
import { BasicTable, useTable } from '/@/components/Table';
|
import { BasicTable, useTable } from '/@/components/Table';
|
||||||
import type { BasicColumn } from '/@/components/Table';
|
import type { BasicColumn } from '/@/components/Table';
|
||||||
import { onMounted, ref, watch } from 'vue';
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
import { useUserStore } from '/@/store/modules/user';
|
||||||
|
import { defHttp } from '/@/utils/http/axios';
|
||||||
import { list as queryApprovalOpinionList } from '/@/views/taskApprovalOpinion/TaskApprovalOpinion.api';
|
import { list as queryApprovalOpinionList } from '/@/views/taskApprovalOpinion/TaskApprovalOpinion.api';
|
||||||
|
|
||||||
interface ApprovalHistoryRecord {
|
interface ApprovalHistoryRecord {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
taskName?: string;
|
taskName?: string;
|
||||||
|
opDeptId?: string;
|
||||||
|
opDeptName?: string;
|
||||||
|
opDeptCode?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CurrentUserDept {
|
||||||
|
id?: string;
|
||||||
|
orgCode?: string;
|
||||||
|
departName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const approvalHistoryColumns: BasicColumn[] = [
|
const approvalHistoryColumns: BasicColumn[] = [
|
||||||
@@ -60,9 +79,17 @@
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
const userStore = useUserStore();
|
||||||
const allApprovalHistoryList = ref<ApprovalHistoryRecord[]>([]);
|
const allApprovalHistoryList = ref<ApprovalHistoryRecord[]>([]);
|
||||||
const taskNameOptions = ref<string[]>([]);
|
const taskNameOptions = ref<string[]>([]);
|
||||||
const selectedTaskNames = ref<string[]>([]);
|
const selectedTaskNames = ref<string[]>([]);
|
||||||
|
const onlyCurrentDept = ref(false);
|
||||||
|
const currentUserDeptList = ref<CurrentUserDept[]>([]);
|
||||||
|
const currentUserDeptIdSet = ref<Set<string>>(new Set());
|
||||||
|
const currentUserDeptCodeSet = ref<Set<string>>(new Set());
|
||||||
|
const currentUserDeptNameSet = ref<Set<string>>(new Set());
|
||||||
|
let currentUserDeptLoaded = false;
|
||||||
|
let currentUserDeptLoadPromise: Promise<void> | null = null;
|
||||||
|
|
||||||
const [registerTable, { reload, setTableData }] = useTable({
|
const [registerTable, { reload, setTableData }] = useTable({
|
||||||
title: '',
|
title: '',
|
||||||
@@ -88,6 +115,20 @@
|
|||||||
return typeof taskName === 'string' ? taskName.trim() : '';
|
return typeof taskName === 'string' ? taskName.trim() : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeText(value: unknown): string {
|
||||||
|
return typeof value === 'string' ? value.trim() : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitValue(value: unknown): string[] {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map((item) => normalizeText(item)).filter(Boolean);
|
||||||
|
}
|
||||||
|
return normalizeText(value)
|
||||||
|
.split(',')
|
||||||
|
.map((item) => item.trim())
|
||||||
|
.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
function resolveRecords(res: any): ApprovalHistoryRecord[] {
|
function resolveRecords(res: any): ApprovalHistoryRecord[] {
|
||||||
if (Array.isArray(res)) {
|
if (Array.isArray(res)) {
|
||||||
return res;
|
return res;
|
||||||
@@ -95,6 +136,13 @@
|
|||||||
return res?.records || res?.result?.records || [];
|
return res?.records || res?.result?.records || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveDeptList(res: any): CurrentUserDept[] {
|
||||||
|
if (Array.isArray(res)) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return res?.records || res?.result || [];
|
||||||
|
}
|
||||||
|
|
||||||
function resolveTotal(res: any, fallbackTotal: number): number {
|
function resolveTotal(res: any, fallbackTotal: number): number {
|
||||||
return Number(res?.total || res?.result?.total || fallbackTotal || 0);
|
return Number(res?.total || res?.result?.total || fallbackTotal || 0);
|
||||||
}
|
}
|
||||||
@@ -104,10 +152,27 @@
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
const selectedNameSet = new Set(selectedTaskNames.value);
|
const selectedNameSet = new Set(selectedTaskNames.value);
|
||||||
return allApprovalHistoryList.value.filter((record) => {
|
const nodeFilteredRecords = allApprovalHistoryList.value.filter((record) => {
|
||||||
const taskName = normalizeTaskName(record.taskName);
|
const taskName = normalizeTaskName(record.taskName);
|
||||||
return taskName && selectedNameSet.has(taskName);
|
return taskName && selectedNameSet.has(taskName);
|
||||||
});
|
});
|
||||||
|
if (!onlyCurrentDept.value) {
|
||||||
|
return nodeFilteredRecords;
|
||||||
|
}
|
||||||
|
return nodeFilteredRecords.filter(isCurrentUserDeptRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isCurrentUserDeptRecord(record: ApprovalHistoryRecord) {
|
||||||
|
const deptCode = normalizeText(record.opDeptCode);
|
||||||
|
if (deptCode) {
|
||||||
|
return currentUserDeptCodeSet.value.has(deptCode);
|
||||||
|
}
|
||||||
|
const deptId = normalizeText(record.opDeptId);
|
||||||
|
if (deptId) {
|
||||||
|
return currentUserDeptIdSet.value.has(deptId);
|
||||||
|
}
|
||||||
|
const deptName = normalizeText(record.opDeptName);
|
||||||
|
return deptName ? currentUserDeptNameSet.value.has(deptName) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetTaskNameFilter(records: ApprovalHistoryRecord[]) {
|
function resetTaskNameFilter(records: ApprovalHistoryRecord[]) {
|
||||||
@@ -116,27 +181,98 @@
|
|||||||
selectedTaskNames.value = [...taskNameOptions.value];
|
selectedTaskNames.value = [...taskNameOptions.value];
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyTaskNameFilter() {
|
function applyApprovalHistoryFilter() {
|
||||||
setTableData(getFilteredApprovalHistoryList());
|
setTableData(getFilteredApprovalHistoryList());
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleTaskNameChange(checkedValues: string[]) {
|
function handleTaskNameChange(checkedValues: string[]) {
|
||||||
selectedTaskNames.value = checkedValues;
|
selectedTaskNames.value = checkedValues;
|
||||||
applyTaskNameFilter();
|
applyApprovalHistoryFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCurrentDeptChange(checked: boolean) {
|
||||||
|
if (typeof checked === 'boolean') {
|
||||||
|
onlyCurrentDept.value = checked;
|
||||||
|
}
|
||||||
|
applyApprovalHistoryFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectAllTaskNames() {
|
function selectAllTaskNames() {
|
||||||
selectedTaskNames.value = [...taskNameOptions.value];
|
selectedTaskNames.value = [...taskNameOptions.value];
|
||||||
applyTaskNameFilter();
|
applyApprovalHistoryFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearTaskNames() {
|
function clearTaskNames() {
|
||||||
selectedTaskNames.value = [];
|
selectedTaskNames.value = [];
|
||||||
applyTaskNameFilter();
|
applyApprovalHistoryFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCurrentUserDeptList(deptList: CurrentUserDept[]) {
|
||||||
|
currentUserDeptList.value = deptList;
|
||||||
|
currentUserDeptIdSet.value = new Set(deptList.map((item) => normalizeText(item.id)).filter(Boolean));
|
||||||
|
currentUserDeptCodeSet.value = new Set(deptList.map((item) => normalizeText(item.orgCode)).filter(Boolean));
|
||||||
|
currentUserDeptNameSet.value = new Set(deptList.map((item) => normalizeText(item.departName)).filter(Boolean));
|
||||||
|
if (deptList.length === 0) {
|
||||||
|
onlyCurrentDept.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadCurrentUserDeptList() {
|
||||||
|
if (currentUserDeptLoaded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (currentUserDeptLoadPromise) {
|
||||||
|
return currentUserDeptLoadPromise;
|
||||||
|
}
|
||||||
|
currentUserDeptLoadPromise = doLoadCurrentUserDeptList()
|
||||||
|
.then(() => {
|
||||||
|
currentUserDeptLoaded = true;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
currentUserDeptLoadPromise = null;
|
||||||
|
});
|
||||||
|
return currentUserDeptLoadPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function doLoadCurrentUserDeptList() {
|
||||||
|
const userInfo = (userStore.getUserInfo || {}) as Record<string, any>;
|
||||||
|
const loginInfo = (userStore.getLoginInfo || {}) as Record<string, any>;
|
||||||
|
const departIds = splitValue(userInfo.departIds);
|
||||||
|
const fallbackDeptList = getFallbackCurrentUserDeptList(userInfo, loginInfo);
|
||||||
|
|
||||||
|
// 本部门按用户全部部门处理,优先用部门ID批量补齐编码和名称,避免只按当前登录部门筛选。
|
||||||
|
if (departIds.length > 0) {
|
||||||
|
try {
|
||||||
|
const res = await defHttp.get({ url: '/sys/sysDepart/listAll', params: { id: departIds.join(',') } });
|
||||||
|
const deptList = resolveDeptList(res);
|
||||||
|
setCurrentUserDeptList(deptList.length > 0 ? deptList : fallbackDeptList);
|
||||||
|
} catch (e) {
|
||||||
|
setCurrentUserDeptList(fallbackDeptList);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentUserDeptList(fallbackDeptList);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFallbackCurrentUserDeptList(userInfo: Record<string, any>, loginInfo: Record<string, any>) {
|
||||||
|
const loginDeparts = Array.isArray(loginInfo.departs) ? loginInfo.departs : [];
|
||||||
|
if (loginDeparts.length > 0) {
|
||||||
|
return loginDeparts;
|
||||||
|
}
|
||||||
|
|
||||||
|
const orgCode = normalizeText(userInfo.orgCode);
|
||||||
|
const departName = normalizeText(userInfo.orgCodeTxt || userInfo.departIds_dictText);
|
||||||
|
if (orgCode || departName) {
|
||||||
|
return [{ orgCode, departName }];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 按流程实例查询审批历史,只查 task_approval_opinion 表
|
// 按流程实例查询审批历史,只查 task_approval_opinion 表
|
||||||
async function getApprovalHistoryList() {
|
async function getApprovalHistoryList() {
|
||||||
|
await loadCurrentUserDeptList();
|
||||||
const processInstId = getProcessInstId();
|
const processInstId = getProcessInstId();
|
||||||
if (!processInstId) {
|
if (!processInstId) {
|
||||||
allApprovalHistoryList.value = [];
|
allApprovalHistoryList.value = [];
|
||||||
@@ -197,7 +333,10 @@
|
|||||||
reload,
|
reload,
|
||||||
taskNameOptions,
|
taskNameOptions,
|
||||||
selectedTaskNames,
|
selectedTaskNames,
|
||||||
|
onlyCurrentDept,
|
||||||
|
currentUserDeptList,
|
||||||
handleTaskNameChange,
|
handleTaskNameChange,
|
||||||
|
handleCurrentDeptChange,
|
||||||
selectAllTaskNames,
|
selectAllTaskNames,
|
||||||
clearTaskNames,
|
clearTaskNames,
|
||||||
};
|
};
|
||||||
@@ -212,11 +351,26 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.approval-history-filter {
|
.approval-history-filter {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
padding: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-history-filter__dept {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 10px;
|
||||||
|
line-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-history-filter__dept-text {
|
||||||
|
color: rgba(0, 0, 0, 0.85);
|
||||||
|
}
|
||||||
|
|
||||||
|
.approval-history-filter__main {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-bottom: 8px;
|
|
||||||
padding: 4px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.approval-history-filter__label {
|
.approval-history-filter__label {
|
||||||
|
|||||||
Reference in New Issue
Block a user