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:
@@ -0,0 +1,123 @@
|
||||
# OFBiz Modern API
|
||||
|
||||
`plugins/modern-api` is the REST contract layer for the Vue 3 + Element Plus rewrite.
|
||||
|
||||
## Endpoints
|
||||
|
||||
```text
|
||||
POST /api/v1/login
|
||||
POST /api/v1/logout
|
||||
GET /api/v1/session
|
||||
GET /api/v1/navigation
|
||||
GET /api/v1/inventory
|
||||
GET /api/v1/pages/:pageId
|
||||
POST /api/v1/actions/:actionId
|
||||
GET /api/v1/entities/:entityName
|
||||
GET /api/v1/lookups/:lookupId
|
||||
GET /api/v1/options/:entityName
|
||||
POST /api/v1/uploads/:uploadId
|
||||
```
|
||||
|
||||
All endpoints return:
|
||||
|
||||
```ts
|
||||
type ApiResult<T> = {
|
||||
ok: boolean
|
||||
data?: T
|
||||
errors?: Array<{ code: string; message: string; field?: string }>
|
||||
messages?: string[]
|
||||
warnings?: string[]
|
||||
meta?: Record<string, unknown>
|
||||
traceId: string
|
||||
}
|
||||
```
|
||||
|
||||
## Inventory
|
||||
|
||||
Generate the migration inventory:
|
||||
|
||||
```bash
|
||||
cd /Users/qiu/Desktop/ERP/ofbiz-framework
|
||||
node plugins/modern-api/scripts/generate-ui-inventory.mjs
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```text
|
||||
plugins/modern-api/generated/ui-inventory.json
|
||||
plugins/modern-ui/app/public/generated/ui-inventory.json
|
||||
plugins/modern-ui/app/public/generated/pages/{pageId}--{hash}.json
|
||||
```
|
||||
|
||||
The generated file includes:
|
||||
|
||||
```text
|
||||
routeManifest
|
||||
pageDefinitions
|
||||
actionDefinitions
|
||||
controller/widget/service counts
|
||||
coverage.missingRoutes
|
||||
coverage.missingActions
|
||||
coverage.pendingE2ePages
|
||||
coverage.highRiskParityPages
|
||||
parityManifest
|
||||
```
|
||||
|
||||
Acceptance gates:
|
||||
|
||||
```text
|
||||
missingRoutes=0
|
||||
missingActions=0
|
||||
generatedOnlyPages=0
|
||||
frontend split PageDefinition files=pageDefinition count
|
||||
pendingE2ePages=0 before final functional-equivalence signoff
|
||||
```
|
||||
|
||||
Run the full structural coverage gate from the modern UI app:
|
||||
|
||||
```bash
|
||||
cd /Users/qiu/Desktop/ERP/ofbiz-framework/plugins/modern-ui/app
|
||||
npm run verify:coverage
|
||||
```
|
||||
|
||||
It writes:
|
||||
|
||||
```text
|
||||
plugins/modern-ui/verification/coverage-verification.json
|
||||
plugins/modern-ui/verification/coverage-verification.md
|
||||
```
|
||||
|
||||
`parityManifest` groups every generated page by domain, component, adapter, requirement, risk, and checklist progress. It is consumed by local verification/reporting. The production Vue app should remain an ERP administrator website, not a parity dashboard.
|
||||
|
||||
The full backend inventory keeps `pageDefinitions` and `actionDefinitions` for `/api/v1/*`. The frontend public index deliberately omits those large maps; each route has `pageDefinitionUrl`, and the SPA loads the exact page JSON on demand.
|
||||
|
||||
## Integration Notes
|
||||
|
||||
- `login` and `logout` run inside the `/api` web context so the modern UI can establish an OFBiz `userLogin` session for `/api/v1/*` requests.
|
||||
- `actions/:actionId` maps v1 action IDs to OFBiz service names when possible and executes through `LocalDispatcher`.
|
||||
- `entities/:entityName`, `lookups/:lookupId`, and `options/:entityName` require an OFBiz `userLogin` and OFBiz entity/business view permission. Business `_ADMIN` permissions and `ENTITY_DATA_ADMIN` imply view access.
|
||||
- `navigation` returns deployable SPA links under `/modern/app/#/pages/...`.
|
||||
- `lookups/:lookupId` maps v1 lookup IDs to OFBiz entity names, supports `query`, `page`, `pageSize`, and `orderBy`, and applies `query` across likely text/id/name/description/code/status fields.
|
||||
- `uploads/:uploadId` is intentionally contract-only until the secure OFBiz upload policy is wired in.
|
||||
|
||||
## API Contract Evidence
|
||||
|
||||
The modern API is not a component showcase surface. It must provide enough backend evidence for the modern ERP UI to distinguish session state, permission failures, empty queues, and contract-only gaps.
|
||||
|
||||
| Endpoint group | Contract evidence | Current behavior |
|
||||
| --- | --- | --- |
|
||||
| `GET /api/v1/session` | `ModernApiContractTests.sessionEndpointReturnsUnauthenticatedContractInsteadOfAuthError` | Always returns `200 ok=true`; `data.authenticated=false` is the unauthenticated state instead of an auth error. |
|
||||
| `GET /api/v1/navigation` | `NavigationResource` checks every webapp base permission through `ModernApiUtil.hasViewPermission`; `ModernApiUtilPermissionTests` covers `_VIEW`, `_ADMIN`, and null-user denial. | Navigation can include denied apps with `allowed=false`; UI must hide or disable them. |
|
||||
| `GET /api/v1/pages/:pageId` and `GET /api/v1/inventory` | `UiInventoryLoader` backed contract documented by generated inventory acceptance gates above. | Returns generated metadata when present and a fallback page contract when missing; it is metadata, not proof of full legacy screen equivalence. |
|
||||
| `POST /api/v1/actions/:actionId` | `ModernApiContractTests.serviceActionsRequireLoginBeforeExecution` | Service-backed actions require `userLogin` before dispatcher execution; unauthenticated calls return `401 AUTH_REQUIRED`. Navigation-only actions may resolve without service execution. |
|
||||
| `GET /api/v1/entities/:entityName` | `ModernApiUtilPermissionTests` plus `ModernApiContractTests.clampsPaginationToModernApiBounds`, `reportsHasMoreWhenNextPageContainsRows`, and `keepsOnlyKnownOrderByFieldsAndFallsBackToPrimaryKey`. | Requires login and entity/business view permission, clamps `page >= 0`, clamps `1 <= pageSize <= 100`, returns `total`, `hasMore`, safe `orderBy`, fields, and an empty `rows` array when no records match. |
|
||||
| `GET /api/v1/lookups/:lookupId` | Shares the same `ModernApiUtil.safePage`, `safePageSize`, `hasMore`, and `safeOrderByFields` contract as entities. | Requires login and entity/business view permission; lookup id maps to an entity name and returns paged rows/fields with safe ordering. |
|
||||
| `GET /api/v1/options/:entityName` | Uses the same `ModernApiUtil.safePageSize` and entity permission checks as entity reads. | Requires login and entity/business view permission; returns `{label,value}` options, applied constraints, `pageSize`, and `hasMore`. |
|
||||
| `POST /api/v1/uploads/:uploadId` | `ModernApiContractTests.uploadsRemainExplicitContractOnlyUntilPolicyIsImplemented` | Returns `501 UPLOAD_CONTRACT_ONLY`; no upload side effects happen until OFBiz secure upload policy is wired. |
|
||||
|
||||
Known non-equivalence remains explicit:
|
||||
|
||||
- `uploads/:uploadId` is contract-only and is not business-equivalent to legacy OFBiz upload flows.
|
||||
- `pages/:pageId` and `inventory` prove route/widget/action metadata availability, not full rendered legacy behavior.
|
||||
- `actions/:actionId` executes service-backed actions and supported web events, but controller flows that only resolve views remain navigation contracts.
|
||||
- `entities`, `lookups`, and `options` provide secure generic read contracts; they do not replace every specialized OFBiz service, validation rule, or workflow-specific authorization branch.
|
||||
Reference in New Issue
Block a user