openxiangda 1.0.38 → 1.0.40

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 (59) hide show
  1. package/README.md +4 -3
  2. package/lib/cli.js +135 -5
  3. package/openxiangda-skills/SKILL.md +8 -5
  4. package/openxiangda-skills/references/best-practices.md +29 -5
  5. package/openxiangda-skills/references/component-guide.md +79 -45
  6. package/openxiangda-skills/references/connector-resources.md +1 -1
  7. package/openxiangda-skills/references/data-views.md +130 -5
  8. package/openxiangda-skills/references/forms/component-registry.md +33 -1
  9. package/openxiangda-skills/references/pages/page-sdk.md +30 -2
  10. package/openxiangda-skills/references/resource-manifest-cheatsheet.md +37 -1
  11. package/openxiangda-skills/skills/openxiangda-core/SKILL.md +2 -2
  12. package/openxiangda-skills/skills/openxiangda-form/SKILL.md +9 -2
  13. package/openxiangda-skills/skills/openxiangda-page/SKILL.md +6 -4
  14. package/package.json +1 -1
  15. package/packages/sdk/dist/runtime/index.cjs +583 -1
  16. package/packages/sdk/dist/runtime/index.cjs.map +1 -1
  17. package/packages/sdk/dist/runtime/index.d.mts +5 -1
  18. package/packages/sdk/dist/runtime/index.d.ts +5 -1
  19. package/packages/sdk/dist/runtime/index.mjs +583 -1
  20. package/packages/sdk/dist/runtime/index.mjs.map +1 -1
  21. package/packages/sdk/src/build-source/scripts/build-forms.mjs +5 -1
  22. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-form.mdc +4 -0
  23. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda-page.mdc +2 -0
  24. package/templates/sy-lowcode-app-workspace/.cursor/rules/openxiangda.mdc +3 -0
  25. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-form.md +4 -0
  26. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda-page.md +2 -0
  27. package/templates/sy-lowcode-app-workspace/.qoder/rules/openxiangda.md +3 -0
  28. package/templates/sy-lowcode-app-workspace/AGENTS.md +5 -0
  29. package/templates/sy-lowcode-app-workspace/examples/best-practices/README.md +8 -0
  30. package/templates/sy-lowcode-app-workspace/examples/best-practices/catalog.json +32 -0
  31. package/templates/sy-lowcode-app-workspace/examples/best-practices/decision-guide.md +20 -0
  32. package/templates/sy-lowcode-app-workspace/examples/best-practices/design-style.md +48 -0
  33. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/App.tsx +8 -0
  34. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/GlassHomeDashboard.tsx +232 -0
  35. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/index.tsx +10 -0
  36. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/page.config.ts +14 -0
  37. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/glass-home-dashboard/styles.css +196 -0
  38. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/App.tsx +8 -0
  39. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/MintAnalyticsDashboard.tsx +279 -0
  40. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/index.tsx +10 -0
  41. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/page.config.ts +14 -0
  42. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mint-analytics-dashboard/styles.css +163 -0
  43. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/App.tsx +8 -0
  44. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/OpsMonitorDashboard.tsx +306 -0
  45. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/index.tsx +10 -0
  46. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/page.config.ts +14 -0
  47. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/ops-monitor-dashboard/styles.css +248 -0
  48. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/App.tsx +8 -0
  49. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/WorkOrderListDrawerPage.tsx +371 -0
  50. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/index.tsx +10 -0
  51. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/page.config.ts +14 -0
  52. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/work-order-list-drawer/styles.css +182 -0
  53. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/DashboardPrimitives.tsx +832 -0
  54. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/chartOptions.ts +140 -0
  55. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/sampleData.ts +466 -0
  56. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/styles.css +874 -0
  57. package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/admin-ui-templates/types.ts +150 -0
  58. package/templates/sy-lowcode-app-workspace/src/forms/README.md +4 -0
  59. package/templates/sy-lowcode-app-workspace/src/main.tsx +4 -0
@@ -1,12 +1,13 @@
1
1
  # Data View Resources
2
2
 
3
- Data views are OpenXiangda-managed read-only PostgreSQL materialized views. They turn repeated multi-form joins into a published resource under `src/resources/data-views/`.
3
+ Data views are OpenXiangda-managed read-only PostgreSQL materialized views. They turn repeated multi-form joins and predefined aggregate statistics into published resources under `src/resources/data-views/`.
4
4
 
5
5
  Use a data view when the app needs read-only joined data from multiple forms, such as:
6
6
 
7
7
  - Ticket list with customer name, owner, SLA, and status fields.
8
8
  - Order list with product, customer, and payment fields.
9
9
  - Project dashboard combining project, member, task, and risk forms.
10
+ - Dashboard statistics such as monthly ticket count, order amount by customer, or task count by status.
10
11
  - Reusable lookup or report data consumed by several pages or automations.
11
12
  - Large list pages where repeated client-side cross-form joins would be slow or inconsistent.
12
13
 
@@ -16,13 +17,18 @@ Do not use a data view for:
16
17
  - Simple one-form dropdown options. Use `SelectField` with `optionSource.type: "linkedForm"`.
17
18
  - Writes or write-back. Data views are read-only.
18
19
  - Strong real-time views after every form update. Data views update after manual or scheduled refresh.
19
- - Raw SQL, incremental refresh, source-table trigger refresh, or group-by aggregation. v1 does not support them.
20
+ - Raw SQL, incremental refresh, source-table trigger refresh, ad-hoc BI/pivot/window analysis, or write-heavy realtime dashboards.
20
21
 
21
22
  ## Authoring
22
23
 
23
24
  Place manifests in `src/resources/data-views/*.json`. Use logical `formCode` values in source files. The CLI resolves them to the current profile's `formUuid` during `resource publish`.
24
25
 
25
- Minimal example:
26
+ Two view types are supported:
27
+
28
+ - `viewType: "row"` or omitted: row-level joined materialized view using `select`.
29
+ - `viewType: "aggregate"`: grouped statistics materialized view using `dimensions` and `measures`; query it with `stats`.
30
+
31
+ Row view example:
26
32
 
27
33
  ```json
28
34
  {
@@ -61,13 +67,67 @@ Minimal example:
61
67
  }
62
68
  ```
63
69
 
70
+ Aggregate statistics example:
71
+
72
+ ```json
73
+ {
74
+ "code": "ticket_stats_by_customer",
75
+ "name": "Ticket Stats By Customer",
76
+ "viewType": "aggregate",
77
+ "base": { "formCode": "service_ticket", "alias": "ticket" },
78
+ "joins": [
79
+ {
80
+ "type": "left",
81
+ "formCode": "customer",
82
+ "alias": "customer",
83
+ "on": [
84
+ {
85
+ "left": "ticket.customer.value",
86
+ "op": "=",
87
+ "right": "customer.form_instance_id"
88
+ }
89
+ ]
90
+ }
91
+ ],
92
+ "dimensions": [
93
+ { "field": "customer.name", "as": "customerName" },
94
+ { "field": "ticket.created_at", "as": "createdMonth", "bucket": "month" }
95
+ ],
96
+ "measures": [
97
+ { "type": "count", "as": "ticketCount" },
98
+ { "type": "sum", "field": "ticket.amount", "as": "totalAmount" },
99
+ { "type": "avg", "field": "ticket.amount", "as": "avgAmount" }
100
+ ],
101
+ "having": { "field": "ticketCount", "op": ">", "value": 0 },
102
+ "indexes": [{ "fields": ["customerName", "createdMonth"] }],
103
+ "refresh": { "mode": "scheduled", "cron": "0 */10 * * * *" },
104
+ "permissionGroups": [
105
+ {
106
+ "code": "ticket_stats_query",
107
+ "name": "Ticket Stats Query",
108
+ "roles": ["manager"],
109
+ "operations": ["query"]
110
+ }
111
+ ]
112
+ }
113
+ ```
114
+
64
115
  Field reference rules:
65
116
 
66
117
  - Use `alias.field`, for example `ticket.title`.
67
118
  - Use system fields directly, such as `form_instance_id`, `created_at`, `updated_at`, `created_by`, and `tenant_id`.
68
119
  - For option-like JSON fields that store `{ label, value }`, use `.value` for joins and `.label` for display when needed.
69
120
  - Every `select` item must have an explicit output alias in `as`.
70
- - Runtime `fields`, `filters`, `order`, indexes, field permissions, and row permissions reference output aliases, not source field references.
121
+ - Aggregate `dimensions` and `measures` also need explicit output aliases in `as`.
122
+ - Runtime `fields`, `filters`, `having`, `order`, indexes, field permissions, and row permissions reference output aliases, not source field references.
123
+
124
+ Aggregate rules:
125
+
126
+ - Measures support `count`, `countDistinct`, `sum`, `avg`, `min`, and `max`.
127
+ - `sum` and `avg` only support `NumberField`.
128
+ - Date buckets support `hour`, `day`, `week`, `month`, `quarter`, and `year`, and only apply to `DateField`, `created_at`, and `updated_at`.
129
+ - `where` filters source rows before grouping; `having` filters aggregate output aliases after grouping.
130
+ - Use aggregate views for stable dashboard/query shapes. They are not an ad-hoc BI query engine.
71
131
 
72
132
  Join rules:
73
133
 
@@ -79,6 +139,7 @@ Filters:
79
139
 
80
140
  - Definition `where` filters source rows before materialization and uses source references such as `ticket.status`.
81
141
  - Runtime query filters use output aliases such as `ticketTitle`.
142
+ - Aggregate definition `having` and runtime stats `having` also use output aliases such as `ticketCount`.
82
143
  - Supported operators include `=`, `!=`, `<>`, `>`, `>=`, `<`, `<=`, `contains`, `notContains`, `in`, `isEmpty`, and `isNotEmpty`, with aliases such as `eq`, `neq`, `gte`, `lte`, `like`, `is_null`, and `is_not_null`.
83
144
 
84
145
  Refresh:
@@ -86,12 +147,45 @@ Refresh:
86
147
  - `manual` means refresh only when an administrator runs refresh or the resource is recreated.
87
148
  - `scheduled` uses cron, for example `0 */10 * * * *`.
88
149
  - Query results may be stale. Show or inspect `lastRefreshedAt` when freshness matters.
150
+ - Do not choose a high-frequency schedule by default. Ask or infer how stale the data may be before setting `scheduled`.
89
151
 
90
152
  Indexes:
91
153
 
92
154
  - Index output aliases that pages filter or sort by.
155
+ - Row views should index stable IDs and common list filters/sort fields.
156
+ - Aggregate views should index dimensions and date buckets used by charts, filters, drill-downs, or ordering.
157
+ - Do not index every output field or every measure; extra indexes make refresh slower.
93
158
  - Use `unique: true` only when the output field combination is truly unique.
94
159
 
160
+ ## Performance And Freshness
161
+
162
+ Data views move expensive joins and aggregations from page runtime to materialized-view refresh time. They reduce repeated page pressure only when the view shape, refresh cadence, and indexes are chosen deliberately.
163
+
164
+ Before creating a data view, confirm these points:
165
+
166
+ - **Freshness tolerance**: ask whether users need near-real-time data, 10-30 minute freshness, hourly/daily reports, or manual snapshots.
167
+ - **Query shape**: list the fields users will filter, sort, group, or drill down by. These should become output aliases and usually indexes.
168
+ - **Data scope**: if the business only needs active, recent, or in-scope records, put that rule in definition `where` so old/source-irrelevant rows are filtered before materialization.
169
+ - **Visible fields**: output only fields the page or permission rules need. Use hidden scope aliases for data permissions when needed, but do not build one huge catch-all view.
170
+
171
+ Refresh cadence guidance:
172
+
173
+ - Use `manual` for admin diagnostics, imported snapshots, low-change reference data, or data that is refreshed after an intentional operation.
174
+ - Use `scheduled` every 10-30 minutes for normal dashboards, joined report lists, and recurring management views.
175
+ - Use hourly or daily schedules for leadership reports, historical statistics, and large aggregate views.
176
+ - Avoid intervals below 5 minutes unless the user explicitly confirms the time sensitivity and expected source-table volume. High-frequency refreshes can pressure both source tables and the materialized view.
177
+ - For strong real-time behavior after each form save, do not use a data view; query the source form directly or design a different backend workflow.
178
+
179
+ Index guidance:
180
+
181
+ - Index only materialized-view output aliases, not source references such as `customer.name`.
182
+ - For row views, index IDs used in drill-down (`ticketId`, `customerId`) and common filters/order fields (`statusValue`, `ownerId`, `createdAt`).
183
+ - For aggregate views, index the dimensions/time buckets used in runtime `filters`, `having` drill-downs, and `order` (`customerId`, `statusValue`, `createdMonth`).
184
+ - Keep compound indexes aligned with common query prefixes. For example, dashboard filters by customer then month should use `["customerId", "createdMonth"]`.
185
+ - `searchKeyWord` across many text columns is inherently heavier than structured filters. Prefer explicit `filters` on indexed aliases.
186
+ - `countDistinct` and high-cardinality dimensions are refresh-heavy. Confirm data volume and avoid very frequent schedules.
187
+ - Show `lastRefreshedAt` on pages or in diagnostics when users may notice refresh delay.
188
+
95
189
  ## Permissions
96
190
 
97
191
  Management APIs require `app:data-view:manage`.
@@ -105,6 +199,7 @@ Permission group behavior:
105
199
  - Missing or empty `fieldPermissions` means all output fields are visible.
106
200
  - When multiple permission groups match, field permissions are most permissive: a field is visible if any matched group allows it.
107
201
  - `dataPermission` is a row condition over output aliases.
202
+ - Hidden output aliases can still be used by `dataPermission`; this is useful for scope keys that should restrict rows but not be returned to pages.
108
203
  - Multiple matched row conditions are ORed.
109
204
  - If any matched group has no row condition, rows are unrestricted.
110
205
 
@@ -127,6 +222,8 @@ openxiangda data-view status ticket_with_customer --profile dev
127
222
  openxiangda data-view refresh ticket_with_customer --profile dev
128
223
  openxiangda data-view query ticket_with_customer --profile dev --fields ticketId,customerName
129
224
  openxiangda data-view query ticket_with_customer --profile dev --query-json query.json
225
+ openxiangda data-view stats ticket_stats_by_customer --profile dev --fields customerName,ticketCount
226
+ openxiangda data-view stats ticket_stats_by_customer --profile dev --query-json stats-query.json
130
227
  ```
131
228
 
132
229
  ## Runtime SDK
@@ -145,6 +242,23 @@ const response = await sdk.dataView.query("ticket_with_customer", {
145
242
  })
146
243
  ```
147
244
 
245
+ Aggregate stats query:
246
+
247
+ ```ts
248
+ const response = await sdk.dataView.stats("ticket_stats_by_customer", {
249
+ fields: ["customerName", "createdMonth", "ticketCount", "totalAmount"],
250
+ filters: [
251
+ { field: "customerName", operator: "contains", value: keyword },
252
+ ],
253
+ having: [
254
+ { field: "ticketCount", operator: ">", value: 0 },
255
+ ],
256
+ order: [{ field: "ticketCount", isAsc: "n" }],
257
+ currentPage: 1,
258
+ pageSize: 20,
259
+ })
260
+ ```
261
+
148
262
  The response data is:
149
263
 
150
264
  ```ts
@@ -170,6 +284,15 @@ export default {
170
284
  defaultFilter: [
171
285
  { field: "ticketTitle", operator: "isNotEmpty" }
172
286
  ]
287
+ },
288
+ {
289
+ key: "ticketStats",
290
+ type: "dataView.stats",
291
+ code: "ticket_stats_by_customer",
292
+ fields: ["customerName", "ticketCount"],
293
+ defaultHaving: [
294
+ { field: "ticketCount", operator: ">", value: 0 }
295
+ ]
173
296
  }
174
297
  ]
175
298
  }
@@ -193,7 +316,8 @@ List page:
193
316
 
194
317
  Dashboard:
195
318
 
196
- - Use one or more data views as read-optimized sources.
319
+ - Use aggregate data views for stable metrics such as counts, totals, averages, status distribution, and time buckets.
320
+ - Use row data views for drill-down lists behind those metrics.
197
321
  - Keep refresh scheduled.
198
322
  - Show `lastRefreshedAt` when business users care about freshness.
199
323
 
@@ -206,6 +330,7 @@ Reusable lookup:
206
330
  Automation diagnosis:
207
331
 
208
332
  - Query the data view with `openxiangda data-view query --query-json`.
333
+ - Query aggregate views with `openxiangda data-view stats --query-json`.
209
334
  - Refresh manually after bulk imports or test data resets.
210
335
 
211
336
  ## Troubleshooting
@@ -1,6 +1,13 @@
1
1
  # Form Component Registry
2
2
 
3
- Use platform-supported component names in FormSchema.
3
+ Use platform-supported component names in FormSchema. AI-authored app code must prefer these platform fields for form-entry UX; do not replace them with raw `<input>`, `<select>`, `<textarea>`, file inputs, hand-written pickers, or hand-written uploaders in `src/forms/**` or `src/pages/**`.
4
+
5
+ Priority:
6
+
7
+ 1. Use the platform field component in `schema.ts`.
8
+ 2. If the standard form layout is not enough, customize presentation in `page.tsx` while still rendering the OpenXiangda standard form/runtime.
9
+ 3. If a real field component is missing, submit feedback with `openxiangda feedback submit --yes`, then use an `antd` / `antd-mobile` wrapper as a local workaround.
10
+ 4. Native HTML controls are only acceptable inside OpenXiangda SDK/platform component internals.
4
11
 
5
12
  Common field components:
6
13
 
@@ -26,9 +33,34 @@ Common field components:
26
33
  | `JSONField` | Structured JSON |
27
34
  | `SubFormField` | Child table; do not recursively flatten child fields unless the runtime requires it |
28
35
 
36
+ Must-use platform components:
37
+
38
+ | Scenario | Component |
39
+ | --- | --- |
40
+ | User picker | `UserSelectField` |
41
+ | Department picker | `DepartmentSelectField` |
42
+ | File upload | `AttachmentField` |
43
+ | Image upload | `ImageField` |
44
+ | Rich text | `EditorField` |
45
+ | Signature | `DigitalSignatureField` |
46
+ | Location | `LocationField` |
47
+
48
+ Preferred platform components:
49
+
50
+ | Scenario | Component |
51
+ | --- | --- |
52
+ | Text / textarea / number | `TextField` / `TextAreaField` / `NumberField` |
53
+ | Date / date range | `DateField` / `CascadeDateField` |
54
+ | Select / multi-select / radio / checkbox | `SelectField` / `MultiSelectField` / `RadioField` / `CheckboxField` |
55
+ | Cascading select | `CascadeSelectField` |
56
+ | Child rows | `SubFormField` |
57
+ | Standard form rendering | `FormProvider` + `FormRenderer` |
58
+
29
59
  Rules:
30
60
 
31
61
  - Prefer simple field types first.
62
+ - Prefer platform fields over page-level custom JSX controls for all normal data entry.
63
+ - Do not emit raw native controls in AI-authored workspace code. Use an `antd` / `antd-mobile` wrapper only when no platform field can represent the UX, and submit feedback for the platform gap.
32
64
  - Do not use a code page where a normal form can solve the workflow.
33
65
  - Keep option values stable; labels may be user-facing.
34
66
  - Avoid generated random field IDs after initial creation.
@@ -6,7 +6,9 @@ Guidelines:
6
6
 
7
7
  - Do not hardcode `/openxiangda-api` calls inside end-user page components unless the page is explicitly an admin tool.
8
8
  - Prefer SDK modules for form data, user context, permissions, and platform navigation.
9
- - Use `sdk.dataView.query` for published read-only multi-form data views. Data view runtime queries can filter, sort, paginate, and select only output aliases.
9
+ - Use `sdk.dataView.query` for published read-only multi-form row data views. Use `sdk.dataView.stats` for aggregate data views declared with `viewType: "aggregate"`.
10
+ - Data view runtime queries can filter, sort, paginate, and select only output aliases.
11
+ - Keep data view page calls paginated and field-scoped. Runtime filters/order should use aliases that the data view indexes, especially for aggregate dimensions and date buckets.
10
12
  - Use `sdk.dataSource.run()` with a page data source descriptor when the page config should own the data view code, default fields, or default filters.
11
13
  - Use `sdk.connector.invoke`, `sdk.connector.call("connector.api")`, or `sdk.connector.download` for external services. The SDK calls the platform runtime connector endpoint; it must not call third-party domains directly.
12
14
  - Use `sdk.notification.sendByType` and `batchSendByType` for reusable business messages. Custom notification types must be declared in `src/resources/notifications/` and published with `openxiangda resource publish`.
@@ -32,6 +34,23 @@ const response = await sdk.dataView.query("ticket_with_customer", {
32
34
  })
33
35
  ```
34
36
 
37
+ Data view stats:
38
+
39
+ ```ts
40
+ const response = await sdk.dataView.stats("ticket_stats_by_customer", {
41
+ fields: ["customerName", "ticketCount", "totalAmount"],
42
+ filters: [
43
+ { field: "customerName", operator: "contains", value: keyword },
44
+ ],
45
+ having: [
46
+ { field: "ticketCount", operator: ">", value: 0 },
47
+ ],
48
+ order: [{ field: "ticketCount", isAsc: "n" }],
49
+ currentPage: 1,
50
+ pageSize: 20,
51
+ })
52
+ ```
53
+
35
54
  Data view data source descriptor:
36
55
 
37
56
  ```ts
@@ -45,6 +64,15 @@ export default {
45
64
  defaultFilter: [
46
65
  { field: "ticketTitle", operator: "isNotEmpty" }
47
66
  ]
67
+ },
68
+ {
69
+ key: "ticketStats",
70
+ type: "dataView.stats",
71
+ code: "ticket_stats_by_customer",
72
+ fields: ["customerName", "ticketCount"],
73
+ defaultHaving: [
74
+ { field: "ticketCount", operator: ">", value: 0 }
75
+ ]
48
76
  }
49
77
  ]
50
78
  }
@@ -57,7 +85,7 @@ const response = await sdk.dataSource.run("tickets", {
57
85
  })
58
86
  ```
59
87
 
60
- Data view filters and fields use output aliases such as `customerName`, not source references such as `customer.name`. If the page only needs one form, prefer `sdk.form.advancedSearch`. If the page only needs a simple one-form dropdown, prefer linkedForm options.
88
+ Data view filters, having, and fields use output aliases such as `customerName` or `ticketCount`, not source references such as `customer.name`. If the page only needs one form, prefer `sdk.form.advancedSearch`. If the page only needs a simple one-form dropdown, prefer linkedForm options.
61
89
 
62
90
  Logout and current-user role switching:
63
91
 
@@ -61,6 +61,14 @@ const data = await sdk.connector.call("crm.getCustomer", { body: { keyword } });
61
61
 
62
62
  ## 2. Data View — `src/resources/data-views/<code>.json`
63
63
 
64
+ 选择规则:
65
+
66
+ - 多表只读联表列表 / lookup / 报表明细:用行级 data view,页面调用 `sdk.dataView.query`。
67
+ - 固定口径统计 / 看板指标 / 图表数据源:用 `viewType: "aggregate"`,页面调用 `sdk.dataView.stats`。
68
+ - ECharts 或自定义 dashboard 只负责展示;统计口径稳定时,数据源优先沉淀成 aggregate data view。
69
+ - 发布前为常用筛选、排序、维度和时间桶声明 `indexes`,并确认刷新延迟是否能被业务接受。
70
+ - 不用于单表 CRUD、简单 `linkedForm` 下拉、强实时、写回或临时 BI 查询。
71
+
64
72
  ```json
65
73
  {
66
74
  "code": "ticket_with_customer",
@@ -101,7 +109,35 @@ const list = await sdk.dataView.query("ticket_with_customer", {
101
109
  });
102
110
  ```
103
111
 
104
- 适用:跨表只读联表 / 报表 / 大列表性能优化。**不适用**:单表 CRUD、`linkedForm` 下拉、强实时、写回。完整规则见 [`data-views.md`](data-views.md)。
112
+ 统计聚合视图:
113
+
114
+ ```json
115
+ {
116
+ "code": "ticket_stats_by_customer",
117
+ "name": "Ticket Stats By Customer",
118
+ "viewType": "aggregate",
119
+ "base": { "formCode": "service_ticket", "alias": "ticket" },
120
+ "dimensions": [
121
+ { "field": "ticket.customer.value", "as": "customerId" },
122
+ { "field": "ticket.created_at", "as": "createdMonth", "bucket": "month" }
123
+ ],
124
+ "measures": [
125
+ { "type": "count", "as": "ticketCount" },
126
+ { "type": "sum", "field": "ticket.amount", "as": "totalAmount" }
127
+ ],
128
+ "having": { "field": "ticketCount", "op": ">", "value": 0 },
129
+ "indexes": [{ "fields": ["customerId", "createdMonth"] }]
130
+ }
131
+ ```
132
+
133
+ ```ts
134
+ const stats = await sdk.dataView.stats("ticket_stats_by_customer", {
135
+ fields: ["customerId", "createdMonth", "ticketCount", "totalAmount"],
136
+ having: [{ field: "ticketCount", op: ">", value: 0 }],
137
+ });
138
+ ```
139
+
140
+ 性能要点:索引只能引用输出 alias;行级视图索引常用 filter/order 字段;聚合视图索引 dimensions/date buckets;`countDistinct` 和高基数维度刷新成本较高;低于 5 分钟的 scheduled refresh 需要用户明确确认时间敏感度。完整规则见 [`data-views.md`](data-views.md)。
105
141
 
106
142
  ## 3. Notification — `src/resources/notifications/<code>.json`
107
143
 
@@ -62,14 +62,14 @@ OPENXIANGDA_FEEDBACK_DINGTALK_WEBHOOK=https://oapi.dingtalk.com/robot/send?acces
62
62
  OPENXIANGDA_FEEDBACK_DINGTALK_SECRET=SEC...
63
63
  ```
64
64
 
65
- When a user confirms that a suspected platform defect, bug, or optimization request should be reported, run:
65
+ When a platform defect, missing capability, unclear design rule, repeated workaround, AI uncertainty, user-visible UX gap, bug, or optimization request appears during development, proactively report it:
66
66
 
67
67
  ```bash
68
68
  openxiangda feedback preview --profile <name> --summary "问题摘要" --description "..." --command "..." --log-file <file>
69
69
  openxiangda feedback submit --profile <name> --summary "问题摘要" --description "..." --command "..." --log-file <file> --yes
70
70
  ```
71
71
 
72
- Feedback includes the logged-in profile user name when available and detailed workspace/platform context. The CLI redacts tokens, cookies, secrets, phone numbers, and emails before sending.
72
+ Prefer `feedback submit --yes` directly when the report is clear. Use `feedback preview` when robot env is missing, submission fails, or you need to capture a sanitized payload for the user. Feedback includes the logged-in profile user name when available and detailed workspace/platform context. The CLI redacts tokens, cookies, secrets, phone numbers, and emails before sending. After submission, tell the user what was reported and include the fingerprint.
73
73
 
74
74
  ## Private Routing
75
75
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: openxiangda-form
3
- description: Create / edit / publish OpenXiangda normal forms and workflow forms in `sy-lowcode-app-workspace` — schema, fields, options, validation rules, layout, linkedForm select sources, hidden permission scope keys, top-level FormEffect, workflow form bundles, single-form publish. Trigger on 创建表单 / 新建表单 / 表单字段 / 修改 schema / form field / placeholder / options / SelectField / linkedForm / FormEffect / workflow form / 审批表单页 / form schema / formCode / src/forms, or any change to `src/forms/<code>/{schema.ts,page.tsx}`.
3
+ description: Create / edit / publish OpenXiangda normal forms and workflow forms in `sy-lowcode-app-workspace` — schema, fields, options, validation rules, layout, linkedForm select sources, hidden permission scope keys, top-level FormEffect, workflow form bundles, single-form publish, and high-quality form-entry UX. Use OpenXiangda platform form components first, Ant Design / antd-mobile wrappers second, and never raw native HTML form controls in AI-authored app code. Trigger on 创建表单 / 新建表单 / 表单字段 / 表单录入 / 修改 schema / form field / placeholder / options / SelectField / linkedForm / FormEffect / workflow form / 审批表单页 / form schema / formCode / src/forms, or any change to `src/forms/<code>/{schema.ts,page.tsx}`.
4
4
  ---
5
5
 
6
6
  # OpenXiangda Form
@@ -35,12 +35,15 @@ openxiangda workspace publish --profile <name> --form <formCode>
35
35
  - ✅ Use `SelectField` / `RadioField` for enums; for cross-form sources use `SelectField` with `optionSource.type: "linkedForm"` (and `remoteSearch: true` + `searchFieldId` when source is large).
36
36
  - ✅ Permission scope keys / sync keys / derived fields stay in schema with `behavior: "HIDDEN"`, derived from visible select/person/department fields via `valueSync`.
37
37
  - ✅ Always provide `options` for option components (Select / MultiSelect / Radio / Checkbox / CascadeSelect).
38
+ - ✅ `schema.ts` is the source of data fields and platform field components; `page.tsx` is presentation only and should render through the OpenXiangda standard form/runtime.
39
+ - ✅ If a custom layout or widget is truly needed, wrap OpenXiangda platform components first. If no platform component exists, wrap `antd` / `antd-mobile` and preserve their props, refs, keyboard behavior, and overlay handling.
38
40
  - ❌ `AssociationFormField` for new form work (use `linkedForm` SelectField).
39
41
  - ❌ Top-level `schema.rules` as validation array. Top-level `rules` is `FormEffect[]` only (`when` / `then`).
40
42
  - ❌ Extra fields for system metadata (creator / updater / created/updated time / depts) — platform creates them automatically.
41
43
  - ❌ Developer notes / implementation comments inside labels / placeholders / tips / section titles / empty states.
42
44
  - ❌ `openxiangda form create` as page generation; it is a low-level repair command.
43
45
  - ❌ Copy `formUuid` from dev to prod — each profile has its own `formUuid` under `.openxiangda/state.json`.
46
+ - ❌ Raw native form controls in app/workspace source: `<input>`, `<select>`, `<textarea>`, `<input type="file">`, hand-written pickers, hand-written uploaders, and custom employee/department selectors. These belong only inside OpenXiangda SDK/platform component internals.
44
47
 
45
48
  ## Required Workspace Flow
46
49
 
@@ -103,7 +106,7 @@ Read these references only when writing or reviewing schema:
103
106
  - `../../references/forms/component-registry.md`
104
107
  - `../../references/forms/layout-and-rules.md`
105
108
  - `../../references/platform-data-model.md` — how each field type is persisted (JSONB, `{label, value}` for option fields, attachment shape). Consult before designing schema or wiring values.
106
- - `../../references/component-guide.md` — when to pick platform form components vs. custom widgets, and the option-component rules.
109
+ - `../../references/component-guide.md` — platform component first, `antd` / `antd-mobile` fallback, and native-control ban for AI-authored app code.
107
110
  - `../../references/best-practices.md` — status lifecycle fields, ownership redundancy, role-governance fields, and the boundary between normal forms and workflow forms.
108
111
 
109
112
  ## Rules
@@ -122,8 +125,12 @@ Read these references only when writing or reviewing schema:
122
125
  - Do not copy `formUuid` from dev to prod unless the target platform explicitly already uses that ID.
123
126
  - Keep `schema.ts` and `page.tsx` as the source for fields/layout/rules and presentation; generated build output is not the source of truth.
124
127
  - In `schema.ts`, import `defineFormSchema` from `openxiangda` and default-export the schema.
128
+ - Treat `schema.ts` as the field/component contract. Prefer platform field components listed in `../../references/forms/component-registry.md`; do not replace them with raw JSX controls in `page.tsx`.
129
+ - Keep `page.tsx` presentation-only. It may customize layout, wrappers, sections, or routing, but should render a complete OpenXiangda standard form/runtime rather than assembling isolated raw controls.
130
+ - If a platform field is missing for a real business need, submit feedback with `openxiangda feedback submit --yes` and then use an `antd` / `antd-mobile` wrapper as a local workaround. Report the workaround and fingerprint to the user.
125
131
  - Put validation on field-level `rules`; never generate old top-level validation arrays under `schema.rules`. Top-level `rules` is only for `FormEffect[]` with `when` and `then`.
126
132
  - Always provide `options` for option components. `SelectField`, `MultiSelectField`, `RadioField`, `CheckboxField`, and `CascadeSelectField` must not be emitted with `options` undefined. See `../../references/component-guide.md` for the full list and `../../references/platform-data-model.md` for the `{label, value}` storage contract.
133
+ - Do not emit raw native form controls in app/workspace source. For basic entry use `TextField`, `TextAreaField`, `NumberField`, `DateField`, `SelectField`, `RadioField`, etc.; for platform-specific entry use `UserSelectField`, `DepartmentSelectField`, `AttachmentField`, `ImageField`, `EditorField`, `DigitalSignatureField`, and `LocationField`.
127
134
  - Workflow form pages use the same workspace form structure plus workflow v3 configuration; publish the form page bundle through workspace publish before treating it as complete.
128
135
  - After editing one form, use `workspace publish --form <formCode>` or preview `--changed --dry-run`; do not run full workspace publish by default.
129
136
  - Use `openxiangda form pull` or app snapshot before overwriting an existing form.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: openxiangda-page
3
- description: Build / edit / publish OpenXiangda custom code pages in `sy-lowcode-app-workspace/src/pages/<pageCode>/` using React + Ant Design + `openxiangda/runtime`. Covers app-shell portals, dashboards, workbenches, data-management lists, mobile portals, page-level connector calls, and single-page publish. Trigger on 创建页面 / 新建页面 / 修改页面 / portal / dashboard / 看板 / 驾驶舱 / 工作台 / 列表页 / mobile portal / app-shell / page.config.ts / pageCode / src/pages, JSX / React / Ant Design page work in this workspace, or any change to `src/pages/<code>/`.
3
+ description: Build / edit / publish OpenXiangda custom code pages in `sy-lowcode-app-workspace/src/pages/<pageCode>/` using React + Ant Design + `openxiangda/runtime`. Covers app-shell portals, dashboards, workbenches, data-management lists, mobile portals, page-level connector calls, filters/search forms, and single-page publish. For platform data entry use OpenXiangda components first, Ant Design / antd-mobile wrappers second, and no raw native HTML form controls in AI-authored page code. Trigger on 创建页面 / 新建页面 / 修改页面 / portal / dashboard / 看板 / 驾驶舱 / 工作台 / 列表页 / mobile portal / app-shell / page.config.ts / pageCode / src/pages, JSX / React / Ant Design page work in this workspace, or any change to `src/pages/<code>/`.
4
4
  ---
5
5
 
6
6
  # OpenXiangda Page
@@ -33,10 +33,12 @@ openxiangda workspace publish --profile <name> --page <pageCode>
33
33
  - ✅ Default to **native Tailwind utilities** for new pages (`bg-white`, `border-slate-200`, `grid-cols-[240px_1fr]`, ...) and `cssIsolation: "none"`. Keep namespace/shadow only for explicit legacy compatibility.
34
34
  - ✅ Split complex pages into `domain/`, `shared/services/`, `shared/hooks/`, `components/`, route/config files, `styles.css` (see `references/best-practices.md` and `references/architecture-patterns.md`).
35
35
  - ✅ List/detail/CRUD pages: follow `DataManagementList` pattern from `references/architecture-patterns.md`. Pagination + structured `filterGroup` + `OR`. Never fetch huge `pageSize` and filter in browser.
36
- - ✅ For external APIs use `src/resources/connectors/<code>.json` + `sdk.connector.invoke()`; for joined read-only queries use `src/resources/data-views/<code>.json`.
36
+ - ✅ For external APIs use `src/resources/connectors/<code>.json` + `sdk.connector.invoke()`; for joined read-only lists use row data views + `sdk.dataView.query`; for stable dashboard metrics use aggregate data views + `sdk.dataView.stats`.
37
+ - ✅ Filters, search bars, modal forms, drawers, and inline edits use platform components for platform data fields, otherwise `antd` / `antd-mobile` controls.
37
38
  - ❌ Single-file giant pages. Split per `references/best-practices.md`.
38
39
  - ❌ Hardcoded `/view/...&isRenderNav=false` URLs scattered through page code; use the runtime navigation helper.
39
40
  - ❌ shadcn token classes like `bg-card` / `text-muted-foreground` / `text-foreground` unless explicitly configured.
41
+ - ❌ Raw native form controls in AI-authored page code (`<input>`, `<select>`, `<textarea>`, file inputs, hand-written pickers/uploaders). Use platform components or `antd` / `antd-mobile`.
40
42
  - ❌ Embed a single `FormProvider` field component temporarily; navigate to a full standard form page or render a complete `StandardFormPage` instead.
41
43
  - ❌ Reuse one form UI for both PC and mobile without verifying overlay / picker / bottom-sheet behavior on both viewports.
42
44
  - ❌ Hardcode notification or platform API URLs; use `openxiangda/runtime` and `src/resources/notifications/` declarations.
@@ -96,7 +98,7 @@ Read these references only when editing page code:
96
98
  - `../../references/pages/publish-flow.md`
97
99
  - `../../references/style-system.md` — style isolation defaults, Tailwind/CSS guidance, and legacy namespace compatibility. Read before writing substantial page CSS or Tailwind classes.
98
100
  - `../../references/architecture-patterns.md` — CRUD data flow, `DataManagementList` pattern, and recommended `src/pages/<pageCode>/` layout. Read before scaffolding a new page or list view.
99
- - `../../references/component-guide.md` — when to pick platform components, raw Ant Design, or custom components. Read before introducing a new component.
101
+ - `../../references/component-guide.md` — platform component first, `antd` / `antd-mobile` fallback, and native-control ban for AI-authored app code. Read before introducing a new component.
100
102
  - `../../references/troubleshooting.md` — known failure modes (missing styles, `options` runtime errors, broken option rendering, etc.) and their fixes. Read when something does not behave as expected.
101
103
 
102
104
  ## Rules
@@ -120,7 +122,7 @@ Read these references only when editing page code:
120
122
  - Follow the style system in `../../references/style-system.md`: default to native Tailwind utilities and arbitrary values for business pages (`bg-white`, `border`, `border-slate-200`, `text-slate-600`, `grid-cols-[240px_1fr]`, etc.). New pages default to `cssIsolation: "none"` and do not need `.sy-app-workspace`; keep namespace/shadow handling only for legacy pages that explicitly configure it. Do not treat platform token classes as the default authoring pattern, and do not use shadcn token classes such as `bg-card`, `text-muted-foreground`, or `text-foreground` unless the workspace explicitly configures them.
121
123
  - For list / detail / CRUD pages, follow `../../references/architecture-patterns.md` (e.g. `DataManagementList`) before writing custom data-fetching loops.
122
124
  - Query pages must use pagination with structured conditions. Do not fetch a large `pageSize` and filter in the browser; avoid default `searchKeyWord`, and build multi-field fuzzy search with explicit `filterGroup` + `OR`.
123
- - Pick components per `../../references/component-guide.md`: prefer the platform component, fall back to Ant Design, and only build a custom component when neither fits.
125
+ - Pick components per `../../references/component-guide.md`: prefer the platform component, fall back to Ant Design / antd-mobile wrappers, and only build a custom component when neither fits. In app/workspace page code, do not emit raw `<input>`, `<select>`, `<textarea>`, file inputs, hand-written pickers, or hand-written uploaders.
124
126
  - When a page misbehaves (lost styles, `options is undefined`, option labels showing raw values, etc.), consult `../../references/troubleshooting.md` before patching symptoms.
125
127
  - For custom portal pages and business modals, do not temporarily embed a single `FormProvider` field component from the standard form runtime. If a standard component is required, navigate to a full standard form page or render a complete `StandardFormPage` inside a dedicated carrier route.
126
128
  - Keep PC and mobile portal styles separate. Do not share one form UI implementation across both viewports unless the surrounding shell, modal layer, date picker, and bottom-sheet behavior have been tested in both contexts.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.38",
3
+ "version": "1.0.40",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {