feat(workbench): 添加待确认tab并调整绩效管理页面标题

This commit is contained in:
dk
2026-07-19 15:02:55 +08:00
parent 7f31bed6f6
commit c2f9c922cf
4 changed files with 65 additions and 18 deletions

View File

@@ -375,7 +375,7 @@
"name": "personal-center_my-performance", "name": "personal-center_my-performance",
"path": "/personal-center/my-performance", "path": "/personal-center/my-performance",
"component": "view.personal-center_my-performance", "component": "view.personal-center_my-performance",
"title": "我的绩效", "title": "绩效管理",
"routeTitle": "personal-center_my-performance", "routeTitle": "personal-center_my-performance",
"i18nKey": "route.personal-center_my-performance", "i18nKey": "route.personal-center_my-performance",
"icon": "mdi:trophy-outline", "icon": "mdi:trophy-outline",
@@ -389,7 +389,7 @@
"redirect": null, "redirect": null,
"props": null, "props": null,
"meta": { "meta": {
"title": "我的绩效", "title": "绩效管理",
"i18nKey": "route.personal-center_my-performance", "i18nKey": "route.personal-center_my-performance",
"icon": "mdi:trophy-outline", "icon": "mdi:trophy-outline",
"localIcon": null, "localIcon": null,

View File

@@ -173,7 +173,7 @@ const local: App.I18n.Schema = {
'personal-center_work-report_weekly': '个人周报', 'personal-center_work-report_weekly': '个人周报',
'personal-center_work-report_monthly': '个人月报', 'personal-center_work-report_monthly': '个人月报',
'personal-center_work-report_project': '项目半月报', 'personal-center_work-report_project': '项目半月报',
'personal-center_my-performance': '我的绩效', 'personal-center_my-performance': '绩效管理',
'personal-center_my-application': '我的申请', 'personal-center_my-application': '我的申请',
'personal-center_overtime-application': '业务学习', 'personal-center_overtime-application': '业务学习',
'personal-center_pending-approval': '待我审批', 'personal-center_pending-approval': '待我审批',

View File

@@ -1,6 +1,6 @@
import dayjs from 'dayjs'; import dayjs from 'dayjs';
export type WorkbenchTodoCategory = 'task' | 'ticket' | 'personal' | 'approval'; export type WorkbenchTodoCategory = 'task' | 'ticket' | 'personal' | 'approval' | 'confirm';
export type WorkbenchTodoMainTab = 'all' | WorkbenchTodoCategory; export type WorkbenchTodoMainTab = 'all' | WorkbenchTodoCategory;
@@ -68,7 +68,8 @@ const todoCategoryMeta: Record<
task: { label: '任务', tone: 'emerald', icon: 'mdi:checkbox-marked-circle-outline' }, task: { label: '任务', tone: 'emerald', icon: 'mdi:checkbox-marked-circle-outline' },
ticket: { label: '工单', tone: 'amber', icon: 'mdi:ticket-confirmation-outline' }, ticket: { label: '工单', tone: 'amber', icon: 'mdi:ticket-confirmation-outline' },
personal: { label: '我的事项', tone: 'violet', icon: 'mdi:notebook-edit-outline' }, personal: { label: '我的事项', tone: 'violet', icon: 'mdi:notebook-edit-outline' },
approval: { label: '待审批', tone: 'sky', icon: 'mdi:checkbox-multiple-marked-outline' } approval: { label: '待审批', tone: 'sky', icon: 'mdi:checkbox-multiple-marked-outline' },
confirm: { label: '待确认', tone: 'rose', icon: 'mdi:clipboard-check-outline' }
}; };
const todoPriorityWeight: Record<WorkbenchTodoPriority, number> = { const todoPriorityWeight: Record<WorkbenchTodoPriority, number> = {

View File

@@ -131,7 +131,8 @@ const mainTabs: Array<{ key: WorkbenchTodoMainTab; label: string }> = [
{ key: 'task', label: '任务' }, { key: 'task', label: '任务' },
{ key: 'ticket', label: '工单' }, { key: 'ticket', label: '工单' },
{ key: 'personal', label: '我的事项' }, { key: 'personal', label: '我的事项' },
{ key: 'approval', label: '待审批' } { key: 'approval', label: '待审批' },
{ key: 'confirm', label: '待确认' }
]; ];
const deadlineFilters: Array<{ key: Exclude<WorkbenchTodoDeadlineFilter, null>; label: string }> = [ const deadlineFilters: Array<{ key: Exclude<WorkbenchTodoDeadlineFilter, null>; label: string }> = [
@@ -144,9 +145,11 @@ const approvalBizTabs: Array<{ key: ApprovalBizType; label: string }> = [
{ key: 'weekly', label: '周报' }, { key: 'weekly', label: '周报' },
{ key: 'monthly', label: '月报' }, { key: 'monthly', label: '月报' },
{ key: 'project', label: '项目半月报' }, { key: 'project', label: '项目半月报' },
{ key: 'performance', label: '我的绩效' },
{ key: 'overtime_application', label: '业务学习' } { key: 'overtime_application', label: '业务学习' }
]; ];
const confirmBizTabs: Array<{ key: Extract<ApprovalBizType, 'performance'>; label: string }> = [
{ key: 'performance', label: '绩效表' }
];
const hasWorkReportApprovePermission = computed(() => hasButtonPermission('project:work-report:approve')); const hasWorkReportApprovePermission = computed(() => hasButtonPermission('project:work-report:approve'));
const hasOvertimeApprovePermission = computed(() => hasButtonPermission('project:overtime-application:approve')); const hasOvertimeApprovePermission = computed(() => hasButtonPermission('project:overtime-application:approve'));
@@ -154,6 +157,14 @@ const hasPerformanceApprovePermission = computed(
() => () =>
hasButtonPermission(PerformancePermission.SheetConfirm) && hasButtonPermission(PerformancePermission.SheetReject) hasButtonPermission(PerformancePermission.SheetConfirm) && hasButtonPermission(PerformancePermission.SheetReject)
); );
const visibleMainTabs = computed(() =>
mainTabs.filter(tab => {
if (tab.key === 'confirm') {
return hasPerformanceApprovePermission.value;
}
return true;
})
);
const visibleApprovalBizTabs = computed(() => const visibleApprovalBizTabs = computed(() =>
approvalBizTabs.filter(tab => { approvalBizTabs.filter(tab => {
if (tab.key === 'performance') { if (tab.key === 'performance') {
@@ -167,6 +178,7 @@ const visibleApprovalBizTabs = computed(() =>
return hasWorkReportApprovePermission.value; return hasWorkReportApprovePermission.value;
}) })
); );
const visibleConfirmBizTabs = computed(() => (hasPerformanceApprovePermission.value ? confirmBizTabs : []));
const myTaskItems = ref<WorkbenchTodoItem[]>([]); const myTaskItems = ref<WorkbenchTodoItem[]>([]);
// 保留任务原始行,供操作图标按 availableActions 渲染并取 projectId / executionId 调状态变更接口 // 保留任务原始行,供操作图标按 availableActions 渲染并取 projectId / executionId 调状态变更接口
@@ -233,7 +245,7 @@ function getApprovalCategoryLabel(bizType: ApprovalBizType) {
if (bizType === 'weekly') return '周报'; if (bizType === 'weekly') return '周报';
if (bizType === 'monthly') return '月报'; if (bizType === 'monthly') return '月报';
if (bizType === 'project') return '项目半月报'; if (bizType === 'project') return '项目半月报';
if (bizType === 'performance') return '我的绩效'; if (bizType === 'performance') return '绩效';
if (bizType === 'overtime_application') return '业务学习'; if (bizType === 'overtime_application') return '业务学习';
return '待审批'; return '待审批';
} }
@@ -549,7 +561,8 @@ const tabCounts = computed(() => {
task: 0, task: 0,
ticket: 0, ticket: 0,
personal: 0, personal: 0,
approval: 0 approval: 0,
confirm: 0
}; };
mergedItems.value.forEach(item => { mergedItems.value.forEach(item => {
counts[item.category] += 1; counts[item.category] += 1;
@@ -563,7 +576,8 @@ const tabOverdueCount = computed(() => {
task: 0, task: 0,
ticket: 0, ticket: 0,
personal: 0, personal: 0,
approval: 0 approval: 0,
confirm: 0
}; };
mergedItems.value.forEach(item => { mergedItems.value.forEach(item => {
if (!isWorkbenchTodoOverdue(item)) return; if (!isWorkbenchTodoOverdue(item)) return;
@@ -580,6 +594,10 @@ const filteredItems = computed(() => {
return itemsInTab.value.filter(item => item.approvalBizType === activeApprovalBizType.value); return itemsInTab.value.filter(item => item.approvalBizType === activeApprovalBizType.value);
} }
if (activeTab.value === 'confirm') {
return itemsInTab.value.filter(item => item.approvalBizType === 'performance');
}
return filterWorkbenchTodoItemsByDeadline(itemsInTab.value, activeDeadlineFilter.value); return filterWorkbenchTodoItemsByDeadline(itemsInTab.value, activeDeadlineFilter.value);
}); });
@@ -650,11 +668,26 @@ watch(
{ immediate: true } { immediate: true }
); );
watch(
visibleMainTabs,
tabs => {
if (!tabs.some(tab => tab.key === activeTab.value)) {
activeTab.value = tabs[0]?.key ?? 'all';
}
},
{ immediate: true }
);
function handleSelectTab(key: WorkbenchTodoMainTab) { function handleSelectTab(key: WorkbenchTodoMainTab) {
if (key === 'confirm' && !hasPerformanceApprovePermission.value) return;
if (activeTab.value === key) return; if (activeTab.value === key) return;
activeTab.value = key; activeTab.value = key;
if (key === 'approval') activeDeadlineFilter.value = null;
activeDeadlineFilter.value = null; activeDeadlineFilter.value = null;
if (key === 'confirm') {
activeApprovalBizType.value = 'performance';
} else if (key === 'approval' && activeApprovalBizType.value === 'performance') {
activeApprovalBizType.value = visibleApprovalBizTabs.value[0]?.key ?? 'weekly';
}
if (key !== 'task' && activeSort.value === 'priority') { if (key !== 'task' && activeSort.value === 'priority') {
activeSort.value = 'deadline'; activeSort.value = 'deadline';
} }
@@ -1015,12 +1048,12 @@ async function loadPerformanceApprovalItems() {
performanceApprovalItems.value = buildWorkbenchTodoItems( performanceApprovalItems.value = buildWorkbenchTodoItems(
data.list.map(item => ({ data.list.map(item => ({
id: `performance-${item.id}`, id: `performance-${item.id}`,
category: 'approval', category: 'confirm',
categoryLabel: '我的绩效', categoryLabel: '绩效',
title: `${item.periodMonth} 绩效待确认`, title: `${item.periodMonth} 绩效待确认`,
createdTime: item.sentTime || item.createTime || item.updateTime || '', createdTime: item.sentTime || item.createTime || item.updateTime || '',
deadline: item.sentTime || item.createTime || item.updateTime || null, deadline: item.sentTime || item.createTime || item.updateTime || null,
source: `我的绩效 · ${item.managerName || '--'}`, source: `绩效 · ${item.managerName || '--'}`,
priority: 'mid', priority: 'mid',
approvalBizType: 'performance', approvalBizType: 'performance',
approvalBizId: item.id approvalBizId: item.id
@@ -1124,7 +1157,7 @@ onActivated(refresh);
<div class="workbench-todo__tabs"> <div class="workbench-todo__tabs">
<div class="workbench-todo__tabs-group"> <div class="workbench-todo__tabs-group">
<ElTooltip <ElTooltip
v-for="tab in mainTabs" v-for="tab in visibleMainTabs"
:key="tab.key" :key="tab.key"
:content="`已逾期 ${tabOverdueCount[tab.key]} 项,建议尽快处理`" :content="`已逾期 ${tabOverdueCount[tab.key]} 项,建议尽快处理`"
:disabled="tabOverdueCount[tab.key] === 0" :disabled="tabOverdueCount[tab.key] === 0"
@@ -1151,7 +1184,7 @@ onActivated(refresh);
</div> </div>
<div class="workbench-todo__filters"> <div class="workbench-todo__filters">
<div v-if="activeTab !== 'approval'" class="workbench-todo__filters-left"> <div v-if="activeTab !== 'approval' && activeTab !== 'confirm'" class="workbench-todo__filters-left">
<button <button
v-for="filter in deadlineFilters" v-for="filter in deadlineFilters"
:key="filter.key" :key="filter.key"
@@ -1163,7 +1196,7 @@ onActivated(refresh);
{{ filter.label }} {{ filter.label }}
</button> </button>
</div> </div>
<div v-else class="workbench-todo__filters-left"> <div v-else-if="activeTab === 'approval'" class="workbench-todo__filters-left">
<button <button
v-for="tab in visibleApprovalBizTabs" v-for="tab in visibleApprovalBizTabs"
:key="tab.key" :key="tab.key"
@@ -1176,6 +1209,19 @@ onActivated(refresh);
<span class="workbench-todo__filter-count">{{ approvalBizTabCounts[tab.key] }}</span> <span class="workbench-todo__filter-count">{{ approvalBizTabCounts[tab.key] }}</span>
</button> </button>
</div> </div>
<div v-else class="workbench-todo__filters-left">
<button
v-for="tab in visibleConfirmBizTabs"
:key="tab.key"
type="button"
class="workbench-todo__filter"
:class="{ 'workbench-todo__filter--active': activeApprovalBizType === tab.key }"
@click="handleSelectApprovalBizType(tab.key)"
>
{{ tab.label }}
<span class="workbench-todo__filter-count">{{ approvalBizTabCounts[tab.key] }}</span>
</button>
</div>
<ElDropdown trigger="click" placement="bottom-end" @command="handleSelectSort"> <ElDropdown trigger="click" placement="bottom-end" @command="handleSelectSort">
<span class="workbench-todo__sort"> <span class="workbench-todo__sort">