my-uniapp-tools 4.0.4 → 4.2.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.
@@ -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},m=(e=!0)=>e&&c?c:s(()=>{const t=uni.getWindowInfo();return e&&(c=t),t},"system","GET_WINDOW_INFO_ERROR",null),p=()=>{if(null!==i)return i;try{const e=m();return i=e?.statusBarHeight||0,i}catch(e){return o.handleError(new t("GET_STATUS_BAR_HEIGHT_ERROR",`获取状态栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),0}},g=()=>{try{const e=f();return 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}},d=()=>{try{const e=f();if(l(e)){const e=g();return e?.height||44}return 44}catch(e){return o.handleError(new t("GET_NAVIGATION_BAR_HEIGHT_ERROR",`获取导航栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),44}},h=()=>{const e=f(),t=p(),n=d();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},y=n.getInstance();function E(e){if(null===e||"object"!=typeof e)return e;try{if("undefined"!=typeof structuredClone)try{return structuredClone(e)}catch(e){}return JSON.parse(JSON.stringify(e))}catch(e){throw y.handleError(new t("DEEP_CLONE_ERROR",`深拷贝失败: ${e instanceof Error?e.message:String(e)}`,"utils"),"utils"),new Error(`深拷贝失败: ${e instanceof Error?e.message:String(e)}`)}}function w(e,t,n=!1){let r,s=null;const o=function(...o){const a=n&&!s;return s&&clearTimeout(s),s=setTimeout(()=>{s=null,n||(r=e.apply(this,o))},t),a&&(r=e.apply(this,o)),r};return o.cancel=()=>{s&&(clearTimeout(s),s=null)},o}const S=e.areaList,R=e.useCascaderAreaData,T=(e="",t=!1,n="none",r=2e3)=>{uni.showToast({title:e,icon:n,mask:t,duration:r})},v=n.getInstance();function x(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 _(e,n){v.handleError(new t(e,n,"navigation"),"navigation")}async function A(e){return new Promise(t=>{const n=x(e.url,e.params);uni.navigateTo({url:n,animationType:e.animationType,animationDuration:e.animationDuration,events:e.events,success:()=>t(!0),fail:e=>{_("NAVIGATE_TO_FAILED",`页面跳转失败: ${n}`),t(!1)}})})}async function P(e){return new Promise(t=>{const n=x(e.url,e.params);uni.reLaunch({url:n,success:()=>t(!0),fail:e=>{_("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){_("PAGE_CALLBACK_ERROR",`页面回调执行失败: ${e instanceof Error?e.message:String(e)}`),n(!0)}},100)},fail:e=>{clearTimeout(o),_("NAVIGATE_BACK_FAILED","导航返回失败"),n(!1)}})})}const O=w(C,300),I={showToast:!0,successMessage:"复制成功",failMessage:"复制失败",timeout:5e3},b=n.getInstance();class L{static instance;cache=new Map;maxCacheSize=100;static getInstance(){return L.instance||(L.instance=new L),L.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 b.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 b.handleError(new t("REMOVE_STORAGE_ERROR",`删除存储失败: ${e}`,"localStorage"),"localStorage"),!1}}clear(){try{return uni.clearStorageSync(),this.cache.clear(),!0}catch(e){return b.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 b.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 b.handleError(new t("CLEAN_EXPIRED_ERROR",`清理过期数据失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),0}}}const D=L.getInstance();function N(e,t,n={}){return D.set(e,t,n)}function $(e,t){return D.get(e,t)}function U(e){if(!e)return;const t=e.split(/[?#]/)[0].match(/\.([^./\\]+)$/);return t?t[1].toLowerCase():void 0}function M(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function k(e,t){return null==t?{valid:!0}:e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function H(e,t){if(0===e.length)return{success:!1,files:e,message:"未选择任何文件"};const{maxSelectFileSizeMB:n,extensions:r}=t;if(n&&e.some(e=>!k(e.size,n).valid))return{success:!1,files:e,message:`部分文件大小超过 ${n}MB 限制`};if(r&&r.length>0){const t=r.map(e=>e.toLowerCase());if(e.some(e=>!e.ext||!t.includes(e.ext)))return{success:!1,files:e,message:`存在不支持的文件类型,仅支持:${r.join(", ")}`}}return{success:!0,files:e}}async function j(e,t,n){const{url:r,maxUploadFileSizeMB:s,showToast:o=!0,beforeUpload:a}=t,i=t.toast||T;if(t.signal?.aborted){const t="已取消上传";return o&&i(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}if("function"==typeof a&&!await Promise.resolve(a(e)))return{file:e,success:!1,message:"已取消上传"};if(!r){const t="上传地址不能为空";return o&&T(t,!1,"error"),Promise.resolve({file:e,success:!1,message:t})}const c=k(e.size,s);return c.valid?"h5"===e.platform&&e.raw instanceof File?function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:l="上传失败",onProgress:u,uploadTimeoutMs:f,autoRevokeObjectURL:m=!1}=t,p=t.toast||T;if(t.signal?.aborted){const t="已取消上传";return i&&p(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(g=>{const d=e.raw;if(!(d&&d instanceof File)){const t="H5 环境缺少原生文件对象";return i&&p(t,!1,"none"),void g({file:e,success:!1,message:t})}const h=m&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&"string"==typeof e.path&&e.path.startsWith("blob:"),y=()=>{if(h)try{URL.revokeObjectURL(e.path)}catch{}},E=new XMLHttpRequest,w=()=>{try{E.abort()}catch{}};if(t.signal)if(t.signal.aborted)try{E.abort()}catch{}else"function"==typeof t.signal.addEventListener&&t.signal.addEventListener("abort",w,{once:!0});const S=new FormData;S.append(s,d,e.name),o&&Object.keys(o).forEach(e=>{S.append(e,String(o[e]))}),u&&E.upload.addEventListener("progress",t=>{if(t.lengthComputable){const n=Math.round(t.loaded/t.total*100);u(e,n)}}),E.addEventListener("load",()=>{if(t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}const r=E.status,s=r>=200&&r<300;let o=E.responseText;try{o=JSON.parse(E.responseText)}catch{}if(s)i&&1===n&&T(c,!1,"none"),y(),g({file:e,success:!0,statusCode:r,data:o});else{const t=`上传失败,状态码:${r}`;i&&T(t,!1,"none"),y(),g({file:e,success:!1,statusCode:r,data:o,message:t})}}),E.addEventListener("error",()=>{if(t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}const n=l;i&&p(n,!1,"none"),y(),g({file:e,success:!1,message:n})}),E.addEventListener("timeout",()=>{if(t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}const n=f?`上传超时(${f}ms)`:"上传超时";i&&p(n,!1,"none"),y(),g({file:e,success:!1,message:n})}),E.addEventListener("abort",()=>{if(t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}y(),g({file:e,success:!1,message:"上传已取消"})}),E.open("POST",r),"number"==typeof f&&f>0&&(E.timeout=f),a&&Object.keys(a).forEach(e=>{E.setRequestHeader(e,a[e])}),E.send(S)})}(e,t,n):function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:l="上传失败",onProgress:u,uploadTimeoutMs:f}=t,m="undefined"==typeof uni?null:uni,p=t.toast||T;if(!m||"function"!=typeof m.uploadFile){const t="当前环境不支持文件上传";return i&&p(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}if(t.signal?.aborted){const t="已取消上传";return i&&p(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(g=>{let d=!1,h=null;const y=e=>{if(!d){if(d=!0,h&&(clearTimeout(h),h=null),t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}g(e)}};let E=null;"number"==typeof f&&f>0&&(h=setTimeout(()=>{try{E&&"function"==typeof E.abort&&E.abort()}catch{}const t=`上传超时(${f}ms)`;i&&T(t,!1,"none"),y({file:e,success:!1,message:t})},f)),E=m.uploadFile({url:r,filePath:e.path,name:s,formData:o,header:a,success:t=>{let r=t.data;try{r=JSON.parse(t.data)}catch{}const s=t.statusCode;if(s>=200&&s<300)i&&1===n&&p(c,!1,"none"),y({file:e,success:!0,statusCode:s,data:r});else{const t=`上传失败,状态码:${s}`;i&&p(t,!1,"none"),y({file:e,success:!1,statusCode:s,data:r,message:t})}},fail:t=>{const n=t?.errMsg||l;i&&p(n,!1,"none"),y({file:e,success:!1,message:n})}});const w=()=>{try{E&&"function"==typeof E.abort&&E.abort()}catch{}const t="已取消上传";i&&p(t,!1,"none"),y({file:e,success:!1,message:t})};t.signal&&(t.signal.aborted?w():"function"==typeof t.signal.addEventListener&&t.signal.addEventListener("abort",w,{once:!0})),u&&E&&"function"==typeof E.onProgressUpdate&&E.onProgressUpdate(t=>{u(e,t.progress)})})}(e,t,n):(o&&c.message&&T(c.message,!1,"error"),Promise.resolve({file:e,success:!1,message:c.message}))}async function B(e){const{showToast:t=!0,failMessage:n="选择文件失败"}=e,r=e.toast||T;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)return void s({success:!1,files:[],message:"当前环境不支持文件选择"});const o=document.createElement("input");o.type="file",o.multiple=n>1,"image"===t?o.accept="image/*":r&&r.length>0&&(o.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(",")),o.onchange=t=>{const n=t.target,r=n?.files;if(!r||0===r.length)return s({success:!1,files:[],message:"用户取消选择"}),void document.body.removeChild(o);const a=H(Array.from(r).map((e,t)=>{const n=U(e.name),r=URL.createObjectURL(e);return{id:M(t),name:e.name,size:e.size,path:r,mimeType:e.type,ext:n,source:"file",platform:"h5",raw:e}}),e);s(a),document.body.removeChild(o)},o.style.display="none",document.body.appendChild(o),o.click()})}(e):function(e){const{type:t="image",count:n=1}=e;return new Promise(r=>{const s="undefined"==typeof uni?null:uni;if(!s)return void r({success:!1,files:[],message:"当前环境不支持文件选择"});const o=e=>{const t=function(e){const t=(e||"").trim();if(!t)return"选择文件失败";const n=t.toLowerCase();return n.includes("fail cancel")||n.includes("cancel")?"用户取消选择":/[\u4e00-\u9fff]/.test(t)?t:"选择文件失败"}(e?.errMsg);r({success:!1,files:[],message:t})},a=function(){let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}();"image"!==t||"function"!=typeof s.chooseImage?"function"!=typeof s.chooseMessageFile?"function"!=typeof s.chooseFile?r({success:!1,files:[],message:"当前平台不支持文件选择"}):s.chooseFile({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=U(e.path);return{id:M(t),name:`file_${t}`,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(H(n,e))},fail:o}):s.chooseMessageFile({count:n,type:"all",success:t=>{const n=t.tempFiles.map((e,t)=>{const n=U(e.name||e.path);return{id:M(t),name:e.name,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(H(n,e))},fail:o}):s.chooseImage({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=U(e.path);return{id:M(t),name:`image_${t}`,size:e.size,path:e.path,ext:n,source:"album",platform:a,raw:e}});r(H(n,e))},fail:o})})}(e)}(e);if(!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.concurrency&&t.concurrency>0?Math.min(t.concurrency,e.length):e.length;let o=0;const a=async()=>{for(;!t.signal?.aborted;){const s=o;if(s>=e.length)break;o+=1;const a=e[s],i=await j(a,t,n);r[s]=i}},i=[];for(let e=0;e<s;e+=1)i.push(a());if(await Promise.all(i),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 F=n.getInstance();let J=!1,G=null;const W=n.getInstance(),K=n.getInstance(),z=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),Y=()=>"undefined"!=typeof window&&"undefined"!=typeof document,q=()=>Y()&&z()&&window.wx||null,V=(e,t=!1)=>{const n={};return e.forEach(e=>{"string"==typeof e&&""!==e.trim()&&(n[e]=t)}),n};let X=!1,Q=null,Z=!1;const ee=(e={})=>{const{timeoutMs:t=1e4}=e;if(X||Y()&&window.wx)return X=!0,Promise.resolve(!0);if(!Y())return Promise.resolve(!1);if(Q)return Q;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 Q=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&&(X=!0),Q=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()}),Q};let te=null;const ne=async(e,n={})=>{const{timeoutMs:r=1e4}=n;return z()?te||(te=(async()=>{if(!await ee({timeoutMs:r}))return K.handleError(new t("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;const n=q();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=>{K.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){K.handleError(new t("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),l(!1)}});return Z=i,i})().finally(()=>{te=null}),te):(console.warn("当前不在微信环境中"),!1)},re=e=>{const t=q();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},se=e=>{const t=q();t&&(t.updateAppMessageShareData?t.updateAppMessageShareData(e):t.onMenuShareAppMessage&&t.onMenuShareAppMessage(e))};class oe{static instance;isConfigured=!1;config=null;initPromise=null;constructor(){}static getInstance(){return oe.instance||(oe.instance=new oe),oe.instance}async init(e){return this.initPromise||(this.config=e,this.initPromise=ne(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return(this.isConfigured||Z)&&z()}getConfig(){return this.config}setShareData(e){this.isReady()?(re(e),se(e)):console.warn("微信 SDK 未就绪")}}exports.ErrorHandler=n,exports.UniAppToolsError=t,exports.VERSION="4.0.0",exports.WechatSDK=oe,exports.areaList=S,exports.batchGetStorage=function(e){const t={};return e.forEach(e=>{t[e]=$(e)}),t},exports.batchSetStorage=function(e,t={}){let n=0;return Object.entries(e).forEach(([e,r])=>{N(e,r,t)&&n++}),n},exports.buildUrl=x,exports.checkWechatJSAPI=(e,n={})=>{const{timeoutMs:r=8e3}=n;return new Promise(n=>{const s=q();if(!s||"function"!=typeof s.checkJsApi)return void n(V(e,!1));let o=!1;const a=e=>{o||(o=!0,n(e))},i=setTimeout(()=>a(V(e,!1)),r);try{s.checkJsApi({jsApiList:e,success:t=>{clearTimeout(i),a({...V(e,!1),...t?.checkResult||{}})}})}catch(n){clearTimeout(i),K.handleError(new t("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${n instanceof Error?n.message:String(n)}`,"weixin"),"weixin"),a(V(e,!1))}})},exports.cleanExpiredStorage=function(){return D.cleanExpired()},exports.clearStorageSync=function(e){return e?D.remove(e):D.clear()},exports.clearSystemCache=()=>{c=null},exports.configWechatJSSDK=ne,exports.copyText=async function(e,t={}){const n={...I,...t};return e&&"string"==typeof e?e.length>1e4?(n.showToast&&T("复制内容过长",!1,"error"),!1):await r(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{n.showToast&&T(n.successMessage),t(!0)},fail:()=>{n.showToast&&T(n.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1:(n.showToast&&T("复制内容不能为空",!1,"error"),!1)},exports.debounce=w,exports.deepClone=E,exports.deepMerge=function(e,t){const n=E(e);return function e(t,n){for(const r in n)if(n.hasOwnProperty(r)){const s=n[r],o=t[r];s&&"object"==typeof s&&!Array.isArray(s)&&o&&"object"==typeof o&&!Array.isArray(o)?e(o,s):t[r]=E(s)}}(n,t),n},exports.extractUrlParts=function(e){try{const t=new URL(e,"http://localhost"),n=t.pathname,r={};return t.searchParams.forEach((e,t)=>{r[t]=e}),{path:n,params:r}}catch(n){return y.handleError(new t("EXTRACT_URL_PARTS_ERROR",`无效的URL: ${e}`,"utils"),"utils"),{path:"",params:{}}}},exports.getCurrentEnv=()=>{try{const e=uni.getAccountInfoSync();return{appId:e.miniProgram?.appId||"",version:e.miniProgram?.version||"",envVersion:e.miniProgram?.envVersion||"",accountInfo:e}}catch(e){return o.handleError(new t("GET_ACCOUNT_INFO_ERROR",`获取小程序账户信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),{appId:"",version:"",envVersion:"",accountInfo:{}}}},exports.getCurrentPageInfo=function(){try{const e=getCurrentPages();if(0===e.length)return null;const t=e[e.length-1];return{route:t.route||"",options:t.options||{}}}catch(e){return _("GET_CURRENT_PAGE_ERROR",`获取当前页面信息失败: ${e instanceof Error?e.message:String(e)}`),null}},exports.getExtension=U,exports.getH5UrlParams=e=>{try{if("undefined"==typeof window||!window.location)throw new Error("不在 H5 浏览器环境中");const t=new URLSearchParams(window.location.search),n={};return t.forEach((e,t)=>{try{n[t]=decodeURIComponent(e)}catch(r){n[t]=e}}),console.log("🔗 H5 URL参数解析:",{fullUrl:window.location.href,searchParams:window.location.search,parsedParams:n,paramName:e}),e?n.hasOwnProperty(e)?n[e]:null:n}catch(n){return y.handleError(new t("GET_H5_URL_PARAMS_ERROR",`获取H5 URL参数失败: ${n instanceof Error?n.message:String(n)}`,"utils"),"utils"),e?null:{}}},exports.getMenuButtonBoundingClientRect=g,exports.getNavHeight=()=>h().totalTopHeight,exports.getNavigationBarHeight=d,exports.getPageStack=function(){try{return getCurrentPages().map(e=>({route:e.route||"",options:e.options||{}}))}catch(e){return _("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($(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t},exports.getStorageInfo=function(){return D.getInfo()},exports.getStorageSync=$,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?J||window.ap?(J=!0,Promise.resolve(!0)):G||(G=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&&F.handleError(new t(a,u,"payment"),"payment"),e&&(J=!0),G=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&&u(!0)},p=e=>{a&&f.parentNode&&f.parentNode.removeChild(f),u(!1,"ALIPAY_SDK_LOAD_ERROR",`支付宝 JSSDK 加载失败: ${String(e?.type||"error")}`)};if(c=m,l=p,f.addEventListener("load",m),f.addEventListener("error",p),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)}`)}}),G):(F.handleError(new t("ALIPAY_SDK_ENV_ERROR","不在浏览器环境中,无法注入支付宝 JSSDK","payment"),"payment"),Promise.resolve(!1)),exports.isWechat=z,exports.loadWechatJSSDK=ee,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=A,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=P,exports.redirectTo=async function(e){return new Promise(t=>{const n=x(e.url,e.params);uni.redirectTo({url:n,success:()=>t(!0),fail:e=>{_("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 A(e))return!0;n<t-1&&(await new Promise(e=>setTimeout(e,1e3*(n+1))),console.log(`[navigation] 第${n+2}次尝试跳转...`))}return!1},exports.safeSync=s,exports.selectAndUpload=B,exports.selectAndUploadImage=async function(e){return B({...e,type:"image"})},exports.setPageIcon=(e,t="image/x-icon")=>s(()=>{const n=f();if("h5"===n||"web"===n){if("undefined"!=typeof document){document.querySelectorAll('link[rel*="icon"]').forEach(e=>e.remove());const n=document.createElement("link");return n.rel="icon",n.type=t,n.href=e,document.head.appendChild(n),!0}}else console.warn("setPageIcon 仅在H5/Web平台有效");return!1},"system","SET_PAGE_ICON_ERROR",!1),exports.setPageTitle=e=>"string"!=typeof e?(console.warn("setPageTitle: title必须是字符串"),Promise.resolve(!1)):""===e.trim()?(console.warn("setPageTitle: title不能为空"),Promise.resolve(!1)):new Promise(n=>{try{uni.setNavigationBarTitle({title:e,success:()=>{n(!0)},fail:e=>{console.warn("设置页面标题失败:",e),n(!1)}})}catch(e){o.handleError(new t("SET_PAGE_TITLE_ERROR",`setPageTitle执行异常: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),n(!1)}}),exports.setStorage=async function(e,t,n={}){return await r(()=>new Promise(r=>{r(N(e,t,n))}),"localStorage","SET_STORAGE_ASYNC_ERROR")??!1},exports.setStorageSync=N,exports.shareToFriend=se,exports.shareToTimeline=re,exports.switchTab=async function(e){return new Promise(t=>{uni.switchTab({url:e,success:()=>t(!0),fail:n=>{_("SWITCH_TAB_FAILED",`Tab切换失败: ${e}`),t(!1)}})})},exports.throttle=function(e,t,n={}){let r,s=null,o=0;const{leading:a=!0,trailing:i=!0}=n,c=function(...n){const c=Date.now();o||a||(o=c);const 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},exports.useBack=C,exports.useBackDebounced=O,exports.useBackOrHome=async function(e="",t={}){const n=getCurrentPages(),r=t.delta||1;if(n.length>r)return await C(e,t);const 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=R,exports.useRegions=function(){return e.useCascaderAreaData()},exports.useToast=T,exports.useTryCatch=function(e,t={}){return async(...n)=>{try{return{data:await e(...n),error:null}}catch(e){return t.onError?.(e),{data:null,error:e}}finally{t.onFinally?.()}}},exports.useWindowInfo=m,exports.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){W.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 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 +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 a=r.getInstance();let i=null,c=null,l=null;const u=()=>{l=null},f=e=>"weixin"===e||"alipay"===e;let m=!1;const d=()=>{if(i)return i;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 i=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 a.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){a.handleError(new n("UPDATE_DOWNLOAD_FAILED","新版本下载失败","system"),"system"),uni.showModal({title:"更新失败",content:"新版本下载失败,请检查网络连接或稍后重试",showCancel:!1,confirmText:"知道了"})})}catch(e){a.handleError(new n("CHECK_UPDATE_ERROR",`版本更新检查失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system")}},y=()=>{if(null!==c)return c;try{const e=g();return c=e?.statusBarHeight||0,c}catch(e){return a.handleError(new n("GET_STATUS_BAR_HEIGHT_ERROR",`获取状态栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),0}},E=()=>{try{const e=d();return f(e)?uni.getMenuButtonBoundingClientRect():null}catch(e){return a.handleError(new n("GET_MENU_BUTTON_ERROR",`获取菜单按钮边界信息失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),null}},w=()=>{try{const e=d();if(f(e)){const e=E();return e?.height||44}return 44}catch(e){return a.handleError(new n("GET_NAVIGATION_BAR_HEIGHT_ERROR",`获取导航栏高度失败: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),44}},R=()=>{const e=d(),t=y(),n=w();return{platform:e,statusBarHeight:t,navigationBarHeight:n,totalTopHeight:t+n}},S=()=>{const e=R();return{statusBarHeight:e.statusBarHeight,navHeight:e.totalTopHeight}},v=()=>R().totalTopHeight,_=e=>"string"!=typeof e?(console.warn("setPageTitle: title必须是字符串"),Promise.resolve(!1)):""===e.trim()?(console.warn("setPageTitle: title不能为空"),Promise.resolve(!1)):new Promise(t=>{try{uni.setNavigationBarTitle({title:e,success:()=>{t(!0)},fail:e=>{console.warn("设置页面标题失败:",e),t(!1)}})}catch(e){a.handleError(new n("SET_PAGE_TITLE_ERROR",`setPageTitle执行异常: ${e instanceof Error?e.message:String(e)}`,"system"),"system"),t(!1)}}),T=(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),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 O(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 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 L(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 I(e,t,n={}){let r,s=null,o=0;const{leading:a=!0,trailing:i=!0}=n,c=function(...n){const c=Date.now();o||a||(o=c);const l=t-(c-o);return l<=0||l>t?(s&&(clearTimeout(s),s=null),o=c,r=e.apply(this,n)):!s&&i&&(s=setTimeout(()=>{o=a?Date.now():0,s=null,r=e.apply(this,n)},l)),r};return c.cancel=()=>{s&&(clearTimeout(s),s=null),o=0},c}function b(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 D=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 x=e,N=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 j(e,t){if(!t||0===Object.keys(t).length)return e;const n=Object.entries(t).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(String(t))}`).join("&");return e+(e.includes("?")?"&":"?")+n}function H(e,t){k.handleError(new n(e,t,"navigation"),"navigation")}async function F(e){return new Promise(t=>{const n=j(e.url,e.params);uni.navigateTo({url:n,animationType:e.animationType,animationDuration:e.animationDuration,events:e.events,success:()=>t(!0),fail:e=>{H("NAVIGATE_TO_FAILED",`页面跳转失败: ${n}`),t(!1)}})})}async function G(e){return new Promise(t=>{const n=j(e.url,e.params);uni.redirectTo({url:n,success:()=>t(!0),fail:e=>{H("REDIRECT_TO_FAILED",`页面重定向失败: ${n}`),t(!1)}})})}async function J(e){return new Promise(t=>{const n=j(e.url,e.params);uni.reLaunch({url:n,success:()=>t(!0),fail:e=>{H("RELAUNCH_FAILED",`重新启动失败: ${n}`),t(!1)}})})}async function B(e){return new Promise(t=>{uni.switchTab({url:e,success:()=>t(!0),fail:n=>{H("SWITCH_TAB_FAILED",`Tab切换失败: ${e}`),t(!1)}})})}async function K(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){H("PAGE_CALLBACK_ERROR",`页面回调执行失败: ${e instanceof Error?e.message:String(e)}`),n(!0)}},100)},fail:e=>{clearTimeout(o),H("NAVIGATE_BACK_FAILED","导航返回失败"),n(!1)}})})}async function W(e,t=3){for(let n=0;n<t;n++){if(await F(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 K(e,t);const s=t.homePage||"pages/index/index",o=s.startsWith("/")?s:`/${s}`;return console.info(`[navigation] 页面栈深度不足,重定向到首页: ${o}`),await J({url:o,params:t.homeParams})}const Y=L(K,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 H("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 H("GET_PAGE_STACK_ERROR",`获取页面栈信息失败: ${e instanceof Error?e.message:String(e)}`),[]}}const X={showToast:!0,successMessage:"复制成功",failMessage:"复制失败",timeout:5e3};async function Q(e,t={}){const n={...X,...t};return e&&"string"==typeof e?e.length>1e4?(n.showToast&&U("复制内容过长",!1,"error"),!1):await s(()=>new Promise(t=>{uni.setClipboardData({data:e,showToast:!1,success:()=>{n.showToast&&U(n.successMessage),t(!0)},fail:()=>{n.showToast&&U(n.failMessage),t(!1)}})}),"clipboard","COPY_TEXT_ERROR")??!1:(n.showToast&&U("复制内容不能为空",!1,"error"),!1)}const Z=r.getInstance();class ee{static instance;cache=new Map;maxCacheSize=100;static getInstance(){return ee.instance||(ee.instance=new ee),ee.instance}isExpired(e){return!!e.ttl&&Date.now()-e.timestamp>e.ttl}set(e,t,r={}){try{if(!e||"string"!=typeof e)throw new Error("存储键不能为空");const n={value:t,timestamp:Date.now(),ttl:r.ttl},s=JSON.stringify(n);if(s.length>1048576)throw new Error("存储数据过大");if(uni.setStorageSync(e,s),this.cache.size>=this.maxCacheSize){const e=this.cache.keys().next().value;e&&this.cache.delete(e)}return this.cache.set(e,n),!0}catch(e){throw Z.handleError(new n("SET_STORAGE_ERROR",`设置存储失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),e}}get(e,t){try{if(!e||"string"!=typeof e)return t;if(this.cache.has(e)){const n=this.cache.get(e);return this.isExpired(n)?(this.cache.delete(e),this.remove(e),t):n.value}const n=uni.getStorageSync(e);if(!n||"string"!=typeof n)return t;const r=JSON.parse(n);let s;return s=r&&"object"==typeof r&&"value"in r&&"timestamp"in r?r:{value:r,timestamp:Date.now()},this.isExpired(s)?(this.remove(e),t):(this.cache.set(e,s),s.value)}catch(n){return console.warn(`[localStorage] 获取存储失败 [${e}]:`,n),t}}remove(e){try{return!(!e||"string"!=typeof e||(uni.removeStorageSync(e),this.cache.delete(e),0))}catch(t){return Z.handleError(new n("REMOVE_STORAGE_ERROR",`删除存储失败: ${e}`,"localStorage"),"localStorage"),!1}}clear(){try{return uni.clearStorageSync(),this.cache.clear(),!0}catch(e){return Z.handleError(new n("CLEAR_STORAGE_ERROR","清空存储失败","localStorage"),"localStorage"),!1}}getInfo(){try{const e=uni.getStorageInfoSync();return{keys:e.keys||[],currentSize:e.currentSize||0,limitSize:e.limitSize||0}}catch(e){return Z.handleError(new n("GET_STORAGE_INFO_ERROR",`获取存储信息失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),{keys:[],currentSize:0,limitSize:0}}}cleanExpired(){try{const e=this.getInfo();let t=0;return e.keys.forEach(e=>{void 0===this.get(e)&&t++}),t}catch(e){return Z.handleError(new n("CLEAN_EXPIRED_ERROR",`清理过期数据失败: ${e instanceof Error?e.message:String(e)}`,"localStorage"),"localStorage"),0}}}const te=ee.getInstance();function ne(e,t,n={}){return te.set(e,t,n)}function re(e,t){return te.get(e,t)}function se(e){return e?te.remove(e):te.clear()}async function oe(e,t,n={}){return await s(()=>new Promise(r=>{r(ne(e,t,n))}),"localStorage","SET_STORAGE_ASYNC_ERROR")??!1}async function ae(e,t){return await s(()=>new Promise(n=>{n(re(e,t))}),"localStorage","GET_STORAGE_ASYNC_ERROR")??t}function ie(){return te.getInfo()}function ce(){return te.cleanExpired()}function 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 me(e){return`${Date.now()}_${e}_${Math.random().toString(16).slice(2)}`}function de(e,t){return null==t?{valid:!0}:e>1024*t*1024?{valid:!1,message:`文件大小不能超过 ${t}MB`}:{valid:!0}}function ge(e,t){if(0===e.length)return{success:!1,files:e,message:"未选择任何文件"};const{maxSelectFileSizeMB:n,extensions:r}=t;if(n&&e.some(e=>!de(e.size,n).valid))return{success:!1,files:e,message:`部分文件大小超过 ${n}MB 限制`};if(r&&r.length>0){const t=r.map(e=>e.toLowerCase());if(e.some(e=>!e.ext||!t.includes(e.ext)))return{success:!1,files:e,message:`存在不支持的文件类型,仅支持:${r.join(", ")}`}}return{success:!0,files:e}}async function pe(e,t,n){const{url:r,maxUploadFileSizeMB:s,showToast:o=!0,beforeUpload:a}=t,i=t.toast||U;if(t.signal?.aborted){const t="已取消上传";return o&&i(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}if("function"==typeof a&&!await Promise.resolve(a(e)))return{file:e,success:!1,message:"已取消上传"};if(!r){const t="上传地址不能为空";return o&&U(t,!1,"error"),Promise.resolve({file:e,success:!1,message:t})}const c=de(e.size,s);return c.valid?"h5"===e.platform&&e.raw instanceof File?function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:l="上传失败",onProgress:u,uploadTimeoutMs:f,autoRevokeObjectURL:m=!1}=t,d=t.toast||U;if(t.signal?.aborted){const t="已取消上传";return i&&d(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(g=>{const p=e.raw;if(!(p&&p instanceof File)){const t="H5 环境缺少原生文件对象";return i&&d(t,!1,"none"),void g({file:e,success:!1,message:t})}const h=m&&"undefined"!=typeof URL&&"function"==typeof URL.revokeObjectURL&&"string"==typeof e.path&&e.path.startsWith("blob:"),y=()=>{if(h)try{URL.revokeObjectURL(e.path)}catch{}},E=new XMLHttpRequest,w=()=>{try{E.abort()}catch{}};if(t.signal)if(t.signal.aborted)try{E.abort()}catch{}else"function"==typeof t.signal.addEventListener&&t.signal.addEventListener("abort",w,{once:!0});const R=new FormData;R.append(s,p,e.name),o&&Object.keys(o).forEach(e=>{R.append(e,String(o[e]))}),u&&E.upload.addEventListener("progress",t=>{if(t.lengthComputable){const n=Math.round(t.loaded/t.total*100);u(e,n)}}),E.addEventListener("load",()=>{if(t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}const r=E.status,s=r>=200&&r<300;let o=E.responseText;try{o=JSON.parse(E.responseText)}catch{}if(s)i&&1===n&&U(c,!1,"none"),y(),g({file:e,success:!0,statusCode:r,data:o});else{const t=`上传失败,状态码:${r}`;i&&U(t,!1,"none"),y(),g({file:e,success:!1,statusCode:r,data:o,message:t})}}),E.addEventListener("error",()=>{if(t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}const n=l;i&&d(n,!1,"none"),y(),g({file:e,success:!1,message:n})}),E.addEventListener("timeout",()=>{if(t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}const n=f?`上传超时(${f}ms)`:"上传超时";i&&d(n,!1,"none"),y(),g({file:e,success:!1,message:n})}),E.addEventListener("abort",()=>{if(t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}y(),g({file:e,success:!1,message:"上传已取消"})}),E.open("POST",r),"number"==typeof f&&f>0&&(E.timeout=f),a&&Object.keys(a).forEach(e=>{E.setRequestHeader(e,a[e])}),E.send(R)})}(e,t,n):function(e,t,n){const{url:r,fieldName:s="file",formData:o,headers:a,showToast:i=!0,successMessage:c="上传成功",failMessage:l="上传失败",onProgress:u,uploadTimeoutMs:f}=t,m="undefined"==typeof uni?null:uni,d=t.toast||U;if(!m||"function"!=typeof m.uploadFile){const t="当前环境不支持文件上传";return i&&d(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}if(t.signal?.aborted){const t="已取消上传";return i&&d(t,!1,"none"),Promise.resolve({file:e,success:!1,message:t})}return new Promise(g=>{let p=!1,h=null;const y=e=>{if(!p){if(p=!0,h&&(clearTimeout(h),h=null),t.signal&&"function"==typeof t.signal.removeEventListener)try{t.signal.removeEventListener("abort",w)}catch{}g(e)}};let E=null;"number"==typeof f&&f>0&&(h=setTimeout(()=>{try{E&&"function"==typeof E.abort&&E.abort()}catch{}const t=`上传超时(${f}ms)`;i&&U(t,!1,"none"),y({file:e,success:!1,message:t})},f)),E=m.uploadFile({url:r,filePath:e.path,name:s,formData:o,header:a,success:t=>{let r=t.data;try{r=JSON.parse(t.data)}catch{}const s=t.statusCode;if(s>=200&&s<300)i&&1===n&&d(c,!1,"none"),y({file:e,success:!0,statusCode:s,data:r});else{const t=`上传失败,状态码:${s}`;i&&d(t,!1,"none"),y({file:e,success:!1,statusCode:s,data:r,message:t})}},fail:t=>{const n=t?.errMsg||l;i&&d(n,!1,"none"),y({file:e,success:!1,message:n})}});const w=()=>{try{E&&"function"==typeof E.abort&&E.abort()}catch{}const t="已取消上传";i&&d(t,!1,"none"),y({file:e,success:!1,message:t})};t.signal&&(t.signal.aborted?w():"function"==typeof t.signal.addEventListener&&t.signal.addEventListener("abort",w,{once:!0})),u&&E&&"function"==typeof E.onProgressUpdate&&E.onProgressUpdate(t=>{u(e,t.progress)})})}(e,t,n):(o&&c.message&&U(c.message,!1,"error"),Promise.resolve({file:e,success:!1,message:c.message}))}async function he(e){const{showToast:t=!0,failMessage:n="选择文件失败"}=e,r=e.toast||U;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)return void s({success:!1,files:[],message:"当前环境不支持文件选择"});const o=document.createElement("input");o.type="file",o.multiple=n>1,"image"===t?o.accept="image/*":r&&r.length>0&&(o.accept=r.map(e=>e.startsWith(".")?e:`.${e}`).join(",")),o.onchange=t=>{const n=t.target,r=n?.files;if(!r||0===r.length)return s({success:!1,files:[],message:"用户取消选择"}),void document.body.removeChild(o);const a=ge(Array.from(r).map((e,t)=>{const n=fe(e.name),r=URL.createObjectURL(e);return{id:me(t),name:e.name,size:e.size,path:r,mimeType:e.type,ext:n,source:"file",platform:"h5",raw:e}}),e);s(a),document.body.removeChild(o)},o.style.display="none",document.body.appendChild(o),o.click()})}(e):function(e){const{type:t="image",count:n=1}=e;return new Promise(r=>{const s="undefined"==typeof uni?null:uni;if(!s)return void r({success:!1,files:[],message:"当前环境不支持文件选择"});const o=e=>{const t=function(e){const t=(e||"").trim();if(!t)return"选择文件失败";const n=t.toLowerCase();return n.includes("fail cancel")||n.includes("cancel")?"用户取消选择":/[\u4e00-\u9fff]/.test(t)?t:"选择文件失败"}(e?.errMsg);r({success:!1,files:[],message:t})},a=function(){let e="unknown";return e="h5",e="weixin",e="alipay",e="app","app"}();"image"!==t||"function"!=typeof s.chooseImage?"function"!=typeof s.chooseMessageFile?"function"!=typeof s.chooseFile?r({success:!1,files:[],message:"当前平台不支持文件选择"}):s.chooseFile({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=fe(e.path);return{id:me(t),name:`file_${t}`,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(ge(n,e))},fail:o}):s.chooseMessageFile({count:n,type:"all",success:t=>{const n=t.tempFiles.map((e,t)=>{const n=fe(e.name||e.path);return{id:me(t),name:e.name,size:e.size,path:e.path,ext:n,source:"file",platform:a,raw:e}});r(ge(n,e))},fail:o}):s.chooseImage({count:n,success:t=>{const n=(Array.isArray(t.tempFiles)?t.tempFiles:[t.tempFiles]).map((e,t)=>{const n=fe(e.path);return{id:me(t),name:`image_${t}`,size:e.size,path:e.path,ext:n,source:"album",platform:a,raw:e}});r(ge(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.concurrency&&t.concurrency>0?Math.min(t.concurrency,e.length):e.length;let o=0;const a=async()=>{for(;!t.signal?.aborted;){const s=o;if(s>=e.length)break;o+=1;const a=e[s],i=await pe(a,t,n);r[s]=i}},i=[];for(let e=0;e<s;e+=1)i.push(a());if(await Promise.all(i),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}]}}async function ye(e){return he({...e,type:"image"})}const Ee=r.getInstance();let we=!1,Re=null;const Se=(e="https://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js")=>"undefined"!=typeof window&&window.document?we||window.ap?(we=!0,Promise.resolve(!0)):Re||(Re=new Promise(t=>{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&&Ee.handleError(new n(a,u,"payment"),"payment"),e&&(we=!0),Re=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");a=!r,i=f;const m=()=>{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=m,l=d,f.addEventListener("load",m),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)}`)}}),Re):(Ee.handleError(new n("ALIPAY_SDK_ENV_ERROR","不在浏览器环境中,无法注入支付宝 JSSDK","payment"),"payment"),Promise.resolve(!1)),ve=r.getInstance(),_e=(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){ve.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)}),Te=r.getInstance(),Ae=()=>!("undefined"==typeof navigator||!navigator.userAgent)&&navigator.userAgent.toLowerCase().includes("micromessenger"),Pe=()=>"undefined"!=typeof window&&"undefined"!=typeof document,Oe=()=>Pe()&&Ae()&&window.wx||null,Ce=(e,t=!1)=>{const n={};return e.forEach(e=>{"string"==typeof e&&""!==e.trim()&&(n[e]=t)}),n};let Le=!1,Ie=null,be=!1;const De=(e={})=>{const{timeoutMs:t=1e4}=e;if(Le||Pe()&&window.wx)return Le=!0,Promise.resolve(!0);if(!Pe())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&&(Le=!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 $e=null;const xe=async(e,t={})=>{const{timeoutMs:r=1e4}=t;return Ae()?$e||($e=(async()=>{if(!await De({timeoutMs:r}))return Te.handleError(new n("WECHAT_JSSDK_LOAD_FAILED","微信 JS-SDK 加载失败","weixin"),"weixin"),!1;const t=Oe();if(!t||"function"!=typeof t.config||"function"!=typeof t.ready||"function"!=typeof t.error)return!1;const s=t.config,o=t.ready,a=t.error,i=await new Promise(t=>{let i=!1,c=null;const l=e=>{i||(i=!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)),a(e=>{Te.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){Te.handleError(new n("WECHAT_JSSDK_CONFIG_EXCEPTION",`微信 JS-SDK 配置异常: ${e instanceof Error?e.message:String(e)}`,"weixin"),"weixin"),l(!1)}});return be=i,i})().finally(()=>{$e=null}),$e):(console.warn("当前不在微信环境中"),!1)},Ne=(e,t={})=>{const{timeoutMs:r=8e3}=t;return new Promise(t=>{const s=Oe();if(!s||"function"!=typeof s.checkJsApi)return void t(Ce(e,!1));let o=!1;const a=e=>{o||(o=!0,t(e))},i=setTimeout(()=>a(Ce(e,!1)),r);try{s.checkJsApi({jsApiList:e,success:t=>{clearTimeout(i),a({...Ce(e,!1),...t?.checkResult||{}})}})}catch(t){clearTimeout(i),Te.handleError(new n("CHECK_WECHAT_JSAPI_ERROR",`检查微信 JS-SDK API 异常: ${t instanceof Error?t.message:String(t)}`,"weixin"),"weixin"),a(Ce(e,!1))}})},Me=e=>{const t=Oe();t&&(t.updateTimelineShareData?t.updateTimelineShareData(e):t.onMenuShareTimeline&&t.onMenuShareTimeline(e))},Ue=e=>{const t=Oe();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=xe(e).then(e=>(this.isConfigured=e,e)).finally(()=>{this.initPromise=null})),this.initPromise}isReady(){return(this.isConfigured||be)&&Ae()}getConfig(){return this.config}setShareData(e){this.isReady()?(Me(e),Ue(e)):console.warn("微信 SDK 未就绪")}}const je="4.0.0";export{r as ErrorHandler,n as UniAppToolsError,je as VERSION,ke as WechatSDK,x as areaList,ue as batchGetStorage,le as batchSetStorage,j as buildUrl,Ne as checkWechatJSAPI,ce as cleanExpiredStorage,se as clearStorageSync,u as clearSystemCache,xe as configWechatJSSDK,Q as copyText,L as debounce,P as deepClone,O as deepMerge,$ as extractUrlParts,p as getCurrentEnv,q as getCurrentPageInfo,fe as getExtension,D as getH5UrlParams,E as getMenuButtonBoundingClientRect,v as getNavHeight,w as getNavigationBarHeight,V as getPageStack,d as getPlatform,y as getStatusBarHeight,ae as getStorage,ie as getStorageInfo,re as getStorageSync,R as getTopBarMetrics,S as getTopNavBarHeight,Se as injectAlipayJsSdk,Ae as isWechat,De as loadWechatJSSDK,C as mergeObjects,F as navigateTo,h as onCheckForUpdate,J as reLaunch,G as redirectTo,s as safeAsync,W as safeNavigateTo,o as safeSync,he as selectAndUpload,ye as selectAndUploadImage,T as setPageIcon,_ as setPageTitle,oe as setStorage,ne as setStorageSync,Ue as shareToFriend,Me as shareToTimeline,B as switchTab,I as throttle,K as useBack,Y as useBackDebounced,z as useBackOrHome,N as useCascaderAreaData,M as useRegions,U as useToast,b as useTryCatch,g as useWindowInfo,de as validateSizeWithLimit,_e 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,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};
@@ -44,10 +44,23 @@ export interface SelectAndUploadOptions {
44
44
  maxUploadFileSizeMB?: number;
45
45
  /** 允许的文件扩展名(不带点,例如:['jpg','png']) */
46
46
  extensions?: string[];
47
+ /**
48
+ * 选择阶段扩展名校验策略(默认 strict,保持向后兼容)
49
+ * @description
50
+ * - strict:无扩展名或不在白名单中则判定失败(旧行为)
51
+ * - mimeTypeFallback:无扩展名时尝试用 `mimeType` 推断扩展名再校验
52
+ * - allowNoExtension:无扩展名时跳过扩展名校验(风险:可能放行不期望文件)
53
+ */
54
+ extensionValidationPolicy?: 'strict' | 'mimeTypeFallback' | 'allowNoExtension';
47
55
  /** 表单字段名,后端通过此字段接收文件 */
48
56
  fieldName?: string;
49
- /** 额外的表单字段 */
50
- formData?: Record<string, string | number>;
57
+ /**
58
+ * 额外的表单字段
59
+ * @description
60
+ * - H5:通过 FormData.append 发送,值会被序列化为字符串(对象/数组默认 JSON.stringify)
61
+ * - 小程序/App:通过 uni.uploadFile 的 formData 发送,值同样会被序列化为字符串以保持一致性
62
+ */
63
+ formData?: Record<string, unknown>;
51
64
  /** HTTP 请求头 */
52
65
  headers?: Record<string, string>;
53
66
  /** 单次最大并发上传数量(默认与文件数相同,即全部并行) */
@@ -74,6 +87,31 @@ export interface SelectAndUploadOptions {
74
87
  failMessage?: string;
75
88
  /** 上传进度回调 */
76
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;
77
115
  /** 可选的取消信号(支持 AbortController.signal),上传在收到 signal.aborted 时会中止 */
78
116
  signal?: AbortSignal;
79
117
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-uniapp-tools",
3
- "version": "4.0.4",
3
+ "version": "4.2.1",
4
4
  "type": "module",
5
5
  "description": "一个功能强大、性能优化的 uni-app 开发工具库,提供剪贴板、本地存储、导航、系统信息等常用功能",
6
6
  "main": "dist/my-uniapp-tools.cjs.js",