74 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.
This spec keeps hyb-oa-specific React/Vite, shared-component, business-boundary
and verification contracts. Do not copy broad aesthetic guidance from
frontend-design into this file; use the skill directly for design judgment.
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. - Default product framing is a small-team Chinese workbench for domestic tech
startups with fewer than 10 people. User-facing copy should be natural
Chinese; avoid English product words such as
Portal,DashboardandWorkflowunless they are internal test fixtures or technical identifiers. - 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 current Trellis task; 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: Page Template Taxonomy
What: hyb-oa frontend pages use six layout templates. New or redesigned pages must pick one primary template before implementation:
工作台总览: Portal and mobile home. Compact summary, today's actionable items, conditional progress/blocker/reminder sections.任务处理列表: workflow task queues. Pending summary, task list, processed records and advanced filters.业务台账列表: reimbursement, contracts, projects, payments, AP and invoices. Page-header primary action, command bar, list/table body and folded ledger tools.主从工作台: procurement, assets and inventory checks. Left/index list plus right/current-object detail and actions.详情工作区: reimbursement detail, workflow task detail, project detail and future contract detail. Overview, facts/evidence, right-side summary/command panel and history.管理配置页: people, organization, master data, approval rules, workflow definitions, feature flags and audit logs. Grouped settings, searchable tables and confirmed destructive/configuration actions.
Contracts:
- A page has one primary template. Local sections may reuse shared components, but the page must not mix ledger, configuration, detail and dashboard patterns without an explicit Trellis task.
- Mobile is the responsive expression of these templates: top status/focus, card list or sectioned detail, bottom primary action. Do not create a PC shell inside mobile routes.
- B-class business pages should usually choose
业务台账列表or主从工作台. Use a ledger when records open into details; use master-detail when users select one object and edit/process it in the same workspace. - A-class task pages must not drift into configuration surfaces. C-class configuration pages must not appear as ordinary employee task pages.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright or screenshot checks for changed A-class, mobile or shared template surfaces.
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 role-aware task navigation. The mental model is a task-first primary list plus collapsed更多; enabled OA-owned business ledgers such as contracts, procurement, assets and projects should not be hidden in更多by default when the current role has access. Management configuration is represented by one管理entry instead of many sidebar rows.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.
Navigation Rules:
- Sidebar entries should be role-aware and task-first for domestic tech startups under 10 people; do not expose all permission-allowed modules as a default module catalog.
- Do show enabled, permission-allowed day-to-day business ledgers directly in
the primary sidebar, including
合同,采购,资产and项目when relevant.更多is for low-frequency, frozen, staged or occasional entries, not a place to bury common work. - Approvers see
待我处理; ordinary employees should not see待办or审批待办in the sidebar by default. - PC leave navigation uses
请假记录unless the current task explicitly opens OA emergency leave submission. - HR/attendance pages must encode WeCom ownership in the UI surface: employee
leave and mobile leave are record-first/read-only, and OA emergency forms are
hidden unless
leave.manage; attendance correction forms are hidden unlessattendance.manage. Labels must sayOA 应急/提交应急审批/提交应急修正instead of generic提交. - When a page repeats the same title in the page header and a content section,
Playwright assertions should target the page header (
h1or the header test id) rather thangetByRole("heading", { name }), which becomes ambiguous. 个人设置stays in the topbar account menu. Notifications stay in the topbar bell and notification center.- Finance labels should use work names such as
付款,应付账款and票据; internal platform words likeAP 运营,ERP 集成and功能开关should be hidden behind management wording or renamed for users. 更多is a lightweight collapsed row for low-frequency, frozen, staged or occasional entries; do not add a sidebar explanation card, subtitle or onboarding copy around it.- Playwright navigation helpers should use exact names or anchored regex for
short sidebar labels such as
管理, otherwise fuzzy role-name matching can click longer labels such as预算管理.
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: Action Placement Baseline
What: Page actions, filters, ledger tools and destructive commands use one system-wide coordinate model. New and redesigned pages should not invent page-local action placement.
Contracts:
- PC page primary action lives in the page header action area
(
WorkspaceHeader/PageHeaderactions). Keep one primary action per page surface and at most two visible secondary actions. - List filters live in the first command bar below the page header. Search,
status, scope and other common filters stay on the left; ledger tools such as
export, batch, statistics, templates and advanced filters stay on the right or
inside
台账工具/更多. - Row-level actions live at the right edge of a table row or at the tail of a
card. Prefer
查看详情,查看处理and继续编辑over broad verbs that hide the result. - Detail pages keep facts and evidence in the main content. High-risk actions
such as approve, reject, return, pay, publish, delete and configuration
switching live in the right command panel or a clearly separated
detail-action-stack, with confirmation that includes the current object summary. - Form save/submit actions live at the form bottom on PC. Long forms may add a right-side summary command panel, but the same action should not be repeated in unrelated header, row and footer locations.
- Mobile pages use top status/focus content plus a bottom safe-area action surface for the primary action. Do not copy PC command bars or wide tables into mobile routes.
- Batch actions only appear after selection, as a contextual command bar or bottom sticky bar.
- Destructive, financial, approval and configuration-changing actions must be visually and structurally separated from normal navigation/edit actions.
Why: hyb-oa targets small teams where one person may switch roles many times per day. Stable action coordinates reduce relearning and help a solo developer avoid page-by-page exceptions.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright or screenshot checks when changing shared page headers, command bars, task lists, detail action panels or mobile bottom actions.
Convention: State-Driven Actions
What: Business actions are derived from explicit object state and current actor context. Do not scatter page-local button conditions across route components.
Contracts:
- Before redesigning a page with mutable business records, define or reference a state matrix. The matrix must cover object state, actor role, primary action, secondary actions, forbidden actions, reason text, risk level and confirmation requirement.
- Common lifecycle states include draft, submitted, in approval, returned or rejected, approved, pending execution or payment, completed or paid, cancelled, abnormal and archived. Use the business module's real names when they differ.
- Draft states prioritize edit, submit and delete draft. Do not show approval or payment actions there.
- In-approval states prioritize progress, withdraw and supplement-material actions. Approve, reject and return actions belong to the current user's workflow task detail, not broad ledger rows.
- Returned or rejected states prioritize correction and resubmission.
- Approved-but-not-paid states route payment work to finance or cashier views; ordinary employee views should explain the next step instead of exposing executable payment controls.
- Payment actions such as mark paid, register payment, cancel payment, batch
payment and execute payment live only in payment, finance-processing,
payment-batch detail or an explicitly current finance task panel.
Reimbursement, procurement, contract and project ledgers/details show payment
status, receipt status,
查看付款,补回单or a payment-record link instead of executable payment controls. - Paid, completed, archived and cancelled states are read-mostly. Print, export,
attachment download and history belong in
更多or audit paths when allowed. - Abnormal states must explain source, impact and next step. A red status label alone is insufficient.
- Destructive, financial, approval and configuration-changing actions require confirmation that shows the current object summary and writes audit evidence when the backend supports it.
- The frontend may hide disabled actions or show reason text, but the backend remains the source of truth for permission and state validation.
- Use destructive lifecycle verbs consistently:
删除only for drafts, non-effective temporary records or wrong materials that have not entered a business process;撤回for initiator withdrawal during allowed workflow states;取消when the business will not continue;作废when a numbered, signed, paid, published or effective object becomes invalid;归档when a completed object is locked for retention. Submitted business records should not be physically deleted from ordinary UI paths.
Why: State-driven actions prevent pages from showing buttons that the user cannot complete and keep reimbursement, procurement, contracts, assets and payments consistent as the system grows.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright coverage for changed state/action behavior, especially draft, rejected/returned, in-approval, approved, paid/completed, cancelled and abnormal states.
Convention: Role-Scoped Data Surfaces
What: The backend is the source of truth for permissions and data scope. The frontend shapes the authorized capabilities into the current task role instead of exposing every allowed tool at once.
Contracts:
- Ordinary employee views default to
我的,与我相关,我发起and需要我补充. Do not show company-wide ledgers, batch tools, export, audit, configuration, internal IDs or other people's sensitive attachments by default. - Initiator views emphasize current status, next step, supplement-material needs, approval/payment progress and whether edit or withdraw is allowed.
- Approver and processor views emphasize
待我处理and the current node task. Show approve, reject, return or transfer actions only when the server-backed task assignment says the current user can act. - Approval actions such as approve, reject, return and transfer execute only in
待我处理, workflow task detail, mobile approval detail or an explicitly current task-processing panel. Business ledger rows and ordinary business details use查看处理,查看进度,补材料or a link into the workflow task; they must not duplicate approval action buttons. - Finance and cashier views may expose authorized reimbursement, payment,
invoice, AP, receipt and exception operations. Full-scope, export, batch,
delegated creation and statistics tools belong in
台账工具,更多or role-only panels. - Owner and project-lead views emphasize team/project scope, blockers, risks and approvals. They should not drift into system configuration unless the route is a management route.
- Admin views live under
管理and cover people, organization, workflow, feature flags, integrations, audit and troubleshooting. Do not mix these controls into ordinary employee paths. - Read-only or audit views can show authorized evidence but must not show mutable edit, approval, payment, publish or disable actions.
- Do not add a global role or identity switcher. Multi-role users do not choose
员工/财务/管理员before using the system. Routes infer the most relevant task view by default. - Multi-role users may switch scope inside a specific authorized ledger, but the
default scope follows the page purpose: reimbursement starts with mine,
workflow tasks start with my tasks, ledgers start with relevant or recent
records, management starts with management scope. Use route-local scope
controls such as
我相关/我负责/财务处理/全范围. - Use explicit controls such as
我的 / 团队 / 全范围only when the server grants those scopes. Hiding controls in the frontend is not a security boundary. - Unauthorized actions should usually be hidden. When explanation is useful,
show short natural Chinese reasons such as
当前节点不是你处理,已支付单据不可编辑or仅财务可导出.
Why: hyb-oa users often wear several hats. Role-scoped surfaces keep one person's broad authority from turning every page into an admin console.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Role-focused Playwright coverage when changing visibility for employee, approver, finance/owner or admin paths.
Convention: User-Facing Identifiers And Copy Semantics
What: Ordinary product surfaces use business identifiers and natural Chinese. Internal identifiers are auxiliary evidence for audit and troubleshooting, not primary user-facing content.
Contracts:
- Use business identifiers, names or summaries as primary labels: reimbursement number, purchase request number, contract number, asset number, payment batch number and project name.
- Do not show UUID, taskId, entityId, permission code, role code, internal state code, raw payload, full local path, API path, database field name, OCR provider, debug trace, Secret or token on ordinary employee, approver, finance or mobile paths.
- Audit logs, admin troubleshooting, integration failure details, printed
evidence and export handoff files may show necessary internal IDs when
authorized. Place them in low-priority areas such as
技术信息,审计信息or排障信息; never use them as the page title, card title, button label or first ordinary list column. - Show one primary identifier for the same object in one surface. Avoid placing business number, UUID, taskId and entityId together unless the route is an audit/troubleshooting route.
- Translate technical enum values and platform words into natural Chinese:
PENDING_APPROVALbecomes审批中;REJECTEDbecomes已驳回or被退回待补正;AP Operationsbecomes应付账款;Feature Flagbecomes management wording. - Time copy should answer the business question. Prefer
已等待多久,接收于,提交于,支付于and归档于over generic更新时间when the user needs to decide what to do. - Errors and abnormal states must explain source, impact and next step in natural Chinese. Do not surface only HTTP codes, backend enum names or red badges.
- Notifications and mobile cards use the shortest useful business identifier or summary. Do not pack long technical IDs into small surfaces.
Why: Internal implementation language makes the product feel complex and unfamiliar. Business identifiers and natural Chinese keep small-team workflows legible.
Tests Required:
cd client && npm run typecheckcd client && npm run build- UI tests or screenshot review for changed list/detail/notification/mobile surfaces to confirm internal IDs and technical enum names are not visible.
Convention: Ledger List Defaults
What: Business list and ledger pages default to a light, task-oriented list. Advanced ledger capabilities remain available but must not dominate the first screen.
Contracts:
- Keep 3 to 5 high-frequency filters visible by default. Prioritize search, status, scope and date/time; add business-specific filters such as project, person or type only when they are genuinely frequent.
- The default view must match the route's main job:
我的报销,待我处理,合同台账,资产台账and similar task nouns. Do not default ordinary users into company-wide management views. - Rows and cards must answer what the object is, current state, why it relates to the current user and the next action.
- Place common filters on the left side of the command bar below the page
header. Put export, batch, statistics, templates, full-scope, advanced
filters, delegated creation and low-frequency module links in
台账工具,更多or role-only panels. - Batch actions appear only after selection, as a contextual command bar or bottom sticky bar. High-risk batch actions such as approve, pay, delete or publish require summary confirmation and result details.
- Export is not a primary page action. Explain export scope and sensitive content when relevant; finance, contract, asset and invoice exports must stay permissioned and auditable.
- PC ledgers may use pagination, sorting and density controls. Default columns should be decision-supporting fields only; low-frequency fields belong in details, column configuration or advanced filters.
- Empty states are status-specific.
没有草稿,没有被驳回,没有待处理and没有异常should not all share one generic explanatory panel. - Mobile routes do not copy PC ledger tools. Use search, status filtering, card lists and one primary action; leave complex analysis, export and broad-scope management to PC.
- Contract, procurement, project and finance ledgers use a list-to-detail
boundary. The list is for discovery, filtering, status reading and navigation.
High-risk or sensitive actions such as contract download, archive, payment,
export, batch processing, void/cancel and sensitive attachment viewing belong
in detail workspaces, detail command panels or
台账工具, with permission, audit and confirmation. - Default ledger scope follows the current task role: ordinary employees see
我发起/我相关, owners and project leads see我负责/项目相关, finance sees待复核/待付款/异常, and admins may enter or switch to全范围. Full scope, export and batch commands stay in台账工具or role-only panels, not ordinary first screens. - Contract ledgers in V1 are registration, archive, due/renewal reminder and
relation surfaces for project, procurement and payment context. Do not design
/contracts-registryas e-signature, legal-review, clause-library, version-collaboration or full CLM software. If contract approval is needed, link to the OA approval center or a separate future task instead of adding an approval workspace inside the contract ledger. - Procurement ledgers in V1 are request, approval, attachment, light
acceptance/archive and relation surfaces for project, contract and payment/AP
context. Do not design
/purchase-requestsas purchase-order lifecycle, inventory, three-way matching, supplier-lifecycle, tendering or ERP software. Approved procurement means the request was approved; it does not imply paid, received into inventory or converted into a fixed asset. - Project pages in V1 are light project ledgers for status, owner/member,
milestone/task, risk, delivery-record and related reimbursement, procurement,
contract and payment context. Do not design
/projectsas full project management software with Gantt charts, complex dependencies, timesheets, resource scheduling, OKR, portfolio management or large collaboration suites. Project pages summarize and route; source records stay in their business modules. - Finance ledgers in V1 are payment-preparation, payment-batch, receipt-audit, AP-status, invoice/OCR-status and agency-accounting handover summaries. Do not design payment, AP or invoice pages as online banking, bank-statement ingestion, ERP/general-ledger, voucher-generation, auto-reconciliation, tax filing or full accounting software. Real payment stays in offline banking or existing finance/accounting workflows; OA records status, evidence and handover summaries.
- Payment, AP and invoice pages default to task/exception visibility:
付款shows review, payment-marking, receipt and exception attention before batch creation;应付账款shows pending payment, exceptions, risks and differences before export;票据shows OCR status, failed invoices and bindable invoices before broad-scope handover tools. Batch creation, export, full-scope views and agency-accounting handover controls live in台账工具or selected-context panels, never as the first-screen primary action. - Payment actions require the finance/payment context: amount, payee or target
object, source records, offline payment explanation, evidence completeness,
receipt requirement and correction boundary. Do not place
标记已付款,取消付款,批量付款or执行付款directly in reimbursement, procurement, contract or project ledgers/details. - Cross-module relation sections are summary-and-route surfaces. Project, procurement, contract, reimbursement, asset and payment pages may show related business number/name, status, amount or quantity, owner, evidence completeness and next-step summary, then link to the owning detail/task/finance page. Do not duplicate the owning module's approval actions, payment actions, invoice/OCR processing, contract-body download, sensitive attachment actions, state machine or batch tools inside another module's relation card.
Why: The product's main complexity complaint is too many visible operations. Light default ledgers keep daily work simple while preserving advanced finance and management workflows.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright or screenshot checks when changing list filters, command
bars,
台账工具, batch selection behavior, empty states or mobile list cards.
Convention: Asset Registry Pages
What: Asset pages render FA fixed assets as a lightweight responsibility
ledger inside the unified asset registry, not as a full accounting fixed-asset
subsystem.
Contracts:
- The default
/assetsview answers where the asset is, who uses it, who is responsible for it, what state it is in and whether it needs inventory or handover. Do not lead with depreciation, accounting subjects or ERP sync. - Register physical items that must be returned, transferred, inventoried or
protected, such as computers, monitors, disks, equipment and security media.
Do not create
FAcards for ordinary consumables. - Every
FAcard needs an asset number. Physical assets that can carry labels should expose QR-label status for scan, inventory, assignment and return workflows. Assets that cannot be labeled must still expose serial number, custodian and location as the lookup fallback. - Inventory cadence is lightweight: quarterly routine checks by default, event checks for departure, transfer, repair and retirement, and monthly custodian plus location confirmation for high-risk physical assets such as backup disks, security media and critical equipment.
- Assignment, return and transfer are daily flow actions that admins may record with audit evidence. Disposal actions such as retirement, loss, sale and gift require owner confirmation, a reason and consequence summary. If compensation, money or responsibility is disputed, the asset UI records pending/confirmed outcomes only and must not complete the dispute in one click.
- Keep acquisition source, business number, owner/custodian, location, status, assignment, return, transfer, repair, retirement, inventory result and handover evidence visible in the business flow.
- Procurement or reimbursement records may expose an asset-candidate signal, but
they must not create an
FAasset card automatically after approval, submission or payment. The asset registry UI may guide admins from candidates to新建资产卡片, but the card is created only after manual verification of delivery, quantity, owner/custodian, consumable status, returns and gifts. - Move depreciation, residual value, accounting subject and monthly depreciation voucher concepts out of the OA primary UI unless a later Trellis task explicitly scopes accounting-ledger work.
- Keep classification maintenance, ERP sync, raw metadata and advanced filters behind management, collapsed or advanced surfaces so they do not dominate the asset list/detail first screen.
- Mobile asset lookup should prefer QR scan and fall back to asset number or serial number input. Do not require heavy photo inventory unless a later task explicitly scopes it.
- Asset list/detail UI may show last inventory, next inventory and overdue hints. Do not turn cadence into a complex scheduling/configuration console in the default asset registry view.
- Disposal commands must be visually separated from assignment/return/transfer commands and use confirmation that shows asset number, name, owner, current custodian, location, reason and effect on asset status.
- Electronic assets (
EA-DOC,EA-SYS,EA-REPO,EA-BKP) are metadata and responsibility indexes. Show owner, custodian/admin, permission-recovery requirement, backup or restore-verification date, sensitivity level and archive-location summary. Do not display or store source packages, secrets, tokens, full configs, real full paths or backup contents. EA-DOClist/detail views show document name, type, hash or verification summary, sensitivity level, owner, related project/contract/payment and archive-location summary. Contract text, bank statements, certificate originals, customer materials, sensitive quotes, payroll/social-security data and personal identity materials must not appear as ordinary asset-page content; route business originals through their module attachment permissions or offline controlled archive.
Tests Required:
- Asset page screenshots or E2E assertions should verify the first screen is asset-list/detail/task oriented, with classification and integration tooling demoted.
- Mobile asset scan tests should cover lookup, summary and one allowed action; mobile must not expose classification maintenance or full metadata editing. Include QR scan or manual asset-number/serial-number fallback when this surface changes.
- Electronic asset UI changes should assert that sensitive source/config/backup content and full paths are not visible in ordinary list/detail/mobile views.
EA-DOCUI changes should assert that high-sensitive originals are not rendered in ordinary asset list/detail/mobile views.
Convention: Forms, Drafts And Validation
What: Long business forms support interruption and recovery. Save draft and submit are distinct actions with different consequences.
Contracts:
- Long forms should support drafts by default when the business object requires multiple fields, line items or materials, including reimbursements, procurement, contract drafting, asset intake and payment supplement flows.
保存草稿stores progress only. It must not trigger approval, payment, publishing or external synchronization.提交enters the business workflow.- Draft save may allow incomplete data, but it must preserve entered fields, line items, attachment references and the recoverable object state.
- Before submit, run business validation and show a summary confirmation with the object summary, amount or quantity, important contract/asset/payment facts, attachment or invoice completeness, and next node or consequence.
- Material upload is type-first. Let the user choose or enter the material type before upload, then apply type-specific copy, validation, permissions, audit and display placement. Do not use one generic attachment uploader for PDF invoices, ordinary attachments, contract files, payment receipts, acceptance materials, asset materials and electronic-document indexes.
- Upload labels must describe the result, such as
上传 PDF 发票,补充付款回单,上传合同文件,补充验收材料or登记资产材料. - Validation errors must point to the field, line item, invoice, attachment,
contract material or asset section that needs work. A top-level
提交失败message alone is insufficient. - Separate blocking errors from warnings. Blocking errors prevent submit; warnings may allow users to confirm and continue when the business rule permits it.
- Server-side validation failures must preserve user input and show repair guidance in natural Chinese.
- Warn before navigation when the form has unsaved changes, including leaving the route, closing a modal, switching record or returning to the list.
- Autosave can be used as an enhancement, but the visible state must still make clear whether the object is draft, submitted or failed to save.
- Mobile forms keep only necessary fields, material upload, status explanation and a bottom safe-area primary action. Do not move admin configuration, complex configuration matrices, bulk import or workflow design into mobile forms.
- Mobile validation messages should appear near the field or material card, and bottom actions must not cover the final input.
Why: Small-team users often switch tasks mid-form. Drafts and precise validation prevent repeated re-entry and reduce support/debugging cost.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright coverage for draft save, submit validation, unsaved-change protection and server-validation failure paths when changing form behavior.
Convention: Detail Evidence Layout
What: Detail pages use one evidence-first structure so users can understand state, facts and consequences before acting.
Contracts:
- Use this order for reimbursement, workflow task, procurement, contract, asset, project and payment details: status/next step, business summary, evidence materials, risk or validation signals, approval/processing history, actions.
- The top overview shows business number or name, current state, critical amount or object facts, current handler or next node, and a clear return path.
- The first content block is
当前状态与下一步: explain where the object is, who needs to act, what happens next and whether there are blockers or warnings. - The business summary block shows the fields needed before approval or review: requester, amount, project, purchase object, contract counterparty, asset owner, payment batch and similar module facts.
- Evidence materials sit in the main content, grouped by business meaning: line items, PDF invoices, attachments, contract files, asset photos/numbers, receipts and acceptance materials.
- Risk or validation sections appear only when there is a real signal such as budget issue, duplicate invoice, missing attachment, contract expiry, asset anomaly or payment failure.
- Approval and processing history is for traceability. Keep a useful summary visible, but do not let full history crowd out current status and evidence.
- PC high-risk actions live in the right command panel or separated action stack. Mobile high-risk actions live in the bottom action surface or a confirmation panel.
- Approve, reject, return, pay, publish, delete and void actions must show the object summary and consequence before execution.
- When evidence is incomplete, change the primary action to supplement material, view issues or an explained disabled state. Do not leave users guessing from a disabled button alone.
- List and ledger rows show only evidence completeness summaries, missing
evidence hints and a detail entry. Invoice preview, attachment download,
contract file viewing, receipt download, evidence deletion and bulk packaging
belong in detail workspaces, detail command panels,
台账工具or authorized audit paths. - Sensitive evidence such as invoices, contracts, receipts and attachments must
be permissioned; download and export belong in
更多or audit paths when appropriate. - Detail evidence sections group materials by type. Do not mix invoices, ordinary attachments, contract files, receipts, asset materials and electronic-document indexes in one undifferentiated list.
- Mobile details use a top focus card, sectioned cards and bottom safe-area actions. Do not copy PC two-column detail or wide tables into mobile.
Why: Detail pages are the place where users decide whether to approve, reject, pay or supplement materials. Consistent evidence order reduces misreads and accidental actions.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright or screenshot checks when changing detail overview, evidence sections, history placement, right command panels or mobile detail bottom actions.
Convention: Mobile Lightweight Surfaces
What: Mobile and Enterprise WeChat WebView routes are lightweight action surfaces. They are not compressed PC management consoles.
Contracts:
- Mobile may support lightweight submit, supplement-material, status lookup, task handling, scanning, upload and message-deeplink flows.
- Keep mobile pages to top status or focus card, card list or sectioned detail, and bottom safe-area primary action.
- Mobile home should show compact status and today's actionable items. Do not add a full module directory or dashboard.
- Mobile home finance summaries are conditional action cards. Render them only
when the current finance/cashier user has pending payment, payment exception
or risk-review counts to handle; do not show disabled finance placeholders or
unconditional mobile
我的finance anchors. - Mobile lists use search/status filtering, cards and one primary action. Do not use wide tables, column configuration, complex multi-column filters, full-scope management, admin configuration, batch export, bulk approval or bulk payment.
- Mobile list search that filters the currently loaded list must expose the
visible label and aria label
当前列表搜索; do not imply global search with labels such as搜索报销or搜索采购unless the page actually queries a global corpus. - Mobile details use a focus card, sectioned evidence and bottom actions. Do not copy PC two-column layouts.
- Mobile forms keep necessary fields, material upload, field-local validation and a bottom action. Do not put admin configuration, workflow configuration, feature flags, statistics dashboards or bulk import into mobile forms.
- Bottom actions must account for safe area and keyboard overlap. Button text must remain readable on narrow screens.
- Dangerous mobile actions must open a confirmation panel that shows object summary and consequence.
- Ordinary mobile paths must not show internal IDs, permission codes, configuration matrices or audit troubleshooting panels.
- Enterprise WeChat remains the primary owner for daily HR/attendance actions such as leave, missed punch, outing, overtime and check-in. OA mobile shows mirror/history/exception/emergency takeover according to the business boundary.
Why: Most mobile use happens from notifications or quick context switches. Reducing mobile scope keeps the phone path fast and prevents PC admin complexity from leaking into WeChat.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Playwright or screenshot coverage for representative narrow viewports when changing mobile home, mobile lists, mobile details, bottom actions, upload surfaces or Enterprise WeChat WebView flows.
- If true Enterprise WeChat device validation is unavailable, record it as paused manual validation; do not claim full WebView acceptance.
Convention: Notifications Versus Tasks
What: Task queues and notifications have separate jobs. A task queue is for action; a notification center is for event awareness and navigation.
Contracts:
待我处理is an action list. Include only items that require the current user to process, supplement material, review, pay, approve, confirm or resolve an exception.- Task rows must have a clear next step, object summary, business state and processing entry.
- Completed items, read-only progress, announcements, successful sync notices and ordinary system messages do not belong in the pending task list.
通知中心is an event inbox for status changes, reminders, failures, sync results, workflow transitions, invoice/attachment recognition results and Enterprise WeChat delivery results.- Notifications should support read/unread, view, jump target and failure explanation. Do not rebuild the full workflow task list inside the notification center.
- Notification clicks must deep-link to the business detail, workflow task, mobile target page or failure explanation. Do not send users back to a generic notification list as the final destination.
- Notification copy should explain what happened, who or what is affected, and the next useful step. Do not expose raw payloads, internal state codes or debug fields.
- Workbench
今日待处理aggregates only actionable items. Ordinary notifications, read-only progress, completed activity and announcements are not counted as pending work. - If a notification represents real work, the backend or aggregation layer should expose it as an explicit task item; the frontend should not infer every notification is a task.
- The topbar bell is the notification entry. Do not add notification center as a default sidebar row.
- Enterprise WeChat messages are an external delivery channel. Keep message content desensitized and deep-link into the OA business or task detail.
Why: Separating event awareness from action prevents Portal, task queue and notification center from showing the same thing in three different ways.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright coverage when changing task aggregation, notification
center rows, topbar bell behavior, notification deep links or workbench
今日待处理counts.
Convention: Sensitive Data And Exports
What: Contracts, finance, invoices, receipts, payments, assets and attachments are sensitive by default. Frontend surfaces show the minimum useful summary unless a permissioned workflow requires more.
Contracts:
- Treat contract text and attachments, quotations, acceptance materials, invoices, receipts, payment information, bank accounts, supplier details, asset serial/location/owner data, personnel records, payroll/performance, audit records, original file names and export files as sensitive.
- Workbench, notifications, ordinary lists, mobile cards and Enterprise WeChat messages show desensitized summaries only.
- Ordinary surfaces must not show full bank/account numbers, full local paths, storage paths, raw payloads, full sensitive attachment names, Secrets, tokens or high-sensitive contract/finance details.
- Previewing contract text, invoices, receipts and attachments requires server-side permission checks. Frontend visibility is not a security boundary.
- High-sensitive previews should explain context or purpose when useful and record view evidence when the backend supports it.
- Download, batch download, export, print, attachment packaging, contract text export and finance ledger export must be controlled by server permissions and data scope.
- Export is never the primary first-screen action. Put exports in
台账工具,更多or role-only finance/admin panels. - Before exporting sensitive ledgers, explain scope and sensitive contents. Finance, contract, asset and invoice exports should write audit records.
- Export file names use business numbers and dates. Do not concatenate complete personal accounts, complete supplier secrets or internal filesystem paths.
- Audit sensitive operations with actor, time, object, action, scope and result where supported.
- Permission-denied and failure messages use natural Chinese without leaking full paths, permission codes, raw URLs, payloads, Secrets or tokens.
Why: The product is for small teams, but the data is still financial, contractual and operationally sensitive. Small team convenience must not turn into broad accidental disclosure.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright or screenshot checks when changing attachment preview, contract/invoice/receipt surfaces, export controls, mobile summaries, notification copy or permission-denied states.
Convention: Permission Empty And Error States
What: Permission-denied, empty and error states use natural Chinese that explains cause and next step. Ordinary users should not inspect platform internals to understand what happened.
Contracts:
- Hide unauthorized actions by default. If a route is opened directly or the user needs context, show a natural Chinese explanation and a real next step such as returning to workbench, viewing related records or contacting an admin.
- Empty states are scoped to the current filter, status or section. Explain what is absent and show one useful next step; if there is no real next step, hide the section instead of adding instructional copy.
- Error states explain business cause, impact and recovery path such as retry, supplement material, return to list or contact admin.
- Ordinary user paths must not show raw
403, API route names, permission codes, internal state codes, route stacks, full paths, raw payloads or long technical error dumps. - Admin, audit and troubleshooting routes may show the minimum technical details needed to diagnose a problem, but the business reason and next step remain primary.
- Mobile and notification targets use shorter copy, but must still include cause and next step.
Why: Small-team users do not have time to decode implementation details. Clear failure states reduce support work and avoid leaking internal platform structure.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright or screenshot checks when changing empty states, permission-denied pages, notification failure targets or shared error components.
Convention: Dangerous Action Confirmation
What: Destructive, financial, approval, configuration, batch and external
sync actions require meaningful confirmation. A generic 确定吗? dialog is not
enough.
Contracts:
- Treat delete, void, revoke, archive, restore, disable, publish, configuration switching, workflow switching and feature-flag changes as dangerous actions.
- Treat pay, batch pay, sensitive export, batch download, contract text download and attachment packaging as dangerous or high-sensitive actions.
- Treat approve, reject, return, transfer, batch approve and batch reject as approval-risk actions that need context before execution.
- Treat external synchronization, retry external write and Enterprise WeChat/OA emergency-takeover switching as integration-risk actions.
- Confirmation UI must show object summary: business number, name, requester or counterparty, amount or quantity and current state when relevant.
- Confirmation UI must explain consequences: target state, reversibility, notifications, payment/approval/configuration impact and external-system effect.
- Confirmation UI must show impact scope for batch, export, configuration and integration actions: selected count, data range, external system, Enterprise WeChat message or audit scope.
- Rejection and return require a reason. Payment, publishing, batch and configuration actions may require a confirmation word, explicit checkbox or selected reason when risk is high.
- Dangerous actions must be visually separated from normal view, edit, save and submit actions.
- Mobile dangerous actions use bottom or full-screen confirmation panels, not instant execution from an easy-to-mistap control.
- Confirmation failure must preserve user input and show result details plus the next repair action.
- Audited actions should record actor, time, object, action, scope, reason and result where backend support exists.
- Delete, withdraw, cancel, void and archive confirmations must use the exact
business verb and explain the target state. Do not label cancel, void or
archive as
删除.
Why: These actions can change finance, contracts, workflow, approvals, configuration and external integrations. Users need context before execution, and support needs an audit trail after execution.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright coverage when changing delete, payment, approval, publish/disable, batch, configuration or external-sync confirmations.
Convention: Integration Boundary And External Status
What: External-system state is conservative. OA shows facts confirmed by its own backend and explicit external acknowledgements; it does not present a queued request, frontend click or message attempt as final business completion.
Contracts:
- OA owns reimbursement, procurement, contracts, projects, payments, AP, invoices, assets, sensitive attachments, audit and OA workflow handling.
- Enterprise WeChat owns daily HR/attendance actions: check-in, leave, missed punch, outing and overtime. OA shows mirror, history, exception, audit and emergency-takeover records for those domains.
- ERP, agency accounting, bank, OCR and Enterprise WeChat messages are external capabilities or delivery channels. They do not replace OA server-side permissions or state machines.
- Show final labels such as
已同步,已发送,已付款and识别完成only when the relevant external system has returned a clear success acknowledgement. - Use in-progress labels such as
同步中,等待回执,银行处理中,识别中and消息发送中when the request has started but is not confirmed. - External failures must show source, impact and next step in natural Chinese,
such as
银行回执未返回orOCR 识别失败,需重新上传 PDF. - Do not expose raw external error codes, payloads, full URLs, secrets, tokens or debug traces to ordinary users.
- External writes, payment execution, ERP sync, Enterprise WeChat resend and OCR retry must be controlled by permissions and state-driven actions.
- Retry confirmation should explain which object will be retried, whether it may send duplicate external messages, external-system impact and audit effect.
- External sync state should not block unrelated primary flows. If it blocks a flow, show the blocker and manual repair path.
- Ordinary routes show summary, failure reason and next step. Admin, finance or troubleshooting routes may show deeper diagnostics when authorized.
- HR/attendance routes should default to Enterprise WeChat record, sync mirror or exception handling copy. Do not expose OA daily leave/missed-punch paths unless OA emergency takeover is explicitly enabled.
- Enterprise WeChat messages carry desensitized summary and OA deeplink only; they do not carry sensitive attachment text or final payment/approval actions.
- If bank, ERP, agency accounting or another integration is not connected or not confirmed, UI copy must not imply the capability already completed.
Why: External integrations are asynchronous and failure-prone. Conservative copy prevents users from trusting a state the system has not actually verified.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright coverage when changing Enterprise WeChat boundary copy, OCR status, bank/payment callbacks, ERP/accounting sync status, retry controls, external failure messages or integration diagnostics.
Convention: Verification And User-Testable Claims
What: Verification claims must describe the actual validation level. Local checks, screenshots and mock Playwright runs do not mean a user can test the change online.
Contracts:
- Local build passing means only the local code built successfully.
- Playwright passing means the specified automated path passed in the specified environment and data state.
- Screenshot review passing means only the captured viewport and state were reviewed.
- Deployment passing must identify the deployed environment, version or commit and health check result when available.
- Say
可以线上测试only after deployment, public access check, key-path smoke testing and necessary screenshot evidence are complete. - Before deployment, say
本地验证通过,尚未线上可测. - After deployment but before public access check, say
已部署,公网检查未完成. - If real-device or Enterprise WeChat WebView validation is unavailable, record it as paused manual validation. Do not substitute automation for full WebView acceptance.
- A-class page changes should keep build, focused Playwright or screenshot evidence according to risk.
- Changes touching permissions, state machines, approval, payment, Enterprise WeChat, external systems, sensitive downloads or production configuration need rollback or manual repair notes.
- Updating this design/spec documentation does not mean pages were refactored, deployed or accepted for live trial.
Why: This keeps delivery status honest and prevents the user from trying a change that has not actually reached a public environment.
Tests Required:
- Documentation-only changes: Trellis task validation, governance check and
git diff --check. - Frontend implementation changes:
cd client && npm run typecheck,cd client && npm run build, plus focused Playwright or screenshots based on affected surface.
Convention: A-Class PC Task-First Pages
What: A-class PC pages such as Portal, approvals, reimbursement list and reimbursement detail should make the current user task obvious before exposing secondary operations:
- Treat the primary persona as a small-team operator wearing multiple hats, not a dedicated OA clerk. The first screen should reduce decision cost for a founder, finance/admin owner, project lead or employee who may switch roles during the same session.
- First visible task surface should answer: what needs attention, what can be started, and where recent progress lives.
- Keep one primary action in the first screen. Allow at most two secondary
entries; move export, batch, delete, templates, complex filters, statistics
and admin/finance tools into
更多,高级 / 台账, detail actions, role-only panels or confirmation dialogs. - Do not turn small-team workflows into platform-builder surfaces by default: approval designers, broad configuration matrices, multi-level enterprise dashboards and batch admin consoles need explicit Trellis task scope.
- Explanation text should only be default-visible for risk, exception or empty states. Do not use repeated subtitles or notice cards to explain normal workflow steps that the layout can express.
- Low-frequency capabilities are hidden or moved, not removed, unless the current Trellis task explicitly deletes the capability.
- Portal/workbench first screen should use a compact status summary plus
今日待处理; do not use a persistent welcome hero, fixed报销进度button, general announcement feed, or folded placeholder sections such as团队与通知,角色重点or试点观测摘要. - Workbench sections after
今日待处理must be conditional:团队卡点only for real blockers,管理提醒only for real admin/trial issues, and我的进度only for reliable status updates. Empty data should disappear, not render as collapsed drawers or statistic cards. - Each workbench action row should state what the item is, why the current user is involved, current status/timing, and one next action. Do not represent raw application counts as progress unless the payload includes an actionable or status-level signal.
- PC reimbursement list defaults to the initiator's own forms even for users
with finance/approval roles. The first screen may use task cards for
rejected corrections, drafts and reviewing progress; ledger/export/batch,
proxy submit, templates and travel-linking remain secondary and must be hidden
unless the current user has a real matching capability. Row workflow copy
should distinguish
待你处理from read-only当前节点.
Why: hyb-oa serves small teams with overlapping roles. Core pages must make the next click clear for ordinary employees and approvers, while keeping finance and admin tools available without dominating the default path.
Tests Required:
cd client && npm run typecheckcd client && npm run build- Focused Playwright or screenshot checks for changed A-class PC pages, asserting the task surface, primary action and secondary/advanced entry behavior.
Convention: Approval Task List Defaults
What: PC approval task lists such as /workflow/tasks should make
查看处理 the default row action. List-level 通过 is disabled by default unless
a later Trellis task adds an explicit backend eligibility contract.
Contracts:
- The row must answer what the item is, who requested it, why it is assigned to the current user, how long it has waited, and the public business reference.
- History entry text should be explicit, such as
已处理记录; avoid user-facing高级 / 历史on the default task surface. - Time labels should prefer
已等待多久and接收于over database-shaped labels such as更新时间when the source field is task creation/arrival time. - HR/attendance items owned by Enterprise WeChat, including leave, missed punch, outing, overtime and check-in related approvals, must not show OA list-level quick approval. OA may show mirror/history/status/exception context and emergency-takeover records according to the business boundary, but normal approval remains in Enterprise WeChat.
- Reimbursement, procurement, travel, contract and other amount/evidence-heavy
OA-owned tasks should route through
查看处理first. - Business ledgers and ordinary business details must follow the same rule:
show the task entry or progress, but do not place
通过,驳回,退回or转审directly in reimbursement, procurement, contract, project or asset tables/details. - Future list-level quick approval requires the backend to expose an explicit
eligibility flag such as
quickApproveEligible=true, plus task-domain and audit semantics in the current Trellis task. Frontend heuristics based only on entity type, duration or row text are not enough. - If list quick approval is reintroduced later, its confirm dialog must still explain action consequences and include the specific task summary.
Why: Small-team approvers should build the habit of opening the task detail before approval, and the OA/Enterprise WeChat ownership boundary must stay clear for HR/attendance workflows.
Convention: Workbench Onboarding And Profile Scope
What: PC workbench and account settings should stay task-first, not become training or permission-maintenance surfaces:
- Do not add a persistent
快速上手/ onboarding checklist to the workbench by default. If first-login guidance is needed, use a dismissible welcome dialog with at most three real business entries. - Welcome or onboarding entries must point to executable user tasks, such as
处理待办,提交报销or请假; do not use explanatory entries like了解流程, and do not route users to settings or notifications as a substitute for task guidance. 个人设置default content is personal profile, password/security, notification preference and Enterprise WeChat binding. Organization, report line and role summary may be folded under账号详情; permission code lists and full employee dossier fields stay out of the default view. Do not add a default查看员工档案/ employee-maintenance jump from the ordinary profile page; profile fields are read-only personal context, while dossier maintenance belongs to人员/管理.- Keep account settings separate from admin configuration.
个人设置may show personal profile, password/security, notification preferences and Enterprise WeChat binding only. Organization maintenance, role assignment, approval rules, feature flags, master data, audit logs, employee maintenance and system configuration belong under管理, not the ordinary profile route. - Mobile
我的and个人设置must not expose an admin matrix or raw internal labels. Hide管理入口/人员管理/组织架构/系统设置from mobile我的, and map account status plus role codes to Chinese labels before display.
Why: Small teams need fewer default decisions. Persistent onboarding and permission-heavy profile pages make ordinary users inspect system internals before doing work.
Tests Required:
- Focused Playwright coverage for changed workbench or profile routes.
- Screenshot evidence for first-login welcome, workbench first screen and profile default view when changing these surfaces.
- Workbench baseline screenshots must explicitly clear onboarding localStorage
such as
hyb_oa_show_welcomeandhyb_oa_onboarding_activebefore capture, unless the test is intentionally verifying the welcome dialog.
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.