feat: 完成 R17-4 试点观测支撑

这个提交包含在:
2026-03-21 22:04:30 +08:00
父节点 736c803d19
当前提交 5e9ef9cab2
共修改 9 个文件,包含 169 行新增和 12 行删除
+15
查看文件
@@ -29,6 +29,21 @@ export type PortalHomePayload = {
weeklySummary: { weekStart: string; submittedCount: number; missingCount: number; needsHelpCount: number; href: string } | null;
todoSummary: { openCount: number; highPriorityCount: number; href: string } | null;
peopleLifecycle: { onboardingCount: number; offboardingCount: number; assetReturnPendingCount: number; href: string } | null;
adoptionSummary:
| {
activeEmployeeCount: number;
login7dCount: number;
weeklySubmittedCount: number;
weeklyMissingCount: number;
presenceUpdatedCount: number;
presenceMissingCount: number;
announcementCount: number;
login7dRate: number;
weeklySubmissionRate: number;
presenceCoverageRate: number;
hints: string[];
}
| null;
};
export async function fetchPortalHome() {
+35
查看文件
@@ -131,6 +131,41 @@ export function PortalHomePage() {
</div>
</div>
{payload.adoptionSummary ? (
<div className="card-std space-y-3 p-6 xl:col-span-2">
<div className="flex items-center justify-between gap-3">
<h3 className="text-base font-semibold text-zinc-900">试点观测摘要</h3>
<Link to="/system/workspace" className="text-sm text-primary hover:underline">查看工作区设置</Link>
</div>
<div className="grid gap-3 md:grid-cols-2 xl:grid-cols-4 text-sm">
<div className="rounded-lg border border-zinc-200 px-3 py-3">
近 7 天登录:<span className="font-medium text-zinc-900">{payload.adoptionSummary.login7dCount}/{payload.adoptionSummary.activeEmployeeCount}</span>
<div className="mt-1 text-xs text-zinc-500">覆盖率 {payload.adoptionSummary.login7dRate}%</div>
</div>
<div className="rounded-lg border border-zinc-200 px-3 py-3">
本周周报:<span className="font-medium text-zinc-900">已交 {payload.adoptionSummary.weeklySubmittedCount}</span>
<div className="mt-1 text-xs text-zinc-500">提交率 {payload.adoptionSummary.weeklySubmissionRate}%</div>
</div>
<div className="rounded-lg border border-zinc-200 px-3 py-3">
今日状态:<span className="font-medium text-zinc-900">已更新 {payload.adoptionSummary.presenceUpdatedCount}</span>
<div className="mt-1 text-xs text-zinc-500">覆盖率 {payload.adoptionSummary.presenceCoverageRate}%</div>
</div>
<div className="rounded-lg border border-zinc-200 px-3 py-3">
当前公告:<span className="font-medium text-zinc-900">{payload.adoptionSummary.announcementCount}</span>
<div className="mt-1 text-xs text-zinc-500">用于试点期统一通知</div>
</div>
</div>
<div className="rounded-lg border border-zinc-200 bg-zinc-50 px-4 py-3 text-sm">
<div className="font-medium text-zinc-900">本周观测提示</div>
<ul className="mt-2 space-y-1 text-zinc-600 list-disc pl-5">
{payload.adoptionSummary.hints.map((hint) => (
<li key={hint}>{hint}</li>
))}
</ul>
</div>
</div>
) : null}
<div className="card-std space-y-3 p-6">
<h3 className="text-base font-semibold text-zinc-900">工作台摘要</h3>
<div className="space-y-3 text-sm">