jinbi-utils 1.0.21 → 1.0.22
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/.eslintignore +7 -0
- package/dist/index.esm.js +3079 -0
- package/dist/index.esm.min.js +15 -0
- package/dist/index.umd.js +3192 -0
- package/dist/index.umd.min.js +16 -0
- package/package.json +1 -1
- package/src/common/index.ts +105 -105
- package/src/constant/common.constant.ts +1 -1
- package/src/file/index.ts +8 -8
- package/src/http/apiBuilder/api-builder.ts +3 -3
- package/src/http/http.ts +2 -2
- package/src/http/httpEnums.ts +7 -7
- package/src/iam/index.ts +3 -3
- package/src/index.ts +6 -6
- package/src/middleware/requestLogger.middware.ts +21 -7
- package/src/middleware/requestLoggerUnified.ts +22 -8
- package/src/number/index.ts +4 -4
- package/src/string/index.ts +1 -1
- package/src/utils/curl.ts +76 -85
- package/src/websocket/emitter.ts +2 -2
- package/src/websocket/manager.ts +4 -4
- package/src/websocket/pinia-store.ts +6 -6
|
@@ -0,0 +1,3192 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('axios'), require('pinia')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', 'axios', 'pinia'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["jinbi-utils"] = {}, global.axios, global.pinia));
|
|
5
|
+
})(this, (function (exports, axios, pinia) { 'use strict';
|
|
6
|
+
|
|
7
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
|
+
|
|
9
|
+
var axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
|
|
10
|
+
|
|
11
|
+
var fromTypeMap = {
|
|
12
|
+
isWxWork: 'wecom',
|
|
13
|
+
isWeixin: 'wechat',
|
|
14
|
+
isMobile: 'mobile',
|
|
15
|
+
isMobileAny: 'mobile',
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 通用函数
|
|
20
|
+
* @packageDocumentation
|
|
21
|
+
* @module Common
|
|
22
|
+
* @preferred
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* 延迟函数(Promise 版本)
|
|
26
|
+
* @param ms - 延迟毫秒数
|
|
27
|
+
* @returns Promise
|
|
28
|
+
*/
|
|
29
|
+
function delay(ms) {
|
|
30
|
+
return new Promise(function (resolve) { return setTimeout(resolve, ms); });
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 检测设备是否为移动设备
|
|
34
|
+
* @returns 是否为移动设备
|
|
35
|
+
*/
|
|
36
|
+
function deviceDetection() {
|
|
37
|
+
if (typeof window === 'undefined')
|
|
38
|
+
return false;
|
|
39
|
+
var userAgent = navigator.userAgent.toLowerCase();
|
|
40
|
+
var isMidp = /midp/i.test(userAgent);
|
|
41
|
+
var isUcweb = /ucweb/i.test(userAgent);
|
|
42
|
+
var isAndroid = /android/i.test(userAgent);
|
|
43
|
+
var isIos = /iphone os/i.test(userAgent);
|
|
44
|
+
var isWinCe = /windows ce/i.test(userAgent);
|
|
45
|
+
var isWinMobile = /windows mobile/i.test(userAgent);
|
|
46
|
+
var isRv = /rv:1.2.3.4/i.test(userAgent);
|
|
47
|
+
return (isMidp || isUcweb || isAndroid || isIos || isWinCe || isWinMobile || isRv);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 判断val 是否是空值
|
|
51
|
+
#### 使用说明
|
|
52
|
+
```
|
|
53
|
+
isEmpty('') 返回 true
|
|
54
|
+
isEmpty(null) 返回 true
|
|
55
|
+
isEmpty(undefined) 返回 true
|
|
56
|
+
isEmpty(12323) 返回 false
|
|
57
|
+
```
|
|
58
|
+
*/
|
|
59
|
+
function isEmpty(val) {
|
|
60
|
+
return val === null || val === '' || val === undefined;
|
|
61
|
+
}
|
|
62
|
+
// from jinbizhihui
|
|
63
|
+
// 获取环境变量
|
|
64
|
+
// export const getEnvValue = (type: string) => {
|
|
65
|
+
// return import.meta.env[type]
|
|
66
|
+
// }
|
|
67
|
+
var clearLoginData = function () {
|
|
68
|
+
// 这里做指定的 key 清除 是为了 避免 清除掉 jsapiticket 等一些需要有的字段 防止多次请求
|
|
69
|
+
localStorage.removeItem('wecom_userinfo');
|
|
70
|
+
localStorage.removeItem('wecom_token');
|
|
71
|
+
localStorage.removeItem('projectActive');
|
|
72
|
+
localStorage.removeItem('loginTime');
|
|
73
|
+
localStorage.removeItem('projectInfo');
|
|
74
|
+
};
|
|
75
|
+
// 获取url中参数
|
|
76
|
+
var getQueryString = function (url, queryKey) {
|
|
77
|
+
var reg = new RegExp("&{1}" + queryKey + "\\=[a-zA-Z0-9_-]+", 'g');
|
|
78
|
+
var matchResult = url.replace(/\?/g, '&').match(reg)[0];
|
|
79
|
+
return matchResult.substr(matchResult.indexOf('=') + 1);
|
|
80
|
+
};
|
|
81
|
+
var getQueryVariable = function (variable) {
|
|
82
|
+
var query = window.location.search.substring(1);
|
|
83
|
+
var vars = query.split('&');
|
|
84
|
+
for (var i = 0; i < vars.length; i++) {
|
|
85
|
+
var pair = vars[i].split('=');
|
|
86
|
+
if (pair[0] === variable) {
|
|
87
|
+
return pair[1];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return (false);
|
|
91
|
+
};
|
|
92
|
+
var getWecomToken = function () {
|
|
93
|
+
return localStorage.getItem('wecom_token');
|
|
94
|
+
};
|
|
95
|
+
// 判断设备类型
|
|
96
|
+
var getDeviceType = function () {
|
|
97
|
+
var ua = navigator.userAgent.toLowerCase();
|
|
98
|
+
var isWxWork = /wxwork/.test(ua); // 企业微信
|
|
99
|
+
var isWeixin = /micromessenger/.test(ua) && !isWxWork; // 微信,排除企业微信
|
|
100
|
+
// 使用屏幕宽度判断是否移动设备
|
|
101
|
+
var isMobileScreen = window.innerWidth <= 768;
|
|
102
|
+
return {
|
|
103
|
+
isWxWork: isWxWork,
|
|
104
|
+
isWeixin: isWeixin,
|
|
105
|
+
isMobileScreen: isMobileScreen,
|
|
106
|
+
isMobileAny: isWxWork || isWeixin || isMobileScreen,
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
var getFromType = function (res) {
|
|
110
|
+
var result = 'wecom';
|
|
111
|
+
for (var key in res) {
|
|
112
|
+
var value = res[key];
|
|
113
|
+
if (value) {
|
|
114
|
+
result = fromTypeMap[key];
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
};
|
|
120
|
+
function randomString(e) {
|
|
121
|
+
e = e || 32;
|
|
122
|
+
var t = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
|
|
123
|
+
var a = t.length;
|
|
124
|
+
var n = '';
|
|
125
|
+
for (var i = 0; i < e; i++)
|
|
126
|
+
n += t.charAt(Math.floor(Math.random() * a));
|
|
127
|
+
return n;
|
|
128
|
+
}
|
|
129
|
+
var getCookie = function (cookieName) {
|
|
130
|
+
var cookie = '';
|
|
131
|
+
var cookieArr = document.cookie.split('; ');
|
|
132
|
+
for (var i = 0; i < cookieArr.length; i++) {
|
|
133
|
+
var valueArr = cookieArr[i].split('=');
|
|
134
|
+
if (valueArr[0] === cookieName) {
|
|
135
|
+
cookie = valueArr[1];
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return cookie;
|
|
140
|
+
};
|
|
141
|
+
// || 'cc51882c781d8035b98335ccb44787b42dd9d91ba3b85a45ff3e867857a526bfbbddcdc27b8edce9a52882d1838e0b8e6ccf658ed105df9a898b1c977c588bd1'
|
|
142
|
+
var buildUUID = function () {
|
|
143
|
+
var hexList = [];
|
|
144
|
+
for (var i = 0; i <= 15; i++) {
|
|
145
|
+
hexList[i] = i.toString(16);
|
|
146
|
+
}
|
|
147
|
+
var uuid = '';
|
|
148
|
+
for (var i = 1; i <= 36; i++) {
|
|
149
|
+
if (i === 9 || i === 14 || i === 19 || i === 24) {
|
|
150
|
+
uuid += '-';
|
|
151
|
+
}
|
|
152
|
+
else if (i === 15) {
|
|
153
|
+
uuid += 4;
|
|
154
|
+
}
|
|
155
|
+
else if (i === 20) {
|
|
156
|
+
uuid += hexList[(Math.random() * 4) | 8];
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
uuid += hexList[(Math.random() * 16) | 0];
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return uuid.replace(/-/g, '');
|
|
163
|
+
};
|
|
164
|
+
var getTicket = function () {
|
|
165
|
+
return localStorage.getItem('jsapiTicket');
|
|
166
|
+
};
|
|
167
|
+
var setTicket = function (jsapiTicket) {
|
|
168
|
+
return localStorage.setItem('jsapiTicket', jsapiTicket);
|
|
169
|
+
};
|
|
170
|
+
var removeTicket = function () {
|
|
171
|
+
return localStorage.removeItem('jsapiTicket');
|
|
172
|
+
};
|
|
173
|
+
var formateTimestamp = function (timestamp, type) {
|
|
174
|
+
if (type === void 0) { type = 'YYYY年MM月DD日 hh:mm:ss'; }
|
|
175
|
+
if (!timestamp) {
|
|
176
|
+
return '-';
|
|
177
|
+
}
|
|
178
|
+
var date = new Date(timestamp);
|
|
179
|
+
var year = date.getFullYear() + '';
|
|
180
|
+
var month = date.getMonth() + 1;
|
|
181
|
+
var day = date.getDate();
|
|
182
|
+
var houre = date.getHours() > 9 ? date.getHours() : '0' + date.getHours();
|
|
183
|
+
var minute = date.getMinutes() > 9 ? date.getMinutes() : '0' + date.getMinutes();
|
|
184
|
+
var second = date.getSeconds() > 9 ? date.getSeconds() : '0' + date.getSeconds();
|
|
185
|
+
var result = type.replace('YYYY', year + '').replace('MM', month + '').replace('DD', day + '').replace('hh', houre + '').replace('mm', minute + '').replace('ss', second + '');
|
|
186
|
+
return result;
|
|
187
|
+
};
|
|
188
|
+
var convertBase64UrlToBlob = function (urlData) {
|
|
189
|
+
// console.log('urlData', urlData)
|
|
190
|
+
// 将以base64的图片url数据转换为Blob
|
|
191
|
+
var bytes = window.atob(urlData.split(',')[1]); // 去掉url的头,并转换为byte
|
|
192
|
+
// 处理异常,将ascii码小于0的转换为大于0
|
|
193
|
+
var ab = new ArrayBuffer(bytes.length);
|
|
194
|
+
var ia = new Uint8Array(ab);
|
|
195
|
+
for (var i = 0; i < bytes.length; i++) {
|
|
196
|
+
ia[i] = bytes.charCodeAt(i);
|
|
197
|
+
}
|
|
198
|
+
return new Blob([ab], { type: 'image/png' });
|
|
199
|
+
};
|
|
200
|
+
var getEnvironment = function () {
|
|
201
|
+
var isMobile = window.navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i); // 是否手机端
|
|
202
|
+
var isWx = /micromessenger/i.test(navigator.userAgent); // 是否微信
|
|
203
|
+
var isComWx = /wxwork/i.test(navigator.userAgent); // 是否企业微信
|
|
204
|
+
if (isComWx && isMobile) { //手机端企业微信
|
|
205
|
+
return 'com-wx-mobile';
|
|
206
|
+
}
|
|
207
|
+
else if (isComWx && !isMobile) { //PC端企业微信
|
|
208
|
+
return 'com-wx-pc';
|
|
209
|
+
}
|
|
210
|
+
else if (isWx && isMobile) { // 手机端微信
|
|
211
|
+
return 'wx-mobile';
|
|
212
|
+
}
|
|
213
|
+
else if (isWx && !isMobile) { // PC端微信
|
|
214
|
+
return 'wx-pc';
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
return 'other';
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
var getIsComWx = function () {
|
|
221
|
+
var isComWx = /wxwork/i.test(navigator.userAgent); // 是否企业微信
|
|
222
|
+
return isComWx;
|
|
223
|
+
};
|
|
224
|
+
var getIsDevelopment = function () {
|
|
225
|
+
var result = false;
|
|
226
|
+
if (location.origin === 'uat2-h5-wecom.hengdayun.com' || location.origin === '127.0.0.1:8081' || location.origin === 'localhost:8081') {
|
|
227
|
+
result = true;
|
|
228
|
+
}
|
|
229
|
+
return result;
|
|
230
|
+
};
|
|
231
|
+
// 处理时间,企微不能通过dayjs以及moment处理时间
|
|
232
|
+
// 过滤数组重复数据
|
|
233
|
+
var filterRepeat = function (arr, fieldName) {
|
|
234
|
+
var set = new Set();
|
|
235
|
+
return arr.filter(function (item) {
|
|
236
|
+
var key = item[fieldName];
|
|
237
|
+
if (set.has(key)) {
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
set.add(key);
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
};
|
|
246
|
+
// 将 base64 转换为 Blob
|
|
247
|
+
var base64ToBlob = function (base64) {
|
|
248
|
+
var arr = base64.split(","), mime = arr[0].match(/:(.\*?);/)[1], bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
|
|
249
|
+
while (n--) {
|
|
250
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
251
|
+
}
|
|
252
|
+
return new Blob([u8arr], {
|
|
253
|
+
type: mime,
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
// 将 base64 转换为 File
|
|
257
|
+
var base64ToFile = function (base64, fileName) {
|
|
258
|
+
var arr = base64.split(",");
|
|
259
|
+
var mime = arr[0].match(/:(.*);/)[1];
|
|
260
|
+
var bstr = atob(arr[1]);
|
|
261
|
+
var n = bstr.length;
|
|
262
|
+
var u8arr = new Uint8Array(n);
|
|
263
|
+
while (n--) {
|
|
264
|
+
u8arr[n] = bstr.charCodeAt(n);
|
|
265
|
+
}
|
|
266
|
+
return new File([u8arr], fileName, { type: mime });
|
|
267
|
+
};
|
|
268
|
+
// 处理时间,企微不能通过dayjs以及moment处理时间
|
|
269
|
+
var isImage = function (type) {
|
|
270
|
+
return /^image\//i.test(type);
|
|
271
|
+
};
|
|
272
|
+
// 获取文件数据
|
|
273
|
+
var getFileData = function (optionName) {
|
|
274
|
+
var _a = optionName.split(','), _b = _a[0], name = _b === void 0 ? '' : _b, _c = _a[1], url = _c === void 0 ? '' : _c;
|
|
275
|
+
return {
|
|
276
|
+
name: decodeURIComponent(name),
|
|
277
|
+
url: decodeURIComponent(url)
|
|
278
|
+
};
|
|
279
|
+
};
|
|
280
|
+
// 验证是否为数字
|
|
281
|
+
var validateTwoDecimal = function (v) {
|
|
282
|
+
if (!v || v === '')
|
|
283
|
+
return true;
|
|
284
|
+
return /^(\d+)(\.\d{1,2})?$/.test(v.toString());
|
|
285
|
+
};
|
|
286
|
+
// 生成uuid
|
|
287
|
+
var uuid = function (len, radix) {
|
|
288
|
+
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
|
|
289
|
+
var uuid = [], i;
|
|
290
|
+
radix = radix || chars.length;
|
|
291
|
+
if (len) {
|
|
292
|
+
// Compact form
|
|
293
|
+
for (i = 0; i < len; i++)
|
|
294
|
+
uuid[i] = chars[0 | Math.random() * radix];
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
// rfc4122, version 4 form
|
|
298
|
+
var r = void 0;
|
|
299
|
+
// rfc4122 requires these characters
|
|
300
|
+
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
|
|
301
|
+
uuid[14] = '4';
|
|
302
|
+
// Fill in random data. At i==19 set the high bits of clock sequence as
|
|
303
|
+
// per rfc4122, sec. 4.1.5
|
|
304
|
+
for (i = 0; i < 36; i++) {
|
|
305
|
+
if (!uuid[i]) {
|
|
306
|
+
r = 0 | Math.random() * 16;
|
|
307
|
+
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return uuid.join('');
|
|
312
|
+
};
|
|
313
|
+
var getToken = function (cacheType, key) {
|
|
314
|
+
if (key === void 0) { key = 'token'; }
|
|
315
|
+
var token = '';
|
|
316
|
+
var cacheTypeToLower = cacheType.toLowerCase();
|
|
317
|
+
if (cacheTypeToLower === 'localstorage') {
|
|
318
|
+
token = localStorage.getItem(key) || '';
|
|
319
|
+
}
|
|
320
|
+
else if (cacheTypeToLower === 'sessionstorage') {
|
|
321
|
+
token = sessionStorage.getItem(key) || '';
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
token = localStorage.getItem(key) || sessionStorage.getItem('token') || '';
|
|
325
|
+
}
|
|
326
|
+
return token;
|
|
327
|
+
};
|
|
328
|
+
var removeToken = function (cacheType, key) {
|
|
329
|
+
if (key === void 0) { key = 'token'; }
|
|
330
|
+
var cacheTypeToLower = cacheType.toLowerCase();
|
|
331
|
+
if (cacheTypeToLower === 'localstorage') {
|
|
332
|
+
localStorage.removeItem(key);
|
|
333
|
+
}
|
|
334
|
+
else if (cacheTypeToLower === 'sessionstorage') {
|
|
335
|
+
sessionStorage.removeItem(key);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
localStorage.removeItem(key);
|
|
339
|
+
sessionStorage.removeItem(key);
|
|
340
|
+
}
|
|
341
|
+
};
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* 时间处理相关
|
|
345
|
+
* @packageDocumentation
|
|
346
|
+
* @module Date
|
|
347
|
+
* @preferred
|
|
348
|
+
*/
|
|
349
|
+
/**
|
|
350
|
+
* 解决ios不支持 new Date('2020-02-02')问题
|
|
351
|
+
#### 使用说明
|
|
352
|
+
```
|
|
353
|
+
compatibleDate('2020-03-04') 返回 2020/03/04
|
|
354
|
+
compatibleDate(Date.now()) 返回 Date.now()
|
|
355
|
+
compatibleDate(new Date()) 返回 new Date()
|
|
356
|
+
```
|
|
357
|
+
*/
|
|
358
|
+
function compatibleDate(date) {
|
|
359
|
+
if (typeof date === 'string') {
|
|
360
|
+
return date.replace(/-/g, '/');
|
|
361
|
+
}
|
|
362
|
+
return date;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* 调用原生 new Date 返回 Date实例 解决ios不支持 yyyy-MM-dd HH:mm:ss 格式new Date
|
|
366
|
+
#### 使用说明
|
|
367
|
+
```
|
|
368
|
+
newDate() 返回 new Date()
|
|
369
|
+
newDate('2020-03-04') 返回 new Date('2020-03-04')
|
|
370
|
+
```
|
|
371
|
+
*/
|
|
372
|
+
function newDate(date) {
|
|
373
|
+
if (!date)
|
|
374
|
+
return new Date();
|
|
375
|
+
return new Date(compatibleDate(date));
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* 格式化时间
|
|
379
|
+
#### 使用说明
|
|
380
|
+
```
|
|
381
|
+
formatTime() 返回 yyyy-MM-dd HH:mm:ss 格式的当前时间
|
|
382
|
+
formatTime('2018-02-02 00:00:00') 返回 2018-02-02 00:00:00
|
|
383
|
+
formatTime('2018-02-02', 'yyyy/MM/dd') 返回 2018/02/02
|
|
384
|
+
formatTime('2018-02-02 23:50:50', 'yyyy/MM/dd HH:mm:ss') 返回 2018/02/02 23:50:50
|
|
385
|
+
formatTime('2018-02-02 23:50:50', 'MM/dd HH:mm:ss') 返回 02/02 23:50:50
|
|
386
|
+
formatTime(new Date('2018-02-02 23:50:50') + 200, 'yyyy/MM/dd HH:mm:ss S') 返回 2018/02/02 23:50:50 200
|
|
387
|
+
```
|
|
388
|
+
*/
|
|
389
|
+
function formatTime(date, fmt) {
|
|
390
|
+
if (date === void 0) { date = Date.now(); }
|
|
391
|
+
if (fmt === void 0) { fmt = 'yyyy-MM-dd HH:mm:ss'; }
|
|
392
|
+
date = compatibleDate(date);
|
|
393
|
+
date = new Date(date);
|
|
394
|
+
var o = {
|
|
395
|
+
'M+': date.getMonth() + 1,
|
|
396
|
+
'd+': date.getDate(),
|
|
397
|
+
'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12,
|
|
398
|
+
'H+': date.getHours(),
|
|
399
|
+
'm+': date.getMinutes(),
|
|
400
|
+
's+': date.getSeconds(),
|
|
401
|
+
'q+': Math.floor((date.getMonth() + 3) / 3),
|
|
402
|
+
S: date.getMilliseconds(),
|
|
403
|
+
};
|
|
404
|
+
if (/(y+)/.test(fmt)) {
|
|
405
|
+
fmt = fmt.replace(RegExp.$1, ("" + date.getFullYear()).substr(4 - RegExp.$1.length));
|
|
406
|
+
}
|
|
407
|
+
Object.keys(o).forEach(function (k) {
|
|
408
|
+
if (new RegExp("(" + k + ")").test(fmt)) {
|
|
409
|
+
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
return fmt;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* 格式化相对时间
|
|
416
|
+
#### 使用说明
|
|
417
|
+
```
|
|
418
|
+
fromNow('') 返回 -
|
|
419
|
+
fromNow(Date.now() - 2000) 返回 刚刚
|
|
420
|
+
fromNow(now - 3420 * 1000) 返回 58分钟前面
|
|
421
|
+
fromNow(now - 3600 * 1000 * 3) 返回 3小时前
|
|
422
|
+
fromNow(now - 3600 * 1000 * 24 * 1.5) 返回 1天前
|
|
423
|
+
fromNow(now - day5) 返回 当前时间的5天前日期 格式 yyyy年MM月dd日 HH时mm分ss秒
|
|
424
|
+
fromNow(Date.now() + 2000) 返回 Date.now() + 2000
|
|
425
|
+
fromNow('', '', 'defaultValue') 等于 defaultValue
|
|
426
|
+
```
|
|
427
|
+
*/
|
|
428
|
+
function fromNow(time, fmt, defaultValue) {
|
|
429
|
+
if (fmt === void 0) { fmt = 'yyyy年MM月dd日 HH时mm分ss秒'; }
|
|
430
|
+
if (defaultValue === void 0) { defaultValue = '-'; }
|
|
431
|
+
if (isEmpty(time)) {
|
|
432
|
+
return defaultValue;
|
|
433
|
+
}
|
|
434
|
+
time = compatibleDate(time);
|
|
435
|
+
var d = new Date(time);
|
|
436
|
+
var now = Date.now();
|
|
437
|
+
var diff = (now - d.getTime()) / 1000;
|
|
438
|
+
if (diff < 0) {
|
|
439
|
+
return time;
|
|
440
|
+
}
|
|
441
|
+
if (diff < 30) {
|
|
442
|
+
return '刚刚';
|
|
443
|
+
}
|
|
444
|
+
if (diff < 3600) {
|
|
445
|
+
return Math.ceil(diff / 60) + "\u5206\u949F\u524D";
|
|
446
|
+
}
|
|
447
|
+
if (diff < 3600 * 24) {
|
|
448
|
+
return Math.floor(diff / 3600) + "\u5C0F\u65F6\u524D";
|
|
449
|
+
}
|
|
450
|
+
if (diff < 3600 * 24 * 2) {
|
|
451
|
+
return '1天前';
|
|
452
|
+
}
|
|
453
|
+
return formatTime(time, fmt);
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* 增加日期天数
|
|
457
|
+
#### 使用说明
|
|
458
|
+
```
|
|
459
|
+
addDays('') 返回 -
|
|
460
|
+
addDays('2018-02-02') 返回 2018-02-02
|
|
461
|
+
addDays('2018-02-02', 2) 返回 2018-02-04
|
|
462
|
+
addDays('2018-02-02', 2, 'yyyy/MM/dd') 返回 2018/02/04
|
|
463
|
+
addDays(new Date('2020-03-04'), 2, 'yyyy/MM/dd') 返回 2020/03/06
|
|
464
|
+
addDays(Date.now(), 2, 'yyyy/MM/dd') 返回 今天 + 2天
|
|
465
|
+
```
|
|
466
|
+
*/
|
|
467
|
+
function addDays(date, days, fmt) {
|
|
468
|
+
if (days === void 0) { days = 0; }
|
|
469
|
+
if (fmt === void 0) { fmt = 'yyyy-MM-dd'; }
|
|
470
|
+
if (isEmpty(date)) {
|
|
471
|
+
return '-';
|
|
472
|
+
}
|
|
473
|
+
date = compatibleDate(date);
|
|
474
|
+
var d = new Date(date);
|
|
475
|
+
d.setDate(d.getDate() + Number(days));
|
|
476
|
+
return formatTime(d, fmt);
|
|
477
|
+
}
|
|
478
|
+
// 获取当前时间月份
|
|
479
|
+
|
|
480
|
+
/*! *****************************************************************************
|
|
481
|
+
Copyright (c) Microsoft Corporation.
|
|
482
|
+
|
|
483
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
484
|
+
purpose with or without fee is hereby granted.
|
|
485
|
+
|
|
486
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
487
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
488
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
489
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
490
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
491
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
492
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
493
|
+
***************************************************************************** */
|
|
494
|
+
/* global Reflect, Promise */
|
|
495
|
+
|
|
496
|
+
var extendStatics = function(d, b) {
|
|
497
|
+
extendStatics = Object.setPrototypeOf ||
|
|
498
|
+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
499
|
+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
500
|
+
return extendStatics(d, b);
|
|
501
|
+
};
|
|
502
|
+
|
|
503
|
+
function __extends(d, b) {
|
|
504
|
+
extendStatics(d, b);
|
|
505
|
+
function __() { this.constructor = d; }
|
|
506
|
+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
var __assign = function() {
|
|
510
|
+
__assign = Object.assign || function __assign(t) {
|
|
511
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
512
|
+
s = arguments[i];
|
|
513
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
514
|
+
}
|
|
515
|
+
return t;
|
|
516
|
+
};
|
|
517
|
+
return __assign.apply(this, arguments);
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
521
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
522
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
523
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
524
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
525
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
526
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
527
|
+
});
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function __generator(thisArg, body) {
|
|
531
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
532
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
533
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
534
|
+
function step(op) {
|
|
535
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
536
|
+
while (_) try {
|
|
537
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
538
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
539
|
+
switch (op[0]) {
|
|
540
|
+
case 0: case 1: t = op; break;
|
|
541
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
542
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
543
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
544
|
+
default:
|
|
545
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
546
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
547
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
548
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
549
|
+
if (t[2]) _.ops.pop();
|
|
550
|
+
_.trys.pop(); continue;
|
|
551
|
+
}
|
|
552
|
+
op = body.call(thisArg, _);
|
|
553
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
554
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
function __spreadArrays() {
|
|
559
|
+
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
|
|
560
|
+
for (var r = Array(s), k = 0, i = 0; i < il; i++)
|
|
561
|
+
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
|
|
562
|
+
r[k] = a[j];
|
|
563
|
+
return r;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* number处理相关
|
|
568
|
+
* @packageDocumentation
|
|
569
|
+
* @module Number
|
|
570
|
+
* @preferred
|
|
571
|
+
*/
|
|
572
|
+
/**
|
|
573
|
+
* 格式化字节大小为可读字符串
|
|
574
|
+
* @param bytes - 字节数
|
|
575
|
+
* @param decimals - 小数位数,默认为 2
|
|
576
|
+
* @returns 格式化后的字符串(如 "1.5 MB")
|
|
577
|
+
*/
|
|
578
|
+
function formatBytes(bytes, decimals) {
|
|
579
|
+
if (decimals === void 0) { decimals = 2; }
|
|
580
|
+
if (bytes === 0)
|
|
581
|
+
return '0 Bytes';
|
|
582
|
+
var k = 1024;
|
|
583
|
+
var dm = decimals < 0 ? 0 : decimals;
|
|
584
|
+
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
585
|
+
var i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
586
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
|
587
|
+
}
|
|
588
|
+
// 默认货币计算选项
|
|
589
|
+
var DEFAULT_MONEY_OPTIONS = {
|
|
590
|
+
operation: 'divide',
|
|
591
|
+
factor: 100,
|
|
592
|
+
precision: 2,
|
|
593
|
+
formatAsCurrency: false,
|
|
594
|
+
currencySymbol: '¥' // 人民币符号
|
|
595
|
+
};
|
|
596
|
+
/**
|
|
597
|
+
* 千分位格式化
|
|
598
|
+
#### 使用说明
|
|
599
|
+
```
|
|
600
|
+
toThousands(1) => 1
|
|
601
|
+
toThousands(12345) => 12,345
|
|
602
|
+
toThousands('12323.12') 返回 '12,323.12'
|
|
603
|
+
```
|
|
604
|
+
*/
|
|
605
|
+
function toThousands(num, defaultValue) {
|
|
606
|
+
if (defaultValue === void 0) { defaultValue = '-'; }
|
|
607
|
+
if (isEmpty(num)) {
|
|
608
|
+
return defaultValue;
|
|
609
|
+
}
|
|
610
|
+
var val = num.toString();
|
|
611
|
+
if (!val.includes('.')) {
|
|
612
|
+
val += '.';
|
|
613
|
+
}
|
|
614
|
+
return val.replace(/\d(?=(\d{3})+\.)/g, function ($0) { return $0 + ","; }).replace(/\.$/, '');
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* 阿拉伯数组转中文数字
|
|
618
|
+
#### 使用说明
|
|
619
|
+
```
|
|
620
|
+
convertCurrency(0) 返回 '壹拾贰元壹角贰分'
|
|
621
|
+
convertCurrency(1234567809) 返回 '壹拾贰亿叁仟肆佰伍拾陆万柒仟捌佰零玖元整'
|
|
622
|
+
```
|
|
623
|
+
* @param {number} money 金额
|
|
624
|
+
*/
|
|
625
|
+
function convertCurrency(money) {
|
|
626
|
+
if (money === void 0) { money = ''; }
|
|
627
|
+
var maxNum = 999999999999999.9999; // 最大处理的数字
|
|
628
|
+
if (isEmpty(money)) {
|
|
629
|
+
return '';
|
|
630
|
+
}
|
|
631
|
+
if (Number(money) >= maxNum) {
|
|
632
|
+
// 超出最大处理数字
|
|
633
|
+
return money;
|
|
634
|
+
}
|
|
635
|
+
var cnNums = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
|
|
636
|
+
var cnIntRadice = ['', '拾', '佰', '仟'];
|
|
637
|
+
var cnIntUnits = ['', '万', '亿', '兆']; // 对应整数部分扩展单位
|
|
638
|
+
var cnDecUnits = ['角', '分', '毫', '厘']; // 对应小数部分单位
|
|
639
|
+
var cnInteger = '整'; // 整数金额时后面跟的字符
|
|
640
|
+
var cnIntLast = '元'; // 整型完以后的单位
|
|
641
|
+
var integerNum; // 金额整数部分
|
|
642
|
+
var decimalNum; // 金额小数部分
|
|
643
|
+
var chineseStr = ''; // 输出的中文金额字符串
|
|
644
|
+
var parts; // 分离金额后用的数组,预定义
|
|
645
|
+
money = parseFloat(money).toString();
|
|
646
|
+
if (money === '0') {
|
|
647
|
+
chineseStr = cnNums[0] + cnIntLast + cnInteger;
|
|
648
|
+
return chineseStr;
|
|
649
|
+
}
|
|
650
|
+
// 转换为字符串
|
|
651
|
+
money = money.toString();
|
|
652
|
+
if (money.indexOf('.') === -1) {
|
|
653
|
+
integerNum = money;
|
|
654
|
+
decimalNum = '';
|
|
655
|
+
}
|
|
656
|
+
else {
|
|
657
|
+
parts = money.split('.');
|
|
658
|
+
integerNum = parts[0];
|
|
659
|
+
decimalNum = parts[1].substr(0, 4);
|
|
660
|
+
}
|
|
661
|
+
// 获取整型部分转换
|
|
662
|
+
if (parseInt(integerNum, 10) > 0) {
|
|
663
|
+
var zeroCount = 0;
|
|
664
|
+
var intLen = integerNum.length;
|
|
665
|
+
for (var i = 0; i < intLen; i += 1) {
|
|
666
|
+
var n = integerNum.substr(i, 1);
|
|
667
|
+
var p = intLen - i - 1;
|
|
668
|
+
var q = p / 4;
|
|
669
|
+
var m = p % 4;
|
|
670
|
+
if (n === '0') {
|
|
671
|
+
zeroCount += 1;
|
|
672
|
+
}
|
|
673
|
+
else {
|
|
674
|
+
if (zeroCount > 0) {
|
|
675
|
+
chineseStr += cnNums[0];
|
|
676
|
+
}
|
|
677
|
+
// 归零
|
|
678
|
+
zeroCount = 0;
|
|
679
|
+
chineseStr += cnNums[parseInt(n, 10)] + cnIntRadice[m];
|
|
680
|
+
}
|
|
681
|
+
if (m === 0 && zeroCount < 4) {
|
|
682
|
+
chineseStr += cnIntUnits[q];
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
chineseStr += cnIntLast;
|
|
686
|
+
}
|
|
687
|
+
// 小数部分
|
|
688
|
+
if (decimalNum !== '') {
|
|
689
|
+
var decLen = decimalNum.length;
|
|
690
|
+
for (var i = 0; i < decLen; i += 1) {
|
|
691
|
+
var dn = decimalNum.substr(i, 1);
|
|
692
|
+
if (dn !== '0') {
|
|
693
|
+
chineseStr += cnNums[Number(dn)] + cnDecUnits[i];
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
if (chineseStr === '') {
|
|
698
|
+
chineseStr += cnNums[0] + cnIntLast + cnInteger;
|
|
699
|
+
}
|
|
700
|
+
else if (decimalNum === '') {
|
|
701
|
+
chineseStr += cnInteger;
|
|
702
|
+
}
|
|
703
|
+
return chineseStr;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* 格式化小数位
|
|
707
|
+
#### 使用说明
|
|
708
|
+
```
|
|
709
|
+
formatFloat('1.2345') 返回 '1.23'
|
|
710
|
+
formatFloat('1.2345', 3) 返回 '1.235'
|
|
711
|
+
formatFloat('1', 3) 返回 '1.000'
|
|
712
|
+
```
|
|
713
|
+
* @param {*} val 小数
|
|
714
|
+
* @param {number} [pos=2] 保留的小数位
|
|
715
|
+
*/
|
|
716
|
+
function formatFloat(val, pos) {
|
|
717
|
+
if (pos === void 0) { pos = 2; }
|
|
718
|
+
var f = parseFloat(String(val));
|
|
719
|
+
if (Number.isNaN(f)) {
|
|
720
|
+
return '';
|
|
721
|
+
}
|
|
722
|
+
f = Math.round(Number(val) * Math.pow(10, pos)) / Math.pow(10, pos); // pow 幂
|
|
723
|
+
var s = f.toString();
|
|
724
|
+
var rs = s.indexOf('.');
|
|
725
|
+
if (rs < 0) {
|
|
726
|
+
rs = s.length;
|
|
727
|
+
s += '.';
|
|
728
|
+
}
|
|
729
|
+
while (s.length <= rs + pos) {
|
|
730
|
+
s += '0';
|
|
731
|
+
}
|
|
732
|
+
return s;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* 向上取整
|
|
736
|
+
#### 使用说明
|
|
737
|
+
```
|
|
738
|
+
ceil('1.23') 返回 2
|
|
739
|
+
ceil('1.234', 2) 返回 1.24
|
|
740
|
+
ceil('1.230', 2) 返回 1.23
|
|
741
|
+
```
|
|
742
|
+
* @param {*} val
|
|
743
|
+
* @param {number} [pos=2] 保留的小数位
|
|
744
|
+
*/
|
|
745
|
+
function ceil(val, pos) {
|
|
746
|
+
if (pos === void 0) { pos = 0; }
|
|
747
|
+
if (isEmpty(val)) {
|
|
748
|
+
return val;
|
|
749
|
+
}
|
|
750
|
+
var swell = Math.pow(10, pos);
|
|
751
|
+
var swellVal = Number(val) * swell;
|
|
752
|
+
var newVal = Math.ceil(swellVal) / swell;
|
|
753
|
+
return newVal;
|
|
754
|
+
}
|
|
755
|
+
/**
|
|
756
|
+
* 向下取整
|
|
757
|
+
#### 使用说明
|
|
758
|
+
```
|
|
759
|
+
floor('1.23') 返回 1
|
|
760
|
+
floor('1.234', 2) 返回 1.23
|
|
761
|
+
floor('1.230', 2) 返回 1.23
|
|
762
|
+
```
|
|
763
|
+
* @param {*} val
|
|
764
|
+
* @param {number} [pos=2] 保留的小数位
|
|
765
|
+
*/
|
|
766
|
+
function floor(val, pos) {
|
|
767
|
+
if (pos === void 0) { pos = 0; }
|
|
768
|
+
if (isEmpty(val)) {
|
|
769
|
+
return val;
|
|
770
|
+
}
|
|
771
|
+
var swell = Math.pow(10, pos);
|
|
772
|
+
var swellVal = Number(val) * swell;
|
|
773
|
+
return Math.floor(swellVal) / swell;
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* 格式化货币数字
|
|
777
|
+
#### 使用说明
|
|
778
|
+
```
|
|
779
|
+
formatMoney(1234) 返回 '12.34'
|
|
780
|
+
formatMoney(1234, { operation: 'multiply', factor: 100 }) 返回 '123400.00'
|
|
781
|
+
formatMoney(1234, { formatAsCurrency: true }) 返回 '¥12.34'
|
|
782
|
+
formatMoney(1234, { formatAsCurrency: true, currencySymbol: '$' }) 返回 '$12.34'
|
|
783
|
+
formatMoney(1234.567, { precision: 3 }) 返回 '12.346'
|
|
784
|
+
formatMoney('1,234.56', { operation: 'multiply', factor: 1 }) 返回 '1234.56'
|
|
785
|
+
```
|
|
786
|
+
* @param value 要格式化的值
|
|
787
|
+
* @param options 格式化选项
|
|
788
|
+
* @returns 格式化后的字符串
|
|
789
|
+
*/
|
|
790
|
+
function formatMoney(value, options) {
|
|
791
|
+
// 先计算值
|
|
792
|
+
var numericResult = computeMoney(value, options);
|
|
793
|
+
// 合并选项
|
|
794
|
+
var mergedOptions = __assign(__assign({}, DEFAULT_MONEY_OPTIONS), options);
|
|
795
|
+
// 格式化
|
|
796
|
+
if (mergedOptions.formatter) {
|
|
797
|
+
// 使用自定义格式化函数
|
|
798
|
+
return mergedOptions.formatter(numericResult);
|
|
799
|
+
}
|
|
800
|
+
// 货币格式化
|
|
801
|
+
if (mergedOptions.formatAsCurrency) {
|
|
802
|
+
var formattedNumber = numericResult.toFixed(mergedOptions.precision);
|
|
803
|
+
// 如果数字超过1000,使用千分位格式化
|
|
804
|
+
var formattedWithThousands = numericResult >= 1000 ? toThousands(formattedNumber) : formattedNumber;
|
|
805
|
+
return "" + mergedOptions.currencySymbol + formattedWithThousands;
|
|
806
|
+
}
|
|
807
|
+
// 默认格式化
|
|
808
|
+
return numericResult.toFixed(mergedOptions.precision);
|
|
809
|
+
}
|
|
810
|
+
/**
|
|
811
|
+
* 执行货币计算
|
|
812
|
+
#### 使用说明
|
|
813
|
+
```
|
|
814
|
+
分转元(除法)
|
|
815
|
+
computeMoney(1234) 返回 12.34
|
|
816
|
+
元转分(乘法)
|
|
817
|
+
computeMoney(12.34, { operation: 'multiply', factor: 100 }) 返回 1234
|
|
818
|
+
自定义精度
|
|
819
|
+
computeMoney(1234.567, { precision: 3 }) 返回 12.346
|
|
820
|
+
处理带有千分位的字符串
|
|
821
|
+
computeMoney('1,234.56', { operation: 'multiply', factor: 1 }) 返回 1234.56
|
|
822
|
+
处理空值
|
|
823
|
+
computeMoney(null) 返回 0
|
|
824
|
+
```
|
|
825
|
+
* @param value 要计算的值
|
|
826
|
+
* @param options 计算选项
|
|
827
|
+
* @returns 计算结果
|
|
828
|
+
*/
|
|
829
|
+
function computeMoney(value, options) {
|
|
830
|
+
// 合并选项
|
|
831
|
+
var mergedOptions = __assign(__assign({}, DEFAULT_MONEY_OPTIONS), options);
|
|
832
|
+
// 处理输入值
|
|
833
|
+
var numericValue;
|
|
834
|
+
// 处理可能的各种输入类型
|
|
835
|
+
if (value === null || value === undefined || value === '') {
|
|
836
|
+
return 0;
|
|
837
|
+
}
|
|
838
|
+
else if (typeof value === 'string') {
|
|
839
|
+
// 尝试将字符串转换为数字,移除非数字字符(保留小数点和负号)
|
|
840
|
+
var cleanedStr = value.replace(/[^\d.-]/g, '');
|
|
841
|
+
numericValue = cleanedStr ? parseFloat(cleanedStr) : 0;
|
|
842
|
+
}
|
|
843
|
+
else {
|
|
844
|
+
numericValue = value;
|
|
845
|
+
}
|
|
846
|
+
if (isNaN(numericValue)) {
|
|
847
|
+
return 0;
|
|
848
|
+
}
|
|
849
|
+
// 执行计算
|
|
850
|
+
var result;
|
|
851
|
+
if (mergedOptions.operation === 'multiply') {
|
|
852
|
+
result = numericValue * mergedOptions.factor;
|
|
853
|
+
}
|
|
854
|
+
else {
|
|
855
|
+
// 防止除以0
|
|
856
|
+
result = mergedOptions.factor !== 0 ? numericValue / mergedOptions.factor : 0;
|
|
857
|
+
}
|
|
858
|
+
// 处理精度
|
|
859
|
+
if (mergedOptions.precision !== undefined) {
|
|
860
|
+
var multiplier = Math.pow(10, mergedOptions.precision);
|
|
861
|
+
result = Math.round(result * multiplier) / multiplier;
|
|
862
|
+
}
|
|
863
|
+
return result;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* 将分转换为元并格式化为货币格式
|
|
867
|
+
#### 使用说明
|
|
868
|
+
```
|
|
869
|
+
formatCentsToYuan(1234) 返回 '¥12.34'
|
|
870
|
+
formatCentsToYuan(123456) 返回 '¥1,234.56'
|
|
871
|
+
formatCentsToYuan(1234, { currencySymbol: '$' }) 返回 '$12.34'
|
|
872
|
+
formatCentsToYuan('1,234', { precision: 3 }) 返回 '¥12.340'
|
|
873
|
+
formatCentsToYuan(null) 返回 '¥0.00'
|
|
874
|
+
```
|
|
875
|
+
* @param cents 分值
|
|
876
|
+
* @param options 格式化选项
|
|
877
|
+
* @returns 格式化后的字符串
|
|
878
|
+
*/
|
|
879
|
+
function formatCentsToYuan(cents, options) {
|
|
880
|
+
return formatMoney(cents, __assign({ operation: 'divide', factor: 100, formatAsCurrency: true }, options));
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
/**
|
|
884
|
+
* 文件处理相关
|
|
885
|
+
* @packageDocumentation
|
|
886
|
+
* @module File
|
|
887
|
+
* @preferred
|
|
888
|
+
*/
|
|
889
|
+
/**
|
|
890
|
+
* 计算文件大小
|
|
891
|
+
#### 使用说明
|
|
892
|
+
```
|
|
893
|
+
calcFileSize(100) 返回 { size: 100, unit: 'B' }
|
|
894
|
+
calcFileSize(1024) 返回 { size: 1, unit: 'KB' }
|
|
895
|
+
calcFileSize(1024, 'KB') 返回 { size: 1, unit: 'MB' }
|
|
896
|
+
calcFileSize(1126.4, 'mb') 返回 { size: 1.1, unit: 'GB' }
|
|
897
|
+
calcFileSize(Math.pow(1024, 2), 'kb') 返回 { size: 1, unit: 'GB' }
|
|
898
|
+
```
|
|
899
|
+
* @param size 单位 k
|
|
900
|
+
* @returns number
|
|
901
|
+
*/
|
|
902
|
+
function calcFileSize(size, unit) {
|
|
903
|
+
if (unit === void 0) { unit = 'B'; }
|
|
904
|
+
var unitList = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
905
|
+
var currentUnitIndex = unitList.indexOf(unit.toUpperCase());
|
|
906
|
+
currentUnitIndex = currentUnitIndex === -1 ? 0 : currentUnitIndex;
|
|
907
|
+
// todo 单位换算。
|
|
908
|
+
while (size >= 1024 && currentUnitIndex < unitList.length) {
|
|
909
|
+
size = size / 1024;
|
|
910
|
+
currentUnitIndex += 1;
|
|
911
|
+
}
|
|
912
|
+
return {
|
|
913
|
+
size: size,
|
|
914
|
+
unit: unitList[currentUnitIndex],
|
|
915
|
+
};
|
|
916
|
+
}
|
|
917
|
+
/**
|
|
918
|
+
* 文件大小转换
|
|
919
|
+
#### 使用说明
|
|
920
|
+
```
|
|
921
|
+
fileSizeFormat('') 返回 -
|
|
922
|
+
fileSizeFormat('1024') 返回 1KB
|
|
923
|
+
fileSizeFormat('1024', 'KB') 返回 1MB
|
|
924
|
+
fileSizeFormat('2645', 'B') 返回 ceil(2645 / 1024, 2)MB
|
|
925
|
+
```
|
|
926
|
+
* @param {string} str 字符串 单位k
|
|
927
|
+
*/
|
|
928
|
+
function fileSizeFormat(str, unit, defaultValue) {
|
|
929
|
+
if (unit === void 0) { unit = 'B'; }
|
|
930
|
+
if (defaultValue === void 0) { defaultValue = '-'; }
|
|
931
|
+
if (isEmpty(str)) {
|
|
932
|
+
return defaultValue;
|
|
933
|
+
}
|
|
934
|
+
var o = calcFileSize(parseFloat(str.toString()), unit);
|
|
935
|
+
return "" + ceil(o.size, 2) + o.unit;
|
|
936
|
+
}
|
|
937
|
+
/**
|
|
938
|
+
* base64转换为file
|
|
939
|
+
* dataurl base64图片
|
|
940
|
+
* */
|
|
941
|
+
function dataURLtoBlob(dataurl) {
|
|
942
|
+
var mime = dataurl.match(/:(.*?);/)[1];
|
|
943
|
+
var bytes = window.atob(dataurl.split(',')[1]); // 去掉url的头,并转换为byte
|
|
944
|
+
// 处理异常,将ascii码小于0的转换为大于0
|
|
945
|
+
var ab = new ArrayBuffer(bytes.length);
|
|
946
|
+
var ia = new Uint8Array(ab);
|
|
947
|
+
for (var i = 0; i < bytes.length; i += 1) {
|
|
948
|
+
ia[i] = bytes.charCodeAt(i);
|
|
949
|
+
}
|
|
950
|
+
return new Blob([ab], { type: mime });
|
|
951
|
+
}
|
|
952
|
+
function blobToDataURL(blob) {
|
|
953
|
+
return new Promise(function (resolve, reject) {
|
|
954
|
+
var reader = new FileReader();
|
|
955
|
+
reader.onload = function (e) {
|
|
956
|
+
if (!e || !e.target) {
|
|
957
|
+
reject(e);
|
|
958
|
+
}
|
|
959
|
+
else {
|
|
960
|
+
resolve(e.target.result);
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
reader.onerror = function (err) {
|
|
964
|
+
reject(err);
|
|
965
|
+
};
|
|
966
|
+
reader.readAsDataURL(blob);
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
/**
|
|
970
|
+
* 压缩图片方法
|
|
971
|
+
* @param file 图片
|
|
972
|
+
* @param scaleCallback 宽高 压缩规则
|
|
973
|
+
* @param qualityCallback 质量 压缩规则
|
|
974
|
+
*/
|
|
975
|
+
function compressImg(file, scaleCallback, qualityCallback) {
|
|
976
|
+
return new Promise(function (resolve, reject) {
|
|
977
|
+
var fileSize = parseFloat((file.size / 1024 / 1024).toString());
|
|
978
|
+
var read = new FileReader();
|
|
979
|
+
read.onload = function (e) {
|
|
980
|
+
var img = new Image();
|
|
981
|
+
img.onload = function () {
|
|
982
|
+
// 读取图片宽高
|
|
983
|
+
var w = img.width;
|
|
984
|
+
var h = img.height;
|
|
985
|
+
// 生成canvas
|
|
986
|
+
var canvas = document.createElement('canvas');
|
|
987
|
+
var ctx = canvas.getContext('2d');
|
|
988
|
+
// 处理函数返回的不是 number & NaN 类型的情况
|
|
989
|
+
var scale = scaleCallback ? scaleCallback(w, h) : 1;
|
|
990
|
+
if (Number.isNaN(scale) || typeof scale !== 'number') {
|
|
991
|
+
scale = 1;
|
|
992
|
+
}
|
|
993
|
+
var quality = qualityCallback ? qualityCallback(fileSize, scale, w, h) : 1;
|
|
994
|
+
if (Number.isNaN(quality) || typeof quality !== 'number') {
|
|
995
|
+
quality = 1;
|
|
996
|
+
}
|
|
997
|
+
// 图片 缩放规则
|
|
998
|
+
if (ctx) {
|
|
999
|
+
var scaleW = parseInt((w * scale).toString(), 10);
|
|
1000
|
+
var scaleH = parseInt((h * scale).toString(), 10);
|
|
1001
|
+
// 创建属性节点
|
|
1002
|
+
canvas.setAttribute('width', scaleW.toString());
|
|
1003
|
+
canvas.setAttribute('height', scaleH.toString());
|
|
1004
|
+
ctx.drawImage(img, 0, 0, scaleW, scaleH);
|
|
1005
|
+
}
|
|
1006
|
+
// 图片质量 压缩
|
|
1007
|
+
var base64 = canvas.toDataURL(file.type, quality);
|
|
1008
|
+
resolve(dataURLtoBlob(base64));
|
|
1009
|
+
};
|
|
1010
|
+
img.onerror = function (evt) {
|
|
1011
|
+
reject(evt);
|
|
1012
|
+
};
|
|
1013
|
+
if (e.target) {
|
|
1014
|
+
img.src = e.target.result;
|
|
1015
|
+
}
|
|
1016
|
+
};
|
|
1017
|
+
read.onerror = function (e) {
|
|
1018
|
+
reject(e);
|
|
1019
|
+
};
|
|
1020
|
+
read.readAsDataURL(file);
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
/**
|
|
1024
|
+
* 生成导出函数
|
|
1025
|
+
*/
|
|
1026
|
+
function genExportByBlob(_a) {
|
|
1027
|
+
var axiosRequest = _a.axiosRequest, _b = _a.notWithCredentials, notWithCredentials = _b === void 0 ? [] : _b;
|
|
1028
|
+
return function exportByBlob(config) {
|
|
1029
|
+
var _this = this;
|
|
1030
|
+
var filename = config.filename;
|
|
1031
|
+
var url = config.url, _a = config.data, data = _a === void 0 ? {} : _a, _b = config.params, params = _b === void 0 ? {} : _b, _c = config.method, method = _c === void 0 ? 'post' : _c;
|
|
1032
|
+
return new Promise(function (resolve, reject) {
|
|
1033
|
+
axiosRequest({
|
|
1034
|
+
method: method,
|
|
1035
|
+
url: url,
|
|
1036
|
+
data: data,
|
|
1037
|
+
params: params,
|
|
1038
|
+
responseType: 'blob',
|
|
1039
|
+
config: {
|
|
1040
|
+
withCredentials: notWithCredentials.some(function (str) {
|
|
1041
|
+
return !url.includes(str);
|
|
1042
|
+
}),
|
|
1043
|
+
},
|
|
1044
|
+
}).then(function (res) { return __awaiter(_this, void 0, void 0, function () {
|
|
1045
|
+
var response, reader_1, headers, contentDisposition, responseFilename, splitFileName, suffix, blob, downloadElement, href;
|
|
1046
|
+
return __generator(this, function (_a) {
|
|
1047
|
+
switch (_a.label) {
|
|
1048
|
+
case 0:
|
|
1049
|
+
response = res === null || res === void 0 ? void 0 : res.data;
|
|
1050
|
+
if (!(response.type === 'application/json')) return [3 /*break*/, 1];
|
|
1051
|
+
reader_1 = new FileReader();
|
|
1052
|
+
reader_1.readAsText(response, 'utf-8');
|
|
1053
|
+
reader_1.onload = function () {
|
|
1054
|
+
var result = {};
|
|
1055
|
+
try {
|
|
1056
|
+
result = JSON.parse(reader_1.result);
|
|
1057
|
+
}
|
|
1058
|
+
catch (e) {
|
|
1059
|
+
result = response;
|
|
1060
|
+
}
|
|
1061
|
+
// Message.error((result && result.message) || '导出失败');
|
|
1062
|
+
reject(result);
|
|
1063
|
+
};
|
|
1064
|
+
return [3 /*break*/, 3];
|
|
1065
|
+
case 1:
|
|
1066
|
+
try {
|
|
1067
|
+
headers = res.headers;
|
|
1068
|
+
contentDisposition = headers['content-disposition'];
|
|
1069
|
+
responseFilename = decodeURIComponent(contentDisposition.split(';')[1].split('filename=')[1]);
|
|
1070
|
+
// 有传文件名称&不带后缀 使用服务端的文件拓展名
|
|
1071
|
+
if (filename && !filename.includes('.')) {
|
|
1072
|
+
splitFileName = responseFilename.split('.');
|
|
1073
|
+
suffix = splitFileName[splitFileName.length - 1];
|
|
1074
|
+
filename += "." + suffix;
|
|
1075
|
+
}
|
|
1076
|
+
else if (!filename) {
|
|
1077
|
+
filename = responseFilename;
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
catch (e) {
|
|
1081
|
+
// 默认名称
|
|
1082
|
+
if (!filename) {
|
|
1083
|
+
filename = 'download.xlsx';
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
blob = new Blob([res.data]);
|
|
1087
|
+
downloadElement = document.createElement('a');
|
|
1088
|
+
return [4 /*yield*/, blobToDataURL(blob)];
|
|
1089
|
+
case 2:
|
|
1090
|
+
href = _a.sent();
|
|
1091
|
+
downloadElement.href = href;
|
|
1092
|
+
downloadElement.download = filename;
|
|
1093
|
+
document.body.appendChild(downloadElement);
|
|
1094
|
+
downloadElement.click(); // 点击下载
|
|
1095
|
+
document.body.removeChild(downloadElement); // 下载完成移除元素
|
|
1096
|
+
// window.URL.revokeObjectURL(href);
|
|
1097
|
+
resolve(res);
|
|
1098
|
+
_a.label = 3;
|
|
1099
|
+
case 3: return [2 /*return*/];
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
}); }).catch(function (e) {
|
|
1103
|
+
reject(e);
|
|
1104
|
+
});
|
|
1105
|
+
});
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
/**
|
|
1109
|
+
* 将 base64 字符串转换为 File 或 Blob
|
|
1110
|
+
* @param {string} base64 - 带有 data URI 的 base64 字符串
|
|
1111
|
+
* @param {string} [filename] - 如果提供了,则返回 File;否则返回 Blob
|
|
1112
|
+
* @returns {File|Blob}
|
|
1113
|
+
*/
|
|
1114
|
+
function base64ToFileOrBlob(base64, filename) {
|
|
1115
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1116
|
+
var _a, meta, content, mime, bstr, len, u8arr, i;
|
|
1117
|
+
return __generator(this, function (_b) {
|
|
1118
|
+
_a = base64.split(','), meta = _a[0], content = _a[1];
|
|
1119
|
+
mime = meta.match(/:(.*?);/)[1];
|
|
1120
|
+
bstr = atob(content);
|
|
1121
|
+
len = bstr.length;
|
|
1122
|
+
u8arr = new Uint8Array(len);
|
|
1123
|
+
for (i = 0; i < len; i++) {
|
|
1124
|
+
u8arr[i] = bstr.charCodeAt(i);
|
|
1125
|
+
}
|
|
1126
|
+
if (filename) {
|
|
1127
|
+
return [2 /*return*/, new File([u8arr], filename, { type: mime })];
|
|
1128
|
+
}
|
|
1129
|
+
else {
|
|
1130
|
+
return [2 /*return*/, new Blob([u8arr], { type: mime })];
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
/**
|
|
1137
|
+
* object处理相关
|
|
1138
|
+
* @packageDocumentation
|
|
1139
|
+
* @module Object
|
|
1140
|
+
* @preferred
|
|
1141
|
+
*/
|
|
1142
|
+
/**
|
|
1143
|
+
* 比较两者的值是否相等
|
|
1144
|
+
#### 使用说明
|
|
1145
|
+
```
|
|
1146
|
+
deepEqual({a: 10}, {a: 10}) 返回 true
|
|
1147
|
+
deepEqual({a: 10}, {a: 10, b: 20}) 返回 false
|
|
1148
|
+
```
|
|
1149
|
+
* @param {*} x 用来比较的值
|
|
1150
|
+
* @param {*} y 另一个用来比较的值
|
|
1151
|
+
*/
|
|
1152
|
+
function deepEqual(x, y) {
|
|
1153
|
+
var ok = Object.keys, tx = typeof x, ty = typeof y;
|
|
1154
|
+
return x && y && tx === 'object' && tx === ty
|
|
1155
|
+
? ok(x).length === ok(y).length && ok(x).every(function (key) { return deepEqual(x[key], y[key]); })
|
|
1156
|
+
: x === y;
|
|
1157
|
+
}
|
|
1158
|
+
function getNodePath(node, nodeValue, nodeKey, childrenKey, path) {
|
|
1159
|
+
if (path === void 0) { path = []; }
|
|
1160
|
+
path.push(node);
|
|
1161
|
+
if (node[nodeKey] === nodeValue) {
|
|
1162
|
+
throw 'GOT IT!';
|
|
1163
|
+
}
|
|
1164
|
+
if (node[childrenKey] && node[childrenKey].length > 0) {
|
|
1165
|
+
for (var i = 0; i < node[childrenKey].length; i++) {
|
|
1166
|
+
getNodePath(node[childrenKey][i], nodeValue, nodeKey, childrenKey, path);
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
path.pop();
|
|
1170
|
+
}
|
|
1171
|
+
/**
|
|
1172
|
+
* 查找树结构节点路径
|
|
1173
|
+
* @param {*} nodeValue 节点值
|
|
1174
|
+
* @param {string} nodeKey 节点键
|
|
1175
|
+
* @param {Array} treeArray 树数据
|
|
1176
|
+
* @param {string} children 子集键
|
|
1177
|
+
*/
|
|
1178
|
+
function findNodePath(nodeValue, nodeKey, treeArray, childrenKey) {
|
|
1179
|
+
var path = [];
|
|
1180
|
+
try {
|
|
1181
|
+
for (var i = 0; i < treeArray.length; i++) {
|
|
1182
|
+
getNodePath(treeArray[i], nodeValue, nodeKey, childrenKey, path);
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
catch (e) {
|
|
1186
|
+
return path;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
/**
|
|
1191
|
+
* validate处理相关
|
|
1192
|
+
* @packageDocumentation
|
|
1193
|
+
* @module Validate
|
|
1194
|
+
* @preferred
|
|
1195
|
+
*/
|
|
1196
|
+
/** 是否是外部网址
|
|
1197
|
+
* @param {string} path
|
|
1198
|
+
* @returns {Boolean}
|
|
1199
|
+
*/
|
|
1200
|
+
function isExternal(path) {
|
|
1201
|
+
return /^(https?:|mailto:|tel:)/.test(path);
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* 去掉前后空格
|
|
1205
|
+
* @param {*} str
|
|
1206
|
+
*/
|
|
1207
|
+
function trimVal(str) {
|
|
1208
|
+
if (!str) {
|
|
1209
|
+
return str;
|
|
1210
|
+
}
|
|
1211
|
+
var reg = /^\s+|\s+$/g;
|
|
1212
|
+
return str.replace(reg, '');
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* 校验 手机
|
|
1216
|
+
* @param {*} val
|
|
1217
|
+
*/
|
|
1218
|
+
function isMobile(val) {
|
|
1219
|
+
var reg = /^0?(13[0-9]|14[5-9]|15[012356789]|166|17[0-8]|18[0-9]|19[8-9])[0-9]{8}$/;
|
|
1220
|
+
return reg.test(val.toString());
|
|
1221
|
+
}
|
|
1222
|
+
/**
|
|
1223
|
+
* 校验 手机
|
|
1224
|
+
* 规则: 以1为开头,总共11位数
|
|
1225
|
+
* @export
|
|
1226
|
+
* @param {*} val
|
|
1227
|
+
* @returns
|
|
1228
|
+
*/
|
|
1229
|
+
function isMobileSimple(val) {
|
|
1230
|
+
var reg = /^1/;
|
|
1231
|
+
val = val.toString();
|
|
1232
|
+
return reg.test(val) && val.length === 11;
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* 校验 固定电话
|
|
1236
|
+
* 规则: 必须带区号
|
|
1237
|
+
* @param {*} val
|
|
1238
|
+
*/
|
|
1239
|
+
function isTelephone(val) {
|
|
1240
|
+
var reg = /^0[1-9][0-9]{1,2}-[2-8][0-9]{6,7}$/;
|
|
1241
|
+
return reg.test(String(val));
|
|
1242
|
+
}
|
|
1243
|
+
/**
|
|
1244
|
+
* 校验 邮箱
|
|
1245
|
+
* @param {*} val
|
|
1246
|
+
*/
|
|
1247
|
+
function isEmail(val) {
|
|
1248
|
+
/* eslint-disable no-useless-escape */
|
|
1249
|
+
var reg = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
|
|
1250
|
+
return reg.test(val);
|
|
1251
|
+
}
|
|
1252
|
+
/**
|
|
1253
|
+
* 校验 QQ
|
|
1254
|
+
* @param {*} val
|
|
1255
|
+
*/
|
|
1256
|
+
function isQQ(val) {
|
|
1257
|
+
var reg = /^[1-9][0-9]{4,9}$/gim;
|
|
1258
|
+
return reg.test(String(val));
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* 校验是否为有效的中国大陆手机号(精确版)
|
|
1262
|
+
* @param value - 待验证的字符串
|
|
1263
|
+
* @returns 是否为有效手机号
|
|
1264
|
+
*/
|
|
1265
|
+
function isPhone(value) {
|
|
1266
|
+
return /^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$/.test(value);
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* 验证是否为有效的 URL
|
|
1270
|
+
* @param value - 待验证的字符串
|
|
1271
|
+
* @returns 是否为有效 URL
|
|
1272
|
+
*/
|
|
1273
|
+
function isUrl(value) {
|
|
1274
|
+
var pattern = '^(?:(https?|ftp|rtsp|mms|ws|wss):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?:localhost)|(?:[1-9]\\d{0,2}(?:\\.\\d{1,3}){3})|(?:$[0-9a-fA-F:]+$)|(?:(?:[a-zA-Z0-9-_]+\\.)+[a-zA-Z]{2,63}))(?::\\d{1,5})?(?:[/?#]\\S*)?$';
|
|
1275
|
+
return new RegExp(pattern, 'i').test(value);
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
/**
|
|
1279
|
+
* string处理相关
|
|
1280
|
+
* @packageDocumentation
|
|
1281
|
+
* @module String
|
|
1282
|
+
* @preferred
|
|
1283
|
+
*/
|
|
1284
|
+
/**
|
|
1285
|
+
* 空值处理
|
|
1286
|
+
*/
|
|
1287
|
+
function formatEmptyValue(value, defaultValue) {
|
|
1288
|
+
if (defaultValue === void 0) { defaultValue = '-'; }
|
|
1289
|
+
if (isEmpty(value)) {
|
|
1290
|
+
return defaultValue;
|
|
1291
|
+
}
|
|
1292
|
+
return value;
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* 格式化手机
|
|
1296
|
+
#### 使用说明
|
|
1297
|
+
* ```
|
|
1298
|
+
* formatPhone('18211572781') => '182 1157 2781'
|
|
1299
|
+
* formatPhone('18211572781', '-') => '182-1157-2781'
|
|
1300
|
+
* ```
|
|
1301
|
+
* @param {string | number} phone 手机号
|
|
1302
|
+
* @param {string} [separator=' '] 连接符
|
|
1303
|
+
*/
|
|
1304
|
+
function formatPhone(phone, separator, defaultValue) {
|
|
1305
|
+
if (separator === void 0) { separator = ' '; }
|
|
1306
|
+
if (defaultValue === void 0) { defaultValue = '-'; }
|
|
1307
|
+
if (isEmpty(phone)) {
|
|
1308
|
+
return defaultValue;
|
|
1309
|
+
}
|
|
1310
|
+
if (phone.toString().length !== 11) {
|
|
1311
|
+
return phone;
|
|
1312
|
+
}
|
|
1313
|
+
var val = phone.toString().replace(/[^\d]/g, '');
|
|
1314
|
+
var arr = val.split('');
|
|
1315
|
+
var str = '';
|
|
1316
|
+
arr.forEach(function (v, index) {
|
|
1317
|
+
if (index === 3 || index === 7) {
|
|
1318
|
+
str += separator;
|
|
1319
|
+
}
|
|
1320
|
+
str += v;
|
|
1321
|
+
});
|
|
1322
|
+
return str;
|
|
1323
|
+
}
|
|
1324
|
+
/**
|
|
1325
|
+
* 隐藏手机号
|
|
1326
|
+
#### 使用说明
|
|
1327
|
+
* ```
|
|
1328
|
+
* formatPhoneHide('18211572781') => '182****2781'
|
|
1329
|
+
* formatPhoneHide('', '-') => '-'
|
|
1330
|
+
* ```
|
|
1331
|
+
* @param {string | number} phone 手机号
|
|
1332
|
+
* @param {string} defaultValue 没有值放回的默认值
|
|
1333
|
+
*/
|
|
1334
|
+
function formatPhoneHide(phone, defaultValue) {
|
|
1335
|
+
if (defaultValue === void 0) { defaultValue = ''; }
|
|
1336
|
+
if (isEmpty(phone)) {
|
|
1337
|
+
return defaultValue;
|
|
1338
|
+
}
|
|
1339
|
+
if (phone.toString().length !== 11) {
|
|
1340
|
+
return phone;
|
|
1341
|
+
}
|
|
1342
|
+
var phoneNumber = phone.toString();
|
|
1343
|
+
return phoneNumber.substr(0, 3) + "****" + phoneNumber.substr(7, 11);
|
|
1344
|
+
}
|
|
1345
|
+
/**
|
|
1346
|
+
* 格式化银行卡 (4位一空格)
|
|
1347
|
+
#### 使用说明
|
|
1348
|
+
* ```
|
|
1349
|
+
* formatBank('6282356862823568123') => '6282 3568 6282 3568 123'
|
|
1350
|
+
* formatBank('', '-') => '-'
|
|
1351
|
+
* ```
|
|
1352
|
+
* @param {strubg | number} val 银行卡号
|
|
1353
|
+
* @param {string} defaultValue 没有值放回的默认值
|
|
1354
|
+
*/
|
|
1355
|
+
function formatBank(val, defaultValue) {
|
|
1356
|
+
if (defaultValue === void 0) { defaultValue = ''; }
|
|
1357
|
+
if (isEmpty(val)) {
|
|
1358
|
+
return defaultValue;
|
|
1359
|
+
}
|
|
1360
|
+
return val.toString().replace(/\s/g, '').replace(/(.{4})/g, '$1 ');
|
|
1361
|
+
}
|
|
1362
|
+
/**
|
|
1363
|
+
* 生成26个字母列表
|
|
1364
|
+
#### 使用说明
|
|
1365
|
+
* ```
|
|
1366
|
+
* generateEnglishLetters() => ['A', ..., 'Z'];
|
|
1367
|
+
* ```
|
|
1368
|
+
*/
|
|
1369
|
+
function generateEnglishLetters() {
|
|
1370
|
+
var englishLettersList = [];
|
|
1371
|
+
for (var i = 65; i < 91; i += 1) {
|
|
1372
|
+
englishLettersList.push(String.fromCharCode(i));
|
|
1373
|
+
}
|
|
1374
|
+
return englishLettersList;
|
|
1375
|
+
}
|
|
1376
|
+
/**
|
|
1377
|
+
* 驼峰式命名转短横线命名
|
|
1378
|
+
*
|
|
1379
|
+
* @export
|
|
1380
|
+
* @param {*} [string='']
|
|
1381
|
+
* @returns
|
|
1382
|
+
*/
|
|
1383
|
+
function humpTurnDashed(string) {
|
|
1384
|
+
if (string === void 0) { string = ''; }
|
|
1385
|
+
var rE = /\B([A-Z])/g;
|
|
1386
|
+
return string.replace(rE, '-$1').toLowerCase();
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* 获取指定分隔符之前的子字符串
|
|
1390
|
+
* @param str - 源字符串
|
|
1391
|
+
* @param delimiter - 分隔符
|
|
1392
|
+
* @returns 分隔符之前的字符串
|
|
1393
|
+
*/
|
|
1394
|
+
function subBefore(str, delimiter) {
|
|
1395
|
+
if (!str || typeof delimiter !== 'string')
|
|
1396
|
+
return '';
|
|
1397
|
+
return str.substring(0, str.indexOf(delimiter));
|
|
1398
|
+
}
|
|
1399
|
+
/**
|
|
1400
|
+
* 解析 URL 查询参数为对象
|
|
1401
|
+
* @param url - URL 字符串
|
|
1402
|
+
* @returns 查询参数对象
|
|
1403
|
+
*/
|
|
1404
|
+
function getQueryMap(url) {
|
|
1405
|
+
var pattern = /^(?:(https?|ftp|rtsp|mms|ws|wss):\/\/)?/i;
|
|
1406
|
+
if (!pattern.test(url)) {
|
|
1407
|
+
console.error(url + "\u4E0D\u7B26\u5408\u8D85\u94FE\u63A5\u89C4\u8303");
|
|
1408
|
+
return {};
|
|
1409
|
+
}
|
|
1410
|
+
var queryIndex = url.indexOf('?');
|
|
1411
|
+
if (queryIndex === -1)
|
|
1412
|
+
return {};
|
|
1413
|
+
var queryString = url.slice(queryIndex + 1);
|
|
1414
|
+
var params = queryString.split('&');
|
|
1415
|
+
var result = {};
|
|
1416
|
+
for (var _i = 0, params_1 = params; _i < params_1.length; _i++) {
|
|
1417
|
+
var param = params_1[_i];
|
|
1418
|
+
var _a = param.split('='), key = _a[0], value = _a[1];
|
|
1419
|
+
if (key) {
|
|
1420
|
+
result[key] = value || '';
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
return result;
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* 隐藏字符串中指定位置的字符
|
|
1427
|
+
* @param text - 源字符串或数字
|
|
1428
|
+
* @param indexes - 要隐藏的位置索引数组或位置对象数组
|
|
1429
|
+
* @param mask - 掩码字符,默认为 '*'
|
|
1430
|
+
* @returns 处理后的字符串
|
|
1431
|
+
*/
|
|
1432
|
+
function hideTextAtIndex(text, indexes, mask) {
|
|
1433
|
+
if (mask === void 0) { mask = '*'; }
|
|
1434
|
+
if (typeof text === 'number') {
|
|
1435
|
+
text = text.toString();
|
|
1436
|
+
}
|
|
1437
|
+
if (!Array.isArray(indexes)) {
|
|
1438
|
+
indexes = [indexes];
|
|
1439
|
+
}
|
|
1440
|
+
var chars = text.split('');
|
|
1441
|
+
for (var _i = 0, indexes_1 = indexes; _i < indexes_1.length; _i++) {
|
|
1442
|
+
var index = indexes_1[_i];
|
|
1443
|
+
if (typeof index === 'object' && !Array.isArray(index)) {
|
|
1444
|
+
var start = index.start, end = index.end;
|
|
1445
|
+
if (start >= 0 && start < end && end < chars.length) {
|
|
1446
|
+
chars.fill(mask, start, end + 1);
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
else if (typeof index === 'number' && Number.isInteger(index) && index >= 0) {
|
|
1450
|
+
if (index < chars.length) {
|
|
1451
|
+
chars[index] = mask;
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
return chars.join('');
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
var httpEnum = {
|
|
1459
|
+
// http响应状态码
|
|
1460
|
+
HTTP_STATUS: {
|
|
1461
|
+
// 1xx,临时响应
|
|
1462
|
+
TEMP_RESPOND: {
|
|
1463
|
+
Continue: 100,
|
|
1464
|
+
SwitchingProtocal: 101 // 针对请求头的Upgrade返回的信息。表明服务器正在切换到指定的协议
|
|
1465
|
+
},
|
|
1466
|
+
// 2xx,成功
|
|
1467
|
+
SUCCESS: {
|
|
1468
|
+
Ok: 200,
|
|
1469
|
+
Created: 201,
|
|
1470
|
+
Accepted: 202,
|
|
1471
|
+
NoAuthoritativeInformation: 203,
|
|
1472
|
+
NoContent: 204,
|
|
1473
|
+
ResetContent: 205,
|
|
1474
|
+
ParticalContent: 206 // 客户端使用Range请求头时,返回该状态码
|
|
1475
|
+
},
|
|
1476
|
+
// 3xx,重定向
|
|
1477
|
+
REDIRECT: {
|
|
1478
|
+
MultipleChoice: 300,
|
|
1479
|
+
MovedPermanently: 301,
|
|
1480
|
+
Found: 302,
|
|
1481
|
+
SeeOther: 303,
|
|
1482
|
+
NotModified: 304,
|
|
1483
|
+
TemporaryRedirect: 307,
|
|
1484
|
+
PermanentRedirect: 308 // 永久重定向。基本和301相同。但是严格禁止修改请求方式和请求体。
|
|
1485
|
+
},
|
|
1486
|
+
// 4xx,请求错误
|
|
1487
|
+
REQUEST_ERROR: {
|
|
1488
|
+
BadRequest: 400,
|
|
1489
|
+
UnAuthorized: 401,
|
|
1490
|
+
Forbidden: 403,
|
|
1491
|
+
NotFound: 404,
|
|
1492
|
+
MethodNotAllowed: 405,
|
|
1493
|
+
NotAccepted: 406,
|
|
1494
|
+
ProxyAuthorizationRequired: 407,
|
|
1495
|
+
RequestTimeout: 408,
|
|
1496
|
+
UpgradeRequired: 426,
|
|
1497
|
+
TokenUnAuthorized: 499,
|
|
1498
|
+
},
|
|
1499
|
+
// 5xx,服务器错误
|
|
1500
|
+
SERVER_ERROR: {
|
|
1501
|
+
InternalServerError: 500,
|
|
1502
|
+
BadGateway: 502,
|
|
1503
|
+
ServiceUnavailable: 503,
|
|
1504
|
+
GateTimeout: 504,
|
|
1505
|
+
HttpVersionNotSupported: 505 // 发出的请求http版本服务器不支持。如果请求通过http2发送,服务器不支持http2.0,就会返回该状态码。
|
|
1506
|
+
}
|
|
1507
|
+
},
|
|
1508
|
+
// http状态码
|
|
1509
|
+
CODES: {
|
|
1510
|
+
Success: '00000',
|
|
1511
|
+
UnAuthorized: '00099',
|
|
1512
|
+
UnAuthorizedPhone: '11001',
|
|
1513
|
+
UnAuthorizedWecom: '11000',
|
|
1514
|
+
UnAuthorizedHavePhone: '11002',
|
|
1515
|
+
},
|
|
1516
|
+
// http状态码白名单,在具体业务中处理
|
|
1517
|
+
ERR_CODE_WHITE_LIST: []
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1520
|
+
var request = axios__default["default"].create({
|
|
1521
|
+
timeout: 15000,
|
|
1522
|
+
headers: {
|
|
1523
|
+
// 'Authorization': getToken(),
|
|
1524
|
+
"Content-Type": "application/json",
|
|
1525
|
+
},
|
|
1526
|
+
});
|
|
1527
|
+
// const requestArr = [request];
|
|
1528
|
+
/**
|
|
1529
|
+
* @param cacheType localStorage | sessionStorage | both
|
|
1530
|
+
* @param currentMode local | dev | test | prod 等自定义mode
|
|
1531
|
+
* @param errorCb 错误回调
|
|
1532
|
+
* @param getTokenCb 获取token的回调
|
|
1533
|
+
* @param tokenKey
|
|
1534
|
+
* */
|
|
1535
|
+
var http = function (_a) {
|
|
1536
|
+
var cacheType = _a.cacheType, currentMode = _a.currentMode, errorCb = _a.errorCb, getTokenCb = _a.getTokenCb, tokenKey = _a.tokenKey;
|
|
1537
|
+
request.interceptors.request.use(function (config) { return __awaiter(void 0, void 0, void 0, function () {
|
|
1538
|
+
var token, deviceType;
|
|
1539
|
+
return __generator(this, function (_a) {
|
|
1540
|
+
token = getToken(cacheType, tokenKey);
|
|
1541
|
+
deviceType = getDeviceType();
|
|
1542
|
+
config.headers.Authorization = token;
|
|
1543
|
+
config.headers.token = token;
|
|
1544
|
+
config.headers.FrontType = getFromType(deviceType);
|
|
1545
|
+
return [2 /*return*/, config];
|
|
1546
|
+
});
|
|
1547
|
+
}); }, function (error) {
|
|
1548
|
+
// do something with request error
|
|
1549
|
+
return Promise.reject(error);
|
|
1550
|
+
});
|
|
1551
|
+
// response interceptor
|
|
1552
|
+
request.interceptors.response.use(function (response) { return __awaiter(void 0, void 0, void 0, function () {
|
|
1553
|
+
var res, statusCode, errMsg;
|
|
1554
|
+
return __generator(this, function (_a) {
|
|
1555
|
+
res = response.data;
|
|
1556
|
+
statusCode = res.code || response.status;
|
|
1557
|
+
// blob文件流
|
|
1558
|
+
if (res instanceof Blob) {
|
|
1559
|
+
return [2 /*return*/, res];
|
|
1560
|
+
}
|
|
1561
|
+
// 成功
|
|
1562
|
+
if (statusCode === httpEnum.CODES.Success) {
|
|
1563
|
+
return [2 /*return*/, res];
|
|
1564
|
+
}
|
|
1565
|
+
// token失效
|
|
1566
|
+
if (statusCode === httpEnum.CODES.UnAuthorized) {
|
|
1567
|
+
if (currentMode !== "local" && currentMode !== "dev" && currentMode !== 'development') {
|
|
1568
|
+
removeToken(cacheType, tokenKey);
|
|
1569
|
+
if (getTokenCb && typeof getTokenCb === "function") {
|
|
1570
|
+
getTokenCb();
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
return [2 /*return*/, Promise.reject(new Error("token过期!"))];
|
|
1574
|
+
}
|
|
1575
|
+
errMsg = res.message || res.msg;
|
|
1576
|
+
return [2 /*return*/, Promise.reject(new Error(errMsg || "Error"))];
|
|
1577
|
+
});
|
|
1578
|
+
}); }, function (error) { return __awaiter(void 0, void 0, void 0, function () {
|
|
1579
|
+
return __generator(this, function (_a) {
|
|
1580
|
+
if (errorCb && typeof errorCb === "function") {
|
|
1581
|
+
errorCb(error);
|
|
1582
|
+
}
|
|
1583
|
+
return [2 /*return*/, Promise.reject(error)];
|
|
1584
|
+
});
|
|
1585
|
+
}); });
|
|
1586
|
+
return request;
|
|
1587
|
+
};
|
|
1588
|
+
|
|
1589
|
+
/**
|
|
1590
|
+
* API 请求参数构建工具
|
|
1591
|
+
* @description 用于快速组装后端 JSON 格式请求参数
|
|
1592
|
+
*/
|
|
1593
|
+
/**
|
|
1594
|
+
* API 构建器基类
|
|
1595
|
+
*/
|
|
1596
|
+
var BaseBuilder = /** @class */ (function () {
|
|
1597
|
+
function BaseBuilder(fieldCatalog) {
|
|
1598
|
+
this.fieldCatalog = fieldCatalog;
|
|
1599
|
+
// 只有传入 fieldCatalog 时才添加到 params
|
|
1600
|
+
this.params = (fieldCatalog ? { field_catalog: fieldCatalog } : {});
|
|
1601
|
+
}
|
|
1602
|
+
/**
|
|
1603
|
+
* 获取构建的参数
|
|
1604
|
+
*/
|
|
1605
|
+
BaseBuilder.prototype.build = function () {
|
|
1606
|
+
return this.params;
|
|
1607
|
+
};
|
|
1608
|
+
return BaseBuilder;
|
|
1609
|
+
}());
|
|
1610
|
+
/**
|
|
1611
|
+
* API 构建器主类
|
|
1612
|
+
*/
|
|
1613
|
+
var ApiBuilder = /** @class */ (function () {
|
|
1614
|
+
function ApiBuilder(fieldCatalog) {
|
|
1615
|
+
this.fieldCatalog = fieldCatalog;
|
|
1616
|
+
}
|
|
1617
|
+
/**
|
|
1618
|
+
* 创建查询请求构建器
|
|
1619
|
+
*/
|
|
1620
|
+
ApiBuilder.prototype.query = function () {
|
|
1621
|
+
return new QueryBuilder(this.fieldCatalog);
|
|
1622
|
+
};
|
|
1623
|
+
/**
|
|
1624
|
+
* 创建新增请求构建器
|
|
1625
|
+
*/
|
|
1626
|
+
ApiBuilder.prototype.insert = function () {
|
|
1627
|
+
return new InsertBuilder(this.fieldCatalog);
|
|
1628
|
+
};
|
|
1629
|
+
/**
|
|
1630
|
+
* 创建更新请求构建器
|
|
1631
|
+
*/
|
|
1632
|
+
ApiBuilder.prototype.update = function () {
|
|
1633
|
+
return new UpdateBuilder(this.fieldCatalog);
|
|
1634
|
+
};
|
|
1635
|
+
// 静态方法保持向后兼容
|
|
1636
|
+
ApiBuilder.query = function (fieldCatalog) {
|
|
1637
|
+
return new QueryBuilder(fieldCatalog);
|
|
1638
|
+
};
|
|
1639
|
+
ApiBuilder.insert = function (fieldCatalog) {
|
|
1640
|
+
return new InsertBuilder(fieldCatalog);
|
|
1641
|
+
};
|
|
1642
|
+
ApiBuilder.update = function (fieldCatalog) {
|
|
1643
|
+
return new UpdateBuilder(fieldCatalog);
|
|
1644
|
+
};
|
|
1645
|
+
return ApiBuilder;
|
|
1646
|
+
}());
|
|
1647
|
+
/**
|
|
1648
|
+
* 嵌套查询构建器类
|
|
1649
|
+
* 用于构建嵌套的过滤条件
|
|
1650
|
+
*/
|
|
1651
|
+
var NestedQueryBuilder = /** @class */ (function () {
|
|
1652
|
+
function NestedQueryBuilder(logic, parent) {
|
|
1653
|
+
this.parent = parent;
|
|
1654
|
+
this.nestedFilters = {
|
|
1655
|
+
logic: logic,
|
|
1656
|
+
filters: []
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
NestedQueryBuilder.prototype.where = function (fieldOrConditions, opOrValue, value) {
|
|
1660
|
+
var _this = this;
|
|
1661
|
+
// 对象形式: where({ user_id: 10086, status: 1 })
|
|
1662
|
+
if (typeof fieldOrConditions === 'object') {
|
|
1663
|
+
Object.entries(fieldOrConditions).forEach(function (_a) {
|
|
1664
|
+
var field = _a[0], val = _a[1];
|
|
1665
|
+
_this.nestedFilters.filters.push({ field: field, op: '=', value: val });
|
|
1666
|
+
});
|
|
1667
|
+
return this;
|
|
1668
|
+
}
|
|
1669
|
+
// 两参数形式: where('user_id', 10086) - 默认 =
|
|
1670
|
+
if (value === undefined) {
|
|
1671
|
+
this.nestedFilters.filters.push({ field: fieldOrConditions, op: '=', value: opOrValue });
|
|
1672
|
+
return this;
|
|
1673
|
+
}
|
|
1674
|
+
// 三参数形式: where('user_id', '=', 10086)
|
|
1675
|
+
this.nestedFilters.filters.push({ field: fieldOrConditions, op: opOrValue, value: value });
|
|
1676
|
+
return this;
|
|
1677
|
+
};
|
|
1678
|
+
/**
|
|
1679
|
+
* 在嵌套查询中添加另一个嵌套组
|
|
1680
|
+
*/
|
|
1681
|
+
NestedQueryBuilder.prototype.group = function (logic) {
|
|
1682
|
+
if (logic === void 0) { logic = 'and'; }
|
|
1683
|
+
return new NestedQueryBuilder(logic, this);
|
|
1684
|
+
};
|
|
1685
|
+
/**
|
|
1686
|
+
* 结束当前嵌套组并返回父查询构建器或父嵌套构建器
|
|
1687
|
+
*/
|
|
1688
|
+
NestedQueryBuilder.prototype.endGroup = function () {
|
|
1689
|
+
if (this.parent instanceof NestedQueryBuilder) {
|
|
1690
|
+
this.parent.addNestedFilters(this.nestedFilters);
|
|
1691
|
+
return this.parent;
|
|
1692
|
+
}
|
|
1693
|
+
else {
|
|
1694
|
+
this.parent.whereNested(this.nestedFilters);
|
|
1695
|
+
return this.parent;
|
|
1696
|
+
}
|
|
1697
|
+
};
|
|
1698
|
+
/**
|
|
1699
|
+
* 添加嵌套过滤条件到当前嵌套组
|
|
1700
|
+
*/
|
|
1701
|
+
NestedQueryBuilder.prototype.addNestedFilters = function (nestedFilters) {
|
|
1702
|
+
this.nestedFilters.filters.push(nestedFilters);
|
|
1703
|
+
};
|
|
1704
|
+
/**
|
|
1705
|
+
* 获取构建的嵌套过滤条件
|
|
1706
|
+
*/
|
|
1707
|
+
NestedQueryBuilder.prototype.build = function () {
|
|
1708
|
+
return this.nestedFilters;
|
|
1709
|
+
};
|
|
1710
|
+
return NestedQueryBuilder;
|
|
1711
|
+
}());
|
|
1712
|
+
/**
|
|
1713
|
+
* 查询构建器
|
|
1714
|
+
*/
|
|
1715
|
+
var QueryBuilder = /** @class */ (function (_super) {
|
|
1716
|
+
__extends(QueryBuilder, _super);
|
|
1717
|
+
function QueryBuilder(fieldCatalog) {
|
|
1718
|
+
var _this = _super.call(this, fieldCatalog) || this;
|
|
1719
|
+
_this.params = __assign(__assign({}, _this.params), { filters: { logic: 'and', filters: [] }, order_by: [], limit: 100, offset: 0 });
|
|
1720
|
+
return _this;
|
|
1721
|
+
}
|
|
1722
|
+
QueryBuilder.prototype.where = function (fieldOrConditions, opOrValue, value) {
|
|
1723
|
+
var _this = this;
|
|
1724
|
+
// 对象形式: where({ user_id: 10086, status: 1 })
|
|
1725
|
+
if (typeof fieldOrConditions === 'object') {
|
|
1726
|
+
Object.entries(fieldOrConditions).forEach(function (_a) {
|
|
1727
|
+
var field = _a[0], val = _a[1];
|
|
1728
|
+
_this.params.filters.filters.push({ field: field, op: '=', value: val });
|
|
1729
|
+
});
|
|
1730
|
+
return this;
|
|
1731
|
+
}
|
|
1732
|
+
// 两参数形式: where('user_id', 10086) - 默认 =
|
|
1733
|
+
if (value === undefined) {
|
|
1734
|
+
this.params.filters.filters.push({ field: fieldOrConditions, op: '=', value: opOrValue });
|
|
1735
|
+
return this;
|
|
1736
|
+
}
|
|
1737
|
+
// 三参数形式: where('user_id', '=', 10086)
|
|
1738
|
+
this.params.filters.filters.push({ field: fieldOrConditions, op: opOrValue, value: value });
|
|
1739
|
+
return this;
|
|
1740
|
+
};
|
|
1741
|
+
/**
|
|
1742
|
+
* 添加嵌套的 WHERE 条件
|
|
1743
|
+
* @param nestedFilters 嵌套的过滤条件
|
|
1744
|
+
*/
|
|
1745
|
+
QueryBuilder.prototype.whereNested = function (nestedFilters) {
|
|
1746
|
+
this.params.filters.filters.push(nestedFilters);
|
|
1747
|
+
return this;
|
|
1748
|
+
};
|
|
1749
|
+
/**
|
|
1750
|
+
* 创建并返回一个嵌套查询构建器,用于构建复杂的嵌套条件
|
|
1751
|
+
*/
|
|
1752
|
+
QueryBuilder.prototype.group = function (logic) {
|
|
1753
|
+
if (logic === void 0) { logic = 'and'; }
|
|
1754
|
+
return new NestedQueryBuilder(logic, this);
|
|
1755
|
+
};
|
|
1756
|
+
QueryBuilder.prototype.orWhere = function (fieldOrConditions, opOrValue, value) {
|
|
1757
|
+
var _a;
|
|
1758
|
+
// 创建一个新的 OR 组
|
|
1759
|
+
var orGroup = {
|
|
1760
|
+
logic: 'or',
|
|
1761
|
+
filters: []
|
|
1762
|
+
};
|
|
1763
|
+
// 对象形式: orWhere({ user_id: 10086, status: 1 })
|
|
1764
|
+
if (typeof fieldOrConditions === 'object') {
|
|
1765
|
+
Object.entries(fieldOrConditions).forEach(function (_a) {
|
|
1766
|
+
var field = _a[0], val = _a[1];
|
|
1767
|
+
orGroup.filters.push({ field: field, op: '=', value: val });
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
// 两参数形式: orWhere('user_id', 10086) - 默认 =
|
|
1771
|
+
else if (value === undefined) {
|
|
1772
|
+
orGroup.filters.push({ field: fieldOrConditions, op: '=', value: opOrValue });
|
|
1773
|
+
}
|
|
1774
|
+
// 三参数形式: orWhere('user_id', '=', 10086)
|
|
1775
|
+
else {
|
|
1776
|
+
orGroup.filters.push({ field: fieldOrConditions, op: opOrValue, value: value });
|
|
1777
|
+
}
|
|
1778
|
+
// 如果当前 filters 为空或者已经是 OR 逻辑,则直接添加
|
|
1779
|
+
if (this.params.filters.filters.length === 0 || this.params.filters.logic === 'or') {
|
|
1780
|
+
(_a = this.params.filters.filters).push.apply(_a, orGroup.filters);
|
|
1781
|
+
this.params.filters.logic = 'or';
|
|
1782
|
+
}
|
|
1783
|
+
else {
|
|
1784
|
+
// 否则将当前所有条件包装成一个 AND 组,然后与新的 OR 组一起放在顶层
|
|
1785
|
+
var andGroup = {
|
|
1786
|
+
logic: 'and',
|
|
1787
|
+
filters: __spreadArrays(this.params.filters.filters)
|
|
1788
|
+
};
|
|
1789
|
+
this.params.filters.filters = [andGroup, orGroup];
|
|
1790
|
+
this.params.filters.logic = 'and';
|
|
1791
|
+
}
|
|
1792
|
+
return this;
|
|
1793
|
+
};
|
|
1794
|
+
/**
|
|
1795
|
+
* WHERE IN
|
|
1796
|
+
*/
|
|
1797
|
+
QueryBuilder.prototype.whereIn = function (field, values) {
|
|
1798
|
+
this.params.filters.filters.push({ field: field, op: 'in', value: values });
|
|
1799
|
+
return this;
|
|
1800
|
+
};
|
|
1801
|
+
/**
|
|
1802
|
+
* WHERE NOT IN
|
|
1803
|
+
*/
|
|
1804
|
+
QueryBuilder.prototype.whereNotIn = function (field, values) {
|
|
1805
|
+
this.params.filters.filters.push({ field: field, op: 'not in', value: values });
|
|
1806
|
+
return this;
|
|
1807
|
+
};
|
|
1808
|
+
/**
|
|
1809
|
+
* WHERE LIKE
|
|
1810
|
+
*/
|
|
1811
|
+
QueryBuilder.prototype.whereLike = function (field, value) {
|
|
1812
|
+
this.params.filters.filters.push({ field: field, op: 'like', value: value });
|
|
1813
|
+
return this;
|
|
1814
|
+
};
|
|
1815
|
+
/**
|
|
1816
|
+
* WHERE BETWEEN
|
|
1817
|
+
*/
|
|
1818
|
+
QueryBuilder.prototype.whereBetween = function (field, min, max) {
|
|
1819
|
+
this.params.filters.filters.push({ field: field, op: 'between', value: [min, max] });
|
|
1820
|
+
return this;
|
|
1821
|
+
};
|
|
1822
|
+
/**
|
|
1823
|
+
* WHERE NULL
|
|
1824
|
+
*/
|
|
1825
|
+
QueryBuilder.prototype.whereNull = function (field) {
|
|
1826
|
+
this.params.filters.filters.push({ field: field, op: 'is null', value: null });
|
|
1827
|
+
return this;
|
|
1828
|
+
};
|
|
1829
|
+
/**
|
|
1830
|
+
* WHERE NOT NULL
|
|
1831
|
+
*/
|
|
1832
|
+
QueryBuilder.prototype.whereNotNull = function (field) {
|
|
1833
|
+
this.params.filters.filters.push({ field: field, op: 'is not null', value: null });
|
|
1834
|
+
return this;
|
|
1835
|
+
};
|
|
1836
|
+
/**
|
|
1837
|
+
* 设置逻辑运算符(不推荐直接使用,建议用 orWhere)
|
|
1838
|
+
*/
|
|
1839
|
+
QueryBuilder.prototype.logic = function (logic) {
|
|
1840
|
+
this.params.filters.logic = logic;
|
|
1841
|
+
return this;
|
|
1842
|
+
};
|
|
1843
|
+
/**
|
|
1844
|
+
* 添加排序
|
|
1845
|
+
*/
|
|
1846
|
+
QueryBuilder.prototype.orderBy = function (field, direction) {
|
|
1847
|
+
if (direction === void 0) { direction = 'asc'; }
|
|
1848
|
+
this.params.order_by.push({ field: field, direction: direction });
|
|
1849
|
+
return this;
|
|
1850
|
+
};
|
|
1851
|
+
/**
|
|
1852
|
+
* 设置 LIMIT
|
|
1853
|
+
*/
|
|
1854
|
+
QueryBuilder.prototype.limit = function (limit) {
|
|
1855
|
+
this.params.limit = limit;
|
|
1856
|
+
return this;
|
|
1857
|
+
};
|
|
1858
|
+
/**
|
|
1859
|
+
* 设置 OFFSET
|
|
1860
|
+
*/
|
|
1861
|
+
QueryBuilder.prototype.offset = function (offset) {
|
|
1862
|
+
this.params.offset = offset;
|
|
1863
|
+
return this;
|
|
1864
|
+
};
|
|
1865
|
+
/**
|
|
1866
|
+
* 设置分页(便捷方法)
|
|
1867
|
+
*/
|
|
1868
|
+
QueryBuilder.prototype.paginate = function (limit, offset) {
|
|
1869
|
+
if (offset === void 0) { offset = 0; }
|
|
1870
|
+
this.params.limit = limit;
|
|
1871
|
+
this.params.offset = offset;
|
|
1872
|
+
return this;
|
|
1873
|
+
};
|
|
1874
|
+
return QueryBuilder;
|
|
1875
|
+
}(BaseBuilder));
|
|
1876
|
+
/**
|
|
1877
|
+
* 新增构建器
|
|
1878
|
+
*/
|
|
1879
|
+
var InsertBuilder = /** @class */ (function (_super) {
|
|
1880
|
+
__extends(InsertBuilder, _super);
|
|
1881
|
+
function InsertBuilder(fieldCatalog) {
|
|
1882
|
+
var _this = _super.call(this, fieldCatalog) || this;
|
|
1883
|
+
_this.params = __assign(__assign({}, _this.params), { insert: [] });
|
|
1884
|
+
return _this;
|
|
1885
|
+
}
|
|
1886
|
+
/**
|
|
1887
|
+
* 添加一条记录
|
|
1888
|
+
*/
|
|
1889
|
+
InsertBuilder.prototype.add = function (data) {
|
|
1890
|
+
this.params.insert.push(data);
|
|
1891
|
+
return this;
|
|
1892
|
+
};
|
|
1893
|
+
/**
|
|
1894
|
+
* 批量添加记录
|
|
1895
|
+
*/
|
|
1896
|
+
InsertBuilder.prototype.addBatch = function (dataList) {
|
|
1897
|
+
var _a;
|
|
1898
|
+
(_a = this.params.insert).push.apply(_a, dataList);
|
|
1899
|
+
return this;
|
|
1900
|
+
};
|
|
1901
|
+
return InsertBuilder;
|
|
1902
|
+
}(BaseBuilder));
|
|
1903
|
+
/**
|
|
1904
|
+
* 更新构建器
|
|
1905
|
+
*/
|
|
1906
|
+
var UpdateBuilder = /** @class */ (function (_super) {
|
|
1907
|
+
__extends(UpdateBuilder, _super);
|
|
1908
|
+
function UpdateBuilder(fieldCatalog) {
|
|
1909
|
+
var _this = _super.call(this, fieldCatalog) || this;
|
|
1910
|
+
_this.currentUpdate = null;
|
|
1911
|
+
_this.params = __assign(__assign({}, _this.params), { update: [] });
|
|
1912
|
+
return _this;
|
|
1913
|
+
}
|
|
1914
|
+
/**
|
|
1915
|
+
* 设置要更新的字段和值
|
|
1916
|
+
*/
|
|
1917
|
+
UpdateBuilder.prototype.set = function (fields) {
|
|
1918
|
+
this.currentUpdate = { set: fields, where: {} };
|
|
1919
|
+
return this;
|
|
1920
|
+
};
|
|
1921
|
+
UpdateBuilder.prototype.where = function (fieldOrConditions, value) {
|
|
1922
|
+
if (!this.currentUpdate) {
|
|
1923
|
+
throw new Error('必须先调用 set() 方法');
|
|
1924
|
+
}
|
|
1925
|
+
if (typeof fieldOrConditions === 'object') {
|
|
1926
|
+
this.currentUpdate.where = __assign(__assign({}, this.currentUpdate.where), fieldOrConditions);
|
|
1927
|
+
}
|
|
1928
|
+
else {
|
|
1929
|
+
this.currentUpdate.where[fieldOrConditions] = value;
|
|
1930
|
+
}
|
|
1931
|
+
return this;
|
|
1932
|
+
};
|
|
1933
|
+
/**
|
|
1934
|
+
* 完成当前更新操作,开始下一个
|
|
1935
|
+
*/
|
|
1936
|
+
UpdateBuilder.prototype.and = function () {
|
|
1937
|
+
if (this.currentUpdate) {
|
|
1938
|
+
this.params.update.push(this.currentUpdate);
|
|
1939
|
+
this.currentUpdate = null;
|
|
1940
|
+
}
|
|
1941
|
+
return this;
|
|
1942
|
+
};
|
|
1943
|
+
/**
|
|
1944
|
+
* 批量添加更新操作
|
|
1945
|
+
*/
|
|
1946
|
+
UpdateBuilder.prototype.setBatch = function (updates) {
|
|
1947
|
+
var _a;
|
|
1948
|
+
(_a = this.params.update).push.apply(_a, updates);
|
|
1949
|
+
return this;
|
|
1950
|
+
};
|
|
1951
|
+
/**
|
|
1952
|
+
* 构建最终参数
|
|
1953
|
+
*/
|
|
1954
|
+
UpdateBuilder.prototype.build = function () {
|
|
1955
|
+
if (this.currentUpdate) {
|
|
1956
|
+
this.params.update.push(this.currentUpdate);
|
|
1957
|
+
this.currentUpdate = null;
|
|
1958
|
+
}
|
|
1959
|
+
return this.params;
|
|
1960
|
+
};
|
|
1961
|
+
return UpdateBuilder;
|
|
1962
|
+
}(BaseBuilder));
|
|
1963
|
+
|
|
1964
|
+
function normalizeHeaders(headers) {
|
|
1965
|
+
return __assign({}, (headers || {}));
|
|
1966
|
+
}
|
|
1967
|
+
function lowerCaseHeaderMap(resHeaders) {
|
|
1968
|
+
var out = {};
|
|
1969
|
+
resHeaders.forEach(function (value, key) {
|
|
1970
|
+
out[key.toLowerCase()] = value;
|
|
1971
|
+
});
|
|
1972
|
+
return out;
|
|
1973
|
+
}
|
|
1974
|
+
function safeJsonParse(text) {
|
|
1975
|
+
try {
|
|
1976
|
+
return JSON.parse(text);
|
|
1977
|
+
}
|
|
1978
|
+
catch (_a) {
|
|
1979
|
+
return undefined;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
var CurlClient = /** @class */ (function () {
|
|
1983
|
+
function CurlClient() {
|
|
1984
|
+
}
|
|
1985
|
+
CurlClient.prototype.request = function (opts) {
|
|
1986
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
1987
|
+
var method, timeoutMs, headers, hasBody, body, hasContentType, controller, timeoutId, res, text, resHeaders, ct, json;
|
|
1988
|
+
return __generator(this, function (_a) {
|
|
1989
|
+
switch (_a.label) {
|
|
1990
|
+
case 0:
|
|
1991
|
+
method = (opts.method || 'GET').toUpperCase();
|
|
1992
|
+
timeoutMs = typeof opts.timeoutMs === 'number' && opts.timeoutMs > 0 ? opts.timeoutMs : 15000;
|
|
1993
|
+
headers = normalizeHeaders(opts.headers);
|
|
1994
|
+
hasBody = opts.data !== undefined && opts.data !== null;
|
|
1995
|
+
body = undefined;
|
|
1996
|
+
if (hasBody) {
|
|
1997
|
+
if (typeof opts.data === 'string') {
|
|
1998
|
+
body = opts.data;
|
|
1999
|
+
}
|
|
2000
|
+
else if (typeof FormData !== 'undefined' && opts.data instanceof FormData ||
|
|
2001
|
+
typeof Blob !== 'undefined' && opts.data instanceof Blob ||
|
|
2002
|
+
typeof ArrayBuffer !== 'undefined' && opts.data instanceof ArrayBuffer) {
|
|
2003
|
+
body = opts.data;
|
|
2004
|
+
}
|
|
2005
|
+
else {
|
|
2006
|
+
hasContentType = Object.keys(headers).some(function (k) { return k.toLowerCase() === 'content-type'; });
|
|
2007
|
+
if (!hasContentType)
|
|
2008
|
+
headers['Content-Type'] = 'application/json';
|
|
2009
|
+
body = JSON.stringify(opts.data);
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
|
2013
|
+
timeoutId = controller ? setTimeout(function () { return controller.abort(); }, timeoutMs) : null;
|
|
2014
|
+
_a.label = 1;
|
|
2015
|
+
case 1:
|
|
2016
|
+
_a.trys.push([1, , 4, 5]);
|
|
2017
|
+
return [4 /*yield*/, fetch(opts.url, {
|
|
2018
|
+
method: method,
|
|
2019
|
+
headers: headers,
|
|
2020
|
+
body: body,
|
|
2021
|
+
redirect: opts.followRedirects === false ? 'manual' : 'follow',
|
|
2022
|
+
signal: controller ? controller.signal : undefined,
|
|
2023
|
+
})];
|
|
2024
|
+
case 2:
|
|
2025
|
+
res = _a.sent();
|
|
2026
|
+
return [4 /*yield*/, res.text()];
|
|
2027
|
+
case 3:
|
|
2028
|
+
text = _a.sent();
|
|
2029
|
+
resHeaders = lowerCaseHeaderMap(res.headers);
|
|
2030
|
+
ct = resHeaders['content-type'] || '';
|
|
2031
|
+
json = ct.includes('application/json') ? safeJsonParse(text) : undefined;
|
|
2032
|
+
return [2 /*return*/, {
|
|
2033
|
+
status: res.status,
|
|
2034
|
+
headers: resHeaders,
|
|
2035
|
+
body: text,
|
|
2036
|
+
json: json,
|
|
2037
|
+
}];
|
|
2038
|
+
case 4:
|
|
2039
|
+
if (timeoutId)
|
|
2040
|
+
clearTimeout(timeoutId);
|
|
2041
|
+
return [7 /*endfinally*/];
|
|
2042
|
+
case 5: return [2 /*return*/];
|
|
2043
|
+
}
|
|
2044
|
+
});
|
|
2045
|
+
});
|
|
2046
|
+
};
|
|
2047
|
+
CurlClient.prototype.get = function (url, opts) {
|
|
2048
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2049
|
+
return __generator(this, function (_a) {
|
|
2050
|
+
return [2 /*return*/, this.request(__assign(__assign({}, (opts || {})), { url: url, method: 'GET' }))];
|
|
2051
|
+
});
|
|
2052
|
+
});
|
|
2053
|
+
};
|
|
2054
|
+
CurlClient.prototype.post = function (url, data, opts) {
|
|
2055
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2056
|
+
return __generator(this, function (_a) {
|
|
2057
|
+
return [2 /*return*/, this.request(__assign(__assign({}, (opts || {})), { url: url, method: 'POST', data: data }))];
|
|
2058
|
+
});
|
|
2059
|
+
});
|
|
2060
|
+
};
|
|
2061
|
+
return CurlClient;
|
|
2062
|
+
}());
|
|
2063
|
+
var curl = new CurlClient();
|
|
2064
|
+
|
|
2065
|
+
// ==================== 通用工具函数 ====================
|
|
2066
|
+
function getNowTime() {
|
|
2067
|
+
var d = new Date();
|
|
2068
|
+
var y = String(d.getFullYear());
|
|
2069
|
+
var m = String(d.getMonth() + 1);
|
|
2070
|
+
var day = String(d.getDate());
|
|
2071
|
+
var h = String(d.getHours());
|
|
2072
|
+
var min = String(d.getMinutes());
|
|
2073
|
+
return y + "\u5E74" + m + "\u6708" + day + "\u65E5" + h + ":" + min;
|
|
2074
|
+
}
|
|
2075
|
+
function sendLog(logData) {
|
|
2076
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2077
|
+
var LOG_HOST, result, err_1;
|
|
2078
|
+
return __generator(this, function (_a) {
|
|
2079
|
+
switch (_a.label) {
|
|
2080
|
+
case 0:
|
|
2081
|
+
_a.trys.push([0, 2, , 3]);
|
|
2082
|
+
LOG_HOST = "https://fe-log-producer.jinbizhihui.com";
|
|
2083
|
+
return [4 /*yield*/, curl.post(LOG_HOST + "/log/save", logData)];
|
|
2084
|
+
case 1:
|
|
2085
|
+
result = _a.sent();
|
|
2086
|
+
console.log("[RequestLogger] 远程日志发送成功, result", result);
|
|
2087
|
+
return [3 /*break*/, 3];
|
|
2088
|
+
case 2:
|
|
2089
|
+
err_1 = _a.sent();
|
|
2090
|
+
console.error("[RequestLogger] \u8FDC\u7A0B\u65E5\u5FD7\u53D1\u9001\u5931\u8D25:", (err_1 === null || err_1 === void 0 ? void 0 : err_1.message) || err_1);
|
|
2091
|
+
return [3 /*break*/, 3];
|
|
2092
|
+
case 3: return [2 /*return*/];
|
|
2093
|
+
}
|
|
2094
|
+
});
|
|
2095
|
+
});
|
|
2096
|
+
}
|
|
2097
|
+
// ==================== Hono 相关处理 ====================
|
|
2098
|
+
function readHonoRequestBody(c) {
|
|
2099
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2100
|
+
var ct, raw, cloned, t;
|
|
2101
|
+
return __generator(this, function (_b) {
|
|
2102
|
+
switch (_b.label) {
|
|
2103
|
+
case 0:
|
|
2104
|
+
ct = c.req.header("content-type") || "";
|
|
2105
|
+
_b.label = 1;
|
|
2106
|
+
case 1:
|
|
2107
|
+
_b.trys.push([1, 4, , 5]);
|
|
2108
|
+
raw = c.req.raw;
|
|
2109
|
+
if (!(raw && typeof raw.clone === "function")) return [3 /*break*/, 3];
|
|
2110
|
+
cloned = raw.clone();
|
|
2111
|
+
return [4 /*yield*/, cloned.text()];
|
|
2112
|
+
case 2:
|
|
2113
|
+
t = _b.sent();
|
|
2114
|
+
if (!t)
|
|
2115
|
+
return [2 /*return*/, undefined];
|
|
2116
|
+
if (ct.includes("application/json")) {
|
|
2117
|
+
try {
|
|
2118
|
+
return [2 /*return*/, JSON.parse(t)];
|
|
2119
|
+
}
|
|
2120
|
+
catch (_c) {
|
|
2121
|
+
return [2 /*return*/, t];
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
return [2 /*return*/, t];
|
|
2125
|
+
case 3: return [3 /*break*/, 5];
|
|
2126
|
+
case 4:
|
|
2127
|
+
_b.sent();
|
|
2128
|
+
return [3 /*break*/, 5];
|
|
2129
|
+
case 5: return [2 /*return*/, undefined];
|
|
2130
|
+
}
|
|
2131
|
+
});
|
|
2132
|
+
});
|
|
2133
|
+
}
|
|
2134
|
+
function readHonoRequestHeaders(c) {
|
|
2135
|
+
var out = {};
|
|
2136
|
+
try {
|
|
2137
|
+
var raw = c.req.raw;
|
|
2138
|
+
var hs = raw === null || raw === void 0 ? void 0 : raw.headers;
|
|
2139
|
+
if (hs) {
|
|
2140
|
+
hs.forEach(function (v, k) {
|
|
2141
|
+
out[k] = v;
|
|
2142
|
+
});
|
|
2143
|
+
}
|
|
2144
|
+
}
|
|
2145
|
+
catch (_a) { }
|
|
2146
|
+
return out;
|
|
2147
|
+
}
|
|
2148
|
+
function readHonoResponseHeaders(c) {
|
|
2149
|
+
var out = {};
|
|
2150
|
+
try {
|
|
2151
|
+
c.res.headers.forEach(function (v, k) {
|
|
2152
|
+
out[k] = v;
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
catch (_a) { }
|
|
2156
|
+
return out;
|
|
2157
|
+
}
|
|
2158
|
+
function handleHono(c, next, systemName) {
|
|
2159
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2160
|
+
var ip, method, url, query, headers, body, timeToString, start, duration, result, logData;
|
|
2161
|
+
return __generator(this, function (_a) {
|
|
2162
|
+
switch (_a.label) {
|
|
2163
|
+
case 0:
|
|
2164
|
+
ip = c.req.header("x-forwarded-for") || c.req.header("x-real-ip") || "unknown";
|
|
2165
|
+
method = c.req.method;
|
|
2166
|
+
url = c.req.url;
|
|
2167
|
+
query = c.req.query();
|
|
2168
|
+
headers = readHonoRequestHeaders(c);
|
|
2169
|
+
return [4 /*yield*/, readHonoRequestBody(c)];
|
|
2170
|
+
case 1:
|
|
2171
|
+
body = _a.sent();
|
|
2172
|
+
timeToString = getNowTime();
|
|
2173
|
+
start = Date.now();
|
|
2174
|
+
return [4 /*yield*/, next()];
|
|
2175
|
+
case 2:
|
|
2176
|
+
_a.sent();
|
|
2177
|
+
duration = Date.now() - start;
|
|
2178
|
+
result = {
|
|
2179
|
+
status: c.res.status,
|
|
2180
|
+
headers: readHonoResponseHeaders(c),
|
|
2181
|
+
duration: duration,
|
|
2182
|
+
};
|
|
2183
|
+
logData = {
|
|
2184
|
+
system: systemName,
|
|
2185
|
+
ip: ip,
|
|
2186
|
+
path: url,
|
|
2187
|
+
method: method,
|
|
2188
|
+
time: timeToString,
|
|
2189
|
+
params: { method: method, url: url, query: query, body: body },
|
|
2190
|
+
headers: headers,
|
|
2191
|
+
result: result,
|
|
2192
|
+
};
|
|
2193
|
+
return [4 /*yield*/, sendLog(logData)];
|
|
2194
|
+
case 3:
|
|
2195
|
+
_a.sent();
|
|
2196
|
+
return [2 /*return*/];
|
|
2197
|
+
}
|
|
2198
|
+
});
|
|
2199
|
+
});
|
|
2200
|
+
}
|
|
2201
|
+
// ==================== Koa/Midway 相关处理 ====================
|
|
2202
|
+
function readKoaRequestHeaders(ctx) {
|
|
2203
|
+
var _a;
|
|
2204
|
+
var out = {};
|
|
2205
|
+
try {
|
|
2206
|
+
var headers = ctx.headers || ((_a = ctx.request) === null || _a === void 0 ? void 0 : _a.headers) || {};
|
|
2207
|
+
for (var _i = 0, _b = Object.entries(headers); _i < _b.length; _i++) {
|
|
2208
|
+
var _c = _b[_i], k = _c[0], v = _c[1];
|
|
2209
|
+
out[k] = String(v);
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
catch (_d) { }
|
|
2213
|
+
return out;
|
|
2214
|
+
}
|
|
2215
|
+
function readKoaResponseHeaders(ctx) {
|
|
2216
|
+
var _a;
|
|
2217
|
+
var out = {};
|
|
2218
|
+
try {
|
|
2219
|
+
var headers = ((_a = ctx.response) === null || _a === void 0 ? void 0 : _a.headers) || {};
|
|
2220
|
+
for (var _i = 0, _b = Object.entries(headers); _i < _b.length; _i++) {
|
|
2221
|
+
var _c = _b[_i], k = _c[0], v = _c[1];
|
|
2222
|
+
out[k] = String(v);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
catch (_d) { }
|
|
2226
|
+
return out;
|
|
2227
|
+
}
|
|
2228
|
+
function handleKoa(ctx, next, systemName) {
|
|
2229
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2230
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2231
|
+
var ip, path, method, url, query, body, headers, timeToString, start, duration, result, logData;
|
|
2232
|
+
return __generator(this, function (_g) {
|
|
2233
|
+
switch (_g.label) {
|
|
2234
|
+
case 0:
|
|
2235
|
+
ip = ctx.ip || ((_a = ctx.request) === null || _a === void 0 ? void 0 : _a.ip) || "unknown";
|
|
2236
|
+
path = ctx.path || ((_b = ctx.request) === null || _b === void 0 ? void 0 : _b.path) || "";
|
|
2237
|
+
method = ctx.method || ((_c = ctx.request) === null || _c === void 0 ? void 0 : _c.method) || "";
|
|
2238
|
+
url = ctx.url || ((_d = ctx.request) === null || _d === void 0 ? void 0 : _d.url) || "";
|
|
2239
|
+
query = ctx.query || ((_e = ctx.request) === null || _e === void 0 ? void 0 : _e.query) || {};
|
|
2240
|
+
body = ((_f = ctx.request) === null || _f === void 0 ? void 0 : _f.body) || {};
|
|
2241
|
+
headers = readKoaRequestHeaders(ctx);
|
|
2242
|
+
timeToString = getNowTime();
|
|
2243
|
+
start = Date.now();
|
|
2244
|
+
return [4 /*yield*/, next()];
|
|
2245
|
+
case 1:
|
|
2246
|
+
_g.sent();
|
|
2247
|
+
duration = Date.now() - start;
|
|
2248
|
+
result = {
|
|
2249
|
+
status: ctx.status,
|
|
2250
|
+
body: ctx.body,
|
|
2251
|
+
headers: readKoaResponseHeaders(ctx),
|
|
2252
|
+
duration: duration,
|
|
2253
|
+
};
|
|
2254
|
+
logData = {
|
|
2255
|
+
system: systemName,
|
|
2256
|
+
ip: ip,
|
|
2257
|
+
path: path,
|
|
2258
|
+
method: method,
|
|
2259
|
+
time: timeToString,
|
|
2260
|
+
params: { method: method, url: url, query: query, body: body },
|
|
2261
|
+
headers: headers,
|
|
2262
|
+
result: result,
|
|
2263
|
+
};
|
|
2264
|
+
return [4 /*yield*/, sendLog(logData)];
|
|
2265
|
+
case 2:
|
|
2266
|
+
_g.sent();
|
|
2267
|
+
return [2 /*return*/];
|
|
2268
|
+
}
|
|
2269
|
+
});
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
// ==================== Fastify 相关处理 ====================
|
|
2273
|
+
function readFastifyRequestHeaders(request) {
|
|
2274
|
+
var out = {};
|
|
2275
|
+
try {
|
|
2276
|
+
var headers = request.headers || {};
|
|
2277
|
+
for (var _i = 0, _a = Object.entries(headers); _i < _a.length; _i++) {
|
|
2278
|
+
var _b = _a[_i], k = _b[0], v = _b[1];
|
|
2279
|
+
out[k] = String(v);
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
catch (_c) { }
|
|
2283
|
+
return out;
|
|
2284
|
+
}
|
|
2285
|
+
function readFastifyResponseHeaders(reply) {
|
|
2286
|
+
var _a;
|
|
2287
|
+
var out = {};
|
|
2288
|
+
try {
|
|
2289
|
+
var headers = ((_a = reply.getHeaders) === null || _a === void 0 ? void 0 : _a.call(reply)) || {};
|
|
2290
|
+
for (var _i = 0, _b = Object.entries(headers); _i < _b.length; _i++) {
|
|
2291
|
+
var _c = _b[_i], k = _c[0], v = _c[1];
|
|
2292
|
+
if (v !== undefined) {
|
|
2293
|
+
out[k] = String(v);
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
catch (_d) { }
|
|
2298
|
+
return out;
|
|
2299
|
+
}
|
|
2300
|
+
function handleFastify(request, reply, systemName) {
|
|
2301
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2302
|
+
var ip, path, method, query, body, headers, timeToString, start, duration, result, logData;
|
|
2303
|
+
return __generator(this, function (_a) {
|
|
2304
|
+
switch (_a.label) {
|
|
2305
|
+
case 0:
|
|
2306
|
+
ip = request.headers["x-forwarded-for"] ||
|
|
2307
|
+
request.headers["x-real-ip"] ||
|
|
2308
|
+
request.ip ||
|
|
2309
|
+
"unknown";
|
|
2310
|
+
path = request.url || "";
|
|
2311
|
+
method = request.method || "";
|
|
2312
|
+
query = request.query || {};
|
|
2313
|
+
body = request.body || {};
|
|
2314
|
+
headers = readFastifyRequestHeaders(request);
|
|
2315
|
+
timeToString = getNowTime();
|
|
2316
|
+
start = Date.now();
|
|
2317
|
+
duration = Date.now() - start;
|
|
2318
|
+
result = {
|
|
2319
|
+
status: reply.statusCode,
|
|
2320
|
+
headers: readFastifyResponseHeaders(reply),
|
|
2321
|
+
duration: duration,
|
|
2322
|
+
};
|
|
2323
|
+
logData = {
|
|
2324
|
+
system: systemName,
|
|
2325
|
+
ip: ip,
|
|
2326
|
+
path: path,
|
|
2327
|
+
method: method,
|
|
2328
|
+
time: timeToString,
|
|
2329
|
+
params: { method: method, url: path, query: query, body: body },
|
|
2330
|
+
headers: headers,
|
|
2331
|
+
result: result,
|
|
2332
|
+
};
|
|
2333
|
+
return [4 /*yield*/, sendLog(logData)];
|
|
2334
|
+
case 1:
|
|
2335
|
+
_a.sent();
|
|
2336
|
+
return [2 /*return*/];
|
|
2337
|
+
}
|
|
2338
|
+
});
|
|
2339
|
+
});
|
|
2340
|
+
}
|
|
2341
|
+
/**
|
|
2342
|
+
* 检测 Fastify 请求对象
|
|
2343
|
+
* Fastify 的 request 对象有特定的属性如 routerPath, routeOptions 等
|
|
2344
|
+
*/
|
|
2345
|
+
function isFastifyRequest(obj) {
|
|
2346
|
+
var _a, _b;
|
|
2347
|
+
return (obj &&
|
|
2348
|
+
typeof obj.method === "string" &&
|
|
2349
|
+
typeof obj.url === "string" &&
|
|
2350
|
+
obj.headers &&
|
|
2351
|
+
(obj.routerPath !== undefined ||
|
|
2352
|
+
obj.routeOptions !== undefined ||
|
|
2353
|
+
typeof obj.getValidationFunction === "function" ||
|
|
2354
|
+
((_b = (_a = obj.raw) === null || _a === void 0 ? void 0 : _a.constructor) === null || _b === void 0 ? void 0 : _b.name) === "IncomingMessage"));
|
|
2355
|
+
}
|
|
2356
|
+
function detectFramework(context, secondArg) {
|
|
2357
|
+
var _a;
|
|
2358
|
+
// Fastify: 检查第一个参数是否是 Fastify request 对象
|
|
2359
|
+
// Fastify hook 签名: (request, reply) => void
|
|
2360
|
+
if (isFastifyRequest(context) && (secondArg === null || secondArg === void 0 ? void 0 : secondArg.statusCode) !== undefined) {
|
|
2361
|
+
return "fastify";
|
|
2362
|
+
}
|
|
2363
|
+
// Hono: 检查是否有 c.req.raw 和 c.res 等 Hono 特有属性
|
|
2364
|
+
if (context &&
|
|
2365
|
+
context.req &&
|
|
2366
|
+
typeof context.req.header === "function" &&
|
|
2367
|
+
typeof context.req.query === "function" &&
|
|
2368
|
+
context.req.raw !== undefined) {
|
|
2369
|
+
return "hono";
|
|
2370
|
+
}
|
|
2371
|
+
// Koa/Midway: 检查是否有 ctx.request, ctx.response 等 Koa 特有属性
|
|
2372
|
+
if (context &&
|
|
2373
|
+
context.request &&
|
|
2374
|
+
context.response &&
|
|
2375
|
+
typeof context.throw === "function") {
|
|
2376
|
+
// 进一步区分 Midway 和 Koa
|
|
2377
|
+
// Midway 通常会有 requestContext 或特定的装饰器注入
|
|
2378
|
+
if (context.requestContext || ((_a = context.app) === null || _a === void 0 ? void 0 : _a.getApplicationContext)) {
|
|
2379
|
+
return "midway";
|
|
2380
|
+
}
|
|
2381
|
+
return "koa";
|
|
2382
|
+
}
|
|
2383
|
+
return "unknown";
|
|
2384
|
+
}
|
|
2385
|
+
// ==================== 统一中间件入口 ====================
|
|
2386
|
+
/**
|
|
2387
|
+
* 统一请求日志中间件
|
|
2388
|
+
* 自动检测运行时框架类型,支持 Hono、Koa、Midway、Fastify
|
|
2389
|
+
*
|
|
2390
|
+
* @param systemName 系统名称,用于日志标识
|
|
2391
|
+
* @returns 返回适配不同框架的中间件函数
|
|
2392
|
+
*/
|
|
2393
|
+
function recordLogMiddleware(systemName) {
|
|
2394
|
+
var _this = this;
|
|
2395
|
+
return function (contextOrC, nextOrReply) { return __awaiter(_this, void 0, void 0, function () {
|
|
2396
|
+
var framework;
|
|
2397
|
+
return __generator(this, function (_a) {
|
|
2398
|
+
framework = detectFramework(contextOrC, nextOrReply);
|
|
2399
|
+
switch (framework) {
|
|
2400
|
+
case "hono":
|
|
2401
|
+
return [2 /*return*/, handleHono(contextOrC, nextOrReply, systemName)];
|
|
2402
|
+
case "fastify":
|
|
2403
|
+
return [2 /*return*/, handleFastify(contextOrC, nextOrReply, systemName)];
|
|
2404
|
+
case "koa":
|
|
2405
|
+
case "midway":
|
|
2406
|
+
return [2 /*return*/, handleKoa(contextOrC, nextOrReply, systemName)];
|
|
2407
|
+
default:
|
|
2408
|
+
// 未知框架,尝试 Koa 风格作为回退
|
|
2409
|
+
console.warn("[requestLoggerUnified] Unknown framework detected, falling back to Koa-style handling");
|
|
2410
|
+
return [2 /*return*/, handleKoa(contextOrC, nextOrReply, systemName)];
|
|
2411
|
+
}
|
|
2412
|
+
return [2 /*return*/];
|
|
2413
|
+
});
|
|
2414
|
+
}); };
|
|
2415
|
+
}
|
|
2416
|
+
// ==================== 针对特定框架的导出 ====================
|
|
2417
|
+
/**
|
|
2418
|
+
* Hono 专用中间件
|
|
2419
|
+
*/
|
|
2420
|
+
function recordLogMiddlewareHono(systemName) {
|
|
2421
|
+
var _this = this;
|
|
2422
|
+
return function (c, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
2423
|
+
return __generator(this, function (_a) {
|
|
2424
|
+
return [2 /*return*/, handleHono(c, next, systemName)];
|
|
2425
|
+
});
|
|
2426
|
+
}); };
|
|
2427
|
+
}
|
|
2428
|
+
/**
|
|
2429
|
+
* Koa 专用中间件
|
|
2430
|
+
*/
|
|
2431
|
+
function recordLogMiddlewareKoa(systemName) {
|
|
2432
|
+
var _this = this;
|
|
2433
|
+
return function (ctx, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
2434
|
+
return __generator(this, function (_a) {
|
|
2435
|
+
return [2 /*return*/, handleKoa(ctx, next, systemName)];
|
|
2436
|
+
});
|
|
2437
|
+
}); };
|
|
2438
|
+
}
|
|
2439
|
+
/**
|
|
2440
|
+
* Midway 专用中间件(本质与 Koa 相同,因为 Midway 基于 Koa)
|
|
2441
|
+
*/
|
|
2442
|
+
function recordLogMiddlewareMidway(systemName) {
|
|
2443
|
+
var _this = this;
|
|
2444
|
+
return function (ctx, next) { return __awaiter(_this, void 0, void 0, function () {
|
|
2445
|
+
return __generator(this, function (_a) {
|
|
2446
|
+
return [2 /*return*/, handleKoa(ctx, next, systemName)];
|
|
2447
|
+
});
|
|
2448
|
+
}); };
|
|
2449
|
+
}
|
|
2450
|
+
/**
|
|
2451
|
+
* Fastify 专用插件
|
|
2452
|
+
* 使用方式:fastify.addHook('onResponse', recordLogMiddlewareFastify('systemName'))
|
|
2453
|
+
*/
|
|
2454
|
+
function recordLogMiddlewareFastify(systemName) {
|
|
2455
|
+
var _this = this;
|
|
2456
|
+
return function (request, reply) { return __awaiter(_this, void 0, void 0, function () {
|
|
2457
|
+
return __generator(this, function (_a) {
|
|
2458
|
+
return [2 /*return*/, handleFastify(request, reply, systemName)];
|
|
2459
|
+
});
|
|
2460
|
+
}); };
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
/**
|
|
2464
|
+
* 扁平化 state 字段
|
|
2465
|
+
* @param state 需要扁平化的 state 字段
|
|
2466
|
+
* @param keyName 需要剥离的 key 名称
|
|
2467
|
+
* @returns 扁平化后的 state 字段
|
|
2468
|
+
*/
|
|
2469
|
+
function flattenStateRecursive(state, keyName) {
|
|
2470
|
+
if (keyName === void 0) { keyName = 'state'; }
|
|
2471
|
+
var result = state;
|
|
2472
|
+
var lastResult;
|
|
2473
|
+
// 递归解码和解析
|
|
2474
|
+
while (typeof result === 'string') {
|
|
2475
|
+
try {
|
|
2476
|
+
lastResult = result;
|
|
2477
|
+
result = decodeURIComponent(result);
|
|
2478
|
+
result = JSON.parse(result);
|
|
2479
|
+
}
|
|
2480
|
+
catch (_a) {
|
|
2481
|
+
result = lastResult;
|
|
2482
|
+
break;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
// 递归剥离 state 字段
|
|
2486
|
+
while (result &&
|
|
2487
|
+
typeof result === 'object' &&
|
|
2488
|
+
keyName in result &&
|
|
2489
|
+
(typeof result[keyName] === 'string' || typeof result[keyName] === 'object')) {
|
|
2490
|
+
result = result[keyName];
|
|
2491
|
+
if (typeof result === 'string') {
|
|
2492
|
+
try {
|
|
2493
|
+
result = decodeURIComponent(result);
|
|
2494
|
+
result = JSON.parse(result);
|
|
2495
|
+
}
|
|
2496
|
+
catch (_b) {
|
|
2497
|
+
break;
|
|
2498
|
+
}
|
|
2499
|
+
}
|
|
2500
|
+
}
|
|
2501
|
+
return result;
|
|
2502
|
+
}
|
|
2503
|
+
var handleFlatStr = function (keyName, value) {
|
|
2504
|
+
// return `${key}=${value}`
|
|
2505
|
+
if (keyName === void 0) { keyName = 'state'; }
|
|
2506
|
+
var flat = flattenStateRecursive(value, keyName);
|
|
2507
|
+
var flatStr = typeof flat === 'object' ? JSON.stringify(flat) : String(flat);
|
|
2508
|
+
return flatStr;
|
|
2509
|
+
};
|
|
2510
|
+
|
|
2511
|
+
/**
|
|
2512
|
+
* 颜色处理相关
|
|
2513
|
+
* @packageDocumentation
|
|
2514
|
+
* @module Color
|
|
2515
|
+
* @preferred
|
|
2516
|
+
*/
|
|
2517
|
+
/**
|
|
2518
|
+
* 将 Hex 颜色转换为 RGB 数组
|
|
2519
|
+
* @param hex - Hex 格式颜色值(如 #ffffff)
|
|
2520
|
+
* @returns RGB 数组 [r, g, b]
|
|
2521
|
+
*/
|
|
2522
|
+
function hexToRgb(hex) {
|
|
2523
|
+
var result = hex.replace('#', '').match(/../g);
|
|
2524
|
+
return result ? result.map(function (val) { return parseInt(val, 16); }) : [0, 0, 0];
|
|
2525
|
+
}
|
|
2526
|
+
/**
|
|
2527
|
+
* 将 RGB 值转换为 Hex 颜色
|
|
2528
|
+
* @param r - 红色值 (0-255)
|
|
2529
|
+
* @param g - 绿色值 (0-255)
|
|
2530
|
+
* @param b - 蓝色值 (0-255)
|
|
2531
|
+
* @returns Hex 格式颜色值(如 #ffffff)
|
|
2532
|
+
*/
|
|
2533
|
+
function rgbToHex(r, g, b) {
|
|
2534
|
+
var toHex = function (n) {
|
|
2535
|
+
var hex = n.toString(16);
|
|
2536
|
+
return hex.length === 1 ? '0' + hex : hex;
|
|
2537
|
+
};
|
|
2538
|
+
return "#" + toHex(r) + toHex(g) + toHex(b);
|
|
2539
|
+
}
|
|
2540
|
+
/**
|
|
2541
|
+
* 颜色加深
|
|
2542
|
+
* 使用 RGB 线性计算:color * (1 - level)
|
|
2543
|
+
* @param color - Hex 格式颜色值
|
|
2544
|
+
* @param level - 加深程度 (0-1)
|
|
2545
|
+
* @returns 加深后的 Hex 颜色值
|
|
2546
|
+
*/
|
|
2547
|
+
function darken(color, level) {
|
|
2548
|
+
var rgb = hexToRgb(color);
|
|
2549
|
+
var darkened = rgb.map(function (val) { return Math.floor(val * (1 - level)); });
|
|
2550
|
+
return rgbToHex(darkened[0], darkened[1], darkened[2]);
|
|
2551
|
+
}
|
|
2552
|
+
/**
|
|
2553
|
+
* 颜色变浅
|
|
2554
|
+
* 使用 RGB 线性计算:(255 - color) * level + color
|
|
2555
|
+
* @param color - Hex 格式颜色值
|
|
2556
|
+
* @param level - 变浅程度 (0-1)
|
|
2557
|
+
* @returns 变浅后的 Hex 颜色值
|
|
2558
|
+
*/
|
|
2559
|
+
function lighten(color, level) {
|
|
2560
|
+
var rgb = hexToRgb(color);
|
|
2561
|
+
var lightened = rgb.map(function (val) { return Math.floor((255 - val) * level + val); });
|
|
2562
|
+
return rgbToHex(lightened[0], lightened[1], lightened[2]);
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
/**
|
|
2566
|
+
* 数组处理相关
|
|
2567
|
+
* @packageDocumentation
|
|
2568
|
+
* @module Array
|
|
2569
|
+
* @preferred
|
|
2570
|
+
*/
|
|
2571
|
+
/**
|
|
2572
|
+
* 从对象数组中提取指定 key 的值,组成新数组
|
|
2573
|
+
* @param arr - 对象数组
|
|
2574
|
+
* @param key - 要提取的键名
|
|
2575
|
+
* @returns 提取的值数组
|
|
2576
|
+
*/
|
|
2577
|
+
function getKeyList(arr, key) {
|
|
2578
|
+
if (!Array.isArray(arr))
|
|
2579
|
+
return [];
|
|
2580
|
+
var result = [];
|
|
2581
|
+
for (var _i = 0, arr_1 = arr; _i < arr_1.length; _i++) {
|
|
2582
|
+
var item = arr_1[_i];
|
|
2583
|
+
if (item && item[key] !== undefined && item[key] !== null) {
|
|
2584
|
+
result.push(item[key]);
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
return result;
|
|
2588
|
+
}
|
|
2589
|
+
/**
|
|
2590
|
+
* 判断父数组是否包含子数组的所有元素(深度比较)
|
|
2591
|
+
* 注意:此函数需要配合深度比较工具使用
|
|
2592
|
+
* @param parent - 父数组
|
|
2593
|
+
* @param children - 子数组
|
|
2594
|
+
* @param compareFn - 比较函数,用于判断两个元素是否相等
|
|
2595
|
+
* @returns 是否包含所有子元素
|
|
2596
|
+
*/
|
|
2597
|
+
function isIncludeAllChildren(parent, children, compareFn) {
|
|
2598
|
+
if (!Array.isArray(parent) || !Array.isArray(children))
|
|
2599
|
+
return false;
|
|
2600
|
+
var defaultCompareFn = function (a, b) { return JSON.stringify(a) === JSON.stringify(b); };
|
|
2601
|
+
var compare = compareFn || defaultCompareFn;
|
|
2602
|
+
return children.every(function (child) { return parent.some(function (item) { return compare(item, child); }); });
|
|
2603
|
+
}
|
|
2604
|
+
/**
|
|
2605
|
+
* 判断数组或对象是否为空
|
|
2606
|
+
* @param value - 待检查的值
|
|
2607
|
+
* @returns 是否为空
|
|
2608
|
+
*/
|
|
2609
|
+
function isAllEmpty(value) {
|
|
2610
|
+
if (value === null || value === undefined)
|
|
2611
|
+
return true;
|
|
2612
|
+
if (typeof value === 'string')
|
|
2613
|
+
return value.trim().length === 0;
|
|
2614
|
+
if (Array.isArray(value))
|
|
2615
|
+
return value.length === 0;
|
|
2616
|
+
if (typeof value === 'object')
|
|
2617
|
+
return Object.keys(value).length === 0;
|
|
2618
|
+
return false;
|
|
2619
|
+
}
|
|
2620
|
+
/**
|
|
2621
|
+
* 计算两个数组的交集
|
|
2622
|
+
* @param arr1 - 数组1
|
|
2623
|
+
* @param arr2 - 数组2
|
|
2624
|
+
* @returns 交集数组
|
|
2625
|
+
*/
|
|
2626
|
+
function intersection(arr1, arr2) {
|
|
2627
|
+
if (!Array.isArray(arr1) || !Array.isArray(arr2))
|
|
2628
|
+
return [];
|
|
2629
|
+
return arr1.filter(function (item) { return arr2.includes(item); });
|
|
2630
|
+
}
|
|
2631
|
+
/**
|
|
2632
|
+
* 数组求和
|
|
2633
|
+
* @param arr - 数字数组
|
|
2634
|
+
* @returns 数组元素之和
|
|
2635
|
+
*/
|
|
2636
|
+
function sum(arr) {
|
|
2637
|
+
return Array.isArray(arr) && arr.length > 0
|
|
2638
|
+
? arr.reduce(function (acc, val) { return acc + val; }, 0)
|
|
2639
|
+
: 0;
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
/**
|
|
2643
|
+
* DOM 操作相关
|
|
2644
|
+
* @packageDocumentation
|
|
2645
|
+
* @module DOM
|
|
2646
|
+
* @preferred
|
|
2647
|
+
*/
|
|
2648
|
+
/**
|
|
2649
|
+
* 检查元素是否包含指定的 class
|
|
2650
|
+
* @param el - DOM 元素
|
|
2651
|
+
* @param cls - class 名称
|
|
2652
|
+
* @returns 是否包含该 class
|
|
2653
|
+
*/
|
|
2654
|
+
function hasClass(el, cls) {
|
|
2655
|
+
if (typeof window === 'undefined' || !el)
|
|
2656
|
+
return false;
|
|
2657
|
+
return !!el.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
|
|
2658
|
+
}
|
|
2659
|
+
/**
|
|
2660
|
+
* 添加 class 到元素
|
|
2661
|
+
* @param el - DOM 元素
|
|
2662
|
+
* @param cls - class 名称
|
|
2663
|
+
*/
|
|
2664
|
+
function addClass(el, cls) {
|
|
2665
|
+
if (typeof window === 'undefined' || !el)
|
|
2666
|
+
return;
|
|
2667
|
+
if (!hasClass(el, cls)) {
|
|
2668
|
+
el.className += ' ' + cls;
|
|
2669
|
+
}
|
|
2670
|
+
}
|
|
2671
|
+
/**
|
|
2672
|
+
* 从元素移除 class
|
|
2673
|
+
* @param el - DOM 元素
|
|
2674
|
+
* @param cls - class 名称
|
|
2675
|
+
*/
|
|
2676
|
+
function removeClass(el, cls) {
|
|
2677
|
+
if (typeof window === 'undefined' || !el)
|
|
2678
|
+
return;
|
|
2679
|
+
if (hasClass(el, cls)) {
|
|
2680
|
+
var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
|
|
2681
|
+
el.className = el.className.replace(reg, ' ').trim();
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
/**
|
|
2685
|
+
* 切换元素的 class
|
|
2686
|
+
* @param flag - 是否添加 class
|
|
2687
|
+
* @param clsName - class 名称
|
|
2688
|
+
* @param target - 目标元素,默认为 document.body
|
|
2689
|
+
*/
|
|
2690
|
+
function toggleClass(flag, clsName, target) {
|
|
2691
|
+
if (typeof window === 'undefined')
|
|
2692
|
+
return;
|
|
2693
|
+
var targetEl = target || document.body;
|
|
2694
|
+
var className = targetEl.className;
|
|
2695
|
+
className = className.replace(clsName, '').trim();
|
|
2696
|
+
targetEl.className = flag ? (className + " " + clsName).trim() : className;
|
|
2697
|
+
}
|
|
2698
|
+
/**
|
|
2699
|
+
* 打开链接
|
|
2700
|
+
* @param url - URL 地址
|
|
2701
|
+
* @param target - 打开方式,默认 "_blank"
|
|
2702
|
+
*/
|
|
2703
|
+
function openLink(url, target) {
|
|
2704
|
+
if (target === void 0) { target = '_blank'; }
|
|
2705
|
+
if (typeof window === 'undefined')
|
|
2706
|
+
return;
|
|
2707
|
+
var link = document.createElement('a');
|
|
2708
|
+
link.setAttribute('href', url);
|
|
2709
|
+
link.setAttribute('target', target);
|
|
2710
|
+
link.setAttribute('rel', 'noreferrer noopener');
|
|
2711
|
+
link.setAttribute('id', 'external');
|
|
2712
|
+
var existingLink = document.getElementById('external');
|
|
2713
|
+
if (existingLink) {
|
|
2714
|
+
document.body.removeChild(existingLink);
|
|
2715
|
+
}
|
|
2716
|
+
document.body.appendChild(link);
|
|
2717
|
+
link.click();
|
|
2718
|
+
link.remove();
|
|
2719
|
+
}
|
|
2720
|
+
/**
|
|
2721
|
+
* 复制文本到剪贴板
|
|
2722
|
+
* @param text - 要复制的文本
|
|
2723
|
+
* @returns 是否复制成功
|
|
2724
|
+
*/
|
|
2725
|
+
function copyTextToClipboard(text) {
|
|
2726
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
2727
|
+
return false;
|
|
2728
|
+
}
|
|
2729
|
+
// 创建临时文本框
|
|
2730
|
+
var textarea = document.createElement('textarea');
|
|
2731
|
+
var activeElement = document.activeElement;
|
|
2732
|
+
textarea.value = text;
|
|
2733
|
+
textarea.setAttribute('readonly', '');
|
|
2734
|
+
textarea.style.position = 'absolute';
|
|
2735
|
+
textarea.style.left = '-9999px';
|
|
2736
|
+
textarea.style.fontSize = '12pt';
|
|
2737
|
+
textarea.style.border = '0';
|
|
2738
|
+
textarea.style.padding = '0';
|
|
2739
|
+
textarea.style.margin = '0';
|
|
2740
|
+
// 保存当前选区
|
|
2741
|
+
var selection = document.getSelection();
|
|
2742
|
+
var originalRange = null;
|
|
2743
|
+
if (selection && selection.rangeCount > 0) {
|
|
2744
|
+
originalRange = selection.getRangeAt(0);
|
|
2745
|
+
}
|
|
2746
|
+
// 添加到 DOM 并选中
|
|
2747
|
+
document.body.appendChild(textarea);
|
|
2748
|
+
textarea.select();
|
|
2749
|
+
textarea.selectionStart = 0;
|
|
2750
|
+
textarea.selectionEnd = text.length;
|
|
2751
|
+
// 执行复制
|
|
2752
|
+
var success = false;
|
|
2753
|
+
try {
|
|
2754
|
+
success = document.execCommand('copy');
|
|
2755
|
+
}
|
|
2756
|
+
catch (err) {
|
|
2757
|
+
console.error('复制失败:', err);
|
|
2758
|
+
}
|
|
2759
|
+
// 清理
|
|
2760
|
+
textarea.remove();
|
|
2761
|
+
// 恢复原选区
|
|
2762
|
+
if (originalRange && selection) {
|
|
2763
|
+
selection.removeAllRanges();
|
|
2764
|
+
selection.addRange(originalRange);
|
|
2765
|
+
}
|
|
2766
|
+
// 恢复焦点
|
|
2767
|
+
if (activeElement) {
|
|
2768
|
+
activeElement.focus();
|
|
2769
|
+
}
|
|
2770
|
+
return success;
|
|
2771
|
+
}
|
|
2772
|
+
/**
|
|
2773
|
+
* 解析 SVG 字符串,提取宽度、高度和 body 内容
|
|
2774
|
+
* @param svg - SVG 字符串
|
|
2775
|
+
* @returns SVG 信息对象或原字符串
|
|
2776
|
+
*/
|
|
2777
|
+
function getSvgInfo(svg) {
|
|
2778
|
+
if (typeof window === 'undefined' || typeof DOMParser === 'undefined') {
|
|
2779
|
+
return svg;
|
|
2780
|
+
}
|
|
2781
|
+
try {
|
|
2782
|
+
var parser = new DOMParser();
|
|
2783
|
+
var doc = parser.parseFromString(svg, 'image/svg+xml');
|
|
2784
|
+
var svgElement = doc.querySelector('svg');
|
|
2785
|
+
if (!svgElement) {
|
|
2786
|
+
return svg;
|
|
2787
|
+
}
|
|
2788
|
+
var viewBox = svgElement.getAttribute('viewBox');
|
|
2789
|
+
if (!viewBox) {
|
|
2790
|
+
throw new Error('Invalid SVG string: Missing viewBox attribute.');
|
|
2791
|
+
}
|
|
2792
|
+
var viewBoxParts = viewBox.split(' ');
|
|
2793
|
+
var width = parseInt(viewBoxParts[2], 10);
|
|
2794
|
+
var height = parseInt(viewBoxParts[3], 10);
|
|
2795
|
+
var paths = Array.from(svgElement.querySelectorAll('path'));
|
|
2796
|
+
var body = paths.map(function (path) { return path.outerHTML; }).join(' ');
|
|
2797
|
+
return {
|
|
2798
|
+
width: width,
|
|
2799
|
+
height: height,
|
|
2800
|
+
body: body,
|
|
2801
|
+
};
|
|
2802
|
+
}
|
|
2803
|
+
catch (error) {
|
|
2804
|
+
console.error('解析 SVG 失败:', error);
|
|
2805
|
+
return svg;
|
|
2806
|
+
}
|
|
2807
|
+
}
|
|
2808
|
+
|
|
2809
|
+
var WebsocketManager = /** @class */ (function () {
|
|
2810
|
+
function WebsocketManager(options) {
|
|
2811
|
+
this.ws = null;
|
|
2812
|
+
this.reconnectAttempts = 0;
|
|
2813
|
+
this.heartbeatTimer = null;
|
|
2814
|
+
this.listeners = new Map();
|
|
2815
|
+
this.opts = {
|
|
2816
|
+
url: options.url,
|
|
2817
|
+
reconnectAttemptsLimit: options.reconnectAttemptsLimit || 5,
|
|
2818
|
+
reconnectInterval: options.reconnectInterval || 5000,
|
|
2819
|
+
heartbeatInterval: options.heartbeatInterval || 30000,
|
|
2820
|
+
registerMessage: options.registerMessage
|
|
2821
|
+
};
|
|
2822
|
+
}
|
|
2823
|
+
Object.defineProperty(WebsocketManager.prototype, "url", {
|
|
2824
|
+
get: function () {
|
|
2825
|
+
return this.opts.url;
|
|
2826
|
+
},
|
|
2827
|
+
enumerable: false,
|
|
2828
|
+
configurable: true
|
|
2829
|
+
});
|
|
2830
|
+
WebsocketManager.prototype.on = function (event, handler) {
|
|
2831
|
+
if (!this.listeners.has(event)) {
|
|
2832
|
+
this.listeners.set(event, new Set());
|
|
2833
|
+
}
|
|
2834
|
+
var set = this.listeners.get(event);
|
|
2835
|
+
set.add(handler);
|
|
2836
|
+
return function () { return set.delete(handler); };
|
|
2837
|
+
};
|
|
2838
|
+
WebsocketManager.prototype.emit = function (event, payload) {
|
|
2839
|
+
var set = this.listeners.get(event);
|
|
2840
|
+
if (!set)
|
|
2841
|
+
return;
|
|
2842
|
+
set.forEach(function (fn) {
|
|
2843
|
+
try {
|
|
2844
|
+
fn(payload);
|
|
2845
|
+
}
|
|
2846
|
+
catch (_a) { }
|
|
2847
|
+
});
|
|
2848
|
+
};
|
|
2849
|
+
WebsocketManager.prototype.connect = function () {
|
|
2850
|
+
try {
|
|
2851
|
+
this.ws = new WebSocket(this.opts.url);
|
|
2852
|
+
this.setupEventListeners();
|
|
2853
|
+
}
|
|
2854
|
+
catch (err) {
|
|
2855
|
+
this.emit('error', { message: 'WebSocket create failed' });
|
|
2856
|
+
}
|
|
2857
|
+
};
|
|
2858
|
+
WebsocketManager.prototype.setupEventListeners = function () {
|
|
2859
|
+
var _this = this;
|
|
2860
|
+
if (!this.ws)
|
|
2861
|
+
return;
|
|
2862
|
+
this.ws.onopen = function () {
|
|
2863
|
+
_this.reconnectAttempts = 0;
|
|
2864
|
+
if (_this.opts.registerMessage) {
|
|
2865
|
+
_this.send(_this.opts.registerMessage);
|
|
2866
|
+
}
|
|
2867
|
+
_this.startHeartbeat();
|
|
2868
|
+
_this.emit('connected', true);
|
|
2869
|
+
};
|
|
2870
|
+
this.ws.onmessage = function (event) {
|
|
2871
|
+
try {
|
|
2872
|
+
var data = JSON.parse(event.data);
|
|
2873
|
+
_this.emit('message', data);
|
|
2874
|
+
}
|
|
2875
|
+
catch (_a) {
|
|
2876
|
+
_this.emit('error', { message: 'Message parse failed' });
|
|
2877
|
+
}
|
|
2878
|
+
};
|
|
2879
|
+
this.ws.onclose = function () {
|
|
2880
|
+
_this.stopHeartbeat();
|
|
2881
|
+
_this.emit('connected', false);
|
|
2882
|
+
_this.emit('closed', undefined);
|
|
2883
|
+
_this.reconnect();
|
|
2884
|
+
};
|
|
2885
|
+
this.ws.onerror = function () {
|
|
2886
|
+
_this.emit('error', { message: 'WebSocket error' });
|
|
2887
|
+
};
|
|
2888
|
+
};
|
|
2889
|
+
WebsocketManager.prototype.send = function (data) {
|
|
2890
|
+
if (this.ws && this.ws.readyState === 1) {
|
|
2891
|
+
try {
|
|
2892
|
+
this.ws.send(JSON.stringify(data));
|
|
2893
|
+
}
|
|
2894
|
+
catch (_a) { }
|
|
2895
|
+
}
|
|
2896
|
+
};
|
|
2897
|
+
WebsocketManager.prototype.startHeartbeat = function () {
|
|
2898
|
+
var _this = this;
|
|
2899
|
+
this.stopHeartbeat();
|
|
2900
|
+
this.heartbeatTimer = setInterval(function () {
|
|
2901
|
+
_this.send({ type: 'ping' });
|
|
2902
|
+
}, this.opts.heartbeatInterval);
|
|
2903
|
+
};
|
|
2904
|
+
WebsocketManager.prototype.stopHeartbeat = function () {
|
|
2905
|
+
if (this.heartbeatTimer != null) {
|
|
2906
|
+
clearInterval(this.heartbeatTimer);
|
|
2907
|
+
this.heartbeatTimer = null;
|
|
2908
|
+
}
|
|
2909
|
+
};
|
|
2910
|
+
WebsocketManager.prototype.reconnect = function () {
|
|
2911
|
+
var _this = this;
|
|
2912
|
+
if (this.reconnectAttempts < this.opts.reconnectAttemptsLimit) {
|
|
2913
|
+
this.reconnectAttempts++;
|
|
2914
|
+
setTimeout(function () {
|
|
2915
|
+
_this.connect();
|
|
2916
|
+
}, this.opts.reconnectInterval);
|
|
2917
|
+
}
|
|
2918
|
+
};
|
|
2919
|
+
WebsocketManager.prototype.disconnect = function () {
|
|
2920
|
+
this.stopHeartbeat();
|
|
2921
|
+
if (this.ws) {
|
|
2922
|
+
try {
|
|
2923
|
+
this.ws.close();
|
|
2924
|
+
}
|
|
2925
|
+
catch (_a) { }
|
|
2926
|
+
}
|
|
2927
|
+
this.ws = null;
|
|
2928
|
+
};
|
|
2929
|
+
Object.defineProperty(WebsocketManager.prototype, "isConnected", {
|
|
2930
|
+
get: function () {
|
|
2931
|
+
return !!this.ws && this.ws.readyState === 1;
|
|
2932
|
+
},
|
|
2933
|
+
enumerable: false,
|
|
2934
|
+
configurable: true
|
|
2935
|
+
});
|
|
2936
|
+
return WebsocketManager;
|
|
2937
|
+
}());
|
|
2938
|
+
|
|
2939
|
+
var WebSocketService = /** @class */ (function () {
|
|
2940
|
+
function WebSocketService() {
|
|
2941
|
+
this.initialized = false;
|
|
2942
|
+
this.manager = null;
|
|
2943
|
+
}
|
|
2944
|
+
WebSocketService.getInstance = function () {
|
|
2945
|
+
if (!WebSocketService.instance) {
|
|
2946
|
+
WebSocketService.instance = new WebSocketService();
|
|
2947
|
+
}
|
|
2948
|
+
return WebSocketService.instance;
|
|
2949
|
+
};
|
|
2950
|
+
WebSocketService.prototype.init = function (options) {
|
|
2951
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
2952
|
+
return __generator(this, function (_a) {
|
|
2953
|
+
if (this.initialized)
|
|
2954
|
+
return [2 /*return*/];
|
|
2955
|
+
this.manager = new WebsocketManager(options);
|
|
2956
|
+
this.manager.connect();
|
|
2957
|
+
this.initialized = true;
|
|
2958
|
+
return [2 /*return*/];
|
|
2959
|
+
});
|
|
2960
|
+
});
|
|
2961
|
+
};
|
|
2962
|
+
WebSocketService.prototype.destroy = function () {
|
|
2963
|
+
this.manager && this.manager.disconnect();
|
|
2964
|
+
this.manager = null;
|
|
2965
|
+
this.initialized = false;
|
|
2966
|
+
};
|
|
2967
|
+
WebSocketService.prototype.getManager = function () {
|
|
2968
|
+
return this.manager;
|
|
2969
|
+
};
|
|
2970
|
+
return WebSocketService;
|
|
2971
|
+
}());
|
|
2972
|
+
var websocketService = WebSocketService.getInstance();
|
|
2973
|
+
|
|
2974
|
+
var Emitter = /** @class */ (function () {
|
|
2975
|
+
function Emitter() {
|
|
2976
|
+
this.listeners = new Map();
|
|
2977
|
+
}
|
|
2978
|
+
Emitter.prototype.on = function (event, handler) {
|
|
2979
|
+
if (!this.listeners.has(event)) {
|
|
2980
|
+
this.listeners.set(event, new Set());
|
|
2981
|
+
}
|
|
2982
|
+
var set = this.listeners.get(event);
|
|
2983
|
+
set.add(handler);
|
|
2984
|
+
return function () { return set.delete(handler); };
|
|
2985
|
+
};
|
|
2986
|
+
Emitter.prototype.off = function (event, handler) {
|
|
2987
|
+
var set = this.listeners.get(event);
|
|
2988
|
+
if (!set)
|
|
2989
|
+
return;
|
|
2990
|
+
set.delete(handler);
|
|
2991
|
+
};
|
|
2992
|
+
Emitter.prototype.emit = function (event, payload) {
|
|
2993
|
+
var set = this.listeners.get(event);
|
|
2994
|
+
if (!set)
|
|
2995
|
+
return;
|
|
2996
|
+
set.forEach(function (fn) {
|
|
2997
|
+
try {
|
|
2998
|
+
fn(payload);
|
|
2999
|
+
}
|
|
3000
|
+
catch (_a) { }
|
|
3001
|
+
});
|
|
3002
|
+
};
|
|
3003
|
+
return Emitter;
|
|
3004
|
+
}());
|
|
3005
|
+
var emitter = new Emitter();
|
|
3006
|
+
|
|
3007
|
+
var createWebSocketStore = function (storeId) {
|
|
3008
|
+
if (storeId === void 0) { storeId = 'websocket'; }
|
|
3009
|
+
return pinia.defineStore(storeId, {
|
|
3010
|
+
state: function () { return ({
|
|
3011
|
+
isConnected: false,
|
|
3012
|
+
wsManager: null,
|
|
3013
|
+
messages: [],
|
|
3014
|
+
connectionError: null
|
|
3015
|
+
}); },
|
|
3016
|
+
getters: {
|
|
3017
|
+
connectionStatus: function (state) { return (state.isConnected ? '已连接' : '未连接'); },
|
|
3018
|
+
lastMessage: function (state) { return state.messages[state.messages.length - 1] || null; }
|
|
3019
|
+
},
|
|
3020
|
+
actions: {
|
|
3021
|
+
connect: function (options) {
|
|
3022
|
+
var _a;
|
|
3023
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
3024
|
+
return __generator(this, function (_b) {
|
|
3025
|
+
if ((_a = this.wsManager) === null || _a === void 0 ? void 0 : _a.isConnected)
|
|
3026
|
+
return [2 /*return*/];
|
|
3027
|
+
this.wsManager = new WebsocketManager(options);
|
|
3028
|
+
this.setupEventListeners();
|
|
3029
|
+
this.wsManager.connect();
|
|
3030
|
+
return [2 /*return*/];
|
|
3031
|
+
});
|
|
3032
|
+
});
|
|
3033
|
+
},
|
|
3034
|
+
setupEventListeners: function () {
|
|
3035
|
+
var _this = this;
|
|
3036
|
+
if (!this.wsManager)
|
|
3037
|
+
return;
|
|
3038
|
+
this.wsManager.on('connected', function (status) {
|
|
3039
|
+
_this.isConnected = status;
|
|
3040
|
+
if (status)
|
|
3041
|
+
_this.connectionError = null;
|
|
3042
|
+
emitter.emit('websocket-connected', status);
|
|
3043
|
+
});
|
|
3044
|
+
this.wsManager.on('message', function (data) {
|
|
3045
|
+
_this.addMessage(data);
|
|
3046
|
+
emitter.emit('websocket-message', data);
|
|
3047
|
+
});
|
|
3048
|
+
this.wsManager.on('error', function (error) {
|
|
3049
|
+
_this.connectionError = (error === null || error === void 0 ? void 0 : error.message) || 'WebSocket error';
|
|
3050
|
+
emitter.emit('websocket-error', { message: _this.connectionError });
|
|
3051
|
+
});
|
|
3052
|
+
this.wsManager.on('closed', function () {
|
|
3053
|
+
_this.isConnected = false;
|
|
3054
|
+
emitter.emit('websocket-closed', undefined);
|
|
3055
|
+
});
|
|
3056
|
+
},
|
|
3057
|
+
sendMessage: function (data) {
|
|
3058
|
+
var _a;
|
|
3059
|
+
(_a = this.wsManager) === null || _a === void 0 ? void 0 : _a.send(data);
|
|
3060
|
+
},
|
|
3061
|
+
addMessage: function (message) {
|
|
3062
|
+
var msg = __assign(__assign({}, message), { timestamp: Date.now(), id: Math.random().toString(36).substring(2, 11) });
|
|
3063
|
+
this.messages.push(msg);
|
|
3064
|
+
if (this.messages.length > 100) {
|
|
3065
|
+
this.messages.shift();
|
|
3066
|
+
}
|
|
3067
|
+
},
|
|
3068
|
+
clearMessages: function () {
|
|
3069
|
+
this.messages = [];
|
|
3070
|
+
},
|
|
3071
|
+
disconnect: function () {
|
|
3072
|
+
var _a;
|
|
3073
|
+
(_a = this.wsManager) === null || _a === void 0 ? void 0 : _a.disconnect();
|
|
3074
|
+
this.wsManager = null;
|
|
3075
|
+
this.isConnected = false;
|
|
3076
|
+
this.connectionError = null;
|
|
3077
|
+
},
|
|
3078
|
+
reset: function () {
|
|
3079
|
+
this.disconnect();
|
|
3080
|
+
this.clearMessages();
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
});
|
|
3084
|
+
};
|
|
3085
|
+
|
|
3086
|
+
exports.ApiBuilder = ApiBuilder;
|
|
3087
|
+
exports.InsertBuilder = InsertBuilder;
|
|
3088
|
+
exports.QueryBuilder = QueryBuilder;
|
|
3089
|
+
exports.UpdateBuilder = UpdateBuilder;
|
|
3090
|
+
exports.WebsocketManager = WebsocketManager;
|
|
3091
|
+
exports.addClass = addClass;
|
|
3092
|
+
exports.addDays = addDays;
|
|
3093
|
+
exports.base64ToBlob = base64ToBlob;
|
|
3094
|
+
exports.base64ToFile = base64ToFile;
|
|
3095
|
+
exports.base64ToFileOrBlob = base64ToFileOrBlob;
|
|
3096
|
+
exports.blobToDataURL = blobToDataURL;
|
|
3097
|
+
exports.buildUUID = buildUUID;
|
|
3098
|
+
exports.calcFileSize = calcFileSize;
|
|
3099
|
+
exports.ceil = ceil;
|
|
3100
|
+
exports.clearLoginData = clearLoginData;
|
|
3101
|
+
exports.compatibleDate = compatibleDate;
|
|
3102
|
+
exports.compressImg = compressImg;
|
|
3103
|
+
exports.computeMoney = computeMoney;
|
|
3104
|
+
exports.convertBase64UrlToBlob = convertBase64UrlToBlob;
|
|
3105
|
+
exports.convertCurrency = convertCurrency;
|
|
3106
|
+
exports.copyTextToClipboard = copyTextToClipboard;
|
|
3107
|
+
exports.createWebSocketStore = createWebSocketStore;
|
|
3108
|
+
exports.darken = darken;
|
|
3109
|
+
exports.dataURLtoBlob = dataURLtoBlob;
|
|
3110
|
+
exports.deepEqual = deepEqual;
|
|
3111
|
+
exports.delay = delay;
|
|
3112
|
+
exports.deviceDetection = deviceDetection;
|
|
3113
|
+
exports.emitter = emitter;
|
|
3114
|
+
exports.fileSizeFormat = fileSizeFormat;
|
|
3115
|
+
exports.filterRepeat = filterRepeat;
|
|
3116
|
+
exports.findNodePath = findNodePath;
|
|
3117
|
+
exports.floor = floor;
|
|
3118
|
+
exports.formatBank = formatBank;
|
|
3119
|
+
exports.formatBytes = formatBytes;
|
|
3120
|
+
exports.formatCentsToYuan = formatCentsToYuan;
|
|
3121
|
+
exports.formatEmptyValue = formatEmptyValue;
|
|
3122
|
+
exports.formatFloat = formatFloat;
|
|
3123
|
+
exports.formatMoney = formatMoney;
|
|
3124
|
+
exports.formatPhone = formatPhone;
|
|
3125
|
+
exports.formatPhoneHide = formatPhoneHide;
|
|
3126
|
+
exports.formatTime = formatTime;
|
|
3127
|
+
exports.formateTimestamp = formateTimestamp;
|
|
3128
|
+
exports.fromNow = fromNow;
|
|
3129
|
+
exports.genExportByBlob = genExportByBlob;
|
|
3130
|
+
exports.generateEnglishLetters = generateEnglishLetters;
|
|
3131
|
+
exports.getCookie = getCookie;
|
|
3132
|
+
exports.getDeviceType = getDeviceType;
|
|
3133
|
+
exports.getEnvironment = getEnvironment;
|
|
3134
|
+
exports.getFileData = getFileData;
|
|
3135
|
+
exports.getFromType = getFromType;
|
|
3136
|
+
exports.getIsComWx = getIsComWx;
|
|
3137
|
+
exports.getIsDevelopment = getIsDevelopment;
|
|
3138
|
+
exports.getKeyList = getKeyList;
|
|
3139
|
+
exports.getQueryMap = getQueryMap;
|
|
3140
|
+
exports.getQueryString = getQueryString;
|
|
3141
|
+
exports.getQueryVariable = getQueryVariable;
|
|
3142
|
+
exports.getSvgInfo = getSvgInfo;
|
|
3143
|
+
exports.getTicket = getTicket;
|
|
3144
|
+
exports.getToken = getToken;
|
|
3145
|
+
exports.getWecomToken = getWecomToken;
|
|
3146
|
+
exports.handleFlatStr = handleFlatStr;
|
|
3147
|
+
exports.hasClass = hasClass;
|
|
3148
|
+
exports.hexToRgb = hexToRgb;
|
|
3149
|
+
exports.hideTextAtIndex = hideTextAtIndex;
|
|
3150
|
+
exports.http = http;
|
|
3151
|
+
exports.httpEnum = httpEnum;
|
|
3152
|
+
exports.humpTurnDashed = humpTurnDashed;
|
|
3153
|
+
exports.intersection = intersection;
|
|
3154
|
+
exports.isAllEmpty = isAllEmpty;
|
|
3155
|
+
exports.isEmail = isEmail;
|
|
3156
|
+
exports.isEmpty = isEmpty;
|
|
3157
|
+
exports.isExternal = isExternal;
|
|
3158
|
+
exports.isImage = isImage;
|
|
3159
|
+
exports.isIncludeAllChildren = isIncludeAllChildren;
|
|
3160
|
+
exports.isMobile = isMobile;
|
|
3161
|
+
exports.isMobileSimple = isMobileSimple;
|
|
3162
|
+
exports.isPhone = isPhone;
|
|
3163
|
+
exports.isQQ = isQQ;
|
|
3164
|
+
exports.isTelephone = isTelephone;
|
|
3165
|
+
exports.isUrl = isUrl;
|
|
3166
|
+
exports.lighten = lighten;
|
|
3167
|
+
exports.newDate = newDate;
|
|
3168
|
+
exports.openLink = openLink;
|
|
3169
|
+
exports.randomString = randomString;
|
|
3170
|
+
exports.recordLogMiddleware = recordLogMiddleware;
|
|
3171
|
+
exports.recordLogMiddlewareFastify = recordLogMiddlewareFastify;
|
|
3172
|
+
exports.recordLogMiddlewareHono = recordLogMiddlewareHono;
|
|
3173
|
+
exports.recordLogMiddlewareKoa = recordLogMiddlewareKoa;
|
|
3174
|
+
exports.recordLogMiddlewareMidway = recordLogMiddlewareMidway;
|
|
3175
|
+
exports.removeClass = removeClass;
|
|
3176
|
+
exports.removeTicket = removeTicket;
|
|
3177
|
+
exports.removeToken = removeToken;
|
|
3178
|
+
exports.rgbToHex = rgbToHex;
|
|
3179
|
+
exports.sendLog = sendLog;
|
|
3180
|
+
exports.setTicket = setTicket;
|
|
3181
|
+
exports.subBefore = subBefore;
|
|
3182
|
+
exports.sum = sum;
|
|
3183
|
+
exports.toThousands = toThousands;
|
|
3184
|
+
exports.toggleClass = toggleClass;
|
|
3185
|
+
exports.trimVal = trimVal;
|
|
3186
|
+
exports.uuid = uuid;
|
|
3187
|
+
exports.validateTwoDecimal = validateTwoDecimal;
|
|
3188
|
+
exports.websocketService = websocketService;
|
|
3189
|
+
|
|
3190
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3191
|
+
|
|
3192
|
+
}));
|