util-helpers 4.10.1 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/util-helpers.js +208 -153
- package/dist/util-helpers.js.map +1 -1
- package/dist/util-helpers.min.js +1 -1
- package/dist/util-helpers.min.js.map +1 -1
- package/esm/bytesToSize.js +4 -3
- package/esm/formatMoney.js +7 -10
- package/esm/isBusinessLicense.js +17 -16
- package/esm/isChinese.js +24 -11
- package/esm/isSocialCreditCode.js +16 -9
- package/esm/isTWCard.js +18 -4
- package/esm/numberToChinese.js +30 -36
- package/esm/parseIdCard.js +9 -24
- package/esm/replaceChar.js +8 -7
- package/esm/round.js +8 -0
- package/esm/utils/devWarn.js +16 -0
- package/esm/utils/math.util.js +52 -29
- package/esm/validatePassword.js +25 -20
- package/lib/bytesToSize.js +4 -3
- package/lib/formatMoney.js +7 -10
- package/lib/isBusinessLicense.js +17 -16
- package/lib/isChinese.js +24 -11
- package/lib/isSocialCreditCode.js +16 -9
- package/lib/isTWCard.js +18 -4
- package/lib/numberToChinese.js +32 -36
- package/lib/parseIdCard.js +9 -24
- package/lib/replaceChar.js +11 -8
- package/lib/round.js +9 -0
- package/lib/utils/devWarn.js +24 -0
- package/lib/utils/math.util.js +54 -29
- package/lib/validatePassword.js +27 -20
- package/package.json +3 -2
- package/types/isBusinessLicense.d.ts +7 -10
- package/types/isChinese.d.ts +13 -3
- package/types/isSocialCreditCode.d.ts +8 -5
- package/types/isTWCard.d.ts +7 -2
- package/types/replaceChar.d.ts +1 -1
- package/types/utils/devWarn.d.ts +7 -0
- package/types/utils/math.util.d.ts +2 -2
- package/types/validatePassword.d.ts +3 -3
package/dist/util-helpers.js
CHANGED
|
@@ -500,7 +500,7 @@
|
|
|
500
500
|
* @since 1.1.0
|
|
501
501
|
* @param {*} value 要检测的值
|
|
502
502
|
* @param {Object} [options] 配置项
|
|
503
|
-
* @param {boolean} [options.
|
|
503
|
+
* @param {boolean} [options.checkCode=true] 是否校验最后一位校验码,如果为false,不校验校验位。
|
|
504
504
|
* @returns {boolean} 值是否为统一社会信用代码
|
|
505
505
|
* @example
|
|
506
506
|
*
|
|
@@ -510,18 +510,25 @@
|
|
|
510
510
|
* isSocialCreditCode('91350100M000100Y4A');
|
|
511
511
|
* // => false
|
|
512
512
|
*
|
|
513
|
-
* //
|
|
514
|
-
* isSocialCreditCode('91350100M000100Y4A', {
|
|
513
|
+
* // 不校验校验位
|
|
514
|
+
* isSocialCreditCode('91350100M000100Y4A', { checkCode: false });
|
|
515
515
|
* // => true
|
|
516
516
|
*
|
|
517
|
+
* isSocialCreditCode('91350100M000100Y', { checkCode: false });
|
|
518
|
+
* // => false
|
|
519
|
+
*
|
|
517
520
|
*/
|
|
518
|
-
function isSocialCreditCode(value,
|
|
521
|
+
function isSocialCreditCode(value, options = {}) {
|
|
519
522
|
const valueStr = normalizeString(value);
|
|
523
|
+
// @ts-ignore
|
|
524
|
+
// TODO 下个版本废弃 loose
|
|
525
|
+
const { loose = false, checkCode: cc = true } = options;
|
|
526
|
+
const needCheckCode = !loose && cc;
|
|
520
527
|
|
|
521
528
|
const passBaseRule = baseReg$1.test(valueStr);
|
|
522
529
|
|
|
523
530
|
// 宽松模式 或 基础规则不通过直接返回
|
|
524
|
-
if (
|
|
531
|
+
if (!needCheckCode || !passBaseRule) {
|
|
525
532
|
return passBaseRule;
|
|
526
533
|
}
|
|
527
534
|
|
|
@@ -551,6 +558,17 @@
|
|
|
551
558
|
config.disableWarning = !!bool;
|
|
552
559
|
}
|
|
553
560
|
|
|
561
|
+
/**
|
|
562
|
+
* 打印警告信息
|
|
563
|
+
*
|
|
564
|
+
* @param {any[]} args 打印的信息
|
|
565
|
+
*/
|
|
566
|
+
function devWarn(...args) {
|
|
567
|
+
if (!config.disableWarning) {
|
|
568
|
+
console.warn(...args);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
554
572
|
const regNumber = /[\d]/;
|
|
555
573
|
const regLowerCaseLetter = /[a-z]/;
|
|
556
574
|
const regUpperCaseLetter = /[A-Z]/;
|
|
@@ -605,15 +623,20 @@
|
|
|
605
623
|
*
|
|
606
624
|
* @private
|
|
607
625
|
* @param {string} val 检测的值
|
|
608
|
-
* @param {string}
|
|
626
|
+
* @param {string} chars 特殊字符
|
|
609
627
|
* @returns {boolean} 是否包含特殊字符
|
|
610
628
|
*/
|
|
611
|
-
function hasSpecialCharacter(val, chars
|
|
612
|
-
if (!chars) {
|
|
629
|
+
function hasSpecialCharacter(val, chars) {
|
|
630
|
+
if (!chars || !val) {
|
|
613
631
|
return false;
|
|
614
632
|
}
|
|
615
633
|
|
|
616
634
|
const specialChars = val.replace(regAllNumberAndLetter, '');
|
|
635
|
+
|
|
636
|
+
if (!specialChars) {
|
|
637
|
+
return false;
|
|
638
|
+
}
|
|
639
|
+
|
|
617
640
|
const regChars = hasHex(chars) ? new RegExp(`[${chars}]`) : null;
|
|
618
641
|
|
|
619
642
|
if (regChars) {
|
|
@@ -635,13 +658,19 @@
|
|
|
635
658
|
*
|
|
636
659
|
* @private
|
|
637
660
|
* @param {string} val 检测的值
|
|
638
|
-
* @param {string} chars
|
|
661
|
+
* @param {string} chars 特殊字符
|
|
639
662
|
* @returns {boolean} 是否包含非法字符
|
|
640
663
|
*/
|
|
641
|
-
function hasUnallowableCharacter(val, chars
|
|
664
|
+
function hasUnallowableCharacter(val, chars) {
|
|
665
|
+
if (!val) {
|
|
666
|
+
return false;
|
|
667
|
+
}
|
|
668
|
+
|
|
642
669
|
const specialChars = val.replace(regAllNumberAndLetter, '');
|
|
643
670
|
|
|
644
|
-
if (!
|
|
671
|
+
if (!specialChars) {
|
|
672
|
+
return false;
|
|
673
|
+
} else if (!chars) {
|
|
645
674
|
return true;
|
|
646
675
|
}
|
|
647
676
|
|
|
@@ -704,7 +733,7 @@
|
|
|
704
733
|
* }
|
|
705
734
|
* }
|
|
706
735
|
*
|
|
707
|
-
* validatePassword('a12345678', {level: 3});
|
|
736
|
+
* validatePassword('a12345678', { level: 3 });
|
|
708
737
|
* // =>
|
|
709
738
|
* {
|
|
710
739
|
* validated: false,
|
|
@@ -718,7 +747,7 @@
|
|
|
718
747
|
* }
|
|
719
748
|
* }
|
|
720
749
|
*
|
|
721
|
-
* validatePassword('_Aa一二三45678', {level: 3, ignoreCase: true});
|
|
750
|
+
* validatePassword('_Aa一二三45678', { level: 3, ignoreCase: true });
|
|
722
751
|
* // =>
|
|
723
752
|
* {
|
|
724
753
|
* validated: false,
|
|
@@ -733,7 +762,7 @@
|
|
|
733
762
|
* }
|
|
734
763
|
*
|
|
735
764
|
* // 自定义特殊字符
|
|
736
|
-
* validatePassword('_Aa一二三45678', {level: 3, ignoreCase: true, special: '_一二三'});
|
|
765
|
+
* validatePassword('_Aa一二三45678', { level: 3, ignoreCase: true, special: '_一二三' });
|
|
737
766
|
* // =>
|
|
738
767
|
* {
|
|
739
768
|
* validated: true,
|
|
@@ -751,9 +780,7 @@
|
|
|
751
780
|
let valStr = value;
|
|
752
781
|
|
|
753
782
|
if (typeof value !== 'string') {
|
|
754
|
-
|
|
755
|
-
console.warn(`[validatePassword] value must be a string.`);
|
|
756
|
-
}
|
|
783
|
+
devWarn(`[validatePassword] value must be a string.`);
|
|
757
784
|
valStr = '';
|
|
758
785
|
}
|
|
759
786
|
|
|
@@ -767,15 +794,15 @@
|
|
|
767
794
|
const containesUpperCaseLetter = hasUpperCaseLetter(valStr);
|
|
768
795
|
// 包含特殊字符
|
|
769
796
|
const containesSpecialCharacter = hasSpecialCharacter(valStr, special);
|
|
770
|
-
//
|
|
797
|
+
// 包含非法字符,即含有非数字字母特殊字符以外的其他字符
|
|
771
798
|
const containesUnallowableCharacter = hasUnallowableCharacter(valStr, special);
|
|
772
799
|
|
|
773
800
|
if (containesNumber) {
|
|
774
801
|
currentLevel += 1;
|
|
775
802
|
}
|
|
776
803
|
|
|
804
|
+
// 不区分大小写
|
|
777
805
|
if (ignoreCase) {
|
|
778
|
-
// 不区分大小写
|
|
779
806
|
if (containesLowerCaseLetter || containesUpperCaseLetter) {
|
|
780
807
|
currentLevel += 1;
|
|
781
808
|
}
|
|
@@ -906,18 +933,16 @@
|
|
|
906
933
|
chineseExtendF: '[\u{2CEB0}-\u{2EBE0}]'
|
|
907
934
|
};
|
|
908
935
|
|
|
909
|
-
|
|
936
|
+
const looseChineseRegExp = chineseDictionary.chineseBasic + '+';
|
|
937
|
+
const chineseRegExp = '^' + chineseDictionary.chineseBasic + '+$';
|
|
910
938
|
|
|
911
|
-
|
|
939
|
+
const chineseWithExtend = '(?:' + chineseDictionary.chineseBasic + '|' + chineseDictionary.chineseExtend + '|' + chineseDictionary.chineseExtendA + '|' + chineseDictionary.chineseExtendB + '|' + chineseDictionary.chineseExtendC + '|' + chineseDictionary.chineseExtendD + '|' + chineseDictionary.chineseExtendE + '|' + chineseDictionary.chineseExtendF + ')';
|
|
940
|
+
const looseChineseExtendRegExp = chineseWithExtend + '+';
|
|
941
|
+
const chineseExtendRegExp = '^' + chineseWithExtend + '+$';
|
|
912
942
|
|
|
913
943
|
// eslint-disable-next-line no-prototype-builtins
|
|
914
944
|
const supportRegExpUnicode = RegExp.prototype.hasOwnProperty('unicode');
|
|
915
945
|
|
|
916
|
-
if (supportRegExpUnicode) {
|
|
917
|
-
looseChineseRegExp = '(?:' + chineseDictionary.chineseBasic + '|' + chineseDictionary.chineseExtend + '|' + chineseDictionary.chineseExtendA + '|' + chineseDictionary.chineseExtendB + '|' + chineseDictionary.chineseExtendC + '|' + chineseDictionary.chineseExtendD + '|' + chineseDictionary.chineseExtendE + '|' + chineseDictionary.chineseExtendF + ')+';
|
|
918
|
-
chineseRegExp = '^(?:' + chineseDictionary.chineseBasic + '|' + chineseDictionary.chineseExtend + '|' + chineseDictionary.chineseExtendA + '|' + chineseDictionary.chineseExtendB + '|' + chineseDictionary.chineseExtendC + '|' + chineseDictionary.chineseExtendD + '|' + chineseDictionary.chineseExtendE + '|' + chineseDictionary.chineseExtendF + ')+$';
|
|
919
|
-
}
|
|
920
|
-
|
|
921
946
|
/**
|
|
922
947
|
* 检测值是否为中文
|
|
923
948
|
*
|
|
@@ -928,6 +953,7 @@
|
|
|
928
953
|
* @param {*} value 要检测的值
|
|
929
954
|
* @param {Object} [options] 配置项
|
|
930
955
|
* @param {boolean} [options.loose=false] 宽松模式。如果为true,只要包含中文即为true
|
|
956
|
+
* @param {boolean} [options.useExtend=false] 使用统一表意文字扩展A-F。注意:如果不支持 `RegExp.prototype.unicode`,扩展字符集将自动不生效,如IE浏览器。
|
|
931
957
|
* @returns {boolean} 值是否为中文
|
|
932
958
|
* @example
|
|
933
959
|
*
|
|
@@ -938,16 +964,30 @@
|
|
|
938
964
|
* // => false
|
|
939
965
|
*
|
|
940
966
|
* // 宽松模式,只要包含中文即为true
|
|
941
|
-
* isChinese('林A', {loose: true});
|
|
967
|
+
* isChinese('林A', { loose: true });
|
|
942
968
|
* // => true
|
|
943
969
|
*
|
|
944
|
-
* isChinese('A林A', {loose: true});
|
|
970
|
+
* isChinese('A林A', { loose: true });
|
|
945
971
|
* // => true
|
|
946
972
|
*
|
|
973
|
+
* isChinese('𠮷');
|
|
974
|
+
* // => false
|
|
975
|
+
*
|
|
976
|
+
* // 使用中文扩展字符集,需要浏览器支持 RegExp.prototype.unicode 才生效。
|
|
977
|
+
* isChinese('𠮷', { useExtend: true });
|
|
978
|
+
* // => true
|
|
979
|
+
* isChinese('𠮷aa', { useExtend: true, loose: true });
|
|
980
|
+
* // => true
|
|
947
981
|
*/
|
|
948
|
-
function isChinese(value, { loose = false } = {}) {
|
|
982
|
+
function isChinese(value, { loose = false, useExtend = false } = {}) {
|
|
949
983
|
const valueStr = normalizeString(value);
|
|
950
|
-
const
|
|
984
|
+
const basicRegExp = loose ? looseChineseRegExp : chineseRegExp;
|
|
985
|
+
const extendRegExp = loose ? looseChineseExtendRegExp : chineseExtendRegExp;
|
|
986
|
+
|
|
987
|
+
const hasExtend = useExtend && supportRegExpUnicode;
|
|
988
|
+
const resultRegExp = hasExtend ? extendRegExp : basicRegExp;
|
|
989
|
+
const flag = hasExtend ? 'u' : undefined;
|
|
990
|
+
const reg = new RegExp(resultRegExp, flag);
|
|
951
991
|
return reg.test(valueStr);
|
|
952
992
|
}
|
|
953
993
|
|
|
@@ -1103,8 +1143,8 @@
|
|
|
1103
1143
|
}
|
|
1104
1144
|
|
|
1105
1145
|
// 反模10计算
|
|
1106
|
-
if (pj ===
|
|
1107
|
-
retNum =
|
|
1146
|
+
if (pj === 1) {
|
|
1147
|
+
retNum = 0;
|
|
1108
1148
|
} else {
|
|
1109
1149
|
retNum = 11 - pj;
|
|
1110
1150
|
}
|
|
@@ -1121,32 +1161,33 @@
|
|
|
1121
1161
|
* @since 3.5.0
|
|
1122
1162
|
* @param {*} value 要检测的值
|
|
1123
1163
|
* @param {Object} [options] 配置项
|
|
1124
|
-
* @param {boolean} [options.
|
|
1164
|
+
* @param {boolean} [options.checkCode=true] 是否校验最后一位校验码,如果为false,不校验校验位。
|
|
1125
1165
|
* @returns {boolean} 值是否为营业执照号
|
|
1126
1166
|
* @example
|
|
1127
1167
|
*
|
|
1128
1168
|
* isBusinessLicense('310115600985533');
|
|
1129
1169
|
* // => true
|
|
1130
1170
|
*
|
|
1131
|
-
* isBusinessLicense('3101156009');
|
|
1132
|
-
* // => false
|
|
1133
|
-
*
|
|
1134
|
-
* isBusinessLicense('3101156009', { loose: true });
|
|
1135
|
-
* // => false
|
|
1136
|
-
*
|
|
1137
1171
|
* isBusinessLicense('310115600985535');
|
|
1138
1172
|
* // => false
|
|
1139
1173
|
*
|
|
1140
|
-
* isBusinessLicense('310115600985535', {
|
|
1174
|
+
* isBusinessLicense('310115600985535', { checkCode: false });
|
|
1141
1175
|
* // => true
|
|
1176
|
+
*
|
|
1177
|
+
* isBusinessLicense('31011560098', { checkCode: false });
|
|
1178
|
+
* // => false
|
|
1142
1179
|
*/
|
|
1143
|
-
function isBusinessLicense(value,
|
|
1180
|
+
function isBusinessLicense(value, options = {}) {
|
|
1144
1181
|
const valueStr = normalizeString(value);
|
|
1182
|
+
// @ts-ignore
|
|
1183
|
+
// TODO 下个版本废弃 loose
|
|
1184
|
+
const { loose = false, checkCode: cc = true } = options;
|
|
1185
|
+
const needCheckCode = !loose && cc;
|
|
1145
1186
|
|
|
1146
1187
|
const passBaseRule = baseReg.test(valueStr);
|
|
1147
1188
|
|
|
1148
1189
|
// 宽松模式 或 基础规则不通过直接返回
|
|
1149
|
-
if (
|
|
1190
|
+
if (!needCheckCode || !passBaseRule) {
|
|
1150
1191
|
return passBaseRule;
|
|
1151
1192
|
}
|
|
1152
1193
|
|
|
@@ -1213,8 +1254,11 @@
|
|
|
1213
1254
|
return regHMCard.test(valueStr);
|
|
1214
1255
|
}
|
|
1215
1256
|
|
|
1216
|
-
//
|
|
1217
|
-
const regTWCard =
|
|
1257
|
+
// 台湾居民来往大陆通行证正则
|
|
1258
|
+
const regTWCard = /^\d{8}$/i;
|
|
1259
|
+
|
|
1260
|
+
// 一次性短期台胞证
|
|
1261
|
+
const singleRegTWCard = /^[\da-z]{10,12}$/i;
|
|
1218
1262
|
|
|
1219
1263
|
/**
|
|
1220
1264
|
* 检测值是否为台湾居民来往大陆通行证,俗称台胞证。
|
|
@@ -1224,17 +1268,23 @@
|
|
|
1224
1268
|
* @since 4.0.0
|
|
1225
1269
|
* @see 参考 {@link https://zh.wikipedia.org/wiki/台湾居民来往大陆通行证|台湾居民来往大陆通行证}
|
|
1226
1270
|
* @param {*} value 要检测的值
|
|
1271
|
+
* @param {Object} [options] 配置项
|
|
1272
|
+
* @param {boolean} [options.loose=false] 宽松模式。如果为true,表示支持一次性短期通行证
|
|
1227
1273
|
* @returns {boolean} 是否为台湾居民来往大陆通行证
|
|
1228
1274
|
* @example
|
|
1229
1275
|
* isTWCard('12345678') // true
|
|
1230
1276
|
* isTWCard('07257456') // true
|
|
1231
1277
|
*
|
|
1232
1278
|
* // 一次性短期
|
|
1233
|
-
* isTWCard('F290299977') //
|
|
1279
|
+
* isTWCard('F290299977') // false
|
|
1280
|
+
* isTWCard('F290299977', { loose: true }) // true
|
|
1234
1281
|
*/
|
|
1235
|
-
function isTWCard(value) {
|
|
1282
|
+
function isTWCard(value, { loose = false } = {}) {
|
|
1236
1283
|
const valueStr = normalizeString(value);
|
|
1237
|
-
|
|
1284
|
+
if (regTWCard.test(valueStr)) {
|
|
1285
|
+
return true;
|
|
1286
|
+
}
|
|
1287
|
+
return loose ? singleRegTWCard.test(valueStr) : false;
|
|
1238
1288
|
}
|
|
1239
1289
|
|
|
1240
1290
|
const reg$1 = /^[A-Z]{6}[A-Z\d]{2}(?:[A-Z\d]{3})?$/;
|
|
@@ -1320,8 +1370,9 @@
|
|
|
1320
1370
|
* @returns {number}
|
|
1321
1371
|
*/
|
|
1322
1372
|
function float2Fixed(num) {
|
|
1323
|
-
|
|
1324
|
-
|
|
1373
|
+
const strNum = String(num);
|
|
1374
|
+
if (!isScientificNumber(strNum)) {
|
|
1375
|
+
return Number(strNum.replace('.', ''));
|
|
1325
1376
|
}
|
|
1326
1377
|
const dLen = digitLength(num);
|
|
1327
1378
|
return dLen > 0 ? strip(+num * Math.pow(10, dLen)) : +num;
|
|
@@ -1334,9 +1385,7 @@
|
|
|
1334
1385
|
*/
|
|
1335
1386
|
function checkBoundary(num) {
|
|
1336
1387
|
if (+num > MAX_SAFE_INTEGER || +num < MIN_SAFE_INTEGER) {
|
|
1337
|
-
|
|
1338
|
-
console.warn(`${num} is beyond boundary when transfer to integer, the results may not be accurate`);
|
|
1339
|
-
}
|
|
1388
|
+
devWarn(`${num} is beyond boundary when transfer to integer, the results may not be accurate`);
|
|
1340
1389
|
}
|
|
1341
1390
|
}
|
|
1342
1391
|
|
|
@@ -1368,37 +1417,63 @@
|
|
|
1368
1417
|
* 2.小数点前边是0,小数点后十分位(包含十分位)之后连续零的个数大于等于6个
|
|
1369
1418
|
*
|
|
1370
1419
|
* @param {string | number} num 科学计数法数字
|
|
1371
|
-
* @returns {string} 转换后的数字字符串
|
|
1420
|
+
* @returns {string | number} 转换后的数字字符串
|
|
1372
1421
|
*/
|
|
1373
1422
|
function scientificToNumber(num) {
|
|
1374
|
-
|
|
1375
|
-
const zero = '0';
|
|
1376
|
-
const parts = String(num).toLowerCase().split('e');
|
|
1377
|
-
const e = parts.pop(); // 存储指数
|
|
1378
|
-
// @ts-ignore
|
|
1379
|
-
const l = Math.abs(e); // 取绝对值,l-1就是0的个数
|
|
1380
|
-
// @ts-ignore
|
|
1381
|
-
const sign = e / l; //判断正负
|
|
1382
|
-
const coeff_array = parts[0].split('.'); // 将系数按照小数点拆分
|
|
1423
|
+
const strNum = String(num);
|
|
1383
1424
|
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
num = zero + '.' + new Array(l).join(zero) + coeff_array.join('');
|
|
1388
|
-
} else {
|
|
1389
|
-
const dec = coeff_array[1];
|
|
1425
|
+
if (!isScientificNumber(strNum)) {
|
|
1426
|
+
return num;
|
|
1427
|
+
}
|
|
1390
1428
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1429
|
+
/** @type string */
|
|
1430
|
+
let ret;
|
|
1431
|
+
|
|
1432
|
+
const zero = '0';
|
|
1433
|
+
const parts = strNum.toLowerCase().split('e');
|
|
1434
|
+
const e = parts.pop(); // 存储指数
|
|
1435
|
+
// @ts-ignore
|
|
1436
|
+
const l = Math.abs(e); // 取绝对值,l-1就是0的个数
|
|
1437
|
+
// @ts-ignore
|
|
1438
|
+
const sign = e / l; //判断正负
|
|
1439
|
+
const coeff_array = parts[0].split('.'); // 将系数按照小数点拆分
|
|
1440
|
+
|
|
1441
|
+
// 如果是小数
|
|
1442
|
+
if (sign === -1) {
|
|
1443
|
+
// 整数部分
|
|
1444
|
+
const intVal = trimLeftZero(coeff_array[0]);
|
|
1445
|
+
|
|
1446
|
+
// 整数部分大于科学计数后面部分
|
|
1447
|
+
// 如: 10e-1, 10.2e-1
|
|
1448
|
+
if (intVal.length > l) {
|
|
1449
|
+
const thanLen = intVal.length - l;
|
|
1450
|
+
const dec = coeff_array[1] || '';
|
|
1451
|
+
|
|
1452
|
+
ret = intVal.slice(0, thanLen);
|
|
1453
|
+
|
|
1454
|
+
// 处理 10e-1, 100e-1
|
|
1455
|
+
if (intVal.slice(thanLen) !== '0' || dec) {
|
|
1456
|
+
ret += '.' + intVal.slice(thanLen) + dec;
|
|
1397
1457
|
}
|
|
1458
|
+
} else {
|
|
1459
|
+
// 整数部分小于等于科学计数后面部分
|
|
1460
|
+
// 如: 1e-1, 0.2e-1, 1.2e-2, 1.2e-1
|
|
1461
|
+
ret = zero + '.' + new Array(l - intVal.length + 1).join(zero) + coeff_array.join('');
|
|
1462
|
+
}
|
|
1463
|
+
} else {
|
|
1464
|
+
// 小数部分
|
|
1465
|
+
const dec = coeff_array[1] || '';
|
|
1466
|
+
|
|
1467
|
+
// 如果是整数,将整数除第一位之外的非零数字计入位数,相应的减少0的个数
|
|
1468
|
+
if (l - dec.length < 0) {
|
|
1469
|
+
ret = trimLeftZero(coeff_array[0] + dec.substring(0, l)) + '.' + dec.substring(l);
|
|
1470
|
+
} else {
|
|
1471
|
+
// 拼接字符串,如果是整数,不需要拼接小数点
|
|
1472
|
+
ret = coeff_array.join('') + new Array(l - dec.length + 1).join(zero);
|
|
1398
1473
|
}
|
|
1399
1474
|
}
|
|
1400
|
-
|
|
1401
|
-
return
|
|
1475
|
+
|
|
1476
|
+
return trimLeftZero(ret);
|
|
1402
1477
|
}
|
|
1403
1478
|
|
|
1404
1479
|
/**
|
|
@@ -1432,9 +1507,7 @@
|
|
|
1432
1507
|
*/
|
|
1433
1508
|
function checkNumber(num) {
|
|
1434
1509
|
if (!(reg.test(num) || isScientificNumber(num)) || _isNaN(num) || (typeof num !== 'number' && typeof num !== 'string') || num === '') {
|
|
1435
|
-
|
|
1436
|
-
console.warn(`${num} invalid parameter.`);
|
|
1437
|
-
}
|
|
1510
|
+
devWarn(`${num} invalid parameter.`);
|
|
1438
1511
|
|
|
1439
1512
|
return false;
|
|
1440
1513
|
}
|
|
@@ -1558,9 +1631,9 @@
|
|
|
1558
1631
|
decimal = typeof decimal === 'string' ? decimal : '.';
|
|
1559
1632
|
|
|
1560
1633
|
// 转换数字字符串,支持科学记数法
|
|
1561
|
-
const
|
|
1634
|
+
const strNum = scientificToNumber(num) + '';
|
|
1562
1635
|
// 整数和小数部分
|
|
1563
|
-
const [intStr, decStr] =
|
|
1636
|
+
const [intStr, decStr] = strNum.split('.');
|
|
1564
1637
|
|
|
1565
1638
|
return symbol + formatInt(intStr, thousand) + formatDec(decStr, precision, decimal);
|
|
1566
1639
|
};
|
|
@@ -1651,12 +1724,13 @@
|
|
|
1651
1724
|
* // => 林**
|
|
1652
1725
|
*
|
|
1653
1726
|
*/
|
|
1654
|
-
function replaceChar(str
|
|
1655
|
-
const
|
|
1727
|
+
function replaceChar(str, { start = 3, end = -4, char = '*', repeat, exclude } = {}) {
|
|
1728
|
+
const realStr = normalizeString(str);
|
|
1729
|
+
const strLen = realStr.length;
|
|
1656
1730
|
|
|
1657
1731
|
// 开始位置超过str长度
|
|
1658
1732
|
if (Math.abs(start) >= strLen) {
|
|
1659
|
-
return
|
|
1733
|
+
return realStr;
|
|
1660
1734
|
}
|
|
1661
1735
|
|
|
1662
1736
|
start = start >= 0 ? start : strLen + start;
|
|
@@ -1664,10 +1738,10 @@
|
|
|
1664
1738
|
|
|
1665
1739
|
// 开始位置大于结束位置
|
|
1666
1740
|
if (start >= end) {
|
|
1667
|
-
return
|
|
1741
|
+
return realStr;
|
|
1668
1742
|
}
|
|
1669
1743
|
|
|
1670
|
-
let middleStr =
|
|
1744
|
+
let middleStr = realStr.substring(start, end);
|
|
1671
1745
|
|
|
1672
1746
|
if (exclude) {
|
|
1673
1747
|
const reg = new RegExp(`[^${exclude}]`, 'g');
|
|
@@ -1677,7 +1751,7 @@
|
|
|
1677
1751
|
middleStr = char.repeat(repeat);
|
|
1678
1752
|
}
|
|
1679
1753
|
|
|
1680
|
-
return
|
|
1754
|
+
return realStr.substring(0, start) + middleStr + realStr.substring(end);
|
|
1681
1755
|
}
|
|
1682
1756
|
|
|
1683
1757
|
// 简体
|
|
@@ -1716,10 +1790,10 @@
|
|
|
1716
1790
|
* @returns {string} 转化的数字
|
|
1717
1791
|
*/
|
|
1718
1792
|
function sectionToChinese(section) {
|
|
1719
|
-
let str = ''
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1793
|
+
let str = '';
|
|
1794
|
+
let chnstr = '';
|
|
1795
|
+
let zero = false; //zero为是否进行补零, 第一次进行取余由于为个位数,默认不补零
|
|
1796
|
+
let unitPos = 0;
|
|
1723
1797
|
|
|
1724
1798
|
while (section > 0) {
|
|
1725
1799
|
// 对数字取余10,得到的数即为个位数
|
|
@@ -1753,18 +1827,18 @@
|
|
|
1753
1827
|
* @returns {string} 中文数字
|
|
1754
1828
|
*/
|
|
1755
1829
|
function convertInteger(num) {
|
|
1756
|
-
|
|
1830
|
+
let numInt = Math.floor(num);
|
|
1757
1831
|
|
|
1758
1832
|
let unitPos = 0;
|
|
1759
|
-
let strIns = ''
|
|
1760
|
-
|
|
1833
|
+
let strIns = '';
|
|
1834
|
+
let chnStr = '';
|
|
1761
1835
|
let needZero = false;
|
|
1762
1836
|
|
|
1763
|
-
if (
|
|
1837
|
+
if (numInt === 0) {
|
|
1764
1838
|
return numberChar[0];
|
|
1765
1839
|
}
|
|
1766
|
-
while (
|
|
1767
|
-
var section =
|
|
1840
|
+
while (numInt > 0) {
|
|
1841
|
+
var section = numInt % 10000;
|
|
1768
1842
|
if (needZero) {
|
|
1769
1843
|
chnStr = numberChar[0] + chnStr;
|
|
1770
1844
|
}
|
|
@@ -1772,7 +1846,7 @@
|
|
|
1772
1846
|
strIns += section !== 0 ? unitSection[unitPos] : unitSection[0];
|
|
1773
1847
|
chnStr = strIns + chnStr;
|
|
1774
1848
|
needZero = section < 1000 && section > 0;
|
|
1775
|
-
|
|
1849
|
+
numInt = Math.floor(numInt / 10000);
|
|
1776
1850
|
unitPos++;
|
|
1777
1851
|
}
|
|
1778
1852
|
return chnStr;
|
|
@@ -1785,13 +1859,13 @@
|
|
|
1785
1859
|
* @param {number} num 要转换的数字
|
|
1786
1860
|
*/
|
|
1787
1861
|
function convertDecimal(num) {
|
|
1788
|
-
const
|
|
1789
|
-
const index =
|
|
1862
|
+
const strNum = num + '';
|
|
1863
|
+
const index = strNum.indexOf('.');
|
|
1790
1864
|
|
|
1791
1865
|
let ret = '';
|
|
1792
1866
|
|
|
1793
1867
|
if (index > -1) {
|
|
1794
|
-
let decimalStr =
|
|
1868
|
+
let decimalStr = strNum.slice(index + 1);
|
|
1795
1869
|
ret = mapNumberChar(parseInt(decimalStr));
|
|
1796
1870
|
}
|
|
1797
1871
|
|
|
@@ -1806,11 +1880,11 @@
|
|
|
1806
1880
|
* @returns {string} 返回中文数字的映射
|
|
1807
1881
|
*/
|
|
1808
1882
|
function mapNumberChar(num) {
|
|
1809
|
-
const
|
|
1883
|
+
const strNum = num + '';
|
|
1810
1884
|
let ret = '';
|
|
1811
1885
|
|
|
1812
|
-
for (let i = 0, len =
|
|
1813
|
-
ret += numberChar[parseInt(
|
|
1886
|
+
for (let i = 0, len = strNum.length; i < len; i++) {
|
|
1887
|
+
ret += numberChar[parseInt(strNum[i])];
|
|
1814
1888
|
}
|
|
1815
1889
|
|
|
1816
1890
|
return ret;
|
|
@@ -1861,25 +1935,10 @@
|
|
|
1861
1935
|
* // => 一九九〇
|
|
1862
1936
|
*
|
|
1863
1937
|
*/
|
|
1864
|
-
function numberToChinese(
|
|
1865
|
-
num,
|
|
1866
|
-
{
|
|
1867
|
-
big5 = false,
|
|
1868
|
-
unit = true,
|
|
1869
|
-
decimal = '点',
|
|
1870
|
-
zero = '',
|
|
1871
|
-
negative = '负',
|
|
1872
|
-
unitConfig = {
|
|
1873
|
-
w: '万', // '萬'
|
|
1874
|
-
y: '亿' // '億'
|
|
1875
|
-
}
|
|
1876
|
-
} = {}
|
|
1877
|
-
) {
|
|
1938
|
+
function numberToChinese(num, { big5 = false, unit = true, decimal = '点', zero = '', negative = '负', unitConfig = {} } = {}) {
|
|
1878
1939
|
// 非数字 或 NaN 不处理
|
|
1879
1940
|
if (typeof num !== 'number' || isNaN(num)) {
|
|
1880
|
-
|
|
1881
|
-
console.warn(`参数错误 ${num},请传入数字`);
|
|
1882
|
-
}
|
|
1941
|
+
devWarn(`参数错误 ${num},请传入数字`);
|
|
1883
1942
|
|
|
1884
1943
|
return '';
|
|
1885
1944
|
}
|
|
@@ -1897,9 +1956,10 @@
|
|
|
1897
1956
|
}
|
|
1898
1957
|
|
|
1899
1958
|
// 设置节点计数单位,万、亿、万亿
|
|
1900
|
-
const
|
|
1901
|
-
const
|
|
1902
|
-
|
|
1959
|
+
const unitWan = unitConfig?.w || '万';
|
|
1960
|
+
const unitYi = unitConfig?.y || '亿';
|
|
1961
|
+
const unitWanYi = unitWan + unitYi;
|
|
1962
|
+
unitSection = ['', unitWan, unitYi, unitWanYi];
|
|
1903
1963
|
|
|
1904
1964
|
// 设置0
|
|
1905
1965
|
if (zero) {
|
|
@@ -1911,16 +1971,17 @@
|
|
|
1911
1971
|
|
|
1912
1972
|
// 整数和小数
|
|
1913
1973
|
let chnInteger, chnDecimal;
|
|
1974
|
+
const numAbs = Math.abs(num);
|
|
1914
1975
|
|
|
1915
1976
|
// 处理整数
|
|
1916
1977
|
if (unit) {
|
|
1917
|
-
chnInteger = convertInteger(
|
|
1978
|
+
chnInteger = convertInteger(numAbs);
|
|
1918
1979
|
} else {
|
|
1919
|
-
chnInteger = mapNumberChar(Math.floor(
|
|
1980
|
+
chnInteger = mapNumberChar(Math.floor(numAbs));
|
|
1920
1981
|
}
|
|
1921
1982
|
|
|
1922
1983
|
// 处理小数
|
|
1923
|
-
chnDecimal = convertDecimal(
|
|
1984
|
+
chnDecimal = convertDecimal(numAbs);
|
|
1924
1985
|
|
|
1925
1986
|
return chnDecimal ? `${preStr}${chnInteger}${decimal}${chnDecimal}` : `${preStr}${chnInteger}`;
|
|
1926
1987
|
}
|
|
@@ -1948,13 +2009,15 @@
|
|
|
1948
2009
|
* // => 1 GB
|
|
1949
2010
|
*/
|
|
1950
2011
|
function bytesToSize(bytes) {
|
|
1951
|
-
|
|
2012
|
+
const numBytes = typeof bytes !== 'number' ? Number(bytes) : bytes;
|
|
2013
|
+
if (numBytes === 0 || isNaN(numBytes)) return '0 B';
|
|
2014
|
+
|
|
1952
2015
|
const k = 1024;
|
|
1953
2016
|
// 存储单位
|
|
1954
2017
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
1955
|
-
const i = Math.floor(Math.log(
|
|
2018
|
+
const i = Math.floor(Math.log(numBytes) / Math.log(k));
|
|
1956
2019
|
|
|
1957
|
-
return sizes[i] ? `${Number((
|
|
2020
|
+
return sizes[i] ? `${Number((numBytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}` : numBytes + '';
|
|
1958
2021
|
}
|
|
1959
2022
|
|
|
1960
2023
|
const regIdCard = /^(?<province>\d{2})(?<city>\d{2})(?<area>\d{2})(?<year>(?:\d{2})?\d{2})(?<month>\d{2})(?<day>\d{2})\d{2}(?<gender>\d)(?:\d|X)?$/i;
|
|
@@ -2095,31 +2158,17 @@
|
|
|
2095
2158
|
* @type {{ province: string, city: string, area: string, year: string, month: string, day: string, gender: string }}
|
|
2096
2159
|
*
|
|
2097
2160
|
*/
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2161
|
+
// @ts-ignore
|
|
2162
|
+
const origin = info?.groups || {
|
|
2163
|
+
province: info[1],
|
|
2164
|
+
city: info[2],
|
|
2165
|
+
area: info[3],
|
|
2166
|
+
year: info[4],
|
|
2167
|
+
month: info[5],
|
|
2168
|
+
day: info[6],
|
|
2169
|
+
gender: info[7]
|
|
2106
2170
|
};
|
|
2107
2171
|
|
|
2108
|
-
if (info.groups) {
|
|
2109
|
-
// @ts-ignore
|
|
2110
|
-
origin = info.groups;
|
|
2111
|
-
} else {
|
|
2112
|
-
origin = {
|
|
2113
|
-
province: info[1],
|
|
2114
|
-
city: info[2],
|
|
2115
|
-
area: info[3],
|
|
2116
|
-
year: info[4],
|
|
2117
|
-
month: info[5],
|
|
2118
|
-
day: info[6],
|
|
2119
|
-
gender: info[7]
|
|
2120
|
-
};
|
|
2121
|
-
}
|
|
2122
|
-
|
|
2123
2172
|
const province = Provinces.find((item) => item[0] === origin.province);
|
|
2124
2173
|
|
|
2125
2174
|
if (!province) {
|
|
@@ -2538,6 +2587,12 @@
|
|
|
2538
2587
|
* // => 4100
|
|
2539
2588
|
*/
|
|
2540
2589
|
function round(num, precision = 0) {
|
|
2590
|
+
// 兼容处理,如果参数为非数字或字符串时,直接返回
|
|
2591
|
+
if ((!isNumber(num) || _isNaN(num)) && !isString(num)) {
|
|
2592
|
+
// @ts-ignore
|
|
2593
|
+
return num;
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2541
2596
|
const base = Math.pow(10, precision);
|
|
2542
2597
|
return divide(Math.round(times(num, base)), base);
|
|
2543
2598
|
}
|