收口报销详情返回与金额展示(07-27-yang-jun-reimbursement-readiness)

这个提交包含在:
2026-08-01 15:03:48 +08:00
父节点 85fad71070
当前提交 3bfcbbfc91
共修改 16 个文件,包含 219 行新增和 81 行删除
@@ -1093,6 +1093,9 @@ test("报销详情固定使用上海时区并收敛只读信息", async ({ page
await expect(page.getByRole("heading", { name: "业务摘要" })).toHaveCount(0);
await expect(page.getByRole("heading", { name: "补充附件" })).toHaveCount(0);
await expect(page.getByRole("heading", { name: "预算与审核提示" })).toHaveCount(0);
await expect(page.getByTestId("reimbursement-back")).toContainText("返回报销列表");
await expect(page.getByTestId("reimbursement-summary")).toContainText("¥1,860.00");
await expect(page.getByTestId("reimbursement-items")).toContainText("¥860.00");
await expect(page.getByTestId("reimbursement-attachments")).toContainText("2026年5月27日 17:10");
await expect(page.getByTestId("reimbursement-materials").getByRole("button", { name: /查看发票原件/ })).toHaveCount(1);
await expect(page.getByTestId("reimbursement-materials").getByRole("button", { name: /查看补充附件/ })).toHaveCount(1);
@@ -1109,6 +1112,8 @@ test("报销详情固定使用上海时区并收敛只读信息", async ({ page
await expect(page.getByRole("heading", { name: "报销概况" })).toBeVisible();
await expect(page.getByRole("heading", { name: "当前办理摘要" })).toHaveCount(0);
await expect(page.getByTestId("mobile-reimbursement-detail-focus")).toContainText(visualMe.name);
await expect(page.getByTestId("mobile-reimbursement-detail-focus")).toContainText("¥1,860.00");
await expect(page.getByTestId("mobile-reimbursement-items")).toContainText("¥860.00");
await expect(page.getByTestId("mobile-reimbursement-processing-progress")).toContainText("负责人复核");
await expect(page.getByTestId("mobile-reimbursement-attachments")).toContainText("2026年5月27日 17:10");
await expect(page.getByTestId("mobile-reimbursement-materials").getByRole("button", { name: /查看发票原件/ })).toHaveCount(1);
@@ -1134,7 +1139,7 @@ test("Wave3 PC 详情和通知中心视觉截图", async ({ page }) => {
await expect(page.getByRole("heading", { name: "补充附件" })).toHaveCount(0);
await expect(page.getByRole("heading", { name: "预算与审核提示" })).toHaveCount(0);
await expect(page.getByTestId("reimbursement-attachments")).toContainText("2026年5月27日 17:10");
await expect(page.getByTestId("reimbursement-first-screen-actions").locator("a,button")).toHaveCount(3);
await expect(page.getByTestId("reimbursement-first-screen-actions").locator("a,button")).toHaveCount(2);
await expect(page.getByTestId("reimbursement-first-screen-actions")).toContainText("看审批进度");
await expect(page.getByTestId("reimbursement-payment-status")).toHaveCount(0);
await page.getByTestId("reimbursement-more-toggle").click();
@@ -1152,7 +1157,8 @@ test("Wave3 PC 详情和通知中心视觉截图", async ({ page }) => {
await page.getByTestId("workflow-task-reimbursement-detail-link").click();
await expect(page).toHaveURL(/\/reimbursements\/reim-wave3$/);
await expect(page.getByTestId("reimbursement-overview")).toBeVisible();
await page.goBack();
await expect(page.getByTestId("reimbursement-back")).toContainText("返回审批详情");
await page.getByTestId("reimbursement-back").click();
await expect(page).toHaveURL(/\/workflow\/tasks\/task-wave3$/);
await expect(page.getByTestId("workflow-task-overview")).toBeVisible();
await page.screenshot({ path: screenshotPath("02-pc-workflow-detail.png"), fullPage: true });
@@ -1199,6 +1205,22 @@ test("Wave3 PC 详情和通知中心视觉截图", async ({ page }) => {
await page.screenshot({ path: screenshotPath("04-pc-contracts-registry.png"), fullPage: true });
});
test("PC 报销详情按来源返回并保留列表筛选", async ({ page }) => {
await page.setViewportSize({ width: 1440, height: 960 });
await page.goto("/reimbursements?status=reviewing&page=1&scope=all");
await page.getByTestId("reimbursement-detail-link").first().click();
await expect(page).toHaveURL(/\/workflow\/tasks\/task-wave3$/);
await expect(page.getByTestId("workflow-task-back")).toContainText("返回报销列表");
await page.getByTestId("workflow-task-back").click();
await expect(page).toHaveURL(/\/reimbursements\?status=reviewing&page=1&scope=all$/);
await page.goto("/workflow/tasks/task-wave3");
await page.getByTestId("workflow-task-reimbursement-detail-link").click();
await expect(page.getByTestId("reimbursement-back")).toContainText("返回审批详情");
await page.getByTestId("reimbursement-back").click();
await expect(page).toHaveURL(/\/workflow\/tasks\/task-wave3$/);
});
test("/contracts-registry 在 768x1024 与 1024x768 下操作列可达", async ({ page }) => {
for (const viewport of [
{ width: 768, height: 1024 },
@@ -586,9 +586,9 @@ async function collectVisualMetrics(page: Page) {
const activeRgb = activeStyle ? parseRgb(activeStyle.backgroundColor) : null;
const stickyActions = document.querySelector("[data-testid='mobile-reimbursement-sticky-actions']");
const stickyRect = stickyActions?.getBoundingClientRect();
const addButton = document.querySelector("[data-testid='mobile-reimbursement-sticky-invoice-add']");
const materialAddButton = document.querySelector("[data-testid='reimbursement-invoice-add']");
const stickyAddButton = document.querySelector("[data-testid='mobile-reimbursement-sticky-invoice-add']");
const submitButton = document.querySelector("[data-testid='reimbursement-submit']");
const addRect = addButton?.getBoundingClientRect();
const submitRect = submitButton?.getBoundingClientRect();
const bodyText = document.body?.innerText ?? "";
@@ -605,8 +605,9 @@ async function collectVisualMetrics(page: Page) {
stickyActionsVisible: Boolean(stickyRect && stickyRect.height > 0 && stickyRect.bottom <= window.innerHeight + 2),
stickyBottomGap: stickyRect ? Math.round(window.innerHeight - stickyRect.bottom) : null,
stickyHeight: stickyRect ? Math.round(stickyRect.height) : 0,
stickyButtonsSameRow: Boolean(addRect && submitRect && Math.abs(addRect.top - submitRect.top) <= 2),
stickyButtonMinHeight: Math.min(addRect?.height ?? 0, submitRect?.height ?? 0),
materialInvoiceAddVisible: Boolean(materialAddButton?.getBoundingClientRect().height),
stickyInvoiceAddVisible: Boolean(stickyAddButton?.getBoundingClientRect().height),
stickyButtonMinHeight: submitRect?.height ?? 0,
activeElementTestId: document.activeElement?.getAttribute("data-testid") ?? "",
bodyText,
};
@@ -732,7 +733,8 @@ test.describe("R111 国内报销发票与附件双端体验", () => {
expect(beforeDialogMetrics.navHeight).toBe(0);
expect(beforeDialogMetrics.stickyActionsVisible).toBe(true);
expect(beforeDialogMetrics.stickyBottomGap).toBeLessThanOrEqual(2);
expect(beforeDialogMetrics.stickyButtonsSameRow).toBe(true);
expect(beforeDialogMetrics.materialInvoiceAddVisible).toBe(true);
expect(beforeDialogMetrics.stickyInvoiceAddVisible).toBe(false);
expect(beforeDialogMetrics.stickyButtonMinHeight).toBeGreaterThanOrEqual(44);
await mobile.page.getByTestId("reimbursement-invoice-add").click();
@@ -274,7 +274,6 @@ async function collectMobileMetrics(page: Page) {
const stickyActions = document.querySelector("[data-testid='mobile-reimbursement-sticky-actions']");
const stickyRect = stickyActions?.getBoundingClientRect();
const stickyButtons = [
document.querySelector("[data-testid='mobile-reimbursement-sticky-invoice-add']"),
document.querySelector("[data-testid='reimbursement-submit']"),
].filter(Boolean).map((element) => element!.getBoundingClientRect());
const actionItems = ["approvals", "capture", "reimbursements", "me", "leave"].map((key) => {
@@ -350,7 +349,7 @@ test.describe("R5 真机反馈移动交互", () => {
serviceWorkers: "block",
});
test("中文头像首字、底部 Tab 固定和详情深层页双按钮符合企业微信体验", async ({ page }) => {
test("中文头像首字、底部 Tab 固定和详情深层页单一主按钮符合企业微信体验", async ({ page }) => {
await mockApis(page);
await login(page);
@@ -417,7 +416,8 @@ test.describe("R5 真机反馈移动交互", () => {
await expect(page.getByTestId("mobile-nav-reimbursements")).toHaveCount(0);
await expect(page.getByRole("link", { name: "返回" })).toBeVisible();
await expect(page.getByTestId("mobile-reimbursement-sticky-actions")).toBeVisible();
await expect(page.getByTestId("mobile-reimbursement-sticky-invoice-add")).toBeVisible();
await expect(page.getByTestId("mobile-reimbursement-sticky-invoice-add")).toHaveCount(0);
await expect(page.getByTestId("reimbursement-invoice-add")).toBeVisible();
await expect(page.getByTestId("reimbursement-submit")).toBeVisible();
await page.screenshot({ path: screenshotPath(`${device.key}-mobile-reimbursement-detail-sticky`), fullPage: true });
@@ -484,7 +484,6 @@ async function collectMetrics(page: Page) {
const stickyActions = document.querySelector("[data-testid='mobile-reimbursement-sticky-actions']");
const stickyRect = stickyActions?.getBoundingClientRect();
const stickyButtons = [
document.querySelector("[data-testid='mobile-reimbursement-sticky-invoice-add']"),
document.querySelector("[data-testid='reimbursement-submit']"),
].filter(Boolean).map((element) => element!.getBoundingClientRect());
return {
@@ -545,7 +545,6 @@ async function collectMetrics(page: Page) {
return before.display !== "none" && before.visibility !== "hidden" && opacity > 0.01 && height > 0;
});
const stickyButtons = [
document.querySelector("[data-testid='mobile-reimbursement-sticky-invoice-add']"),
document.querySelector("[data-testid='reimbursement-submit']"),
].filter(Boolean).map((element) => element!.getBoundingClientRect());
return {
@@ -433,7 +433,6 @@ async function collectRenderingMetrics(page: Page) {
});
const stickyActions = document.querySelector("[data-testid='mobile-reimbursement-sticky-actions']");
const stickyButtons = [
document.querySelector("[data-testid='mobile-reimbursement-sticky-invoice-add']"),
document.querySelector("[data-testid='reimbursement-submit']"),
].filter(Boolean).map((element) => element!.getBoundingClientRect());
const mobileShell = document.querySelector(".hyb-mobile-shell");