From 47da709f072b62d93819202232aed74a116a749c Mon Sep 17 00:00:00 2001 From: shunli Date: Mon, 11 May 2026 12:01:50 +0800 Subject: [PATCH] =?UTF-8?q?UI6=20=E4=BC=98=E5=8C=96=E7=A7=BB=E5=8A=A8?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=BF=AB=E6=8D=B7=E5=8D=A1=E8=A7=86=E8=A7=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/pages/MobilePortalPage.tsx | 21 ++++++++----- .../r5-real-device-feedback-mobile-ux.spec.ts | 30 +++++++++++++++++++ 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/client/src/pages/MobilePortalPage.tsx b/client/src/pages/MobilePortalPage.tsx index b39a982b..a1f8c166 100644 --- a/client/src/pages/MobilePortalPage.tsx +++ b/client/src/pages/MobilePortalPage.tsx @@ -130,18 +130,25 @@ function ActionTile({ action }: { action: MobileAction }) { to={action.to} className={ isPrimary - ? "flex min-h-24 flex-col justify-between rounded-lg border border-primary-100 bg-primary-50 p-3 text-primary shadow-sm" + ? "relative flex min-h-24 flex-col justify-between rounded-lg border border-primary-100 bg-primary-50 p-3 pr-14 text-primary shadow-sm" : isWarning - ? "flex min-h-24 flex-col justify-between rounded-lg border border-amber-200 bg-amber-50 p-3 text-amber-900" - : "flex min-h-24 flex-col justify-between rounded-lg border border-zinc-200 bg-white p-3 text-zinc-900 shadow-sm" + ? "relative flex min-h-24 flex-col justify-between rounded-lg border border-amber-200 bg-amber-50 p-3 pr-14 text-amber-900" + : "relative flex min-h-24 flex-col justify-between rounded-lg border border-zinc-200 bg-white p-3 pr-14 text-zinc-900 shadow-sm" } data-testid={`mobile-action-${action.key}`} > -
- {action.label} - {action.icon} +
+ + {action.label} +
-
{action.meta}
+ + {action.icon} + +
{action.meta}
); } diff --git a/client/tests/e2e/r5-real-device-feedback-mobile-ux.spec.ts b/client/tests/e2e/r5-real-device-feedback-mobile-ux.spec.ts index b2adff94..2b673c3e 100644 --- a/client/tests/e2e/r5-real-device-feedback-mobile-ux.spec.ts +++ b/client/tests/e2e/r5-real-device-feedback-mobile-ux.spec.ts @@ -263,6 +263,25 @@ async function collectMobileMetrics(page: Page) { document.querySelector("[data-testid='mobile-reimbursement-sticky-invoice-add']"), document.querySelector("[data-testid='reimbursement-submit']"), ].filter(Boolean).map((element) => element!.getBoundingClientRect()); + const actionLabels = Array.from(document.querySelectorAll("[data-testid^='mobile-action-'][data-testid$='-label']")).map((element) => { + const rect = element.getBoundingClientRect(); + const style = window.getComputedStyle(element); + const key = element.getAttribute("data-testid")?.replace(/^mobile-action-/, "").replace(/-label$/, "") ?? ""; + const icon = document.querySelector(`[data-testid='mobile-action-${key}-icon']`); + const iconRect = icon?.getBoundingClientRect(); + return { + text: element.textContent?.trim() ?? "", + width: rect.width, + height: rect.height, + right: rect.right, + lineHeight: Number.parseFloat(style.lineHeight) || 24, + whiteSpace: style.whiteSpace, + iconLeft: iconRect?.left ?? null, + iconWidth: iconRect?.width ?? 0, + iconHeight: iconRect?.height ?? 0, + gapToIcon: iconRect ? iconRect.left - rect.right : null, + }; + }); return { width: window.innerWidth, height: window.innerHeight, @@ -278,6 +297,7 @@ async function collectMobileMetrics(page: Page) { stickyButtons.length === 2 ? Math.abs(stickyButtons[0].top - stickyButtons[1].top) <= 2 : stickyButtons.length <= 1, stickyButtonMinHeight: stickyButtons.length ? Math.min(...stickyButtons.map((rect) => rect.height)) : 0, stickyButtonMinWidth: stickyButtons.length ? Math.min(...stickyButtons.map((rect) => rect.width)) : 0, + actionLabels, text: document.body?.innerText ?? "", }; }); @@ -314,6 +334,16 @@ test.describe("R5 真机反馈移动交互", () => { expect(homeMetrics.bottomNavBottomGap).not.toBeNull(); expect(homeMetrics.bottomNavBottomGap!).toBeLessThanOrEqual(2); expect(homeMetrics.scrollWidth).toBeLessThanOrEqual(homeMetrics.width + 2); + expect(homeMetrics.actionLabels.length).toBeGreaterThanOrEqual(4); + for (const label of homeMetrics.actionLabels) { + expect(label.whiteSpace, `${device.label} ${label.text} action label no wrap`).toBe("nowrap"); + expect(label.height, `${device.label} ${label.text} action label single line`).toBeLessThanOrEqual(label.lineHeight + 2); + expect(label.width, `${device.label} ${label.text} action label readable width`).toBeGreaterThanOrEqual(40); + expect(label.iconWidth, `${device.label} ${label.text} action icon width`).toBeGreaterThanOrEqual(28); + expect(label.iconHeight, `${device.label} ${label.text} action icon height`).toBeGreaterThanOrEqual(28); + expect(label.gapToIcon, `${device.label} ${label.text} action label/icon spacing`).not.toBeNull(); + expect(label.gapToIcon!, `${device.label} ${label.text} action label/icon spacing`).toBeGreaterThanOrEqual(6); + } for (const item of homeMetrics.navItems) { expect(item.visible, `${device.label} ${item.key} nav item visible`).toBe(true); expect(item.width, `${device.label} ${item.key} nav item touch width`).toBeGreaterThanOrEqual(44);