openxiangda-skill-kit 2.0.0-alpha.37 → 2.0.0-alpha.39
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/best-practice-template-rebuild-v2.md +1 -1
- package/docs/architecture/field-component-migration-matrix-v1-to-v2.md +8 -11
- package/docs/architecture/proven-field-components-and-standard-surfaces-v2.md +14 -6
- package/docs/architecture/school-contact-default-access-v2.md +13 -0
- package/docs/architecture/standard-surface-runtime-corrections-v2.md +108 -0
- package/docs/data-authz.md +3 -1
- package/docs/field-components.md +93 -0
- package/docs/frontend.md +2 -2
- package/docs/index.md +2 -0
- package/docs/llms.txt +1 -0
- package/docs/school-contact-relations.md +26 -7
- package/package.json +2 -2
- package/skills/openxiangda-v2/SKILL.md +4 -2
- package/skills/openxiangda-v2-data-authz/SKILL.md +11 -3
- package/skills/openxiangda-v2-frontend/SKILL.md +9 -7
|
@@ -184,7 +184,7 @@ Admin 工作台还原本轮决策:
|
|
|
184
184
|
| Shell | 任一路径恰好一个菜单选中;标签边界对齐;无全局搜索和内容区重复标题;直接 URL、关闭、恢复、身份/环境切换正确 |
|
|
185
185
|
| 视觉 | PC 冻结稿尺寸 1536x1024(并补充 1280x800 结构检查);移动 390x844、375x812 截图回归 |
|
|
186
186
|
| 数据 | 默认一行与更多筛选、服务端搜索/排序/分页、四类列表设置、空/错/加载、revision 冲突 |
|
|
187
|
-
| 字段 | 官方验收表单覆盖 `text/textarea/number/money/percent/boolean/date/datetime/dateRange/option/options/radio/checkbox/cascade/user/users/department/departments/attachments/images/address/location/richtext/signature/subtable/json/serial/
|
|
187
|
+
| 字段 | 官方验收表单覆盖 `text/textarea/number/money/percent/boolean/date/datetime/dateRange/option/options/radio/checkbox/cascade/user/users/department/departments/attachments/images/address/location/richtext/signature/subtable/json/serial/workflowStatus`;关联表单组件弃用 |
|
|
188
188
|
| 目录 | 打开即能看到真实根组织;树展开、搜索、路径、单选/多选和失败重试 |
|
|
189
189
|
| 身份 | 页面显示真实姓名/部门;正则扫描页面不存在裸 UUID |
|
|
190
190
|
| 流程 | 提交前没有预览;保存和 prepare 后弹窗;预览仅含具体审批人路径;Surface DataRef 可读业务数据;同意、拒绝、转交、回退、加签和代理按 Surface 展示 |
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
# OpenXiangda 1.x → 2.0 全量字段组件迁移矩阵
|
|
2
2
|
|
|
3
|
-
状态:2026-08-18
|
|
3
|
+
状态:2026-08-18 已完成并通过组件、模板与三端回归验证
|
|
4
4
|
|
|
5
5
|
关联决策:[`proven-field-components-and-standard-surfaces-v2.md`](./proven-field-components-and-standard-surfaces-v2.md)
|
|
6
6
|
|
|
7
|
-
1.x 基线:`tools/openxiangda/packages/sdk/src/components/core/defaultRegistry.ts`
|
|
8
|
-
|
|
9
7
|
## 1. 迁移原则
|
|
10
8
|
|
|
11
9
|
- “复用 1.0”指复用已经验证的功能、信息顺序、交互状态、错误反馈和移动端适配,不在 2.0
|
|
@@ -21,15 +19,15 @@
|
|
|
21
19
|
|
|
22
20
|
| 1.x Registry 名称 | 2.0 `FieldKind` | 2.0 稳定值 | Desktop / Mobile 行为基线 | 当前实施状态 |
|
|
23
21
|
| --- | --- | --- | --- | --- |
|
|
24
|
-
| `TextField` | `text` | `string \| null` | 单行输入、placeholder
|
|
25
|
-
| `NumberField` | `number` / `money` / `percent` | `number \| null` |
|
|
26
|
-
| `TextAreaField` / `TextareaField` | `textarea` | `string \| null` |
|
|
22
|
+
| `TextField` | `text` | `string \| null` | 单行输入、placeholder、长度/计数、清空、前后缀、只读文本 | 已完成 |
|
|
23
|
+
| `NumberField` | `number` / `money` / `percent` | `number \| null` | 数值边界、步长、精度、单位位置、千分位;移动数字输入 | 已完成 |
|
|
24
|
+
| `TextAreaField` / `TextareaField` | `textarea` | `string \| null` | 多行自适应、最少/最多行、长度/计数、只读换行 | 已完成 |
|
|
27
25
|
| `SelectField` | `option` | `{label,value} \| null` | 搜索、清空、禁用项、稳定标签回显 | 已完成,纳入回归 |
|
|
28
|
-
| `MultiSelectField` | `options` | `{label,value}[]` |
|
|
26
|
+
| `MultiSelectField` | `options` | `{label,value}[]` | 多选、最大数量、响应式标签、移动 Popup/CheckList | 已完成 |
|
|
29
27
|
| `RadioField` | `radio` | `{label,value} \| null` | 单选组、禁用项、只读标签 | 已完成,纳入回归 |
|
|
30
28
|
| `CheckboxField` | `checkbox` | `{label,value}[]` | 多选组、禁用项、只读标签集合 | 已完成,纳入回归 |
|
|
31
29
|
| `DateField` | `date` / `datetime` | ISO/格式化日期字符串或 `null` | 日期与日期时间选择、清空、只读格式化 | 已完成,纳入回归 |
|
|
32
|
-
| `CascadeDateField` | `dateRange` | `[start,end]` |
|
|
30
|
+
| `CascadeDateField` | `dateRange` | `[start,end]` | 成对日期、可选日期限制、范围校验、移动分步选择 | 已完成 |
|
|
33
31
|
| `AttachmentField` | `attachments` | `StableAttachmentValue[]` | 上传进度、取消/重试、预览、下载、删除、同名文件不合并 | 已完成 |
|
|
34
32
|
| `ImageField` | `images` | `StableAttachmentValue[]`,`variant=image` | 图片选择、缩略图、预览、上传状态、删除 | 已完成 |
|
|
35
33
|
| `SubFormField` | `subtable` | `Record<string,unknown>[]` | 行增删、子字段编辑、最少/最多行、只读明细 | 已完成 |
|
|
@@ -37,7 +35,7 @@
|
|
|
37
35
|
| `DepartmentSelectField` | `department` / `departments` | `{label,value}` 或数组 | 部门树、路径、搜索、单/多选 | 已完成,纳入回归 |
|
|
38
36
|
| `CascadeSelectField` | `cascade` | `{label,value}[]` 路径 | 级联路径、叶子选择、清空、只读路径 | 已完成,纳入回归 |
|
|
39
37
|
| `AddressField` | `address` | `StableAddressValue` | 省市区级联、详细地址、完整地址回显 | 已完成,纳入回归 |
|
|
40
|
-
| `AssociationFormField` |
|
|
38
|
+
| `AssociationFormField` | 不迁移 | - | 平台组件弃用;复杂关联查询由应用页面和 App API 实现 | 已确认弃用 |
|
|
41
39
|
| `EditorField` | `richtext` | 清洗后的 HTML `string` | 常用格式、链接安全、移动简化工具栏、只读二次清洗 | 已完成 |
|
|
42
40
|
| `SerialNumberField` | `serial` | 平台生成的 `string \| null` | 创建前占位、创建后只读,不允许客户端伪造 | 已完成,纳入回归 |
|
|
43
41
|
| `LocationField` | `location` | `StableLocationValue` | 钉钉优先、浏览器降级、地址/坐标/精度、重定位/清空 | 已完成 |
|
|
@@ -69,8 +67,7 @@
|
|
|
69
67
|
|
|
70
68
|
## 5. 验收清单
|
|
71
69
|
|
|
72
|
-
-
|
|
73
|
-
不重复实现。
|
|
70
|
+
- 除已明确弃用的关联表单外,1.0 标准字段都有明确的 2.0 映射;别名不重复实现。
|
|
74
71
|
- 每种 `FieldKind` 至少有值归一化测试;关键字段有 Desktop、Mobile、只读和失败态测试。
|
|
75
72
|
- `attachments` 与 `images` 只能绑定到真实声明为 `file` 的 DataResource 字段。
|
|
76
73
|
- 同名不同 `fileId` 的文件保留两份;相同 `fileId` 或同一稳定 URL 只显示一份。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 经过验证的平台字段组件与三端标准页面决策
|
|
2
2
|
|
|
3
|
-
状态:2026-08-18
|
|
3
|
+
状态:2026-08-18 已实现并通过组件、模板、三端与完整本地运行时验证
|
|
4
4
|
|
|
5
5
|
适用范围:OpenXiangda 2.0 `openxiangda-contracts`、`openxiangda-field-kit`、
|
|
6
6
|
`openxiangda-user`、官方应用模板及其本地验收夹具。OpenXiangda 1.x 运行时、
|
|
@@ -62,9 +62,13 @@
|
|
|
62
62
|
9. Admin、业务用户 PC 与 Mobile 使用相同 route/data/workflow 合同;三端可以有独立页面组合,
|
|
63
63
|
不能维护第二份数据、权限或流程状态。
|
|
64
64
|
|
|
65
|
-
公开受影响面包括:
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
公开受影响面包括:Field Kit 的 Desktop/Mobile/Readonly 导出与样式、User 包的标准页面、
|
|
66
|
+
模板 DataResource/Surface/fixture、组件使用指南和参考应用路由与测试。Native Data API 的文件
|
|
67
|
+
安全语义和现有 URL 不变化。
|
|
68
|
+
|
|
69
|
+
本轮采用简单目录和单一 Registry。1.x 只提供已验证的功能、样式、交互与移动端基线,不建立
|
|
70
|
+
逐文件追溯、兼容运行时或第二套协议。组件通过一个 `fileService` 调用既有 2.0 文件接口,页面和
|
|
71
|
+
字段组件不感知 initiate/PUT/complete/delete-unbound 的步骤。
|
|
68
72
|
|
|
69
73
|
## 4. 失败、并发与清理行为
|
|
70
74
|
|
|
@@ -75,8 +79,9 @@ API 的文件安全语义和现有 URL 不变化。
|
|
|
75
79
|
- 预览 Object URL 在关闭、替换和卸载时释放;预览失败保留下载动作和可重试错误。
|
|
76
80
|
- 定位优先使用钉钉能力,失败后降级浏览器 Geolocation;超时、拒绝和不支持分别显示可恢复错误。
|
|
77
81
|
- 签名保存只接受非空轨迹,生成图片和哈希任一步失败都不覆盖原值;重复保存以最后一次成功值为准。
|
|
78
|
-
- 富文本迁移 1.x
|
|
79
|
-
|
|
82
|
+
- 富文本迁移 1.x 的完整格式、表格、链接、图片、粘贴/拖拽与安全只读能力。需要上传图片时,
|
|
83
|
+
Surface 显式提供一个声明为 `file` 的伴随字段,编辑器仍通过同一个 `fileService` 上传;未配置时
|
|
84
|
+
保留图片 URL,不建立旁路上传协议。编辑器销毁后不得提交迟到回调。
|
|
80
85
|
- Workflow prepare/start 使用既有 revision、token 和幂等键;审批人解析为空时保留节点编码并引导修正配置。
|
|
81
86
|
|
|
82
87
|
## 5. 安全与资源上限
|
|
@@ -110,6 +115,9 @@ API 的文件安全语义和现有 URL 不变化。
|
|
|
110
115
|
新增验收资源可随模板 AppVersion 回滚;既有 `purchase_requests` 数据和文件绑定不修改。
|
|
111
116
|
1.x 仓库、已发布 1.x 包、其他租户和当前生产 Head 不引用本次未发布源码,影响面为零。
|
|
112
117
|
|
|
118
|
+
`relation`/关联表单不再属于 Field Kit 标准组件,不迁移到新模板。普通供应商选择使用单选、
|
|
119
|
+
下拉或应用自己的业务页面;复杂关联查询由应用 App API 和页面自行实现。
|
|
120
|
+
|
|
113
121
|
## 8. 可证伪验收
|
|
114
122
|
|
|
115
123
|
1. Desktop/Mobile 连续上传两个同名文件时,每个服务端 `fileId` 只显示一次;上传成功不保留本地副本。
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# School-contact default access v2
|
|
2
|
+
|
|
3
|
+
## Decision
|
|
4
|
+
|
|
5
|
+
- Problem evidence: the product contract says an authenticated application user defaults to the unrestricted tenant-local school-contact scope, while `OpenXiangdaSchoolContactV2Service.resolveAccess` currently denies a valid Principal when its active RoleSession has no explicit school-contact capability.
|
|
6
|
+
- Capability owner: the platform school-contact service owns relation data-scope resolution. The Native authorization kernel remains the owner of Principal and RoleSession verification and is not bypassed or duplicated.
|
|
7
|
+
- Stable invariants: platform identity codes remain descriptive claims rather than switchable application roles; tenant, application, environment, Principal, RoleSession, pagination, and query enforcement remain server-verified.
|
|
8
|
+
- Contract: a verified non-guest Principal with no explicit school-contact scope defaults to `all`. Explicit `read`, `class:read`, and `self:read` resolve in the order `all > class > self`, allowing an application role to narrow the default. Invalid or missing Principal/RoleSession continues to fail before data access.
|
|
9
|
+
- Failure and concurrency: authorization errors propagate unchanged; access resolution is read-only and introduces no cache, retry, queue, lock, or cross-request state.
|
|
10
|
+
- Security and resource bounds: the default applies only after the existing v2 authentication and RoleSession boundary and never relaxes tenant/application isolation. The broader authenticated-user visibility is the explicitly accepted product policy.
|
|
11
|
+
- Affected contracts: the typed NestJS school-contact client and response types do not change. Only the default scope selected by the platform service changes.
|
|
12
|
+
- Rollback: code and documentation rollback only; there is no migration or persisted authorization rewrite.
|
|
13
|
+
- Falsifiable verification: tests prove default `all`, explicit `class`/`self`, widest-capability precedence, and fail-closed missing Principal evidence; `pnpm verify:affected` must pass.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Standard surface runtime corrections v2
|
|
2
|
+
|
|
3
|
+
Status: accepted for implementation on 2026-08-20.
|
|
4
|
+
|
|
5
|
+
## Problem evidence
|
|
6
|
+
|
|
7
|
+
- Standard Admin filters send scalar `eq` predicates for stable JSON option and
|
|
8
|
+
directory values. PostgreSQL rejects values such as `software` as invalid
|
|
9
|
+
JSON with SQLSTATE `22P02`.
|
|
10
|
+
- A department field is rendered by the platform field kit in forms, but its
|
|
11
|
+
search value is not normalized with the same field contract before a Data
|
|
12
|
+
API query is created.
|
|
13
|
+
- Admin tabs persist path metadata while the active Umi `Outlet` is unmounted
|
|
14
|
+
on every navigation. Returning to a tab therefore recreates and reloads the
|
|
15
|
+
page. Query-string changes do not have an explicit page-instance invalidation
|
|
16
|
+
key.
|
|
17
|
+
- The official mobile application shell explicitly contributes a role switcher
|
|
18
|
+
even though this surface is the normal end-user entry.
|
|
19
|
+
- The procurement reference workflow binds department approval to an
|
|
20
|
+
application role scope. The configured platform organization department
|
|
21
|
+
supervisor is therefore not consulted.
|
|
22
|
+
- Native clients request the durable record audit endpoint at
|
|
23
|
+
`/native/data/:resource/records/:id/audit`, but the Native Data controller has
|
|
24
|
+
no matching route. Desktop and mobile detail pages load data and audit in one
|
|
25
|
+
request group, so the missing audit route makes the whole detail page fail.
|
|
26
|
+
- The desktop end-user workflow submission route removes primary navigation
|
|
27
|
+
without contributing a back action.
|
|
28
|
+
|
|
29
|
+
## Capability owners
|
|
30
|
+
|
|
31
|
+
- `openxiangda-admin` owns standard search-value normalization, tab metadata,
|
|
32
|
+
and bounded mounted page instances.
|
|
33
|
+
- `openxiangda-field-kit` remains the owner of department and other platform
|
|
34
|
+
field controls and stable values; no application-specific selector is added.
|
|
35
|
+
- Native Data API owns durable business-audit reads and row/field enforcement.
|
|
36
|
+
- Platform organization data and `department_supervisor` resolution are the
|
|
37
|
+
only owners of configured department supervisors.
|
|
38
|
+
- `openxiangda-user` owns standard desktop submission navigation affordances;
|
|
39
|
+
the application supplies the destination.
|
|
40
|
+
- The application template owns which optional controls appear on its mobile
|
|
41
|
+
shell and which workflow provider its domain workflow selects.
|
|
42
|
+
|
|
43
|
+
## Stable invariants and affected contracts
|
|
44
|
+
|
|
45
|
+
1. Data API remains the only business-record store and query boundary. Stable
|
|
46
|
+
directory and option values keep their existing `{ label, value }` shapes.
|
|
47
|
+
2. Search predicates for those values use JSON containment; text, dates,
|
|
48
|
+
numbers, booleans, and physical scalar identifiers keep their current
|
|
49
|
+
operators.
|
|
50
|
+
3. Tabs, mounted page instances, query responses, and drafts remain separate
|
|
51
|
+
state. At most twelve tabs and six mounted pages are retained per identity.
|
|
52
|
+
4. A tab is identified by pathname. A change to that pathname's search/hash
|
|
53
|
+
location key remounts the active page and therefore reloads URL-bound data.
|
|
54
|
+
5. Identity epoch changes discard every mounted instance. Closing or LRU
|
|
55
|
+
eviction discards only the affected instance; the persisted tab may remain.
|
|
56
|
+
6. Native audit returns the existing `openxiangda.data-audit-page/v2`
|
|
57
|
+
contract. No second application audit API or database is introduced.
|
|
58
|
+
7. Native audit rechecks the current role's resource capability, row policy,
|
|
59
|
+
and field policy before returning each durable outbox event.
|
|
60
|
+
8. Mobile RoleSession behavior is unchanged; only the visible top-level role
|
|
61
|
+
switch button is removed from the standard user template.
|
|
62
|
+
9. Workflow Kernel contracts do not change. The reference binding selects the
|
|
63
|
+
already-supported `department_supervisor` provider with `departmentId`
|
|
64
|
+
facts.
|
|
65
|
+
10. OpenXiangda 1.x applications and runtime contracts are not affected.
|
|
66
|
+
|
|
67
|
+
## Failure, concurrency, security, and resource bounds
|
|
68
|
+
|
|
69
|
+
- Invalid or unreadable search fields still fail closed at Data API. The Admin
|
|
70
|
+
never falls back to browser filtering.
|
|
71
|
+
- Cached pages are hidden but remain mounted. LRU eviction is deterministic and
|
|
72
|
+
bounded to six instances; identity changes synchronously invalidate the pool.
|
|
73
|
+
- A changed URL location key replaces only the active cached instance. Stale
|
|
74
|
+
requests remain guarded by each standard page's request generation.
|
|
75
|
+
- Audit pagination is bounded, reads at most 500 matching durable events, and
|
|
76
|
+
omits events whose record snapshot no longer passes the current row policy.
|
|
77
|
+
- Audit is read-only and introduces no lock, receipt, retry loop, or mutable
|
|
78
|
+
application state.
|
|
79
|
+
- Department supervisor resolution remains tenant-scoped and uses the existing
|
|
80
|
+
organization service. Empty resolution continues to fail closed.
|
|
81
|
+
|
|
82
|
+
## Rollback boundary
|
|
83
|
+
|
|
84
|
+
- Platform rollback is the previous platform-server image; no SQL migration is
|
|
85
|
+
required.
|
|
86
|
+
- Frontend rollback is the previous independently published package set.
|
|
87
|
+
- Application rollback is the previous immutable preproduction AppVersion.
|
|
88
|
+
- No compatibility switch or duplicate endpoint is kept after rollback.
|
|
89
|
+
|
|
90
|
+
## Falsifiable verification
|
|
91
|
+
|
|
92
|
+
1. Admin tests prove department search uses the Field Kit control and stable
|
|
93
|
+
option/directory values compile to JSON containment rather than scalar `eq`.
|
|
94
|
+
2. Admin lifecycle tests prove switching between two tabs preserves component
|
|
95
|
+
state, the seventh cacheable page evicts the least recently used instance,
|
|
96
|
+
closing a tab unmounts it, identity changes clear all instances, and a query
|
|
97
|
+
change remounts the active instance.
|
|
98
|
+
3. Native Data tests prove the audit route exists, returns masked durable
|
|
99
|
+
history, enforces current row policy, and supports bounded pagination.
|
|
100
|
+
4. Workflow tests/config checks prove a configured platform department
|
|
101
|
+
supervisor resolves for `department-review` without an application-managed
|
|
102
|
+
department membership.
|
|
103
|
+
5. Mobile Chromium has no role button and can open a purchase detail page.
|
|
104
|
+
6. Desktop Chromium can return from the standalone submission page and URL
|
|
105
|
+
query changes reload the appropriate page.
|
|
106
|
+
7. Platform `verify:openxiangda-v2:release`, toolchain `verify:release`, and the
|
|
107
|
+
standard application's generate/check/test/build gates pass before a new
|
|
108
|
+
preproduction deployment is activated.
|
package/docs/data-authz.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
2.0 权限由 RBAC 与上下文数据策略共同组成:角色回答“可以做什么”,策略回答“在当前角色下可以对哪些数据和字段做”。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
家校关系使用相同的活动角色边界。有效 Principal/RoleSession 未声明任何 `school-contact:*` 范围能力时默认使用不限制的 `all`;需要收紧时显式授予 `self:read` 或 `class:read`,范围由平台在查询中强制执行,页面不能靠客户端过滤。应用自己的 App API 仍必须使用正常的业务操作 capability。见[家校通讯录关系](./school-contact-relations.md)。
|
|
6
6
|
|
|
7
7
|
## 请求模型
|
|
8
8
|
|
|
@@ -72,6 +72,8 @@ authz: {
|
|
|
72
72
|
|
|
73
73
|
`roleCodes` 把一条数据规则限定到当前 `RoleSession` 选中的角色。同一用户同时是申请人、学院管理员时,切换到学院管理员后,`applicant` 的 `current_user` 规则不再参与 OR 计算。多角色应用的角色特有规则必须声明 `roleCodes`;未声明时表示该规则对所有活动角色通用。编译器会拒绝空数组、重复或未声明的角色代码。
|
|
74
74
|
|
|
75
|
+
平台家校身份是另一条只读维度:使用 `platformRoleCodes`(`SCHOOL_GUARDIAN`、`SCHOOL_STUDENT`、`SCHOOL_TEACHER`)表达家长、学生、老师,不把它们塞进应用 `roleCodes`。这些编码由平台家校同步维护并在可信 Principal/RoleSession context 中返回;默认不增加数据限制,应用只有在明确需要时才在 App API 服务端做身份条件判断。浏览器请求中的同名字段不是授权凭据,不能用于放行。
|
|
76
|
+
|
|
75
77
|
角色成员、学院范围授权和“用户—仪器”关系授权属于环境运行数据,不进入不可变应用包。它们通过 Native 管理 API 维护,部署新版本不会删除。所有写操作要求 UUID `operationId`、目标资源 revision 和活动管理 RoleSession;平台在数据库事务内完成权限复核、幂等回执、CAS、相关会话撤销与审计。
|
|
76
78
|
|
|
77
79
|
新应用由 `openxiangda app provision` 为创建者建立平台保留的 `platform.app-super-admin` grant。它不是应用包中的普通角色,不能被业务流程代理或通过多个角色合并获得。重复执行 provision 会复用同一个 grant,可用于补齐早期创建但尚未初始化 Native 管理员的 2.0 应用。
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# 平台字段组件使用指南
|
|
2
|
+
|
|
3
|
+
OpenXiangda 2.0 应用的持久化表单字段统一使用 `openxiangda-field-kit`。桌面端从
|
|
4
|
+
`openxiangda-field-kit/desktop` 导入,移动端从 `openxiangda-field-kit/mobile` 导入;列表、
|
|
5
|
+
详情和只读状态使用对应的 `FieldValue`。应用可以自由组合页面,但不要在业务页面重新实现字段值、
|
|
6
|
+
文件上传、人员部门目录、地址、定位或签名协议。
|
|
7
|
+
|
|
8
|
+
## 基本用法
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { DesktopFieldControl, DesktopFieldValue } from 'openxiangda-field-kit/desktop';
|
|
12
|
+
|
|
13
|
+
<DesktopFieldControl
|
|
14
|
+
definition={{ code: 'amount', label: '预算金额', kind: 'money', precision: 2 }}
|
|
15
|
+
value={values.amount}
|
|
16
|
+
onChange={amount => setValues(current => ({ ...current, amount }))}
|
|
17
|
+
/>
|
|
18
|
+
|
|
19
|
+
<DesktopFieldValue
|
|
20
|
+
definition={{ code: 'amount', label: '预算金额', kind: 'money', precision: 2 }}
|
|
21
|
+
value={values.amount}
|
|
22
|
+
/>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
移动端替换为 `MobileFieldControl` 与 `MobileFieldValue`。平台目录、地址、定位和文件字段还需要传入
|
|
26
|
+
当前应用的 `FieldPlatformContext`;标准 Admin/User 页面已经自动提供。
|
|
27
|
+
|
|
28
|
+
常用体验配置继续沿用 1.0 的语义:文本支持 `maxLength`、`showCount`、前后缀和清空;数值支持
|
|
29
|
+
`min`、`max`、`step`、`precision`、单位位置和千分位;日期支持今天之前、今天之后或自定义区间;
|
|
30
|
+
多选支持 `maxCount`,子表支持 `minRows` / `maxRows`。这些都是页面行为,不改变 2.0 稳定值协议。
|
|
31
|
+
标准模板锁定 Ant Design 的尺寸、圆角和密度,不开放会造成三端样式分裂的任意 `variant` / `size` 覆盖。
|
|
32
|
+
|
|
33
|
+
## 什么时候使用哪个组件
|
|
34
|
+
|
|
35
|
+
| 需求 | 使用 | 不应使用 |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| 标题、名称、编号 | `text` | 不用富文本 |
|
|
38
|
+
| 多行纯文本说明 | `textarea` | 不需要格式时不用 `richtext` |
|
|
39
|
+
| 表格、链接、图片和带格式正文 | `richtext` | 简单备注不用它 |
|
|
40
|
+
| 数量、金额、比例 | `number` / `money` / `percent` | 不用文本保存可计算数值 |
|
|
41
|
+
| 少量互斥选项 | `radio` | 选项很多时用 `option` |
|
|
42
|
+
| 少量并列多选 | `checkbox` | 选项很多时用 `options` |
|
|
43
|
+
| 平台成员与组织 | `user(s)` / `department(s)` | 不用自由文本或复制组织树 |
|
|
44
|
+
| 邮寄或行政区地址 | `address` | 需要经纬度时用 `location` |
|
|
45
|
+
| 现场打点、签到 | `location` | 普通地址填写不用定位 |
|
|
46
|
+
| 任意类型文件 | `attachments` | 只收图片时使用 `images` |
|
|
47
|
+
| 照片、截图、凭证 | `images` | 不要直接使用 Ant Upload |
|
|
48
|
+
| 同一表单的多行明细 | `subtable` | 独立生命周期的大量记录应建资源页面 |
|
|
49
|
+
| 现场手写确认 | `signature` | 法律电子签章接专业签署服务 |
|
|
50
|
+
| 流程状态展示 | `workflowStatus` | 不允许页面直接编辑流程状态 |
|
|
51
|
+
|
|
52
|
+
完整机器可读清单由 `fieldCatalog` 导出,包含每个 `FieldKind` 的值协议、适用和不适用场景。
|
|
53
|
+
|
|
54
|
+
关联表单组件已经弃用。普通关联选择使用 `option`、`radio` 或文本;需要分页检索、复杂权限和业务
|
|
55
|
+
联动时,由应用通过 NestJS App API 实现独立页面,不把业务查询重新塞进通用字段组件。
|
|
56
|
+
|
|
57
|
+
## 附件和图片
|
|
58
|
+
|
|
59
|
+
DataResource 中对应字段必须声明为 `type: 'file'`。组件保留 1.0 已验证的上传、进度、取消、失败
|
|
60
|
+
重试、预览、下载和删除交互;底层由一个 `fileService` 调用 2.0 Native Files API。应用不接触
|
|
61
|
+
`initiate → PUT → complete → delete-unbound` 细节,也不要拼接对象存储地址。
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
{ code: 'attachments', type: 'file', nullable: true,
|
|
65
|
+
file: { multiple: true, maxCount: 10, maxSizeMb: 50 } }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
同名文件不会合并;只按平台 `fileId` 或稳定 URL 去重。图片字段可以配置 `imageCompression`,但页面
|
|
69
|
+
不能放宽 DataResource 已声明的数量、类型和大小限制。
|
|
70
|
+
|
|
71
|
+
## 富文本图片
|
|
72
|
+
|
|
73
|
+
富文本本身仍保存清洗后的 HTML 字符串。需要上传内嵌图片时,把 `richTextImageFieldCode` 指向同一
|
|
74
|
+
资源中真实的 `file` 字段;标准表单会把上传结果追加到该文件字段,确保记录保存时完成文件绑定。
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
{
|
|
78
|
+
code: 'description',
|
|
79
|
+
label: '详细说明',
|
|
80
|
+
kind: 'richtext',
|
|
81
|
+
richTextToolbar: 'full',
|
|
82
|
+
richTextImageFieldCode: 'images',
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
没有配置伴随文件字段时,桌面编辑器仍支持图片 URL,但不会开放本地图片上传。
|
|
87
|
+
|
|
88
|
+
## 验收要求
|
|
89
|
+
|
|
90
|
+
- 编辑、禁用、只读和空值均可用。
|
|
91
|
+
- 必填标识紧邻标签;提交失败定位到第一个错误字段。
|
|
92
|
+
- Desktop 与 Mobile 使用独立 renderer,移动入口不加载桌面 Ant Design 录入控件。
|
|
93
|
+
- 附件、图片、富文本、人员、部门、地址、定位和签名必须在标准模板真实保存后回显。
|
package/docs/frontend.md
CHANGED
|
@@ -53,11 +53,11 @@ OpenXiangda 2.0 桌面管理端采用 React 19、Ant Design 6、Umi Max 4、ProC
|
|
|
53
53
|
|
|
54
54
|
## Field Kit 与移动用户端
|
|
55
55
|
|
|
56
|
-
所有平台字段使用 `openxiangda-field-kit`
|
|
56
|
+
所有平台字段使用 `openxiangda-field-kit` 的稳定值协议。人员、部门、单选、多选、单选框、复选框、日期、日期区间、地址、图片、附件、富文本和数值等都由统一定义驱动存储与显示。组件选型见[平台字段组件使用指南](./field-components.md)。
|
|
57
57
|
|
|
58
58
|
- 桌面 Admin 从 `openxiangda-field-kit/desktop` 使用 Ant Design 控件。
|
|
59
59
|
- 移动用户端由 `openxiangda-user/mobile` 提供工作台、数据列表/表单/详情和流程提交/任务/实例页面,并从 `openxiangda-field-kit/mobile` 使用 Ant Design Mobile 的独立字段交互;不把桌面 Select、DatePicker 或 Cascader 缩小后复用。
|
|
60
|
-
-
|
|
60
|
+
- 人员、部门、行政区、上传、下载和预览都通过平台 API;应用不自行复制平台目录或文件协议。关联表单平台组件已弃用,复杂关联查询由应用页面和 App API 实现。
|
|
61
61
|
- UI 必填、默认值、显隐、布局和帮助文本属于页面层;后端业务不应假设自定义页面一定执行了前端校验。
|
|
62
62
|
|
|
63
63
|
生成模板将桌面 Admin 与移动用户端放在同一个 AppPackage 的两个独立懒加载路由树中;`/admin` 只加载 Pro 页面,`/m` 只加载 `openxiangda-user/mobile`,根入口按设备能力一次性选择。移动 Chromium 已验证两棵树不混用 DOM,并覆盖稳定角色切换、列表/详情、流程发起与平台特殊字段。
|
package/docs/index.md
CHANGED
|
@@ -23,3 +23,5 @@ features:
|
|
|
23
23
|
OpenXiangda 2.0 保留平台统一数据与治理能力,同时把应用开发恢复成成熟的前后端工程。本工具链只面向 2.0 应用;旧应用由独立的 1.x 产品线维护。
|
|
24
24
|
|
|
25
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 页面协议建立在这些可验证的运行时事实之上。
|
|
26
|
+
|
|
27
|
+
开发表单、列表或详情前阅读[平台字段组件使用指南](/field-components),按场景选择桌面、移动和只读组件。
|
package/docs/llms.txt
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
- /getting-started.md: standard workspace and development loop
|
|
4
4
|
- /concepts.md: application, platform, data, runtime, and version boundaries
|
|
5
5
|
- /frontend.md: React admin shell, role session, CRUD, workflow UI
|
|
6
|
+
- /field-components.md: platform field catalog, usage, selection rules, file and rich-text examples
|
|
6
7
|
- /backend.md: NestJS modules, identity, Data API, health, secrets
|
|
7
8
|
- /data-authz.md: RBAC plus contextual data and field authorization
|
|
8
9
|
- /workflow-events.md: Workflow Kernel v2, providers, actions, durable events
|
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
|
|
5
5
|
## 数据合同
|
|
6
6
|
|
|
7
|
+
### 平台内置身份角色
|
|
8
|
+
|
|
9
|
+
成功的家校全量同步会维护平台层身份角色(不属于应用 `RoleSession` 的可切换角色):
|
|
10
|
+
|
|
11
|
+
| 展示名 | 稳定编码 | 来源 |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| 家长 | `SCHOOL_GUARDIAN` | 家校成员 `guardian` |
|
|
14
|
+
| 学生 | `SCHOOL_STUDENT` | 家校成员 `student` |
|
|
15
|
+
| 老师 | `SCHOOL_TEACHER` | 家校成员 `teacher` |
|
|
16
|
+
|
|
17
|
+
身份可组合,同一用户可以同时拥有多个编码。2.0 的 `NativePrincipal` / `Principal` 和 `RoleSessionContext` 以可选的 `platformRoleCodes` 暴露这些编码;它们只用于业务身份判断,不能替代当前应用角色、不能参与 `roleCodes` 的切换,也不能由浏览器提交。权限默认不限制,应用若需要按身份限制页面或 App API,应在服务端使用这些可信编码显式校验。
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
const isTeacher =
|
|
21
|
+
request.openxiangda?.principal.platformRoleCodes?.includes('SCHOOL_TEACHER')
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
应用开发者不直接写 `roles` 绑定,也不在本地复制同步结果;下一次完整同步会自动增删平台身份绑定。
|
|
25
|
+
|
|
7
26
|
平台同步钉钉家校通讯录后,以只读关系返回监护人、学生和班级。关系两端都包含:
|
|
8
27
|
|
|
9
28
|
- `userId`:平台用户 ID,业务数据应保存这个稳定标识;
|
|
@@ -15,15 +34,15 @@
|
|
|
15
34
|
|
|
16
35
|
## 权限与默认范围
|
|
17
36
|
|
|
18
|
-
|
|
37
|
+
通过既有认证和 `RoleSession` 校验的非游客用户,在没有声明任何 `school-contact:*` 范围能力时,平台默认使用 `all`,可以查看当前租户全部已同步关系。应用自己的 App API 仍按正常方式声明业务操作能力,例如:
|
|
19
38
|
|
|
20
39
|
```ts
|
|
21
40
|
authz: {
|
|
22
41
|
capabilities: [
|
|
23
42
|
{
|
|
24
|
-
code: 'app:school-service:
|
|
43
|
+
code: 'app:school-service:family:read',
|
|
25
44
|
kind: 'backend',
|
|
26
|
-
name: '
|
|
45
|
+
name: '使用家庭关系功能',
|
|
27
46
|
},
|
|
28
47
|
{
|
|
29
48
|
code: 'app:school-service:school-contact:self:read',
|
|
@@ -40,13 +59,13 @@ authz: {
|
|
|
40
59
|
{
|
|
41
60
|
code: 'user',
|
|
42
61
|
name: '普通用户',
|
|
43
|
-
capabilities: ['app:school-service:
|
|
62
|
+
capabilities: ['app:school-service:family:read'],
|
|
44
63
|
},
|
|
45
64
|
],
|
|
46
65
|
}
|
|
47
66
|
```
|
|
48
67
|
|
|
49
|
-
|
|
68
|
+
应用自己的查询接口进入不可变 App API 合同并使用业务操作能力:
|
|
50
69
|
|
|
51
70
|
```ts
|
|
52
71
|
backend: {
|
|
@@ -55,7 +74,7 @@ backend: {
|
|
|
55
74
|
code: 'family.mine',
|
|
56
75
|
method: 'GET',
|
|
57
76
|
path: '/api/family/mine',
|
|
58
|
-
capability: 'app:school-service:
|
|
77
|
+
capability: 'app:school-service:family:read',
|
|
59
78
|
requestSchema: { type: 'object', additionalProperties: false },
|
|
60
79
|
responseSchema: { type: 'object' },
|
|
61
80
|
},
|
|
@@ -63,7 +82,7 @@ backend: {
|
|
|
63
82
|
}
|
|
64
83
|
```
|
|
65
84
|
|
|
66
|
-
|
|
85
|
+
未给活动角色授予任何 `school-contact:*` 范围能力时,数据范围就是 `all`,不限制,可以查看全部已同步关系。只有业务明确需要最小化可见范围时,才给角色增加 `self:read` 或 `class:read`;可选的 `school-contact:read` 表示显式保持 `all`。同一角色同时获得多个范围能力时按 `all > class > self` 取最宽范围,避免前后端对范围产生不同解释。无有效 Principal/RoleSession、游客和跨租户请求仍然拒绝。
|
|
67
86
|
|
|
68
87
|
## NestJS App API
|
|
69
88
|
|
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.39",
|
|
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.28"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"tsx": "4.23.12",
|
|
@@ -39,8 +39,10 @@ For a new repository, link it to the target platform and let an authorized platf
|
|
|
39
39
|
- Build one immutable application package; the platform owns deployment execution, health gates, promotion, and rollback.
|
|
40
40
|
- Reject any workspace that does not declare the native 2.0 application configuration.
|
|
41
41
|
- Read school-contact relationships only through a NestJS App API bound to the
|
|
42
|
-
active RoleSession.
|
|
43
|
-
|
|
42
|
+
active RoleSession. A verified non-guest Principal defaults to unrestricted
|
|
43
|
+
`all` without a school-contact scope capability; narrower self/class access
|
|
44
|
+
must be an explicit authorization decision. The App API still requires its
|
|
45
|
+
normal business-operation capability.
|
|
44
46
|
|
|
45
47
|
## Delivery Gate
|
|
46
48
|
|
|
@@ -27,10 +27,18 @@ Model permissions as capability checks plus contextual data predicates. A role g
|
|
|
27
27
|
- Require the application directory capability before using department or user
|
|
28
28
|
selectors. Store stable IDs and resolve display labels through Directory v2;
|
|
29
29
|
do not copy tenant contact data into application records.
|
|
30
|
-
- School-contact access defaults to
|
|
31
|
-
|
|
30
|
+
- School-contact access defaults to unrestricted `all` for a verified
|
|
31
|
+
non-guest Principal/RoleSession even when no `school-contact:*` scope
|
|
32
|
+
capability is assigned. Use `school-contact:self:read` or
|
|
32
33
|
`school-contact:class:read` only when the product explicitly requires a
|
|
33
|
-
narrower scope;
|
|
34
|
+
narrower scope; keep the application's own App API behind its normal
|
|
35
|
+
business-operation capability and rely on the platform query boundary, not
|
|
36
|
+
browser filtering.
|
|
37
|
+
- The synchronized platform identities `SCHOOL_GUARDIAN`, `SCHOOL_STUDENT`,
|
|
38
|
+
and `SCHOOL_TEACHER` are additive `platformRoleCodes` on the trusted
|
|
39
|
+
Principal/RoleSession context, not selectable application `roleCodes`.
|
|
40
|
+
They are maintained by the platform sync and are unrestricted by default;
|
|
41
|
+
use them only for an explicit server-side identity check.
|
|
34
42
|
- Apply field policies consistently to queries, search controls, forms, CSV
|
|
35
43
|
transfer and restricted transactions.
|
|
36
44
|
- Use the bounded server-side aggregate endpoint for charts and summaries. Only
|
|
@@ -23,13 +23,15 @@ Build in `apps/web` with React 19, Ant Design 6, Umi Max 4 and ProComponents 3.
|
|
|
23
23
|
## Platform fields and mobile user UI
|
|
24
24
|
|
|
25
25
|
1. Use `openxiangda-field-kit/desktop` in the desktop Admin. Build the independent mobile tree with `OpenXiangdaUserProvider` from `openxiangda-user` and the standard pages from `openxiangda-user/mobile`; those pages consume `openxiangda-field-kit/mobile`. Mobile is not a CSS-responsive copy of the Admin.
|
|
26
|
-
2.
|
|
27
|
-
3.
|
|
28
|
-
4.
|
|
29
|
-
5.
|
|
30
|
-
6.
|
|
31
|
-
7.
|
|
32
|
-
8.
|
|
26
|
+
2. Before choosing a field, read [Platform field components](../../docs/field-components.md) or the exported `fieldCatalog`. It records every kind's value contract, when to use it and when not to use it.
|
|
27
|
+
3. Platform fields include text/textarea/richtext, number/money/percent, boolean, single/multiple select, radio/checkbox/cascade, date/datetime/date range, user/users, department/departments, address/location, image/attachments, signature, subtable/JSON, serial and workflow status. The association-form/relation platform component is discontinued; use option/radio for ordinary choices or an application page plus App API for complex relation queries.
|
|
28
|
+
4. Persist established stable values. Directory and option 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.
|
|
29
|
+
5. Personnel, departments, administrative divisions, uploads, downloads and previews must use platform APIs. Do not copy platform directory data or write a second upload protocol. Do not use Ant Upload or a raw file input in an application page for a persistent file field.
|
|
30
|
+
6. Use `attachments` for general files and `images` when thumbnail/preview/photo selection is required. The DataResource field must be `file`. Rich-text local images require `richTextImageFieldCode` pointing to a companion `file` field so uploaded files bind with the saved record.
|
|
31
|
+
7. 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.
|
|
32
|
+
8. 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.
|
|
33
|
+
9. Prefer `MobileAppShell`, `MobileWorkbenchPage`, `MobileResourceListPage`, `MobileResourceFormPage`, `MobileResourceDetailPage`, `MobileWorkflowSubmissionPage`, `MobileWorkflowWorkCenterPage`, `MobileWorkflowTaskPage` and `MobileWorkflowInstancePage`. The Workflow submission page must show only the business form and one Submit action until save and prepare succeed; only then open the approval preview.
|
|
34
|
+
10. Keep the mobile package out of NestJS dependencies. The browser may call only platform-relative Native clients under the current RoleSession; it must not persist platform tokens, service addresses, permission decisions or business responses.
|
|
33
35
|
|
|
34
36
|
## Verification
|
|
35
37
|
|