openxiangda 1.0.26 → 1.0.28
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 +16 -0
- package/lib/cli.js +324 -17
- package/openxiangda-skills/SKILL.md +1 -1
- package/openxiangda-skills/references/automation-v3.md +56 -0
- package/openxiangda-skills/references/component-guide.md +9 -9
- package/openxiangda-skills/references/openxiangda-api.md +4 -0
- package/openxiangda-skills/references/style-system.md +121 -114
- package/openxiangda-skills/references/workflow-v3.md +44 -0
- package/openxiangda-skills/skills/openxiangda-page/SKILL.md +2 -2
- package/openxiangda-skills/skills/openxiangda-workflow-automation/SKILL.md +4 -0
- package/package.json +6 -1
- package/packages/sdk/dist/workflow/index.cjs +230 -0
- package/packages/sdk/dist/workflow/index.cjs.map +1 -0
- package/packages/sdk/dist/workflow/index.d.mts +61 -0
- package/packages/sdk/dist/workflow/index.d.ts +61 -0
- package/packages/sdk/dist/workflow/index.mjs +209 -0
- package/packages/sdk/dist/workflow/index.mjs.map +1 -0
- package/templates/sy-lowcode-app-workspace/examples/best-practices/design-style.md +4 -0
- package/templates/sy-lowcode-app-workspace/scripts/build-js-code.mjs +56 -16
- package/templates/sy-lowcode-app-workspace/tsconfig.js-code-nodes.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# OpenXiangda 样式体系参考
|
|
2
|
-
|
|
3
|
-
> 本文档面向 AI Agent
|
|
1
|
+
# OpenXiangda 样式体系参考
|
|
2
|
+
|
|
3
|
+
> 本文档面向 AI Agent,提供代码页面/表单/工作流自定义节点的推荐样式基线。平台 CSS 变量与语义类是优先选择,不是唯一选择;当业务视觉、品牌表达、图表、看板、动效或复杂布局需要更精确控制时,可以使用 Tailwind 普通工具类、Tailwind 任意值、局部 CSS、页面级 CSS 变量或必要的 inline style。
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
└──────────────────────────────────────────────────────────────┘
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
**核心原则**:平台视觉基线优先来源于 Layer 1 的 CSS Variables;AntD 与 Tailwind 默认消费这套变量。业务页面可以在 `.sy-app-workspace` 命名空间内扩展页面级样式,不要求所有视觉值都必须来自内置 Token。
|
|
36
36
|
|
|
37
37
|
### 1.2 为什么不使用 Shadow DOM
|
|
38
38
|
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
|
|
55
55
|
---
|
|
56
56
|
|
|
57
|
-
## 2. Layer 1:CSS Variables 设计 Token
|
|
58
|
-
|
|
59
|
-
>
|
|
57
|
+
## 2. Layer 1:CSS Variables 设计 Token
|
|
58
|
+
|
|
59
|
+
> 推荐基线。**所有平台变量同时挂载在 `:root` 与 `.sy-app-workspace`**,前者用于全局可用,后者保证命名空间生效时不依赖根选择器。页面可以继续定义自己的局部变量,例如 `--sales-dashboard-accent`、`--kanban-column-width`。
|
|
60
60
|
|
|
61
61
|
```css
|
|
62
62
|
:root, .sy-app-workspace {
|
|
@@ -199,9 +199,9 @@ export function AppThemeProvider({ children }: { children: React.ReactNode }) {
|
|
|
199
199
|
|
|
200
200
|
---
|
|
201
201
|
|
|
202
|
-
## 4. Layer 3:Tailwind 语义化工具类
|
|
203
|
-
|
|
204
|
-
`tailwind-preset.ts` 基于 CSS Variables
|
|
202
|
+
## 4. Layer 3:Tailwind 语义化工具类
|
|
203
|
+
|
|
204
|
+
`tailwind-preset.ts` 基于 CSS Variables 扩展语义化类。语义类适合常规后台页面、表单、列表和状态展示;普通 Tailwind 工具类与任意值适合特殊布局、品牌视觉、图表容器、复杂动效和一次性精调。
|
|
205
205
|
|
|
206
206
|
### 4.1 颜色类
|
|
207
207
|
|
|
@@ -247,110 +247,117 @@ export function AppThemeProvider({ children }: { children: React.ReactNode }) {
|
|
|
247
247
|
| `text-xl-sy` | `font-size: var(--sy-font-size-xl)` |
|
|
248
248
|
| `text-2xl-sy` | `font-size: var(--sy-font-size-2xl)` |
|
|
249
249
|
|
|
250
|
-
> 通用 Tailwind 数值类(如 `p-4`、`text-sm
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## 5.
|
|
255
|
-
|
|
256
|
-
| # |
|
|
257
|
-
|---|---|---|---|
|
|
258
|
-
| 1 |
|
|
259
|
-
| 2 |
|
|
260
|
-
| 3 |
|
|
261
|
-
| 4 |
|
|
262
|
-
| 5 |
|
|
263
|
-
| 6 |
|
|
264
|
-
| 7 |
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## 6.
|
|
269
|
-
|
|
270
|
-
### 示例 1:主操作按钮的容器
|
|
271
|
-
|
|
272
|
-
```tsx
|
|
273
|
-
//
|
|
274
|
-
<div
|
|
275
|
-
<
|
|
276
|
-
</div>
|
|
277
|
-
|
|
278
|
-
//
|
|
279
|
-
<div
|
|
280
|
-
<
|
|
281
|
-
</div>
|
|
282
|
-
```
|
|
283
|
-
|
|
284
|
-
### 示例 2:表单字段布局
|
|
285
|
-
|
|
286
|
-
```tsx
|
|
287
|
-
//
|
|
288
|
-
<div className="flex flex-col gap-
|
|
289
|
-
<Input
|
|
290
|
-
<Input
|
|
291
|
-
</div>
|
|
292
|
-
|
|
293
|
-
//
|
|
294
|
-
<div className="flex flex-col gap-
|
|
295
|
-
<Input />
|
|
296
|
-
<Input />
|
|
297
|
-
</div>
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### 示例 3:状态文案
|
|
301
|
-
|
|
302
|
-
```tsx
|
|
303
|
-
//
|
|
304
|
-
<span
|
|
305
|
-
<span
|
|
306
|
-
|
|
307
|
-
//
|
|
308
|
-
<span className="text-
|
|
309
|
-
<span
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
### 示例 4:卡片容器
|
|
313
|
-
|
|
314
|
-
```tsx
|
|
315
|
-
//
|
|
316
|
-
<div
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
```
|
|
325
|
-
|
|
326
|
-
### 示例 5:次要文本 + 提示
|
|
327
|
-
|
|
328
|
-
```tsx
|
|
329
|
-
//
|
|
330
|
-
<p
|
|
331
|
-
|
|
332
|
-
//
|
|
333
|
-
<p className="text-
|
|
334
|
-
```
|
|
335
|
-
|
|
336
|
-
### 示例 6:自定义代码节点的 CSS(局部样式表)
|
|
337
|
-
|
|
338
|
-
```css
|
|
339
|
-
/*
|
|
340
|
-
.my-node-card {
|
|
341
|
-
background: #ffffff;
|
|
342
|
-
border: 1px solid #d9d9d9;
|
|
343
|
-
padding: 16px;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/*
|
|
347
|
-
.sy-app-workspace .my-node-card {
|
|
348
|
-
background: var(--sy-color-bg-container);
|
|
349
|
-
border: 1px solid var(--sy-color-border);
|
|
350
|
-
padding: var(--sy-spacing-md);
|
|
351
|
-
border-radius: var(--sy-radius-md);
|
|
352
|
-
}
|
|
353
|
-
|
|
250
|
+
> 通用 Tailwind 数值类(如 `p-4`、`text-sm`)和任意值(如 `grid-cols-[240px_1fr]`、`bg-[#0f766e]`)都可以使用。常规业务组件优先使用语义类,特殊页面按实际视觉需求选择更合适的 Tailwind/CSS 写法。
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## 5. 推荐顺序与硬边界
|
|
255
|
+
|
|
256
|
+
| # | 场景 | 推荐做法 | 允许的扩展 |
|
|
257
|
+
|---|---|---|---|
|
|
258
|
+
| 1 | 常规后台、列表、表单、详情页 | 优先用语义类、平台 CSS 变量和 antd token,保证与平台一致 | 可用 `p-4`、`gap-6`、`text-sm` 等 Tailwind 普通类做快速布局 |
|
|
259
|
+
| 2 | 品牌化首页、门户、看板、数据大屏、营销视觉 | 按视觉目标设计,不要为了套 Token 牺牲效果 | 可用 Tailwind 任意值、CSS 渐变、图片背景、页面级变量、局部 CSS |
|
|
260
|
+
| 3 | 精确布局、复杂 Grid、图表容器、动效 | Tailwind 普通类/任意值和 `styles.css` 都可以直接使用 | 例如 `grid-cols-[280px_1fr]`、`h-[calc(100vh-64px)]`、`transition-[height]` |
|
|
261
|
+
| 4 | 需要运行时动态值 | 少量 inline style 可以使用,尤其是动态尺寸、颜色、坐标、图表变量 | 避免把大段静态样式写进 inline style,静态样式优先放到 class/CSS |
|
|
262
|
+
| 5 | antd 主题 | 优先通过 `ConfigProvider.theme`、CSS 变量和 `className` 控制 | 如确实要覆盖内部 class,必须限定在页面命名空间内,并接受升级风险 |
|
|
263
|
+
| 6 | antd 弹层、Drawer、Modal、DatePicker、Select | 这是硬要求:通过 `getPopupContainer` 锚定到 `.sy-app-workspace` 或就近容器 | 否则弹层可能丢样式或被宿主页面污染 |
|
|
264
|
+
| 7 | CSS 作用域 | 这是硬要求:业务 CSS 必须在 `.sy-app-workspace` 或页面根类下收敛作用域 | 避免写全局裸选择器污染宿主平台 |
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## 6. 推荐示例与可接受变体
|
|
269
|
+
|
|
270
|
+
### 示例 1:主操作按钮的容器
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
// 常规后台表单:推荐用语义类 + antd 组件
|
|
274
|
+
<div className="bg-container p-form rounded-form">
|
|
275
|
+
<Button type="primary">提交</Button>
|
|
276
|
+
</div>
|
|
277
|
+
|
|
278
|
+
// 品牌化或特殊视觉:可以使用 Tailwind 任意值 / 自定义 CSS
|
|
279
|
+
<div style={{ background: '#fff', padding: 24, borderRadius: 6 }}>
|
|
280
|
+
<button style={{ background: '#1677ff', color: '#fff' }}>提交</button>
|
|
281
|
+
</div>
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 示例 2:表单字段布局
|
|
285
|
+
|
|
286
|
+
```tsx
|
|
287
|
+
// 推荐:表单语义类
|
|
288
|
+
<div className="flex flex-col gap-form p-form">
|
|
289
|
+
<Input />
|
|
290
|
+
<Input />
|
|
291
|
+
</div>
|
|
292
|
+
|
|
293
|
+
// 可接受:特殊布局精调用 Tailwind 普通类 / 任意值
|
|
294
|
+
<div className="flex flex-col gap-[18px] p-6">
|
|
295
|
+
<Input className="h-[32px]" />
|
|
296
|
+
<Input className="h-[32px]" />
|
|
297
|
+
</div>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### 示例 3:状态文案
|
|
301
|
+
|
|
302
|
+
```tsx
|
|
303
|
+
// 推荐:平台状态语义
|
|
304
|
+
<span className="text-success">已通过</span>
|
|
305
|
+
<span className="text-error">已驳回</span>
|
|
306
|
+
|
|
307
|
+
// 可接受:页面专属状态色
|
|
308
|
+
<span className="text-[#16a34a]">已通过</span>
|
|
309
|
+
<span style={{ color: riskLevelColor }}>风险等级</span>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### 示例 4:卡片容器
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
// 推荐:语义类
|
|
316
|
+
<div className="bg-container shadow-card rounded-card">...</div>
|
|
317
|
+
|
|
318
|
+
// 可接受:特殊卡片视觉
|
|
319
|
+
<div style={{
|
|
320
|
+
background: '#fff',
|
|
321
|
+
boxShadow: '0 6px 16px rgba(0,0,0,0.08)',
|
|
322
|
+
borderRadius: 8
|
|
323
|
+
}}>...</div>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### 示例 5:次要文本 + 提示
|
|
327
|
+
|
|
328
|
+
```tsx
|
|
329
|
+
// 推荐:层级语义
|
|
330
|
+
<p className="text-secondary text-sm-sy">提示信息</p>
|
|
331
|
+
|
|
332
|
+
// 可接受:需要匹配图表或品牌视觉时直接设定
|
|
333
|
+
<p className="text-[13px] text-slate-500">提示信息</p>
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
### 示例 6:自定义代码节点的 CSS(局部样式表)
|
|
337
|
+
|
|
338
|
+
```css
|
|
339
|
+
/* 避免:全局裸选择器,容易污染宿主页面 */
|
|
340
|
+
.my-node-card {
|
|
341
|
+
background: #ffffff;
|
|
342
|
+
border: 1px solid #d9d9d9;
|
|
343
|
+
padding: 16px;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* 推荐:限定在平台命名空间或页面根类下 */
|
|
347
|
+
.sy-app-workspace .my-node-card {
|
|
348
|
+
background: var(--sy-color-bg-container);
|
|
349
|
+
border: 1px solid var(--sy-color-border);
|
|
350
|
+
padding: var(--sy-spacing-md);
|
|
351
|
+
border-radius: var(--sy-radius-md);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/* 可接受:页面专属视觉值,只要作用域收敛 */
|
|
355
|
+
.sy-app-workspace .sales-dashboard .my-node-card {
|
|
356
|
+
background: linear-gradient(135deg, #0f766e, #0ea5e9);
|
|
357
|
+
border-radius: 14px;
|
|
358
|
+
padding: 20px;
|
|
359
|
+
}
|
|
360
|
+
```
|
|
354
361
|
|
|
355
362
|
---
|
|
356
363
|
|
|
@@ -2,6 +2,50 @@
|
|
|
2
2
|
|
|
3
3
|
Workflow definitions are JSON objects saved by `openxiangda workflow create`.
|
|
4
4
|
|
|
5
|
+
AI-authored workflows should prefer compile-time TypeScript SDK when the user does not need canvas editing. The SDK compiles local `workflow.ts` into the current v3 graph JSON, so the backend still uses the existing workflow engine for approval tasks, copy tasks, callback waits, branch advancement, operation logs, and process completion events.
|
|
6
|
+
|
|
7
|
+
Example `src/workflows/expense_approval/workflow.ts`:
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { defineWorkflow } from "openxiangda/workflow";
|
|
11
|
+
|
|
12
|
+
export default defineWorkflow({
|
|
13
|
+
build(flow) {
|
|
14
|
+
const start = flow.start();
|
|
15
|
+
const approve = flow.approval("manager_approval", {
|
|
16
|
+
label: "主管审批",
|
|
17
|
+
approverType: "ext_target_approval",
|
|
18
|
+
approvals: ["USER_MANAGER"],
|
|
19
|
+
approvalNames: ["主管"],
|
|
20
|
+
multiApprove: "or",
|
|
21
|
+
});
|
|
22
|
+
const copy = flow.copy("copy_finance", {
|
|
23
|
+
label: "抄送财务",
|
|
24
|
+
approverType: "ext_target_approval",
|
|
25
|
+
approvals: ["USER_FINANCE"],
|
|
26
|
+
approvalNames: ["财务"],
|
|
27
|
+
});
|
|
28
|
+
const end = flow.end();
|
|
29
|
+
flow.sequence(start, approve, copy, end);
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Resource manifest:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{
|
|
38
|
+
"code": "expense_approval",
|
|
39
|
+
"formCode": "expense",
|
|
40
|
+
"workflowFile": "../../../workflows/expense_approval/workflow.ts",
|
|
41
|
+
"definitionFile": "definition.v3.json",
|
|
42
|
+
"previewFile": "preview.json",
|
|
43
|
+
"publish": true
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
During `openxiangda resource publish`, the CLI compiles `workflowFile`, writes `definitionFile` and `previewFile` when configured, sends v3 `definitionJson` to the backend, and stores the preview in `viewJson` for read-only frontend display.
|
|
48
|
+
|
|
5
49
|
Minimum shape:
|
|
6
50
|
|
|
7
51
|
```json
|
|
@@ -60,7 +60,7 @@ Read these references only when editing page code:
|
|
|
60
60
|
- `../../references/pages/page-sdk.md`
|
|
61
61
|
- `../../references/notifications.md` — notification resources and `sdk.notification` usage. Read before adding reminders, alerts, or message templates to a page.
|
|
62
62
|
- `../../references/pages/publish-flow.md`
|
|
63
|
-
- `../../references/style-system.md` — three-layer style architecture, CSS namespace, and
|
|
63
|
+
- `../../references/style-system.md` — three-layer style architecture, CSS namespace, and flexible Tailwind/CSS guidance. Read before writing substantial page CSS or Tailwind classes.
|
|
64
64
|
- `../../references/architecture-patterns.md` — CRUD data flow, `DataManagementList` pattern, and recommended `src/pages/<pageCode>/` layout. Read before scaffolding a new page or list view.
|
|
65
65
|
- `../../references/component-guide.md` — when to pick platform components, raw Ant Design, or custom components. Read before introducing a new component.
|
|
66
66
|
- `../../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.
|
|
@@ -82,7 +82,7 @@ Read these references only when editing page code:
|
|
|
82
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.
|
|
83
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.
|
|
84
84
|
- For prod, explicitly run with `--profile prod`; never rely on the current profile for release operations.
|
|
85
|
-
- Follow the style system in `../../references/style-system.md`:
|
|
85
|
+
- Follow the style system in `../../references/style-system.md`: prefer platform CSS variables, semantic Tailwind classes, and the page CSS namespace for consistency, but do not force every visual value through built-in tokens. Tailwind ordinary utilities, Tailwind arbitrary values, local CSS, page-level CSS variables, and small dynamic inline styles are allowed when they better match the product design.
|
|
86
86
|
- For list / detail / CRUD pages, follow `../../references/architecture-patterns.md` (e.g. `DataManagementList`) before writing custom data-fetching loops.
|
|
87
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`.
|
|
88
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.
|
|
@@ -52,6 +52,10 @@ Use `workflow pull` to inspect the live definition. Use logical workflow codes l
|
|
|
52
52
|
|
|
53
53
|
JS_CODE is the backend execution escape hatch for workflow and automation. Use it when the logic must run on the server after a backend trigger, such as a fixed cron schedule, a form date-field schedule, a form submit/update/delete/field-change event, or a workflow approval/process event. It is appropriate for cross-form data queries, create/update/batch update operations, process termination, platform API calls, external HTTP calls, and complex orchestration that the frontend cannot handle reliably.
|
|
54
54
|
|
|
55
|
+
For new AI-authored automations, prefer code-first `automation_code_ts` resources instead of visual v3 graph definitions. Put the source in `src/automations/<resourceCode>/index.ts`, define `definition.code.json` with `kind: "automation_code_ts"`, and provide `preview.json` for read-only frontend display. Use `ctx.logger.debug/info/warn/error(message, data?)` at every important step; OpenXiangda can inspect logs with `automation executions`, `automation logs`, and `automation diagnose`.
|
|
56
|
+
|
|
57
|
+
For new AI-authored workflows where users do not need canvas editing, prefer compile-time `workflow.ts` using `openxiangda/workflow`. The CLI compiles it to v3 `definitionJson` and `preview.json`; the backend still runs the normal workflow engine for approval tasks, copy tasks, callback waits, branch advancement, and process records.
|
|
58
|
+
|
|
55
59
|
Do not use JS_CODE for simple UI interactions, ordinary form validation, display-only page behavior, or logic that belongs in a normal React code page. For non-trivial backend logic, prefer JS_CODE V2 trusted Node scripts over large inline snippets. AI-authored JS_CODE source must be TypeScript:
|
|
56
60
|
|
|
57
61
|
1. Put source in `sy-lowcode-app-workspace/src/js-code-nodes/<scriptCode>/index.ts`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.28",
|
|
4
4
|
"description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"bin": {
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
"import": "./packages/sdk/dist/build/index.mjs",
|
|
27
27
|
"require": "./packages/sdk/dist/build/index.cjs"
|
|
28
28
|
},
|
|
29
|
+
"./workflow": {
|
|
30
|
+
"types": "./packages/sdk/dist/workflow/index.d.ts",
|
|
31
|
+
"import": "./packages/sdk/dist/workflow/index.mjs",
|
|
32
|
+
"require": "./packages/sdk/dist/workflow/index.cjs"
|
|
33
|
+
},
|
|
29
34
|
"./tailwind-preset": {
|
|
30
35
|
"types": "./packages/sdk/dist/styles/tailwind-preset.d.ts",
|
|
31
36
|
"import": "./packages/sdk/dist/styles/tailwind-preset.mjs",
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// packages/sdk/src/workflow/index.ts
|
|
21
|
+
var workflow_exports = {};
|
|
22
|
+
__export(workflow_exports, {
|
|
23
|
+
WorkflowBuilder: () => WorkflowBuilder,
|
|
24
|
+
defineWorkflow: () => defineWorkflow
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(workflow_exports);
|
|
27
|
+
function sanitizeId(value) {
|
|
28
|
+
return String(value || "").trim().replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
29
|
+
}
|
|
30
|
+
function createPosition(index) {
|
|
31
|
+
return { x: 400, y: 100 + index * 150 };
|
|
32
|
+
}
|
|
33
|
+
var WorkflowBuilder = class {
|
|
34
|
+
constructor(meta = {}) {
|
|
35
|
+
this.meta = meta;
|
|
36
|
+
this.nodes = [];
|
|
37
|
+
this.edges = [];
|
|
38
|
+
this.flowConfig = {};
|
|
39
|
+
this.globalSettings = {};
|
|
40
|
+
this.data = {
|
|
41
|
+
retrieveSingle: (id, data) => this.node("data_retrieve_single", id, {
|
|
42
|
+
type: "data_retrieve_single",
|
|
43
|
+
label: data.label || "\u83B7\u53D6\u5355\u6761\u6570\u636E",
|
|
44
|
+
filterType: data.filterType || "condition",
|
|
45
|
+
...data
|
|
46
|
+
}),
|
|
47
|
+
retrieveBatch: (id, data) => this.node("data_retrieve_batch", id, {
|
|
48
|
+
type: "data_retrieve_batch",
|
|
49
|
+
label: data.label || "\u83B7\u53D6\u591A\u6761\u6570\u636E",
|
|
50
|
+
filterType: data.filterType || "condition",
|
|
51
|
+
...data
|
|
52
|
+
}),
|
|
53
|
+
create: (id, data) => this.node("data_create", id, {
|
|
54
|
+
type: "data_create",
|
|
55
|
+
label: data.label || "\u65B0\u589E\u6570\u636E",
|
|
56
|
+
insertType: data.insertType || "form",
|
|
57
|
+
assignments: data.assignments || [],
|
|
58
|
+
...data
|
|
59
|
+
}),
|
|
60
|
+
update: (id, data) => this.node("data_update", id, {
|
|
61
|
+
type: "data_update",
|
|
62
|
+
label: data.label || "\u66F4\u65B0\u6570\u636E",
|
|
63
|
+
updateType: data.updateType || "direct_form",
|
|
64
|
+
assignments: data.assignments || [],
|
|
65
|
+
noneOperation: data.noneOperation || "ignored",
|
|
66
|
+
...data
|
|
67
|
+
})
|
|
68
|
+
};
|
|
69
|
+
this.globalSettings = { ...meta.globalSettings || {} };
|
|
70
|
+
}
|
|
71
|
+
start(id = "start", data = {}) {
|
|
72
|
+
return this.node("start", id, { label: "\u5F00\u59CB\u8282\u70B9", ...data });
|
|
73
|
+
}
|
|
74
|
+
end(id = "end", data = {}) {
|
|
75
|
+
return this.node("end", id, { label: "\u7ED3\u675F\u8282\u70B9", ...data });
|
|
76
|
+
}
|
|
77
|
+
approval(id, data) {
|
|
78
|
+
return this.node("approval", id, {
|
|
79
|
+
label: data.label || "\u5BA1\u6279",
|
|
80
|
+
value: data.value || "",
|
|
81
|
+
approverType: data.approverType || "ext_target_approval",
|
|
82
|
+
approvals: data.approvals || [],
|
|
83
|
+
approvalNames: data.approvalNames || [],
|
|
84
|
+
multiApprove: data.multiApprove || "or",
|
|
85
|
+
...data
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
copy(id, data) {
|
|
89
|
+
return this.node("copy", id, {
|
|
90
|
+
label: data.label || "\u6284\u9001",
|
|
91
|
+
value: data.value || "",
|
|
92
|
+
approverType: data.approverType || "ext_target_approval",
|
|
93
|
+
approvals: data.approvals || [],
|
|
94
|
+
approvalNames: data.approvalNames || [],
|
|
95
|
+
...data
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
jsCode(id, data) {
|
|
99
|
+
return this.node("js_code", id, {
|
|
100
|
+
label: data.label || "JS\u4EE3\u7801\u8282\u70B9",
|
|
101
|
+
runtimeMode: "trusted_node",
|
|
102
|
+
sourceType: data.sourceFile ? "file_snapshot" : data.sourceType || "inline",
|
|
103
|
+
timeout: data.timeout || data.timeoutMs || 3e4,
|
|
104
|
+
...data
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
callbackWait(id, data) {
|
|
108
|
+
return this.node("callback_wait", id, {
|
|
109
|
+
type: "callback_wait",
|
|
110
|
+
label: data.label || "\u56DE\u8C03\u7B49\u5F85",
|
|
111
|
+
timeoutSeconds: data.timeoutSeconds || 86400,
|
|
112
|
+
timeoutStrategy: data.timeoutStrategy || "FAIL",
|
|
113
|
+
...data
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
connectorCall(id, data) {
|
|
117
|
+
return this.node("connector_call", id, {
|
|
118
|
+
type: "connector_call",
|
|
119
|
+
label: data.label || "\u8FDE\u63A5\u5668",
|
|
120
|
+
timeout: data.timeout || 3e4,
|
|
121
|
+
...data
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
workNotification(id, data) {
|
|
125
|
+
return this.node("work_notification", id, {
|
|
126
|
+
label: data.label || "\u5DE5\u4F5C\u901A\u77E5",
|
|
127
|
+
buttonText: data.buttonText || "\u67E5\u770B\u8BE6\u60C5",
|
|
128
|
+
linkType: data.linkType || "current_form",
|
|
129
|
+
...data
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
dingtalkCard(id, data) {
|
|
133
|
+
return this.node("dingtalk_card", id, {
|
|
134
|
+
config: {
|
|
135
|
+
type: "dingtalk_card",
|
|
136
|
+
label: data.label || "\u9489\u9489\u6D88\u606F\u5361\u7247",
|
|
137
|
+
sameFieldStrategy: "create",
|
|
138
|
+
...data.config || data
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
condition(id, data) {
|
|
143
|
+
return this.node("condition_branch", id, {
|
|
144
|
+
type: "condition_branch",
|
|
145
|
+
label: data.label || "\u6761\u4EF6\u5206\u652F",
|
|
146
|
+
condition: data.condition || { ruleType: "group", condition: "AND", rules: [] },
|
|
147
|
+
isElse: data.isElse === true,
|
|
148
|
+
priority: data.priority || "1",
|
|
149
|
+
trueNodeId: data.trueNodeId,
|
|
150
|
+
falseNodeId: data.falseNodeId,
|
|
151
|
+
...data
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
node(type, id, data) {
|
|
155
|
+
const nodeId = sanitizeId(id);
|
|
156
|
+
if (!nodeId) throw new Error("workflow node id is required");
|
|
157
|
+
if (this.nodes.some((node) => node.id === nodeId)) {
|
|
158
|
+
throw new Error(`duplicate workflow node id: ${nodeId}`);
|
|
159
|
+
}
|
|
160
|
+
this.nodes.push({
|
|
161
|
+
id: nodeId,
|
|
162
|
+
type,
|
|
163
|
+
data,
|
|
164
|
+
position: createPosition(this.nodes.length)
|
|
165
|
+
});
|
|
166
|
+
if (Array.isArray(data.fieldPermissions)) {
|
|
167
|
+
this.flowConfig[nodeId] = data.fieldPermissions;
|
|
168
|
+
}
|
|
169
|
+
return nodeId;
|
|
170
|
+
}
|
|
171
|
+
edge(source, target, data = {}) {
|
|
172
|
+
const id = data.id || `edge_${source}_${target}`;
|
|
173
|
+
this.edges.push({
|
|
174
|
+
id,
|
|
175
|
+
source,
|
|
176
|
+
target,
|
|
177
|
+
type: data.type || "custom",
|
|
178
|
+
...data.label ? { label: data.label } : {}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
sequence(...refs) {
|
|
182
|
+
for (let index = 0; index < refs.length - 1; index += 1) {
|
|
183
|
+
this.edge(refs[index], refs[index + 1]);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
setFieldPermissions(nodeId, permissions) {
|
|
187
|
+
this.flowConfig[nodeId] = permissions;
|
|
188
|
+
}
|
|
189
|
+
setGlobalSettings(settings) {
|
|
190
|
+
this.globalSettings = { ...this.globalSettings, ...settings };
|
|
191
|
+
}
|
|
192
|
+
compile() {
|
|
193
|
+
return {
|
|
194
|
+
definitionJson: {
|
|
195
|
+
version: "v3",
|
|
196
|
+
nodes: this.nodes,
|
|
197
|
+
edges: this.edges,
|
|
198
|
+
flowConfig: this.flowConfig,
|
|
199
|
+
globalSettings: this.globalSettings
|
|
200
|
+
},
|
|
201
|
+
previewJson: {
|
|
202
|
+
kind: "workflow_code_preview",
|
|
203
|
+
version: "preview_v1",
|
|
204
|
+
sourceMode: "workflow_code_ts",
|
|
205
|
+
steps: this.nodes.map((node) => ({
|
|
206
|
+
id: node.id,
|
|
207
|
+
type: node.type,
|
|
208
|
+
label: node.data?.label || node.id,
|
|
209
|
+
config: node.data
|
|
210
|
+
})),
|
|
211
|
+
edges: this.edges.map((edge) => ({
|
|
212
|
+
source: edge.source,
|
|
213
|
+
target: edge.target,
|
|
214
|
+
label: edge.label
|
|
215
|
+
}))
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
function defineWorkflow(input) {
|
|
221
|
+
return {
|
|
222
|
+
__openxiangdaWorkflow: true,
|
|
223
|
+
compile() {
|
|
224
|
+
const builder = new WorkflowBuilder(input);
|
|
225
|
+
input.build(builder);
|
|
226
|
+
return builder.compile();
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/workflow/index.ts"],"sourcesContent":["export type WorkflowNodeRef = string;\n\nexport interface WorkflowCompileResult {\n definitionJson: {\n version: \"v3\";\n nodes: any[];\n edges: any[];\n flowConfig: Record<string, any[]>;\n globalSettings: Record<string, any>;\n };\n previewJson: {\n kind: \"workflow_code_preview\";\n version: \"preview_v1\";\n steps: any[];\n edges: any[];\n sourceMode: \"workflow_code_ts\";\n };\n}\n\nexport interface WorkflowDefinitionInput {\n name?: string;\n formCode?: string;\n formUuid?: string;\n globalSettings?: Record<string, any>;\n build: (flow: WorkflowBuilder) => void;\n}\n\ntype NodeOptions = Record<string, any>;\n\nfunction sanitizeId(value: string) {\n return String(value || \"\")\n .trim()\n .replace(/[^a-zA-Z0-9_-]/g, \"_\");\n}\n\nfunction createPosition(index: number) {\n return { x: 400, y: 100 + index * 150 };\n}\n\nexport class WorkflowBuilder {\n private nodes: any[] = [];\n private edges: any[] = [];\n private flowConfig: Record<string, any[]> = {};\n private globalSettings: Record<string, any> = {};\n\n constructor(private readonly meta: Omit<WorkflowDefinitionInput, \"build\"> = {}) {\n this.globalSettings = { ...(meta.globalSettings || {}) };\n }\n\n start(id = \"start\", data: NodeOptions = {}): WorkflowNodeRef {\n return this.node(\"start\", id, { label: \"开始节点\", ...data });\n }\n\n end(id = \"end\", data: NodeOptions = {}): WorkflowNodeRef {\n return this.node(\"end\", id, { label: \"结束节点\", ...data });\n }\n\n approval(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"approval\", id, {\n label: data.label || \"审批\",\n value: data.value || \"\",\n approverType: data.approverType || \"ext_target_approval\",\n approvals: data.approvals || [],\n approvalNames: data.approvalNames || [],\n multiApprove: data.multiApprove || \"or\",\n ...data,\n });\n }\n\n copy(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"copy\", id, {\n label: data.label || \"抄送\",\n value: data.value || \"\",\n approverType: data.approverType || \"ext_target_approval\",\n approvals: data.approvals || [],\n approvalNames: data.approvalNames || [],\n ...data,\n });\n }\n\n jsCode(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"js_code\", id, {\n label: data.label || \"JS代码节点\",\n runtimeMode: \"trusted_node\",\n sourceType: data.sourceFile ? \"file_snapshot\" : data.sourceType || \"inline\",\n timeout: data.timeout || data.timeoutMs || 30000,\n ...data,\n });\n }\n\n callbackWait(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"callback_wait\", id, {\n type: \"callback_wait\",\n label: data.label || \"回调等待\",\n timeoutSeconds: data.timeoutSeconds || 86400,\n timeoutStrategy: data.timeoutStrategy || \"FAIL\",\n ...data,\n });\n }\n\n connectorCall(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"connector_call\", id, {\n type: \"connector_call\",\n label: data.label || \"连接器\",\n timeout: data.timeout || 30000,\n ...data,\n });\n }\n\n workNotification(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"work_notification\", id, {\n label: data.label || \"工作通知\",\n buttonText: data.buttonText || \"查看详情\",\n linkType: data.linkType || \"current_form\",\n ...data,\n });\n }\n\n dingtalkCard(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"dingtalk_card\", id, {\n config: {\n type: \"dingtalk_card\",\n label: data.label || \"钉钉消息卡片\",\n sameFieldStrategy: \"create\",\n ...(data.config || data),\n },\n });\n }\n\n condition(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"condition_branch\", id, {\n type: \"condition_branch\",\n label: data.label || \"条件分支\",\n condition: data.condition || { ruleType: \"group\", condition: \"AND\", rules: [] },\n isElse: data.isElse === true,\n priority: data.priority || \"1\",\n trueNodeId: data.trueNodeId,\n falseNodeId: data.falseNodeId,\n ...data,\n });\n }\n\n data = {\n retrieveSingle: (id: string, data: NodeOptions) =>\n this.node(\"data_retrieve_single\", id, {\n type: \"data_retrieve_single\",\n label: data.label || \"获取单条数据\",\n filterType: data.filterType || \"condition\",\n ...data,\n }),\n retrieveBatch: (id: string, data: NodeOptions) =>\n this.node(\"data_retrieve_batch\", id, {\n type: \"data_retrieve_batch\",\n label: data.label || \"获取多条数据\",\n filterType: data.filterType || \"condition\",\n ...data,\n }),\n create: (id: string, data: NodeOptions) =>\n this.node(\"data_create\", id, {\n type: \"data_create\",\n label: data.label || \"新增数据\",\n insertType: data.insertType || \"form\",\n assignments: data.assignments || [],\n ...data,\n }),\n update: (id: string, data: NodeOptions) =>\n this.node(\"data_update\", id, {\n type: \"data_update\",\n label: data.label || \"更新数据\",\n updateType: data.updateType || \"direct_form\",\n assignments: data.assignments || [],\n noneOperation: data.noneOperation || \"ignored\",\n ...data,\n }),\n };\n\n node(type: string, id: string, data: NodeOptions): WorkflowNodeRef {\n const nodeId = sanitizeId(id);\n if (!nodeId) throw new Error(\"workflow node id is required\");\n if (this.nodes.some((node) => node.id === nodeId)) {\n throw new Error(`duplicate workflow node id: ${nodeId}`);\n }\n this.nodes.push({\n id: nodeId,\n type,\n data,\n position: createPosition(this.nodes.length),\n });\n if (Array.isArray(data.fieldPermissions)) {\n this.flowConfig[nodeId] = data.fieldPermissions;\n }\n return nodeId;\n }\n\n edge(source: WorkflowNodeRef, target: WorkflowNodeRef, data: NodeOptions = {}) {\n const id = data.id || `edge_${source}_${target}`;\n this.edges.push({\n id,\n source,\n target,\n type: data.type || \"custom\",\n ...(data.label ? { label: data.label } : {}),\n });\n }\n\n sequence(...refs: WorkflowNodeRef[]) {\n for (let index = 0; index < refs.length - 1; index += 1) {\n this.edge(refs[index], refs[index + 1]);\n }\n }\n\n setFieldPermissions(nodeId: WorkflowNodeRef, permissions: any[]) {\n this.flowConfig[nodeId] = permissions;\n }\n\n setGlobalSettings(settings: Record<string, any>) {\n this.globalSettings = { ...this.globalSettings, ...settings };\n }\n\n compile(): WorkflowCompileResult {\n return {\n definitionJson: {\n version: \"v3\",\n nodes: this.nodes,\n edges: this.edges,\n flowConfig: this.flowConfig,\n globalSettings: this.globalSettings,\n },\n previewJson: {\n kind: \"workflow_code_preview\",\n version: \"preview_v1\",\n sourceMode: \"workflow_code_ts\",\n steps: this.nodes.map((node) => ({\n id: node.id,\n type: node.type,\n label: node.data?.label || node.id,\n config: node.data,\n })),\n edges: this.edges.map((edge) => ({\n source: edge.source,\n target: edge.target,\n label: edge.label,\n })),\n },\n };\n }\n}\n\nexport function defineWorkflow(input: WorkflowDefinitionInput) {\n return {\n __openxiangdaWorkflow: true,\n compile() {\n const builder = new WorkflowBuilder(input);\n input.build(builder);\n return builder.compile();\n },\n };\n}\n"],"mappings":"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","names":[]}
|