openxiangda 1.0.21 → 1.0.22
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/lib/cli.js +452 -0
- package/openxiangda-skills/SKILL.md +1 -0
- package/openxiangda-skills/references/automation-v3.md +2 -0
- package/openxiangda-skills/references/connector-resources.md +3 -0
- package/openxiangda-skills/references/notifications.md +80 -0
- package/openxiangda-skills/references/openxiangda-api.md +45 -0
- package/openxiangda-skills/references/pages/page-sdk.md +1 -0
- package/openxiangda-skills/skills/openxiangda-page/SKILL.md +2 -0
- package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +2 -0
- package/package.json +1 -1
- package/packages/sdk/dist/runtime/index.cjs +34 -2
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.d.mts +66 -1
- package/packages/sdk/dist/runtime/index.d.ts +66 -1
- package/packages/sdk/dist/runtime/index.mjs +34 -2
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Notification Resources
|
|
2
|
+
|
|
3
|
+
Use notification resources when a page, workflow, or automation needs reusable message templates.
|
|
4
|
+
|
|
5
|
+
AI generation rule: declare notification resources first, then call `sdk.notification` in code pages or `ctx.notification` in JS_CODE. Do not hardcode `/api/notification-config/*` or store channel credentials in source.
|
|
6
|
+
|
|
7
|
+
## Resource Files
|
|
8
|
+
|
|
9
|
+
Place JSON under `src/resources/notifications/`.
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"templates": [
|
|
14
|
+
{
|
|
15
|
+
"code": "reservation_reminder",
|
|
16
|
+
"name": "预约提醒",
|
|
17
|
+
"content": "{{title}}",
|
|
18
|
+
"variables": ["title", "instrumentName", "startTime"],
|
|
19
|
+
"channelsConfig": {
|
|
20
|
+
"inapp": {
|
|
21
|
+
"enabled": true,
|
|
22
|
+
"content": "{{instrumentName}} 将于 {{startTime}} 开始"
|
|
23
|
+
},
|
|
24
|
+
"dingding": {
|
|
25
|
+
"enabled": true,
|
|
26
|
+
"content": "{{title}}"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
],
|
|
31
|
+
"typeConfigs": [
|
|
32
|
+
{
|
|
33
|
+
"notificationType": "reservation_reminder",
|
|
34
|
+
"templateCode": "reservation_reminder",
|
|
35
|
+
"enabled": true,
|
|
36
|
+
"priority": 0
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
For form-level notifications, add `level: "form"` and `formCode` to both the template and type config. Prefer `formCode`; the CLI resolves `formUuid` per profile.
|
|
43
|
+
|
|
44
|
+
Allowed channels: `inapp`, `email`, `dingding`, `wechat`, `thirdparty_todo`.
|
|
45
|
+
|
|
46
|
+
Do not include `token`, `secret`, `password`, `authorization`, `auth`, `credential`, or `headers` fields. Platform admins configure channel credentials outside resources.
|
|
47
|
+
|
|
48
|
+
## Runtime Calls
|
|
49
|
+
|
|
50
|
+
Code pages:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
await sdk.notification.sendByType({
|
|
54
|
+
notificationType: "reservation_reminder",
|
|
55
|
+
recipientId: userId,
|
|
56
|
+
payload: {
|
|
57
|
+
title: "预约提醒",
|
|
58
|
+
instrumentName,
|
|
59
|
+
startTime,
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Automation or workflow JS_CODE:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
export default async function notify(ctx) {
|
|
68
|
+
await ctx.notification.sendByType({
|
|
69
|
+
notificationType: "reservation_reminder",
|
|
70
|
+
recipientId: ctx.operator.userId,
|
|
71
|
+
payload: {
|
|
72
|
+
title: "预约提醒",
|
|
73
|
+
instrumentName: ctx.formData.current.instrument_name,
|
|
74
|
+
startTime: ctx.formData.current.start_time,
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Use `work_notification` for simple declarative notifications. Use JS_CODE only for dynamic recipients, conditional sending, or payload assembly.
|
|
@@ -205,6 +205,51 @@ Requires Bearer token. Deletes a menu item.
|
|
|
205
205
|
|
|
206
206
|
Requires Bearer token. Updates menu sorting and parent relationships in batch.
|
|
207
207
|
|
|
208
|
+
## Notifications
|
|
209
|
+
|
|
210
|
+
### POST `/apps/:appType/notifications/send-by-type`
|
|
211
|
+
|
|
212
|
+
Requires Bearer token. Sends a notification in the current app scope.
|
|
213
|
+
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"notificationType": "reservation_reminder",
|
|
217
|
+
"recipientId": "user-id",
|
|
218
|
+
"payload": {
|
|
219
|
+
"title": "预约提醒"
|
|
220
|
+
},
|
|
221
|
+
"channels": ["inapp"]
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### POST `/apps/:appType/notifications/batch-send-by-type`
|
|
226
|
+
|
|
227
|
+
Requires Bearer token. Sends one notification type to multiple recipients.
|
|
228
|
+
|
|
229
|
+
### GET `/apps/:appType/notifications/templates`
|
|
230
|
+
|
|
231
|
+
Requires Bearer token. Lists app/form notification templates.
|
|
232
|
+
|
|
233
|
+
### PUT `/apps/:appType/notifications/templates/:code`
|
|
234
|
+
|
|
235
|
+
Requires app admin permission. Upserts an app/form notification template by code.
|
|
236
|
+
|
|
237
|
+
### POST `/apps/:appType/notifications/templates/preview`
|
|
238
|
+
|
|
239
|
+
Requires Bearer token. Body uses `templateCode` or `templateId` plus `payload`.
|
|
240
|
+
|
|
241
|
+
### GET `/apps/:appType/notifications/type-configs`
|
|
242
|
+
|
|
243
|
+
Requires Bearer token. Lists notification type bindings.
|
|
244
|
+
|
|
245
|
+
### GET `/apps/:appType/notifications/type-configs/:notificationType`
|
|
246
|
+
|
|
247
|
+
Requires Bearer token. Resolves the active binding by notification type and optional `formUuid`.
|
|
248
|
+
|
|
249
|
+
### PUT `/apps/:appType/notifications/type-configs/:notificationType`
|
|
250
|
+
|
|
251
|
+
Requires app admin permission. Upserts a binding with `templateCode` or `templateId`.
|
|
252
|
+
|
|
208
253
|
### GET `/apps/:appType/workflows`
|
|
209
254
|
|
|
210
255
|
Requires Bearer token. Lists workflow definitions in the app. Supports `formUuid`, `isPublished`, `page`, and `pageSize` query parameters.
|
|
@@ -7,6 +7,7 @@ Guidelines:
|
|
|
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
9
|
- 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.
|
|
10
|
+
- 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`.
|
|
10
11
|
- For the current user's department hierarchy, use `sdk.department.getCurrentUserParentDepartments()`; do not hardcode `GET /department/:id/parentDepartments` in page code.
|
|
11
12
|
- Keep API calls behind small local functions so generated UI stays testable.
|
|
12
13
|
- Treat user context and tenant context as runtime-provided values.
|
|
@@ -42,6 +42,7 @@ Read these references only when editing page code:
|
|
|
42
42
|
- `../../references/pages/workspace-structure.md`
|
|
43
43
|
- `../../references/pages/app-shell.md` — formal backend / PC portal / mobile portal entry pattern. Read before creating any user-facing main entry or admin console.
|
|
44
44
|
- `../../references/pages/page-sdk.md`
|
|
45
|
+
- `../../references/notifications.md` — notification resources and `sdk.notification` usage. Read before adding reminders, alerts, or message templates to a page.
|
|
45
46
|
- `../../references/pages/publish-flow.md`
|
|
46
47
|
- `../../references/style-system.md` — three-layer style architecture, CSS namespace, and the no-hardcoded-color rule. Read before writing any page CSS or Tailwind class.
|
|
47
48
|
- `../../references/architecture-patterns.md` — CRUD data flow, `DataManagementList` pattern, and recommended `src/pages/<pageCode>/` layout. Read before scaffolding a new page or list view.
|
|
@@ -54,6 +55,7 @@ Read these references only when editing page code:
|
|
|
54
55
|
- 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`.
|
|
55
56
|
- Store live `pageId`, `routeKey`, and `legacyFormUuid` under the current profile only.
|
|
56
57
|
- Use `openxiangda/runtime` for platform data access instead of hardcoding backend URLs in page code.
|
|
58
|
+
- For reminders, alerts, and business messages, declare `src/resources/notifications/` first and call `sdk.notification`; do not hardcode notification API URLs.
|
|
57
59
|
- Named imports from `@ant-design/icons` are supported by the `openxiangda` workspace build proxy, which enumerates icon module exports at runtime.
|
|
58
60
|
- Publish through `openxiangda workspace publish --profile <name>` unless there is a specific repair reason to call `page publish` directly.
|
|
59
61
|
- Do not create custom code pages by writing platform schema directly. The source is React workspace code plus `page.config.ts`.
|
|
@@ -76,6 +76,7 @@ Inside the TypeScript script, prefer `export default async function (ctx) {}` or
|
|
|
76
76
|
|
|
77
77
|
- Context: `ctx.triggerEvent`, `ctx.formData`, `ctx.workflowData`, `ctx.operator`, `ctx.app`, `ctx.variables`, and `ctx.node`.
|
|
78
78
|
- Data/process methods: `ctx.methods.queryOneData`, `queryManyData`, `updateOneData`, `updateDataByFormInstanceId`, `updateManyData`, `createOneData`, `terminateProcess`, and `getAllParentDepartments`.
|
|
79
|
+
- Notification bridge: `ctx.notification.sendByType`, `batchSendByType`, `findConfig`, and `previewTemplate`. Declare templates in `src/resources/notifications/` before using custom `notificationType`.
|
|
79
80
|
- Platform API bridge: `ctx.platform.api.get/post/put/patch/delete/request` for `/openxiangda-api/v1`.
|
|
80
81
|
- Node runtime helpers: `require`, `process`, `Buffer`, `ctx.utils`, `ctx.utils.http`, and `ctx.console`.
|
|
81
82
|
|
|
@@ -102,5 +103,6 @@ Use `automation disable` before risky edits. Published automations create a draf
|
|
|
102
103
|
|
|
103
104
|
- Workflow v3 JSON: `../../references/workflow-v3.md`
|
|
104
105
|
- Automation v3 JSON and triggers: `../../references/automation-v3.md`
|
|
106
|
+
- Notification resources and runtime calls: `../../references/notifications.md`
|
|
105
107
|
- API fields: `../../references/openxiangda-api.md`
|
|
106
108
|
- Profile-isolated IDs: `../../references/workspace-state.md`
|
package/package.json
CHANGED
|
@@ -65,6 +65,9 @@ var resolveAppType = (context, explicitAppType) => {
|
|
|
65
65
|
return appType;
|
|
66
66
|
};
|
|
67
67
|
var buildAppPath = (context, explicitAppType, suffix) => `/${resolveAppType(context, explicitAppType)}${suffix}`;
|
|
68
|
+
var buildOpenXiangdaAppPath = (context, explicitAppType, suffix) => `/openxiangda-api/v1/apps/${encodePathSegment(
|
|
69
|
+
resolveAppType(context, explicitAppType)
|
|
70
|
+
)}${suffix}`;
|
|
68
71
|
var encodePathSegment = (value) => encodeURIComponent(String(value));
|
|
69
72
|
var getHeaderValue = (headers, name) => {
|
|
70
73
|
if (!headers) {
|
|
@@ -1077,7 +1080,11 @@ var createPageSdk = (context) => {
|
|
|
1077
1080
|
};
|
|
1078
1081
|
const notification = {
|
|
1079
1082
|
sendByType: (params) => request({
|
|
1080
|
-
path:
|
|
1083
|
+
path: buildOpenXiangdaAppPath(
|
|
1084
|
+
context,
|
|
1085
|
+
params.appType,
|
|
1086
|
+
"/notifications/send-by-type"
|
|
1087
|
+
),
|
|
1081
1088
|
method: "post",
|
|
1082
1089
|
body: {
|
|
1083
1090
|
...params,
|
|
@@ -1085,7 +1092,32 @@ var createPageSdk = (context) => {
|
|
|
1085
1092
|
}
|
|
1086
1093
|
}),
|
|
1087
1094
|
batchSendByType: (params) => request({
|
|
1088
|
-
path:
|
|
1095
|
+
path: buildOpenXiangdaAppPath(
|
|
1096
|
+
context,
|
|
1097
|
+
params.appType,
|
|
1098
|
+
"/notifications/batch-send-by-type"
|
|
1099
|
+
),
|
|
1100
|
+
method: "post",
|
|
1101
|
+
body: {
|
|
1102
|
+
...params,
|
|
1103
|
+
appType: resolveAppType(context, params.appType)
|
|
1104
|
+
}
|
|
1105
|
+
}),
|
|
1106
|
+
findConfig: (notificationType, params = {}) => request({
|
|
1107
|
+
path: buildOpenXiangdaAppPath(
|
|
1108
|
+
context,
|
|
1109
|
+
params.appType,
|
|
1110
|
+
`/notifications/type-configs/${encodePathSegment(notificationType)}`
|
|
1111
|
+
),
|
|
1112
|
+
method: "get",
|
|
1113
|
+
query: params.formUuid ? { formUuid: params.formUuid } : void 0
|
|
1114
|
+
}),
|
|
1115
|
+
previewTemplate: (params) => request({
|
|
1116
|
+
path: buildOpenXiangdaAppPath(
|
|
1117
|
+
context,
|
|
1118
|
+
params.appType,
|
|
1119
|
+
"/notifications/templates/preview"
|
|
1120
|
+
),
|
|
1089
1121
|
method: "post",
|
|
1090
1122
|
body: {
|
|
1091
1123
|
...params,
|