AP6 增加审批催办与效率摘要
这个提交包含在:
@@ -15,6 +15,7 @@ import {
|
||||
type PortalRecentActivity,
|
||||
type PortalTeamStatusItem,
|
||||
} from "../api/portal";
|
||||
import { fetchWorkflowTaskSummary, type WorkflowTaskProductivitySummary } from "../api/workflow";
|
||||
import { isApiError } from "../api/types";
|
||||
import { useAuth } from "../auth/AuthContext";
|
||||
import { hasAnyPermission, isManagerRole } from "../auth/permissions";
|
||||
@@ -46,6 +47,15 @@ type SummaryItem = {
|
||||
tone?: "normal" | "warning";
|
||||
};
|
||||
|
||||
function workflowEntityLabel(entityType: string) {
|
||||
if (entityType === "reimbursement") return "报销";
|
||||
if (entityType === "leave") return "请假";
|
||||
if (entityType === "purchase_request") return "采购";
|
||||
if (entityType === "travel_request") return "差旅";
|
||||
if (entityType === "unknown") return "未知业务";
|
||||
return entityType;
|
||||
}
|
||||
|
||||
type TodoAggregateItem = {
|
||||
title: string;
|
||||
sourceLabel: string;
|
||||
@@ -435,6 +445,52 @@ function FinanceSummaryPanel({ summary }: { summary: PortalHomePayload["financeS
|
||||
return <SummaryPanel title="财务待处理" items={items} />;
|
||||
}
|
||||
|
||||
function ApprovalProductivityPanel({
|
||||
summary,
|
||||
title = "审批效率摘要",
|
||||
}: {
|
||||
summary: WorkflowTaskProductivitySummary | null;
|
||||
title?: string;
|
||||
}) {
|
||||
if (!summary) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const typeDistribution = summary.byEntityType
|
||||
.filter((item) => item.pendingTotal > 0)
|
||||
.map((item) => `${workflowEntityLabel(item.key)} ${item.pendingTotal}`)
|
||||
.join(" / ");
|
||||
const items: SummaryItem[] = [
|
||||
{
|
||||
key: "workflow-pending-total",
|
||||
href: "/workflow/tasks",
|
||||
label: "当前待办",
|
||||
value: `${summary.pendingTotal} 条`,
|
||||
note: summary.earliestPendingAt
|
||||
? `最早待处理:${formatRelativeTime(summary.earliestPendingAt)}`
|
||||
: "暂无待处理审批。",
|
||||
tone: summary.pendingTotal > 0 ? "warning" : "normal",
|
||||
},
|
||||
{
|
||||
key: "workflow-overdue-total",
|
||||
href: "/workflow/tasks",
|
||||
label: "超时待办",
|
||||
value: `${summary.overdueTotal} 条`,
|
||||
note: `平均等待 ${summary.averagePendingAgeHours} 小时`,
|
||||
tone: summary.overdueTotal > 0 ? "warning" : "normal",
|
||||
},
|
||||
{
|
||||
key: "workflow-entity-distribution",
|
||||
href: "/workflow/tasks",
|
||||
label: "业务分布",
|
||||
value: typeDistribution || "暂无",
|
||||
note: "按报销、请假、采购、差旅汇总。",
|
||||
},
|
||||
];
|
||||
|
||||
return <SummaryPanel title={title} items={items} />;
|
||||
}
|
||||
|
||||
function AnnouncementsList({ announcements }: { announcements: PortalHomePayload["announcements"] }) {
|
||||
const safeAnnouncements = Array.isArray(announcements) ? announcements : [];
|
||||
|
||||
@@ -875,6 +931,16 @@ export function PortalHomePage() {
|
||||
queryFn: () => fetchMyTodayAttendance(),
|
||||
retry: (failureCount, error) => !isAttendanceFeatureDisabled(error) && failureCount < 2,
|
||||
});
|
||||
const workflowSummaryQuery = useQuery({
|
||||
enabled: hasAnyPermission(permissions, APPROVAL_PORTAL_PERMISSIONS),
|
||||
queryKey: ["workflow", "tasks", "summary", "mine"],
|
||||
queryFn: () => fetchWorkflowTaskSummary(),
|
||||
});
|
||||
const workflowSystemSummaryQuery = useQuery({
|
||||
enabled: hasAnyPermission(permissions, ["system.audit.view"]),
|
||||
queryKey: ["workflow", "tasks", "summary", "system"],
|
||||
queryFn: () => fetchWorkflowTaskSummary({ scope: "system" }),
|
||||
});
|
||||
const canSetupWorkspace = hasAnyPermission(permissions, ["system.settings"]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -1281,6 +1347,15 @@ export function PortalHomePage() {
|
||||
{roleCapabilities.canApproveTasks ? (
|
||||
<SummaryPanel title="审批处理" items={approvalSummaryItems} />
|
||||
) : null}
|
||||
{roleCapabilities.canApproveTasks ? (
|
||||
<ApprovalProductivityPanel summary={workflowSummaryQuery.data ?? null} />
|
||||
) : null}
|
||||
{roleCapabilities.canManageSystem ? (
|
||||
<ApprovalProductivityPanel
|
||||
title="全局审批效率摘要"
|
||||
summary={workflowSystemSummaryQuery.data ?? null}
|
||||
/>
|
||||
) : null}
|
||||
{roleCapabilities.canUseFinance ? (
|
||||
<FinanceSummaryPanel summary={payload.financeSummary ?? null} />
|
||||
) : null}
|
||||
|
||||
在新工单中引用
屏蔽一个用户