@i17hush/h5-utils 1.1.1 → 1.1.2

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/index.cjs.js CHANGED
@@ -221,15 +221,36 @@ function createTaroAdapter(taro) {
221
221
  }
222
222
 
223
223
  let currentAdapter = null;
224
+ /**
225
+ * 运行时检测是否在 Taro 环境中
226
+ * 不依赖 process.env.TARO_ENV(构建时替换,预编译库无法获取)
227
+ * 改为检测 Taro 运行时特征
228
+ */
229
+ function isTaroEnv() {
230
+ // 1. 检测小程序全局对象(微信 wx、支付宝 my、字节 tt、百度 swan、QQ qq)
231
+ if (typeof wx !== 'undefined' ||
232
+ typeof my !== 'undefined' ||
233
+ typeof tt !== 'undefined' ||
234
+ typeof swan !== 'undefined' ||
235
+ typeof qq !== 'undefined') {
236
+ return true;
237
+ }
238
+ // 2. 检测 Taro 运行时注入的全局变量
239
+ const g = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : {};
240
+ if (g.__TARO || g.__taro__) {
241
+ return true;
242
+ }
243
+ // 3. process.env.TARO_ENV 作为补充(Taro H5 模式下可能有效)
244
+ if (typeof process !== 'undefined' && process.env && process.env.TARO_ENV) {
245
+ return true;
246
+ }
247
+ return false;
248
+ }
224
249
  /**
225
250
  * 自动检测运行环境并创建对应适配器
226
251
  */
227
252
  function detectAdapter() {
228
- // Taro 构建时会注入 process.env.TARO_ENV(如 'weapp', 'h5', 'alipay' 等)
229
- const env = typeof process !== 'undefined' && process.env
230
- ? process.env.TARO_ENV
231
- : '';
232
- if (env) {
253
+ if (isTaroEnv()) {
233
254
  try {
234
255
  // eslint-disable-next-line @typescript-eslint/no-var-requires
235
256
  const Taro = require('@tarojs/taro');
@@ -257,6 +278,35 @@ function setAdapter(adapter) {
257
278
  currentAdapter = adapter;
258
279
  }
259
280
 
281
+ /**
282
+ * 内部错误处理工具
283
+ */
284
+ const PREFIX = '[h5-utils]';
285
+ /**
286
+ * 安全执行函数,出错时打印错误并返回默认值
287
+ */
288
+ function safeCall(fn, fallback, method) {
289
+ try {
290
+ return fn();
291
+ }
292
+ catch (e) {
293
+ console.error(`${PREFIX} ${method} error:`, (e === null || e === void 0 ? void 0 : e.message) || e);
294
+ return fallback;
295
+ }
296
+ }
297
+ /**
298
+ * 安全执行异步函数
299
+ */
300
+ async function safeCallAsync(fn, fallback, method) {
301
+ try {
302
+ return await fn();
303
+ }
304
+ catch (e) {
305
+ console.error(`${PREFIX} ${method} error:`, (e === null || e === void 0 ? void 0 : e.message) || e);
306
+ return fallback;
307
+ }
308
+ }
309
+
260
310
  /**
261
311
  * URL 解析与操作工具
262
312
  */
@@ -264,57 +314,63 @@ function setAdapter(adapter) {
264
314
  * 解析 URL 为结构化对象
265
315
  */
266
316
  function parseUrl(url) {
267
- const a = document.createElement('a');
268
- a.href = url;
269
- const query = {};
270
- if (a.search) {
271
- a.search
272
- .slice(1)
273
- .split('&')
274
- .forEach((pair) => {
275
- const [key, val] = pair.split('=');
276
- if (key)
277
- query[decodeURIComponent(key)] = decodeURIComponent(val || '');
278
- });
279
- }
280
- return {
281
- protocol: a.protocol,
282
- host: a.host,
283
- port: a.port,
284
- pathname: a.pathname,
285
- search: a.search,
286
- hash: a.hash,
287
- query,
288
- };
317
+ return safeCall(() => {
318
+ const a = document.createElement('a');
319
+ a.href = url;
320
+ const query = {};
321
+ if (a.search) {
322
+ a.search
323
+ .slice(1)
324
+ .split('&')
325
+ .forEach((pair) => {
326
+ const [key, val] = pair.split('=');
327
+ if (key)
328
+ query[decodeURIComponent(key)] = decodeURIComponent(val || '');
329
+ });
330
+ }
331
+ return {
332
+ protocol: a.protocol,
333
+ host: a.host,
334
+ port: a.port,
335
+ pathname: a.pathname,
336
+ search: a.search,
337
+ hash: a.hash,
338
+ query,
339
+ };
340
+ }, { protocol: '', host: '', port: '', pathname: '', search: '', hash: '', query: {} }, 'parseUrl');
289
341
  }
290
342
  /**
291
343
  * 拼接带查询参数的 URL
292
344
  */
293
345
  function buildUrl(base, params) {
294
- const search = Object.entries(params)
295
- .filter(([, v]) => v !== undefined && v !== null)
296
- .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
297
- .join('&');
298
- if (!search)
299
- return base;
300
- const separator = base.includes('?') ? '&' : '?';
301
- return `${base}${separator}${search}`;
346
+ return safeCall(() => {
347
+ const search = Object.entries(params)
348
+ .filter(([, v]) => v !== undefined && v !== null)
349
+ .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
350
+ .join('&');
351
+ if (!search)
352
+ return base;
353
+ const separator = base.includes('?') ? '&' : '?';
354
+ return `${base}${separator}${search}`;
355
+ }, base, 'buildUrl');
302
356
  }
303
357
  /**
304
358
  * 获取当前页面指定查询参数
305
359
  */
306
360
  function getQueryParam(name) {
307
- return new URLSearchParams(window.location.search).get(name);
361
+ return safeCall(() => new URLSearchParams(window.location.search).get(name), null, 'getQueryParam');
308
362
  }
309
363
  /**
310
364
  * 获取当前页面所有查询参数
311
365
  */
312
366
  function getAllQueryParams() {
313
- const params = {};
314
- new URLSearchParams(window.location.search).forEach((value, key) => {
315
- params[key] = value;
316
- });
317
- return params;
367
+ return safeCall(() => {
368
+ const params = {};
369
+ new URLSearchParams(window.location.search).forEach((value, key) => {
370
+ params[key] = value;
371
+ });
372
+ return params;
373
+ }, {}, 'getAllQueryParams');
318
374
  }
319
375
 
320
376
  /**
@@ -326,42 +382,46 @@ function getAllQueryParams() {
326
382
  * 获取存储值,支持 JSON 自动反序列化
327
383
  */
328
384
  function get$1(key) {
329
- const raw = getAdapter().storage.get(key);
330
- if (raw === null)
331
- return null;
332
- try {
333
- const item = JSON.parse(raw);
334
- if (item.expireAt !== null && Date.now() > item.expireAt) {
335
- getAdapter().storage.remove(key);
385
+ return safeCall(() => {
386
+ const raw = getAdapter().storage.get(key);
387
+ if (raw === null)
336
388
  return null;
389
+ try {
390
+ const item = JSON.parse(raw);
391
+ if (item.expireAt !== null && Date.now() > item.expireAt) {
392
+ getAdapter().storage.remove(key);
393
+ return null;
394
+ }
395
+ return item.value;
337
396
  }
338
- return item.value;
339
- }
340
- catch (_a) {
341
- return raw;
342
- }
397
+ catch (_a) {
398
+ return raw;
399
+ }
400
+ }, null, 'getStorage');
343
401
  }
344
402
  /**
345
403
  * 设置存储值,支持过期时间
346
404
  */
347
405
  function set$1(key, value, options) {
348
- const item = {
349
- value,
350
- expireAt: (options === null || options === void 0 ? void 0 : options.expires) ? Date.now() + options.expires : null,
351
- };
352
- getAdapter().storage.set(key, JSON.stringify(item), options);
406
+ safeCall(() => {
407
+ const item = {
408
+ value,
409
+ expireAt: (options === null || options === void 0 ? void 0 : options.expires) ? Date.now() + options.expires : null,
410
+ };
411
+ getAdapter().storage.set(key, JSON.stringify(item), options);
412
+ }, undefined, 'setStorage');
353
413
  }
354
414
  /**
355
415
  * 删除存储值
356
416
  */
357
417
  function remove$1(key) {
358
- getAdapter().storage.remove(key);
418
+ safeCall(() => getAdapter().storage.remove(key), undefined, 'removeStorage');
359
419
  }
360
420
  /**
361
421
  * 清空所有存储
362
422
  */
363
423
  function clear() {
364
- getAdapter().storage.clear();
424
+ safeCall(() => getAdapter().storage.clear(), undefined, 'clearStorage');
365
425
  }
366
426
 
367
427
  /**
@@ -371,27 +431,31 @@ function clear() {
371
431
  * 获取 Cookie 值
372
432
  */
373
433
  function get(name) {
374
- const match = document.cookie.match(new RegExp(`(?:^|;\\s*)${encodeURIComponent(name)}=([^;]*)`));
375
- return match ? decodeURIComponent(match[1]) : null;
434
+ return safeCall(() => {
435
+ const match = document.cookie.match(new RegExp(`(?:^|;\\s*)${encodeURIComponent(name)}=([^;]*)`));
436
+ return match ? decodeURIComponent(match[1]) : null;
437
+ }, null, 'getCookie');
376
438
  }
377
439
  /**
378
440
  * 设置 Cookie
379
441
  */
380
442
  function set(name, value, options = {}) {
381
- const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
382
- if (options.days) {
383
- const expires = new Date(Date.now() + options.days * 864e5).toUTCString();
384
- parts.push(`expires=${expires}`);
385
- }
386
- if (options.path)
387
- parts.push(`path=${options.path}`);
388
- if (options.domain)
389
- parts.push(`domain=${options.domain}`);
390
- if (options.secure)
391
- parts.push('secure');
392
- if (options.sameSite)
393
- parts.push(`samesite=${options.sameSite}`);
394
- document.cookie = parts.join('; ');
443
+ safeCall(() => {
444
+ const parts = [`${encodeURIComponent(name)}=${encodeURIComponent(value)}`];
445
+ if (options.days) {
446
+ const expires = new Date(Date.now() + options.days * 864e5).toUTCString();
447
+ parts.push(`expires=${expires}`);
448
+ }
449
+ if (options.path)
450
+ parts.push(`path=${options.path}`);
451
+ if (options.domain)
452
+ parts.push(`domain=${options.domain}`);
453
+ if (options.secure)
454
+ parts.push('secure');
455
+ if (options.sameSite)
456
+ parts.push(`samesite=${options.sameSite}`);
457
+ document.cookie = parts.join('; ');
458
+ }, undefined, 'setCookie');
395
459
  }
396
460
  /**
397
461
  * 删除 Cookie
@@ -407,60 +471,73 @@ function remove(name, options = {}) {
407
471
  * 是否为 iOS
408
472
  */
409
473
  function isIOS() {
410
- return getAdapter().device.getInfo().ios;
474
+ return safeCall(() => getAdapter().device.getInfo().ios, false, 'isIOS');
411
475
  }
412
476
  /**
413
477
  * 是否为 Android
414
478
  */
415
479
  function isAndroid() {
416
- return getAdapter().device.getInfo().android;
480
+ return safeCall(() => getAdapter().device.getInfo().android, false, 'isAndroid');
417
481
  }
418
482
  /**
419
483
  * 是否为微信浏览器
420
484
  */
421
485
  function isWeChat() {
422
- return getAdapter().device.getInfo().weChat;
486
+ return safeCall(() => getAdapter().device.getInfo().weChat, false, 'isWeChat');
423
487
  }
424
488
  /**
425
489
  * 是否为移动端
426
490
  */
427
491
  function isMobile() {
428
- return getAdapter().device.getInfo().mobile;
492
+ return safeCall(() => getAdapter().device.getInfo().mobile, false, 'isMobile');
429
493
  }
430
494
  /**
431
495
  * 获取浏览器类型(H5 专用)
432
496
  */
433
497
  function getBrowserType() {
434
- const ua = typeof navigator !== 'undefined' ? navigator.userAgent : '';
435
- if (/MicroMessenger/i.test(ua))
436
- return 'weixin';
437
- if (/\bQQ\//i.test(ua))
438
- return 'qq';
439
- if (/UCBrowser/i.test(ua))
440
- return 'uc';
441
- if (/Edg/i.test(ua))
442
- return 'edge';
443
- if (/Firefox/i.test(ua))
444
- return 'firefox';
445
- if (/MSIE|Trident/i.test(ua))
446
- return 'ie';
447
- if (/Chrome/i.test(ua))
448
- return 'chrome';
449
- if (/Safari/i.test(ua))
450
- return 'safari';
451
- return 'unknown';
498
+ return safeCall(() => {
499
+ const ua = typeof navigator !== 'undefined' ? navigator.userAgent : '';
500
+ if (/MicroMessenger/i.test(ua))
501
+ return 'weixin';
502
+ if (/\bQQ\//i.test(ua))
503
+ return 'qq';
504
+ if (/UCBrowser/i.test(ua))
505
+ return 'uc';
506
+ if (/Edg/i.test(ua))
507
+ return 'edge';
508
+ if (/Firefox/i.test(ua))
509
+ return 'firefox';
510
+ if (/MSIE|Trident/i.test(ua))
511
+ return 'ie';
512
+ if (/Chrome/i.test(ua))
513
+ return 'chrome';
514
+ if (/Safari/i.test(ua))
515
+ return 'safari';
516
+ return 'unknown';
517
+ }, 'unknown', 'getBrowserType');
452
518
  }
453
519
  /**
454
520
  * 获取操作系统信息
455
521
  */
456
522
  function getOS() {
457
- return getAdapter().device.getInfo().os;
523
+ return safeCall(() => getAdapter().device.getInfo().os, 'Unknown', 'getOS');
458
524
  }
459
525
  /**
460
526
  * 获取完整设备信息
461
527
  */
462
528
  function getDeviceInfo() {
463
- return getAdapter().device.getInfo();
529
+ return safeCall(() => getAdapter().device.getInfo(), {
530
+ ios: false,
531
+ android: false,
532
+ mobile: false,
533
+ weChat: false,
534
+ os: 'Unknown',
535
+ brand: '',
536
+ model: '',
537
+ screenWidth: 0,
538
+ screenHeight: 0,
539
+ pixelRatio: 1,
540
+ }, 'getDeviceInfo');
464
541
  }
465
542
 
466
543
  /**
@@ -470,53 +547,56 @@ function getDeviceInfo() {
470
547
  * 查询单个元素
471
548
  */
472
549
  function $(selector) {
473
- return getAdapter().dom.select(selector);
550
+ return safeCall(() => getAdapter().dom.select(selector), null, '$');
474
551
  }
475
552
  /**
476
553
  * 查询多个元素
477
554
  */
478
555
  function $$(selector) {
479
- return getAdapter().dom.selectAll(selector);
556
+ return safeCall(() => getAdapter().dom.selectAll(selector), [], '$$');
480
557
  }
481
558
  /**
482
559
  * 添加 class
483
560
  */
484
561
  function addClass(el, cls) {
485
- el.classList.add(cls);
562
+ safeCall(() => el.classList.add(cls), undefined, 'addClass');
486
563
  }
487
564
  /**
488
565
  * 移除 class
489
566
  */
490
567
  function removeClass(el, cls) {
491
- el.classList.remove(cls);
568
+ safeCall(() => el.classList.remove(cls), undefined, 'removeClass');
492
569
  }
493
570
  /**
494
571
  * 切换 class
495
572
  */
496
573
  function toggleClass(el, cls) {
497
- el.classList.toggle(cls);
574
+ safeCall(() => el.classList.toggle(cls), undefined, 'toggleClass');
498
575
  }
499
576
  /**
500
577
  * 判断是否包含 class
501
578
  */
502
579
  function hasClass(el, cls) {
503
- return el.classList.contains(cls);
580
+ return safeCall(() => el.classList.contains(cls), false, 'hasClass');
504
581
  }
505
582
  /**
506
583
  * 获取元素样式
507
584
  */
508
585
  function getStyle(el, prop) {
509
- return (el.style.getPropertyValue(prop) || getComputedStyle(el).getPropertyValue(prop));
586
+ return safeCall(() => el.style.getPropertyValue(prop) ||
587
+ getComputedStyle(el).getPropertyValue(prop), '', 'getStyle');
510
588
  }
511
589
  /**
512
590
  * 判断元素是否在可视区域内
513
591
  */
514
592
  function isInViewport(el) {
515
- const rect = el.getBoundingClientRect();
516
- return (rect.top >= 0 &&
517
- rect.left >= 0 &&
518
- rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
519
- rect.right <= (window.innerWidth || document.documentElement.clientWidth));
593
+ return safeCall(() => {
594
+ const rect = el.getBoundingClientRect();
595
+ return (rect.top >= 0 &&
596
+ rect.left >= 0 &&
597
+ rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
598
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth));
599
+ }, false, 'isInViewport');
520
600
  }
521
601
 
522
602
  /**
@@ -526,19 +606,19 @@ function isInViewport(el) {
526
606
  * 绑定事件
527
607
  */
528
608
  function on(el, event, handler, options) {
529
- el.addEventListener(event, handler, options);
609
+ safeCall(() => el.addEventListener(event, handler, options), undefined, 'on');
530
610
  }
531
611
  /**
532
612
  * 解绑事件
533
613
  */
534
614
  function off(el, event, handler, options) {
535
- el.removeEventListener(event, handler, options);
615
+ safeCall(() => el.removeEventListener(event, handler, options), undefined, 'off');
536
616
  }
537
617
  /**
538
618
  * 单次监听事件
539
619
  */
540
620
  function once(el, event, handler) {
541
- el.addEventListener(event, handler, { once: true });
621
+ safeCall(() => el.addEventListener(event, handler, { once: true }), undefined, 'once');
542
622
  }
543
623
  /**
544
624
  * 事件委托
@@ -548,14 +628,16 @@ function once(el, event, handler) {
548
628
  * @param handler 回调函数
549
629
  */
550
630
  function delegate(parent, selector, event, handler) {
551
- const wrappedHandler = (e) => {
552
- var _a;
553
- const target = (_a = e.target) === null || _a === void 0 ? void 0 : _a.closest(selector);
554
- if (target) {
555
- handler(target, e);
556
- }
557
- };
558
- parent.addEventListener(event, wrappedHandler);
631
+ safeCall(() => {
632
+ const wrappedHandler = (e) => {
633
+ var _a;
634
+ const target = (_a = e.target) === null || _a === void 0 ? void 0 : _a.closest(selector);
635
+ if (target) {
636
+ handler(target, e);
637
+ }
638
+ };
639
+ parent.addEventListener(event, wrappedHandler);
640
+ }, undefined, 'delegate');
559
641
  }
560
642
 
561
643
  /**
@@ -565,13 +647,13 @@ function delegate(parent, selector, event, handler) {
565
647
  * 复制文本到剪贴板
566
648
  */
567
649
  function copyText(text) {
568
- return getAdapter().clipboard.write(text);
650
+ return safeCallAsync(() => getAdapter().clipboard.write(text), undefined, 'copyText');
569
651
  }
570
652
  /**
571
653
  * 读取剪贴板文本
572
654
  */
573
655
  function readText() {
574
- return getAdapter().clipboard.read();
656
+ return safeCallAsync(() => getAdapter().clipboard.read(), '', 'readText');
575
657
  }
576
658
 
577
659
  /**
@@ -582,34 +664,40 @@ let scrollLockCount = 0;
582
664
  * 滚动到页面顶部
583
665
  */
584
666
  function scrollToTop(smooth = true) {
585
- getAdapter().scroll.scrollTo({ top: 0, animated: smooth });
667
+ safeCall(() => getAdapter().scroll.scrollTo({ top: 0, animated: smooth }), undefined, 'scrollToTop');
586
668
  }
587
669
  /**
588
670
  * 滚动到指定元素
589
671
  */
590
672
  function scrollToElement(el, options = {}) {
591
- const { offset = 0, smooth = true } = options;
592
- const rect = el.getBoundingClientRect();
593
- const top = window.scrollY + rect.top + offset;
594
- getAdapter().scroll.scrollTo({ top, animated: smooth });
673
+ safeCall(() => {
674
+ const { offset = 0, smooth = true } = options;
675
+ const rect = el.getBoundingClientRect();
676
+ const top = window.scrollY + rect.top + offset;
677
+ getAdapter().scroll.scrollTo({ top, animated: smooth });
678
+ }, undefined, 'scrollToElement');
595
679
  }
596
680
  /**
597
681
  * 锁定页面滚动
598
682
  */
599
683
  function lockScroll() {
600
- scrollLockCount++;
601
- if (scrollLockCount === 1) {
602
- getAdapter().scroll.lockScroll();
603
- }
684
+ safeCall(() => {
685
+ scrollLockCount++;
686
+ if (scrollLockCount === 1) {
687
+ getAdapter().scroll.lockScroll();
688
+ }
689
+ }, undefined, 'lockScroll');
604
690
  }
605
691
  /**
606
692
  * 解锁页面滚动
607
693
  */
608
694
  function unlockScroll() {
609
- scrollLockCount = Math.max(0, scrollLockCount - 1);
610
- if (scrollLockCount === 0) {
611
- getAdapter().scroll.unlockScroll();
612
- }
695
+ safeCall(() => {
696
+ scrollLockCount = Math.max(0, scrollLockCount - 1);
697
+ if (scrollLockCount === 0) {
698
+ getAdapter().scroll.unlockScroll();
699
+ }
700
+ }, undefined, 'unlockScroll');
613
701
  }
614
702
 
615
703
  /**
@@ -620,49 +708,53 @@ function unlockScroll() {
620
708
  * @example formatDate(new Date(), 'YYYY-MM-DD HH:mm:ss')
621
709
  */
622
710
  function formatDate(date, fmt = 'YYYY-MM-DD HH:mm:ss') {
623
- const d = new Date(date);
624
- const map = {
625
- YYYY: String(d.getFullYear()),
626
- MM: String(d.getMonth() + 1).padStart(2, '0'),
627
- DD: String(d.getDate()).padStart(2, '0'),
628
- HH: String(d.getHours()).padStart(2, '0'),
629
- mm: String(d.getMinutes()).padStart(2, '0'),
630
- ss: String(d.getSeconds()).padStart(2, '0'),
631
- };
632
- let result = fmt;
633
- for (const [key, val] of Object.entries(map)) {
634
- result = result.replace(key, val);
635
- }
636
- return result;
711
+ return safeCall(() => {
712
+ const d = new Date(date);
713
+ const map = {
714
+ YYYY: String(d.getFullYear()),
715
+ MM: String(d.getMonth() + 1).padStart(2, '0'),
716
+ DD: String(d.getDate()).padStart(2, '0'),
717
+ HH: String(d.getHours()).padStart(2, '0'),
718
+ mm: String(d.getMinutes()).padStart(2, '0'),
719
+ ss: String(d.getSeconds()).padStart(2, '0'),
720
+ };
721
+ let result = fmt;
722
+ for (const [key, val] of Object.entries(map)) {
723
+ result = result.replace(key, val);
724
+ }
725
+ return result;
726
+ }, '', 'formatDate');
637
727
  }
638
728
  /**
639
729
  * 数字格式化(千分位等)
640
730
  */
641
731
  function formatNumber(num, options = {}) {
642
- const { precision, separator = ',' } = options;
643
- let str = precision !== undefined ? num.toFixed(precision) : String(num);
644
- const [intPart, decPart] = str.split('.');
645
- const formatted = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
646
- return decPart !== undefined ? `${formatted}.${decPart}` : formatted;
732
+ return safeCall(() => {
733
+ const { precision, separator = ',' } = options;
734
+ let str = precision !== undefined ? num.toFixed(precision) : String(num);
735
+ const [intPart, decPart] = str.split('.');
736
+ const formatted = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, separator);
737
+ return decPart !== undefined ? `${formatted}.${decPart}` : formatted;
738
+ }, String(num), 'formatNumber');
647
739
  }
648
740
  /**
649
741
  * 手机号格式化 (xxx xxxx xxxx)
650
742
  */
651
743
  function formatPhone(phone) {
652
- return phone.replace(/(\d{3})(\d{0,4})(\d{0,4})/, (_, a, b, c) => {
744
+ return safeCall(() => phone.replace(/(\d{3})(\d{0,4})(\d{0,4})/, (_, a, b, c) => {
653
745
  let result = a;
654
746
  if (b)
655
747
  result += ` ${b}`;
656
748
  if (c)
657
749
  result += ` ${c}`;
658
750
  return result;
659
- });
751
+ }), phone, 'formatPhone');
660
752
  }
661
753
  /**
662
754
  * 金额格式化
663
755
  */
664
756
  function formatMoney(amount, precision = 2) {
665
- return formatNumber(amount, { precision });
757
+ return safeCall(() => formatNumber(amount, { precision }), String(amount), 'formatMoney');
666
758
  }
667
759
  /**
668
760
  * 节流
@@ -673,7 +765,12 @@ function throttle(fn, delay) {
673
765
  const now = Date.now();
674
766
  if (now - last >= delay) {
675
767
  last = now;
676
- fn.apply(this, args);
768
+ try {
769
+ fn.apply(this, args);
770
+ }
771
+ catch (e) {
772
+ console.error('[h5-utils] throttle error:', (e === null || e === void 0 ? void 0 : e.message) || e);
773
+ }
677
774
  }
678
775
  };
679
776
  }
@@ -685,7 +782,14 @@ function debounce(fn, delay) {
685
782
  return function (...args) {
686
783
  if (timer)
687
784
  clearTimeout(timer);
688
- timer = setTimeout(() => fn.apply(this, args), delay);
785
+ timer = setTimeout(() => {
786
+ try {
787
+ fn.apply(this, args);
788
+ }
789
+ catch (e) {
790
+ console.error('[h5-utils] debounce error:', (e === null || e === void 0 ? void 0 : e.message) || e);
791
+ }
792
+ }, delay);
689
793
  };
690
794
  }
691
795
 
@@ -703,40 +807,41 @@ const patterns = {
703
807
  * 手机号格式校验
704
808
  */
705
809
  function isMobilePhone(str) {
706
- return patterns.mobile.test(str);
810
+ return safeCall(() => patterns.mobile.test(str), false, 'isMobilePhone');
707
811
  }
708
812
  /**
709
813
  * 邮箱校验
710
814
  */
711
815
  function isEmail(str) {
712
- return patterns.email.test(str);
816
+ return safeCall(() => patterns.email.test(str), false, 'isEmail');
713
817
  }
714
818
  /**
715
819
  * 身份证号校验(18位)
716
820
  */
717
821
  function isIdCard(str) {
718
- if (!patterns.idCard.test(str))
719
- return false;
720
- // 校验位验证
721
- const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
722
- const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
723
- let sum = 0;
724
- for (let i = 0; i < 17; i++) {
725
- sum += parseInt(str[i], 10) * weights[i];
726
- }
727
- return checkCodes[sum % 11] === str[17].toUpperCase();
822
+ return safeCall(() => {
823
+ if (!patterns.idCard.test(str))
824
+ return false;
825
+ const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
826
+ const checkCodes = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
827
+ let sum = 0;
828
+ for (let i = 0; i < 17; i++) {
829
+ sum += parseInt(str[i], 10) * weights[i];
830
+ }
831
+ return checkCodes[sum % 11] === str[17].toUpperCase();
832
+ }, false, 'isIdCard');
728
833
  }
729
834
  /**
730
835
  * URL 校验
731
836
  */
732
837
  function isUrl(str) {
733
- return patterns.url.test(str);
838
+ return safeCall(() => patterns.url.test(str), false, 'isUrl');
734
839
  }
735
840
  /**
736
841
  * 中文校验
737
842
  */
738
843
  function isChinese(str) {
739
- return patterns.chinese.test(str);
844
+ return safeCall(() => patterns.chinese.test(str), false, 'isChinese');
740
845
  }
741
846
 
742
847
  exports.$ = $;