From 2a11ab9da8b2e849dbb52c5cad95943b9f7d1862 Mon Sep 17 00:00:00 2001 From: shunli Date: Wed, 27 May 2026 12:04:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=A4=E8=AF=81=E9=A1=B5?= =?UTF-8?q?=20Tab=20=E7=84=A6=E7=82=B9=E9=A1=BA=E5=BA=8F=2005-26-oa-auth-l?= =?UTF-8?q?ayout-wecom-login-ux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../spec/hyb-oa/frontend-react-vite-design.md | 22 +++++++++++++++++ .../implement.md | 11 +++++++++ .../prd.md | 1 + client/src/pages/LoginPage.tsx | 24 +++++++++++-------- client/tests/e2e/login-portal-ux.spec.ts | 3 +++ 5 files changed, 51 insertions(+), 10 deletions(-) diff --git a/.trellis/spec/hyb-oa/frontend-react-vite-design.md b/.trellis/spec/hyb-oa/frontend-react-vite-design.md index 0ff88ebc..4bd1a81c 100644 --- a/.trellis/spec/hyb-oa/frontend-react-vite-design.md +++ b/.trellis/spec/hyb-oa/frontend-react-vite-design.md @@ -138,6 +138,10 @@ onNeedRefresh() { should feel like an OA workstation entry, not a marketing split hero. - Place `忘记密码?` beside the password label or directly below the password input on the right; do not bury it in help text or page footer. +- Keep the DOM/tab order aligned with the main form flow even when CSS places + `忘记密码?` visually beside the password label: username/email input -> password + input -> secondary controls. Do not render the forgot-password link before the + password input in DOM order. - Use password visibility icon buttons with accessible labels and preserve the current input value. @@ -158,6 +162,8 @@ onNeedRefresh() { - Frontend typecheck and build. - Focused auth E2E covering: - password visibility and forgot-password navigation on `/login`; + - keyboard Tab from the username/email field lands on the password input, not + the forgot-password link; - password recovery request-code and reset flow on `/forgot-password`; - normal-browser Enterprise WeChat entry as secondary CTA; - WeCom WebView Enterprise WeChat entry as primary CTA with password fallback. @@ -186,3 +192,19 @@ onNeedRefresh() { ``` + +#### Wrong + +```tsx + +忘记密码? + +``` + +#### Correct + +```tsx + + +忘记密码? +``` diff --git a/.trellis/tasks/05-26-oa-auth-layout-wecom-login-ux/implement.md b/.trellis/tasks/05-26-oa-auth-layout-wecom-login-ux/implement.md index 3bdbeb2f..b25920ab 100644 --- a/.trellis/tasks/05-26-oa-auth-layout-wecom-login-ux/implement.md +++ b/.trellis/tasks/05-26-oa-auth-layout-wecom-login-ux/implement.md @@ -5,6 +5,7 @@ - 新增共享认证页组件 `AuthPanel`,统一品牌、标题、副标题、内容区和页脚样式。 - 调整 `AuthLayout`,仅保留认证页面背景、居中容器、PWA 更新提示和路由出口。 - 重构登录页,移除卡片套卡片;普通浏览器以账号密码登录为主,企业微信/SSO 放入次级登录区。 +- 修正登录页键盘 Tab 顺序:用户名输入后先进入密码输入,“忘记密码?”视觉仍在密码行右侧但不打断主表单输入流。 - 重构企业微信 WebView 登录页层级,企业微信一键进入为主 CTA,账号密码保留为兜底入口。 - 重构找回密码页和修改密码页,复用同一认证面板,不改后端认证接口。 - 收窄企业微信入口 E2E,避免前端 UI 用例依赖真实登录和个人设置页跳转。 @@ -27,6 +28,16 @@ - `git diff --check`:已通过。 - 登录/找回密码 focused E2E:已通过,2 passed。 - 企业微信入口 E2E:已通过,2 passed。 +- 2026-05-27 登录页 Tab 顺序回归: + - `cd client && npm run typecheck`:已通过。 + - `cd client && npm run build`:已通过。 + - `E2E_BASE_URL=http://127.0.0.1:3000 npx playwright test tests/e2e/login-portal-ux.spec.ts -g "登录页提供找回密码" --workers=1 --reporter=list`:已通过,1 passed。 + - `E2E_BASE_URL=http://127.0.0.1:3000 npx playwright test tests/e2e/login-portal-ux.spec.ts -g "登录页提供|邮箱验证码登录|邮件服务不可用|找回密码流程" --workers=1 --reporter=list`:已通过,4 passed。 + - `E2E_BASE_URL=http://127.0.0.1:3000 npx playwright test tests/e2e/wecom-entry.spec.ts --workers=1 --reporter=list`:已通过,2 passed。 + - `node scripts/qa/check-ui-design-rules.mjs --strict`:已通过。 + - `python3 ./.trellis/scripts/task.py validate 05-26-oa-auth-layout-wecom-login-ux`:已通过。 + - `node scripts/qa/check-trellis-governance.mjs`:已通过;保留既有 implement/check 非 spec 上下文 warning。 + - `git diff --check`:已通过。 - 完整 `login-portal-ux.spec.ts`:认证页、找回密码、企业微信 WebView 相关 5 passed;Portal 历史文案断言 3 failed,见下方已知漂移。 - 视觉截图已生成: - `output/playwright/oa-auth-layout-wecom-login-ux/desktop-login.png` diff --git a/.trellis/tasks/05-26-oa-auth-layout-wecom-login-ux/prd.md b/.trellis/tasks/05-26-oa-auth-layout-wecom-login-ux/prd.md index c9f96323..6e2fbb70 100644 --- a/.trellis/tasks/05-26-oa-auth-layout-wecom-login-ux/prd.md +++ b/.trellis/tasks/05-26-oa-auth-layout-wecom-login-ux/prd.md @@ -57,6 +57,7 @@ - [ ] 普通浏览器下账号密码为主,企业微信登录为次级入口。 - [ ] 企业微信 WebView 下企业微信一键进入为主,账号密码为兜底入口。 - [ ] 忘记密码入口位于密码 label 右侧,密码显隐控件仍可用。 +- [ ] 键盘 Tab 顺序符合表单习惯:用户名输入后进入密码输入,不被“忘记密码?”链接打断。 - [ ] 找回密码页和改密页复用同一认证页视觉模板。 - [ ] 原有登录、找回密码、企业微信入口 E2E 仍通过。 - [ ] 前端 typecheck、build、设计规则检查通过。 diff --git a/client/src/pages/LoginPage.tsx b/client/src/pages/LoginPage.tsx index cf4d06d7..0be6e3b8 100644 --- a/client/src/pages/LoginPage.tsx +++ b/client/src/pages/LoginPage.tsx @@ -239,21 +239,25 @@ export function LoginPage() { /> -
-
+
+
+
+
+ setPassword(event.target.value)} + placeholder="请输入密码" + value={password} + /> +
+
忘记密码?
- setPassword(event.target.value)} - placeholder="请输入密码" - value={password} - />
{error ?
{error}
: null} diff --git a/client/tests/e2e/login-portal-ux.spec.ts b/client/tests/e2e/login-portal-ux.spec.ts index 7a4169a8..a80d1848 100644 --- a/client/tests/e2e/login-portal-ux.spec.ts +++ b/client/tests/e2e/login-portal-ux.spec.ts @@ -348,6 +348,9 @@ test("登录页提供找回密码、密码显隐,PWA 更新不会清空正在 await page.goto("/login"); await page.getByTestId("login-identifier").fill("user@example.test"); + await page.getByTestId("login-identifier").focus(); + await page.keyboard.press("Tab"); + await expect(page.getByTestId("login-password")).toBeFocused(); await page.getByTestId("login-password").fill("PasswordA1234"); await expect(page.getByTestId("login-password")).toHaveAttribute("type", "password");