@steedos-labs/plugin-workflow 3.0.12 → 3.0.14
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/README.md +24 -1
- package/main/default/applications/approve_workflow.app.yml +160 -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 +53 -45
- package/main/default/objects/flows/buttons/design_form_layout.button.js +1 -3
- package/main/default/objects/flows/flows.object.yml +4 -3
- package/main/default/objects/instances/buttons/instance_reassign.button.yml +5 -4
- package/main/default/pages/instance_detail.page.amis.json +2 -100
- 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_instance_upgrade.router.js +5 -0
- package/main/default/routes/api_workflow_nav.router.js +160 -136
- package/main/default/routes/api_workflow_next_step.router.js +111 -30
- package/main/default/routes/flow_form_design.ejs +16 -1
- package/main/default/services/instance.service.js +10 -1
- package/package.json +1 -1
- package/public/workflow/index.css +208 -10
- 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
package/README.md
CHANGED
|
@@ -6,4 +6,27 @@
|
|
|
6
6
|
* @Description:
|
|
7
7
|
-->
|
|
8
8
|
## 功能说明
|
|
9
|
-
- 审批王服务,包含 流程触发器
|
|
9
|
+
- 审批王服务,包含 流程触发器
|
|
10
|
+
|
|
11
|
+
## 环境变量配置
|
|
12
|
+
|
|
13
|
+
### STEEDOS_WORKFLOW_ENABLE_CATEGORY_FILTER
|
|
14
|
+
- **说明**: 控制是否在"待处理"、"监控箱"视图以及左侧导航菜单中按流程分类进行筛选和显示
|
|
15
|
+
- **默认行为**: 启用分类筛选(当环境变量未设置或设置为除 'false' 以外的任何值时)
|
|
16
|
+
- **可选值**:
|
|
17
|
+
- 不设置或设置为除 `'false'` 以外的任何值: 启用按分类筛选,根据应用(app)显示对应分类的流程
|
|
18
|
+
- `'false'` (字符串): 禁用按分类筛选,显示所有流程
|
|
19
|
+
- **使用场景**: 国产化优化,简化流程展示逻辑
|
|
20
|
+
- **影响范围**:
|
|
21
|
+
- 待处理(Pending)和监控箱(Monitor Box)视图的数据筛选
|
|
22
|
+
- 左侧导航菜单结构:禁用时仅显示box层级(待办箱、监控箱等),不显示分类和流程子菜单
|
|
23
|
+
|
|
24
|
+
**示例配置**:
|
|
25
|
+
```bash
|
|
26
|
+
# 禁用分类筛选
|
|
27
|
+
STEEDOS_WORKFLOW_ENABLE_CATEGORY_FILTER=false
|
|
28
|
+
|
|
29
|
+
# 启用分类筛选(以下任一方式)
|
|
30
|
+
# STEEDOS_WORKFLOW_ENABLE_CATEGORY_FILTER=true
|
|
31
|
+
# 或者不设置该环境变量(默认启用)
|
|
32
|
+
```
|
|
@@ -6,8 +6,165 @@ icon_slds: approval
|
|
|
6
6
|
is_creator: true
|
|
7
7
|
mobile: true
|
|
8
8
|
sort: 10
|
|
9
|
-
tabs:
|
|
10
|
-
|
|
9
|
+
# tabs:
|
|
10
|
+
# - object_instance_tasks
|
|
11
|
+
default_tab: object_instance_tasks
|
|
12
|
+
|
|
13
|
+
showSidebar: true
|
|
14
|
+
enable_nav_schema: true
|
|
15
|
+
nav_schema: {
|
|
16
|
+
"type": "wrapper",
|
|
17
|
+
"size": "none",
|
|
18
|
+
"body": [
|
|
19
|
+
{
|
|
20
|
+
"type": "steedos-app-menu",
|
|
21
|
+
"stacked": true,
|
|
22
|
+
"appId": "approve_workflow",
|
|
23
|
+
"ignoreNavSchema": true
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"type": "wrapper",
|
|
27
|
+
"size": "none",
|
|
28
|
+
"className": "instances-sidebar-wrapper mt-1 bg-white",
|
|
29
|
+
"body": [
|
|
30
|
+
{
|
|
31
|
+
"type": "service",
|
|
32
|
+
"id": "u:instanceNav",
|
|
33
|
+
"className": "bg-white",
|
|
34
|
+
"onEvent": {
|
|
35
|
+
"@data.changed.instances": {
|
|
36
|
+
"actions": [
|
|
37
|
+
{
|
|
38
|
+
"actionType": "reload"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"body": [
|
|
44
|
+
{
|
|
45
|
+
"type": "button",
|
|
46
|
+
"label": "刷新",
|
|
47
|
+
"className": "instance-nav-reload hidden",
|
|
48
|
+
"onEvent": {
|
|
49
|
+
"click": {
|
|
50
|
+
"actions": [
|
|
51
|
+
{
|
|
52
|
+
"actionType": "reload",
|
|
53
|
+
"componentId": "u:instanceNav"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"type": "input-tree",
|
|
61
|
+
"name": "tree",
|
|
62
|
+
"treeContainerClassName": "h-full bg-white",
|
|
63
|
+
"className": "instance-box-tree h-full w-full p-0 bg-white",
|
|
64
|
+
"id": "u:9f3dd961ca12",
|
|
65
|
+
"stacked": true,
|
|
66
|
+
"multiple": false,
|
|
67
|
+
"enableNodePath": false,
|
|
68
|
+
"hideRoot": true,
|
|
69
|
+
"showIcon": true,
|
|
70
|
+
"initiallyOpen": false,
|
|
71
|
+
"virtualThreshold": 100000,
|
|
72
|
+
"value": "${value}",
|
|
73
|
+
"size": "md",
|
|
74
|
+
"onEvent": {
|
|
75
|
+
"change": {
|
|
76
|
+
"actions": [
|
|
77
|
+
{
|
|
78
|
+
"actionType": "setValue",
|
|
79
|
+
"componentId": "instances_list_service",
|
|
80
|
+
"args": {
|
|
81
|
+
"value": {
|
|
82
|
+
"isFlowDataDone": false
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"actionType": "custom",
|
|
88
|
+
"script": "//获取上一次的flowId和categoryId\nconst lastFlowId = event.data.flowId;\nconst lastCategoryId = event.data.categoryId;\n//从value中获取最新的flowId\nvar flowIdRegex = /&flowId=([^&]+)/;\nvar flowIdMatch = event.data.value.match(flowIdRegex);\nconst flowId = flowIdMatch && flowIdMatch.length > 0 ? flowIdMatch[1] : \"\";\n//从value中获取最新的categoryId\nvar categoryIdRegex = /&categoryId=([^&]+)/;\nvar categoryIdMatch = event.data.value.match(categoryIdRegex);\nconst categoryId = categoryIdMatch && categoryIdMatch.length > 0 ? categoryIdMatch[1] : \"\";\n//获取上一次的listname和最新的listname\nconst lastListName = event.data.listName;\nconst listName = event.data.value.split('?')[0].split('instances/grid/')[1];\n//切换流程时清除过滤条件\nif (lastListName == \"monitor\" && listName == \"monitor\" && (flowId != lastFlowId || categoryId != lastCategoryId)) {\n listViewPropsStoreKey = window.location.pathname + \"/crud\";\n sessionStorage.removeItem(listViewPropsStoreKey);\n sessionStorage.removeItem(listViewPropsStoreKey + \"/query\");\n}"
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"actionType": "setValue",
|
|
92
|
+
"componentId": "instances_list_service",
|
|
93
|
+
"args": {
|
|
94
|
+
"value": {
|
|
95
|
+
"additionalFilters": [
|
|
96
|
+
"${event.data.options.name}",
|
|
97
|
+
"=",
|
|
98
|
+
"${event.data.options.value}"
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"expression": "${event.data.options.level>=10}"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"args": {
|
|
106
|
+
"link": "${event.data.value}",
|
|
107
|
+
"blank": false
|
|
108
|
+
},
|
|
109
|
+
"actionType": "link"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
"menuTpl": {
|
|
115
|
+
"type": "wrapper",
|
|
116
|
+
"className": "flex items-center py-1.5 px-3 m-0 rounded-md transition-colors duration-150",
|
|
117
|
+
"body": [
|
|
118
|
+
{
|
|
119
|
+
"type": "tpl",
|
|
120
|
+
"className": "flex-1 leading-6 truncate instance-menu-label",
|
|
121
|
+
"tpl": "${label}",
|
|
122
|
+
"id": "u:9dee51f00db4"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"type": "tpl",
|
|
126
|
+
"className": "ml-auto",
|
|
127
|
+
"tpl": "",
|
|
128
|
+
"badge": {
|
|
129
|
+
"className": "h-0",
|
|
130
|
+
"offset": [
|
|
131
|
+
-5,
|
|
132
|
+
0
|
|
133
|
+
],
|
|
134
|
+
"mode": "text",
|
|
135
|
+
"text": "${tag | toInt}",
|
|
136
|
+
"overflowCount": 999
|
|
137
|
+
},
|
|
138
|
+
"id": "u:2329cd1fecc2"
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
"id": "u:545154bcc334"
|
|
142
|
+
},
|
|
143
|
+
"unfoldedLevel": 2,
|
|
144
|
+
"source": "${options}"
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
"api": {
|
|
148
|
+
"method": "get",
|
|
149
|
+
"url": "${context.rootUrl}/api/${appId}/workflow/nav",
|
|
150
|
+
"headers": {
|
|
151
|
+
"Authorization": "Bearer ${context.tenantId},${context.authToken}"
|
|
152
|
+
},
|
|
153
|
+
"messages": {},
|
|
154
|
+
"adaptor": "payload.data.value = window.location.pathname + decodeURIComponent(window.location.search); return payload;"
|
|
155
|
+
},
|
|
156
|
+
"messages": {},
|
|
157
|
+
"dsType": "api"
|
|
158
|
+
}
|
|
159
|
+
],
|
|
160
|
+
"isFixedHeight": false,
|
|
161
|
+
"isFixedWidth": false
|
|
162
|
+
}
|
|
163
|
+
],
|
|
164
|
+
"isFixedHeight": false,
|
|
165
|
+
"isFixedWidth": false
|
|
166
|
+
}
|
|
167
|
+
|
|
11
168
|
admin_menus:
|
|
12
169
|
# 分部管理员可以创建和设置流程及相关参数。
|
|
13
170
|
- _id: menu_workflow
|
|
@@ -86,4 +243,4 @@ admin_menus:
|
|
|
86
243
|
permission_sets:
|
|
87
244
|
- admin
|
|
88
245
|
object_name: object_workflows
|
|
89
|
-
parent: menu_workflow
|
|
246
|
+
parent: menu_workflow
|
|
@@ -787,7 +787,7 @@ getHandlersManager.getHandlers = async function (instance_id, step_id, login_use
|
|
|
787
787
|
users = applicantSuperiors;
|
|
788
788
|
}
|
|
789
789
|
|
|
790
|
-
await excuteTriggers(login_user_id, flow_id, instance_id, current_step, users);
|
|
790
|
+
await excuteTriggers({ when: 'cacluateNextStepUsers', userId: login_user_id, flowId: flow_id, insId: instance_id, nextStep: current_step, nextUserIds: users });
|
|
791
791
|
return users;
|
|
792
792
|
};
|
|
793
793
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @Author: sunhaolin@hotoa.com
|
|
3
|
+
* @Date: 2022-12-22 15:02:53
|
|
4
|
+
* @LastEditors: sunhaolin@hotoa.com
|
|
5
|
+
* @LastEditTime: 2022-12-22 15:03:32
|
|
6
|
+
* @Description:
|
|
7
|
+
*/
|
|
8
|
+
var _eval;
|
|
9
|
+
|
|
10
|
+
_eval = require('eval');
|
|
11
|
+
const { getCollection } = require('../utils/collection');
|
|
12
|
+
const _ = require('lodash');
|
|
13
|
+
module.exports = {
|
|
14
|
+
instanceNumberBuilder: async function (spaceId, name) {
|
|
15
|
+
var _NUMBER, _YYYY, context, date, e, numberRules, padding, res, rules, script;
|
|
16
|
+
const db = await getCollection("instance_number_rules");
|
|
17
|
+
numberRules = await db.findOne({
|
|
18
|
+
space: spaceId,
|
|
19
|
+
name: name
|
|
20
|
+
});
|
|
21
|
+
if (!numberRules) {
|
|
22
|
+
throw new Meteor.Error('error!', `${name}`);
|
|
23
|
+
}
|
|
24
|
+
date = new Date();
|
|
25
|
+
context = {};
|
|
26
|
+
context._ = _;
|
|
27
|
+
_YYYY = date.getFullYear();
|
|
28
|
+
_NUMBER = (numberRules.number || 0) + 1;
|
|
29
|
+
context.YYYY = _.clone(_YYYY);
|
|
30
|
+
context.MM = date.getMonth() + 1;
|
|
31
|
+
context.mm = date.getMonth() + 1;
|
|
32
|
+
if (context.MM < 10) {
|
|
33
|
+
context.MM = "0" + context.MM;
|
|
34
|
+
}
|
|
35
|
+
context.DD = date.getDate();
|
|
36
|
+
context.dd = date.getDate();
|
|
37
|
+
if (context.DD < 10) {
|
|
38
|
+
context.DD = "0" + context.DD;
|
|
39
|
+
}
|
|
40
|
+
if (context.YYYY !== numberRules.year) {
|
|
41
|
+
_NUMBER = numberRules.first_number || 1;
|
|
42
|
+
}
|
|
43
|
+
let pLenConst = process.env.STEEDOS_WORKFLOW_INSTANCE_NUMBER_RULES_PADDING_LEN
|
|
44
|
+
let paddingLen = 5
|
|
45
|
+
if (pLenConst) {
|
|
46
|
+
const _paddingLen = parseInt(pLenConst);
|
|
47
|
+
if (_paddingLen >= 0) { // 处理 _paddingLen 值为NaN的情况
|
|
48
|
+
paddingLen = _paddingLen
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
padding = function (num, length) {
|
|
52
|
+
if (length == 0) {
|
|
53
|
+
return num;
|
|
54
|
+
}
|
|
55
|
+
var diff, len;
|
|
56
|
+
len = (num + '').length;
|
|
57
|
+
diff = length - len;
|
|
58
|
+
if (diff > 0) {
|
|
59
|
+
return Array(diff + 1).join('0') + num;
|
|
60
|
+
}
|
|
61
|
+
return num;
|
|
62
|
+
};
|
|
63
|
+
context.NUMBER = padding(_.clone(_NUMBER), paddingLen);
|
|
64
|
+
rules = numberRules.rules.replace("{YYYY}", "' + YYYY + '").replace("{MM}", "' + MM + '").replace("{NUMBER}", "' + NUMBER + '");
|
|
65
|
+
script = `var newNo = '${rules}'; exports.newNo = newNo`;
|
|
66
|
+
try {
|
|
67
|
+
res = _eval(script, "newNo", context, false).newNo;
|
|
68
|
+
await db.update({
|
|
69
|
+
_id: numberRules._id
|
|
70
|
+
}, {
|
|
71
|
+
$set: {
|
|
72
|
+
year: _YYYY,
|
|
73
|
+
number: _NUMBER
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
} catch (error) {
|
|
77
|
+
e = error;
|
|
78
|
+
res = {
|
|
79
|
+
_error: e
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return res;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
@@ -40,6 +40,39 @@ async function _count(query) {
|
|
|
40
40
|
return await getObject('instance_tasks').count(query);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* 更新相关通知为已读
|
|
45
|
+
* @param {String} instance 申请单ID
|
|
46
|
+
* @param {String} handler 处理人ID
|
|
47
|
+
*/
|
|
48
|
+
async function _updateNotificationsAsRead(instance, handler) {
|
|
49
|
+
const notificationsObj = getObject('notifications')
|
|
50
|
+
await notificationsObj.directUpdateMany([
|
|
51
|
+
['owner', '=', handler],
|
|
52
|
+
['is_read', '!=', true],
|
|
53
|
+
['related_to.o', '=', 'instances'],
|
|
54
|
+
['related_to.ids', '=', instance]
|
|
55
|
+
], {
|
|
56
|
+
is_read: true
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 更新相关通知为已删除
|
|
62
|
+
* @param {String} instance 申请单ID
|
|
63
|
+
* @param {String} handler 处理人ID
|
|
64
|
+
*/
|
|
65
|
+
async function _updateNotificationsAsDeleted(instance, handler) {
|
|
66
|
+
const notificationsObj = getObject('notifications')
|
|
67
|
+
await notificationsObj.directUpdateMany([
|
|
68
|
+
['owner', '=', handler],
|
|
69
|
+
['related_to.o', '=', 'instances'],
|
|
70
|
+
['related_to.ids', '=', instance]
|
|
71
|
+
], {
|
|
72
|
+
is_deleted: true
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
43
76
|
/**
|
|
44
77
|
* 新增instance_tasks记录
|
|
45
78
|
* @param {String} insId 申请单ID
|
|
@@ -90,6 +123,16 @@ async function update_instance_tasks(insId, traceId, approveId, doc) {
|
|
|
90
123
|
delete taskDoc._id
|
|
91
124
|
}
|
|
92
125
|
const result = await _update(approveId, taskDoc)
|
|
126
|
+
|
|
127
|
+
// 如果任务已完成,更新相关通知为已读
|
|
128
|
+
if (taskDoc.is_finished) {
|
|
129
|
+
const instance = taskDoc.instance || insId
|
|
130
|
+
const handler = taskDoc.handler
|
|
131
|
+
if (instance && handler) {
|
|
132
|
+
await _updateNotificationsAsRead(instance, handler)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
93
136
|
return result
|
|
94
137
|
}
|
|
95
138
|
|
|
@@ -114,6 +157,15 @@ async function update_many_instance_tasks(insId, traceId, approveIds, keys) {
|
|
|
114
157
|
}
|
|
115
158
|
const result = await _update(aId, taskDoc)
|
|
116
159
|
results.push(result)
|
|
160
|
+
|
|
161
|
+
// 如果任务已完成,更新相关通知为已读
|
|
162
|
+
if (taskDoc.is_finished) {
|
|
163
|
+
const instance = taskDoc.instance || insId
|
|
164
|
+
const handler = taskDoc.handler
|
|
165
|
+
if (instance && handler) {
|
|
166
|
+
await _updateNotificationsAsRead(instance, handler)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
117
169
|
}
|
|
118
170
|
return results
|
|
119
171
|
}
|
|
@@ -124,7 +176,18 @@ async function update_many_instance_tasks(insId, traceId, approveIds, keys) {
|
|
|
124
176
|
* @returns 1
|
|
125
177
|
*/
|
|
126
178
|
async function remove_instance_tasks(approveId) {
|
|
179
|
+
// 删除前先获取任务信息用于更新通知
|
|
180
|
+
const taskDoc = await getObject('instance_tasks').findOne(approveId)
|
|
127
181
|
const result = await _remove(approveId)
|
|
182
|
+
|
|
183
|
+
// 删除任务后,更新相关通知为已删除
|
|
184
|
+
if (taskDoc) {
|
|
185
|
+
const { instance, handler } = taskDoc
|
|
186
|
+
if (instance && handler) {
|
|
187
|
+
await _updateNotificationsAsDeleted(instance, handler)
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
128
191
|
return result
|
|
129
192
|
}
|
|
130
193
|
|
|
@@ -136,8 +199,18 @@ async function remove_instance_tasks(approveId) {
|
|
|
136
199
|
async function remove_many_instance_tasks(approveIds) {
|
|
137
200
|
const results = []
|
|
138
201
|
for (const aId of approveIds) {
|
|
202
|
+
// 删除前先获取任务信息用于更新通知
|
|
203
|
+
const taskDoc = await getObject('instance_tasks').findOne(aId)
|
|
139
204
|
const r = await _remove(aId)
|
|
140
205
|
results.push(r)
|
|
206
|
+
|
|
207
|
+
// 删除任务后,更新相关通知为已删除
|
|
208
|
+
if (taskDoc) {
|
|
209
|
+
const { instance, handler } = taskDoc
|
|
210
|
+
if (instance && handler) {
|
|
211
|
+
await _updateNotificationsAsDeleted(instance, handler)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
141
214
|
}
|
|
142
215
|
return results
|
|
143
216
|
}
|
|
@@ -153,11 +226,16 @@ async function remove_instance_tasks_by_instance_id(insId) {
|
|
|
153
226
|
filters: [
|
|
154
227
|
['instance', '=', insId]
|
|
155
228
|
],
|
|
156
|
-
fields: ['_id']
|
|
229
|
+
fields: ['_id', 'instance', 'handler']
|
|
157
230
|
})
|
|
158
231
|
for (const t of taskDocs) {
|
|
159
232
|
const r = await _remove(t._id)
|
|
160
233
|
results.push(r)
|
|
234
|
+
|
|
235
|
+
// 删除任务后,更新相关通知为已删除
|
|
236
|
+
if (t.instance && t.handler) {
|
|
237
|
+
await _updateNotificationsAsDeleted(t.instance, t.handler)
|
|
238
|
+
}
|
|
161
239
|
}
|
|
162
240
|
return results
|
|
163
241
|
}
|
|
@@ -557,7 +557,7 @@ UUFlowManager.isFlowSpaceMatched = function (flow, space_id) {
|
|
|
557
557
|
}
|
|
558
558
|
};
|
|
559
559
|
|
|
560
|
-
|
|
560
|
+
UUFlowManager.isAmisFormula = (formula) => {
|
|
561
561
|
// 有${}包裹的表达式就识别为amis公式
|
|
562
562
|
return /\$\{.+\}/.test(formula);
|
|
563
563
|
};
|
|
@@ -605,6 +605,7 @@ UUFlowManager.calculateConditionWithAmis = function (values, condition_str) {
|
|
|
605
605
|
* @returns {Boolean} Condition result
|
|
606
606
|
*/
|
|
607
607
|
UUFlowManager.calculateCondition = function (values, condition_str) {
|
|
608
|
+
// console.log('calculateCondition', values, condition_str);
|
|
608
609
|
try {
|
|
609
610
|
const __values = values;
|
|
610
611
|
|
|
@@ -796,6 +797,54 @@ function isSkipStep(instance, step) {
|
|
|
796
797
|
return instance.skip_steps?.includes(step._id);
|
|
797
798
|
}
|
|
798
799
|
|
|
800
|
+
UUFlowManager.initFormulaValues = async function (instance, values) {
|
|
801
|
+
// Get values for condition calculation
|
|
802
|
+
let __values = values !== undefined ? values : UUFlowManager.getUpdatedValues(instance);
|
|
803
|
+
|
|
804
|
+
// Get current and start approve
|
|
805
|
+
let current_approve = null;
|
|
806
|
+
let start_approve = null;
|
|
807
|
+
|
|
808
|
+
for (const trace of instance.traces) {
|
|
809
|
+
if (trace.is_finished === false) {
|
|
810
|
+
current_approve = trace.approves[0];
|
|
811
|
+
}
|
|
812
|
+
if (!trace.previous_trace_ids || trace.previous_trace_ids.length === 0) {
|
|
813
|
+
start_approve = trace.approves[0];
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// Set variables for condition evaluation
|
|
818
|
+
__values["applicant"] = {
|
|
819
|
+
roles: await UUFlowManager.getUserRoles(instance.applicant, instance.space),
|
|
820
|
+
name: instance.applicant_name,
|
|
821
|
+
organization: await UUFlowManager.getOrganization(instance.applicant_organization),
|
|
822
|
+
id: instance.applicant
|
|
823
|
+
};
|
|
824
|
+
|
|
825
|
+
__values["submitter"] = {
|
|
826
|
+
roles: await UUFlowManager.getUserRoles(start_approve.handler, instance.space),
|
|
827
|
+
name: start_approve.handler_name,
|
|
828
|
+
organization: {
|
|
829
|
+
fullname: start_approve.handler_organization_fullname,
|
|
830
|
+
name: start_approve.handler_organization_name
|
|
831
|
+
},
|
|
832
|
+
id: start_approve.handler
|
|
833
|
+
};
|
|
834
|
+
|
|
835
|
+
__values["approver"] = {
|
|
836
|
+
roles: await UUFlowManager.getUserRoles(current_approve.handler, instance.space),
|
|
837
|
+
name: current_approve.handler_name,
|
|
838
|
+
organization: {
|
|
839
|
+
fullname: current_approve.handler_organization_fullname,
|
|
840
|
+
name: current_approve.handler_organization_name
|
|
841
|
+
},
|
|
842
|
+
id: current_approve.handler
|
|
843
|
+
};
|
|
844
|
+
|
|
845
|
+
return __values;
|
|
846
|
+
}
|
|
847
|
+
|
|
799
848
|
/**
|
|
800
849
|
* Get next steps for instance
|
|
801
850
|
* @param {Object} instance - Instance object
|
|
@@ -810,49 +859,8 @@ UUFlowManager.getNextSteps = async function (instance, flow, step, judge, values
|
|
|
810
859
|
let nextSteps = [];
|
|
811
860
|
|
|
812
861
|
if (step_type === "condition") {
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
// Get current and start approve
|
|
817
|
-
let current_approve = null;
|
|
818
|
-
let start_approve = null;
|
|
819
|
-
|
|
820
|
-
for (const trace of instance.traces) {
|
|
821
|
-
if (trace.is_finished === false) {
|
|
822
|
-
current_approve = trace.approves[0];
|
|
823
|
-
}
|
|
824
|
-
if (!trace.previous_trace_ids || trace.previous_trace_ids.length === 0) {
|
|
825
|
-
start_approve = trace.approves[0];
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
// Set variables for condition evaluation
|
|
830
|
-
__values["applicant"] = {
|
|
831
|
-
roles: await UUFlowManager.getUserRoles(instance.applicant, instance.space),
|
|
832
|
-
name: instance.applicant_name,
|
|
833
|
-
organization: {
|
|
834
|
-
fullname: instance.applicant_organization_fullname,
|
|
835
|
-
name: instance.applicant_organization_name
|
|
836
|
-
}
|
|
837
|
-
};
|
|
838
|
-
|
|
839
|
-
__values["submitter"] = {
|
|
840
|
-
roles: await UUFlowManager.getUserRoles(start_approve.handler, instance.space),
|
|
841
|
-
name: start_approve.handler_name,
|
|
842
|
-
organization: {
|
|
843
|
-
fullname: start_approve.handler_organization_fullname,
|
|
844
|
-
name: start_approve.handler_organization_name
|
|
845
|
-
}
|
|
846
|
-
};
|
|
847
|
-
|
|
848
|
-
__values["approver"] = {
|
|
849
|
-
roles: await UUFlowManager.getUserRoles(current_approve.handler, instance.space),
|
|
850
|
-
name: current_approve.handler_name,
|
|
851
|
-
organization: {
|
|
852
|
-
fullname: current_approve.handler_organization_fullname,
|
|
853
|
-
name: current_approve.handler_organization_name
|
|
854
|
-
}
|
|
855
|
-
};
|
|
862
|
+
|
|
863
|
+
const __values = await UUFlowManager.initFormulaValues(instance, values);
|
|
856
864
|
|
|
857
865
|
// Get form and form version
|
|
858
866
|
const form = await UUFlowManager.getForm(instance.form);
|
|
@@ -875,7 +883,7 @@ UUFlowManager.getNextSteps = async function (instance, flow, step, judge, values
|
|
|
875
883
|
if (step_line.state === "submitted") {
|
|
876
884
|
let step_line_condition = step_line.condition;
|
|
877
885
|
let allow = false;
|
|
878
|
-
if (isAmisFormula(step_line_condition)) {
|
|
886
|
+
if (UUFlowManager.isAmisFormula(step_line_condition)) {
|
|
879
887
|
allow = UUFlowManager.calculateConditionWithAmis(__values, step_line_condition);
|
|
880
888
|
}
|
|
881
889
|
else {
|
|
@@ -60,6 +60,9 @@ fields:
|
|
|
60
60
|
readonly: true
|
|
61
61
|
visible_on: "{{global.mode !='read' ? false : true}}"
|
|
62
62
|
name: current_no
|
|
63
|
+
company_id:
|
|
64
|
+
label: Main Division
|
|
65
|
+
visible_on: "{{true}}"
|
|
63
66
|
description:
|
|
64
67
|
label: Description
|
|
65
68
|
type: textarea
|
|
@@ -77,8 +80,6 @@ fields:
|
|
|
77
80
|
type: textarea
|
|
78
81
|
is_wide: true
|
|
79
82
|
name: help_text
|
|
80
|
-
company_id:
|
|
81
|
-
label: Main Division
|
|
82
83
|
created_by:
|
|
83
84
|
label: Created by
|
|
84
85
|
sort_no: 9999
|
|
@@ -906,7 +907,7 @@ permission_set:
|
|
|
906
907
|
allowEdit: false
|
|
907
908
|
allowRead: true
|
|
908
909
|
modifyAllRecords: false
|
|
909
|
-
viewAllRecords:
|
|
910
|
+
viewAllRecords: false
|
|
910
911
|
admin:
|
|
911
912
|
allowCreate: true
|
|
912
913
|
allowDelete: false
|
|
@@ -37,9 +37,9 @@ amis_schema: |-
|
|
|
37
37
|
{
|
|
38
38
|
"type": "tpl",
|
|
39
39
|
"tpl": "当前步骤: <p class='font-medium inline'>${record.currentStep.name}</p>",
|
|
40
|
-
"inline":
|
|
41
|
-
"
|
|
42
|
-
"
|
|
40
|
+
"inline": false,
|
|
41
|
+
"id": "u:1f7dd93080d3",
|
|
42
|
+
"className": "m-b-sm"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
45
45
|
"type": "steedos-select-user",
|
|
@@ -57,7 +57,8 @@ amis_schema: |-
|
|
|
57
57
|
"id": "u:bffe87a42168",
|
|
58
58
|
"minRows": 3,
|
|
59
59
|
"maxRows": 20,
|
|
60
|
-
"placeholder": "请填写重定位的理由"
|
|
60
|
+
"placeholder": "请填写重定位的理由",
|
|
61
|
+
"className": "m-t-sm"
|
|
61
62
|
}
|
|
62
63
|
],
|
|
63
64
|
"id": "u:1779a48caedb",
|