@object-ui/plugin-aggrid 0.4.1 → 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 (46) hide show
  1. package/.turbo/turbo-build.log +99 -0
  2. package/CHANGELOG.md +16 -0
  3. package/OBJECT_AGGRID_CN.md +483 -0
  4. package/QUICKSTART.md +186 -0
  5. package/README.md +221 -1
  6. package/dist/AddressField-Bntpynvd.js +95 -0
  7. package/dist/AgGridImpl-3Mmf2qrR.js +229 -0
  8. package/dist/AutoNumberField-C1kBJaxh.js +8 -0
  9. package/dist/FileField-BDwbJvor.js +101 -0
  10. package/dist/FormulaField-BXNiyGoh.js +9 -0
  11. package/dist/GeolocationField-Df3yYcM9.js +141 -0
  12. package/dist/GridField-CcjQp4WM.js +29 -0
  13. package/dist/LocationField-BIfN5QIq.js +33 -0
  14. package/dist/MasterDetailField-CAEmxbIT.js +117 -0
  15. package/dist/ObjectAgGridImpl-EjifM4aY.js +28727 -0
  16. package/dist/ObjectField-BpkQpIF-.js +51 -0
  17. package/dist/QRCodeField-VCBewTDG.js +96 -0
  18. package/dist/RichTextField-CyQwSi2C.js +37 -0
  19. package/dist/SignatureField-Cr4tsEbj.js +96 -0
  20. package/dist/SummaryField-CnEJ_GZI.js +9 -0
  21. package/dist/UserField-DJjaVyrV.js +49 -0
  22. package/dist/VectorField-cPYmcKnV.js +25 -0
  23. package/dist/{index-B6NPAFZx.js → index-B87wd1E0.js} +301 -143
  24. package/dist/index.css +1 -1
  25. package/dist/index.js +4 -3
  26. package/dist/index.umd.cjs +225 -2
  27. package/dist/src/AgGridImpl.d.ts +5 -2
  28. package/dist/src/ObjectAgGridImpl.d.ts +6 -0
  29. package/dist/src/VirtualScrolling.d.ts +72 -0
  30. package/dist/src/field-renderers.d.ts +67 -0
  31. package/dist/src/index.d.ts +47 -2
  32. package/dist/src/object-aggrid.types.d.ts +74 -0
  33. package/dist/src/types.d.ts +48 -1
  34. package/package.json +11 -9
  35. package/src/AgGridImpl.tsx +100 -11
  36. package/src/ObjectAgGridImpl.tsx +501 -0
  37. package/src/VirtualScrolling.ts +74 -0
  38. package/src/field-renderers.test.tsx +383 -0
  39. package/src/field-renderers.tsx +224 -0
  40. package/src/index.test.ts +1 -1
  41. package/src/index.tsx +211 -2
  42. package/src/object-aggrid.test.ts +99 -0
  43. package/src/object-aggrid.types.ts +123 -0
  44. package/src/types.ts +57 -1
  45. package/vite.config.ts +13 -0
  46. package/dist/AgGridImpl-DKkq6v1B.js +0 -171
@@ -0,0 +1,99 @@
1
+
2
+ > @object-ui/plugin-aggrid@2.0.0 build /home/runner/work/objectui/objectui/packages/plugin-aggrid
3
+ > vite build
4
+
5
+ vite v7.3.1 building client environment for production...
6
+ transforming...
7
+ ✓ 1749 modules transformed.
8
+ rendering chunks...
9
+ [plugin vite:reporter]
10
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/TextField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
11
+ 
12
+ [plugin vite:reporter]
13
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/NumberField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
14
+ 
15
+ [plugin vite:reporter]
16
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/BooleanField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
17
+ 
18
+ [plugin vite:reporter]
19
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/SelectField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
20
+ 
21
+ [plugin vite:reporter]
22
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/DateField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
23
+ 
24
+ [plugin vite:reporter]
25
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/EmailField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
26
+ 
27
+ [plugin vite:reporter]
28
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/PhoneField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
29
+ 
30
+ [plugin vite:reporter]
31
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/UrlField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
32
+ 
33
+ [plugin vite:reporter]
34
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/CurrencyField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
35
+ 
36
+ [plugin vite:reporter]
37
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/TextAreaField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
38
+ 
39
+ [plugin vite:reporter]
40
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/LookupField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
41
+ 
42
+ [plugin vite:reporter]
43
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/DateTimeField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
44
+ 
45
+ [plugin vite:reporter]
46
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/TimeField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
47
+ 
48
+ [plugin vite:reporter]
49
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/PercentField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
50
+ 
51
+ [plugin vite:reporter]
52
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/PasswordField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
53
+ 
54
+ [plugin vite:reporter]
55
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/ImageField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
56
+ 
57
+ [plugin vite:reporter]
58
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/ColorField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
59
+ 
60
+ [plugin vite:reporter]
61
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/SliderField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
62
+ 
63
+ [plugin vite:reporter]
64
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/RatingField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
65
+ 
66
+ [plugin vite:reporter]
67
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/CodeField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
68
+ 
69
+ [plugin vite:reporter]
70
+ (!) /home/runner/work/objectui/objectui/packages/fields/src/widgets/AvatarField.tsx is dynamically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx but also statically imported by /home/runner/work/objectui/objectui/packages/fields/src/index.tsx, dynamic import will not move module into another chunk.
71
+ 
72
+ 
73
+ [vite:dts] Start generate declaration files...
74
+ computing gzip size...
75
+ [vite:dts] Declaration files built in 14443ms.
76
+ 
77
+ dist/index.css 318.68 kB │ gzip: 61.72 kB
78
+ dist/index.js  0.22 kB │ gzip: 0.16 kB
79
+ dist/AutoNumberField-C1kBJaxh.js  0.29 kB │ gzip: 0.25 kB
80
+ dist/SummaryField-CnEJ_GZI.js  0.49 kB │ gzip: 0.36 kB
81
+ dist/FormulaField-BXNiyGoh.js  0.53 kB │ gzip: 0.37 kB
82
+ dist/VectorField-cPYmcKnV.js  0.81 kB │ gzip: 0.43 kB
83
+ dist/LocationField-BIfN5QIq.js  0.95 kB │ gzip: 0.53 kB
84
+ dist/RichTextField-CyQwSi2C.js  1.19 kB │ gzip: 0.58 kB
85
+ dist/ObjectField-BpkQpIF-.js  1.65 kB │ gzip: 0.76 kB
86
+ dist/GridField-CcjQp4WM.js  1.75 kB │ gzip: 0.67 kB
87
+ dist/UserField-DJjaVyrV.js  2.50 kB │ gzip: 0.93 kB
88
+ dist/AddressField-Bntpynvd.js  3.12 kB │ gzip: 0.75 kB
89
+ dist/SignatureField-Cr4tsEbj.js  3.40 kB │ gzip: 1.28 kB
90
+ dist/QRCodeField-VCBewTDG.js  3.46 kB │ gzip: 1.24 kB
91
+ dist/FileField-BDwbJvor.js  3.59 kB │ gzip: 1.34 kB
92
+ dist/MasterDetailField-CAEmxbIT.js  3.96 kB │ gzip: 1.17 kB
93
+ dist/GeolocationField-Df3yYcM9.js  4.57 kB │ gzip: 1.51 kB
94
+ dist/AgGridImpl-3Mmf2qrR.js  7.21 kB │ gzip: 2.37 kB
95
+ dist/index-B87wd1E0.js  20.43 kB │ gzip: 5.11 kB
96
+ dist/ObjectAgGridImpl-EjifM4aY.js 941.84 kB │ gzip: 207.85 kB
97
+ dist/index.css 318.68 kB │ gzip: 61.72 kB
98
+ dist/index.umd.cjs 612.26 kB │ gzip: 182.92 kB
99
+ ✓ built in 24.22s
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @object-ui/plugin-aggrid
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - b859617: Release v1.0.0 — unify all package versions to 1.0.0
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [b859617]
12
+ - @object-ui/types@2.0.0
13
+ - @object-ui/core@2.0.0
14
+ - @object-ui/react@2.0.0
15
+ - @object-ui/components@2.0.0
16
+ - @object-ui/fields@2.0.0
17
+ - @object-ui/data-objectstack@2.0.0
18
+
3
19
  ## 0.4.1
4
20
 
5
21
  ### Patch Changes
@@ -0,0 +1,483 @@
1
+ # ObjectAgGrid - 元数据驱动的数据网格
2
+
3
+ ObjectAgGrid 是基于 AG Grid 的元数据驱动数据网格组件,通过 `@objectstack/client` 自动获取对象元数据和数据,支持所有字段类型的自动渲染和格式化。
4
+
5
+ ## 主要特性
6
+
7
+ - ✅ **自动元数据获取**:从 ObjectStack 后端自动获取对象架构
8
+ - ✅ **自动数据加载**:支持分页、过滤和排序的数据获取
9
+ - ✅ **全字段类型支持**:支持所有 ObjectUI 字段类型,包括基础类型、高级类型和复杂类型
10
+ - ✅ **零列配置**:根据元数据自动生成列定义
11
+ - ✅ **内联编辑**:支持单元格编辑并自动保存到后端
12
+ - ✅ **选择性显示**:可选择只显示特定字段
13
+ - ✅ **CSV导出**:内置数据导出功能
14
+ - ✅ **完全类型安全**:TypeScript 类型定义完整
15
+
16
+ ## 安装
17
+
18
+ ```bash
19
+ pnpm add @object-ui/plugin-aggrid @object-ui/data-objectstack ag-grid-community ag-grid-react
20
+ ```
21
+
22
+ ## 基础用法
23
+
24
+ ### 1. 创建数据源
25
+
26
+ ```typescript
27
+ import { ObjectStackAdapter } from '@object-ui/data-objectstack';
28
+
29
+ const dataSource = new ObjectStackAdapter({
30
+ baseUrl: 'https://api.example.com',
31
+ token: 'your-api-token'
32
+ });
33
+ ```
34
+
35
+ ### 2. 使用 ObjectAgGrid
36
+
37
+ ```typescript
38
+ import '@object-ui/plugin-aggrid';
39
+
40
+ const schema = {
41
+ type: 'object-aggrid',
42
+ objectName: 'contacts', // 要获取的对象名称
43
+ dataSource: dataSource, // ObjectStack 数据源
44
+ pagination: true,
45
+ pageSize: 20,
46
+ theme: 'quartz',
47
+ height: 600
48
+ };
49
+
50
+ // 在 SchemaRenderer 中使用
51
+ <SchemaRenderer schema={schema} />
52
+ ```
53
+
54
+ ## 支持的字段类型
55
+
56
+ ObjectAgGrid 自动为所有字段类型应用适当的格式化器和单元格渲染器:
57
+
58
+ ### 基础类型
59
+ - **text, textarea, markdown, html**: 普通文本显示
60
+ - **number**: 数字格式化(可选精度)
61
+ - **boolean**: 显示为 ✓ Yes / ✗ No
62
+ - **date**: 本地化日期格式
63
+ - **datetime**: 本地化日期时间格式
64
+ - **time**: 时间显示
65
+
66
+ ### 高级类型
67
+ - **currency**: 货币格式化(例如:$1,234.56)
68
+ ```typescript
69
+ { type: 'currency', currency: 'USD', precision: 2 }
70
+ // 渲染为: $1,234.56
71
+ ```
72
+
73
+ - **percent**: 百分比格式化(例如:45.5%)
74
+ ```typescript
75
+ { type: 'percent', precision: 1 }
76
+ // 渲染为: 45.5%
77
+ ```
78
+
79
+ - **email**: 可点击的邮件链接
80
+ ```typescript
81
+ { type: 'email' }
82
+ // 渲染为: <a href="mailto:user@example.com">user@example.com</a>
83
+ ```
84
+
85
+ - **phone**: 可点击的电话链接
86
+ ```typescript
87
+ { type: 'phone' }
88
+ // 渲染为: <a href="tel:+1-555-0101">+1-555-0101</a>
89
+ ```
90
+
91
+ - **url**: 可点击的网址链接
92
+ ```typescript
93
+ { type: 'url' }
94
+ // 渲染为: <a href="https://example.com" target="_blank">https://example.com</a>
95
+ ```
96
+
97
+ ### 选择和查找类型
98
+ - **select**: 显示选项标签
99
+ ```typescript
100
+ {
101
+ type: 'select',
102
+ options: [
103
+ { label: '激活', value: 'active' },
104
+ { label: '停用', value: 'inactive' }
105
+ ]
106
+ }
107
+ ```
108
+
109
+ - **lookup, master_detail**: 显示关联对象的名称或标签
110
+ ```typescript
111
+ { type: 'lookup', reference_to: 'accounts' }
112
+ ```
113
+
114
+ ### 可视化类型
115
+ - **color**: 带颜色色块的显示
116
+ ```typescript
117
+ { type: 'color' }
118
+ // 渲染为: [色块] #FF5733
119
+ ```
120
+
121
+ - **rating**: 星级评分
122
+ ```typescript
123
+ { type: 'rating', max: 5 }
124
+ // 渲染为: ⭐⭐⭐⭐⭐
125
+ ```
126
+
127
+ - **image**: 缩略图显示
128
+ ```typescript
129
+ { type: 'image' }
130
+ // 渲染为 40x40px 图片
131
+ ```
132
+
133
+ - **avatar**: 圆形头像
134
+ ```typescript
135
+ { type: 'avatar' }
136
+ // 渲染为 32x32px 圆形头像
137
+ ```
138
+
139
+ ### 高级字段类型
140
+ - **formula**: 只读计算字段
141
+ - **summary**: 汇总/汇总字段
142
+ - **auto_number**: 自动编号字段
143
+ - **user, owner**: 用户字段
144
+ - **file**: 文件字段
145
+
146
+ ## Schema API
147
+
148
+ ```typescript
149
+ interface ObjectAgGridSchema {
150
+ // 必需
151
+ type: 'object-aggrid';
152
+ objectName: string; // 对象名称
153
+ dataSource: DataSource; // ObjectStack 数据源实例
154
+
155
+ // 可选字段配置
156
+ fieldNames?: string[]; // 只显示这些字段(默认:全部)
157
+ fields?: FieldMetadata[]; // 覆盖字段元数据
158
+
159
+ // 查询参数
160
+ filters?: Record<string, any>; // 查询过滤器
161
+ sort?: Record<string, 'asc' | 'desc'>; // 排序
162
+ pageSize?: number; // 每页行数(默认:10)
163
+
164
+ // 显示选项(与 aggrid 相同)
165
+ pagination?: boolean; // 启用分页(默认:true)
166
+ theme?: string; // 网格主题(默认:'quartz')
167
+ height?: number | string; // 网格高度(默认:500)
168
+
169
+ // 编辑
170
+ editable?: boolean; // 启用内联编辑(自动保存到后端)
171
+
172
+ // 导出、状态栏、回调等(与 aggrid 相同)
173
+ exportConfig?: ExportConfig;
174
+ statusBar?: StatusBarConfig;
175
+ columnConfig?: ColumnConfig;
176
+ callbacks?: {
177
+ onDataLoaded?: (data: any[]) => void;
178
+ onDataError?: (error: Error) => void;
179
+ // ... 其他 aggrid 回调
180
+ };
181
+ }
182
+ ```
183
+
184
+ ## 使用示例
185
+
186
+ ### 基础示例
187
+
188
+ ```typescript
189
+ const schema = {
190
+ type: 'object-aggrid',
191
+ objectName: 'users',
192
+ dataSource: myDataSource,
193
+ pagination: true,
194
+ pageSize: 25
195
+ };
196
+ ```
197
+
198
+ ### 字段选择
199
+
200
+ 只显示特定字段:
201
+
202
+ ```typescript
203
+ const schema = {
204
+ type: 'object-aggrid',
205
+ objectName: 'contacts',
206
+ dataSource: myDataSource,
207
+ fieldNames: ['name', 'email', 'phone', 'company'],
208
+ pagination: true
209
+ };
210
+ ```
211
+
212
+ ### 过滤和排序
213
+
214
+ ```typescript
215
+ const schema = {
216
+ type: 'object-aggrid',
217
+ objectName: 'products',
218
+ dataSource: myDataSource,
219
+ filters: {
220
+ category: 'Electronics',
221
+ price: { $lt: 1000 }
222
+ },
223
+ sort: {
224
+ price: 'asc'
225
+ },
226
+ pagination: true
227
+ };
228
+ ```
229
+
230
+ ### 可编辑网格(自动保存)
231
+
232
+ ```typescript
233
+ const schema = {
234
+ type: 'object-aggrid',
235
+ objectName: 'tasks',
236
+ dataSource: myDataSource,
237
+ editable: true, // 启用编辑
238
+ singleClickEdit: true, // 单击编辑
239
+ callbacks: {
240
+ onCellValueChanged: (event) => {
241
+ // 更改自动保存到后端
242
+ console.log('已保存:', event.data);
243
+ },
244
+ onDataError: (error) => {
245
+ console.error('数据错误:', error);
246
+ }
247
+ }
248
+ };
249
+ ```
250
+
251
+ ### CSV 导出
252
+
253
+ ```typescript
254
+ const schema = {
255
+ type: 'object-aggrid',
256
+ objectName: 'sales',
257
+ dataSource: myDataSource,
258
+ exportConfig: {
259
+ enabled: true,
260
+ fileName: 'sales-report.csv'
261
+ },
262
+ callbacks: {
263
+ onExport: (data, format) => {
264
+ console.log(`导出 ${data.length} 条记录为 ${format}`);
265
+ }
266
+ }
267
+ };
268
+ ```
269
+
270
+ ### 列配置
271
+
272
+ 全局应用列设置:
273
+
274
+ ```typescript
275
+ const schema = {
276
+ type: 'object-aggrid',
277
+ objectName: 'contacts',
278
+ dataSource: myDataSource,
279
+ columnConfig: {
280
+ resizable: true, // 所有列可调整大小
281
+ sortable: true, // 所有列可排序
282
+ filterable: true // 所有列可过滤
283
+ },
284
+ enableRangeSelection: true // Excel 样式范围选择
285
+ };
286
+ ```
287
+
288
+ ### 状态栏和聚合
289
+
290
+ 在网格底部显示汇总统计:
291
+
292
+ ```typescript
293
+ const schema = {
294
+ type: 'object-aggrid',
295
+ objectName: 'orders',
296
+ dataSource: myDataSource,
297
+ statusBar: {
298
+ enabled: true,
299
+ aggregations: ['count', 'sum', 'avg', 'min', 'max']
300
+ }
301
+ };
302
+ ```
303
+
304
+ ### 多主题支持
305
+
306
+ ```typescript
307
+ // Quartz 主题(默认)
308
+ { type: 'object-aggrid', theme: 'quartz', ... }
309
+
310
+ // Alpine 主题
311
+ { type: 'object-aggrid', theme: 'alpine', ... }
312
+
313
+ // Balham 主题
314
+ { type: 'object-aggrid', theme: 'balham', ... }
315
+
316
+ // Material 主题
317
+ { type: 'object-aggrid', theme: 'material', ... }
318
+ ```
319
+
320
+ ## 完整示例
321
+
322
+ ```typescript
323
+ import { ObjectStackAdapter } from '@object-ui/data-objectstack';
324
+ import { ObjectAgGridRenderer } from '@object-ui/plugin-aggrid';
325
+
326
+ // 创建数据源
327
+ const dataSource = new ObjectStackAdapter({
328
+ baseUrl: process.env.REACT_APP_API_URL,
329
+ token: localStorage.getItem('authToken')
330
+ });
331
+
332
+ // 定义 schema
333
+ const schema = {
334
+ type: 'object-aggrid',
335
+ objectName: 'opportunities',
336
+ dataSource: dataSource,
337
+
338
+ // 只显示关键字段
339
+ fieldNames: [
340
+ 'name',
341
+ 'account',
342
+ 'amount',
343
+ 'probability',
344
+ 'stage',
345
+ 'close_date',
346
+ 'owner'
347
+ ],
348
+
349
+ // 查询参数
350
+ filters: {
351
+ stage: { $in: ['Qualification', 'Proposal', 'Negotiation'] },
352
+ amount: { $gte: 10000 }
353
+ },
354
+ sort: {
355
+ close_date: 'asc'
356
+ },
357
+
358
+ // 显示设置
359
+ pagination: true,
360
+ pageSize: 50,
361
+ theme: 'quartz',
362
+ height: 700,
363
+
364
+ // 功能
365
+ editable: true,
366
+ exportConfig: {
367
+ enabled: true,
368
+ fileName: 'opportunities.csv'
369
+ },
370
+ statusBar: {
371
+ enabled: true,
372
+ aggregations: ['count', 'sum']
373
+ },
374
+ columnConfig: {
375
+ resizable: true,
376
+ sortable: true,
377
+ filterable: true
378
+ },
379
+
380
+ // 回调
381
+ callbacks: {
382
+ onDataLoaded: (data) => {
383
+ console.log(`加载了 ${data.length} 条商机`);
384
+ },
385
+ onCellValueChanged: (event) => {
386
+ console.log('字段更新:', event.colDef.field, event.newValue);
387
+ },
388
+ onDataError: (error) => {
389
+ alert('加载数据失败: ' + error.message);
390
+ }
391
+ }
392
+ };
393
+
394
+ // 渲染组件
395
+ function App() {
396
+ return (
397
+ <div className="container mx-auto p-4">
398
+ <h1 className="text-2xl font-bold mb-4">商机管理</h1>
399
+ <ObjectAgGridRenderer schema={schema} />
400
+ </div>
401
+ );
402
+ }
403
+ ```
404
+
405
+ ## 与标准 AgGrid 的对比
406
+
407
+ | 特性 | AgGrid | ObjectAgGrid |
408
+ |------|--------|--------------|
409
+ | 列定义 | 手动定义 `columnDefs` | 自动从元数据生成 |
410
+ | 数据获取 | 手动传入 `rowData` | 自动从后端获取 |
411
+ | 字段格式化 | 手动配置 formatter | 根据字段类型自动应用 |
412
+ | 编辑保存 | 手动处理 | 自动保存到后端 |
413
+ | 适用场景 | 静态/已知数据结构 | 动态/元数据驱动 |
414
+
415
+ ## 最佳实践
416
+
417
+ 1. **缓存数据源实例**:避免在每次渲染时创建新的 DataSource
418
+ ```typescript
419
+ const dataSource = useMemo(() => new ObjectStackAdapter({...}), []);
420
+ ```
421
+
422
+ 2. **使用 fieldNames 优化性能**:只显示需要的字段
423
+ ```typescript
424
+ fieldNames: ['id', 'name', 'email', 'status']
425
+ ```
426
+
427
+ 3. **合理设置分页大小**:根据数据量调整
428
+ ```typescript
429
+ pageSize: 25 // 适中的默认值
430
+ ```
431
+
432
+ 4. **处理错误**:实现 onDataError 回调
433
+ ```typescript
434
+ callbacks: {
435
+ onDataError: (error) => {
436
+ // 显示友好的错误消息
437
+ toast.error('数据加载失败');
438
+ }
439
+ }
440
+ ```
441
+
442
+ 5. **编辑时的字段验证**:在后端实现验证逻辑
443
+ ```typescript
444
+ editable: true,
445
+ callbacks: {
446
+ onCellValueChanged: async (event) => {
447
+ try {
448
+ // 后端会进行验证
449
+ await dataSource.update(...);
450
+ } catch (error) {
451
+ // 恢复原值
452
+ event.node.setDataValue(event.colDef.field!, event.oldValue);
453
+ }
454
+ }
455
+ }
456
+ ```
457
+
458
+ ## 故障排除
459
+
460
+ ### 数据未加载
461
+ - 检查 `dataSource` 是否正确初始化
462
+ - 验证 `objectName` 是否存在于后端
463
+ - 检查网络请求和 API 响应
464
+
465
+ ### 列未显示
466
+ - 确认对象架构中有字段定义
467
+ - 检查 `fieldNames` 配置是否正确
468
+ - 查看浏览器控制台的错误信息
469
+
470
+ ### 编辑不工作
471
+ - 确保 `editable: true`
472
+ - 检查字段是否标记为 `readonly`
473
+ - 验证后端 update API 是否可用
474
+
475
+ ## 许可证
476
+
477
+ MIT
478
+
479
+ ## 相关资源
480
+
481
+ - [AG Grid 文档](https://www.ag-grid.com/documentation/)
482
+ - [ObjectStack Client 文档](https://docs.objectstack.ai/client)
483
+ - [ObjectUI 类型系统](../types/README.md)