Files
QiufengandClaude Opus 4.8 5e51dc3f56 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>
2026-06-15 19:19:15 +08:00

30 KiB
Raw Permalink Blame History

OFBiz Modern UI 使用手册

定位

plugins/modern-ui 是 OFBiz 现代管理端的生产 UI。目标界面是 /modern/app/ 下的管理员工作台、领域管理页、业务操作页和系统维护页,服务对象是每天处理订单、库存、财务、客户、内容、系统维护等任务的后台操作员。

本手册说明如何用 Vue 3、Element Plus 和 ERP wrapper 构建 OFBiz 管理端。原有 FreeMarker、widget XML、controller XML 和 service XML 是元数据来源、兼容路由和回退依据;生产页面要面向业务操作员,使用订单、商品、客户、财务、库存、履约、采购、人事、内容、POS、电商、系统维护等业务语言。

/Users/qiu/Desktop/ERP/element-plus-lab 可以作为样式试验来源,但不能作为 modern-ui 的产品目标。生产 UI 的入口、样式、组件调用和验收边界都以本目录代码为准。

代码入口

关注点 文件
应用启动、Element Plus 注册、全局图标注册、全局样式导入 plugins/modern-ui/app/src/main.ts
Hash 路由、登录门禁、视图选择、业务页参数传递 plugins/modern-ui/app/src/App.vue
侧栏、顶栏、全局命令、快捷动作、会话身份 plugins/modern-ui/app/src/components/erp/ErpAppShell.vue
模块目录、模块路由、标签、图标、业务前缀、快捷页、工作流 plugins/modern-ui/app/src/data/moduleCatalog.ts
领域管理页模板 plugins/modern-ui/app/src/components/erp/ErpDomainAdminView.vue
生成业务页路由 #/pages/:pageId plugins/modern-ui/app/src/views/BusinessPageView.vue
PageDefinition block 渲染、页面动作、回执 plugins/modern-ui/app/src/components/erp/ErpPageRenderer.vue
非普通 form/table/action block 的适配与 workspace 分发 plugins/modern-ui/app/src/components/erp/ErpAdapterBlock.vue
ERP wrapper 组件 plugins/modern-ui/app/src/components/erp/*.vue
API、action、lookup、option、entity rows、fallback 数据 plugins/modern-ui/app/src/services/api.ts, plugins/modern-ui/app/src/services/fallback.ts
共享类型 plugins/modern-ui/app/src/types/api.ts
标签清洗和业务文案格式化 plugins/modern-ui/app/src/utils/display.ts, plugins/modern-ui/app/src/utils/erpMetadata.ts
样式入口 plugins/modern-ui/app/src/styles/erp-ui.css, plugins/modern-ui/app/src/styles/modern.css
设计变量、Element Plus 覆盖、ERP 可复用模式 plugins/modern-ui/app/src/styles/tokens.css, plugins/modern-ui/app/src/styles/element-overrides.css, plugins/modern-ui/app/src/styles/erp-patterns.css
生成页面 JSON plugins/modern-ui/app/public/generated, plugins/modern-ui/webapp/modern/app/generated

应用入口只导入一次全局样式:

import './styles/erp-ui.css'
import './styles/modern.css'

业务视图不要重复导入 Element Plus CSS,不要在页面内重新定义主题变量,也不要自建第二套视觉体系。

全局样式入口

erp-ui.css 是可复用 ERP 视觉系统入口,顺序为:

  1. Element Plus 官方 CSS。
  2. tokens.css:颜色、字号、间距、圆角、阴影、边框等全局变量。
  3. base.css:基础页面和元素规则。
  4. element-overrides.cssElement Plus 变量映射和窄范围覆盖。
  5. erp-patterns.css:ERP 表单、表格、状态、上传、lookup、菜单、详情、分页、空状态等可复用类。

modern.css 负责管理端 shell、领域页、生成业务页和少量页面级布局。规则归属如下:

  • 改颜色、字号、间距、圆角、阴影:优先改 tokens.css
  • 改 Element Plus 全局变量或基础组件密度:放在 element-overrides.css
  • 可复用 ERP 模式:放在 erp-patterns.css
  • 某个页面或某类业务页的布局:放在 modern.css,使用明确的页面或 block class。
  • 组件私有且不可复用的小范围布局:留在组件 <style scoped>,但避免硬编码主题值。

不要在业务页面里散落一次性颜色、深层选择器、任意 padding、超出 8px 的圆角或装饰性阴影。页面章节应是工作区域,不要做卡片套卡片。

Token 和密度契约

生产样式以 tokens.css 为唯一变量来源:

维度 Token / 规则
主色 --erp-color-primary 用于全局导航、主按钮、选中态和可操作焦点
状态色 success 表示完成/健康/已连接,warning 表示待处理/需复核/后台处理中,danger 表示错误/拒绝/取消/删除,info 表示中性元数据
字号 24px 页面标题,18px 大面板标题,14px 正文和主要控件,13px 紧凑文本,12px 标签和元数据
间距 全站使用 4px grid--erp-space-1--erp-space-8
控件高度 标准 32px,紧凑 28px,大控件 36px
圆角 常规 4px / 6px,上限 8px
阴影 后台工作区默认不用装饰阴影,只在浮层或确需层级时使用
表格 表头/行高 34pxcell 垂直 padding 5px,横向 padding 8px

element-overrides.css 只把 Element Plus 变量映射到 ERP token,不承载业务页面布局。erp-patterns.css 承载可复用的 .erp-table.erp-dense-pagination.erp-status-tag.erp-state-line.erp-work-area.erp-form--search.erp-form--entity.erp-action-stack 等模式。

样式依赖规则

业务页只能走以下路径:

Element Plus primitive -> ERP wrapper / ERP pattern -> 业务页面
  • 表单、表格、动作、状态、lookup、上传、抽屉、审计优先调用 wrapper。
  • 没有 wrapper 时,先复用 erp-patterns.css 中的模式类;确实缺失时补窄 pattern,再让页面使用。
  • modern.css 只放 shell、领域页和生成页的布局组合,不新增颜色体系、字号体系、阴影体系或按钮体系。
  • <style scoped> 只能处理组件私有排版,且必须引用 token;不能散写主题色、任意圆角、装饰阴影或深层覆盖 Element Plus。
  • 业务页面不得重复手写 form/table/action/status/lookup/upload/detail drawer/audit timeline 的样式组合。

按钮层级

  • 每个工作区最多一个 primary action;其余为 default / link / text。
  • 删除、取消、移除、拒绝等危险动作使用 danger,并在高风险动作前加确认。
  • 普通动作区最多展示 4 个动作,紧凑动作区最多 2 个,其余进入 更多
  • 表格行操作使用 link button,短标签优先:查看、审计、编辑、打开。
  • 成功、失败、不可执行、需人工处理等结果必须留在工作区内;toast 只能补充。

Element Plus 与 ERP Wrapper

生产页面采用:

Element Plus primitive -> ERP wrapper / ERP pattern -> OFBiz business page

直接使用 Element Plus 的场景:

  • el-tabs:同一业务对象的不同表面,如总览、数据、动作、流程、审计、权限。
  • el-menu:页面内子导航或横向菜单。
  • el-alertel-emptyel-skeletonloading、empty、permission、unavailable、error、success receipt。
  • el-descriptionsel-timeline:只读事实和历史,但优先由 wrapper 承载。
  • el-dialogel-popconfirm:短确认、短阻塞表单、危险动作确认。
  • el-buttonel-tag:局部小控件,且没有对应业务 wrapper 时。

业务对象优先使用 wrapper

业务需要 使用
管理端 shell、全局导航、会话 ErpAppShell
标题、说明、面包屑、头部动作 ErpPageHeader
查询、筛选、报表参数 ErpSearchForm
新建、编辑、维护表单 ErpEntityForm
业务列表、实体表、分页、排序、行详情 ErpDataTable
保存、提交、审批、取消、导出、打印等动作 ErpActionBar
业务状态、队列状态、回执状态 ErpStatusTag
Party/Product/Order 等实体查找 ErpLookup
行详情、审计、附件、权限上下文侧检 ErpDrawer
审计历史 ErpAuditTimeline
附件、媒体、导入文件 ErpUpload, ErpMediaWorkspace
生成页面 block 渲染 ErpPageRenderer
非普通 form/table/action 的生成 block ErpAdapterBlock
领域流程工作台 ErpOrderWorkspace, ErpFinanceWorkspace, ErpInventoryWorkspace, ErpProcurementWorkspace, ErpCatalogWorkspace, ErpPartyWorkspace, ErpContentWorkspace, ErpSystemWorkspace, ErpCommerceSurface, ErpPosWorkspace

如果一个业务视图重复手写 form、table、action bar、status tag、lookup、upload、detail drawer 或 audit timeline,应该改为调用 wrapper,或在 components/erp 新增窄 wrapper 后再复用。

当前覆盖事实

截至 2026-06-09 的审计口径:

  • 1772 个 legacy view route 映射到 1767 个 unique PageDefinition,有 5 个重复 route alias。
  • 1767 个 split PageDefinition JSON 文件位于 plugins/modern-ui/webapp/modern/app/generated/pages
  • ErpPageRenderer / ErpAdapterBlock 结构支持 1767 个生成页,当前没有 unsupported block type。
  • 553 个 table block 都有 data-source contract,其中 505 个 entity-backed48 个 derived/report/history。
  • 1409 个 form block 都有 submit/read contract,其中 602 个 service-ready146 个 event-ready369 个 navigation-action,其余为 readonly、dynamic、local、navigation-target 或 preserved unmapped target。
  • 当前 verification 截图目录有 112 张 PNG;这不是全量 1767 页浏览器截图。
  • 当前 parity artifact 只有 4 个 Accounting 页面 runtime smoke 通过;它不能代表全域 E2E parity。
  • 当前浏览器运行时验收使用本地 Google Chrome + CDP fallbackbrowser-runtime-report.jsonhttp://127.0.0.1:8080/modern/app/ 通过,截图为 plugins/modern-ui/verification/browser-runtime-admin.png
  • Codex in-app browser / iab 当前不可用,根因为 agent.browsers.get('iab') -> Browser is not available: iab。不要把 iab 不可用解释为 Modern UI 失败,也不要无限重试;按 Chrome/CDP 验证链路处理。
  • 1721 个页面仍是 pending business E2E876 个是 high-risk pending 页面。

这组事实只允许声明“结构覆盖/renderer 覆盖/contract 覆盖已建立”。不要在产品文案、PR、交付说明或验收报告里写“full parity complete”、“全量业务等价完成”或类似结论。

Wrapper 使用边界

生成页默认由 BusinessPageView -> ErpPageRenderer -> ErpAdapterBlock 承载。只有在以下情况才新增或扩展 dedicated Vue/workspace

  • 页面需要跨多个实体编排流程,而不是单个 form/table/action block。
  • 需要真实业务状态机、步骤条、异常交接、审计、上传、导入、导出、PDF/CSV/print、POS/cart/payment、report output 等行为。
  • legacy 页面依赖复杂 JavaScript、FreeMarker/Groovy 模板语义或多请求副作用,metadata renderer 只能保留结构。
  • 同一领域已有 workspace 可复用,如 ErpFinanceWorkspaceErpOrderWorkspaceErpProcurementWorkspaceErpContentWorkspaceErpPosWorkspaceErpBirtReportingWorkspaceErpSystemWorkspace

不要为了单个普通 legacy form/table 复制一套页面结构。先把元数据送进 wrapper;当 E2E 证明 metadata renderer 无法表达业务行为时,再把那段行为提升成窄 workspace 或 wrapper。

表单规则

查询、筛选、报表参数和生成 legacy form block 使用 ErpSearchForm

<ErpSearchForm
  :fields="formBlock.fields"
  :submit-action="formBlock.submitAction"
  :initial-values="routePayload"
  @submit="handleSubmit"
  @reset="handleReset"
  @update:model="mergePayload"
/>

新建、编辑、维护业务对象使用 ErpEntityForm

<ErpEntityForm
  :fields="editBlock.fields"
  :submit-action="editBlock.submitAction"
  :initial-values="currentRecord"
  @submit="handleSubmit"
  @update:model="mergePayload"
/>

表单布局规则:

  • 搜索表单使用四列密集网格,编辑表单使用两列;抽屉或窄面板内使用一列。
  • 身份字段优先:party、product、order、invoice、payment、facility、content、work effort、employee 等。
  • 只读事实用 el-descriptions.erp-detail-descriptions,不要用 disabled form 假装详情。
  • ErpSearchForm 当前最多展示 16 个可见字段,ErpEntityForm 当前最多展示 24 个可见字段。需要更多字段时分组、分 tab 或高级区,不要绕过 wrapper。
  • hidden、ignored、submit widget 不作为普通输入控件显示。
  • disabled、readonly、requires-login、contract-only、backend-only 等状态必须可见并有业务含义,不要直接隐藏整块表单。

Select、Radio、Lookup 与 Option

来自 OFBiz widget XML 的 drop-downselectradio 必须继续使用生成元数据,不要在业务页面手写 <el-select> options。

选择控件的三类数据契约:

field.options: 静态 <option key="" description=""> 值
field.optionSources[type=entity-options]: 动态 <entity-options> 来源
field.optionSources[type=list-options]: 旧 list-options 上下文,等待页面数据注入

ErpSearchFormErpEntityForm 通过 fieldOptions.ts 合并静态选项和远程 entity options。实体选项调用:

GET /api/v1/options/:entityName
  ?keyFieldName=geoId
  &description=${geoName} [${geoId}]
  &constraint=geoTypeId:STATE
  &pageSize=60

lookup 规则:

  • Party、Product、OrderHeader 或可推断实体引用使用 ErpLookup
  • 描述性文本可以用普通 input;实体身份字段不要用自由文本代替 lookup。
  • lookup 数据通过 services/api.ts#getLookup 获取。
  • lookup 弹层、autocomplete、选中值展示不要在业务页重复手写。

上传规则:

  • 普通字段上传由表单 wrapper 的 file widget 或 ErpUpload 承载。
  • 媒体资产、内容关联、审核工作流使用 ErpMediaWorkspace
  • 上传、导入、PDF、CSV、print、export 都属于业务验收敏感路径,不能只验证页面可渲染。

表格和列表

业务列表使用 ErpDataTable

<ErpDataTable
  :columns="tableBlock.fields"
  :rows="tableBlock.rows"
  :data-source="tableBlock.dataSource"
/>

数据契约示例:

{ type: 'entity', entityName: 'Party', endpoint: '/api/v1/entities/Party' }
{ type: 'derived', derivedType: 'report-list', reason: '需要进入对应业务流程后加载数据' }

ErpDataTable 负责:

  • provided rows 和 remote entity rows。
  • 搜索、刷新、服务端排序、分页。
  • 默认 page size 20,可选 10 / 20 / 50 / 100。
  • 默认最多 12 个可见列。
  • hidden、ignored、submit widget 不显示为列。
  • amounttotalprice 等金额列右对齐。
  • status 类列用 ErpStatusTag
  • 固定右侧操作列,短动作如 查看审计
  • 420px 详情抽屉,显示 el-descriptions 和审计时间线。
  • loading、empty、unavailable、error、derived/fallback 状态。

当用户需要扫描、排序、比较、分页或执行行级动作时,不要用装饰卡片替代表格。空数据必须解释业务状态:当前条件无匹配记录、权限不足、会话缺失、服务不可用、或数据需要进入业务流程后加载。

动作和按钮

页面动作使用 ErpActionBar

<ErpActionBar
  :actions="page.actions"
  :payload="pagePayload"
  @executed="setActionResult"
/>

动作规则:

  • 一个区域只保留一个 primary actionErpActionBar 默认第一个可见动作是 primary。
  • 删除、取消、移除、拒绝、delete、cancel、remove、reject 等危险动作使用 danger,并在高风险时加 el-popconfirm
  • 普通模式最多显示 4 个动作,compact 模式最多显示 2 个,其余进入 更多
  • 表格行操作使用 link button,标签短而明确:查看、审计、编辑、打开。
  • 成功、失败、不可执行、需人工处理等结果要留在页面工作区或 ErpPageRenderer action receipt 中;ElMessage 只能作为补充。
  • 不要做长横向按钮带,不要在多个区域重复同一个 submit,不要在 API 或 OFBiz 返回结果不支持时宣称动作成功。

ErpPageRenderer 只在 submitAction.apiExecutable 为 true 且存在 actionId 时调用 /api/v1/actions/:actionId。其他 action contract 要在页面里显示原因和下一步。

菜单、面包屑和路由

ErpAppShell 拥有全局导航。业务页面不要重建侧栏、顶栏、全局命令、会话身份或支持链接。

模块导航来自:

plugins/modern-ui/app/src/data/moduleCatalog.ts

新增或调整模块时先维护 idnavLabellandingPathtitleeyebrowdescriptionicontoneprefixeslegacyIncludesquickPagesworkflowsApp.vueErpAppShell.vueDashboardView.vueModuleWorkspaceView.vue 都依赖该目录。

导航规则:

  • 侧栏:全局模块和系统入口。
  • 顶栏快捷动作:高频跨模块跳转,标签保持短。
  • el-tabs:同一业务对象的多个表面。
  • 横向 el-menu:页内路由或锚点,active state 是 1px 下划线,不是圆角 pill。
  • 面包屑:通过 ErpPageHeadercrumbs,使用业务层级,如 OFBiz 管理 / 订单履约 / 订单查询,不要暴露组件路径、JSON 文件名或生成来源。
  • legacy GET 路由进入现代页时必须保留 query 参数,如 partyIdorderIdproductId

抽屉、弹窗和状态

抽屉用于非阻塞业务检查:

  • 行详情
  • 审计历史
  • 附件和媒体审查
  • 权限上下文
  • side-by-side 数据检查
  • 低频编辑

弹窗只用于确认和短阻塞表单。不要把完整业务流程、大表、多 tab、长审计或复杂上传塞进 dialog。popover 和 tooltip 只放轻量上下文,不能承载关键错误或多步工作。

状态规则:

状态 表达
Loading 工作区内保留骨架或 loading 文案
Empty 说明业务含义和下一步
Unavailable 说明权限、会话、服务、数据源或流程依赖
Error 页面内保留错误原因,不只 toast
Success 页面内回执或结果区,toast 只补充
Disabled 尽量显示为何不能操作

状态是文字第一、颜色第二。蓝色用于主导航和主动作,绿色用于完成/健康/已连接,黄色用于待处理/需复核/后台处理,红色用于错误/拒绝/取消/删除,灰色用于中性元数据和不可用说明。

页面排版

后台页面是桌面优先的密集工作台,当前宽度目标约 1180px。POS 和 commerce 可以更适合触控,但 back-office 页面仍保持紧凑、稳定、可扫描。

推荐结构:

  1. ErpPageHeader:面包屑、短说明、有限头部动作。
  2. tabs:当页面有总览、数据、动作、流程、审计、权限等不同表面。
  3. 查询/命令/动作带:只在能帮助操作员时出现。
  4. 主工作区:form、table、action bar、domain workspace。
  5. 侧向上下文:文档摘要、流程、审计、权限、交接状态。

密度规则:

  • 24px 用于页面 h1,18px 用于面板标题,14px 用于正文和主要控件,13px 用于菜单/面包屑/紧凑文本,12px 用于状态、标签和元数据。
  • 使用 4px spacing grid 和 --erp-space-*
  • 圆角不超过 --erp-radius-md 8px。
  • 表格用 1px soft border、紧凑 cell、稳定分页。
  • cards 只用于重复项、摘要指标、队列行和真正 framed tools;不要卡片套卡片。
  • 不做营销 hero,不用大段解释挡住主工作区,第一屏要看到真实业务工作。

PageDefinition 业务页

PageDefinition 是业务操作页的主要元数据契约,包含:

  • pageIdtitlecomponentdomainlayout
  • blocks: form、table、actions、menu、links、permission、section、workspace、report、adapter 等 PageBlock[]
  • actions: 字符串 action 或 ActionDefinition[]
  • permissions: OFBiz 继承权限。
  • legacy: 旧 source path 和 widget traceability。
  • acceptance: renderability、mapping、risk、checklist、scenario 等验收线索。

路由和渲染流程:

controller.xml + widget XML + service XML
  -> plugins/modern-api/generated/ui-inventory.json
  -> plugins/modern-ui/app/public/generated/ui-inventory.json
  -> /modern/app/generated/ui-inventory.json
  -> GET /api/v1/pages/:pageId 或 generated page JSON fallback
  -> BusinessPageView
  -> ErpPageRenderer
  -> Element Plus ERP wrappers

BusinessPageView 接收 pageId 和 hash query,解析 PageDefinition,保留 route payload,并传给 ErpPageRendererErpPageRenderer 负责页面动作状态、ErpActionBar、上传处理、动作回执、domain workspace 选择和 block 渲染。

不要在自定义 view 中按 route id 手工重建生成业务页。优先修 PageDefinition 元数据、renderer 映射或 workspace 映射,让同类页面一起受益。

legacy query 不能丢:

/accounting/control/EditBillingAccount?partyId=DemoCustomer
  -> /modern/app/#/pages/accounting__EditBillingAccount?partyId=DemoCustomer

这些参数要进入 initialPayload,并预填匹配的 ErpSearchForm / ErpEntityForm 字段。

Block 和 Workspace 选择

常见 block 映射:

Block 类型 使用
form ErpSearchForm;编辑语义明确时用 ErpEntityForm
table ErpDataTable
actions ErpActionBar
menu Element Plus el-menu 或业务链接组
links Element Plus button/link group
permission el-descriptions / el-alert 展示业务权限含义
section 业务摘要或只读事实
report ErpReportWorkspace 或 report adapter
search-workspace 查询表单 + 结果表格
entity-editor ErpEntityForm + 校验/审计上下文
domain-workspace 摘要、tabs、line tables、领域动作
tree-workspace 树导航 + 详情面板
calendar el-calendar + .erp-calendar
lookup-workspace lookup 搜索 + 可选结果
commerce-surface ErpCommerceSurface
pos-workspace ErpPosWorkspace
client-behavior dependent selects、多选、前端校验说明
route-workspace 没有 widget block 的旧路由工作区
template-adapter, html-template, legacy-screen 临时结构承载;业务签收前必须确认行为或替换成领域实现

领域流程优先使用 dedicated workspace,例如:

  • 订单、购物车、发运、履约:ErpOrderWorkspace, ErpFulfillmentWorkspace, ErpReturnWorkspace
  • 财务、手工分录、对账:ErpFinanceWorkspace, ErpFinanceOperationsWorkspace
  • 库存、采购、制造:ErpInventoryWorkspace, ErpProcurementWorkspace, ErpManufacturingWorkspace
  • 商品、目录、促销、媒体:ErpCatalogWorkspace, ErpMediaWorkspace
  • 客户、关系、沟通:ErpPartyWorkspace
  • 内容、报表、BI、系统、扩展、网关、门户:对应 Erp*Workspace

Dedicated workspace 仍然要消费 PageBlockPageDefinition、actions、fields、items、capabilities 和 dataSource,不要把业务规则写成孤立静态布局。

页面配方

领域管理页

适用于订单、客户、商品、财务、库存、生产、人事、采购、内容、营销、电商、POS、扩展、系统等模块。

  1. moduleCatalog.ts 维护模块身份和导航。
  2. 使用 ErpDomainAdminView 或领域 admin view。
  3. 顶部使用 ErpPageHeader
  4. 指标用 .metrics-grid.erp-metric-card
  5. 主体展示队列、近期记录、风险、交接、治理信息。
  6. 记录列表使用 ErpDataTable 或领域 workspace 内表格。
  7. 原始诊断信息只放系统/诊断区域,不进第一屏。

查询和列表维护

  1. ErpPageHeader
  2. ErpSearchForm
  3. ErpActionBar,当存在查询、导出、打印或批处理动作
  4. ErpDataTable
  5. 内置详情抽屉或 ErpDrawer
  6. 需要审计时使用 ErpAuditTimeline

新建和编辑

  1. ErpPageHeader
  2. 权限、来源或后台契约 el-alert
  3. ErpEntityForm
  4. ErpActionBar 或 form submit action
  5. 既有记录的详情/审计侧栏

必填和身份字段前置,实体引用用 lookup,大表单拆成 tabs 或 sections。

流程、审批、履约

  1. 当前对象摘要和状态标签
  2. 一个明确的 primary next action
  3. 主流程 workspace:行项目、数量、付款、发运、退货、凭证或审批数据
  4. 侧栏显示审计、权限、风险、交接
  5. 提交后保留 action receipt

流程页必须说明当前状态、下一步、阻塞原因和审计相关结果。

报表和导出

使用 ErpReportWorkspaceErpAdapterBlock 的 report surface

  1. 参数表单
  2. 输出模式:页面预览、PDF、CSV、print、export
  3. 结果表格或不可用原因
  4. 导出状态或 action receipt

报表、PDF、CSV、print、export 要验证参数、权限、输出内容和文件行为。

系统、安全、运维

  1. ErpPageHeader
  2. 服务、权限、缓存、job、安全状态 alert
  3. logs、jobs、services、users、groups、rules 使用密集表格
  4. 危险动作必须确认
  5. 只有代码、日志、配置值使用 monospace

文案规则

使用短、具体、可操作的中文业务文案。

推荐:

  • 当前单据
  • 业务数据
  • 提交动作
  • 权限上下文
  • 待处理队列
  • 异常交接
  • 处理回执
  • 业务流转
  • 审计记录

生产页面避免使用内部工程叙事作为主文案。操作员可见区域必须围绕业务对象、业务状态、下一步动作、权限原因和处理回执;生成来源、适配状态、覆盖率、签收阶段、路由映射和工程报告只放内部验证、开发诊断或交付说明。

文档和交付说明可以客观描述从原有 OFBiz 页面到现代管理端的迁移策略,但必须以生产管理站点为中心:哪些业务对象可操作、哪些动作可执行、哪些流程仍需业务签收、哪些验证命令证明了什么。

验收边界

可以声明“结构已覆盖”的条件:

  • 有 route manifest entry 和 PageDefinition
  • 能进入 Vue + Element Plus renderer。
  • block 映射到 form、table、action、adapter 或 workspace。
  • 表单控件有明确 read/submit contract。
  • action 有 ActionDefinition 或明确不可执行状态。
  • 代表性 runtime 检查无 console/runtime 错误。

不能把结构覆盖等同于业务完成。业务签收需要旧流程和现代流程在以下行为上匹配:

  • query 参数和表单预填
  • 查询结果、分页和排序
  • lookup 和 option loading
  • create/edit/submit/action side effects
  • service/event 返回、错误和跳转
  • upload、media、import、export、PDF、print、report output
  • permission、login、session、validation
  • 状态流转、审计相关影响、导航目标

template-adapterhtml-templatelegacy-screen、derived dataSource、local submit contract 等都只能说明页面有结构承载;涉及业务副作用时必须做 old-vs-new E2E 或改成 dedicated Vue/workspace。

内部验证

代码或 UI 行为改动后,从 plugins/modern-ui/app 运行:

npm run build
npm run verify:browser-runtime
npm run verify:coverage
npm run verify:preview
npm run verify:parity

命令含义:

命令 能证明 不能证明
npm run build TypeScript 和 Vite 构建成功 业务行为正确
npm run verify:browser-runtime /modern/app/ 管理端在浏览器渲染,收集 console/runtime 健康 全路由和业务等价
npm run verify:coverage route/page/action/form/table/API contract 的结构覆盖 old-vs-new 功能等价
npm run verify:preview 代表性页面渲染、交互、生成资源和场景覆盖 所有业务页已签收
npm run verify:parity rewrite gate 和 parity accounting 报告 所有业务副作用已匹配

文档-only 改动可做轻量检查:

git status --short -- plugins/modern-ui/UI.md plugins/modern-ui/DESIGN.md plugins/modern-ui/app/src/styles
rg -n "Token 和密度契约|样式依赖规则|按钮层级|表单规则|表格和列表|验收边界|内部验证" plugins/modern-ui/UI.md
rg -n "<本次任务禁用的三组中文主导词>" plugins/modern-ui/UI.md plugins/modern-ui/DESIGN.md plugins/modern-ui/app/src/styles

最后一条把占位内容替换成审查清单中的禁用主导词后应无结果。

当前 Codex in-app browser / iab 不可用时,浏览器验收命令仍应走本地 Chrome/CDP fallback

CHROME_BIN="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" npm run verify:browser-runtime

验收报告路径是 plugins/modern-ui/verification/browser-runtime-report.json,截图路径是 plugins/modern-ui/verification/browser-runtime-admin.png。如果该命令失败,优先检查 /modern/app/ 是否可达、CHROME_BIN 是否存在、CDP 是否能启动;不要改用无限 iab 重试作为替代。

Review Checklist

审核 modern-ui 页面或组件改动时确认:

  • 页面使用合适的 ErpPageHeaderErpSearchFormErpEntityFormErpDataTableErpActionBarErpStatusTagErpLookupErpUploadErpDrawerErpPageRendererErpAdapterBlock
  • 颜色、字号、间距、圆角、边框、阴影来自 tokens 和 ERP pattern。
  • 表格密集、可分页、状态真实,不发明业务记录。
  • 动作有 primary、secondary、danger、overflow 层级。
  • loading、empty、unavailable、permission、error、success、disabled 都在页面内有表达。
  • 面包屑和文案使用业务语言,不把生成来源、组件路径或内部验证状态暴露为主 UI。
  • PageDefinition 页面保持 renderer-driven,除非有明确领域 workspace 理由。
  • 没有把内部验证状态、覆盖率或适配状态说成最终产品目标。