收口导航与报销审批入口(05-30-nav-reimbursement-approval-surface)
这个提交包含在:
@@ -184,7 +184,10 @@ function mockNavigation(page: import("@playwright/test").Page, mode: "employee"
|
||||
{ key: "portal", href: "/portal", label: "工作台", icon: "home_app_logo", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "workflow", href: "/workflow/tasks", label: "待我处理", icon: "fact_check", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "expense", href: "/reimbursements", label: "报销", icon: "request_quote", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "purchase", href: "/purchase-requests", label: "采购申请", icon: "shopping_cart", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "contracts", href: "/contracts-registry", label: "合同台账", icon: "description", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "projects", href: "/projects", label: "项目", icon: "workspaces", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "assets", href: "/assets", label: "资产", icon: "inventory_2", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "team", href: "/team", label: "团队", icon: "groups", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "leave", href: "/leave-requests", label: "请假记录", icon: "event_available", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
],
|
||||
@@ -192,22 +195,22 @@ function mockNavigation(page: import("@playwright/test").Page, mode: "employee"
|
||||
{ key: "settings", href: "/system/settings", label: "管理", icon: "settings", placement: "admin", permissionCodes: [], featureFlagKey: null },
|
||||
],
|
||||
backup: [
|
||||
{ key: "assets", href: "/assets", label: "资产", icon: "inventory_2", placement: "backup", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "weekly", href: "/weekly-reports", label: "周报", icon: "article", placement: "backup", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "announcements", href: "/announcements", label: "公告", icon: "campaign", placement: "backup", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "purchase", href: "/purchase-requests", label: "采购申请", icon: "shopping_cart", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "travel", href: "/travel-requests", label: "差旅申请", icon: "flight", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "travel", href: "/travel-requests", label: "差旅申请", icon: "flight", placement: "backup", permissionCodes: [], featureFlagKey: null },
|
||||
],
|
||||
}
|
||||
: {
|
||||
main: [
|
||||
{ key: "portal", href: "/portal", label: "工作台", icon: "home_app_logo", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "expense", href: "/reimbursements", label: "报销", icon: "request_quote", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "purchase", href: "/purchase-requests", label: "采购申请", icon: "shopping_cart", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "projects", href: "/projects", label: "项目", icon: "workspaces", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "assets", href: "/assets", label: "资产", icon: "inventory_2", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "leave", href: "/leave-requests", label: "请假记录", icon: "event_available", placement: "main", permissionCodes: [], featureFlagKey: null },
|
||||
],
|
||||
admin: [],
|
||||
backup: [
|
||||
{ key: "assets", href: "/assets", label: "资产", icon: "inventory_2", placement: "backup", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "weekly", href: "/weekly-reports", label: "周报", icon: "article", placement: "backup", permissionCodes: [], featureFlagKey: null },
|
||||
{ key: "announcements", href: "/announcements", label: "公告", icon: "campaign", placement: "backup", permissionCodes: [], featureFlagKey: null },
|
||||
],
|
||||
|
||||
@@ -117,8 +117,12 @@ async function mockVisualApis(page: Page) {
|
||||
sections: {
|
||||
main: [
|
||||
navigationItem("portal", "/portal", "工作台", "home_app_logo"),
|
||||
navigationItem("reimbursements", "/reimbursements", "报销", "request_quote"),
|
||||
navigationItem("approvals", "/workflow/tasks", "待我处理", "fact_check"),
|
||||
navigationItem("reimbursements", "/reimbursements", "报销", "request_quote"),
|
||||
navigationItem("purchase", "/purchase-requests", "采购申请", "shopping_cart"),
|
||||
navigationItem("contracts", "/contracts-registry", "合同台账", "description"),
|
||||
navigationItem("projects", "/projects", "项目", "workspaces"),
|
||||
navigationItem("assets", "/assets", "资产", "inventory_2"),
|
||||
],
|
||||
admin: [],
|
||||
backup: [navigationItem("invoice", "/invoice-pool", "票据", "receipt_long")],
|
||||
@@ -239,42 +243,82 @@ async function mockVisualApis(page: Page) {
|
||||
}
|
||||
|
||||
if (path === "/api/reimbursements") {
|
||||
const requestedStatus = url.searchParams.get("status");
|
||||
const reviewingItem = {
|
||||
id: "rb-r96-reviewing",
|
||||
formNumber: "BX20260506002",
|
||||
status: "reviewing",
|
||||
reimbursementDate: "2026-05-06",
|
||||
totalAmount: "320.00",
|
||||
description: "待处理报销",
|
||||
payment: {
|
||||
paymentVoucherNo: null,
|
||||
paymentDate: null,
|
||||
paymentChannel: null,
|
||||
paidAt: null,
|
||||
paidBy: null,
|
||||
},
|
||||
owner: {
|
||||
id: "employee-r96",
|
||||
employeeNo: "R96001",
|
||||
name: "Employee",
|
||||
},
|
||||
submitter: {
|
||||
id: "employee-r96",
|
||||
employeeNo: "R96001",
|
||||
name: "Employee",
|
||||
},
|
||||
project: null,
|
||||
pendingWorkflow: {
|
||||
task: {
|
||||
id: "task-r96",
|
||||
stepName: "经理审批",
|
||||
assigneeEmployeeId: "employee-r96",
|
||||
assigneeRoleCode: "manager",
|
||||
status: "pending",
|
||||
createdAt: "2026-05-06T09:00:00.000Z",
|
||||
},
|
||||
allowedActions: ["approve", "reject"],
|
||||
},
|
||||
createdAt: "2026-05-06T09:00:00.000Z",
|
||||
updatedAt: "2026-05-06T09:00:00.000Z",
|
||||
};
|
||||
const draftItem = {
|
||||
id: "rb-r96",
|
||||
formNumber: "BX20260506001",
|
||||
status: "draft",
|
||||
reimbursementDate: "2026-05-06",
|
||||
totalAmount: "168.30",
|
||||
description: "视觉基线报销",
|
||||
payment: {
|
||||
paymentVoucherNo: null,
|
||||
paymentDate: null,
|
||||
paymentChannel: null,
|
||||
paidAt: null,
|
||||
paidBy: null,
|
||||
},
|
||||
owner: {
|
||||
id: "employee-r96",
|
||||
employeeNo: "R96001",
|
||||
name: "Employee",
|
||||
},
|
||||
submitter: {
|
||||
id: "employee-r96",
|
||||
employeeNo: "R96001",
|
||||
name: "Employee",
|
||||
},
|
||||
project: null,
|
||||
pendingWorkflow: null,
|
||||
createdAt: "2026-05-06T09:00:00.000Z",
|
||||
updatedAt: "2026-05-06T09:00:00.000Z",
|
||||
};
|
||||
const items = requestedStatus === "reviewing" ? [reviewingItem] : [draftItem];
|
||||
await fulfillJson(route, {
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
total: 1,
|
||||
scope: "own",
|
||||
items: [
|
||||
{
|
||||
id: "rb-r96",
|
||||
formNumber: "BX20260506001",
|
||||
status: "draft",
|
||||
reimbursementDate: "2026-05-06",
|
||||
totalAmount: "168.30",
|
||||
description: "视觉基线报销",
|
||||
payment: {
|
||||
paymentVoucherNo: null,
|
||||
paymentDate: null,
|
||||
paymentChannel: null,
|
||||
paidAt: null,
|
||||
paidBy: null,
|
||||
},
|
||||
owner: {
|
||||
id: "employee-r96",
|
||||
employeeNo: "R96001",
|
||||
name: "Employee",
|
||||
},
|
||||
submitter: {
|
||||
id: "employee-r96",
|
||||
employeeNo: "R96001",
|
||||
name: "Employee",
|
||||
},
|
||||
project: null,
|
||||
pendingWorkflow: null,
|
||||
createdAt: "2026-05-06T09:00:00.000Z",
|
||||
updatedAt: "2026-05-06T09:00:00.000Z",
|
||||
},
|
||||
],
|
||||
total: items.length,
|
||||
scope: url.searchParams.get("scope") ?? "own",
|
||||
items,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -323,6 +367,10 @@ test.describe("visual shell", () => {
|
||||
await expect(page.locator("aside")).toBeVisible();
|
||||
await expect(page.getByTestId("topbar-profile-trigger")).toBeVisible();
|
||||
await expect(page.locator("aside").getByRole("link", { name: "工作台", exact: true })).toBeVisible();
|
||||
await expect(page.locator("aside").getByRole("link", { name: "采购申请" })).toBeVisible();
|
||||
await expect(page.locator("aside").getByRole("link", { name: "合同台账" })).toBeVisible();
|
||||
await expect(page.locator("aside").getByRole("link", { name: "项目" })).toBeVisible();
|
||||
await expect(page.locator("aside").getByRole("link", { name: "资产" })).toBeVisible();
|
||||
await expect(page.locator("summary").filter({ hasText: "更多" })).toBeVisible();
|
||||
|
||||
await attachScreenshot(page, testInfo, "app-shell.png");
|
||||
@@ -346,7 +394,15 @@ test.describe("visual shell", () => {
|
||||
await expect(page.getByTestId("reimbursements-export")).not.toBeVisible();
|
||||
await expect(page.getByTestId("reimbursements-status-tabs")).toBeVisible();
|
||||
await expect(page.getByTestId("reimbursements-table")).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "批量操作" })).toHaveCount(0);
|
||||
await attachScreenshot(page, testInfo, "pc-reimbursements-wave1.png");
|
||||
|
||||
await page.goto("/reimbursements?status=reviewing&scope=all");
|
||||
await expect(page.getByTestId("reimbursements-table")).toBeVisible();
|
||||
await expect(page.getByRole("link", { name: "查看处理" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "批量操作" })).toHaveCount(0);
|
||||
await expect(page.getByRole("button", { name: "批量通过" })).toHaveCount(0);
|
||||
await expect(page.getByRole("button", { name: "批量驳回" })).toHaveCount(0);
|
||||
});
|
||||
|
||||
test("移动首页任务化布局基线", async ({ page }, testInfo) => {
|
||||
|
||||
在新工单中引用
屏蔽一个用户