my-uniapp-tools 4.2.1 → 5.0.1

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
@@ -240,30 +240,31 @@ clearSystemCache();
240
240
 
241
241
  ### 📤 文件上传功能
242
242
 
243
- > **重要变更**: v3.0.0 完全重写了上传模块,旧API已移除
243
+ > **重要变更**: v5.0.0 扁平化 UploadOptions,移除历史兼容层与多层嵌套配置
244
244
 
245
245
  #### selectAndUpload(options) ⭐ 核心API
246
246
 
247
247
  选择并上传文件(一体化业务入口)
248
248
 
249
- **参数 SelectAndUploadOptions:**
249
+ **参数 UploadOptions(v5):**
250
250
  - `url` (string, 必须): 上传地址
251
- - `type` ('image' | 'file' | 'any'): 文件类型,默认 'image'
251
+ - `files` (UniFile[]): 直接上传已有文件(跳过选择阶段)
252
+ - `type` ('image' | 'file' | 'any'): 文件类型(选择阶段),默认 'image'
252
253
  - `count` (number): 最多选择文件数,默认 1
253
- - `maxSelectFileSizeMB` (number): 选择阶段体积限制(MB)
254
- - `maxUploadFileSizeMB` (number): 上传阶段体积限制(MB)
255
- - `extensions` (string[]): 允许的文件扩展名,如 ['jpg', 'png']
254
+ - `maxSizeMB` (number): 文件体积限制(MB),`0` 表示不允许选择/上传任何文件
255
+ - `extensions` (string[]): 允许的文件扩展名白名单(严格模式),如 ['jpg', 'png']
256
256
  - `fieldName` (string): 文件字段名,默认 'file'
257
257
  - `formData` (Record<string, any>): 额外的表单数据
258
258
  - `headers` (Record<string, string>): 自定义请求头
259
- - `concurrency` (number): 最大并发上传数
260
- - `uploadTimeoutMs` (number): 上传超时时间(ms)
261
- - `autoRevokeObjectURL` (boolean): H5环境下是否自动回收blob URL
259
+ - `timeoutMs` (number): 上传超时时间(ms)
260
+ - `autoRevokeObjectURL` (boolean): H5环境下是否自动回收 blob URL
261
+ - `concurrency` (number): 最大并发上传数(不传默认全并发)
262
+ - `signal` (AbortSignal): 取消信号(AbortController.signal)
262
263
  - `beforeUpload` (function): 上传前拦截钩子,返回 false 跳过该文件
263
- - `showToast` (boolean): 是否显示提示,默认 true
264
- - `successMessage` (string): 成功提示文本
265
- - `failMessage` (string): 失败提示文本
266
264
  - `onProgress` (function): 进度回调 (file, progress) => void
265
+ - `showToast` (boolean): 是否显示提示,默认 true
266
+ - `successMessage` (string): 成功提示文本(单文件成功时)
267
+ - `failMessage` (string): 失败提示文本(保留字段)
267
268
 
268
269
  **返回值**: `Promise<UploadResult[]>`
269
270
  - `file` (UniFile | null): 文件信息
@@ -278,7 +279,7 @@ const results = await selectAndUpload({
278
279
  url: 'https://api.example.com/upload',
279
280
  type: 'image',
280
281
  count: 3,
281
- maxUploadFileSizeMB: 5,
282
+ maxSizeMB: 5,
282
283
  formData: { userId: '123' },
283
284
  headers: { 'Authorization': 'Bearer token' },
284
285
  onProgress: (file, progress) => {
@@ -303,7 +304,7 @@ results.forEach((result) => {
303
304
  const results = await selectAndUploadImage({
304
305
  url: 'https://api.example.com/upload',
305
306
  count: 1,
306
- maxUploadFileSizeMB: 5
307
+ maxSizeMB: 5
307
308
  });
308
309
  ```
309
310
 
@@ -335,7 +336,7 @@ const results = await selectAndUpload({
335
336
  url: 'https://api.example.com/upload',
336
337
  type: 'file',
337
338
  extensions: ['pdf', 'doc', 'docx'],
338
- maxSelectFileSizeMB: 20
339
+ maxSizeMB: 20
339
340
  });
340
341
  ```
341
342
 
package/dist/index.d.ts CHANGED
@@ -8,5 +8,5 @@ export * from "./localStorage";
8
8
  export * from "./upload";
9
9
  export * from "./payment";
10
10
  export * from "./weixin";
11
- export const VERSION: "4.0.0";
11
+ export const VERSION: "5.0.0";
12
12
  export { getExtension, validateSizeWithLimit } from "./upload";
@@ -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,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 l=e=>"weixin"===e||"alipay"===e;let u=!1;const f=()=>{if(a)return a;let e="unknown";try{"undefined"!=typeof uni&&("undefined"!=typeof wx&&wx.getSystemInfoSync?e="weixin":"undefined"!=typeof my&&my.getSystemInfoSync?e="alipay":"undefined"!=typeof window&&window.document?e="h5":"undefined"!=typeof plus&&(e="app"))}catch(t){e="weixin",e="web",e="app",e="alipay",e="h5"}return a=e,e},p=(e=!0)=>e&&c?c:s(()=>{const t=uni.getWindowInfo();return e&&(c=t),t},"system","GET_WINDOW_INFO_ERROR",null),d=()=>{if(null!==i)return i;try{const e=p();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}},m=()=>{try{const e=f();return l(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}},g=()=>{try{const e=f();if(l(e)){const e=m();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=d(),n=g();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},y=n.getInstance();function w(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 E(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 S(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}const T=e.areaList,v=e.useCascaderAreaData,R=(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 P(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 b(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 L(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 C=E(L,300),O={showToast:!0,successMessage:"复制成功",failMessage:"复制失败",timeout:5e3},I=n.getInstance();class ${static instance;cache=new Map;maxCacheSize=100;static getInstance(){return $.instance||($.instance=new $),$.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 I.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 I.handleError(new t("REMOVE_STORAGE_ERROR",`删除存储失败: ${e}`,"localStorage"),"localStorage"),!1}}clear(){try{return uni.clearStorageSync(),this.cache.clear(),!0}catch(e){return I.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 I.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 I.handleError(new t("CLEAN_EXPIRED_ERROR",`清理过期数据失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),0}}}const U=$.getInstance();function D(e,t,n={}){return U.set(e,t,n)}function N(e,t){return U.get(e,t)}function M(e){if(!e)return;const t=e.split(/[?#]/)[0].match(/\.([^./\\]+)$/);return t?t[1].toLowerCase():void 0}function k(e){if(e&&"string"==typeof e)return{"image/jpeg":"jpg","image/jpg":"jpg","image/png":"png","image/gif":"gif","image/webp":"webp","image/heic":"heic","image/heif":"heif","video/mp4":"mp4","application/pdf":"pdf","text/plain":"txt","application/zip":"zip","application/x-zip-compressed":"zip","application/msword":"doc","application/vnd.openxmlformats-officedocument.wordprocessingml.document":"docx","application/vnd.ms-excel":"xls","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":"xlsx"}[e.toLowerCase().trim()]}function j(e){const t=e.toLowerCase().replace(/^\./,"");return"jpeg"===t||"jpe"===t?"jpg":t}function F(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function H(e){return"string"==typeof e&&e.startsWith("blob:")}function B(e){if(H(e)&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL)try{URL.revokeObjectURL(e)}catch{}}function z(e){if("string"!=typeof e)return e;try{return JSON.parse(e)}catch{return e}}function J(e){if(null==e)return"";const t=typeof e;if("string"===t||"number"===t||"boolean"===t)return String(e);if("object"===t)try{return JSON.stringify(e)}catch{return String(e)}return String(e)}function G(e){if(!e)return;const t={};return Object.keys(e).forEach(n=>{t[n]=J(e[n])}),t}class W{isShowing=!1;updateToastThrottled=null;showTitle(e){this.isShowing?this.updateToastThrottled&&this.updateToastThrottled(e):(this.showLoading(e),this.isShowing=!0,this.updateToastThrottled=S(e=>{this.isShowing&&this.showLoading(e)},200,{leading:!0,trailing:!0}))}show(e,t,n={}){const{currentIndex:r,totalCount:s,formatter:o}=n;let a;a=o?o(e,t,r,s):s&&s>1&&r?`上传中 (${r}/${s}) ${t}%`:`上传中 ${t}%`,this.showTitle(a)}hide(){if(!this.isShowing)return;try{this.updateToastThrottled?.cancel?.()}catch{}this.isShowing=!1,this.updateToastThrottled=null;const e="undefined"==typeof uni?null:uni;if(e&&"function"==typeof e.hideLoading)try{e.hideLoading()}catch{}}showLoading(e){const t="undefined"==typeof uni?null:uni;if(t&&"function"==typeof t.showLoading)try{t.showLoading({title:e,mask:!0})}catch{}}}function K(e,t){return null==t||"number"!=typeof t||!Number.isFinite(t)||t<0?{valid:!0}:e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function Y(e,t){if(0===e.length)return{success:!1,files:e,message:"未选择任何文件"};const{maxSelectFileSizeMB:n,extensions:r}=t,s=t.extensionValidationPolicy||"strict",o=null!=n,a=Array.isArray(r)&&r.length>0,i=a?new Set(r.map(e=>j(e))):null;if(o&&0===n)return{success:!1,files:e,message:"当前不允许选择文件"};let c=!1;for(const t of e){if(o&&!K(t.size,n).valid)return{success:!1,files:e,message:`部分文件大小超过 ${n}MB 限制`};if(a&&i){const e=t.ext?j(t.ext):void 0;if(e)i.has(e)||(c=!0);else if("allowNoExtension"===s);else if("mimeTypeFallback"===s){const e=k(t.mimeType),n=e?j(e):void 0;n&&i.has(n)||(c=!0)}else c=!0}}return c?{success:!1,files:e,message:`存在不支持的文件类型,仅支持:${r?.join(", ")}`}:{success:!0,files:e}}async function q(e,t,n,r){const{url:s,maxUploadFileSizeMB:o,showToast:a=!0,beforeUpload:i}=t,c=t.toast||R;if(t.signal?.aborted){const t="已取消上传";return a&&c(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}if("function"==typeof i)try{if(!await Promise.resolve(i(e)))return t.autoRevokeObjectURL&&"h5"===e.platform&&B(e.path),{file:e,success:!1,message:"已取消上传"}}catch(n){console.error("[Upload] beforeUpload 钩子执行异常:",n);const r=n instanceof Error?`上传前检查失败: ${n.message}`:"上传前检查失败";return a&&c(r,!1,"error"),t.autoRevokeObjectURL&&"h5"===e.platform&&B(e.path),{file:e,success:!1,message:r}}if(!s){const t="上传地址不能为空";return a&&c(t,!1,"error"),Promise.resolve({file:e,success:!1,message:t})}const l=K(e.size,o);return l.valid?"h5"===e.platform&&e.raw instanceof File?function(e,t,n,r){const{url:s,fieldName:o="file",formData:a,headers:i,showToast:c=!0,successMessage:l="上传成功",failMessage:u="上传失败",onProgress:f,uploadTimeoutMs:p,autoRevokeObjectURL:d=!1,showProgressToast:m=!1,progressToastFormatter:g}=t,h=t.toast||R;if(t.signal?.aborted){const t="已取消上传";return c&&h(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(y=>{let w=!1;const E=e.raw;if(!(E&&E instanceof File)){const t="H5 环境缺少原生文件对象";return c&&h(t,!1,"none"),void y({file:e,success:!1,message:t})}const S=d&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&"string"==typeof e.path&&H(e.path),T=m&&r?.manager||null,v=new XMLHttpRequest,R=n=>{if(!w){if(w=!0,t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",x)}catch{}S&&B(e.path),y(n)}},x=()=>{try{v.abort()}catch{}};if(t.signal)if(t.signal.aborted)try{v.abort()}catch{}else"function"==typeof t.signal.addEventListener&&t.signal.addEventListener("abort",x,{once:!0});const _=new FormData;_.append(o,E,e.name),a&&Object.keys(a).forEach(e=>{const t=a[e];_.append(e,J(t))}),(f||T)&&v.upload.addEventListener("progress",t=>{if(t.lengthComputable){const s=Math.round(t.loaded/t.total*100);f&&f(e,s),T&&(r?.onToastProgressUpdate?r.onToastProgressUpdate(s):T.show(e,s,{currentIndex:n>1?r?.currentIndex:void 0,totalCount:n>1?n:void 0,formatter:g}))}}),v.addEventListener("load",()=>{const t=v.status,r=t>=200&&t<300;let s=v.responseText;if(s=z(v.responseText),r)c&&1===n&&h(l,!1,"none"),R({file:e,success:!0,statusCode:t,data:s});else{const n=`上传失败,状态码:${t}`;c&&h(n,!1,"none"),R({file:e,success:!1,statusCode:t,data:s,message:n})}}),v.addEventListener("error",()=>{const t=u;c&&h(t,!1,"none"),R({file:e,success:!1,message:t})}),v.addEventListener("timeout",()=>{const t=p?`上传超时(${p}ms)`:"上传超时";c&&h(t,!1,"none"),R({file:e,success:!1,message:t})}),v.addEventListener("abort",()=>{R({file:e,success:!1,message:"上传已取消"})});try{v.open("POST",s),"number"==typeof p&&p>0&&(v.timeout=p),i&&Object.keys(i).forEach(e=>{v.setRequestHeader(e,i[e])}),v.send(_)}catch(t){const n=t instanceof Error?`上传请求失败: ${t.message}`:u;c&&h(n,!1,"none"),R({file:e,success:!1,message:n})}})}(e,t,n,r):function(e,t,n,r){const{url:s,fieldName:o="file",formData:a,headers:i,showToast:c=!0,successMessage:l="上传成功",failMessage:u="上传失败",onProgress:f,uploadTimeoutMs:p,showProgressToast:d=!1,progressToastFormatter:m}=t,g="undefined"==typeof uni?null:uni,h=t.toast||R;if(!g||"function"!=typeof g.uploadFile){const t="当前环境不支持文件上传";return c&&h(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}if(t.signal?.aborted){const t="已取消上传";return c&&h(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(y=>{let w=!1,E=null;const S=d&&r?.manager||null,T=e=>{if(!w){if(w=!0,E&&(clearTimeout(E),E=null),t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",R)}catch{}y(e)}};let v=null;"number"==typeof p&&p>0&&(E=setTimeout(()=>{try{v&&"function"==typeof v.abort&&v.abort()}catch{}const t=`上传超时(${p}ms)`;c&&h(t,!1,"none"),T({file:e,success:!1,message:t})},p)),v=g.uploadFile({url:s,filePath:e.path,name:o,formData:G(a),header:i,success:t=>{let r=t.data;r=z(t.data);const s=function(e){if(e&&"number"==typeof e.statusCode)return e.statusCode;if(e&&"number"==typeof e.status)return e.status;const t="string"==typeof e?.errMsg?e.errMsg:"";return/:ok\b/i.test(t)?200:0}(t);if(s>=200&&s<300)c&&1===n&&h(l,!1,"none"),T({file:e,success:!0,statusCode:s,data:r});else{const t=s?`上传失败,状态码:${s}`:"上传失败";c&&h(t,!1,"none"),T({file:e,success:!1,statusCode:s||void 0,data:r,message:t})}},fail:t=>{const n=t?.errMsg||u;c&&h(n,!1,"none"),T({file:e,success:!1,message:n})}});const R=()=>{try{v&&"function"==typeof v.abort&&v.abort()}catch{}const t="已取消上传";c&&h(t,!1,"none"),T({file:e,success:!1,message:t})};t.signal&&(t.signal.aborted?R():"function"==typeof t.signal.addEventListener&&t.signal.addEventListener("abort",R,{once:!0})),(f||S)&&v&&"function"==typeof v.onProgressUpdate&&v.onProgressUpdate(t=>{f&&f(e,t.progress),S&&(r?.onToastProgressUpdate?r.onToastProgressUpdate(t.progress):S.show(e,t.progress,{currentIndex:n>1?r?.currentIndex:void 0,totalCount:n>1?n:void 0,formatter:m}))})})}(e,t,n,r):(a&&l.message&&c(l.message,!1,"error"),Promise.resolve({file:e,success:!1,message:l.message}))}async function V(e){const{showToast:t=!0,failMessage:n="选择文件失败"}=e,r=e.toast||R;if(e.signal?.aborted){const e="已取消上传";return t&&e&&r(e,!1,"none"),[{file:null,success:!1,message:e}]}try{const s=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||"undefined"==typeof window)return void s({success:!1,files:[],message:"当前环境不支持文件选择"});const o="number"==typeof n&&Number.isFinite(n)&&n>0?Math.floor(n):1,a=document.createElement("input");a.type="file",a.multiple=o>1,"image"===t?a.accept="image/*":r&&r.length>0&&(a.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(","));let i=!1,c=null;const l=e=>{i||(i=!0,f(),s(e))},u=()=>{l({success:!1,files:[],message:"用户取消选择"})},f=()=>{c&&(clearTimeout(c),c=null);try{a.removeEventListener("change",d)}catch{}try{a.removeEventListener("cancel",m)}catch{}try{window.removeEventListener("focus",g)}catch{}try{document.removeEventListener("visibilitychange",h)}catch{}try{window.removeEventListener("pagehide",y)}catch{}try{window.removeEventListener("beforeunload",w)}catch{}if(e.signal&&"function"==typeof e.signal.removeEventListener)try{e.signal.removeEventListener("abort",E)}catch{}try{a.parentNode&&a.parentNode.removeChild(a)}catch{}},p=t=>{if(!t||0===t.length)return void u();const n=Array.from(t).slice(0,o),r=[],s=Y(n.map((e,t)=>{const n=M(e.name),s=URL.createObjectURL(e);return r.push(s),{id:F(t),name:e.name,size:e.size,path:s,mimeType:e.type,ext:n,source:"file",platform:"h5",raw:e}}),e);s.success||r.forEach(B),l(s)},d=e=>{const t=e.target;p(t?.files)},m=()=>{u()},g=()=>{i||(c&&(clearTimeout(c),c=null),c=setTimeout(()=>{i||p(a.files)},0))},h=()=>{i||"string"==typeof document.visibilityState&&"visible"===document.visibilityState&&g()};function y(){f()}function w(){f()}function E(){u()}if(e.signal){if(e.signal.aborted)return void u();"function"==typeof e.signal.addEventListener&&e.signal.addEventListener("abort",E,{once:!0})}a.addEventListener("change",d),a.addEventListener("cancel",m),window.addEventListener("focus",g),document.addEventListener("visibilitychange",h),window.addEventListener("pagehide",y),window.addEventListener("beforeunload",w),a.style.display="none",document.body.appendChild(a),a.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||"weixin"!==a||"function"!=typeof s.chooseMedia?"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=M(e.path);return{id:F(t),name:`file_${t}`,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(Y(n,e))},fail:o}):s.chooseMessageFile({count:n,type:"all",success:t=>{const n=t.tempFiles.map((e,t)=>{const n=M(e.name||e.path);return{id:F(t),name:e.name,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(Y(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=M(e.path);return{id:F(t),name:`image_${t}`,size:e.size,path:e.path,ext:n,source:"album",platform:a,raw:e}});r(Y(n,e))},fail:o}):s.chooseMedia({count:n,mediaType:["image"],success:t=>{const n=(Array.isArray(t?.tempFiles)?t.tempFiles:[]).map((e,t)=>{const n=e?.tempFilePath||e?.path||e?.filePath||"",r=M(n),s="number"==typeof e?.size?e.size:"number"==typeof e?.fileSize?e.fileSize:"number"==typeof e?.originalFileSize?e.originalFileSize:0;return{id:F(t),name:`image_${t}`,size:s,path:n,mimeType:"string"==typeof e?.type?e.type:void 0,ext:r,source:"album",platform:a,raw:e}});r(Y(n,e))},fail:o})})}(e)}(e);if(!s.success){const e=s.message||n;return t&&e&&r(e,!1,"none"),[{file:null,success:!1,message:e}]}const o=s.files;if(0===o.length)return[];if(e.signal?.aborted){const e="已取消上传";return t&&r(e,!1,"none"),[{file:null,success:!1,message:e}]}const a=o.length;return await async function(e,t,n){const r=new Array(e.length),s=t.showProgressToast?new W:null,o=t.concurrency&&t.concurrency>0?Math.min(t.concurrency,e.length):e.length;let a=0;const i=Boolean(s)&&o>1&&n>1,c=i?new Array(n).fill(0):null;let l=0,u=0;const f=()=>{if(!i||!s||!c)return;const e=Math.round(l/n);s.showTitle(`上传中 (${u}/${n}) ${e}%`)},p=(e,t)=>{if(!i||!c)return;const n=Math.max(0,Math.min(100,Math.round(t))),r=c[e]||0;r!==n&&(c[e]=n,l+=n-r)};i&&f();const d=async()=>{for(;!t.signal?.aborted;){const o=a;if(o>=e.length)break;a+=1;const l=e[o];let d={file:l,success:!1,message:"上传失败"};try{d=await q(l,t,n,{manager:s,currentIndex:o+1,onToastProgressUpdate:i&&c?e=>{p(o,e),f()}:void 0})}catch(e){console.error("[Upload] worker 未预期异常:",e);const n=e instanceof Error?`上传失败: ${e.message}`:"上传失败";(t.showToast??1)&&(t.toast||R)(n,!1,"none"),d={file:l,success:!1,message:n}}finally{r[o]=d,i&&c&&(p(o,100),u+=1,f())}}},m=[];for(let e=0;e<o;e+=1)m.push(d());try{await Promise.all(m)}finally{s&&s.hide()}if(t.signal?.aborted)for(let t=0;t<r.length;t+=1)void 0===r[t]&&(r[t]={file:e[t],success:!1,message:"已取消上传"});return r}(o,e,a)}catch(e){const s=n;return t&&s&&r(s,!1,"none"),[{file:null,success:!1,message:s}]}}const X=n.getInstance();let Q=!1,Z=null;const ee=n.getInstance(),te=n.getInstance(),ne=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),re=()=>"undefined"!=typeof window&&"undefined"!=typeof document,se=()=>re()&&ne()&&window.wx||null,oe=(e,t=!1)=>{const n={};return e.forEach(e=>{"string"==typeof e&&""!==e.trim()&&(n[e]=t)}),n};let ae=!1,ie=null,ce=!1;const le=(e={})=>{const{timeoutMs:t=1e4}=e;if(ae||re()&&window.wx)return ae=!0,Promise.resolve(!0);if(!re())return Promise.resolve(!1);if(ie)return ie;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 ie=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&&(ae=!0),ie=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()}),ie};let ue=null;const fe=async(e,n={})=>{const{timeoutMs:r=1e4}=n;return ne()?ue||(ue=(async()=>{if(!await le({timeoutMs:r}))return te.handleError(new t("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;const n=se();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 l=e=>{i||(i=!0,c&&(clearTimeout(c),c=null),n(e))};c=setTimeout(()=>l(!1),r);try{s({debug:e.debug||!1,appId:e.appId,timestamp:e.timestamp,nonceStr:e.nonceStr,signature:e.signature,jsApiList:e.jsApiList}),o(()=>l(!0)),a(e=>{te.handleError(new t("WECHAT_JSSDK_CONFIG_ERROR",`微信 JS-SDK 配置错误: ${(e=>{try{return JSON.stringify(e)}catch{return String(e)}})(e)}`,"weixin"),"weixin"),l(!1)})}catch(e){te.handleError(new t("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),l(!1)}});return ce=i,i})().finally(()=>{ue=null}),ue):(console.warn("当前不在微信环境中"),!1)},pe=e=>{const t=se();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},de=e=>{const t=se();t&&(t.updateAppMessageShareData?t.updateAppMessageShareData(e):t.onMenuShareAppMessage&&t.onMenuShareAppMessage(e))};class me{static instance;isConfigured=!1;config=null;initPromise=null;constructor(){}static getInstance(){return me.instance||(me.instance=new me),me.instance}async init(e){return this.initPromise||(this.config=e,this.initPromise=fe(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return(this.isConfigured||ce)&&ne()}getConfig(){return this.config}setShareData(e){this.isReady()?(pe(e),de(e)):console.warn("微信 SDK 未就绪")}}exports.ErrorHandler=n,exports.UniAppToolsError=t,exports.VERSION="4.0.0",exports.WechatSDK=me,exports.areaList=T,exports.batchGetStorage=function(e){const t={};return e.forEach(e=>{t[e]=N(e)}),t},exports.batchSetStorage=function(e,t={}){let n=0;return Object.entries(e).forEach(([e,r])=>{D(e,r,t)&&n++}),n},exports.buildUrl=_,exports.checkWechatJSAPI=(e,n={})=>{const{timeoutMs:r=8e3}=n;return new Promise(n=>{const s=se();if(!s||"function"!=typeof s.checkJsApi)return void n(oe(e,!1));let o=!1;const a=e=>{o||(o=!0,n(e))},i=setTimeout(()=>a(oe(e,!1)),r);try{s.checkJsApi({jsApiList:e,success:t=>{clearTimeout(i),a({...oe(e,!1),...t?.checkResult||{}})}})}catch(n){clearTimeout(i),te.handleError(new t("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${n instanceof Error?n.message:String(n)}`,"weixin"),"weixin"),a(oe(e,!1))}})},exports.cleanExpiredStorage=function(){return U.cleanExpired()},exports.clearStorageSync=function(e){return e?U.remove(e):U.clear()},exports.clearSystemCache=()=>{c=null},exports.configWechatJSSDK=fe,exports.copyText=async function(e,t={}){const n={...O,...t};return e&&"string"==typeof e?e.length>1e4?(n.showToast&&R("复制内容过长",!1,"error"),!1):await r(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{n.showToast&&R(n.successMessage),t(!0)},fail:()=>{n.showToast&&R(n.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1:(n.showToast&&R("复制内容不能为空",!1,"error"),!1)},exports.debounce=E,exports.deepClone=w,exports.deepMerge=function(e,t){const n=w(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]=w(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.getExtension=M,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=m,exports.getNavHeight=()=>h().totalTopHeight,exports.getNavigationBarHeight=g,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=d,exports.getStorage=async function(e,t){return await r(()=>new Promise(n=>{n(N(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t},exports.getStorageInfo=function(){return U.getInfo()},exports.getStorageSync=N,exports.getTopBarMetrics=h,exports.getTopNavBarHeight=()=>{const e=h();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},exports.injectAlipayJsSdk=(e="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js")=>"undefined"!=typeof window&&window.document?Q||window.ap?(Q=!0,Promise.resolve(!0)):Z||(Z=new Promise(n=>{let r=!1,s=null,o=null,a=!1,i=null,c=null,l=null;const u=(e,a,u)=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&(clearInterval(o),o=null),i&&c&&i.removeEventListener("load",c),i&&l&&i.removeEventListener("error",l),!e&&a&&u&&X.handleError(new t(a,u,"payment"),"payment"),e&&(Q=!0),Z=null,n(e))};try{const t=(()=>{try{return new URL(e,window.location.href).href}catch{return e}})(),n=document.getElementsByTagName("script");let r=null;for(let e=0;e<n.length;e++){const s=n[e];if(s&&s.src===t){r=s;break}}const f=r??document.createElement("script");a=!r,i=f;const p=()=>{window.ap&&u(!0)},d=e=>{a&&f.parentNode&&f.parentNode.removeChild(f),u(!1,"ALIPAY_SDK_LOAD_ERROR",`支付宝 JSSDK 加载失败: ${String(e?.type||"error")}`)};if(c=p,l=d,f.addEventListener("load",p),f.addEventListener("error",d),o=setInterval(()=>{window.ap&&u(!0)},50),s=setTimeout(()=>{a&&f.parentNode&&f.parentNode.removeChild(f),u(!1,"ALIPAY_SDK_LOAD_TIMEOUT","支付宝 JSSDK 加载超时")},1e4),a){f.type="text/javascript",f.src=t,f.async=!0,f.setAttribute("data-uniapp-tools","alipay-jssdk");const e=document.head||document.body||document.documentElement||null;if(!e)return void u(!1,"ALIPAY_SDK_INJECT_ERROR","无法找到可用的 script 注入容器");e.appendChild(f)}window.ap&&u(!0)}catch(e){u(!1,"ALIPAY_SDK_INJECT_ERROR",`注入支付宝 JSSDK 发生异常: ${e instanceof Error?e.message:String(e)}`)}}),Z):(X.handleError(new t("ALIPAY_SDK_ENV_ERROR","不在浏览器环境中,无法注入支付宝 JSSDK","payment"),"payment"),Promise.resolve(!1)),exports.isWechat=ne,exports.loadWechatJSSDK=le,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(!u)try{const e=uni.getUpdateManager();u=!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=b,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 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=s,exports.selectAndUpload=V,exports.selectAndUploadImage=async function(e){return V({...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(D(e,t,n))}),"localStorage","SET_STORAGE_ASYNC_ERROR")??!1},exports.setStorageSync=D,exports.shareToFriend=de,exports.shareToTimeline=pe,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=S,exports.useBack=L,exports.useBackDebounced=C,exports.useBackOrHome=async function(e="",t={}){const n=getCurrentPages(),r=t.delta||1;if(n.length>r)return await L(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})},exports.useCascaderAreaData=v,exports.useRegions=function(){return e.useCascaderAreaData()},exports.useToast=R,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=p,exports.validateSizeWithLimit=K,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){ee.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
+ "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";try{"undefined"!=typeof uni&&("undefined"!=typeof wx&&wx.getSystemInfoSync?e="weixin":"undefined"!=typeof my&&my.getSystemInfoSync?e="alipay":"undefined"!=typeof window&&window.document?e="h5":"undefined"!=typeof plus&&(e="app"))}catch(t){e="weixin",e="web",e="app",e="alipay",e="h5"}return a=e,e},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}},d=()=>{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}},g=()=>{try{const e=f();if(u(e)){const e=d();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=g();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},y=n.getInstance();function w(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 E(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 S(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}const R=e.areaList,T=e.useCascaderAreaData,x=(e="",t=!1,n="none",r=2e3)=>{uni.showToast({title:e,icon:n,mask:t,duration:r})},_=n.getInstance();function A(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 v(e,n){_.handleError(new t(e,n,"navigation"),"navigation")}async function O(e){return new Promise(t=>{const n=A(e.url,e.params);uni.navigateTo({url:n,animationType:e.animationType,animationDuration:e.animationDuration,events:e.events,success:()=>t(!0),fail:e=>{v("NAVIGATE_TO_FAILED",`页面跳转失败: ${n}`),t(!1)}})})}async function P(e){return new Promise(t=>{const n=A(e.url,e.params);uni.reLaunch({url:n,success:()=>t(!0),fail:e=>{v("RELAUNCH_FAILED",`重新启动失败: ${n}`),t(!1)}})})}async function C(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){v("PAGE_CALLBACK_ERROR",`页面回调执行失败: ${e instanceof Error?e.message:String(e)}`),n(!0)}},100)},fail:e=>{clearTimeout(o),v("NAVIGATE_BACK_FAILED","导航返回失败"),n(!1)}})})}const I=E(C,300),b={showToast:!0,successMessage:"复制成功",failMessage:"复制失败",timeout:5e3},L=n.getInstance();class D{static instance;cache=new Map;maxCacheSize=100;static getInstance(){return D.instance||(D.instance=new D),D.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 L.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 L.handleError(new t("REMOVE_STORAGE_ERROR",`删除存储失败: ${e}`,"localStorage"),"localStorage"),!1}}clear(){try{return uni.clearStorageSync(),this.cache.clear(),!0}catch(e){return L.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 L.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 L.handleError(new t("CLEAN_EXPIRED_ERROR",`清理过期数据失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),0}}}const N=D.getInstance();function $(e,t,n={}){return N.set(e,t,n)}function M(e,t){return N.get(e,t)}const U="上传失败",k="已取消上传",F="选择文件失败",H="用户取消选择",j=e=>`部分文件大小超过 ${e}MB 限制`,B=e=>`存在不支持的文件类型,仅支持:${e.join(", ")}`,J="当前环境不支持文件选择",W=e=>`上传超时(${e}ms)`,G=e=>`上传请求失败: ${e}`,K=e=>`上传失败,状态码:${e}`,z={FILE_TYPE:"image",COUNT:1,SHOW_TOAST:!0};function Y(e){if(!e)return;const t=e.split(/[?#]/)[0].match(/\.([^./\\]+)$/);return t?t[1].toLowerCase():void 0}function q(e){const t=e.toLowerCase().replace(/^\./,"");return"jpeg"===t||"jpe"===t?"jpg":t}function V(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function X(e){return"string"==typeof e&&e.startsWith("blob:")}function Q(e){if("string"!=typeof e)return e;try{return JSON.parse(e)}catch{return e}}function Z(e){if(null==e)return"";const t=typeof e;if("string"===t||"number"===t||"boolean"===t)return String(e);if("object"===t)try{return JSON.stringify(e)}catch{return String(e)}return String(e)}function ee(e){if(!e)return;const t={};return Object.keys(e).forEach(n=>{t[n]=Z(e[n])}),t}function te(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:"选择文件失败"}function ne(e,t){return null==t||"number"!=typeof t||!Number.isFinite(t)||t<0?{valid:!0}:e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function re(e,t){return!Number.isFinite(t)||t<=0?0:"number"!=typeof e||!Number.isFinite(e)||e<=0?t:Math.min(Math.floor(e),t)}function se(e){return{toast:e.toast||x,shouldShowToast:e.showToast??z.SHOW_TOAST}}function oe(e){return Boolean(e?.aborted)}function ae(e){return[{file:null,success:!1,message:e}]}function ie(){return ae(k)}async function ce(e,t,n){const{url:r,files:s,type:o=z.FILE_TYPE,count:a=z.COUNT,maxSizeMB:i,extensions:c,signal:u,successMessage:l}=e,{toast:f,shouldShowToast:m}=se(e);if(!r.trim()){const e="上传地址不能为空";return m&&f(e,!1,"none"),ae(e)}if(oe(u))return m&&f(k,!1,"none"),ie();let p=s||[];if(0===p.length)try{const e=await t({type:o,count:a,extensions:c});if(!e.success)return m&&e.message&&f(e.message,!1,"none"),[{file:null,success:!1,message:e.message}];p=e.files}catch(e){const t=e instanceof Error?e.message:F;return m&&f(t,!1,"none"),ae(t)}if(0===p.length)return[];const d=function(e,t){if(!e||0===e.length)return{success:!1,message:"未选择任何文件"};const{maxSizeMB:n,extensions:r}=t;if(0===n)return{success:!1,message:"当前不允许选择文件"};const s=null!=n&&"number"==typeof n&&Number.isFinite(n)&&n>0,o=Array.isArray(r)&&r.length>0;if(!s&&!o)return{success:!0};const a=o?new Set(r.map(e=>q(e))):null;for(const t of e){if(s&&!ne(t.size,n).valid)return{success:!1,message:j(n)};if(o&&a){const e=t.ext?q(t.ext):void 0;if(!e||!a.has(e))return{success:!1,message:B(r)}}}return{success:!0}}(p,{maxSizeMB:i,extensions:c});if(!d.success){const e=d.message||F;return m&&f(e,!1,"none"),ae(e)}if(oe(u))return m&&f(k,!1,"none"),ie();const g=await async function(e,t,n,r){const{concurrency:s,signal:o,beforeUpload:a,onProgress:i,showProgressToast:c,progressToastFormatter:u}=t,{toast:l,shouldShowToast:f}=se(t),m=new Array(e.length);let p=0;const d=e.length,g=re(s,d),h=Boolean(c&&d>0),y="undefined"!=typeof uni?uni:null,w=Boolean(h&&y&&"function"==typeof y.showLoading&&"function"==typeof y.hideLoading),E=w,R=S((t,n)=>{if(!w)return;const r=function(e){const{files:t,index:n,pct:r,finishedCount:s,totalCount:o,progressToastFormatter:a}=e;return a?a(t[n],r,n+1,o):1===o?`上传中 ${r}%`:`上传中 (${s}/${o})`}({files:e,index:t,pct:n,finishedCount:p,totalCount:d,progressToastFormatter:u});y.showLoading({title:r,mask:!0})},200);const T=async s=>{const c=e[s];let u=null;try{if(oe(o))return u={file:c,success:!1,message:k},void(w&&R(s,0));const e=await async function(e){if(!a)return null;try{return await a(e)?null:{file:e,success:!1,message:k}}catch(t){const n=(e=>`上传前检查失败: ${e}`)(t.message||"unknown");return f&&l(n,!1,"error"),{file:e,success:!1,message:n}}}(c);if(e)return void(u=e);const m=function(e){return E?{...t,onProgress:(t,n)=>{R(e,n),i&&i(t,n)}}:t}(s);u=await r(c,m,n)}catch(e){u={file:c,success:!1,message:e.message||"Unknown error"}}finally{u||(u={file:c,success:!1,message:"Unknown error"}),m[s]=u,p++,u.success&&R(s,100)}};for(let e=0;e<d;e+=g){const t=Math.min(e+g,d),n=[];for(let r=e;r<t;r+=1)n.push(T(r));await Promise.all(n)}return w&&(R.cancel?.(),y.hideLoading()),m}(p,e,r,n);return g.filter(e=>e.success).length===g.length&&1===g.length&&m&&f(l||"上传成功",!1,"none"),g}function ue(e,t,n,r,s,o,a){return{id:V(t),name:a||`file_${t}`,size:n,path:e,ext:Y(a||e),source:r,platform:s,raw:o}}const le="undefined"!=typeof window&&"undefined"!=typeof document&&!function(){const e="undefined"==typeof uni?null:uni;return Boolean(e&&"function"==typeof e.uploadFile)}(),fe=le?function(e){const{type:t="image",count:n=1,extensions:r}=e;return new Promise(e=>{if("undefined"==typeof document||"undefined"==typeof window)return void e({success:!1,files:[],message:J});const s=document.createElement("input");s.type="file",s.multiple=n>1,s.style.display="none","image"===t?s.accept="image/*":r&&r.length>0&&(s.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(","));let o=!1,a=null;const i=t=>{o||(o=!0,(()=>{a&&(clearTimeout(a),a=null),window.removeEventListener("focus",u);try{s.remove()}catch{}})(),e(t))},c=e=>{if(!e||0===e.length)return void i({success:!1,files:[],message:H});const t=Array.from(e).slice(0,n).map((e,t)=>({id:V(t),name:e.name,size:e.size,path:URL.createObjectURL(e),mimeType:e.type,ext:Y(e.name),source:"file",platform:"h5",raw:e}));i({success:!0,files:t})};s.addEventListener("change",()=>c(s.files)),s.addEventListener("cancel",()=>i({success:!1,files:[],message:H}));const u=()=>{o||(a=window.setTimeout(()=>{o||(s.files&&0!==s.files.length?c(s.files):i({success:!1,files:[],message:H}))},300))};window.addEventListener("focus",u),document.body.appendChild(s),s.click()})}:function(e){const{type:t="image",count:n=1}=e;return new Promise(e=>{const r="undefined"==typeof uni?null:uni;if(!r)return void e({success:!1,files:[],message:J});const s=function(){if("undefined"!=typeof wx&&wx?.getSystemInfoSync)return"weixin";if("undefined"!=typeof my&&my?.getSystemInfoSync)return"alipay";if("undefined"!=typeof window&&"undefined"!=typeof document)return"h5";if("undefined"!=typeof plus)return"app";let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}(),o=t=>{e({success:!1,files:[],message:te(t?.errMsg)})},a=[{name:"chooseMedia(image)",when:()=>"image"===t&&"weixin"===s&&"function"==typeof r.chooseMedia,run:()=>{r.chooseMedia({count:n,mediaType:["image"],success:t=>{const n=(Array.isArray(t?.tempFiles)?t.tempFiles:[]).map((e,t)=>{const n=e.size||e.fileSize||e.originalFileSize||0;return ue(e.tempFilePath,t,n,"album",s,e)});e({success:!0,files:n})},fail:o})}},{name:"chooseImage",when:()=>"image"===t&&"function"==typeof r.chooseImage,run:()=>{r.chooseImage({count:n,success:t=>{const n=(Array.isArray(t?.tempFiles)?t.tempFiles:t?.tempFiles?[t.tempFiles]:[]).map((e,t)=>ue(e.path,t,e.size,"album",s,e));e({success:!0,files:n})},fail:o})}},{name:"chooseMessageFile(all)",when:()=>"function"==typeof r.chooseMessageFile,run:()=>{r.chooseMessageFile({count:n,type:"all",success:t=>{const n=(Array.isArray(t?.tempFiles)?t.tempFiles:[]).map((e,t)=>ue(e.path,t,e.size,"file",s,e,e.name));e({success:!0,files:n})},fail:o})}}];for(const e of a)if(e.when())return void e.run();e({success:!1,files:[],message:"当前平台不支持文件选择"})})},me=le?function(e,t,n){const{fieldName:r="file",formData:s,headers:o,timeoutMs:a,autoRevokeObjectURL:i}=t,{signal:c,onProgress:u}=t;return new Promise(t=>{const l=e.raw;if(!(l&&l instanceof File))return void t({file:e,success:!1,message:"H5 环境缺少原生文件对象"});const f=new XMLHttpRequest;let m=!1;const p=n=>{m||(m=!0,i&&X(e.path)&&function(e){if(X(e)&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL)try{URL.revokeObjectURL(e)}catch{}}(e.path),t(n))};if(c){if(c.aborted)return void p({file:e,success:!1,message:k});c.addEventListener("abort",()=>{f.abort(),p({file:e,success:!1,message:k})},{once:!0})}f.open("POST",n),a&&a>0&&(f.timeout=a),o&&Object.keys(o).forEach(e=>{f.setRequestHeader(e,o[e])});const d=new FormData;d.append(r,l,e.name),s&&Object.keys(s).forEach(e=>{d.append(e,Z(s[e]))}),f.upload.onprogress=t=>{if(t.lengthComputable&&u){const n=Math.round(t.loaded/t.total*100);u(e,n)}},f.onload=()=>{const t=f.status,n=t>=200&&t<300;let r=Q(f.responseText);p({file:e,success:n,statusCode:t,data:r,message:n?void 0:K(t)})},f.onerror=()=>p({file:e,success:!1,message:U}),f.ontimeout=()=>p({file:e,success:!1,message:W(a||0)}),f.onabort=()=>p({file:e,success:!1,message:k});try{f.send(d)}catch(t){const n=t instanceof Error?t.message:"Unknown error";p({file:e,success:!1,message:G(n)})}})}:function(e,t,n){const{fieldName:r="file",formData:s,headers:o,timeoutMs:a}=t,{signal:i,onProgress:c}=t;return new Promise(t=>{const u="undefined"==typeof uni?null:uni;if(!u?.uploadFile)return void t({file:e,success:!1,message:"当前环境不支持文件上传"});let l=!1,f=null,m=null;const p=e=>{l||(l=!0,f&&clearTimeout(f),t(e))};a&&a>0&&(f=setTimeout(()=>{m?.abort?.(),p({file:e,success:!1,message:W(a)})},a)),m=u.uploadFile({url:n,filePath:e.path,name:r,header:o,formData:ee(s),success:t=>{const n=function(e){if(e&&"number"==typeof e.statusCode)return e.statusCode;if(e&&"number"==typeof e.status)return e.status;const t="string"==typeof e?.errMsg?e.errMsg:"";return/:ok\b/i.test(t)?200:0}(t),r=n>=200&&n<300,s=Q(t.data);p({file:e,success:r,statusCode:n,data:s,message:r?void 0:K(n)})},fail:t=>{l||p({file:e,success:!1,message:t?.errMsg||U})}}),c&&m?.onProgressUpdate&&m.onProgressUpdate(t=>{l||"number"!=typeof t.progress||c(e,t.progress)}),i&&(i.aborted?(m?.abort?.(),p({file:e,success:!1,message:k})):i.addEventListener("abort",()=>{m?.abort?.(),p({file:e,success:!1,message:k})},{once:!0}))})};async function pe(e){return ce(e,fe,me)}const de=n.getInstance();let ge=!1,he=null;const ye=n.getInstance(),we=n.getInstance(),Ee=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),Se=()=>"undefined"!=typeof window&&"undefined"!=typeof document,Re=()=>Se()&&Ee()&&window.wx||null,Te=(e,t=!1)=>{const n={};return e.forEach(e=>{"string"==typeof e&&""!==e.trim()&&(n[e]=t)}),n};let xe=!1,_e=null,Ae=!1;const ve=(e={})=>{const{timeoutMs:t=1e4}=e;if(xe||Se()&&window.wx)return xe=!0,Promise.resolve(!0);if(!Se())return Promise.resolve(!1);if(_e)return _e;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 _e=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&&(xe=!0),_e=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()}),_e};let Oe=null;const Pe=async(e,n={})=>{const{timeoutMs:r=1e4}=n;return Ee()?Oe||(Oe=(async()=>{if(!await ve({timeoutMs:r}))return we.handleError(new t("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;const n=Re();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=>{we.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){we.handleError(new t("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),u(!1)}});return Ae=i,i})().finally(()=>{Oe=null}),Oe):(console.warn("当前不在微信环境中"),!1)},Ce=e=>{const t=Re();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},Ie=e=>{const t=Re();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=Pe(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return(this.isConfigured||Ae)&&Ee()}getConfig(){return this.config}setShareData(e){this.isReady()?(Ce(e),Ie(e)):console.warn("微信 SDK 未就绪")}}exports.ErrorHandler=n,exports.UniAppToolsError=t,exports.VERSION="5.0.0",exports.WechatSDK=be,exports.areaList=R,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])=>{$(e,r,t)&&n++}),n},exports.buildUrl=A,exports.checkWechatJSAPI=(e,n={})=>{const{timeoutMs:r=8e3}=n;return new Promise(n=>{const s=Re();if(!s||"function"!=typeof s.checkJsApi)return void n(Te(e,!1));let o=!1;const a=e=>{o||(o=!0,n(e))},i=setTimeout(()=>a(Te(e,!1)),r);try{s.checkJsApi({jsApiList:e,success:t=>{clearTimeout(i),a({...Te(e,!1),...t?.checkResult||{}})}})}catch(n){clearTimeout(i),we.handleError(new t("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${n instanceof Error?n.message:String(n)}`,"weixin"),"weixin"),a(Te(e,!1))}})},exports.cleanExpiredStorage=function(){return N.cleanExpired()},exports.clearStorageSync=function(e){return e?N.remove(e):N.clear()},exports.clearSystemCache=()=>{c=null},exports.configWechatJSSDK=Pe,exports.copyText=async function(e,t={}){const n={...b,...t};return e&&"string"==typeof e?e.length>1e4?(n.showToast&&x("复制内容过长",!1,"error"),!1):await r(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{n.showToast&&x(n.successMessage),t(!0)},fail:()=>{n.showToast&&x(n.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1:(n.showToast&&x("复制内容不能为空",!1,"error"),!1)},exports.debounce=E,exports.deepClone=w,exports.deepMerge=function(e,t){const n=w(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]=w(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 v("GET_CURRENT_PAGE_ERROR",`获取当前页面信息失败: ${e instanceof Error?e.message:String(e)}`),null}},exports.getExtension=Y,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=d,exports.getNavHeight=()=>h().totalTopHeight,exports.getNavigationBarHeight=g,exports.getPageStack=function(){try{return getCurrentPages().map(e=>({route:e.route||"",options:e.options||{}}))}catch(e){return v("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 N.getInfo()},exports.getStorageSync=M,exports.getTopBarMetrics=h,exports.getTopNavBarHeight=()=>{const e=h();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},exports.injectAlipayJsSdk=(e="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js")=>"undefined"!=typeof window&&window.document?ge||window.ap?(ge=!0,Promise.resolve(!0)):he||(he=new Promise(n=>{let r=!1,s=null,o=null,a=!1,i=null,c=null,u=null;const l=(e,a,l)=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&(clearInterval(o),o=null),i&&c&&i.removeEventListener("load",c),i&&u&&i.removeEventListener("error",u),!e&&a&&l&&de.handleError(new t(a,l,"payment"),"payment"),e&&(ge=!0),he=null,n(e))};try{const t=(()=>{try{return new URL(e,window.location.href).href}catch{return e}})(),n=document.getElementsByTagName("script");let r=null;for(let e=0;e<n.length;e++){const s=n[e];if(s&&s.src===t){r=s;break}}const f=r??document.createElement("script");a=!r,i=f;const m=()=>{window.ap&&l(!0)},p=e=>{a&&f.parentNode&&f.parentNode.removeChild(f),l(!1,"ALIPAY_SDK_LOAD_ERROR",`支付宝 JSSDK 加载失败: ${String(e?.type||"error")}`)};if(c=m,u=p,f.addEventListener("load",m),f.addEventListener("error",p),o=setInterval(()=>{window.ap&&l(!0)},50),s=setTimeout(()=>{a&&f.parentNode&&f.parentNode.removeChild(f),l(!1,"ALIPAY_SDK_LOAD_TIMEOUT","支付宝 JSSDK 加载超时")},1e4),a){f.type="text/javascript",f.src=t,f.async=!0,f.setAttribute("data-uniapp-tools","alipay-jssdk");const e=document.head||document.body||document.documentElement||null;if(!e)return void l(!1,"ALIPAY_SDK_INJECT_ERROR","无法找到可用的 script 注入容器");e.appendChild(f)}window.ap&&l(!0)}catch(e){l(!1,"ALIPAY_SDK_INJECT_ERROR",`注入支付宝 JSSDK 发生异常: ${e instanceof Error?e.message:String(e)}`)}}),he):(de.handleError(new t("ALIPAY_SDK_ENV_ERROR","不在浏览器环境中,无法注入支付宝 JSSDK","payment"),"payment"),Promise.resolve(!1)),exports.isWechat=Ee,exports.loadWechatJSSDK=ve,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=O,exports.normalizeConcurrency=re,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=P,exports.redirectTo=async function(e){return new Promise(t=>{const n=A(e.url,e.params);uni.redirectTo({url:n,success:()=>t(!0),fail:e=>{v("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 O(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=pe,exports.selectAndUploadImage=async function(e){return pe({...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($(e,t,n))}),"localStorage","SET_STORAGE_ASYNC_ERROR")??!1},exports.setStorageSync=$,exports.shareToFriend=Ie,exports.shareToTimeline=Ce,exports.switchTab=async function(e){return new Promise(t=>{uni.switchTab({url:e,success:()=>t(!0),fail:n=>{v("SWITCH_TAB_FAILED",`Tab切换失败: ${e}`),t(!1)}})})},exports.throttle=S,exports.useBack=C,exports.useBackDebounced=I,exports.useBackOrHome=async function(e="",t={}){const n=getCurrentPages(),r=t.delta||1;if(n.length>r)return await C(e,t);const s=t.homePage||"pages/index/index",o=s.startsWith("/")?s:`/${s}`;return console.info(`[navigation] 页面栈深度不足,重定向到首页: ${o}`),await P({url:o,params:t.homeParams})},exports.useCascaderAreaData=T,exports.useRegions=function(){return e.useCascaderAreaData()},exports.useToast=x,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.validateSizeWithLimit=ne,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){ye.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}}const i=r.getInstance();let a=null,c=null,l=null;const u=()=>{l=null},f=e=>"weixin"===e||"alipay"===e;let d=!1;const m=()=>{if(a)return a;let e="unknown";try{"undefined"!=typeof uni&&("undefined"!=typeof wx&&wx.getSystemInfoSync?e="weixin":"undefined"!=typeof my&&my.getSystemInfoSync?e="alipay":"undefined"!=typeof window&&window.document?e="h5":"undefined"!=typeof plus&&(e="app"))}catch(t){e="weixin",e="web",e="app",e="alipay",e="h5"}return a=e,e},g=(e=!0)=>e&&l?l:o(()=>{const t=uni.getWindowInfo();return e&&(l=t),t},"system","GET_WINDOW_INFO_ERROR",null),p=()=>{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 n("GET_ACCOUNT_INFO_ERROR",`获取小程序账户信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),{appId:"",version:"",envVersion:"",accountInfo:{}}}},h=()=>{if(!d)try{const e=uni.getUpdateManager();d=!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 n("UPDATE_DOWNLOAD_FAILED","新版本下载失败","system"),"system"),uni.showModal({title:"更新失败",content:"新版本下载失败,请检查网络连接或稍后重试",showCancel:!1,confirmText:"知道了"})})}catch(e){i.handleError(new n("CHECK_UPDATE_ERROR",`版本更新检查失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system")}},y=()=>{if(null!==c)return c;try{const e=g();return c=e?.statusBarHeight||0,c}catch(e){return i.handleError(new n("GET_STATUS_BAR_HEIGHT_ERROR",`获取状态栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),0}},w=()=>{try{const e=m();return f(e)?uni.getMenuButtonBoundingClientRect():null}catch(e){return i.handleError(new n("GET_MENU_BUTTON_ERROR",`获取菜单按钮边界信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),null}},E=()=>{try{const e=m();if(f(e)){const e=w();return e?.height||44}return 44}catch(e){return i.handleError(new n("GET_NAVIGATION_BAR_HEIGHT_ERROR",`获取导航栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),44}},S=()=>{const e=m(),t=y(),n=E();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},v=()=>{const e=S();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},R=()=>S().totalTopHeight,T=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){i.handleError(new n("SET_PAGE_TITLE_ERROR",`setPageTitle执行异常: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),t(!1)}}),_=(e,t="image/x-icon")=>o(()=>{const n=m();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),A=r.getInstance();function P(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 A.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 b(e,t){const n=P(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]=P(s)}}(n,t),n}function L(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 O(e,t,n=!1){let r,s=null;const o=function(...o){const i=n&&!s;return s&&clearTimeout(s),s=setTimeout(()=>{s=null,n||(r=e.apply(this,o))},t),i&&(r=e.apply(this,o)),r};return o.cancel=()=>{s&&(clearTimeout(s),s=null)},o}function C(e,t,n={}){let r,s=null,o=0;const{leading:i=!0,trailing:a=!0}=n,c=function(...n){const c=Date.now();o||i||(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&&a&&(s=setTimeout(()=>{o=i?Date.now():0,s=null,r=e.apply(this,n)},l)),r};return c.cancel=()=>{s&&(clearTimeout(s),s=null),o=0},c}function I(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 x=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 A.handleError(new n("GET_H5_URL_PARAMS_ERROR",`获取H5 URL参数失败: ${t instanceof Error?t.message:String(t)}`,"utils"),"utils"),e?null:{}}};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(t){return A.handleError(new n("EXTRACT_URL_PARTS_ERROR",`无效的URL: ${e}`,"utils"),"utils"),{path:"",params:{}}}}const U=e,D=t;function M(){return t()}const N=(e="",t=!1,n="none",r=2e3)=>{uni.showToast({title:e,icon:n,mask:t,duration:r})},j=r.getInstance();function k(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){j.handleError(new n(e,t,"navigation"),"navigation")}async function H(e){return new Promise(t=>{const n=k(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 z(e){return new Promise(t=>{const n=k(e.url,e.params);uni.redirectTo({url:n,success:()=>t(!0),fail:e=>{F("REDIRECT_TO_FAILED",`页面重定向失败: ${n}`),t(!1)}})})}async function G(e){return new Promise(t=>{const n=k(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 B(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 K(e,t=3){for(let n=0;n<t;n++){if(await H(e))return!0;n<t-1&&(await new Promise(e=>setTimeout(e,1e3*(n+1))),console.log(`[navigation] 第${n+2}次尝试跳转...`))}return!1}async function W(e="",t={}){const n=getCurrentPages(),r=t.delta||1;if(n.length>r)return await B(e,t);const s=t.homePage||"pages/index/index",o=s.startsWith("/")?s:`/${s}`;return console.info(`[navigation] 页面栈深度不足,重定向到首页: ${o}`),await G({url:o,params:t.homeParams})}const Y=O(B,300);function q(){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 V(){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&&N("复制内容过长",!1,"error"),!1):await s(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{n.showToast&&N(n.successMessage),t(!0)},fail:()=>{n.showToast&&N(n.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1:(n.showToast&&N("复制内容不能为空",!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 ie(e,t){return await s(()=>new Promise(n=>{n(re(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t}function ae(){return te.getInfo()}function ce(){return te.cleanExpired()}function le(e,t={}){let n=0;return Object.entries(e).forEach(([e,r])=>{ne(e,r,t)&&n++}),n}function ue(e){const t={};return e.forEach(e=>{t[e]=re(e)}),t}function fe(e){if(!e)return;const t=e.split(/[?#]/)[0].match(/\.([^./\\]+)$/);return t?t[1].toLowerCase():void 0}function de(e){if(e&&"string"==typeof e)return{"image/jpeg":"jpg","image/jpg":"jpg","image/png":"png","image/gif":"gif","image/webp":"webp","image/heic":"heic","image/heif":"heif","video/mp4":"mp4","application/pdf":"pdf","text/plain":"txt","application/zip":"zip","application/x-zip-compressed":"zip","application/msword":"doc","application/vnd.openxmlformats-officedocument.wordprocessingml.document":"docx","application/vnd.ms-excel":"xls","application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":"xlsx"}[e.toLowerCase().trim()]}function me(e){const t=e.toLowerCase().replace(/^\./,"");return"jpeg"===t||"jpe"===t?"jpg":t}function ge(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function pe(e){return"string"==typeof e&&e.startsWith("blob:")}function he(e){if(pe(e)&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL)try{URL.revokeObjectURL(e)}catch{}}function ye(e){if("string"!=typeof e)return e;try{return JSON.parse(e)}catch{return e}}function we(e){if(null==e)return"";const t=typeof e;if("string"===t||"number"===t||"boolean"===t)return String(e);if("object"===t)try{return JSON.stringify(e)}catch{return String(e)}return String(e)}function Ee(e){if(!e)return;const t={};return Object.keys(e).forEach(n=>{t[n]=we(e[n])}),t}class Se{isShowing=!1;updateToastThrottled=null;showTitle(e){this.isShowing?this.updateToastThrottled&&this.updateToastThrottled(e):(this.showLoading(e),this.isShowing=!0,this.updateToastThrottled=C(e=>{this.isShowing&&this.showLoading(e)},200,{leading:!0,trailing:!0}))}show(e,t,n={}){const{currentIndex:r,totalCount:s,formatter:o}=n;let i;i=o?o(e,t,r,s):s&&s>1&&r?`上传中 (${r}/${s}) ${t}%`:`上传中 ${t}%`,this.showTitle(i)}hide(){if(!this.isShowing)return;try{this.updateToastThrottled?.cancel?.()}catch{}this.isShowing=!1,this.updateToastThrottled=null;const e="undefined"==typeof uni?null:uni;if(e&&"function"==typeof e.hideLoading)try{e.hideLoading()}catch{}}showLoading(e){const t="undefined"==typeof uni?null:uni;if(t&&"function"==typeof t.showLoading)try{t.showLoading({title:e,mask:!0})}catch{}}}function ve(e,t){return null==t||"number"!=typeof t||!Number.isFinite(t)||t<0?{valid:!0}:e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function Re(e,t){if(0===e.length)return{success:!1,files:e,message:"未选择任何文件"};const{maxSelectFileSizeMB:n,extensions:r}=t,s=t.extensionValidationPolicy||"strict",o=null!=n,i=Array.isArray(r)&&r.length>0,a=i?new Set(r.map(e=>me(e))):null;if(o&&0===n)return{success:!1,files:e,message:"当前不允许选择文件"};let c=!1;for(const t of e){if(o&&!ve(t.size,n).valid)return{success:!1,files:e,message:`部分文件大小超过 ${n}MB 限制`};if(i&&a){const e=t.ext?me(t.ext):void 0;if(e)a.has(e)||(c=!0);else if("allowNoExtension"===s);else if("mimeTypeFallback"===s){const e=de(t.mimeType),n=e?me(e):void 0;n&&a.has(n)||(c=!0)}else c=!0}}return c?{success:!1,files:e,message:`存在不支持的文件类型,仅支持:${r?.join(", ")}`}:{success:!0,files:e}}async function Te(e,t,n,r){const{url:s,maxUploadFileSizeMB:o,showToast:i=!0,beforeUpload:a}=t,c=t.toast||N;if(t.signal?.aborted){const t="已取消上传";return i&&c(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}if("function"==typeof a)try{if(!await Promise.resolve(a(e)))return t.autoRevokeObjectURL&&"h5"===e.platform&&he(e.path),{file:e,success:!1,message:"已取消上传"}}catch(n){console.error("[Upload] beforeUpload 钩子执行异常:",n);const r=n instanceof Error?`上传前检查失败: ${n.message}`:"上传前检查失败";return i&&c(r,!1,"error"),t.autoRevokeObjectURL&&"h5"===e.platform&&he(e.path),{file:e,success:!1,message:r}}if(!s){const t="上传地址不能为空";return i&&c(t,!1,"error"),Promise.resolve({file:e,success:!1,message:t})}const l=ve(e.size,o);return l.valid?"h5"===e.platform&&e.raw instanceof File?function(e,t,n,r){const{url:s,fieldName:o="file",formData:i,headers:a,showToast:c=!0,successMessage:l="上传成功",failMessage:u="上传失败",onProgress:f,uploadTimeoutMs:d,autoRevokeObjectURL:m=!1,showProgressToast:g=!1,progressToastFormatter:p}=t,h=t.toast||N;if(t.signal?.aborted){const t="已取消上传";return c&&h(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(y=>{let w=!1;const E=e.raw;if(!(E&&E instanceof File)){const t="H5 环境缺少原生文件对象";return c&&h(t,!1,"none"),void y({file:e,success:!1,message:t})}const S=m&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&"string"==typeof e.path&&pe(e.path),v=g&&r?.manager||null,R=new XMLHttpRequest,T=n=>{if(!w){if(w=!0,t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",_)}catch{}S&&he(e.path),y(n)}},_=()=>{try{R.abort()}catch{}};if(t.signal)if(t.signal.aborted)try{R.abort()}catch{}else"function"==typeof t.signal.addEventListener&&t.signal.addEventListener("abort",_,{once:!0});const A=new FormData;A.append(o,E,e.name),i&&Object.keys(i).forEach(e=>{const t=i[e];A.append(e,we(t))}),(f||v)&&R.upload.addEventListener("progress",t=>{if(t.lengthComputable){const s=Math.round(t.loaded/t.total*100);f&&f(e,s),v&&(r?.onToastProgressUpdate?r.onToastProgressUpdate(s):v.show(e,s,{currentIndex:n>1?r?.currentIndex:void 0,totalCount:n>1?n:void 0,formatter:p}))}}),R.addEventListener("load",()=>{const t=R.status,r=t>=200&&t<300;let s=R.responseText;if(s=ye(R.responseText),r)c&&1===n&&h(l,!1,"none"),T({file:e,success:!0,statusCode:t,data:s});else{const n=`上传失败,状态码:${t}`;c&&h(n,!1,"none"),T({file:e,success:!1,statusCode:t,data:s,message:n})}}),R.addEventListener("error",()=>{const t=u;c&&h(t,!1,"none"),T({file:e,success:!1,message:t})}),R.addEventListener("timeout",()=>{const t=d?`上传超时(${d}ms)`:"上传超时";c&&h(t,!1,"none"),T({file:e,success:!1,message:t})}),R.addEventListener("abort",()=>{T({file:e,success:!1,message:"上传已取消"})});try{R.open("POST",s),"number"==typeof d&&d>0&&(R.timeout=d),a&&Object.keys(a).forEach(e=>{R.setRequestHeader(e,a[e])}),R.send(A)}catch(t){const n=t instanceof Error?`上传请求失败: ${t.message}`:u;c&&h(n,!1,"none"),T({file:e,success:!1,message:n})}})}(e,t,n,r):function(e,t,n,r){const{url:s,fieldName:o="file",formData:i,headers:a,showToast:c=!0,successMessage:l="上传成功",failMessage:u="上传失败",onProgress:f,uploadTimeoutMs:d,showProgressToast:m=!1,progressToastFormatter:g}=t,p="undefined"==typeof uni?null:uni,h=t.toast||N;if(!p||"function"!=typeof p.uploadFile){const t="当前环境不支持文件上传";return c&&h(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}if(t.signal?.aborted){const t="已取消上传";return c&&h(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(y=>{let w=!1,E=null;const S=m&&r?.manager||null,v=e=>{if(!w){if(w=!0,E&&(clearTimeout(E),E=null),t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",T)}catch{}y(e)}};let R=null;"number"==typeof d&&d>0&&(E=setTimeout(()=>{try{R&&"function"==typeof R.abort&&R.abort()}catch{}const t=`上传超时(${d}ms)`;c&&h(t,!1,"none"),v({file:e,success:!1,message:t})},d)),R=p.uploadFile({url:s,filePath:e.path,name:o,formData:Ee(i),header:a,success:t=>{let r=t.data;r=ye(t.data);const s=function(e){if(e&&"number"==typeof e.statusCode)return e.statusCode;if(e&&"number"==typeof e.status)return e.status;const t="string"==typeof e?.errMsg?e.errMsg:"";return/:ok\b/i.test(t)?200:0}(t);if(s>=200&&s<300)c&&1===n&&h(l,!1,"none"),v({file:e,success:!0,statusCode:s,data:r});else{const t=s?`上传失败,状态码:${s}`:"上传失败";c&&h(t,!1,"none"),v({file:e,success:!1,statusCode:s||void 0,data:r,message:t})}},fail:t=>{const n=t?.errMsg||u;c&&h(n,!1,"none"),v({file:e,success:!1,message:n})}});const T=()=>{try{R&&"function"==typeof R.abort&&R.abort()}catch{}const t="已取消上传";c&&h(t,!1,"none"),v({file:e,success:!1,message:t})};t.signal&&(t.signal.aborted?T():"function"==typeof t.signal.addEventListener&&t.signal.addEventListener("abort",T,{once:!0})),(f||S)&&R&&"function"==typeof R.onProgressUpdate&&R.onProgressUpdate(t=>{f&&f(e,t.progress),S&&(r?.onToastProgressUpdate?r.onToastProgressUpdate(t.progress):S.show(e,t.progress,{currentIndex:n>1?r?.currentIndex:void 0,totalCount:n>1?n:void 0,formatter:g}))})})}(e,t,n,r):(i&&l.message&&c(l.message,!1,"error"),Promise.resolve({file:e,success:!1,message:l.message}))}async function _e(e){const{showToast:t=!0,failMessage:n="选择文件失败"}=e,r=e.toast||N;if(e.signal?.aborted){const e="已取消上传";return t&&e&&r(e,!1,"none"),[{file:null,success:!1,message:e}]}try{const s=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||"undefined"==typeof window)return void s({success:!1,files:[],message:"当前环境不支持文件选择"});const o="number"==typeof n&&Number.isFinite(n)&&n>0?Math.floor(n):1,i=document.createElement("input");i.type="file",i.multiple=o>1,"image"===t?i.accept="image/*":r&&r.length>0&&(i.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(","));let a=!1,c=null;const l=e=>{a||(a=!0,f(),s(e))},u=()=>{l({success:!1,files:[],message:"用户取消选择"})},f=()=>{c&&(clearTimeout(c),c=null);try{i.removeEventListener("change",m)}catch{}try{i.removeEventListener("cancel",g)}catch{}try{window.removeEventListener("focus",p)}catch{}try{document.removeEventListener("visibilitychange",h)}catch{}try{window.removeEventListener("pagehide",y)}catch{}try{window.removeEventListener("beforeunload",w)}catch{}if(e.signal&&"function"==typeof e.signal.removeEventListener)try{e.signal.removeEventListener("abort",E)}catch{}try{i.parentNode&&i.parentNode.removeChild(i)}catch{}},d=t=>{if(!t||0===t.length)return void u();const n=Array.from(t).slice(0,o),r=[],s=Re(n.map((e,t)=>{const n=fe(e.name),s=URL.createObjectURL(e);return r.push(s),{id:ge(t),name:e.name,size:e.size,path:s,mimeType:e.type,ext:n,source:"file",platform:"h5",raw:e}}),e);s.success||r.forEach(he),l(s)},m=e=>{const t=e.target;d(t?.files)},g=()=>{u()},p=()=>{a||(c&&(clearTimeout(c),c=null),c=setTimeout(()=>{a||d(i.files)},0))},h=()=>{a||"string"==typeof document.visibilityState&&"visible"===document.visibilityState&&p()};function y(){f()}function w(){f()}function E(){u()}if(e.signal){if(e.signal.aborted)return void u();"function"==typeof e.signal.addEventListener&&e.signal.addEventListener("abort",E,{once:!0})}i.addEventListener("change",m),i.addEventListener("cancel",g),window.addEventListener("focus",p),document.addEventListener("visibilitychange",h),window.addEventListener("pagehide",y),window.addEventListener("beforeunload",w),i.style.display="none",document.body.appendChild(i),i.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})},i=function(){let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}();"image"!==t||"weixin"!==i||"function"!=typeof s.chooseMedia?"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:ge(t),name:`file_${t}`,size:e.size,path:e.path,ext:n,source:"file",platform:i,raw:e}});r(Re(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:ge(t),name:e.name,size:e.size,path:e.path,ext:n,source:"file",platform:i,raw:e}});r(Re(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:ge(t),name:`image_${t}`,size:e.size,path:e.path,ext:n,source:"album",platform:i,raw:e}});r(Re(n,e))},fail:o}):s.chooseMedia({count:n,mediaType:["image"],success:t=>{const n=(Array.isArray(t?.tempFiles)?t.tempFiles:[]).map((e,t)=>{const n=e?.tempFilePath||e?.path||e?.filePath||"",r=fe(n),s="number"==typeof e?.size?e.size:"number"==typeof e?.fileSize?e.fileSize:"number"==typeof e?.originalFileSize?e.originalFileSize:0;return{id:ge(t),name:`image_${t}`,size:s,path:n,mimeType:"string"==typeof e?.type?e.type:void 0,ext:r,source:"album",platform:i,raw:e}});r(Re(n,e))},fail:o})})}(e)}(e);if(!s.success){const e=s.message||n;return t&&e&&r(e,!1,"none"),[{file:null,success:!1,message:e}]}const o=s.files;if(0===o.length)return[];if(e.signal?.aborted){const e="已取消上传";return t&&r(e,!1,"none"),[{file:null,success:!1,message:e}]}const i=o.length;return await async function(e,t,n){const r=new Array(e.length),s=t.showProgressToast?new Se:null,o=t.concurrency&&t.concurrency>0?Math.min(t.concurrency,e.length):e.length;let i=0;const a=Boolean(s)&&o>1&&n>1,c=a?new Array(n).fill(0):null;let l=0,u=0;const f=()=>{if(!a||!s||!c)return;const e=Math.round(l/n);s.showTitle(`上传中 (${u}/${n}) ${e}%`)},d=(e,t)=>{if(!a||!c)return;const n=Math.max(0,Math.min(100,Math.round(t))),r=c[e]||0;r!==n&&(c[e]=n,l+=n-r)};a&&f();const m=async()=>{for(;!t.signal?.aborted;){const o=i;if(o>=e.length)break;i+=1;const l=e[o];let m={file:l,success:!1,message:"上传失败"};try{m=await Te(l,t,n,{manager:s,currentIndex:o+1,onToastProgressUpdate:a&&c?e=>{d(o,e),f()}:void 0})}catch(e){console.error("[Upload] worker 未预期异常:",e);const n=e instanceof Error?`上传失败: ${e.message}`:"上传失败";(t.showToast??1)&&(t.toast||N)(n,!1,"none"),m={file:l,success:!1,message:n}}finally{r[o]=m,a&&c&&(d(o,100),u+=1,f())}}},g=[];for(let e=0;e<o;e+=1)g.push(m());try{await Promise.all(g)}finally{s&&s.hide()}if(t.signal?.aborted)for(let t=0;t<r.length;t+=1)void 0===r[t]&&(r[t]={file:e[t],success:!1,message:"已取消上传"});return r}(o,e,i)}catch(e){const s=n;return t&&s&&r(s,!1,"none"),[{file:null,success:!1,message:s}]}}async function Ae(e){return _e({...e,type:"image"})}const Pe=r.getInstance();let be=!1,Le=null;const Oe=(e="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js")=>"undefined"!=typeof window&&window.document?be||window.ap?(be=!0,Promise.resolve(!0)):Le||(Le=new Promise(t=>{let r=!1,s=null,o=null,i=!1,a=null,c=null,l=null;const u=(e,i,u)=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&(clearInterval(o),o=null),a&&c&&a.removeEventListener("load",c),a&&l&&a.removeEventListener("error",l),!e&&i&&u&&Pe.handleError(new n(i,u,"payment"),"payment"),e&&(be=!0),Le=null,t(e))};try{const t=(()=>{try{return new URL(e,window.location.href).href}catch{return e}})(),n=document.getElementsByTagName("script");let r=null;for(let e=0;e<n.length;e++){const s=n[e];if(s&&s.src===t){r=s;break}}const f=r??document.createElement("script");i=!r,a=f;const d=()=>{window.ap&&u(!0)},m=e=>{i&&f.parentNode&&f.parentNode.removeChild(f),u(!1,"ALIPAY_SDK_LOAD_ERROR",`支付宝 JSSDK 加载失败: ${String(e?.type||"error")}`)};if(c=d,l=m,f.addEventListener("load",d),f.addEventListener("error",m),o=setInterval(()=>{window.ap&&u(!0)},50),s=setTimeout(()=>{i&&f.parentNode&&f.parentNode.removeChild(f),u(!1,"ALIPAY_SDK_LOAD_TIMEOUT","支付宝 JSSDK 加载超时")},1e4),i){f.type="text/javascript",f.src=t,f.async=!0,f.setAttribute("data-uniapp-tools","alipay-jssdk");const e=document.head||document.body||document.documentElement||null;if(!e)return void u(!1,"ALIPAY_SDK_INJECT_ERROR","无法找到可用的 script 注入容器");e.appendChild(f)}window.ap&&u(!0)}catch(e){u(!1,"ALIPAY_SDK_INJECT_ERROR",`注入支付宝 JSSDK 发生异常: ${e instanceof Error?e.message:String(e)}`)}}),Le):(Pe.handleError(new n("ALIPAY_SDK_ENV_ERROR","不在浏览器环境中,无法注入支付宝 JSSDK","payment"),"payment"),Promise.resolve(!1)),Ce=r.getInstance(),Ie=(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){Ce.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)}),xe=r.getInstance(),$e=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),Ue=()=>"undefined"!=typeof window&&"undefined"!=typeof document,De=()=>Ue()&&$e()&&window.wx||null,Me=(e,t=!1)=>{const n={};return e.forEach(e=>{"string"==typeof e&&""!==e.trim()&&(n[e]=t)}),n};let Ne=!1,je=null,ke=!1;const Fe=(e={})=>{const{timeoutMs:t=1e4}=e;if(Ne||Ue()&&window.wx)return Ne=!0,Promise.resolve(!0);if(!Ue())return Promise.resolve(!1);if(je)return je;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 je=new Promise(e=>{let r=!1,s=null,o=null,i=0;const a=t=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&o.parentNode&&o.parentNode.removeChild(o),t&&(Ne=!0),je=null,e(t))},c=()=>{if(i>=n.length)return void a(!1);if(!document.head)return void a(!1);const e=n[i];i+=1;const t=document.createElement("script");o=t,t.src=e,t.async=!0,t.onload=()=>a(!0),t.onerror=()=>{t.parentNode&&t.parentNode.removeChild(t),o=null,c()},document.head.appendChild(t)};s=setTimeout(()=>{a(!1)},t),c()}),je};let He=null;const ze=async(e,t={})=>{const{timeoutMs:r=1e4}=t;return $e()?He||(He=(async()=>{if(!await Fe({timeoutMs:r}))return xe.handleError(new n("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;const t=De();if(!t||"function"!=typeof t.config||"function"!=typeof t.ready||"function"!=typeof t.error)return!1;const s=t.config,o=t.ready,i=t.error,a=await new Promise(t=>{let a=!1,c=null;const l=e=>{a||(a=!0,c&&(clearTimeout(c),c=null),t(e))};c=setTimeout(()=>l(!1),r);try{s({debug:e.debug||!1,appId:e.appId,timestamp:e.timestamp,nonceStr:e.nonceStr,signature:e.signature,jsApiList:e.jsApiList}),o(()=>l(!0)),i(e=>{xe.handleError(new n("WECHAT_JSSDK_CONFIG_ERROR",`微信 JS-SDK 配置错误: ${(e=>{try{return JSON.stringify(e)}catch{return String(e)}})(e)}`,"weixin"),"weixin"),l(!1)})}catch(e){xe.handleError(new n("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),l(!1)}});return ke=a,a})().finally(()=>{He=null}),He):(console.warn("当前不在微信环境中"),!1)},Ge=(e,t={})=>{const{timeoutMs:r=8e3}=t;return new Promise(t=>{const s=De();if(!s||"function"!=typeof s.checkJsApi)return void t(Me(e,!1));let o=!1;const i=e=>{o||(o=!0,t(e))},a=setTimeout(()=>i(Me(e,!1)),r);try{s.checkJsApi({jsApiList:e,success:t=>{clearTimeout(a),i({...Me(e,!1),...t?.checkResult||{}})}})}catch(t){clearTimeout(a),xe.handleError(new n("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${t instanceof Error?t.message:String(t)}`,"weixin"),"weixin"),i(Me(e,!1))}})},Je=e=>{const t=De();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},Be=e=>{const t=De();t&&(t.updateAppMessageShareData?t.updateAppMessageShareData(e):t.onMenuShareAppMessage&&t.onMenuShareAppMessage(e))};class Ke{static instance;isConfigured=!1;config=null;initPromise=null;constructor(){}static getInstance(){return Ke.instance||(Ke.instance=new Ke),Ke.instance}async init(e){return this.initPromise||(this.config=e,this.initPromise=ze(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return(this.isConfigured||ke)&&$e()}getConfig(){return this.config}setShareData(e){this.isReady()?(Je(e),Be(e)):console.warn("微信 SDK 未就绪")}}const We="4.0.0";export{r as ErrorHandler,n as UniAppToolsError,We as VERSION,Ke as WechatSDK,U as areaList,ue as batchGetStorage,le as batchSetStorage,k as buildUrl,Ge as checkWechatJSAPI,ce as cleanExpiredStorage,se as clearStorageSync,u as clearSystemCache,ze as configWechatJSSDK,Q as copyText,O as debounce,P as deepClone,b as deepMerge,$ as extractUrlParts,p as getCurrentEnv,q as getCurrentPageInfo,fe as getExtension,x as getH5UrlParams,w as getMenuButtonBoundingClientRect,R as getNavHeight,E as getNavigationBarHeight,V as getPageStack,m as getPlatform,y as getStatusBarHeight,ie as getStorage,ae as getStorageInfo,re as getStorageSync,S as getTopBarMetrics,v as getTopNavBarHeight,Oe as injectAlipayJsSdk,$e as isWechat,Fe as loadWechatJSSDK,L as mergeObjects,H as navigateTo,h as onCheckForUpdate,G as reLaunch,z as redirectTo,s as safeAsync,K as safeNavigateTo,o as safeSync,_e as selectAndUpload,Ae as selectAndUploadImage,_ as setPageIcon,T as setPageTitle,oe as setStorage,ne as setStorageSync,Be as shareToFriend,Je as shareToTimeline,J as switchTab,C as throttle,B as useBack,Y as useBackDebounced,W as useBackOrHome,D as useCascaderAreaData,M as useRegions,N as useToast,I as useTryCatch,g as useWindowInfo,ve as validateSizeWithLimit,Ie 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 i=r.getInstance();let a=null,c=null,u=null;const l=()=>{u=null},f=e=>"weixin"===e||"alipay"===e;let m=!1;const d=()=>{if(a)return a;let e="unknown";try{"undefined"!=typeof uni&&("undefined"!=typeof wx&&wx.getSystemInfoSync?e="weixin":"undefined"!=typeof my&&my.getSystemInfoSync?e="alipay":"undefined"!=typeof window&&window.document?e="h5":"undefined"!=typeof plus&&(e="app"))}catch(t){e="weixin",e="web",e="app",e="alipay",e="h5"}return a=e,e},g=(e=!0)=>e&&u?u:o(()=>{const t=uni.getWindowInfo();return e&&(u=t),t},"system","GET_WINDOW_INFO_ERROR",null),p=()=>{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 n("GET_ACCOUNT_INFO_ERROR",`获取小程序账户信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),{appId:"",version:"",envVersion:"",accountInfo:{}}}},h=()=>{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 n("UPDATE_DOWNLOAD_FAILED","新版本下载失败","system"),"system"),uni.showModal({title:"更新失败",content:"新版本下载失败,请检查网络连接或稍后重试",showCancel:!1,confirmText:"知道了"})})}catch(e){i.handleError(new n("CHECK_UPDATE_ERROR",`版本更新检查失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system")}},y=()=>{if(null!==c)return c;try{const e=g();return c=e?.statusBarHeight||0,c}catch(e){return i.handleError(new n("GET_STATUS_BAR_HEIGHT_ERROR",`获取状态栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),0}},w=()=>{try{const e=d();return f(e)?uni.getMenuButtonBoundingClientRect():null}catch(e){return i.handleError(new n("GET_MENU_BUTTON_ERROR",`获取菜单按钮边界信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),null}},E=()=>{try{const e=d();if(f(e)){const e=w();return e?.height||44}return 44}catch(e){return i.handleError(new n("GET_NAVIGATION_BAR_HEIGHT_ERROR",`获取导航栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),44}},S=()=>{const e=d(),t=y(),n=E();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},R=()=>{const e=S();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},T=()=>S().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){i.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=d();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),v=r.getInstance();function O(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 v.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=O(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]=O(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 i=n&&!s;return s&&clearTimeout(s),s=setTimeout(()=>{s=null,n||(r=e.apply(this,o))},t),i&&(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:i=!0,trailing:a=!0}=n,c=function(...n){const c=Date.now();o||i||(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&&a&&(s=setTimeout(()=>{o=i?Date.now():0,s=null,r=e.apply(this,n)},u)),r};return c.cancel=()=>{s&&(clearTimeout(s),s=null),o=0},c}function L(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 x=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 v.handleError(new n("GET_H5_URL_PARAMS_ERROR",`获取H5 URL参数失败: ${t instanceof Error?t.message:String(t)}`,"utils"),"utils"),e?null:{}}};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(t){return v.handleError(new n("EXTRACT_URL_PARTS_ERROR",`无效的URL: ${e}`,"utils"),"utils"),{path:"",params:{}}}}const N=e,D=t;function M(){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 F(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 j(e,t){k.handleError(new n(e,t,"navigation"),"navigation")}async function H(e){return new Promise(t=>{const n=F(e.url,e.params);uni.navigateTo({url:n,animationType:e.animationType,animationDuration:e.animationDuration,events:e.events,success:()=>t(!0),fail:e=>{j("NAVIGATE_TO_FAILED",`页面跳转失败: ${n}`),t(!1)}})})}async function B(e){return new Promise(t=>{const n=F(e.url,e.params);uni.redirectTo({url:n,success:()=>t(!0),fail:e=>{j("REDIRECT_TO_FAILED",`页面重定向失败: ${n}`),t(!1)}})})}async function G(e){return new Promise(t=>{const n=F(e.url,e.params);uni.reLaunch({url:n,success:()=>t(!0),fail:e=>{j("RELAUNCH_FAILED",`重新启动失败: ${n}`),t(!1)}})})}async function J(e){return new Promise(t=>{uni.switchTab({url:e,success:()=>t(!0),fail:n=>{j("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){j("PAGE_CALLBACK_ERROR",`页面回调执行失败: ${e instanceof Error?e.message:String(e)}`),n(!0)}},100)},fail:e=>{clearTimeout(o),j("NAVIGATE_BACK_FAILED","导航返回失败"),n(!1)}})})}async function K(e,t=3){for(let n=0;n<t;n++){if(await H(e))return!0;n<t-1&&(await new Promise(e=>setTimeout(e,1e3*(n+1))),console.log(`[navigation] 第${n+2}次尝试跳转...`))}return!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 G({url:o,params:t.homeParams})}const Y=I(W,300);function q(){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 j("GET_CURRENT_PAGE_ERROR",`获取当前页面信息失败: ${e instanceof Error?e.message:String(e)}`),null}}function V(){try{return getCurrentPages().map(e=>({route:e.route||"",options:e.options||{}}))}catch(e){return j("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 ie(e,t){return await s(()=>new Promise(n=>{n(re(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t}function ae(){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}const fe="上传失败",me="已取消上传",de="选择文件失败",ge="用户取消选择",pe=e=>`部分文件大小超过 ${e}MB 限制`,he=e=>`存在不支持的文件类型,仅支持:${e.join(", ")}`,ye="当前环境不支持文件选择",we=e=>`上传超时(${e}ms)`,Ee=e=>`上传请求失败: ${e}`,Se=e=>`上传失败,状态码:${e}`,Re={FILE_TYPE:"image",COUNT:1,SHOW_TOAST:!0};function Te(e){if(!e)return;const t=e.split(/[?#]/)[0].match(/\.([^./\\]+)$/);return t?t[1].toLowerCase():void 0}function _e(e){const t=e.toLowerCase().replace(/^\./,"");return"jpeg"===t||"jpe"===t?"jpg":t}function Ae(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function ve(e){return"string"==typeof e&&e.startsWith("blob:")}function Oe(e){if("string"!=typeof e)return e;try{return JSON.parse(e)}catch{return e}}function Pe(e){if(null==e)return"";const t=typeof e;if("string"===t||"number"===t||"boolean"===t)return String(e);if("object"===t)try{return JSON.stringify(e)}catch{return String(e)}return String(e)}function Ce(e){if(!e)return;const t={};return Object.keys(e).forEach(n=>{t[n]=Pe(e[n])}),t}function Ie(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:"选择文件失败"}function be(e,t){return null==t||"number"!=typeof t||!Number.isFinite(t)||t<0?{valid:!0}:e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function Le(e,t){return!Number.isFinite(t)||t<=0?0:"number"!=typeof e||!Number.isFinite(e)||e<=0?t:Math.min(Math.floor(e),t)}function xe(e){return{toast:e.toast||U,shouldShowToast:e.showToast??Re.SHOW_TOAST}}function $e(e){return Boolean(e?.aborted)}function Ne(e){return[{file:null,success:!1,message:e}]}function De(){return Ne(me)}async function Me(e,t,n){const{url:r,files:s,type:o=Re.FILE_TYPE,count:i=Re.COUNT,maxSizeMB:a,extensions:c,signal:u,successMessage:l}=e,{toast:f,shouldShowToast:m}=xe(e);if(!r.trim()){const e="上传地址不能为空";return m&&f(e,!1,"none"),Ne(e)}if($e(u))return m&&f(me,!1,"none"),De();let d=s||[];if(0===d.length)try{const e=await t({type:o,count:i,extensions:c});if(!e.success)return m&&e.message&&f(e.message,!1,"none"),[{file:null,success:!1,message:e.message}];d=e.files}catch(e){const t=e instanceof Error?e.message:de;return m&&f(t,!1,"none"),Ne(t)}if(0===d.length)return[];const g=function(e,t){if(!e||0===e.length)return{success:!1,message:"未选择任何文件"};const{maxSizeMB:n,extensions:r}=t;if(0===n)return{success:!1,message:"当前不允许选择文件"};const s=null!=n&&"number"==typeof n&&Number.isFinite(n)&&n>0,o=Array.isArray(r)&&r.length>0;if(!s&&!o)return{success:!0};const i=o?new Set(r.map(e=>_e(e))):null;for(const t of e){if(s&&!be(t.size,n).valid)return{success:!1,message:pe(n)};if(o&&i){const e=t.ext?_e(t.ext):void 0;if(!e||!i.has(e))return{success:!1,message:he(r)}}}return{success:!0}}(d,{maxSizeMB:a,extensions:c});if(!g.success){const e=g.message||de;return m&&f(e,!1,"none"),Ne(e)}if($e(u))return m&&f(me,!1,"none"),De();const p=await async function(e,t,n,r){const{concurrency:s,signal:o,beforeUpload:i,onProgress:a,showProgressToast:c,progressToastFormatter:u}=t,{toast:l,shouldShowToast:f}=xe(t),m=new Array(e.length);let d=0;const g=e.length,p=Le(s,g),h=Boolean(c&&g>0),y="undefined"!=typeof uni?uni:null,w=Boolean(h&&y&&"function"==typeof y.showLoading&&"function"==typeof y.hideLoading),E=w,S=b((t,n)=>{if(!w)return;const r=function(e){const{files:t,index:n,pct:r,finishedCount:s,totalCount:o,progressToastFormatter:i}=e;return i?i(t[n],r,n+1,o):1===o?`上传中 ${r}%`:`上传中 (${s}/${o})`}({files:e,index:t,pct:n,finishedCount:d,totalCount:g,progressToastFormatter:u});y.showLoading({title:r,mask:!0})},200);const R=async s=>{const c=e[s];let u=null;try{if($e(o))return u={file:c,success:!1,message:me},void(w&&S(s,0));const e=await async function(e){if(!i)return null;try{return await i(e)?null:{file:e,success:!1,message:me}}catch(t){const n=(e=>`上传前检查失败: ${e}`)(t.message||"unknown");return f&&l(n,!1,"error"),{file:e,success:!1,message:n}}}(c);if(e)return void(u=e);const m=function(e){return E?{...t,onProgress:(t,n)=>{S(e,n),a&&a(t,n)}}:t}(s);u=await r(c,m,n)}catch(e){u={file:c,success:!1,message:e.message||"Unknown error"}}finally{u||(u={file:c,success:!1,message:"Unknown error"}),m[s]=u,d++,u.success&&S(s,100)}};for(let e=0;e<g;e+=p){const t=Math.min(e+p,g),n=[];for(let r=e;r<t;r+=1)n.push(R(r));await Promise.all(n)}return w&&(S.cancel?.(),y.hideLoading()),m}(d,e,r,n);return p.filter(e=>e.success).length===p.length&&1===p.length&&m&&f(l||"上传成功",!1,"none"),p}function Ue(e,t,n,r,s,o,i){return{id:Ae(t),name:i||`file_${t}`,size:n,path:e,ext:Te(i||e),source:r,platform:s,raw:o}}const ke="undefined"!=typeof window&&"undefined"!=typeof document&&!function(){const e="undefined"==typeof uni?null:uni;return Boolean(e&&"function"==typeof e.uploadFile)}(),Fe=ke?function(e){const{type:t="image",count:n=1,extensions:r}=e;return new Promise(e=>{if("undefined"==typeof document||"undefined"==typeof window)return void e({success:!1,files:[],message:ye});const s=document.createElement("input");s.type="file",s.multiple=n>1,s.style.display="none","image"===t?s.accept="image/*":r&&r.length>0&&(s.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(","));let o=!1,i=null;const a=t=>{o||(o=!0,(()=>{i&&(clearTimeout(i),i=null),window.removeEventListener("focus",u);try{s.remove()}catch{}})(),e(t))},c=e=>{if(!e||0===e.length)return void a({success:!1,files:[],message:ge});const t=Array.from(e).slice(0,n).map((e,t)=>({id:Ae(t),name:e.name,size:e.size,path:URL.createObjectURL(e),mimeType:e.type,ext:Te(e.name),source:"file",platform:"h5",raw:e}));a({success:!0,files:t})};s.addEventListener("change",()=>c(s.files)),s.addEventListener("cancel",()=>a({success:!1,files:[],message:ge}));const u=()=>{o||(i=window.setTimeout(()=>{o||(s.files&&0!==s.files.length?c(s.files):a({success:!1,files:[],message:ge}))},300))};window.addEventListener("focus",u),document.body.appendChild(s),s.click()})}:function(e){const{type:t="image",count:n=1}=e;return new Promise(e=>{const r="undefined"==typeof uni?null:uni;if(!r)return void e({success:!1,files:[],message:ye});const s=function(){if("undefined"!=typeof wx&&wx?.getSystemInfoSync)return"weixin";if("undefined"!=typeof my&&my?.getSystemInfoSync)return"alipay";if("undefined"!=typeof window&&"undefined"!=typeof document)return"h5";if("undefined"!=typeof plus)return"app";let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}(),o=t=>{e({success:!1,files:[],message:Ie(t?.errMsg)})},i=[{name:"chooseMedia(image)",when:()=>"image"===t&&"weixin"===s&&"function"==typeof r.chooseMedia,run:()=>{r.chooseMedia({count:n,mediaType:["image"],success:t=>{const n=(Array.isArray(t?.tempFiles)?t.tempFiles:[]).map((e,t)=>{const n=e.size||e.fileSize||e.originalFileSize||0;return Ue(e.tempFilePath,t,n,"album",s,e)});e({success:!0,files:n})},fail:o})}},{name:"chooseImage",when:()=>"image"===t&&"function"==typeof r.chooseImage,run:()=>{r.chooseImage({count:n,success:t=>{const n=(Array.isArray(t?.tempFiles)?t.tempFiles:t?.tempFiles?[t.tempFiles]:[]).map((e,t)=>Ue(e.path,t,e.size,"album",s,e));e({success:!0,files:n})},fail:o})}},{name:"chooseMessageFile(all)",when:()=>"function"==typeof r.chooseMessageFile,run:()=>{r.chooseMessageFile({count:n,type:"all",success:t=>{const n=(Array.isArray(t?.tempFiles)?t.tempFiles:[]).map((e,t)=>Ue(e.path,t,e.size,"file",s,e,e.name));e({success:!0,files:n})},fail:o})}}];for(const e of i)if(e.when())return void e.run();e({success:!1,files:[],message:"当前平台不支持文件选择"})})},je=ke?function(e,t,n){const{fieldName:r="file",formData:s,headers:o,timeoutMs:i,autoRevokeObjectURL:a}=t,{signal:c,onProgress:u}=t;return new Promise(t=>{const l=e.raw;if(!(l&&l instanceof File))return void t({file:e,success:!1,message:"H5 环境缺少原生文件对象"});const f=new XMLHttpRequest;let m=!1;const d=n=>{m||(m=!0,a&&ve(e.path)&&function(e){if(ve(e)&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL)try{URL.revokeObjectURL(e)}catch{}}(e.path),t(n))};if(c){if(c.aborted)return void d({file:e,success:!1,message:me});c.addEventListener("abort",()=>{f.abort(),d({file:e,success:!1,message:me})},{once:!0})}f.open("POST",n),i&&i>0&&(f.timeout=i),o&&Object.keys(o).forEach(e=>{f.setRequestHeader(e,o[e])});const g=new FormData;g.append(r,l,e.name),s&&Object.keys(s).forEach(e=>{g.append(e,Pe(s[e]))}),f.upload.onprogress=t=>{if(t.lengthComputable&&u){const n=Math.round(t.loaded/t.total*100);u(e,n)}},f.onload=()=>{const t=f.status,n=t>=200&&t<300;let r=Oe(f.responseText);d({file:e,success:n,statusCode:t,data:r,message:n?void 0:Se(t)})},f.onerror=()=>d({file:e,success:!1,message:fe}),f.ontimeout=()=>d({file:e,success:!1,message:we(i||0)}),f.onabort=()=>d({file:e,success:!1,message:me});try{f.send(g)}catch(t){const n=t instanceof Error?t.message:"Unknown error";d({file:e,success:!1,message:Ee(n)})}})}:function(e,t,n){const{fieldName:r="file",formData:s,headers:o,timeoutMs:i}=t,{signal:a,onProgress:c}=t;return new Promise(t=>{const u="undefined"==typeof uni?null:uni;if(!u?.uploadFile)return void t({file:e,success:!1,message:"当前环境不支持文件上传"});let l=!1,f=null,m=null;const d=e=>{l||(l=!0,f&&clearTimeout(f),t(e))};i&&i>0&&(f=setTimeout(()=>{m?.abort?.(),d({file:e,success:!1,message:we(i)})},i)),m=u.uploadFile({url:n,filePath:e.path,name:r,header:o,formData:Ce(s),success:t=>{const n=function(e){if(e&&"number"==typeof e.statusCode)return e.statusCode;if(e&&"number"==typeof e.status)return e.status;const t="string"==typeof e?.errMsg?e.errMsg:"";return/:ok\b/i.test(t)?200:0}(t),r=n>=200&&n<300,s=Oe(t.data);d({file:e,success:r,statusCode:n,data:s,message:r?void 0:Se(n)})},fail:t=>{l||d({file:e,success:!1,message:t?.errMsg||fe})}}),c&&m?.onProgressUpdate&&m.onProgressUpdate(t=>{l||"number"!=typeof t.progress||c(e,t.progress)}),a&&(a.aborted?(m?.abort?.(),d({file:e,success:!1,message:me})):a.addEventListener("abort",()=>{m?.abort?.(),d({file:e,success:!1,message:me})},{once:!0}))})};async function He(e){return Me(e,Fe,je)}async function Be(e){return He({...e,type:"image"})}const Ge=r.getInstance();let Je=!1,We=null;const Ke=(e="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js")=>"undefined"!=typeof window&&window.document?Je||window.ap?(Je=!0,Promise.resolve(!0)):We||(We=new Promise(t=>{let r=!1,s=null,o=null,i=!1,a=null,c=null,u=null;const l=(e,i,l)=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&(clearInterval(o),o=null),a&&c&&a.removeEventListener("load",c),a&&u&&a.removeEventListener("error",u),!e&&i&&l&&Ge.handleError(new n(i,l,"payment"),"payment"),e&&(Je=!0),We=null,t(e))};try{const t=(()=>{try{return new URL(e,window.location.href).href}catch{return e}})(),n=document.getElementsByTagName("script");let r=null;for(let e=0;e<n.length;e++){const s=n[e];if(s&&s.src===t){r=s;break}}const f=r??document.createElement("script");i=!r,a=f;const m=()=>{window.ap&&l(!0)},d=e=>{i&&f.parentNode&&f.parentNode.removeChild(f),l(!1,"ALIPAY_SDK_LOAD_ERROR",`支付宝 JSSDK 加载失败: ${String(e?.type||"error")}`)};if(c=m,u=d,f.addEventListener("load",m),f.addEventListener("error",d),o=setInterval(()=>{window.ap&&l(!0)},50),s=setTimeout(()=>{i&&f.parentNode&&f.parentNode.removeChild(f),l(!1,"ALIPAY_SDK_LOAD_TIMEOUT","支付宝 JSSDK 加载超时")},1e4),i){f.type="text/javascript",f.src=t,f.async=!0,f.setAttribute("data-uniapp-tools","alipay-jssdk");const e=document.head||document.body||document.documentElement||null;if(!e)return void l(!1,"ALIPAY_SDK_INJECT_ERROR","无法找到可用的 script 注入容器");e.appendChild(f)}window.ap&&l(!0)}catch(e){l(!1,"ALIPAY_SDK_INJECT_ERROR",`注入支付宝 JSSDK 发生异常: ${e instanceof Error?e.message:String(e)}`)}}),We):(Ge.handleError(new n("ALIPAY_SDK_ENV_ERROR","不在浏览器环境中,无法注入支付宝 JSSDK","payment"),"payment"),Promise.resolve(!1)),ze=r.getInstance(),Ye=(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){ze.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)}),qe=r.getInstance(),Ve=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),Xe=()=>"undefined"!=typeof window&&"undefined"!=typeof document,Qe=()=>Xe()&&Ve()&&window.wx||null,Ze=(e,t=!1)=>{const n={};return e.forEach(e=>{"string"==typeof e&&""!==e.trim()&&(n[e]=t)}),n};let et=!1,tt=null,nt=!1;const rt=(e={})=>{const{timeoutMs:t=1e4}=e;if(et||Xe()&&window.wx)return et=!0,Promise.resolve(!0);if(!Xe())return Promise.resolve(!1);if(tt)return tt;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 tt=new Promise(e=>{let r=!1,s=null,o=null,i=0;const a=t=>{r||(r=!0,s&&(clearTimeout(s),s=null),o&&o.parentNode&&o.parentNode.removeChild(o),t&&(et=!0),tt=null,e(t))},c=()=>{if(i>=n.length)return void a(!1);if(!document.head)return void a(!1);const e=n[i];i+=1;const t=document.createElement("script");o=t,t.src=e,t.async=!0,t.onload=()=>a(!0),t.onerror=()=>{t.parentNode&&t.parentNode.removeChild(t),o=null,c()},document.head.appendChild(t)};s=setTimeout(()=>{a(!1)},t),c()}),tt};let st=null;const ot=async(e,t={})=>{const{timeoutMs:r=1e4}=t;return Ve()?st||(st=(async()=>{if(!await rt({timeoutMs:r}))return qe.handleError(new n("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;const t=Qe();if(!t||"function"!=typeof t.config||"function"!=typeof t.ready||"function"!=typeof t.error)return!1;const s=t.config,o=t.ready,i=t.error,a=await new Promise(t=>{let a=!1,c=null;const u=e=>{a||(a=!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)),i(e=>{qe.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){qe.handleError(new n("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),u(!1)}});return nt=a,a})().finally(()=>{st=null}),st):(console.warn("当前不在微信环境中"),!1)},it=(e,t={})=>{const{timeoutMs:r=8e3}=t;return new Promise(t=>{const s=Qe();if(!s||"function"!=typeof s.checkJsApi)return void t(Ze(e,!1));let o=!1;const i=e=>{o||(o=!0,t(e))},a=setTimeout(()=>i(Ze(e,!1)),r);try{s.checkJsApi({jsApiList:e,success:t=>{clearTimeout(a),i({...Ze(e,!1),...t?.checkResult||{}})}})}catch(t){clearTimeout(a),qe.handleError(new n("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${t instanceof Error?t.message:String(t)}`,"weixin"),"weixin"),i(Ze(e,!1))}})},at=e=>{const t=Qe();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},ct=e=>{const t=Qe();t&&(t.updateAppMessageShareData?t.updateAppMessageShareData(e):t.onMenuShareAppMessage&&t.onMenuShareAppMessage(e))};class ut{static instance;isConfigured=!1;config=null;initPromise=null;constructor(){}static getInstance(){return ut.instance||(ut.instance=new ut),ut.instance}async init(e){return this.initPromise||(this.config=e,this.initPromise=ot(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return(this.isConfigured||nt)&&Ve()}getConfig(){return this.config}setShareData(e){this.isReady()?(at(e),ct(e)):console.warn("微信 SDK 未就绪")}}const lt="5.0.0";export{r as ErrorHandler,n as UniAppToolsError,lt as VERSION,ut as WechatSDK,N as areaList,le as batchGetStorage,ue as batchSetStorage,F as buildUrl,it as checkWechatJSAPI,ce as cleanExpiredStorage,se as clearStorageSync,l as clearSystemCache,ot as configWechatJSSDK,Q as copyText,I as debounce,O as deepClone,P as deepMerge,$ as extractUrlParts,p as getCurrentEnv,q as getCurrentPageInfo,Te as getExtension,x as getH5UrlParams,w as getMenuButtonBoundingClientRect,T as getNavHeight,E as getNavigationBarHeight,V as getPageStack,d as getPlatform,y as getStatusBarHeight,ie as getStorage,ae as getStorageInfo,re as getStorageSync,S as getTopBarMetrics,R as getTopNavBarHeight,Ke as injectAlipayJsSdk,Ve as isWechat,rt as loadWechatJSSDK,C as mergeObjects,H as navigateTo,Le as normalizeConcurrency,h as onCheckForUpdate,G as reLaunch,B as redirectTo,s as safeAsync,K as safeNavigateTo,o as safeSync,He as selectAndUpload,Be as selectAndUploadImage,A as setPageIcon,_ as setPageTitle,oe as setStorage,ne as setStorageSync,ct as shareToFriend,at as shareToTimeline,J as switchTab,b as throttle,W as useBack,Y as useBackDebounced,z as useBackOrHome,D as useCascaderAreaData,M as useRegions,U as useToast,L as useTryCatch,g as useWindowInfo,be as validateSizeWithLimit,Ye as weChatOfficialAccountPayment};
@@ -3,6 +3,9 @@
3
3
  */
4
4
  /**
5
5
  * 显示消息提示框
6
+ *
7
+ * @description
8
+ * 本项目定位:仅在 uni-app 项目中使用(存在 `uni.showToast`)。
6
9
  * @param title 提示的内容,默认为空字符串
7
10
  * @param mask 是否显示透明蒙层,默认为 false
8
11
  * @param icon 图标类型,默认为 'none'
@@ -1,162 +1,24 @@
1
1
  /**
2
- * 多端文件上传工具(全新实现)
3
- * 核心入口:selectAndUpload 一步完成“选择 + 上传”业务流程
4
- * 支持 H5、微信小程序、App 等 uni-app 运行环境
2
+ * 多端文件上传工具 (Refactored)
3
+ * @description
4
+ * 统一对外入口,基于运行时环境检测实现平台代码分离
5
+ *
6
+ * 核心重构目标:
7
+ * 1. H5/Uni 平台实现分离,保证对外 API 行为一致
8
+ * 2. 简化配置参数结构 (UploadOptions)
9
+ * 3. 移除过度抽象 (Settler)
5
10
  */
6
- import { useToast } from '../ui';
7
- /**
8
- * 单个文件的统一描述结构
9
- * 将各平台返回值规整成统一的 UniFile,方便业务使用
10
- */
11
- export interface UniFile {
12
- /** 文件唯一标识(由本工具生成) */
13
- id: string;
14
- /** 文件名 */
15
- name: string;
16
- /** 文件大小(字节) */
17
- size: number;
18
- /** 本地临时路径 / H5 对象 URL */
19
- path: string;
20
- /** MIME 类型(如果可用) */
21
- mimeType?: string;
22
- /** 文件扩展名(不带点,例如:jpg、png) */
23
- ext?: string;
24
- /** 文件来源(相册、相机、本地文件等) */
25
- source?: 'camera' | 'album' | 'file' | 'chat' | 'unknown';
26
- /** 运行平台(仅作标记使用) */
27
- platform?: 'weixin' | 'alipay' | 'h5' | 'app' | 'unknown';
28
- /** 平台原始返回对象,保留以备高级用法 */
29
- raw?: unknown;
30
- }
31
- /**
32
- * 选择 + 上传 一体化配置
33
- */
34
- export interface SelectAndUploadOptions {
35
- /** 上传服务器地址 */
36
- url: string;
37
- /** 选择的文件类型 */
38
- type?: 'image' | 'file' | 'any';
39
- /** 最多可以选择的文件数量 */
40
- count?: number;
41
- /** 选择阶段:单个文件允许的最大体积(MB),超出则认为选择失败 */
42
- maxSelectFileSizeMB?: number;
43
- /** 上传阶段:单个文件允许的最大体积(MB),超出则不会发起上传请求 */
44
- maxUploadFileSizeMB?: number;
45
- /** 允许的文件扩展名(不带点,例如:['jpg','png']) */
46
- extensions?: string[];
47
- /**
48
- * 选择阶段扩展名校验策略(默认 strict,保持向后兼容)
49
- * @description
50
- * - strict:无扩展名或不在白名单中则判定失败(旧行为)
51
- * - mimeTypeFallback:无扩展名时尝试用 `mimeType` 推断扩展名再校验
52
- * - allowNoExtension:无扩展名时跳过扩展名校验(风险:可能放行不期望文件)
53
- */
54
- extensionValidationPolicy?: 'strict' | 'mimeTypeFallback' | 'allowNoExtension';
55
- /** 表单字段名,后端通过此字段接收文件 */
56
- fieldName?: string;
57
- /**
58
- * 额外的表单字段
59
- * @description
60
- * - H5:通过 FormData.append 发送,值会被序列化为字符串(对象/数组默认 JSON.stringify)
61
- * - 小程序/App:通过 uni.uploadFile 的 formData 发送,值同样会被序列化为字符串以保持一致性
62
- */
63
- formData?: Record<string, unknown>;
64
- /** HTTP 请求头 */
65
- headers?: Record<string, string>;
66
- /** 单次最大并发上传数量(默认与文件数相同,即全部并行) */
67
- concurrency?: number;
68
- /** 上传超时(毫秒),超时将中止上传并返回失败结果 */
69
- uploadTimeoutMs?: number;
70
- /**
71
- * H5 环境下是否在上传结束后自动释放 `URL.createObjectURL` 创建的对象 URL
72
- * @description
73
- * - 默认 false:保持旧行为不变(部分业务可能在上传后仍需要用 path 预览)
74
- * - 若业务不再需要该 blob URL,建议开启以减少长时间使用下的内存占用
75
- */
76
- autoRevokeObjectURL?: boolean;
77
- /**
78
- * 上传前拦截钩子
79
- * 返回 false 或 Promise<false> 将跳过该文件的上传,并在结果中标记为失败(不弹 toast)
80
- */
81
- beforeUpload?: (file: UniFile) => boolean | Promise<boolean>;
82
- /** 是否显示 toast 提示,默认 true */
83
- showToast?: boolean;
84
- /** 上传成功的提示信息(仅单文件上传时生效) */
85
- successMessage?: string;
86
- /** 上传失败的默认提示信息 */
87
- failMessage?: string;
88
- /** 上传进度回调 */
89
- onProgress?: (file: UniFile, progress: number) => void;
90
- /**
91
- * 是否显示上传进度 Toast,默认 false
92
- * @description
93
- * - 开启后会使用 uni.showLoading 显示上传进度
94
- * - 单文件上传显示 "上传中 XX%"
95
- * - 多文件上传显示 "上传中 (X/总数) XX%"
96
- * - 进度更新会自动节流(200ms),避免性能问题
97
- */
98
- showProgressToast?: boolean;
99
- /**
100
- * 自定义进度 Toast 内容生成函数
101
- * @param file 当前上传的文件
102
- * @param progress 上传进度(0-100)
103
- * @param currentIndex 当前文件索引(从1开始,多文件上传时有值)
104
- * @param totalCount 总文件数(多文件上传时有值)
105
- * @returns 要显示的 Toast 文案
106
- * @example
107
- * progressToastFormatter: (file, progress, currentIndex, totalCount) => {
108
- * if (totalCount && totalCount > 1) {
109
- * return `正在上传 ${file.name} (${currentIndex}/${totalCount}) ${progress}%`;
110
- * }
111
- * return `上传中 ${progress}%`;
112
- * }
113
- */
114
- progressToastFormatter?: (file: UniFile, progress: number, currentIndex?: number, totalCount?: number) => string;
115
- /** 可选的取消信号(支持 AbortController.signal),上传在收到 signal.aborted 时会中止 */
116
- signal?: AbortSignal;
117
- /**
118
- * 可注入的 toast 函数,默认使用内部 `useToast`,用于降低与 UI 的耦合,便于测试
119
- * 类型与 `useToast` 保持一致
120
- */
121
- toast?: typeof useToast;
122
- }
123
- /**
124
- * 单个文件的上传结果
125
- */
126
- export interface UploadResult {
127
- /** 对应的文件,选择阶段失败时为 null */
128
- file: UniFile | null;
129
- /** 是否上传成功 */
130
- success: boolean;
131
- /** HTTP 状态码(如果有) */
132
- statusCode?: number;
133
- /** 服务器返回的数据(成功或失败时的响应体) */
134
- data?: unknown;
135
- /** 提示信息 */
136
- message?: string;
137
- }
138
- /**
139
- * 根据文件名或路径提取扩展名(不带点)
140
- */
141
- export declare function getExtension(path: string): string | undefined;
142
- /**
143
- * 将文件大小(字节)与 MB 限制进行比较
144
- * @param size 文件大小(字节)
145
- * @param maxMB 限制(MB)
146
- */
147
- export declare function validateSizeWithLimit(size: number, maxMB?: number): {
148
- valid: boolean;
149
- message?: string;
150
- };
11
+ import { UploadOptions, UploadResult } from './types';
151
12
  /**
152
13
  * 选择并上传文件(业务一体化入口)
153
14
  * @param options 选择与上传配置
154
- * @returns 每个文件对应的上传结果列表
155
15
  */
156
- export declare function selectAndUpload(options: SelectAndUploadOptions): Promise<UploadResult[]>;
16
+ export declare function selectAndUpload(options: UploadOptions): Promise<UploadResult[]>;
157
17
  /**
158
18
  * 选择并上传图片的便捷方法
159
19
  * 等价于在 selectAndUpload 中指定 type: 'image'
160
20
  * @param options 业务配置
161
21
  */
162
- export declare function selectAndUploadImage(options: Omit<SelectAndUploadOptions, 'type'>): Promise<UploadResult[]>;
22
+ export declare function selectAndUploadImage(options: Omit<UploadOptions, 'type'>): Promise<UploadResult[]>;
23
+ export * from './types';
24
+ export { getExtension, normalizeConcurrency, validateFileSize as validateSizeWithLimit } from './utils';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-uniapp-tools",
3
- "version": "4.2.1",
3
+ "version": "5.0.1",
4
4
  "type": "module",
5
5
  "description": "一个功能强大、性能优化的 uni-app 开发工具库,提供剪贴板、本地存储、导航、系统信息等常用功能",
6
6
  "main": "dist/my-uniapp-tools.cjs.js",