恢复点(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
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
pnpm install
pnpm dev --port 5174
pnpm build
node scripts/generate-element-plus-inventory.mjs
Local preview:
http://localhost:5174/
Direct page preview:
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
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:
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:
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:
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:
{
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:
elementPlusInventory.js = package truth
erpComponentDocs.js = OFBiz local usage and style truth
High-frequency ERP components already have concrete preview and ERP code patterns:
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:
import './styles/erp-ui.css'
import './styles/app.css'
erp-ui.css keeps this internal order:
- Element Plus official CSS.
- ERP tokens.
- Global baseline.
- Element Plus overrides.
- 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:
Element Plus primitive -> ERP wrapper/pattern -> OFBiz feature page
Example:
<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:
<ErpTable :rows="rows" :columns="columns" row-key="orderId" />
Component Decision Rules
Pick components by business task first, not by visual taste.
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
Tablefor auditable ERP records; useTable V2only when row count and scroll performance are the actual problem. - Use
Descriptionsfor read-only details; do not make read-only content look like disabled forms. - Use
Tabsfor views inside the same business object; useMenufor module-level navigation. - Use
Stepsfor current process position; useTimelinefor history and audit records. - Use
Drawerfor side details and audit context; useDialogfor short blocking confirmation or editing. - Use
Messagefor short save feedback; useAlertfor persistent warnings; useResultonly at a flow endpoint. - Use
Autocomplete,Tree Select, orCascaderfor entity lookup; do not overload plainInputwith hidden lookup logic. - Use
Dropdownfor 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.
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
primarybutton. 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:
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:
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:
展示
原始代码
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:
#/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:
id
label
icon
title
description
Each file under src/components/showcase/ owns one documentation page:
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.
<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:
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:
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:
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:
<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:
<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:
src/styles/tokens.css
src/styles/element-overrides.css
src/styles/erp-patterns.css
Current reusable classes:
.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:
src/data/erpComponentDocs.js
groupContracts
groupGuidance
previewGuidance
componentDocOverrides
erpComponentUsageMap
erpLayoutPlaybook
Catalog UI and per-component detail layout live in:
src/components/showcase/ComponentCatalogShowcase.vue
Only product-reusable styling belongs in:
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:
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:
<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:
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:
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:
- Recreate the target page in the lab with sample data.
- Extract reusable wrappers.
- Connect the page to OFBiz services/API.
- Preserve permissions, auditability, and business workflow semantics.
- Replace the legacy page only after visual and workflow checks pass.