恢复点(restore point)。别人改崩后可 git reset --hard 回到此提交。 == 此快照内容 == - 后端 oa-backend: 734 控制器 / 711 实体 (Spring Boot 3.2.5 + SQLite, 端口8091) - 前端 modern-ui/app: Vue3+Vite, 约700页 (构建产物已在 oa-backend/src/main/resources/static) - 数据库 oa-backend/data/oa.db: 含全部演示数据 (强制入库, 6.6MB) - 交接文档 go.md + go-code-reference/endpoints/entities/database.md - 多代理建设脚本 .claude/wf-*.js == 状态 == - 对 凯迪科技ERP_20260507.xlsx 合规 MET ~73.3% (PARTIAL 75: 34可建+6种子/bug+35外部硬天花板) - 安全: 5轮红队+5轮复检, default-deny分级鉴权, 连续零可利用 - W3~W7 累计补完436缺口; W8末轮(40缺口)为半成品(源码树可编译但未集成) - 运行: cd oa-backend; java -jar build/libs/oa-backend-0.1.0.jar --server.port=8091; admin/123456 == 排除(gitignore, 可再生) == node_modules / oa-backend/build / .jdks / *.log / Backup-ERP-* / 弃用的OFBiz核心(只保留modern-ui) 完整文件夹备份见同目录 Backup-ERP-20260615-191517/ (含上述全部, 仅缺 node_modules) 时间戳: 20260615-191517 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
18 KiB
18 KiB
UI Handbook
This handbook defines how business pages in the modern ERP app should use Element Plus through the local ERP wrapper layer. It is the practical companion to DESIGN.md.
Wrapper-First Rule
- Start with
src/components/erpbefore composing raw Element Plus controls. - Use wrappers for shared behavior, state handling, density, labels, and administrator-facing copy.
- Use local page CSS only for page-specific grid placement or one-off domain composition.
- Do not scatter colors, spacing, radius, table density, or state styles across business pages.
- When two pages need the same arrangement, promote it into an ERP wrapper or a class in
src/styles/erp-patterns.css.
Style and Token Ownership
src/styles/erp-ui.cssis the style entry and imports the ERP design system files.src/styles/tokens.cssowns color, spacing, radius, typography, control height, table height, card density, and shadows.src/styles/base.cssowns global element defaults such as box sizing, body typography, and base surface color.src/styles/element-overrides.cssmaps Element Plus variables and base component styling to ERP tokens.src/styles/erp-patterns.cssowns reusable ERP classes such as forms, panels, cards, metrics, tables, status lines, menus, breadcrumbs, drawers, upload, empty, skeleton, and detail descriptions.src/styles/modern.cssowns the application shell, top menu, left menu, route layout, and existing domain-specific layout patterns, and is imported directly bysrc/main.ts.
Use tokens such as --erp-space-3, --erp-control-height, --erp-table-row-height, --erp-radius-xs, --erp-color-border-soft, and --erp-color-surface-quiet instead of hard-coded values.
Page Structure
Use this order for business pages:
ErpPageHeaderfor module position, domain title, short operational description, and the one primary command for the page.- Search or filter area with
ErpSearchFormwhen fields come from metadata, or wrapper-owned compact controls when the page only has one or two fixed filters. - State summary using metric cards, queue rows, alerts, or
ErpStatusTagwhen the state changes what the administrator should inspect next. - Main data area with
ErpDataTablefor record lists, remote entity rows, or route-owned rows. - Detail entry through the table drawer or
ErpDrawer; keep long record facts out of inline expanded rows. - Secondary executable actions through
ErpActionBar; use a right-side panel only when actions need supporting context.
For common domain pages, prefer ErpDomainAdminView because it already combines header, search, metrics, queue, table, side panel, and detail drawers.
Component Choice Matrix
| Need | Use | Notes |
|---|---|---|
| Application shell, left menu, top menu | ErpAppShell |
Do not duplicate global navigation inside pages. |
| Page title and breadcrumbs | ErpPageHeader |
Use crumbs and the actions slot for page-level commands. |
| Domain management page | ErpDomainAdminView |
Best default for order, product, party, accounting, facility, operations, content, marketing, HR, and similar workspaces. |
| Data listing | ErpDataTable |
Includes loading, empty, unavailable, error, pagination, sorting, status cells, and detail drawer. |
| Search filters | ErpSearchForm |
Metadata-driven fields, lookup, option loading, reset and submit. |
| Entity create or edit form | ErpEntityForm |
Use for submit-oriented fields and disabled state handling. |
| Status label | ErpStatusTag |
Use for row status, queue state, and record detail status. |
| Action group | ErpActionBar |
Use for executable actions, disabled reasons, running state, and overflow. |
| Status-grouped data panel | ErpTabbedDataPanel |
Use when one data panel needs stable tabs, header actions, and table or queue content. |
| Record detail | ErpDrawer or table drawer |
Prefer drawer over expanding large inline detail blocks. |
| File selection | ErpUpload or upload field in ErpEntityForm |
Keep upload copy and permission behavior consistent. |
| Lookup field | ErpLookup through form wrappers |
Use for party, product, order, and related entity selection. |
Tabbed Data Panels
- Use
ErpTabbedDataPanelwhen one work area contains the same kind of records split by operational state, queue, or ownership. - Good fits: sales orders by fulfillment state, procurement requirements by approval state, inventory exceptions by facility, accounting documents by close state, content items by publish state, and work requests by assignment state.
- Keep tabs stable across refreshes. Do not create tabs from every transient filter value; use filters inside the active tab for dates, owner, keyword, and related entity.
- Put
ErpDataTable, a compact queue list, or a focused review panel in the default slot. Search, pagination, and row details stay owned by that inner content. - Use
countwhen each tab represents a queue size; usestatuswhen the tab needs a short state label such as Ready, Review, or Processing. - Use
densefor secondary panels inside a wider workspace. Leave normal density for the main record panel. - Use the actions slot for panel-level refresh, assignment, export, create, or batch commands that apply to the active tab. If the action applies to a selected row, keep it in the table row or detail drawer instead.
- Do not use it for whole-page route navigation, decorative tab stacks, or unrelated datasets that do not share columns or workflow.
Tables
- Use
ErpDataTablefor business records: orders, invoices, payments, requirements, shipments, inventory items, parties, work efforts, requests, content records, system jobs, and entity-backed rows. - Use the
rowsprop when the page already owns a filtered list. UsedataSourcewhen the table should load an entity list and keep the source tag, search, refresh, pagination, and unavailable state together. - The wrapper displays up to 12 visible data columns and then the fixed action column. If a workflow needs more facts, move secondary facts into the drawer or a support panel instead of widening the table.
- Put status fields through
ErpStatusTag;ErpDataTablealready detects status-like column names for standard cells. - Keep row details in the table drawer unless the page has a domain-specific drawer with stronger record context.
- Use pagination for remote, large, or repeatedly refreshed record sets. Default scan size is 20 rows; 10 is suitable for narrow panels, 50 or 100 for audit-heavy pages.
- Keep table search in the source toolbar for broad keyword search. Use
ErpSearchFormabove the table for structured filters such as party, product, facility, status, date range, and owner. - Preserve built-in loading, empty, unavailable, and error states. Do not replace the whole page when only one table source fails.
- Use
.erp-tableand.erp-dense-paginationonly when a wrapper cannot be used, such as a route renderer that supplies specialized table slots.
Table layout rules:
- Primary identifier or name comes first.
- Status and date columns stay visible when possible.
- Amount columns align right.
- Action columns stay narrow and predictable.
- Long secondary values use muted subtext and ellipsis.
Table density rules:
- Main work tables use compact small rows from
ErpDataTable; this is the default ERP density. - Dense side tables should show 5-8 rows and avoid multi-line cells.
- Audit or exception tables may show 20-50 rows, but must keep identifier, state, timestamp, owner, and action columns visible.
- Do not increase row height to carry descriptions. Put descriptions in the drawer, a tooltip, or muted subtext under the primary value.
- Keep toolbar, total count, and pagination visible near the table so operators can tell whether they are seeing a filtered subset.
Search Forms
- Use
ErpSearchFormwhen query fields come from screen metadata, entity definitions, adapter blocks, or an action contract. - Use direct compact controls only for one or two page-local switches such as status, facility, or active tab. Once the page has three or more structured fields, use
ErpSearchForm. - Place search forms above the table or inside the domain wrapper's control area. Do not place a full search form inside a table body.
- The wrapper shows up to 16 visible fields. Put the most operational fields first: identifier, status, related party/product/facility, date range, owner, and free text.
- Use
ErpLookupfor related records rather than free text when the domain has a known entity. - Keep top labels and compact controls. Avoid placeholder-only forms; labels must remain visible.
- Preserve reset and submit behavior. The action row also carries form status such as queryable, submittable, login required, readonly, or processing.
- Put rarely used filters behind a drawer or collapsible panel, but keep the current filter state visible near the table after applying it.
Search form layout:
- Desktop: four compact columns when space allows.
- Medium width: two columns.
- Narrow width and drawers: one column.
- Actions align to the end using
.erp-form-actions.
Entity Forms
- Use
ErpEntityFormfor create, edit, and submit-oriented flows. - Use one column inside drawers and dialogs.
- Use two columns in wider page panels only when fields are short and related.
- Show readonly values with wrapper readonly display, not disabled inputs unless the value belongs in a form control.
- Show disabled reasons near the form or action area.
- Keep submit actions in a stable bottom action row.
Navigation
ErpAppShellowns top-level navigation and the left menu.- Business pages should receive navigation context rather than rebuilding it.
- Use
ErpPageHeaderbreadcrumbs for page-level location. - Use
ErpPageHeaderon every route-level admin page, including domain workspaces, entity search pages, and operational consoles. - Header actions are for page-level commands such as create, refresh, export, or open a global action. Row-specific commands stay in
ErpDataTable, the drawer, orErpActionBar. - Keep the page description to one sentence that states the operator's job: which records are managed, which queue is handled, or which state is monitored.
- Use
.erp-side-menuonly for page-local secondary navigation. - Use
.erp-horizontal-menufor top-level tabs or route groups inside the shell. - Top menu items should be short domain labels.
- Left menu groups should be stable and scan-friendly.
Breadcrumb rules:
- First item is the admin workspace or module root.
- Middle items are domain or sub-area.
- Last item is the current page or record label.
- Breadcrumb text should be business-facing and concise.
Cards, Panels, and Metrics
- Use
.erp-panelor.erp-work-areafor framed work sections. - Use
.erp-cardonly for individual repeated items, not for whole page sections. - Use
.erp-metric-cardfor numeric summaries. - Use density variants deliberately:
- Large: first-screen domain summaries with a number, short label, and one operational hint, such as open orders, exceptions, value at risk, or jobs running.
- Medium: normal panel item, queue card, or record group that carries a title, one secondary line, and one status or action.
- Small: row summary, action candidate, handoff, warning, or compact queue item in a side panel.
- Mini: numeric counters and short KPI chips inside a header or compact workspace.
- Avoid nested cards.
- Use neutral surfaces; state color belongs on a side border, tag, alert, or icon.
- A card must help an operator compare, choose, or act. If it only wraps text, use a heading, list row, or panel section instead.
- Large cards should be rare on record-heavy pages; use them for the top 3-4 domain measures, then return to tables.
- Medium and small cards may repeat in grids or side panels. Keep their internal text short enough that the grid height remains stable.
- Do not use cards as section containers around
ErpDataTable,ErpSearchForm, orErpTabbedDataPanel; those wrappers already provide the working surface.
Status, Alerts, and Feedback
- Use
ErpStatusTagfor record, queue, tab, and drawer labels when the value is a business state such as Approved, Review, Created, Processing, Error, Cancelled, Ready, Packed, or equivalent domain wording. - Use status tags in table cells, queue rows, selected record headers, and compact metric cards. Avoid placing multiple status tags in the page header unless they describe the whole page.
- Keep the source status from the data, then map display labels through the wrapper. Do not invent local color classes for every domain state.
- Use
.erp-state-linefor state rows that need short text plus a state color. - Use Element Plus alerts with
.erp-status-alertfor warnings or errors that affect a whole panel. - Pair every color with text.
- Place state messages near the affected control or table.
State expectations:
- Loading: indicate what is loading.
- Empty: explain the current filter or missing selection.
- Error: name the affected area and keep other controls usable.
- Disabled: explain why the action cannot run.
- Success: keep feedback brief and tied to the completed action.
Dialogs and Drawers
- Use drawers for record details, edit forms, action setup, and side-by-side review.
- Use dialogs for short confirmations or focused blocking decisions.
- Drawer titles must identify the record or action.
- Drawer content should use one-column forms, descriptions, timelines, or action lists.
- Long detail content should be grouped with headings and descriptions.
- Keep primary and secondary actions at the bottom or in a stable action row.
- Use
.erp-drawer,.erp-dialog, and.erp-detail-descriptionsclasses where applicable.
Upload
- Use
ErpUploador the upload field support insideErpEntityForm. - Keep upload areas compact and connected to the form they affect.
- Show file selection state and any permission note close to the upload control.
- Do not create custom drag areas with local CSS when the shared upload wrapper is enough.
- Use
.erp-uploadfor shared upload styling when direct Element Plus upload is unavoidable.
Actions
- Use
ErpActionBarfor executable business actions returned by a route, adapter block, service contract, or selected record context. - Use the page header for one page-level primary command. Use
ErpActionBarwhen there are multiple executable choices, permission-dependent actions, batch commands, or a need to show why an action cannot run. - Primary action appears first and uses primary styling. Destructive actions use danger styling and clear labels.
- Normal mode shows up to four primary buttons before overflow. Compact mode shows up to two; use compact mode in side panels, drawers, and secondary consoles.
- The wrapper shows enabled count, disabled reason, running state, success, warning, and error feedback. Do not duplicate that feedback with page-local banners unless the whole panel is affected.
- Disabled actions must expose a reason through the action definition. A disabled button without a reason is not acceptable for administrator workflows.
- Running actions show button loading and should not shift layout.
- Use
.erp-action-stackand.erp-action-buttonfor custom action groups that cannot useErpActionBar.
Top Menu and Left Menu
- Top menu:
- Use shell-owned top navigation.
- Keep labels short and domain-oriented.
- Active state uses the ERP primary token and a restrained underline.
- Left menu:
- Use shell-owned left navigation for modules and durable route groups.
- Use
.erp-side-menuonly for local subnavigation. - Keep item height aligned with the 38px menu rhythm.
- Active state uses primary color and a left border, not a filled pill.
Empty, Loading, and Error States
- Empty states use Element Plus empty components or
.erp-empty-state. - Loading states use wrapper loading behavior, Element Plus loading, or
.erp-skeleton. - Error states should not replace the whole page unless the whole page is unusable.
- For tables, keep the toolbar and search visible during failures.
- For forms, preserve entered values when an option load or submit action fails.
Responsive Layout
- Use CSS grid and wrappers that can collapse cleanly.
- Search forms should move from four columns to two and then one.
- Metrics should wrap instead of shrinking text below readable size.
- Side panels move below the main table on narrow widths.
- Drawers keep one-column content and readable labels.
- Do not scale font size with viewport width.
Accessibility and Interaction
- Keep visible focus behavior from Element Plus and token overrides.
- Do not remove native labels from forms or headers from tables.
- Icon-only buttons require accessible labels or tooltips.
- Use buttons for actions and links for navigation.
- Keep hover states helpful but nonessential.
- Do not communicate status by color alone.
Content Rules
- Write for administrators: short, operational, and specific.
- Use verbs for buttons: search, reset, refresh, create, save, assign, approve, cancel.
- Use nouns for sections: filters, records, details, actions, queue, status.
- Avoid visible implementation wording.
- Avoid promising behavior that the page cannot currently perform.
Local CSS Rules
- Business pages may add local classes for layout only when no wrapper or pattern exists.
- Local CSS should reference ERP tokens and stay narrowly scoped.
- Do not redefine Element Plus button, input, table, tag, menu, or card styles inside a page.
- Do not add hard-coded state colors in pages.
- If a layout pattern appears in multiple pages, move it into
src/styles/erp-patterns.cssor an ERP wrapper.
Review Checklist
- Does the page use the right ERP wrapper for shell, header, table, form, status, actions, detail, and upload?
- Are tokens used instead of hard-coded color, spacing, radius, and table density?
- Are search, data table, state labels, action area, detail entry, empty, loading, and error states visible?
- Does the page avoid decorative card stacks and local style drift?
- Is copy business-facing and useful to an administrator?
- Does the page work at desktop, medium, and narrow widths?