SNAPSHOT W7 已部署稳定态 — 凯迪ERP+OA一体化平台 (MET 73.3%)

恢复点(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>
This commit is contained in:
Qiufeng
2026-06-15 19:19:15 +08:00
co-authored by Claude Opus 4.8
commit 5e51dc3f56
10584 changed files with 2501339 additions and 0 deletions
+239
View File
@@ -0,0 +1,239 @@
# 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/erp` before 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.css` is the style entry and imports the ERP design system files.
- `src/styles/tokens.css` owns color, spacing, radius, typography, control height, table height, card density, and shadows.
- `src/styles/base.css` owns global element defaults such as box sizing, body typography, and base surface color.
- `src/styles/element-overrides.css` maps Element Plus variables and base component styling to ERP tokens.
- `src/styles/erp-patterns.css` owns reusable ERP classes such as forms, panels, cards, metrics, tables, status lines, menus, breadcrumbs, drawers, upload, empty, skeleton, and detail descriptions.
- `src/styles/modern.css` owns the application shell, top menu, left menu, route layout, and existing domain-specific layout patterns, and is imported directly by `src/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:
1. `ErpPageHeader` for module position, domain title, short operational description, and the one primary command for the page.
2. Search or filter area with `ErpSearchForm` when fields come from metadata, or wrapper-owned compact controls when the page only has one or two fixed filters.
3. State summary using metric cards, queue rows, alerts, or `ErpStatusTag` when the state changes what the administrator should inspect next.
4. Main data area with `ErpDataTable` for record lists, remote entity rows, or route-owned rows.
5. Detail entry through the table drawer or `ErpDrawer`; keep long record facts out of inline expanded rows.
6. 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 `ErpTabbedDataPanel` when 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 `count` when each tab represents a queue size; use `status` when the tab needs a short state label such as Ready, Review, or Processing.
- Use `dense` for 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 `ErpDataTable` for business records: orders, invoices, payments, requirements, shipments, inventory items, parties, work efforts, requests, content records, system jobs, and entity-backed rows.
- Use the `rows` prop when the page already owns a filtered list. Use `dataSource` when 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`; `ErpDataTable` already 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 `ErpSearchForm` above 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-table` and `.erp-dense-pagination` only 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 `ErpSearchForm` when 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 `ErpLookup` for 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 `ErpEntityForm` for 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
- `ErpAppShell` owns top-level navigation and the left menu.
- Business pages should receive navigation context rather than rebuilding it.
- Use `ErpPageHeader` breadcrumbs for page-level location.
- Use `ErpPageHeader` on 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, or `ErpActionBar`.
- 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-menu` only for page-local secondary navigation.
- Use `.erp-horizontal-menu` for 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-panel` or `.erp-work-area` for framed work sections.
- Use `.erp-card` only for individual repeated items, not for whole page sections.
- Use `.erp-metric-card` for 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`, or `ErpTabbedDataPanel`; those wrappers already provide the working surface.
## Status, Alerts, and Feedback
- Use `ErpStatusTag` for 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-line` for state rows that need short text plus a state color.
- Use Element Plus alerts with `.erp-status-alert` for 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-descriptions` classes where applicable.
## Upload
- Use `ErpUpload` or the upload field support inside `ErpEntityForm`.
- 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-upload` for shared upload styling when direct Element Plus upload is unavoidable.
## Actions
- Use `ErpActionBar` for 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 `ErpActionBar` when 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-stack` and `.erp-action-button` for custom action groups that cannot use `ErpActionBar`.
## 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-menu` only 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.css` or 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?