openxiangda-skill-kit 2.0.0-alpha.25 → 2.0.0-alpha.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/architecture/admin-shell-v2.md +3 -1
- package/docs/architecture/ant-design-pro-v6-admin-foundation.md +320 -0
- package/docs/architecture/frontend-runtime-mount-v2.md +82 -0
- package/docs/architecture/implementation-roadmap.md +13 -14
- package/docs/architecture/local-development-v2.md +3 -1
- package/docs/architecture/stable-field-protocol-adoption.md +174 -0
- package/docs/design/admin/README.md +2 -0
- package/docs/design/admin-pro-v6/README.md +24 -0
- package/docs/design/admin-pro-v6/data-management.png +0 -0
- package/docs/design/admin-pro-v6/workbench.png +0 -0
- package/docs/design/admin-pro-v6/workflow-submit-modal.png +0 -0
- package/docs/design/admin-v2/README.md +3 -2
- package/docs/frontend.md +58 -48
- package/docs/getting-started.md +2 -2
- package/docs/index.md +1 -1
- package/package.json +3 -2
- package/skills/openxiangda-v2-architecture/SKILL.md +3 -2
- package/skills/openxiangda-v2-frontend/SKILL.md +36 -66
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
# OpenXiangda Admin Shell v2
|
|
1
|
+
# OpenXiangda Admin Shell v2 历史设计(已被 Pro v6 决策取代)
|
|
2
2
|
|
|
3
3
|
状态:方案已确认并进入分阶段实现;2026-08-14 已完成平台 Native A1 有界 RoleSession context 及真实 PostgreSQL 验收
|
|
4
4
|
|
|
5
|
+
> 2026-08-16 架构修订:Admin 表现层和工具链已决定[全量切换到 Ant Design Pro v6](./ant-design-pro-v6-admin-foundation.md)。本文关于“不引入 ProComponents/Umi”“继续使用 Vite/自研 Shell”“流程提交常驻双栏预览”的结论全部废止;本文保留的现状审计以及 RoleSession、route manifest、权限、标签/保活、脏状态、Data/Workflow 合同继续作为迁移不变量,不再作为 UI 技术选型依据。
|
|
6
|
+
|
|
5
7
|
适用范围:OpenXiangda 2.0 新应用,不兼容 1.x 运行时
|
|
6
8
|
|
|
7
9
|
决策对象:`openxiangda-admin`、官方应用模板、参考应用,以及必要的平台身份协议
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
# Ant Design Pro v6 Admin 全量切换决策
|
|
2
|
+
|
|
3
|
+
状态:2026-08-16 已确认,进入实现;这是 OpenXiangda 2.0 的替换型架构决策
|
|
4
|
+
|
|
5
|
+
适用范围:`openxiangda-admin`、`create-openxiangda` 官方模板、2.0 CLI/生成器/MCP/Skills、2.0 参考应用与前端验收。OpenXiangda 1.x 不在范围内。
|
|
6
|
+
|
|
7
|
+
## 1. 决策
|
|
8
|
+
|
|
9
|
+
OpenXiangda 2.0 的默认 Admin 基础彻底切换到官方 Ant Design Pro v6 Simple 模板体系:React 19、Ant Design 6、Umi Max 4、ProComponents 3,以及 Pro v6 采用的样式与构建方案。`openxiangda-admin` 只保留新的包名与职责边界,`src`、测试和样式从空目录重建;旧实现不作为迁移源,也不复制其组件、路由器、缓存器、页面结构或 CSS。新包是平台集成层和经过约束的标准业务组件集合,不再自行实现一套与 Ant Design Pro 竞争的布局、路由承载、搜索表格、表单和详情框架。
|
|
10
|
+
|
|
11
|
+
这是直接替换,不建立双框架、双路由、运行时开关或 2.0 兼容适配层。当前 2.0 只有内部测试应用,可以重新生成或废弃;正式的 2.0 包只在旧实现删除、完整验收通过后发布。
|
|
12
|
+
|
|
13
|
+
采用以下官方能力作为默认实现:
|
|
14
|
+
|
|
15
|
+
- `ProLayout` 与 Umi 路由承担 Admin 桌面布局、导航和面包屑;
|
|
16
|
+
- `PageContainer`、`ProCard`、`StatisticCard` 承担标准页面和工作台骨架;
|
|
17
|
+
- `ProTable` 承担搜索、服务端列表、列配置、排序和分页交互;
|
|
18
|
+
- `ProForm` 承担标准业务表单和操作表单;
|
|
19
|
+
- `ProDescriptions` 承担标准详情信息展示;
|
|
20
|
+
- ECharts React 适配层承担受限聚合图表,不把完整业务数据下载到浏览器聚合。
|
|
21
|
+
|
|
22
|
+
实施基线固定为 Ant Design Pro `v6.0.2`(commit `2b453c67b535b76f5f95d6542397a4b987b61de2`)。依赖精确锁定为 `@umijs/max@4.6.51`、`@ant-design/pro-components@3.1.12-0`、`antd@6.4.3`;React 保持当前仓库已经验证的 `19.2.8`。安装结果由 `pnpm-lock.yaml` 固定,不使用浮动 `latest`,也不把 Ant Design Pro 作为 Git submodule。任何版本升级都必须作为新的架构主题重新完成 API、构建与浏览器验收。
|
|
23
|
+
|
|
24
|
+
实现只复用官方源码的公开包、配置结构与页面范式,不复制官方示例登录、Mock 用户、演示 API 或业务页面。上游 tag/commit、精确依赖和本仓库 lockfile 三者共同构成可复现基线。
|
|
25
|
+
|
|
26
|
+
参考:
|
|
27
|
+
|
|
28
|
+
- [Ant Design Pro](https://github.com/ant-design/ant-design-pro)
|
|
29
|
+
- [Ant Design Pro v6 发布说明](https://github.com/ant-design/ant-design-pro/releases)
|
|
30
|
+
- [ProComponents](https://github.com/ant-design/pro-components)
|
|
31
|
+
|
|
32
|
+
## 2. 为什么替换
|
|
33
|
+
|
|
34
|
+
### 2.1 问题证据
|
|
35
|
+
|
|
36
|
+
当前自研 Admin 已经实现了身份、路由、标签、数据页、表单、工作流页面等大量能力,但产品层仍出现以下问题:
|
|
37
|
+
|
|
38
|
+
- 默认页面视觉和交互粗糙,内部编码、协议字段和错误容易直接暴露;
|
|
39
|
+
- 布局、表格、表单、详情、工作台都由平台重复实现,成熟度和一致性不足;
|
|
40
|
+
- 页面基础能力与平台业务协议耦合,单点修复容易影响壳层、查询或生命周期;
|
|
41
|
+
- 当前方案建立在旧的 ProComponents 兼容性判断上,而 ProComponents 3 已进入 Ant Design 6 技术栈;
|
|
42
|
+
- 流程提交把审批预览长期放在页面中,偏离普通用户“填写并提交”的主任务。
|
|
43
|
+
|
|
44
|
+
因此继续修补当前表现层会延长自研框架维护成本。2.0 没有稳定外部应用包袱,适合在公开发布前一次性换到底层成熟框架,同时保留已经验证的平台协议和业务内核。
|
|
45
|
+
|
|
46
|
+
### 2.2 能力所有者
|
|
47
|
+
|
|
48
|
+
| 能力 | 唯一所有者 |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| 布局、导航承载、基础页面交互 | Ant Design Pro v6 / Umi Max / ProComponents |
|
|
51
|
+
| 用户端桌面/移动页面表现 | 应用仓库的 Desktop Renderer 与 Mobile Renderer;共享 OpenXiangda 2.0 页面协议 |
|
|
52
|
+
| 表单字段、附件与业务值渲染 | OpenXiangda 2.0 Field Kit;平台合同是唯一数据语义来源 |
|
|
53
|
+
| OAuth2、Principal、RoleSession、角色切换 | OpenXiangda Platform |
|
|
54
|
+
| capability、数据范围与最终授权 | OpenXiangda Platform;浏览器只消费投影 |
|
|
55
|
+
| 路由与菜单业务声明 | 应用仓库 route manifest,经 OpenXiangda 确定性生成 |
|
|
56
|
+
| Data API/App API 查询、事务与业务数据 | OpenXiangda Platform / 应用 NestJS 后端 |
|
|
57
|
+
| Workflow 状态机、Surface、允许操作和字段策略 | Workflow Kernel v2 |
|
|
58
|
+
| 标签边界、保活、脏状态和身份失效 | `openxiangda-admin` 平台集成层 |
|
|
59
|
+
| 环境、AppVersion、构建和发布状态 | OpenXiangda Platform 与 2.0 CLI |
|
|
60
|
+
|
|
61
|
+
Ant Design Pro 的 `access` 只能作为 capability 结果的 UI 投影,不能成为授权事实源。Umi `initialState`、浏览器缓存和模板 Mock 都不能成为身份、权限、业务数据或平台运行状态的第二存储。
|
|
62
|
+
|
|
63
|
+
## 3. 稳定不变量
|
|
64
|
+
|
|
65
|
+
1. 一个应用版本仍由前端、NestJS 后端、配置合同、生成类型和构建摘要共同构成不可变 AppVersion。
|
|
66
|
+
2. 远程环境仍只有 `preproduction` 与按需创建的 `production`;本地是运行模式,不是第三个远程环境。
|
|
67
|
+
3. 服务端始终是身份、授权、数据、流程动作与部署状态的最终裁决者。
|
|
68
|
+
4. 业务字段始终由 Data API/App API 保存;Workflow Kernel 只保存流程状态、参与者、动作、字段策略和不可变审计。
|
|
69
|
+
5. 当前角色是稳定、显式的 RoleSession;同一用户的多个角色不隐式合并。应用管理员保留明确的最高授权声明。
|
|
70
|
+
6. 路由、菜单和直接 URL 访问使用同一份应用 route manifest 与同一 capability 结果。
|
|
71
|
+
7. 标签持久化、组件保活、数据查询和业务草稿仍是四类不同状态;身份 epoch 改变时旧请求、实例和选择必须失效。
|
|
72
|
+
8. 1.x 应用、流程、自动化、View 和发布工具不引用本决策中的包或运行时。
|
|
73
|
+
9. Admin 是桌面 B 端产品,默认验收宽度为 1280px 及以上,不为手机端维护抽屉导航、压缩表格或触摸版后台交互。
|
|
74
|
+
10. 用户端共享数据、表单、校验和流程合同,但 Desktop UI 与 Mobile UI 是两个独立 renderer;设备只在应用入口判定一次,不在同一组件树中堆叠响应式分支。
|
|
75
|
+
|
|
76
|
+
## 4. 前端合同
|
|
77
|
+
|
|
78
|
+
### 4.1 工程与路由
|
|
79
|
+
|
|
80
|
+
官方模板的 `apps/web` 从 Vite/手写 React Router 切换为 Umi Max。应用继续声明 OpenXiangda route manifest;`openxiangda generate` 将其确定性编译成 Umi 路由和 ProLayout 菜单元数据。生成结果必须可重复,人工维护的第二份路由树、菜单树或权限树视为构建错误。
|
|
81
|
+
|
|
82
|
+
Pro 模板自带的登录页、Mock 用户、示例 API、演示菜单和无用页面全部删除。身份启动只调用平台 RoleSession bootstrap;失败时显示可恢复的壳层错误界面,不能白屏,也不能回退到模板假用户。
|
|
83
|
+
|
|
84
|
+
应用业务路由按模块 lazy load。标签和保活由新的 `openxiangda-admin` 对 Umi 生命周期做薄封装:默认最多 12 个标签、6 个保活实例,按身份和 manifest fingerprint 隔离;动态详情、任务和编辑页默认不持久化、不保活。这里只保留产品不变量,不保留旧标签或保活实现代码。
|
|
85
|
+
|
|
86
|
+
### 4.2 标准数据管理
|
|
87
|
+
|
|
88
|
+
`DataListPage` 使用 ProTable,但只允许通过 OpenXiangda request adapter 访问类型化 Data API/App API。adapter 把 ProTable 参数转换成现有 DataQuery 的服务端分页、排序和有界筛选;不增加第二套查询 DSL,不在浏览器下载全量数据后过滤。
|
|
89
|
+
|
|
90
|
+
列显隐、密度、页大小与搜索展开状态可以按 `tenant + app + environment + roleSubject + resource + configVersion` 保存为 UI 偏好。Token、权限判定、行数据、查询结果、选择结果和业务字段不得持久化。字段策略决定列表、搜索、导入、导出、查看和编辑是否可见或可写。
|
|
91
|
+
|
|
92
|
+
### 4.3 标准表单与详情
|
|
93
|
+
|
|
94
|
+
`DataFormPage` 使用 ProForm,由 DataResource、字段策略和应用的业务标签生成控件。创建和修改经类型化客户端提交,revision 冲突、幂等失败、服务端字段错误和脏状态由标准适配层处理。
|
|
95
|
+
|
|
96
|
+
`DataRecordPage` 使用 PageContainer、ProDescriptions、附件和业务审计时间线。普通用户只看到业务标签和值;resource code、workflow code、node id、revision 和原始 JSON 只在开发/诊断边界按权限展示。
|
|
97
|
+
|
|
98
|
+
### 4.4 流程页面
|
|
99
|
+
|
|
100
|
+
流程提交页的正常状态只展示业务表单和一个主按钮“提交”。用户点击后按以下顺序执行:
|
|
101
|
+
|
|
102
|
+
1. 校验并通过 Data API/App API 保存业务数据,取得 `businessKey` 与 revision-bound `dataRef`;
|
|
103
|
+
2. 调用 Workflow prepare;
|
|
104
|
+
3. 在 Modal 中展示真实审批路径、条件分支、审批人,并仅在必要时收集主部门或未解析审批人;
|
|
105
|
+
4. 用户确认后以稳定幂等键发起流程。
|
|
106
|
+
|
|
107
|
+
审批预览不常驻页面,不把“预览流程”“保存并生成预览”“发起”暴露成三个主要步骤。业务字段、主部门或审批人答案变化后旧 preparation token 立即失效。保存草稿可以作为应用显式贡献,但不是所有流程页的第二主操作。
|
|
108
|
+
|
|
109
|
+
任务和流程详情使用 PageContainer、ProDescriptions、Timeline 与标准 Action Surface。允许按钮、字段读写、操作表单和下一处理人只消费后端 Surface;同意、拒绝、转交、回退、加签和代理不在浏览器复制状态机规则。
|
|
110
|
+
|
|
111
|
+
### 4.5 工作台与个人中心
|
|
112
|
+
|
|
113
|
+
默认工作台使用 ProCard/StatisticCard 组织指标、趋势、待办、快捷入口和最近访问。统计只来自带 RoleSession 和数据范围的服务端受限聚合;无真实数据时展示空态,不伪造数字。
|
|
114
|
+
|
|
115
|
+
个人中心统一展示资料、当前环境、稳定角色、数据范围、退出和角色切换。流程代理作为 Workflow 的可选贡献,不让 Core 静态依赖 Workflow。切换角色后更新 identity epoch,取消或丢弃旧请求,并恢复该角色自己的有界 UI 偏好。
|
|
116
|
+
|
|
117
|
+
### 4.6 用户端双 UI 与 Field Kit
|
|
118
|
+
|
|
119
|
+
Admin 与用户端是两个产品入口。Admin 只提供桌面管理体验;用户端由应用声明同一份页面、字段、动作和流程协议,再分别交给 Desktop Renderer 与 Mobile Renderer。两个 renderer 共享请求状态机、表单值、校验规则、字段策略、幂等键和错误模型,但不共享页面布局组件。平台在入口根据设备能力和用户显式偏好选择 renderer;切换 renderer 不改变 URL 业务语义、RoleSession 或业务草稿标识。
|
|
120
|
+
|
|
121
|
+
移动端不是桌面页缩放:表单采用单列、触摸目标、移动日期/选择器、底部安全区动作栏、图片拍摄/选择和适合小屏的分步反馈;桌面用户端可以使用栅格、侧栏详情和批量能力。需要同时支持两端的应用页面必须提供两套 view composition;纯管理页面无需生成移动版本。
|
|
122
|
+
|
|
123
|
+
新增独立的 OpenXiangda 2.0 Field Kit,按[稳定字段数据协议采用与声明分层决策](./stable-field-protocol-adoption.md)提供桌面与移动 renderer。物理存储、值形状、查询和索引协议不重新设计;V1 低代码组件名和展示 Schema 不作为 2.0 数据合同,新的可选 Surface Definition 只负责默认 UI。允许移植 1.x 中已经验证的平台能力控制器和测试,但禁止把 1.x Admin、页面壳、发布生命周期或样式运行时带入 2.0。
|
|
124
|
+
|
|
125
|
+
移动端的强制平台组件边界覆盖全部已支持的标准持久化字段,而不是只覆盖有独立后台接口的复杂类型。文本、数值、单/多选、下拉、级联、日期、日期区间、地址、人员、部门、附件、图片、富文本、签名和子表等都由 Mobile Field Kit 输入和规范化;其中选择面板、日期流程、地址级联、键盘、触摸目标和安全区沿用并升级平台已经验证的移动体验。页面可以自由使用移动组件库完成布局、导航、按钮和普通弹层,但不得直接用 Ant Design 桌面字段、原生输入控件或临时移动控件替代标准平台字段。缺失能力通过显式 Field Kit 扩展补齐,不在业务页面内形成第二套字段协议。
|
|
126
|
+
|
|
127
|
+
图片和附件字段只能使用 Field Kit 的平台附件组件。组件继续使用稳定附件值、上传、下载、鉴权预览、图片压缩和未绑定文件清理协议;应用不得直接使用 Ant Design `Upload`、原生文件输入或自行拼接对象存储 URL。生成器、ESLint 规则和模板静态审计把绕过行为视为构建错误。
|
|
128
|
+
|
|
129
|
+
列表、详情和表单使用同一 Field Renderer Registry。基础类型覆盖文本、长文本、布尔、日期时间、数值、金额、百分比、链接和枚举;平台类型覆盖成员、部门、角色主体、图片、附件和流程状态。成员/部门展示头像、名称和辅助组织信息,枚举使用声明色彩和标签,多选采用有界折叠,数值按精度、单位和 locale 格式化;未知类型使用安全文本降级并在开发诊断中报告,不能直接渲染 `[object Object]` 或原始内部编码。
|
|
130
|
+
|
|
131
|
+
## 5. 本地开发、构建与发布
|
|
132
|
+
|
|
133
|
+
`openxiangda dev` 继续是一条命令的生命周期入口,但改为监督 Umi 开发服务、NestJS 和独立本地平台服务。真实 PostgreSQL 仍由本地平台按工作区隔离管理,不要求开发者在电脑中手工安装数据库。Umi Mock 不能承载平台事实;本地平台与远程平台消费同构的身份、Data、Workflow 和 Event HTTP 合同。
|
|
134
|
+
|
|
135
|
+
AppPackage 的边界不变:生产构建仍输出静态前端 `dist`、NestJS OCI 镜像、配置合同和摘要。构建入口从 Vite 迁移到 Umi/utoopack;同一源代码连续构建必须闭包一致,生产包静态证明不包含本地 Mock、测试用户或开发凭据。
|
|
136
|
+
|
|
137
|
+
生产体积门禁按浏览器实际传输成本和解析上限分别约束:每个异步 JavaScript 块 gzip 后不得超过 420KB、解压后不得超过 1.5MB,首屏脚本解压总量不得超过 1.5MB。Ant Design/Pro 的异步共享块不再沿用 Vite 时代 800KB 的单一原始文本阈值;路由拆分数量、首屏闭包和开发标记扫描仍独立失败关闭。
|
|
138
|
+
|
|
139
|
+
正式切换完成时删除:
|
|
140
|
+
|
|
141
|
+
- Vite 配置和只服务旧模板的插件;
|
|
142
|
+
- 手写 React Router 路由树和重复菜单树;
|
|
143
|
+
- 自研 `AdminShell` 布局及其专用 CSS;
|
|
144
|
+
- 与 ProTable、ProForm、ProDescriptions 重复的通用搜索、列表、表单和详情壳;
|
|
145
|
+
- 旧流程提交常驻预览布局;
|
|
146
|
+
- 模板中的仪器业务演示和所有兼容开关。
|
|
147
|
+
|
|
148
|
+
不删除平台服务端身份、Data/Workflow HTTP 合同、route manifest 合同和运行诊断协议。旧前端中的 Provider、DirtyStateRegistry、受限偏好存储、路由匹配和生命周期实现全部删除;需要的产品行为在新的 Pro/Umi 边界重新实现,不允许通过 import、包装或复制旧源码继续使用。
|
|
149
|
+
|
|
150
|
+
允许复用的代码仅限不含 React、DOM、路由、样式或页面状态的生成契约与 HTTP 客户端。凡位于旧 `openxiangda-admin/src` 或旧模板 `apps/web/src` 的实现,一律视为待删除前端代码。
|
|
151
|
+
|
|
152
|
+
## 6. 默认参考应用
|
|
153
|
+
|
|
154
|
+
新参考应用改为“企业采购申请”,避免用仪器系统代表通用框架。默认覆盖:
|
|
155
|
+
|
|
156
|
+
- 采购申请人、部门负责人、财务、采购管理员和应用管理员;
|
|
157
|
+
- 采购单 CRUD、服务端搜索/排序/分页、附件、金额统计和部门数据范围;
|
|
158
|
+
- 多角色稳定切换、应用管理员授权声明和字段读写策略;
|
|
159
|
+
- 金额条件分支、审批预览 Modal、同意/拒绝/转交/回退/加签/代理;
|
|
160
|
+
- 流程事件消费、一个应用自定义 App API 动作与幂等回执;
|
|
161
|
+
- preproduction 默认运行,只有执行发布正式功能后才创建 production workload。
|
|
162
|
+
|
|
163
|
+
参考应用是验收载体,不向 `openxiangda-admin` 引入采购领域代码。
|
|
164
|
+
|
|
165
|
+
## 7. 失败、并发与资源边界
|
|
166
|
+
|
|
167
|
+
- route manifest 生成不一致、重复路径、缺 renderer 或权限漂移必须在 generate/check/build 阶段失败。
|
|
168
|
+
- Umi 开发服务唯一拥有 `src/.umi`;普通类型检查复用已存在的开发类型,只在目录缺失时初始化。生产构建只使用 `src/.umi-production`,不得通过 `max setup` 删除正在运行的开发工件。
|
|
169
|
+
- RoleSession bootstrap 失败时 fail closed,并提供重试、重新登录和 request id;页面不能以无权限空态掩盖系统错误。
|
|
170
|
+
- identity epoch 变化后中止旧请求;无法中止的 ProTable/React Query 响应按 generation 丢弃。
|
|
171
|
+
- 表单保存、流程 prepare/start 和自定义动作使用 revision/CAS 与稳定幂等键,重复点击或网络重试不能重复创建。
|
|
172
|
+
- 异步 chunk 加载失败使用路由级错误边界和就地重试,不能把整个应用变成白屏。
|
|
173
|
+
- 浏览器持久存储只允许有界 UI 偏好和逻辑路由,不保存 token、capability、业务响应或表单草稿。
|
|
174
|
+
- 删除 Pro 模板无用依赖和页面,业务模块按路由拆包;为首屏、单 chunk、总 JavaScript 和可选 Workflow chunk 建立预算。
|
|
175
|
+
|
|
176
|
+
## 8. 回滚边界
|
|
177
|
+
|
|
178
|
+
在首个正式 2.0 包发布前,回滚单位是整个工具链/模板/Admin 提交或 AppVersion,不在运行时保留旧 Shell。实现可以分提交,但对外只发布已删除旧实现且通过门禁的完整版本。
|
|
179
|
+
|
|
180
|
+
已经生成的 2.0 测试应用直接重新初始化或迁移源码贡献,不承诺 UI 组件 API 兼容。1.x 保持在 `tools/openxiangda` 与原平台运行时中,既不迁移也不回滚。
|
|
181
|
+
|
|
182
|
+
## 9. 可证伪验收
|
|
183
|
+
|
|
184
|
+
全量切换只有同时满足以下条件才算完成:
|
|
185
|
+
|
|
186
|
+
1. 从已打包工件在空目录创建企业采购参考应用,`openxiangda generate/check/test`、类型检查和 Umi production build 全部通过;
|
|
187
|
+
2. 依赖与源码审计证明没有 Vite、手写 React Router、旧 AdminShell、常驻流程预览或模板 Mock 进入生产包;
|
|
188
|
+
3. Ant Design lint、单元测试和 Playwright 覆盖 Admin 的 1280/1440px 桌面布局,以及用户端独立 Desktop/Mobile Renderer 的身份、字段、表单和流程主路径;Mobile 验收必须包含单/多选、下拉、级联、日期/日期区间、地址、人员/部门、数值、附件/图片和子表,且证明未加载桌面数据录入控件;
|
|
189
|
+
4. ProTable 覆盖服务端搜索、排序、分页、列配置、字段裁剪、修订冲突、导入导出和身份切换旧响应隔离;
|
|
190
|
+
5. ProForm/详情覆盖新建、编辑、脏状态、附件、审计、内部编码隐藏和服务端错误;
|
|
191
|
+
6. 流程页覆盖“业务表单 → 点击提交 → Modal 预览/补充选择 → 确认发起”,以及任务的完整标准动作;
|
|
192
|
+
7. `openxiangda dev/status/stop/reset` 在真实 PostgreSQL 上通过,前端与 Nest 热更新、本地重启保留和显式 reset 清理均有证据;
|
|
193
|
+
8. production bundle 不含 local canary、假用户、Mock API 或原始 Secret,并通过 chunk/首屏预算;
|
|
194
|
+
9. 同一 AppVersion 先部署 preproduction,再原样创建/晋级 production;失败可回滚上一 AppVersion;
|
|
195
|
+
10. 1.x View、流程、自动化与 1.x 发布回归无变化。
|
|
196
|
+
|
|
197
|
+
## 10. 实施顺序
|
|
198
|
+
|
|
199
|
+
1. 冻结官方 Pro v6 基线、依赖和新版页面设计验收稿;
|
|
200
|
+
2. 删除旧 Admin 与旧模板前端源码,建立空白 Umi Max / ProComponents 工程边界;
|
|
201
|
+
3. 从零实现 ProLayout、Umi route generator、身份启动、ProTable/ProForm/ProDescriptions、工作台和新的有界生命周期能力;
|
|
202
|
+
4. 改造流程提交 Modal、工作中心、任务和详情 Surface;
|
|
203
|
+
5. 从空白边界实现 2.0 Field Kit、用户端 Desktop/Mobile Renderer 与附件绕过门禁;
|
|
204
|
+
6. 更新本地开发编排、CLI/MCP/Skills、打包和发布门禁;
|
|
205
|
+
7. 用正式候选 tarball 创建企业采购参考应用并完成真实浏览器、NestJS、PostgreSQL、preproduction 验收;
|
|
206
|
+
8. 静态证明发布包没有旧源码、旧领域代码和兼容开关,通过 Changesets 物化一次正式候选版本。
|
|
207
|
+
|
|
208
|
+
上述步骤是一个发布单元内的实现顺序,不代表对外提供双框架。任一步不能达到可逆和可验证状态时,停止在源码提交边界修正,不把半成品发布给新应用。
|
|
209
|
+
|
|
210
|
+
## 11. 2026-08-16 实现轮门禁
|
|
211
|
+
|
|
212
|
+
### 问题证据与影响范围
|
|
213
|
+
|
|
214
|
+
- 当前模板仍受旧手写 `ApplicationShell`、路由匹配器、生命周期和仪器示例结构影响;局部替换为 ProLayout 后,真实浏览器验收出现身份操作被旧侧栏生命周期挤到底部的结构性冲突,证明渐进改造路线不可接受。
|
|
215
|
+
- `WorkflowSubmissionPage` 把审批预览常驻在页面,并把保存、预览、确认拆成多个主要动作。
|
|
216
|
+
- 影响范围限定为 `tools/openxiangda-v2` 的 Admin 包、模板、生成器、CLI/MCP/Skills 和新参考应用;1.x 仓库、1.x View、流程和自动化不引用本轮包。
|
|
217
|
+
|
|
218
|
+
### 稳定合同与失败语义
|
|
219
|
+
|
|
220
|
+
- route manifest 是路由、菜单和 capability 投影的唯一业务声明;生成器只产生 Umi/ProLayout 所需工件,不建立人工维护的第二棵树。
|
|
221
|
+
- RoleSession、DataQuery、Workflow Surface、AppVersion 与环境 Head 的服务端合同保持唯一事实源;Pro 组件只负责表现和参数适配。
|
|
222
|
+
- 身份初始化、异步 chunk、数据查询和流程 prepare 任一失败都显示带 request id 和重试动作的语义错误态,不允许白屏或伪装成空数据。
|
|
223
|
+
- 流程 prepare token 绑定业务数据 revision、主部门/审批人答案和身份 epoch;任一变化使旧 token 失效。重复确认使用稳定幂等键。
|
|
224
|
+
|
|
225
|
+
### 安全、资源与并发边界
|
|
226
|
+
|
|
227
|
+
- 浏览器不持久化 token、capability、业务响应、流程 token 或表单草稿;只保存有界 UI 偏好和逻辑路由。
|
|
228
|
+
- 标签最多 12 个、保活实例最多 6 个;身份 epoch 切换取消或丢弃旧请求与选择状态。
|
|
229
|
+
- 列表只做服务端分页、排序和有界筛选;图表只消费服务端受限聚合。
|
|
230
|
+
- production bundle 禁止包含模板 Mock、假用户、开发凭据和原始 Secret。
|
|
231
|
+
|
|
232
|
+
### 设计评审与回滚边界
|
|
233
|
+
|
|
234
|
+
本轮形成 3 张独立横向设计基线,见 [Admin Pro v6 设计说明](../design/admin-pro-v6/README.md):工作台、标准数据管理、流程提交 Modal。设计参数为视觉变化 3/10、动效 2/10、信息密度 5/10;实现以 Pro v6 token 和真实浏览器证据为准。首个新包发布前的回滚单位是整个 Admin/模板提交与 AppVersion,不保留旧 Shell 运行时开关。
|
|
235
|
+
|
|
236
|
+
### 可证伪检查
|
|
237
|
+
|
|
238
|
+
1. 空目录新建应用后不存在 Vite、手写路由树、旧 Shell、旧 Admin 源码引用和仪器领域代码;Umi production build 可重复通过。
|
|
239
|
+
2. ProTable、ProForm、ProDescriptions 和 ProLayout 的 API 均来自锁定版本,Ant Design lint、类型检查、单测和 Chromium 验收通过。
|
|
240
|
+
3. 流程提交页面静态审计只有一个主提交动作;审批路径只在 prepare 成功后的 Modal 中出现。
|
|
241
|
+
4. 直接 URL、菜单裁剪、标签恢复和 capability 使用同一生成 manifest;身份切换后旧请求不能回写当前页面。
|
|
242
|
+
5. `openxiangda-admin/src` 与模板 `apps/web/src` 的新实现不存在对被删除前端文件的 import、包装或复制;门禁不通过时只回滚整个绿地提交或候选 AppVersion,不发布半成品。
|
|
243
|
+
|
|
244
|
+
## 12. 2026-08-16 本地 Workflow Kernel 清单驱动决策
|
|
245
|
+
|
|
246
|
+
### 问题证据与能力所有者
|
|
247
|
+
|
|
248
|
+
- 本地平台已经接收编译后的 Workflow Definition、Binding 与 Activation,但准备、发起、条件分支、审批推进、退回、字段策略和参与人校验仍写死为旧“仪器预约”节点。这会让新应用的页面与清单看似正确,而真实提交执行另一套隐藏状态机。
|
|
249
|
+
- Workflow Definition/Binding 是节点、转移、操作、字段策略和审批角色的唯一所有者;Activation 是本地生效版本的唯一所有者;应用 NestJS 是 App API 业务逻辑的唯一所有者。本地平台不得再保存示例领域路由或第二份流程规则。
|
|
250
|
+
|
|
251
|
+
### 稳定不变量与失败语义
|
|
252
|
+
|
|
253
|
+
1. 本地 prepare、start、approve、reject、return、resubmit 与 Surface 全部读取当前 Activation 指向的 Definition/Binding;条件表达式复用 `openxiangda-workflow` 的解释器。
|
|
254
|
+
2. 业务数据继续由 Data API/App API 保存。完整模式的 App API 只代理当前 NestJS;纯前端模式仅提供平台诊断端点,业务接口明确返回不存在,不伪造成功。
|
|
255
|
+
3. 未激活流程、无效节点、不可解析审批角色、不允许的退回目标和并发版本冲突均失败关闭,且不写入一半实例或任务。
|
|
256
|
+
4. 代理、转交与加签仍校验当前节点 Binding 的角色和数据范围;应用管理员仍可按最高授权声明处理任务,但不改变原审批角色事实。
|
|
257
|
+
5. 变更只存在于 OpenXiangda 2.0 本地平台与新模板;1.x 流程、自动化、View 和发布链路没有依赖关系。
|
|
258
|
+
|
|
259
|
+
### 资源、并发与回滚边界
|
|
260
|
+
|
|
261
|
+
- 单次无人工节点解析最多 200 步,沿用 Workflow 编译器的无环校验;准备令牌继续绑定首个审批身份,发起前身份或分派变化必须重新预览。
|
|
262
|
+
- PostgreSQL 模式继续通过版本/CAS、幂等回执和单事务写入实例、任务与时间线;内存模式保持同样的可观察结果。
|
|
263
|
+
- 回滚单位是本地平台包、模板和生成清单的同一候选提交,不保留旧领域分支或兼容开关。
|
|
264
|
+
|
|
265
|
+
### 可证伪验证
|
|
266
|
+
|
|
267
|
+
1. 采购参考流程的低额路径直接进入采购审批,高额或专项复核路径依次进入部门、财务、采购审批;节点、标题与字段策略均与清单一致。
|
|
268
|
+
2. 退回目标只能来自当前审批节点的 `returnTargets`,重提回到原任务节点;非 `sequence` 审批模式不被本地运行时强制改写。
|
|
269
|
+
3. 更换为测试用的另一套节点名称和角色后,本地平台无需改代码即可 prepare/start/approve。
|
|
270
|
+
4. 源码与打包审计不再包含 `reservation-approval`、`college-review`、`instrument-review` 或示例 App API 路由。
|
|
271
|
+
|
|
272
|
+
### 本地代理身份夹具边界
|
|
273
|
+
|
|
274
|
+
- 问题证据:本地 Workflow Kernel 曾在运行时代码中内置“学院管理员/仪器管理员”和固定用户,导致代理、加签与身份切换只对旧示例成立,也让本地平台成为应用角色的第二个定义源。
|
|
275
|
+
- 能力归属:角色 code、名称和能力只由应用 `authz.roles` 声明;`openxiangda.local.json` 仅声明本地外部用户对应哪个既有角色成员身份及其测试范围。
|
|
276
|
+
- 稳定约束:本地代理目标必须引用已声明角色、已声明范围维度和 Directory 中的用户;平台不得生成行业角色或猜测用户授权。
|
|
277
|
+
- 契约:本地夹具新增可选 `workflowDelegationTargets[]`,每项使用稳定 code、userId、roleCode、scopeGrants;其本地 RoleSubject key 由平台确定性派生,不进入应用包或远端环境。
|
|
278
|
+
- 失败与并发:重复 code、未知用户、未知角色或未知范围维度在本地平台启动时立即失败;代理规则的重叠、幂等和版本竞争仍由 Workflow Kernel/PostgreSQL 事务负责。
|
|
279
|
+
- 安全与资源边界:该夹具只在 `local` 环境生效,不产生远端授权;应用超级管理员仍可做本地验收,但不会改变代理目标的正式角色能力。
|
|
280
|
+
- 回滚边界:删除 `workflowDelegationTargets` 只会关闭本地外部代理模拟,不影响清单、业务数据或远端环境;旧的内置行业目标不保留兼容分支。
|
|
281
|
+
- 可证伪验证:通用采购模板可将部门负责人代理给 Directory 用户并完成代理、加签、重启恢复和并发命令验收;运行时代码和打包模板不再出现旧行业角色常量。
|
|
282
|
+
|
|
283
|
+
### 加签参与者完成语义
|
|
284
|
+
|
|
285
|
+
- 问题证据:`any`/`single` 审批模式在用户执行后加签后仍会由原参与者的一次同意直接完成节点,等待中的加签参与者被取消,违背“显式加签必须处理”的用户意图。
|
|
286
|
+
- 能力归属:Workflow Kernel 是参与者队列与审批完成判定的唯一所有者;页面只提交 `add_assignee` 命令并渲染后端返回的参与者状态。
|
|
287
|
+
- 稳定约束:任何处于 `pending` 且 `required` 的参与者都是显式建立的顺序义务;当前参与者通过后必须先激活该参与者,不能被节点的 `single`/`any` 原始审批模式跳过。
|
|
288
|
+
- 失败与并发:参与者推进与任务/实例版本在同一 Workflow 命令事务内 CAS;重复命令走幂等回执,竞争命令只有一个版本胜出。
|
|
289
|
+
- 回滚边界:变更只影响 2.0 Kernel 的参与者完成规划,不修改 1.x 流程,也不增加兼容开关。
|
|
290
|
+
- 可证伪验证:`single`/`any` 节点的前加签和后加签均先推进必需参与者,所有必需参与者完成后才允许节点流转;完整 PostgreSQL 生命周期覆盖代理后加签和重启恢复。
|
|
291
|
+
|
|
292
|
+
## 13. 2026-08-16 候选包与独立参考应用一致性决策
|
|
293
|
+
|
|
294
|
+
### 问题证据与能力所有者
|
|
295
|
+
|
|
296
|
+
- 绿地 Admin 删除旧源码后,候选 tarball 仍包含旧 `dist` 文件;原因是 TypeScript 增量构建不会删除已经失去源码的历史输出。tarball 验证只检查入口存在,无法证明包内没有旧实现。
|
|
297
|
+
- 独立参考应用只更新依赖版本但仍保留旧仪器/预约源码,安装新 Admin 候选后类型检查失败。模板仓库与长期参考应用之间缺少“同代应用源码”约束。
|
|
298
|
+
- 每个公开包自己的 `build/prepack` 是发布字节的唯一所有者;`create-openxiangda` 模板是新建应用结构的唯一所有者;独立参考应用只拥有自身 app code、名称、仓库历史和线上 AppVersion,不另行维护一套框架源码。
|
|
299
|
+
|
|
300
|
+
### 稳定不变量、失败与并发
|
|
301
|
+
|
|
302
|
+
1. 所有公开包必须提供 `build:release`,在完整构建前删除已经没有对应 TypeScript 源文件的孤儿输出,且 `prepack` 必须执行该构建;修剪脚本只允许处理当前仓库 `packages/*/dist` 的文件,路径不匹配立即失败。它不删除仍有源码的当前输出,避免另一个 Turbo 任务或本地消费者在打包窗口读不到依赖类型。
|
|
303
|
+
2. 新建应用验收与独立参考应用验收使用同一组不可变候选 tarball。新建应用证明模板完整,独立应用证明真实仓库、锁文件与升级/部署链路完整。
|
|
304
|
+
3. Admin/模板发生绿地代际切换时,参考应用必须从当前模板重新生成并只保留自己的身份和业务增量;禁止靠兼容导出让旧示例继续编译。
|
|
305
|
+
4. 版本、参考应用源码或 lockfile 任一不一致时 release plan 失败关闭;不得发布部分包或让 registry tag 指向混合版本。
|
|
306
|
+
5. 同一候选的普通 build/check 与其他包的 release-build 可以并行;release-build 只修剪自己包内的孤儿文件,不制造当前入口缺失窗口。发布仍由单一 release plan 串行提交 registry tag,避免不同会话覆盖候选字节。
|
|
307
|
+
|
|
308
|
+
### 安全、资源与回滚边界
|
|
309
|
+
|
|
310
|
+
- 清理范围固定为直接包工作区下的 `dist`,不接受参数、环境变量、通配符或仓库根目录;不会接触源码、用户数据和 1.x 工件。
|
|
311
|
+
- 独立参考应用的绿地同步只删除其 Git 可恢复的旧 2.0 示例源码,不保留运行时兼容开关;线上回滚仍以最后一个健康 AppVersion 为单位。
|
|
312
|
+
- 回滚工具链时回滚构建不变量提交和对应 alpha 版本;参考应用可以从 Git 历史恢复上一提交。1.x 应用、流程、自动化和发布链路不在影响范围。
|
|
313
|
+
|
|
314
|
+
### 可证伪验证
|
|
315
|
+
|
|
316
|
+
1. 先构建含已删除源码的包,再执行 `pnpm pack`,tarball 中不存在对应历史 `dist` 文件。
|
|
317
|
+
2. 工作区编排门禁枚举所有公开包,缺少独立 release-build 或 prune-before-pack 任一约束即失败;并行 affected gate 中 pack 不会删除下游正在读取的当前输出。
|
|
318
|
+
3. 从候选 tarball 新建空目录应用以及绿地同步后的独立参考应用均通过 generate/check/test/build;旧 `ApplicationShell`、仪器和预约源码不再存在。
|
|
319
|
+
4. release plan 只在参考应用 manifest 与全部公开包候选版本完全一致时生成;正式发布前重新校验 lockfile 与 registry 工件一致。
|
|
320
|
+
5. 参考验收调用标准 CLI 命令而不要求应用增加仓库私有的 generate 脚本;显式安装候选到参考工作树时先写入一次生成契约,后续隔离副本和普通发布验收只允许 `generate --check`。生成模板必须从 Git 与 OCI 构建上下文排除 `.codegraph`、`.openxiangda`、`.env` 等本地状态。
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# OpenXiangda 2.0 前端运行时挂载路径
|
|
2
|
+
|
|
3
|
+
状态:2026-08-16 已实现待发布,当前发布阻断项。
|
|
4
|
+
|
|
5
|
+
## 问题证据
|
|
6
|
+
|
|
7
|
+
同一个 Native 2.0 前端制品会先挂载在
|
|
8
|
+
`/service/openxiangda-apps/{appCode}/preproduction/`,通过验收后再原样挂载到
|
|
9
|
+
`/view/{appCode}/`。平台已经在返回的 `index.html` 中注入 `<base>` 和
|
|
10
|
+
`openxiangda-runtime-base`,但官方 Umi 模板仍以 `basename=/` 创建 browser
|
|
11
|
+
history。应用加载后,根路由重定向会把预发地址改写成域名根目录;静态资源已经加载,
|
|
12
|
+
但后续路由、刷新和身份初始化不再处于该应用的环境挂载路径。
|
|
13
|
+
|
|
14
|
+
这不是单个参考应用的页面错误,而是官方模板与平台动态挂载契约不闭合。把模板改为
|
|
15
|
+
hash history 可以规避跳转,但会降低正式地址质量,也会把已有 browser route、标签页和
|
|
16
|
+
深链接语义全部改成另一套协议,因此不采用。
|
|
17
|
+
|
|
18
|
+
## 能力归属
|
|
19
|
+
|
|
20
|
+
- Platform Server 是环境、活动前端修订和运行时挂载路径的唯一所有者。
|
|
21
|
+
- Platform Server 通过受控的 `index.html` 装饰写入
|
|
22
|
+
`meta[name="openxiangda-runtime-base"]`;应用、CLI 和 AI 不自行拼接环境 URL。
|
|
23
|
+
- `openxiangda-admin` 是 Umi/React Admin 的平台适配层,唯一负责把平台挂载路径转换为
|
|
24
|
+
Umi runtime `basename`。
|
|
25
|
+
- 应用只在 `src/app.ts` 注册官方适配函数,不复制解析、校验或环境判断逻辑。
|
|
26
|
+
|
|
27
|
+
## 决策
|
|
28
|
+
|
|
29
|
+
1. 继续使用 Umi browser history,不改为 hash history。
|
|
30
|
+
2. `openxiangda-admin` 提供纯函数读取并校验平台注入的 runtime base,再提供 Umi
|
|
31
|
+
`modifyContextOpts` 适配函数。
|
|
32
|
+
3. 官方模板在 `src/app.ts` 注册该适配函数;开发者页面和业务路由仍只使用以 `/` 开头的
|
|
33
|
+
应用内路径。
|
|
34
|
+
4. 本地开发没有 runtime meta 时稳定回退到 `/`。
|
|
35
|
+
5. runtime base 必须是同源绝对路径,不接受协议、host、query、fragment、反斜杠、控制字符
|
|
36
|
+
或超长输入。无效输入关闭到 `/`,不导航到外部 origin。
|
|
37
|
+
6. 前端制品、AppPackage 和 AppVersion 不包含环境专用 base;预发到正式晋级仍复用完全相同
|
|
38
|
+
的制品摘要。
|
|
39
|
+
|
|
40
|
+
## 稳定不变量与契约
|
|
41
|
+
|
|
42
|
+
- 环境挂载路径只由当前 HTTP 响应中的平台 meta 决定,不由 localStorage、构建变量、角色、
|
|
43
|
+
URL query 或应用业务数据决定。
|
|
44
|
+
- Umi 的路由定义、`useNavigate('/path')`、Admin 菜单路径和标签页路径始终是应用内路径;
|
|
45
|
+
SDK 只在 history/router 边界加一次 basename。
|
|
46
|
+
- `/service` Data API、App API、OAuth2 和身份端点仍是平台同源绝对服务路径,不拼入前端
|
|
47
|
+
basename。
|
|
48
|
+
- 深链接和刷新必须回到同一环境的前端修订;预发路由不得落入 production,production
|
|
49
|
+
路由不得落入预发。
|
|
50
|
+
- 该契约只作用于 Native 2.0 前端,不修改 1.x View、流程或自动化路由。
|
|
51
|
+
|
|
52
|
+
## 失败、并发与安全边界
|
|
53
|
+
|
|
54
|
+
- runtime base 在 React/Umi 创建 history 前同步解析,不产生异步竞争或第二份状态。
|
|
55
|
+
- 多标签、多角色切换和环境同时存在时,每个 HTML 文档只消费自己的 meta;标签之间不共享
|
|
56
|
+
mutable basename。
|
|
57
|
+
- 平台漏注入或输入非法时回退 `/`,页面可以显示确定性诊断;SDK 不猜测 appCode 或环境。
|
|
58
|
+
- 解析最长接受 2048 字符,只允许以单个 `/` 开头的 pathname,并规范为尾部 `/`。
|
|
59
|
+
- 适配函数不读取 Cookie、token、用户资料或业务数据,不扩大身份和授权边界。
|
|
60
|
+
|
|
61
|
+
## 资源与性能边界
|
|
62
|
+
|
|
63
|
+
该方案只增加一次同步 meta 查询和 pathname 校验,不增加请求、缓存、数据库状态或运行实例。
|
|
64
|
+
前端仍只产出一份可复用制品,不为预发和正式重复构建。
|
|
65
|
+
|
|
66
|
+
## 回滚边界
|
|
67
|
+
|
|
68
|
+
- SDK helper、官方模板注册和文档属于一个独立发布主题,可通过回退对应
|
|
69
|
+
`openxiangda-admin` 与 `create-openxiangda` 版本撤销。
|
|
70
|
+
- 平台现有 `<base>`/meta 注入保持兼容,不需要数据库迁移或 Platform Server 发布。
|
|
71
|
+
- 已生成的 2.0 测试应用可显式采用 helper;不自动改写 1.x 或其他历史应用。
|
|
72
|
+
|
|
73
|
+
## 可证伪验收
|
|
74
|
+
|
|
75
|
+
1. 纯函数对预发和正式 base 返回规范 pathname,对外部 URL、query、fragment、控制字符和
|
|
76
|
+
超长输入回退 `/`。
|
|
77
|
+
2. 官方模板继续声明 browser history,并注册 SDK 的 Umi runtime context 适配器。
|
|
78
|
+
3. 生产构建在注入预发 meta 后访问应用根路径,浏览器 URL 保持在预发挂载路径;导航、回退、
|
|
79
|
+
深链接刷新均不离开该前缀。
|
|
80
|
+
4. 同一前端 artifact 晋升 production 后,在 `/view/{appCode}/` 下通过相同场景。
|
|
81
|
+
5. 两个环境的身份请求分别携带正确环境语义,控制台没有未处理异常、资源 404 或无效 JSON。
|
|
82
|
+
6. 全量 2.0 release gate、仓库外参考应用构建与线上 preproduction→production 验收通过。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenXiangda 2.0 实施路线图与证据矩阵
|
|
2
2
|
|
|
3
|
-
状态日期:2026-08-
|
|
3
|
+
状态日期:2026-08-16
|
|
4
4
|
|
|
5
5
|
本文只记录可由源码、自动测试、真实 HTTP、新应用黑盒或已发布工件证明的状态。文档存在不等于运行时完成,Mock 通过不等于平台集成完成,npm 已发布也不等于某个应用已经部署。
|
|
6
6
|
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
| --- | --- |
|
|
11
11
|
| 已交付 | 平台/工具链实现、正式门禁和独立应用证据均闭环 |
|
|
12
12
|
| 已实现待晋级 | 代码与门禁已通过,但尚未作为目标 AppVersion 晋级指定环境 |
|
|
13
|
+
| 已确认待实施 | 架构决策已经确认,运行时尚未按新方案完成,不能对外宣称交付 |
|
|
13
14
|
| 已设计待确认 | 所有权、不变量、契约、失败恢复和验收矩阵已形成;根据架构门禁,确认前不修改运行时 |
|
|
14
15
|
| 未开始 | 尚无可以进入实现的确认设计 |
|
|
15
16
|
|
|
@@ -30,19 +31,20 @@
|
|
|
30
31
|
| 确定性工具链发布 | Changesets 版本提交、冻结工件清单、release receipt | 已交付 | 待消费 Changeset 在构建前 fail-fast;版本只由 Changesets 物化;正式发布只验证一次同一批 tarball;CLI alpha.20 与 skill-kit alpha.19 已按该状态机发布并打 Git tag | 周期性全量审计保留;不得恢复人工选包、手工版本或重复正式门禁 |
|
|
31
32
|
| 环境配置内核 E0-E6 | AppVersion/component revision + native Runtime Environment + minimal Environment Head + 环境运行态 | E1-C0/C1/S0/S1/T0 已完成 | breaking config/contracts v3、平台纯编译器、六领域不可变投影、聚合投影、AppVersion binding、compile receipt、精确 artifact shadow prepare 与真实 PostgreSQL 并发/来源防伪/绑定后不可变已经通过;全新 `openxiangda-v2-native-reference-app` 由候选 tarball 创建并完成 check/test/build,连续构建逐字节一致,config/contract v3 闭包和 artifact/manifest 篡改拒绝已进入发布门禁 | 下一步进入 A0 Native 环境授权;随后实现 Data physical/logical、最小 Head CAS、pending credential、调用委托/网关断言、runtime lease、候选 GC 与 generation cutover。旧 alpha 只留审计历史,不做双读、双写或导入 |
|
|
32
33
|
| 授权内核 A0-N/C/P | 不可变 authz revision + 环境 authz state + native role/scope 表 | 已确认实施;N0/N1/N2/C1/C2/P 完成 | N1/C1 建立不可变定义、两环境 state 与原子版本;N2 建立独立 Native 运行表与局部撤权;C2 建立 DB-authoritative evaluator、request cache、环境/版本 cache namespace、边界 TTL 与 RelationshipGrant 直读;P 升级 `native-2` 配置契约并建立 source definition、projection state/job/receipt/value/closure/effective grant、Data API 与 membership 原子失效、冷启动恢复与 strict gate;89 个 SQL migration 校验、35 个 2.0 migration 真实 PostgreSQL 幂等应用、39 个平台套件 / 263 项测试和工具链全 workspace 测试通过 | 当前推进 N3-N5。alpha membership/grant 不复制、不迁移,禁止给 legacy 表补 environmentKey 或建立长期双读/双写 |
|
|
33
|
-
|
|
|
34
|
+
| Ant Design Pro v6 Admin 全量切换 | Ant Design Pro v6 承担通用 Admin;`openxiangda-admin` 承担平台集成 | 已实现待发布 | Vite/旧自研 Shell 与仪器示例已从模板删除;React 19、Ant Design 6、Umi Max 4、ProComponents 3、utoopack、ProLayout、ProTable、ProForm、Field Kit 和企业采购参考应用已落地。桌面 Chromium 单链路通过工作台、菜单、会话标签、稳定角色切换、列表/详情、独立供应商表单、工作中心、单按钮流程提交和个人中心,并断言无运行时错误;production build 通过 420KB gzip/1.5MB raw 异步块与 1.5MB 首屏门禁 | 补 Changesets、`verify:affected` 和正式包发布;随后以已发布 tarball 创建仓库外新应用并完成 preproduction→production 在线验收。移动用户端 Field Kit 已有独立 renderer,完整移动页面模板与设备 Chromium 验收另列下一阶段 |
|
|
35
|
+
| 前端动态挂载路径 | Platform Server 注入 runtime base;`openxiangda-admin` 适配 Umi basename | 已实现待发布 | 线上预发证实 browser history 错误离开环境前缀;SDK 已实现有界同源 pathname 校验与 Umi runtime context,官方模板保持 browser history 并通过窄 `runtime` 入口消费,纯函数测试、生成器测试、affected gate 与生产 bundle 标记/体积门禁通过 | 发布 `openxiangda-admin` 与 `create-openxiangda`,仓库外参考应用升级后以同一 artifact 完成 preproduction→production 在线导航、深链接刷新、身份与控制台验收;不改 hash history,不增加环境专用构建 |
|
|
34
36
|
| Admin A1 RoleSession 上下文 | Native RoleSession bootstrap 是唯一身份资料/role subject/scope 来源 | 已设计待确认 | SubjectProfile 字段白名单、tenant 联合查询、非 active scope=null、capability=`authz.role-session-context`、有界 role subject 分页与切换 CAS 已定义 | A0 native cutover 后实现;A1 自身不再增加身份存储,但不得建立在 alpha 全局 assignment 上;平台先发,工具链后要求 capability |
|
|
35
37
|
| Admin B0-O 租户公共 Origin | Platform Server Origin module + 版本/head/hostname claim registry | 已设计待确认 | 全仓确认多套模糊解析和广泛 URL 调用者;prod-1 证实 HTTPS/HTTP 配置差异、未登记 vhost 别名,且生产 `default_configs` 没有源码宣称的复合唯一约束;稳定租户 UUID、不可变 staged→challenge→verified→active、head revision CAS、hostname claim、事务审计、全局兼容阶段+单租户事实源状态、无长期双写和[逐文件实施蓝图](./tenant-public-origin-implementation-blueprint.md)已定义 | 确认后先做 O0 只读 inventory/digest 与 plan validator;操作者显式决定 migrate/decommission,所有服务实例同版后进入 migrating,再逐租户冻结/验证/切换,单租户失败不阻塞全平台;B0-R 不得绕过该阶段 |
|
|
36
38
|
| Admin B0-C Cookie 安全 | Platform Server `AuthCookieService` + 无状态 policy resolver | 已设计待确认 | 已确认当前 DOMAIN JSON 同时决定 Cookie Domain 且 `secure:false`;共享会话/协议 Cookie 所有权、HTTPS Secure/`__Host-`/host-only、版本化名称、legacy scope manifest、C0/C1/C2 状态机和旧 host retirement 已定义 | B0-O registry 稳定后独立实现;首期不支持跨子域共享;C1 后只能回滚到理解 v2 Cookie 的兼容镜像,不和 Origin 数据迁移、return target 或 OAuth state 混发 |
|
|
37
39
|
| Admin B0-R 登录 return target 安全 | 平台通用登录代理和服务端 CAS 校验 | 已设计待确认 | 全仓审计确认平台、1.x View、流程、旧编辑器和 CLI 合法生产者均可归入同源;一次解析、8 KiB 上限、精确 origin、CAS 双阶段规范化、错误链路 fail closed 及回归向量已定义 | 明确确认后作为独立平台安全提交,不和 Shell 改造、OAuth state 或身份协议混发 |
|
|
38
40
|
| 旧平台第三方认证 S0 | Platform Server 一次性 OAuth state 与 purpose 绑定 | 未开始 | 已证明旧登录 state 仅为 tenantId、回调未消费 state,账号绑定指向未注册 `/bind-callback` 且 tenantId 为空 | 先单独形成登录/绑定事务、TTL、一次性消费和迁移设计;不得把它混入 B0-R,也不重做 2.0 Client Credentials/App Auth |
|
|
39
|
-
| Admin
|
|
41
|
+
| Admin 既有协议迁移输入 | `openxiangda-admin` 平台适配层与显式可选 contribution | 已实现,待迁入 Pro v6 | anyOf/allOf、manifest 闭包、直接 URL 403、独立数据表单/详情、资源级失效、工作中心服务端分页、DirtyStateRegistry、12 标签/6 keepAlive LRU、identityScope/epoch 隔离、个人中心贡献化和 Core-only Workflow 负向证明已有测试证据 | 保留协议和并发不变量,删除旧 UI 与重复通用组件;不得为旧组件 API 建兼容层,也不得引入临时全局状态、角色名判断、未绑定环境的缓存键或第二套查询 DSL |
|
|
40
42
|
|
|
41
43
|
## 3. 当前关键路径
|
|
42
44
|
|
|
43
45
|
```mermaid
|
|
44
46
|
flowchart LR
|
|
45
|
-
Audit["B0-R 全仓生产者审计(已完成)"] --> Confirm["确认 Admin
|
|
47
|
+
Audit["B0-R 全仓生产者审计(已完成)"] --> Confirm["确认 Admin 平台边界"]
|
|
46
48
|
Confirm --> CP["CP0/CP1 alpha 退役 preflight"]
|
|
47
49
|
CP --> E1["E1 Native config/contracts v3"]
|
|
48
50
|
E1 --> T0["E1-T0 全新 Native reference(已完成)"]
|
|
@@ -56,21 +58,18 @@ flowchart LR
|
|
|
56
58
|
B0O --> B0["B0-R 平台 return target 收敛"]
|
|
57
59
|
B0O --> B0C["B0-C Cookie 安全迁移"]
|
|
58
60
|
A1 --> A2["A2 identityScope / epoch"]
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
A2 --> D["D Data Workbench controller"]
|
|
61
|
+
A2 --> Pro6["Ant Design Pro v6 全量切换"]
|
|
62
|
+
B0 --> Pro6
|
|
63
|
+
Pro6 --> Pages["ProTable / ProForm / Workflow Surface"]
|
|
64
|
+
Pro6 --> Life["标签 / 有界 keepAlive / 个人中心"]
|
|
64
65
|
B0C --> Fresh["完整新应用 Chromium 验收"]
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
C --> Fresh
|
|
68
|
-
D --> Fresh
|
|
66
|
+
Pages --> Fresh
|
|
67
|
+
Life --> Fresh
|
|
69
68
|
Fresh --> Release["Changesets 物化与单次正式发布"]
|
|
70
69
|
Release --> Promote["同一 AppVersion 预发/正式晋级"]
|
|
71
70
|
```
|
|
72
71
|
|
|
73
|
-
|
|
72
|
+
当前产品缺陷与上游兼容性已经构成重写 Admin 表现层的证据,因此采用 [Ant Design Pro v6 全量切换](./ant-design-pro-v6-admin-foundation.md);这不等于重写 OAuth2、Secret、Events、Workflow、RoleSession、DataQuery 或环境内核。平台数据/授权轨仍按 CP0/CP1、E1/A0/E4 与 Native generation 边界推进;具体隔离与退役合同见[Alpha 退役与 Native 切换前置审计](./native-kernel-inventory-v2.md),bundle v3、最小 Head、不可变投影和激活事务边界见[原生配置投影蓝图](./native-configuration-projection-v2.md)。安全轨从 B0-O0/O1 开始;新 Pro Shell 的安全退出仍等待 B0-R,完整生产晋级同时通过 B0-C。不能为了页面迁移先改缓存、角色判断、登录跳转或给 legacy 表临时加环境分支。
|
|
74
73
|
|
|
75
74
|
## 4. 每轮执行记录要求
|
|
76
75
|
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
状态:L0-L3 已实现,并由打包工具链创建的全新应用在真实 PostgreSQL 上验证;本轮补齐可审计的 status/stop/reset 生命周期控制
|
|
4
4
|
|
|
5
|
+
> 2026-08-16 架构修订:Admin 前端目标工具链已[全量切换到 Ant Design Pro v6 / Umi Max](./ant-design-pro-v6-admin-foundation.md)。本文出现的 Vite 只描述切换前已实现证据;迁移后由 Umi 开发服务接替页面与 HMR,本地平台、真实 PostgreSQL、NestJS、生命周期与安全边界保持不变。
|
|
6
|
+
|
|
5
7
|
## 1. 产品结论
|
|
6
8
|
|
|
7
9
|
开发者在新建应用后只需要运行:
|
|
@@ -10,7 +12,7 @@
|
|
|
10
12
|
openxiangda dev
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
命令打开完整 Admin 应用并同时启动 React/
|
|
15
|
+
命令打开完整 Admin 应用并同时启动 React/Umi Max、NestJS 和本地平台服务。前端、后端、生成契约和应用声明支持有界热更新;开发者不需要先 provision、登录远程平台或创建第三个远程环境。
|
|
14
16
|
|
|
15
17
|
远程部署环境只有 `preproduction`、`production`。`local` 是进程运行模式,不是 environment registry 记录:
|
|
16
18
|
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# 稳定字段数据协议采用与声明分层决策
|
|
2
|
+
|
|
3
|
+
状态:2026-08-16 已确认,OpenXiangda 2.0 实现必须遵守
|
|
4
|
+
|
|
5
|
+
适用范围:OpenXiangda 2.0 Data 声明、编译器、类型生成、Data API 适配、Field Kit、默认 Admin/用户端页面和参考应用。V1 应用运行时和发布链不在改造范围内。
|
|
6
|
+
|
|
7
|
+
## 1. 决策
|
|
8
|
+
|
|
9
|
+
OpenXiangda 2.0 原样采用已经长期运行的字段**数据协议**:值形状、PostgreSQL 物理存储、写入归一化、查询语义、索引策略,以及人员、部门、文件等平台数据能力保持不变。
|
|
10
|
+
|
|
11
|
+
V1 面向低代码设计器的完整组件 Schema 不作为 2.0 的数据合同。`required`、默认值、placeholder、隐藏、禁用、布局、联动、具体控件等展示属性可以按 2.0 页面需求重新设计;它们不能继续伪装成数据库约束或后端业务校验。
|
|
12
|
+
|
|
13
|
+
2.0 将字段数据、服务端写入规则和默认页面表现拆成三个独立且单向依赖的合同:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
Data Definition(权威数据结构)
|
|
17
|
+
├── PostgreSQL 存储计划
|
|
18
|
+
├── 稳定字段值 codec
|
|
19
|
+
├── Data API 结构校验/查询/索引
|
|
20
|
+
└── 生成 TypeScript 类型
|
|
21
|
+
|
|
22
|
+
Server Write Contract(权威业务不变量)
|
|
23
|
+
├── NestJS DTO/domain 校验
|
|
24
|
+
├── App API / Data API 服务端约束
|
|
25
|
+
└── 并发、幂等与业务错误
|
|
26
|
+
|
|
27
|
+
Surface Definition(可选默认 UI)
|
|
28
|
+
├── Admin 表单/列表/详情
|
|
29
|
+
├── 用户端 Desktop/Mobile 页面
|
|
30
|
+
└── 控件、顺序、布局、提示和客户端校验
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
自定义页面可以完全不声明或不消费 Surface Definition,但仍必须提交稳定字段值并通过服务端写入规则。Surface 的必填、隐藏和默认值只影响体验;真正的业务必填、范围和状态约束必须由服务端合同执行。
|
|
34
|
+
|
|
35
|
+
这不是把 V1 Admin、页面壳、低代码编辑器或发布流程带入 2.0。2.0 的 Umi/Ant Design Pro Admin、双端用户页面、NestJS 后端、AppPackage、环境和发布仍按绿地架构实现。
|
|
36
|
+
|
|
37
|
+
## 2. 能力所有者
|
|
38
|
+
|
|
39
|
+
| 能力 | 唯一所有者 |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| 字段逻辑数据类型、稳定值形状 | Data Definition + 平台稳定字段数据协议 |
|
|
42
|
+
| 字段到 PostgreSQL 列的映射 | 平台 Data 存储规划器 |
|
|
43
|
+
| 结构校验、查询操作符和索引 | 平台 Data API |
|
|
44
|
+
| 业务必填、业务范围、跨字段/状态校验 | 应用 NestJS domain/App API,或显式服务端 Data write constraint |
|
|
45
|
+
| 人员、部门、文件、图片、富文本、签名和位置后端能力 | 对应平台服务 |
|
|
46
|
+
| 默认 Desktop/Mobile/Readonly/List/Detail 外观 | OpenXiangda 2.0 Field Kit + Surface Definition |
|
|
47
|
+
| 自定义页面布局与交互 | 应用前端;不拥有数据协议或授权 |
|
|
48
|
+
| 流程节点字段读写状态 | Workflow Kernel Surface;后端最终校验 |
|
|
49
|
+
|
|
50
|
+
`required` 如果只出现在 Surface 中就是客户端提示;只有出现在 Server Write Contract 或数据库约束中才是业务不变量。编译器和文档必须明确区分,不能把两者自动等同后让自定义页面误以为可以信任前端。
|
|
51
|
+
|
|
52
|
+
## 3. 固定数据协议不变量
|
|
53
|
+
|
|
54
|
+
1. 简单字段继续使用现有原生列映射:文本/富文本为 `TEXT`,数字为 `FLOAT`,日期为 `TIMESTAMP`。
|
|
55
|
+
2. 日期范围继续展开为 `<fieldId>_start`、`<fieldId>_end` 两个 `TIMESTAMP` 列,对外保持既有日期范围值语义。
|
|
56
|
+
3. 选择、人员、部门、附件、图片、子表、级联、地址、关联数据、位置、签名和 JSON 等复杂字段继续使用 `JSONB`。
|
|
57
|
+
4. 选择类、人员和部门继续保存稳定的 `{ label, value }` 快照;单值为对象,多值始终为数组。展示使用 `label`,业务比较、查询和授权使用 `value`。
|
|
58
|
+
5. 附件和图片继续使用稳定附件项数组及现有上传、下载、预览、压缩变体协议;不得替换为未经迁移的新 `DataFileRef` 表单值,也不得在应用中直接拼接存储凭据。
|
|
59
|
+
6. 子表继续保存对象数组;子字段值协议和查询能力按现有规则执行,不允许页面自行改变持久化结构。
|
|
60
|
+
7. 字段写入保持“提交协议值、查询返回同一协议值”,平台只执行现有归一化与安全校验,不做应用可见的隐式翻译。
|
|
61
|
+
8. 现有 BTREE、JSONB value 表达式和 GIN `jsonb_path_ops` 语义保持一致。2.0 可以重构实现位置,但不能改变相同数据类型和索引声明产生的结果。
|
|
62
|
+
9. 已存在字段的物理类型不可隐式变更。类型变化继续 fail closed,并要求显式 shadow migration 和明确回填规则。
|
|
63
|
+
10. 数据权限和业务校验始终由后端执行。前端隐藏、只读、客户端校验和默认值不能扩大权限,也不能替代服务端约束。
|
|
64
|
+
|
|
65
|
+
新增数据类型必须有新的稳定 type code 和显式协议版本,不能修改既有类型的存储和值语义。
|
|
66
|
+
|
|
67
|
+
## 4. 最小 Data Definition
|
|
68
|
+
|
|
69
|
+
2.0 应用默认只声明字段 code、字段名称和逻辑数据类型。单值/多值使用不同 type code,使值形状无需额外低代码参数即可确定:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
export default defineDataResource({
|
|
73
|
+
code: 'purchase_request',
|
|
74
|
+
name: '采购申请',
|
|
75
|
+
fields: {
|
|
76
|
+
title: data.text('申请标题'),
|
|
77
|
+
amount: data.number('采购金额'),
|
|
78
|
+
applicant: data.user('申请人'),
|
|
79
|
+
approvers: data.users('审批人'),
|
|
80
|
+
department: data.department('申请部门'),
|
|
81
|
+
status: data.option('状态'),
|
|
82
|
+
tags: data.options('标签'),
|
|
83
|
+
attachments: data.attachments('附件'),
|
|
84
|
+
},
|
|
85
|
+
indexes: [
|
|
86
|
+
data.index('by_status_created', ['status', 'createdAt']),
|
|
87
|
+
data.index('by_department', ['department']),
|
|
88
|
+
],
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`fields` 的对象 key 是稳定字段 code;factory 只确定稳定数据类型和值协议。应用不声明 `componentName`、PostgreSQL 类型、serializer、query operator、index method 或 renderer。索引只声明业务字段组合和是否唯一,平台根据稳定数据类型选择普通列、`value` 表达式或 GIN 实现。
|
|
93
|
+
|
|
94
|
+
初始 type code 至少覆盖当前稳定数据能力:文本、数字、日期、日期范围、单/多选项、单/多人员、单/多部门、附件、图片、子表、级联、地址、位置、签名、富文本、JSON、流水号和关联数据。V1 的 `EmployeeSelectField`、`TextareaField`、`TableField`、`Jsx` 等名称进入审计映射,但不是新源码必须继续使用的 UI 组件名。
|
|
95
|
+
|
|
96
|
+
Data Definition 只保证结构正确:例如人员值必须是稳定 `{label,value}`,附件必须是附件项数组,数字能够按既有方式写入。它默认不判断“采购金额必须大于零”“状态只能从草稿变为已提交”等业务规则。
|
|
97
|
+
|
|
98
|
+
## 5. Server Write Contract
|
|
99
|
+
|
|
100
|
+
真正影响数据正确性的约束必须在服务端表达并执行,主要有两种方式:
|
|
101
|
+
|
|
102
|
+
1. 复杂业务写入通过 NestJS App API,由 DTO/domain service 校验必填、范围、跨字段关系、状态迁移和外部依赖。
|
|
103
|
+
2. 直接开放标准 Data API CRUD 的资源,可以声明少量平台服务端 write constraints;它们由 Data API 执行,并可投影给默认页面作为客户端提示。
|
|
104
|
+
|
|
105
|
+
默认页面可以把服务端约束投影为必填标记、数字范围和错误文案,但投影不是新的事实源。自定义页面即使不展示这些提示,服务端仍拒绝非法写入。只有纯展示偏好的 `ui.requiredHint`、默认值或隐藏设置不会升级成服务端约束。
|
|
106
|
+
|
|
107
|
+
前端、CLI 和生成客户端应区分结构错误、业务校验错误、权限错误和 revision 冲突,并把服务端字段错误映射回对应控件;不能只返回一个泛化的“提交失败”。
|
|
108
|
+
|
|
109
|
+
## 6. Surface Definition
|
|
110
|
+
|
|
111
|
+
Surface 是可选的默认页面协议,不参与建表:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
export const purchaseCreateSurface = defineFormSurface({
|
|
115
|
+
resource: 'purchase_request',
|
|
116
|
+
fields: {
|
|
117
|
+
title: ui.text({ placeholder: '填写本次采购事项' }),
|
|
118
|
+
applicant: ui.user({ readonly: true }),
|
|
119
|
+
department: ui.department(),
|
|
120
|
+
amount: ui.money({ unit: '元', precision: 2 }),
|
|
121
|
+
status: ui.radio({ options: purchaseStatusOptions }),
|
|
122
|
+
attachments: ui.attachment({ maxCount: 10 }),
|
|
123
|
+
},
|
|
124
|
+
desktop: desktopFormLayout(...),
|
|
125
|
+
mobile: mobileFormLayout(...),
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
不声明 Surface 时,平台按字段类型和名称生成干净的默认列表、表单和详情:字段顺序使用 Data Definition 顺序,控件和只读 renderer 使用 Field Kit 默认映射,不猜业务必填、默认值或隐藏逻辑。
|
|
130
|
+
|
|
131
|
+
自定义页面可以直接使用 Field Kit 组件、生成的 Data 类型和 Data/App API 客户端,而不使用 `defineFormSurface`。平台组件负责输出稳定字段值;页面负责交互;服务端负责最终正确性。
|
|
132
|
+
|
|
133
|
+
### 6.1 移动字段组件边界
|
|
134
|
+
|
|
135
|
+
用户端 Mobile Renderer 和 AI 生成的移动页面,对平台已经支持的持久化字段类型必须使用 Mobile Field Kit,不只限于人员、部门、附件和图片。适用范围至少包括文本、长文本、数值、金额、布尔、单选、多选、下拉单选、下拉复选、级联选择、日期、日期时间、日期区间、人员、部门、地址、位置、附件、图片、富文本、签名和子表。该要求同时复用稳定值 codec 与已经验证的移动交互,不允许把 Ant Design 桌面控件、原生 `input/select/file` 或未经平台适配的通用字段控件直接放进移动表单。
|
|
136
|
+
|
|
137
|
+
Mobile Field Kit 负责触摸目标、软键盘、底部选择面板、安全区、搜索与多选收起、日期/区间选择步骤、时区和值归一化、地址级联与平台数据、上传预览以及取消/确认状态。它可以在内部组合经过评审的移动组件库,但应用页面不拥有这些平台字段的值转换和交互实现。应用仍可使用移动组件库实现导航、布局、卡片、按钮、普通弹层和不写入平台字段的临时交互。
|
|
138
|
+
|
|
139
|
+
自定义移动页面的“自定义”指页面布局、信息组织和业务交互可完全自定义,不代表重新发明平台字段控件。平台尚未覆盖的新字段必须先通过显式 Field Kit 扩展注册 renderer、codec、只读/list/detail 表现和测试;不得在单个页面中静默降级为临时控件。Admin 的 PC 页面和用户端 Desktop Renderer 可组合 Ant Design/ProComponents,但默认页面仍优先使用 Desktop Field Kit 保持值和展示一致;人员、部门、地址、位置、附件、图片等平台集成字段在桌面自定义页中也继续使用 Field Kit。
|
|
140
|
+
|
|
141
|
+
工作流页面在基础 Surface 上叠加 Kernel 返回的 field policy。节点的隐藏、只读和必填由当前 Surface 展示并由流程/App API 后端再次校验,不写回 Data Definition。
|
|
142
|
+
|
|
143
|
+
## 7. 实现与迁移边界
|
|
144
|
+
|
|
145
|
+
1. 从 V1 组件注册表、服务端存储映射、写入 handler、查询 switch、索引集合、导入导出、SDK tests 和冻结 FormRelease 提取**数据协议矩阵**;不要求 2.0 复刻所有 V1 低代码展示属性。
|
|
146
|
+
2. 将稳定数据协议定义为不依赖 React 的共享合同和黄金测试向量;V1 代码继续独立运行,2.0 不反向引用其发布工具。
|
|
147
|
+
3. 2.0 Data 编译器从最小 Data Definition 确定性生成存储计划、Data API 合同和 TypeScript 类型。
|
|
148
|
+
4. 2.0 Field Kit 为每个稳定数据类型提供 Desktop/Mobile/Readonly/List/Detail 默认 renderer;Mobile Field Kit 覆盖所有已支持的标准持久化字段,优先移植并重新验证 1.x 中成熟的移动选择、日期、地址、组织、附件等控制器和测试,而不是用桌面组件替代。
|
|
149
|
+
5. Surface Definition 和自定义页面只消费生成字段类型,不拥有或复制存储 codec。
|
|
150
|
+
6. Admin 只提供桌面 renderer;用户端分别提供 Desktop 与 Mobile composition。两端提交完全相同的稳定字段值。
|
|
151
|
+
|
|
152
|
+
## 8. 失败、并发和安全边界
|
|
153
|
+
|
|
154
|
+
- 未知数据类型、缺失 codec、存储类型漂移、查询操作符漂移或索引策略漂移在 generate/check 阶段失败,不能退化为任意 JSONB 后继续发布。
|
|
155
|
+
- Surface 缺失 renderer 时默认页面构建失败,但不改变资源的数据库定义;自定义页面不受无关 Surface 影响。
|
|
156
|
+
- 文件上传成功但业务写入未完成时继续使用平台既有的未绑定文件清理语义;重复上传、预览鉴权和 Blob 下载由平台组件处理。
|
|
157
|
+
- 组织选择调用平台人员/部门能力并产生稳定协议值;自定义页面也不应自行发明人员、部门 ID 或附件结构。
|
|
158
|
+
- 移动页面直接使用 Ant Design 桌面数据录入控件、原生字段控件或绕过 Mobile Field Kit 的标准持久化字段时,生成检查与模板静态审计失败。移动组件库只可用于页面结构、动作和平台尚未覆盖但已显式注册的 Field Kit 扩展。
|
|
159
|
+
- 类型或索引变更必须在 preproduction 对真实 PostgreSQL 预检;production 只晋级相同 AppVersion 和确定性存储计划。
|
|
160
|
+
|
|
161
|
+
## 9. 回滚边界
|
|
162
|
+
|
|
163
|
+
本决策不修改 V1 运行时代码和线上表。2.0 实现的回滚单位是 Data 编译器、Field Kit、Surface 包或 AppVersion。Surface 可以随前端版本回滚;Data Definition 和 Server Write Contract 按数据库/AppVersion 兼容边界回滚,不能通过切换 UI 绕过。
|
|
164
|
+
|
|
165
|
+
## 10. 可证伪验收
|
|
166
|
+
|
|
167
|
+
1. 自动计算 `V1 存储映射 ∪ 写入处理器 ∪ 查询分支 ∪ 索引集合 ∪ 冻结应用字段类型`;减去数据协议矩阵后必须为空。
|
|
168
|
+
2. 每个稳定数据类型至少有 Definition → DDL、写入 → 读取、空值、单/多值、查询操作符和索引计划黄金测试。
|
|
169
|
+
3. 在真实 PostgreSQL 中创建临时资源,验证物理列、往返值、筛选、排序和索引 DDL 与稳定协议一致。
|
|
170
|
+
4. 同一服务端 write constraint 通过默认页面和自定义 API 客户端写入都得到相同结果;只声明 Surface 必填时,测试明确证明它不冒充服务端约束。
|
|
171
|
+
5. Desktop、Mobile、Readonly、列表和详情 renderer 使用同一黄金值;提交结果与稳定数据协议逐字段深度相等。Mobile 在真实触摸视口覆盖单/多选、下拉、级联、日期/日期区间、地址、人员/部门、数值键盘、附件/图片和子表主路径。
|
|
172
|
+
6. 人员、部门、附件、图片、富文本、签名、位置和子表完成平台 API 集成测试,应用源码没有自建替代数据协议。
|
|
173
|
+
7. 2.0 构建静态审计禁止 ID-only 人员/部门值、未经批准的 `DataFileRef` 表单值和页面级持久化格式翻译。
|
|
174
|
+
8. V1 View、表单、流程、自动化与发布回归无变化。
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# OpenXiangda 2.0 Admin 设计基线
|
|
2
2
|
|
|
3
|
+
状态:2026-08-16 已退役,仅保留历史记录。新 Admin 将按 [Ant Design Pro v6 全量切换决策](../../architecture/ant-design-pro-v6-admin-foundation.md)重新设计和实现,本目录图片不再是验收基线。
|
|
4
|
+
|
|
3
5
|
## 设计判断
|
|
4
6
|
|
|
5
7
|
OpenXiangda 2.0 Admin 面向应用开发者、应用管理员和业务角色用户。界面采用冷静、干净、中低密度的企业级产品语言,组件与交互基于 Ant Design 6,并吸收 ProComponents 的数据管理页面模式。
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# OpenXiangda Admin Pro v6 设计基线
|
|
2
|
+
|
|
3
|
+
状态:2026-08-16 已评审,作为 Ant Design Pro v6 全量切换的实现输入。
|
|
4
|
+
|
|
5
|
+
这组设计只约束信息架构、密度、操作层级和视觉 token。最终实现必须使用锁定的 Ant Design Pro v6、ProComponents 与 Ant Design 6 公共 API,并以真实浏览器、响应式、可访问性和协议验收为准,不能把图片当成业务数据或逐像素截图模板。
|
|
6
|
+
|
|
7
|
+
## 设计参数
|
|
8
|
+
|
|
9
|
+
- 模式:2.0 全量重构,不保留旧 Shell 或旧页面兼容层。
|
|
10
|
+
- 视觉变化:3/10;动效:2/10;信息密度:5/10。
|
|
11
|
+
- 主题:统一浅色;冷灰背景、白色内容面、单一 Ant Design 蓝色强调。
|
|
12
|
+
- 形状:控件与内容面统一 8px 圆角,细边框优先,阴影克制。
|
|
13
|
+
- 操作:一个操作面只有一个主动作;错误、空、加载和重试是必需状态。
|
|
14
|
+
- 内容:普通用户只看到业务标签,内部 UUID、环境 key、角色/权限 code、流程节点 key 和原始 JSON 不进入默认页面。
|
|
15
|
+
|
|
16
|
+
## 已评审界面
|
|
17
|
+
|
|
18
|
+
| 界面 | 文件 | 评审结论 |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| 工作台 | [workbench.png](./workbench.png) | 保留 ProLayout、环境入口、标签缓存、待办、快捷入口和受限聚合;实现时把四色大图标收敛为单一主色/必要语义色。 |
|
|
21
|
+
| 标准数据管理 | [data-management.png](./data-management.png) | 使用 ProTable 搜索、服务端排序/分页、列配置、密度和行操作;空状态只在无结果时替换表格,不与有数据列表同时出现。 |
|
|
22
|
+
| 流程提交 | [workflow-submit-modal.png](./workflow-submit-modal.png) | 页面只保留“提交申请”主按钮;点击后 prepare 并在 Modal 展示真实审批路径,确认后用稳定幂等键启动流程。 |
|
|
23
|
+
|
|
24
|
+
示例业务统一使用企业采购申请,只作为验收载体;采购领域代码不得进入 `openxiangda-admin`。
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# OpenXiangda Admin v2 标准页面设计基线
|
|
2
2
|
|
|
3
|
-
状态:2026-08-
|
|
3
|
+
状态:2026-08-16 已退役,仅保留为历史评审记录。新的实现基线是 [Ant Design Pro v6 Admin 全量切换决策](../../architecture/ant-design-pro-v6-admin-foundation.md),实施前将按 Pro v6 重新形成设计稿并评审。
|
|
4
|
+
|
|
5
|
+
> 本目录关于“不引入 ProComponents 运行时”和“流程提交常驻双栏审批预览”的结论已经废止,图片不得再用于实现验收。保留图片只为解释过去的产品判断和迁移输入。
|
|
4
6
|
|
|
5
7
|
适用范围:OpenXiangda 2.0 新应用。本文和配套设计稿不承担 1.x 兼容,不改变 1.x 页面、流程或自动化运行时。
|
|
6
8
|
|
|
@@ -56,4 +58,3 @@ OpenXiangda 2.0 的 Admin 使用一套平台官方 React 管理端框架。应
|
|
|
56
58
|
本组图片使用内置图片生成能力分别生成,每张图只对应一个标准页面。提示词共同约束为:`production-realistic Ant Design 6 enterprise admin UI, Chinese B2B, 1440x900, medium-low density, solid deep navy navigation, one cobalt primary color, flat-first borders, no gradients/glassmorphism/marketing hero`,再分别补充工作台、数据列表、表单提交、表单详情、流程提交和流程任务的真实字段与操作。
|
|
57
59
|
|
|
58
60
|
工作台首稿在评审后又做了一次定向编辑:侧栏改为纯色,快捷入口去除绿/紫装饰色,指标只保留必要语义色。其余五张的结构与视觉约束一次通过;实现阶段仍以 Ant Design token、真实协议和响应式验收为最终证据。
|
|
59
|
-
|
package/docs/frontend.md
CHANGED
|
@@ -1,68 +1,78 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 前端架构
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
状态:2026-08-16 已实现待发布。旧自研 Shell 与 Vite 模板已经删除,企业采购参考应用已通过类型检查、测试、Umi production build 与桌面 Chromium 验收。完整决策见[Ant Design Pro v6 Admin 全量切换](/architecture/ant-design-pro-v6-admin-foundation),状态证据见[实施路线图](/architecture/implementation-roadmap)。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 默认技术栈
|
|
6
6
|
|
|
7
|
-
OpenXiangda 2.0
|
|
7
|
+
OpenXiangda 2.0 桌面管理端采用 React 19、Ant Design 6、Umi Max 4、ProComponents 3 与 utoopack。`openxiangda-admin` 是平台集成层,不重复实现一套后台组件库:
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- ProLayout:应用壳、菜单、页头与桌面导航;
|
|
10
|
+
- PageContainer:统一页面层级和主操作;
|
|
11
|
+
- ProTable:服务端搜索、排序、分页和列配置;
|
|
12
|
+
- ProForm:数据表单和流程业务表单;
|
|
13
|
+
- Descriptions / ProCard:详情、审计与流程摘要;
|
|
14
|
+
- ECharts:当前角色权限内的聚合指标与趋势。
|
|
10
15
|
|
|
11
|
-
|
|
12
|
-
- 数据管理页:`PageHeader -> SearchPanel -> TableToolbar -> Table -> Pagination`。默认服务端分页和排序,支持搜索折叠、列显隐、密度、跨页选择、批量业务动作以及独立新建/详情/编辑路由;页面不下载全量数据再过滤。
|
|
13
|
-
- 标准表单页:标题、业务说明和主操作固定在页头,字段按业务分组进入有限宽度内容区;标签始终位于控件上方,帮助文案和字段错误分别位于控件下方。离开、刷新、关闭标签和切换身份都接入统一脏状态协议。
|
|
14
|
-
- 流程提交页:桌面端使用业务表单与审批预览双栏,窄屏降为单栏。业务数据先由 Data API/App API 保存并获得 revision,随后才能预览和发起;字段、主部门或审批人答案变化会使旧预览失效。
|
|
15
|
-
- 数据详情页:以业务字段为主,操作和审计为辅;支持独立 URL、面包屑、标签和字段权限。不可读字段不占位,空值使用统一文本,不把 JSON 协议值直接暴露给用户。
|
|
16
|
-
- 流程详情页:依次展示流程标题与业务摘要、允许的当前操作、业务字段、审批参与者和不可变流转记录。按钮、字段策略和操作表单由后端 Surface 协议驱动;前端不复制流程可操作性规则。
|
|
17
|
-
- 流程工作中心:分类、表格和真实服务端分页处于同一内容表面;默认每页 20 条,显示总数并允许 10/20/50/100 切换。分类、页码或身份变化后旧响应不得覆盖当前页面。
|
|
16
|
+
应用不得建立第二套身份存储、权限判断、查询 DSL 或业务数据缓存。前端 capability 只负责界面裁剪,Data API、App API 与 Workflow API 始终在服务端授权。
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
## 路由、菜单与标签
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
应用页面路径、组件、标题、菜单、capability 与标签属性来自一份 `applicationRoutes`。Umi route 与 ProLayout metadata 从它派生;重复路径和 fallback 漂移在 check/build 阶段失败。未来由 `openxiangda generate` 生成时也只能替换这个单一事实源。
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
- Data API 与 App API 使用类型化客户端,不在组件中拼接平台 URL。
|
|
25
|
-
- 当前角色是显式会话状态。角色选项同时展示业务数据范围,解决同一用户拥有多个同名角色绑定时的歧义。切换角色后重新获取 capability、数据范围与待办,并恢复该角色自己的标签;不会把多个角色权限隐式合并。RoleSession 在到期前自动续期,浏览器从休眠恢复时再次校验;短暂网络故障会保留最后一个可用会话并提供就地重试,不会把整个应用切换成错误页。
|
|
26
|
-
- `tabPersistence` 只决定刷新后是否恢复标签,`keepAlive` 只决定切换后是否保留 React 实例。静态路由默认 `session + none`,动态详情默认 `none + none`;列表和工作台可显式使用 `keepAlive:"memory"`。标签最多 12 个,页面实例最多 6 个并按 LRU 淘汰,离开前台 30 分钟的实例自动卸载。会话数据按 `identityScope + manifest fingerprint` 隔离且最多 16 KiB,不保存权限、业务响应或表单值。业务路由使用独立错误边界,局部渲染错误不会导致整个应用白屏。
|
|
27
|
-
- `DirtyStateRegistry` 统一保护标准全页表单、列表内编辑弹窗、流程提交选择和节点可编辑业务字段。菜单/History 导航、标签关闭/批量关闭/刷新、LRU/超时、角色切换和退出使用同一确认协议;取消后原实例与字段值保持不变,保存或确认放弃后才卸载。浏览器刷新仅使用原生 `beforeunload`,草稿不会写入前端持久存储。自定义页面可用 `useAdminDirtyState` 注册草稿、用同步 `useAdminBeforeDispose` 释放订阅/worker/object URL;后者不能保存业务数据或阻止撤权、identity/manifest 安全失效。
|
|
28
|
-
- 标准数据管理模块把搜索字段转换成 Data API filter,并在服务端处理分页、排序、修订冲突和错误展示;搜索区折叠、列显隐、密度、跨页选择和批量业务动作是统一扩展点。分页大小、表格密度、可见列与搜索展开状态按应用/角色绑定/资源保存;异步查询会中止旧请求并按 generation 丢弃无法中止的旧响应,失败时提供就地重试。
|
|
29
|
-
- `useDataWorkbenchController` 是 `DataListPage` 复用的无头读取状态机。普通资源页直接使用标准列表;只有自定义表面或组合视图才从 `openxiangda-admin/data` 使用 controller,并传入稳定的身份 scope、资源、配置版本、行标识器和类型化 `load` 适配器。它沿用同一个 DataQuery,不在浏览器筛选全量数据,不保存业务响应;identity epoch 改变时同步清空旧 page、错误与选择。控制面客户端暂不接收 `AbortSignal` 时,generation 仍保证旧响应不能覆盖新身份或新查询。
|
|
30
|
-
- `PageHeader`、`PageSection`、标准搜索卡片和数据表面构成统一页面骨架;列表默认采用“标题与主操作 → 搜索 → 工具条与表格 → 分页”的稳定顺序。应用只声明资源、字段与业务动作,不再自行复制布局 CSS。`OpenXiangdaAdminProvider` 统一提供 Ant Design 主题与简体中文 locale,页面不得再各自覆盖分页、日期、空态或无障碍标签。
|
|
31
|
-
- `department`、`user` 和 `relation` 可直接用于列表搜索与编辑表单。`DepartmentText` / `UserText` 把持久化 ID 批量解析成可读名称,按应用、RoleSession 和类型隔离缓存,解析失败时安全回退到原始 ID。
|
|
32
|
-
- 标准数据编辑表单从 DataResource 生成类型化基础控件,应用只需声明业务标签、枚举选项、帮助信息和少量覆盖;JSON、日期时间和保存错误由框架统一处理。字段读写权限统一来自 DataResource 的 fieldPolicies:不可读字段不会出现在列表、搜索、导出和表单中,只读字段不能提交修改,应用管理员明确 bypass。
|
|
33
|
-
- 标准数据列表默认提供“查看”入口和行详情抽屉。详情抽屉复用 Data API 单记录接口,按字段策略展示业务字段,并以时间线显示当前记录的持久业务审计;操作者名称通过 Directory v2 解析,加载、空状态、失败和重试都有统一交互。
|
|
34
|
-
- 需要独立 URL、面包屑和标签的业务使用 `DataFormPage` / `DataRecordPage`;列表通过 `onCreate/onDetail/onEdit` 导航到生成合同中的静态或动态子路由。轻量操作仍可保留 Modal/Drawer。创建、修改或删除成功只增加当前资源的内存失效版本,缓存列表和详情据此重新查询;标签恢复不会保存记录响应、权限结果或表单草稿。
|
|
35
|
-
- `file` 字段使用平台托管附件组件:浏览器按签名计划直传对象存储,完成校验后只把稳定 `DataFileRef` 写入业务记录;查看和下载仍通过 Data API 执行行权限及字段权限。应用不能拼对象存储地址或保存临时签名 URL。
|
|
36
|
-
- 数据导出沿用当前服务端 filter/order 并按权限裁剪字段;CSV 防公式注入并限制最大导出量。导入先本地解析与类型预检,再以最多 100 个操作的受限事务批次提交,每批使用稳定幂等键,支持失败后安全重试。
|
|
37
|
-
- `DashboardPage`、`MetricCard`、`WorkflowCountMetric`、`DataCountMetric`、`DashboardQuickActions`、`DataAggregateChart`、`DataDistributionChart`、`DataTrendChart` 和 `DashboardSection` 提供 RoleSession 约束的标准概览页。图表使用服务端受限聚合,ECharts 运行时按需加载;指标查询丢弃过期响应并提供独立错误恢复,不要求每个应用重复搭建卡片、图表与加载状态。
|
|
38
|
-
- `ApplicationOperationsPage` 提供应用管理员运行视图:平台契约、当前身份、后端 readiness/version、不可变 AppVersion 最近部署、事件重试/死信和 `eventId/requestId/traceId` 关联信息集中展示;事件订阅与定时事件可按 revision 暂停/启用,重试或死信可显式创建新投递并保留原记录。各探针独立失败,不会因为一个依赖不可用而把整页变成白屏,诊断快照可一键复制。
|
|
39
|
-
- `ApplicationCredentialsPage` 提供标准的应用管理员安全控制面:外部 OAuth2 Client 生命周期与审计、平台托管后端运行时凭据的分阶段轮换、环境级只写应用 Secret 生命周期与审计、Workflow 审批人 Provider 密钥轮换。浏览器只保存当前表单状态;外部 Client Secret 仅在成功响应后一次性展示,关闭即清除;应用 Secret、运行时凭据和 Provider 密钥永不回显或写入快照、日志与持久化缓存。
|
|
40
|
-
- 生产应用从 `openxiangda-admin/core`、`/data`、`/dashboard`、`/operations`、`/credentials`、`/workflow` 子路径导入,并用 `React.lazy` 声明业务路由。个人中心领域区块通过 `definePersonalCenterSections` 显式装配;Workflow 代理只从 `/workflow/personal-center` 导入。官方模板的构建门禁要求首页、数据页、运维页、凭据页和流程页保持独立异步 chunk,同时限制单 chunk 与首屏 JavaScript 预算,并用 Core-only 构建证明无 Workflow 应用不会携带代理代码。
|
|
41
|
-
- 工作流页面按后端返回的 actions、fieldPolicy 和 presentation 渲染按钮与字段。`WorkflowSubmissionPage` 并列展示业务表单与审批预览,应用只实现 `saveBusiness`:用 Data API 或 NestJS App API 保存后返回 `businessKey + dataRef(revision) + facts`。提交页、任务页和实例页用可选 `workflowName` 展示业务名称,稳定 `workflowCode` 仍用于协议请求,不把内部 code 当作主要产品文案。流程详情使用可读的流程名称、当前环节和流程状态;`nodeId` 与实例/任务 version 继续服务于路由、并发和命令协议,不作为普通用户的主要信息。业务字段、主部门或审批人答案发生变化后,旧 preparation token 立即失效;业务保存与实例发起各自使用稳定幂等键,网络重试不会重复创建。标准流程详情页分离业务字段、流程摘要、当前操作、审批参与者和流转审计。业务记录由 Data API/App API 加载,`edit_required` 在操作前验证,变更以 revision 乐观锁先保存后执行流程命令;Workflow Kernel 不保存业务字段,业务状态的后续投影由 App API 或流程事件消费者负责。
|
|
42
|
-
- 流程工作中心使用统一 `PageHeader` 装配发起与刷新操作;应用只用 `workflowLabels` 提供业务流程名称和 `onOpen` 导航。Kernel 返回同一数据库快照中的 `total/limit/offset` 和确定性排序结果;Admin 只把页码转换为 offset。分类、页码或身份切换会使旧请求失效,错误在页面内重试,状态、时间、空态和“处理/查看”入口由 Admin 统一呈现,不做客户端搜索或第二套查询规则。
|
|
43
|
-
- 个人中心 Core 固定展示资料、环境、当前身份、数据范围、刷新和角色切换。领域区块复用路由的 `capability` / `access` 表达式并 fail closed;Workflow 模块可选贡献长期代理,选择代理人后必须再选择其具体应用角色绑定和数据范围。代理始终绑定发起人的当前稳定身份,不合并其他角色权限。
|
|
22
|
+
`AdminLayout` 提供最多 12 个会话标签。标签只保存路径、标题和打开顺序,并按平台 `identityScope` 隔离;不保存 Token、授权结论、表单草稿或业务响应。切换稳定角色会更新 identity epoch 并重新建立页面上下文。当前版本没有伪装成缓存的隐藏 keep-alive 实例池;需要真实保活时必须另行设计资源上限和失效协议。
|
|
44
23
|
|
|
45
|
-
##
|
|
24
|
+
## 身份与平台访问
|
|
46
25
|
|
|
47
|
-
|
|
26
|
+
- `OpenXiangdaAdminProvider` 从平台读取 Principal、RoleSession、角色绑定和 capability。
|
|
27
|
+
- 多角色用户每次只使用一个稳定角色,不隐式合并权限。
|
|
28
|
+
- 应用管理员由平台授予最高能力,前端不按角色名称硬编码绕过。
|
|
29
|
+
- `useOpenXiangdaAdmin().appApi()` 通过平台同源网关调用当前环境 NestJS 后端;浏览器不保存集群 Service 地址和 Token。
|
|
30
|
+
- Data API 客户端始终携带当前 RoleSession,并使用服务端分页、筛选、排序与 revision/CAS。
|
|
48
31
|
|
|
49
|
-
##
|
|
32
|
+
## 标准页面
|
|
50
33
|
|
|
51
|
-
|
|
34
|
+
### 工作台
|
|
52
35
|
|
|
53
|
-
|
|
36
|
+
`WorkbenchPage` 按“关键指标、趋势、快捷入口”组织中低密度首页。生产指标必须来自当前 RoleSession 下的服务端受限聚合;参考应用的本地种子统计仅用于开发验收。
|
|
54
37
|
|
|
55
|
-
|
|
38
|
+
### 数据管理
|
|
56
39
|
|
|
57
|
-
|
|
40
|
+
`ResourceTablePage` 使用 ProTable 提供页面标题、新建主操作、显式搜索、服务端列表、分页、排序、列设置和权限化操作。`ResourcePageDefinition` 只描述页面字段与交互;DataResource 继续只描述数据库字段、类型、索引、文件约束与 Data API 能力。
|
|
41
|
+
|
|
42
|
+
`ResourceFormPage` 提供独立新建/编辑页面,使用 revision/CAS 保存。`ResourceDetailPage` 展示平台字段渲染、附件和审计时间线。列表也可默认使用轻量 Modal/Drawer;业务拥有独立流程入口时可以关闭通用 create/update/delete,避免绕过业务后端。
|
|
43
|
+
|
|
44
|
+
### 流程提交
|
|
45
|
+
|
|
46
|
+
`WorkflowSubmissionPage` 默认只展示业务表单和“提交”。点击后先经 Data API/App API 保存业务记录,再调用 Kernel prepare,并在 Modal 中显示真实审批路径和必要的主部门/审批人选择。用户确认后才消费 preparation token 发起流程;审批预览不常驻页面,Workflow Kernel 不保存业务字段。
|
|
47
|
+
|
|
48
|
+
### 工作中心、任务与实例
|
|
49
|
+
|
|
50
|
+
`WorkflowWorkCenterPage` 显示当前稳定角色的待办、已处理与我发起。`WorkflowTaskPage` / `WorkflowInstancePage` 解释后端 Surface 的流程信息、业务数据、审计时间线与允许操作;同意、拒绝、退回、转交、代理和加签仍由 Kernel 做并发与权限判定。
|
|
51
|
+
|
|
52
|
+
应用领域动作使用 `loadAppActions` 加载 `app_action`,使用 `executeAppAction` 调用 NestJS App API。自定义动作不能覆盖 Kernel 同名操作;加载失败只关闭业务动作,不阻断标准审批。
|
|
53
|
+
|
|
54
|
+
## Field Kit 与移动用户端
|
|
55
|
+
|
|
56
|
+
所有平台字段使用 `openxiangda-field-kit` 的稳定值协议。人员、部门、单选、多选、单选框、复选框、日期、日期区间、地址、关联、图片、附件、数值等都由统一定义驱动存储与显示。
|
|
57
|
+
|
|
58
|
+
- 桌面 Admin 从 `openxiangda-field-kit/desktop` 使用 Ant Design 控件。
|
|
59
|
+
- 移动用户端从 `openxiangda-field-kit/mobile` 使用 Ant Design Mobile 的独立交互,不把桌面 Select、DatePicker 或 Cascader 缩小后复用。
|
|
60
|
+
- 人员、部门、行政区、关联数据、上传、下载和预览都通过平台 API;应用不自行复制平台目录或文件协议。
|
|
61
|
+
- UI 必填、默认值、显隐、布局和帮助文本属于页面层;后端业务不应假设自定义页面一定执行了前端校验。
|
|
62
|
+
|
|
63
|
+
完整移动用户端页面模板和移动 Chromium 设备验收仍是下一阶段交付;不能用桌面 Admin 的响应式效果冒充完成。
|
|
64
|
+
|
|
65
|
+
## 本地开发与门禁
|
|
58
66
|
|
|
59
67
|
```bash
|
|
60
|
-
|
|
61
|
-
|
|
68
|
+
openxiangda dev
|
|
69
|
+
openxiangda generate
|
|
70
|
+
openxiangda check
|
|
71
|
+
openxiangda test
|
|
72
|
+
pnpm --filter @app/web test:e2e
|
|
73
|
+
pnpm --filter @app/web build
|
|
62
74
|
```
|
|
63
75
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
切换到“应用管理员”后可进入“运行与诊断 → 本地故障实验室”,为匹配的下一次请求注入身份 401、授权 403、修订冲突 409、后端 503 或 3 秒数据延迟;规则默认命中一次并可随时清空,用于验证标准错误、重试和恢复交互。
|
|
76
|
+
CLI 同时监督 Umi、NestJS、本地平台与工作区 PostgreSQL。UI-only 只用于非持久化界面预览。当前桌面 Chromium 链路覆盖工作台、菜单、标签、角色切换、数据列表/详情、供应商标准表单、流程工作中心、单按钮流程提交与个人中心,并断言没有浏览器运行时错误。
|
|
67
77
|
|
|
68
|
-
|
|
78
|
+
生产构建分别约束首屏脚本、异步 chunk 的 gzip/原始体积与开发标记;不得包含模板假用户、Umi Mock、开发 Secret、Vite 或旧 AdminShell。
|
package/docs/getting-started.md
CHANGED
|
@@ -49,11 +49,11 @@ pnpm test:e2e
|
|
|
49
49
|
|
|
50
50
|
需要使用钉钉家校监护关系的应用,应先阅读[家校通讯录关系](./school-contact-relations.md)。2.0 尚未正式投产,当前生产应用继续使用 1.0 SDK;2.0 应用必须通过 NestJS App API 和当前 RoleSession 读取,不能复制 1.0 页面 SDK 代码。
|
|
51
51
|
|
|
52
|
-
`openxiangda dev` 是唯一受监督的日常入口:它启动完整 Admin、相互隔离的 React/
|
|
52
|
+
`openxiangda dev` 是唯一受监督的日常入口:它启动完整 Ant Design Pro Admin、相互隔离的 React/Umi Max 与 NestJS 进程、独立 loopback 本地平台,以及工作区隔离的 PostgreSQL。开发者**不需要安装 PostgreSQL**,只需要 Docker Desktop 或兼容容器运行时;CLI 自动下载摘要固定的镜像、创建数据库、选择端口并限制容器资源。2.0 模板已经删除 Vite/旧自研 Shell,不保留兼容档位。关闭前台命令或执行 `openxiangda dev stop` 时只停止进程和容器并保留项目专属 volume,因此数据在重启后仍存在;受管进程组带工作区身份记录,监督进程意外中断后也可由下一次启动或 stop 安全回收。`openxiangda dev status` 查看当前/上次会话;只有显式执行 `openxiangda dev reset --data` 才会在校验工作区、容器、数据卷和凭据归属后删除本地数据库与凭据。`openxiangda dev --reset` 是“安全重置后立即启动”的快捷形式。工作区内部 `pnpm dev` 只供 CLI 编排,不负责平台进程、数据库、会话锁和清理,不作为公开开发命令。local 不是远程环境,不要求 provision 或远程 OAuth/Secret。`generate` 根据配置生成 Data、AuthZ、Event 与 Workflow 类型。`check` 必须是确定性的:同一提交、同一依赖锁、同一配置产生同一结果。完整本地模型见 [本地开发内核](./architecture/local-development-v2.md)。
|
|
53
53
|
|
|
54
54
|
默认 `pnpm test:e2e` 会自行启动隔离的 UI-only 快速回归。需要把同一套 Chromium 场景作为完整本地集成证据时,先保持 `openxiangda dev --no-open` 运行,再执行 `OPENXIANGDA_E2E_BASE_URL=http://127.0.0.1:<web-port> pnpm test:e2e`。此时 Playwright 不创建第二个服务器,而是验证浏览器、独立本地平台、NestJS 与项目专属 PostgreSQL 的同一受监督会话;`<web-port>` 以 `openxiangda dev status` 为准。外部会话模式不会隐式重置开发数据,针对确定性种子数据的整套回归只能指向一次性验收应用,或由开发者先明确停止并执行 `openxiangda dev --reset`;不得在测试配置中绕过 CLI 所有权校验直接清理容器或 volume。
|
|
55
55
|
|
|
56
|
-
完整模式下,浏览器对 App API 的请求先进入本地平台网关:网关验证当前稳定 RoleSession,丢弃浏览器自带的 Authorization,再用仅限 loopback 的短期平台身份转发给 NestJS。CLI 另外创建一个 workspace runtime OAuth client,只把原始 Secret 注入 `dev:server`,供 Worker/Scheduler/后台业务调用 Data API
|
|
56
|
+
完整模式下,浏览器对 App API 的请求先进入本地平台网关:网关验证当前稳定 RoleSession,丢弃浏览器自带的 Authorization,再用仅限 loopback 的短期平台身份转发给 NestJS。CLI 另外创建一个 workspace runtime OAuth client,只把原始 Secret 注入 `dev:server`,供 Worker/Scheduler/后台业务调用 Data API;前端开发进程拿不到该 Secret。数据库连接、OAuth 凭据和其他本地状态位于 Git 忽略的 `.openxiangda/local/state/`,权限为仅当前用户可读写,并且不会进入 AppPackage。
|
|
57
57
|
|
|
58
58
|
开发 2.0 工具链本身时,每一轮可用一个命令完成发布前同等级的本地验收:
|
|
59
59
|
|
package/docs/index.md
CHANGED
|
@@ -22,4 +22,4 @@ features:
|
|
|
22
22
|
|
|
23
23
|
OpenXiangda 2.0 保留平台统一数据与治理能力,同时把应用开发恢复成成熟的前后端工程。本工具链只面向 2.0 应用;旧应用由独立的 1.x 产品线维护。
|
|
24
24
|
|
|
25
|
-
当前能力的完成证据、真实缺口和实施顺序见[实施路线图与证据矩阵](/architecture/implementation-roadmap)
|
|
25
|
+
当前能力的完成证据、真实缺口和实施顺序见[实施路线图与证据矩阵](/architecture/implementation-roadmap)。Admin 已确认[全量切换到 Ant Design Pro v6](/architecture/ant-design-pro-v6-admin-foundation),不再维护自研 Shell/Vite 双轨。实现前先阅读[环境配置内核](/architecture/environment-configuration-kernel-v2)、[Alpha 退役与 Native 切换前置审计](/architecture/native-kernel-inventory-v2)、[原生配置投影蓝图](/architecture/native-configuration-projection-v2)与[授权一致性内核](/architecture/authorization-consistency-v2),Admin 页面协议建立在这些可验证的运行时事实之上。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda-skill-kit",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.28",
|
|
4
4
|
"description": "Validation and deterministic packaging for OpenXiangda 2.0 AI skills.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"README.md"
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"openxiangda-devkit-core": "2.0.0-alpha.
|
|
24
|
+
"openxiangda-devkit-core": "2.0.0-alpha.23"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"tsx": "4.23.12",
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"scripts": {
|
|
35
35
|
"build": "tsc -p tsconfig.json",
|
|
36
|
+
"build:release": "node ../../scripts/prune-package-dist.mjs && pnpm build",
|
|
36
37
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
37
38
|
"test": "tsx --test test/*.test.ts"
|
|
38
39
|
}
|
|
@@ -5,7 +5,7 @@ description: Design OpenXiangda 2.0 application boundaries and typed contracts.
|
|
|
5
5
|
|
|
6
6
|
# OpenXiangda 2.0 Architecture
|
|
7
7
|
|
|
8
|
-
Design one independently versioned application with
|
|
8
|
+
Design one independently versioned application with the OpenXiangda Ant Design Pro v6 frontend baseline and NestJS backend. Do not introduce a Vite/custom-shell compatibility path for 2.0 applications.
|
|
9
9
|
|
|
10
10
|
## Design Sequence
|
|
11
11
|
|
|
@@ -15,6 +15,7 @@ Design one independently versioned application with a standard React frontend an
|
|
|
15
15
|
4. Keep synchronous user interactions in App APIs; move retryable side effects to event consumers.
|
|
16
16
|
5. Use a workflow provider when assignee resolution or a workflow action depends on application data.
|
|
17
17
|
6. Generate types with `openxiangda generate`, then run `openxiangda check`.
|
|
18
|
+
7. For Admin changes, keep Ant Design Pro/Umi responsible for generic UI structure and OpenXiangda responsible for identity, authorization, Data, Workflow, lifecycle and delivery contracts.
|
|
18
19
|
|
|
19
20
|
## Required Decisions
|
|
20
21
|
|
|
@@ -26,4 +27,4 @@ Design one independently versioned application with a standard React frontend an
|
|
|
26
27
|
|
|
27
28
|
Do not design environment-specific code paths. Environment values and secrets are injected by the platform at deployment time.
|
|
28
29
|
|
|
29
|
-
Read [Concepts](../../docs/concepts.md) before introducing a new platform-facing contract.
|
|
30
|
+
Read [Concepts](../../docs/concepts.md) before introducing a new platform-facing contract. Read the [Ant Design Pro v6 cutover decision](../../docs/architecture/ant-design-pro-v6-admin-foundation.md) before changing the frontend foundation.
|
|
@@ -1,76 +1,46 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: openxiangda-v2-frontend
|
|
3
|
-
description: Build OpenXiangda 2.0
|
|
3
|
+
description: Build OpenXiangda 2.0 Ant Design Pro desktop Admin and separate mobile user experiences. Use for routes, menus, data pages, platform fields, role switching, workflow pages, or application actions.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# OpenXiangda 2.0 Frontend
|
|
7
7
|
|
|
8
|
-
Build
|
|
8
|
+
Build in `apps/web` with React 19, Ant Design 6, Umi Max 4 and ProComponents 3. `openxiangda-admin` is the platform integration layer. Do not preserve or recreate the former Vite/custom-shell implementation or any 1.x compatibility path.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Desktop Admin
|
|
11
11
|
|
|
12
|
-
1.
|
|
13
|
-
2.
|
|
14
|
-
3. Use
|
|
15
|
-
4.
|
|
16
|
-
5.
|
|
17
|
-
6.
|
|
18
|
-
7.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
keep-alive. Dynamic detail, workflow task and edit routes stay non-persistent
|
|
23
|
-
and non-cached. Build management lists
|
|
24
|
-
with the standard search, pagination, sorting, density, column settings,
|
|
25
|
-
revision-aware editing and batch action surfaces before adding custom UI.
|
|
26
|
-
8. Use `department`, `user`, and `relation` search/form controls for persisted
|
|
27
|
-
identifiers. Render directory identifiers with `DepartmentText` or
|
|
28
|
-
`UserText`; do not expose internal IDs as the primary business label.
|
|
29
|
-
9. Keep DataResource field policies effective across list columns, search,
|
|
30
|
-
forms, import and export. Authorization loading or errors must fail closed.
|
|
31
|
-
10. Use the standard dashboard and CSV transfer modules before creating
|
|
32
|
-
application-specific copies. Imports must use restricted transactions and
|
|
33
|
-
stable idempotency keys.
|
|
34
|
-
11. Keep the standard record detail drawer and business-audit timeline unless
|
|
35
|
-
the domain needs a genuinely different presentation. Use `DataFileField`
|
|
36
|
-
for managed attachments and the aggregate chart components for summaries;
|
|
37
|
-
never expose storage URLs or aggregate complete result sets in-browser.
|
|
38
|
-
12. Import from the narrow `openxiangda-admin/core`, `/data`, `/dashboard`,
|
|
39
|
-
and `/workflow` entrypoints. Register optional personal-center domains with
|
|
40
|
-
`definePersonalCenterSections`; import Workflow delegation only from
|
|
41
|
-
`/workflow/personal-center`. Core must not import a domain module, and a
|
|
42
|
-
no-Workflow production build must not contain its delegation chunk. Keep
|
|
43
|
-
business route modules lazy and preserve the template's chunk-cycle and
|
|
44
|
-
size budgets.
|
|
45
|
-
13. Use `DataFormPage` / `DataRecordPage` for full-page CRUD and
|
|
46
|
-
`WorkflowSubmissionPage` for business-backed approval submission. Its
|
|
47
|
-
`saveBusiness` adapter must persist through Data API or NestJS App API and
|
|
48
|
-
return `businessKey`, revision-bound `dataRef`, and workflow `facts`.
|
|
49
|
-
Never hard-code a demo record reference or keep a preview valid after
|
|
50
|
-
business fields, department, or approver answers change.
|
|
51
|
-
14. Standard data and workflow forms already participate in the scoped
|
|
52
|
-
`DirtyStateRegistry`. Custom editors must call `useAdminDirtyState` instead
|
|
53
|
-
of adding their own `beforeunload` or router prompt. Use synchronous
|
|
54
|
-
`useAdminBeforeDispose` only to release subscriptions, workers, or object
|
|
55
|
-
URLs; it must not persist business data or veto identity/permission
|
|
56
|
-
invalidation.
|
|
57
|
-
15. Prefer `DataListPage` for ordinary resource management. Use
|
|
58
|
-
`useDataWorkbenchController` from `openxiangda-admin/data` only when a
|
|
59
|
-
business workbench genuinely needs a custom surface or composed view. Bind
|
|
60
|
-
it to stable `identityScope`, `identityEpoch`, `resourceCode`, and
|
|
61
|
-
`configVersion`; adapt reads through the existing typed Data API or App API
|
|
62
|
-
client, honor its `AbortSignal` when the client supports cancellation, and
|
|
63
|
-
keep the standard `DataQuery` contract. Do not fetch complete datasets for
|
|
64
|
-
browser filtering, add a second query DSL, or persist page results,
|
|
65
|
-
selection, errors, tokens, or authorization decisions. Do not synchronize
|
|
66
|
-
filters to the URL until each search field explicitly declares itself
|
|
67
|
-
shareable and the application enforces bounded values.
|
|
68
|
-
16. Use `WorkflowWorkCenterPage` for pending, completed, and created workflow
|
|
69
|
-
records. Treat `total`, `limit`, and `offset` as Kernel facts, keep the
|
|
70
|
-
standard 20-row server page, reset offset on category or identity changes,
|
|
71
|
-
and never derive a total, search result, or sort order from the current
|
|
72
|
-
browser page.
|
|
12
|
+
1. Keep one route fact source. In the official template, edit `apps/web/config/routes.ts`; Umi routes, menu items and tab descriptors must derive from it. Do not hand-maintain a second path/menu tree.
|
|
13
|
+
2. Use `OpenXiangdaAdminProvider` and `AdminLayout` from `openxiangda-admin/core`. Use the platform Principal and one active RoleSession; switching role replaces the current permission/data context instead of merging roles.
|
|
14
|
+
3. Use capability codes only for UI visibility. The Data API, App API and Workflow API remain authoritative and must reject unauthorized requests independently.
|
|
15
|
+
4. Prefer `ResourceTablePage`, `ResourceFormPage` and `ResourceDetailPage` from `openxiangda-admin/data` for normal management pages. They provide ProTable server pagination/filter/order, ProForm, revision/CAS, field policies, platform rendering and audit history.
|
|
16
|
+
5. Set `allowCreate`, `allowUpdate` or `allowDelete` to false when a business operation is owned by a workflow or NestJS endpoint. Route the page action to the real owner; never offer a generic Data API write that bypasses derived fields or state transitions.
|
|
17
|
+
6. Use `WorkbenchPage` from `openxiangda-admin/dashboard`. Production metrics and ECharts series must come from bounded server-side aggregation under the current RoleSession.
|
|
18
|
+
7. Use `WorkflowSubmissionPage` for approval submission. The normal page shows a business form and one primary submit action. Save through Data API/App API first; only then call prepare and open a Modal with the real path and unresolved department/approver choices. Never keep approval preview visible before submit.
|
|
19
|
+
8. Use `WorkflowWorkCenterPage`, `WorkflowTaskPage` and `WorkflowInstancePage` for Kernel surfaces. Render Kernel operations exactly as returned. Application business actions use `loadAppActions` and `executeAppAction`; they must be `app_action`, cannot override Kernel keys, and must execute through an authorized NestJS App API.
|
|
20
|
+
9. Import narrow browser-safe entrypoints: `openxiangda-admin/core`, `/navigation`, `/data`, `/dashboard`, `/workflow`, `openxiangda-devkit-core/client`, and `openxiangda-contracts/browser`.
|
|
21
|
+
10. Admin is desktop-only. Do not spend scope on squeezing ProLayout/ProTable into a phone layout.
|
|
73
22
|
|
|
74
|
-
|
|
23
|
+
## Platform fields and mobile user UI
|
|
75
24
|
|
|
76
|
-
|
|
25
|
+
1. Use `openxiangda-field-kit/desktop` in the desktop Admin and `openxiangda-field-kit/mobile` in mobile user pages. Mobile is a separate UI tree, not a CSS-responsive copy of the Admin.
|
|
26
|
+
2. Platform fields include all supported kinds, not only personnel and files: text/textarea, number/money/percent, boolean, single/multiple select, radio/checkbox/cascade, date/datetime/date range, user/users, department/departments, relation, address/location, image/attachments, signature, subtable/JSON, serial and workflow status.
|
|
27
|
+
3. Persist established stable values. Directory/option/relation values use `{ label, value }`; address, location and attachment values use the `openxiangda-field-kit` types. Never replace them with display-only strings or Ant Design component instances.
|
|
28
|
+
4. Personnel, departments, administrative divisions, relations, uploads, downloads and previews must use platform APIs. Do not copy platform directory data or write a second upload protocol.
|
|
29
|
+
5. Keep database declarations minimal: field code, storage type, nullability, index and storage constraints. Required/default/hidden/layout/help/conditional display are page behavior. A custom page may implement different UI validation, so critical business rules must also be enforced by NestJS/Data API policy.
|
|
30
|
+
6. Render list/detail values by field kind. Show readable labels, tags, formatted dates/numbers/amounts, address text, user/department identity, image preview and attachment download instead of raw JSON or internal IDs.
|
|
31
|
+
|
|
32
|
+
## Verification
|
|
33
|
+
|
|
34
|
+
After contracts or pages change, run:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
openxiangda generate
|
|
38
|
+
openxiangda check
|
|
39
|
+
openxiangda test
|
|
40
|
+
pnpm --filter @app/web test:e2e
|
|
41
|
+
pnpm --filter @app/web build
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Use accessible role/label locators rather than private Ant Design DOM classes. The current desktop Chromium gate covers shell, menu, tabs, stable role switch, data list/detail, full-page form, workflow work center/submission and personal center. When adding a mobile user template, add a separate mobile-device Chromium gate; do not claim mobile completion from the desktop suite.
|
|
45
|
+
|
|
46
|
+
Production source/dependency audits must reject Vite, the former AdminShell, template fake users, Umi Mock APIs and development Secrets. Read [Frontend](../../docs/frontend.md) and [Ant Design Pro v6 cutover](../../docs/architecture/ant-design-pro-v6-admin-foundation.md) before changing the foundation.
|