@steedos-labs/plugin-workflow 3.0.11 → 3.0.13
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/AI_PLUGIN_GUIDE.md +939 -0
- package/main/default/applications/approve_workflow.app.yml +159 -3
- package/main/default/manager/handlers_manager.js +1 -1
- package/main/default/manager/instance_number_rules.js +84 -0
- package/main/default/manager/instance_tasks_manager.js +79 -1
- package/main/default/manager/uuflow_manager.js +60 -45
- package/main/default/objects/flows/flows.object.yml +1 -4
- package/main/default/objects/instances/buttons/instance_delete.button.yml +4 -24
- package/main/default/objects/instances/buttons/instance_new.button.yml +11 -11
- package/main/default/objects/instances/buttons/instance_reassign.button.yml +5 -4
- package/main/default/objects/instances/buttons/instance_save.button.yml +6 -8
- package/main/default/pages/flow_selector.page.amis.json +5 -0
- package/main/default/pages/flow_selector.page.yml +7 -0
- package/main/default/pages/instance_detail.page.amis.json +1 -99
- package/main/default/pages/instance_tasks_detail.page.amis.json +0 -100
- package/main/default/pages/page_instance_view.page.amis.json +1 -1
- package/main/default/routes/api_auto_number.router.js +233 -0
- package/main/default/routes/api_files.router.js +21 -0
- package/main/default/routes/api_have_read.router.js +20 -2
- package/main/default/routes/api_workflow_chart.router.js +23 -3
- package/main/default/routes/api_workflow_next_step.router.js +135 -30
- package/main/default/routes/api_workflow_next_step_users.router.js +63 -10
- package/main/default/routes/nextStepUsers.router.js +3 -3
- package/main/default/services/instance.service.js +1 -9
- package/package.json +1 -1
- package/public/workflow/index.css +12 -4
- package/main/default/pages/instance_tasks_list.page.amis.json +0 -330
- package/main/default/pages/instance_tasks_list.page.yml +0 -12
- package/main/default/pages/instances_list.page.amis.json +0 -327
- package/main/default/pages/instances_list.page.yml +0 -12
|
@@ -0,0 +1,939 @@
|
|
|
1
|
+
# Plugin-Workflow 开发文档
|
|
2
|
+
|
|
3
|
+
> 审批王插件 - 提供完整的流程审批管理系统
|
|
4
|
+
|
|
5
|
+
## 目录
|
|
6
|
+
|
|
7
|
+
1. [插件概述](#插件概述)
|
|
8
|
+
2. [核心概念](#核心概念)
|
|
9
|
+
3. [文件结构](#文件结构)
|
|
10
|
+
4. [核心对象](#核心对象)
|
|
11
|
+
5. [队列系统](#队列系统)
|
|
12
|
+
6. [API接口](#api接口)
|
|
13
|
+
7. [触发器](#触发器)
|
|
14
|
+
8. [开发指南](#开发指南)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 插件概述
|
|
19
|
+
|
|
20
|
+
### 基本信息
|
|
21
|
+
|
|
22
|
+
- **包名**: `@steedos-labs/plugin-workflow`
|
|
23
|
+
- **版本**: 3.0.12
|
|
24
|
+
- **许可证**: MIT
|
|
25
|
+
- **主入口**: `package.service.js`
|
|
26
|
+
|
|
27
|
+
### 功能描述
|
|
28
|
+
|
|
29
|
+
审批王是一款创新的流程自动化解决方案,提供:
|
|
30
|
+
|
|
31
|
+
1. **流程设计器**: 可视化流程设计工具
|
|
32
|
+
2. **审批单管理**: 完整的审批单生命周期管理
|
|
33
|
+
3. **表单设计**: 动态表单设计和渲染
|
|
34
|
+
4. **实例同步**: 审批单与业务对象的双向同步
|
|
35
|
+
5. **Webhook集成**: 支持外部系统集成
|
|
36
|
+
6. **历史记录**: 完整的审批历史追踪
|
|
37
|
+
|
|
38
|
+
### 许可证要求
|
|
39
|
+
|
|
40
|
+
```yaml
|
|
41
|
+
license:
|
|
42
|
+
- platform-professional
|
|
43
|
+
- platform-enterprise
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
需要专业版或企业版许可证才能使用。
|
|
47
|
+
|
|
48
|
+
### 技术栈
|
|
49
|
+
|
|
50
|
+
- JavaScript/Node.js
|
|
51
|
+
- Moleculer微服务
|
|
52
|
+
- MongoDB
|
|
53
|
+
- Redis队列
|
|
54
|
+
- AMIS表单引擎
|
|
55
|
+
|
|
56
|
+
### 核心依赖
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"graphql-parse-resolve-info": "^4.12.3",
|
|
61
|
+
"he": "^1.2.0",
|
|
62
|
+
"lodash": "^4.17.21",
|
|
63
|
+
"node-schedule": "^2.0.0",
|
|
64
|
+
"formidable": "^2.1.5",
|
|
65
|
+
"jszip": "^3.10.1"
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## 核心概念
|
|
72
|
+
|
|
73
|
+
### 1. 流程 (Flow)
|
|
74
|
+
|
|
75
|
+
流程是审批过程的模板定义,包含:
|
|
76
|
+
- 流程步骤 (Steps)
|
|
77
|
+
- 审批人规则
|
|
78
|
+
- 字段权限
|
|
79
|
+
- 触发条件
|
|
80
|
+
|
|
81
|
+
### 2. 审批单 (Instance)
|
|
82
|
+
|
|
83
|
+
审批单是流程的具体执行实例,包含:
|
|
84
|
+
- 表单数据
|
|
85
|
+
- 当前状态
|
|
86
|
+
- 审批历史
|
|
87
|
+
- 附件信息
|
|
88
|
+
|
|
89
|
+
### 3. 审批任务 (Instance Task)
|
|
90
|
+
|
|
91
|
+
每个审批步骤对应一个或多个审批任务,分配给具体审批人。
|
|
92
|
+
|
|
93
|
+
### 4. 表单 (Form)
|
|
94
|
+
|
|
95
|
+
表单定义审批单的数据结构和UI布局:
|
|
96
|
+
- 使用AMIS Schema定义
|
|
97
|
+
- 支持动态字段
|
|
98
|
+
- 支持复杂布局
|
|
99
|
+
|
|
100
|
+
### 5. 对象流程关联 (Object Workflow)
|
|
101
|
+
|
|
102
|
+
将流程与业务对象关联,实现:
|
|
103
|
+
- 从对象发起流程
|
|
104
|
+
- 审批单数据同步到对象
|
|
105
|
+
- 对象变更触发流程
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## 文件结构
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
plugin-workflow/
|
|
113
|
+
├── package.json # NPM包配置
|
|
114
|
+
├── package.service.js # Moleculer服务入口
|
|
115
|
+
├── package.service.yml # 服务元数据
|
|
116
|
+
├── README.md # 说明文档
|
|
117
|
+
│
|
|
118
|
+
├── src/ # 源代码
|
|
119
|
+
│ ├── instance_record_queue.js # 实例记录队列
|
|
120
|
+
│ ├── webhook_queue.js # Webhook队列
|
|
121
|
+
│ ├── rests/ # REST API
|
|
122
|
+
│ │ ├── updateFormFields.js
|
|
123
|
+
│ │ ├── getInstanceServiceSchema.js
|
|
124
|
+
│ │ ├── flow_copy.js
|
|
125
|
+
│ │ └── ...
|
|
126
|
+
│ ├── schema/ # Schema定义
|
|
127
|
+
│ │ ├── steedos_form_schema.amis.js
|
|
128
|
+
│ │ ├── instance_form_schema.amis.js
|
|
129
|
+
│ │ └── ...
|
|
130
|
+
│ └── util/ # 工具函数
|
|
131
|
+
│
|
|
132
|
+
├── main/default/ # Steedos元数据
|
|
133
|
+
│ ├── objects/ # 对象定义
|
|
134
|
+
│ │ ├── instances.object.yml # 审批单
|
|
135
|
+
│ │ ├── instance_tasks/ # 审批任务
|
|
136
|
+
│ │ ├── forms/ # 表单
|
|
137
|
+
│ │ ├── flows/ # 流程
|
|
138
|
+
│ │ ├── object_workflows.object.yml # 对象流程关联
|
|
139
|
+
│ │ └── ...
|
|
140
|
+
│ ├── triggers/ # 触发器
|
|
141
|
+
│ │ ├── instances.trigger.js
|
|
142
|
+
│ │ ├── instance_tasks.trigger.js
|
|
143
|
+
│ │ ├── flows.trigger.js
|
|
144
|
+
│ │ └── amis_form_design.trigger.js
|
|
145
|
+
│ ├── routes/ # 路由
|
|
146
|
+
│ │ ├── api_workflow_redirect.router.js
|
|
147
|
+
│ │ ├── api_workflow_approve_save.router.js
|
|
148
|
+
│ │ └── ...
|
|
149
|
+
│ ├── applications/ # 应用
|
|
150
|
+
│ ├── tabs/ # 选项卡
|
|
151
|
+
│ ├── translations/ # 国际化
|
|
152
|
+
│ └── ...
|
|
153
|
+
│
|
|
154
|
+
└── public/ # 静态资源
|
|
155
|
+
├── applications/ # 流程设计器应用
|
|
156
|
+
│ └── designer/
|
|
157
|
+
└── workflow/ # 工作流相关资源
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 核心对象
|
|
163
|
+
|
|
164
|
+
### 1. flows (流程)
|
|
165
|
+
|
|
166
|
+
流程定义对象。
|
|
167
|
+
|
|
168
|
+
**核心字段**:
|
|
169
|
+
```yaml
|
|
170
|
+
name: # 流程名称
|
|
171
|
+
type: text
|
|
172
|
+
required: true
|
|
173
|
+
|
|
174
|
+
form: # 关联表单
|
|
175
|
+
type: lookup
|
|
176
|
+
reference_to: forms
|
|
177
|
+
|
|
178
|
+
is_valid: # 是否有效
|
|
179
|
+
type: boolean
|
|
180
|
+
|
|
181
|
+
current_version: # 当前版本
|
|
182
|
+
type: number
|
|
183
|
+
|
|
184
|
+
steps: # 流程步骤
|
|
185
|
+
type: grid
|
|
186
|
+
# 步骤定义包括审批人、字段权限等
|
|
187
|
+
|
|
188
|
+
perms: # 流程权限
|
|
189
|
+
type: grid
|
|
190
|
+
# 可以发起流程的用户/组织
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**文件位置**: `main/default/objects/flows/`
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
### 2. forms (表单)
|
|
198
|
+
|
|
199
|
+
表单定义对象。
|
|
200
|
+
|
|
201
|
+
**核心字段**:
|
|
202
|
+
```yaml
|
|
203
|
+
name: # 表单名称
|
|
204
|
+
type: text
|
|
205
|
+
|
|
206
|
+
amis_schema: # AMIS表单Schema
|
|
207
|
+
type: object
|
|
208
|
+
# JSON格式的AMIS配置
|
|
209
|
+
|
|
210
|
+
fields: # 表单字段
|
|
211
|
+
type: grid
|
|
212
|
+
# 字段定义数组
|
|
213
|
+
|
|
214
|
+
current: # 是否当前版本
|
|
215
|
+
type: boolean
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**AMIS Schema结构**:
|
|
219
|
+
```javascript
|
|
220
|
+
{
|
|
221
|
+
type: "page",
|
|
222
|
+
body: [
|
|
223
|
+
{
|
|
224
|
+
type: "form",
|
|
225
|
+
body: [
|
|
226
|
+
{
|
|
227
|
+
type: "input-text",
|
|
228
|
+
name: "field_name",
|
|
229
|
+
label: "字段标签",
|
|
230
|
+
required: true
|
|
231
|
+
}
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**文件位置**: `main/default/objects/forms/`
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
### 3. instances (审批单)
|
|
243
|
+
|
|
244
|
+
审批单实例对象。
|
|
245
|
+
|
|
246
|
+
**核心字段**:
|
|
247
|
+
```yaml
|
|
248
|
+
name: # 审批单标题
|
|
249
|
+
type: text
|
|
250
|
+
|
|
251
|
+
applicant: # 申请人
|
|
252
|
+
type: lookup
|
|
253
|
+
reference_to: users
|
|
254
|
+
|
|
255
|
+
applicant_name: # 申请人姓名
|
|
256
|
+
type: text
|
|
257
|
+
|
|
258
|
+
applicant_organization: # 申请人部门
|
|
259
|
+
type: lookup
|
|
260
|
+
reference_to: organizations
|
|
261
|
+
|
|
262
|
+
flow: # 关联流程
|
|
263
|
+
type: lookup
|
|
264
|
+
reference_to: flows
|
|
265
|
+
|
|
266
|
+
flow_version: # 流程版本
|
|
267
|
+
type: number
|
|
268
|
+
|
|
269
|
+
form: # 关联表单
|
|
270
|
+
type: lookup
|
|
271
|
+
reference_to: forms
|
|
272
|
+
|
|
273
|
+
form_version: # 表单版本
|
|
274
|
+
type: number
|
|
275
|
+
|
|
276
|
+
state: # 审批状态
|
|
277
|
+
type: select
|
|
278
|
+
options:
|
|
279
|
+
- draft # 草稿
|
|
280
|
+
- pending # 进行中
|
|
281
|
+
- completed # 已完成
|
|
282
|
+
- canceled # 已取消
|
|
283
|
+
|
|
284
|
+
values: # 表单数据
|
|
285
|
+
type: object
|
|
286
|
+
# JSON格式存储表单填写的值
|
|
287
|
+
|
|
288
|
+
traces: # 审批历史
|
|
289
|
+
type: grid
|
|
290
|
+
# 审批步骤记录
|
|
291
|
+
|
|
292
|
+
attachments: # 附件
|
|
293
|
+
type: grid
|
|
294
|
+
|
|
295
|
+
cc: # 抄送人
|
|
296
|
+
type: lookup
|
|
297
|
+
multiple: true
|
|
298
|
+
reference_to: users
|
|
299
|
+
|
|
300
|
+
inbox_users: # 待办人
|
|
301
|
+
type: lookup
|
|
302
|
+
multiple: true
|
|
303
|
+
reference_to: users
|
|
304
|
+
|
|
305
|
+
outbox_users: # 已办人
|
|
306
|
+
type: lookup
|
|
307
|
+
multiple: true
|
|
308
|
+
reference_to: users
|
|
309
|
+
|
|
310
|
+
record_ids: # 关联业务对象记录
|
|
311
|
+
type: grid
|
|
312
|
+
# [{o: "objectName", ids: ["recordId1", "recordId2"]}]
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
**文件位置**: `main/default/objects/instances/`
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
### 4. instance_tasks (审批任务)
|
|
320
|
+
|
|
321
|
+
审批任务对象。
|
|
322
|
+
|
|
323
|
+
**核心字段**:
|
|
324
|
+
```yaml
|
|
325
|
+
instance: # 关联审批单
|
|
326
|
+
type: master_detail
|
|
327
|
+
reference_to: instances
|
|
328
|
+
|
|
329
|
+
name: # 任务名称
|
|
330
|
+
type: text
|
|
331
|
+
|
|
332
|
+
assignee: # 审批人
|
|
333
|
+
type: lookup
|
|
334
|
+
reference_to: users
|
|
335
|
+
|
|
336
|
+
due_date: # 截止日期
|
|
337
|
+
type: date
|
|
338
|
+
|
|
339
|
+
state: # 任务状态
|
|
340
|
+
type: select
|
|
341
|
+
options:
|
|
342
|
+
- pending # 待处理
|
|
343
|
+
- approved # 已批准
|
|
344
|
+
- rejected # 已拒绝
|
|
345
|
+
|
|
346
|
+
description: # 审批意见
|
|
347
|
+
type: textarea
|
|
348
|
+
|
|
349
|
+
is_read: # 是否已读
|
|
350
|
+
type: boolean
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
**文件位置**: `main/default/objects/instance_tasks/`
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
### 5. object_workflows (对象流程关联)
|
|
358
|
+
|
|
359
|
+
对象与流程的关联配置。
|
|
360
|
+
|
|
361
|
+
**核心字段**:
|
|
362
|
+
```yaml
|
|
363
|
+
object_name: # 对象API名称
|
|
364
|
+
type: text
|
|
365
|
+
|
|
366
|
+
flow_id: # 关联流程
|
|
367
|
+
type: lookup
|
|
368
|
+
reference_to: flows
|
|
369
|
+
|
|
370
|
+
field_map: # 字段映射
|
|
371
|
+
type: grid
|
|
372
|
+
# [{workflow_field: "申请金额", object_field: "amount"}]
|
|
373
|
+
|
|
374
|
+
sync_direction: # 同步方向
|
|
375
|
+
type: select
|
|
376
|
+
options:
|
|
377
|
+
- "both" # 双向同步
|
|
378
|
+
- "obj_to_ins" # 对象到实例
|
|
379
|
+
- "ins_to_obj" # 实例到对象
|
|
380
|
+
|
|
381
|
+
sync_type: # 同步类型
|
|
382
|
+
type: select
|
|
383
|
+
options:
|
|
384
|
+
- "every_step" # 每步同步
|
|
385
|
+
- "end_step" # 结束时同步
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**文件位置**: `main/default/objects/object_workflows.object.yml`
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## 队列系统
|
|
393
|
+
|
|
394
|
+
### 1. Instance Record Queue (实例记录队列)
|
|
395
|
+
|
|
396
|
+
**文件**: `src/instance_record_queue.js`
|
|
397
|
+
|
|
398
|
+
**功能**: 将审批单数据同步到业务对象记录。
|
|
399
|
+
|
|
400
|
+
**队列表**: `instance_record_queue`
|
|
401
|
+
|
|
402
|
+
**队列记录结构**:
|
|
403
|
+
```javascript
|
|
404
|
+
{
|
|
405
|
+
instance_id: "审批单ID",
|
|
406
|
+
record_id: "业务对象记录ID",
|
|
407
|
+
object_name: "业务对象名称",
|
|
408
|
+
operation: "insert|update|delete",
|
|
409
|
+
data: { /* 字段映射后的数据 */ },
|
|
410
|
+
state: "pending|processing|completed|failed",
|
|
411
|
+
error: "错误信息",
|
|
412
|
+
created: "创建时间",
|
|
413
|
+
modified: "修改时间"
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
**处理流程**:
|
|
418
|
+
|
|
419
|
+
1. **触发条件**:
|
|
420
|
+
- 审批单状态变更
|
|
421
|
+
- 审批单字段更新
|
|
422
|
+
- 对象流程关联配置的同步规则
|
|
423
|
+
|
|
424
|
+
2. **数据映射**:
|
|
425
|
+
```javascript
|
|
426
|
+
const getObjectFields = async function (objectApiName) {
|
|
427
|
+
return await objectql.getObject(objectApiName).getFields()
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// 根据field_map映射数据
|
|
431
|
+
const mappedData = {};
|
|
432
|
+
for (const mapping of fieldMappings) {
|
|
433
|
+
mappedData[mapping.object_field] =
|
|
434
|
+
instanceValues[mapping.workflow_field];
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
3. **执行同步**:
|
|
439
|
+
```javascript
|
|
440
|
+
const objectInsert = async function (objectApiName, data) {
|
|
441
|
+
return await objectql.getObject(objectApiName).insert(data)
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
const objectUpdate = async function (objectApiName, id, data) {
|
|
445
|
+
return await objectql.getObject(objectApiName).update(id, data);
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
4. **公式和汇总字段更新**:
|
|
450
|
+
```javascript
|
|
451
|
+
var runQuoted = async function (objectName, recordId) {
|
|
452
|
+
await objectql.runQuotedByObjectFieldFormulas(objectName, recordId);
|
|
453
|
+
await objectql.runQuotedByObjectFieldSummaries(objectName, recordId);
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
**定时任务配置**:
|
|
458
|
+
```bash
|
|
459
|
+
# .env文件
|
|
460
|
+
STEEDOS_CRON_ENABLED=true
|
|
461
|
+
STEEDOS_CRON_INSTANCERECORDQUEUE_INTERVAL=1000 # 毫秒
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
### 2. Webhook Queue (Webhook队列)
|
|
467
|
+
|
|
468
|
+
**文件**: `src/webhook_queue.js`
|
|
469
|
+
|
|
470
|
+
**功能**: 向外部系统发送审批单事件通知。
|
|
471
|
+
|
|
472
|
+
**使用场景**:
|
|
473
|
+
- 审批完成后通知第三方系统
|
|
474
|
+
- 实时推送审批状态变更
|
|
475
|
+
- 集成外部业务系统
|
|
476
|
+
|
|
477
|
+
**Webhook配置**:
|
|
478
|
+
在流程或对象流程中配置:
|
|
479
|
+
```yaml
|
|
480
|
+
webhooks:
|
|
481
|
+
- url: "https://example.com/api/webhook"
|
|
482
|
+
method: "POST"
|
|
483
|
+
trigger_when: "completed" # draft|pending|completed|rejected
|
|
484
|
+
headers:
|
|
485
|
+
Authorization: "Bearer token"
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
**推送数据格式**:
|
|
489
|
+
```javascript
|
|
490
|
+
{
|
|
491
|
+
event: "instance.completed",
|
|
492
|
+
instance_id: "审批单ID",
|
|
493
|
+
instance: {
|
|
494
|
+
name: "审批单标题",
|
|
495
|
+
state: "completed",
|
|
496
|
+
applicant: "申请人ID",
|
|
497
|
+
values: { /* 表单数据 */ }
|
|
498
|
+
},
|
|
499
|
+
timestamp: "2026-01-09T06:00:00Z"
|
|
500
|
+
}
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
## API接口
|
|
506
|
+
|
|
507
|
+
### 1. 流程相关API
|
|
508
|
+
|
|
509
|
+
#### 复制流程
|
|
510
|
+
|
|
511
|
+
**路由**: `POST /api/workflow/flows/copy`
|
|
512
|
+
|
|
513
|
+
**文件**: `src/rests/flow_copy.js`
|
|
514
|
+
|
|
515
|
+
**功能**: 复制现有流程创建新版本或新流程。
|
|
516
|
+
|
|
517
|
+
**请求参数**:
|
|
518
|
+
```javascript
|
|
519
|
+
{
|
|
520
|
+
flowId: "源流程ID",
|
|
521
|
+
name: "新流程名称",
|
|
522
|
+
copyVersion: true // 是否作为新版本
|
|
523
|
+
}
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
---
|
|
527
|
+
|
|
528
|
+
#### 获取流程权限
|
|
529
|
+
|
|
530
|
+
**路由**: `GET /api/workflow/flows/:flowId/permissions`
|
|
531
|
+
|
|
532
|
+
**文件**: `main/default/routes/api_flow_permission.router.js`
|
|
533
|
+
|
|
534
|
+
**功能**: 检查当前用户是否有权限发起该流程。
|
|
535
|
+
|
|
536
|
+
---
|
|
537
|
+
|
|
538
|
+
### 2. 审批单相关API
|
|
539
|
+
|
|
540
|
+
#### 提交审批
|
|
541
|
+
|
|
542
|
+
**路由**: `POST /api/workflow/instances/:instanceId/submit`
|
|
543
|
+
|
|
544
|
+
**文件**: `main/default/routes/api_workflow_approve_save.router.js`
|
|
545
|
+
|
|
546
|
+
**功能**: 提交审批意见(批准/拒绝)。
|
|
547
|
+
|
|
548
|
+
**请求参数**:
|
|
549
|
+
```javascript
|
|
550
|
+
{
|
|
551
|
+
action: "approve|reject",
|
|
552
|
+
description: "审批意见",
|
|
553
|
+
next_steps: [{
|
|
554
|
+
step: "步骤ID",
|
|
555
|
+
users: ["用户ID1", "用户ID2"]
|
|
556
|
+
}]
|
|
557
|
+
}
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
---
|
|
561
|
+
|
|
562
|
+
#### 传阅/抄送
|
|
563
|
+
|
|
564
|
+
**路由**: `POST /api/workflow/instances/:instanceId/cc`
|
|
565
|
+
|
|
566
|
+
**文件**: `main/default/routes/api_cc_submit.router.js`
|
|
567
|
+
|
|
568
|
+
**功能**: 提交传阅意见。
|
|
569
|
+
|
|
570
|
+
---
|
|
571
|
+
|
|
572
|
+
#### 批量删除审批单
|
|
573
|
+
|
|
574
|
+
**路由**: `POST /api/workflow/instances/batch-remove`
|
|
575
|
+
|
|
576
|
+
**文件**: `src/rests/api_workflow_instance_batch_remove.js`
|
|
577
|
+
|
|
578
|
+
**功能**: 批量删除审批单。
|
|
579
|
+
|
|
580
|
+
---
|
|
581
|
+
|
|
582
|
+
#### 导出审批单
|
|
583
|
+
|
|
584
|
+
**路由**: `GET /api/workflow/instances/:instanceId/export`
|
|
585
|
+
|
|
586
|
+
**文件**: `main/default/routes/api_workflow_export.router.js`
|
|
587
|
+
|
|
588
|
+
**功能**: 导出审批单为PDF或其他格式。
|
|
589
|
+
|
|
590
|
+
---
|
|
591
|
+
|
|
592
|
+
### 3. 表单相关API
|
|
593
|
+
|
|
594
|
+
#### 更新表单字段
|
|
595
|
+
|
|
596
|
+
**路由**: `POST /api/workflow/forms/:formId/updateFields`
|
|
597
|
+
|
|
598
|
+
**文件**: `src/rests/updateFormFields.js`
|
|
599
|
+
|
|
600
|
+
**功能**: 动态更新表单字段定义。
|
|
601
|
+
|
|
602
|
+
**请求参数**:
|
|
603
|
+
```javascript
|
|
604
|
+
{
|
|
605
|
+
fields: [
|
|
606
|
+
{
|
|
607
|
+
code: "field_name",
|
|
608
|
+
name: "字段标签",
|
|
609
|
+
type: "text",
|
|
610
|
+
required: true
|
|
611
|
+
}
|
|
612
|
+
]
|
|
613
|
+
}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
---
|
|
617
|
+
|
|
618
|
+
#### 获取实例Service Schema
|
|
619
|
+
|
|
620
|
+
**路由**: `GET /api/workflow/instances/:instanceId/service-schema`
|
|
621
|
+
|
|
622
|
+
**文件**: `src/rests/getInstanceServiceSchema.js`
|
|
623
|
+
|
|
624
|
+
**功能**: 获取审批单的AMIS Service Schema用于前端渲染。
|
|
625
|
+
|
|
626
|
+
---
|
|
627
|
+
|
|
628
|
+
### 4. 文件相关API
|
|
629
|
+
|
|
630
|
+
**路由**: `/api/workflow/files/*`
|
|
631
|
+
|
|
632
|
+
**文件**: `main/default/routes/api_files.router.js`
|
|
633
|
+
|
|
634
|
+
**功能**: 处理审批单附件的上传和下载。
|
|
635
|
+
|
|
636
|
+
---
|
|
637
|
+
|
|
638
|
+
## 触发器
|
|
639
|
+
|
|
640
|
+
### 1. instances.trigger.js
|
|
641
|
+
|
|
642
|
+
**文件**: `main/default/triggers/instances.trigger.js`
|
|
643
|
+
|
|
644
|
+
**监听对象**: `instances`
|
|
645
|
+
|
|
646
|
+
**功能**:
|
|
647
|
+
- 审批单状态变更时触发队列同步
|
|
648
|
+
- 更新待办人/已办人列表
|
|
649
|
+
- 发送通知
|
|
650
|
+
|
|
651
|
+
**示例**:
|
|
652
|
+
```javascript
|
|
653
|
+
module.exports = {
|
|
654
|
+
listenTo: 'instances',
|
|
655
|
+
|
|
656
|
+
afterUpdate: async function() {
|
|
657
|
+
const { doc, previousDoc } = this;
|
|
658
|
+
|
|
659
|
+
// 状态变更
|
|
660
|
+
if (doc.state !== previousDoc.state) {
|
|
661
|
+
// 触发同步队列
|
|
662
|
+
if (doc.state === 'completed') {
|
|
663
|
+
await addToInstanceRecordQueue(doc._id);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
// 发送通知
|
|
667
|
+
await sendNotification(doc);
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
---
|
|
674
|
+
|
|
675
|
+
### 2. instance_tasks.trigger.js
|
|
676
|
+
|
|
677
|
+
**文件**: `main/default/triggers/instance_tasks.trigger.js`
|
|
678
|
+
|
|
679
|
+
**监听对象**: `instance_tasks`
|
|
680
|
+
|
|
681
|
+
**功能**:
|
|
682
|
+
- 审批任务创建时发送通知
|
|
683
|
+
- 任务完成时更新审批单状态
|
|
684
|
+
|
|
685
|
+
---
|
|
686
|
+
|
|
687
|
+
### 3. flows.trigger.js
|
|
688
|
+
|
|
689
|
+
**文件**: `main/default/triggers/flows.trigger.js`
|
|
690
|
+
|
|
691
|
+
**监听对象**: `flows`
|
|
692
|
+
|
|
693
|
+
**功能**:
|
|
694
|
+
- 流程版本管理
|
|
695
|
+
- 流程启用/停用处理
|
|
696
|
+
|
|
697
|
+
**示例**:
|
|
698
|
+
```javascript
|
|
699
|
+
module.exports = {
|
|
700
|
+
listenTo: 'flows',
|
|
701
|
+
|
|
702
|
+
beforeUpdate: async function() {
|
|
703
|
+
const { doc } = this;
|
|
704
|
+
|
|
705
|
+
// 停用流程时检查是否有进行中的审批单
|
|
706
|
+
if (doc.is_valid === false) {
|
|
707
|
+
const pendingInstances = await objectql
|
|
708
|
+
.getObject('instances')
|
|
709
|
+
.find({
|
|
710
|
+
filters: [
|
|
711
|
+
['flow', '=', doc._id],
|
|
712
|
+
['state', '=', 'pending']
|
|
713
|
+
]
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
if (pendingInstances.length > 0) {
|
|
717
|
+
throw new Error('存在进行中的审批单,无法停用流程');
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
---
|
|
725
|
+
|
|
726
|
+
### 4. amis_form_design.trigger.js
|
|
727
|
+
|
|
728
|
+
**文件**: `main/default/triggers/amis_form_design.trigger.js`
|
|
729
|
+
|
|
730
|
+
**监听对象**: `forms`
|
|
731
|
+
|
|
732
|
+
**功能**:
|
|
733
|
+
- AMIS表单Schema验证
|
|
734
|
+
- 表单字段同步
|
|
735
|
+
- 表单版本管理
|
|
736
|
+
|
|
737
|
+
**重要**: 这是一个大型触发器(约19000行代码),包含复杂的表单处理逻辑。
|
|
738
|
+
|
|
739
|
+
---
|
|
740
|
+
|
|
741
|
+
## 开发指南
|
|
742
|
+
|
|
743
|
+
### 本地开发
|
|
744
|
+
|
|
745
|
+
#### 1. 安装依赖
|
|
746
|
+
|
|
747
|
+
```bash
|
|
748
|
+
cd steedos-packages/plugin-workflow
|
|
749
|
+
yarn install
|
|
750
|
+
```
|
|
751
|
+
|
|
752
|
+
#### 2. 启动开发环境
|
|
753
|
+
|
|
754
|
+
```bash
|
|
755
|
+
# 在项目根目录
|
|
756
|
+
cd ../..
|
|
757
|
+
|
|
758
|
+
# 启动数据库
|
|
759
|
+
yarn start:db
|
|
760
|
+
|
|
761
|
+
# 启动服务
|
|
762
|
+
yarn start
|
|
763
|
+
```
|
|
764
|
+
|
|
765
|
+
#### 3. 访问流程设计器
|
|
766
|
+
|
|
767
|
+
打开浏览器访问:
|
|
768
|
+
```
|
|
769
|
+
http://localhost:5100/app/admin/workflow/designer
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
---
|
|
773
|
+
|
|
774
|
+
### 添加新流程步骤类型
|
|
775
|
+
|
|
776
|
+
#### 1. 定义步骤类型
|
|
777
|
+
|
|
778
|
+
在流程步骤配置中添加新类型:
|
|
779
|
+
|
|
780
|
+
```javascript
|
|
781
|
+
const stepTypes = {
|
|
782
|
+
approval: {
|
|
783
|
+
label: "审批",
|
|
784
|
+
icon: "approval",
|
|
785
|
+
handler: approvalStepHandler
|
|
786
|
+
},
|
|
787
|
+
condition: {
|
|
788
|
+
label: "条件",
|
|
789
|
+
icon: "condition",
|
|
790
|
+
handler: conditionStepHandler
|
|
791
|
+
},
|
|
792
|
+
custom_new_type: { // 新步骤类型
|
|
793
|
+
label: "自定义步骤",
|
|
794
|
+
icon: "custom",
|
|
795
|
+
handler: customStepHandler
|
|
796
|
+
}
|
|
797
|
+
};
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
#### 2. 实现步骤处理器
|
|
801
|
+
|
|
802
|
+
```javascript
|
|
803
|
+
async function customStepHandler(instance, step, context) {
|
|
804
|
+
// 执行自定义逻辑
|
|
805
|
+
const result = await performCustomAction(instance, step);
|
|
806
|
+
|
|
807
|
+
// 返回下一步骤
|
|
808
|
+
return {
|
|
809
|
+
nextStep: step.next_step_id,
|
|
810
|
+
data: result
|
|
811
|
+
};
|
|
812
|
+
}
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
---
|
|
816
|
+
|
|
817
|
+
### 自定义审批规则
|
|
818
|
+
|
|
819
|
+
#### 1. 创建自定义审批人规则
|
|
820
|
+
|
|
821
|
+
```javascript
|
|
822
|
+
// 在流程配置中添加自定义规则
|
|
823
|
+
const approverRules = {
|
|
824
|
+
manager: {
|
|
825
|
+
label: "直属主管",
|
|
826
|
+
handler: async (applicant) => {
|
|
827
|
+
const user = await getUser(applicant);
|
|
828
|
+
return user.manager_id;
|
|
829
|
+
}
|
|
830
|
+
},
|
|
831
|
+
custom_rule: { // 新规则
|
|
832
|
+
label: "自定义规则",
|
|
833
|
+
handler: async (applicant, context) => {
|
|
834
|
+
// 实现自定义逻辑
|
|
835
|
+
// 返回审批人ID数组
|
|
836
|
+
return ["userId1", "userId2"];
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
```
|
|
841
|
+
|
|
842
|
+
---
|
|
843
|
+
|
|
844
|
+
### 扩展字段映射
|
|
845
|
+
|
|
846
|
+
#### 1. 添加自定义字段映射函数
|
|
847
|
+
|
|
848
|
+
```javascript
|
|
849
|
+
const fieldMappers = {
|
|
850
|
+
// 简单映射
|
|
851
|
+
simple: (value) => value,
|
|
852
|
+
|
|
853
|
+
// 日期格式转换
|
|
854
|
+
dateFormat: (value, format) => {
|
|
855
|
+
return moment(value).format(format);
|
|
856
|
+
},
|
|
857
|
+
|
|
858
|
+
// 自定义映射
|
|
859
|
+
custom: (value, context) => {
|
|
860
|
+
// 实现转换逻辑
|
|
861
|
+
return transformedValue;
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
#### 2. 在对象流程关联中使用
|
|
867
|
+
|
|
868
|
+
```yaml
|
|
869
|
+
field_map:
|
|
870
|
+
- workflow_field: "申请日期"
|
|
871
|
+
object_field: "apply_date"
|
|
872
|
+
mapper: "dateFormat"
|
|
873
|
+
mapper_params: "YYYY-MM-DD"
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
---
|
|
877
|
+
|
|
878
|
+
### 调试技巧
|
|
879
|
+
|
|
880
|
+
#### 1. 查看队列状态
|
|
881
|
+
|
|
882
|
+
```javascript
|
|
883
|
+
// 在MongoDB中查询队列
|
|
884
|
+
db.instance_record_queue.find({
|
|
885
|
+
state: "failed"
|
|
886
|
+
}).sort({ modified: -1 });
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
#### 2. 手动触发队列处理
|
|
890
|
+
|
|
891
|
+
```javascript
|
|
892
|
+
// 通过Moleculer调用
|
|
893
|
+
const result = await broker.call('workflow.processQueue', {
|
|
894
|
+
queueId: "队列记录ID"
|
|
895
|
+
});
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
#### 3. 调试审批单同步
|
|
899
|
+
|
|
900
|
+
```bash
|
|
901
|
+
# 启用详细日志
|
|
902
|
+
STEEDOS_LOG_LEVEL=debug yarn start
|
|
903
|
+
|
|
904
|
+
# 查看同步日志
|
|
905
|
+
tail -f logs/workflow.log | grep "instance_record_queue"
|
|
906
|
+
```
|
|
907
|
+
|
|
908
|
+
---
|
|
909
|
+
|
|
910
|
+
## 注意事项
|
|
911
|
+
|
|
912
|
+
### 1. 性能优化
|
|
913
|
+
|
|
914
|
+
- 大量审批单时考虑分页加载
|
|
915
|
+
- 队列处理使用批量操作
|
|
916
|
+
- 定期清理已完成的队列记录
|
|
917
|
+
|
|
918
|
+
### 2. 数据一致性
|
|
919
|
+
|
|
920
|
+
- 使用事务处理关键操作
|
|
921
|
+
- 队列失败时需要重试机制
|
|
922
|
+
- 记录详细的错误日志
|
|
923
|
+
|
|
924
|
+
### 3. 安全性
|
|
925
|
+
|
|
926
|
+
- 验证用户权限
|
|
927
|
+
- 防止SQL注入和XSS攻击
|
|
928
|
+
- 敏感数据加密存储
|
|
929
|
+
|
|
930
|
+
### 4. 兼容性
|
|
931
|
+
|
|
932
|
+
- 确保与Steedos平台版本兼容
|
|
933
|
+
- 测试不同浏览器的兼容性
|
|
934
|
+
- 向后兼容旧版本流程数据
|
|
935
|
+
|
|
936
|
+
---
|
|
937
|
+
|
|
938
|
+
**文档版本**: 1.0
|
|
939
|
+
**最后更新**: 2026-01-09
|