恢复点(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>
610 lines
18 KiB
Markdown
610 lines
18 KiB
Markdown
# OFBiz Element Plus UI Lab
|
|
|
|
This directory is the UI lab for rebuilding OFBiz screens with Vue 3 and Element Plus. It is not wired to the OFBiz backend yet; it is the place to define reusable UI rules, component wrappers, and visual behavior before replacing real pages.
|
|
|
|
## Run
|
|
|
|
```bash
|
|
pnpm install
|
|
pnpm dev --port 5174
|
|
pnpm build
|
|
node scripts/generate-element-plus-inventory.mjs
|
|
```
|
|
|
|
Local preview:
|
|
|
|
```text
|
|
http://localhost:5174/
|
|
```
|
|
|
|
Direct page preview:
|
|
|
|
```text
|
|
http://localhost:5174/#/page/navigation
|
|
http://localhost:5174/#/page/catalog?group=数据展示
|
|
http://localhost:5174/#/component/table
|
|
http://localhost:5174/#/component/table?view=code
|
|
```
|
|
|
|
## File Map
|
|
|
|
```text
|
|
src/main.js
|
|
Imports Element Plus, global CSS, and mounts the app.
|
|
|
|
src/App.vue
|
|
Thin app entry. It renders ElementPlusShowcase only.
|
|
|
|
src/components/ElementPlusShowcase.vue
|
|
Page shell for the lab: sidebar, topbar, active page state, and page composition.
|
|
|
|
src/components/docs/DemoBlock.vue
|
|
Shared documentation block. Every component example uses 展示 / 代码 tabs.
|
|
|
|
src/components/showcase/
|
|
One file per documentation page. Keep examples split by component family.
|
|
|
|
src/data/showcaseData.js
|
|
Page menu, Element Plus inventory, ERP priority levels, sample order rows, metric cards, and utility functions.
|
|
|
|
src/data/elementPlusInventory.js
|
|
Generated full Element Plus inventory. Contains every local component directory, public El* export, and directive.
|
|
|
|
src/data/erpComponentDocs.js
|
|
ERP documentation layer on top of the generated inventory. Adds wrapper names, local CSS classes,
|
|
preview types, original code, ERP code, local style snippets, and OFBiz usage notes for every component.
|
|
|
|
scripts/generate-element-plus-inventory.mjs
|
|
Regenerates the full inventory from node_modules/element-plus. Run after upgrading Element Plus.
|
|
|
|
src/styles/tokens.css
|
|
ERP design tokens: color, spacing, radius, typography, shadows.
|
|
|
|
src/styles/erp-ui.css
|
|
Global UI entry. Import this once before page-specific CSS in every modern OFBiz frontend.
|
|
|
|
src/styles/base.css
|
|
Global reset and page baseline.
|
|
|
|
src/styles/element-overrides.css
|
|
Element Plus CSS variable mapping and direct Element class overrides.
|
|
|
|
src/styles/erp-patterns.css
|
|
Reusable ERP-specific classes such as .erp-table, .erp-form, .risk-dot, .component-chip.
|
|
|
|
src/styles/app.css
|
|
Lab shell and demo-only layout styles. Do not put reusable product patterns here.
|
|
```
|
|
|
|
## Element Plus Inventory
|
|
|
|
The catalog in `src/data/showcaseData.js` is checked against the local package:
|
|
|
|
```text
|
|
element-plus: 2.14.1
|
|
node_modules/element-plus/es/components: 122 directories
|
|
public El* exports from element-plus: 123
|
|
node_modules/element-plus/es/directives: 4 directories
|
|
```
|
|
|
|
The showcase intentionally separates three things:
|
|
|
|
```text
|
|
Component directories
|
|
Concrete Element Plus component folders, including subcomponents such as Table Column,
|
|
Tab Pane, Option, Dropdown Item, Carousel Item, and internal foundations.
|
|
|
|
Public El* exports
|
|
Components plus public services/directives such as ElMessage, ElMessageBox,
|
|
ElNotification, ElLoadingService, and Popper subparts.
|
|
|
|
Directive directories
|
|
click-outside, mousewheel, repeat-click, trap-focus.
|
|
```
|
|
|
|
When Element Plus is upgraded, run:
|
|
|
|
```bash
|
|
node scripts/generate-element-plus-inventory.mjs
|
|
```
|
|
|
|
Do not hand-edit component counts. The generated facts stay in `src/data/elementPlusInventory.js`.
|
|
ERP-specific decisions stay in `src/data/erpComponentDocs.js`, so package upgrades do not wipe local design decisions.
|
|
|
|
## Local Component Docs
|
|
|
|
Every Element Plus component directory gets a local ERP doc record:
|
|
|
|
```js
|
|
{
|
|
slug: 'table',
|
|
tag: 'el-table',
|
|
exportName: 'ElTable',
|
|
group: '数据展示',
|
|
priority: '高',
|
|
wrapperName: 'ErpTable',
|
|
localClass: 'erp-table',
|
|
originalCode: '<el-table ... />',
|
|
erpCode: '<el-table class="erp-table" ... />',
|
|
styleCode: '/* src/styles/erp-patterns.css */ ...',
|
|
detailRoute: '#/component/table'
|
|
}
|
|
```
|
|
|
|
The catalog page reads `erpComponentDocs`, not the raw inventory directly. That is the split:
|
|
|
|
```text
|
|
elementPlusInventory.js = package truth
|
|
erpComponentDocs.js = OFBiz local usage and style truth
|
|
```
|
|
|
|
High-frequency ERP components already have concrete preview and ERP code patterns:
|
|
|
|
```text
|
|
Table / Table V2 / Pagination
|
|
Menu / Sub Menu / Menu Item
|
|
Breadcrumb / Breadcrumb Item / Page Header
|
|
Form / Form Item / Input / Select / Select V2 / Date Picker
|
|
Button / Button Group / Dropdown
|
|
Dialog / Drawer / Popconfirm / Tooltip
|
|
Tag / Alert / Message / MessageBox / Notification
|
|
Tree / Tree V2 / Tree Select / Upload / Descriptions
|
|
Empty / Progress / Result / Skeleton
|
|
Timeline / Steps / Collapse / Tabs / Segmented
|
|
Calendar / Image / Carousel / Statistic
|
|
Switch / Slider / Rate / Color Picker / Transfer
|
|
Space / Text / Link / Divider
|
|
```
|
|
|
|
Subcomponents such as `Table Column`, `Breadcrumb Item`, `Menu Item`, `Dropdown Item`, `Option`, and `Tab Pane`
|
|
are retained as independent detail pages, but their wrapper guidance points back to the parent component.
|
|
|
|
## CSS Order
|
|
|
|
Use the single global entry in future OFBiz frontend pages:
|
|
|
|
```js
|
|
import './styles/erp-ui.css'
|
|
import './styles/app.css'
|
|
```
|
|
|
|
`erp-ui.css` keeps this internal order:
|
|
|
|
1. Element Plus official CSS.
|
|
2. ERP tokens.
|
|
3. Global baseline.
|
|
4. Element Plus overrides.
|
|
5. Reusable ERP patterns.
|
|
|
|
Page-specific styles come after `erp-ui.css`. Do not import Element Plus CSS directly in feature pages.
|
|
|
|
## Component Rules
|
|
|
|
Use Element Plus as the raw component layer. Do not use raw Element Plus directly in OFBiz feature pages once a reusable ERP wrapper exists.
|
|
|
|
Preferred path:
|
|
|
|
```text
|
|
Element Plus primitive -> ERP wrapper/pattern -> OFBiz feature page
|
|
```
|
|
|
|
Example:
|
|
|
|
```vue
|
|
<el-table :data="rows" class="erp-table" stripe>
|
|
<el-table-column prop="orderId" label="单据号" width="126" />
|
|
<el-table-column prop="amount" label="金额" align="right" />
|
|
</el-table>
|
|
```
|
|
|
|
Later wrapper target:
|
|
|
|
```vue
|
|
<ErpTable :rows="rows" :columns="columns" row-key="orderId" />
|
|
```
|
|
|
|
## Component Decision Rules
|
|
|
|
Pick components by business task first, not by visual taste.
|
|
|
|
```text
|
|
Page skeleton
|
|
Container / Aside / Main / Card / Collapse / Splitter
|
|
Use for module frame, page sections, details summary, and collapsible advanced content.
|
|
|
|
Navigation location
|
|
Menu / Breadcrumb / Page Header / Tabs / Steps / Timeline
|
|
Use for module switching, current path, local views, process position, and audit history.
|
|
|
|
Query and input
|
|
Form / Input / Select / Date Picker / Tree Select / Autocomplete / Upload
|
|
Use for search bars, editing forms, entity lookup, legal values, dates, and attachments.
|
|
|
|
Data scanning
|
|
Table / Table V2 / Pagination / Descriptions / Tree / Statistic / Tag
|
|
Use for dense business objects, read-only summaries, hierarchy, metrics, and statuses.
|
|
|
|
Actions and feedback
|
|
Button / Dropdown / Popconfirm / Dialog / Drawer / Message / Alert / Result
|
|
Use for primary actions, secondary action menus, confirmations, details, and completion states.
|
|
|
|
State and loading
|
|
Empty / Skeleton / Progress / Badge / Calendar / Image / Transfer
|
|
Use for no-data states, loading, measurable progress, counters, schedules, media, and assignment.
|
|
```
|
|
|
|
Important component choices:
|
|
|
|
- Use `Table` for auditable ERP records; use `Table V2` only when row count and scroll performance are the actual problem.
|
|
- Use `Descriptions` for read-only details; do not make read-only content look like disabled forms.
|
|
- Use `Tabs` for views inside the same business object; use `Menu` for module-level navigation.
|
|
- Use `Steps` for current process position; use `Timeline` for history and audit records.
|
|
- Use `Drawer` for side details and audit context; use `Dialog` for short blocking confirmation or editing.
|
|
- Use `Message` for short save feedback; use `Alert` for persistent warnings; use `Result` only at a flow endpoint.
|
|
- Use `Autocomplete`, `Tree Select`, or `Cascader` for entity lookup; do not overload plain `Input` with hidden lookup logic.
|
|
- Use `Dropdown` for secondary or low-frequency actions; never hide the main workflow action inside it.
|
|
|
|
## Page Layout Playbook
|
|
|
|
Use these four page skeletons before selecting individual controls.
|
|
|
|
```text
|
|
List page
|
|
Breadcrumb / Page Header
|
|
Query Form
|
|
Toolbar with one primary action
|
|
Table
|
|
Pagination
|
|
Drawer for row details or audit context
|
|
|
|
Detail page
|
|
Breadcrumb / object title / status tags
|
|
Descriptions summary
|
|
Tabs for lines, audit, attachments
|
|
Table for line items
|
|
Drawer for side context
|
|
|
|
Entry page
|
|
Two-column Form
|
|
Entity pickers for customer, supplier, org, warehouse
|
|
Upload only near attachment fields
|
|
Footer actions with one primary submit
|
|
Popconfirm for destructive or irreversible actions
|
|
|
|
Process page
|
|
Steps for current progress
|
|
Alert for blocking warning
|
|
Progress for measurable work
|
|
Skeleton while content loads
|
|
Result only when the process has ended
|
|
```
|
|
|
|
Layout defaults:
|
|
|
|
- Query forms use 4 columns on desktop. Editing forms use 2 columns. Detail summaries use 2-3 columns.
|
|
- List pages follow this order: page context, filters, toolbar, table, pagination, detail drawer.
|
|
- The visible work area gets one `primary` button. Secondary actions are normal buttons, links, or dropdown items.
|
|
- Numbers and money align right. Status is near the business object it describes.
|
|
- Dense table pages should keep vertical rhythm tight; dialogs and destructive confirmations should keep more reading space.
|
|
|
|
## Catalog Layout Contract
|
|
|
|
The full component catalog is intentionally split into four layers:
|
|
|
|
```text
|
|
Catalog summary
|
|
Count and completeness signals for the local Element Plus inventory.
|
|
|
|
Page playbook
|
|
OFBiz page templates that map common page types to component sets.
|
|
|
|
Usage map
|
|
Business scenarios that link directly to the components used in that scenario.
|
|
|
|
Grouped component library
|
|
All 122 Element Plus component directories, grouped by component family.
|
|
```
|
|
|
|
Every component card includes:
|
|
|
|
```text
|
|
Component name
|
|
Element Plus tag and export
|
|
ERP priority
|
|
One-line usage rule
|
|
Independent 展示 / 代码 tabs
|
|
Direct detail link
|
|
Direct component code page link
|
|
```
|
|
|
|
Every component detail page includes:
|
|
|
|
```text
|
|
展示
|
|
原始代码
|
|
ERP代码
|
|
本地样式
|
|
什么时候用
|
|
什么时候不用
|
|
排版规则
|
|
落地 CSS 文件
|
|
同组组件跳转
|
|
```
|
|
|
|
## Page Split Contract
|
|
|
|
The lab is a multi-page component document. The left menu switches pages instead of scrolling to anchors.
|
|
|
|
Routes are hash based so every page and component can be linked directly:
|
|
|
|
```text
|
|
#/page/catalog
|
|
#/page/catalog?group=数据展示
|
|
#/component/table
|
|
#/component/menu
|
|
#/component/breadcrumb
|
|
```
|
|
|
|
The left menu calls `navigateTo('page/<id>')`, so page changes are real URL changes. The full catalog card titles
|
|
and detail buttons call `navigateTo('component/<slug>')`, so every component has a direct page.
|
|
|
|
Pages are registered in `docPages` inside `src/data/showcaseData.js`. Each page carries:
|
|
|
|
```text
|
|
id
|
|
label
|
|
icon
|
|
title
|
|
description
|
|
```
|
|
|
|
Each file under `src/components/showcase/` owns one documentation page:
|
|
|
|
```text
|
|
FoundationShowcase.vue Tokens and product tone
|
|
MetricsShowcase.vue Statistic cards and dashboard summaries
|
|
ComponentCatalogShowcase.vue Full Element Plus inventory
|
|
ButtonShowcase.vue Buttons, groups, dropdown actions
|
|
FormShowcase.vue Form, input, select, picker, switches
|
|
TableShowcase.vue Table, columns, pagination, cells
|
|
StatusShowcase.vue Tag, alert, progress, badge, timeline
|
|
NavigationShowcase.vue Side menu, top menu, breadcrumb, page header
|
|
TokenRail.vue Token notes and next component queue
|
|
DocumentDrawer.vue Drawer detail preview
|
|
```
|
|
|
|
When adding a new component family, create a new `*Showcase.vue` file, register it in `docPages`, and render it from `ElementPlusShowcase.vue`. Put sample data in `src/data/showcaseData.js` unless it is purely local demo state.
|
|
|
|
## Demo / Code Tabs
|
|
|
|
Every component page should use `DemoBlock.vue` so examples always include both the rendered component and the corresponding code.
|
|
|
|
```vue
|
|
<DemoBlock
|
|
:code="tableCode"
|
|
description="ERP 表格优先保证扫描效率、状态清晰、数字右对齐和固定操作列。"
|
|
eyebrow="Data Table"
|
|
title="订单工作台表格"
|
|
>
|
|
<el-table :data="orderRows" class="erp-table" stripe />
|
|
</DemoBlock>
|
|
```
|
|
|
|
Code snippets live near the component demo as string constants. Keep snippets short and focused; do not paste an entire page when the user only needs the component call pattern.
|
|
|
|
The full catalog has its own tab contract:
|
|
|
|
```text
|
|
Catalog card tabs:
|
|
展示
|
|
代码
|
|
|
|
Single component detail tabs:
|
|
展示
|
|
原始代码
|
|
ERP代码
|
|
本地样式
|
|
```
|
|
|
|
Catalog card tab state is per component slug, so switching `Table` to `代码` does not switch `Button` or other cards.
|
|
|
|
Use direct links when reviewing:
|
|
|
|
```text
|
|
http://localhost:5174/#/page/catalog
|
|
http://localhost:5174/#/page/catalog?group=数据展示
|
|
http://localhost:5174/#/component/table
|
|
http://localhost:5174/#/component/table?view=code
|
|
http://localhost:5174/#/component/menu
|
|
http://localhost:5174/#/component/breadcrumb
|
|
```
|
|
|
|
## Local Style Ownership
|
|
|
|
Reusable product CSS lives here:
|
|
|
|
```text
|
|
src/styles/tokens.css
|
|
Color, radius, spacing, typography, surface, state tokens.
|
|
|
|
src/styles/element-overrides.css
|
|
Element Plus CSS variables and global Element class overrides.
|
|
|
|
src/styles/erp-patterns.css
|
|
OFBiz reusable patterns: .erp-table, .erp-side-menu, .erp-breadcrumb,
|
|
.erp-field-control, .erp-dense-pagination, .erp-tabs, .erp-status-tag,
|
|
.erp-detail-descriptions, .erp-entity-card, .erp-upload.
|
|
```
|
|
|
|
The lab-only page layout stays in `src/styles/app.css`. Do not move product wrapper styles there.
|
|
|
|
## Calling Pattern
|
|
|
|
State lives in the composition shell while each showcase section receives explicit props and emits updates:
|
|
|
|
```vue
|
|
<FormShowcase
|
|
v-model:check-values="checkValues"
|
|
v-model:date-range="dateRange"
|
|
v-model:order-status="orderStatus"
|
|
/>
|
|
```
|
|
|
|
Inside the section, keep Element Plus calls direct and obvious:
|
|
|
|
```vue
|
|
<el-select :model-value="orderStatus" @update:model-value="$emit('update:orderStatus', $event)">
|
|
<el-option label="已审批" value="approved" />
|
|
</el-select>
|
|
```
|
|
|
|
This is the migration pattern for OFBiz pages too: page state stays near the business workflow; reusable display or input behavior moves into an ERP wrapper only after it repeats.
|
|
|
|
## Reusable CSS
|
|
|
|
Use these files first:
|
|
|
|
```text
|
|
src/styles/tokens.css
|
|
src/styles/element-overrides.css
|
|
src/styles/erp-patterns.css
|
|
```
|
|
|
|
Current reusable classes:
|
|
|
|
```text
|
|
.erp-form
|
|
.erp-metric-card
|
|
.erp-metric-card--large
|
|
.erp-metric-card--small
|
|
.erp-metric-card--mini
|
|
.erp-table
|
|
.form-grid
|
|
.table-search
|
|
.icon-cell
|
|
.risk-dot
|
|
.component-chip
|
|
```
|
|
|
|
Component usage data lives in:
|
|
|
|
```text
|
|
src/data/erpComponentDocs.js
|
|
groupContracts
|
|
groupGuidance
|
|
previewGuidance
|
|
componentDocOverrides
|
|
erpComponentUsageMap
|
|
erpLayoutPlaybook
|
|
```
|
|
|
|
Catalog UI and per-component detail layout live in:
|
|
|
|
```text
|
|
src/components/showcase/ComponentCatalogShowcase.vue
|
|
```
|
|
|
|
Only product-reusable styling belongs in:
|
|
|
|
```text
|
|
src/styles/erp-patterns.css
|
|
src/styles/element-overrides.css
|
|
src/styles/tokens.css
|
|
```
|
|
|
|
Catalog-only grouping, playbook cards, mini previews, and documentation layout belong in:
|
|
|
|
```text
|
|
src/styles/app.css
|
|
```
|
|
|
|
Rule of thumb:
|
|
|
|
- If a style should apply across OFBiz modules, put it in `erp-patterns.css`.
|
|
- If it changes Element Plus global behavior, put it in `element-overrides.css`.
|
|
- If it is only for the lab page layout, put it in `app.css`.
|
|
- If it is a primitive value such as color, spacing, radius, font, or shadow, put it in `tokens.css`.
|
|
|
|
## Metric Cards
|
|
|
|
Do not use the old left-color-bar card for OFBiz dashboards. It is too decorative and does not read like a durable ERP control.
|
|
|
|
Use one KPI component with three size levels:
|
|
|
|
```vue
|
|
<div class="erp-metric-card erp-metric-card--large is-primary">...</div>
|
|
<div class="erp-metric-card erp-metric-card--small is-warning">...</div>
|
|
<div class="erp-metric-card erp-metric-card--mini is-danger">...</div>
|
|
```
|
|
|
|
Default dashboard size: `erp-metric-card--large`.
|
|
|
|
Use `--large` for dashboard summary rows and landing workspaces. Use `--small` above dense tables or within secondary panels. Use `--mini` inside narrow sidebars, table toolbars, or pages with many metrics.
|
|
|
|
## Design Intent
|
|
|
|
This UI system should feel quiet, durable, and operational. OFBiz users need to scan dense business data, make safe changes, and repeat workflows all day.
|
|
|
|
Keep these defaults:
|
|
|
|
- Typography: 12/13/14/18/24.
|
|
- Main radius: 6px for controls, 8px for panels.
|
|
- Tables: compact row height, sticky action column when needed, numbers right-aligned.
|
|
- Colors: low-saturation status colors, strong enough for scanning.
|
|
- Buttons: one primary action per visible work area.
|
|
- Forms: grouped fields, predictable labels, clear validation states.
|
|
- Avoid marketing layouts, oversized heroes, decorative cards, and one-hue themes.
|
|
|
|
## Priority For OFBiz
|
|
|
|
High-priority components to turn into ERP wrappers first:
|
|
|
|
```text
|
|
Table / Table V2
|
|
Form
|
|
Input / Select / Date Picker / Tree Select
|
|
Button / Dropdown
|
|
Tag / Alert / Message / Popconfirm
|
|
Tabs / Menu / Breadcrumb / Steps
|
|
Drawer / Dialog
|
|
Upload
|
|
Descriptions
|
|
Tree / Tree V2
|
|
Pagination
|
|
```
|
|
|
|
Lower-priority components can stay as direct Element Plus usage until real OFBiz screens need them.
|
|
|
|
## Adding A Wrapper
|
|
|
|
Create wrappers under a future `src/components/erp/` directory. Keep wrappers narrow and composable.
|
|
|
|
Example target structure:
|
|
|
|
```text
|
|
src/components/erp/ErpTable.vue
|
|
src/components/erp/ErpSearchBar.vue
|
|
src/components/erp/ErpStatusTag.vue
|
|
src/components/erp/ErpMoneyCell.vue
|
|
src/components/erp/ErpEntityPicker.vue
|
|
src/components/erp/ErpAuditTimeline.vue
|
|
```
|
|
|
|
Wrapper acceptance criteria:
|
|
|
|
- Has a simple prop API.
|
|
- Uses Element Plus internally.
|
|
- Uses tokens and ERP classes rather than hardcoded one-off styles.
|
|
- Handles empty, loading, disabled, error, and long-content states.
|
|
- Is demonstrated in a showcase section before being used in OFBiz pages.
|
|
|
|
## Backend Integration Direction
|
|
|
|
Keep OFBiz backend unchanged at first. Build the modern frontend page by page:
|
|
|
|
1. Recreate the target page in the lab with sample data.
|
|
2. Extract reusable wrappers.
|
|
3. Connect the page to OFBiz services/API.
|
|
4. Preserve permissions, auditability, and business workflow semantics.
|
|
5. Replace the legacy page only after visual and workflow checks pass.
|