@tmsfe/tms-core 0.0.22 → 0.0.26

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.
@@ -1,651 +0,0 @@
1
- /**
2
- * 本文件负责对小程序调用wx同步方法的管理
3
- */
4
- let systemInfo = null; // 系统信息。
5
-
6
- let launchOptions = null; // 启动参数
7
-
8
- let accountInfo = null; // 小程序账号信息
9
-
10
- /**
11
- * 获取系统信息。同wx.getSystemInfoSync
12
- * @returns {Object} 系统信息
13
- */
14
-
15
- const getSystemInfoSync = () => {
16
- if (systemInfo) {
17
- return systemInfo;
18
- }
19
-
20
- try {
21
- systemInfo = wx.getSystemInfoSync();
22
- return systemInfo;
23
- } catch (_) {
24
- return {};
25
- }
26
- };
27
- /**
28
- * 重置系统信息,仅用于单元测试
29
- * @returns {undefined}
30
- */
31
-
32
-
33
- const resetSystemInfoSync = () => {
34
- systemInfo = null;
35
- };
36
- /**
37
- * 获取启动参数。同wx.getLaunchOptionsSync
38
- * @returns {Object} 启动参数
39
- */
40
-
41
-
42
- const getLaunchOptionsSync = () => {
43
- if (launchOptions) {
44
- return launchOptions;
45
- }
46
-
47
- try {
48
- launchOptions = wx.getLaunchOptionsSync();
49
- return launchOptions;
50
- } catch (_) {
51
- return {};
52
- }
53
- };
54
- /**
55
- * 获取客户端平台。同wx.getSystemInfoSync().platform
56
- * @returns {String} 平台名称
57
- */
58
-
59
-
60
- const getPlatform = () => {
61
- const UNKNOWN = 'unknown';
62
-
63
- try {
64
- const systemInfo = getSystemInfoSync();
65
- const {
66
- platform
67
- } = systemInfo;
68
- return platform || UNKNOWN;
69
- } catch (_) {
70
- return UNKNOWN;
71
- }
72
- };
73
- /**
74
- * 获取字符串类型的启动参数
75
- * @returns {String} 序列化的参数字符串
76
- */
77
-
78
-
79
- const getLaunchParamOfString = () => {
80
- try {
81
- const options = getLaunchOptionsSync() || {};
82
- return JSON.stringify(options);
83
- } catch (_) {
84
- return '';
85
- }
86
- };
87
- /**
88
- * @description 获取小程序账号信息
89
- * @returns {Object} 小程序账号信息,返回内容同wx.getAccountInfoSync()
90
- */
91
-
92
-
93
- const getAccountInfoSync = () => {
94
- if (accountInfo) {
95
- return accountInfo;
96
- }
97
-
98
- try {
99
- accountInfo = wx.getAccountInfoSync();
100
- return accountInfo;
101
- } catch (_) {
102
- return {};
103
- }
104
- };
105
- const obj = {
106
- getPlatform,
107
- getSystemInfoSync,
108
- getLaunchOptionsSync,
109
- getLaunchParamOfString,
110
- resetSystemInfoSync,
111
- getAccountInfoSync
112
- };
113
- var syncApi = obj;
114
-
115
- /**
116
- * @description rpx to px
117
- * @param {Number} rpx 需要转换的rpx数值
118
- * @returns {Number} 转换后的rpx数值
119
- */
120
-
121
- const rpxToPx = rpx => {
122
- const sys = syncApi.getSystemInfoSync();
123
- const ww = sys.windowWidth;
124
- const ratio = ww / 750;
125
- return rpx * ratio;
126
- };
127
-
128
- /**
129
- * 字符串截断,处理时按可见字符长度进行截断
130
- * 可见字符的含义是指:字母、数字、汉字、表情等均等价于一个字符
131
- * @param {String} str - 原始字符串
132
- * @param {Number} maxLen - 字符串截断后的最大长度
133
- * @returns {String} 截断后的字符串;如果确实进行了截断,在最后面加'...';
134
- */
135
- const subStr = (str, maxLen) => {
136
- // 按照码点(codePoint),把原始字符串的前maxLen+1个字符放到chars数组中
137
- const chars = [];
138
-
139
- for (const codePoint of str) {
140
- // eslint-disable-line
141
- chars.push(codePoint);
142
- if (chars.length > maxLen) break;
143
- } // 如果可见字符数量小于等于字符串截断后的最大长度,无需截断,返回原始字符串
144
-
145
-
146
- if (chars.length <= maxLen) {
147
- return str;
148
- } // 可见字符数量多于字符串截断后的最大长度,需要截断,并在末尾添加...
149
- // 注意,此时返回的字符串是 maxLen-2个可见字符 + ...(maxLen-2是因为...占用2个汉字字符位置)
150
-
151
-
152
- return `${chars.splice(0, maxLen - 2).join('')}...`;
153
- };
154
- /**
155
- * 手机号处理,隐藏中间部分位数
156
- * 隐藏规则:假设隐藏部分位数后,手机号由ABC构成,其中A、C是可见部分,B是隐藏部分
157
- * 1. 隐藏部分(B)占手机号总位数的1/3,且隐藏部分的位数向上取整
158
- * 2. 不被隐藏的部分(A、C)要均匀分布在隐藏部分(B)的两侧,即尽量使AC等长
159
- * 3. 如果不隐藏部分(A、C)长度无法等长,则使C多显示一位
160
- * @param {String} phone 手机号
161
- * @returns {String} 隐藏后的手机号
162
- */
163
-
164
-
165
- const hidePhoneCenter = phone => {
166
- const len = phone && phone.length;
167
-
168
- if (!len) {
169
- return '';
170
- } // 各部分位数
171
-
172
-
173
- const center = Math.ceil(len / 3);
174
- const left = Math.floor((len - center) / 2);
175
- const right = len - center - left; // 各部分字符串
176
-
177
- const centerStr = phone.substr(left, center).replace(/./g, '*');
178
- const leftStr = phone.substr(0, left);
179
- const rightStr = phone.substr(-right);
180
- return `${leftStr}${centerStr}${rightStr}`;
181
- };
182
- /**
183
- * 格式化车牌
184
- * 例如:京A12345 -> 京A·12345
185
- * @param {String} plate 车牌号
186
- * @returns {String} 格式化后的车牌号
187
- */
188
-
189
-
190
- const formatPlate = plate => {
191
- if (!plate || typeof plate !== 'string') {
192
- return '';
193
- }
194
-
195
- if (plate.length <= 2 || /·/.test(plate)) {
196
- return plate;
197
- }
198
-
199
- return `${plate.substring(0, 2)}·${plate.substring(2)}`;
200
- };
201
- /**
202
- * 检查手机号是否合法
203
- * @param {String} phone 手机号
204
- * @returns {Boolean} 手机号是否合法
205
- */
206
-
207
-
208
- const isValidPhone = phone => /^1[\d]{10}$/.test(phone);
209
- /**
210
- * 检查验证码是否合法
211
- * @param {String} code 验证码
212
- * @returns {Boolean} 验证码是否合法
213
- */
214
-
215
-
216
- const isValidAuthCode = code => /^[\d]{6}$/.test(code);
217
-
218
- const validPlateFirstLetters = ['京', '津', '冀', '晋', '蒙', '辽', '吉', '黑', '沪', '苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘', '粤', '桂', '琼', '渝', '川', '贵', '云', '藏', '陕', '甘', '青', '宁', '新', '使', '领'];
219
- /**
220
- * 检查车牌是否合法
221
- * @param {String} plate 车牌
222
- * @returns {Boolean} 车牌是否合法
223
- */
224
-
225
- const isValidPlate = plate => {
226
- if (!plate || typeof plate !== 'string') {
227
- return false;
228
- } // 检查首位是否是合法的汉字
229
-
230
-
231
- const [firstLetter] = plate;
232
-
233
- if (validPlateFirstLetters.indexOf(firstLetter) === -1) {
234
- return false;
235
- }
236
-
237
- if (!/[使领警学]/.test(plate)) {
238
- // 普通车牌
239
- const number = plate.substring(1);
240
- return /^[a-zA-Z][0-9a-zA-Z]{5}$/.test(number) // 第一位是字母,后面5位是字母或数字
241
- || /^[a-zA-Z][a-zA-Z][0-9a-zA-Z]{5}$/.test(number) // 第一位是字母,第二位是字母,后面再跟5位字母或数字(新能源小车)
242
- || /^[a-zA-Z][0-9a-zA-Z]{5}[a-zA-Z]$/.test(number) // 第一位是字母,最后一位是字母,中间5位字母或数字(新能源大车)
243
- || /^粤Z[0-9a-zA-Z]{4,5}[港澳]{1}/.test(plate); // 广东港澳两地车牌
244
- } // return /^[^使领警学]{1}[a-zA-Z][0-9a-zA-Z]{3,4}[使领警学]{1}$/.test(plate) || // 使/领/警/学车牌
245
- // /^[使领]{1}[0-9a-zA-Z]{5}$/.test(plate); // 使馆领事馆特殊车牌
246
-
247
-
248
- return false;
249
- };
250
- /**
251
- * 四舍五入,并返回格式化的字符串
252
- * 支持保留n位小数,n>=0,如 roundStr(1.325, 2)=1.33
253
- * 支持格式化字符串时取出末尾的0,如roundStr(1.109, 2, true)=1.1
254
- * @param {any} x 原数字
255
- * 如果n不是合法数字或者无法转换为合法数字,roundStr结果返回''
256
- * @param {any} n 保留几位小数,默认0
257
- * 如果n不是合法数字或者无法转换为合法数字,roundStr结果返回''
258
- * 如果n小于0,roundStr结果返回''
259
- * 如果n的值包含小数部分,roundStr处理时只关注n的整数部分值
260
- * @param {boolean} removeTrailingZero 是否移除字符串末尾的无效数字0
261
- * @returns {string} 返回四舍五入后的字符串,异常情况下返回空字符串''
262
- */
263
-
264
-
265
- const roundStr = (x, n = 2, removeTrailingZero = false) => {
266
- let xNum = Number(x); // x转换为数字
267
-
268
- const nNum = Math.floor(Number(n)); // n转换为数字,且只保留整数部分
269
- // 异常情况,返回''
270
-
271
- if (isNaN(xNum) || isNaN(nNum) || nNum < 0) return ''; // 仅保留整数的情况
272
-
273
- if (nNum === 0) return Math.round(xNum); // 保留n位小数的情况
274
-
275
- const xStr = xNum.toString();
276
- const rexExp = new RegExp(`\\.\\d{${nNum}}5`); // 1. 大部分情况下,四舍五入使用Number.toFixed即可
277
- // 2. 然而,Number.toFixed方法在某些情况下对第n+1位是5的四舍五入存在问题,如1.325保留2小数时结果为1.32(期望为1.33)
278
- // 对此种情况下,有两种处理方式:
279
- // 2.1 先扩大10^n倍,舍掉小数部分取整数部分,然后加1,最后缩小10^n倍
280
- // 但此种情况下,不能处理过大的数字,也不能处理保留小数位数过多的情况,会可能导致数字超过Infinity
281
- // 2.2 Number.toFixed是四舍6入,对于第n+1位是5的情况,增加2*10^(-n-1),保证满足第n+1位>6
282
- // 增加2*10^(-n-1)而不是增加1*10^(-n-1)是因为后者不能保证第n+1位>=6,例如1.325+0.001=1.32599999...第n+1位仍然为5
283
- // 此处,采用2.2方式,解决Number.toFixed的问题,又能避免2.1方式中数字超过Infinity的问题
284
-
285
- if (rexExp.test(xStr)) {
286
- // 情况2,处理方式2.1:如果小数部分第n+1位是5,增加2*10^(-n-1)
287
- xNum += 2 * 10 ** (-nNum - 1);
288
- }
289
-
290
- const str = xNum.toFixed(nNum);
291
- if (!removeTrailingZero) return str; // 去除末尾的0
292
-
293
- if (/^\d+\.0*$/.test(str)) {
294
- // 小数部分全是0
295
- return str.replace(/^(\d+)(\.0*)$/, (_m, s1) => s1);
296
- }
297
-
298
- return str.replace(/^(\d+\.\d*[1-9]{1})(0*)$/, (_m, s1) => s1);
299
- };
300
-
301
- var stringUtils = /*#__PURE__*/Object.freeze({
302
- __proto__: null,
303
- formatPlate: formatPlate,
304
- subStr: subStr,
305
- hidePhoneCenter: hidePhoneCenter,
306
- isValidPhone: isValidPhone,
307
- isValidPlate: isValidPlate,
308
- isValidAuthCode: isValidAuthCode,
309
- roundStr: roundStr
310
- });
311
-
312
- /**
313
- * Tencent Inc. All Rights Reserved.
314
- * @author:
315
- * Created:
316
- * Description: format time.
317
- * History:
318
- * 2017-07-26 @davislu modify.
319
- */
320
-
321
- /**
322
- * @function
323
- * @description 格式化时间
324
- * @param {Number} seconds 秒数
325
- * @returns {String} 格式化的时间 -> 2小时47分钟或者12天
326
- */
327
- const formatTime = seconds => {
328
- if (typeof seconds !== 'number') return seconds;
329
- const PER_MINUTE = 60 * 1;
330
- const PER_HOUR = 60 * PER_MINUTE;
331
- const PRE_DAY = 24 * PER_HOUR;
332
- let cost = ''; // >24小时的显示 【x天】
333
-
334
- if (seconds >= PRE_DAY) {
335
- cost = `${Math.floor(seconds / PRE_DAY)}天`; // <1小时的显示 【x分钟】 ,x取整数上限,最低为1分钟。
336
- } else if (seconds < PER_HOUR) {
337
- cost = `${Math.ceil(seconds / PER_MINUTE)}分钟`; // <24小时&>1小时的显示 【x小时y分钟】 ,分钟取整数上限
338
- } else {
339
- cost = `${Math.floor(seconds / PER_HOUR)}小时`;
340
- const s = seconds % PER_HOUR;
341
-
342
- if (s > 0) {
343
- cost += `${Math.ceil(s / PER_MINUTE)}分钟`;
344
- }
345
- }
346
-
347
- return cost;
348
- };
349
- /**
350
- * @function
351
- * @description 将秒数格式化为x天y小时z分钟
352
- * @param {Number} oriSeconds 秒数
353
- * @returns {String} 格式化后的文案
354
- */
355
-
356
-
357
- const formatTimeWithDetails = oriSeconds => {
358
- let seconds = oriSeconds; // 非Number类型,直接返回,不进行处理
359
-
360
- if (typeof seconds !== 'number') return seconds; // 参数为NaN类型,直接抛出异常
361
-
362
- if (isNaN(seconds)) throw new Error(`formatTimeWithDetails方法的参数seconds必须时一个非NaN数字,现在的值为${seconds}`); // 定义一些常量
363
- // 1分钟包含的秒数
364
-
365
- const PER_MINUTE = 60 * 1; // 1小时包含的秒数
366
-
367
- const PER_HOUR = 60 * PER_MINUTE; // 1天包含的秒数
368
-
369
- const PRE_DAY = 24 * PER_HOUR;
370
- let cost = ''; // 秒数多于1天
371
-
372
- if (seconds >= PRE_DAY) {
373
- cost = `${Math.floor(seconds / PRE_DAY)}天`;
374
- seconds %= PRE_DAY;
375
- } // 秒数小于1小时
376
-
377
-
378
- if (seconds < PER_HOUR) {
379
- if (cost) {
380
- cost += '0小时';
381
- }
382
-
383
- cost += `${Math.ceil(seconds / PER_MINUTE)}分钟`;
384
- } else {
385
- // 秒数介于1天和1分钟之间
386
- cost += `${Math.floor(seconds / PER_HOUR)}小时`;
387
- const s = seconds % PER_HOUR;
388
-
389
- if (s > 0) {
390
- cost += `${Math.ceil(s / PER_MINUTE)}分钟`;
391
- }
392
- }
393
-
394
- return cost;
395
- };
396
- /**
397
- * @function
398
- * @description 对原有时间字符串进行格式化
399
- * @param {String} str - 原字符串
400
- * @param {String} dateSeprator - 日期分隔符
401
- * @param {Boolean} keepSeconds - 是否保留秒数
402
- * @returns {String} 格式化后的文案
403
- */
404
-
405
-
406
- const formatTimeStr = (str = '', dateSeprator = '.', keepSeconds = false) => {
407
- if (typeof str !== 'string' || str === '') {
408
- return '';
409
- }
410
-
411
- let s = str.replace(/-/g, dateSeprator).replace(/:/g, ':'); // 不保留秒的时候,如果有两个冒号,截取第二个冒号之前的部分
412
-
413
- if (!keepSeconds && /[^:]*:[^:]*:/.test(s)) {
414
- const firstIndex = s.indexOf(':');
415
- const secondIndex = s.indexOf(':', firstIndex + 1);
416
-
417
- if (secondIndex > -1) {
418
- s = s.substring(0, secondIndex);
419
- }
420
- }
421
-
422
- return s;
423
- };
424
- /**
425
- * @description 格式化时间戳为 yyyy-mm-dd, yyyy-mm-dd HH:MM, yyyy-mm-dd HH:MM:SS
426
- * @param {Date} date 日期
427
- * @param {Boolean} withTime 是否带时间
428
- * @param {Boolean} withSeconds 是否带秒数
429
- * @param {String} join 连字符
430
- * @returns {String} 格式化后的字符串,如 2021-03-18 或者 2021-03-18 10:11
431
- */
432
-
433
-
434
- const dateToString = (date, withTime = false, withSeconds = false, join = '-') => {
435
- const DATE = date ? new Date(date) : new Date(); // 为兼容ios,android平台的差异,故而不使用toLocaleDateString方法
436
-
437
- const year = DATE.getFullYear();
438
- const month = DATE.getMonth() + 1;
439
- const day = DATE.getDate();
440
- const time = DATE.toTimeString().slice(0, 8);
441
- let dateStr = year + join + month + join + day;
442
-
443
- if (!withTime) {
444
- return dateStr.replace(/\b\d\b/g, '0$&');
445
- }
446
-
447
- dateStr = `${dateStr} ${time}`.replace(/\b\d\b/g, '0$&');
448
-
449
- if (!withSeconds) {
450
- dateStr = dateStr.slice(0, -3);
451
- }
452
-
453
- return dateStr;
454
- };
455
-
456
- var timeUtils = /*#__PURE__*/Object.freeze({
457
- __proto__: null,
458
- formatTime: formatTime,
459
- formatTimeStr: formatTimeStr,
460
- formatTimeWithDetails: formatTimeWithDetails,
461
- dateToString: dateToString
462
- });
463
-
464
- /**
465
- * Tencent Inc. All Rights Reserved.
466
- * @author: petegao@tencent.com
467
- * Created: 2019-01-14.
468
- *
469
- */
470
- let isInit = false;
471
- let isIPXSign = false;
472
- let ipxClass = '';
473
- /**
474
- * @returns {undefined}
475
- */
476
-
477
- function init() {
478
- if (isInit) {
479
- return;
480
- }
481
-
482
- isInit = true;
483
- const sysInfo = syncApi.getSystemInfoSync();
484
- const {
485
- model,
486
- platform: pl
487
- } = sysInfo;
488
-
489
- if (pl !== 'ios') {
490
- return;
491
- }
492
-
493
- if (model.search('iPhone X') > -1 || model.search('iPhone 11') > -1) {
494
- isIPXSign = true;
495
- ipxClass = 'view__ipx';
496
- }
497
- }
498
- /**
499
- * @returns {Boolean} 判断是否是 iPhoneX
500
- */
501
-
502
-
503
- function isIPX() {
504
- init();
505
- return isIPXSign;
506
- }
507
- /**
508
- * @returns {String} 返回 ipxClass
509
- */
510
-
511
-
512
- function getIpxClass() {
513
- init();
514
- return ipxClass;
515
- }
516
- /**
517
- * @param {Object} config 用户需要合并的IPX的配置
518
- * @returns {Object} 合并后的IPX的配置
519
- */
520
-
521
-
522
- function getIpxConfig(config) {
523
- init();
524
- return { ...config,
525
- data: { ...config.data,
526
- isIPX: isIPXSign,
527
- ipxClass
528
- }
529
- };
530
- } // 兼容旧接口,已经没什么用了
531
-
532
-
533
- function ipxInit() {}
534
-
535
- var ipxHelper = /*#__PURE__*/Object.freeze({
536
- __proto__: null,
537
- ipxInit: ipxInit,
538
- isIPX: isIPX,
539
- getIpxClass: getIpxClass,
540
- getIpxConfig: getIpxConfig
541
- });
542
-
543
- /**
544
- * 保存数据到localstorage
545
- * @param key
546
- * @param data
547
- * @returns {boolean} true为成功,false为报错
548
- */
549
- function setItem(key, data) {
550
- try {
551
- wx.setStorageSync(key, data);
552
- return true;
553
- } catch {
554
- return false;
555
- }
556
- }
557
- /**
558
- * 从localstorage取数据
559
- * @param key
560
- * @param defaultValue wx接口报错时返回默认值
561
- * @returns {null|any}
562
- */
563
-
564
-
565
- function getItem(key, defaultValue = null) {
566
- try {
567
- const val = wx.getStorageSync(key);
568
- return val === '' ? defaultValue : val;
569
- } catch {
570
- return defaultValue;
571
- }
572
- }
573
- /**
574
- * 从localstorage中删除
575
- * @param key
576
- * @returns {boolean}
577
- */
578
-
579
-
580
- function removeItem(key) {
581
- try {
582
- wx.removeStorageSync(key);
583
- return true;
584
- } catch {
585
- return false;
586
- }
587
- }
588
-
589
- const cleanQueue = [];
590
- let cleanTimerId = 0;
591
-
592
- function cleanTask() {
593
- while (cleanQueue.length > 0) {
594
- const {
595
- key,
596
- version
597
- } = cleanQueue.pop();
598
-
599
- for (let i = version - 1; i > version - 10 && i > 0; i--) {
600
- removeItem(`${key}_v${i}`);
601
- }
602
- }
603
-
604
- cleanTimerId = 0;
605
- }
606
- /**
607
- * 缓存组件或页面的缓存data
608
- * @param key
609
- * @param version 低于该版本号的缓存会被异步清除
610
- * @param data
611
- * @returns {boolean}
612
- */
613
-
614
-
615
- function setCacheData(key, version, data) {
616
- // 异步清理旧数据,不要阻塞当前线程
617
- cleanQueue.push({
618
- key,
619
- version
620
- });
621
-
622
- if (cleanTimerId === 0) {
623
- cleanTimerId = setTimeout(cleanTask, 2000);
624
- }
625
-
626
- const str = `${key}_v${version}`;
627
- return setItem(str, data);
628
- }
629
- /**
630
- * 获取组件或页面的缓存data
631
- * @param key
632
- * @param version
633
- * @param defaultData
634
- * @returns {*|null}
635
- */
636
-
637
-
638
- function getCacheData(key, version, defaultData = null) {
639
- const str = `${key}_v${version}`;
640
- return getItem(str, defaultData);
641
- }
642
-
643
- var storage = /*#__PURE__*/Object.freeze({
644
- __proto__: null,
645
- getItem: getItem,
646
- setItem: setItem,
647
- setCacheData: setCacheData,
648
- getCacheData: getCacheData
649
- });
650
-
651
- export { subStr as a, isValidPlate as b, isValidAuthCode as c, formatTime as d, formatTimeStr as e, formatPlate as f, formatTimeWithDetails as g, hidePhoneCenter as h, isValidPhone as i, dateToString as j, ipxInit as k, isIPX as l, getIpxClass as m, getIpxConfig as n, rpxToPx as o, storage as p, stringUtils as q, roundStr as r, syncApi as s, timeUtils as t, ipxHelper as u };