openxiangda 1.0.22 → 1.0.25
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/README.md +28 -10
- package/lib/cli.js +351 -20
- package/lib/workspace-init.js +13 -0
- package/openxiangda-skills/SKILL.md +26 -10
- package/openxiangda-skills/references/architecture-patterns.md +44 -22
- package/openxiangda-skills/references/best-practices.md +180 -0
- package/openxiangda-skills/references/component-guide.md +34 -8
- package/openxiangda-skills/references/pages/publish-flow.md +26 -0
- package/openxiangda-skills/references/pages/workspace-structure.md +5 -3
- package/openxiangda-skills/references/workspace-state.md +6 -0
- package/openxiangda-skills/skills/openxiangda-app/SKILL.md +12 -7
- package/openxiangda-skills/skills/openxiangda-core/SKILL.md +34 -4
- package/openxiangda-skills/skills/openxiangda-form/SKILL.md +13 -1
- package/openxiangda-skills/skills/openxiangda-page/SKILL.md +22 -1
- package/openxiangda-skills/skills/openxiangda-permission-settings/SKILL.md +3 -0
- package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +7 -0
- package/package.json +1 -1
- package/packages/sdk/src/build-source/scripts/publish-all.mjs +44 -5
- package/packages/sdk/src/build-source/scripts/utils/incremental.mjs +95 -0
- package/packages/sdk/src/build-source/scripts/utils/incremental.test.ts +62 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/README.md +32 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/catalog.json +61 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/decision-guide.md +44 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/design-style.md +36 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/module-structure.md +48 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/role-governance/index.ts +2 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/role-governance/permissions.test.ts +35 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/role-governance/permissions.ts +24 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/role-governance/types.ts +17 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/index.ts +4 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/permissions.test.ts +42 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/permissions.ts +23 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/state-machine.test.ts +63 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/state-machine.ts +73 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/ticket-query.test.ts +34 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/ticket-query.ts +73 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/domain/service-ticket/types.ts +64 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/app-role/page.tsx +1 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/app-role/schema.ts +57 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/customer-profile/page.tsx +1 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/customer-profile/schema.ts +83 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/service-ticket/page.tsx +1 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/service-ticket/schema.ts +97 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/ticket-action-log/page.tsx +1 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/forms/ticket-action-log/schema.ts +65 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/js-code-nodes/daily_ticket_digest/index.ts +44 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/js-code-nodes/sync_roles_to_platform/index.ts +33 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/App.tsx +7 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/WorkbenchPage.tsx +36 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/components/ConfigPanel.tsx +34 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/components/PreviewPanel.tsx +17 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/index.tsx +10 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/page.config.ts +9 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/reducer.ts +29 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/interactive-workbench/styles.css +24 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/App.tsx +7 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/MobilePortalShell.tsx +31 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/index.tsx +10 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/modules/MobileHome.tsx +13 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/page.config.ts +14 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/routes.ts +13 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/mobile-portal-shell/styles.css +11 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/App.tsx +7 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/PcPortalShell.tsx +35 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/components/PortalMetric.tsx +11 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/index.tsx +10 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/modules/HomeModule.tsx +25 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/modules/TicketsModule.tsx +14 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/page.config.ts +14 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/routes.ts +19 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/pc-portal-shell/styles.css +35 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/App.tsx +7 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/TicketOpsPage.tsx +105 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/components/TicketActionTimeline.tsx +22 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/components/TicketDetailDrawer.tsx +41 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/components/TicketTableActions.tsx +55 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/index.tsx +10 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/page.config.ts +9 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/pages/service-ticket-ops/styles.css +35 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/automations/daily-ticket-digest/automation.json +25 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/automations/daily-ticket-digest/trigger.json +9 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/notifications/daily-ticket-digest.json +24 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/permissions/form-groups/service-ticket-college.json +21 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/permissions/roles.json +17 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/resources/workflows/expense-approval-workflow.json +48 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/ConfirmAction.tsx +22 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/QueryState.tsx +37 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/components/StatusTag.tsx +20 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/hooks/useTicketOps.ts +96 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/services/role-governance.ts +48 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/src/shared/services/service-ticket.ts +113 -0
- package/templates/sy-lowcode-app-workspace/package.json +2 -0
- package/templates/sy-lowcode-app-workspace/src/dev/App.tsx +11 -1
- package/templates/sy-lowcode-app-workspace/tsconfig.examples.json +24 -0
|
@@ -29,9 +29,10 @@
|
|
|
29
29
|
| 编写 REST API | 平台自动生成数据 API |
|
|
30
30
|
| 维护权限中间件 | 表单字段级权限 + 部门/角色 |
|
|
31
31
|
| 自建文件存储 | `AttachmentField` 直接接入平台存储 |
|
|
32
|
-
|
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
| 业务状态流转 | 表单 + `status` 字段 + 操作日志 + domain/service |
|
|
33
|
+
| 真审批流程 | 表单 + workflow + js-code-nodes |
|
|
34
|
+
|
|
35
|
+
AI Agent 在该平台上写代码时,**不应该考虑数据库、表结构、后端接口**——这些由表单 schema 自动派生。
|
|
35
36
|
|
|
36
37
|
---
|
|
37
38
|
|
|
@@ -144,12 +145,20 @@ export default function InstrumentListPage() {
|
|
|
144
145
|
| 页面类型 | 实现方式 | 适用场景 |
|
|
145
146
|
| --- | --- | --- |
|
|
146
147
|
| 表单录入 / 编辑页 | `src/forms/xxx/` (`schema.ts` + `page.tsx`) | 新增数据、修改数据 |
|
|
147
|
-
| 数据管理页 | `src/pages/xxx/` 使用 `DataManagementList` | 列表、查询、批量操作、导出 |
|
|
148
|
-
|
|
|
149
|
-
|
|
|
150
|
-
|
|
|
151
|
-
|
|
152
|
-
|
|
148
|
+
| 数据管理页 | `src/pages/xxx/` 使用 `DataManagementList` | 列表、查询、批量操作、导出 |
|
|
149
|
+
| 状态流转页 | 普通表单 + 状态字段 + 操作日志 + 代码页 service | 工单、订单、任务等业务状态变化 |
|
|
150
|
+
| 流程表单页 | `src/forms/xxx/` 关联 workflow | 真实审批流程发起、节点处理、审批意见 |
|
|
151
|
+
| 自定义业务页 | `src/pages/xxx/` 自由编码 | 仪表盘、看板、复杂交互、对外门户 |
|
|
152
|
+
| 详情页 | `src/pages/xxx/[id].tsx` 使用 `FormSummaryCard` 等 | 查看单条数据、关联记录 |
|
|
153
|
+
|
|
154
|
+
> AI Agent 在创建新页面前,先按上表判断「应该走表单还是代码页」,避免把列表场景误塞进表单页。
|
|
155
|
+
|
|
156
|
+
### 4.1 状态流转不是审批流
|
|
157
|
+
|
|
158
|
+
- 普通业务流转默认使用普通表单:`status` 字段、责任人/归属冗余字段、操作日志表、domain 状态机、service 统一提交。
|
|
159
|
+
- 每次状态变更都由 service 完成,统一写操作日志并更新责任人、归属、更新时间等冗余字段。
|
|
160
|
+
- workflow 只用于真实审批:审批人、审批任务、同意/驳回、审批意见、节点权限、流程记录明确存在的场景。
|
|
161
|
+
- 不要把「待处理 / 处理中 / 已完成 / 已关闭」这类状态流转建成流程表单。
|
|
153
162
|
|
|
154
163
|
---
|
|
155
164
|
|
|
@@ -175,7 +184,7 @@ export default function InstrumentListPage() {
|
|
|
175
184
|
- **UI 库分端**:
|
|
176
185
|
- PC → `antd`
|
|
177
186
|
- Mobile → `antd-mobile`
|
|
178
|
-
- **逻辑层共享**:`src/domain/` 与 `src/shared/services/` 在两端复用,确保业务规则一处实现。
|
|
187
|
+
- **逻辑层共享**:`src/domain/` 与 `src/shared/services/` 在两端复用,确保业务规则一处实现。
|
|
179
188
|
|
|
180
189
|
### 5.2 共享 / 分离原则
|
|
181
190
|
|
|
@@ -228,15 +237,28 @@ forms ──▶ shared ──▶ domain
|
|
|
228
237
|
```
|
|
229
238
|
|
|
230
239
|
- `domain/` 不依赖 `shared/` 或 UI。
|
|
231
|
-
- `shared/` 不依赖 `pages/` 或 `forms/`。
|
|
232
|
-
- 反向依赖(如 domain 导入 pages)= 立刻拒绝。
|
|
233
|
-
|
|
234
|
-
---
|
|
235
|
-
|
|
236
|
-
##
|
|
237
|
-
|
|
238
|
-
-
|
|
239
|
-
-
|
|
240
|
-
-
|
|
241
|
-
-
|
|
242
|
-
-
|
|
240
|
+
- `shared/` 不依赖 `pages/` 或 `forms/`。
|
|
241
|
+
- 反向依赖(如 domain 导入 pages)= 立刻拒绝。
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 7. 查询与交互性能
|
|
246
|
+
|
|
247
|
+
- 列表必须走分页接口,传 `currentPage`、`pageSize`、排序和结构化条件。
|
|
248
|
+
- 禁止一次取大 `pageSize` 再在页面内筛选。
|
|
249
|
+
- 默认不要使用 `searchKeyWord`;多字段模糊查询用 `filterGroup` + `OR`,并显式指定字段。
|
|
250
|
+
- 查询条件构造放在 `domain/` 或 `shared/services/`,不要散落在 TSX 事件处理里。
|
|
251
|
+
- 列表刷新时保留当前数据,使用局部刷新态,避免整页闪烁。
|
|
252
|
+
- 操作需要统一的确认、pending、成功反馈、失败刷新或回滚。
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## 速查 Checklist(AI Agent 自检)
|
|
257
|
+
|
|
258
|
+
- [ ] 新增数据场景:是否已经定义表单 schema?
|
|
259
|
+
- [ ] 列表/查询场景:是否使用 `DataManagementList` 而非平台 view?
|
|
260
|
+
- [ ] 查询:是否使用分页和结构化条件,而不是大 pageSize、页面内过滤或 `searchKeyWord`?
|
|
261
|
+
- [ ] 流程判断:是否确认这是「真审批」,而不是普通状态流转?
|
|
262
|
+
- [ ] 菜单绑定:是否指向代码页 `--type=page`?
|
|
263
|
+
- [ ] PC/Mobile:是否分离页面、共享 domain?
|
|
264
|
+
- [ ] 目录:业务逻辑是否落在 `domain/`,未污染 UI 层?
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# OpenXiangda Best Practices
|
|
2
|
+
|
|
3
|
+
Use this reference before scaffolding a real app, a complex page, a data
|
|
4
|
+
management view, a portal shell, role governance, notification automation, or a
|
|
5
|
+
business lifecycle flow.
|
|
6
|
+
|
|
7
|
+
The workspace template includes examples under:
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
examples/best-practices/
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
These examples are copied by `openxiangda workspace init`, but they are not
|
|
14
|
+
published by default. Copy only the selected pattern into `src/`, then adapt the
|
|
15
|
+
form codes, field names, permissions, and page route names.
|
|
16
|
+
|
|
17
|
+
## AI Development Flow
|
|
18
|
+
|
|
19
|
+
1. Choose the architecture before writing code:
|
|
20
|
+
- normal form
|
|
21
|
+
- custom form page
|
|
22
|
+
- data management page
|
|
23
|
+
- custom data management page
|
|
24
|
+
- app-shell PC portal
|
|
25
|
+
- app-shell mobile portal
|
|
26
|
+
- pure interactive workbench
|
|
27
|
+
- business status lifecycle
|
|
28
|
+
- real approval workflow
|
|
29
|
+
- automation / JS_CODE
|
|
30
|
+
- role governance / permissions
|
|
31
|
+
2. Read the matching files in `examples/best-practices/`.
|
|
32
|
+
3. Copy the smallest useful slice into `src/`.
|
|
33
|
+
4. Keep view code thin; put reusable business logic in `domain/` and platform
|
|
34
|
+
calls in `shared/services/`.
|
|
35
|
+
5. Run `pnpm examples:check` while changing examples, and `pnpm check` after
|
|
36
|
+
copying code into the app source.
|
|
37
|
+
|
|
38
|
+
## State Flow Is Not Workflow
|
|
39
|
+
|
|
40
|
+
Most business processes are status lifecycles, not approval workflows.
|
|
41
|
+
|
|
42
|
+
Use a normal form plus:
|
|
43
|
+
|
|
44
|
+
- a `status` field
|
|
45
|
+
- responsibility fields such as `ownerUserId`, `ownerDeptId`, `collegeId`,
|
|
46
|
+
`classId`
|
|
47
|
+
- an action log form
|
|
48
|
+
- a pure state machine in `domain/<feature>/state-machine.ts`
|
|
49
|
+
- a service method that changes status and writes the log in one path
|
|
50
|
+
- optional automation / JS_CODE for timed reminders or backend follow-up
|
|
51
|
+
|
|
52
|
+
Use workflow only when there are real approval tasks:
|
|
53
|
+
|
|
54
|
+
- approver assignment
|
|
55
|
+
- agree / reject / transfer / countersign behavior
|
|
56
|
+
- approval opinions
|
|
57
|
+
- node-level permissions
|
|
58
|
+
- process task records and audit requirements
|
|
59
|
+
- notification or JS_CODE nodes tied to approval nodes
|
|
60
|
+
|
|
61
|
+
Do not model ordinary "pending -> processing -> resolved -> closed" state
|
|
62
|
+
changes as workflow forms.
|
|
63
|
+
|
|
64
|
+
## Layering Rules
|
|
65
|
+
|
|
66
|
+
Use this dependency direction:
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
pages/forms -> shared -> domain
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- `domain/<feature>/`: pure TypeScript business types, state machine,
|
|
73
|
+
permission predicates, and query condition builders. No React, Ant Design,
|
|
74
|
+
runtime SDK, CSS, or platform IDs.
|
|
75
|
+
- `shared/services/<feature>.ts`: SDK/API access, paginated queries, status
|
|
76
|
+
updates, log writes, resource calls.
|
|
77
|
+
- `shared/hooks/<feature>/`: loading, refresh, submit pending, error handling,
|
|
78
|
+
optimistic or rollback behavior.
|
|
79
|
+
- `shared/components/`: reusable empty, loading, error, status tag,
|
|
80
|
+
confirmation, timeline, and list action components.
|
|
81
|
+
- `pages/<feature>/components/`: page-local reusable components.
|
|
82
|
+
- `pages/<feature>/styles.css`: page CSS namespace. Do not put all styling in
|
|
83
|
+
TSX.
|
|
84
|
+
- `pages/<feature>/index.tsx`: entry and composition only. Avoid large business
|
|
85
|
+
logic blocks here.
|
|
86
|
+
|
|
87
|
+
PC and mobile pages may have different layout/components, but must reuse the
|
|
88
|
+
same `domain/` and `shared/services/` when the business behavior is the same.
|
|
89
|
+
|
|
90
|
+
## Module Size Rules
|
|
91
|
+
|
|
92
|
+
- Avoid single-file pages. A page file over about 250 lines should be split.
|
|
93
|
+
- Move table columns, filter definitions, route configs, status configs, and
|
|
94
|
+
action visibility rules into separate files.
|
|
95
|
+
- Do not let page components assemble complex API payloads directly. Call a hook
|
|
96
|
+
or service.
|
|
97
|
+
- Keep shared modules independent from specific page folders.
|
|
98
|
+
- Keep domain functions unit-testable without a browser or platform runtime.
|
|
99
|
+
|
|
100
|
+
## Permission And Data Isolation
|
|
101
|
+
|
|
102
|
+
For apps with dynamic roles:
|
|
103
|
+
|
|
104
|
+
1. Create an app role maintenance form, such as `app-role`.
|
|
105
|
+
2. Use automation / JS_CODE to sync role records to platform roles.
|
|
106
|
+
3. Add redundant ownership fields to business forms, for example:
|
|
107
|
+
- `collegeId`
|
|
108
|
+
- `classId`
|
|
109
|
+
- `ownerDeptId`
|
|
110
|
+
- `ownerUserId`
|
|
111
|
+
- `roleCode`
|
|
112
|
+
4. Create page permission groups for entry visibility.
|
|
113
|
+
5. Create form permission groups with condition-based data permissions for real
|
|
114
|
+
data isolation.
|
|
115
|
+
|
|
116
|
+
Frontend button hiding is only user experience. It is not permission control.
|
|
117
|
+
Every sensitive action must still be protected by platform role/form permission
|
|
118
|
+
groups or backend-side JS_CODE checks.
|
|
119
|
+
|
|
120
|
+
## Query Performance
|
|
121
|
+
|
|
122
|
+
- Always use paginated APIs with `currentPage`, `pageSize`, sort, and structured
|
|
123
|
+
conditions.
|
|
124
|
+
- Do not fetch a huge page and filter in the browser.
|
|
125
|
+
- Do not default to `searchKeyWord`. It is broad and expensive.
|
|
126
|
+
- For multi-field fuzzy search, build `filterGroup` with `OR` across explicit
|
|
127
|
+
fields.
|
|
128
|
+
- Put query construction in `domain/<feature>/ticket-query.ts` or the service
|
|
129
|
+
layer, not inside JSX.
|
|
130
|
+
- Keep current table/list data visible during refresh and show local refresh
|
|
131
|
+
state to avoid flicker.
|
|
132
|
+
|
|
133
|
+
## Interaction Rules
|
|
134
|
+
|
|
135
|
+
- Every list/detail page needs loading, empty, error, refresh, and submit-pending
|
|
136
|
+
states.
|
|
137
|
+
- Destructive or state-changing actions need confirmation.
|
|
138
|
+
- Show processing feedback and success/failure feedback.
|
|
139
|
+
- On failure, refresh or rollback the affected row instead of leaving stale UI.
|
|
140
|
+
- Keep interaction styles consistent across PC and mobile, but do not force the
|
|
141
|
+
same layout component onto both viewports.
|
|
142
|
+
|
|
143
|
+
## Library Selection
|
|
144
|
+
|
|
145
|
+
- Do not hand-write mature controls or engines. Use platform components for
|
|
146
|
+
personnel, departments, files, images, rich text, locations, and data lists.
|
|
147
|
+
- Use `antd` / `antd-mobile` for standard controls, overlays, tables, steps,
|
|
148
|
+
tabs, forms, and feedback. Avoid raw native inputs unless the behavior is
|
|
149
|
+
truly trivial and already styled by a wrapper.
|
|
150
|
+
- Use ECharts for charts and dashboards.
|
|
151
|
+
- Use GSAP for complex timeline/scroll/sequence animations; simple transitions
|
|
152
|
+
can stay in CSS. If an animation-specific skill is available, read it before
|
|
153
|
+
implementing.
|
|
154
|
+
- For drag/drop, virtual lists, calendars, spreadsheet-like input, QR/barcode,
|
|
155
|
+
or export/import, research maintained packages and official docs before
|
|
156
|
+
writing code.
|
|
157
|
+
- New dependencies should have a clear reason and a small adapter layer in the
|
|
158
|
+
app, not copied third-party internals.
|
|
159
|
+
|
|
160
|
+
## Template Catalog
|
|
161
|
+
|
|
162
|
+
- `customer-profile`: standard form schema with validation, members,
|
|
163
|
+
departments, attachments, and child table.
|
|
164
|
+
- `service-ticket-lifecycle`: status lifecycle with ticket form, action-log
|
|
165
|
+
form, state machine, service layer, and operation log.
|
|
166
|
+
- `service-ticket-ops`: custom data management page based on
|
|
167
|
+
`DataManagementList`, split into page, components, hook, query builder, and
|
|
168
|
+
detail drawer.
|
|
169
|
+
- `role-governance`: role maintenance form, role sync JS_CODE, redundant
|
|
170
|
+
ownership fields, and permission-group resource examples.
|
|
171
|
+
- `pc-portal-shell`: app-shell PC portal with routes, modules, components, and
|
|
172
|
+
services.
|
|
173
|
+
- `mobile-portal-shell`: app-shell mobile portal with mobile-only components
|
|
174
|
+
reusing the same domain/service layer.
|
|
175
|
+
- `interactive-workbench`: pure interactive page with reducer, modular panels,
|
|
176
|
+
preview, loading/error, and batch operations.
|
|
177
|
+
- `expense-approval-workflow`: real approval workflow example; use only for
|
|
178
|
+
approval scenarios.
|
|
179
|
+
- `daily-ticket-digest`: automation / JS_CODE example for paginated overdue
|
|
180
|
+
query, notification, and log writing.
|
|
@@ -4,14 +4,40 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 1. 核心原则
|
|
8
|
-
|
|
9
|
-
1. **平台组件优先**:所有平台组件已经接入了组织架构、文件存储、权限、多端适配等平台能力,重写一遍 = 丢能力 + 后续无法维护。
|
|
10
|
-
2. **基于 antd / antd-mobile 包装**:自定义组件必须站在 antd 之上,保证 PC 和移动端的基础体验一致。
|
|
11
|
-
3.
|
|
12
|
-
4.
|
|
13
|
-
|
|
14
|
-
|
|
7
|
+
## 1. 核心原则
|
|
8
|
+
|
|
9
|
+
1. **平台组件优先**:所有平台组件已经接入了组织架构、文件存储、权限、多端适配等平台能力,重写一遍 = 丢能力 + 后续无法维护。
|
|
10
|
+
2. **基于 antd / antd-mobile 包装**:自定义组件必须站在 antd 之上,保证 PC 和移动端的基础体验一致。
|
|
11
|
+
3. **成熟能力先调研开源方案**:图表、动画、拖拽、虚拟列表、富文本、日历、导入导出、复杂表格等,不要直接手写。先查当前项目依赖、官方文档和维护状态,再决定使用库或轻量封装。
|
|
12
|
+
4. **样式走变量与语义类**:使用 CSS 变量、Tailwind 语义类,**禁止**在 JSX 中硬编码颜色、间距、字号、圆角。
|
|
13
|
+
5. **不覆盖组件内部 class**:组件库内部类名(`ant-select-selector` 等)是私有 API,下个版本就可能变。
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 1.1 开源库选型规则
|
|
18
|
+
|
|
19
|
+
AI 在实现成熟交互前必须先判断是否已有可靠组件或库:
|
|
20
|
+
|
|
21
|
+
| 场景 | 优先方案 | 说明 |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| PC 表单控件、筛选、弹窗、表格、步骤条 | `antd` | 不要用原生 `<input>` / `<select>` 复刻。用 `Input`、`Input.Search`、`Select`、`DatePicker`、`Table`、`Modal`、`Drawer`、`Form` 等。 |
|
|
24
|
+
| 移动端操作、列表、弹层、Tab | `antd-mobile` | 移动端不要强行套 PC 组件。 |
|
|
25
|
+
| 平台数据录入能力 | `openxiangda` 平台字段组件 | 人员、部门、附件、图片、富文本、位置、数据管理列表优先平台组件。 |
|
|
26
|
+
| 图表、仪表盘、经营看板 | `echarts` + `echarts-for-react` | 不要手写 canvas/SVG 图表,除非只是非常小的装饰图形。 |
|
|
27
|
+
| 复杂时间轴动画、编排动画、滚动动画 | `gsap` | 需要动画库时先查 GSAP 官方文档;如果当前 Agent 有动画/GSAP skill,先读取该 skill。简单 hover/transition 用 CSS 即可。 |
|
|
28
|
+
| 拖拽排序、看板、可拖卡片 | `@dnd-kit/*` | 不要自己处理 pointer/mouse/touch 全套事件。 |
|
|
29
|
+
| 大列表虚拟滚动 | antd Table virtual / `rc-virtual-list` | 不要一次渲染几千行 DOM。 |
|
|
30
|
+
| 日期时间处理 | `dayjs` + antd 日期组件 | 不要手写日期解析、时区格式化。 |
|
|
31
|
+
| 富文本 | 平台 `EditorField` 或成熟编辑器封装 | 不要用 contenteditable 从零做编辑器。 |
|
|
32
|
+
|
|
33
|
+
选型流程:
|
|
34
|
+
|
|
35
|
+
1. 先看模板 `package.json` 已有依赖,已有依赖优先复用。
|
|
36
|
+
2. 没有依赖但功能成熟复杂时,调研官方文档、维护状态、包体积和授权,再通过包管理器加入。
|
|
37
|
+
3. 页面代码只写业务适配层,不复制第三方库内部逻辑。
|
|
38
|
+
4. 新增依赖后,在提交说明或实现注释中保留一句选择原因。
|
|
39
|
+
|
|
40
|
+
---
|
|
15
41
|
|
|
16
42
|
## 2. 必须使用平台组件(重做即丢能力)
|
|
17
43
|
|
|
@@ -6,6 +6,32 @@ Preferred publish command:
|
|
|
6
6
|
openxiangda workspace publish --profile <name>
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
+
For day-to-day AI edits, prefer a targeted publish:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Preview what git-touched forms/pages would publish.
|
|
13
|
+
openxiangda workspace publish --profile <name> --changed --dry-run
|
|
14
|
+
|
|
15
|
+
# Publish only git-touched src/forms/* and src/pages/* modules.
|
|
16
|
+
openxiangda workspace publish --profile <name> --changed
|
|
17
|
+
|
|
18
|
+
# Publish one code page or one form when the changed module is known.
|
|
19
|
+
openxiangda workspace publish --profile <name> --page dashboard
|
|
20
|
+
openxiangda workspace publish --profile <name> --form customer
|
|
21
|
+
|
|
22
|
+
# Publish several explicit modules.
|
|
23
|
+
openxiangda workspace publish --profile <name> --only pages/dashboard,forms/customer
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Do not use full workspace publish as a reflex. Full publish is only appropriate
|
|
27
|
+
when many modules were intentionally changed, shared/config changes affect many
|
|
28
|
+
pages, or the incremental cache needs a repair pass. For a single page edit,
|
|
29
|
+
publish that page.
|
|
30
|
+
|
|
31
|
+
Targeted publish skips `src/resources` by default. Add `--resources` if resource
|
|
32
|
+
manifests changed too, or run `openxiangda resource plan|publish` separately.
|
|
33
|
+
Use `--skip-resources` when you explicitly want forms/pages only.
|
|
34
|
+
|
|
9
35
|
The CLI injects:
|
|
10
36
|
|
|
11
37
|
- `OPENXIANGDA_PROFILE`
|
|
@@ -5,16 +5,18 @@ Form pages, workflow form pages, and custom code pages live in `sy-lowcode-app-w
|
|
|
5
5
|
Create a new workspace with:
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
openxiangda workspace init ./my-app-workspace
|
|
8
|
+
openxiangda workspace init ./my-app-workspace --profile <name> --app-name "应用名称"
|
|
9
9
|
cd ./my-app-workspace
|
|
10
10
|
pnpm install
|
|
11
|
-
openxiangda workspace bind --profile <name> --app-type APP_XXXX
|
|
12
11
|
```
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
Local workspace state is authoritative. If the current folder has no app binding, create a new app; do not search the platform for similar app names.
|
|
14
|
+
|
|
15
|
+
Bind an existing app only when the user explicitly provides `appType` or asks to reuse that app:
|
|
15
16
|
|
|
16
17
|
```bash
|
|
17
18
|
openxiangda workspace init ./my-app-workspace --profile <name> --app-type APP_XXXX
|
|
19
|
+
openxiangda workspace bind --profile <name> --app-type APP_XXXX
|
|
18
20
|
```
|
|
19
21
|
|
|
20
22
|
Typical code page layout:
|
|
@@ -31,6 +31,10 @@ Tokens never belong in the project. User tokens live in `~/.openxiangda/profiles
|
|
|
31
31
|
"menus": {},
|
|
32
32
|
"roles": {},
|
|
33
33
|
"connectors": {},
|
|
34
|
+
"notifications": {
|
|
35
|
+
"templates": {},
|
|
36
|
+
"typeConfigs": {}
|
|
37
|
+
},
|
|
34
38
|
"pagePermissionGroups": {},
|
|
35
39
|
"formPermissionGroups": {},
|
|
36
40
|
"formSettings": {}
|
|
@@ -44,6 +48,8 @@ Tokens never belong in the project. User tokens live in `~/.openxiangda/profiles
|
|
|
44
48
|
|
|
45
49
|
- Profile is the deployment boundary.
|
|
46
50
|
- `baseUrl` is the backend API base. On standard private deployments it is `<origin>/service`; management pages use `/platform`, and app runtime pages use `/view`.
|
|
51
|
+
- Local state is authoritative for app binding. If a workspace has no `appType` for the target profile, create a new app/workspace with `openxiangda workspace init <dir> --profile <name> --app-name "应用名称"`.
|
|
52
|
+
- Do not search platform apps or reuse similar names unless the user explicitly asks to reuse an existing app or provides an `appType`.
|
|
47
53
|
- Local resource keys are logical codes.
|
|
48
54
|
- Live IDs and lightweight runtime aliases are nested under the profile that produced them.
|
|
49
55
|
- Do not store business configuration or secrets in `.openxiangda/state.json`; store those in `src/resources/`.
|
|
@@ -19,16 +19,16 @@ openxiangda auth status --profile <name>
|
|
|
19
19
|
If the workspace is not bound:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
openxiangda app
|
|
23
|
-
|
|
22
|
+
openxiangda workspace init ./my-app-workspace --profile <name> --app-name "应用名称"
|
|
23
|
+
cd ./my-app-workspace
|
|
24
|
+
pnpm install
|
|
24
25
|
```
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
Bind to an existing app only when the user explicitly provides `appType` or asks to reuse an existing platform app:
|
|
27
28
|
|
|
28
29
|
```bash
|
|
29
30
|
openxiangda workspace init ./my-app-workspace --profile <name> --app-type APP_XXX
|
|
30
|
-
|
|
31
|
-
pnpm install
|
|
31
|
+
openxiangda workspace bind --profile <name> --app-type APP_XXX
|
|
32
32
|
```
|
|
33
33
|
|
|
34
34
|
For menu work:
|
|
@@ -39,7 +39,7 @@ openxiangda menu create main --name "主菜单" --type nav --profile <name>
|
|
|
39
39
|
openxiangda menu create customer-entry --name "客户信息" --type receipt --form-code customer --profile <name>
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
If the app
|
|
42
|
+
If the user explicitly asks to create an app without initializing a workspace:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
openxiangda app create "应用名称" --profile <name>
|
|
@@ -50,9 +50,12 @@ openxiangda workspace bind --profile <name> --app-type APP_XXX
|
|
|
50
50
|
|
|
51
51
|
- Never ask for AK/SK.
|
|
52
52
|
- Always pass `--profile` for publish or cross-platform operations.
|
|
53
|
-
-
|
|
53
|
+
- Local `.openxiangda/state.json` is authoritative. If the user starts from a new empty directory or the workspace has no app binding, create a new app with `openxiangda workspace init <dir> --profile <name> --app-name "应用名称"`.
|
|
54
|
+
- Do not search platform apps or reuse similar app names unless the user explicitly asks to reuse an existing app or gives an `appType`.
|
|
54
55
|
- Store platform-specific IDs only in `.openxiangda/state.json`.
|
|
55
56
|
- Use logical local codes for forms, pages, workflows, automations, and menus.
|
|
57
|
+
- Before scaffolding a new business app, read `../../references/best-practices.md` and pick an architecture from the initialized `examples/best-practices/` catalog. Do not generate a large single-file app page when a template pattern already covers the scenario.
|
|
58
|
+
- When publishing after app edits, prefer targeted commands (`workspace publish --changed --dry-run`, then `--changed`, `--page`, `--form`, or `--only`). Do not publish all forms/pages just because one page changed.
|
|
56
59
|
- Use `openxiangda app snapshot <APP_XXX> --profile <name> --json` before changing an existing app.
|
|
57
60
|
|
|
58
61
|
## Resource State
|
|
@@ -62,3 +65,5 @@ Read `../../references/workspace-state.md` when changing `.openxiangda/state.jso
|
|
|
62
65
|
Read `../../references/openxiangda-api.md` when exact endpoint fields are needed.
|
|
63
66
|
|
|
64
67
|
Read `../../references/architecture-patterns.md` to understand the overall app structure (how forms, pages, menus, workflows, and permissions compose into an app, and the recommended `src/forms` / `src/pages` layout) before scaffolding or restructuring an app workspace.
|
|
68
|
+
|
|
69
|
+
Read `../../references/best-practices.md` before implementing app-level patterns such as status lifecycles, role governance, PC/mobile portals, high-performance data management pages, workflow boundaries, and automation.
|
|
@@ -40,22 +40,35 @@ Use `--profile` for every destructive or publishing action. Treat the profile as
|
|
|
40
40
|
|
|
41
41
|
Run write commands sequentially in the same workspace because they update `.openxiangda/state.json`. Read-only commands such as list, pull, snapshot, and inspect may run in parallel.
|
|
42
42
|
|
|
43
|
+
## Updates
|
|
44
|
+
|
|
45
|
+
Use the official npm registry for OpenXiangda package updates because domestic mirrors may lag:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install -g openxiangda@latest --registry=https://registry.npmjs.org
|
|
49
|
+
openxiangda update check --json
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
At the start of substantial work, run `openxiangda update check --json`. If `updateAvailable` is true, run `openxiangda update install` before generating or publishing so the CLI and installed skills stay compatible. If the installed CLI does not support `update`, reinstall with the official registry command above, then run `openxiangda skill install --force`.
|
|
53
|
+
|
|
43
54
|
## Workspace State
|
|
44
55
|
|
|
45
56
|
Create a workspace when the current project does not already contain a `sy-lowcode-app-workspace`:
|
|
46
57
|
|
|
47
58
|
```bash
|
|
48
|
-
openxiangda workspace init ./my-app-workspace --profile dev --app-
|
|
59
|
+
openxiangda workspace init ./my-app-workspace --profile dev --app-name "测试应用"
|
|
49
60
|
cd ./my-app-workspace
|
|
50
61
|
pnpm install
|
|
51
62
|
openxiangda env --profile dev
|
|
52
63
|
```
|
|
53
64
|
|
|
54
|
-
If the
|
|
65
|
+
Local workspace state is authoritative. If `.openxiangda/state.json` already contains an app binding for the target profile, use it. If there is no local binding, create a new app with `workspace init --app-name`; do not search platform apps for similar names.
|
|
66
|
+
|
|
67
|
+
After workspace initialization, inspect `examples/best-practices/` before generating a real app. The examples are copied locally but are not published by default; copy only the selected pattern into `src/`.
|
|
68
|
+
|
|
69
|
+
If the workspace already exists and the user explicitly provides an existing app, bind each platform to its own app, then publish from `sy-lowcode-app-workspace`:
|
|
55
70
|
|
|
56
71
|
```bash
|
|
57
|
-
openxiangda app list --profile dev
|
|
58
|
-
openxiangda app create "测试应用" --profile dev
|
|
59
72
|
openxiangda workspace bind --profile dev --app-type APP_DEV
|
|
60
73
|
openxiangda workspace bind --profile prod --app-type APP_PROD
|
|
61
74
|
cd /path/to/sy-lowcode-app-workspace
|
|
@@ -96,6 +109,10 @@ Project state is stored in `.openxiangda/state.json`:
|
|
|
96
109
|
"menus": {},
|
|
97
110
|
"roles": {},
|
|
98
111
|
"connectors": {},
|
|
112
|
+
"notifications": {
|
|
113
|
+
"templates": {},
|
|
114
|
+
"typeConfigs": {}
|
|
115
|
+
},
|
|
99
116
|
"pagePermissionGroups": {},
|
|
100
117
|
"formPermissionGroups": {},
|
|
101
118
|
"formSettings": {}
|
|
@@ -125,6 +142,18 @@ openxiangda workspace publish --profile prod
|
|
|
125
142
|
|
|
126
143
|
The CLI checks that the target profile is logged in and bound to an app. It then runs the workspace publish script with these environment variables:
|
|
127
144
|
|
|
145
|
+
For normal development, inspect and publish only changed or targeted modules:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
openxiangda workspace publish --profile dev --changed --dry-run
|
|
149
|
+
openxiangda workspace publish --profile dev --changed
|
|
150
|
+
openxiangda workspace publish --profile dev --page dashboard
|
|
151
|
+
openxiangda workspace publish --profile dev --form customer
|
|
152
|
+
openxiangda workspace publish --profile dev --only pages/dashboard,forms/customer
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Do not run a full publish automatically after a single page or form edit. Full publish is for intentional broad changes, shared/config changes that affect many modules, or cache repair. Targeted publish skips resources by default; pass `--resources` or run `openxiangda resource publish` when resource manifests changed.
|
|
156
|
+
|
|
128
157
|
- `OPENXIANGDA_PROFILE`
|
|
129
158
|
- `OPENXIANGDA_BASE_URL`
|
|
130
159
|
- `OPENXIANGDA_ACCESS_TOKEN`
|
|
@@ -145,3 +174,4 @@ The publish script is responsible for:
|
|
|
145
174
|
- `../../references/openxiangda-api.md` — exact endpoint contracts.
|
|
146
175
|
- `../../references/workspace-state.md` — `.openxiangda/state.json` shape and profile-scoped resource maps.
|
|
147
176
|
- `../../references/architecture-patterns.md` — overall architecture of an OpenXiangda app workspace (CRUD data flow, page/form layering, recommended directory organization). Read this when you need to understand how forms, pages, workflows, and platform state fit together end-to-end.
|
|
177
|
+
- `../../references/best-practices.md` — initialized best-practice templates and rules for modular pages, status lifecycles, role governance, data isolation, query performance, and workflow boundaries.
|
|
@@ -18,11 +18,13 @@ cd /path/to/sy-lowcode-app-workspace
|
|
|
18
18
|
If the workspace does not exist yet, create it before writing form source:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
openxiangda workspace init ./my-app-workspace --profile <name> --app-
|
|
21
|
+
openxiangda workspace init ./my-app-workspace --profile <name> --app-name "应用名称"
|
|
22
22
|
cd ./my-app-workspace
|
|
23
23
|
pnpm install
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
Use `--app-type APP_XXX` only when the user explicitly provides an existing app to reuse.
|
|
27
|
+
|
|
26
28
|
Create or edit workspace source:
|
|
27
29
|
|
|
28
30
|
```text
|
|
@@ -37,6 +39,12 @@ Then publish:
|
|
|
37
39
|
openxiangda workspace publish --profile <name>
|
|
38
40
|
```
|
|
39
41
|
|
|
42
|
+
For a single form edit, publish that form only:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
openxiangda workspace publish --profile <name> --form <formCode>
|
|
46
|
+
```
|
|
47
|
+
|
|
40
48
|
The workspace publish script receives `OPENXIANGDA_BASE_URL`, `OPENXIANGDA_ACCESS_TOKEN`, and `OPENXIANGDA_APP_TYPE` from the CLI. It creates/binds the platform form shell only when needed, syncs form metadata, builds the React form page bundle, uploads assets, and registers the bundle.
|
|
41
49
|
|
|
42
50
|
## Low-level Commands
|
|
@@ -61,10 +69,13 @@ Read these references only when writing or reviewing schema:
|
|
|
61
69
|
- `../../references/forms/layout-and-rules.md`
|
|
62
70
|
- `../../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.
|
|
63
71
|
- `../../references/component-guide.md` — when to pick platform form components vs. custom widgets, and the option-component rules.
|
|
72
|
+
- `../../references/best-practices.md` — status lifecycle fields, ownership redundancy, role-governance fields, and the boundary between normal forms and workflow forms.
|
|
64
73
|
|
|
65
74
|
## Rules
|
|
66
75
|
|
|
67
76
|
- Prefer deterministic `formCode` as local key; bind live `formUuid` under the active profile.
|
|
77
|
+
- For business lifecycles, model status with normal form fields (`status`, owner/responsibility fields, action-log relation fields) unless the scenario has real approval tasks. Do not create workflow forms for ordinary status transitions.
|
|
78
|
+
- For permission isolation, add redundant ownership fields such as `collegeId`, `classId`, `ownerDeptId`, and `ownerUserId` at schema time so form permission groups can use structured conditions later.
|
|
68
79
|
- For multi-platform publishing, create or bind the form separately for each profile.
|
|
69
80
|
- Do not copy `formUuid` from dev to prod unless the target platform explicitly already uses that ID.
|
|
70
81
|
- Keep `schema.ts` and `page.tsx` as the source for fields/layout/rules and presentation; generated build output is not the source of truth.
|
|
@@ -72,5 +83,6 @@ Read these references only when writing or reviewing schema:
|
|
|
72
83
|
- 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`.
|
|
73
84
|
- 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.
|
|
74
85
|
- 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.
|
|
86
|
+
- After editing one form, use `workspace publish --form <formCode>` or preview `--changed --dry-run`; do not run full workspace publish by default.
|
|
75
87
|
- Use `openxiangda form pull` or app snapshot before overwriting an existing form.
|
|
76
88
|
- Before assuming a value shape (e.g. dates, attachments, member fields, option fields), verify against `../../references/platform-data-model.md` instead of guessing.
|
|
@@ -16,14 +16,29 @@ cd /path/to/sy-lowcode-app-workspace
|
|
|
16
16
|
openxiangda workspace publish --profile <name>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
For a page-only edit, prefer targeted publish:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
openxiangda workspace publish --profile <name> --page <pageCode>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
If multiple files changed and the target is not obvious, preview first:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
openxiangda workspace publish --profile <name> --changed --dry-run
|
|
29
|
+
openxiangda workspace publish --profile <name> --changed
|
|
30
|
+
```
|
|
31
|
+
|
|
19
32
|
If the workspace does not exist yet, initialize it first:
|
|
20
33
|
|
|
21
34
|
```bash
|
|
22
|
-
openxiangda workspace init ./my-app-workspace --profile <name> --app-
|
|
35
|
+
openxiangda workspace init ./my-app-workspace --profile <name> --app-name "应用名称"
|
|
23
36
|
cd ./my-app-workspace
|
|
24
37
|
pnpm install
|
|
25
38
|
```
|
|
26
39
|
|
|
40
|
+
Use `--app-type APP_XXX` only when the user explicitly provides an existing app to reuse.
|
|
41
|
+
|
|
27
42
|
Direct publish is only for already built assets or targeted repair:
|
|
28
43
|
|
|
29
44
|
```bash
|
|
@@ -41,6 +56,7 @@ Read these references only when editing page code:
|
|
|
41
56
|
|
|
42
57
|
- `../../references/pages/workspace-structure.md`
|
|
43
58
|
- `../../references/pages/app-shell.md` — formal backend / PC portal / mobile portal entry pattern. Read before creating any user-facing main entry or admin console.
|
|
59
|
+
- `../../references/best-practices.md` — initialized examples for modular pages, status lifecycles, role governance, high-performance queries, portal shells, and interactive workbenches. Read before scaffolding complex pages or data management pages.
|
|
44
60
|
- `../../references/pages/page-sdk.md`
|
|
45
61
|
- `../../references/notifications.md` — notification resources and `sdk.notification` usage. Read before adding reminders, alerts, or message templates to a page.
|
|
46
62
|
- `../../references/pages/publish-flow.md`
|
|
@@ -53,17 +69,22 @@ Read these references only when editing page code:
|
|
|
53
69
|
|
|
54
70
|
- Keep `pageCode` stable and use it as the local logical key.
|
|
55
71
|
- Formal user-facing entries such as admin consoles, PC portals, and mobile portals must be app-shell code pages. Declare `entry: { mode: "app-shell", hidePlatformNav: true, defaultRoute: "<home-route>" }` in `page.config.ts`.
|
|
72
|
+
- Do not generate single-file large pages. Split complex code pages into `domain/`, `shared/services/`, `shared/hooks/`, shared/page-local `components/`, route/config files, and `styles.css` as described in `../../references/best-practices.md`.
|
|
73
|
+
- Keep view code thin. Page components call hooks/services; business rules, state transition rules, permission predicates, and query builders live outside TSX and are reusable by PC and mobile pages.
|
|
56
74
|
- Store live `pageId`, `routeKey`, and `legacyFormUuid` under the current profile only.
|
|
57
75
|
- Use `openxiangda/runtime` for platform data access instead of hardcoding backend URLs in page code.
|
|
58
76
|
- For reminders, alerts, and business messages, declare `src/resources/notifications/` first and call `sdk.notification`; do not hardcode notification API URLs.
|
|
77
|
+
- Before hand-writing mature UI behavior, consult `../../references/component-guide.md` and use established libraries: platform components for platform data fields, antd/antd-mobile for controls and overlays, ECharts for charts, GSAP for complex animation timelines, and maintained packages such as dnd-kit for drag/drop. Do not rebuild mature controls with raw DOM/native inputs.
|
|
59
78
|
- Named imports from `@ant-design/icons` are supported by the `openxiangda` workspace build proxy, which enumerates icon module exports at runtime.
|
|
60
79
|
- Publish through `openxiangda workspace publish --profile <name>` unless there is a specific repair reason to call `page publish` directly.
|
|
80
|
+
- After editing one code page, publish with `--page <pageCode>` instead of triggering all forms/pages. Use `--changed --dry-run` before `--changed` when git touched several modules.
|
|
61
81
|
- Do not create custom code pages by writing platform schema directly. The source is React workspace code plus `page.config.ts`.
|
|
62
82
|
- Do not scatter hardcoded `/view/...&isRenderNav=false` URLs through page code. Use the runtime navigation API or the local route helper generated for the app shell.
|
|
63
83
|
- Platform menus should bind only the formal app-shell code page for user-facing entry points. Original forms, workflows, and native view pages may remain as development / maintenance resources or permission targets, but should not become the product navigation shell.
|
|
64
84
|
- For prod, explicitly run with `--profile prod`; never rely on the current profile for release operations.
|
|
65
85
|
- Follow the style system in `../../references/style-system.md`: never hardcode colors, fonts, spacing, or radii — use the platform CSS variables and the page CSS namespace.
|
|
66
86
|
- For list / detail / CRUD pages, follow `../../references/architecture-patterns.md` (e.g. `DataManagementList`) before writing custom data-fetching loops.
|
|
87
|
+
- 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`.
|
|
67
88
|
- 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.
|
|
68
89
|
- When a page misbehaves (lost styles, `options is undefined`, option labels showing raw values, etc.), consult `../../references/troubleshooting.md` before patching symptoms.
|
|
69
90
|
- 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.
|