17 KiB
Frontend React / Vite / Design
Source Of Truth
Frontend visual and interaction design uses the installed frontend-design
skill as the primary design authority. docs/产品设计规则.md remains a product
experience and business-boundary fact source, not a visual, brand or aesthetic
rulebook. For PC/mobile/WeCom pages, add Playwright or visual verification when
reasonable.
Rules
- Use existing React/Vite/Tailwind patterns and shared components before adding page-local UI systems.
- When
frontend-designand older project visual rules conflict, followfrontend-designfor visual direction while preserving security, privacy, Trellis, deployment and business data boundaries. - PC pages should keep dense but orderly OA layouts: clear header, filters, table/list, status, details and predictable actions.
- Mobile pages must reuse the existing unified mobile shell, card/list rows,
safe-area and sticky action patterns unless the current task intentionally
redesigns them with
frontend-design. - Do not add decorative landing-page styling to operational OA pages.
- Run
cd client && npm run typecheck && npm run buildfor frontend changes.
Frozen / Boundary Items
Frozen modules and Enterprise WeChat-owned HR/attendance entries must be labeled or hidden according to the active Issue; do not silently re-enable them.
- Use the shared
WorkspaceNoticepattern for trial boundaries, safety notes, and post-trial capabilities instead of page-local warning blocks. - Trial-facing PC lists must hide obvious TEST/SMOKE records by default when a page-level toggle exists; the toggle may reveal them for troubleshooting.
Scenario: Business Flow Tests And Frozen Modules
1. Scope / Trigger
- Trigger: Playwright or QA shell tests need to create workflow data while some product modules are frozen for launch.
- Applies to
client/tests/e2e/**,scripts/qa/run-business-flow-gates.sh, and frontend route/permission assertions.
2. Signatures
- QA command:
BUSINESS_FLOW_GROUPS=<groups> bash scripts/qa/run-business-flow-gates.sh local. - Frozen-module API expectation: non-admin launch roles may receive
403for frozen module list/create/submit endpoints. - Enabled workflow test data sources should use active entities such as leave, reimbursement or procurement unless the task explicitly reopens the frozen module.
3. Contracts
- Do not use a frozen module as fixture setup for an unrelated enabled feature. Example: mobile approval offline sync should not create a travel request when travel permissions are intentionally frozen.
- Permission direct-access tests must assert the frozen contract directly, such
as employee
GET /api/travel-requests?...returning403. - UI route smoke may still verify that a frozen page displays a boundary state without entering a management or write-capable mode.
- Do not loosen roles or seed permissions merely to make old E2E data setup pass.
4. Validation & Error Matrix
- Frozen role calls frozen module create/submit/list endpoint ->
403or the documented feature-gate status. - Enabled workflow feature needs pending task data -> create data through an enabled workflow entity.
- E2E fails with
PERM_001while setting up unrelated feature data -> update the test data source before changing app permissions.
5. Good/Base/Bad Cases
- Good: mobile approval offline test creates a submitted leave request, then verifies pending-task deep link, offline queue, sync success and conflict.
- Base: travel-specific tests are skipped or admin-scoped while travel remains frozen.
- Bad: grant employee
travel.createonly so a mobile approval test can build a fixture.
6. Tests Required
- Focused E2E group that previously failed.
- Full affected business-flow group after the focused fix.
cd client && npm run typecheck && npm run buildwhen TypeScript test code changes.
7. Wrong vs Correct
Wrong
await createSubmittedTravelRequestViaApi({ user: EMPLOYEE });
Correct
await createSubmittedLeaveViaApi({ user: EMPLOYEE });
Convention: PC Operation List Density
What: PC list/workflow pages that combine status metrics, tabs/filters,
range controls, export and table/list content should reuse the shared operation
classes in client/src/index.css:
ops-status-stripfor compact status metrics.ops-command-bar,ops-command-bar__row,ops-command-bar__tabs,ops-command-bar__actionsandops-filter-labelfor tabs, filters and secondary actions.ops-table-focusfor the primary desktop table container.ops-inline-alertfor temporary mode hints such as batch operation notices.PrimaryTablealready appliesops-table-focusby default; page code may add responsive visibility classes such ashidden md:block, but should not recreate a separate table frame.- Finance/admin status summaries should prefer the shared
finance-status-stripandfinance-metric-cardclasses unless the task introduces a new reusable metric component.
Why: This keeps high-frequency PC pages dense and predictable without
recreating page-local Tailwind command bars. It also lets frontend-design
change the visual treatment once while preserving component contracts.
Example:
<StatStrip columns={4} className="ops-status-strip">
<MetricCard title="待办总数" value={summary.pendingTotal} />
</StatStrip>
<FilterBar className="ops-command-bar !p-3 md:!p-3.5">
<div className="ops-command-bar__row">
<Tabs value={status}>
<TabsList className="ops-command-bar__tabs !h-auto !justify-start !bg-slate-50">
<TabsTrigger value="pending">待处理</TabsTrigger>
</TabsList>
</Tabs>
<div className="ops-command-bar__actions">...</div>
</div>
</FilterBar>
<PrimaryTable className="hidden md:block">...</PrimaryTable>
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright screenshot coverage when changing login, Portal, primary PC list pages or command-bar/table styling.
Convention: Global Shell And Page Header Baseline
What: PC page redesigns should preserve the shared Wave0-2 shell and header baseline instead of recreating page-local wrappers:
AppShellLayoutowns the PC shell background and content offset throughapp-shellandapp-shell-main.SidebarandNavLinksown primary navigation grouping. The mental model is工作->业务->财务->管理-> collapsed更多.Topbaris a compact command surface: page title, group badge, user context, global search and notifications. Do not expand it back into a large hero.PageHeaderandWorkspaceHeadershould usepage-header-shell,page-header-shell__eyebrow,page-header-shell__title,page-header-shell__subtitleandpage-header-shell__actions.- Auth guidance and step hints may use
ux-command-note,ux-step-listandux-step-itemwhen they explain the next action without adding page-local warning cards.
Why: The shell/header baseline gives Wave3-5 pages a stable visual entry point and prevents each route from inventing a different title/action layout.
Example:
<WorkspaceHeader
eyebrow="审批"
title="审批中心"
subtitle="先看待处理,再进入详情核对依据。"
/>
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright coverage when changing
AppShellLayout,Sidebar,Topbar,NavLinks,PageHeader,WorkspaceHeader, login, Portal or other A-class pages.
Convention: Detail And Mobile Command Surfaces
What: PC detail pages and notification-like flows should reuse the Wave3
surface classes in client/src/index.css before adding page-local Tailwind
card systems:
detail-workspace-gridfor the main PC detail two-column workspace.detail-command-panel,detail-fact-gridanddetail-fact-cardfor compact status, summary, payment, export and evidence facts.detail-evidence-cardfor attachments, invoices and other proof material.detail-timelineanddetail-timeline-itemfor approval progress and history.detail-action-stackanddetail-action-cardfor approve/reject/return, payment and other high-risk command groups.notification-inbox,notification-row-cardandnotification-row-card--unreadfor PC notification streams; avoid reverting notifications to a desktop table unless a task explicitly requires tabular comparison.
Mobile key pages should reuse the mobile command classes in
client/src/styles/mobile-touch.css:
mobile-focus-cardfor the current task, current list or account summary.mobile-command-surfacefor tabs, search and filters.mobile-list-card--focusandmobile-list-card--unreadfor state emphasis.
Why: Detail pages should feel like quiet command surfaces: status, summary, primary action, evidence and history have predictable places. Mobile pages should stay card/list based, with no PC tables, no horizontal overflow and no button text squeeze.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright screenshot coverage for changed PC detail, notification and mobile pages.
- UI design rules check when changing shared visual classes.
Scenario: Auth Pages And PWA Updates
1. Scope / Trigger
- Trigger: login, password change, password recovery or other unauthenticated forms are active while the PWA service worker finds a new frontend version.
- Applies to
client/src/pwa.ts,client/src/layouts/AuthLayout.tsx, and auth routes such as/login,/change-password,/forgot-password, and future reset-password pages.
2. Signatures
- Event name:
hyb-oa:pwa-update-ready. - Event detail:
{ applyUpdate?: () => void | Promise<void> }. - Route predicate: auth input pages must be checked by pathname before calling
updateServiceWorker(true).
3. Contracts
- Auth input pages must not auto-reload when
onNeedRefresh()fires. - Auth input pages must show an explicit update prompt with a user-triggered refresh action.
- Non-auth pages may keep automatic service-worker update behavior when the task does not change broader runtime policy.
- Passwords and verification codes must stay only in React component state; do
not write them to
localStorage,sessionStorage, URL params, reports, or Trellis task evidence. - Password visibility controls must use icon buttons with accessible labels and preserve the current input value.
4. Validation & Error Matrix
- PWA update on
/login-> dispatch update-ready event and keep form state. - PWA update on
/forgot-password-> dispatch update-ready event and keep email/code/password fields in memory. - User clicks refresh in the prompt -> run the captured update handler.
- User dismisses prompt -> no reload and no form reset.
- Password reset request returns success for any email -> show generic sent message; do not reveal whether the account exists.
5. Good/Base/Bad Cases
- Good: user is typing a password, update prompt appears, typed values remain.
- Base: user is on a normal portal page, PWA update can refresh per existing runtime behavior.
- Bad: service-worker update auto-refreshes an auth form and clears credentials.
- Bad: tests use real-looking personal email addresses or persist example passwords outside the test file.
6. Tests Required
- Frontend typecheck and build.
- Focused Playwright auth UX test asserting:
- login password can be shown/hidden without losing value;
- forgot-password flow calls request-code and reset endpoints;
- auth-page PWA update prompt appears without clearing inputs.
- UI design rules check when auth page layout changes.
- Any Playwright test that renders
/login,/forgot-passwordor another auth route with mocked/api/*responses must mock/api/auth/capabilitieswithemailDelivery.ready,emailLoginCode.enabledandpasswordReset.enabled. Returning{}for unknown auth APIs can crash auth pages before the visual or navigation assertion actually runs.
7. Wrong vs Correct
Wrong
onNeedRefresh() {
void updateServiceWorker?.(true);
}
Correct
onNeedRefresh() {
if (isAuthInputPath(window.location.pathname)) {
window.dispatchEvent(new CustomEvent(PWA_UPDATE_READY_EVENT, { detail: { applyUpdate } }));
return;
}
applyUpdate();
}
Scenario: Auth Page Layout And Login Entry Hierarchy
1. Scope / Trigger
- Trigger: login, password recovery, forced password change or future unauthenticated auth forms need layout changes.
- Applies to
client/src/layouts/AuthLayout.tsx, shared auth components underclient/src/components/auth/, and auth routes such as/login,/forgot-passwordand/change-password.
2. Component Contract
- Auth routes should use one shared auth panel for brand, page title, subtitle, content and optional footer links.
AuthLayoutowns only the auth page shell: background, width constraint, centering, PWA update prompt and route outlet.- Page implementations own only their form fields, submit actions, validation messages and route-specific login-entry choices.
3. Visual Contracts
- Do not nest a form card inside another login card.
- Put the brand block inside the auth panel so logo, system name, title and form share one visual axis.
- Keep the panel width stable around the current auth-shell width; auth pages 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.
4. Login Entry Hierarchy
- Normal browser: account/password login is primary; Enterprise WeChat and OIDC entries belong below the primary submit button as secondary methods.
- Enterprise WeChat WebView: Enterprise WeChat one-click entry is primary; account/password login remains available as the fallback path.
- Enterprise WeChat entry changes must remain frontend entry hierarchy changes unless the task explicitly approves backend OAuth, binding or WeCom API work.
- Email verification-code login is a separate login mode. Do not infer it from password-recovery verification-code flows without a backend login-code contract and abuse-control plan.
5. Tests Required
- 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.
- password visibility and forgot-password navigation on
- UI design rules check and Playwright screenshot evidence when the auth layout changes visibly.
6. Wrong vs Correct
Wrong
<AuthLayout>
<Card>
<Card>
<LoginForm />
</Card>
</Card>
</AuthLayout>
Correct
<AuthPanel title="登录工作台" subtitle="账号密码登录">
<LoginForm />
<SecondaryLoginMethods />
</AuthPanel>
Wrong
<Label htmlFor="login-password">密码</Label>
<Link to="/forgot-password">忘记密码?</Link>
<PasswordInput id="login-password" />
Correct
<Label htmlFor="login-password">密码</Label>
<PasswordInput id="login-password" />
<Link className="row-start-1" to="/forgot-password">忘记密码?</Link>
Convention: Finance And Admin Console Surfaces
What: PC finance and C-class admin pages should reuse Wave4 shared classes
from client/src/index.css before creating page-local card/table layouts:
finance-status-strip,finance-metric-card,finance-metric-card__labelandfinance-metric-card__valuefor compact five-column status summaries.finance-workspace-grid,finance-command-panel,finance-list-cardandfinance-list-card--activefor payment/AP/invoice operational workspaces.admin-command-panel,admin-tile-grid,admin-tile-cardandadmin-workspace-gridfor settings, workflow, feature-flag, user, master data, notification-channel and audit pages.
Why: Finance/admin pages are lower-frequency but high-risk operational surfaces. They need dense scanability, stable command regions and clear risk hierarchy without turning every page into a bespoke Tailwind card system.
Example:
<div className="finance-status-strip" data-testid="payment-batches-summary">
<div className="finance-metric-card">
<div className="finance-metric-card__label">可处理</div>
<div className="finance-metric-card__value">{actionableCount}</div>
</div>
</div>
<div className="finance-workspace-grid">
<section className="finance-command-panel">...</section>
<section className="finance-command-panel">...</section>
</div>
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright coverage for changed finance/admin pages. The Wave4
baseline test is
client/tests/e2e/pc-finance-admin-visual-wave4.spec.ts. - UI design rules check when changing these shared classes.