RS6 修复移动响应式布局体系

这个提交包含在:
2026-05-11 12:52:30 +08:00
父节点 5dd4c96bec
当前提交 e399376e25
共修改 16 个文件,包含 841 行新增和 97 行删除
@@ -263,25 +263,46 @@ 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 actionItems = ["approvals", "capture", "reimbursements", "me", "leave"].map((key) => {
const element = document.querySelector(`[data-testid='mobile-action-${key}']`);
const label = document.querySelector(`[data-testid='mobile-action-${key}-label']`);
const icon = document.querySelector(`[data-testid='mobile-action-${key}-icon']`);
const rect = element?.getBoundingClientRect();
const labelRect = label?.getBoundingClientRect();
const iconRect = icon?.getBoundingClientRect();
const style = label ? window.getComputedStyle(label) : null;
const overlaps = Boolean(
labelRect &&
iconRect &&
!(labelRect.right <= iconRect.left || labelRect.left >= iconRect.right || labelRect.bottom <= iconRect.top || labelRect.top >= iconRect.bottom),
);
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,
key,
visible: Boolean(rect && rect.width > 0 && rect.height > 0),
width: rect?.width ?? 0,
height: rect?.height ?? 0,
text: label?.textContent?.trim() ?? "",
labelWidth: labelRect?.width ?? 0,
labelHeight: labelRect?.height ?? 0,
labelLineHeight: style ? Number.parseFloat(style.lineHeight) || 18 : 18,
labelWhiteSpace: style?.whiteSpace ?? "",
iconWidth: iconRect?.width ?? 0,
iconHeight: iconRect?.height ?? 0,
gapToIcon: iconRect ? iconRect.left - rect.right : null,
overlaps,
labelWithin:
Boolean(rect && labelRect) &&
labelRect!.left >= rect!.left - 1 &&
labelRect!.right <= rect!.right + 1 &&
labelRect!.top >= rect!.top - 1 &&
labelRect!.bottom <= rect!.bottom + 1,
iconWithin:
Boolean(rect && iconRect) &&
iconRect!.left >= rect!.left - 1 &&
iconRect!.right <= rect!.right + 1 &&
iconRect!.top >= rect!.top - 1 &&
iconRect!.bottom <= rect!.bottom + 1,
};
});
}).filter((item) => item.visible);
return {
width: window.innerWidth,
height: window.innerHeight,
@@ -297,7 +318,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,
actionItems,
text: document.body?.innerText ?? "",
};
});
@@ -334,15 +355,17 @@ 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);
expect(homeMetrics.actionItems.length).toBeGreaterThanOrEqual(4);
for (const action of homeMetrics.actionItems) {
expect(action.height, `${device.label} ${action.text} action touch height`).toBeGreaterThanOrEqual(44);
expect(action.labelWhiteSpace, `${device.label} ${action.text} action label no wrap`).toBe("nowrap");
expect(action.labelHeight, `${device.label} ${action.text} action label single line`).toBeLessThanOrEqual(action.labelLineHeight + 2);
expect(action.labelWidth, `${device.label} ${action.text} action label readable width`).toBeGreaterThanOrEqual(20);
expect(action.iconWidth, `${device.label} ${action.text} action icon width`).toBeGreaterThanOrEqual(28);
expect(action.iconHeight, `${device.label} ${action.text} action icon height`).toBeGreaterThanOrEqual(28);
expect(action.overlaps, `${device.label} ${action.text} action label/icon overlap`).toBe(false);
expect(action.labelWithin, `${device.label} ${action.text} action label within tile`).toBe(true);
expect(action.iconWithin, `${device.label} ${action.text} action icon within tile`).toBe(true);
}
for (const item of homeMetrics.navItems) {
expect(item.visible, `${device.label} ${item.key} nav item visible`).toBe(true);