my-uniapp-tools 3.1.0 → 4.0.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/README.md CHANGED
@@ -7,7 +7,6 @@
7
7
  - 🚀 **高性能**: 简化缓存机制,删除过度设计,性能提升20%+
8
8
  - 🛡️ **类型安全**: 完整的 TypeScript 支持
9
9
  - 🔧 **统一错误处理**: 全局错误管理和监控
10
- - 📊 **性能监控**: 可选的性能分析工具
11
10
  - 💾 **本地存储**: 支持TTL过期管理
12
11
  - 🔄 **简洁设计**: 遵循Linus"好品味"原则,消除特殊情况
13
12
  - 📱 **跨平台**: 支持 H5、App、微信/支付宝小程序
@@ -37,19 +36,13 @@ setStorageSync('userInfo', { name: '张三', age: 25 });
37
36
  useToast('操作成功');
38
37
  ```
39
38
 
40
- ### 高级配置
39
+ ### 错误监听(可选)
41
40
 
42
41
  ```javascript
43
- import { initUniAppTools } from 'my-uniapp-tools';
44
-
45
- // 初始化工具库
46
- initUniAppTools({
47
- enablePerformanceMonitor: true, // 启用性能监控
48
- performanceReportInterval: 30000, // 每30秒输出性能报告
49
- enableErrorHandler: true, // 启用错误处理
50
- onError: (error) => { // 自定义错误处理
51
- console.error(error);
52
- }
42
+ import { ErrorHandler } from 'my-uniapp-tools';
43
+
44
+ ErrorHandler.getInstance().onError((error) => {
45
+ console.error(`[${error.module}] ${error.code}: ${error.message}`, error);
53
46
  });
54
47
  ```
55
48
 
@@ -57,21 +50,6 @@ initUniAppTools({
57
50
 
58
51
  ### 🎯 核心功能
59
52
 
60
- #### initUniAppTools(config)
61
-
62
- 初始化工具库配置
63
-
64
- ```javascript
65
- initUniAppTools({
66
- enablePerformanceMonitor: false, // 是否启用性能监控
67
- performanceReportInterval: 0, // 性能报告间隔(ms),0表示不输出
68
- enableErrorHandler: true, // 是否启用错误处理
69
- onError: (error) => { // 自定义错误回调
70
- console.log(`[${error.module}] ${error.message}`);
71
- }
72
- });
73
- ```
74
-
75
53
  #### ErrorHandler
76
54
 
77
55
  全局错误处理器
@@ -88,25 +66,6 @@ errorHandler.onError((error) => {
88
66
  });
89
67
  ```
90
68
 
91
- #### PerformanceMonitor
92
-
93
- 性能监控工具(可选使用)
94
-
95
- ```javascript
96
- import { PerformanceMonitor } from 'my-uniapp-tools';
97
-
98
- const monitor = PerformanceMonitor.getInstance();
99
-
100
- // 开始监控
101
- monitor.start('operationName', 'moduleName');
102
-
103
- // 结束监控
104
- monitor.end('operationName');
105
-
106
- // 获取性能报告
107
- const report = monitor.getReport();
108
- ```
109
-
110
69
  ### 📋 剪贴板功能
111
70
 
112
71
  #### copyText(text, config?)
@@ -122,29 +81,8 @@ await copyText('要复制的文本', {
122
81
  showToast: true, // 是否显示提示
123
82
  successMessage: '复制成功', // 成功提示文本
124
83
  failMessage: '复制失败', // 失败提示文本
125
- timeout: 5000 // 超时时间(ms)
126
- });
127
- ```
128
-
129
- #### readClipboard(config?)
130
-
131
- 读取剪贴板内容(仅H5支持)
132
-
133
- ```javascript
134
- const content = await readClipboard();
135
- if (content) {
136
- console.log('剪贴板内容:', content);
137
- }
138
- ```
139
-
140
- #### isClipboardSupported()
141
-
142
- 检查剪贴板API是否可用
143
-
144
- ```javascript
145
- if (isClipboardSupported()) {
146
- // 执行剪贴板操作
147
- }
84
+ timeout: 5000 // 超时时间(ms)
85
+ });
148
86
  ```
149
87
 
150
88
  ### 💾 本地存储功能
@@ -489,7 +427,6 @@ throttledFn.cancel();
489
427
 
490
428
  ```javascript
491
429
  import {
492
- initUniAppTools,
493
430
  copyText,
494
431
  setStorageSync,
495
432
  navigateTo,
@@ -497,12 +434,6 @@ import {
497
434
  debounce
498
435
  } from 'my-uniapp-tools';
499
436
 
500
- // 应用启动时初始化
501
- initUniAppTools({
502
- enablePerformanceMonitor: false,
503
- enableErrorHandler: true
504
- });
505
-
506
437
  // 页面中使用
507
438
  export default {
508
439
  data() {
@@ -602,10 +533,6 @@ errorHandler.onError((error) => {
602
533
 
603
534
  ## 🐛 常见问题
604
535
 
605
- ### Q: 如何启用性能监控?
606
-
607
- A: 在应用启动时调用 `initUniAppTools({ enablePerformanceMonitor: true, performanceReportInterval: 30000 })`
608
-
609
536
  ### Q: 存储的数据会自动过期吗?
610
537
 
611
538
  A: 是的,设置了TTL的数据会自动过期,可以调用 `cleanExpiredStorage()` 手动清理
@@ -618,25 +545,6 @@ A: 支持 uni-app 的所有平台:H5、App、微信小程序、支付宝小程
618
545
 
619
546
  A: 使用 `safeNavigateTo` 函数,它提供重试机制和更好的错误处理
620
547
 
621
- ### Q: 旧版upload API怎么迁移?
622
-
623
- A: v3.0.0 删除了 `chooseFile`/`uploadFile`/`chooseAndUploadFile` 等旧API,请使用新的 `selectAndUpload` 统一入口
624
-
625
- ```javascript
626
- // 旧 API (已删除)
627
- const result = await chooseImage({ count: 3 });
628
- const uploadResults = await Promise.all(
629
- result.tempFilePaths.map(path => uploadFile(path, { url }))
630
- );
631
-
632
- // 新 API (推荐)
633
- const results = await selectAndUpload({
634
- url,
635
- type: 'image',
636
- count: 3
637
- });
638
- ```
639
-
640
548
  ## 📄 更新日志
641
549
 
642
550
  ### v3.0.2 (当前版本)
package/dist/index.d.ts CHANGED
@@ -1,27 +1,4 @@
1
- /**
2
- * 初始化 UniAppTools
3
- * @param {Object} config 配置项
4
- * @param {boolean} config.enablePerformanceMonitor - 是否启用性能监控,默认false
5
- * @param {boolean} config.enableErrorHandler - 是否启用错误处理器,默认true
6
- * @param {Function} config.onError - 错误回调函数
7
- * @param {number} config.performanceReportInterval - 性能报告输出间隔(ms),默认0(不输出)
8
- * @param {boolean} config.showInitMessage - 是否显示初始化消息提示,默认false
9
- * @param {boolean} config.silent - 是否静默模式(不输出任何日志),默认false
10
- * @param {'info'|'warn'|'error'} config.logLevel - 日志输出级别,默认'warn'
11
- * @param {boolean} config.enablePerformanceLog - 是否输出性能监控日志,默认false
12
- */
13
- export function initUniAppTools(config?: {
14
- enablePerformanceMonitor: boolean;
15
- enableErrorHandler: boolean;
16
- onError: Function;
17
- performanceReportInterval: number;
18
- showInitMessage: boolean;
19
- silent: boolean;
20
- logLevel: "info" | "warn" | "error";
21
- enablePerformanceLog: boolean;
22
- }): void;
23
1
  export * from "./core/errorHandler";
24
- export * from "./core/performance";
25
2
  export * from "./system";
26
3
  export * from "./utils";
27
4
  export * from "./ui";
@@ -31,4 +8,4 @@ export * from "./localStorage";
31
8
  export * from "./upload";
32
9
  export * from "./payment";
33
10
  export * from "./weixin";
34
- export const VERSION: "3.1.0";
11
+ export const VERSION: "4.0.0";
@@ -1 +1 @@
1
- "use strict";var e=require("@vant/area-data");class t extends Error{code;module;timestamp;constructor(e,t,n){super(t),this.name="UniAppToolsError",this.code=e,this.module=n,this.timestamp=Date.now()}}class n{static instance;errorCallbacks=[];static getInstance(){return n.instance||(n.instance=new n),n.instance}onError(e){this.errorCallbacks.push(e)}handleError(e,n){const r={code:e instanceof t?e.code:"UNKNOWN_ERROR",message:e.message,module:e instanceof t?e.module:n,timestamp:e instanceof t?e.timestamp:Date.now(),stack:e.stack};console.error(`[${r.module}] ${r.code}: ${r.message}`,r),this.errorCallbacks.forEach(e=>{try{e(r)}catch(e){console.error("Error in error callback:",e)}})}createModuleErrorHandler(e){return(n,r,o)=>{const s=new t(n,r,e);return o&&(s.stack=o.stack),this.handleError(s,e),s}}}async function r(e,t,r="ASYNC_ERROR"){try{return await e()}catch(e){return n.getInstance().createModuleErrorHandler(t)(r,`异步操作失败: ${e instanceof Error?e.message:String(e)}`,e),null}}function o(e,t,r="SYNC_ERROR",o=null){try{return e()}catch(e){return n.getInstance().createModuleErrorHandler(t)(r,`同步操作失败: ${e instanceof Error?e.message:String(e)}`,e),o}}function s(){return"undefined"!=typeof performance&&"function"==typeof performance.now?performance.now():Date.now()}class a{static instance;metrics=new Map;completedMetrics=[];maxStoredMetrics=100;static getInstance(){return a.instance||(a.instance=new a),a.instance}start(e,t,n){const r={name:e,startTime:s(),module:t,metadata:n};this.metrics.set(e,r)}end(e){const t=this.metrics.get(e);return t?(t.endTime=s(),t.duration=t.endTime-t.startTime,this.metrics.delete(e),this.completedMetrics.push(t),this.completedMetrics.length>this.maxStoredMetrics&&this.completedMetrics.shift(),console.log(`[Performance] ${t.module}.${t.name}: ${t.duration?.toFixed(2)}ms`),t):(console.warn(`Performance metric "${e}" not found`),null)}getReport(){const e={},t={};this.completedMetrics.forEach(n=>{e[n.module]||(e[n.module]=[]),e[n.module].push(n);const r=`${n.module}.${n.name}`;t[r]||(t[r]={total:0,count:0}),t[r].total+=n.duration||0,t[r].count+=1});const n={};Object.entries(t).forEach(([e,t])=>{n[e]=t.total/t.count});const r=[...this.completedMetrics].sort((e,t)=>(t.duration||0)-(e.duration||0)).slice(0,10);return{byModule:e,slowest:r,average:n}}clear(){this.metrics.clear(),this.completedMetrics=[]}}const i=n.getInstance();let c=null,l=null,u=null;const p=e=>"weixin"===e||"alipay"===e;let m=!1;const f=()=>{if(c)return c;let e="unknown";return e="weixin",e="web",e="app",e="alipay",e="h5",c="h5","h5"},g=(e=!0)=>e&&u?u:o(()=>{const t=uni.getWindowInfo();return e&&(u=t),t},"system","GET_WINDOW_INFO_ERROR",null),d=()=>{if(null!==l)return l;try{const e=g();return l=e?.statusBarHeight||0,l}catch(e){return i.handleError(new t("GET_STATUS_BAR_HEIGHT_ERROR",`获取状态栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),0}},h=()=>{try{const e=f();return p(e)?uni.getMenuButtonBoundingClientRect():null}catch(e){return i.handleError(new t("GET_MENU_BUTTON_ERROR",`获取菜单按钮边界信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),null}},w=()=>{try{const e=f();if(p(e)){const e=h();return e?.height||44}return 44}catch(e){return i.handleError(new t("GET_NAVIGATION_BAR_HEIGHT_ERROR",`获取导航栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),44}},y=()=>{const e=f(),t=d(),n=w();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},E=n.getInstance();function S(e){if(null===e||"object"!=typeof e)return e;try{if("undefined"!=typeof structuredClone)try{return structuredClone(e)}catch(e){}return JSON.parse(JSON.stringify(e))}catch(e){throw E.handleError(new t("DEEP_CLONE_ERROR",`深拷贝失败: ${e instanceof Error?e.message:String(e)}`,"utils"),"utils"),new Error(`深拷贝失败: ${e instanceof Error?e.message:String(e)}`)}}function T(e,t,n=!1){let r,o=null;const s=function(...s){const a=n&&!o;return o&&clearTimeout(o),o=setTimeout(()=>{o=null,n||(r=e.apply(this,s))},t),a&&(r=e.apply(this,s)),r};return s.cancel=()=>{o&&(clearTimeout(o),o=null)},s}const R=e.areaList,x=e.useCascaderAreaData,v=(e="",t=!1,n="none",r=2e3)=>{uni.showToast({title:e,icon:n,mask:t,duration:r})},A=n.getInstance();function _(e,t){if(!t||0===Object.keys(t).length)return e;const n=Object.entries(t).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(String(t))}`).join("&");return e+(e.includes("?")?"&":"?")+n}async function P(e){return new Promise(n=>{const r=_(e.url,e.params);uni.navigateTo({url:r,animationType:e.animationType,animationDuration:e.animationDuration,events:e.events,success:()=>n(!0),fail:e=>{A.handleError(new t("NAVIGATE_TO_FAILED",`页面跳转失败: ${r}`,"navigation"),"navigation"),n(!1)}})})}async function C(e="",n={}){return new Promise(r=>{const o=n.delta||1,s=n.timeout||5e3;if(getCurrentPages().length<=o)return console.warn(`[navigation] 无法返回${o}页,当前页面栈深度不足`),void r(!1);const a=setTimeout(()=>{console.warn("[navigation] 导航返回超时"),r(!1)},s);uni.navigateBack({delta:o,success:()=>{clearTimeout(a),setTimeout(()=>{try{const t=getCurrentPages();if(t.length>0){const n=t[t.length-1];n.$vm&&"function"==typeof n.$vm.init&&n.$vm.init(e)}r(!0)}catch(e){A.handleError(new t("PAGE_CALLBACK_ERROR",`页面回调执行失败: ${e instanceof Error?e.message:String(e)}`,"navigation"),"navigation"),r(!0)}},100)},fail:e=>{clearTimeout(a),A.handleError(new t("NAVIGATE_BACK_FAILED","导航返回失败","navigation"),"navigation"),r(!1)}})})}const O=T(C,300);async function I(e){return new Promise(n=>{const r=_(e.url,e.params);uni.reLaunch({url:r,success:()=>n(!0),fail:e=>{A.handleError(new t("RELAUNCH_FAILED",`重新启动失败: ${r}`,"navigation"),"navigation"),n(!1)}})})}const $={showToast:!0,successMessage:"复制成功",failMessage:"复制失败",timeout:5e3},M=n.getInstance();class b{static instance;cache=new Map;maxCacheSize=100;static getInstance(){return b.instance||(b.instance=new b),b.instance}isExpired(e){return!!e.ttl&&Date.now()-e.timestamp>e.ttl}set(e,n,r={}){try{if(!e||"string"!=typeof e)throw new Error("存储键不能为空");const t={value:n,timestamp:Date.now(),ttl:r.ttl},o=JSON.stringify(t);if(o.length>1048576)throw new Error("存储数据过大");if(uni.setStorageSync(e,o),this.cache.size>=this.maxCacheSize){const e=this.cache.keys().next().value;e&&this.cache.delete(e)}return this.cache.set(e,t),!0}catch(e){throw M.handleError(new t("SET_STORAGE_ERROR",`设置存储失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),e}}get(e,t){try{if(!e||"string"!=typeof e)return t;if(this.cache.has(e)){const n=this.cache.get(e);return this.isExpired(n)?(this.cache.delete(e),this.remove(e),t):n.value}const n=uni.getStorageSync(e);if(!n||"string"!=typeof n)return t;const r=JSON.parse(n);let o;return o=r&&"object"==typeof r&&"value"in r&&"timestamp"in r?r:{value:r,timestamp:Date.now()},this.isExpired(o)?(this.remove(e),t):(this.cache.set(e,o),o.value)}catch(n){return console.warn(`[localStorage] 获取存储失败 [${e}]:`,n),t}}remove(e){try{return!(!e||"string"!=typeof e||(uni.removeStorageSync(e),this.cache.delete(e),0))}catch(n){return M.handleError(new t("REMOVE_STORAGE_ERROR",`删除存储失败: ${e}`,"localStorage"),"localStorage"),!1}}clear(){try{return uni.clearStorageSync(),this.cache.clear(),!0}catch(e){return M.handleError(new t("CLEAR_STORAGE_ERROR","清空存储失败","localStorage"),"localStorage"),!1}}getInfo(){try{const e=uni.getStorageInfoSync();return{keys:e.keys||[],currentSize:e.currentSize||0,limitSize:e.limitSize||0}}catch(e){return M.handleError(new t("GET_STORAGE_INFO_ERROR",`获取存储信息失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),{keys:[],currentSize:0,limitSize:0}}}cleanExpired(){try{const e=this.getInfo();let t=0;return e.keys.forEach(e=>{void 0===this.get(e)&&t++}),t}catch(e){return M.handleError(new t("CLEAN_EXPIRED_ERROR",`清理过期数据失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),0}}}const U=b.getInstance();function D(e,t,n={}){return U.set(e,t,n)}function L(e,t){return U.get(e,t)}function N(e){const t=e.lastIndexOf(".");if(-1!==t&&t!==e.length-1)return e.slice(t+1).toLowerCase()}function k(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function H(e,t){return t&&e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function F(e,t){if(0===e.length)return{success:!1,files:e,message:"未选择任何文件"};const{maxSelectFileSizeMB:n,extensions:r}=t;if(n&&e.some(e=>!H(e.size,n).valid))return{success:!1,files:e,message:`部分文件大小超过 ${n}MB 限制`};if(r&&r.length>0){const t=r.map(e=>e.toLowerCase());if(e.some(e=>!e.ext||!t.includes(e.ext)))return{success:!1,files:e,message:`存在不支持的文件类型,仅支持:${r.join(", ")}`}}return{success:!0,files:e}}async function B(e,t,n){const{url:r,maxUploadFileSizeMB:o,showToast:s=!0,beforeUpload:a}=t;if("function"==typeof a&&!await Promise.resolve(a(e)))return{file:e,success:!1,message:"已取消上传"};if(!r){const t="上传地址不能为空";return s&&v(t,!1,"error"),Promise.resolve({file:e,success:!1,message:t})}const i=H(e.size,o);return i.valid?"h5"===e.platform&&e.raw instanceof File?function(e,t,n){const{url:r,fieldName:o="file",formData:s,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:l="上传失败",onProgress:u,uploadTimeoutMs:p,autoRevokeObjectURL:m=!1}=t;return new Promise(t=>{const f=e.raw;if(!(f&&f instanceof File)){const n="H5 环境缺少原生文件对象";return i&&v(n,!1,"none"),void t({file:e,success:!1,message:n})}const g=m&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&"string"==typeof e.path&&e.path.startsWith("blob:"),d=()=>{if(g)try{URL.revokeObjectURL(e.path)}catch{}},h=new XMLHttpRequest,w=new FormData;w.append(o,f,e.name),s&&Object.keys(s).forEach(e=>{w.append(e,String(s[e]))}),u&&h.upload.addEventListener("progress",t=>{if(t.lengthComputable){const n=Math.round(t.loaded/t.total*100);u(e,n)}}),h.addEventListener("load",()=>{const r=h.status,o=r>=200&&r<300;let s=h.responseText;try{s=JSON.parse(h.responseText)}catch{}if(o)i&&1===n&&v(c,!1,"none"),d(),t({file:e,success:!0,statusCode:r,data:s});else{const n=`上传失败,状态码:${r}`;i&&v(n,!1,"none"),d(),t({file:e,success:!1,statusCode:r,data:s,message:n})}}),h.addEventListener("error",()=>{const n=l;i&&v(n,!1,"none"),d(),t({file:e,success:!1,message:n})}),h.addEventListener("timeout",()=>{const n=p?`上传超时(${p}ms)`:"上传超时";i&&v(n,!1,"none"),d(),t({file:e,success:!1,message:n})}),h.addEventListener("abort",()=>{d(),t({file:e,success:!1,message:"上传已取消"})}),h.open("POST",r),"number"==typeof p&&p>0&&(h.timeout=p),a&&Object.keys(a).forEach(e=>{h.setRequestHeader(e,a[e])}),h.send(w)})}(e,t,n):function(e,t,n){const{url:r,fieldName:o="file",formData:s,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:l="上传失败",onProgress:u,uploadTimeoutMs:p}=t,m="undefined"==typeof uni?null:uni;if(!m||"function"!=typeof m.uploadFile){const t="当前环境不支持文件上传";return i&&v(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(t=>{let f=!1,g=null;const d=e=>{f||(f=!0,g&&(clearTimeout(g),g=null),t(e))};let h=null;"number"==typeof p&&p>0&&(g=setTimeout(()=>{try{h&&"function"==typeof h.abort&&h.abort()}catch{}const t=`上传超时(${p}ms)`;i&&v(t,!1,"none"),d({file:e,success:!1,message:t})},p)),h=m.uploadFile({url:r,filePath:e.path,name:o,formData:s,header:a,success:t=>{let r=t.data;try{r=JSON.parse(t.data)}catch{}const o=t.statusCode;if(o>=200&&o<300)i&&1===n&&v(c,!1,"none"),d({file:e,success:!0,statusCode:o,data:r});else{const t=`上传失败,状态码:${o}`;i&&v(t,!1,"none"),d({file:e,success:!1,statusCode:o,data:r,message:t})}},fail:t=>{const n=t?.errMsg||l;i&&v(n,!1,"none"),d({file:e,success:!1,message:n})}}),u&&h&&"function"==typeof h.onProgressUpdate&&h.onProgressUpdate(t=>{u(e,t.progress)})})}(e,t,n):(s&&i.message&&v(i.message,!1,"error"),Promise.resolve({file:e,success:!1,message:i.message}))}async function G(e){const{showToast:t=!0,failMessage:n="选择文件失败"}=e;try{const r=await async function(e){return"undefined"!=typeof document&&"undefined"!=typeof window?function(e){const{type:t="image",count:n=1,extensions:r}=e;return new Promise(o=>{if("undefined"==typeof document)return void o({success:!1,files:[],message:"当前环境不支持文件选择"});const s=document.createElement("input");s.type="file",s.multiple=n>1,"image"===t?s.accept="image/*":r&&r.length>0&&(s.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(",")),s.onchange=t=>{const n=t.target,r=n?.files;if(!r||0===r.length)return o({success:!1,files:[],message:"用户取消选择"}),void document.body.removeChild(s);const a=F(Array.from(r).map((e,t)=>{const n=N(e.name),r=URL.createObjectURL(e);return{id:k(t),name:e.name,size:e.size,path:r,mimeType:e.type,ext:n,source:"file",platform:"h5",raw:e}}),e);o(a),document.body.removeChild(s)},s.style.display="none",document.body.appendChild(s),s.click()})}(e):function(e){const{type:t="image",count:n=1}=e;return new Promise(r=>{const o="undefined"==typeof uni?null:uni;if(!o)return void r({success:!1,files:[],message:"当前环境不支持文件选择"});const s=e=>{const t=function(e){const t=(e||"").trim();if(!t)return"选择文件失败";const n=t.toLowerCase();return n.includes("fail cancel")||n.includes("cancel")?"用户取消选择":/[\u4e00-\u9fff]/.test(t)?t:"选择文件失败"}(e?.errMsg);r({success:!1,files:[],message:t})},a=function(){let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}();"image"!==t||"function"!=typeof o.chooseImage?"function"!=typeof o.chooseMessageFile?"function"!=typeof o.chooseFile?r({success:!1,files:[],message:"当前平台不支持文件选择"}):o.chooseFile({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=N(e.path);return{id:k(t),name:`file_${t}`,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(F(n,e))},fail:s}):o.chooseMessageFile({count:n,type:"all",success:t=>{const n=t.tempFiles.map((e,t)=>{const n=N(e.name||e.path);return{id:k(t),name:e.name,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(F(n,e))},fail:s}):o.chooseImage({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=N(e.path);return{id:k(t),name:`image_${t}`,size:e.size,path:e.path,ext:n,source:"album",platform:a,raw:e}});r(F(n,e))},fail:s})})}(e)}(e);if(!r.success){const e=r.message||n;return t&&e&&v(e,!1,"none"),[{file:null,success:!1,message:e}]}const o=r.files;if(0===o.length)return[];const s=o.length;return await async function(e,t,n){const r=new Array(e.length),o=t.concurrency&&t.concurrency>0?Math.min(t.concurrency,e.length):e.length;let s=0;const a=async()=>{for(;;){const o=s;if(o>=e.length)break;s+=1;const a=e[o],i=await B(a,t,n);r[o]=i}},i=[];for(let e=0;e<o;e+=1)i.push(a());return await Promise.all(i),r}(o,e,s)}catch(e){const r=n;return t&&r&&v(r,!1,"none"),[{file:null,success:!1,message:r}]}}const j=n.getInstance(),W=n.getInstance(),J=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),z=()=>"undefined"!=typeof window&&"undefined"!=typeof document,K=()=>z()&&J()&&window.wx||null;let q=!1,V=null;const Y=(e={})=>{const{timeoutMs:t=1e4}=e;if(q||z()&&window.wx)return q=!0,Promise.resolve(!0);if(!z())return Promise.resolve(!1);if(V)return V;const n=e.cdnUrls&&e.cdnUrls.length>0?e.cdnUrls:["https://res.wx.qq.com/open/js/jweixin-1.6.0.js","https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"];return V=new Promise(e=>{let r=!1,o=null,s=null,a=0;const i=t=>{r||(r=!0,o&&(clearTimeout(o),o=null),s&&s.parentNode&&s.parentNode.removeChild(s),t&&(q=!0),V=null,e(t))},c=()=>{if(a>=n.length)return void i(!1);if(!document.head)return void i(!1);const e=n[a];a+=1;const t=document.createElement("script");s=t,t.src=e,t.async=!0,t.onload=()=>i(!0),t.onerror=()=>{t.parentNode&&t.parentNode.removeChild(t),s=null,c()},document.head.appendChild(t)};o=setTimeout(()=>{i(!1)},t),c()}),V};let X=null;const Q=async(e,n={})=>{const{timeoutMs:r=1e4}=n;if(!J())return console.warn("当前不在微信环境中"),!1;if(X)return X;if(!await Y({timeoutMs:r}))return W.handleError(new t("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;if(!z())return!1;const o=window.wx;return!!o&&(X=new Promise(n=>{let s=!1,a=null;const i=e=>{s||(s=!0,a&&(clearTimeout(a),a=null),X=null,n(e))};a=setTimeout(()=>i(!1),r);try{o.config({debug:e.debug||!1,appId:e.appId,timestamp:e.timestamp,nonceStr:e.nonceStr,signature:e.signature,jsApiList:e.jsApiList}),o.ready(()=>{console.log("微信 JS-SDK 初始化完成"),i(!0)}),o.error(e=>{W.handleError(new t("WECHAT_JSSDK_CONFIG_ERROR",`微信 JS-SDK 配置错误: ${JSON.stringify(e)}`,"weixin"),"weixin"),i(!1)})}catch(e){W.handleError(new t("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),i(!1)}}),X)},Z=e=>{const t=K();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},ee=e=>{const t=K();t&&(t.updateAppMessageShareData?t.updateAppMessageShareData(e):t.onMenuShareAppMessage&&t.onMenuShareAppMessage(e))};class te{static instance;isConfigured=!1;config=null;initPromise=null;constructor(){}static getInstance(){return te.instance||(te.instance=new te),te.instance}async init(e){return this.initPromise||(this.config=e,this.initPromise=Q(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return this.isConfigured&&J()}getConfig(){return this.config}setShareData(e){this.isReady()?(Z(e),ee(e)):console.warn("微信 SDK 未就绪")}}const ne="3.1.0",re={info:0,warn:1,error:2};exports.ErrorHandler=n,exports.PerformanceMonitor=a,exports.UniAppToolsError=t,exports.VERSION=ne,exports.WechatSDK=te,exports.areaList=R,exports.batchGetStorage=function(e){const t=a.getInstance();t.start("batchGetStorage","localStorage");const n={};return e.forEach(e=>{n[e]=L(e)}),t.end("batchGetStorage"),n},exports.batchSetStorage=function(e,t={}){const n=a.getInstance();n.start("batchSetStorage","localStorage");let r=0;return Object.entries(e).forEach(([e,n])=>{D(e,n,t)&&r++}),n.end("batchSetStorage"),r},exports.checkWechatJSAPI=(e,n={})=>{const{timeoutMs:r=8e3}=n;return new Promise(n=>{const o=K();if(!o||"function"!=typeof o.checkJsApi)return void n({});let s=!1;const a=e=>{s||(s=!0,n(e))},i=setTimeout(()=>a({}),r);try{o.checkJsApi({jsApiList:e,success:e=>{clearTimeout(i),a(e?.checkResult||{})}})}catch(e){clearTimeout(i),W.handleError(new t("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),a({})}})},exports.cleanExpiredStorage=function(){return U.cleanExpired()},exports.clearStorageSync=function(e){return e?U.remove(e):U.clear()},exports.clearSystemCache=()=>{u=null},exports.configWechatJSSDK=Q,exports.copyText=async function(e,t={}){const n=a.getInstance();n.start("copyText","clipboard",{textLength:e.length});const o={...$,...t};if(!e||"string"!=typeof e)return o.showToast&&v("复制内容不能为空",!1,"error"),n.end("copyText"),!1;if(e.length>1e4)return o.showToast&&v("复制内容过长",!1,"error"),n.end("copyText"),!1;const s=await r(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{o.showToast&&v(o.successMessage),t(!0)},fail:()=>{o.showToast&&v(o.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1;return n.end("copyText"),s},exports.debounce=T,exports.deepClone=S,exports.deepMerge=function(e,t){const n=S(e);return function e(t,n){for(const r in n)if(n.hasOwnProperty(r)){const o=n[r],s=t[r];o&&"object"==typeof o&&!Array.isArray(o)&&s&&"object"==typeof s&&!Array.isArray(s)?e(s,o):t[r]=S(o)}}(n,t),n},exports.extractUrlParts=function(e){try{const t=new URL(e,"http://localhost"),n=t.pathname,r={};return t.searchParams.forEach((e,t)=>{r[t]=e}),{path:n,params:r}}catch(n){return E.handleError(new t("EXTRACT_URL_PARTS_ERROR",`无效的URL: ${e}`,"utils"),"utils"),{path:"",params:{}}}},exports.getCurrentEnv=()=>{try{const e=uni.getAccountInfoSync();return{appId:e.miniProgram?.appId||"",version:e.miniProgram?.version||"",envVersion:e.miniProgram?.envVersion||"",accountInfo:e}}catch(e){return i.handleError(new t("GET_ACCOUNT_INFO_ERROR",`获取小程序账户信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),{appId:"",version:"",envVersion:"",accountInfo:{}}}},exports.getCurrentPageInfo=function(){try{const e=getCurrentPages();if(0===e.length)return null;const t=e[e.length-1];return{route:t.route||"",options:t.options||{}}}catch(e){return A.handleError(new t("GET_CURRENT_PAGE_ERROR",`获取当前页面信息失败: ${e instanceof Error?e.message:String(e)}`,"navigation"),"navigation"),null}},exports.getH5UrlParams=e=>{try{if("undefined"==typeof window||!window.location)throw new Error("不在 H5 浏览器环境中");const t=new URLSearchParams(window.location.search),n={};return t.forEach((e,t)=>{try{n[t]=decodeURIComponent(e)}catch(r){n[t]=e}}),console.log("🔗 H5 URL参数解析:",{fullUrl:window.location.href,searchParams:window.location.search,parsedParams:n,paramName:e}),e?n.hasOwnProperty(e)?n[e]:null:n}catch(n){return E.handleError(new t("GET_H5_URL_PARAMS_ERROR",`获取H5 URL参数失败: ${n instanceof Error?n.message:String(n)}`,"utils"),"utils"),e?null:{}}},exports.getMenuButtonBoundingClientRect=h,exports.getNavHeight=()=>y().totalTopHeight,exports.getNavigationBarHeight=w,exports.getPageStack=function(){try{return getCurrentPages().map(e=>({route:e.route||"",options:e.options||{}}))}catch(e){return A.handleError(new t("GET_PAGE_STACK_ERROR",`获取页面栈信息失败: ${e instanceof Error?e.message:String(e)}`,"navigation"),"navigation"),[]}},exports.getPlatform=f,exports.getStatusBarHeight=d,exports.getStorage=async function(e,t){return await r(()=>new Promise(n=>{n(L(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t},exports.getStorageInfo=function(){return U.getInfo()},exports.getStorageSync=L,exports.getTopBarMetrics=y,exports.getTopNavBarHeight=()=>{const e=y();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},exports.initUniAppTools=function(e={}){const{enablePerformanceMonitor:t=!1,enableErrorHandler:r=!0,onError:o=null,performanceReportInterval:s=0,showInitMessage:i=!1,silent:c=!1,logLevel:l="warn",enablePerformanceLog:u=!1}=e,p=re[l]||re.warn,m=(...e)=>{!c&&p<=re.info&&console.log(...e)},f=(...e)=>{!c&&p<=re.warn&&console.warn(...e)};if(r){const e=n.getInstance();"function"==typeof o?e.onError(o):e.onError(e=>{((...e)=>{!c&&p<=re.error&&console.error(...e)})(`[UniAppTools] ${e.module} - ${e.code}: ${e.message}`,e)})}if(t){const e=a.getInstance();u?s>0?(m("[UniAppTools] 性能监控已启用"),m("[UniAppTools] - 模式1: 每次操作结束时会输出单次性能日志"),m(`[UniAppTools] - 模式2: 每 ${s}ms 输出完整性能报告`),setInterval(()=>{const t=e.getReport();t.slowest.length>0?m("[UniAppTools] 性能报告:",t):m("[UniAppTools] 性能报告: 暂无性能数据(请调用工具函数以产生性能记录)")},s)):(m("[UniAppTools] 性能监控已启用(仅单次日志模式)"),m("[UniAppTools] 提示: 每次操作结束时会输出单次性能日志"),f("[UniAppTools] 警告: 未设置 performanceReportInterval,定期性能报告不会输出"),f("[UniAppTools] 如需启用定期报告,请设置 performanceReportInterval 为大于 0 的毫秒数(如: 30000 表示每30秒)")):m("[UniAppTools] 性能监控已启用(静默模式 - 不输出日志)")}if(m(`[UniAppTools] v${ne} 初始化完成`),i&&"undefined"!=typeof uni)try{uni.showToast({title:`工具库v${ne}已就绪`,icon:"none",duration:2e3})}catch(e){}},exports.isWechat=J,exports.loadWechatJSSDK=Y,exports.measurePerformance=function(e){return function(t,n,r){const o=r.value;r.value=function(...r){const s=a.getInstance(),i=`${t.constructor.name}.${n}`;s.start(i,e,{args:r.length});try{const e=o.apply(this,r);return e instanceof Promise?e.finally(()=>{s.end(i)}):(s.end(i),e)}catch(e){throw s.end(i),e}}}},exports.mergeObjects=function(e,t){if(!t||0===Object.keys(t).length)return e;const n={...e};for(const r of Object.keys(e))Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n},exports.navigateTo=P,exports.onCheckForUpdate=()=>{if(!m)try{const e=uni.getUpdateManager();m=!0,e.onCheckForUpdate(function(e){e.hasUpdate}),e.onUpdateReady(function(t){uni.showModal({title:"更新提示",content:"新版本已经准备好,是否重启应用?",showCancel:!0,cancelText:"稍后",confirmText:"立即重启",success(t){t.confirm&&e.applyUpdate()}})}),e.onUpdateFailed(function(e){i.handleError(new t("UPDATE_DOWNLOAD_FAILED","新版本下载失败","system"),"system"),uni.showModal({title:"更新失败",content:"新版本下载失败,请检查网络连接或稍后重试",showCancel:!1,confirmText:"知道了"})})}catch(e){i.handleError(new t("CHECK_UPDATE_ERROR",`版本更新检查失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system")}},exports.reLaunch=I,exports.redirectTo=async function(e){return new Promise(n=>{const r=_(e.url,e.params);uni.redirectTo({url:r,success:()=>n(!0),fail:e=>{A.handleError(new t("REDIRECT_TO_FAILED",`页面重定向失败: ${r}`,"navigation"),"navigation"),n(!1)}})})},exports.safeAsync=r,exports.safeNavigateTo=async function(e,t=3){for(let n=0;n<t;n++){if(await P(e))return!0;n<t-1&&(await new Promise(e=>setTimeout(e,1e3*(n+1))),console.log(`[navigation] 第${n+2}次尝试跳转...`))}return!1},exports.safeSync=o,exports.selectAndUpload=G,exports.selectAndUploadImage=async function(e){return G({...e,type:"image"})},exports.setPageIcon=(e,t="image/x-icon")=>o(()=>{const n=f();if("h5"===n||"web"===n){if("undefined"!=typeof document){document.querySelectorAll('link[rel*="icon"]').forEach(e=>e.remove());const n=document.createElement("link");return n.rel="icon",n.type=t,n.href=e,document.head.appendChild(n),!0}}else console.warn("setPageIcon 仅在H5/Web平台有效");return!1},"system","SET_PAGE_ICON_ERROR",!1),exports.setPageTitle=e=>"string"!=typeof e?(console.warn("setPageTitle: title必须是字符串"),Promise.resolve(!1)):""===e.trim()?(console.warn("setPageTitle: title不能为空"),Promise.resolve(!1)):new Promise(n=>{try{uni.setNavigationBarTitle({title:e,success:()=>{n(!0)},fail:e=>{console.warn("设置页面标题失败:",e),n(!1)}})}catch(e){i.handleError(new t("SET_PAGE_TITLE_ERROR",`setPageTitle执行异常: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),n(!1)}}),exports.setStorage=async function(e,t,n={}){return await r(()=>new Promise(r=>{r(D(e,t,n))}),"localStorage","SET_STORAGE_ASYNC_ERROR")??!1},exports.setStorageSync=D,exports.shareToFriend=ee,exports.shareToTimeline=Z,exports.switchTab=async function(e){return new Promise(n=>{uni.switchTab({url:e,success:()=>n(!0),fail:r=>{A.handleError(new t("SWITCH_TAB_FAILED",`Tab切换失败: ${e}`,"navigation"),"navigation"),n(!1)}})})},exports.throttle=function(e,t,n={}){let r,o=null,s=0;const{leading:a=!0,trailing:i=!0}=n,c=function(...n){const c=Date.now();s||a||(s=c);const l=t-(c-s);return l<=0||l>t?(o&&(clearTimeout(o),o=null),s=c,r=e.apply(this,n)):!o&&i&&(o=setTimeout(()=>{s=a?Date.now():0,o=null,r=e.apply(this,n)},l)),r};return c.cancel=()=>{o&&(clearTimeout(o),o=null),s=0},c},exports.useBack=C,exports.useBackDebounced=O,exports.useBackOrHome=async function(e="",t={}){const n=getCurrentPages(),r=t.delta||1;if(n.length>r)return await C(e,t);const o=t.homePage||"pages/index/index",s=o.startsWith("/")?o:`/${o}`;return console.info(`[navigation] 页面栈深度不足,重定向到首页: ${s}`),await I({url:s,params:t.homeParams})},exports.useCascaderAreaData=x,exports.useRegions=function(){return e.useCascaderAreaData()},exports.useToast=v,exports.useTryCatch=function(e,t={}){return async(...n)=>{try{return{data:await e(...n),error:null}}catch(e){return t.onError?.(e),{data:null,error:e}}finally{t.onFinally?.()}}},exports.useWindowInfo=g,exports.weChatOfficialAccountPayment=(e,n,r)=>{const s=a.getInstance();return s.start("weChatOfficialAccountPayment","payment"),new Promise(a=>{o(()=>{if("undefined"==typeof window||!window.navigator)throw new Error("不在浏览器环境中,无法调用微信支付");if(!(e&&e.appId&&e.timeStamp&&e.nonceStr&&e.package&&e.paySign))throw new Error("微信支付配置参数不完整");function o(){try{window.WeixinJSBridge.invoke("getBrandWCPayRequest",e,function(e){s.end("weChatOfficialAccountPayment"),console.log("🚀 ~ 微信支付结果:",e),"get_brand_wcpay_request:ok"===e.err_msg?(console.log("✅ 微信支付成功"),n?.(e),a(!0)):(console.warn("❌ 微信支付失败或取消:",e.err_msg),r?.(e),a(!1))})}catch(e){s.end("weChatOfficialAccountPayment"),j.handleError(new t("WECHAT_PAY_INVOKE_ERROR",`调用微信支付接口失败: ${e instanceof Error?e.message:String(e)}`,"payment"),"payment");const n={err_msg:"get_brand_wcpay_request:fail",err_desc:e instanceof Error?e.message:"未知错误"};r?.(n),a(!1)}}if(void 0===window.WeixinJSBridge){const e=window.document;e.addEventListener?e.addEventListener("WeixinJSBridgeReady",o,!1):e.attachEvent&&(e.attachEvent("WeixinJSBridgeReady",o),e.attachEvent("onWeixinJSBridgeReady",o))}else o();return!0},"payment","WECHAT_PAY_ERROR",!1)||(s.end("weChatOfficialAccountPayment"),a(!1))})};
1
+ "use strict";var e=require("@vant/area-data");class t extends Error{code;module;timestamp;constructor(e,t,n){super(t),this.name="UniAppToolsError",this.code=e,this.module=n,this.timestamp=Date.now()}}class n{static instance;errorCallbacks=[];static getInstance(){return n.instance||(n.instance=new n),n.instance}onError(e){this.errorCallbacks.push(e)}handleError(e,n){const r={code:e instanceof t?e.code:"UNKNOWN_ERROR",message:e.message,module:e instanceof t?e.module:n,timestamp:e instanceof t?e.timestamp:Date.now(),stack:e.stack};console.error(`[${r.module}] ${r.code}: ${r.message}`,r),this.errorCallbacks.forEach(e=>{try{e(r)}catch(e){console.error("Error in error callback:",e)}})}createModuleErrorHandler(e){return(n,r,s)=>{const o=new t(n,r,e);return s&&(o.stack=s.stack),this.handleError(o,e),o}}}async function r(e,t,r="ASYNC_ERROR"){try{return await e()}catch(e){return n.getInstance().createModuleErrorHandler(t)(r,`异步操作失败: ${e instanceof Error?e.message:String(e)}`,e),null}}function s(e,t,r="SYNC_ERROR",s=null){try{return e()}catch(e){return n.getInstance().createModuleErrorHandler(t)(r,`同步操作失败: ${e instanceof Error?e.message:String(e)}`,e),s}}const o=n.getInstance();let a=null,i=null,c=null;const u=e=>"weixin"===e||"alipay"===e;let l=!1;const f=()=>{if(a)return a;let e="unknown";return e="weixin",e="web",e="app",e="alipay",e="h5",a="h5","h5"},m=(e=!0)=>e&&c?c:s(()=>{const t=uni.getWindowInfo();return e&&(c=t),t},"system","GET_WINDOW_INFO_ERROR",null),p=()=>{if(null!==i)return i;try{const e=m();return i=e?.statusBarHeight||0,i}catch(e){return o.handleError(new t("GET_STATUS_BAR_HEIGHT_ERROR",`获取状态栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),0}},g=()=>{try{const e=f();return u(e)?uni.getMenuButtonBoundingClientRect():null}catch(e){return o.handleError(new t("GET_MENU_BUTTON_ERROR",`获取菜单按钮边界信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),null}},d=()=>{try{const e=f();if(u(e)){const e=g();return e?.height||44}return 44}catch(e){return o.handleError(new t("GET_NAVIGATION_BAR_HEIGHT_ERROR",`获取导航栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),44}},h=()=>{const e=f(),t=p(),n=d();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},y=n.getInstance();function E(e){if(null===e||"object"!=typeof e)return e;try{if("undefined"!=typeof structuredClone)try{return structuredClone(e)}catch(e){}return JSON.parse(JSON.stringify(e))}catch(e){throw y.handleError(new t("DEEP_CLONE_ERROR",`深拷贝失败: ${e instanceof Error?e.message:String(e)}`,"utils"),"utils"),new Error(`深拷贝失败: ${e instanceof Error?e.message:String(e)}`)}}function w(e,t,n=!1){let r,s=null;const o=function(...o){const a=n&&!s;return s&&clearTimeout(s),s=setTimeout(()=>{s=null,n||(r=e.apply(this,o))},t),a&&(r=e.apply(this,o)),r};return o.cancel=()=>{s&&(clearTimeout(s),s=null)},o}const S=e.areaList,R=e.useCascaderAreaData,T=(e="",t=!1,n="none",r=2e3)=>{uni.showToast({title:e,icon:n,mask:t,duration:r})},x=n.getInstance();function _(e,t){if(!t||0===Object.keys(t).length)return e;const n=Object.entries(t).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(String(t))}`).join("&");return e+(e.includes("?")?"&":"?")+n}function A(e,n){x.handleError(new t(e,n,"navigation"),"navigation")}async function v(e){return new Promise(t=>{const n=_(e.url,e.params);uni.navigateTo({url:n,animationType:e.animationType,animationDuration:e.animationDuration,events:e.events,success:()=>t(!0),fail:e=>{A("NAVIGATE_TO_FAILED",`页面跳转失败: ${n}`),t(!1)}})})}async function C(e){return new Promise(t=>{const n=_(e.url,e.params);uni.reLaunch({url:n,success:()=>t(!0),fail:e=>{A("RELAUNCH_FAILED",`重新启动失败: ${n}`),t(!1)}})})}async function P(e="",t={}){return new Promise(n=>{const r=t.delta||1,s=t.timeout||5e3;if(getCurrentPages().length<=r)return console.warn(`[navigation] 无法返回${r}页,当前页面栈深度不足`),void n(!1);const o=setTimeout(()=>{console.warn("[navigation] 导航返回超时"),n(!1)},s);uni.navigateBack({delta:r,success:()=>{clearTimeout(o),setTimeout(()=>{try{const t=getCurrentPages();if(t.length>0){const n=t[t.length-1];n.$vm&&"function"==typeof n.$vm.init&&n.$vm.init(e)}n(!0)}catch(e){A("PAGE_CALLBACK_ERROR",`页面回调执行失败: ${e instanceof Error?e.message:String(e)}`),n(!0)}},100)},fail:e=>{clearTimeout(o),A("NAVIGATE_BACK_FAILED","导航返回失败"),n(!1)}})})}const O=w(P,300),I={showToast:!0,successMessage:"复制成功",failMessage:"复制失败",timeout:5e3},$=n.getInstance();class b{static instance;cache=new Map;maxCacheSize=100;static getInstance(){return b.instance||(b.instance=new b),b.instance}isExpired(e){return!!e.ttl&&Date.now()-e.timestamp>e.ttl}set(e,n,r={}){try{if(!e||"string"!=typeof e)throw new Error("存储键不能为空");const t={value:n,timestamp:Date.now(),ttl:r.ttl},s=JSON.stringify(t);if(s.length>1048576)throw new Error("存储数据过大");if(uni.setStorageSync(e,s),this.cache.size>=this.maxCacheSize){const e=this.cache.keys().next().value;e&&this.cache.delete(e)}return this.cache.set(e,t),!0}catch(e){throw $.handleError(new t("SET_STORAGE_ERROR",`设置存储失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),e}}get(e,t){try{if(!e||"string"!=typeof e)return t;if(this.cache.has(e)){const n=this.cache.get(e);return this.isExpired(n)?(this.cache.delete(e),this.remove(e),t):n.value}const n=uni.getStorageSync(e);if(!n||"string"!=typeof n)return t;const r=JSON.parse(n);let s;return s=r&&"object"==typeof r&&"value"in r&&"timestamp"in r?r:{value:r,timestamp:Date.now()},this.isExpired(s)?(this.remove(e),t):(this.cache.set(e,s),s.value)}catch(n){return console.warn(`[localStorage] 获取存储失败 [${e}]:`,n),t}}remove(e){try{return!(!e||"string"!=typeof e||(uni.removeStorageSync(e),this.cache.delete(e),0))}catch(n){return $.handleError(new t("REMOVE_STORAGE_ERROR",`删除存储失败: ${e}`,"localStorage"),"localStorage"),!1}}clear(){try{return uni.clearStorageSync(),this.cache.clear(),!0}catch(e){return $.handleError(new t("CLEAR_STORAGE_ERROR","清空存储失败","localStorage"),"localStorage"),!1}}getInfo(){try{const e=uni.getStorageInfoSync();return{keys:e.keys||[],currentSize:e.currentSize||0,limitSize:e.limitSize||0}}catch(e){return $.handleError(new t("GET_STORAGE_INFO_ERROR",`获取存储信息失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),{keys:[],currentSize:0,limitSize:0}}}cleanExpired(){try{const e=this.getInfo();let t=0;return e.keys.forEach(e=>{void 0===this.get(e)&&t++}),t}catch(e){return $.handleError(new t("CLEAN_EXPIRED_ERROR",`清理过期数据失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),0}}}const D=b.getInstance();function L(e,t,n={}){return D.set(e,t,n)}function M(e,t){return D.get(e,t)}function U(e){const t=e.lastIndexOf(".");if(-1!==t&&t!==e.length-1)return e.slice(t+1).toLowerCase()}function N(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function k(e,t){return t&&e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function H(e,t){if(0===e.length)return{success:!1,files:e,message:"未选择任何文件"};const{maxSelectFileSizeMB:n,extensions:r}=t;if(n&&e.some(e=>!k(e.size,n).valid))return{success:!1,files:e,message:`部分文件大小超过 ${n}MB 限制`};if(r&&r.length>0){const t=r.map(e=>e.toLowerCase());if(e.some(e=>!e.ext||!t.includes(e.ext)))return{success:!1,files:e,message:`存在不支持的文件类型,仅支持:${r.join(", ")}`}}return{success:!0,files:e}}async function F(e,t,n){const{url:r,maxUploadFileSizeMB:s,showToast:o=!0,beforeUpload:a}=t;if("function"==typeof a&&!await Promise.resolve(a(e)))return{file:e,success:!1,message:"已取消上传"};if(!r){const t="上传地址不能为空";return o&&T(t,!1,"error"),Promise.resolve({file:e,success:!1,message:t})}const i=k(e.size,s);return i.valid?"h5"===e.platform&&e.raw instanceof File?function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:u="上传失败",onProgress:l,uploadTimeoutMs:f,autoRevokeObjectURL:m=!1}=t;return new Promise(t=>{const p=e.raw;if(!(p&&p instanceof File)){const n="H5 环境缺少原生文件对象";return i&&T(n,!1,"none"),void t({file:e,success:!1,message:n})}const g=m&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&"string"==typeof e.path&&e.path.startsWith("blob:"),d=()=>{if(g)try{URL.revokeObjectURL(e.path)}catch{}},h=new XMLHttpRequest,y=new FormData;y.append(s,p,e.name),o&&Object.keys(o).forEach(e=>{y.append(e,String(o[e]))}),l&&h.upload.addEventListener("progress",t=>{if(t.lengthComputable){const n=Math.round(t.loaded/t.total*100);l(e,n)}}),h.addEventListener("load",()=>{const r=h.status,s=r>=200&&r<300;let o=h.responseText;try{o=JSON.parse(h.responseText)}catch{}if(s)i&&1===n&&T(c,!1,"none"),d(),t({file:e,success:!0,statusCode:r,data:o});else{const n=`上传失败,状态码:${r}`;i&&T(n,!1,"none"),d(),t({file:e,success:!1,statusCode:r,data:o,message:n})}}),h.addEventListener("error",()=>{const n=u;i&&T(n,!1,"none"),d(),t({file:e,success:!1,message:n})}),h.addEventListener("timeout",()=>{const n=f?`上传超时(${f}ms)`:"上传超时";i&&T(n,!1,"none"),d(),t({file:e,success:!1,message:n})}),h.addEventListener("abort",()=>{d(),t({file:e,success:!1,message:"上传已取消"})}),h.open("POST",r),"number"==typeof f&&f>0&&(h.timeout=f),a&&Object.keys(a).forEach(e=>{h.setRequestHeader(e,a[e])}),h.send(y)})}(e,t,n):function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:u="上传失败",onProgress:l,uploadTimeoutMs:f}=t,m="undefined"==typeof uni?null:uni;if(!m||"function"!=typeof m.uploadFile){const t="当前环境不支持文件上传";return i&&T(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(t=>{let p=!1,g=null;const d=e=>{p||(p=!0,g&&(clearTimeout(g),g=null),t(e))};let h=null;"number"==typeof f&&f>0&&(g=setTimeout(()=>{try{h&&"function"==typeof h.abort&&h.abort()}catch{}const t=`上传超时(${f}ms)`;i&&T(t,!1,"none"),d({file:e,success:!1,message:t})},f)),h=m.uploadFile({url:r,filePath:e.path,name:s,formData:o,header:a,success:t=>{let r=t.data;try{r=JSON.parse(t.data)}catch{}const s=t.statusCode;if(s>=200&&s<300)i&&1===n&&T(c,!1,"none"),d({file:e,success:!0,statusCode:s,data:r});else{const t=`上传失败,状态码:${s}`;i&&T(t,!1,"none"),d({file:e,success:!1,statusCode:s,data:r,message:t})}},fail:t=>{const n=t?.errMsg||u;i&&T(n,!1,"none"),d({file:e,success:!1,message:n})}}),l&&h&&"function"==typeof h.onProgressUpdate&&h.onProgressUpdate(t=>{l(e,t.progress)})})}(e,t,n):(o&&i.message&&T(i.message,!1,"error"),Promise.resolve({file:e,success:!1,message:i.message}))}async function B(e){const{showToast:t=!0,failMessage:n="选择文件失败"}=e;try{const r=await async function(e){return"undefined"!=typeof document&&"undefined"!=typeof window?function(e){const{type:t="image",count:n=1,extensions:r}=e;return new Promise(s=>{if("undefined"==typeof document)return void s({success:!1,files:[],message:"当前环境不支持文件选择"});const o=document.createElement("input");o.type="file",o.multiple=n>1,"image"===t?o.accept="image/*":r&&r.length>0&&(o.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(",")),o.onchange=t=>{const n=t.target,r=n?.files;if(!r||0===r.length)return s({success:!1,files:[],message:"用户取消选择"}),void document.body.removeChild(o);const a=H(Array.from(r).map((e,t)=>{const n=U(e.name),r=URL.createObjectURL(e);return{id:N(t),name:e.name,size:e.size,path:r,mimeType:e.type,ext:n,source:"file",platform:"h5",raw:e}}),e);s(a),document.body.removeChild(o)},o.style.display="none",document.body.appendChild(o),o.click()})}(e):function(e){const{type:t="image",count:n=1}=e;return new Promise(r=>{const s="undefined"==typeof uni?null:uni;if(!s)return void r({success:!1,files:[],message:"当前环境不支持文件选择"});const o=e=>{const t=function(e){const t=(e||"").trim();if(!t)return"选择文件失败";const n=t.toLowerCase();return n.includes("fail cancel")||n.includes("cancel")?"用户取消选择":/[\u4e00-\u9fff]/.test(t)?t:"选择文件失败"}(e?.errMsg);r({success:!1,files:[],message:t})},a=function(){let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}();"image"!==t||"function"!=typeof s.chooseImage?"function"!=typeof s.chooseMessageFile?"function"!=typeof s.chooseFile?r({success:!1,files:[],message:"当前平台不支持文件选择"}):s.chooseFile({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=U(e.path);return{id:N(t),name:`file_${t}`,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(H(n,e))},fail:o}):s.chooseMessageFile({count:n,type:"all",success:t=>{const n=t.tempFiles.map((e,t)=>{const n=U(e.name||e.path);return{id:N(t),name:e.name,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(H(n,e))},fail:o}):s.chooseImage({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=U(e.path);return{id:N(t),name:`image_${t}`,size:e.size,path:e.path,ext:n,source:"album",platform:a,raw:e}});r(H(n,e))},fail:o})})}(e)}(e);if(!r.success){const e=r.message||n;return t&&e&&T(e,!1,"none"),[{file:null,success:!1,message:e}]}const s=r.files;if(0===s.length)return[];const o=s.length;return await async function(e,t,n){const r=new Array(e.length),s=t.concurrency&&t.concurrency>0?Math.min(t.concurrency,e.length):e.length;let o=0;const a=async()=>{for(;;){const s=o;if(s>=e.length)break;o+=1;const a=e[s],i=await F(a,t,n);r[s]=i}},i=[];for(let e=0;e<s;e+=1)i.push(a());return await Promise.all(i),r}(s,e,o)}catch(e){const r=n;return t&&r&&T(r,!1,"none"),[{file:null,success:!1,message:r}]}}const j=n.getInstance(),G=n.getInstance(),W=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),J=()=>"undefined"!=typeof window&&"undefined"!=typeof document,z=()=>J()&&W()&&window.wx||null,K=(e,t=!1)=>{const n={};return e.forEach(e=>{"string"==typeof e&&""!==e.trim()&&(n[e]=t)}),n};let q=!1,V=null,Y=!1;const X=(e={})=>{const{timeoutMs:t=1e4}=e;if(q||J()&&window.wx)return q=!0,Promise.resolve(!0);if(!J())return Promise.resolve(!1);if(V)return V;const n=e.cdnUrls&&e.cdnUrls.length>0?e.cdnUrls:["https://res.wx.qq.com/open/js/jweixin-1.6.0.js","https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"];return V=new Promise(e=>{let r=!1,s=null,o=null,a=0;const i=t=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&o.parentNode&&o.parentNode.removeChild(o),t&&(q=!0),V=null,e(t))},c=()=>{if(a>=n.length)return void i(!1);if(!document.head)return void i(!1);const e=n[a];a+=1;const t=document.createElement("script");o=t,t.src=e,t.async=!0,t.onload=()=>i(!0),t.onerror=()=>{t.parentNode&&t.parentNode.removeChild(t),o=null,c()},document.head.appendChild(t)};s=setTimeout(()=>{i(!1)},t),c()}),V};let Q=null;const Z=async(e,n={})=>{const{timeoutMs:r=1e4}=n;return W()?Q||(Q=(async()=>{if(!await X({timeoutMs:r}))return G.handleError(new t("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;const n=z();if(!n||"function"!=typeof n.config||"function"!=typeof n.ready||"function"!=typeof n.error)return!1;const s=n.config,o=n.ready,a=n.error,i=await new Promise(n=>{let i=!1,c=null;const u=e=>{i||(i=!0,c&&(clearTimeout(c),c=null),n(e))};c=setTimeout(()=>u(!1),r);try{s({debug:e.debug||!1,appId:e.appId,timestamp:e.timestamp,nonceStr:e.nonceStr,signature:e.signature,jsApiList:e.jsApiList}),o(()=>u(!0)),a(e=>{G.handleError(new t("WECHAT_JSSDK_CONFIG_ERROR",`微信 JS-SDK 配置错误: ${(e=>{try{return JSON.stringify(e)}catch{return String(e)}})(e)}`,"weixin"),"weixin"),u(!1)})}catch(e){G.handleError(new t("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),u(!1)}});return Y=i,i})().finally(()=>{Q=null}),Q):(console.warn("当前不在微信环境中"),!1)},ee=e=>{const t=z();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},te=e=>{const t=z();t&&(t.updateAppMessageShareData?t.updateAppMessageShareData(e):t.onMenuShareAppMessage&&t.onMenuShareAppMessage(e))};class ne{static instance;isConfigured=!1;config=null;initPromise=null;constructor(){}static getInstance(){return ne.instance||(ne.instance=new ne),ne.instance}async init(e){return this.initPromise||(this.config=e,this.initPromise=Z(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return(this.isConfigured||Y)&&W()}getConfig(){return this.config}setShareData(e){this.isReady()?(ee(e),te(e)):console.warn("微信 SDK 未就绪")}}exports.ErrorHandler=n,exports.UniAppToolsError=t,exports.VERSION="4.0.0",exports.WechatSDK=ne,exports.areaList=S,exports.batchGetStorage=function(e){const t={};return e.forEach(e=>{t[e]=M(e)}),t},exports.batchSetStorage=function(e,t={}){let n=0;return Object.entries(e).forEach(([e,r])=>{L(e,r,t)&&n++}),n},exports.buildUrl=_,exports.checkWechatJSAPI=(e,n={})=>{const{timeoutMs:r=8e3}=n;return new Promise(n=>{const s=z();if(!s||"function"!=typeof s.checkJsApi)return void n(K(e,!1));let o=!1;const a=e=>{o||(o=!0,n(e))},i=setTimeout(()=>a(K(e,!1)),r);try{s.checkJsApi({jsApiList:e,success:t=>{clearTimeout(i),a({...K(e,!1),...t?.checkResult||{}})}})}catch(n){clearTimeout(i),G.handleError(new t("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${n instanceof Error?n.message:String(n)}`,"weixin"),"weixin"),a(K(e,!1))}})},exports.cleanExpiredStorage=function(){return D.cleanExpired()},exports.clearStorageSync=function(e){return e?D.remove(e):D.clear()},exports.clearSystemCache=()=>{c=null},exports.configWechatJSSDK=Z,exports.copyText=async function(e,t={}){const n={...I,...t};return e&&"string"==typeof e?e.length>1e4?(n.showToast&&T("复制内容过长",!1,"error"),!1):await r(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{n.showToast&&T(n.successMessage),t(!0)},fail:()=>{n.showToast&&T(n.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1:(n.showToast&&T("复制内容不能为空",!1,"error"),!1)},exports.debounce=w,exports.deepClone=E,exports.deepMerge=function(e,t){const n=E(e);return function e(t,n){for(const r in n)if(n.hasOwnProperty(r)){const s=n[r],o=t[r];s&&"object"==typeof s&&!Array.isArray(s)&&o&&"object"==typeof o&&!Array.isArray(o)?e(o,s):t[r]=E(s)}}(n,t),n},exports.extractUrlParts=function(e){try{const t=new URL(e,"http://localhost"),n=t.pathname,r={};return t.searchParams.forEach((e,t)=>{r[t]=e}),{path:n,params:r}}catch(n){return y.handleError(new t("EXTRACT_URL_PARTS_ERROR",`无效的URL: ${e}`,"utils"),"utils"),{path:"",params:{}}}},exports.getCurrentEnv=()=>{try{const e=uni.getAccountInfoSync();return{appId:e.miniProgram?.appId||"",version:e.miniProgram?.version||"",envVersion:e.miniProgram?.envVersion||"",accountInfo:e}}catch(e){return o.handleError(new t("GET_ACCOUNT_INFO_ERROR",`获取小程序账户信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),{appId:"",version:"",envVersion:"",accountInfo:{}}}},exports.getCurrentPageInfo=function(){try{const e=getCurrentPages();if(0===e.length)return null;const t=e[e.length-1];return{route:t.route||"",options:t.options||{}}}catch(e){return A("GET_CURRENT_PAGE_ERROR",`获取当前页面信息失败: ${e instanceof Error?e.message:String(e)}`),null}},exports.getH5UrlParams=e=>{try{if("undefined"==typeof window||!window.location)throw new Error("不在 H5 浏览器环境中");const t=new URLSearchParams(window.location.search),n={};return t.forEach((e,t)=>{try{n[t]=decodeURIComponent(e)}catch(r){n[t]=e}}),console.log("🔗 H5 URL参数解析:",{fullUrl:window.location.href,searchParams:window.location.search,parsedParams:n,paramName:e}),e?n.hasOwnProperty(e)?n[e]:null:n}catch(n){return y.handleError(new t("GET_H5_URL_PARAMS_ERROR",`获取H5 URL参数失败: ${n instanceof Error?n.message:String(n)}`,"utils"),"utils"),e?null:{}}},exports.getMenuButtonBoundingClientRect=g,exports.getNavHeight=()=>h().totalTopHeight,exports.getNavigationBarHeight=d,exports.getPageStack=function(){try{return getCurrentPages().map(e=>({route:e.route||"",options:e.options||{}}))}catch(e){return A("GET_PAGE_STACK_ERROR",`获取页面栈信息失败: ${e instanceof Error?e.message:String(e)}`),[]}},exports.getPlatform=f,exports.getStatusBarHeight=p,exports.getStorage=async function(e,t){return await r(()=>new Promise(n=>{n(M(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t},exports.getStorageInfo=function(){return D.getInfo()},exports.getStorageSync=M,exports.getTopBarMetrics=h,exports.getTopNavBarHeight=()=>{const e=h();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},exports.isWechat=W,exports.loadWechatJSSDK=X,exports.mergeObjects=function(e,t){if(!t||0===Object.keys(t).length)return e;const n={...e};for(const r of Object.keys(e))Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n},exports.navigateTo=v,exports.onCheckForUpdate=()=>{if(!l)try{const e=uni.getUpdateManager();l=!0,e.onCheckForUpdate(function(e){e.hasUpdate}),e.onUpdateReady(function(t){uni.showModal({title:"更新提示",content:"新版本已经准备好,是否重启应用?",showCancel:!0,cancelText:"稍后",confirmText:"立即重启",success(t){t.confirm&&e.applyUpdate()}})}),e.onUpdateFailed(function(e){o.handleError(new t("UPDATE_DOWNLOAD_FAILED","新版本下载失败","system"),"system"),uni.showModal({title:"更新失败",content:"新版本下载失败,请检查网络连接或稍后重试",showCancel:!1,confirmText:"知道了"})})}catch(e){o.handleError(new t("CHECK_UPDATE_ERROR",`版本更新检查失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system")}},exports.reLaunch=C,exports.redirectTo=async function(e){return new Promise(t=>{const n=_(e.url,e.params);uni.redirectTo({url:n,success:()=>t(!0),fail:e=>{A("REDIRECT_TO_FAILED",`页面重定向失败: ${n}`),t(!1)}})})},exports.safeAsync=r,exports.safeNavigateTo=async function(e,t=3){for(let n=0;n<t;n++){if(await v(e))return!0;n<t-1&&(await new Promise(e=>setTimeout(e,1e3*(n+1))),console.log(`[navigation] 第${n+2}次尝试跳转...`))}return!1},exports.safeSync=s,exports.selectAndUpload=B,exports.selectAndUploadImage=async function(e){return B({...e,type:"image"})},exports.setPageIcon=(e,t="image/x-icon")=>s(()=>{const n=f();if("h5"===n||"web"===n){if("undefined"!=typeof document){document.querySelectorAll('link[rel*="icon"]').forEach(e=>e.remove());const n=document.createElement("link");return n.rel="icon",n.type=t,n.href=e,document.head.appendChild(n),!0}}else console.warn("setPageIcon 仅在H5/Web平台有效");return!1},"system","SET_PAGE_ICON_ERROR",!1),exports.setPageTitle=e=>"string"!=typeof e?(console.warn("setPageTitle: title必须是字符串"),Promise.resolve(!1)):""===e.trim()?(console.warn("setPageTitle: title不能为空"),Promise.resolve(!1)):new Promise(n=>{try{uni.setNavigationBarTitle({title:e,success:()=>{n(!0)},fail:e=>{console.warn("设置页面标题失败:",e),n(!1)}})}catch(e){o.handleError(new t("SET_PAGE_TITLE_ERROR",`setPageTitle执行异常: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),n(!1)}}),exports.setStorage=async function(e,t,n={}){return await r(()=>new Promise(r=>{r(L(e,t,n))}),"localStorage","SET_STORAGE_ASYNC_ERROR")??!1},exports.setStorageSync=L,exports.shareToFriend=te,exports.shareToTimeline=ee,exports.switchTab=async function(e){return new Promise(t=>{uni.switchTab({url:e,success:()=>t(!0),fail:n=>{A("SWITCH_TAB_FAILED",`Tab切换失败: ${e}`),t(!1)}})})},exports.throttle=function(e,t,n={}){let r,s=null,o=0;const{leading:a=!0,trailing:i=!0}=n,c=function(...n){const c=Date.now();o||a||(o=c);const u=t-(c-o);return u<=0||u>t?(s&&(clearTimeout(s),s=null),o=c,r=e.apply(this,n)):!s&&i&&(s=setTimeout(()=>{o=a?Date.now():0,s=null,r=e.apply(this,n)},u)),r};return c.cancel=()=>{s&&(clearTimeout(s),s=null),o=0},c},exports.useBack=P,exports.useBackDebounced=O,exports.useBackOrHome=async function(e="",t={}){const n=getCurrentPages(),r=t.delta||1;if(n.length>r)return await P(e,t);const s=t.homePage||"pages/index/index",o=s.startsWith("/")?s:`/${s}`;return console.info(`[navigation] 页面栈深度不足,重定向到首页: ${o}`),await C({url:o,params:t.homeParams})},exports.useCascaderAreaData=R,exports.useRegions=function(){return e.useCascaderAreaData()},exports.useToast=T,exports.useTryCatch=function(e,t={}){return async(...n)=>{try{return{data:await e(...n),error:null}}catch(e){return t.onError?.(e),{data:null,error:e}}finally{t.onFinally?.()}}},exports.useWindowInfo=m,exports.weChatOfficialAccountPayment=(e,n,r)=>new Promise(o=>{s(()=>{if("undefined"==typeof window||!window.navigator)throw new Error("不在浏览器环境中,无法调用微信支付");if(!(e&&e.appId&&e.timeStamp&&e.nonceStr&&e.package&&e.paySign))throw new Error("微信支付配置参数不完整");function s(){try{window.WeixinJSBridge.invoke("getBrandWCPayRequest",e,function(e){console.log("🚀 ~ 微信支付结果:",e),"get_brand_wcpay_request:ok"===e.err_msg?(console.log("✅ 微信支付成功"),n?.(e),o(!0)):(console.warn("❌ 微信支付失败或取消:",e.err_msg),r?.(e),o(!1))})}catch(e){j.handleError(new t("WECHAT_PAY_INVOKE_ERROR",`调用微信支付接口失败: ${e instanceof Error?e.message:String(e)}`,"payment"),"payment");const n={err_msg:"get_brand_wcpay_request:fail",err_desc:e instanceof Error?e.message:"未知错误"};r?.(n),o(!1)}}if(void 0===window.WeixinJSBridge){const e=window.document;e.addEventListener?e.addEventListener("WeixinJSBridgeReady",s,!1):e.attachEvent&&(e.attachEvent("WeixinJSBridgeReady",s),e.attachEvent("onWeixinJSBridgeReady",s))}else s();return!0},"payment","WECHAT_PAY_ERROR",!1)||o(!1)});
@@ -1 +1 @@
1
- import{areaList as e,useCascaderAreaData as t}from"@vant/area-data";class n extends Error{code;module;timestamp;constructor(e,t,n){super(t),this.name="UniAppToolsError",this.code=e,this.module=n,this.timestamp=Date.now()}}class r{static instance;errorCallbacks=[];static getInstance(){return r.instance||(r.instance=new r),r.instance}onError(e){this.errorCallbacks.push(e)}handleError(e,t){const r={code:e instanceof n?e.code:"UNKNOWN_ERROR",message:e.message,module:e instanceof n?e.module:t,timestamp:e instanceof n?e.timestamp:Date.now(),stack:e.stack};console.error(`[${r.module}] ${r.code}: ${r.message}`,r),this.errorCallbacks.forEach(e=>{try{e(r)}catch(e){console.error("Error in error callback:",e)}})}createModuleErrorHandler(e){return(t,r,s)=>{const o=new n(t,r,e);return s&&(o.stack=s.stack),this.handleError(o,e),o}}}async function s(e,t,n="ASYNC_ERROR"){try{return await e()}catch(e){return r.getInstance().createModuleErrorHandler(t)(n,`异步操作失败: ${e instanceof Error?e.message:String(e)}`,e),null}}function o(e,t,n="SYNC_ERROR",s=null){try{return e()}catch(e){return r.getInstance().createModuleErrorHandler(t)(n,`同步操作失败: ${e instanceof Error?e.message:String(e)}`,e),s}}function a(){return"undefined"!=typeof performance&&"function"==typeof performance.now?performance.now():Date.now()}class i{static instance;metrics=new Map;completedMetrics=[];maxStoredMetrics=100;static getInstance(){return i.instance||(i.instance=new i),i.instance}start(e,t,n){const r={name:e,startTime:a(),module:t,metadata:n};this.metrics.set(e,r)}end(e){const t=this.metrics.get(e);return t?(t.endTime=a(),t.duration=t.endTime-t.startTime,this.metrics.delete(e),this.completedMetrics.push(t),this.completedMetrics.length>this.maxStoredMetrics&&this.completedMetrics.shift(),console.log(`[Performance] ${t.module}.${t.name}: ${t.duration?.toFixed(2)}ms`),t):(console.warn(`Performance metric "${e}" not found`),null)}getReport(){const e={},t={};this.completedMetrics.forEach(n=>{e[n.module]||(e[n.module]=[]),e[n.module].push(n);const r=`${n.module}.${n.name}`;t[r]||(t[r]={total:0,count:0}),t[r].total+=n.duration||0,t[r].count+=1});const n={};Object.entries(t).forEach(([e,t])=>{n[e]=t.total/t.count});const r=[...this.completedMetrics].sort((e,t)=>(t.duration||0)-(e.duration||0)).slice(0,10);return{byModule:e,slowest:r,average:n}}clear(){this.metrics.clear(),this.completedMetrics=[]}}function c(e){return function(t,n,r){const s=r.value;r.value=function(...r){const o=i.getInstance(),a=`${t.constructor.name}.${n}`;o.start(a,e,{args:r.length});try{const e=s.apply(this,r);return e instanceof Promise?e.finally(()=>{o.end(a)}):(o.end(a),e)}catch(e){throw o.end(a),e}}}}const l=r.getInstance();let u=null,m=null,f=null;const d=()=>{f=null},g=e=>"weixin"===e||"alipay"===e;let h=!1;const p=()=>{if(u)return u;let e="unknown";return e="weixin",e="web",e="app",e="alipay",e="h5",u="h5","h5"},w=(e=!0)=>e&&f?f:o(()=>{const t=uni.getWindowInfo();return e&&(f=t),t},"system","GET_WINDOW_INFO_ERROR",null),y=()=>{try{const e=uni.getAccountInfoSync();return{appId:e.miniProgram?.appId||"",version:e.miniProgram?.version||"",envVersion:e.miniProgram?.envVersion||"",accountInfo:e}}catch(e){return l.handleError(new n("GET_ACCOUNT_INFO_ERROR",`获取小程序账户信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),{appId:"",version:"",envVersion:"",accountInfo:{}}}},E=()=>{if(!h)try{const e=uni.getUpdateManager();h=!0,e.onCheckForUpdate(function(e){e.hasUpdate}),e.onUpdateReady(function(t){uni.showModal({title:"更新提示",content:"新版本已经准备好,是否重启应用?",showCancel:!0,cancelText:"稍后",confirmText:"立即重启",success(t){t.confirm&&e.applyUpdate()}})}),e.onUpdateFailed(function(e){l.handleError(new n("UPDATE_DOWNLOAD_FAILED","新版本下载失败","system"),"system"),uni.showModal({title:"更新失败",content:"新版本下载失败,请检查网络连接或稍后重试",showCancel:!1,confirmText:"知道了"})})}catch(e){l.handleError(new n("CHECK_UPDATE_ERROR",`版本更新检查失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system")}},R=()=>{if(null!==m)return m;try{const e=w();return m=e?.statusBarHeight||0,m}catch(e){return l.handleError(new n("GET_STATUS_BAR_HEIGHT_ERROR",`获取状态栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),0}},S=()=>{try{const e=p();return g(e)?uni.getMenuButtonBoundingClientRect():null}catch(e){return l.handleError(new n("GET_MENU_BUTTON_ERROR",`获取菜单按钮边界信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),null}},T=()=>{try{const e=p();if(g(e)){const e=S();return e?.height||44}return 44}catch(e){return l.handleError(new n("GET_NAVIGATION_BAR_HEIGHT_ERROR",`获取导航栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),44}},_=()=>{const e=p(),t=R(),n=T();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},v=()=>{const e=_();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},A=()=>_().totalTopHeight,P=e=>"string"!=typeof e?(console.warn("setPageTitle: title必须是字符串"),Promise.resolve(!1)):""===e.trim()?(console.warn("setPageTitle: title不能为空"),Promise.resolve(!1)):new Promise(t=>{try{uni.setNavigationBarTitle({title:e,success:()=>{t(!0)},fail:e=>{console.warn("设置页面标题失败:",e),t(!1)}})}catch(e){l.handleError(new n("SET_PAGE_TITLE_ERROR",`setPageTitle执行异常: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),t(!1)}}),O=(e,t="image/x-icon")=>o(()=>{const n=p();if("h5"===n||"web"===n){if("undefined"!=typeof document){document.querySelectorAll('link[rel*="icon"]').forEach(e=>e.remove());const n=document.createElement("link");return n.rel="icon",n.type=t,n.href=e,document.head.appendChild(n),!0}}else console.warn("setPageIcon 仅在H5/Web平台有效");return!1},"system","SET_PAGE_ICON_ERROR",!1),C=r.getInstance();function I(e){if(null===e||"object"!=typeof e)return e;try{if("undefined"!=typeof structuredClone)try{return structuredClone(e)}catch(e){}return JSON.parse(JSON.stringify(e))}catch(e){throw C.handleError(new n("DEEP_CLONE_ERROR",`深拷贝失败: ${e instanceof Error?e.message:String(e)}`,"utils"),"utils"),new Error(`深拷贝失败: ${e instanceof Error?e.message:String(e)}`)}}function $(e,t){const n=I(e);return function e(t,n){for(const r in n)if(n.hasOwnProperty(r)){const s=n[r],o=t[r];s&&"object"==typeof s&&!Array.isArray(s)&&o&&"object"==typeof o&&!Array.isArray(o)?e(o,s):t[r]=I(s)}}(n,t),n}function x(e,t){if(!t||0===Object.keys(t).length)return e;const n={...e};for(const r of Object.keys(e))Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n}function M(e,t,n=!1){let r,s=null;const o=function(...o){const a=n&&!s;return s&&clearTimeout(s),s=setTimeout(()=>{s=null,n||(r=e.apply(this,o))},t),a&&(r=e.apply(this,o)),r};return o.cancel=()=>{s&&(clearTimeout(s),s=null)},o}function b(e,t,n={}){let r,s=null,o=0;const{leading:a=!0,trailing:i=!0}=n,c=function(...n){const c=Date.now();o||a||(o=c);const l=t-(c-o);return l<=0||l>t?(s&&(clearTimeout(s),s=null),o=c,r=e.apply(this,n)):!s&&i&&(s=setTimeout(()=>{o=a?Date.now():0,s=null,r=e.apply(this,n)},l)),r};return c.cancel=()=>{s&&(clearTimeout(s),s=null),o=0},c}function U(e,t={}){return async(...n)=>{try{return{data:await e(...n),error:null}}catch(e){return t.onError?.(e),{data:null,error:e}}finally{t.onFinally?.()}}}const L=e=>{try{if("undefined"==typeof window||!window.location)throw new Error("不在 H5 浏览器环境中");const t=new URLSearchParams(window.location.search),n={};return t.forEach((e,t)=>{try{n[t]=decodeURIComponent(e)}catch(r){n[t]=e}}),console.log("🔗 H5 URL参数解析:",{fullUrl:window.location.href,searchParams:window.location.search,parsedParams:n,paramName:e}),e?n.hasOwnProperty(e)?n[e]:null:n}catch(t){return C.handleError(new n("GET_H5_URL_PARAMS_ERROR",`获取H5 URL参数失败: ${t instanceof Error?t.message:String(t)}`,"utils"),"utils"),e?null:{}}};function D(e){try{const t=new URL(e,"http://localhost"),n=t.pathname,r={};return t.searchParams.forEach((e,t)=>{r[t]=e}),{path:n,params:r}}catch(t){return C.handleError(new n("EXTRACT_URL_PARTS_ERROR",`无效的URL: ${e}`,"utils"),"utils"),{path:"",params:{}}}}const N=e,k=t;function H(){return t()}const F=(e="",t=!1,n="none",r=2e3)=>{uni.showToast({title:e,icon:n,mask:t,duration:r})},G=r.getInstance();function j(e,t){if(!t||0===Object.keys(t).length)return e;const n=Object.entries(t).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(String(t))}`).join("&");return e+(e.includes("?")?"&":"?")+n}async function B(e){return new Promise(t=>{const r=j(e.url,e.params);uni.navigateTo({url:r,animationType:e.animationType,animationDuration:e.animationDuration,events:e.events,success:()=>t(!0),fail:e=>{G.handleError(new n("NAVIGATE_TO_FAILED",`页面跳转失败: ${r}`,"navigation"),"navigation"),t(!1)}})})}async function J(e){return new Promise(t=>{const r=j(e.url,e.params);uni.redirectTo({url:r,success:()=>t(!0),fail:e=>{G.handleError(new n("REDIRECT_TO_FAILED",`页面重定向失败: ${r}`,"navigation"),"navigation"),t(!1)}})})}async function W(e="",t={}){return new Promise(r=>{const s=t.delta||1,o=t.timeout||5e3;if(getCurrentPages().length<=s)return console.warn(`[navigation] 无法返回${s}页,当前页面栈深度不足`),void r(!1);const a=setTimeout(()=>{console.warn("[navigation] 导航返回超时"),r(!1)},o);uni.navigateBack({delta:s,success:()=>{clearTimeout(a),setTimeout(()=>{try{const t=getCurrentPages();if(t.length>0){const n=t[t.length-1];n.$vm&&"function"==typeof n.$vm.init&&n.$vm.init(e)}r(!0)}catch(e){G.handleError(new n("PAGE_CALLBACK_ERROR",`页面回调执行失败: ${e instanceof Error?e.message:String(e)}`,"navigation"),"navigation"),r(!0)}},100)},fail:e=>{clearTimeout(a),G.handleError(new n("NAVIGATE_BACK_FAILED","导航返回失败","navigation"),"navigation"),r(!1)}})})}async function z(e="",t={}){const n=getCurrentPages(),r=t.delta||1;if(n.length>r)return await W(e,t);const s=t.homePage||"pages/index/index",o=s.startsWith("/")?s:`/${s}`;return console.info(`[navigation] 页面栈深度不足,重定向到首页: ${o}`),await V({url:o,params:t.homeParams})}const K=M(W,300);async function q(e){return new Promise(t=>{uni.switchTab({url:e,success:()=>t(!0),fail:r=>{G.handleError(new n("SWITCH_TAB_FAILED",`Tab切换失败: ${e}`,"navigation"),"navigation"),t(!1)}})})}async function V(e){return new Promise(t=>{const r=j(e.url,e.params);uni.reLaunch({url:r,success:()=>t(!0),fail:e=>{G.handleError(new n("RELAUNCH_FAILED",`重新启动失败: ${r}`,"navigation"),"navigation"),t(!1)}})})}function Y(){try{const e=getCurrentPages();if(0===e.length)return null;const t=e[e.length-1];return{route:t.route||"",options:t.options||{}}}catch(e){return G.handleError(new n("GET_CURRENT_PAGE_ERROR",`获取当前页面信息失败: ${e instanceof Error?e.message:String(e)}`,"navigation"),"navigation"),null}}function X(){try{return getCurrentPages().map(e=>({route:e.route||"",options:e.options||{}}))}catch(e){return G.handleError(new n("GET_PAGE_STACK_ERROR",`获取页面栈信息失败: ${e instanceof Error?e.message:String(e)}`,"navigation"),"navigation"),[]}}async function Q(e,t=3){for(let n=0;n<t;n++){if(await B(e))return!0;n<t-1&&(await new Promise(e=>setTimeout(e,1e3*(n+1))),console.log(`[navigation] 第${n+2}次尝试跳转...`))}return!1}const Z={showToast:!0,successMessage:"复制成功",failMessage:"复制失败",timeout:5e3};async function ee(e,t={}){const n=i.getInstance();n.start("copyText","clipboard",{textLength:e.length});const r={...Z,...t};if(!e||"string"!=typeof e)return r.showToast&&F("复制内容不能为空",!1,"error"),n.end("copyText"),!1;if(e.length>1e4)return r.showToast&&F("复制内容过长",!1,"error"),n.end("copyText"),!1;const o=await s(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{r.showToast&&F(r.successMessage),t(!0)},fail:()=>{r.showToast&&F(r.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1;return n.end("copyText"),o}const te=r.getInstance();class ne{static instance;cache=new Map;maxCacheSize=100;static getInstance(){return ne.instance||(ne.instance=new ne),ne.instance}isExpired(e){return!!e.ttl&&Date.now()-e.timestamp>e.ttl}set(e,t,r={}){try{if(!e||"string"!=typeof e)throw new Error("存储键不能为空");const n={value:t,timestamp:Date.now(),ttl:r.ttl},s=JSON.stringify(n);if(s.length>1048576)throw new Error("存储数据过大");if(uni.setStorageSync(e,s),this.cache.size>=this.maxCacheSize){const e=this.cache.keys().next().value;e&&this.cache.delete(e)}return this.cache.set(e,n),!0}catch(e){throw te.handleError(new n("SET_STORAGE_ERROR",`设置存储失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),e}}get(e,t){try{if(!e||"string"!=typeof e)return t;if(this.cache.has(e)){const n=this.cache.get(e);return this.isExpired(n)?(this.cache.delete(e),this.remove(e),t):n.value}const n=uni.getStorageSync(e);if(!n||"string"!=typeof n)return t;const r=JSON.parse(n);let s;return s=r&&"object"==typeof r&&"value"in r&&"timestamp"in r?r:{value:r,timestamp:Date.now()},this.isExpired(s)?(this.remove(e),t):(this.cache.set(e,s),s.value)}catch(n){return console.warn(`[localStorage] 获取存储失败 [${e}]:`,n),t}}remove(e){try{return!(!e||"string"!=typeof e||(uni.removeStorageSync(e),this.cache.delete(e),0))}catch(t){return te.handleError(new n("REMOVE_STORAGE_ERROR",`删除存储失败: ${e}`,"localStorage"),"localStorage"),!1}}clear(){try{return uni.clearStorageSync(),this.cache.clear(),!0}catch(e){return te.handleError(new n("CLEAR_STORAGE_ERROR","清空存储失败","localStorage"),"localStorage"),!1}}getInfo(){try{const e=uni.getStorageInfoSync();return{keys:e.keys||[],currentSize:e.currentSize||0,limitSize:e.limitSize||0}}catch(e){return te.handleError(new n("GET_STORAGE_INFO_ERROR",`获取存储信息失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),{keys:[],currentSize:0,limitSize:0}}}cleanExpired(){try{const e=this.getInfo();let t=0;return e.keys.forEach(e=>{void 0===this.get(e)&&t++}),t}catch(e){return te.handleError(new n("CLEAN_EXPIRED_ERROR",`清理过期数据失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),0}}}const re=ne.getInstance();function se(e,t,n={}){return re.set(e,t,n)}function oe(e,t){return re.get(e,t)}function ae(e){return e?re.remove(e):re.clear()}async function ie(e,t,n={}){return await s(()=>new Promise(r=>{r(se(e,t,n))}),"localStorage","SET_STORAGE_ASYNC_ERROR")??!1}async function ce(e,t){return await s(()=>new Promise(n=>{n(oe(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t}function le(){return re.getInfo()}function ue(){return re.cleanExpired()}function me(e,t={}){const n=i.getInstance();n.start("batchSetStorage","localStorage");let r=0;return Object.entries(e).forEach(([e,n])=>{se(e,n,t)&&r++}),n.end("batchSetStorage"),r}function fe(e){const t=i.getInstance();t.start("batchGetStorage","localStorage");const n={};return e.forEach(e=>{n[e]=oe(e)}),t.end("batchGetStorage"),n}function de(e){const t=e.lastIndexOf(".");if(-1!==t&&t!==e.length-1)return e.slice(t+1).toLowerCase()}function ge(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function he(e,t){return t&&e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function pe(e,t){if(0===e.length)return{success:!1,files:e,message:"未选择任何文件"};const{maxSelectFileSizeMB:n,extensions:r}=t;if(n&&e.some(e=>!he(e.size,n).valid))return{success:!1,files:e,message:`部分文件大小超过 ${n}MB 限制`};if(r&&r.length>0){const t=r.map(e=>e.toLowerCase());if(e.some(e=>!e.ext||!t.includes(e.ext)))return{success:!1,files:e,message:`存在不支持的文件类型,仅支持:${r.join(", ")}`}}return{success:!0,files:e}}async function we(e,t,n){const{url:r,maxUploadFileSizeMB:s,showToast:o=!0,beforeUpload:a}=t;if("function"==typeof a&&!await Promise.resolve(a(e)))return{file:e,success:!1,message:"已取消上传"};if(!r){const t="上传地址不能为空";return o&&F(t,!1,"error"),Promise.resolve({file:e,success:!1,message:t})}const i=he(e.size,s);return i.valid?"h5"===e.platform&&e.raw instanceof File?function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:l="上传失败",onProgress:u,uploadTimeoutMs:m,autoRevokeObjectURL:f=!1}=t;return new Promise(t=>{const d=e.raw;if(!(d&&d instanceof File)){const n="H5 环境缺少原生文件对象";return i&&F(n,!1,"none"),void t({file:e,success:!1,message:n})}const g=f&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&"string"==typeof e.path&&e.path.startsWith("blob:"),h=()=>{if(g)try{URL.revokeObjectURL(e.path)}catch{}},p=new XMLHttpRequest,w=new FormData;w.append(s,d,e.name),o&&Object.keys(o).forEach(e=>{w.append(e,String(o[e]))}),u&&p.upload.addEventListener("progress",t=>{if(t.lengthComputable){const n=Math.round(t.loaded/t.total*100);u(e,n)}}),p.addEventListener("load",()=>{const r=p.status,s=r>=200&&r<300;let o=p.responseText;try{o=JSON.parse(p.responseText)}catch{}if(s)i&&1===n&&F(c,!1,"none"),h(),t({file:e,success:!0,statusCode:r,data:o});else{const n=`上传失败,状态码:${r}`;i&&F(n,!1,"none"),h(),t({file:e,success:!1,statusCode:r,data:o,message:n})}}),p.addEventListener("error",()=>{const n=l;i&&F(n,!1,"none"),h(),t({file:e,success:!1,message:n})}),p.addEventListener("timeout",()=>{const n=m?`上传超时(${m}ms)`:"上传超时";i&&F(n,!1,"none"),h(),t({file:e,success:!1,message:n})}),p.addEventListener("abort",()=>{h(),t({file:e,success:!1,message:"上传已取消"})}),p.open("POST",r),"number"==typeof m&&m>0&&(p.timeout=m),a&&Object.keys(a).forEach(e=>{p.setRequestHeader(e,a[e])}),p.send(w)})}(e,t,n):function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:l="上传失败",onProgress:u,uploadTimeoutMs:m}=t,f="undefined"==typeof uni?null:uni;if(!f||"function"!=typeof f.uploadFile){const t="当前环境不支持文件上传";return i&&F(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(t=>{let d=!1,g=null;const h=e=>{d||(d=!0,g&&(clearTimeout(g),g=null),t(e))};let p=null;"number"==typeof m&&m>0&&(g=setTimeout(()=>{try{p&&"function"==typeof p.abort&&p.abort()}catch{}const t=`上传超时(${m}ms)`;i&&F(t,!1,"none"),h({file:e,success:!1,message:t})},m)),p=f.uploadFile({url:r,filePath:e.path,name:s,formData:o,header:a,success:t=>{let r=t.data;try{r=JSON.parse(t.data)}catch{}const s=t.statusCode;if(s>=200&&s<300)i&&1===n&&F(c,!1,"none"),h({file:e,success:!0,statusCode:s,data:r});else{const t=`上传失败,状态码:${s}`;i&&F(t,!1,"none"),h({file:e,success:!1,statusCode:s,data:r,message:t})}},fail:t=>{const n=t?.errMsg||l;i&&F(n,!1,"none"),h({file:e,success:!1,message:n})}}),u&&p&&"function"==typeof p.onProgressUpdate&&p.onProgressUpdate(t=>{u(e,t.progress)})})}(e,t,n):(o&&i.message&&F(i.message,!1,"error"),Promise.resolve({file:e,success:!1,message:i.message}))}async function ye(e){const{showToast:t=!0,failMessage:n="选择文件失败"}=e;try{const r=await async function(e){return"undefined"!=typeof document&&"undefined"!=typeof window?function(e){const{type:t="image",count:n=1,extensions:r}=e;return new Promise(s=>{if("undefined"==typeof document)return void s({success:!1,files:[],message:"当前环境不支持文件选择"});const o=document.createElement("input");o.type="file",o.multiple=n>1,"image"===t?o.accept="image/*":r&&r.length>0&&(o.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(",")),o.onchange=t=>{const n=t.target,r=n?.files;if(!r||0===r.length)return s({success:!1,files:[],message:"用户取消选择"}),void document.body.removeChild(o);const a=pe(Array.from(r).map((e,t)=>{const n=de(e.name),r=URL.createObjectURL(e);return{id:ge(t),name:e.name,size:e.size,path:r,mimeType:e.type,ext:n,source:"file",platform:"h5",raw:e}}),e);s(a),document.body.removeChild(o)},o.style.display="none",document.body.appendChild(o),o.click()})}(e):function(e){const{type:t="image",count:n=1}=e;return new Promise(r=>{const s="undefined"==typeof uni?null:uni;if(!s)return void r({success:!1,files:[],message:"当前环境不支持文件选择"});const o=e=>{const t=function(e){const t=(e||"").trim();if(!t)return"选择文件失败";const n=t.toLowerCase();return n.includes("fail cancel")||n.includes("cancel")?"用户取消选择":/[\u4e00-\u9fff]/.test(t)?t:"选择文件失败"}(e?.errMsg);r({success:!1,files:[],message:t})},a=function(){let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}();"image"!==t||"function"!=typeof s.chooseImage?"function"!=typeof s.chooseMessageFile?"function"!=typeof s.chooseFile?r({success:!1,files:[],message:"当前平台不支持文件选择"}):s.chooseFile({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=de(e.path);return{id:ge(t),name:`file_${t}`,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(pe(n,e))},fail:o}):s.chooseMessageFile({count:n,type:"all",success:t=>{const n=t.tempFiles.map((e,t)=>{const n=de(e.name||e.path);return{id:ge(t),name:e.name,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(pe(n,e))},fail:o}):s.chooseImage({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=de(e.path);return{id:ge(t),name:`image_${t}`,size:e.size,path:e.path,ext:n,source:"album",platform:a,raw:e}});r(pe(n,e))},fail:o})})}(e)}(e);if(!r.success){const e=r.message||n;return t&&e&&F(e,!1,"none"),[{file:null,success:!1,message:e}]}const s=r.files;if(0===s.length)return[];const o=s.length;return await async function(e,t,n){const r=new Array(e.length),s=t.concurrency&&t.concurrency>0?Math.min(t.concurrency,e.length):e.length;let o=0;const a=async()=>{for(;;){const s=o;if(s>=e.length)break;o+=1;const a=e[s],i=await we(a,t,n);r[s]=i}},i=[];for(let e=0;e<s;e+=1)i.push(a());return await Promise.all(i),r}(s,e,o)}catch(e){const r=n;return t&&r&&F(r,!1,"none"),[{file:null,success:!1,message:r}]}}async function Ee(e){return ye({...e,type:"image"})}const Re=r.getInstance(),Se=(e,t,r)=>{const s=i.getInstance();return s.start("weChatOfficialAccountPayment","payment"),new Promise(a=>{o(()=>{if("undefined"==typeof window||!window.navigator)throw new Error("不在浏览器环境中,无法调用微信支付");if(!(e&&e.appId&&e.timeStamp&&e.nonceStr&&e.package&&e.paySign))throw new Error("微信支付配置参数不完整");function o(){try{window.WeixinJSBridge.invoke("getBrandWCPayRequest",e,function(e){s.end("weChatOfficialAccountPayment"),console.log("🚀 ~ 微信支付结果:",e),"get_brand_wcpay_request:ok"===e.err_msg?(console.log("✅ 微信支付成功"),t?.(e),a(!0)):(console.warn("❌ 微信支付失败或取消:",e.err_msg),r?.(e),a(!1))})}catch(e){s.end("weChatOfficialAccountPayment"),Re.handleError(new n("WECHAT_PAY_INVOKE_ERROR",`调用微信支付接口失败: ${e instanceof Error?e.message:String(e)}`,"payment"),"payment");const t={err_msg:"get_brand_wcpay_request:fail",err_desc:e instanceof Error?e.message:"未知错误"};r?.(t),a(!1)}}if(void 0===window.WeixinJSBridge){const e=window.document;e.addEventListener?e.addEventListener("WeixinJSBridgeReady",o,!1):e.attachEvent&&(e.attachEvent("WeixinJSBridgeReady",o),e.attachEvent("onWeixinJSBridgeReady",o))}else o();return!0},"payment","WECHAT_PAY_ERROR",!1)||(s.end("weChatOfficialAccountPayment"),a(!1))})},Te=r.getInstance(),_e=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),ve=()=>"undefined"!=typeof window&&"undefined"!=typeof document,Ae=()=>ve()&&_e()&&window.wx||null;let Pe=!1,Oe=null;const Ce=(e={})=>{const{timeoutMs:t=1e4}=e;if(Pe||ve()&&window.wx)return Pe=!0,Promise.resolve(!0);if(!ve())return Promise.resolve(!1);if(Oe)return Oe;const n=e.cdnUrls&&e.cdnUrls.length>0?e.cdnUrls:["https://res.wx.qq.com/open/js/jweixin-1.6.0.js","https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"];return Oe=new Promise(e=>{let r=!1,s=null,o=null,a=0;const i=t=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&o.parentNode&&o.parentNode.removeChild(o),t&&(Pe=!0),Oe=null,e(t))},c=()=>{if(a>=n.length)return void i(!1);if(!document.head)return void i(!1);const e=n[a];a+=1;const t=document.createElement("script");o=t,t.src=e,t.async=!0,t.onload=()=>i(!0),t.onerror=()=>{t.parentNode&&t.parentNode.removeChild(t),o=null,c()},document.head.appendChild(t)};s=setTimeout(()=>{i(!1)},t),c()}),Oe};let Ie=null;const $e=async(e,t={})=>{const{timeoutMs:r=1e4}=t;if(!_e())return console.warn("当前不在微信环境中"),!1;if(Ie)return Ie;if(!await Ce({timeoutMs:r}))return Te.handleError(new n("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;if(!ve())return!1;const s=window.wx;return!!s&&(Ie=new Promise(t=>{let o=!1,a=null;const i=e=>{o||(o=!0,a&&(clearTimeout(a),a=null),Ie=null,t(e))};a=setTimeout(()=>i(!1),r);try{s.config({debug:e.debug||!1,appId:e.appId,timestamp:e.timestamp,nonceStr:e.nonceStr,signature:e.signature,jsApiList:e.jsApiList}),s.ready(()=>{console.log("微信 JS-SDK 初始化完成"),i(!0)}),s.error(e=>{Te.handleError(new n("WECHAT_JSSDK_CONFIG_ERROR",`微信 JS-SDK 配置错误: ${JSON.stringify(e)}`,"weixin"),"weixin"),i(!1)})}catch(e){Te.handleError(new n("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),i(!1)}}),Ie)},xe=(e,t={})=>{const{timeoutMs:r=8e3}=t;return new Promise(t=>{const s=Ae();if(!s||"function"!=typeof s.checkJsApi)return void t({});let o=!1;const a=e=>{o||(o=!0,t(e))},i=setTimeout(()=>a({}),r);try{s.checkJsApi({jsApiList:e,success:e=>{clearTimeout(i),a(e?.checkResult||{})}})}catch(e){clearTimeout(i),Te.handleError(new n("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),a({})}})},Me=e=>{const t=Ae();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},be=e=>{const t=Ae();t&&(t.updateAppMessageShareData?t.updateAppMessageShareData(e):t.onMenuShareAppMessage&&t.onMenuShareAppMessage(e))};class Ue{static instance;isConfigured=!1;config=null;initPromise=null;constructor(){}static getInstance(){return Ue.instance||(Ue.instance=new Ue),Ue.instance}async init(e){return this.initPromise||(this.config=e,this.initPromise=$e(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return this.isConfigured&&_e()}getConfig(){return this.config}setShareData(e){this.isReady()?(Me(e),be(e)):console.warn("微信 SDK 未就绪")}}const Le="3.1.0",De={info:0,warn:1,error:2};function Ne(e={}){const{enablePerformanceMonitor:t=!1,enableErrorHandler:n=!0,onError:s=null,performanceReportInterval:o=0,showInitMessage:a=!1,silent:c=!1,logLevel:l="warn",enablePerformanceLog:u=!1}=e,m=De[l]||De.warn,f=(...e)=>{!c&&m<=De.info&&console.log(...e)},d=(...e)=>{!c&&m<=De.warn&&console.warn(...e)};if(n){const e=r.getInstance();"function"==typeof s?e.onError(s):e.onError(e=>{((...e)=>{!c&&m<=De.error&&console.error(...e)})(`[UniAppTools] ${e.module} - ${e.code}: ${e.message}`,e)})}if(t){const e=i.getInstance();u?o>0?(f("[UniAppTools] 性能监控已启用"),f("[UniAppTools] - 模式1: 每次操作结束时会输出单次性能日志"),f(`[UniAppTools] - 模式2: 每 ${o}ms 输出完整性能报告`),setInterval(()=>{const t=e.getReport();t.slowest.length>0?f("[UniAppTools] 性能报告:",t):f("[UniAppTools] 性能报告: 暂无性能数据(请调用工具函数以产生性能记录)")},o)):(f("[UniAppTools] 性能监控已启用(仅单次日志模式)"),f("[UniAppTools] 提示: 每次操作结束时会输出单次性能日志"),d("[UniAppTools] 警告: 未设置 performanceReportInterval,定期性能报告不会输出"),d("[UniAppTools] 如需启用定期报告,请设置 performanceReportInterval 为大于 0 的毫秒数(如: 30000 表示每30秒)")):f("[UniAppTools] 性能监控已启用(静默模式 - 不输出日志)")}if(f(`[UniAppTools] v${Le} 初始化完成`),a&&"undefined"!=typeof uni)try{uni.showToast({title:`工具库v${Le}已就绪`,icon:"none",duration:2e3})}catch(e){}}export{r as ErrorHandler,i as PerformanceMonitor,n as UniAppToolsError,Le as VERSION,Ue as WechatSDK,N as areaList,fe as batchGetStorage,me as batchSetStorage,xe as checkWechatJSAPI,ue as cleanExpiredStorage,ae as clearStorageSync,d as clearSystemCache,$e as configWechatJSSDK,ee as copyText,M as debounce,I as deepClone,$ as deepMerge,D as extractUrlParts,y as getCurrentEnv,Y as getCurrentPageInfo,L as getH5UrlParams,S as getMenuButtonBoundingClientRect,A as getNavHeight,T as getNavigationBarHeight,X as getPageStack,p as getPlatform,R as getStatusBarHeight,ce as getStorage,le as getStorageInfo,oe as getStorageSync,_ as getTopBarMetrics,v as getTopNavBarHeight,Ne as initUniAppTools,_e as isWechat,Ce as loadWechatJSSDK,c as measurePerformance,x as mergeObjects,B as navigateTo,E as onCheckForUpdate,V as reLaunch,J as redirectTo,s as safeAsync,Q as safeNavigateTo,o as safeSync,ye as selectAndUpload,Ee as selectAndUploadImage,O as setPageIcon,P as setPageTitle,ie as setStorage,se as setStorageSync,be as shareToFriend,Me as shareToTimeline,q as switchTab,b as throttle,W as useBack,K as useBackDebounced,z as useBackOrHome,k as useCascaderAreaData,H as useRegions,F as useToast,U as useTryCatch,w as useWindowInfo,Se as weChatOfficialAccountPayment};
1
+ import{areaList as e,useCascaderAreaData as t}from"@vant/area-data";class n extends Error{code;module;timestamp;constructor(e,t,n){super(t),this.name="UniAppToolsError",this.code=e,this.module=n,this.timestamp=Date.now()}}class r{static instance;errorCallbacks=[];static getInstance(){return r.instance||(r.instance=new r),r.instance}onError(e){this.errorCallbacks.push(e)}handleError(e,t){const r={code:e instanceof n?e.code:"UNKNOWN_ERROR",message:e.message,module:e instanceof n?e.module:t,timestamp:e instanceof n?e.timestamp:Date.now(),stack:e.stack};console.error(`[${r.module}] ${r.code}: ${r.message}`,r),this.errorCallbacks.forEach(e=>{try{e(r)}catch(e){console.error("Error in error callback:",e)}})}createModuleErrorHandler(e){return(t,r,s)=>{const o=new n(t,r,e);return s&&(o.stack=s.stack),this.handleError(o,e),o}}}async function s(e,t,n="ASYNC_ERROR"){try{return await e()}catch(e){return r.getInstance().createModuleErrorHandler(t)(n,`异步操作失败: ${e instanceof Error?e.message:String(e)}`,e),null}}function o(e,t,n="SYNC_ERROR",s=null){try{return e()}catch(e){return r.getInstance().createModuleErrorHandler(t)(n,`同步操作失败: ${e instanceof Error?e.message:String(e)}`,e),s}}const a=r.getInstance();let i=null,c=null,u=null;const l=()=>{u=null},f=e=>"weixin"===e||"alipay"===e;let m=!1;const g=()=>{if(i)return i;let e="unknown";return e="weixin",e="web",e="app",e="alipay",e="h5",i="h5","h5"},d=(e=!0)=>e&&u?u:o(()=>{const t=uni.getWindowInfo();return e&&(u=t),t},"system","GET_WINDOW_INFO_ERROR",null),h=()=>{try{const e=uni.getAccountInfoSync();return{appId:e.miniProgram?.appId||"",version:e.miniProgram?.version||"",envVersion:e.miniProgram?.envVersion||"",accountInfo:e}}catch(e){return a.handleError(new n("GET_ACCOUNT_INFO_ERROR",`获取小程序账户信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),{appId:"",version:"",envVersion:"",accountInfo:{}}}},p=()=>{if(!m)try{const e=uni.getUpdateManager();m=!0,e.onCheckForUpdate(function(e){e.hasUpdate}),e.onUpdateReady(function(t){uni.showModal({title:"更新提示",content:"新版本已经准备好,是否重启应用?",showCancel:!0,cancelText:"稍后",confirmText:"立即重启",success(t){t.confirm&&e.applyUpdate()}})}),e.onUpdateFailed(function(e){a.handleError(new n("UPDATE_DOWNLOAD_FAILED","新版本下载失败","system"),"system"),uni.showModal({title:"更新失败",content:"新版本下载失败,请检查网络连接或稍后重试",showCancel:!1,confirmText:"知道了"})})}catch(e){a.handleError(new n("CHECK_UPDATE_ERROR",`版本更新检查失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system")}},y=()=>{if(null!==c)return c;try{const e=d();return c=e?.statusBarHeight||0,c}catch(e){return a.handleError(new n("GET_STATUS_BAR_HEIGHT_ERROR",`获取状态栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),0}},E=()=>{try{const e=g();return f(e)?uni.getMenuButtonBoundingClientRect():null}catch(e){return a.handleError(new n("GET_MENU_BUTTON_ERROR",`获取菜单按钮边界信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),null}},w=()=>{try{const e=g();if(f(e)){const e=E();return e?.height||44}return 44}catch(e){return a.handleError(new n("GET_NAVIGATION_BAR_HEIGHT_ERROR",`获取导航栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),44}},R=()=>{const e=g(),t=y(),n=w();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},S=()=>{const e=R();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},T=()=>R().totalTopHeight,_=e=>"string"!=typeof e?(console.warn("setPageTitle: title必须是字符串"),Promise.resolve(!1)):""===e.trim()?(console.warn("setPageTitle: title不能为空"),Promise.resolve(!1)):new Promise(t=>{try{uni.setNavigationBarTitle({title:e,success:()=>{t(!0)},fail:e=>{console.warn("设置页面标题失败:",e),t(!1)}})}catch(e){a.handleError(new n("SET_PAGE_TITLE_ERROR",`setPageTitle执行异常: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),t(!1)}}),A=(e,t="image/x-icon")=>o(()=>{const n=g();if("h5"===n||"web"===n){if("undefined"!=typeof document){document.querySelectorAll('link[rel*="icon"]').forEach(e=>e.remove());const n=document.createElement("link");return n.rel="icon",n.type=t,n.href=e,document.head.appendChild(n),!0}}else console.warn("setPageIcon 仅在H5/Web平台有效");return!1},"system","SET_PAGE_ICON_ERROR",!1),O=r.getInstance();function v(e){if(null===e||"object"!=typeof e)return e;try{if("undefined"!=typeof structuredClone)try{return structuredClone(e)}catch(e){}return JSON.parse(JSON.stringify(e))}catch(e){throw O.handleError(new n("DEEP_CLONE_ERROR",`深拷贝失败: ${e instanceof Error?e.message:String(e)}`,"utils"),"utils"),new Error(`深拷贝失败: ${e instanceof Error?e.message:String(e)}`)}}function P(e,t){const n=v(e);return function e(t,n){for(const r in n)if(n.hasOwnProperty(r)){const s=n[r],o=t[r];s&&"object"==typeof s&&!Array.isArray(s)&&o&&"object"==typeof o&&!Array.isArray(o)?e(o,s):t[r]=v(s)}}(n,t),n}function C(e,t){if(!t||0===Object.keys(t).length)return e;const n={...e};for(const r of Object.keys(e))Object.prototype.hasOwnProperty.call(t,r)&&(n[r]=t[r]);return n}function I(e,t,n=!1){let r,s=null;const o=function(...o){const a=n&&!s;return s&&clearTimeout(s),s=setTimeout(()=>{s=null,n||(r=e.apply(this,o))},t),a&&(r=e.apply(this,o)),r};return o.cancel=()=>{s&&(clearTimeout(s),s=null)},o}function $(e,t,n={}){let r,s=null,o=0;const{leading:a=!0,trailing:i=!0}=n,c=function(...n){const c=Date.now();o||a||(o=c);const u=t-(c-o);return u<=0||u>t?(s&&(clearTimeout(s),s=null),o=c,r=e.apply(this,n)):!s&&i&&(s=setTimeout(()=>{o=a?Date.now():0,s=null,r=e.apply(this,n)},u)),r};return c.cancel=()=>{s&&(clearTimeout(s),s=null),o=0},c}function x(e,t={}){return async(...n)=>{try{return{data:await e(...n),error:null}}catch(e){return t.onError?.(e),{data:null,error:e}}finally{t.onFinally?.()}}}const L=e=>{try{if("undefined"==typeof window||!window.location)throw new Error("不在 H5 浏览器环境中");const t=new URLSearchParams(window.location.search),n={};return t.forEach((e,t)=>{try{n[t]=decodeURIComponent(e)}catch(r){n[t]=e}}),console.log("🔗 H5 URL参数解析:",{fullUrl:window.location.href,searchParams:window.location.search,parsedParams:n,paramName:e}),e?n.hasOwnProperty(e)?n[e]:null:n}catch(t){return O.handleError(new n("GET_H5_URL_PARAMS_ERROR",`获取H5 URL参数失败: ${t instanceof Error?t.message:String(t)}`,"utils"),"utils"),e?null:{}}};function M(e){try{const t=new URL(e,"http://localhost"),n=t.pathname,r={};return t.searchParams.forEach((e,t)=>{r[t]=e}),{path:n,params:r}}catch(t){return O.handleError(new n("EXTRACT_URL_PARTS_ERROR",`无效的URL: ${e}`,"utils"),"utils"),{path:"",params:{}}}}const b=e,D=t;function N(){return t()}const U=(e="",t=!1,n="none",r=2e3)=>{uni.showToast({title:e,icon:n,mask:t,duration:r})},k=r.getInstance();function H(e,t){if(!t||0===Object.keys(t).length)return e;const n=Object.entries(t).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(String(t))}`).join("&");return e+(e.includes("?")?"&":"?")+n}function F(e,t){k.handleError(new n(e,t,"navigation"),"navigation")}async function j(e){return new Promise(t=>{const n=H(e.url,e.params);uni.navigateTo({url:n,animationType:e.animationType,animationDuration:e.animationDuration,events:e.events,success:()=>t(!0),fail:e=>{F("NAVIGATE_TO_FAILED",`页面跳转失败: ${n}`),t(!1)}})})}async function G(e){return new Promise(t=>{const n=H(e.url,e.params);uni.redirectTo({url:n,success:()=>t(!0),fail:e=>{F("REDIRECT_TO_FAILED",`页面重定向失败: ${n}`),t(!1)}})})}async function B(e){return new Promise(t=>{const n=H(e.url,e.params);uni.reLaunch({url:n,success:()=>t(!0),fail:e=>{F("RELAUNCH_FAILED",`重新启动失败: ${n}`),t(!1)}})})}async function J(e){return new Promise(t=>{uni.switchTab({url:e,success:()=>t(!0),fail:n=>{F("SWITCH_TAB_FAILED",`Tab切换失败: ${e}`),t(!1)}})})}async function W(e="",t={}){return new Promise(n=>{const r=t.delta||1,s=t.timeout||5e3;if(getCurrentPages().length<=r)return console.warn(`[navigation] 无法返回${r}页,当前页面栈深度不足`),void n(!1);const o=setTimeout(()=>{console.warn("[navigation] 导航返回超时"),n(!1)},s);uni.navigateBack({delta:r,success:()=>{clearTimeout(o),setTimeout(()=>{try{const t=getCurrentPages();if(t.length>0){const n=t[t.length-1];n.$vm&&"function"==typeof n.$vm.init&&n.$vm.init(e)}n(!0)}catch(e){F("PAGE_CALLBACK_ERROR",`页面回调执行失败: ${e instanceof Error?e.message:String(e)}`),n(!0)}},100)},fail:e=>{clearTimeout(o),F("NAVIGATE_BACK_FAILED","导航返回失败"),n(!1)}})})}async function z(e,t=3){for(let n=0;n<t;n++){if(await j(e))return!0;n<t-1&&(await new Promise(e=>setTimeout(e,1e3*(n+1))),console.log(`[navigation] 第${n+2}次尝试跳转...`))}return!1}async function K(e="",t={}){const n=getCurrentPages(),r=t.delta||1;if(n.length>r)return await W(e,t);const s=t.homePage||"pages/index/index",o=s.startsWith("/")?s:`/${s}`;return console.info(`[navigation] 页面栈深度不足,重定向到首页: ${o}`),await B({url:o,params:t.homeParams})}const q=I(W,300);function V(){try{const e=getCurrentPages();if(0===e.length)return null;const t=e[e.length-1];return{route:t.route||"",options:t.options||{}}}catch(e){return F("GET_CURRENT_PAGE_ERROR",`获取当前页面信息失败: ${e instanceof Error?e.message:String(e)}`),null}}function Y(){try{return getCurrentPages().map(e=>({route:e.route||"",options:e.options||{}}))}catch(e){return F("GET_PAGE_STACK_ERROR",`获取页面栈信息失败: ${e instanceof Error?e.message:String(e)}`),[]}}const X={showToast:!0,successMessage:"复制成功",failMessage:"复制失败",timeout:5e3};async function Q(e,t={}){const n={...X,...t};return e&&"string"==typeof e?e.length>1e4?(n.showToast&&U("复制内容过长",!1,"error"),!1):await s(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{n.showToast&&U(n.successMessage),t(!0)},fail:()=>{n.showToast&&U(n.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1:(n.showToast&&U("复制内容不能为空",!1,"error"),!1)}const Z=r.getInstance();class ee{static instance;cache=new Map;maxCacheSize=100;static getInstance(){return ee.instance||(ee.instance=new ee),ee.instance}isExpired(e){return!!e.ttl&&Date.now()-e.timestamp>e.ttl}set(e,t,r={}){try{if(!e||"string"!=typeof e)throw new Error("存储键不能为空");const n={value:t,timestamp:Date.now(),ttl:r.ttl},s=JSON.stringify(n);if(s.length>1048576)throw new Error("存储数据过大");if(uni.setStorageSync(e,s),this.cache.size>=this.maxCacheSize){const e=this.cache.keys().next().value;e&&this.cache.delete(e)}return this.cache.set(e,n),!0}catch(e){throw Z.handleError(new n("SET_STORAGE_ERROR",`设置存储失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),e}}get(e,t){try{if(!e||"string"!=typeof e)return t;if(this.cache.has(e)){const n=this.cache.get(e);return this.isExpired(n)?(this.cache.delete(e),this.remove(e),t):n.value}const n=uni.getStorageSync(e);if(!n||"string"!=typeof n)return t;const r=JSON.parse(n);let s;return s=r&&"object"==typeof r&&"value"in r&&"timestamp"in r?r:{value:r,timestamp:Date.now()},this.isExpired(s)?(this.remove(e),t):(this.cache.set(e,s),s.value)}catch(n){return console.warn(`[localStorage] 获取存储失败 [${e}]:`,n),t}}remove(e){try{return!(!e||"string"!=typeof e||(uni.removeStorageSync(e),this.cache.delete(e),0))}catch(t){return Z.handleError(new n("REMOVE_STORAGE_ERROR",`删除存储失败: ${e}`,"localStorage"),"localStorage"),!1}}clear(){try{return uni.clearStorageSync(),this.cache.clear(),!0}catch(e){return Z.handleError(new n("CLEAR_STORAGE_ERROR","清空存储失败","localStorage"),"localStorage"),!1}}getInfo(){try{const e=uni.getStorageInfoSync();return{keys:e.keys||[],currentSize:e.currentSize||0,limitSize:e.limitSize||0}}catch(e){return Z.handleError(new n("GET_STORAGE_INFO_ERROR",`获取存储信息失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),{keys:[],currentSize:0,limitSize:0}}}cleanExpired(){try{const e=this.getInfo();let t=0;return e.keys.forEach(e=>{void 0===this.get(e)&&t++}),t}catch(e){return Z.handleError(new n("CLEAN_EXPIRED_ERROR",`清理过期数据失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),0}}}const te=ee.getInstance();function ne(e,t,n={}){return te.set(e,t,n)}function re(e,t){return te.get(e,t)}function se(e){return e?te.remove(e):te.clear()}async function oe(e,t,n={}){return await s(()=>new Promise(r=>{r(ne(e,t,n))}),"localStorage","SET_STORAGE_ASYNC_ERROR")??!1}async function ae(e,t){return await s(()=>new Promise(n=>{n(re(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t}function ie(){return te.getInfo()}function ce(){return te.cleanExpired()}function ue(e,t={}){let n=0;return Object.entries(e).forEach(([e,r])=>{ne(e,r,t)&&n++}),n}function le(e){const t={};return e.forEach(e=>{t[e]=re(e)}),t}function fe(e){const t=e.lastIndexOf(".");if(-1!==t&&t!==e.length-1)return e.slice(t+1).toLowerCase()}function me(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function ge(e,t){return t&&e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function de(e,t){if(0===e.length)return{success:!1,files:e,message:"未选择任何文件"};const{maxSelectFileSizeMB:n,extensions:r}=t;if(n&&e.some(e=>!ge(e.size,n).valid))return{success:!1,files:e,message:`部分文件大小超过 ${n}MB 限制`};if(r&&r.length>0){const t=r.map(e=>e.toLowerCase());if(e.some(e=>!e.ext||!t.includes(e.ext)))return{success:!1,files:e,message:`存在不支持的文件类型,仅支持:${r.join(", ")}`}}return{success:!0,files:e}}async function he(e,t,n){const{url:r,maxUploadFileSizeMB:s,showToast:o=!0,beforeUpload:a}=t;if("function"==typeof a&&!await Promise.resolve(a(e)))return{file:e,success:!1,message:"已取消上传"};if(!r){const t="上传地址不能为空";return o&&U(t,!1,"error"),Promise.resolve({file:e,success:!1,message:t})}const i=ge(e.size,s);return i.valid?"h5"===e.platform&&e.raw instanceof File?function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:u="上传失败",onProgress:l,uploadTimeoutMs:f,autoRevokeObjectURL:m=!1}=t;return new Promise(t=>{const g=e.raw;if(!(g&&g instanceof File)){const n="H5 环境缺少原生文件对象";return i&&U(n,!1,"none"),void t({file:e,success:!1,message:n})}const d=m&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&"string"==typeof e.path&&e.path.startsWith("blob:"),h=()=>{if(d)try{URL.revokeObjectURL(e.path)}catch{}},p=new XMLHttpRequest,y=new FormData;y.append(s,g,e.name),o&&Object.keys(o).forEach(e=>{y.append(e,String(o[e]))}),l&&p.upload.addEventListener("progress",t=>{if(t.lengthComputable){const n=Math.round(t.loaded/t.total*100);l(e,n)}}),p.addEventListener("load",()=>{const r=p.status,s=r>=200&&r<300;let o=p.responseText;try{o=JSON.parse(p.responseText)}catch{}if(s)i&&1===n&&U(c,!1,"none"),h(),t({file:e,success:!0,statusCode:r,data:o});else{const n=`上传失败,状态码:${r}`;i&&U(n,!1,"none"),h(),t({file:e,success:!1,statusCode:r,data:o,message:n})}}),p.addEventListener("error",()=>{const n=u;i&&U(n,!1,"none"),h(),t({file:e,success:!1,message:n})}),p.addEventListener("timeout",()=>{const n=f?`上传超时(${f}ms)`:"上传超时";i&&U(n,!1,"none"),h(),t({file:e,success:!1,message:n})}),p.addEventListener("abort",()=>{h(),t({file:e,success:!1,message:"上传已取消"})}),p.open("POST",r),"number"==typeof f&&f>0&&(p.timeout=f),a&&Object.keys(a).forEach(e=>{p.setRequestHeader(e,a[e])}),p.send(y)})}(e,t,n):function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:u="上传失败",onProgress:l,uploadTimeoutMs:f}=t,m="undefined"==typeof uni?null:uni;if(!m||"function"!=typeof m.uploadFile){const t="当前环境不支持文件上传";return i&&U(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(t=>{let g=!1,d=null;const h=e=>{g||(g=!0,d&&(clearTimeout(d),d=null),t(e))};let p=null;"number"==typeof f&&f>0&&(d=setTimeout(()=>{try{p&&"function"==typeof p.abort&&p.abort()}catch{}const t=`上传超时(${f}ms)`;i&&U(t,!1,"none"),h({file:e,success:!1,message:t})},f)),p=m.uploadFile({url:r,filePath:e.path,name:s,formData:o,header:a,success:t=>{let r=t.data;try{r=JSON.parse(t.data)}catch{}const s=t.statusCode;if(s>=200&&s<300)i&&1===n&&U(c,!1,"none"),h({file:e,success:!0,statusCode:s,data:r});else{const t=`上传失败,状态码:${s}`;i&&U(t,!1,"none"),h({file:e,success:!1,statusCode:s,data:r,message:t})}},fail:t=>{const n=t?.errMsg||u;i&&U(n,!1,"none"),h({file:e,success:!1,message:n})}}),l&&p&&"function"==typeof p.onProgressUpdate&&p.onProgressUpdate(t=>{l(e,t.progress)})})}(e,t,n):(o&&i.message&&U(i.message,!1,"error"),Promise.resolve({file:e,success:!1,message:i.message}))}async function pe(e){const{showToast:t=!0,failMessage:n="选择文件失败"}=e;try{const r=await async function(e){return"undefined"!=typeof document&&"undefined"!=typeof window?function(e){const{type:t="image",count:n=1,extensions:r}=e;return new Promise(s=>{if("undefined"==typeof document)return void s({success:!1,files:[],message:"当前环境不支持文件选择"});const o=document.createElement("input");o.type="file",o.multiple=n>1,"image"===t?o.accept="image/*":r&&r.length>0&&(o.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(",")),o.onchange=t=>{const n=t.target,r=n?.files;if(!r||0===r.length)return s({success:!1,files:[],message:"用户取消选择"}),void document.body.removeChild(o);const a=de(Array.from(r).map((e,t)=>{const n=fe(e.name),r=URL.createObjectURL(e);return{id:me(t),name:e.name,size:e.size,path:r,mimeType:e.type,ext:n,source:"file",platform:"h5",raw:e}}),e);s(a),document.body.removeChild(o)},o.style.display="none",document.body.appendChild(o),o.click()})}(e):function(e){const{type:t="image",count:n=1}=e;return new Promise(r=>{const s="undefined"==typeof uni?null:uni;if(!s)return void r({success:!1,files:[],message:"当前环境不支持文件选择"});const o=e=>{const t=function(e){const t=(e||"").trim();if(!t)return"选择文件失败";const n=t.toLowerCase();return n.includes("fail cancel")||n.includes("cancel")?"用户取消选择":/[\u4e00-\u9fff]/.test(t)?t:"选择文件失败"}(e?.errMsg);r({success:!1,files:[],message:t})},a=function(){let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}();"image"!==t||"function"!=typeof s.chooseImage?"function"!=typeof s.chooseMessageFile?"function"!=typeof s.chooseFile?r({success:!1,files:[],message:"当前平台不支持文件选择"}):s.chooseFile({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=fe(e.path);return{id:me(t),name:`file_${t}`,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(de(n,e))},fail:o}):s.chooseMessageFile({count:n,type:"all",success:t=>{const n=t.tempFiles.map((e,t)=>{const n=fe(e.name||e.path);return{id:me(t),name:e.name,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(de(n,e))},fail:o}):s.chooseImage({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=fe(e.path);return{id:me(t),name:`image_${t}`,size:e.size,path:e.path,ext:n,source:"album",platform:a,raw:e}});r(de(n,e))},fail:o})})}(e)}(e);if(!r.success){const e=r.message||n;return t&&e&&U(e,!1,"none"),[{file:null,success:!1,message:e}]}const s=r.files;if(0===s.length)return[];const o=s.length;return await async function(e,t,n){const r=new Array(e.length),s=t.concurrency&&t.concurrency>0?Math.min(t.concurrency,e.length):e.length;let o=0;const a=async()=>{for(;;){const s=o;if(s>=e.length)break;o+=1;const a=e[s],i=await he(a,t,n);r[s]=i}},i=[];for(let e=0;e<s;e+=1)i.push(a());return await Promise.all(i),r}(s,e,o)}catch(e){const r=n;return t&&r&&U(r,!1,"none"),[{file:null,success:!1,message:r}]}}async function ye(e){return pe({...e,type:"image"})}const Ee=r.getInstance(),we=(e,t,r)=>new Promise(s=>{o(()=>{if("undefined"==typeof window||!window.navigator)throw new Error("不在浏览器环境中,无法调用微信支付");if(!(e&&e.appId&&e.timeStamp&&e.nonceStr&&e.package&&e.paySign))throw new Error("微信支付配置参数不完整");function o(){try{window.WeixinJSBridge.invoke("getBrandWCPayRequest",e,function(e){console.log("🚀 ~ 微信支付结果:",e),"get_brand_wcpay_request:ok"===e.err_msg?(console.log("✅ 微信支付成功"),t?.(e),s(!0)):(console.warn("❌ 微信支付失败或取消:",e.err_msg),r?.(e),s(!1))})}catch(e){Ee.handleError(new n("WECHAT_PAY_INVOKE_ERROR",`调用微信支付接口失败: ${e instanceof Error?e.message:String(e)}`,"payment"),"payment");const t={err_msg:"get_brand_wcpay_request:fail",err_desc:e instanceof Error?e.message:"未知错误"};r?.(t),s(!1)}}if(void 0===window.WeixinJSBridge){const e=window.document;e.addEventListener?e.addEventListener("WeixinJSBridgeReady",o,!1):e.attachEvent&&(e.attachEvent("WeixinJSBridgeReady",o),e.attachEvent("onWeixinJSBridgeReady",o))}else o();return!0},"payment","WECHAT_PAY_ERROR",!1)||s(!1)}),Re=r.getInstance(),Se=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),Te=()=>"undefined"!=typeof window&&"undefined"!=typeof document,_e=()=>Te()&&Se()&&window.wx||null,Ae=(e,t=!1)=>{const n={};return e.forEach(e=>{"string"==typeof e&&""!==e.trim()&&(n[e]=t)}),n};let Oe=!1,ve=null,Pe=!1;const Ce=(e={})=>{const{timeoutMs:t=1e4}=e;if(Oe||Te()&&window.wx)return Oe=!0,Promise.resolve(!0);if(!Te())return Promise.resolve(!1);if(ve)return ve;const n=e.cdnUrls&&e.cdnUrls.length>0?e.cdnUrls:["https://res.wx.qq.com/open/js/jweixin-1.6.0.js","https://res2.wx.qq.com/open/js/jweixin-1.6.0.js"];return ve=new Promise(e=>{let r=!1,s=null,o=null,a=0;const i=t=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&o.parentNode&&o.parentNode.removeChild(o),t&&(Oe=!0),ve=null,e(t))},c=()=>{if(a>=n.length)return void i(!1);if(!document.head)return void i(!1);const e=n[a];a+=1;const t=document.createElement("script");o=t,t.src=e,t.async=!0,t.onload=()=>i(!0),t.onerror=()=>{t.parentNode&&t.parentNode.removeChild(t),o=null,c()},document.head.appendChild(t)};s=setTimeout(()=>{i(!1)},t),c()}),ve};let Ie=null;const $e=async(e,t={})=>{const{timeoutMs:r=1e4}=t;return Se()?Ie||(Ie=(async()=>{if(!await Ce({timeoutMs:r}))return Re.handleError(new n("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;const t=_e();if(!t||"function"!=typeof t.config||"function"!=typeof t.ready||"function"!=typeof t.error)return!1;const s=t.config,o=t.ready,a=t.error,i=await new Promise(t=>{let i=!1,c=null;const u=e=>{i||(i=!0,c&&(clearTimeout(c),c=null),t(e))};c=setTimeout(()=>u(!1),r);try{s({debug:e.debug||!1,appId:e.appId,timestamp:e.timestamp,nonceStr:e.nonceStr,signature:e.signature,jsApiList:e.jsApiList}),o(()=>u(!0)),a(e=>{Re.handleError(new n("WECHAT_JSSDK_CONFIG_ERROR",`微信 JS-SDK 配置错误: ${(e=>{try{return JSON.stringify(e)}catch{return String(e)}})(e)}`,"weixin"),"weixin"),u(!1)})}catch(e){Re.handleError(new n("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),u(!1)}});return Pe=i,i})().finally(()=>{Ie=null}),Ie):(console.warn("当前不在微信环境中"),!1)},xe=(e,t={})=>{const{timeoutMs:r=8e3}=t;return new Promise(t=>{const s=_e();if(!s||"function"!=typeof s.checkJsApi)return void t(Ae(e,!1));let o=!1;const a=e=>{o||(o=!0,t(e))},i=setTimeout(()=>a(Ae(e,!1)),r);try{s.checkJsApi({jsApiList:e,success:t=>{clearTimeout(i),a({...Ae(e,!1),...t?.checkResult||{}})}})}catch(t){clearTimeout(i),Re.handleError(new n("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${t instanceof Error?t.message:String(t)}`,"weixin"),"weixin"),a(Ae(e,!1))}})},Le=e=>{const t=_e();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},Me=e=>{const t=_e();t&&(t.updateAppMessageShareData?t.updateAppMessageShareData(e):t.onMenuShareAppMessage&&t.onMenuShareAppMessage(e))};class be{static instance;isConfigured=!1;config=null;initPromise=null;constructor(){}static getInstance(){return be.instance||(be.instance=new be),be.instance}async init(e){return this.initPromise||(this.config=e,this.initPromise=$e(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return(this.isConfigured||Pe)&&Se()}getConfig(){return this.config}setShareData(e){this.isReady()?(Le(e),Me(e)):console.warn("微信 SDK 未就绪")}}const De="4.0.0";export{r as ErrorHandler,n as UniAppToolsError,De as VERSION,be as WechatSDK,b as areaList,le as batchGetStorage,ue as batchSetStorage,H as buildUrl,xe as checkWechatJSAPI,ce as cleanExpiredStorage,se as clearStorageSync,l as clearSystemCache,$e as configWechatJSSDK,Q as copyText,I as debounce,v as deepClone,P as deepMerge,M as extractUrlParts,h as getCurrentEnv,V as getCurrentPageInfo,L as getH5UrlParams,E as getMenuButtonBoundingClientRect,T as getNavHeight,w as getNavigationBarHeight,Y as getPageStack,g as getPlatform,y as getStatusBarHeight,ae as getStorage,ie as getStorageInfo,re as getStorageSync,R as getTopBarMetrics,S as getTopNavBarHeight,Se as isWechat,Ce as loadWechatJSSDK,C as mergeObjects,j as navigateTo,p as onCheckForUpdate,B as reLaunch,G as redirectTo,s as safeAsync,z as safeNavigateTo,o as safeSync,pe as selectAndUpload,ye as selectAndUploadImage,A as setPageIcon,_ as setPageTitle,oe as setStorage,ne as setStorageSync,Me as shareToFriend,Le as shareToTimeline,J as switchTab,$ as throttle,W as useBack,q as useBackDebounced,K as useBackOrHome,D as useCascaderAreaData,N as useRegions,U as useToast,x as useTryCatch,d as useWindowInfo,we as weChatOfficialAccountPayment};
@@ -7,18 +7,12 @@
7
7
  * 3. 移除 safeAsync 包装(让错误自然抛出)
8
8
  * 4. 移除性能监控(在开发环境手动测量即可)
9
9
  * 5. 简化代码逻辑,提升可维护性
10
+ * 6. v4.0.0: 函数重新排序,抽取公共错误处理,补充详细注释
10
11
  */
11
- /**
12
- * 导航配置选项
13
- */
14
- interface NavigationOptions {
15
- delta?: number;
16
- timeout?: number;
17
- }
18
12
  /**
19
13
  * 页面跳转选项
20
14
  */
21
- interface NavigateOptions {
15
+ export interface NavigateOptions {
22
16
  url: string;
23
17
  params?: Record<string, any>;
24
18
  animationType?: 'auto' | 'none' | 'slide-in-right' | 'slide-in-left' | 'slide-in-top' | 'slide-in-bottom' | 'fade-in' | 'zoom-out' | 'zoom-fade-out' | 'pop-in';
@@ -26,57 +20,217 @@ interface NavigateOptions {
26
20
  events?: Record<string, Function>;
27
21
  }
28
22
  /**
29
- * 跳转到指定页面
23
+ * 返回导航配置选项
24
+ */
25
+ export interface BackOptions {
26
+ delta?: number;
27
+ timeout?: number;
28
+ }
29
+ /**
30
+ * 返回上一页或跳转首页选项
31
+ */
32
+ export interface BackOrHomeOptions extends BackOptions {
33
+ homePage?: string;
34
+ homeParams?: Record<string, any>;
35
+ }
36
+ /**
37
+ * 构建完整 URL(带参数)
38
+ *
39
+ * @param url 基础URL路径
40
+ * @param params URL查询参数对象
41
+ * @returns 完整的URL字符串
42
+ *
43
+ * @example
44
+ * buildUrl('/pages/detail/detail', { id: 123, type: 'product' })
45
+ * // 返回: '/pages/detail/detail?id=123&type=product'
46
+ */
47
+ export declare function buildUrl(url: string, params?: Record<string, any>): string;
48
+ /**
49
+ * 跳转到指定页面(保留当前页面)
50
+ *
30
51
  * @param options 导航选项
31
- * @returns Promise<boolean> 是否成功
52
+ * @param options.url 目标页面路径(必填)
53
+ * @param options.params URL参数对象
54
+ * @param options.animationType 窗口显示动画效果
55
+ * @param options.animationDuration 窗口动画持续时间(毫秒)
56
+ * @param options.events 页面间通信接口
57
+ * @returns Promise<boolean> 返回 true 表示跳转成功,false 表示失败
58
+ *
59
+ * @example
60
+ * // 基础跳转
61
+ * await navigateTo({ url: '/pages/detail/detail' });
62
+ *
63
+ * // 带参数跳转
64
+ * await navigateTo({
65
+ * url: '/pages/detail/detail',
66
+ * params: { id: 123, type: 'product' }
67
+ * });
68
+ *
69
+ * // 带动画效果跳转
70
+ * await navigateTo({
71
+ * url: '/pages/detail/detail',
72
+ * animationType: 'slide-in-right',
73
+ * animationDuration: 300
74
+ * });
32
75
  */
33
76
  export declare function navigateTo(options: NavigateOptions): Promise<boolean>;
34
77
  /**
35
- * 重定向到指定页面
78
+ * 重定向到指定页面(关闭当前页面)
79
+ *
36
80
  * @param options 导航选项
37
- * @returns Promise<boolean> 是否成功
81
+ * @param options.url 目标页面路径(必填)
82
+ * @param options.params URL参数对象
83
+ * @returns Promise<boolean> 返回 true 表示重定向成功,false 表示失败
84
+ *
85
+ * @example
86
+ * // 重定向到登录页
87
+ * await redirectTo({ url: '/pages/login/login' });
88
+ *
89
+ * // 带参数重定向
90
+ * await redirectTo({
91
+ * url: '/pages/result/result',
92
+ * params: { status: 'success', orderId: '12345' }
93
+ * });
38
94
  */
39
95
  export declare function redirectTo(options: NavigateOptions): Promise<boolean>;
96
+ /**
97
+ * 重新启动到指定页面(关闭所有页面)
98
+ *
99
+ * @param options 导航选项
100
+ * @param options.url 目标页面路径(必填)
101
+ * @param options.params URL参数对象
102
+ * @returns Promise<boolean> 返回 true 表示重启成功,false 表示失败
103
+ *
104
+ * @example
105
+ * // 重启到首页
106
+ * await reLaunch({ url: '/pages/index/index' });
107
+ *
108
+ * // 登录成功后重启应用
109
+ * await reLaunch({
110
+ * url: '/pages/home/home',
111
+ * params: { user: 'john' }
112
+ * });
113
+ */
114
+ export declare function reLaunch(options: NavigateOptions): Promise<boolean>;
115
+ /**
116
+ * 切换到Tab页面(只能打开app.json的tabBar字段定义的页面)
117
+ *
118
+ * @param url Tab页面路径
119
+ * @returns Promise<boolean> 返回 true 表示切换成功,false 表示失败
120
+ *
121
+ * @example
122
+ * // 切换到首页Tab
123
+ * await switchTab('/pages/index/index');
124
+ *
125
+ * // 切换到我的Tab
126
+ * await switchTab('/pages/user/user');
127
+ */
128
+ export declare function switchTab(url: string): Promise<boolean>;
40
129
  /**
41
130
  * 返回上一页
42
- * @param params 返回上一页时传入的参数
131
+ *
132
+ * @param params 返回上一页时传入的参数(会调用目标页面的 init 方法)
43
133
  * @param options 导航选项
44
- * @returns Promise<boolean> 是否成功
134
+ * @param options.delta 返回的页面数,默认1
135
+ * @param options.timeout 超时时间(毫秒),默认5000
136
+ * @returns Promise<boolean> 返回 true 表示导航成功,false 表示失败(页面栈不足或超时)
137
+ *
138
+ * @example
139
+ * // 基础返回
140
+ * await useBack();
141
+ *
142
+ * // 返回并传递刷新参数
143
+ * await useBack({ refresh: true, updatedData: {...} });
144
+ *
145
+ * // 返回两层页面
146
+ * await useBack('', { delta: 2 });
147
+ *
148
+ * // 设置超时时间
149
+ * await useBack('', { timeout: 3000 });
45
150
  */
46
- export declare function useBack(params?: any, options?: NavigationOptions): Promise<boolean>;
151
+ export declare function useBack(params?: any, options?: BackOptions): Promise<boolean>;
47
152
  /**
48
- * 返回上一页或跳转首页选项
153
+ * 安全的页面跳转(带重试机制)
154
+ *
155
+ * @param options 导航选项
156
+ * @param maxRetries 最大重试次数,默认3次
157
+ * @returns Promise<boolean> 返回 true 表示跳转成功,false 表示所有重试都失败
158
+ *
159
+ * @description
160
+ * 当页面跳转失败时,会自动重试指定次数。
161
+ * 重试间隔会逐渐增加:第1次等待1秒,第2次等待2秒,第3次等待3秒
162
+ *
163
+ * @example
164
+ * // 使用默认重试次数(3次)
165
+ * const success = await safeNavigateTo({ url: '/pages/detail/detail' });
166
+ *
167
+ * // 自定义重试次数
168
+ * const success = await safeNavigateTo(
169
+ * { url: '/pages/detail/detail' },
170
+ * 5 // 最多重试5次
171
+ * );
49
172
  */
50
- interface BackOrHomeOptions extends NavigationOptions {
51
- homePage?: string;
52
- homeParams?: Record<string, any>;
53
- }
173
+ export declare function safeNavigateTo(options: NavigateOptions, maxRetries?: number): Promise<boolean>;
54
174
  /**
55
- * 返回上一页,若没有上一页则重定向到首页
175
+ * 返回上一页,若页面栈不足则重定向到首页
176
+ *
56
177
  * @param params 返回上一页时传入的参数
57
178
  * @param options 导航选项
58
- * @returns Promise<boolean> 是否成功
179
+ * @param options.delta 返回的页面数,默认1
180
+ * @param options.timeout 超时时间(毫秒),默认5000
181
+ * @param options.homePage 首页路径,默认 'pages/index/index'
182
+ * @param options.homeParams 首页参数
183
+ * @returns Promise<boolean> 返回 true 表示操作成功,false 表示失败
184
+ *
185
+ * @description
186
+ * 智能返回函数:
187
+ * - 如果页面栈深度足够,执行正常返回
188
+ * - 如果页面栈深度不足(如只有1个页面),则重定向到首页
189
+ *
190
+ * @example
191
+ * // 基础使用(页面栈不足时跳转到默认首页)
192
+ * await useBackOrHome();
193
+ *
194
+ * // 自定义首页路径
195
+ * await useBackOrHome('', {
196
+ * homePage: '/pages/home/home',
197
+ * homeParams: { from: 'auto' }
198
+ * });
199
+ *
200
+ * // 返回两层,不足则跳首页
201
+ * await useBackOrHome('', { delta: 2 });
59
202
  */
60
203
  export declare function useBackOrHome(params?: any, options?: BackOrHomeOptions): Promise<boolean>;
61
204
  /**
62
205
  * 防抖版本的返回上一页
206
+ *
207
+ * @description
208
+ * 300毫秒内的多次调用会被合并为一次,防止用户快速点击导致的重复返回
209
+ *
210
+ * @example
211
+ * // 在按钮点击事件中使用
212
+ * <button @click="useBackDebounced()">返回</button>
63
213
  */
64
214
  export declare const useBackDebounced: typeof useBack;
65
- /**
66
- * 切换到Tab页面
67
- * @param url Tab页面路径
68
- * @returns Promise<boolean> 是否成功
69
- */
70
- export declare function switchTab(url: string): Promise<boolean>;
71
- /**
72
- * 重新启动到指定页面
73
- * @param options 导航选项
74
- * @returns Promise<boolean> 是否成功
75
- */
76
- export declare function reLaunch(options: NavigateOptions): Promise<boolean>;
77
215
  /**
78
216
  * 获取当前页面信息
79
- * @returns 当前页面信息
217
+ *
218
+ * @returns 当前页面信息对象,包含路由路径和参数;如果获取失败返回 null
219
+ * @returns {string} route 当前页面的路由路径
220
+ * @returns {any} options 当前页面的参数对象
221
+ *
222
+ * @example
223
+ * const pageInfo = getCurrentPageInfo();
224
+ * if (pageInfo) {
225
+ * console.log('当前页面路由:', pageInfo.route);
226
+ * console.log('当前页面参数:', pageInfo.options);
227
+ * }
228
+ *
229
+ * // 示例返回值
230
+ * // {
231
+ * // route: 'pages/detail/detail',
232
+ * // options: { id: '123', type: 'product' }
233
+ * // }
80
234
  */
81
235
  export declare function getCurrentPageInfo(): {
82
236
  route: string;
@@ -84,17 +238,27 @@ export declare function getCurrentPageInfo(): {
84
238
  } | null;
85
239
  /**
86
240
  * 获取页面栈信息
87
- * @returns 页面栈数组
241
+ *
242
+ * @returns 页面栈数组,包含所有页面的路由和参数;如果获取失败返回空数组
243
+ *
244
+ * @description
245
+ * 返回完整的页面栈信息,从第一个页面到当前页面。
246
+ * 数组索引0是最底层的页面,最后一个元素是当前页面。
247
+ *
248
+ * @example
249
+ * const stack = getPageStack();
250
+ * console.log('页面栈深度:', stack.length);
251
+ * console.log('第一个页面:', stack[0]);
252
+ * console.log('当前页面:', stack[stack.length - 1]);
253
+ *
254
+ * // 示例返回值
255
+ * // [
256
+ * // { route: 'pages/index/index', options: {} },
257
+ * // { route: 'pages/list/list', options: { category: 'tech' } },
258
+ * // { route: 'pages/detail/detail', options: { id: '123' } }
259
+ * // ]
88
260
  */
89
261
  export declare function getPageStack(): Array<{
90
262
  route: string;
91
263
  options: any;
92
264
  }>;
93
- /**
94
- * 安全的页面跳转(带重试机制)
95
- * @param options 导航选项
96
- * @param maxRetries 最大重试次数
97
- * @returns Promise<boolean> 是否成功
98
- */
99
- export declare function safeNavigateTo(options: NavigateOptions, maxRetries?: number): Promise<boolean>;
100
- export {};
@@ -14,22 +14,29 @@ interface WxShareConfig {
14
14
  success?: () => void;
15
15
  cancel?: () => void;
16
16
  }
17
+ /**
18
+ * checkJsApi 返回结果
19
+ */
20
+ interface WxCheckJsApiSuccessResult {
21
+ checkResult?: Record<string, boolean>;
22
+ [key: string]: unknown;
23
+ }
17
24
  declare global {
18
25
  interface Window {
19
26
  wx?: {
20
- config: (config: WxConfig) => void;
21
- ready: (callback: () => void) => void;
22
- error: (callback: (res: any) => void) => void;
23
- checkJsApi: (config: {
27
+ config?: (config: WxConfig) => void;
28
+ ready?: (callback: () => void) => void;
29
+ error?: (callback: (res: unknown) => void) => void;
30
+ checkJsApi?: (config: {
24
31
  jsApiList: string[];
25
- success: (res: any) => void;
32
+ success: (res: WxCheckJsApiSuccessResult) => void;
26
33
  }) => void;
27
- updateAppMessageShareData: (config: WxShareConfig) => void;
28
- updateTimelineShareData: (config: WxShareConfig) => void;
29
- onMenuShareTimeline: (config: WxShareConfig) => void;
30
- onMenuShareAppMessage: (config: WxShareConfig) => void;
31
- onMenuShareWeibo: (config: WxShareConfig) => void;
32
- onMenuShareQZone: (config: WxShareConfig) => void;
34
+ updateAppMessageShareData?: (config: WxShareConfig) => void;
35
+ updateTimelineShareData?: (config: WxShareConfig) => void;
36
+ onMenuShareTimeline?: (config: WxShareConfig) => void;
37
+ onMenuShareAppMessage?: (config: WxShareConfig) => void;
38
+ onMenuShareWeibo?: (config: WxShareConfig) => void;
39
+ onMenuShareQZone?: (config: WxShareConfig) => void;
33
40
  };
34
41
  }
35
42
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-uniapp-tools",
3
- "version": "3.1.0",
3
+ "version": "4.0.2",
4
4
  "type": "module",
5
5
  "description": "一个功能强大、性能优化的 uni-app 开发工具库,提供剪贴板、本地存储、导航、系统信息等常用功能",
6
6
  "main": "dist/my-uniapp-tools.cjs.js",
@@ -37,7 +37,6 @@
37
37
  "storage",
38
38
  "navigation",
39
39
  "system",
40
- "performance",
41
40
  "typescript",
42
41
  "微信小程序",
43
42
  "支付宝小程序",
@@ -77,8 +76,5 @@
77
76
  "sass-embedded": "^1.89.2",
78
77
  "typescript": "^5.8.3",
79
78
  "vuepress": "^2.0.0-rc.24"
80
- },
81
- "directories": {
82
- "example": "examples"
83
79
  }
84
80
  }