openyida 1.0.0-beta.7 → 1.1.0
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 +2 -2
- package/bin/yida.js +32 -2
- package/lib/configure-process.js +881 -0
- package/lib/create-app.js +3 -1
- package/lib/create-process.js +303 -0
- package/lib/get-permission.js +207 -0
- package/lib/locales/en.js +7 -2
- package/lib/locales/ja.js +3 -2
- package/lib/locales/zh.js +7 -2
- package/lib/save-permission.js +548 -0
- package/package.json +3 -2
- package/scripts/validate-structure.js +26 -3
- package/yida-skills/SKILL.md +3 -0
- package/yida-skills/skills/yida-create-app/SKILL.md +2 -2
- package/yida-skills/skills/yida-create-process/SKILL.md +195 -0
- package/yida-skills/skills/yida-custom-page/SKILL.md +481 -1
- package/yida-skills/skills/yida-custom-page/examples/tabs-visibility-control.js +7 -7
- package/yida-skills/skills/yida-form-permission/SKILL.md +206 -0
- package/yida-skills/skills/yida-process-rule/SKILL.md +363 -0
|
@@ -0,0 +1,881 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* configure-process.js - 宜搭流程规则配置命令
|
|
4
|
+
*
|
|
5
|
+
* 用法:openyida configure-process <appType> <formUuid> <processDefinitionFile> [processCode]
|
|
6
|
+
*
|
|
7
|
+
* 功能:
|
|
8
|
+
* 根据流程定义 JSON 文件,自动配置宜搭流程表单的审批流程。
|
|
9
|
+
* 支持条件分支、嵌套分支、审批节点、字段权限、抄送节点、跳转规则。
|
|
10
|
+
*
|
|
11
|
+
* 核心流程:
|
|
12
|
+
* 1. 获取 processCode(优先使用传入参数,否则通过 switchFormType + getAppPlatFormParam 自动获取)
|
|
13
|
+
* 2. 查询流程版本列表,获取当前已发布版本的 processId
|
|
14
|
+
* 3. 创建新流程版本草稿
|
|
15
|
+
* 4. 根据流程定义 JSON 构建 processJson 和 viewJson(严格匹配宜搭真实格式)
|
|
16
|
+
* 5. 调用 saveProcessById 保存流程
|
|
17
|
+
* 6. 调用 publishProcessById 发布流程
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
"use strict";
|
|
21
|
+
|
|
22
|
+
const fs = require("fs");
|
|
23
|
+
const path = require("path");
|
|
24
|
+
const querystring = require("querystring");
|
|
25
|
+
const {
|
|
26
|
+
findProjectRoot,
|
|
27
|
+
loadCookieData,
|
|
28
|
+
triggerLogin,
|
|
29
|
+
refreshCsrfToken,
|
|
30
|
+
resolveBaseUrl,
|
|
31
|
+
httpPost,
|
|
32
|
+
httpGet,
|
|
33
|
+
requestWithAutoLogin,
|
|
34
|
+
} = require("./utils");
|
|
35
|
+
const { t } = require("./i18n");
|
|
36
|
+
|
|
37
|
+
// ── 操作符映射(基于浏览器捕获的真实数据)────────────
|
|
38
|
+
|
|
39
|
+
const OP_CODE_TO_DISPLAY = {
|
|
40
|
+
Equal: "等于",
|
|
41
|
+
NotEqual: "不等于",
|
|
42
|
+
Contains: "包含",
|
|
43
|
+
NotContain: "不包含",
|
|
44
|
+
IsEmpty: "为空",
|
|
45
|
+
IsNotEmpty: "不为空",
|
|
46
|
+
GreaterThan: "大于",
|
|
47
|
+
Bigger: "大于",
|
|
48
|
+
GreaterThanOrEqual: "大于等于",
|
|
49
|
+
LessThan: "小于",
|
|
50
|
+
LessThanOrEqual: "小于等于",
|
|
51
|
+
In: "属于",
|
|
52
|
+
NotIn: "不属于",
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// 注意:从浏览器捕获数据来看,NumberField 的 ruleType 实际是 "rule_text"
|
|
56
|
+
const COMPONENT_TO_RULE_TYPE = {
|
|
57
|
+
TextField: "rule_text",
|
|
58
|
+
TextareaField: "rule_text",
|
|
59
|
+
NumberField: "rule_text",
|
|
60
|
+
SelectField: "rule_select",
|
|
61
|
+
RadioField: "rule_radio",
|
|
62
|
+
DateField: "rule_date",
|
|
63
|
+
EmployeeField: "rule_employee",
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// ── 辅助函数 ─────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
function generateUuid() {
|
|
69
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
|
|
70
|
+
const r = (Math.random() * 16) | 0;
|
|
71
|
+
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
|
72
|
+
return v.toString(16);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
let nodeIdCounter = 1;
|
|
77
|
+
function generateNodeId() {
|
|
78
|
+
return "node_oc" + Date.now().toString(36) + (nodeIdCounter++).toString(36);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function i18n(zhText, enText) {
|
|
82
|
+
return { en_US: enText || zhText, zh_CN: zhText, type: "i18n" };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ── 构建审批/抄送动作列表 ────────────────────────────
|
|
86
|
+
|
|
87
|
+
function buildActions() {
|
|
88
|
+
const actionDefs = [
|
|
89
|
+
{ action: "agree", zh: "同意", en: "Agree", hidden: false },
|
|
90
|
+
{ action: "disagree", zh: "拒绝", en: "Disagree", hidden: false },
|
|
91
|
+
{ action: "save", zh: "保存", en: "Save", hidden: true },
|
|
92
|
+
{ action: "forward", zh: "转交", en: "Forward", hidden: true },
|
|
93
|
+
{ action: "append", zh: "加签", en: "Append", hidden: true },
|
|
94
|
+
{ action: "return", zh: "退回", en: "Return", hidden: true },
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
return actionDefs.map(function (def) {
|
|
98
|
+
return {
|
|
99
|
+
action: def.action,
|
|
100
|
+
name: i18n(def.zh, def.en),
|
|
101
|
+
hidden: def.hidden,
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function buildAppendActions() {
|
|
107
|
+
return [
|
|
108
|
+
{ action: "appendBefore", name: i18n("前加签", "Prepend"), hidden: false },
|
|
109
|
+
{ action: "appendAfter", name: i18n("后加签", "Append After"), hidden: false },
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// ── 构建条件规则 ─────────────────────────────────────
|
|
114
|
+
|
|
115
|
+
function buildConditionRules(rules) {
|
|
116
|
+
return rules.map(function (rule) {
|
|
117
|
+
const ruleType = COMPONENT_TO_RULE_TYPE[rule.componentType] || "rule_text";
|
|
118
|
+
const opDisplay = OP_CODE_TO_DISPLAY[rule.op] || rule.op;
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
fieldId: rule.fieldId,
|
|
122
|
+
fieldName: i18n(rule.fieldName || rule.fieldId),
|
|
123
|
+
ruleType: ruleType,
|
|
124
|
+
componentType: rule.componentType || "TextField",
|
|
125
|
+
op: opDisplay,
|
|
126
|
+
opCode: rule.op,
|
|
127
|
+
value: Array.isArray(rule.value) ? rule.value : [String(rule.value)],
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ── 递归分配 nodeId ──────────────────────────────────
|
|
133
|
+
|
|
134
|
+
function assignNodeIdsRecursive(nodes, nameToIdMap) {
|
|
135
|
+
nodes.forEach(function (node) {
|
|
136
|
+
if (node.type === "route") {
|
|
137
|
+
node._nodeId = generateNodeId();
|
|
138
|
+
const conditions = node.conditions || [];
|
|
139
|
+
conditions.forEach(function (cond) {
|
|
140
|
+
cond._nodeId = generateNodeId();
|
|
141
|
+
if (cond.childNodes && cond.childNodes.length > 0) {
|
|
142
|
+
assignNodeIdsRecursive(cond.childNodes, nameToIdMap);
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
} else {
|
|
146
|
+
node._nodeId = generateNodeId();
|
|
147
|
+
if (node.name) {
|
|
148
|
+
nameToIdMap[node.name] = node._nodeId;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ── 递归构建节点 ─────────────────────────────────────
|
|
155
|
+
|
|
156
|
+
function buildNodeListRecursive(nodes, exitNodeId, nameToIdMap) {
|
|
157
|
+
const processNodes = [];
|
|
158
|
+
const viewNodes = [];
|
|
159
|
+
|
|
160
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
161
|
+
const node = nodes[i];
|
|
162
|
+
const nextNodeId = i + 1 < nodes.length ? nodes[i + 1]._nodeId : exitNodeId;
|
|
163
|
+
|
|
164
|
+
if (node.type === "route") {
|
|
165
|
+
const routeResult = buildRouteNode(node, nextNodeId, nameToIdMap);
|
|
166
|
+
processNodes.push(routeResult.processNode);
|
|
167
|
+
viewNodes.push(routeResult.viewNode);
|
|
168
|
+
} else if (node.type === "approval") {
|
|
169
|
+
const approvalResult = buildApprovalNode(node, nextNodeId, nameToIdMap);
|
|
170
|
+
processNodes.push(approvalResult.processNode);
|
|
171
|
+
viewNodes.push(approvalResult.viewNode);
|
|
172
|
+
} else if (node.type === "carbon") {
|
|
173
|
+
const carbonResult = buildCarbonNode(node, nextNodeId);
|
|
174
|
+
processNodes.push(carbonResult.processNode);
|
|
175
|
+
viewNodes.push(carbonResult.viewNode);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return { processNodes, viewNodes };
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// ── 构建审批节点 ─────────────────────────────────────
|
|
183
|
+
|
|
184
|
+
function buildApprovalNode(node, nextNodeId, nameToIdMap) {
|
|
185
|
+
const nodeId = node._nodeId;
|
|
186
|
+
const approverType = node.approver === "originator"
|
|
187
|
+
? "ext_target_approval_originator"
|
|
188
|
+
: "ext_target_approval_originator";
|
|
189
|
+
|
|
190
|
+
const processNode = {
|
|
191
|
+
name: i18n(node.name || "审批", "Approval"),
|
|
192
|
+
description: i18n(node.description || "发起人审批", "Sponsor approval"),
|
|
193
|
+
type: "approval",
|
|
194
|
+
approvalType: approverType,
|
|
195
|
+
nodeId: nodeId,
|
|
196
|
+
prevId: "",
|
|
197
|
+
nextId: [nextNodeId],
|
|
198
|
+
props: {
|
|
199
|
+
approvals: [[node.approver || "originator"]],
|
|
200
|
+
actions: buildActions(),
|
|
201
|
+
appendActions: buildAppendActions(),
|
|
202
|
+
openDigitalSign: false,
|
|
203
|
+
noActionersType: "stopProcess",
|
|
204
|
+
},
|
|
205
|
+
childNodes: [],
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// 跳转规则(routeRule)
|
|
209
|
+
if (node.routeRules && node.routeRules.length > 0) {
|
|
210
|
+
const routeRuleRules = [];
|
|
211
|
+
node.routeRules.forEach(function (rr) {
|
|
212
|
+
const targetNodeId = nameToIdMap[rr.jumpTo] || nextNodeId;
|
|
213
|
+
routeRuleRules.push({
|
|
214
|
+
action: rr.when || "disagree",
|
|
215
|
+
nextId: targetNodeId,
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
processNode.props.routeRule = {
|
|
220
|
+
rules: routeRuleRules,
|
|
221
|
+
triggerRule: "y",
|
|
222
|
+
ruleIfMiss: "terminate",
|
|
223
|
+
defaultNextId: [],
|
|
224
|
+
};
|
|
225
|
+
} else {
|
|
226
|
+
processNode.props.routeRule = {
|
|
227
|
+
rules: [],
|
|
228
|
+
triggerRule: "n",
|
|
229
|
+
ruleIfMiss: "terminate",
|
|
230
|
+
defaultNextId: [],
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// 字段权限(formConfig)
|
|
235
|
+
if (node.formConfig) {
|
|
236
|
+
processNode.props.formConfig = node.formConfig;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const viewNode = {
|
|
240
|
+
componentName: "ApprovalNode",
|
|
241
|
+
id: nodeId,
|
|
242
|
+
props: {
|
|
243
|
+
nodeName: "ApprovalNode",
|
|
244
|
+
name: i18n(node.name || "审批", "Approval"),
|
|
245
|
+
description: i18n(node.description || "发起人审批", "Sponsor approval"),
|
|
246
|
+
approverRules: {
|
|
247
|
+
type: "APPROVER",
|
|
248
|
+
approvalType: approverType,
|
|
249
|
+
approvals: [[node.approver || "originator"]],
|
|
250
|
+
},
|
|
251
|
+
actions: {
|
|
252
|
+
actions: buildActions(),
|
|
253
|
+
appendActions: buildAppendActions(),
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// viewNode 中的 routeRule
|
|
259
|
+
if (node.routeRules && node.routeRules.length > 0) {
|
|
260
|
+
viewNode.props.routeRule = processNode.props.routeRule;
|
|
261
|
+
} else {
|
|
262
|
+
viewNode.props.routeRule = {
|
|
263
|
+
rules: [],
|
|
264
|
+
triggerRule: "n",
|
|
265
|
+
ruleIfMiss: "terminate",
|
|
266
|
+
defaultNextId: [],
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// viewNode 中的 formConfig
|
|
271
|
+
if (node.formConfig) {
|
|
272
|
+
viewNode.props.formConfig = node.formConfig;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return { processNode, viewNode };
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// ── 构建抄送节点 ─────────────────────────────────────
|
|
279
|
+
|
|
280
|
+
function buildCarbonNode(node, nextNodeId) {
|
|
281
|
+
const nodeId = node._nodeId;
|
|
282
|
+
|
|
283
|
+
const processNode = {
|
|
284
|
+
name: i18n(node.name || "抄送人", "CC"),
|
|
285
|
+
description: "",
|
|
286
|
+
type: "carbon",
|
|
287
|
+
approvalType: "ext_target_approval_originator",
|
|
288
|
+
nodeId: nodeId,
|
|
289
|
+
prevId: "",
|
|
290
|
+
nextId: [nextNodeId],
|
|
291
|
+
props: {
|
|
292
|
+
conditionalMode: "conditional",
|
|
293
|
+
params: [
|
|
294
|
+
{ key: "nodeId", value: nodeId },
|
|
295
|
+
{ key: "instId", value: "#procInstId" },
|
|
296
|
+
{ key: "userId", value: "#originator" },
|
|
297
|
+
{ key: "receiver", value: { type: "VARIABLE", value: [[node.approver || "originator"]] } },
|
|
298
|
+
],
|
|
299
|
+
},
|
|
300
|
+
childNodes: [],
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
const viewNode = {
|
|
304
|
+
componentName: "CarbonNode",
|
|
305
|
+
id: nodeId,
|
|
306
|
+
props: {
|
|
307
|
+
nodeName: "CarbonNode",
|
|
308
|
+
name: i18n(node.name || "抄送人", "CC"),
|
|
309
|
+
approverRules: {
|
|
310
|
+
type: "CC",
|
|
311
|
+
approvalType: "ext_target_approval_originator",
|
|
312
|
+
approvals: [[node.approver || "originator"]],
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
return { processNode, viewNode };
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// ── 构建条件分支路由节点 ─────────────────────────────
|
|
321
|
+
|
|
322
|
+
function buildRouteNode(node, exitNodeId, nameToIdMap) {
|
|
323
|
+
const routeNodeId = node._nodeId;
|
|
324
|
+
const conditions = node.conditions || [];
|
|
325
|
+
|
|
326
|
+
const conditionNodeIds = [];
|
|
327
|
+
const conditionProcessNodes = [];
|
|
328
|
+
const conditionViewNodes = [];
|
|
329
|
+
|
|
330
|
+
// 构建每个条件分支
|
|
331
|
+
conditions.forEach(function (cond, index) {
|
|
332
|
+
const condNodeId = cond._nodeId;
|
|
333
|
+
conditionNodeIds.push(condNodeId);
|
|
334
|
+
|
|
335
|
+
// 递归构建条件分支内的子节点
|
|
336
|
+
let childProcessNodes = [];
|
|
337
|
+
let childViewNodes = [];
|
|
338
|
+
if (cond.childNodes && cond.childNodes.length > 0) {
|
|
339
|
+
const childResult = buildNodeListRecursive(cond.childNodes, exitNodeId, nameToIdMap);
|
|
340
|
+
childProcessNodes = childResult.processNodes;
|
|
341
|
+
childViewNodes = childResult.viewNodes;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// 构建条件规则
|
|
345
|
+
let conditionProps = {
|
|
346
|
+
priority: index + 1,
|
|
347
|
+
isDefault: false,
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
if (cond.rules && cond.rules.length > 0) {
|
|
351
|
+
conditionProps.conditions = {
|
|
352
|
+
condition: (cond.logic || "AND").toUpperCase(),
|
|
353
|
+
conditionCode: cond.logic === "OR" ? "||" : "&&",
|
|
354
|
+
rules: buildConditionRules(cond.rules),
|
|
355
|
+
ruleId: "group-" + generateUuid(),
|
|
356
|
+
};
|
|
357
|
+
conditionProps.calculate = "condition";
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const condProcessNode = {
|
|
361
|
+
name: i18n(cond.name || "条件 " + (index + 1), "Condition " + (index + 1)),
|
|
362
|
+
description: "",
|
|
363
|
+
type: "condition",
|
|
364
|
+
nodeId: condNodeId,
|
|
365
|
+
prevId: routeNodeId,
|
|
366
|
+
nextId: [exitNodeId],
|
|
367
|
+
props: conditionProps,
|
|
368
|
+
childNodes: childProcessNodes,
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
conditionProcessNodes.push(condProcessNode);
|
|
372
|
+
|
|
373
|
+
const condViewNode = {
|
|
374
|
+
componentName: "ConditionNode",
|
|
375
|
+
id: condNodeId,
|
|
376
|
+
props: {
|
|
377
|
+
isDefault: false,
|
|
378
|
+
buttons: [{ name: "关闭" }],
|
|
379
|
+
name: i18n(cond.name || "条件 " + (index + 1), "Condition " + (index + 1)),
|
|
380
|
+
description: "",
|
|
381
|
+
},
|
|
382
|
+
children: childViewNodes,
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
if (cond.rules && cond.rules.length > 0) {
|
|
386
|
+
condViewNode.props.conditions = conditionProps.conditions;
|
|
387
|
+
condViewNode.props.calculate = "condition";
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
conditionViewNodes.push(condViewNode);
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// 添加默认条件分支("其他情况")
|
|
394
|
+
const defaultCondNodeId = generateNodeId();
|
|
395
|
+
conditionNodeIds.push(defaultCondNodeId);
|
|
396
|
+
|
|
397
|
+
const defaultCondProcessNode = {
|
|
398
|
+
name: i18n("其他情况", "Other situations"),
|
|
399
|
+
description: "",
|
|
400
|
+
type: "condition",
|
|
401
|
+
nodeId: defaultCondNodeId,
|
|
402
|
+
prevId: routeNodeId,
|
|
403
|
+
nextId: [exitNodeId],
|
|
404
|
+
props: {
|
|
405
|
+
priority: 2147483647,
|
|
406
|
+
isDefault: true,
|
|
407
|
+
},
|
|
408
|
+
childNodes: [],
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
conditionProcessNodes.push(defaultCondProcessNode);
|
|
412
|
+
|
|
413
|
+
const defaultCondViewNode = {
|
|
414
|
+
componentName: "ConditionNode",
|
|
415
|
+
id: defaultCondNodeId,
|
|
416
|
+
props: {
|
|
417
|
+
isDefault: true,
|
|
418
|
+
buttons: [{ name: "关闭" }],
|
|
419
|
+
name: i18n("其他情况", "Other situations"),
|
|
420
|
+
description: "",
|
|
421
|
+
},
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
conditionViewNodes.push(defaultCondViewNode);
|
|
425
|
+
|
|
426
|
+
// 构建 route processNode
|
|
427
|
+
const routeProcessNode = {
|
|
428
|
+
name: { zh_CN: "ConditionNode", en_US: "" },
|
|
429
|
+
description: "",
|
|
430
|
+
type: "route",
|
|
431
|
+
nodeId: routeNodeId,
|
|
432
|
+
prevId: "",
|
|
433
|
+
nextId: conditionNodeIds,
|
|
434
|
+
props: { outgoingType: "priority" },
|
|
435
|
+
childNodes: conditionProcessNodes,
|
|
436
|
+
};
|
|
437
|
+
|
|
438
|
+
// 构建 route viewNode(ConditionContainer)
|
|
439
|
+
const routeViewNode = {
|
|
440
|
+
componentName: "ConditionContainer",
|
|
441
|
+
id: routeNodeId,
|
|
442
|
+
props: {},
|
|
443
|
+
title: "条件分支",
|
|
444
|
+
children: conditionViewNodes,
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
return { processNode: routeProcessNode, viewNode: routeViewNode };
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
// ── 构建完整的 processJson 和 viewJson ──────────────
|
|
451
|
+
|
|
452
|
+
function buildProcessAndViewJson(definition, processCode, formUuid, baseUrl, appType) {
|
|
453
|
+
const finishNodeId = generateNodeId();
|
|
454
|
+
const nodes = definition.nodes || [];
|
|
455
|
+
|
|
456
|
+
// 第一遍:递归分配 nodeId 并收集名称映射
|
|
457
|
+
const nodeNameToIdMap = {};
|
|
458
|
+
assignNodeIdsRecursive(nodes, nodeNameToIdMap);
|
|
459
|
+
|
|
460
|
+
// 将结束节点加入映射
|
|
461
|
+
nodeNameToIdMap["结束"] = finishNodeId;
|
|
462
|
+
nodeNameToIdMap["finish"] = finishNodeId;
|
|
463
|
+
nodeNameToIdMap["end"] = finishNodeId;
|
|
464
|
+
|
|
465
|
+
// 第二遍:递归构建所有节点
|
|
466
|
+
const middleResult = buildNodeListRecursive(nodes, finishNodeId, nodeNameToIdMap);
|
|
467
|
+
|
|
468
|
+
const firstMiddleNodeId = middleResult.processNodes.length > 0
|
|
469
|
+
? middleResult.processNodes[0].nodeId
|
|
470
|
+
: finishNodeId;
|
|
471
|
+
|
|
472
|
+
// 组装发起节点
|
|
473
|
+
const applyProcessNode = {
|
|
474
|
+
name: i18n("发起", "start"),
|
|
475
|
+
description: "",
|
|
476
|
+
type: "apply",
|
|
477
|
+
nodeId: "sid_instStart",
|
|
478
|
+
prevId: "",
|
|
479
|
+
nextId: [firstMiddleNodeId],
|
|
480
|
+
props: {},
|
|
481
|
+
childNodes: [],
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// 组装结束节点
|
|
485
|
+
const finishProcessNode = {
|
|
486
|
+
name: i18n("结束", "end"),
|
|
487
|
+
description: "",
|
|
488
|
+
type: "finish",
|
|
489
|
+
nodeId: finishNodeId,
|
|
490
|
+
prevId: "",
|
|
491
|
+
nextId: [],
|
|
492
|
+
props: {},
|
|
493
|
+
childNodes: [],
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
// 组装 processJson
|
|
497
|
+
const processNodes = [applyProcessNode];
|
|
498
|
+
middleResult.processNodes.forEach(function (node) {
|
|
499
|
+
processNodes.push(node);
|
|
500
|
+
});
|
|
501
|
+
processNodes.push(finishProcessNode);
|
|
502
|
+
|
|
503
|
+
const processJson = {
|
|
504
|
+
props: {
|
|
505
|
+
allowWithdraw: true,
|
|
506
|
+
allowCollaboration: true,
|
|
507
|
+
allowTemporaryStorage: true,
|
|
508
|
+
processCode: processCode,
|
|
509
|
+
processDetailUrl: baseUrl + "/alibaba/web/" + appType + "/inst/taskDetail.htm",
|
|
510
|
+
processInitUrl: baseUrl + "/alibaba/web/" + appType + "/inst/instStart.htm?processCode=" + processCode,
|
|
511
|
+
processMobileDetailUrl: baseUrl + "/alibaba/mobile/" + appType + "/inst/detail/taskDetail/",
|
|
512
|
+
bindingForm: formUuid,
|
|
513
|
+
stopAssociationRulesIfFailed: false,
|
|
514
|
+
noRecordRecall: false,
|
|
515
|
+
untimedRule: [],
|
|
516
|
+
},
|
|
517
|
+
nodes: processNodes,
|
|
518
|
+
flowConfig: {},
|
|
519
|
+
formulaRules: [],
|
|
520
|
+
approvalSummary: [],
|
|
521
|
+
nodeI18nKeyMap: {},
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// 组装 viewJson
|
|
525
|
+
const viewChildren = [];
|
|
526
|
+
|
|
527
|
+
viewChildren.push({
|
|
528
|
+
componentName: "ApplyNode",
|
|
529
|
+
id: generateNodeId(),
|
|
530
|
+
props: {
|
|
531
|
+
nodeName: "ApplyNode",
|
|
532
|
+
name: i18n("发起", "start"),
|
|
533
|
+
},
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
middleResult.viewNodes.forEach(function (node) {
|
|
537
|
+
viewChildren.push(node);
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
viewChildren.push({
|
|
541
|
+
componentName: "EndNode",
|
|
542
|
+
id: finishNodeId,
|
|
543
|
+
props: {
|
|
544
|
+
name: i18n("结束", "end"),
|
|
545
|
+
},
|
|
546
|
+
});
|
|
547
|
+
|
|
548
|
+
const viewJson = {
|
|
549
|
+
schema: {
|
|
550
|
+
componentName: "CanvasEngine",
|
|
551
|
+
id: generateNodeId(),
|
|
552
|
+
props: {},
|
|
553
|
+
children: viewChildren,
|
|
554
|
+
},
|
|
555
|
+
bindingForm: formUuid,
|
|
556
|
+
formulaRules: [],
|
|
557
|
+
globalSetting: {
|
|
558
|
+
enableSignature: false,
|
|
559
|
+
stopAssociationRulesIfFailed: false,
|
|
560
|
+
nodeMerge: false,
|
|
561
|
+
originatorMerge: false,
|
|
562
|
+
allNodeMerge: false,
|
|
563
|
+
behaviorList: [],
|
|
564
|
+
needOpenDigitalSignNodes: [],
|
|
565
|
+
approvalSummary: [],
|
|
566
|
+
noRecordRecall: false,
|
|
567
|
+
untimedRule: [],
|
|
568
|
+
},
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
return { processJson, viewJson };
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// ── API 调用函数 ─────────────────────────────────────
|
|
575
|
+
|
|
576
|
+
function queryProcessVersions(authRef, appType, processCode, status) {
|
|
577
|
+
const requestPath = "/alibaba/web/" + appType + "/query/process/pageProcessVersion.json"
|
|
578
|
+
+ "?_api=Process.getProcessVersionInfo&_mock=false"
|
|
579
|
+
+ "&_csrf_token=" + encodeURIComponent(authRef.csrfToken)
|
|
580
|
+
+ "&_locale_time_zone_offset=28800000"
|
|
581
|
+
+ "&processCode=" + encodeURIComponent(processCode)
|
|
582
|
+
+ "&appType=" + encodeURIComponent(appType)
|
|
583
|
+
+ "&status=" + (status || "")
|
|
584
|
+
+ "&pageIndex=1&pageSize=10"
|
|
585
|
+
+ "&orderByModifyTime=desc"
|
|
586
|
+
+ "&_stamp=" + Date.now();
|
|
587
|
+
return httpGet(authRef.baseUrl, requestPath, null, authRef.cookies);
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
function switchFormType(authRef, appType, formUuid) {
|
|
591
|
+
const requestPath = "/" + appType + "/query/formdesign/switchFormType.json"
|
|
592
|
+
+ "?_api=Nav.transformForm&_mock=false&_stamp=" + Date.now();
|
|
593
|
+
const postData = querystring.stringify({
|
|
594
|
+
_csrf_token: authRef.csrfToken,
|
|
595
|
+
_locale_time_zone_offset: "28800000",
|
|
596
|
+
toFormType: "process",
|
|
597
|
+
formUuid: formUuid,
|
|
598
|
+
});
|
|
599
|
+
return httpPost(authRef.baseUrl, requestPath, postData, authRef.cookies);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
function getProcessCodeFromAppParam(authRef, appType, formUuid) {
|
|
603
|
+
const requestPath = "/" + appType + "/query/app/getAppPlatFormParam.json"
|
|
604
|
+
+ "?_api=nattyFetch&_mock=false"
|
|
605
|
+
+ "&_csrf_token=" + encodeURIComponent(authRef.csrfToken)
|
|
606
|
+
+ "&_locale_time_zone_offset=28800000"
|
|
607
|
+
+ "&pageIndex=1&pageSize=50"
|
|
608
|
+
+ "&_stamp=" + Date.now();
|
|
609
|
+
return httpGet(authRef.baseUrl, requestPath, null, authRef.cookies).then(function (result) {
|
|
610
|
+
if (result.success && result.content && result.content.formNavigationList) {
|
|
611
|
+
const navList = result.content.formNavigationList;
|
|
612
|
+
for (let i = 0; i < navList.length; i++) {
|
|
613
|
+
if (navList[i].formUuid === formUuid && navList[i].processCode) {
|
|
614
|
+
return navList[i].processCode;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
return null;
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
function getProcessCodeFromSchema(authRef, appType, formUuid) {
|
|
623
|
+
const requestPath = "/dingtalk/web/" + appType + "/query/formdesign/getFormSchema.json"
|
|
624
|
+
+ "?formUuid=" + encodeURIComponent(formUuid)
|
|
625
|
+
+ "&schemaVersion=V5";
|
|
626
|
+
return httpGet(authRef.baseUrl, requestPath, null, authRef.cookies).then(function (result) {
|
|
627
|
+
if (result.success && result.content) {
|
|
628
|
+
const schemaStr = typeof result.content === "string" ? result.content : JSON.stringify(result.content);
|
|
629
|
+
const matches = schemaStr.match(/TPROC[A-Za-z0-9_-]+/g);
|
|
630
|
+
if (matches && matches.length > 0) {
|
|
631
|
+
const unique = [];
|
|
632
|
+
const seen = {};
|
|
633
|
+
matches.forEach(function (m) {
|
|
634
|
+
if (!seen[m]) { seen[m] = true; unique.push(m); }
|
|
635
|
+
});
|
|
636
|
+
return unique[0];
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
return null;
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
function newDraftProcess(authRef, appType, processCode, formUuid, processId, processVersion) {
|
|
644
|
+
const requestPath = "/" + appType + "/query/simpleProcess/newDraftProcess.json";
|
|
645
|
+
const postObj = {
|
|
646
|
+
_csrf_token: authRef.csrfToken,
|
|
647
|
+
_locale_time_zone_offset: "28800000",
|
|
648
|
+
formUuid: formUuid,
|
|
649
|
+
processCode: processCode,
|
|
650
|
+
};
|
|
651
|
+
if (processId) postObj.processId = String(processId);
|
|
652
|
+
if (processVersion !== undefined && processVersion !== null) postObj.processVersion = String(processVersion);
|
|
653
|
+
return httpPost(authRef.baseUrl, requestPath, querystring.stringify(postObj), authRef.cookies);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function saveProcessById(authRef, appType, formUuid, processCode, processId, processVersion, processJsonStr, viewJsonStr) {
|
|
657
|
+
const requestPath = "/alibaba/web/" + appType + "/query/simpleProcess/saveProcessById.json";
|
|
658
|
+
return httpPost(authRef.baseUrl, requestPath, querystring.stringify({
|
|
659
|
+
_csrf_token: authRef.csrfToken,
|
|
660
|
+
formUuid: formUuid,
|
|
661
|
+
isOnline: "true",
|
|
662
|
+
json: processJsonStr,
|
|
663
|
+
needReportLine: "y",
|
|
664
|
+
processCode: processCode,
|
|
665
|
+
processId: String(processId),
|
|
666
|
+
processVersion: String(processVersion),
|
|
667
|
+
viewJson: viewJsonStr,
|
|
668
|
+
}), authRef.cookies);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
function publishProcessById(authRef, appType, formUuid, processCode, processId, processVersion) {
|
|
672
|
+
const requestPath = "/alibaba/web/" + appType + "/query/simpleProcess/publishProcessById.json";
|
|
673
|
+
return httpPost(authRef.baseUrl, requestPath, querystring.stringify({
|
|
674
|
+
_csrf_token: authRef.csrfToken,
|
|
675
|
+
formUuid: formUuid,
|
|
676
|
+
processCode: processCode,
|
|
677
|
+
processId: String(processId),
|
|
678
|
+
processVersion: String(processVersion),
|
|
679
|
+
}), authRef.cookies);
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// ── 主流程 ───────────────────────────────────────────
|
|
683
|
+
|
|
684
|
+
async function run(args) {
|
|
685
|
+
if (args.length < 3) {
|
|
686
|
+
console.error(t("configure_process.usage"));
|
|
687
|
+
process.exit(1);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const appType = args[0];
|
|
691
|
+
const formUuid = args[1];
|
|
692
|
+
const processDefinitionFile = path.resolve(args[2]);
|
|
693
|
+
const processCodeArg = args[3] || null;
|
|
694
|
+
|
|
695
|
+
console.error("🔧 " + t("configure_process.title"));
|
|
696
|
+
console.error(" " + t("configure_process.app_id") + ": " + appType);
|
|
697
|
+
console.error(" " + t("configure_process.form_uuid") + ": " + formUuid);
|
|
698
|
+
console.error(" " + t("configure_process.definition_file") + ": " + processDefinitionFile);
|
|
699
|
+
if (processCodeArg) {
|
|
700
|
+
console.error(" processCode: " + processCodeArg + " (" + t("configure_process.from_cli") + ")");
|
|
701
|
+
}
|
|
702
|
+
console.error("");
|
|
703
|
+
|
|
704
|
+
// 1. 读取流程定义
|
|
705
|
+
if (!fs.existsSync(processDefinitionFile)) {
|
|
706
|
+
console.error(" ❌ " + t("configure_process.file_not_found") + ": " + processDefinitionFile);
|
|
707
|
+
process.exit(1);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
let definition;
|
|
711
|
+
try {
|
|
712
|
+
definition = JSON.parse(fs.readFileSync(processDefinitionFile, "utf-8"));
|
|
713
|
+
} catch (e) {
|
|
714
|
+
console.error(" ❌ " + t("configure_process.parse_failed") + ": " + e.message);
|
|
715
|
+
process.exit(1);
|
|
716
|
+
}
|
|
717
|
+
console.error(" ✅ " + t("configure_process.definition_loaded") + " (" + (definition.nodes || []).length + " " + t("configure_process.nodes") + ")");
|
|
718
|
+
|
|
719
|
+
// 2. 读取登录态
|
|
720
|
+
console.error("\n🔑 " + t("configure_process.loading_auth") + "...");
|
|
721
|
+
let cookieData = loadCookieData();
|
|
722
|
+
if (!cookieData || !cookieData.cookies || cookieData.cookies.length === 0) {
|
|
723
|
+
cookieData = triggerLogin();
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
const authRef = {
|
|
727
|
+
csrfToken: cookieData.csrf_token,
|
|
728
|
+
cookies: cookieData.cookies,
|
|
729
|
+
baseUrl: resolveBaseUrl(cookieData),
|
|
730
|
+
cookieData: cookieData,
|
|
731
|
+
};
|
|
732
|
+
console.error(" ✅ " + t("configure_process.auth_loaded") + ", baseUrl: " + authRef.baseUrl);
|
|
733
|
+
|
|
734
|
+
// 3. 获取 processCode
|
|
735
|
+
console.error("\n🔍 " + t("configure_process.getting_process_code") + "...");
|
|
736
|
+
let processCode = processCodeArg;
|
|
737
|
+
|
|
738
|
+
if (!processCode) {
|
|
739
|
+
// 确保表单是流程表单
|
|
740
|
+
console.error(" " + t("configure_process.switching_form_type") + "...");
|
|
741
|
+
const switchResult = await switchFormType(authRef, appType, formUuid);
|
|
742
|
+
if (switchResult.success) {
|
|
743
|
+
console.error(" ✅ " + t("configure_process.switch_success"));
|
|
744
|
+
} else {
|
|
745
|
+
const switchMsg = switchResult.errorMsg || "";
|
|
746
|
+
if (switchMsg.indexOf("已转换") >= 0 || switchMsg.indexOf("已经是") >= 0) {
|
|
747
|
+
console.error(" ✅ " + t("configure_process.already_process"));
|
|
748
|
+
} else {
|
|
749
|
+
console.error(" ⚠️ " + t("configure_process.switch_warning") + ": " + switchMsg);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// 方法 1: 从 getAppPlatFormParam 接口提取
|
|
754
|
+
console.error(" " + t("configure_process.method1") + "...");
|
|
755
|
+
processCode = await getProcessCodeFromAppParam(authRef, appType, formUuid);
|
|
756
|
+
if (processCode) {
|
|
757
|
+
console.error(" ✅ " + t("configure_process.got_process_code") + ": " + processCode);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
// 方法 2: 从 getFormSchema 中提取
|
|
761
|
+
if (!processCode) {
|
|
762
|
+
console.error(" " + t("configure_process.method2") + "...");
|
|
763
|
+
processCode = await getProcessCodeFromSchema(authRef, appType, formUuid);
|
|
764
|
+
if (processCode) {
|
|
765
|
+
console.error(" ✅ " + t("configure_process.got_from_schema") + ": " + processCode);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
if (!processCode) {
|
|
771
|
+
console.error(" ❌ " + t("configure_process.no_process_code"));
|
|
772
|
+
console.error(" 💡 " + t("configure_process.manual_hint"));
|
|
773
|
+
process.exit(1);
|
|
774
|
+
}
|
|
775
|
+
console.error(" ✅ processCode: " + processCode);
|
|
776
|
+
|
|
777
|
+
// 4. 查询流程版本列表
|
|
778
|
+
console.error("\n🔍 " + t("configure_process.querying_versions") + "...");
|
|
779
|
+
const publishedResult = await queryProcessVersions(authRef, appType, processCode, "PUBLISHED");
|
|
780
|
+
|
|
781
|
+
let latestProcessId = null;
|
|
782
|
+
let latestVersion = 0;
|
|
783
|
+
|
|
784
|
+
if (publishedResult.success && publishedResult.content && publishedResult.content.data && publishedResult.content.data.length > 0) {
|
|
785
|
+
const publishedVersion = publishedResult.content.data[0];
|
|
786
|
+
latestProcessId = publishedVersion.id;
|
|
787
|
+
latestVersion = parseInt(publishedVersion.version, 10);
|
|
788
|
+
console.error(" ✅ " + t("configure_process.found_published") + ": processId=" + latestProcessId + ", version=" + latestVersion);
|
|
789
|
+
} else {
|
|
790
|
+
console.error(" ℹ️ " + t("configure_process.no_published") + "...");
|
|
791
|
+
const allVersionsResult = await queryProcessVersions(authRef, appType, processCode, "");
|
|
792
|
+
if (allVersionsResult.success && allVersionsResult.content && allVersionsResult.content.data && allVersionsResult.content.data.length > 0) {
|
|
793
|
+
const latestItem = allVersionsResult.content.data[0];
|
|
794
|
+
latestProcessId = latestItem.id;
|
|
795
|
+
latestVersion = parseInt(latestItem.version, 10);
|
|
796
|
+
console.error(" ✅ " + t("configure_process.found_latest") + ": processId=" + latestProcessId + ", version=" + latestVersion);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
const newVersion = latestVersion + 1;
|
|
801
|
+
|
|
802
|
+
// 5. 创建新流程版本草稿
|
|
803
|
+
console.error("\n📝 " + t("configure_process.creating_draft") + "...");
|
|
804
|
+
const draftResult = await newDraftProcess(authRef, appType, processCode, formUuid, latestProcessId, newVersion);
|
|
805
|
+
|
|
806
|
+
let newProcessId = null;
|
|
807
|
+
|
|
808
|
+
if (draftResult.success && draftResult.content && draftResult.content.processId) {
|
|
809
|
+
newProcessId = draftResult.content.processId;
|
|
810
|
+
console.error(" ✅ " + t("configure_process.draft_created") + ": processId=" + newProcessId);
|
|
811
|
+
} else if (draftResult.success) {
|
|
812
|
+
console.error(" ✅ " + t("configure_process.draft_created_no_id"));
|
|
813
|
+
const savedResult = await queryProcessVersions(authRef, appType, processCode, "");
|
|
814
|
+
if (savedResult.success && savedResult.content && savedResult.content.data) {
|
|
815
|
+
const savedVersions = savedResult.content.data.filter(function (item) { return item.status === "SAVED"; });
|
|
816
|
+
if (savedVersions.length > 0) {
|
|
817
|
+
newProcessId = savedVersions[0].id;
|
|
818
|
+
} else {
|
|
819
|
+
newProcessId = savedResult.content.data[0].id;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
} else {
|
|
823
|
+
console.error(" ❌ " + t("configure_process.draft_failed") + ": " + (draftResult.errorMsg || JSON.stringify(draftResult)));
|
|
824
|
+
process.exit(1);
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
if (!newProcessId) {
|
|
828
|
+
console.error(" ❌ " + t("configure_process.no_draft_id"));
|
|
829
|
+
process.exit(1);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
// 6. 构建 processJson 和 viewJson
|
|
833
|
+
console.error("\n🏗️ " + t("configure_process.building_json") + "...");
|
|
834
|
+
const result = buildProcessAndViewJson(definition, processCode, formUuid, authRef.baseUrl, appType);
|
|
835
|
+
const processJsonStr = JSON.stringify(result.processJson);
|
|
836
|
+
const viewJsonStr = JSON.stringify(result.viewJson);
|
|
837
|
+
console.error(" ✅ processJson: " + processJsonStr.length + " chars");
|
|
838
|
+
console.error(" ✅ viewJson: " + viewJsonStr.length + " chars");
|
|
839
|
+
|
|
840
|
+
// 7. 保存流程
|
|
841
|
+
console.error("\n💾 " + t("configure_process.saving") + "...");
|
|
842
|
+
const saveResult = await saveProcessById(
|
|
843
|
+
authRef, appType, formUuid, processCode, newProcessId, newVersion,
|
|
844
|
+
processJsonStr, viewJsonStr
|
|
845
|
+
);
|
|
846
|
+
|
|
847
|
+
if (saveResult.success) {
|
|
848
|
+
console.error(" ✅ " + t("configure_process.save_success"));
|
|
849
|
+
} else {
|
|
850
|
+
console.error(" ❌ " + t("configure_process.save_failed") + ": " + (saveResult.errorMsg || JSON.stringify(saveResult)));
|
|
851
|
+
process.exit(1);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// 8. 发布流程
|
|
855
|
+
console.error("\n🚀 " + t("configure_process.publishing") + "...");
|
|
856
|
+
const publishResult = await publishProcessById(
|
|
857
|
+
authRef, appType, formUuid, processCode, newProcessId, newVersion
|
|
858
|
+
);
|
|
859
|
+
|
|
860
|
+
if (publishResult.success) {
|
|
861
|
+
console.error(" ✅ " + t("configure_process.publish_success"));
|
|
862
|
+
} else {
|
|
863
|
+
console.error(" ❌ " + t("configure_process.publish_failed") + ": " + (publishResult.errorMsg || JSON.stringify(publishResult)));
|
|
864
|
+
process.exit(1);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// 9. 输出结果
|
|
868
|
+
const output = {
|
|
869
|
+
success: true,
|
|
870
|
+
processCode: processCode,
|
|
871
|
+
processId: newProcessId,
|
|
872
|
+
processVersion: newVersion,
|
|
873
|
+
appType: appType,
|
|
874
|
+
formUuid: formUuid,
|
|
875
|
+
};
|
|
876
|
+
|
|
877
|
+
console.log(JSON.stringify(output));
|
|
878
|
+
console.error("\n🎉 " + t("configure_process.done"));
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
module.exports = { run };
|