R60 A1-A6:首页工作台优化
这个提交包含在:
@@ -11,7 +11,6 @@ function envelope(data: unknown) {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function mockMe(page: import("@playwright/test").Page, roleCodes: string[], name: string) {
|
||||
return page.route("**/api/me", async (route) => {
|
||||
await route.fulfill({
|
||||
@@ -101,6 +100,21 @@ function mockNavigation(page: import("@playwright/test").Page, mode: "employee"
|
||||
});
|
||||
}
|
||||
|
||||
function mockAttendanceToday(page: import("@playwright/test").Page) {
|
||||
return page.route("**/api/attendance/me/today", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify(envelope({
|
||||
workDate: "2026-03-22",
|
||||
needClockIn: true,
|
||||
exemptionReason: null,
|
||||
item: null,
|
||||
})),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function mockPortalHome(page: import("@playwright/test").Page, mode: "employee" | "manager") {
|
||||
return page.route("**/api/portal/home", async (route) => {
|
||||
const data = mode === "manager"
|
||||
@@ -133,6 +147,14 @@ function mockPortalHome(page: import("@playwright/test").Page, mode: "employee"
|
||||
projectSummary: { myCount: 5, overdueMilestonesCount: 2, highPriorityTaskCount: 2, openRiskCount: 1, followUpDueTodayCount: 2, closurePendingProjectCount: 1, href: "/projects" },
|
||||
peopleLifecycle: { onboardingCount: 1, offboardingCount: 0, assetReturnPendingCount: 1, href: "/people" },
|
||||
adoptionSummary: { activeEmployeeCount: 8, login7dCount: 8, weeklySubmittedCount: 6, weeklyMissingCount: 2, presenceUpdatedCount: 7, presenceMissingCount: 1, announcementCount: 1, login7dRate: 100, weeklySubmissionRate: 75, presenceCoverageRate: 87.5, hints: ["本周仍有 2 人未提交周报"] },
|
||||
recentActivities: [
|
||||
{ id: "activity-1", type: "reimbursement.submit", actorName: "张三", summary: "张三 提交了报销单", createdAt: "2026-03-22T09:00:00.000Z", href: "/reimbursements/reimbursement-1" },
|
||||
{ id: "activity-2", type: "attendance.clock_in", actorName: "李四", summary: "李四 完成了上班打卡", createdAt: "2026-03-22T08:50:00.000Z", href: "/attendance" },
|
||||
],
|
||||
teamStatusBoard: [
|
||||
{ employeeId: "employee-1", name: "张三", avatarUrl: null, presenceStatus: "office", attendanceClockIn: "2026-03-22T00:55:00.000Z", attendanceClockOut: null, onLeave: false, leaveType: null },
|
||||
{ employeeId: "employee-2", name: "李四", avatarUrl: null, presenceStatus: "leave", attendanceClockIn: null, attendanceClockOut: null, onLeave: true, leaveType: "年假" },
|
||||
],
|
||||
}
|
||||
: {
|
||||
workspace: { id: "workspace-1", persisted: true, profile: "small_team_internal" },
|
||||
@@ -162,6 +184,13 @@ function mockPortalHome(page: import("@playwright/test").Page, mode: "employee"
|
||||
projectSummary: { myCount: 2, overdueMilestonesCount: 1, highPriorityTaskCount: 1, openRiskCount: 0, followUpDueTodayCount: 1, closurePendingProjectCount: 0, href: "/projects" },
|
||||
peopleLifecycle: null,
|
||||
adoptionSummary: null,
|
||||
recentActivities: [
|
||||
{ id: "activity-1", type: "leave.submit", actorName: "Employee", summary: "Employee 提交了请假单", createdAt: "2026-03-22T09:00:00.000Z", href: "/leave-requests" },
|
||||
],
|
||||
teamStatusBoard: [
|
||||
{ employeeId: "employee-1", name: "Employee", avatarUrl: null, presenceStatus: "office", attendanceClockIn: "2026-03-22T00:55:00.000Z", attendanceClockOut: null, onLeave: false, leaveType: null },
|
||||
{ employeeId: "employee-2", name: "同事", avatarUrl: null, presenceStatus: "remote", attendanceClockIn: null, attendanceClockOut: null, onLeave: false, leaveType: null },
|
||||
],
|
||||
};
|
||||
|
||||
await route.fulfill({
|
||||
@@ -175,6 +204,7 @@ function mockPortalHome(page: import("@playwright/test").Page, mode: "employee"
|
||||
test("Portal 员工视角优先显示今日动作顺序", async ({ page }) => {
|
||||
await mockNavigation(page, "employee");
|
||||
await mockPortalHome(page, "employee");
|
||||
await mockAttendanceToday(page);
|
||||
await mockMe(page, ["employee"], "Employee");
|
||||
|
||||
await login(page, EMPLOYEE);
|
||||
@@ -195,11 +225,16 @@ test("Portal 员工视角优先显示今日动作顺序", async ({ page }) => {
|
||||
|
||||
await expect(page.getByText("我的申请与资产")).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "公告" })).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "快捷操作栏" })).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "团队全员状态" })).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "今日待办聚合" })).toBeVisible();
|
||||
await expect(page.getByRole("heading", { name: "近期动态流" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("Portal 管理视角重排正确,备用模块默认折叠", async ({ page }) => {
|
||||
await mockNavigation(page, "manager");
|
||||
await mockPortalHome(page, "manager");
|
||||
await mockAttendanceToday(page);
|
||||
await mockMe(page, ["admin"], "Admin");
|
||||
|
||||
await login(page, ADMIN);
|
||||
@@ -226,6 +261,7 @@ test("Portal 管理视角重排正确,备用模块默认折叠", async ({ page
|
||||
test("Portal 域管理角色也进入经理视图", async ({ page }) => {
|
||||
await mockNavigation(page, "manager");
|
||||
await mockPortalHome(page, "manager");
|
||||
await mockAttendanceToday(page);
|
||||
await mockMe(page, ["administration"], "Administration");
|
||||
|
||||
await login(page, EMPLOYEE);
|
||||
@@ -244,6 +280,7 @@ test("企微 WebView 下顶栏显示入口提示", async ({ page }) => {
|
||||
});
|
||||
await mockNavigation(page, "employee");
|
||||
await mockPortalHome(page, "employee");
|
||||
await mockAttendanceToday(page);
|
||||
await mockMe(page, ["employee"], "Employee");
|
||||
|
||||
await login(page, EMPLOYEE);
|
||||
|
||||
在新工单中引用
屏蔽一个用户