midway-fatcms 0.0.19 → 0.0.20
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/.prettierrc.js +1 -0
- package/dist/controller/manage/ProxyApiMangeApi.js +2 -1
- package/dist/libs/crud-pro/services/CrudProDataTypeConvertService.js +3 -19
- package/dist/libs/crud-pro-quick/fixSoftDelete.d.ts +4 -4
- package/dist/libs/crud-pro-quick/fixSoftDelete.js +2 -6
- package/dist/service/curd/CurdMixService.d.ts +1 -1
- package/dist/service/proxyapi/ProxyApiLoadService.js +2 -1
- package/dist/service/proxyapi/ProxyApiUtils.d.ts +2 -0
- package/dist/service/proxyapi/ProxyApiUtils.js +9 -1
- package/package.json +1 -1
- package/src/controller/home.controller.ts +6 -6
- package/src/controller/manage/ProxyApiMangeApi.ts +2 -1
- package/src/libs/crud-pro/interfaces.ts +71 -71
- package/src/libs/crud-pro/services/CrudProDataTypeConvertService.ts +21 -39
- package/src/libs/crud-pro/utils/MixinUtils.ts +309 -309
- package/src/libs/crud-pro-quick/fixSoftDelete.ts +10 -50
- package/src/service/curd/CurdMixService.ts +1 -4
- package/src/service/curd/CurdProService.ts +8 -9
- package/src/service/curd/fixCfgModel.ts +145 -145
- package/src/service/proxyapi/ProxyApiLoadService.ts +3 -2
- package/src/service/proxyapi/ProxyApiUtils.ts +8 -0
|
@@ -1,309 +1,309 @@
|
|
|
1
|
-
import { CommonException, Exceptions } from '../exceptions';
|
|
2
|
-
import { generateSnowflakeId, uuid, generateSnowflakeIdExt } from './idgene';
|
|
3
|
-
|
|
4
|
-
// 至少需要2个字符
|
|
5
|
-
const FIELD_NAME_REG_EXP = /^[a-zA-Z][0-9a-zA-Z_]+$/;
|
|
6
|
-
|
|
7
|
-
const MixinUtils = {
|
|
8
|
-
isNil(obj: any): boolean {
|
|
9
|
-
return typeof obj === 'undefined' || obj === null;
|
|
10
|
-
},
|
|
11
|
-
isNotNil(obj: any): boolean {
|
|
12
|
-
return !MixinUtils.isNil(obj);
|
|
13
|
-
},
|
|
14
|
-
isEmpty(obj: any): boolean {
|
|
15
|
-
if (typeof obj === 'number' || typeof obj === 'boolean') {
|
|
16
|
-
return false; // ✅ 数字和布尔值永远不为空
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
if (obj === null || obj === undefined) {
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (typeof obj === 'string') {
|
|
24
|
-
return obj.length === 0;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (Array.isArray(obj)) {
|
|
28
|
-
return obj.length === 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (typeof obj === 'object') {
|
|
32
|
-
return Object.keys(obj).length === 0;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return false;
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
isNotEmpty(obj: any): boolean {
|
|
39
|
-
return !MixinUtils.isEmpty(obj);
|
|
40
|
-
},
|
|
41
|
-
|
|
42
|
-
equals(obj1: any, obj2: any): boolean {
|
|
43
|
-
return obj1 === obj2;
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
equalsIgnoreCase(str1: string, str2: string): boolean {
|
|
47
|
-
// 严格检查类型
|
|
48
|
-
if (typeof str1 !== 'string' || typeof str2 !== 'string') {
|
|
49
|
-
return str1 === str2;
|
|
50
|
-
}
|
|
51
|
-
return str1.toUpperCase() === str2.toUpperCase();
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
startsWith(str1: string, str2: string): boolean {
|
|
55
|
-
if (typeof str1 === 'string' && typeof str2 === 'string') {
|
|
56
|
-
return str1.startsWith(str2);
|
|
57
|
-
}
|
|
58
|
-
return false;
|
|
59
|
-
},
|
|
60
|
-
|
|
61
|
-
isValidFieldName(s: string): boolean {
|
|
62
|
-
if (MixinUtils.isEmpty(s)) {
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
return FIELD_NAME_REG_EXP.test(s);
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
isElementAllMatch(array: any, match: (e: any) => boolean): boolean {
|
|
69
|
-
for (let i = 0; i < array.length; i++) {
|
|
70
|
-
const e = array[i];
|
|
71
|
-
if (!match(e)) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return true;
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
parseColumns(columns: string | string[]) {
|
|
79
|
-
return MixinUtils.parseStringArray(columns);
|
|
80
|
-
},
|
|
81
|
-
|
|
82
|
-
parseStringArray(columns: string | string[]): any[] {
|
|
83
|
-
if (!columns || columns === '*') {
|
|
84
|
-
return [];
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (typeof columns === 'string') {
|
|
88
|
-
const columnsTrim = columns.trim();
|
|
89
|
-
// JSON形式
|
|
90
|
-
if (columnsTrim.startsWith('[') && columnsTrim.endsWith(']')) {
|
|
91
|
-
return MixinUtils.parseJsonObject(columnsTrim);
|
|
92
|
-
}
|
|
93
|
-
//逗号形式
|
|
94
|
-
return columnsTrim.split(',').filter(s => {
|
|
95
|
-
return s.length > 0;
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (!Array.isArray(columns)) {
|
|
100
|
-
throw new CommonException(Exceptions.CFG_PARSE_ERROR, 'params must be an array or string');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return columns.filter(s => {
|
|
104
|
-
return !MixinUtils.isEmpty(s);
|
|
105
|
-
});
|
|
106
|
-
},
|
|
107
|
-
|
|
108
|
-
removeStringPrefix(str: string, prefix: string): string {
|
|
109
|
-
if (!str) {
|
|
110
|
-
return '';
|
|
111
|
-
}
|
|
112
|
-
if (str === prefix) {
|
|
113
|
-
return '';
|
|
114
|
-
}
|
|
115
|
-
if (str.startsWith(prefix)) {
|
|
116
|
-
return str.substring(prefix.length);
|
|
117
|
-
}
|
|
118
|
-
return str;
|
|
119
|
-
},
|
|
120
|
-
getErrorMessage(e: any) {
|
|
121
|
-
if (!e) {
|
|
122
|
-
return '';
|
|
123
|
-
}
|
|
124
|
-
const obj = {};
|
|
125
|
-
let fieldCount = 0;
|
|
126
|
-
const keys = ['code', 'message', 'errno', 'sql', 'sqlState', 'sqlMessage', 'stack'];
|
|
127
|
-
for (let i = 0; i < keys.length; i++) {
|
|
128
|
-
const key = keys[i];
|
|
129
|
-
const value = e[key];
|
|
130
|
-
if (value) {
|
|
131
|
-
obj[key] = value;
|
|
132
|
-
fieldCount++;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (fieldCount > 0) {
|
|
137
|
-
return JSON.stringify(obj);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return '' + e;
|
|
141
|
-
},
|
|
142
|
-
|
|
143
|
-
parseJsonObject(str: any): any {
|
|
144
|
-
if (!str) {
|
|
145
|
-
return null;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (typeof str === 'object' || Array.isArray(str)) {
|
|
149
|
-
return str;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
if (typeof str === 'string') {
|
|
153
|
-
str = str.trim();
|
|
154
|
-
if (str.startsWith('{') || str.startsWith('[')) {
|
|
155
|
-
try {
|
|
156
|
-
return JSON.parse(str);
|
|
157
|
-
} catch (e) {
|
|
158
|
-
return null;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return null;
|
|
164
|
-
},
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* 将数组转换成Map方便查询
|
|
168
|
-
* @param list
|
|
169
|
-
* @param getKey
|
|
170
|
-
*/
|
|
171
|
-
toMap<T>(list: T[], getKey: (e: T) => string): Record<string, T> {
|
|
172
|
-
const map = {};
|
|
173
|
-
if (Array.isArray(list) && list.length) {
|
|
174
|
-
for (let i = 0; i < list.length; i++) {
|
|
175
|
-
const e = list[i];
|
|
176
|
-
const key = getKey(e);
|
|
177
|
-
map[key] = e;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return map;
|
|
181
|
-
},
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* 将数组转换成Map方便查询
|
|
185
|
-
* @param list
|
|
186
|
-
* @param getKey
|
|
187
|
-
*/
|
|
188
|
-
toNewMap<T>(list: T[], getKey: (e: T) => string): Map<string, T> {
|
|
189
|
-
const map = new Map();
|
|
190
|
-
if (list && list.length) {
|
|
191
|
-
for (let i = 0; i < list.length; i++) {
|
|
192
|
-
const e = list[i];
|
|
193
|
-
const key = getKey(e);
|
|
194
|
-
map.set(key, e);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return map;
|
|
198
|
-
},
|
|
199
|
-
|
|
200
|
-
deepTravelObject(obj: any, objTravelCallback: (value, key, index, keyPath) => void, keyPath: string) {
|
|
201
|
-
if (!obj || !objTravelCallback) {
|
|
202
|
-
return;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (Array.isArray(obj)) {
|
|
206
|
-
const collection = obj;
|
|
207
|
-
for (let i = 0; i < collection.length; i++) {
|
|
208
|
-
const value = collection[i];
|
|
209
|
-
const curKeyPath = keyPath + '[' + i + ']';
|
|
210
|
-
objTravelCallback(value, null, i, curKeyPath);
|
|
211
|
-
MixinUtils.deepTravelObject(value, objTravelCallback, curKeyPath);
|
|
212
|
-
}
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (typeof obj === 'object') {
|
|
217
|
-
const keys = Object.keys(obj);
|
|
218
|
-
for (let i = 0; i < keys.length; i++) {
|
|
219
|
-
const objKey = keys[i];
|
|
220
|
-
const keyStr = objKey;
|
|
221
|
-
const value = obj[objKey];
|
|
222
|
-
const curKeyPath = keyPath + '.' + keyStr;
|
|
223
|
-
objTravelCallback(value, keyStr, null, curKeyPath);
|
|
224
|
-
MixinUtils.deepTravelObject(value, objTravelCallback, curKeyPath);
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
},
|
|
228
|
-
removeEmptyAttrs(obj: any): any {
|
|
229
|
-
const result = {};
|
|
230
|
-
const keys = Object.keys(obj);
|
|
231
|
-
for (let i = 0; i < keys.length; i++) {
|
|
232
|
-
const key = keys[i];
|
|
233
|
-
const value = obj[key];
|
|
234
|
-
if (MixinUtils.isNotNil(value)) {
|
|
235
|
-
result[key] = value;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
return result;
|
|
239
|
-
},
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* 判断集合A中,是否包含任意一个集合B中的元素
|
|
243
|
-
* @param a
|
|
244
|
-
* @param b
|
|
245
|
-
*/
|
|
246
|
-
hasAny(a: string[], b: string[]): boolean {
|
|
247
|
-
const aSet = new Set(a);
|
|
248
|
-
for (let i = 0; i < b.length; i++) {
|
|
249
|
-
const bElement = b[i];
|
|
250
|
-
if (aSet.has(bElement)) {
|
|
251
|
-
return true;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
return false;
|
|
255
|
-
},
|
|
256
|
-
|
|
257
|
-
selectNotEmpty(a: any, b: any): any {
|
|
258
|
-
if (MixinUtils.isNotEmpty(a)) {
|
|
259
|
-
return a;
|
|
260
|
-
}
|
|
261
|
-
return b;
|
|
262
|
-
},
|
|
263
|
-
|
|
264
|
-
parseValueByType(value: any, targetType: string): any {
|
|
265
|
-
if (value === undefined || value === null) {
|
|
266
|
-
return value;
|
|
267
|
-
}
|
|
268
|
-
if (targetType === 'string') {
|
|
269
|
-
return '' + value;
|
|
270
|
-
}
|
|
271
|
-
if (targetType === 'number') {
|
|
272
|
-
return Number(value);
|
|
273
|
-
}
|
|
274
|
-
if (targetType === 'boolean') {
|
|
275
|
-
return value === 1 || value === true || value === 'true';
|
|
276
|
-
}
|
|
277
|
-
if (targetType === 'array') {
|
|
278
|
-
return MixinUtils.parseStringArray(value);
|
|
279
|
-
}
|
|
280
|
-
if (targetType === 'JSONObject') {
|
|
281
|
-
return MixinUtils.parseJsonObject(value);
|
|
282
|
-
}
|
|
283
|
-
return value;
|
|
284
|
-
},
|
|
285
|
-
sleepMs(ms: number): Promise<any> {
|
|
286
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
287
|
-
},
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* 生成 UUID v4 字符串(纯随机,无外部依赖)
|
|
291
|
-
* 格式:xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,其中 y 为 8/9/a/b 之一
|
|
292
|
-
* @returns 符合 RFC 4122 v4 规范的 UUID 字符串
|
|
293
|
-
*/
|
|
294
|
-
uuid: uuid,
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* 生成雪花ID(64位整数,以字符串返回)
|
|
298
|
-
* 结构:1位符号 + 41位时间戳(ms) + 10位机器ID + 12位序列号
|
|
299
|
-
* 同一毫秒内可生成 4096 个不重复ID,单机每秒可生成约 400 万个
|
|
300
|
-
*
|
|
301
|
-
* @param machineId 机器ID(0-1023),不传则依次从环境变量 SNOWFLAKE_MACHINE_ID、process.pid 获取
|
|
302
|
-
* @returns 雪花ID字符串
|
|
303
|
-
*/
|
|
304
|
-
generateSnowflakeId: generateSnowflakeId,
|
|
305
|
-
|
|
306
|
-
generateSnowflakeIdExt: generateSnowflakeIdExt,
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
export { MixinUtils };
|
|
1
|
+
import { CommonException, Exceptions } from '../exceptions';
|
|
2
|
+
import { generateSnowflakeId, uuid, generateSnowflakeIdExt } from './idgene';
|
|
3
|
+
|
|
4
|
+
// 至少需要2个字符
|
|
5
|
+
const FIELD_NAME_REG_EXP = /^[a-zA-Z][0-9a-zA-Z_]+$/;
|
|
6
|
+
|
|
7
|
+
const MixinUtils = {
|
|
8
|
+
isNil(obj: any): boolean {
|
|
9
|
+
return typeof obj === 'undefined' || obj === null;
|
|
10
|
+
},
|
|
11
|
+
isNotNil(obj: any): boolean {
|
|
12
|
+
return !MixinUtils.isNil(obj);
|
|
13
|
+
},
|
|
14
|
+
isEmpty(obj: any): boolean {
|
|
15
|
+
if (typeof obj === 'number' || typeof obj === 'boolean') {
|
|
16
|
+
return false; // ✅ 数字和布尔值永远不为空
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
if (obj === null || obj === undefined) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
if (typeof obj === 'string') {
|
|
24
|
+
return obj.length === 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(obj)) {
|
|
28
|
+
return obj.length === 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (typeof obj === 'object') {
|
|
32
|
+
return Object.keys(obj).length === 0;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return false;
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
isNotEmpty(obj: any): boolean {
|
|
39
|
+
return !MixinUtils.isEmpty(obj);
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
equals(obj1: any, obj2: any): boolean {
|
|
43
|
+
return obj1 === obj2;
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
equalsIgnoreCase(str1: string, str2: string): boolean {
|
|
47
|
+
// 严格检查类型
|
|
48
|
+
if (typeof str1 !== 'string' || typeof str2 !== 'string') {
|
|
49
|
+
return str1 === str2;
|
|
50
|
+
}
|
|
51
|
+
return str1.toUpperCase() === str2.toUpperCase();
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
startsWith(str1: string, str2: string): boolean {
|
|
55
|
+
if (typeof str1 === 'string' && typeof str2 === 'string') {
|
|
56
|
+
return str1.startsWith(str2);
|
|
57
|
+
}
|
|
58
|
+
return false;
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
isValidFieldName(s: string): boolean {
|
|
62
|
+
if (MixinUtils.isEmpty(s)) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return FIELD_NAME_REG_EXP.test(s);
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
isElementAllMatch(array: any, match: (e: any) => boolean): boolean {
|
|
69
|
+
for (let i = 0; i < array.length; i++) {
|
|
70
|
+
const e = array[i];
|
|
71
|
+
if (!match(e)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
parseColumns(columns: string | string[]) {
|
|
79
|
+
return MixinUtils.parseStringArray(columns);
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
parseStringArray(columns: string | string[]): any[] {
|
|
83
|
+
if (!columns || columns === '*') {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (typeof columns === 'string') {
|
|
88
|
+
const columnsTrim = columns.trim();
|
|
89
|
+
// JSON形式
|
|
90
|
+
if (columnsTrim.startsWith('[') && columnsTrim.endsWith(']')) {
|
|
91
|
+
return MixinUtils.parseJsonObject(columnsTrim);
|
|
92
|
+
}
|
|
93
|
+
//逗号形式
|
|
94
|
+
return columnsTrim.split(',').filter(s => {
|
|
95
|
+
return s.length > 0;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (!Array.isArray(columns)) {
|
|
100
|
+
throw new CommonException(Exceptions.CFG_PARSE_ERROR, 'params must be an array or string');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return columns.filter(s => {
|
|
104
|
+
return !MixinUtils.isEmpty(s);
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
removeStringPrefix(str: string, prefix: string): string {
|
|
109
|
+
if (!str) {
|
|
110
|
+
return '';
|
|
111
|
+
}
|
|
112
|
+
if (str === prefix) {
|
|
113
|
+
return '';
|
|
114
|
+
}
|
|
115
|
+
if (str.startsWith(prefix)) {
|
|
116
|
+
return str.substring(prefix.length);
|
|
117
|
+
}
|
|
118
|
+
return str;
|
|
119
|
+
},
|
|
120
|
+
getErrorMessage(e: any) {
|
|
121
|
+
if (!e) {
|
|
122
|
+
return '';
|
|
123
|
+
}
|
|
124
|
+
const obj = {};
|
|
125
|
+
let fieldCount = 0;
|
|
126
|
+
const keys = ['code', 'message', 'errno', 'sql', 'sqlState', 'sqlMessage', 'stack'];
|
|
127
|
+
for (let i = 0; i < keys.length; i++) {
|
|
128
|
+
const key = keys[i];
|
|
129
|
+
const value = e[key];
|
|
130
|
+
if (value) {
|
|
131
|
+
obj[key] = value;
|
|
132
|
+
fieldCount++;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (fieldCount > 0) {
|
|
137
|
+
return JSON.stringify(obj);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return '' + e;
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
parseJsonObject(str: any): any {
|
|
144
|
+
if (!str) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (typeof str === 'object' || Array.isArray(str)) {
|
|
149
|
+
return str;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (typeof str === 'string') {
|
|
153
|
+
str = str.trim();
|
|
154
|
+
if (str.startsWith('{') || str.startsWith('[')) {
|
|
155
|
+
try {
|
|
156
|
+
return JSON.parse(str);
|
|
157
|
+
} catch (e) {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return null;
|
|
164
|
+
},
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* 将数组转换成Map方便查询
|
|
168
|
+
* @param list
|
|
169
|
+
* @param getKey
|
|
170
|
+
*/
|
|
171
|
+
toMap<T>(list: T[], getKey: (e: T) => string): Record<string, T> {
|
|
172
|
+
const map = {};
|
|
173
|
+
if (Array.isArray(list) && list.length) {
|
|
174
|
+
for (let i = 0; i < list.length; i++) {
|
|
175
|
+
const e = list[i];
|
|
176
|
+
const key = getKey(e);
|
|
177
|
+
map[key] = e;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return map;
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* 将数组转换成Map方便查询
|
|
185
|
+
* @param list
|
|
186
|
+
* @param getKey
|
|
187
|
+
*/
|
|
188
|
+
toNewMap<T>(list: T[], getKey: (e: T) => string): Map<string, T> {
|
|
189
|
+
const map = new Map();
|
|
190
|
+
if (list && list.length) {
|
|
191
|
+
for (let i = 0; i < list.length; i++) {
|
|
192
|
+
const e = list[i];
|
|
193
|
+
const key = getKey(e);
|
|
194
|
+
map.set(key, e);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return map;
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
deepTravelObject(obj: any, objTravelCallback: (value, key, index, keyPath) => void, keyPath: string) {
|
|
201
|
+
if (!obj || !objTravelCallback) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (Array.isArray(obj)) {
|
|
206
|
+
const collection = obj;
|
|
207
|
+
for (let i = 0; i < collection.length; i++) {
|
|
208
|
+
const value = collection[i];
|
|
209
|
+
const curKeyPath = keyPath + '[' + i + ']';
|
|
210
|
+
objTravelCallback(value, null, i, curKeyPath);
|
|
211
|
+
MixinUtils.deepTravelObject(value, objTravelCallback, curKeyPath);
|
|
212
|
+
}
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (typeof obj === 'object') {
|
|
217
|
+
const keys = Object.keys(obj);
|
|
218
|
+
for (let i = 0; i < keys.length; i++) {
|
|
219
|
+
const objKey = keys[i];
|
|
220
|
+
const keyStr = objKey;
|
|
221
|
+
const value = obj[objKey];
|
|
222
|
+
const curKeyPath = keyPath + '.' + keyStr;
|
|
223
|
+
objTravelCallback(value, keyStr, null, curKeyPath);
|
|
224
|
+
MixinUtils.deepTravelObject(value, objTravelCallback, curKeyPath);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
removeEmptyAttrs(obj: any): any {
|
|
229
|
+
const result = {};
|
|
230
|
+
const keys = Object.keys(obj);
|
|
231
|
+
for (let i = 0; i < keys.length; i++) {
|
|
232
|
+
const key = keys[i];
|
|
233
|
+
const value = obj[key];
|
|
234
|
+
if (MixinUtils.isNotNil(value)) {
|
|
235
|
+
result[key] = value;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return result;
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* 判断集合A中,是否包含任意一个集合B中的元素
|
|
243
|
+
* @param a
|
|
244
|
+
* @param b
|
|
245
|
+
*/
|
|
246
|
+
hasAny(a: string[], b: string[]): boolean {
|
|
247
|
+
const aSet = new Set(a);
|
|
248
|
+
for (let i = 0; i < b.length; i++) {
|
|
249
|
+
const bElement = b[i];
|
|
250
|
+
if (aSet.has(bElement)) {
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return false;
|
|
255
|
+
},
|
|
256
|
+
|
|
257
|
+
selectNotEmpty(a: any, b: any): any {
|
|
258
|
+
if (MixinUtils.isNotEmpty(a)) {
|
|
259
|
+
return a;
|
|
260
|
+
}
|
|
261
|
+
return b;
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
parseValueByType(value: any, targetType: string): any {
|
|
265
|
+
if (value === undefined || value === null) {
|
|
266
|
+
return value;
|
|
267
|
+
}
|
|
268
|
+
if (targetType === 'string') {
|
|
269
|
+
return '' + value;
|
|
270
|
+
}
|
|
271
|
+
if (targetType === 'number') {
|
|
272
|
+
return Number(value);
|
|
273
|
+
}
|
|
274
|
+
if (targetType === 'boolean') {
|
|
275
|
+
return value === 1 || value === true || value === 'true';
|
|
276
|
+
}
|
|
277
|
+
if (targetType === 'array') {
|
|
278
|
+
return MixinUtils.parseStringArray(value);
|
|
279
|
+
}
|
|
280
|
+
if (targetType === 'JSONObject') {
|
|
281
|
+
return MixinUtils.parseJsonObject(value);
|
|
282
|
+
}
|
|
283
|
+
return value;
|
|
284
|
+
},
|
|
285
|
+
sleepMs(ms: number): Promise<any> {
|
|
286
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
287
|
+
},
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* 生成 UUID v4 字符串(纯随机,无外部依赖)
|
|
291
|
+
* 格式:xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,其中 y 为 8/9/a/b 之一
|
|
292
|
+
* @returns 符合 RFC 4122 v4 规范的 UUID 字符串
|
|
293
|
+
*/
|
|
294
|
+
uuid: uuid,
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* 生成雪花ID(64位整数,以字符串返回)
|
|
298
|
+
* 结构:1位符号 + 41位时间戳(ms) + 10位机器ID + 12位序列号
|
|
299
|
+
* 同一毫秒内可生成 4096 个不重复ID,单机每秒可生成约 400 万个
|
|
300
|
+
*
|
|
301
|
+
* @param machineId 机器ID(0-1023),不传则依次从环境变量 SNOWFLAKE_MACHINE_ID、process.pid 获取
|
|
302
|
+
* @returns 雪花ID字符串
|
|
303
|
+
*/
|
|
304
|
+
generateSnowflakeId: generateSnowflakeId,
|
|
305
|
+
|
|
306
|
+
generateSnowflakeIdExt: generateSnowflakeIdExt,
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
export { MixinUtils };
|