@yjli/wedaopenapi 1.0.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/auth.js +65 -0
- package/index.js +4 -0
- package/package.json +25 -0
- package/test.js +20 -0
- package/wedaopenapi.js +836 -0
- package/workflow.js +130 -0
package/auth.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
const fetch = require('node-fetch');
|
|
2
|
+
|
|
3
|
+
class Auth {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this.options = Object.assign(
|
|
6
|
+
{
|
|
7
|
+
// 主机地址
|
|
8
|
+
host: 'https://weda.web.scut.edu.cn',
|
|
9
|
+
|
|
10
|
+
// 访问令牌密钥
|
|
11
|
+
secretId: undefined,
|
|
12
|
+
secretKey: undefined,
|
|
13
|
+
|
|
14
|
+
debug: false,
|
|
15
|
+
},
|
|
16
|
+
options
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
if (!this.options.secretId || !this.options.secretKey) {
|
|
20
|
+
throw new Error('secretId 或 secretKey 未设置');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* 获取访问令牌
|
|
26
|
+
*/
|
|
27
|
+
async getAccessToken() {
|
|
28
|
+
// 如果缓存中存在(未过期),则直接返回缓存中的值
|
|
29
|
+
if (this.token && this.tokenExpiredAt > Date.now()) {
|
|
30
|
+
return this.token;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// 否则,获取 token,并存入缓存
|
|
34
|
+
const tokenResponse = await fetch(
|
|
35
|
+
`${this.options.host}/auth/v1/token/clientCredential`,
|
|
36
|
+
{
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
Authorization: `Basic ${Buffer.from(
|
|
41
|
+
`${this.options.secretId}:${this.options.secretKey}`
|
|
42
|
+
).toString('base64')}`,
|
|
43
|
+
},
|
|
44
|
+
body: JSON.stringify({
|
|
45
|
+
grant_type: 'client_credentials',
|
|
46
|
+
}),
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const json = await tokenResponse.json();
|
|
51
|
+
|
|
52
|
+
if (this.options.debug) {
|
|
53
|
+
console.log('Access Token Response', json);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const { access_token, expires_in } = json;
|
|
57
|
+
|
|
58
|
+
// 缓存 token,并设置过期时间,提前 1 分钟过期扩大容错。
|
|
59
|
+
this.token = access_token;
|
|
60
|
+
this.tokenExpiredAt = Date.now() + expires_in * 1000 - 60000;
|
|
61
|
+
|
|
62
|
+
return access_token;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
module.exports = Auth;
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yjli/wedaopenapi",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://ncgit.scut.edu.cn/dev/lowcode/wedaopenapi.git"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"weda",
|
|
14
|
+
"openapi"
|
|
15
|
+
],
|
|
16
|
+
"author": "yjli",
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"description": "",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"node-fetch": "^2.7.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"dotenv": "^17.4.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/test.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require('dotenv').config({ path: require('path').resolve(__dirname, '.env.test') });
|
|
2
|
+
|
|
3
|
+
const { WedaOpenApi } = require('./index');
|
|
4
|
+
|
|
5
|
+
(async () => {
|
|
6
|
+
try {
|
|
7
|
+
const api = new WedaOpenApi({
|
|
8
|
+
host: process.env.WEDA_HOST,
|
|
9
|
+
envId: process.env.WEDA_ENV_ID,
|
|
10
|
+
secretId: process.env.WEDA_SECRET_ID,
|
|
11
|
+
secretKey: process.env.WEDA_SECRET_KEY,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const res = await api.describeUserList(1, 10);
|
|
15
|
+
console.log('describeUserList result:', res);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error('Failed to initialize WedaOpenApi:', error);
|
|
18
|
+
process.exitCode = 1;
|
|
19
|
+
}
|
|
20
|
+
})();
|
package/wedaopenapi.js
ADDED
|
@@ -0,0 +1,836 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 微搭 open api (服务端接口)
|
|
3
|
+
* const WedaOpenApi = require("./wedaopenapi");
|
|
4
|
+
* const wedaapi = new WedaOpenApi({host: "hhh", envId: "iii", secretId: "xxx", secretKey: "xxx"});
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
const fetch = require('node-fetch');
|
|
8
|
+
const Auth = require('./auth');
|
|
9
|
+
|
|
10
|
+
class WedaOpenApi {
|
|
11
|
+
constructor(options = {}) {
|
|
12
|
+
this.wedaPath = this.wedaPath.bind(this);
|
|
13
|
+
this.auth = this.auth.bind(this);
|
|
14
|
+
|
|
15
|
+
this.options = Object.assign(
|
|
16
|
+
{
|
|
17
|
+
// 主机地址
|
|
18
|
+
host: 'https://weda.web.scut.edu.cn',
|
|
19
|
+
|
|
20
|
+
// 环境信息
|
|
21
|
+
envId: 'lowcode-7gwjk8v14d46dda1',
|
|
22
|
+
envType: 'prod',
|
|
23
|
+
|
|
24
|
+
// 访问令牌密钥
|
|
25
|
+
secretId: undefined,
|
|
26
|
+
secretKey: undefined,
|
|
27
|
+
|
|
28
|
+
debug: false,
|
|
29
|
+
},
|
|
30
|
+
options,
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
this.oauth = new Auth(this.options);
|
|
34
|
+
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 请求指定微搭路径
|
|
40
|
+
* @param {String} path 路径
|
|
41
|
+
* @param {String} httpMethod http 方法,用到:GET|PUT|POST|PATCH|DELETE
|
|
42
|
+
* @param {String} queryString 查询字符串
|
|
43
|
+
* @param {Object} bodyObject 请求体
|
|
44
|
+
* @returns
|
|
45
|
+
*/
|
|
46
|
+
async wedaPath(path, httpMethod, queryString, body) {
|
|
47
|
+
const timeLabel = 'weda-api-' + Date.now() + Math.random();
|
|
48
|
+
|
|
49
|
+
const token = await this.oauth.getAccessToken();
|
|
50
|
+
let request = {
|
|
51
|
+
method: httpMethod,
|
|
52
|
+
headers: {
|
|
53
|
+
'Content-Type': 'application/json',
|
|
54
|
+
Authorization: `Bearer ${token}`,
|
|
55
|
+
'X-Request-Id': timeLabel,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
let url = this.options.host + path;
|
|
60
|
+
|
|
61
|
+
if (queryString && queryString.trim().length > 0) {
|
|
62
|
+
url = url.concat('?').concat(queryString.trim());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (body) {
|
|
66
|
+
request.body = JSON.stringify(body);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (this.options.debug) {
|
|
70
|
+
console.time(timeLabel);
|
|
71
|
+
console.log(new Date().toLocaleString(), 'Request URL', url);
|
|
72
|
+
console.log(request);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const response = await fetch(url, request);
|
|
76
|
+
|
|
77
|
+
if (this.options.debug) {
|
|
78
|
+
console.log('Response Status:', response.status);
|
|
79
|
+
console.timeEnd(timeLabel);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (response.status >= 400) {
|
|
83
|
+
console.error(`Response url: ${response.url}`);
|
|
84
|
+
console.error(`Response status: ${response.status}`);
|
|
85
|
+
console.error(`Response statusText: ${response.statusText}`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return response;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
//-------------------------------------------------------------------------------//
|
|
92
|
+
// 以下是 auth 接口
|
|
93
|
+
//-------------------------------------------------------------------------------//
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* auth 接口
|
|
97
|
+
* @see https://docs.cloudbase.net/lowcode/manage/auth
|
|
98
|
+
* @param {String} methodName 接口方法名
|
|
99
|
+
* @param {String} version 版本
|
|
100
|
+
* @param {String} httpMethod HTTP 请求方法名
|
|
101
|
+
* @param {String} queryString queryString
|
|
102
|
+
* @param {Object} body 请求 body
|
|
103
|
+
* @returns
|
|
104
|
+
*/
|
|
105
|
+
async auth(methodName, version, httpMethod, queryString, body) {
|
|
106
|
+
return await (
|
|
107
|
+
await this.wedaPath(
|
|
108
|
+
`/weda/auth/${version}/${this.options.envType}/${methodName}`,
|
|
109
|
+
httpMethod,
|
|
110
|
+
queryString,
|
|
111
|
+
body,
|
|
112
|
+
)
|
|
113
|
+
).json();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* 增加用户
|
|
118
|
+
* @param {Object} user 用户对象,example: {Name: "john", NickName: "John Smith", Uuid: "john"}
|
|
119
|
+
* @returns {Object}
|
|
120
|
+
*/
|
|
121
|
+
async addUser(user) {
|
|
122
|
+
return await this.auth('addUser', 'v1.1', 'POST', undefined, user);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 删除用户
|
|
127
|
+
* @param {Array} userIdArray 用户id数组,example: ["17023423432497238478", "17034832794329988"]
|
|
128
|
+
* @returns {Object}
|
|
129
|
+
*/
|
|
130
|
+
async deleteUser(userIdArray) {
|
|
131
|
+
return await this.auth('deleteUser', 'v1.1', 'POST', undefined, {
|
|
132
|
+
UserIdList: userIdArray,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 更新用户信息
|
|
138
|
+
* @param {Object} user 用户对象,example: {UserId: "id", Name: "john", NickName: "John Smith", Uuid: "john"}
|
|
139
|
+
* 注意:MainOrg 和 Orgs 参数,不传或传 null 时,都会清空。其他参数不传表示不修改。
|
|
140
|
+
* @returns {Object} {Response: {Error: {Code, Message}, Data: boolean}}
|
|
141
|
+
*/
|
|
142
|
+
async updateUserInfoByUserId(user) {
|
|
143
|
+
return await this.auth(
|
|
144
|
+
'updateUserInfoByUserId',
|
|
145
|
+
'v1.1',
|
|
146
|
+
'POST',
|
|
147
|
+
undefined,
|
|
148
|
+
user,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* 查询用户详细信息
|
|
154
|
+
* @param {String} id 用户id
|
|
155
|
+
* @param {Boolean} fetchRoles 是否获取角色
|
|
156
|
+
* @param {Boolean} fetchIdentities 是否获取 IdP Token 信息
|
|
157
|
+
* @returns {Object} {Response: {Data: {Name, NickName, UserId, RelatedRoles: {Id,...}, MainOrg: {OrgId,...}, ...}}}
|
|
158
|
+
*/
|
|
159
|
+
async describeWedaUser(id, fetchRoles = false, fetchIdentities = false) {
|
|
160
|
+
const body = { UserId: id };
|
|
161
|
+
if (fetchRoles) {
|
|
162
|
+
body.RelatedType = 'UserRelatedRole';
|
|
163
|
+
}
|
|
164
|
+
if (fetchIdentities) {
|
|
165
|
+
body.WithIdentities = true;
|
|
166
|
+
}
|
|
167
|
+
return await this.auth('describeWedaUser', 'v1.1', 'POST', undefined, body);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* 分页查询所有用户
|
|
172
|
+
* @param {Number} pageNumber 页码,从第1页开始,默认是1
|
|
173
|
+
* @param {Number} pageSize 每页记录数,默认100
|
|
174
|
+
* @returns {Object}
|
|
175
|
+
*/
|
|
176
|
+
async describeUserList(pageNumber = 1, pageSize = 100) {
|
|
177
|
+
const body = {
|
|
178
|
+
PageNo: pageNumber < 1 ? 1 : pageNumber,
|
|
179
|
+
PageSize: pageSize < 0 ? 100 : pageSize,
|
|
180
|
+
};
|
|
181
|
+
return await this.auth('describeUserList', 'v1.1', 'POST', undefined, body);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 批量增加新用户
|
|
186
|
+
* 注意:此接口目前混合云不支持
|
|
187
|
+
* @param {Array} users 用户对象数组,数量不能超过100. eg: {users: [{"name": "", nickName: "", uuid: "", roleIds: ["1", "2"], mainOrg: {"orgId": "id"}}]}
|
|
188
|
+
* @returns {Object}
|
|
189
|
+
*/
|
|
190
|
+
async batchAddUsers(users) {
|
|
191
|
+
return await this.auth('batchAddUsers', 'v1', 'POST', undefined, {
|
|
192
|
+
users: users,
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* 新建组织机构
|
|
198
|
+
* @param {Object} org 组织机构对象,{*departmentCode,*departmentName, departmentParentCode, info}
|
|
199
|
+
* @returns {Object}
|
|
200
|
+
*/
|
|
201
|
+
async addOrg(org) {
|
|
202
|
+
const body = {
|
|
203
|
+
OrgData: JSON.stringify(org),
|
|
204
|
+
};
|
|
205
|
+
return await this.auth('addOrg', 'v1', 'POST', undefined, body);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* 更新组织机构
|
|
210
|
+
* @param {Object} org 组织机构对象,{*_id, departmentName, departmentParentCode, info}
|
|
211
|
+
* @returns {Object} { Response: { RequestId: '03e0a9f91364c', Data: 1 } }
|
|
212
|
+
*/
|
|
213
|
+
async updateOrg(org) {
|
|
214
|
+
const body = {
|
|
215
|
+
OrgData: JSON.stringify(org),
|
|
216
|
+
};
|
|
217
|
+
return await this.auth('updateOrg', 'v1', 'POST', undefined, body);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* 删除组织机构
|
|
222
|
+
* @param {String} id
|
|
223
|
+
* @returns {Object} { Response: { RequestId: 'caeddf6c3136c', Data: 1 } }
|
|
224
|
+
*/
|
|
225
|
+
async deleteOrg(id) {
|
|
226
|
+
const body = {
|
|
227
|
+
OrgId: id,
|
|
228
|
+
};
|
|
229
|
+
return await this.auth('deleteOrg', 'v1', 'POST', undefined, body);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* 分页查询组织机构
|
|
234
|
+
* @param {Number} pageNumber 页码,从第1页开始,默认是1
|
|
235
|
+
* @param {Number} pageSize 每页记录数,默认1000
|
|
236
|
+
* @returns {Object} {Response: {RequestId, Data: {Total, Schema, DataList[{DataId: _id, DataRecord: jsonString}]}}}
|
|
237
|
+
* jsonString: '{"departmentName":"","departmentParentCode":"!!ROOT","departmentCode":"","source":1.0,"depth":1,"_id":"","##DATA":{"_userInfoList":[]}}'
|
|
238
|
+
*/
|
|
239
|
+
async describeOrgs(pageNumber = 1, pageSize = 1000) {
|
|
240
|
+
const body = {
|
|
241
|
+
PageNo: pageNumber < 1 ? 1 : pageNumber,
|
|
242
|
+
PageSize: pageSize < 0 ? 1000 : pageSize,
|
|
243
|
+
};
|
|
244
|
+
return await this.auth('describeOrgs', 'v1', 'POST', undefined, body);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* 设置组织机构负责人
|
|
249
|
+
* @param {String} orgId 组织机构id
|
|
250
|
+
* @param {Array} userIdList 用户id数组
|
|
251
|
+
* @returns {Object}
|
|
252
|
+
*/
|
|
253
|
+
async setOrgPrincipal(orgId, userIdList) {
|
|
254
|
+
const body = {
|
|
255
|
+
orgId: orgId,
|
|
256
|
+
userIdList: userIdList,
|
|
257
|
+
};
|
|
258
|
+
return await this.auth('setOrgPrincipal', 'v1', 'POST', undefined, body);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* 新建角色
|
|
263
|
+
* @param {Object} role 角色对象 {*roleName, *roleIdentity, description}
|
|
264
|
+
* @returns {Object} {response: {requestId, error: {code, message}, data: roleId}}
|
|
265
|
+
*/
|
|
266
|
+
async createRole(role) {
|
|
267
|
+
return await this.auth('createRole', 'v1', 'POST', undefined, role);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* 修改角色
|
|
272
|
+
* @param {Object} role 角色对象 {*roleId, roleName, description}
|
|
273
|
+
* @returns {Object} {response: {requestId, error: {code, message}, data: boolean}}
|
|
274
|
+
*/
|
|
275
|
+
async modifyRole(role) {
|
|
276
|
+
return await this.auth('modifyRole', 'v1', 'PUT', undefined, role);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* 删除角色
|
|
281
|
+
* @param {String} roleId 角色id
|
|
282
|
+
* @returns {Object} {response: {requestId, error: {code, message}, data: boolean}}
|
|
283
|
+
*/
|
|
284
|
+
async deleteRole(roleId) {
|
|
285
|
+
return await this.auth(
|
|
286
|
+
'deleteRole',
|
|
287
|
+
'v1',
|
|
288
|
+
'DELETE',
|
|
289
|
+
`roleId=${roleId}`,
|
|
290
|
+
undefined,
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* 查询角色详情
|
|
296
|
+
* @param {String} roleName 角色名
|
|
297
|
+
* @returns {Object} {response: {requestId, error: {code, message}, data: {roleName, roleIdentity, roleId, description, isReleased}}}
|
|
298
|
+
*/
|
|
299
|
+
async describeRole(roleName) {
|
|
300
|
+
return await this.auth(
|
|
301
|
+
'describeRole',
|
|
302
|
+
'v1',
|
|
303
|
+
'GET',
|
|
304
|
+
`roleName=${roleName}`,
|
|
305
|
+
undefined,
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* 分页查询角色
|
|
311
|
+
* @param {Number} pageNumber 页码,从第1页开始,默认是1
|
|
312
|
+
* @param {Number} pageSize 每页记录数,默认1000
|
|
313
|
+
* @returns {Object} {Response: {RequestId, Data: {Total, RoleList: []}}}
|
|
314
|
+
*/
|
|
315
|
+
async describeRoleList(pageNumber = 1, pageSize = 1000) {
|
|
316
|
+
const body = {
|
|
317
|
+
PageNo: pageNumber < 1 ? 1 : pageNumber,
|
|
318
|
+
PageSize: pageSize < 0 ? 1000 : pageSize,
|
|
319
|
+
};
|
|
320
|
+
return await this.auth('describeRoleList', 'v1.1', 'POST', undefined, body);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* 查询拥有角色的用户
|
|
325
|
+
* @param {String} roleId 角色 id
|
|
326
|
+
* @param {Number} pageNumber 页码,从第1页开始,默认是1
|
|
327
|
+
* @param {Number} pageSize 每页记录数,默认1000
|
|
328
|
+
* @returns {Object} {Response: {RequestId, Data: {Total, UserList: []}}}
|
|
329
|
+
*/
|
|
330
|
+
async describeUsersByRoleId(roleId, pageNumber = 1, pageSize = 1000) {
|
|
331
|
+
const body = {
|
|
332
|
+
RoleId: roleId,
|
|
333
|
+
PageNo: pageNumber < 1 ? 1 : pageNumber,
|
|
334
|
+
PageSize: pageSize < 0 ? 1000 : pageSize,
|
|
335
|
+
};
|
|
336
|
+
return await this.auth(
|
|
337
|
+
'describeUsersByRoleId',
|
|
338
|
+
'v1',
|
|
339
|
+
'POST',
|
|
340
|
+
undefined,
|
|
341
|
+
body,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/**
|
|
346
|
+
* 批量设置关联角色,注意此操作会完全替换用户的角色,并非增加关联。
|
|
347
|
+
* @param {Array} authorizations 授权数组 [{UserId, RoleIds: []}, ...]
|
|
348
|
+
* @returns {Object} {Response: {RequestId, Error: {Code, Message}, Data: boolean}}
|
|
349
|
+
*/
|
|
350
|
+
async batchAuthorize(authorizations) {
|
|
351
|
+
const body = {
|
|
352
|
+
AuthorizeParam: authorizations,
|
|
353
|
+
};
|
|
354
|
+
return await this.auth('batchAuthorize', 'v1', 'POST', undefined, body);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* 取消指定角色的关联用户
|
|
359
|
+
* @param {String} roleId 角色 id
|
|
360
|
+
* @param {Array} userIds 用户 id 数组
|
|
361
|
+
* @returns {Object} {response: {requestId, error: {code, message}, data: boolean}}
|
|
362
|
+
*/
|
|
363
|
+
async unbindRoleUsers(roleId, userIds) {
|
|
364
|
+
const body = {
|
|
365
|
+
roleId: roleId,
|
|
366
|
+
userIds: userIds,
|
|
367
|
+
};
|
|
368
|
+
return await this.auth('unbindRoleUsers', 'v1', 'POST', undefined, body);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* 更新指定角色的关联用户。
|
|
373
|
+
* @param {String} roleId 角色 id
|
|
374
|
+
* @param {Array} userIds 用户 id 数组
|
|
375
|
+
* @returns {Object} {response: {requestId, error: {code, message}, data: boolean}}
|
|
376
|
+
*/
|
|
377
|
+
async updateRoleUsers(roleId, userIds) {
|
|
378
|
+
const body = {
|
|
379
|
+
roleId: roleId,
|
|
380
|
+
userIds: userIds,
|
|
381
|
+
};
|
|
382
|
+
return await this.auth('updateRoleUsers', 'v1', 'POST', undefined, body);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* 查询角色的资源权限
|
|
387
|
+
* @param {String} roleId 角色 id
|
|
388
|
+
* @param {String} resourceType 资源类型,app, page, modelApp, modelAppPage, dataSource, flow
|
|
389
|
+
* @param {Array} resourceIds 资源 id 数组
|
|
390
|
+
* @returns {Object} {response: {data: [{roleId, resourceType, resourceId, isAccess, rowPermissionParams: [{rowPermissionScopeType, rowPermissionOperationType}]}]}}
|
|
391
|
+
*/
|
|
392
|
+
async checkRoleResource(roleId, resourceType, resourceIds) {
|
|
393
|
+
const body = {
|
|
394
|
+
roleId: roleId,
|
|
395
|
+
resourceType: resourceType,
|
|
396
|
+
resourceIds: resourceIds,
|
|
397
|
+
};
|
|
398
|
+
return await this.auth('checkRoleResource', 'v1', 'POST', undefined, body);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* 查询角色对 APIs 方法的权限
|
|
403
|
+
* @param {String} roleId 角色 id
|
|
404
|
+
* @param {String} dataSourceId 属于源 id
|
|
405
|
+
* @returns {Object} {response: {data: {methodAuthList: [{methodName, isAccess: boolean}]}}}
|
|
406
|
+
*/
|
|
407
|
+
async describeMethodAuth(roleId, dataSourceId) {
|
|
408
|
+
return await this.auth(
|
|
409
|
+
'describeMethodAuth',
|
|
410
|
+
'v1',
|
|
411
|
+
'GET',
|
|
412
|
+
`roleId=${roleId}&dataSourceId=${dataSourceId}`,
|
|
413
|
+
undefined,
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* 查询角色绑定的数据模型列权限
|
|
419
|
+
* @param {String} roleId 角色 id
|
|
420
|
+
* @param {String} dataSourceId 数据源 id
|
|
421
|
+
* @param {Array} columnList 字段数组
|
|
422
|
+
* @returns {Object} {response: {data: {columnAuthList: [{column, auth: boolean}]}}}
|
|
423
|
+
*/
|
|
424
|
+
async describeColumnAuth(roleId, dataSourceId, columnList) {
|
|
425
|
+
return await this.auth(
|
|
426
|
+
'describeColumnAuth',
|
|
427
|
+
'v1',
|
|
428
|
+
'GET',
|
|
429
|
+
`roleId=${roleId}&dataSourceId=${dataSourceId}&columnList=${columnList.join(',')}`,
|
|
430
|
+
undefined,
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* 查询用户对资源的权限(资源鉴权)
|
|
436
|
+
* @param {String} userId 用户 id
|
|
437
|
+
* @param {String} resourceType 资源类型,自定义应用:app,模型应用:modelApp,数据源:dataSource,流程:flow
|
|
438
|
+
* @param {Array} resourceList 资源列表,[{ResourceId: appId|datasourceId|flowId, SubResourceId: [pageId...], MethodIdList: [methodId...], ColumnList: []}]
|
|
439
|
+
* @returns {Object} {Response: {Data: [{ResourceId, ResourceType, IsAccess}]}}
|
|
440
|
+
*/
|
|
441
|
+
async describeResourcesPermission(userId, resourceType, resourceList) {
|
|
442
|
+
const body = {
|
|
443
|
+
UserInfo: {
|
|
444
|
+
Uid: userId,
|
|
445
|
+
Source: 4,
|
|
446
|
+
},
|
|
447
|
+
ResourceList: resourceList,
|
|
448
|
+
ResourceType: resourceType,
|
|
449
|
+
};
|
|
450
|
+
return await this.auth(
|
|
451
|
+
'describeResourcesPermission',
|
|
452
|
+
'v1',
|
|
453
|
+
'POST',
|
|
454
|
+
undefined,
|
|
455
|
+
body,
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
//-------------------------------------------------------------------------------//
|
|
460
|
+
// 以下是数据源操作接口 //
|
|
461
|
+
//-------------------------------------------------------------------------------//
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* 查询数据模型信息
|
|
465
|
+
* @param {Object} params {PageNum = 1, PageSize = 10, IdList, NameList, QueryAll = boolean}
|
|
466
|
+
* @returns {Object} {response: {data: {DataSourceList, Total}}}
|
|
467
|
+
*/
|
|
468
|
+
async describeDataSourceList(params) {
|
|
469
|
+
let body = Object.assign(
|
|
470
|
+
{
|
|
471
|
+
PageNum: 1,
|
|
472
|
+
PageSize: 10,
|
|
473
|
+
},
|
|
474
|
+
params,
|
|
475
|
+
);
|
|
476
|
+
return await (
|
|
477
|
+
await this.wedaPath(
|
|
478
|
+
'/weda/model/v1/describeDataSourceList',
|
|
479
|
+
'POST',
|
|
480
|
+
undefined,
|
|
481
|
+
body,
|
|
482
|
+
)
|
|
483
|
+
).json();
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* 查询选项集信息
|
|
488
|
+
* @param {Array} optionSetNames 选项集标识列表
|
|
489
|
+
* @returns {Object} {response: {data: {total, items: [{name, title, config, data}]}}}
|
|
490
|
+
*/
|
|
491
|
+
async describeOptionSet(optionSetNames) {
|
|
492
|
+
return await (
|
|
493
|
+
await this.wedaPath(
|
|
494
|
+
'/weda/model/v1/describeOptionSet',
|
|
495
|
+
'POST',
|
|
496
|
+
undefined,
|
|
497
|
+
{ optionSetNames: optionSetNames },
|
|
498
|
+
)
|
|
499
|
+
).json();
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* 查询数据源 Schema
|
|
504
|
+
* @param {String} dataSourceName 数据源标识,不提供时查询环境下所有 Schema
|
|
505
|
+
* @returns {Response: {Data: {QueryDataSourceSchemaResultList}}}
|
|
506
|
+
*/
|
|
507
|
+
async getSchemaList(dataSourceName = '') {
|
|
508
|
+
console.log(dataSourceName);
|
|
509
|
+
return await (
|
|
510
|
+
await this.wedaPath(
|
|
511
|
+
`/weda/model/v1/getSchemaList/${dataSourceName}`,
|
|
512
|
+
'GET',
|
|
513
|
+
undefined,
|
|
514
|
+
undefined,
|
|
515
|
+
)
|
|
516
|
+
).json();
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* 新建一个数据
|
|
521
|
+
* @param {String} dataSourceName 数据模型标识
|
|
522
|
+
* @param {Object} data 数据对象
|
|
523
|
+
* @returns {Object} 成功返回数据对象json,失败返回{error: {code, message}}
|
|
524
|
+
*/
|
|
525
|
+
async odataCreate(dataSourceName, data) {
|
|
526
|
+
return await (
|
|
527
|
+
await this.wedaPath(
|
|
528
|
+
`/weda/odata/v1/${this.options.envType}/${dataSourceName}`,
|
|
529
|
+
'POST',
|
|
530
|
+
undefined,
|
|
531
|
+
data,
|
|
532
|
+
)
|
|
533
|
+
).json();
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* 更新一个数据
|
|
538
|
+
* @param {String} dataSourceName 数据模型标识
|
|
539
|
+
* @param {String} id 数据 id
|
|
540
|
+
* @param {Object} data 需要修改的数据属性及其取值
|
|
541
|
+
* @returns {Number} status
|
|
542
|
+
*/
|
|
543
|
+
async odataUpdate(dataSourceName, id, data) {
|
|
544
|
+
return (
|
|
545
|
+
await this.wedaPath(
|
|
546
|
+
`/weda/odata/v1/${this.options.envType}/${dataSourceName}('${id}')`,
|
|
547
|
+
'PATCH',
|
|
548
|
+
undefined,
|
|
549
|
+
data,
|
|
550
|
+
)
|
|
551
|
+
).ok;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* 删除一个数据
|
|
556
|
+
* @param {String} dataSourceName 数据模型标识
|
|
557
|
+
* @param {String} id 数据 id
|
|
558
|
+
* @returns {Number} response status
|
|
559
|
+
*/
|
|
560
|
+
async odataDelete(dataSourceName, id) {
|
|
561
|
+
return (
|
|
562
|
+
await this.wedaPath(
|
|
563
|
+
`/weda/odata/v1/${this.options.envType}/${dataSourceName}('${id}')`,
|
|
564
|
+
'DELETE',
|
|
565
|
+
undefined,
|
|
566
|
+
undefined,
|
|
567
|
+
)
|
|
568
|
+
).ok;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* 根据 id 获取一个数据
|
|
573
|
+
* @param {String} dataSourceName 数据模型标识
|
|
574
|
+
* @param {String} id 数据 id
|
|
575
|
+
* @returns {Object} 数据对象。如果没有对应数据,则对象里面所有属性为 null,可以检查 _id 是否为 null。
|
|
576
|
+
*/
|
|
577
|
+
async odataById(dataSourceName, id) {
|
|
578
|
+
if (id) {
|
|
579
|
+
return await (
|
|
580
|
+
await this.wedaPath(
|
|
581
|
+
`/weda/odata/v1/${this.options.envType}/${dataSourceName}('${id}')`,
|
|
582
|
+
'GET',
|
|
583
|
+
undefined,
|
|
584
|
+
undefined,
|
|
585
|
+
)
|
|
586
|
+
).json();
|
|
587
|
+
} else {
|
|
588
|
+
return await (
|
|
589
|
+
await this.wedaPath(
|
|
590
|
+
`/weda/odata/v1/${this.options.envType}/${dataSourceName}`,
|
|
591
|
+
'GET',
|
|
592
|
+
undefined,
|
|
593
|
+
undefined,
|
|
594
|
+
)
|
|
595
|
+
).json();
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* 查询数据
|
|
601
|
+
* @param {String} dataSourceName 数据模型标识
|
|
602
|
+
* @param {Object} params {$filter, $select, $orderby, $skip=0, $top=10, $count, NotQueryRelateDepartment=true, ResultWithRelation=false}
|
|
603
|
+
* @returns {Object} {"@odata.context", "@odata.count", value=[]}
|
|
604
|
+
* @param {String} version v1,v2
|
|
605
|
+
*/
|
|
606
|
+
async odataQuery(dataSourceName, params, version = 'v1') {
|
|
607
|
+
const query = Object.assign(
|
|
608
|
+
{
|
|
609
|
+
$skip: 0,
|
|
610
|
+
$top: 10,
|
|
611
|
+
NotQueryRelateDepartment: true,
|
|
612
|
+
ResultWithRelation: false,
|
|
613
|
+
},
|
|
614
|
+
params,
|
|
615
|
+
);
|
|
616
|
+
|
|
617
|
+
let queryArray = [];
|
|
618
|
+
for (let q in query) {
|
|
619
|
+
queryArray.push(`${q}=${query[q]}`);
|
|
620
|
+
}
|
|
621
|
+
const response = await this.wedaPath(
|
|
622
|
+
`/weda/odata/${version}/${this.options.envType}/${dataSourceName}`,
|
|
623
|
+
'GET',
|
|
624
|
+
queryArray.join('&'),
|
|
625
|
+
);
|
|
626
|
+
const json = await response.json();
|
|
627
|
+
|
|
628
|
+
if (!response.ok) {
|
|
629
|
+
console.error(json);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
return json;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* 批量创建数据
|
|
637
|
+
* 注意:混合云不支持此接口
|
|
638
|
+
* @param {String} dataSourceName 数据模型标识
|
|
639
|
+
* @param {Array} objects 需要创建的对象数组
|
|
640
|
+
* @returns {Object} {"@odata.context", value=[]}
|
|
641
|
+
*/
|
|
642
|
+
async odataBatchCreate(dataSourceName, objects) {
|
|
643
|
+
return await (
|
|
644
|
+
await this.wedaPath(
|
|
645
|
+
`/weda/odata/v1/batch/${this.options.envType}/${dataSourceName}`,
|
|
646
|
+
'POST',
|
|
647
|
+
undefined,
|
|
648
|
+
{ value: objects },
|
|
649
|
+
)
|
|
650
|
+
).json();
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/**
|
|
654
|
+
* 批量更新
|
|
655
|
+
* @param {String} dataSourceName 数据模型标识
|
|
656
|
+
* @param {Array} ids id 数组,注意数组长度,组装后 url 总长度不要超过长度限制(2048)
|
|
657
|
+
* @param {Object} obj 更新的属性和值
|
|
658
|
+
* @returns {Object} {updateCount}
|
|
659
|
+
*/
|
|
660
|
+
async odataBatchUpdate(dataSourceName, ids, obj) {
|
|
661
|
+
return await (
|
|
662
|
+
await this.wedaPath(
|
|
663
|
+
`/weda/odata/v1/batch/${this.options.envType}/${dataSourceName}('${ids.join(',')}')`,
|
|
664
|
+
'PATCH',
|
|
665
|
+
undefined,
|
|
666
|
+
obj,
|
|
667
|
+
)
|
|
668
|
+
).json();
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* 根据 id 批量获取数据
|
|
673
|
+
* @param {String} dataSourceName 数据模型标识
|
|
674
|
+
* @param {Array} ids 数据 id 数组,注意数组长度,组装后 url 总长度不要超过长度限制(2048)
|
|
675
|
+
* @returns {Object} {"odata.context", value=[]}
|
|
676
|
+
*/
|
|
677
|
+
async odataByIds(dataSourceName, ids) {
|
|
678
|
+
return await (
|
|
679
|
+
await this.wedaPath(
|
|
680
|
+
`/weda/odata/v1/batch/${this.options.envType}/${dataSourceName}('${ids.join(',')}')`,
|
|
681
|
+
'GET',
|
|
682
|
+
undefined,
|
|
683
|
+
undefined,
|
|
684
|
+
)
|
|
685
|
+
).json();
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* 根据 id 批量获取数据
|
|
690
|
+
* @param {String} dataSourceName 数据模型标识
|
|
691
|
+
* @param {Array} ids 数据 id 数组,注意数组长度,组装后 url 总长度不要超过长度限制(2048)
|
|
692
|
+
* @returns {Object} {deleteCount}
|
|
693
|
+
*/
|
|
694
|
+
async odataBatchDelete(dataSourceName, ids) {
|
|
695
|
+
return await (
|
|
696
|
+
await this.wedaPath(
|
|
697
|
+
`/weda/odata/v1/batch/${this.options.envType}/${dataSourceName}('${ids.join(',')}')`,
|
|
698
|
+
'DELETE',
|
|
699
|
+
undefined,
|
|
700
|
+
undefined,
|
|
701
|
+
)
|
|
702
|
+
).json();
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
//-------------------------------------------------------------------------------//
|
|
706
|
+
// 以下是自定义接口 //
|
|
707
|
+
//-------------------------------------------------------------------------------//
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* 对某个属性,提供多个值按批次循环进行相等查询,返回所有结果。
|
|
711
|
+
* 适合于对某个属性进行查询,但是值很多的情况,避免请求长度过长的问题。
|
|
712
|
+
* 2025-04-11: 服务器端目前限制查询参数 batch 不能超过10
|
|
713
|
+
* @param {Object} parameters {dataSourceName, prop, values, select, order, batch: 10, version: 'v1'|'v2'}
|
|
714
|
+
* 注意 v2 目前不支持 order
|
|
715
|
+
* @returns
|
|
716
|
+
*/
|
|
717
|
+
async odataQueryByPropEQValues(parameters) {
|
|
718
|
+
const params = Object.assign({ batch: 10, version: 'v1' }, parameters);
|
|
719
|
+
|
|
720
|
+
const query = {};
|
|
721
|
+
if (params.select) {
|
|
722
|
+
query.$select = params.select;
|
|
723
|
+
} else {
|
|
724
|
+
query.$select = '*';
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// 2025-04-11: 服务器端目前限制查询参数 batch 不能超过10
|
|
728
|
+
if (params.batch > 10) {
|
|
729
|
+
params.batch = 10;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
if (params.order) {
|
|
733
|
+
query.$orderby = params.order;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
const items = [];
|
|
737
|
+
|
|
738
|
+
for (let i = 0; i < params.values.length; i += params.batch) {
|
|
739
|
+
query.$filter = params.values
|
|
740
|
+
.slice(i, i + params.batch)
|
|
741
|
+
.map((v) => `${params.prop} eq '${v}'`)
|
|
742
|
+
.join(' or ');
|
|
743
|
+
const response = await this.odataQueryCollectAll(
|
|
744
|
+
params.dataSourceName,
|
|
745
|
+
query,
|
|
746
|
+
params.version,
|
|
747
|
+
);
|
|
748
|
+
|
|
749
|
+
for (const item of response) {
|
|
750
|
+
items.push(item);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
return items;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* 收集所有结果,受限于 api 每次最多1000个记录的限制,需要多次查询。注意结果集对内存的需求。
|
|
759
|
+
* @param {String} dataSourceName
|
|
760
|
+
* @param {Object} params {$filter, $select, $orderby, $skip=0, $top=10, $count, NotQueryRelateDepartment=true, ResultWithRelation=false}
|
|
761
|
+
* $orderby 应该提供,避免排序不稳定导致数据重复或遗漏
|
|
762
|
+
* @param {String} version v1,v2
|
|
763
|
+
* @returns
|
|
764
|
+
*/
|
|
765
|
+
async odataQueryCollectAll(dataSourceName, params, version = 'v1') {
|
|
766
|
+
const items = [];
|
|
767
|
+
const batch = version === 'v1' ? 1000 : 200;
|
|
768
|
+
const _params = Object.assign({}, params);
|
|
769
|
+
_params.$top = batch;
|
|
770
|
+
_params.$count = true;
|
|
771
|
+
|
|
772
|
+
for (let i = 0, count = -1; i < count || count == -1; i += batch) {
|
|
773
|
+
_params.$skip = i;
|
|
774
|
+
const response = await this.odataQuery(dataSourceName, _params, version);
|
|
775
|
+
|
|
776
|
+
if (count === -1) {
|
|
777
|
+
count = response['@odata.count'] ? response['@odata.count'] : 0;
|
|
778
|
+
_params.$count = false;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
if (response.value) {
|
|
782
|
+
for (const item of response.value) {
|
|
783
|
+
items.push(item);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
return items;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* 为指定用户分配角色(增加)
|
|
792
|
+
* @param {String} userId 用户id
|
|
793
|
+
* @param {Array} roleIds 角色id数组
|
|
794
|
+
* @returns {Boolean}
|
|
795
|
+
* @throws
|
|
796
|
+
*/
|
|
797
|
+
async addAuthorizes(userId, roleIds) {
|
|
798
|
+
const _roleIds = roleIds.slice();
|
|
799
|
+
|
|
800
|
+
// 合并已有角色授权
|
|
801
|
+
const describeResponse = await this.describeWedaUser(userId, true, false);
|
|
802
|
+
if (describeResponse.Response.Error) {
|
|
803
|
+
throw new Error(
|
|
804
|
+
`describeWedaUser('${userId}', true, false): ${JSON.stringify(describeResponse.Response.Error)}`,
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
const wedaUser = describeResponse.Response.Data;
|
|
808
|
+
if (wedaUser && wedaUser.RelatedRoles) {
|
|
809
|
+
const existsRoleIds = wedaUser.RelatedRoles.map((r) => r.Id);
|
|
810
|
+
|
|
811
|
+
// 如果没有新的角色需要授权,直接返回
|
|
812
|
+
if (roleIds.every((id) => existsRoleIds.includes(id))) {
|
|
813
|
+
return false;
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
existsRoleIds.forEach((id) => {
|
|
817
|
+
if (!_roleIds.includes(id)) {
|
|
818
|
+
_roleIds.push(id);
|
|
819
|
+
}
|
|
820
|
+
});
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const response = await this.batchAuthorize([
|
|
824
|
+
{ UserId: userId, RoleIds: _roleIds },
|
|
825
|
+
]);
|
|
826
|
+
if (response.Response.Error) {
|
|
827
|
+
throw new Error(
|
|
828
|
+
`batchAuthorize('${userId}', ${JSON.stringify(_roleIds)}): ${JSON.stringify(response.Response.Error)}`,
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
return true;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
module.exports = WedaOpenApi;
|
package/workflow.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const fetch = require('node-fetch');
|
|
2
|
+
const Auth = require('./auth');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 审批流接口
|
|
6
|
+
* 详细文档:https://cloud.tencent.com/document/product/1301/94470
|
|
7
|
+
*
|
|
8
|
+
* 流程:ProcessKey 为流程的唯一标识。流程可以有多个版本。
|
|
9
|
+
* 流程具体版本:FlowCode 为流程具体版本的唯一标识,在流程每次保存、发布后,会生成新的 FlowCode(ProcessKey 不变)
|
|
10
|
+
*
|
|
11
|
+
* 流程实例:触发流程后产生的运行态实例;InstanceId 为流程实例的唯一标识;一个流程可以被触发多次,即一个流程在运行态包含多个流程实例。
|
|
12
|
+
* 审批任务:每个审批节点下每个审批人被分配的任务;FlowTaskId(TaskId)为审批任务的唯一标识;在一个流程实例中,流转到某一个审批节点时,会为该审批节点下每个审批人分配审批任务,即一个流程实例包含多个审批任务。
|
|
13
|
+
*/
|
|
14
|
+
class Workflow {
|
|
15
|
+
constructor(options) {
|
|
16
|
+
|
|
17
|
+
this.options = Object.assign(
|
|
18
|
+
{
|
|
19
|
+
// 主机地址
|
|
20
|
+
host: 'https://weda.web.scut.edu.cn',
|
|
21
|
+
|
|
22
|
+
// 环境信息
|
|
23
|
+
envId: 'lowcode-7gwjk8v14d46dda1',
|
|
24
|
+
envType: 'prod',
|
|
25
|
+
|
|
26
|
+
debug: false,
|
|
27
|
+
},
|
|
28
|
+
options
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
console.log(this.options);
|
|
32
|
+
|
|
33
|
+
this.auth = new Auth(this.options);
|
|
34
|
+
this.baseUrl = `${this.options.host}/weda/workflow/v1/${this.options.envType}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async post(path, body) {
|
|
38
|
+
const token = await this.auth.getAccessToken();
|
|
39
|
+
|
|
40
|
+
if (this.options.debug) {
|
|
41
|
+
console.log(`Request URL: ${this.baseUrl}/${path}`);
|
|
42
|
+
console.log("Request Body:", body);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const response = await fetch(`${this.baseUrl}/${path}`, {
|
|
46
|
+
method: 'POST',
|
|
47
|
+
headers: {
|
|
48
|
+
"Content-Type": "application/json",
|
|
49
|
+
"Authorization": `Bearer ${token}`,
|
|
50
|
+
},
|
|
51
|
+
body: JSON.stringify(body)
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
if (this.options.debug) {
|
|
55
|
+
console.log(response);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const data = await response.json();
|
|
59
|
+
return data;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 查询已部署的流程列表
|
|
64
|
+
* @param {Object} body {Type: integer}
|
|
65
|
+
* Type: 1 逻辑流,2 审批流
|
|
66
|
+
* @returns
|
|
67
|
+
*/
|
|
68
|
+
async listDeployedFlows(body) {
|
|
69
|
+
return this.post('ListDeployedFlows', body);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 根据类型查询流程实例列表
|
|
74
|
+
* @param {Object} body
|
|
75
|
+
* @returns
|
|
76
|
+
*/
|
|
77
|
+
async ListProcessInstances(body) {
|
|
78
|
+
return this.post('ListProcessInstances', body);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* 查询流程任务相关信息
|
|
83
|
+
* @param {Object} body
|
|
84
|
+
* @returns
|
|
85
|
+
*/
|
|
86
|
+
async getFlowInstanceTasks(body) {
|
|
87
|
+
return this.post('GetFlowInstanceTasks', body);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* 查询流程实例详情
|
|
92
|
+
* @param {Object} body { FlowTaskId: string, PageType: string, UserInfo, NeedUserExtraInfo: boolean }
|
|
93
|
+
* PageType: 'TODO' | 'DONE' | 'CREATE' | 'CC'
|
|
94
|
+
* UserInfo: { UserId: string, Type: integer }
|
|
95
|
+
* @returns
|
|
96
|
+
*/
|
|
97
|
+
async describeProcessInstance(body) {
|
|
98
|
+
return this.post('DescribeProcessInstance', body);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* 终止单个流程实例
|
|
103
|
+
* @param {Object} body { InstanceId: string, Operator: UserInfo, DeleteReason: string }
|
|
104
|
+
* UserInfo: { UserId: string, Type: integer }
|
|
105
|
+
* @returns { Response: { RequestId: string, Data: { Result: boolean } } }
|
|
106
|
+
*/
|
|
107
|
+
async stopFlow(body) {
|
|
108
|
+
return this.post('StopFlow', body);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 管理后台终止操作
|
|
113
|
+
* @param {Object} body { InstanceIdList: [string], UserInfo: UserInfo }
|
|
114
|
+
* @returns { Response: { RequestId: string, Data: { Result: boolean } } }
|
|
115
|
+
*/
|
|
116
|
+
async manageStopProcessList(body) {
|
|
117
|
+
return this.post('ManageStopProcessList', body);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 查询流程操作相关信息
|
|
122
|
+
* @param {Object} body { InstanceId: string, ElementIds: [string], OperatorUser: UserInfo, PageNumber: integer, PageSize: integer, NeedUserExtraInfo: boolean }
|
|
123
|
+
* @returns { Response: { RequestId: string, Data: { Result: [] }, TotalCount: integer } }
|
|
124
|
+
*/
|
|
125
|
+
async getFlowInstanceOperations(body) {
|
|
126
|
+
return this.post('GetFlowInstanceOperations', body);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
module.exports = Workflow;
|