openxiangda 2.0.0-alpha.99 → 2.0.0

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.
Files changed (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -20
  3. package/bin/distribution/commands.js +55 -0
  4. package/bin/distribution/launcher.js +49 -0
  5. package/bin/distribution/migrate.js +60 -0
  6. package/bin/distribution/releases.js +52 -0
  7. package/bin/distribution/skills.js +80 -0
  8. package/bin/distribution/update.js +68 -0
  9. package/bin/distribution/workspace.js +85 -0
  10. package/bin/run.js +9 -11
  11. package/dist/browser/AuthoritativeSelector.d.ts +3 -2
  12. package/dist/browser/AuthoritativeSelector.d.ts.map +1 -1
  13. package/dist/browser/AuthoritativeSelector.js +39 -24
  14. package/dist/browser/AuthoritativeSelector.js.map +1 -1
  15. package/dist/browser/components/platform-fields/MobileFieldControls.d.ts.map +1 -1
  16. package/dist/browser/components/platform-fields/MobileFieldControls.js +2 -2
  17. package/dist/browser/components/platform-fields/MobileFieldControls.js.map +1 -1
  18. package/dist/browser/components/platform-fields/ResourceReferenceField.d.ts +4 -2
  19. package/dist/browser/components/platform-fields/ResourceReferenceField.d.ts.map +1 -1
  20. package/dist/browser/components/platform-fields/ResourceReferenceField.js +2 -2
  21. package/dist/browser/components/platform-fields/ResourceReferenceField.js.map +1 -1
  22. package/dist/browser/components/platform-fields/rich-text-value.d.ts.map +1 -1
  23. package/dist/browser/components/platform-fields/rich-text-value.js +11 -1
  24. package/dist/browser/components/platform-fields/rich-text-value.js.map +1 -1
  25. package/dist/browser/components/resource/RecordDetailFrame.js +1 -1
  26. package/dist/browser/components/resource/RecordDetailFrame.js.map +1 -1
  27. package/dist/browser/components/resource/SurfaceFields.d.ts +3 -2
  28. package/dist/browser/components/resource/SurfaceFields.d.ts.map +1 -1
  29. package/dist/browser/components/resource/SurfaceFields.js +14 -7
  30. package/dist/browser/components/resource/SurfaceFields.js.map +1 -1
  31. package/dist/browser/components/resource/resource-import.d.ts +16 -1
  32. package/dist/browser/components/resource/resource-import.d.ts.map +1 -1
  33. package/dist/browser/components/resource/resource-import.js +58 -34
  34. package/dist/browser/components/resource/resource-import.js.map +1 -1
  35. package/dist/browser/components/resource/useResourceFormDrafts.d.ts.map +1 -1
  36. package/dist/browser/components/todo/ApplicationTodoCenterPage.d.ts.map +1 -1
  37. package/dist/browser/components/todo/ApplicationTodoCenterPage.js +1 -2
  38. package/dist/browser/components/todo/ApplicationTodoCenterPage.js.map +1 -1
  39. package/dist/browser/components/workflow/StandardWorkflowPages.d.ts.map +1 -1
  40. package/dist/browser/components/workflow/StandardWorkflowPages.js +54 -52
  41. package/dist/browser/components/workflow/StandardWorkflowPages.js.map +1 -1
  42. package/dist/browser/platform-client.d.ts +3 -2
  43. package/dist/browser/platform-client.d.ts.map +1 -1
  44. package/dist/browser/platform-client.js +69 -18
  45. package/dist/browser/platform-client.js.map +1 -1
  46. package/dist/browser/record-detail.css +3 -2
  47. package/dist/browser/runtime.d.ts.map +1 -1
  48. package/dist/browser/runtime.js +26 -2
  49. package/dist/browser/runtime.js.map +1 -1
  50. package/dist/browser/workflow-launch.d.ts +4 -1
  51. package/dist/browser/workflow-launch.d.ts.map +1 -1
  52. package/dist/browser/workflow-launch.js +32 -0
  53. package/dist/browser/workflow-launch.js.map +1 -1
  54. package/dist/core.d.ts +1 -1
  55. package/dist/core.d.ts.map +1 -1
  56. package/dist/core.js.map +1 -1
  57. package/documentation/AGENTS.md +26 -0
  58. package/documentation/administration.md +27 -0
  59. package/documentation/application-foundation.md +162 -0
  60. package/documentation/appspec.md +152 -0
  61. package/documentation/backend.md +132 -0
  62. package/documentation/concepts.md +61 -0
  63. package/documentation/data-authz.md +62 -0
  64. package/documentation/delivery.md +110 -0
  65. package/documentation/development.md +32 -0
  66. package/documentation/field-components.md +236 -0
  67. package/documentation/frontend.md +269 -0
  68. package/documentation/getting-started.md +66 -0
  69. package/documentation/interaction-patterns.md +56 -0
  70. package/documentation/manifest.json +120 -0
  71. package/documentation/product-design.md +142 -0
  72. package/documentation/public-access.md +167 -0
  73. package/documentation/reference/cli.md +27 -0
  74. package/documentation/reference/mcp.md +649 -0
  75. package/documentation/testing.md +63 -0
  76. package/documentation/upgrading.md +39 -0
  77. package/documentation/workflow-events.md +181 -0
  78. package/launcher-skill/openxiangda/SKILL.md +24 -0
  79. package/package.json +72 -9
  80. package/releases/2.0.0.json +50 -0
  81. package/skills/manifest.json +2 -2
  82. package/skills/openxiangda-v2/SKILL.md +64 -51
  83. package/skills/openxiangda-v2/agents/openai.yaml +2 -2
  84. package/skills/openxiangda-v2/references/administration.md +27 -0
  85. package/skills/openxiangda-v2/references/application-foundation.md +162 -0
  86. package/skills/openxiangda-v2/references/appspec.md +132 -47
  87. package/skills/openxiangda-v2/references/backend.md +101 -248
  88. package/skills/openxiangda-v2/references/cli.md +27 -0
  89. package/skills/openxiangda-v2/references/concepts.md +61 -0
  90. package/skills/openxiangda-v2/references/data-authz.md +36 -388
  91. package/skills/openxiangda-v2/references/delivery.md +110 -49
  92. package/skills/openxiangda-v2/references/development.md +32 -0
  93. package/skills/openxiangda-v2/references/field-components.md +236 -0
  94. package/skills/openxiangda-v2/references/frontend.md +254 -280
  95. package/skills/openxiangda-v2/references/getting-started.md +66 -0
  96. package/skills/openxiangda-v2/references/interaction-patterns.md +56 -0
  97. package/skills/openxiangda-v2/references/mcp.md +649 -0
  98. package/skills/openxiangda-v2/references/product-design.md +142 -0
  99. package/skills/openxiangda-v2/references/public-access.md +92 -84
  100. package/skills/openxiangda-v2/references/testing.md +45 -56
  101. package/skills/openxiangda-v2/references/upgrading.md +39 -0
  102. package/skills/openxiangda-v2/references/workflow-events.md +143 -285
  103. package/skills/openxiangda-v2/references/architecture.md +0 -9
  104. package/skills/openxiangda-v2/references/commands.md +0 -21
  105. package/skills/openxiangda-v2/references/discovery.md +0 -15
  106. package/skills/openxiangda-v2/references/workspace.md +0 -62
@@ -0,0 +1,236 @@
1
+ # OpenXiangda 2.0 字段组件协议
2
+
3
+ OpenXiangda 2.0 只声明业务语义字段。字段的 TypeScript 值、JSON Schema、
4
+ PostgreSQL 物理列、索引、查询运算符、权限路径和桌面/移动组件都由编译器从同一份声明生成,
5
+ 应用不能另外声明存储类型或第二套字段元数据。
6
+
7
+ 完整的架构约束、验收矩阵和进度证据见
8
+ [数据与权限](data-authz.md)。
9
+
10
+ ## 字段与存储
11
+
12
+ | 语义类型 | 标准组件 | Data API 存储/读取值 | PostgreSQL |
13
+ | --- | --- | --- | --- |
14
+ | `text.short` | 单行、邮箱、手机号 | `string` | `varchar(length)` |
15
+ | `text.long` | 多行文本 | `string` | `text` |
16
+ | `text.rich` | 富文本 | 清洗后的 HTML `string` | `text` |
17
+ | `number.integer` | 整数 | `number` | `bigint` |
18
+ | `number.decimal` | 小数、金额、百分比 | `number` | `numeric(p,s)` |
19
+ | `boolean` | 是/否选择 | `boolean` | `boolean` |
20
+ | `date` | 日期 | `YYYY-MM-DD` | `date` |
21
+ | `time` | 时间,可声明分钟或秒精度 | `HH:mm:ss` | `time(0)` |
22
+ | `datetime` | 日期时间 | RFC3339 instant | `timestamptz` |
23
+ | `date-range` | 日期范围 | `{start,end}` | `daterange` |
24
+ | `datetime-range` | 日期时间范围 | `{start,end}` | `tstzrange` |
25
+ | `option.single` | 静态单选下拉、单选按钮 | `{label,value,...}` | `jsonb` |
26
+ | `option.multiple` | 静态多选下拉、复选框 | `{label,value,...}[]` | `jsonb` |
27
+ | `cascade.single` | 单路径级联 | `{label,value,...}[]` | `jsonb` |
28
+ | `cascade.multiple` | 多路径级联 | `{label,value,...}[][]` | `jsonb` |
29
+ | `user.single` | 成员单选 | 完整成员快照或 `null` | `jsonb` |
30
+ | `user.multiple` | 成员多选 | 完整成员快照数组 | `jsonb` |
31
+ | `department.single` | 部门单选 | 完整部门/路径快照或 `null` | `jsonb` |
32
+ | `department.multiple` | 部门多选 | 完整部门/路径快照数组 | `jsonb` |
33
+ | `resource-ref.single` | 动态下拉、单选按钮、资源选择 | 资源 `{label,value,resourceCode,snapshot}` | `jsonb` |
34
+ | `resource-ref.multiple` | 动态多选、复选框、资源选择 | 资源快照数组 | `jsonb` |
35
+ | `file` | 附件 | `DataFileRef[]` | `jsonb` |
36
+ | `image` | 图片 | 带尺寸、缩略图和预览地址的 `DataImageRef[]` | `jsonb` |
37
+ | `signature` | 手写业务签名 | 托管 PNG、签署人、时间、轨迹和哈希 | `jsonb` |
38
+ | `address` | 行政区划地址 | 行政区划标签路径、详细地址和完整地址 | `jsonb` |
39
+ | `location` | 精确定位 | 钉钉/浏览器 WGS84 经纬度和只读服务快照 | `jsonb` |
40
+ | `json` | JSON 编辑器 | 有界 JSON | `jsonb` |
41
+ | `serial-number` | 流水号只读框 | 平台生成 `string` | `varchar(255)` |
42
+ | `uuid` | UUID 业务字段 | 校验 UUID 格式,可按权限修改 | `uuid` |
43
+ | `subtable` | 子表 | 普通子资源行集合 | 独立子表 |
44
+
45
+ 单值空值统一使用 `null`;多值、附件和图片统一使用 `[]`。`subtable` 不在父表保存
46
+ JSON,而是通过标准 Data API 事务维护普通子资源。
47
+
48
+ 布尔字段没有默认值时显示“未选择”,不会把未填写当成“否”。PC 和移动端可以直接选择“否”并提交 `false`;`false` 是有效值,不是必填校验中的空值。只有明确声明默认值时才初始化对应布尔值。
49
+
50
+ ## 图片、缩略图和附件读取
51
+
52
+ 文件本体保存于平台对象存储,业务字段保存 `DataFileRef[]` 或 `DataImageRef[]`,不把 Base64 图片、文件字节、浏览器 `blob:` 地址写入业务字段。`previewUrl` 和 `thumbnailUrl` 是平台按当前应用、环境和文件权限生成的读取地址,不是永久公开 OSS 地址;不要自行替换域名、删除环境参数或拼接对象存储路径。
53
+
54
+ 图片上传完成后,平台保留原文件,并生成最长边 480 像素、保持比例、不放大小图的 WebP 缩略图,编码质量参数为 82。列表、活动卡片、小封面和头像优先用缩略图;大图预览和下载按需读取原文件。当前原生文件端点只支持原文件和 `variant=thumbnail`,不能自行拼接 `width`、`quality` 等未声明参数。附件字段中的图片不保证具有缩略图,需要缩略图能力时声明 `image` 字段。
55
+
56
+ 标准图片/附件展示可以直接使用 Field Kit:
57
+
58
+ ```tsx
59
+ import { AttachmentFileList } from 'openxiangda/field-kit';
60
+
61
+ <AttachmentFileList
62
+ files={record.cover ?? []}
63
+ resourceCode="activities"
64
+ imageTiles
65
+ mobile={isMobile}
66
+ />
67
+ ```
68
+
69
+ 组件按文件引用选择缩略图,预览和下载经过平台接口。自定义活动封面同样先选择 `cover.thumbnailUrl`;只有平台引用没有缩略图时才回退 `cover.previewUrl`。不要写 `previewUrl || thumbnailUrl`,否则小卡片也会下载完整原图。保留真实宽高或稳定的封面比例,非首屏图片使用懒加载;不得在列表渲染时预取所有原图。
70
+
71
+ 受限文件的缓存必须保留权限核验。配套平台支持私有条件缓存时,浏览器可以保存文件响应,再次访问由平台先核对当前权限,内容未变化返回 304,从本地复用字节;`no-cache` 表示复用前校验,和 `no-store` 禁止保存不同。缺少可靠实体标识或请求失败时仍禁止缓存。不应由应用添加长期免校验缓存、公开 CDN 缓存或跨账号 Blob 缓存来绕过该规则。公开长期缓存需要独立、明确的公开发布契约,不能仅因字段名叫封面就视为公开。
72
+
73
+ 验收时同时记录原图/缩略图字节、列表实际请求的变体、重复访问传输量和权限撤销结果。仅看到 `blob:` 地址不能判断用了 Base64,HTTP 200 也不能证明命中了缓存。
74
+
75
+ ## 声明示例
76
+
77
+ ```ts
78
+ {
79
+ code: 'status',
80
+ type: 'option.single',
81
+ label: '状态',
82
+ widget: 'radio',
83
+ required: true,
84
+ indexed: true,
85
+ filter: true,
86
+ options: [
87
+ { label: '草稿', value: 'draft', color: 'default' },
88
+ { label: '已提交', value: 'submitted', color: 'blue' },
89
+ ],
90
+ }
91
+ ```
92
+
93
+ 前端提交并读取完整快照,例如 `{label:'草稿',value:'draft'}`。后端信任显示快照,
94
+ 只做有界结构校验;查询和权限以 `value` 为稳定比较键。选项后来改名不会改变历史记录的显示值。
95
+
96
+ 动态选项使用同应用资源引用:
97
+
98
+ `source.labelField` 必须指向目标资源的 `text.short` 或 `text.long` 字段。流水号字段可以放进
99
+ `searchFields`、`descriptionFields` 或 `snapshotFields`,但不能作为显示标签。
100
+
101
+ ```ts
102
+ {
103
+ code: 'customer',
104
+ type: 'resource-ref.single',
105
+ label: '客户',
106
+ widget: 'select',
107
+ indexed: true,
108
+ filter: true,
109
+ source: {
110
+ kind: 'resource',
111
+ resourceCode: 'customers',
112
+ labelField: 'name',
113
+ searchFields: ['name', 'code'],
114
+ descriptionFields: ['code'],
115
+ snapshotFields: ['code', 'level'],
116
+ pageSize: 20,
117
+ loadMode: 'search',
118
+ },
119
+ }
120
+ ```
121
+
122
+ 来源端点接受当前表单绑定值、关键字和游标;页大小由 `source.pageSize` 固定。
123
+ 标准流程的具名动作发起表单由 `WorkflowSubmissionPage` 自动传递 `launch: { workflowCode, operationCode }`。
124
+ 平台核对当前环境已部署的流程、动作、输入字段映射和当前用户动作权限;不要求额外授予宿主表单 CRUD 权限。
125
+ 普通 CRUD 表单不传此绑定,继续检查对应创建/修改权限。自定义选择器可通过 `searchResource` 的同名选项传递
126
+ 已声明的发起绑定,不能用它扩大目标资源的读取范围或执行动作。
127
+ 使用此功能的编译包自动要求平台能力 `workflow.named-input-sources` 的 `1.0.0` 版本;先检查目标平台能力,配套升级后再发布。
128
+ 平台按来源资源的字段权限和 PostgreSQL RLS 查询并返回完整资源快照。来源记录改名或删除后,
129
+ 已经保存的 `{label,value,resourceCode,snapshot}` 仍可直接展示,不需要再次查询。
130
+
131
+ 成员和部门同样保存完整显示快照:
132
+
133
+ ```ts
134
+ { code: 'owner', type: 'user.single', label: '负责人', required: true }
135
+ { code: 'participants', type: 'user.multiple', label: '参与人' }
136
+ { code: 'college', type: 'department.single', label: '学院', indexed: true, filter: true }
137
+ { code: 'supportDepartments', type: 'department.multiple', label: '协作部门' }
138
+ ```
139
+
140
+ 成员快照可包含头像、工号、职务、手机号、邮箱和所属部门;部门快照可包含完整路径、
141
+ 路径节点和父部门。凭证、Token 和认证秘密永远不能进入快照。
142
+
143
+ 仅选择时间时使用 `time`,并显式决定精度:
144
+
145
+ ```ts
146
+ { code: 'reminderMinute', type: 'time', label: '提醒时间', timePrecision: 'minute' }
147
+ { code: 'checkpointSecond', type: 'time', label: '检查时间', timePrecision: 'second' }
148
+ ```
149
+
150
+ 定位只支持钉钉定位或浏览器 Geolocation 采集 WGS84 经纬度。组件没有地址输入、
151
+ 手工定位或地图选点;服务商返回的地址/POI 只能作为该坐标的只读显示快照。
152
+
153
+ ## 移动选择交互
154
+
155
+ `MobileSurfaceFieldControl` 为成员、部门、级联和动态资源字段提供统一的移动弹层。
156
+ 直接使用目录选择组件时也可传 `mobile`;显式移动界面不会因窗口较宽而切回 PC 控件。
157
+ 应用继续声明同一份业务字段,使用平台组件即可,无需自己拼目录树或搜索接口。
158
+
159
+ - 成员按部门逐层浏览,部门支持逐层选择和下钻;搜索、部门层级和成员列表均按页读取。
160
+ - 级联通过路径导航选择末级项;多选或较多候选支持完整路径搜索,多选保留每条完整路径快照。
161
+ - 当前已选项独立显示,可以移除或清空;切换路径、搜索和翻页不丢失尚未确认的选择。
162
+ - 单选和多选均点击“确定”才写回表单;“取消”或“关闭”放弃本次弹层修改。候选读取失败可重试。
163
+
164
+ 界面使用平台封装的 Ant Design Mobile 组件;样式与弹层留在移动组件作用域内。
165
+ 存储快照、来源过滤和权限仍遵循上述标准契约,不为移动端增加第二套数据或权限接口。
166
+
167
+ ## 查询与权限
168
+
169
+ 列表、聚合、导出、动态来源和事务断言共用 `openxiangda.data-query/v2` 的有界 `where`:
170
+
171
+ ```ts
172
+ {
173
+ schemaVersion: 'openxiangda.data-query/v2',
174
+ where: {
175
+ and: [
176
+ { field: 'status', operator: 'eq', value: 'submitted' },
177
+ { field: 'customer', path: 'snapshot.level', operator: 'eq', value: 'A' },
178
+ ],
179
+ },
180
+ order: [{ field: 'status', direction: 'asc' }],
181
+ limit: 20,
182
+ }
183
+ ```
184
+
185
+ 客户端不能发送 SQL、PostgREST 表达式或任意 JSONPath。编译器只接受字段类型允许的运算符
186
+ 和已声明的快照路径,所有值都使用 SQL 参数。标量索引使用 BTREE,单快照 `value/label`
187
+ 使用表达式 BTREE,多值/JSON 使用 GIN,范围使用 GiST,模糊搜索使用 trigram GIN。
188
+
189
+ 资源 capability 决定能否执行 read/create/update/delete;数据策略决定该角色能操作哪些行;
190
+ 字段策略决定字段可读、可创建和可更新范围。当前用户字段和学院等业务范围都由同一声明生成
191
+ PostgreSQL RLS,列表、详情、聚合、导出、来源查询、审计和事务不能绕过。
192
+
193
+ ## 验证
194
+
195
+ 只检查应用时运行统一入口,随后按实际变化补充真实浏览器验收:
196
+
197
+ ```bash
198
+ pnpm openxiangda check
199
+
200
+ ```
201
+
202
+ 平台维护者负责字段存储、查询运算符、索引和 RLS 的内核回归。应用开发者验证自己声明的字段、角色和业务交互,详见[检查与验收](testing.md)。
203
+
204
+ ## 移动附件和图片
205
+
206
+ 移动附件显示图标、文件名、大小和预览/下载/移除按钮;图片使用缩略图与加号上传格。
207
+ 文件数量和大小限制沿用字段声明。上传失败保留文件并显示完整错误,支持重试;移除上传中的文件后,
208
+ 迟到的结果不会回填表单。关闭编辑器同样使旧上传结果失效,已发出的请求可能继续在
209
+ 服务端完成。移除字段引用不等于删除存储文件。
210
+
211
+ 图片使用作用域内的移动图片预览,支持手势浏览、缩放和关闭;普通文件继续使用平台
212
+ 预览路由。文件值仍为 `DataFileRef[]`,上传与下载继续由原有平台接口鉴权。
213
+
214
+
215
+ ## 移动字段呈现与分组
216
+
217
+ 移动字段自身提供无边框输入、上下标签、行分隔和错误提示;标准表单与自定义页面使用同一
218
+ 字段组件。页面负责把相关字段组织在浅色背景上的白色分组中,不另设移动主题配置。
219
+
220
+ - 单选、复选直接展示选项;下拉单选/复选使用可搜索的底部弹层,多选展示已选数量。
221
+ - 日期使用月历,日期时间可切换时间滚轮;区间依次选择开始和结束,可返回上一步修改。
222
+ - 地址采用地区路径逐层选择,详细地址单独输入。定位沿用当前可用的钉钉或浏览器能力。
223
+ - 子表单直接展开行内字段,支持折叠、添加和删除;父表提交校验所有行,包括折叠的行。
224
+ 权限、最大行数、原子事务和已存行的 revision 继续由原有资源契约约束。
225
+ - 签名在底部画布手写并保存;图片、签名和附件仍通过托管文件接口上传与鉴权读取。
226
+ - 手机富文本编辑降级为多行文本。未修改时保留已有 HTML;修改后将纯文本转为转义后的
227
+ 段落 HTML,继续使用原有 `text.rich` 数据类型。
228
+
229
+ 评分是整数的可选控件,默认五颗星,声明示例:
230
+
231
+ ```ts
232
+ { code: 'score', type: 'number.integer', label: '评分', widget: 'rating', min: 0, max: 5 }
233
+ ```
234
+
235
+ `rating` 需要支持该控件的编译器、前端包与服务端 Surface 校验组合;存储、查询和校验仍为
236
+ 整数。它不会修改已有 `number.integer` 字段的默认数值输入控件。