@gingkoo/base-server 0.0.1-alpha.0 → 0.0.1-alpha.10
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 +4 -0
- package/app.js +41 -40
- package/backend/common/entity.js +55 -0
- package/backend/common/enum.js +247 -0
- package/backend/common/fss/index.js +18 -0
- package/backend/common/fss/routers/attachment.js +45 -0
- package/backend/common/fss/routers/download.js +43 -0
- package/backend/common/fss/routers/import_export.js +113 -0
- package/backend/common/fss/routers/resources.js +149 -0
- package/backend/common/fss/routers/upload.js +81 -0
- package/backend/common/fss/services/import_export.js +159 -0
- package/backend/common/fss/services/index.js +92 -0
- package/backend/common/fss/utils.js +39 -0
- package/backend/common/ginfo/config.js +5 -0
- package/backend/common/ginfo/index.js +62 -0
- package/backend/common/index_template.html +28 -0
- package/backend/common/logger/index.js +96 -0
- package/backend/common/mapping.js +128 -0
- package/backend/common/middleware/auth.js +109 -0
- package/backend/common/middleware/cors.js +13 -0
- package/backend/common/middleware/response.js +25 -0
- package/backend/common/page_engine.js +487 -0
- package/backend/common/schedule.js +45 -0
- package/backend/common/services/dataCombine.js +67 -0
- package/backend/common/services/dept.js +37 -0
- package/backend/common/services/dict.js +488 -0
- package/backend/common/services/email.js +49 -0
- package/backend/common/services/generalConfig.js +137 -0
- package/backend/common/services/login.js +18 -0
- package/backend/common/services/notice.js +260 -0
- package/backend/common/services/permission.js +500 -0
- package/backend/common/services/roles.js +57 -0
- package/backend/common/services/send-notice.js +86 -0
- package/backend/common/services/task.js +259 -0
- package/backend/common/services/user.js +673 -0
- package/backend/common/socket.js +18 -0
- package/backend/common/sse/index.js +81 -0
- package/backend/common/sse/router.js +30 -0
- package/backend/common/task.js +75 -0
- package/backend/common/wechat/index.js +9 -0
- package/backend/common/wechat/routers/auth.js +238 -0
- package/{modules/user/frontend → backend/common/wechat/routers}/index.html +14 -7
- package/backend/common/wechat/services/auth.js +209 -0
- package/backend/common/wechat/services/notice.js +171 -0
- package/backend/config/index.js +61 -0
- package/backend/config/path.js +3 -0
- package/backend/router.js +100 -0
- package/backend/routers/app.js +222 -0
- package/backend/routers/automate.js +276 -0
- package/backend/routers/dict.js +370 -0
- package/backend/routers/email.js +85 -0
- package/backend/routers/generalConfig.js +276 -0
- package/backend/routers/idm.js +245 -0
- package/backend/routers/module.js +357 -0
- package/backend/routers/notice.js +138 -0
- package/backend/routers/pages.js +46 -0
- package/backend/routers/permission.js +985 -0
- package/backend/routers/setting.js +184 -0
- package/backend/routers/team/index.js +22 -0
- package/backend/routers/team/routers/mapping.js +29 -0
- package/backend/routers/team/routers/member.js +72 -0
- package/backend/routers/team/routers/membermanage.js +289 -0
- package/backend/routers/team/routers/pages.js +47 -0
- package/backend/routers/team/routers/roles.js +92 -0
- package/backend/routers/team/routers/teaminfo.js +27 -0
- package/backend/routers/team/routers/usergroup.js +213 -0
- package/backend/routers/team/services/mapping.js +101 -0
- package/backend/routers/team/services/member.js +206 -0
- package/backend/routers/team/services/roles.js +71 -0
- package/backend/routers/team/services/teaminfo.js +20 -0
- package/backend/routers/team/services/usergroup.js +128 -0
- package/backend/routers/user.js +436 -0
- package/backend/services/automate.js +60 -0
- package/backend/services/config.js +14 -0
- package/backend/services/module.js +298 -0
- package/backend/services/permission.js +192 -0
- package/backend/services/services.js +115 -0
- package/backend/services/setting.js +190 -0
- package/backend/services/token.js +42 -0
- package/backend/space.js +52 -0
- package/backend/space_mapping.js +22 -0
- package/backend/utils/avatar.js +48 -0
- package/backend/utils/color_gen_helper.js +20 -0
- package/backend/utils/date.js +66 -0
- package/backend/utils/excel.js +446 -0
- package/backend/utils/fs/doc.md +64 -0
- package/backend/utils/fs/index.js +127 -0
- package/backend/utils/jwt.js +54 -0
- package/backend/utils/modules/sequence.js +93 -0
- package/backend/utils/object.js +31 -0
- package/backend/utils/page-query-helper/index.js +61 -0
- package/backend/utils/path.js +123 -0
- package/backend/utils/run.js +25 -0
- package/backend/utils/tokenize.js +82 -0
- package/backend/utils/typeof.js +5 -0
- package/backend/utils/util.js +153 -0
- package/backend/views/api/index.js +32 -0
- package/backend/views/api/index.xml +49 -0
- package/backend/views/dict/index.js +80 -0
- package/backend/views/dict/index.xml +52 -0
- package/backend/views/index.js +32 -0
- package/backend/views/members_manage/index.js +68 -0
- package/backend/views/members_manage/index.xml +68 -0
- package/backend/views/roles/index.js +17 -0
- package/backend/views/roles/index.xml +47 -0
- package/backend/views/usergroup/index.js +68 -0
- package/backend/views/usergroup/index.xml +65 -0
- package/dist/base-assets/css/index-ffdb55a5.css +3 -0
- package/dist/base-assets/css/index-ffdb55a5.css.gz +0 -0
- package/dist/base-assets/js/index-b3998a47.js +762 -0
- package/dist/base-assets/js/index-b3998a47.js.gz +0 -0
- package/dist/base-assets/js/react-cropper.es-d5f06996.js +10 -0
- package/dist/base-assets/js/react-cropper.es-d5f06996.js.gz +0 -0
- package/dist/base-assets/png/u9-2348c304.png +0 -0
- package/dist/base-assets/woff2/materialicons-83be7b2f.woff2 +0 -0
- package/dist/index.html +162 -0
- package/package.json +62 -5
- package/common/router.js +0 -42
- package/modules/user/backend/index.js +0 -19
- package/modules/user/backend/routers/user.js +0 -11
- package/modules/user/frontend/index.js +0 -1
- package/serve.js +0 -9
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { v4: uuidv4 } = require('uuid');
|
|
3
|
+
const { sqlExecutor, insertSqlBuilder } = require('@gingkoo/node-tools');
|
|
4
|
+
|
|
5
|
+
async function gen(orgId, moduleId, seqId, count, { minValue, maxValue }) {
|
|
6
|
+
let strUUID = uuidv4();
|
|
7
|
+
//锁定记录
|
|
8
|
+
let curValue = null;
|
|
9
|
+
let newValue = null;
|
|
10
|
+
|
|
11
|
+
//获取序号
|
|
12
|
+
let dbResult = await sqlExecutor(
|
|
13
|
+
'select CUR_VALUE,MIN_VALUE,MAX_VALUE from BASE_SEQ_CTL where ORG_ID=? and MODULE_ID=? and SEQ_ID=? ',
|
|
14
|
+
[orgId, moduleId, seqId],
|
|
15
|
+
);
|
|
16
|
+
if (dbResult.error) {
|
|
17
|
+
console.log(dbResult.error);
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
//没有创建seq
|
|
22
|
+
if (dbResult.results.length == 0) {
|
|
23
|
+
let params = {
|
|
24
|
+
ORG_ID: orgId,
|
|
25
|
+
MODULE_ID: moduleId,
|
|
26
|
+
SEQ_ID: seqId,
|
|
27
|
+
CUR_VALUE: minValue + count,
|
|
28
|
+
MIN_VALUE: minValue,
|
|
29
|
+
MAX_VALUE: maxValue,
|
|
30
|
+
DATA_LOCK_ID: strUUID,
|
|
31
|
+
DATA_LOCK_EXPIRE: 'current_timestamp()+2',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
let sqlResult = insertSqlBuilder('BASE_SEQ_CTL', params, ['DATA_LOCK_EXPIRE']);
|
|
35
|
+
console.log(sqlResult);
|
|
36
|
+
dbResult = await sqlExecutor(sqlResult.sql, sqlResult.params);
|
|
37
|
+
if (dbResult.error) {
|
|
38
|
+
console.log(dbResult.error);
|
|
39
|
+
} else {
|
|
40
|
+
curValue = minValue;
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
let dataRow = dbResult.results[0];
|
|
44
|
+
curValue = dataRow['CUR_VALUE'];
|
|
45
|
+
newValue = curValue + count;
|
|
46
|
+
if (newValue >= dataRow['MAX_VALUE']) {
|
|
47
|
+
newValue = dataRow['MIN_VALUE'];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//更新值
|
|
51
|
+
dbResult = await sqlExecutor(
|
|
52
|
+
'update BASE_SEQ_CTL set CUR_VALUE=?, DATA_LOCK_ID=? , DATA_LOCK_EXPIRE=current_timestamp()+2 where ORG_ID=? and MODULE_ID=? and SEQ_ID=? and (DATA_LOCK_ID is null or DATA_LOCK_EXPIRE<current_timestamp())',
|
|
53
|
+
[newValue, strUUID, orgId, moduleId, seqId],
|
|
54
|
+
);
|
|
55
|
+
if (dbResult.error) {
|
|
56
|
+
console.log(dbResult.error);
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//记录更新0条,被其他进程获取,需要重新获取锁。
|
|
61
|
+
if (dbResult.affectedRows == 0) {
|
|
62
|
+
curValue = null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (curValue) {
|
|
67
|
+
//清除锁
|
|
68
|
+
dbResult = await sqlExecutor(
|
|
69
|
+
'update BASE_SEQ_CTL set DATA_LOCK_ID=null , DATA_LOCK_EXPIRE=0 where ORG_ID=? and MODULE_ID=? and SEQ_ID=? and DATA_LOCK_ID=?',
|
|
70
|
+
[orgId, moduleId, seqId, strUUID],
|
|
71
|
+
);
|
|
72
|
+
if (dbResult.error) {
|
|
73
|
+
console.log(dbResult.error);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
//被其他应用获取了值,延迟重新获取
|
|
78
|
+
var delay = new Promise(function (resolve, reject) {
|
|
79
|
+
setTimeout(() => {
|
|
80
|
+
resolve();
|
|
81
|
+
}, 10);
|
|
82
|
+
});
|
|
83
|
+
await delay;
|
|
84
|
+
|
|
85
|
+
curValue = await gen(orgId, moduleId, seqId, count, { minValue, maxValue });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return curValue;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
gen,
|
|
93
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 对象深度合并
|
|
3
|
+
* @param {object | array} obj1
|
|
4
|
+
* @param {object | array} obj2
|
|
5
|
+
*/
|
|
6
|
+
const deepMerge = (obj1 = {}, obj2) => {
|
|
7
|
+
if (Array.isArray(obj2)) {
|
|
8
|
+
if (Array.isArray(obj1)) {
|
|
9
|
+
obj2.forEach((item, index) => {
|
|
10
|
+
obj1[index] = deepMerge(obj1[index], item);
|
|
11
|
+
});
|
|
12
|
+
} else {
|
|
13
|
+
obj1 = obj2;
|
|
14
|
+
}
|
|
15
|
+
} else {
|
|
16
|
+
for (let key in obj2) {
|
|
17
|
+
let val = obj2[key];
|
|
18
|
+
if (val.toString() === '[object Object]') {
|
|
19
|
+
obj1[key] = deepMerge(obj1[key], val);
|
|
20
|
+
} else {
|
|
21
|
+
obj1[key] = val;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return obj1;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
module.exports = {
|
|
30
|
+
deepMerge,
|
|
31
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 处理query 参数
|
|
5
|
+
* @param {object} params 参数集合
|
|
6
|
+
* @param {array} filterKeys 从参数集合里面剔除的参数key
|
|
7
|
+
* @param {boolean} page 是否有分页
|
|
8
|
+
* @param {number} defaultPageSize 默认一页条数
|
|
9
|
+
*/
|
|
10
|
+
function parseQueryParams(params, filterKeys, page, defaultPageSize) {
|
|
11
|
+
let result = {
|
|
12
|
+
params: {},
|
|
13
|
+
pageInfo: {},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
let pageIndex = 0;
|
|
17
|
+
let pageSize = defaultPageSize;
|
|
18
|
+
let orderBy = '';
|
|
19
|
+
let orderDir = 'DESC';
|
|
20
|
+
let sort = null;
|
|
21
|
+
|
|
22
|
+
for (let k in params) {
|
|
23
|
+
if (filterKeys.indexOf(k.toUpperCase()) != -1) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
if (!params[k]) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (k == 'page') {
|
|
31
|
+
page = true;
|
|
32
|
+
pageIndex = parseInt(params[k]) - 1;
|
|
33
|
+
} else if (k == 'size') {
|
|
34
|
+
pageSize = parseInt(params[k]);
|
|
35
|
+
} else if (k == 'orderBy') {
|
|
36
|
+
orderBy = params[k];
|
|
37
|
+
} else if (k == 'orderDir' && params[k]) {
|
|
38
|
+
orderDir = params[k];
|
|
39
|
+
} else {
|
|
40
|
+
if (params[k].indexOf(',') > 0) {
|
|
41
|
+
result.params[k] = params[k].split(',');
|
|
42
|
+
} else {
|
|
43
|
+
result.params[k] = params[k];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
result.pageInfo = {
|
|
48
|
+
page: page,
|
|
49
|
+
pageIndex: pageIndex,
|
|
50
|
+
pageSize: pageSize,
|
|
51
|
+
orderBy,
|
|
52
|
+
orderDir,
|
|
53
|
+
sort: sort,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
parseQueryParams,
|
|
61
|
+
};
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
var path = require('path');
|
|
2
|
+
var fs = require('fs');
|
|
3
|
+
const config = require('../config/index');
|
|
4
|
+
|
|
5
|
+
const { access, constants, readFileSync, writeFile, unlink } = fs;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 判读路径是否存在,如不存在创建文件夹
|
|
9
|
+
* 为了安全,限制在 app_home 文件夹内创建
|
|
10
|
+
*/
|
|
11
|
+
function mkdirPath(pathStr) {
|
|
12
|
+
var uploadRootPath = config.app.home;
|
|
13
|
+
|
|
14
|
+
const relative = path.relative(uploadRootPath, pathStr);
|
|
15
|
+
if (relative.startsWith('..')) {
|
|
16
|
+
console.log('请注意,路径不在app_home下面');
|
|
17
|
+
return pathStr;
|
|
18
|
+
}
|
|
19
|
+
var tempDirArray;
|
|
20
|
+
if (relative.indexOf('\\') !== -1) {
|
|
21
|
+
tempDirArray = relative.split('\\');
|
|
22
|
+
}
|
|
23
|
+
if (relative.indexOf('/') !== -1) {
|
|
24
|
+
tempDirArray = relative.split('/');
|
|
25
|
+
}
|
|
26
|
+
if (relative.indexOf('/') == -1 && relative.indexOf('\\') == -1) {
|
|
27
|
+
tempDirArray = [relative];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
var projectPath = uploadRootPath;
|
|
31
|
+
for (var i = 0; i < tempDirArray.length; i++) {
|
|
32
|
+
projectPath += '/' + tempDirArray[i];
|
|
33
|
+
|
|
34
|
+
if (fs.existsSync(projectPath)) {
|
|
35
|
+
var tempstats = fs.statSync(projectPath);
|
|
36
|
+
if (!tempstats.isDirectory()) {
|
|
37
|
+
fs.unlinkSync(projectPath); // 如果存在同名文件 要不要删除?
|
|
38
|
+
fs.mkdirSync(projectPath);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
fs.mkdirSync(projectPath);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return projectPath;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 判断文件是否存在
|
|
50
|
+
* @param {string} path 文件路径
|
|
51
|
+
* @returns boolean
|
|
52
|
+
*/
|
|
53
|
+
function fileExist(path) {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
access(path, constants.F_OK, (err) => {
|
|
56
|
+
if (err) {
|
|
57
|
+
resolve(false);
|
|
58
|
+
} else {
|
|
59
|
+
resolve(true);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* 查询文件内容
|
|
67
|
+
* @param {string} path
|
|
68
|
+
*/
|
|
69
|
+
function readFileContent(path) {
|
|
70
|
+
let content = readFileSync(path, {
|
|
71
|
+
encoding: 'utf-8',
|
|
72
|
+
});
|
|
73
|
+
return content;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* 保存文件
|
|
78
|
+
* @param {string} path
|
|
79
|
+
* @param {string} content
|
|
80
|
+
* @returns
|
|
81
|
+
*/
|
|
82
|
+
function saveFile(path, content) {
|
|
83
|
+
return new Promise((resolve) => {
|
|
84
|
+
writeFile(path, content, (err) => {
|
|
85
|
+
if (err) {
|
|
86
|
+
console.error(err);
|
|
87
|
+
return resolve(false);
|
|
88
|
+
}
|
|
89
|
+
resolve(true);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 删除文件
|
|
96
|
+
* @param {string} path
|
|
97
|
+
* @returns
|
|
98
|
+
*/
|
|
99
|
+
function delFile(path) {
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
unlink(path, (err) => {
|
|
102
|
+
if (err) {
|
|
103
|
+
console.error(err);
|
|
104
|
+
return resolve(false);
|
|
105
|
+
}
|
|
106
|
+
resolve(true);
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function getResolvePath(pathname) {
|
|
112
|
+
return path.resolve(pathname);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
module.exports = {
|
|
116
|
+
mkdirPath,
|
|
117
|
+
delFile,
|
|
118
|
+
saveFile,
|
|
119
|
+
fileExist,
|
|
120
|
+
readFileContent,
|
|
121
|
+
getResolvePath,
|
|
122
|
+
join: path.join,
|
|
123
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const execa = require('execa');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 执行命令
|
|
5
|
+
* @param {string} bin
|
|
6
|
+
* @param {array} args
|
|
7
|
+
* @param {object} opts
|
|
8
|
+
*/
|
|
9
|
+
const run = async (bin, args, opts = {}, cb) => {
|
|
10
|
+
let result;
|
|
11
|
+
try {
|
|
12
|
+
console.info(`开始执行:${bin} ${args.join(' ')}`);
|
|
13
|
+
result = await execa(bin, args, { stdio: 'pipe', ...opts });
|
|
14
|
+
console.info(result.stdout);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
result = error;
|
|
17
|
+
console.error(error);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
typeof cb === 'function' && cb(result);
|
|
21
|
+
|
|
22
|
+
return result;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
module.exports = run;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const resolveVariableAndFilter = (path, data = {}) => {
|
|
2
|
+
if (!path) {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
const m = /^(\\)?\$(?:((?:\w+\:)?[a-z0-9_.][a-z0-9_.\[\]]*)|{([\s\S]+)})$/i.exec(path);
|
|
7
|
+
|
|
8
|
+
if (!m) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const [_, escape, key, key2] = m;
|
|
13
|
+
|
|
14
|
+
// 如果是转义如: `\$abc` => `$abc`
|
|
15
|
+
if (escape) {
|
|
16
|
+
return _.substring(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let finalKey = key || key2;
|
|
20
|
+
|
|
21
|
+
// 先只支持一层吧
|
|
22
|
+
finalKey = finalKey.replace(
|
|
23
|
+
/(\\|\\\$)?\$(?:([a-zA-Z0-9_.][a-zA-Z0-9_.\[\]]*)|{([^}{]+)})/g,
|
|
24
|
+
(_, escape) => {
|
|
25
|
+
return escape ? _.substring(1) : resolveVariableAndFilter(_, data);
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
let paths = finalKey.split(/\s*\|\s*/g);
|
|
30
|
+
finalKey = paths.shift();
|
|
31
|
+
|
|
32
|
+
let ret = data[finalKey];
|
|
33
|
+
|
|
34
|
+
let prevConInputChanged = false; // 前一个类三元过滤器生效,则跳过后续类三元过滤器
|
|
35
|
+
|
|
36
|
+
return paths.reduce((input, filter) => {
|
|
37
|
+
let params = filter
|
|
38
|
+
.replace(
|
|
39
|
+
/([^\\])\\([\:\\])/g,
|
|
40
|
+
(_, affix, content) => `${affix}__${content === ':' ? 'colon' : 'slash'}__`,
|
|
41
|
+
)
|
|
42
|
+
.split(':')
|
|
43
|
+
.map((item) =>
|
|
44
|
+
item.replace(/__(slash|colon)__/g, (_, type) => (type === 'colon' ? ':' : '\\')),
|
|
45
|
+
);
|
|
46
|
+
let key = params.shift();
|
|
47
|
+
|
|
48
|
+
if (~['isTrue', 'isFalse', 'isMatch', 'isEquals', 'notMatch', 'notEquals'].indexOf(key)) {
|
|
49
|
+
if (prevConInputChanged) {
|
|
50
|
+
return input;
|
|
51
|
+
} else {
|
|
52
|
+
const result = input;
|
|
53
|
+
prevConInputChanged = result !== input;
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
// 后面再遇到非类三元filter就重置了吧,不影响再后面的其他三元filter
|
|
58
|
+
prevConInputChanged = false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return input;
|
|
62
|
+
}, ret);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const tokenize = (str, data) => {
|
|
66
|
+
if (!str || typeof str !== 'string') {
|
|
67
|
+
return str;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return str.replace(
|
|
71
|
+
/(\\)?\$(?:((?:\w+\:)?[a-z0-9_\.][a-z0-9_\.\[\]]*|&|\$)|{([^}{]+?)})/gi,
|
|
72
|
+
(_, escape, key1, key2, index, source) => {
|
|
73
|
+
let val = escape ? _.substring(1) : resolveVariableAndFilter(_, data) ?? '';
|
|
74
|
+
if (!val) {
|
|
75
|
+
val = '${' + key2 + '}';
|
|
76
|
+
}
|
|
77
|
+
return val;
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
module.exports = tokenize;
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
var urlencode = require('urlencode');
|
|
2
|
+
var { readFileSync } = require('fs');
|
|
3
|
+
const { isObject } = require('./typeof');
|
|
4
|
+
const pako = require('pako');
|
|
5
|
+
|
|
6
|
+
String.prototype.format = function (args) {
|
|
7
|
+
var result = this;
|
|
8
|
+
if (arguments.length > 0) {
|
|
9
|
+
if (arguments.length == 1 && typeof args == 'object') {
|
|
10
|
+
for (var key in args) {
|
|
11
|
+
if (args[key] != undefined) {
|
|
12
|
+
var reg = new RegExp('({' + key + '})', 'g');
|
|
13
|
+
result = result.replace(reg, args[key]);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
} else {
|
|
17
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
18
|
+
if (arguments[i] != undefined) {
|
|
19
|
+
var reg = new RegExp('({)' + i + '(})', 'g');
|
|
20
|
+
result = result.replace(reg, arguments[i]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
String.prototype.replaceAll = function (FindText, RepText) {
|
|
29
|
+
let regExp = new RegExp(FindText, 'g');
|
|
30
|
+
return this.replace(regExp, RepText);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
function urlencodeObject(params) {
|
|
34
|
+
let result = '';
|
|
35
|
+
Object.keys(params).forEach(function (item) {
|
|
36
|
+
if (result.length > 0) {
|
|
37
|
+
result = result + '&';
|
|
38
|
+
}
|
|
39
|
+
result = result + item + '=' + urlencode(params[item]);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* 剔除对象上无用的key
|
|
47
|
+
* eg. cleanUselessKey({a:1, b: undefined, c: null})
|
|
48
|
+
* return. {a:1}
|
|
49
|
+
*/
|
|
50
|
+
const cleanUselessKey = (obj) => {
|
|
51
|
+
if (!isObject(obj)) return obj;
|
|
52
|
+
|
|
53
|
+
let newObj = { ...obj };
|
|
54
|
+
Reflect.ownKeys(newObj).forEach((v) => {
|
|
55
|
+
newObj[v] ?? Reflect.deleteProperty(newObj, v);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return newObj;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 根据文件路径获取文件内容
|
|
63
|
+
* @param {string} filePath 文件路径
|
|
64
|
+
* @param {string} charset? 字符集
|
|
65
|
+
* @returns
|
|
66
|
+
*/
|
|
67
|
+
const getFileContent = (filePath, charset = 'utf8') => {
|
|
68
|
+
let htmlContent = readFileSync(filePath, charset);
|
|
69
|
+
return htmlContent || '';
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const unzip = function (key) {
|
|
73
|
+
// 解压
|
|
74
|
+
// 将二进制字符串转换为字符数组
|
|
75
|
+
var charData = key.split('').map(function (x) {
|
|
76
|
+
return x.charCodeAt(0);
|
|
77
|
+
});
|
|
78
|
+
// 将数字数组转换成字节数组
|
|
79
|
+
var binData = new Uint8Array(charData);
|
|
80
|
+
// 解压
|
|
81
|
+
var data = pako.inflate(binData);
|
|
82
|
+
// var data = poko.unzip(binData)
|
|
83
|
+
var res = '';
|
|
84
|
+
// var chunk = 16 * 1024;
|
|
85
|
+
var i;
|
|
86
|
+
// for (i = 0; i < data.length / chunk; i++) {
|
|
87
|
+
// res += String.fromCharCode.apply(null, data.slice(i * chunk, (i + 1) * chunk));
|
|
88
|
+
// }
|
|
89
|
+
// res += String.fromCharCode.apply(null, data.slice(i * chunk));
|
|
90
|
+
for (i = 0; i < data.length; i++) {
|
|
91
|
+
res += String.fromCharCode(data[i]);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return decodeURIComponent(res);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const getParam = function (str) {
|
|
98
|
+
let params = {};
|
|
99
|
+
let index = str.lastIndexOf('?');
|
|
100
|
+
if (~index) {
|
|
101
|
+
str
|
|
102
|
+
.slice(index + 1)
|
|
103
|
+
.split('&')
|
|
104
|
+
.forEach((v) => {
|
|
105
|
+
let item = v.split('=');
|
|
106
|
+
params[item[0]] = item[1];
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return params;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
function getCurrentDate() {
|
|
113
|
+
const date = new Date();
|
|
114
|
+
const year = date.getFullYear();
|
|
115
|
+
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
116
|
+
const day = String(date.getDate()).padStart(2, '0');
|
|
117
|
+
const hours = String(date.getHours()).padStart(2, '0');
|
|
118
|
+
const minutes = String(date.getMinutes()).padStart(2, '0');
|
|
119
|
+
const seconds = String(date.getSeconds()).padStart(2, '0');
|
|
120
|
+
|
|
121
|
+
return `${year}${month}${day}${hours}${minutes}${seconds}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function getCookies(rawHeaders) {
|
|
125
|
+
let index = 0;
|
|
126
|
+
rawHeaders.forEach((v, i) => {
|
|
127
|
+
if (v === 'Cookie') {
|
|
128
|
+
index = i + 1;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return rawHeaders[index];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getCookie(_cookies, name) {
|
|
135
|
+
const cookies = _cookies.split(';');
|
|
136
|
+
for (let i = 0; i < cookies.length; i++) {
|
|
137
|
+
let cookie = cookies[i].trim();
|
|
138
|
+
if (cookie.indexOf(name + '=') == 0) {
|
|
139
|
+
return cookie.substring(name.length + 1, cookie.length);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
module.exports = {
|
|
145
|
+
urlencodeObject,
|
|
146
|
+
cleanUselessKey,
|
|
147
|
+
getFileContent,
|
|
148
|
+
unzip,
|
|
149
|
+
getParam,
|
|
150
|
+
getCurrentDate,
|
|
151
|
+
getCookies,
|
|
152
|
+
getCookie,
|
|
153
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
let role = {
|
|
2
|
+
body: [
|
|
3
|
+
{
|
|
4
|
+
type: 'table',
|
|
5
|
+
addRowInfo: {
|
|
6
|
+
layoutSet: [
|
|
7
|
+
'API_NAME',
|
|
8
|
+
'API_DESC',
|
|
9
|
+
'API_TYPE',
|
|
10
|
+
'API_ID',
|
|
11
|
+
'API_KEY',
|
|
12
|
+
'API_WHITE_LIST',
|
|
13
|
+
'API_RANGE',
|
|
14
|
+
],
|
|
15
|
+
},
|
|
16
|
+
rowInfo: {
|
|
17
|
+
mode: 'form',
|
|
18
|
+
layoutSet: [
|
|
19
|
+
'API_NAME',
|
|
20
|
+
'API_DESC',
|
|
21
|
+
'API_TYPE',
|
|
22
|
+
'API_ID',
|
|
23
|
+
'API_KEY',
|
|
24
|
+
'API_WHITE_LIST',
|
|
25
|
+
'API_RANGE',
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
module.exports = role;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<PageView title="API" blockApi="/space/mapping" initApi="">
|
|
3
|
+
<Fields>
|
|
4
|
+
<element id="DATA_ID" isFilter="false"/>
|
|
5
|
+
<element id="API_NAME" component="text" label="应用名称" clearable="true" placeholder="请输入阶段名称" required="true" labelTpl="${value} - ${label}"/>
|
|
6
|
+
<element id="API_DESC" component="textarea" label="应用说明" placeholder="请输入阶段说明" required="false" isFilter="false"/>
|
|
7
|
+
<element id="API_TYPE" component="dropdown" label="应用类型" source="$dict.APP_APPLY_TYPE" clearable="true" size="sm" labelTpl="${value} - ${label}" searchable="true" required="true"/>
|
|
8
|
+
<element id="API_ID" component="text" label="APP_ID" clearable="true" size="sm" multiple="true" labelTpl="${value} - ${label}" searchable="true" required="true"/>
|
|
9
|
+
<element id="API_KEY" component="text" label="APP_KEY" clearable="true" size="sm" multiple="true" labelTpl="${value} - ${label}" searchable="true" required="true"/>
|
|
10
|
+
<element id="API_WHITE_LIST" component="textarea" label="IP白名单" clearable="true" size="sm" multiple="true" labelTpl="${value} - ${label}" searchable="true"/>
|
|
11
|
+
<element id="API_RANGE" component="textarea" label="API范围"/>
|
|
12
|
+
</Fields>
|
|
13
|
+
|
|
14
|
+
<Operations>
|
|
15
|
+
<element id="BTN_ADD" type="button" label="新增" level="primary" actionType="add" icon="plus" size="sm" title="新增API" />
|
|
16
|
+
<element id="BTN_DEL" type="button" label="删除" level="danger" actionType="del" />
|
|
17
|
+
<element id="BTN_MOD" type="button" label="修改" level="" actionType="edit" title="API修改" />
|
|
18
|
+
</Operations>
|
|
19
|
+
|
|
20
|
+
<Table rowKey="DATA_ID" autoFillHeight="true"
|
|
21
|
+
api="/space/setting/api-list"
|
|
22
|
+
addApi="post:/space/setting/api-list"
|
|
23
|
+
delApi="delete:/space/setting/api-list/${DATA_ID}"
|
|
24
|
+
editApi="put:/space/setting/api-list/${DATA_ID}"
|
|
25
|
+
>
|
|
26
|
+
<DefaultQuery>
|
|
27
|
+
<element id="page" value="1"/>
|
|
28
|
+
<element id="size" value="50"/>
|
|
29
|
+
</DefaultQuery>
|
|
30
|
+
|
|
31
|
+
<TableHead isReset="true" isMode="false" isContrl="true" isFilterPlus="false" isGroup="true">
|
|
32
|
+
<filter list="API_NAME, dynamic"/>
|
|
33
|
+
<action components="BTN_ADD"/>
|
|
34
|
+
</TableHead>
|
|
35
|
+
|
|
36
|
+
<TableBody>
|
|
37
|
+
<column id="API_NAME" width="114" fixed="left" />
|
|
38
|
+
<column id="API_DESC" width="200" />
|
|
39
|
+
<column id="API_TYPE" width="140" />
|
|
40
|
+
<column id="API_ID" width="140" />
|
|
41
|
+
<column id="API_KEY" width="140" />
|
|
42
|
+
<column id="API_WHITE_LIST" width="140" />
|
|
43
|
+
<column id="API_RANGE" width="140" />
|
|
44
|
+
<column id="opr" width='120' label="操作" fixed="right" components="BTN_MOD, BTN_DEL"/>
|
|
45
|
+
</TableBody>
|
|
46
|
+
|
|
47
|
+
<TableFoot show="true" showPageInput="true" statistics="" placeLeft="statistics" placeRight="pagination,switchPage" switchPage="5, 10, 20, 50, 100" />
|
|
48
|
+
</Table>
|
|
49
|
+
</PageView>
|