js工具库

type 类型判断

数值相关

截断数字

将小数点后的某些数字截断而不取四舍五入

1
2
3
4
export const toFixed = (n, fixed) =>
`${n}`.match(new RegExp(`^-?\d+(?:.\d{0,${fixed}})?`))[0];

toFixed(10.255, 2); // 10.25

四舍五入

将小数点后的某些数字截断,并取四舍五入

1
2
3
4
export const round = (n, decimals = 0) =>
Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`);

round(10.255, 2); // 10.26

进制转换

toString(n)

将 10 进制转换成 n 进制

1
2
3
export const toDecimal = (num, n = 10) => num.toString(n);
// 假设数字10要转换成2进制
toDecimal(10, 2); // '1010'

parseInt(num, n)

将 n 进制转换成 10 进制

1
2
3
4
// 10 的 2 进制为1010
export const toDecimalism = (num, n = 10) => parseInt(num, n);

toDecimalism(1010, 2);

整数前补 0

1
2
3
4
5
6
7
8
9
/**
* 整数前补0
* @param {Number} num 数字
* @param {Number} n 保留位数
*/
export const prefixZero = (num, n = 2) => (Array(n).join("0") + num).slice(-n);

export const prefixZero = (num, len, zero = 0) =>
num.toString().padStart(len, zero);

数字格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 格式化数字(四舍五入)
* @param {Number} val 数字
* @param {Number} num 小数点保留位数(noZero为true时该字段为最大位数)
* @param {Boolean} noZero 是否去除小数点末尾0
* @param {String} placeholder val不存在时显示的占位符
*/
export function numF(val, num = 4, noZero = false, placeholder = "--") {
if (isNaN(val) || (!val && val !== 0)) return placeholder;
val = val ? Number(val).toFixed(num) : 0;

// 整数部分
var intFormat = String(parseInt(val)).replace(/(\d)(?=(?:\d{3})+$)/g, "$1,"); // 千分位

// 小数部分
var floatNum = String(noZero ? Number(val) : val).split(".")[1] || "";

return intFormat + (floatNum ? "." + floatNum : "");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* 格式化数字(超出保留位数直接截断)
* @val {Number} 数字
* @num {Number} 小数点保留位数(noZero为true时该字段为最大位数)
* @noZero {Boolean} 是否去除小数点末尾0
* @placeholder {String} val 不存在时显示的占位符
* @comma {Boolean} 是否用逗号隔开
*/
export function numF(
val,
num = 4,
noZero = false,
placeholder = "--",
comma = true
) {
if (isNaN(val) || (!val && val !== 0)) return placeholder;
val = Number(val) + "";
var pointInd = val.lastIndexOf(".");
val = val
? pointInd > -1
? Number(val.substring(0, val.lastIndexOf(".") + num + 1))
: Number(val)
: 0;

let commaFormat = comma ? "," : "";
// 整数部分
var intFormat = String(parseInt(val)).replace(
/(\d)(?=(?:\d{3})+$)/g,
"$1" + commaFormat
); // 千分位

// 小数部分
var floatVal = String(Number(val)).split(".")[1] || "";

var floatNum = floatVal || "";
if (!noZero) {
floatNum = floatVal.padEnd(num, 0);
}
return intFormat + (floatNum ? "." + floatNum : "");
}

生成并返回一个从 m 到 n 全区间的随机数

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 生成并返回一个从m到n全区间的随机数
* @param m 开始(含)
* @param n 结束(含)
*/
export function randomNum(m = 1, n = 100) {
if (min >= 0 && max > 0 && max >= min) {
return Math.floor(Math.random() * (n - m + 1) + m);
} else {
return 0;
}
}

字符串相关

手机号脱敏

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 手机号脱敏
* @mobile {String} 手机号
*/
export function mobileF(mobile) {
if (mobile && mobile.length == 11) {
var pat = /(\d{3})\d*(\d{4})/;
return mobile.replace(pat, "$1****$2");
} else {
return "";
}
}

去除空格

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 去除空格
* @param {string} str 需要去除空格的字符串
* @param {both | left | right | all} pos 需要去除空格的位置
* @returns
*/
export function trim(str, pos = "both") {
if (pos == "both") {
return str.replace(/^\s+|\s+$/g, "");
} else if (pos == "left") {
return str.replace(/^\s*/, "");
} else if (pos == "right") {
return str.replace(/(\s*$)/g, "");
} else if (pos == "all") {
return str.replace(/\s+/g, "");
} else {
return str;
}
}

字符串表达式计算

1
2
3
4
5
6
7
8
9
/**
* 字符串表达式计算
* @expression {String} 字符串表达式
* 例:evil("2+3") // 5
*/
export function evil(expression) {
const Fn = Function;
return new Fn("return " + expression)();
}

判断回文字符串(对称字符串)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 字符串表达式计算
* @str {String} 需要判断的字符串
* 例:isReserveSame("cbdcbc") // false
*/
export function isReserveSame(str) {
if (str[0] == str[str.length - 1]) {
//头尾字符相同
if (str.length <= 3) {
//三个字符及以下则对称
return true;
} else {
str = str.substring(1, str.length - 1); //截取去掉头尾后的子串
return isReserveSame(str); //递归继续判断
}
} else {
return false; //头尾不同时
}
}

随机生成一串字符串

1
2
3
4
5
6
7
8
export function randomStr(len = 6) {
let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
let l = str.length;
let pwd = "";
for (let i = 0; i < len; i++)
pwd += str.charAt(Math.floor(Math.random() * l));
return pwd;
}

输出字符串中每个字符出现的次数

1
2
3
4
5
export function getStatistics(str) {
return str.split("").reduce((p, k) => (p[k]++ || (p[k] = 1), p), {});
}

getStatistics("abcdaabc"); // { a: 3, b: 2, c: 2, d: 1 }

获取字符串的字节长度

1
2
3
4
export function getBytes(s) {
s = String(s);
return s.length + (s.match(/[^\x00-\xff]/g) || "").length; // 加上匹配到的全角字符长度
}

获取首字母

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
export function checkChar(str) {
str = str.replace(/(^\s*)|(\s*$)/g, "");
if (!str) return;
if (checkEn(str)) {
return str.slice(0, 1);
}

const strChineseFirstPY =
"YDYQSXMWZSSXJBYMGCCZQPSSQBYCDSCDQLDYLYBSSJGYZZJJFKCCLZDHWDWZJLJPFYYNWJJTMYHZWZHFLZPPQHGSCYYYNJQYXXGJHHSDSJNKKTMOMLCRXYPSNQSECCQZGGLLYJLMYZZSECYKYYHQWJSSGGYXYZYJWWKDJHYCHMYXJTLXJYQBYXZLDWRDJRWYSRLDZJPCBZJJBRCFTLECZSTZFXXZHTRQHYBDLYCZSSYMMRFMYQZPWWJJYFCRWFDFZQPYDDWYXKYJAWJFFXYPSFTZYHHYZYSWCJYXSCLCXXWZZXNBGNNXBXLZSZSBSGPYSYZDHMDZBQBZCWDZZYYTZHBTSYYBZGNTNXQYWQSKBPHHLXGYBFMJEBJHHGQTJCYSXSTKZHLYCKGLYSMZXYALMELDCCXGZYRJXSDLTYZCQKCNNJWHJTZZCQLJSTSTBNXBTYXCEQXGKWJYFLZQLYHYXSPSFXLMPBYSXXXYDJCZYLLLSJXFHJXPJBTFFYABYXBHZZBJYZLWLCZGGBTSSMDTJZXPTHYQTGLJSCQFZKJZJQNLZWLSLHDZBWJNCJZYZSQQYCQYRZCJJWYBRTWPYFTWEXCSKDZCTBZHYZZYYJXZCFFZZMJYXXSDZZOTTBZLQWFCKSZSXFYRLNYJMBDTHJXSQQCCSBXYYTSYFBXDZTGBCNSLCYZZPSAZYZZSCJCSHZQYDXLBPJLLMQXTYDZXSQJTZPXLCGLQTZWJBHCTSYJSFXYEJJTLBGXSXJMYJQQPFZASYJNTYDJXKJCDJSZCBARTDCLYJQMWNQNCLLLKBYBZZSYHQQLTWLCCXTXLLZNTYLNEWYZYXCZXXGRKRMTCNDNJTSYYSSDQDGHSDBJGHRWRQLYBGLXHLGTGXBQJDZPYJSJYJCTMRNYMGRZJCZGJMZMGXMPRYXKJNYMSGMZJYMKMFXMLDTGFBHCJHKYLPFMDXLQJJSMTQGZSJLQDLDGJYCALCMZCSDJLLNXDJFFFFJCZFMZFFPFKHKGDPSXKTACJDHHZDDCRRCFQYJKQCCWJDXHWJLYLLZGCFCQDSMLZPBJJPLSBCJGGDCKKDEZSQCCKJGCGKDJTJDLZYCXKLQSCGJCLTFPCQCZGWPJDQYZJJBYJHSJDZWGFSJGZKQCCZLLPSPKJGQJHZZLJPLGJGJJTHJJYJZCZMLZLYQBGJWMLJKXZDZNJQSYZMLJLLJKYWXMKJLHSKJGBMCLYYMKXJQLBMLLKMDXXKWYXYSLMLPSJQQJQXYXFJTJDXMXXLLCXQBSYJBGWYMBGGBCYXPJYGPEPFGDJGBHBNSQJYZJKJKHXQFGQZKFHYGKHDKLLSDJQXPQYKYBNQSXQNSZSWHBSXWHXWBZZXDMNSJBSBKBBZKLYLXGWXDRWYQZMYWSJQLCJXXJXKJEQXSCYETLZHLYYYSDZPAQYZCMTLSHTZCFYZYXYLJSDCJQAGYSLCQLYYYSHMRQQKLDXZSCSSSYDYCJYSFSJBFRSSZQSBXXPXJYSDRCKGJLGDKZJZBDKTCSYQPYHSTCLDJDHMXMCGXYZHJDDTMHLTXZXYLYMOHYJCLTYFBQQXPFBDFHHTKSQHZYYWCNXXCRWHOWGYJLEGWDQCWGFJYCSNTMYTOLBYGWQWESJPWNMLRYDZSZTXYQPZGCWXHNGPYXSHMYQJXZTDPPBFYHZHTJYFDZWKGKZBLDNTSXHQEEGZZYLZMMZYJZGXZXKHKSTXNXXWYLYAPSTHXDWHZYMPXAGKYDXBHNHXKDPJNMYHYLPMGOCSLNZHKXXLPZZLBMLSFBHHGYGYYGGBHSCYAQTYWLXTZQCEZYDQDQMMHTKLLSZHLSJZWFYHQSWSCWLQAZYNYTLSXTHAZNKZZSZZLAXXZWWCTGQQTDDYZTCCHYQZFLXPSLZYGPZSZNGLNDQTBDLXGTCTAJDKYWNSYZLJHHZZCWNYYZYWMHYCHHYXHJKZWSXHZYXLYSKQYSPSLYZWMYPPKBYGLKZHTYXAXQSYSHXASMCHKDSCRSWJPWXSGZJLWWSCHSJHSQNHCSEGNDAQTBAALZZMSSTDQJCJKTSCJAXPLGGXHHGXXZCXPDMMHLDGTYBYSJMXHMRCPXXJZCKZXSHMLQXXTTHXWZFKHCCZDYTCJYXQHLXDHYPJQXYLSYYDZOZJNYXQEZYSQYAYXWYPDGXDDXSPPYZNDLTWRHXYDXZZJHTCXMCZLHPYYYYMHZLLHNXMYLLLMDCPPXHMXDKYCYRDLTXJCHHZZXZLCCLYLNZSHZJZZLNNRLWHYQSNJHXYNTTTKYJPYCHHYEGKCTTWLGQRLGGTGTYGYHPYHYLQYQGCWYQKPYYYTTTTLHYHLLTYTTSPLKYZXGZWGPYDSSZZDQXSKCQNMJJZZBXYQMJRTFFBTKHZKBXLJJKDXJTLBWFZPPTKQTZTGPDGNTPJYFALQMKGXBDCLZFHZCLLLLADPMXDJHLCCLGYHDZFGYDDGCYYFGYDXKSSEBDHYKDKDKHNAXXYBPBYYHXZQGAFFQYJXDMLJCSQZLLPCHBSXGJYNDYBYQSPZWJLZKSDDTACTBXZDYZYPJZQSJNKKTKNJDJGYYPGTLFYQKASDNTCYHBLWDZHBBYDWJRYGKZYHEYYFJMSDTYFZJJHGCXPLXHLDWXXJKYTCYKSSSMTWCTTQZLPBSZDZWZXGZAGYKTYWXLHLSPBCLLOQMMZSSLCMBJCSZZKYDCZJGQQDSMCYTZQQLWZQZXSSFPTTFQMDDZDSHDTDWFHTDYZJYQJQKYPBDJYYXTLJHDRQXXXHAYDHRJLKLYTWHLLRLLRCXYLBWSRSZZSYMKZZHHKYHXKSMDSYDYCJPBZBSQLFCXXXNXKXWYWSDZYQOGGQMMYHCDZTTFJYYBGSTTTYBYKJDHKYXBELHTYPJQNFXFDYKZHQKZBYJTZBXHFDXKDASWTAWAJLDYJSFHBLDNNTNQJTJNCHXFJSRFWHZFMDRYJYJWZPDJKZYJYMPCYZNYNXFBYTFYFWYGDBNZZZDNYTXZEMMQBSQEHXFZMBMFLZZSRXYMJGSXWZJSPRYDJSJGXHJJGLJJYNZZJXHGXKYMLPYYYCXYTWQZSWHWLYRJLPXSLSXMFSWWKLCTNXNYNPSJSZHDZEPTXMYYWXYYSYWLXJQZQXZDCLEEELMCPJPCLWBXSQHFWWTFFJTNQJHJQDXHWLBYZNFJLALKYYJLDXHHYCSTYYWNRJYXYWTRMDRQHWQCMFJDYZMHMYYXJWMYZQZXTLMRSPWWCHAQBXYGZYPXYYRRCLMPYMGKSJSZYSRMYJSNXTPLNBAPPYPYLXYYZKYNLDZYJZCZNNLMZHHARQMPGWQTZMXXMLLHGDZXYHXKYXYCJMFFYYHJFSBSSQLXXNDYCANNMTCJCYPRRNYTYQNYYMBMSXNDLYLYSLJRLXYSXQMLLYZLZJJJKYZZCSFBZXXMSTBJGNXYZHLXNMCWSCYZYFZLXBRNNNYLBNRTGZQYSATSWRYHYJZMZDHZGZDWYBSSCSKXSYHYTXXGCQGXZZSHYXJSCRHMKKBXCZJYJYMKQHZJFNBHMQHYSNJNZYBKNQMCLGQHWLZNZSWXKHLJHYYBQLBFCDSXDLDSPFZPSKJYZWZXZDDXJSMMEGJSCSSMGCLXXKYYYLNYPWWWGYDKZJGGGZGGSYCKNJWNJPCXBJJTQTJWDSSPJXZXNZXUMELPXFSXTLLXCLJXJJLJZXCTPSWXLYDHLYQRWHSYCSQYYBYAYWJJJQFWQCQQCJQGXALDBZZYJGKGXPLTZYFXJLTPADKYQHPMATLCPDCKBMTXYBHKLENXDLEEGQDYMSAWHZMLJTWYGXLYQZLJEEYYBQQFFNLYXRDSCTGJGXYYNKLLYQKCCTLHJLQMKKZGCYYGLLLJDZGYDHZWXPYSJBZKDZGYZZHYWYFQYTYZSZYEZZLYMHJJHTSMQWYZLKYYWZCSRKQYTLTDXWCTYJKLWSQZWBDCQYNCJSRSZJLKCDCDTLZZZACQQZZDDXYPLXZBQJYLZLLLQDDZQJYJYJZYXNYYYNYJXKXDAZWYRDLJYYYRJLXLLDYXJCYWYWNQCCLDDNYYYNYCKCZHXXCCLGZQJGKWPPCQQJYSBZZXYJSQPXJPZBSBDSFNSFPZXHDWZTDWPPTFLZZBZDMYYPQJRSDZSQZSQXBDGCPZSWDWCSQZGMDHZXMWWFYBPDGPHTMJTHZSMMBGZMBZJCFZWFZBBZMQCFMBDMCJXLGPNJBBXGYHYYJGPTZGZMQBQTCGYXJXLWZKYDPDYMGCFTPFXYZTZXDZXTGKMTYBBCLBJASKYTSSQYYMSZXFJEWLXLLSZBQJJJAKLYLXLYCCTSXMCWFKKKBSXLLLLJYXTYLTJYYTDPJHNHNNKBYQNFQYYZBYYESSESSGDYHFHWTCJBSDZZTFDMXHCNJZYMQWSRYJDZJQPDQBBSTJGGFBKJBXTGQHNGWJXJGDLLTHZHHYYYYYYSXWTYYYCCBDBPYPZYCCZYJPZYWCBDLFWZCWJDXXHYHLHWZZXJTCZLCDPXUJCZZZLYXJJTXPHFXWPYWXZPTDZZBDZCYHJHMLXBQXSBYLRDTGJRRCTTTHYTCZWMXFYTWWZCWJWXJYWCSKYBZSCCTZQNHXNWXXKHKFHTSWOCCJYBCMPZZYKBNNZPBZHHZDLSYDDYTYFJPXYNGFXBYQXCBHXCPSXTYZDMKYSNXSXLHKMZXLYHDHKWHXXSSKQYHHCJYXGLHZXCSNHEKDTGZXQYPKDHEXTYKCNYMYYYPKQYYYKXZLTHJQTBYQHXBMYHSQCKWWYLLHCYYLNNEQXQWMCFBDCCMLJGGXDQKTLXKGNQCDGZJWYJJLYHHQTTTNWCHMXCXWHWSZJYDJCCDBQCDGDNYXZTHCQRXCBHZTQCBXWGQWYYBXHMBYMYQTYEXMQKYAQYRGYZSLFYKKQHYSSQYSHJGJCNXKZYCXSBXYXHYYLSTYCXQTHYSMGSCPMMGCCCCCMTZTASMGQZJHKLOSQYLSWTMXSYQKDZLJQQYPLSYCZTCQQPBBQJZCLPKHQZYYXXDTDDTSJCXFFLLCHQXMJLWCJCXTSPYCXNDTJSHJWXDQQJSKXYAMYLSJHMLALYKXCYYDMNMDQMXMCZNNCYBZKKYFLMCHCMLHXRCJJHSYLNMTJZGZGYWJXSRXCWJGJQHQZDQJDCJJZKJKGDZQGJJYJYLXZXXCDQHHHEYTMHLFSBDJSYYSHFYSTCZQLPBDRFRZTZYKYWHSZYQKWDQZRKMSYNBCRXQBJYFAZPZZEDZCJYWBCJWHYJBQSZYWRYSZPTDKZPFPBNZTKLQYHBBZPNPPTYZZYBQNYDCPJMMCYCQMCYFZZDCMNLFPBPLNGQJTBTTNJZPZBBZNJKLJQYLNBZQHKSJZNGGQSZZKYXSHPZSNBCGZKDDZQANZHJKDRTLZLSWJLJZLYWTJNDJZJHXYAYNCBGTZCSSQMNJPJYTYSWXZFKWJQTKHTZPLBHSNJZSYZBWZZZZLSYLSBJHDWWQPSLMMFBJDWAQYZTCJTBNNWZXQXCDSLQGDSDPDZHJTQQPSWLYYJZLGYXYZLCTCBJTKTYCZJTQKBSJLGMGZDMCSGPYNJZYQYYKNXRPWSZXMTNCSZZYXYBYHYZAXYWQCJTLLCKJJTJHGDXDXYQYZZBYWDLWQCGLZGJGQRQZCZSSBCRPCSKYDZNXJSQGXSSJMYDNSTZTPBDLTKZWXQWQTZEXNQCZGWEZKSSBYBRTSSSLCCGBPSZQSZLCCGLLLZXHZQTHCZMQGYZQZNMCOCSZJMMZSQPJYGQLJYJPPLDXRGZYXCCSXHSHGTZNLZWZKJCXTCFCJXLBMQBCZZWPQDNHXLJCTHYZLGYLNLSZZPCXDSCQQHJQKSXZPBAJYEMSMJTZDXLCJYRYYNWJBNGZZTMJXLTBSLYRZPYLSSCNXPHLLHYLLQQZQLXYMRSYCXZLMMCZLTZSDWTJJLLNZGGQXPFSKYGYGHBFZPDKMWGHCXMSGDXJMCJZDYCABXJDLNBCDQYGSKYDQTXDJJYXMSZQAZDZFSLQXYJSJZYLBTXXWXQQZBJZUFBBLYLWDSLJHXJYZJWTDJCZFQZQZZDZSXZZQLZCDZFJHYSPYMPQZMLPPLFFXJJNZZYLSJEYQZFPFZKSYWJJJHRDJZZXTXXGLGHYDXCSKYSWMMZCWYBAZBJKSHFHJCXMHFQHYXXYZFTSJYZFXYXPZLCHMZMBXHZZSXYFYMNCWDABAZLXKTCSHHXKXJJZJSTHYGXSXYYHHHJWXKZXSSBZZWHHHCWTZZZPJXSNXQQJGZYZYWLLCWXZFXXYXYHXMKYYSWSQMNLNAYCYSPMJKHWCQHYLAJJMZXHMMCNZHBHXCLXTJPLTXYJHDYYLTTXFSZHYXXSJBJYAYRSMXYPLCKDUYHLXRLNLLSTYZYYQYGYHHSCCSMZCTZQXKYQFPYYRPFFLKQUNTSZLLZMWWTCQQYZWTLLMLMPWMBZSSTZRBPDDTLQJJBXZCSRZQQYGWCSXFWZLXCCRSZDZMCYGGDZQSGTJSWLJMYMMZYHFBJDGYXCCPSHXNZCSBSJYJGJMPPWAFFYFNXHYZXZYLREMZGZCYZSSZDLLJCSQFNXZKPTXZGXJJGFMYYYSNBTYLBNLHPFZDCYFBMGQRRSSSZXYSGTZRNYDZZCDGPJAFJFZKNZBLCZSZPSGCYCJSZLMLRSZBZZLDLSLLYSXSQZQLYXZLSKKBRXBRBZCYCXZZZEEYFGKLZLYYHGZSGZLFJHGTGWKRAAJYZKZQTSSHJJXDCYZUYJLZYRZDQQHGJZXSSZBYKJPBFRTJXLLFQWJHYLQTYMBLPZDXTZYGBDHZZRBGXHWNJTJXLKSCFSMWLSDQYSJTXKZSCFWJLBXFTZLLJZLLQBLSQMQQCGCZFPBPHZCZJLPYYGGDTGWDCFCZQYYYQYSSCLXZSKLZZZGFFCQNWGLHQYZJJCZLQZZYJPJZZBPDCCMHJGXDQDGDLZQMFGPSYTSDYFWWDJZJYSXYYCZCYHZWPBYKXRYLYBHKJKSFXTZJMMCKHLLTNYYMSYXYZPYJQYCSYCWMTJJKQYRHLLQXPSGTLYYCLJSCPXJYZFNMLRGJJTYZBXYZMSJYJHHFZQMSYXRSZCWTLRTQZSSTKXGQKGSPTGCZNJSJCQCXHMXGGZTQYDJKZDLBZSXJLHYQGGGTHQSZPYHJHHGYYGKGGCWJZZYLCZLXQSFTGZSLLLMLJSKCTBLLZZSZMMNYTPZSXQHJCJYQXYZXZQZCPSHKZZYSXCDFGMWQRLLQXRFZTLYSTCTMJCXJJXHJNXTNRZTZFQYHQGLLGCXSZSJDJLJCYDSJTLNYXHSZXCGJZYQPYLFHDJSBPCCZHJJJQZJQDYBSSLLCMYTTMQTBHJQNNYGKYRQYQMZGCJKPDCGMYZHQLLSLLCLMHOLZGDYYFZSLJCQZLYLZQJESHNYLLJXGJXLYSYYYXNBZLJSSZCQQCJYLLZLTJYLLZLLBNYLGQCHXYYXOXCXQKYJXXXYKLXSXXYQXCYKQXQCSGYXXYQXYGYTQOHXHXPYXXXULCYEYCHZZCBWQBBWJQZSCSZSSLZYLKDESJZWMYMCYTSDSXXSCJPQQSQYLYYZYCMDJDZYWCBTJSYDJKCYDDJLBDJJSODZYSYXQQYXDHHGQQYQHDYXWGMMMAJDYBBBPPBCMUUPLJZSMTXERXJMHQNUTPJDCBSSMSSSTKJTSSMMTRCPLZSZMLQDSDMJMQPNQDXCFYNBFSDQXYXHYAYKQYDDLQYYYSSZBYDSLNTFQTZQPZMCHDHCZCWFDXTMYQSPHQYYXSRGJCWTJTZZQMGWJJTJHTQJBBHWZPXXHYQFXXQYWYYHYSCDYDHHQMNMTMWCPBSZPPZZGLMZFOLLCFWHMMSJZTTDHZZYFFYTZZGZYSKYJXQYJZQBHMBZZLYGHGFMSHPZFZSNCLPBQSNJXZSLXXFPMTYJYGBXLLDLXPZJYZJYHHZCYWHJYLSJEXFSZZYWXKZJLUYDTMLYMQJPWXYHXSKTQJEZRPXXZHHMHWQPWQLYJJQJJZSZCPHJLCHHNXJLQWZJHBMZYXBDHHYPZLHLHLGFWLCHYYTLHJXCJMSCPXSTKPNHQXSRTYXXTESYJCTLSSLSTDLLLWWYHDHRJZSFGXTSYCZYNYHTDHWJSLHTZDQDJZXXQHGYLTZPHCSQFCLNJTCLZPFSTPDYNYLGMJLLYCQHYSSHCHYLHQYQTMZYPBYWRFQYKQSYSLZDQJMPXYYSSRHZJNYWTQDFZBWWTWWRXCWHGYHXMKMYYYQMSMZHNGCEPMLQQMTCWCTMMPXJPJJHFXYYZSXZHTYBMSTSYJTTQQQYYLHYNPYQZLCYZHZWSMYLKFJXLWGXYPJYTYSYXYMZCKTTWLKSMZSYLMPWLZWXWQZSSAQSYXYRHSSNTSRAPXCPWCMGDXHXZDZYFJHGZTTSBJHGYZSZYSMYCLLLXBTYXHBBZJKSSDMALXHYCFYGMQYPJYCQXJLLLJGSLZGQLYCJCCZOTYXMTMTTLLWTGPXYMZMKLPSZZZXHKQYSXCTYJZYHXSHYXZKXLZWPSQPYHJWPJPWXQQYLXSDHMRSLZZYZWTTCYXYSZZSHBSCCSTPLWSSCJCHNLCGCHSSPHYLHFHHXJSXYLLNYLSZDHZXYLSXLWZYKCLDYAXZCMDDYSPJTQJZLNWQPSSSWCTSTSZLBLNXSMNYYMJQBQHRZWTYYDCHQLXKPZWBGQYBKFCMZWPZLLYYLSZYDWHXPSBCMLJBSCGBHXLQHYRLJXYSWXWXZSLDFHLSLYNJLZYFLYJYCDRJLFSYZFSLLCQYQFGJYHYXZLYLMSTDJCYHBZLLNWLXXYGYYHSMGDHXXHHLZZJZXCZZZCYQZFNGWPYLCPKPYYPMCLQKDGXZGGWQBDXZZKZFBXXLZXJTPJPTTBYTSZZDWSLCHZHSLTYXHQLHYXXXYYZYSWTXZKHLXZXZPYHGCHKCFSYHUTJRLXFJXPTZTWHPLYXFCRHXSHXKYXXYHZQDXQWULHYHMJTBFLKHTXCWHJFWJCFPQRYQXCYYYQYGRPYWSGSUNGWCHKZDXYFLXXHJJBYZWTSXXNCYJJYMSWZJQRMHXZWFQSYLZJZGBHYNSLBGTTCSYBYXXWXYHXYYXNSQYXMQYWRGYQLXBBZLJSYLPSYTJZYHYZAWLRORJMKSCZJXXXYXCHDYXRYXXJDTSQFXLYLTSFFYXLMTYJMJUYYYXLTZCSXQZQHZXLYYXZHDNBRXXXJCTYHLBRLMBRLLAXKYLLLJLYXXLYCRYLCJTGJCMTLZLLCYZZPZPCYAWHJJFYBDYYZSMPCKZDQYQPBPCJPDCYZMDPBCYYDYCNNPLMTMLRMFMMGWYZBSJGYGSMZQQQZTXMKQWGXLLPJGZBQCDJJJFPKJKCXBLJMSWMDTQJXLDLPPBXCWRCQFBFQJCZAHZGMYKPHYYHZYKNDKZMBPJYXPXYHLFPNYYGXJDBKXNXHJMZJXSTRSTLDXSKZYSYBZXJLXYSLBZYSLHXJPFXPQNBYLLJQKYGZMCYZZYMCCSLCLHZFWFWYXZMWSXTYNXJHPYYMCYSPMHYSMYDYSHQYZCHMJJMZCAAGCFJBBHPLYZYLXXSDJGXDHKXXTXXNBHRMLYJSLTXMRHNLXQJXYZLLYSWQGDLBJHDCGJYQYCMHWFMJYBMBYJYJWYMDPWHXQLDYGPDFXXBCGJSPCKRSSYZJMSLBZZJFLJJJLGXZGYXYXLSZQYXBEXYXHGCXBPLDYHWETTWWCJMBTXCHXYQXLLXFLYXLLJLSSFWDPZSMYJCLMWYTCZPCHQEKCQBWLCQYDPLQPPQZQFJQDJHYMMCXTXDRMJWRHXCJZYLQXDYYNHYYHRSLSRSYWWZJYMTLTLLGTQCJZYABTCKZCJYCCQLJZQXALMZYHYWLWDXZXQDLLQSHGPJFJLJHJABCQZDJGTKHSSTCYJLPSWZLXZXRWGLDLZRLZXTGSLLLLZLYXXWGDZYGBDPHZPBRLWSXQBPFDWOFMWHLYPCBJCCLDMBZPBZZLCYQXLDOMZBLZWPDWYYGDSTTHCSQSCCRSSSYSLFYBFNTYJSZDFNDPDHDZZMBBLSLCMYFFGTJJQWFTMTPJWFNLBZCMMJTGBDZLQLPYFHYYMJYLSDCHDZJWJCCTLJCLDTLJJCPDDSQDSSZYBNDBJLGGJZXSXNLYCYBJXQYCBYLZCFZPPGKCXZDZFZTJJFJSJXZBNZYJQTTYJYHTYCZHYMDJXTTMPXSPLZCDWSLSHXYPZGTFMLCJTYCBPMGDKWYCYZCDSZZYHFLYCTYGWHKJYYLSJCXGYWJCBLLCSNDDBTZBSCLYZCZZSSQDLLMQYYHFSLQLLXFTYHABXGWNYWYYPLLSDLDLLBJCYXJZMLHLJDXYYQYTDLLLBUGBFDFBBQJZZMDPJHGCLGMJJPGAEHHBWCQXAXHHHZCHXYPHJAXHLPHJPGPZJQCQZGJJZZUZDMQYYBZZPHYHYBWHAZYJHYKFGDPFQSDLZMLJXKXGALXZDAGLMDGXMWZQYXXDXXPFDMMSSYMPFMDMMKXKSYZYSHDZKXSYSMMZZZMSYDNZZCZXFPLSTMZDNMXCKJMZTYYMZMZZMSXHHDCZJEMXXKLJSTLWLSQLYJZLLZJSSDPPMHNLZJCZYHMXXHGZCJMDHXTKGRMXFWMCGMWKDTKSXQMMMFZZYDKMSCLCMPCGMHSPXQPZDSSLCXKYXTWLWJYAHZJGZQMCSNXYYMMPMLKJXMHLMLQMXCTKZMJQYSZJSYSZHSYJZJCDAJZYBSDQJZGWZQQXFKDMSDJLFWEHKZQKJPEYPZYSZCDWYJFFMZZYLTTDZZEFMZLBNPPLPLPEPSZALLTYLKCKQZKGENQLWAGYXYDPXLHSXQQWQCQXQCLHYXXMLYCCWLYMQYSKGCHLCJNSZKPYZKCQZQLJPDMDZHLASXLBYDWQLWDNBQCRYDDZTJYBKBWSZDXDTNPJDTCTQDFXQQMGNXECLTTBKPWSLCTYQLPWYZZKLPYGZCQQPLLKCCYLPQMZCZQCLJSLQZDJXLDDHPZQDLJJXZQDXYZQKZLJCYQDYJPPYPQYKJYRMPCBYMCXKLLZLLFQPYLLLMBSGLCYSSLRSYSQTMXYXZQZFDZUYSYZTFFMZZSMZQHZSSCCMLYXWTPZGXZJGZGSJSGKDDHTQGGZLLBJDZLCBCHYXYZHZFYWXYZYMSDBZZYJGTSMTFXQYXQSTDGSLNXDLRYZZLRYYLXQHTXSRTZNGZXBNQQZFMYKMZJBZYMKBPNLYZPBLMCNQYZZZSJZHJCTZKHYZZJRDYZHNPXGLFZTLKGJTCTSSYLLGZRZBBQZZKLPKLCZYSSUYXBJFPNJZZXCDWXZYJXZZDJJKGGRSRJKMSMZJLSJYWQSKYHQJSXPJZZZLSNSHRNYPZTWCHKLPSRZLZXYJQXQKYSJYCZTLQZYBBYBWZPQDWWYZCYTJCJXCKCWDKKZXSGKDZXWWYYJQYYTCYTDLLXWKCZKKLCCLZCQQDZLQLCSFQCHQHSFSMQZZLNBJJZBSJHTSZDYSJQJPDLZCDCWJKJZZLPYCGMZWDJJBSJQZSYZYHHXJPBJYDSSXDZNCGLQMBTSFSBPDZDLZNFGFJGFSMPXJQLMBLGQCYYXBQKDJJQYRFKZTJDHCZKLBSDZCFJTPLLJGXHYXZCSSZZXSTJYGKGCKGYOQXJPLZPBPGTGYJZGHZQZZLBJLSQFZGKQQJZGYCZBZQTLDXRJXBSXXPZXHYZYCLWDXJJHXMFDZPFZHQHQMQGKSLYHTYCGFRZGNQXCLPDLBZCSCZQLLJBLHBZCYPZZPPDYMZZSGYHCKCPZJGSLJLNSCDSLDLXBMSTLDDFJMKDJDHZLZXLSZQPQPGJLLYBDSZGQLBZLSLKYYHZTTNTJYQTZZPSZQZTLLJTYYLLQLLQYZQLBDZLSLYYZYMDFSZSNHLXZNCZQZPBWSKRFBSYZMTHBLGJPMCZZLSTLXSHTCSYZLZBLFEQHLXFLCJLYLJQCBZLZJHHSSTBRMHXZHJZCLXFNBGXGTQJCZTMSFZKJMSSNXLJKBHSJXNTNLZDNTLMSJXGZJYJCZXYJYJWRWWQNZTNFJSZPZSHZJFYRDJSFSZJZBJFZQZZHZLXFYSBZQLZSGYFTZDCSZXZJBQMSZKJRHYJZCKMJKHCHGTXKXQGLXPXFXTRTYLXJXHDTSJXHJZJXZWZLCQSBTXWXGXTXXHXFTSDKFJHZYJFJXRZSDLLLTQSQQZQWZXSYQTWGWBZCGZLLYZBCLMQQTZHZXZXLJFRMYZFLXYSQXXJKXRMQDZDMMYYBSQBHGZMWFWXGMXLZPYYTGZYCCDXYZXYWGSYJYZNBHPZJSQSYXSXRTFYZGRHZTXSZZTHCBFCLSYXZLZQMZLMPLMXZJXSFLBYZMYQHXJSXRXSQZZZSSLYFRCZJRCRXHHZXQYDYHXSJJHZCXZBTYNSYSXJBQLPXZQPYMLXZKYXLXCJLCYSXXZZLXDLLLJJYHZXGYJWKJRWYHCPSGNRZLFZWFZZNSXGXFLZSXZZZBFCSYJDBRJKRDHHGXJLJJTGXJXXSTJTJXLYXQFCSGSWMSBCTLQZZWLZZKXJMLTMJYHSDDBXGZHDLBMYJFRZFSGCLYJBPMLYSMSXLSZJQQHJZFXGFQFQBPXZGYYQXGZTCQWYLTLGWSGWHRLFSFGZJMGMGBGTJFSYZZGZYZAFLSSPMLPFLCWBJZCLJJMZLPJJLYMQDMYYYFBGYGYZMLYZDXQYXRQQQHSYYYQXYLJTYXFSFSLLGNQCYHYCWFHCCCFXPYLYPLLZYXXXXXKQHHXSHJZCFZSCZJXCPZWHHHHHAPYLQALPQAFYHXDYLUKMZQGGGDDESRNNZLTZGCHYPPYSQJJHCLLJTOLNJPZLJLHYMHEYDYDSQYCDDHGZUNDZCLZYZLLZNTNYZGSLHSLPJJBDGWXPCDUTJCKLKCLWKLLCASSTKZZDNQNTTLYYZSSYSSZZRYLJQKCQDHHCRXRZYDGRGCWCGZQFFFPPJFZYNAKRGYWYQPQXXFKJTSZZXSWZDDFBBXTBGTZKZNPZZPZXZPJSZBMQHKCYXYLDKLJNYPKYGHGDZJXXEAHPNZKZTZCMXCXMMJXNKSZQNMNLWBWWXJKYHCPSTMCSQTZJYXTPCTPDTNNPGLLLZSJLSPBLPLQHDTNJNLYYRSZFFJFQWDPHZDWMRZCCLODAXNSSNYZRESTYJWJYJDBCFXNMWTTBYLWSTSZGYBLJPXGLBOCLHPCBJLTMXZLJYLZXCLTPNCLCKXTPZJSWCYXSFYSZDKNTLBYJCYJLLSTGQCBXRYZXBXKLYLHZLQZLNZCXWJZLJZJNCJHXMNZZGJZZXTZJXYCYYCXXJYYXJJXSSSJSTSSTTPPGQTCSXWZDCSYFPTFBFHFBBLZJCLZZDBXGCXLQPXKFZFLSYLTUWBMQJHSZBMDDBCYSCCLDXYCDDQLYJJWMQLLCSGLJJSYFPYYCCYLTJANTJJPWYCMMGQYYSXDXQMZHSZXPFTWWZQSWQRFKJLZJQQYFBRXJHHFWJJZYQAZMYFRHCYYBYQWLPEXCCZSTYRLTTDMQLYKMBBGMYYJPRKZNPBSXYXBHYZDJDNGHPMFSGMWFZMFQMMBCMZZCJJLCNUXYQLMLRYGQZCYXZLWJGCJCGGMCJNFYZZJHYCPRRCMTZQZXHFQGTJXCCJEAQCRJYHPLQLSZDJRBCQHQDYRHYLYXJSYMHZYDWLDFRYHBPYDTSSCNWBXGLPZMLZZTQSSCPJMXXYCSJYTYCGHYCJWYRXXLFEMWJNMKLLSWTXHYYYNCMMCWJDQDJZGLLJWJRKHPZGGFLCCSCZMCBLTBHBQJXQDSPDJZZGKGLFQYWBZYZJLTSTDHQHCTCBCHFLQMPWDSHYYTQWCNZZJTLBYMBPDYYYXSQKXWYYFLXXNCWCXYPMAELYKKJMZZZBRXYYQJFLJPFHHHYTZZXSGQQMHSPGDZQWBWPJHZJDYSCQWZKTXXSQLZYYMYSDZGRXCKKUJLWPYSYSCSYZLRMLQSYLJXBCXTLWDQZPCYCYKPPPNSXFYZJJRCEMHSZMSXLXGLRWGCSTLRSXBZGBZGZTCPLUJLSLYLYMTXMTZPALZXPXJTJWTCYYZLBLXBZLQMYLXPGHDSLSSDMXMBDZZSXWHAMLCZCPJMCNHJYSNSYGCHSKQMZZQDLLKABLWJXSFMOCDXJRRLYQZKJMYBYQLYHETFJZFRFKSRYXFJTWDSXXSYSQJYSLYXWJHSNLXYYXHBHAWHHJZXWMYLJCSSLKYDZTXBZSYFDXGXZJKHSXXYBSSXDPYNZWRPTQZCZENYGCXQFJYKJBZMLJCMQQXUOXSLYXXLYLLJDZBTYMHPFSTTQQWLHOKYBLZZALZXQLHZWRRQHLSTMYPYXJJXMQSJFNBXYXYJXXYQYLTHYLQYFMLKLJTMLLHSZWKZHLJMLHLJKLJSTLQXYLMBHHLNLZXQJHXCFXXLHYHJJGBYZZKBXSCQDJQDSUJZYYHZHHMGSXCSYMXFEBCQWWRBPYYJQTYZCYQYQQZYHMWFFHGZFRJFCDPXNTQYZPDYKHJLFRZXPPXZDBBGZQSTLGDGYLCQMLCHHMFYWLZYXKJLYPQHSYWMQQGQZMLZJNSQXJQSYJYCBEHSXFSZPXZWFLLBCYYJDYTDTHWZSFJMQQYJLMQXXLLDTTKHHYBFPWTYYSQQWNQWLGWDEBZWCMYGCULKJXTMXMYJSXHYBRWFYMWFRXYQMXYSZTZZTFYKMLDHQDXWYYNLCRYJBLPSXCXYWLSPRRJWXHQYPHTYDNXHHMMYWYTZCSQMTSSCCDALWZTCPQPYJLLQZYJSWXMZZMMYLMXCLMXCZMXMZSQTZPPQQBLPGXQZHFLJJHYTJSRXWZXSCCDLXTYJDCQJXSLQYCLZXLZZXMXQRJMHRHZJBHMFLJLMLCLQNLDXZLLLPYPSYJYSXCQQDCMQJZZXHNPNXZMEKMXHYKYQLXSXTXJYYHWDCWDZHQYYBGYBCYSCFGPSJNZDYZZJZXRZRQJJYMCANYRJTLDPPYZBSTJKXXZYPFDWFGZZRPYMTNGXZQBYXNBUFNQKRJQZMJEGRZGYCLKXZDSKKNSXKCLJSPJYYZLQQJYBZSSQLLLKJXTBKTYLCCDDBLSPPFYLGYDTZJYQGGKQTTFZXBDKTYYHYBBFYTYYBCLPDYTGDHRYRNJSPTCSNYJQHKLLLZSLYDXXWBCJQSPXBPJZJCJDZFFXXBRMLAZHCSNDLBJDSZBLPRZTSWSBXBCLLXXLZDJZSJPYLYXXYFTFFFBHJJXGBYXJPMMMPSSJZJMTLYZJXSWXTYLEDQPJMYGQZJGDJLQJWJQLLSJGJGYGMSCLJJXDTYGJQJQJCJZCJGDZZSXQGSJGGCXHQXSNQLZZBXHSGZXCXYLJXYXYYDFQQJHJFXDHCTXJYRXYSQTJXYEFYYSSYYJXNCYZXFXMSYSZXYYSCHSHXZZZGZZZGFJDLTYLNPZGYJYZYYQZPBXQBDZTZCZYXXYHHSQXSHDHGQHJHGYWSZTMZMLHYXGEBTYLZKQWYTJZRCLEKYSTDBCYKQQSAYXCJXWWGSBHJYZYDHCSJKQCXSWXFLTYNYZPZCCZJQTZWJQDZZZQZLJJXLSBHPYXXPSXSHHEZTXFPTLQYZZXHYTXNCFZYYHXGNXMYWXTZSJPTHHGYMXMXQZXTSBCZYJYXXTYYZYPCQLMMSZMJZZLLZXGXZAAJZYXJMZXWDXZSXZDZXLEYJJZQBHZWZZZQTZPSXZTDSXJJJZNYAZPHXYYSRNQDTHZHYYKYJHDZXZLSWCLYBZYECWCYCRYLCXNHZYDZYDYJDFRJJHTRSQTXYXJRJHOJYNXELXSFSFJZGHPZSXZSZDZCQZBYYKLSGSJHCZSHDGQGXYZGXCHXZJWYQWGYHKSSEQZZNDZFKWYSSTCLZSTSYMCDHJXXYWEYXCZAYDMPXMDSXYBSQMJMZJMTZQLPJYQZCGQHXJHHLXXHLHDLDJQCLDWBSXFZZYYSCHTYTYYBHECXHYKGJPXHHYZJFXHWHBDZFYZBCAPNPGNYDMSXHMMMMAMYNBYJTMPXYYMCTHJBZYFCGTYHWPHFTWZZEZSBZEGPFMTSKFTYCMHFLLHGPZJXZJGZJYXZSBBQSCZZLZCCSTPGXMJSFTCCZJZDJXCYBZLFCJSYZFGSZLYBCWZZBYZDZYPSWYJZXZBDSYUXLZZBZFYGCZXBZHZFTPBGZGEJBSTGKDMFHYZZJHZLLZZGJQZLSFDJSSCBZGPDLFZFZSZYZYZSYGCXSNXXCHCZXTZZLJFZGQSQYXZJQDCCZTQCDXZJYQJQCHXZTDLGSCXZSYQJQTZWLQDQZTQCHQQJZYEZZZPBWKDJFCJPZTYPQYQTTYNLMBDKTJZPQZQZZFPZSBNJLGYJDXJDZZKZGQKXDLPZJTCJDQBXDJQJSTCKNXBXZMSLYJCQMTJQWWCJQNJNLLLHJCWQTBZQYDZCZPZZDZYDDCYZZZCCJTTJFZDPRRTZTJDCQTQZDTJNPLZBCLLCTZSXKJZQZPZLBZRBTJDCXFCZDBCCJJLTQQPLDCGZDBBZJCQDCJWYNLLZYZCCDWLLXWZLXRXNTQQCZXKQLSGDFQTDDGLRLAJJTKUYMKQLLTZYTDYYCZGJWYXDXFRSKSTQTENQMRKQZHHQKDLDAZFKYPBGGPZREBZZYKZZSPEGJXGYKQZZZSLYSYYYZWFQZYLZZLZHWCHKYPQGNPGBLPLRRJYXCCSYYHSFZFYBZYYTGZXYLXCZWXXZJZBLFFLGSKHYJZEYJHLPLLLLCZGXDRZELRHGKLZZYHZLYQSZZJZQLJZFLNBHGWLCZCFJYSPYXZLZLXGCCPZBLLCYBBBBUBBCBPCRNNZCZYRBFSRLDCGQYYQXYGMQZWTZYTYJXYFWTEHZZJYWLCCNTZYJJZDEDPZDZTSYQJHDYMBJNYJZLXTSSTPHNDJXXBYXQTZQDDTJTDYYTGWSCSZQFLSHLGLBCZPHDLYZJYCKWTYTYLBNYTSDSYCCTYSZYYEBHEXHQDTWNYGYCLXTSZYSTQMYGZAZCCSZZDSLZCLZRQXYYELJSBYMXSXZTEMBBLLYYLLYTDQYSHYMRQWKFKBFXNXSBYCHXBWJYHTQBPBSBWDZYLKGZSKYHXQZJXHXJXGNLJKZLYYCDXLFYFGHLJGJYBXQLYBXQPQGZTZPLNCYPXDJYQYDYMRBESJYYHKXXSTMXRCZZYWXYQYBMCLLYZHQYZWQXDBXBZWZMSLPDMYSKFMZKLZCYQYCZLQXFZZYDQZPZYGYJYZMZXDZFYFYTTQTZHGSPCZMLCCYTZXJCYTJMKSLPZHYSNZLLYTPZCTZZCKTXDHXXTQCYFKSMQCCYYAZHTJPCYLZLYJBJXTPNYLJYYNRXSYLMMNXJSMYBCSYSYLZYLXJJQYLDZLPQBFZZBLFNDXQKCZFYWHGQMRDSXYCYTXNQQJZYYPFZXDYZFPRXEJDGYQBXRCNFYYQPGHYJDYZXGRHTKYLNWDZNTSMPKLBTHBPYSZBZTJZSZZJTYYXZPHSSZZBZCZPTQFZMYFLYPYBBJQXZMXXDJMTSYSKKBJZXHJCKLPSMKYJZCXTMLJYXRZZQSLXXQPYZXMKYXXXJCLJPRMYYGADYSKQLSNDHYZKQXZYZTCGHZTLMLWZYBWSYCTBHJHJFCWZTXWYTKZLXQSHLYJZJXTMPLPYCGLTBZZTLZJCYJGDTCLKLPLLQPJMZPAPXYZLKKTKDZCZZBNZDYDYQZJYJGMCTXLTGXSZLMLHBGLKFWNWZHDXUHLFMKYSLGXDTWWFRJEJZTZHYDXYKSHWFZCQSHKTMQQHTZHYMJDJSKHXZJZBZZXYMPAGQMSTPXLSKLZYNWRTSQLSZBPSPSGZWYHTLKSSSWHZZLYYTNXJGMJSZSUFWNLSOZTXGXLSAMMLBWLDSZYLAKQCQCTMYCFJBSLXCLZZCLXXKSBZQCLHJPSQPLSXXCKSLNHPSFQQYTXYJZLQLDXZQJZDYYDJNZPTUZDSKJFSLJHYLZSQZLBTXYDGTQFDBYAZXDZHZJNHHQBYKNXJJQCZMLLJZKSPLDYCLBBLXKLELXJLBQYCXJXGCNLCQPLZLZYJTZLJGYZDZPLTQCSXFDMNYCXGBTJDCZNBGBQYQJWGKFHTNPYQZQGBKPBBYZMTJDYTBLSQMPSXTBNPDXKLEMYYCJYNZCTLDYKZZXDDXHQSHDGMZSJYCCTAYRZLPYLTLKXSLZCGGEXCLFXLKJRTLQJAQZNCMBYDKKCXGLCZJZXJHPTDJJMZQYKQSECQZDSHHADMLZFMMZBGNTJNNLGBYJBRBTMLBYJDZXLCJLPLDLPCQDHLXZLYCBLCXZZJADJLNZMMSSSMYBHBSQKBHRSXXJMXSDZNZPXLGBRHWGGFCXGMSKLLTSJYYCQLTSKYWYYHYWXBXQYWPYWYKQLSQPTNTKHQCWDQKTWPXXHCPTHTWUMSSYHBWCRWXHJMKMZNGWTMLKFGHKJYLSYYCXWHYECLQHKQHTTQKHFZLDXQWYZYYDESBPKYRZPJFYYZJCEQDZZDLATZBBFJLLCXDLMJSSXEGYGSJQXCWBXSSZPDYZCXDNYXPPZYDLYJCZPLTXLSXYZYRXCYYYDYLWWNZSAHJSYQYHGYWWAXTJZDAXYSRLTDPSSYYFNEJDXYZHLXLLLZQZSJNYQYQQXYJGHZGZCYJCHZLYCDSHWSHJZYJXCLLNXZJJYYXNFXMWFPYLCYLLABWDDHWDXJMCXZTZPMLQZHSFHZYNZTLLDYWLSLXHYMMYLMBWWKYXYADTXYLLDJPYBPWUXJMWMLLSAFDLLYFLBHHHBQQLTZJCQJLDJTFFKMMMBYTHYGDCQRDDWRQJXNBYSNWZDBYYTBJHPYBYTTJXAAHGQDQTMYSTQXKBTZPKJLZRBEQQSSMJJBDJOTGTBXPGBKTLHQXJJJCTHXQDWJLWRFWQGWSHCKRYSWGFTGYGBXSDWDWRFHWYTJJXXXJYZYSLPYYYPAYXHYDQKXSHXYXGSKQHYWFDDDPPLCJLQQEEWXKSYYKDYPLTJTHKJLTCYYHHJTTPLTZZCDLTHQKZXQYSTEEYWYYZYXXYYSTTJKLLPZMCYHQGXYHSRMBXPLLNQYDQHXSXXWGDQBSHYLLPJJJTHYJKYPPTHYYKTYEZYENMDSHLCRPQFDGFXZPSFTLJXXJBSWYYSKSFLXLPPLBBBLBSFXFYZBSJSSYLPBBFFFFSSCJDSTZSXZRYYSYFFSYZYZBJTBCTSBSDHRTJJBYTCXYJEYLXCBNEBJDSYXYKGSJZBXBYTFZWGENYHHTHZHHXFWGCSTBGXKLSXYWMTMBYXJSTZSCDYQRCYTWXZFHMYMCXLZNSDJTTTXRYCFYJSBSDYERXJLJXBBDEYNJGHXGCKGSCYMBLXJMSZNSKGXFBNBPTHFJAAFXYXFPXMYPQDTZCXZZPXRSYWZDLYBBKTYQPQJPZYPZJZNJPZJLZZFYSBTTSLMPTZRTDXQSJEHBZYLZDHLJSQMLHTXTJECXSLZZSPKTLZKQQYFSYGYWPCPQFHQHYTQXZKRSGTTSQCZLPTXCDYYZXSQZSLXLZMYCPCQBZYXHBSXLZDLTCDXTYLZJYYZPZYZLTXJSJXHLPMYTXCQRBLZSSFJZZTNJYTXMYJHLHPPLCYXQJQQKZZSCPZKSWALQSBLCCZJSXGWWWYGYKTJBBZTDKHXHKGTGPBKQYSLPXPJCKBMLLXDZSTBKLGGQKQLSBKKTFXRMDKBFTPZFRTBBRFERQGXYJPZSSTLBZTPSZQZSJDHLJQLZBPMSMMSXLQQNHKNBLRDDNXXDHDDJCYYGYLXGZLXSYGMQQGKHBPMXYXLYTQWLWGCPBMQXCYZYDRJBHTDJYHQSHTMJSBYPLWHLZFFNYPMHXXHPLTBQPFBJWQDBYGPNZTPFZJGSDDTQSHZEAWZZYLLTYYBWJKXXGHLFKXDJTMSZSQYNZGGSWQSPHTLSSKMCLZXYSZQZXNCJDQGZDLFNYKLJCJLLZLMZZNHYDSSHTHZZLZZBBHQZWWYCRZHLYQQJBEYFXXXWHSRXWQHWPSLMSSKZTTYGYQQWRSLALHMJTQJSMXQBJJZJXZYZKXBYQXBJXSHZTSFJLXMXZXFGHKZSZGGYLCLSARJYHSLLLMZXELGLXYDJYTLFBHBPNLYZFBBHPTGJKWETZHKJJXZXXGLLJLSTGSHJJYQLQZFKCGNNDJSSZFDBCTWWSEQFHQJBSAQTGYPQLBXBMMYWXGSLZHGLZGQYFLZBYFZJFRYSFMBYZHQGFWZSYFYJJPHZBYYZFFWODGRLMFTWLBZGYCQXCDJYGZYYYYTYTYDWEGAZYHXJLZYYHLRMGRXXZCLHNELJJTJTPWJYBJJBXJJTJTEEKHWSLJPLPSFYZPQQBDLQJJTYYQLYZKDKSQJYYQZLDQTGJQYZJSUCMRYQTHTEJMFCTYHYPKMHYZWJDQFHYYXWSHCTXRLJHQXHCCYYYJLTKTTYTMXGTCJTZAYYOCZLYLBSZYWJYTSJYHBYSHFJLYGJXXTMZYYLTXXYPZLXYJZYZYYPNHMYMDYYLBLHLSYYQQLLNJJYMSOYQBZGDLYXYLCQYXTSZEGXHZGLHWBLJHEYXTWQMAKBPQCGYSHHEGQCMWYYWLJYJHYYZLLJJYLHZYHMGSLJLJXCJJYCLYCJPCPZJZJMMYLCQLNQLJQJSXYJMLSZLJQLYCMMHCFMMFPQQMFYLQMCFFQMMMMHMZNFHHJGTTHHKHSLNCHHYQDXTMMQDCYZYXYQMYQYLTDCYYYZAZZCYMZYDLZFFFMMYCQZWZZMABTBYZTDMNZZGGDFTYPCGQYTTSSFFWFDTZQSSYSTWXJHXYTSXXYLBYQHWWKXHZXWZNNZZJZJJQJCCCHYYXBZXZCYZTLLCQXYNJYCYYCYNZZQYYYEWYCZDCJYCCHYJLBTZYYCQWMPWPYMLGKDLDLGKQQBGYCHJXY";
//此处收录了375个多音字
const oMultiDiff = {
19969: "DZ",
19975: "WM",
19988: "QJ",
20048: "YL",
20056: "SC",
20060: "NM",
20094: "QG",
20127: "QJ",
20167: "QC",
20193: "YG",
20250: "KH",
20256: "ZC",
20282: "SC",
20285: "QJG",
20291: "TD",
20314: "YD",
20340: "NE",
20375: "TD",
20389: "YJ",
20391: "CZ",
20415: "PB",
20446: "YS",
20447: "SQ",
20504: "TC",
20608: "KG",
20854: "QJ",
20857: "ZC",
20911: "PF",
20985: "AW",
21032: "PB",
21048: "XQ",
21049: "SC",
21089: "YS",
21119: "JC",
21242: "SB",
21273: "SC",
21305: "YP",
21306: "QO",
21330: "ZC",
21333: "SDC",
21345: "QK",
21378: "CA",
21397: "SC",
21414: "XS",
21442: "SC",
21477: "JG",
21480: "TD",
21484: "ZS",
21494: "YX",
21505: "YX",
21512: "HG",
21523: "XH",
21537: "PB",
21542: "PF",
21549: "KH",
21571: "E",
21574: "DA",
21588: "TD",
21589: "O",
21618: "ZC",
21621: "KHA",
21632: "ZJ",
21654: "KG",
21679: "LKG",
21683: "KH",
21710: "A",
21719: "YH",
21734: "WOE",
21769: "A",
21780: "WN",
21804: "XH",
21834: "A",
21899: "ZD",
21903: "RN",
21908: "WO",
21939: "ZC",
21956: "SA",
21964: "YA",
21970: "TD",
22003: "A",
22031: "JG",
22040: "XS",
22060: "ZC",
22066: "ZC",
22079: "MH",
22129: "XJ",
22179: "XA",
22237: "NJ",
22244: "TD",
22280: "JQ",
22300: "YH",
22313: "XW",
22331: "YQ",
22343: "YJ",
22351: "PH",
22395: "DC",
22412: "TD",
22484: "PB",
22500: "PB",
22534: "ZD",
22549: "DH",
22561: "PB",
22612: "TD",
22771: "KQ",
22831: "HB",
22841: "JG",
22855: "QJ",
22865: "XQ",
23013: "ML",
23081: "WM",
23487: "SX",
23558: "QJ",
23561: "YW",
23586: "YW",
23614: "YW",
23615: "SN",
23631: "PB",
23646: "ZS",
23663: "ZT",
23673: "YG",
23762: "TD",
23769: "ZS",
23780: "QJ",
23884: "QK",
24055: "XH",
24113: "DC",
24162: "ZC",
24191: "GA",
24273: "QJ",
24324: "NL",
24377: "TD",
24378: "QJ",
24439: "PF",
24554: "ZS",
24683: "TD",
24694: "WE",
24733: "LK",
24925: "TN",
25094: "ZG",
25100: "XQ",
25103: "XH",
25153: "PB",
25170: "PB",
25179: "KG",
25203: "PB",
25240: "ZS",
25282: "FB",
25303: "NA",
25324: "KG",
25341: "ZY",
25373: "WZ",
25375: "XJ",
25384: "A",
25457: "A",
25528: "SD",
25530: "SC",
25552: "TD",
25774: "ZC",
25874: "ZC",
26044: "YW",
26080: "WM",
26292: "PB",
26333: "PB",
26355: "ZY",
26366: "CZ",
26397: "ZC",
26399: "QJ",
26415: "ZS",
26451: "SB",
26526: "ZC",
26552: "JG",
26561: "TD",
26588: "JG",
26597: "CZ",
26629: "ZS",
26638: "YL",
26646: "XQ",
26653: "KG",
26657: "XJ",
26727: "HG",
26894: "ZC",
26937: "ZS",
26946: "ZC",
26999: "KJ",
27099: "KJ",
27449: "YQ",
27481: "XS",
27542: "ZS",
27663: "ZS",
27748: "TS",
27784: "SC",
27788: "ZD",
27795: "TD",
27812: "O",
27850: "PB",
27852: "MB",
27895: "SL",
27898: "PL",
27973: "QJ",
27981: "KH",
27986: "HX",
27994: "XJ",
28044: "YC",
28065: "WG",
28177: "SM",
28267: "QJ",
28291: "KH",
28337: "ZQ",
28463: "TL",
28548: "DC",
28601: "TD",
28689: "PB",
28805: "JG",
28820: "QG",
28846: "PB",
28952: "TD",
28975: "ZC",
29100: "A",
29325: "QJ",
29575: "SL",
29602: "FB",
30010: "TD",
30044: "CX",
30058: "PF",
30091: "YSP",
30111: "YN",
30229: "XJ",
30427: "SC",
30465: "SX",
30631: "YQ",
30655: "QJ",
30684: "QJG",
30707: "SD",
30729: "XH",
30796: "LG",
30917: "PB",
31074: "NM",
31085: "JZ",
31109: "SC",
31181: "ZC",
31192: "MLB",
31293: "JQ",
31400: "YX",
31584: "YJ",
31896: "ZN",
31909: "ZY",
31995: "XJ",
32321: "PF",
32327: "ZY",
32418: "HG",
32420: "XQ",
32421: "HG",
32438: "LG",
32473: "GJ",
32488: "TD",
32521: "QJ",
32527: "PB",
32562: "ZSQ",
32564: "JZ",
32735: "ZD",
32793: "PB",
33071: "PF",
33098: "XL",
33100: "YA",
33152: "PB",
33261: "CX",
33324: "BP",
33333: "TD",
33406: "YA",
33426: "WM",
33432: "PB",
33445: "JG",
33486: "ZN",
33493: "TS",
33507: "QJ",
33540: "QJ",
33544: "ZC",
33564: "XQ",
33617: "YT",
33632: "QJ",
33636: "XH",
33637: "YX",
33694: "WG",
33705: "PF",
33728: "YW",
33882: "SR",
34067: "WM",
34074: "YW",
34121: "QJ",
34255: "ZC",
34259: "XL",
34425: "JH",
34430: "XH",
34485: "KH",
34503: "YS",
34532: "HG",
34552: "XS",
34558: "YE",
34593: "ZL",
34660: "YQ",
34892: "XH",
34928: "SC",
34999: "QJ",
35048: "PB",
35059: "SC",
35098: "ZC",
35203: "TQ",
35265: "JX",
35299: "JX",
35782: "SZ",
35828: "YS",
35830: "E",
35843: "TD",
35895: "YG",
35977: "MH",
36158: "JG",
36228: "QJ",
36426: "XQ",
36466: "DC",
36710: "JC",
36711: "ZYG",
36767: "PB",
36866: "SK",
36951: "YW",
37034: "YX",
37063: "XH",
37218: "ZC",
37325: "ZC",
38063: "PB",
38079: "TD",
38085: "QY",
38107: "DC",
38116: "TD",
38123: "YD",
38224: "HG",
38241: "XTC",
38271: "ZC",
38415: "YE",
38426: "KH",
38461: "YD",
38463: "AE",
38466: "PB",
38477: "XJ",
38518: "YT",
38551: "WK",
38585: "ZC",
38704: "XS",
38739: "LJ",
38761: "GJ",
38808: "SQ",
39048: "JG",
39049: "XJ",
39052: "HG",
39076: "CZ",
39271: "XT",
39534: "TD",
39552: "TD",
39584: "PB",
39647: "SB",
39730: "LG",
39748: "TPB",
40109: "ZQ",
40479: "ND",
40516: "HG",
40536: "HG",
40583: "QJ",
40765: "YQ",
40784: "QJ",
40840: "YK",
40863: "QJG"
};
//參数,中文字符串
//返回值:拼音首字母串数组
function makePy(str) {
if (typeof str != "string")
throw new Error(-1, "函数makePy须要字符串类型參数!");
var arrResult = []; //保存中间结果的数组
for (var i = 0, len = str.length; i < len; i++) {
//获得unicode码
var ch = str.charAt(i);
//检查该unicode码是否在处理范围之内,在则返回该码对映汉字的拼音首字母,不在则调用其他函数处理
arrResult.push(checkCh(ch));
}
//处理arrResult,返回全部可能的拼音首字母串数组
return mkRslt(arrResult);
}
function checkCh(ch) {
var uni = ch.charCodeAt(0);
//假设不在汉字处理范围之内,返回原字符,也能够调用自己的处理函数
if (uni > 40869 || uni < 19968) return ch; //dealWithOthers(ch);
//检查是否是多音字,是按多音字处理,不是就直接在strChineseFirstPY字符串中找相应的首字母
return oMultiDiff[uni]
? oMultiDiff[uni]
: strChineseFirstPY.charAt(uni - 19968);
}
function checkEn(en) {
return /[a-zA-Z]/.test(en);
}
function mkRslt(arr) {
var arrRslt = [""];
for (var i = 0, len = arr.length; i < len; i++) {
var str = arr[i];
var strlen = str.length;
if (strlen == 1) {
for (var k = 0; k < arrRslt.length; k++) {
arrRslt[k] += str;
}
} else {
var tmpArr = arrRslt.slice(0);
arrRslt = [];
for (k = 0; k < strlen; k++) {
//复制一个同样的arrRslt
var tmp = tmpArr.slice(0);
//把当前字符str[k]加入到每一个元素末尾
for (var j = 0; j < tmp.length; j++) {
tmp[j] += str.charAt(k);
}
//把复制并改动后的数组连接到arrRslt上
arrRslt = arrRslt.concat(tmp);
}
}
}
return arrRslt;
}

return makePy(str);
}

下划线转驼峰

1
2
3
4
5
6
7
8
9
10
/**
* 下划线转驼峰
* @param {*} str 形如 IS_AUTO_UPLOAD => isAutoUpload
* @returns
*/
export function toHump(str, isToLower = false) {
if (!str.includes("_")) return str;
str = isToLower ? str.toLowerCase() : str;
return str.replace(/_([a-z]{1})/g, ($1) => $1.toUpperCase().substring(1));
}

驼峰转大写下划线

1
2
3
4
5
6
7
/**
* 驼峰转大写下划线
* @param {string} name
*/
export function toLine(name) {
return name.replace(/([A-Z])/g, "_$1").toUpperCase();
}

DOM 相关

全局唯一标识符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 唯一标识符
* @param {Number} len uuid的长度
* @param {Boolean} firstU 将返回的首字母置为"u"
* @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
*/
export function guid(len = 32, firstU = true, radix = null) {
const chars =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");
const uuid = [];
radix = radix || chars.length;

if (len) {
// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
for (let i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)];
} else {
let r;
// rfc4122标准要求返回的uuid中,某些位为固定的字符
uuid[8] = uuid[13] = uuid[18] = uuid[23] = "-";
uuid[14] = "4";

for (let i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | (Math.random() * 16);
uuid[i] = chars[i == 19 ? (r & 0x3) | 0x8 : r];
}
}
}
// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
if (firstU) {
uuid.shift();
return `u${uuid.join("")}`;
}
return uuid.join("");
}

获取元素相对于屏幕顶部的相对位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* 获取元素相对于屏幕顶部的相对位置
* @param {Object} dom dom元素
* @return {Object} 绝对位置{currentX, currentY}
*/
export function getElPosition(dom, fixed = false) {
let top = dom.offsetTop;
let left = dom.offsetLeft;
while ((dom = dom.offsetParent)) {
let translate = tools.getTranslate(dom);
top += dom.offsetTop;
top += translate[1];
left += dom.offsetLeft;
left += translate[0];
// body不统计scroll
if (dom.tagName != "BODY") {
top -= dom.scrollTop;
left -= dom.scrollLeft;
}
}
// fixed需要统计scroll
if (fixed) {
console.print("!fixed scroll", scrollTop, scrollLeft, top, left);
let scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
let scrollLeft =
window.pageXOffset ||
document.documentElement.scrollLeft ||
document.body.scrollLeft;
top += scrollTop;
left += scrollLeft;
}
return { top, left };
}

滑动方向判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 滑动方向判断
* @param {Object} obj
* @returns {String}
*/
export function getDirection({ startx, starty, endx, endy }) {
let angx = endx - startx;
let angy = endy - starty;
let result = "none";

//如果滑动距离太短
if (Math.abs(angx) < 100 && Math.abs(angy) < 100) {
return result;
}
let angle = (Math.atan2(angy, angx) * 180) / Math.PI;
if (angle >= -135 && angle <= -45) {
result = "up";
} else if (angle > 45 && angle < 135) {
result = "down";
} else if (
(angle >= 135 && angle <= 180) ||
(angle >= -180 && angle < -135)
) {
result = "left";
} else if (angle >= -45 && angle <= 45) {
result = "right";
}

return result;
}

px 转成 rem

1
2
3
4
5
6
7
8
9
/**
* px转成rem
* @px {String} 像素
*/
export function px2rem(px = "") {
const scale = 37.5;
let numberPx = Number(px) / scale;
return numberPx ? numberPx.toFixed(2) + "rem" : "inherit";
}

防抖和节流

防抖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
*/
let timeout = null;

export function debounce(func, wait = 500, immediate = false) {
// 清除定时器
if (timeout !== null) clearTimeout(timeout);
// 立即执行,此类情况一般用不到
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(function () {
timeout = null;
}, wait);
if (callNow) typeof func === "function" && func();
} else {
// 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
timeout = setTimeout(function () {
typeof func === "function" && func();
}, wait);
}
}

节流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* 节流原理:在一定时间内,只能触发一次
* @param {Function} func 要执行的回调函数
* @param {Number} wait 延时的时间
* @param {Boolean} immediate 是否立即执行
*/
let timer, flag;

export function throttle(func, wait = 500, immediate = true) {
if (immediate) {
if (!flag) {
flag = true;
// 如果是立即执行,则在wait毫秒内开始时执行
typeof func === "function" && func();
timer = setTimeout(() => {
flag = false;
}, wait);
}
} else {
if (!flag) {
flag = true;
// 如果是非立即执行,则在wait毫秒内的结束处执行
timer = setTimeout(() => {
flag = false;
typeof func === "function" && func();
}, wait);
}
}
}

对象相关

删除无效属性

删除一个对象中的属性值为 null 或 undefined 的所有属性

1
2
3
4
5
6
7
export const removeNullUndefined = (obj) =>
Object.entries(obj).reduce(
(a, [k, v]) => (v == null ? a : ((a[k] = v), a)),
{}
);

removeNullUndefined({ name: "", age: undefined, sex: null }); // { name: '' }

反转对象键值

将对象的键值对交换

1
2
3
export const invert = (obj) =>
Object.keys(obj).reduce((res, k) => Object.assign(res, { [obj[k]]: k }), {});
invert({ name: "jack" }); // {jack: 'name'}

字符串转对象

1
2
3
4
5
6
7
8
// 将一串字符串比如`'{name: "jack"}'`转换成对象时,直接使用 `JSON.parse` 将会报错。

export const strParse = (str) =>
JSON.parse(
str.replace(/(\w+)\s*:/g, (_, p1) => `"${p1}":`).replace(/\'/g, '"')
);

strParse('{name: "jack"}');

将以·隔开的字符串转为获取对象某个属性值

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 将以`·`隔开的字符串转为获取对象某个属性值
* @val {string} 字符串 如:"obj.a.c"
* @obj {object} 需要获取值的对象 obj
*/
export function splitPath(str = "", obj = {}) {
const strArr = str.split(".");
let _obj = { ...obj };
strArr.forEach((item) => {
_obj = _obj[item];
});
return _obj;
}

解构赋值对象中的一些属性

1
2
3
4
5
6
7
8
9
/**
* 解构赋值对象中的一些属性(会去除一些空值)
* @param {object} obj 需要解构的数组
* @param {*} arr 需要提出的参数
* @returns {object}
*/
export function objF(obj, arr) {
return JSON.parse(JSON.stringify(obj || {}, arr));
}

深度克隆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 深度克隆
* @param {object} obj 需要克隆的对象或数组
*/
export function deepClone(obj) {
// 对常见的“非”值,直接返回原来值
if ([null, undefined, NaN, false].includes(obj)) return obj;
if (typeof obj !== "object" && typeof obj !== "function") {
//原始类型直接返回
return obj;
}
var o = isArray(obj) ? [] : {};
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
o[i] = typeof obj[i] === "object" ? deepClone(obj[i]) : obj[i];
}
}
return o;
}

JS 对象深度合并

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* JS对象深度合并
* @param {object} target 目标对象
* @param {object} source 源对象
*/
export function deepMerge(target = {}, source = {}) {
target = deepClone(target);
if (typeof target !== "object" || typeof source !== "object") return false;
for (var prop in source) {
if (!source.hasOwnProperty(prop)) continue;
if (prop in target) {
if (typeof target[prop] !== "object") {
target[prop] = source[prop];
} else {
if (typeof source[prop] !== "object") {
target[prop] = source[prop];
} else {
if (target[prop].concat && source[prop].concat) {
target[prop] = target[prop].concat(source[prop]);
} else {
target[prop] = deepMerge(target[prop], source[prop]);
}
}
}
} else {
target[prop] = source[prop];
}
}
return target;
}

获取深层数组对象的 val

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 获取深层数组对象的val
* @param {object | array} val 类型名称
* @param {array} arr 索引数组
*/
export function getValDeep(val, arr) {
return arr.reduce((pre, i) => {
if (typeof i === "number" && i < 0 && typeof pre === "object") {
i = pre.length - Math.abs(i);
}
return pre?.[i] || "";
}, val);
}

序列化对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 序列化对象(仅支持简单类型)
* @param {Object} obj
* @returns {String}
*/
export function qsObj(obj = {}) {
let str = "";
for (const k in obj) {
if (Object.hasOwnProperty.call(obj, k)) {
str += `${str ? "&" : "?"}${k}=${encodeURIComponent(obj[k])}`;
}
}
return str;
}

比较两个对象

当你需要比较两个对象,js 的等于只能判断对象的地址是否相同,当地址不相同的时候无法判断两个对象的键值对是否一致。

1
2
3
4
5
const isEqual = (...objects) =>
objects.every((obj) => JSON.stringify(obj) === JSON.stringify(objects[0]));

// isEqual({ name: "jack" }, { name: "jack" }); // true
// isEqual({ name: "jack" }, { name: "jack1" }, { name: "jack" }); // false

数组相关

对象数组排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 对象数组排序
* @param {array} arr 对象数组 eg: [{name: "A", sort: 1}, {name: "C", sort: 2}, {name: "B", sort: 0}]
* @param {string} property 对象排序的属性字段
* @param {string[asc|desc]} order 升序/降序
*/
export function sortByProperty(arr, property, order = "asc") {
if (order === "asc") {
return arr.sort((a, b) => a[property] - b[property]);
} else if (order === "desc") {
return arr.sort((a, b) => b[property] - a[property]);
} else {
console.error("请确认参数");
return arr;
}
}

查找最小值索引

1
2
3
4
export const getMinIndex = (arr) =>
arr.reduce((prev, curr, i, a) => (curr < a[prev] ? i : prev), 0);

// getMinIndex([2, 5, 3, 4, 1, 0, 9]); // 5

查找最大值索引

1
2
3
4
export const getMaxIndex = (arr) =>
arr.reduce((prev, curr, i, a) => (curr > a[prev] ? i : prev), 0);

// getMaxIndex([1, 3, 9, 7, 5]); // 2

找到最接近的数值

1
2
3
4
5
6
export const closest = (arr, n) =>
arr.reduce((prev, curr) =>
Math.abs(curr - n) < Math.abs(prev - n) ? curr : prev
);

closest([29, 87, 8, 78, 97, 20, 75, 33, 24, 17], 50); // 33

数组去重

循环遍历去重

for

1
2
3
4
5
6
7
8
9
10
export function unique(arr) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i]);
}
}
return newArr;
}
unique([2, 4, 4, 5, "a", "a"]); // [2, 4, 5, "a"]

includes 检测数组是否有某个值

1
2
3
4
5
6
7
8
9
10
export function unique(arr) {
let newArr = [];
for (let i = 0; i < arr.length; i++) {
if (!newArr.includes(arr[i])) {
newArr.push(arr[i]);
}
}
return newArr;
}
unique([2, 4, 4, 5, "a", "a"]); // [2, 4, 5, "a"]

双层 for 循环 + splice 去重

1
2
3
4
5
6
7
8
9
10
11
12
export function unique(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) {
arr.splice(j, 1);
j--;
}
}
}
return arr;
}
unique([2, 4, 4, 5, "a", "a"]); // [2, 4, 5, "a"]
1
2
3
4
5
6
7
8
9
10
11
12
export function unique(arr) {
let hash = [],
newArr = [];
for (let i = 0, ele; (ele = arr[i]) != null; i++) {
if (!hash[ele]) {
newArr.push(ele);
hash[ele] = true;
}
}
return newArr;
}
unique([2, 4, 4, 5, "a", "a"]); // [2, 4, 5, "a"]

map

1
2
3
4
5
6
7
8
9
10
export function unique(arr) {
let newArr = [];
arr.map((item, i) => {
if (arr.indexOf(arr[i]) === i) {
newArr.push(item);
}
});
return newArr;
}
unique([2, 4, 4, 5, "a", "a"]); // [2, 4, 5, "a"]

filter 去重

1
2
export const unique = (arr) =>
arr.filter((ele, index, array) => array.indexOf(ele) === index);
1
2
export const unique = (arr) =>
arr.filter((ele, index, array) => array.lastIndexOf(ele) === index);

对象数组去重,将数组中完全相同的对象去重组成一个新的数组

1
2
3
4
5
export const unique = (arr) =>
arr.filter((ele, index, array) => {
array.findIndex((item) => item.key == ele.key && item.name == ele.name) ===
index;
});

reduce() 去重

1
2
3
4
5
export const unique = (input) =>
input.reduce(
(cur, next) => (cur.indexOf(next) !== -1 ? cur : [...cur, next]),
[]
);

数组下标法

1
2
3
4
5
export const unique = (input) =>
input.reduce(
(cur, next, i) => (input.indexOf(next) !== i ? cur : [...cur, next]),
[]
);

一行搞定排序 + 去重

1
2
3
4
5
6
7
export const unique = (input) =>
input
.sort((a, b) => a > b)
.reduce(
(cur, next) => (cur[cur.length - 1] === next ? cur : [...cur, next]),
[]
);

对象键值 + reduce 去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 速度最快, 占空间最多(空间换时间)
* 该方法执行的速度比其他任何方法都快, 就是占用的内存大一些
* 现思路:新建一js对象以及新数组,遍历传入数组时,判断值是否为js对象的键
* 不是的话给对象新增该键并放入新数组
* 注意点:判断是否为js对象键时,会自动对传入的键执行“toString()”
* 不同的键可能会被误认为一样,例如n[val]-- n[1]、n["1"]
* 解决上述问题还是得调用 indexOf
*/
const obj = {};
export const unique = (input) =>
input.reduce(
(cur, next) => (obj[next] ? cur : (obj[next] = true && [...cur, next])),
[]
);

Set 去重

1
export const uniq = (arr) => [...new Set(arr)];

利用 SetArray.from 去重

1
2
// Array.from 方法可以将 Set 结构转为数组
export const uniq = (arr) => Array.from(new Set(arr));

利用对象的属性不能相同的特点去重

1
2
3
4
5
6
7
8
9
10
11
12
export function unique(arr) {
let obj = {},
result = [];
for (let i = 0; i < arr.length; i++) {
if (!obj[arr[i]]) {
// 如果能查找到,证明数组元素重复了
obj[arr[i]] = 1;
result.push(arr[i]);
}
}
return result;
}

递归去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export function unique(arr) {
arr.sort(function (a, b) {
//对数组进行排序才能方便比较
return a - b;
});
function loop(index) {
if (index >= 1) {
if (arr[index] === arr[index - 1]) {
arr.splice(index, 1);
}
loop(index - 1); //递归loop函数进行去重
}
}
loop(arr.length - 1);
return arr;
}

对象数组唯一值数据去重

1
2
3
4
5
6
7
8
9
10
export const unique = (list) => [
...list.reduce((prev, cur) => prev.set(cur.id, cur), new Map()).values()
];

unique([
{ id: 1, name: "jack" },
{ id: 2, name: "rose" },
{ id: 1, name: "jack" }
]);
// [{id: 1, name: 'jack'}, {id: 2, name: 'rose'}]

两个数组相关计算

求并集

合并两个数组并去重

1
2
3
export function getArrUnion(arr1, arr2) {
return [...new Set([...arr1, ...arr2])];
}

求交集

取出两个数组中相同项,生成一个新数组

1
2
3
4
5
6
7
8
9
10
11
export function getArrEqual(arr1, arr2) {
let newArr = [];
for (let i = 0; i < arr2.length; i++) {
for (let j = 0; j < arr1.length; j++) {
if (arr1[j] === arr2[i]) {
newArr.push(arr1[j]);
}
}
}
return newArr;
}
1
2
3
export function getArrEqual(arr1, arr2) {
return [...new Set(arr1)].filter((item) => new Set(arr2).has(item));
}
1
2
3
export function getArrEqual(arr1, arr2) {
return arr1.filter((item) => arr2.indexOf(item) > -1);
}
1
2
3
export function getArrEqual(arr1, arr2) {
return arr1.filter((item) => arr2.includes(item));
}
1
2
3
export function getArrEqual(arr1, arr2) {
return arr1.filter((a) => arr2.find((b) => b == a));
}

多数组取交集

1
2
3
4
export const intersection = (a, ...arr) =>
[...new Set(a)].filter((v) => arr.every((b) => b.includes(v)));

// intersection([1, 2, 3, 4], [2, 3, 4, 7, 8], [1, 3, 4, 9]); // [3, 4]

求补集

过滤两个数组中相同项,生成一个新数组

1
2
3
4
5
export function getArrComplement(arr1, arr2) {
return [...new Set(arr1), ...new Set(arr2)].filter(
(value, index, arr) => arr.indexOf(value) === arr.lastIndexOf(value)
);
}
1
2
3
4
5
6
export function getArrComplement(arr1, arr2) {
return [
...arr1.filter((item) => !new Set(arr2).has(item)),
...arr2.filter((item) => !new Set(arr1).has(item))
];
}
1
2
3
4
5
export function getArrDiffer(arr1, arr2) {
return arr1
.filter((item) => !arr2.some((e) => e === item))
.concat(arr2.filter((item) => !arr1.some((e) => e === item)));
}
1
2
3
4
5
export function getArrDiffer(arr1, arr2) {
return arr1
.filter((item) => arr2.every((e) => e !== item))
.concat(arr2.filter((item) => arr1.every((e) => e !== item)));
}

求差集

过滤 arr2 中不与 arr1 相同的项

1
2
3
export function getArrDiffer(arr1, arr2) {
return arr2.filter((item) => !arr1.some((e) => e === item));
}
1
2
3
export function getArrDiffer(arr1, arr2) {
return arr2.filter((item) => arr1.every((e) => e !== item));
}

多个数组

求交集

1
2
export const getArrEqual = (a, ...arr) =>
[...new Set(a)].filter((v) => arr.every((b) => b.includes(v)));

压缩

1
2
3
4
5
6
export const zip = (...arr) =>
Array.from({ length: Math.max(...arr.map((a) => a.length)) }, (_, i) =>
arr.map((a) => a[i])
);

zip([1, 2, 3, 4], ["a", "b", "c", "d"], ["A", "B", "C", "D"]); // [[1, 'a', 'A'], [2, 'b', 'B'], [3, 'c', 'C'], [4, 'd', 'D']]

将数组随机混排

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 将数组随机混排
* @arr {Array} 数组
*/
export function randomSort(arr = []) {
let m = arr.length,
t,
i;
while (m) {
i = Math.floor(Math.random() * m--);
t = arr[m];
arr[m] = arr[i];
arr[i] = t;
}
return arr;
}
1
export const randomSort = (list) => list.sort(() => Math.random() - 0.5);
1
2
3
4
5
// 打乱数组
export function randomSort(array = []) {
// 原理是sort排序,Math.random()产生0<= x < 1之间的数,会导致x-0.05大于或者小于0
return array.sort(() => Math.random() - 0.5);
}

从数组中随机获取几个元素(不重复)

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 从数组中随机获取几个元素(不重复)
* @param arr 可选值
* @param num 可选值
*/
export function getRandom(arr = [], num = 1) {
let a = [...arr];
let newArr = [];
for (let i = 0; i < num; i++)
newArr.push(a.splice(Math.floor(Math.random() * a.length), 1)[0]);
return newArr;
}

生成 1 到 N 的数组 [1,2,3…,N]

1
2
3
4
5
export const createArr = (n) => [...Array(n + 1).keys()].splice(1, n);

export const createArr = (n) => Array.from(new Array(n), (v, i) => i);

export const createArr = (n) => new Array(n).fill(0).map((v, i) => i);

时间相关

判断日期是否为今天

1
2
export const isToday = (date) =>
date.toISOString().slice(0, 10) === new Date().toISOString().slice(0, 10);

时间字符串校验

1
2
3
4
5
6
7
8
9
10
/**
* 时间字符串校验
* @param {string} date 时间字符串
* @returns {boolean}
*/
export function verifyDateLegal(date) {
return /((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))0229))|((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29))$/.test(
date
);
}

时间格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/**
* 时间格式化
* @param {*} date 时间(可以传入时间戳)
* @param {*} format 格式
* YYYY-MM-DD(yyyy-MM-dd)
* HH:mm:ss hh:mm:ss "H: 24小时计时 h: 12小时计时"
* 星期W 第Q季度
*/
export function timeF(date, format) {
date = date || new Date();
format = format || "YYYY-MM-DD";
// 转换毫秒和字符串为时间对象
if (typeof date === "string") {
if (/^\d+$/.test(date)) {
date = parseInt(date);
} else {
// 处理日期兼容(火狐和safari浏览器)
date = date.replace(new RegExp(/-/gm), "/");
}
} else if (typeof date === "number" && date.toString().length === 10) {
date = date * 1000;
}
let d = new Date(date);
// d是NaN的时候返回空
if (isNaN(d)) return "";

function fillZero(num) {
return num.toString().padStart(2, "0");
}
const WEEK_DISPLAY = ["日", "一", "二", "三", "四", "五", "六"];
const formatObj = {
YYYY: d.getFullYear(), // 年
yyyy: d.getFullYear(), // 年
MM: fillZero(d.getMonth() + 1), // 月份 [01..12]
M: d.getMonth() + 1, // 月份 [1..12]
DD: fillZero(d.getDate()), // 日期 [01..31]
D: d.getDate(), // 日期 [1..31]
dd: fillZero(d.getDate()), // 日期 [01..31]
d: d.getDate(), // 日期 [1..31]
W: WEEK_DISPLAY[d.getDay()], // 星期
hh: fillZero(d.getHours() % 12 || 12), // 时 [01..12]
h: d.getHours() % 12 || 12, // 时 [1.12]
HH: fillZero(d.getHours()), // 时 [00..23]
H: d.getHours(), // 时 [0..23]
mm: fillZero(d.getMinutes()), // 分钟 [00..59]
m: d.getMinutes(), // 分钟 [0..59]
ss: fillZero(d.getSeconds()), // 秒 [00..59]
s: d.getSeconds(), // 秒 [0..59]
S: d.getMilliseconds(), // 毫秒
Q: Math.ceil((d.getMonth() + 1) / 3), // 季度
x: d.getTime(), // 时间戳,单位:毫秒
X: Math.floor(d.getTime() / 1000) // 时间戳,单位:秒
};
const reg =
/Y{4}|y{4}|M{1,2}|D{1,2}|d{1,2}|H{1,2}|h{1,2}|m{1,2}|s{1,2}|S|W|Q|x|X/g;
return format.replace(reg, (match) =>
formatObj[match] ? formatObj[match] : ""
);
}
1
2
3
4
5
6
7
8
9
10
// 需要引入moment.js
moment.locale("zh-cn");

export function timeF(
time,
pattern = "YYYY-MM-DD HH:mm:ss",
placeholder = "--"
) {
return time ? moment(time).format(pattern) : placeholder;
}

获取日期所在周起止时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* 获取日期所在周起止时间
* @param {Date|String|Number} time 对比时间
* @param {Boolean} sundayFirst 一周的第一天是 周日:true 周一:false
* @returns {Object}
*/
export function getTimeWeek(time, fromTime, fmt, sundayFirst = true) {
// @ts-ignore
let newTime = timeF("date", time, true, fromTime);
// @ts-ignore
let dayCode = newTime.getDay();

let curTime = timeF(fmt || "yyyy-MM-dd", newTime);
let startTime = timeF(
fmt || "yyyy-MM-dd 00:00:00",
`-${sundayFirst ? dayCode : dayCode - 1} day`,
true,
newTime
);
let endTime = timeF(
fmt || "yyyy-MM-dd 23:59:59",
`+${sundayFirst ? 6 - dayCode : 7 - dayCode} day`,
true,
newTime
);

return {
curTime,
startTime,
endTime,
days: [
timeF("yyyy-MM-dd", startTime),
timeF("yyyy-MM-dd", "+1 day", true, startTime),
timeF("yyyy-MM-dd", "+2 day", true, startTime),
timeF("yyyy-MM-dd", "+3 day", true, startTime),
timeF("yyyy-MM-dd", "+4 day", true, startTime),
timeF("yyyy-MM-dd", "+5 day", true, startTime),
timeF("yyyy-MM-dd", "+6 day", true, startTime)
]
};
}

获取日期所在月起止时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 获取日期所在月起止时间
* @param {Date|String|Number} time 对比时间
*/
export function getTimeMonth(time, fromTime, fmt) {
const newTime = timeF("date", time, true, fromTime);
const monthLast = timeF("date", newTime);
const startTime = timeF(fmt || "yyyy-MM-01 00:00:00", monthLast);
// @ts-ignore
monthLast.setMonth(monthLast.getMonth() + 1, 0);
const endTime = timeF(fmt || "yyyy-MM-dd 23:59:59", monthLast);
const ym = String(endTime).slice(0, 8);
const endDay = new Date(monthLast).getDate();
const days = [];
let day = 1;
while (day <= endDay) {
days.push(ym + String(day).padStart(2, "0"));
day++;
}

time = timeF("date", time);
return {
curTime: timeF(fmt || "yyyy-MM-dd", newTime),
startTime,
endTime,
days
};
}

获取上个月 下个月 起止时间

1
2
3
4
5
6
7
8
9
10
11
/**
* 获取上个月 下个月 起止时间
* @param {String} type next prev
* @returns {Object}
*/
export function getNextMonth(type = "next", fromTime, curFmt) {
const monthNext = timeF("date", fromTime);
// @ts-ignore
monthNext.setMonth(monthNext.getMonth() + (type === "next" ? 1 : -1));
return getTimeMonth(monthNext, undefined, curFmt);
}

时间处理成 N 分钟的倍数(向下取整)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 时间处理成N分钟的倍数(向下取整)
* @param {string} [str] 标准时间格式yyyy-MM-dd hh:mm:ss
* @param {Number} [num] 间隔的分钟
* @returns {string}
*/
export function timeStrF(str, num = 5) {
str = str || String(timeF());
return str.replace(
/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})(.*)/,
(_, y, M, d, h, m, s) => {
const _m = parseInt(String(m / num)) * num;
return `${y}-${M}-${d} ${h}:${_m < 10 ? "0" : ""}${_m}:00`;
}
);
}

时间长短

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/**
* 两个日期之间的时长
*/
export function timeL(date1, date2) {
const f = { y: "年", M: "月", d: "天", h: "小时", m: "分", s: "秒" };

let l = new Date(+timeF("t", date1) - +timeF("t", date2));
let o = {
y: l.getUTCFullYear() - 1970,
M: l.getUTCMonth(),
d: l.getUTCDate() - 1,
h: l.getUTCHours(),
m: l.getUTCMinutes(),
s: l.getUTCSeconds()
};

const arr = Object.keys(o);
o["t"] = arr.reduce((p, c) => p + (o[c] ? o[c] + f[c] : ""), "");

return o;
}

/**
* 时间长短
* @param {number} time 毫秒数
* @param {string} fmt 格式,例如 {y}年{d}天{h}小时{m}分{s}秒
* @param {object} options
* @param {boolean} [options.clear] 清理前面的0值
* @param {string} [options.last] 最后一位处理方式,floor:向下取整,ceil:向上取整,round:四舍五入,fix1:保留1位(前面值都是0时候生效)
* @returns {object}
*/
export function timeL(options = {}) {
let {
tl /* time length */,
t1,
t2,
fmt = "{y}年{M}月{d}天{h}小时{m}分{s}秒",
clear = true,
last = "floor"
} = options;

if (!tl && (!t1 || !t2)) return { t: "" };

tl = tl || Math.abs(timeF("t", t1) - timeF("t", t2));

let o = {
"{y}": 365 * 24 * 60 * 60 * 1000, // 年
"{M}": 30 * 24 * 60 * 60 * 1000, // 月
"{d}": 24 * 60 * 60 * 1000, // 日
"{h}": 60 * 60 * 1000, // 小时
"{m}": 60 * 1000, // 分
"{s}": 1000 // 秒
};
const reg = new RegExp(Object.keys(o).join("|"), "g");
let fmt_last;
let first_num = -1;
let fmt_num = 0;
fmt.replace(reg, (f) => ((fmt_last = f), ""));
let data = {};
let a = Number(tl);
const fun = (num) =>
last === "fix1" ? Number(num.toFixed(1)) : Math[last](num);
let str = fmt.replace(reg, (f, i) => {
// 是否有非0值
const noVal = first_num == -1;
let v =
f === "{s}"
? Math.ceil(a / o[f])
: fmt_last === f && noVal
? fun(a / o[f])
: Math.floor(a / o[f]);
a %= o[f];
if (clear && ((v !== 0 && noVal) || fmt_last === f)) {
first_num = i - fmt_num;
}
if (clear && first_num != -1) {
data[f.replace(/[{}]/g, "")] = v;
}
if (first_num == -1) {
fmt_num += 2;
}
return v;
});
// str = str.slice(first_num);
data["t"] = str;
return data;
}

日期转换

将日期转换为为 YYYY-MM-DD 格式

1
2
export const formatYmd = (date) => date.toISOString().slice(0, 10);
formatYmd(new Date());

秒数转换

将秒数转换为 hh:mm:ss 格式

1
2
3
export const formatSeconds = (s) =>
new Date(s * 1000).toISOString().substr(11, 8);
formatSeconds(200); // 00:03:20

时间戳转为多久之前

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/**
* 时间戳转为多久之前
* @param String timestamp 时间戳
* @param String | Boolean format 如果为时间格式字符串,超出一定时间范围,返回固定的时间格式;
* 如果为布尔值false,无论什么时间,都返回多久以前的格式
*/
export function timeFrom(dateTime = null, format = "yyyy-mm-dd") {
// 如果为null,则格式化当前时间
if (!dateTime) dateTime = Number(new Date());
// 如果dateTime长度为10或者13,则为秒和毫秒的时间戳,如果超过13位,则为其他的时间格式
if (dateTime.toString().length == 10) dateTime *= 1000;
let timestamp = +new Date(Number(dateTime));

let timer = (Number(new Date()) - timestamp) / 1000;
// 如果小于5分钟,则返回"刚刚",其他以此类推
let tips = "";
switch (true) {
case timer < 300:
tips = "刚刚";
break;
case timer >= 300 && timer < 3600:
tips = parseInt(timer / 60) + "分钟前";
break;
case timer >= 3600 && timer < 86400:
tips = parseInt(timer / 3600) + "小时前";
break;
case timer >= 86400 && timer < 2592000:
tips = parseInt(timer / 86400) + "天前";
break;
default:
// 如果format为false,则无论什么时间戳,都显示xx之前
if (format === false) {
if (timer >= 2592000 && timer < 365 * 86400) {
tips = parseInt(timer / (86400 * 30)) + "个月前";
} else {
tips = parseInt(timer / (86400 * 365)) + "年前";
}
} else {
tips = timeF(timestamp, format);
}
}
return tips;
}

计算两个日期间的天数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* 计算两个日期间的天数
* @param {Number} startTime 开始日期
* @param {Number} endTime 截止日期
*/
export function timeCount(startTime = null, endTime = new Date()) {
if (!startTime) return "1天";
startTime = +timeF("t", startTime);
endTime = +timeF("t", endTime);

let timer = endTime - startTime;

return Math.ceil(timer / 86400000) + "天";
}

返回指定长度的月份集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
* 返回指定长度的月份集合
*
* @param {time} 时间
* @param {len} 长度
* @param {direction} 方向: 1: 前几个月; 2: 后几个月; 3:前后几个月 默认 3
* @return {Array} 数组
*
* @example getMonths('2018-1-29', 6, 1) // -> ["2018-1", "2017-12", "2017-11", "2017-10", "2017-9", "2017-8", "2017-7"]
*/
export function getMonths(time, len, direction) {
var mm = new Date(time).getMonth(),
yy = new Date(time).getFullYear(),
direction = isNaN(direction) ? 3 : direction,
index = mm;
var cutMonth = function (index) {
if (index <= len && index >= -len) {
return direction === 1
? formatPre(index).concat(cutMonth(++index))
: direction === 2
? formatNext(index).concat(cutMonth(++index))
: formatCurr(index).concat(cutMonth(++index));
}
return [];
};
var formatNext = function (i) {
var y = Math.floor(i / 12),
m = i % 12;
return [yy + y + "-" + (m + 1)];
};
var formatPre = function (i) {
var y = Math.ceil(i / 12),
m = i % 12;
m = m === 0 ? 12 : m;
return [yy - y + "-" + (13 - m)];
};
var formatCurr = function (i) {
var y = Math.floor(i / 12),
yNext = Math.ceil(i / 12),
m = i % 12,
mNext = m === 0 ? 12 : m;
return [yy - yNext + "-" + (13 - mNext), yy + y + "-" + (m + 1)];
};
// 数组去重
var unique = function (arr) {
if (Array.hasOwnProperty("from")) {
return Array.from(new Set(arr));
} else {
var n = {},
r = [];
for (var i = 0; i < arr.length; i++) {
if (!n[arr[i]]) {
n[arr[i]] = true;
r.push(arr[i]);
}
}
return r;
}
};
return direction !== 3
? cutMonth(index)
: unique(
cutMonth(index).sort(function (t1, t2) {
return new Date(t1).getTime() - new Date(t2).getTime();
})
);
}

返回指定长度的天数集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* 返回指定长度的天数集合
*
* @param {time} 时间
* @param {len} 长度
* @param {direction} 方向: 1: 前几天; 2: 后几天; 3:前后几天 默认 3
* @return {Array} 数组
*
* @example date.getDays('2018-1-29', 6) // -> ["2018-1-26", "2018-1-27", "2018-1-28", "2018-1-29", "2018-1-30", "2018-1-31", "2018-2-1"]
*/
export function getDays(time, len, diretion) {
var tt = new Date(time);
var getDay = function (day) {
var t = new Date(time);
t.setDate(t.getDate() + day);
var m = t.getMonth() + 1;
return t.getFullYear() + "-" + m + "-" + t.getDate();
};
var arr = [];
if (diretion === 1) {
for (var i = 1; i <= len; i++) {
arr.unshift(getDay(-i));
}
} else if (diretion === 2) {
for (var i = 1; i <= len; i++) {
arr.push(getDay(i));
}
} else {
for (var i = 1; i <= len; i++) {
arr.unshift(getDay(-i));
}
arr.push(tt.getFullYear() + "-" + (tt.getMonth() + 1) + "-" + tt.getDate());
for (var i = 1; i <= len; i++) {
arr.push(getDay(i));
}
}
return diretion === 1
? arr.concat([
tt.getFullYear() + "-" + (tt.getMonth() + 1) + "-" + tt.getDate()
])
: diretion === 2
? [
tt.getFullYear() + "-" + (tt.getMonth() + 1) + "-" + tt.getDate()
].concat(arr)
: arr;
}

转化秒数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* @param {s} 秒数
* @return {String} 字符串
*
* @example formatHMS(3610) // -> 1h0m10s
*/
export function formatHMS(s) {
var str = "";
if (s > 3600) {
str =
Math.floor(s / 3600) +
"h" +
Math.floor((s % 3600) / 60) +
"m" +
(s % 60) +
"s";
} else if (s > 60) {
str = Math.floor(s / 60) + "m" + (s % 60) + "s";
} else {
str = (s % 60) + "s";
}
return str;
}

获取某月有多少天

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/*获取某月有多少天*/
export function getMonthOfDay(time) {
var date = new Date(time);
var year = date.getFullYear();
var mouth = date.getMonth() + 1;
var days;

// 当月份为二月时,根据闰年还是非闰年判断天数
if (mouth == 2) {
days =
(year % 4 == 0 && year % 100 == 0 && year % 400 == 0) ||
(year % 4 == 0 && year % 100 != 0)
? 28
: 29;
} else if (
mouth == 1 ||
mouth == 3 ||
mouth == 5 ||
mouth == 7 ||
mouth == 8 ||
mouth == 10 ||
mouth == 12
) {
// 月份为:1,3,5,7,8,10,12 时,为大月.则天数为31;
days = 31;
} else {
// 其他月份,天数为:30.
days = 30;
}
return days;
}

获取某年有多少天

1
2
3
4
5
6
7
8
/* 获取某年有多少天 */
export function getYearOfDay(time) {
var firstDayYear = this.getFirstDayOfYear(time);
var lastDayYear = this.getLastDayOfYear(time);
var numSecond =
(new Date(lastDayYear).getTime() - new Date(firstDayYear).getTime()) / 1000;
return Math.ceil(numSecond / (24 * 3600));
}

获取某年的第一天

1
2
3
4
5
6
7
8
/* 获取某年的第一天 */
export function getFirstDayOfYear(time) {
var year = new Date(time).getFullYear();
return year + "-01-01 00:00:00";
}

export const getFirstDate = (d = new Date()) =>
new Date(d.getFullYear(), d.getMonth(), 1);

获取某年最后一天

1
2
3
4
5
6
7
/* 获取某年最后一天 */
export function getLastDayOfYear(time) {
var year = new Date(time).getFullYear();
var dateString = year + "-12-01 00:00:00";
var endDay = this.getMonthOfDay(dateString);
return year + "-12-" + endDay + " 23:59:59";
}

获取某个日期是当年中的第几天

1
2
3
4
5
6
7
/* 获取某个日期是当年中的第几天 */
export function getDayOfYear(time) {
var firstDayYear = this.getFirstDayOfYear(time);
var numSecond =
(new Date(time).getTime() - new Date(firstDayYear).getTime()) / 1000;
return Math.ceil(numSecond / (24 * 3600));
}

获取某个日期在这一年的第几周

1
2
3
4
5
/* 获取某个日期在这一年的第几周 */
export function getDayOfYearWeek(time) {
var numdays = this.getDayOfYear(time);
return Math.ceil(numdays / 7);
}

获取某年某月的第一天

1
2
3
4
export const getFirstDate = (d = new Date()) =>
new Date(d.getFullYear(), d.getMonth(), 1);

getFirstDate(new Date("2022-04")); // Fri Apr 01 2022 00:00:00 GMT+0800 (中国标准时间)

获取某年某月的最后一天

1
2
3
4
export const getLastDate = (d = new Date()) =>
new Date(d.getFullYear(), d.getMonth() + 1, 0);

getLastDate(new Date("2023-03-04")); // Fri Mar 31 2023 00:00:00 GMT+0800 (中国标准时间)

获取某年月份天数

1
2
3
export const getDaysNum = (year, month) => new Date(year, month, 0).getDate();

export const day = getDaysNum(2024, 2); // 29

获取年龄

1
2
3
4
5
6
7
8
9
export function getAge(birthday) {
if (!birthday) return;
//出生时间 毫秒
var birthDayTime = new Date(birthday).getTime();
//当前时间 毫秒
var nowTime = new Date().getTime();
//一年毫秒数(365 * 86400000 = 31536000000)
return Math.ceil((nowTime - birthDayTime) / 31536000000);
}

颜色渐变相关

colorGradient-颜色渐变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/**
* 求两个颜色之间的渐变值
* @param {string} startColor 开始的颜色
* @param {string} endColor 结束的颜色
* @param {number} step 颜色等分的份额
* */
export function colorGradient(
startColor = "rgb(0, 0, 0)",
endColor = "rgb(255, 255, 255)",
step = 10
) {
let startRGB = hexToRgb(startColor, false); //转换为rgb数组模式
let startR = startRGB[0];
let startG = startRGB[1];
let startB = startRGB[2];

let endRGB = hexToRgb(endColor, false);
let endR = endRGB[0];
let endG = endRGB[1];
let endB = endRGB[2];

let sR = (endR - startR) / step; //总差值
let sG = (endG - startG) / step;
let sB = (endB - startB) / step;
let colorArr = [];
for (let i = 0; i < step; i++) {
//计算每一步的hex值
let hex = rgbToHex(
"rgb(" +
Math.round(sR * i + startR) +
"," +
Math.round(sG * i + startG) +
"," +
Math.round(sB * i + startB) +
")"
);
colorArr.push(hex);
}
return colorArr;
}

hexToRgb-十六进制颜色转 rgb 颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* 将hex表示方式转换为rgb表示方式
* @param {*} sColor 16进制颜色
* @param {*} str 是否字符串
*/
export function hexToRgb(sColor, str = true) {
let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
sColor = sColor.toLowerCase();
if (sColor && reg.test(sColor)) {
if (sColor.length === 4) {
let sColorNew = "#";
for (let i = 1; i < 4; i += 1) {
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
}
sColor = sColorNew;
}
//处理六位的颜色值
let sColorChange = [];
for (let i = 1; i < 7; i += 2) {
sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
}
if (!str) {
return sColorChange;
} else {
return `rgb(${sColorChange[0]},${sColorChange[1]},${sColorChange[2]})`;
}
} else if (/^(rgb|RGB)/.test(sColor)) {
let arr = sColor.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
return arr.map((val) => Number(val));
} else {
return sColor;
}
}

rgbToHex

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 将rgb表示方式转换为hex表示方式
* @param {string} rgb 颜色
*/
export function rgbToHex(rgb) {
let _this = rgb;
let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
if (/^(rgb|RGB)/.test(_this)) {
let aColor = _this.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
let strHex = "#";
for (let i = 0; i < aColor.length; i++) {
let hex = Number(aColor[i]).toString(16);
hex = String(hex).length == 1 ? 0 + "" + hex : hex; // 保证每个rgb的值为2位
if (hex === "0") {
hex += hex;
}
strHex += hex;
}
if (strHex.length !== 7) {
strHex = _this;
}
return strHex;
} else if (reg.test(_this)) {
let aNum = _this.replace(/#/, "").split("");
if (aNum.length === 6) {
return _this;
} else if (aNum.length === 3) {
let numHex = "#";
for (let i = 0; i < aNum.length; i += 1) {
numHex += aNum[i] + aNum[i];
}
return numHex;
}
} else {
return _this;
}
}

十六进制转换为 rgb 或 rgba

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* 颜色十六进制转换为rgb或rgba,返回的格式为 rgba(255,255,255,0.5)字符串
* sHex为传入的十六进制的色值
* alpha为rgba的透明度
*/
export function colorToRgba(color, alpha = 0.3) {
color = rgbToHex(color);
// 十六进制颜色值的正则表达式
var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
/* 16进制颜色转为RGB格式 */
let sColor = color.toLowerCase();
if (sColor && reg.test(sColor)) {
if (sColor.length === 4) {
var sColorNew = "#";
for (let i = 1; i < 4; i += 1) {
sColorNew += sColor.slice(i, i + 1).concat(sColor.slice(i, i + 1));
}
sColor = sColorNew;
}
// 处理六位的颜色值
var sColorChange = [];
for (let i = 1; i < 7; i += 2) {
sColorChange.push(parseInt("0x" + sColor.slice(i, i + 2)));
}
// return sColorChange.join(',')
return "rgba(" + sColorChange.join(",") + "," + alpha + ")";
} else {
return sColor;
}
}

url 相关

对象转 url 参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/**
* 对象转url参数
* @param {*} data,对象
* @param {*} isPrefix,是否自动加上"?"
*/
export function queryParams(
data = {},
isPrefix = true,
arrayFormat = "brackets"
) {
let prefix = isPrefix ? "?" : "";
let _result = [];
if (["indices", "brackets", "repeat", "comma"].indexOf(arrayFormat) == -1)
arrayFormat = "brackets";
for (let key in data) {
let value = data[key];
// 去掉为空的参数
if (["", undefined, null].indexOf(value) >= 0) {
continue;
}
// 如果值为数组,另行处理
if (value.constructor === Array) {
// e.g. {ids: [1, 2, 3]}
switch (arrayFormat) {
case "indices":
// 结果: ids[0]=1&ids[1]=2&ids[2]=3
for (let i = 0; i < value.length; i++) {
_result.push(key + "[" + i + "]=" + value[i]);
}
break;
case "brackets":
// 结果: ids[]=1&ids[]=2&ids[]=3
value.forEach((_value) => {
_result.push(key + "[]=" + _value);
});
break;
case "repeat":
// 结果: ids=1&ids=2&ids=3
value.forEach((_value) => {
_result.push(key + "=" + _value);
});
break;
case "comma":
// 结果: ids=1,2,3
let commaStr = "";
value.forEach((_value) => {
commaStr += (commaStr ? "," : "") + _value;
});
_result.push(key + "=" + commaStr);
break;
default:
value.forEach((_value) => {
_result.push(key + "[]=" + _value);
});
}
} else {
_result.push(key + "=" + value);
}
}
return _result.length ? prefix + _result.join("&") : "";
}

获取 url 中的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 获取url中的参数
*/
export function getUrlParams() {
var url = location.search; // 获取url中"?"符后的字串
var theParams = {}; // 初始化空对象接受url中的所有参数
if (url.indexOf("?") != -1) {
var str = url.substr(1),
strs = str.split("&"); // 各个参数放到数组里
for (var i = 0; i < strs.length; i++) {
theParams[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
}
}
return theParams;
}

web 相关

重新加载当前页面

1
2
export const reload = () => location.reload();
reload();

滚动到页面顶部

如果你需要将页面翻到最顶部

1
2
export const goToTop = () => window.scrollTo(0, 0);
goToTop();

元素滚动

如果你希望将一个元素顺滑的滚动到可视区域的起点

1
2
3
export const scrollToTop = (element) =>
element.scrollIntoView({ behavior: "smooth", block: "start" });
scrollToTop(document.body);

如果你希望将一个元素顺滑的滚动到可视区域的终点

1
2
3
export const scrollToBottom = (element) =>
element.scrollIntoView({ behavior: "smooth", block: "end" });
scrollToBottom(document.body);

检查当前是否 IE 浏览器

1
export const isIE = !!document.documentMode;

从给定文本中剥离 html

1
2
3
4
5
// 在某个文本中将里面的标签全部过滤掉

export const stripHtml = (html) =>
new DOMParser().parseFromString(html, "text/html").body.textContent || "";
stripHtml("<div>test</div>"); // 'test'

重定向

1
2
3
// 跳转到其他页面

export const goTo = (url) => (location.href = url);

文本粘贴

1
2
3
4
5
// 复制文本到粘贴板上

export const copy = (text) =>
navigator.clipboard?.writeText && navigator.clipboard.writeText(text);
copy("你需要粘贴的文本");

文件

获取文件名和后缀

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 获取文件名和后缀
* @param {String} name
*/
export const getFileExt = (name) => {
const last_len = name.lastIndexOf(".");
const len = name.length;
return {
name: name.substring(0, last_len),
ext: name.substring(last_len + 1, len)
};
};

获取扩展名

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 获取扩展名
* @param {Array} file
*/
export const getExtName = (file) => {
if (!Array.isArray(file)) {
let extname = file.replace(/(\[|\])/g, "");
return extname.split(",");
} else {
return file;
}
};

文件大小字节转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* @param {*} size 单位B
*/
export function sizeTostr(size) {
var data = "";
if (size < 0.1 * 1024) {
//如果小于0.1KB转化成B
data = size.toFixed(2) + "B";
} else if (size < 0.1 * 1024 * 1024) {
//如果小于0.1MB转化成KB
data = (size / 1024).toFixed(2) + "KB";
} else if (size < 0.1 * 1024 * 1024 * 1024) {
//如果小于0.1GB转化成MB
data = (size / (1024 * 1024)).toFixed(2) + "MB";
} else {
//其他转化成GB
data = (size / (1024 * 1024 * 1024)).toFixed(2) + "GB";
}
var sizestr = data + "";
var len = sizestr.indexOf(".");
var dec = sizestr.substr(len + 1, 2);
if (dec == "00") {
//当小数点后为00时 去掉小数部分
return sizestr.substring(0, len) + sizestr.substr(len + 3, 2);
}
return sizestr;
}

其他

异步操作和结束标志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 异步操作和结束标志
* @param {function} fn
*/
export function runEndWith(fn) {
return function (...args) {
let times = 0;
let end = false;
return new Promise((resolve, reject) => {
end = end ? end : args[args.length - 1];
times++;
fn(...args).finally(() => {
times--;
end && times === 0 ? resolve() : reject();
});
});
};
}

获取随机 ip

1
2
3
4
5
export const randomIp = () =>
Array(4)
.fill(0)
.map((_, i) => Math.floor(Math.random() * 255) + (i === 0 ? 1 : 0))
.join(".");

将 cookie 转换成对象

1
2
3
4
5
6
export const getCookie = () =>
document.cookie
.split(";")
.map((item) => item.split("="))
.reduce((acc, [k, v]) => (acc[k.trim().replace('"', "")] = v) && acc, {});
getCookie();

强制等待

等待一段时间,但又不想写在 setTimeout 函数中,造成回调地狱

1
2
3
4
5
export const sleep = async (t) =>
new Promise((resolve) => setTimeout(resolve, t));
sleep(2000).then(() => {
console.log("time");
});

版本号比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 当前版本号是否小于比较方法
* @param {String} curV 当前版本号
* @param {String} newV 新版本号
* @returns {Boolean}
*/
export function compareVersion(curV, newV) {
if (newV && curV && newV !== curV) {
//将两个版本号拆成数字
let curVArr = curV.split("."),
newVArr = newV.split(".");
let maxLength = Math.max(curVArr.length, newVArr.length),
diff = 0;
//依次比较版本号每一位大小,当对比得出结果后跳出循环
for (let i = 0; i < maxLength; i++) {
diff = parseInt(curVArr[i] || "0") - parseInt(newVArr[i] || "0");
if (diff !== 0) {
break;
}
}
//若curV大于reqV,则返回true
return diff < 0;
} else {
return false;
}
}