MME6 优化移动我的页自适应视觉
这个提交包含在:
@@ -60,7 +60,7 @@ export function AppShellLayout() {
|
||||
{isMobileRoute ? null : <Sidebar />}
|
||||
|
||||
<main
|
||||
className={`flex min-w-0 flex-1 flex-col ${isMobileRoute ? "overflow-hidden" : "lg:ml-72"}`}
|
||||
className={`flex min-w-0 flex-1 flex-col ${isMobileRoute ? "hyb-mobile-shell overflow-hidden" : "lg:ml-72"}`}
|
||||
style={isMobileRoute ? { height: "var(--mobile-viewport-height, 100vh)", maxHeight: "var(--mobile-viewport-height, 100vh)", minHeight: "var(--mobile-viewport-height, 100vh)" } : undefined}
|
||||
>
|
||||
{isMobileRoute ? null : <Topbar />}
|
||||
|
||||
@@ -38,10 +38,11 @@ function MobileActionLink({
|
||||
return (
|
||||
<Link
|
||||
to={to}
|
||||
className="flex min-h-12 items-center gap-3 rounded-lg border border-zinc-200 bg-white px-3 py-2 text-left shadow-sm transition-colors hover:bg-zinc-50"
|
||||
className="mobile-me-action-link"
|
||||
data-testid="mobile-me-action-link"
|
||||
>
|
||||
<MobileIcon name={icon} className="size-8 rounded-lg bg-zinc-100 p-1.5 text-zinc-700" />
|
||||
<span className="min-w-0">
|
||||
<MobileIcon name={icon} className="mobile-me-action-icon" />
|
||||
<span className="mobile-me-action-copy">
|
||||
<span className="block text-sm font-semibold text-zinc-900">{label}</span>
|
||||
{description ? <span className="mt-0.5 block text-xs leading-5 text-zinc-500">{description}</span> : null}
|
||||
</span>
|
||||
@@ -81,10 +82,14 @@ export function MobileMePage() {
|
||||
<PageHeader title="我的" />
|
||||
|
||||
<SectionPanel title="个人信息">
|
||||
<div className="flex items-center gap-3">
|
||||
<EmployeeAvatar name={me?.name ?? "员工"} src={profile?.avatarUrl} size="md" />
|
||||
<div className="min-w-0 space-y-1">
|
||||
<div className="text-lg font-semibold text-zinc-900">{me?.name ?? "-"}</div>
|
||||
<div className="mobile-me-profile-row" data-testid="mobile-me-profile-row">
|
||||
<div className="mobile-me-avatar-slot" data-testid="mobile-me-avatar-slot">
|
||||
<EmployeeAvatar name={me?.name ?? "员工"} src={profile?.avatarUrl} size="md" />
|
||||
</div>
|
||||
<div className="mobile-me-profile-copy" data-testid="mobile-me-profile-copy">
|
||||
<div className="text-lg font-semibold leading-7 text-zinc-900" data-testid="mobile-me-profile-name">
|
||||
{me?.name ?? "-"}
|
||||
</div>
|
||||
<div className="text-sm text-zinc-500">{departmentName}</div>
|
||||
{me?.employeeNo ? <div className="text-xs text-zinc-400">员工号:{me.employeeNo}</div> : null}
|
||||
</div>
|
||||
@@ -108,7 +113,7 @@ export function MobileMePage() {
|
||||
</SectionPanel>
|
||||
|
||||
<SectionPanel title="更多入口">
|
||||
<div className="mobile-adaptive-grid" data-testid="mobile-more-links">
|
||||
<div className="mobile-me-entry-grid" data-testid="mobile-more-links">
|
||||
<MobileActionLink to="/mobile/notifications" label="通知中心" icon="notifications" />
|
||||
<MobileActionLink to="/mobile/leave" label="请假" icon="event_available" />
|
||||
<MobileActionLink to="/mobile/reimbursements" label="报销" icon="request_quote" />
|
||||
@@ -120,7 +125,7 @@ export function MobileMePage() {
|
||||
|
||||
{canAccessAdmin ? (
|
||||
<SectionPanel title="管理入口">
|
||||
<div className="mobile-adaptive-grid">
|
||||
<div className="mobile-me-entry-grid">
|
||||
<MobileActionLink to="/mobile/me" label="人员管理" icon="group" />
|
||||
<MobileActionLink to="/mobile/me" label="组织架构" icon="account_tree" />
|
||||
<MobileActionLink to="/mobile/me" label="系统设置" icon="settings" />
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
--mobile-bottom-nav-height: 68px;
|
||||
--mobile-sticky-action-height: 78px;
|
||||
--mobile-icon-action-min-height: 72px;
|
||||
--mobile-me-slot-gap: clamp(12px, 3.7vw, 16px);
|
||||
--mobile-me-action-icon-slot: 36px;
|
||||
}
|
||||
|
||||
.page-scaffold.mobile-fixed-action-page {
|
||||
@@ -37,6 +39,10 @@
|
||||
padding: var(--mobile-card-padding);
|
||||
}
|
||||
|
||||
.hyb-mobile-shell .section-panel::before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-icon-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
@@ -113,6 +119,87 @@
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mobile-me-entry-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: var(--mobile-card-gap);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mobile-me-profile-row {
|
||||
display: grid;
|
||||
grid-template-columns: 44px minmax(0, 1fr);
|
||||
column-gap: var(--mobile-me-slot-gap);
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mobile-me-avatar-slot {
|
||||
width: 44px;
|
||||
min-width: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mobile-me-profile-copy {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mobile-me-profile-copy > * {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mobile-me-action-link {
|
||||
display: grid;
|
||||
grid-template-columns: var(--mobile-me-action-icon-slot) minmax(0, 1fr);
|
||||
column-gap: var(--mobile-me-slot-gap);
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
min-height: 48px;
|
||||
border: 1px solid rgb(228 228 231);
|
||||
border-radius: 10px;
|
||||
background: rgb(255 255 255);
|
||||
padding: 8px 12px;
|
||||
text-align: left;
|
||||
box-shadow: 0 1px 2px rgb(15 23 42 / 0.06);
|
||||
transition: background-color 150ms ease, border-color 150ms ease;
|
||||
}
|
||||
|
||||
.mobile-me-action-link:hover {
|
||||
background: rgb(250 250 250);
|
||||
}
|
||||
|
||||
.mobile-me-action-icon {
|
||||
width: var(--mobile-me-action-icon-slot);
|
||||
height: var(--mobile-me-action-icon-slot);
|
||||
border-radius: 10px;
|
||||
background: rgb(244 244 245);
|
||||
color: rgb(63 63 70);
|
||||
padding: 7px;
|
||||
}
|
||||
|
||||
.mobile-me-action-icon svg {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mobile-me-action-copy {
|
||||
display: block;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.mobile-me-action-copy > * {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.mobile-info-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(min(100%, 7.5rem), 1fr));
|
||||
@@ -151,6 +238,8 @@
|
||||
--mobile-card-gap: 6px;
|
||||
--mobile-card-padding: 10px;
|
||||
--mobile-icon-action-min-height: 68px;
|
||||
--mobile-me-slot-gap: 12px;
|
||||
--mobile-me-action-icon-slot: 34px;
|
||||
}
|
||||
|
||||
.mobile-icon-action__icon {
|
||||
|
||||
@@ -406,6 +406,38 @@ async function collectRenderingMetrics(page: Page) {
|
||||
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");
|
||||
const avatarSlotRect = document.querySelector("[data-testid='mobile-me-avatar-slot']")?.getBoundingClientRect();
|
||||
const profileNameRect = document.querySelector("[data-testid='mobile-me-profile-name']")?.getBoundingClientRect();
|
||||
const actionGaps = Array.from(document.querySelectorAll("[data-testid='mobile-me-action-link']")).map((element) => {
|
||||
const iconRect = element.querySelector(".mobile-me-action-icon")?.getBoundingClientRect();
|
||||
const copyRect = element.querySelector(".mobile-me-action-copy")?.getBoundingClientRect();
|
||||
const linkRect = element.getBoundingClientRect();
|
||||
return {
|
||||
gap: iconRect && copyRect ? copyRect.left - iconRect.right : 0,
|
||||
iconWithin:
|
||||
Boolean(iconRect) &&
|
||||
iconRect!.left >= linkRect.left - 1 &&
|
||||
iconRect!.right <= linkRect.right + 1 &&
|
||||
iconRect!.top >= linkRect.top - 1 &&
|
||||
iconRect!.bottom <= linkRect.bottom + 1,
|
||||
copyWithin:
|
||||
Boolean(copyRect) &&
|
||||
copyRect!.left >= linkRect.left - 1 &&
|
||||
copyRect!.right <= linkRect.right + 1 &&
|
||||
copyRect!.top >= linkRect.top - 1 &&
|
||||
copyRect!.bottom <= linkRect.bottom + 1,
|
||||
};
|
||||
});
|
||||
const moreLinkRects = Array.from(document.querySelectorAll("[data-testid='mobile-more-links'] > *")).map((element) =>
|
||||
element.getBoundingClientRect(),
|
||||
);
|
||||
const mobileSectionHasDecorativeTopLine = Array.from(document.querySelectorAll(".hyb-mobile-shell .section-panel")).some((element) => {
|
||||
const before = window.getComputedStyle(element, "::before");
|
||||
const opacity = Number.parseFloat(before.opacity || "1");
|
||||
const height = Number.parseFloat(before.height || "0");
|
||||
return before.display !== "none" && before.visibility !== "hidden" && opacity > 0.01 && height > 0;
|
||||
});
|
||||
return {
|
||||
viewportWidth,
|
||||
scrollWidth: Math.max(document.documentElement.scrollWidth, document.body?.scrollWidth ?? 0),
|
||||
@@ -419,6 +451,18 @@ async function collectRenderingMetrics(page: Page) {
|
||||
stickyButtonsSameRow:
|
||||
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,
|
||||
mobileMe: {
|
||||
shellScoped: Boolean(mobileShell),
|
||||
profileGap: avatarSlotRect && profileNameRect ? profileNameRect.left - avatarSlotRect.right : null,
|
||||
actionGapMin: actionGaps.length ? Math.min(...actionGaps.map((item) => item.gap)) : null,
|
||||
actionGapMax: actionGaps.length ? Math.max(...actionGaps.map((item) => item.gap)) : null,
|
||||
actionSlotsWithin: actionGaps.every((item) => item.iconWithin && item.copyWithin),
|
||||
moreLinksTwoColumns:
|
||||
moreLinkRects.length >= 2
|
||||
? Math.abs(moreLinkRects[0].top - moreLinkRects[1].top) <= 4 && moreLinkRects[0].right <= moreLinkRects[1].left
|
||||
: true,
|
||||
hasDecorativeTopLine: mobileSectionHasDecorativeTopLine,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -474,7 +518,18 @@ async function exerciseMobileRendering(page: Page, key: string, label: string) {
|
||||
|
||||
await page.goto("/mobile/me");
|
||||
await expect(page.getByTestId("mobile-more-links")).toBeVisible();
|
||||
await expectRenderingStable(page, label, `${key}-mobile-me`);
|
||||
const meMetrics = await expectRenderingStable(page, label, `${key}-mobile-me`);
|
||||
const minSlotGap = meMetrics.viewportWidth >= 390 ? 14 : 12;
|
||||
expect(meMetrics.mobileMe.shellScoped, `${label} mobile shell scope`).toBe(true);
|
||||
expect(meMetrics.mobileMe.profileGap, `${label} profile avatar/text gap`).not.toBeNull();
|
||||
expect(meMetrics.mobileMe.profileGap ?? 0, `${label} profile avatar/text gap min`).toBeGreaterThanOrEqual(minSlotGap);
|
||||
expect(meMetrics.mobileMe.profileGap ?? 0, `${label} profile avatar/text gap max`).toBeLessThanOrEqual(20);
|
||||
expect(meMetrics.mobileMe.actionGapMin, `${label} action icon/text gap min`).not.toBeNull();
|
||||
expect(meMetrics.mobileMe.actionGapMin ?? 0, `${label} action icon/text gap min`).toBeGreaterThanOrEqual(minSlotGap);
|
||||
expect(meMetrics.mobileMe.actionGapMax ?? 0, `${label} action icon/text gap max`).toBeLessThanOrEqual(18);
|
||||
expect(meMetrics.mobileMe.actionSlotsWithin, `${label} action slots within link`).toBe(true);
|
||||
expect(meMetrics.mobileMe.moreLinksTwoColumns, `${label} more links keep two columns`).toBe(true);
|
||||
expect(meMetrics.mobileMe.hasDecorativeTopLine, `${label} mobile section top line hidden`).toBe(false);
|
||||
|
||||
await page.goto("/mobile/reimbursements/wcm6-reimbursement");
|
||||
await expect(page.getByTestId("mobile-reimbursement-detail")).toBeVisible();
|
||||
|
||||
@@ -116,6 +116,7 @@ R6 之后的 PC、移动和审批体验参考国内主流协同/OA 产品的共
|
||||
- toast、dialog、actionsheet、tabbar、cell、button 等语义参考微信生态习惯;样式必须回到 hyb-oa 自身品牌和组件规则。
|
||||
- 企业微信入口应尽量免登录;绑定失败或权限不足时显示明确下一步,而不是让用户反复登录。
|
||||
- 头像 fallback 遵循国内中文习惯:中文/CJK 姓名默认取首个可见字符,英文或拼音姓名保留两段首字母。
|
||||
- “我的”页和更多入口使用组件级自适应槽位:头像/图标槽固定,文字槽使用 `minmax(0, 1fr)` 可收缩,间距使用移动 token 或 `clamp()`;不按具体 iPhone/Android 机型写补丁,不通过放大字号、放大卡片或改成单列来规避图文拥挤。
|
||||
- 移动角色差异采用“同框架、按角色裁剪内容和动作”:员工、审批人、财务、管理员、负责人看到不同入口、摘要、动作和敏感信息,但不做多套角色专属移动 UI。
|
||||
- 移动验收必须包含跨视口自动化和代表性真机确认;若真机验证暂缓,只能记为 `PAUSED`,不能把相关移动阻断标为完成。
|
||||
|
||||
|
||||
@@ -63,6 +63,8 @@
|
||||
| R6-ISSUE-001 | 阻断 | 审批人 / 员工 | iPhone 12 / iOS 14.1 / 企业微信 WebView | 移动底部导航、审批入口、首页快捷卡 | 旧记录误写为 iPhone 11;用户更正为 iPhone 12 / iOS 14.1。真机截图显示首页快捷卡和底部 Tab 的字体图标漂移、重影、挤压,底部“审批”体验不稳定;自动化 Chromium UA 截图与真实 iOS 企业微信 WebView 存在差异 | `PAUSED`:WCM6 已部署公网并完成自动复检,移动核心图标改 SVG,补企业微信 WebView viewport/字号/safe-area,底部角标独立定位;公网 WCM6 视觉专项 8 passed,live smoke readiness PASS,截图 `output/playwright/r6-wecom-mobile-rendering-hardening/`;待 iPhone 12 / iOS 14.1 / 企业微信和 Redmi K60 真机确认后关闭或降级 | Codex / 待指派 | open | `issues/2026-05-11_20-38-33-r6-wecom-mobile-rendering-hardening.csv` |
|
||||
| R6-ISSUE-002 | 一般 | 自动化 / 员工与财务测试账号 | 本地隔离 E2E / PC | 报销审批进度、报销支付批次 | `BUSINESS_FLOW_GROUPS=reimbursement bash scripts/qa/run-business-flow-gates.sh local` 中 2 条用例曾失败,失败点为 Playwright 查找旧导航入口 `票据中心`;当前正式员工路径应从报销详情添加 PDF 发票 | 已关闭:测试已改为报销详情页“添加发票”路径,不恢复普通员工“票据中心”入口;支付批次用例同步按业务编号定位待办,并按金额选择财务或财务主管二级审批;报销业务流 gate 10 passed、1 skipped | Codex | closed | `issues/2026-05-11_15-50-00-r6-reimbursement-e2e-nav-alignment.csv` |
|
||||
|
||||
MME6 补充(2026-05-11):针对用户补充的 iPhone 12 / iOS 14.1 图文贴近与 iPhone 14 / iOS 16.2 卡片顶边观感,已把 `/mobile/me` 改为固定头像/图标槽 + `minmax(0, 1fr)` 文字槽,移动卡片顶边装饰线仅在 `/mobile` 作用域禁用,并将该规则写入产品设计规约。本地 `client typecheck`、`client build`、WCM6 视觉专项 8 passed、R5/R6/R124 移动相关回归 10 passed;部署后 `/ready` 正常、public bundle `findings=0`、live smoke readiness PASS、真实 OCR 样票返回重复发票可解释终态且测试通过,公网 WCM6 视觉专项 8 passed,报告 `artifacts/qa-flow/live-smoke-readiness-20260511-230918`。三台代表性真机确认前,`R6-ISSUE-001` 继续 `open/PAUSED`。
|
||||
|
||||
级别定义:
|
||||
|
||||
- 阻断:权限泄漏、付款状态错乱、企业微信入口不可用、审批主流程无法继续、真实 OCR 大面积失败。
|
||||
|
||||
@@ -41,6 +41,8 @@
|
||||
- 深层页如报销详情、审批详情隐藏底部 Tab;一级页才显示“首页、审批、报销、我的”底部导航。
|
||||
- 底部四项 Tab 必须等宽、可见、可点;不能被滚动层、卡片、安全区或遮罩覆盖。
|
||||
- 首页图标宫格必须保持图标在上、短标题在下;小屏不显示长辅助说明,标题不得逐字换行或压住图标。
|
||||
- “我的”页个人信息和更多入口必须使用固定头像/图标槽与可收缩文字槽;图标/头像与文字不能贴得过近,入口保持两列且不逐字换行,不通过放大卡片或改成单列来规避问题。
|
||||
- 移动卡片不应出现明显蓝青色顶边装饰线;保留白卡、浅边框和轻阴影即可。
|
||||
- 若现场暂时看不到真机效果或用户暂停验证,记录为 `PAUSED`;不得把 `RS6-7`、`UI6-6`、`R6-ISSUE-001` 误标完成。
|
||||
|
||||
## 报销流程
|
||||
@@ -112,6 +114,7 @@
|
||||
- `2026-05-11` 通知与 deeplink 自动视觉补充:`SMOKE101` 现有两条未读报销待办站内通知,iPhone 近似视口与 Redmi K60 近似视口、企业微信 UA 下通知页无横向溢出,通知卡片和“查看”按钮可见;点击后进入 `/mobile/approvals?taskId=177b3a9e-67fe-447d-92f4-96a652a06841` 移动审批详情,无 PC 壳混入,截图目录 `output/playwright/r5-notification-deeplink-live/`。该历史待办已处理,因此本证据只证明站内通知和移动 deeplink,不证明新待办审批按钮;通知投递审计显示渠道 `R50-MOCK-007334` 为 `mock_sent`,真实企业微信外发应用消息仍待通道确认或真机记录。
|
||||
- `2026-05-11` 个人企微应用消息补充:部署 `b1ae41f` 后启用 `R5-WECOM-APP-PERSONAL / wecom_app_message`,停用旧 mock 渠道;`SMOKE002` 创建请假测试单据并生成 `SMOKE101` 待办 `936362d8-c4e0-454f-a589-9c9653bcbfda`,通知 `9ee0602e-66a5-4a6e-81e5-04d41908c782` 投递审计为 `wecom_app_sent`、`errcode=0`、无 `invaliduser`。iPhone 近似视口与 Redmi K60 企业微信 UA 自动视觉验证通知列表和审批详情均无横向溢出,截图目录 `output/playwright/r5-wecom-app-message-live/`。用户确认手机企业微信 `oa_smoke_02` 收到“海音达工作台”应用消息,标题正确;点击后首次进入会提示进入工作台,进入后可看到移动审批,后续再次进入可直接看到移动审批;存在消息通知但未观察到系统弹窗。
|
||||
- `2026-05-11` R6 移动体验补充:RS6 响应式体系修复已完成公网自动化,320/360/375/390/393/414/430px 视觉矩阵通过;用户补充真实设备为 iPhone 12 / iOS 14.1 / 企业微信,截图显示字体图标漂移、重影和首页/底部导航视觉拥挤。当前记录为 `PAUSED`,不得将 `RS6-7`、`UI6-6` 或 `R6-ISSUE-001` 置为完成;WCM6 已部署公网并完成自动复检,移动核心 SVG 图标、企业微信 WebView 基线、多手机视口和字体失败场景均已覆盖,公网 WCM6 视觉专项 8 passed,截图目录 `output/playwright/r6-wecom-mobile-rendering-hardening/`;R6-3 继续等待代表性真机确认。
|
||||
- `2026-05-11` MME6 我的页自适应补充:针对 iPhone 12 / iOS 14.1 企业微信中图文贴近和 iPhone 14 / iOS 16.2 企业微信中卡片顶边观感,`/mobile/me` 已改为固定头像/图标槽 + 可收缩文字槽,移动卡片顶边装饰线仅在 `/mobile` 作用域禁用。本地 WCM6 视觉专项 8 passed,R5/R6/R124 移动相关回归 10 passed;部署后 `/ready` 正常、public bundle `findings=0`、live smoke readiness PASS、真实 OCR 样票返回重复发票可解释终态且测试通过,公网 WCM6 视觉专项 8 passed,报告 `artifacts/qa-flow/live-smoke-readiness-20260511-230918`。iPhone 12 / iPhone 14 / Redmi K60 真机确认前,`R6-ISSUE-001` 继续 `PAUSED`。
|
||||
|
||||
- 经理账号可在移动端看到审批待办。
|
||||
- 审批详情可查看申请摘要、附件、发票、审批记录。
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
ID,Title,Description,Acceptance,Test_Method,Tools,Dev_Status,Review1_Status,Regression_Status,Files,Dependencies,Notes
|
||||
MME6-1,建档 移动我的页自适应视觉优化,"记录 iPhone12/iOS14 企业微信图文间距偏近、iPhone14/iOS16.2 卡片顶部蓝青色线条明显的问题;本轮只优化 /mobile/me 视觉自适应。","1) 本 CSV 存在且校验通过;2) R6-ISSUE-001 保持 open/PAUSED;3) 不启动 R6;4) 不改业务逻辑、权限、审批链、通知、PDF-only 或后端。","流程级验证:python3 /home/shunli/.codex/skills/plan/scripts/validate_issues_csv.py issues/2026-05-11_22-42-11-r6-mobile-me-adaptive-visual-polish.csv;人工核对 docs/trialrun/manual-trialrun-report.md 中 R6-ISSUE-001 仍为 open/PAUSED。",python3|manual,DONE,DONE,DONE,issues/2026-05-11_22-42-11-r6-mobile-me-adaptive-visual-polish.csv,[],MME6-1 completed:CSV 校验通过;R6-ISSUE-001 保持 open/PAUSED;本轮不启动 R6。
|
||||
MME6-2,移动 Shell 增加稳定作用域,"为 /mobile 路由增加稳定移动作用域类,便于移动端样式覆盖只作用于企业微信/手机页面,不影响 PC 页面。","1) /mobile 路由容器具备稳定 class;2) PC 路由不带该 class;3) 原底部导航和深层页隐藏规则不变。","流程级验证:WCM6 Playwright 打开 /mobile/me,断言页面处于移动作用域;打开 /mobile/reimbursements/:id 仍隐藏底部 Tab;PC 页面不在本轮修改范围。",typescript|playwright,DONE,DONE,DONE,client/src/layouts/AppShellLayout.tsx,["MME6-1"],MME6-2 completed:/mobile 路由已增加 hyb-mobile-shell 稳定作用域;WCM6 专项确认 /mobile/me 处于移动作用域且报销详情深层页规则不回归。回滚路径:移除移动作用域 class。
|
||||
MME6-3,我的页头像与入口槽位自适应,"将 /mobile/me 的个人信息和入口项改为固定头像/图标槽 + minmax(0,1fr) 文字槽;间距使用 clamp token,避免 iOS14 图文贴近,同时不撑宽 iOS16 页面。","1) 头像与姓名间距不小于 12px,390px 视口不小于 14px,不超过 20px;2) 入口图标与文字间距不小于 12px,390px 视口不小于 14px,不超过 18px;3) 两列入口保持两列;4) 文字超长不撑宽卡片。","流程级验证:WCM6 Playwright 320/360/375/390/393/414/430px 打开 /mobile/me;断言 scrollWidth <= viewportWidth + 2、槽位间距范围、两列入口不重叠。",typescript|playwright,DONE,DONE,DONE,client/src/pages/MobileMePage.tsx|client/src/styles/mobile-touch.css,["MME6-2"],MME6-3 completed:个人信息与更多入口已改为固定头像/图标槽 + 可收缩文字槽;WCM6 320/360/375/390/393/414/430px 间距、两列和无横向滚动断言通过。不放大页面、不提高字号、不改权限入口;回滚路径:恢复 MobileMePage 与移动样式改动。
|
||||
MME6-4,移动卡片顶边视觉收口,"仅在 /mobile 页面禁用 SectionPanel 顶部蓝青色渐变线,保留白卡、浅边框和轻阴影,解决 iOS16.2 企业微信卡片顶部漏边观感。","1) /mobile/me 的 SectionPanel 顶部无蓝青色渐变线;2) PC SectionPanel 装饰线不受影响;3) 移动卡片边框、圆角、阴影仍清晰。","流程级验证:WCM6 Playwright 390x844 iPhone 企业微信近似视口打开 /mobile/me;断言移动 SectionPanel ::before 不可见或透明;截图输出 output/playwright/r6-wecom-mobile-rendering-hardening/。",css|playwright,DONE,DONE,DONE,client/src/styles/mobile-touch.css|client/src/layouts/AppShellLayout.tsx,["MME6-2"],MME6-4 completed:仅在 hyb-mobile-shell 下禁用 SectionPanel 顶部蓝青色渐变线;PC SectionPanel 不在本轮改动范围;WCM6 断言移动卡片顶边不可见。回滚路径:恢复移动 SectionPanel 伪元素覆盖。
|
||||
MME6-5,补强我的页自适应视觉断言,"在 WCM6 企业微信多手机视觉专项中补 /mobile/me 槽位间距、两列入口、卡片顶边和底部导航稳定断言。","1) 覆盖 320/360/375/390/393/414/430px;2) 覆盖 Material Symbols 字体失败场景;3) 截图输出到既有 WCM6 目录;4) 不把真实企业微信真机验收替换为自动化。","流程级验证:cd client && npm run test:e2e -- r6-wecom-mobile-rendering-hardening.spec.ts --workers=1 --reporter=list。",playwright,DONE,DONE,DONE,client/tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts,"[""MME6-3"",""MME6-4""]",MME6-5 completed:WCM6 专项已补 /mobile/me 槽位间距、两列入口、卡片顶边和底部导航断言;8 passed,截图输出 output/playwright/r6-wecom-mobile-rendering-hardening/。回滚路径:移除新增断言;自动化不能替代真机。
|
||||
MME6-6,本地验证与状态回填,"执行前端 typecheck/build、WCM6 专项和必要移动回归;通过后回填 MME6-1 到 MME6-6。","1) typecheck 通过;2) build 通过;3) WCM6 专项通过;4) git diff --check 通过;5) R6-ISSUE-001 仍 open/PAUSED。","流程级验证:cd client && npm run typecheck;cd client && npm run build;cd client && npm run test:e2e -- r6-wecom-mobile-rendering-hardening.spec.ts --workers=1 --reporter=list;git diff --check。",npm|playwright|git,DONE,DONE,DONE,client|issues|docs,["MME6-5"],MME6-6 completed:client typecheck 通过;client build 通过;WCM6 专项 8 passed;R5/R6/R124 移动相关回归 10 passed;R6-ISSUE-001 仍 open/PAUSED。回滚路径:撤销本轮前端、测试与文档变更。
|
||||
MME6-7,部署公网复检并等待真机门禁,"本地验证通过后受控部署,复检 /ready、bundle、live smoke 和公网 WCM6 视觉专项;等待 iPhone12/iOS14、iPhone14/iOS16.2、Redmi K60 真机确认。","1) 部署后 /ready 正常;2) bundle findings=0;3) live smoke PASS;4) 公网 WCM6 视觉专项通过;5) 真机确认前 R6-ISSUE-001 不关闭。","流程级验证:bash deploy/trialrun/deploy.sh;node scripts/qa/check-public-bundle-copy.mjs https://oa.hyinda.com;LIVE_SMOKE_BASE_URL=https://oa.hyinda.com bash scripts/qa/run-live-smoke-readiness.sh;E2E_MODE=live 运行 WCM6 专项;人工真机确认。",bash|playwright|manual,DONE,DONE,TODO,deploy/trialrun/*|docs/trialrun/*.md,["MME6-6"],MME6-7 automated completed:已部署公网,/ready 正常,public bundle findings=0,live smoke readiness PASS,真实 OCR 样票返回重复发票可解释终态且测试通过,公网 WCM6 视觉专项 8 passed,报告 artifacts/qa-flow/live-smoke-readiness-20260511-230918;真机通过前 R6-ISSUE-001 保持 open/PAUSED,R6-3 不启动。默认不覆盖远端 .env。
|
||||
|
无法渲染此文件,因为它包含了意外字符,其位于第 3 行和第 575 列。
|
在新工单中引用
屏蔽一个用户