ziya-utils 1.1.10 → 1.1.12

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
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ZiyaUtils={})}(this,function(e){"use strict";function t(e,t,n,o){return new(n||(n=Promise))(function(s,r){function i(e){try{c(o.next(e))}catch(e){r(e)}}function a(e){try{c(o.throw(e))}catch(e){r(e)}}function c(e){var t;e.done?s(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(i,a)}c((o=o.apply(e,t||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;const n={PHONE:/^1[3-9]\d{9}$/,EMAIL:/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,ID_CARD:/(^\d{15}$)|(^\d{17}(\d|X|x)$)/,URL:/^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/,IPV4:/^(\d{1,3}\.){3}\d{1,3}$/,STRONG_PASSWORD:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/,CHINESE:/^[\u4e00-\u9fa5]+$/};class o{}class s extends o{static isPhone(e){return n.PHONE.test(e)}static isEmail(e){return n.EMAIL.test(e)}static isIdCard(e){return n.ID_CARD.test(e)}static isUrl(e){return n.URL.test(e)}static isIpv4(e){return n.IPV4.test(e)}static isStrongPassword(e){return n.STRONG_PASSWORD.test(e)}static isChinese(e){return n.CHINESE.test(e)}}var r={patterns:n,validator:s};const i=e=>{if(!e)return"";const t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return-1===t?e:e.slice(t+1)};function a(e){if("string"==typeof e){if(!/^\d+$/.test(e))return!1;e=Number(e)}if("number"!=typeof e||isNaN(e))return!1;const t=41024448e5;return 13===e.toString().length?e>=0&&e<=t:10===e.toString().length&&(e>=0&&e<=4102444800)}const c=e=>a(e)&&10===e.toString().length;class l{constructor(e={}){var t;this.interceptRules=[],this.isActive=!1,this.originalXMLHttpRequest=window.XMLHttpRequest,this.enableLogging=null===(t=e.enableLogging)||void 0===t||t}start(){if(this.isActive)return void this.log("拦截器已经启动");const e=this;window.XMLHttpRequest=function(){const t=new e.originalXMLHttpRequest;let n="";const o=t.open;t.open=function(e,t,s=!0,r,i){return n="string"==typeof t?t:t.toString(),o.call(this,e,t,s,r,i)};const s=t.send;return t.send=function(o){const r=e.findMatchingRule(n);if(!r)return s.call(this,o);let i=o;if(r.requestCallback&&o)try{i=r.requestCallback(o,n)}catch(e){console.error("XHR请求拦截器处理失败:",e),i=o}const a=t.onreadystatechange;return t.onreadystatechange=function(o){if(4===t.readyState&&t.status>=200&&t.status<300)try{const o=JSON.parse(t.responseText),s=r.responseCallback(o,n);Object.defineProperty(t,"responseText",{writable:!0,configurable:!0,value:JSON.stringify(s)}),Object.defineProperty(t,"response",{writable:!0,configurable:!0,value:JSON.stringify(s)}),e.log(`已拦截并修改响应: ${n}`)}catch(t){e.log("拦截器处理失败:",t)}a&&a.call(this,o)},s.call(this,i)},t},Object.setPrototypeOf(window.XMLHttpRequest,this.originalXMLHttpRequest),window.XMLHttpRequest.prototype=this.originalXMLHttpRequest.prototype,this.isActive=!0,this.log("XHR拦截器已启动")}stop(){this.isActive?(window.XMLHttpRequest=this.originalXMLHttpRequest,this.isActive=!1,this.log("XHR拦截器已停止,已恢复原始XMLHttpRequest")):this.log("拦截器未启动")}setRules(e){this.interceptRules=[...e],this.log("已设置拦截规则:",e.map(e=>e.url))}addRule(e,t,n){this.interceptRules.push({url:e,responseCallback:t,requestCallback:n}),this.log(`已添加拦截规则: ${e}`)}removeRule(e){const t=this.interceptRules.length;this.interceptRules=this.interceptRules.filter(t=>t.url!==e);const n=this.interceptRules.length<t;return n?this.log(`已移除拦截规则: ${e}`):this.log(`未找到拦截规则: ${e}`),n}clearRules(){this.interceptRules=[],this.log("已清除所有拦截规则")}getRules(){return[...this.interceptRules]}getStatus(){return{isActive:this.isActive,rulesCount:this.interceptRules.length}}findMatchingRule(e){return this.interceptRules.find(t=>e.includes(t.url))}log(e,...t){this.enableLogging&&console.log(`[XHRInterceptor] ${e}`,...t)}}const d=new l({enableLogging:!0}),u="ziya-utils",h=999999999;e.Global_Mask_Zindex=h,e.Lib_Name=u,e.RegexPatterns=n,e.RegexValidator=s,e.ScriptDomBuilder=class{constructor(e=document.body,t="glk-script-container"){this.container=null,this.elements=new Map,this.data=new Map,this.styleElement=null,this.parentNode=e,this.containerId=t}createMain(e,t="",n={}){return t&&this.createStyles(t),this.container=this.createElement("div",Object.assign({id:this.containerId},n)),e.forEach((e,t)=>{const n=this.createItem(e,t);n&&this.container.appendChild(n)}),this.parentNode.appendChild(this.container),{container:this.container,get:e=>this.getChild(e),getValue:e=>this.getValue(e),setValue:(e,t)=>this.setValue(e,t),show:e=>this.show(e),hide:e=>this.hide(e),remove:()=>this.remove(),on:(e,t,n)=>this.on(e,t,n),getData:e=>this.getData(e),setData:(e,t)=>this.setData(e,t)}}createStyles(e){this.styleElement=document.createElement("style"),this.styleElement.textContent=e,document.head.appendChild(this.styleElement)}createItem(e,t){const{type:n,keyword:o}=e;!function(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(n[o]=e[o]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var s=0;for(o=Object.getOwnPropertySymbols(e);s<o.length;s++)t.indexOf(o[s])<0&&Object.prototype.propertyIsEnumerable.call(e,o[s])&&(n[o[s]]=e[o[s]])}}(e,["type","keyword"]);let s=null;switch(n){case"input":s=this.createInput(e);break;case"button":s=this.createButton(e);break;case"select":s=this.createSelect(e);break;case"textarea":s=this.createTextarea(e);break;case"checkbox":s=this.createCheckbox(e);break;case"label":s=this.createLabel(e);break;case"div":s=this.createDiv(e);break;default:return console.warn(`未支持的元素类型: ${n}`),null}return o&&s&&(this.setChild(o,s),e.saveToLocal&&this.isFormElement(n)&&this.handleLocalStorage(s,e,n)),s}isFormElement(e){return["input","textarea","select","checkbox"].includes(e)}handleLocalStorage(e,t,n){const o=this.getStorageKey(t.keyword),s=this.getFromLocalStorage(o);if(null!==s)if("checkbox"===n){const t=e.querySelector('input[type="checkbox"]');t&&(t.checked="true"===s)}else{e.value=s}else if("checkbox"===n){const n=e.querySelector('input[type="checkbox"]');n&&(n.checked=t.checked||!1)}else{e.value=t.value||""}if("checkbox"===n){const t=e.querySelector('input[type="checkbox"]');t&&t.addEventListener("change",e=>{const t=e.target;this.saveToLocalStorage(o,t.checked.toString())})}else{const t="select"===n?"change":"input";e.addEventListener(t,e=>{const t=e.target;this.saveToLocalStorage(o,t.value)})}}createInput(e){const t=this.createElement("input",Object.assign({type:e.inputType||"text",name:e.keyword,placeholder:e.placeholder||"",value:e.value||""},e.props));return this.bindEvents(t,e),t}createButton(e){const t=this.createElement("button",Object.assign({textContent:e.text||e.keyword||"Button",name:e.keyword},e.props));return this.bindEvents(t,e),t}createSelect(e){const t=this.createElement("select",Object.assign({name:e.keyword},e.props));return e.options&&e.options.forEach(e=>{const n=document.createElement("option");"string"==typeof e?(n.value=e,n.textContent=e):(n.value=e.value||e.text||"",n.textContent=e.text||e.value||"",e.selected&&(n.selected=!0)),t.appendChild(n)}),this.bindEvents(t,e),t}createTextarea(e){const t=this.createElement("textarea",Object.assign({name:e.keyword,placeholder:e.placeholder||"",value:e.value||"",rows:e.rows||3},e.props));return this.bindEvents(t,e),t}createCheckbox(e){const t=document.createElement("div"),n=this.createElement("input",Object.assign({type:"checkbox",id:e.keyword,name:e.keyword,checked:e.checked||!1},e.props)),o=document.createElement("label");return o.setAttribute("for",e.keyword||""),o.textContent=e.text||e.keyword||"Checkbox",this.bindEvents(n,e),t.appendChild(n),t.appendChild(o),e.keyword&&this.setChild(e.keyword,n),t}createLabel(e){return this.createElement("label",Object.assign({textContent:e.text||e.keyword||"",name:e.keyword},e.props))}createDiv(e){const t=this.createElement("div",Object.assign({textContent:e.text||"",innerHTML:e.html||void 0,name:e.keyword},e.props));return this.bindEvents(t,e),t}createElement(e,t={}){const n=document.createElement(e);return Object.keys(t).forEach(e=>{"innerHTML"===e?n.innerHTML=t[e]:n[e]=t[e]}),n}bindEvents(e,t){["onClick","onChange","onInput","onFocus","onBlur","onMouseEnter","onMouseLeave"].forEach(n=>{const o=t[n];if(o){const t=n.slice(2).toLowerCase();e.addEventListener(t,o)}})}getChild(e){return this.elements.get(e)||null}setChild(e,t){this.elements.has(e)||this.elements.set(e,t)}getValue(e){const t=this.getChild(e);if(!t)return null;if("checkbox"===t.type)return t.checked;return t.value||t.textContent||null}setValue(e,t){const n=this.getChild(e);if(n)if("checkbox"===n.type)n.checked=Boolean(t);else{const e=n;void 0!==e.value?e.value=String(t):n.textContent=String(t)}}show(e){if(e){const t=this.getChild(e);if(t){const e="checkbox"===t.type?t.parentElement:t;e&&(e.style.display="")}}else this.container&&(this.container.style.display="")}hide(e){if(e){const t=this.getChild(e);if(t){const e="checkbox"===t.type?t.parentElement:t;e&&(e.style.display="none")}}else this.container&&(this.container.style.display="none")}remove(){this.container&&(this.container.remove(),this.container=null,this.elements.clear()),this.styleElement&&(this.styleElement.remove(),this.styleElement=null)}on(e,t,n){const o=this.getChild(e);o&&o.addEventListener(t,n)}getStorageKey(e){return`${this.containerId}_${e}`}saveToLocalStorage(e,t){try{localStorage.setItem(e,t)}catch(e){console.warn("无法保存到本地存储:",e)}}getFromLocalStorage(e){try{return localStorage.getItem(e)}catch(e){return console.warn("无法从本地存储读取:",e),null}}setData(e,t){this.data.set(e,t)}getData(e){return this.data.get(e)}},e.XHRInterceptor=l,e.addStyleStr=(e="")=>{let t=document.createElement("style");return t.innerHTML=e,document.getElementsByTagName("head")[0].appendChild(t),t},e.compelSetInputValue=(e,t)=>{var n;const o=null===(n=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,"value"))||void 0===n?void 0:n.set;o&&o.call(e,t);const s=new Event("input",{bubbles:!0});e.dispatchEvent(s)},e.copyToClipboard=function(e){return t(this,void 0,void 0,function*(){try{var t=JSON.stringify(e);if(navigator.clipboard&&(window.isSecureContext||"https:"===location.protocol||"localhost"===location.hostname))return yield navigator.clipboard.writeText(t),!0;var n=document.createElement("textarea");n.value=t,n.style.position="fixed",n.style.left="-9999px",n.style.top="-9999px",document.body.appendChild(n),n.select();var o=document.execCommand("copy");return document.body.removeChild(n),o}catch(e){return console.error("复制失败:",e),!1}})},e.createAsyncTask=function(e=()=>null,n=()=>{},o={}){const{duration:s=1,timeout:r,immediate:i=!1}=o;return new Promise((o,a)=>{let c=null,l=null;const d=()=>{c&&(clearInterval(c),c=null),l&&(clearTimeout(l),l=null)},u=()=>t(this,void 0,void 0,function*(){try{const t=yield e();if(t){d();const e=yield n(t);o(e)}}catch(e){d(),a(e)}});r&&r>0&&(l=setTimeout(()=>{d(),a(new Error(`${r} 秒后任务将会超时。`))},1e3*r)),i&&u(),c=setInterval(u,1e3*s)})},e.createFormData=e=>{const t=new FormData;if("string"==typeof e){const n=new URLSearchParams(e);for(const[e,o]of n)t.append(e,o)}else"object"==typeof e&&null!==e&&Object.keys(e).forEach(n=>{const o=e[n];null!=o?Array.isArray(o)?o.forEach(e=>t.append(n,String(e))):o instanceof File||o instanceof Blob?t.append(n,o):"object"==typeof o?t.append(n,JSON.stringify(o)):t.append(n,String(o)):t.append(n,"")});return t},e.createMaskLoading=(e="加载中...",t="")=>{const n=`${u}-mask-loading-container`,o=document.getElementById(n);o&&document.body.removeChild(o);const s=document.createElement("div");s.id=n,s.innerHTML=`\n <div class="mask"></div>\n <div class="message">${e}</div>\n `;const r=document.createElement("style");return r.innerHTML=`\n #${n} {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 999999999;\n transition: opacity 0.3s;\n }\n #${n} .mask {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.45);\n }\n #${n} .message {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: #fff;\n }\n\n ${t}\n `,document.head.appendChild(r),document.body.append(s),{close:()=>{document.body.removeChild(s)},updateMsg:e=>{s.querySelector(".message").innerHTML=e}}},e.downloadSingleFile=(e,n)=>t(void 0,void 0,void 0,function*(){if(!e||!r.validator.isUrl(e))throw new Error("无效的URL");try{const t=yield fetch(e);if(!t.ok)throw new Error(`下载失败: ${t.status} ${t.statusText}`);let o=n;if(!o){o=i(e);const t=o.indexOf("?");-1!==t&&(o=o.substring(0,t)),o||(o="downloaded_file")}const s=yield t.blob(),r=URL.createObjectURL(s),a=document.createElement("a");a.href=r,a.download=o,document.body.appendChild(a),a.click(),setTimeout(()=>{URL.revokeObjectURL(r),a.remove()},100)}catch(e){throw console.error("文件下载失败:",e),e}}),e.extractFileNameFromPath=i,e.formatDateTypeSafe=function(e,t){return function(e,t){const n=t||new Date,o=(e,t=2)=>e.toString().padStart(t,"0"),s={year:n.getFullYear(),month:n.getMonth()+1,day:n.getDate(),hours:n.getHours(),minutes:n.getMinutes(),seconds:n.getSeconds(),milliseconds:n.getMilliseconds()},r={YYYY:s.year.toString(),YY:s.year.toString().slice(-2),MM:o(s.month),M:s.month.toString(),DD:o(s.day),D:s.day.toString(),HH:o(s.hours),H:s.hours.toString(),mm:o(s.minutes),m:s.minutes.toString(),ss:o(s.seconds),s:s.seconds.toString(),SSS:o(s.milliseconds,3)};return Object.keys(r).sort((e,t)=>t.length-e.length).reduce((e,t)=>e.replace(new RegExp(t,"g"),r[t]),e)}(e,t)},e.generateNumberRange=(e,t,n=.005)=>{const o=[];if(e===t)return[e];e>t&&([e,t]=[t,e]);if(n<=0||n>=t-e)return[e,t];const s=1/n;for(let n=Math.round(e*s);n<=Math.round(t*s);n++)o.push(n/s);return o},e.getElapsedTimeSince=e=>{const t=Date.now();a(e)||(e=t);const n=Math.max(0,t-(c(e)?1e3*e:e));return{hours:Math.floor(n/36e5),minutes:Math.floor(n%36e5/6e4),seconds:Math.floor(n%6e4/1e3)}},e.getFromLocalStorage=e=>{try{return localStorage.getItem(e)}catch(e){return console.warn("无法从本地存储读取:",e),null}},e.getUuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)})},e.isMillisecondTimestamp=e=>a(e)&&13===e.toString().length,e.isSecondTimestamp=c,e.isValidTimestamp=a,e.jsonToQueryString=e=>new URLSearchParams(e).toString(),e.precisionFormat=(e,t,n=!0,o=!0)=>{var s=e<0&&o?-1:1;const r=Math.pow(10,t);return n?Math.round(e*r*s)/r*s:Math.floor(e*r*s)/r*s},e.saveToLocalStorage=(e,t)=>{try{localStorage.setItem(e,t)}catch(e){console.warn("无法保存到本地存储:",e)}},e.showTip=(e,t=2,n)=>new Promise(o=>{const s=document.getElementById("show_tip");s&&document.body.removeChild(s),window.show_tip_timer&&clearTimeout(window.show_tip_timer);const r=document.createElement("div");if(document.body.appendChild(r),r.id="show_tip",Object.assign(r.style,{position:"fixed",maxWidth:"80vw",top:"50%",left:"50%",transform:"translate(-50%, -50%)",lineHeight:"20px",zIndex:h,color:"#fff",backgroundColor:"#303133",borderRadius:"4px",padding:"10px",textAlign:"center",opacity:"0.9",fontSize:"1em"}),n){const{left:e,top:t,offsetX:o=0,offsetY:s=0}=n;Object.assign(r.style,{top:t+s+"px",left:e+o+"px",transform:"none"})}r.innerText=e,window.show_tip_timer=setTimeout(()=>{const e=document.getElementById("show_tip");e&&(document.body.removeChild(e),o())},1e3*t-100)}),e.sleep=e=>new Promise(t=>{setTimeout(()=>{t(!0)},1e3*e)}),e.waitForCondition=function(e,t=10){return new Promise(n=>{const o=()=>{e()?n():setTimeout(o,t)};o()})},e.xhrInterceptor=d});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ZiyaUtils={})}(this,function(e){"use strict";function t(e,t,n,o){return new(n||(n=Promise))(function(s,r){function i(e){try{c(o.next(e))}catch(e){r(e)}}function a(e){try{c(o.throw(e))}catch(e){r(e)}}function c(e){var t;e.done?s(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(i,a)}c((o=o.apply(e,t||[])).next())})}"function"==typeof SuppressedError&&SuppressedError;const n={PHONE:/^1[3-9]\d{9}$/,EMAIL:/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,ID_CARD:/(^\d{15}$)|(^\d{17}(\d|X|x)$)/,URL:/^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/,IPV4:/^(\d{1,3}\.){3}\d{1,3}$/,STRONG_PASSWORD:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/,CHINESE:/^[\u4e00-\u9fa5]+$/};class o{}class s extends o{static isPhone(e){return n.PHONE.test(e)}static isEmail(e){return n.EMAIL.test(e)}static isIdCard(e){return n.ID_CARD.test(e)}static isUrl(e){return n.URL.test(e)}static isIpv4(e){return n.IPV4.test(e)}static isStrongPassword(e){return n.STRONG_PASSWORD.test(e)}static isChinese(e){return n.CHINESE.test(e)}}var r={patterns:n,validator:s};const i=e=>{if(!e)return"";const t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\"));return-1===t?e:e.slice(t+1)};function a(e){if("string"==typeof e){if(!/^\d+$/.test(e))return!1;e=Number(e)}if("number"!=typeof e||isNaN(e))return!1;const t=41024448e5;return 13===e.toString().length?e>=0&&e<=t:10===e.toString().length&&(e>=0&&e<=4102444800)}const c=e=>a(e)&&10===e.toString().length;class l{constructor(e={}){var t;this.interceptRules=[],this.isActive=!1,this.originalXMLHttpRequest=window.XMLHttpRequest,this.enableLogging=null===(t=e.enableLogging)||void 0===t||t}start(){if(this.isActive)return void this.log("拦截器已经启动");const e=this;window.XMLHttpRequest=function(){const t=new e.originalXMLHttpRequest;let n="";const o=t.open;t.open=function(e,t,s=!0,r,i){return n="string"==typeof t?t:t.toString(),o.call(this,e,t,s,r,i)};const s=t.send;return t.send=function(o){const r=e.findMatchingRule(n);if(!r)return s.call(this,o);let i=o;if(r.requestCallback&&o)try{i=r.requestCallback(o,n)}catch(e){console.error("XHR请求拦截器处理失败:",e),i=o}const a=t.onreadystatechange;return t.onreadystatechange=function(o){if(4===t.readyState&&t.status>=200&&t.status<300)try{let o=t.responseText;const s=[")]}'",")]}'\n","while(1);","for(;;);"];for(const e of s)if(o.startsWith(e)){o=o.slice(e.length);break}const i=JSON.parse(o),a=r.responseCallback(i,n);Object.defineProperty(t,"responseText",{writable:!0,configurable:!0,value:JSON.stringify(a)}),Object.defineProperty(t,"response",{writable:!0,configurable:!0,value:JSON.stringify(a)}),e.log(`已拦截并修改响应: ${n}`)}catch(t){e.log("拦截器处理失败:",t)}a&&a.call(this,o)},s.call(this,i)},t},Object.setPrototypeOf(window.XMLHttpRequest,this.originalXMLHttpRequest),window.XMLHttpRequest.prototype=this.originalXMLHttpRequest.prototype,this.isActive=!0,this.log("XHR拦截器已启动")}stop(){this.isActive?(window.XMLHttpRequest=this.originalXMLHttpRequest,this.isActive=!1,this.log("XHR拦截器已停止,已恢复原始XMLHttpRequest")):this.log("拦截器未启动")}setRules(e){this.interceptRules=[...e],this.log("已设置拦截规则:",e.map(e=>e.url))}addRule(e,t,n){this.interceptRules.push({url:e,responseCallback:t,requestCallback:n}),this.log(`已添加拦截规则: ${e}`)}removeRule(e){const t=this.interceptRules.length;this.interceptRules=this.interceptRules.filter(t=>t.url!==e);const n=this.interceptRules.length<t;return n?this.log(`已移除拦截规则: ${e}`):this.log(`未找到拦截规则: ${e}`),n}clearRules(){this.interceptRules=[],this.log("已清除所有拦截规则")}getRules(){return[...this.interceptRules]}getStatus(){return{isActive:this.isActive,rulesCount:this.interceptRules.length}}findMatchingRule(e){return this.interceptRules.find(t=>e.includes(t.url))}log(e,...t){this.enableLogging&&console.log(`[XHRInterceptor] ${e}`,...t)}}const d=new l({enableLogging:!1}),u="ziya-utils",h=999999999;e.Global_Mask_Zindex=h,e.Lib_Name=u,e.RegexPatterns=n,e.RegexValidator=s,e.ScriptDomBuilder=class{constructor(e=document.body,t="glk-script-container"){this.container=null,this.elements=new Map,this.data=new Map,this.styleElement=null,this.parentNode=e,this.containerId=t}createMain(e,t="",n={}){return t&&this.createStyles(t),this.container=this.createElement("div",Object.assign({id:this.containerId},n)),e.forEach((e,t)=>{const n=this.createItem(e,t);n&&this.container.appendChild(n)}),this.parentNode.appendChild(this.container),{container:this.container,get:e=>this.getChild(e),getValue:e=>this.getValue(e),setValue:(e,t)=>this.setValue(e,t),show:e=>this.show(e),hide:e=>this.hide(e),remove:()=>this.remove(),on:(e,t,n)=>this.on(e,t,n),getData:e=>this.getData(e),setData:(e,t)=>this.setData(e,t)}}createStyles(e){this.styleElement=document.createElement("style"),this.styleElement.textContent=e,document.head.appendChild(this.styleElement)}createItem(e,t){const{type:n,keyword:o}=e;!function(e,t){var n={};for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(n[o]=e[o]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var s=0;for(o=Object.getOwnPropertySymbols(e);s<o.length;s++)t.indexOf(o[s])<0&&Object.prototype.propertyIsEnumerable.call(e,o[s])&&(n[o[s]]=e[o[s]])}}(e,["type","keyword"]);let s=null;switch(n){case"input":s=this.createInput(e);break;case"button":s=this.createButton(e);break;case"select":s=this.createSelect(e);break;case"textarea":s=this.createTextarea(e);break;case"checkbox":s=this.createCheckbox(e);break;case"label":s=this.createLabel(e);break;case"div":s=this.createDiv(e);break;default:return console.warn(`未支持的元素类型: ${n}`),null}return o&&s&&(this.setChild(o,s),e.saveToLocal&&this.isFormElement(n)&&this.handleLocalStorage(s,e,n)),s}isFormElement(e){return["input","textarea","select","checkbox"].includes(e)}handleLocalStorage(e,t,n){const o=this.getStorageKey(t.keyword),s=this.getFromLocalStorage(o);if(null!==s)if("checkbox"===n){const t=e.querySelector('input[type="checkbox"]');t&&(t.checked="true"===s)}else{e.value=s}else if("checkbox"===n){const n=e.querySelector('input[type="checkbox"]');n&&(n.checked=t.checked||!1)}else{e.value=t.value||""}if("checkbox"===n){const t=e.querySelector('input[type="checkbox"]');t&&t.addEventListener("change",e=>{const t=e.target;this.saveToLocalStorage(o,t.checked.toString())})}else{const t="select"===n?"change":"input";e.addEventListener(t,e=>{const t=e.target;this.saveToLocalStorage(o,t.value)})}}createInput(e){const t=this.createElement("input",Object.assign({type:e.inputType||"text",name:e.keyword,placeholder:e.placeholder||"",value:e.value||""},e.props));return this.bindEvents(t,e),t}createButton(e){const t=this.createElement("button",Object.assign({textContent:e.text||e.keyword||"Button",name:e.keyword},e.props));return this.bindEvents(t,e),t}createSelect(e){const t=this.createElement("select",Object.assign({name:e.keyword},e.props));return e.options&&e.options.forEach(e=>{const n=document.createElement("option");"string"==typeof e?(n.value=e,n.textContent=e):(n.value=e.value||e.text||"",n.textContent=e.text||e.value||"",e.selected&&(n.selected=!0)),t.appendChild(n)}),this.bindEvents(t,e),t}createTextarea(e){const t=this.createElement("textarea",Object.assign({name:e.keyword,placeholder:e.placeholder||"",value:e.value||"",rows:e.rows||3},e.props));return this.bindEvents(t,e),t}createCheckbox(e){const t=document.createElement("div"),n=this.createElement("input",Object.assign({type:"checkbox",id:e.keyword,name:e.keyword,checked:e.checked||!1},e.props)),o=document.createElement("label");return o.setAttribute("for",e.keyword||""),o.textContent=e.text||e.keyword||"Checkbox",this.bindEvents(n,e),t.appendChild(n),t.appendChild(o),e.keyword&&this.setChild(e.keyword,n),t}createLabel(e){return this.createElement("label",Object.assign({textContent:e.text||e.keyword||"",name:e.keyword},e.props))}createDiv(e){const t=this.createElement("div",Object.assign({textContent:e.text||"",innerHTML:e.html||void 0,name:e.keyword},e.props));return this.bindEvents(t,e),t}createElement(e,t={}){const n=document.createElement(e);return Object.keys(t).forEach(e=>{"innerHTML"===e?n.innerHTML=t[e]:n[e]=t[e]}),n}bindEvents(e,t){["onClick","onChange","onInput","onFocus","onBlur","onMouseEnter","onMouseLeave"].forEach(n=>{const o=t[n];if(o){const t=n.slice(2).toLowerCase();e.addEventListener(t,o)}})}getChild(e){return this.elements.get(e)||null}setChild(e,t){this.elements.has(e)||this.elements.set(e,t)}getValue(e){const t=this.getChild(e);if(!t)return null;if("checkbox"===t.type)return t.checked;return t.value||t.textContent||null}setValue(e,t){const n=this.getChild(e);if(n)if("checkbox"===n.type)n.checked=Boolean(t);else{const e=n;void 0!==e.value?e.value=String(t):n.textContent=String(t)}}show(e){if(e){const t=this.getChild(e);if(t){const e="checkbox"===t.type?t.parentElement:t;e&&(e.style.display="")}}else this.container&&(this.container.style.display="")}hide(e){if(e){const t=this.getChild(e);if(t){const e="checkbox"===t.type?t.parentElement:t;e&&(e.style.display="none")}}else this.container&&(this.container.style.display="none")}remove(){this.container&&(this.container.remove(),this.container=null,this.elements.clear()),this.styleElement&&(this.styleElement.remove(),this.styleElement=null)}on(e,t,n){const o=this.getChild(e);o&&o.addEventListener(t,n)}getStorageKey(e){return`${this.containerId}_${e}`}saveToLocalStorage(e,t){try{localStorage.setItem(e,t)}catch(e){console.warn("无法保存到本地存储:",e)}}getFromLocalStorage(e){try{return localStorage.getItem(e)}catch(e){return console.warn("无法从本地存储读取:",e),null}}setData(e,t){this.data.set(e,t)}getData(e){return this.data.get(e)}},e.XHRInterceptor=l,e.addStyleStr=(e="")=>{let t=document.createElement("style");return t.innerHTML=e,document.getElementsByTagName("head")[0].appendChild(t),t},e.compelSetInputValue=(e,t)=>{var n;const o=null===(n=Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype,"value"))||void 0===n?void 0:n.set;o&&o.call(e,t);const s=new Event("input",{bubbles:!0});e.dispatchEvent(s)},e.copyToClipboard=function(e){return t(this,void 0,void 0,function*(){try{var t=JSON.stringify(e);if(navigator.clipboard&&(window.isSecureContext||"https:"===location.protocol||"localhost"===location.hostname))return yield navigator.clipboard.writeText(t),!0;var n=document.createElement("textarea");n.value=t,n.style.position="fixed",n.style.left="-9999px",n.style.top="-9999px",document.body.appendChild(n),n.select();var o=document.execCommand("copy");return document.body.removeChild(n),o}catch(e){return console.error("复制失败:",e),!1}})},e.createAsyncTask=function(e=()=>null,n=()=>{},o={}){const{duration:s=1,timeout:r,immediate:i=!1}=o;return new Promise((o,a)=>{let c=null,l=null;const d=()=>{c&&(clearInterval(c),c=null),l&&(clearTimeout(l),l=null)},u=()=>t(this,void 0,void 0,function*(){try{const t=yield e();if(t){d();const e=yield n(t);o(e)}}catch(e){d(),a(e)}});r&&r>0&&(l=setTimeout(()=>{d(),a(new Error(`${r} 秒后任务将会超时。`))},1e3*r)),i&&u(),c=setInterval(u,1e3*s)})},e.createFormData=e=>{const t=new FormData;if("string"==typeof e){const n=new URLSearchParams(e);for(const[e,o]of n)t.append(e,o)}else"object"==typeof e&&null!==e&&Object.keys(e).forEach(n=>{const o=e[n];null!=o?Array.isArray(o)?o.forEach(e=>t.append(n,String(e))):o instanceof File||o instanceof Blob?t.append(n,o):"object"==typeof o?t.append(n,JSON.stringify(o)):t.append(n,String(o)):t.append(n,"")});return t},e.createMaskLoading=(e="加载中...",t="")=>{const n=`${u}-mask-loading-container`,o=document.getElementById(n);o&&document.body.removeChild(o);const s=document.createElement("div");s.id=n,s.innerHTML=`\n <div class="mask"></div>\n <div class="message">${e}</div>\n `;const r=document.createElement("style");return r.innerHTML=`\n #${n} {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 999999999;\n transition: opacity 0.3s;\n }\n #${n} .mask {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.45);\n }\n #${n} .message {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: #fff;\n }\n\n ${t}\n `,document.head.appendChild(r),document.body.append(s),{close:()=>{document.body.removeChild(s)},updateMsg:e=>{s.querySelector(".message").innerHTML=e}}},e.downloadObjectAsJson=(e,t)=>{let n=JSON.stringify(...e),o=new Blob([n],{type:"application/json"}),s=document.createElement("a");s.href=URL.createObjectURL(o),s.download=`${t||"data"}.json`,s.click()},e.downloadSingleFile=(e,n)=>t(void 0,void 0,void 0,function*(){if(!e||!r.validator.isUrl(e))throw new Error("无效的URL");try{const t=yield fetch(e);if(!t.ok)throw new Error(`下载失败: ${t.status} ${t.statusText}`);let o=n;if(!o){o=i(e);const t=o.indexOf("?");-1!==t&&(o=o.substring(0,t)),o||(o="downloaded_file")}const s=yield t.blob(),r=URL.createObjectURL(s),a=document.createElement("a");a.href=r,a.download=o,document.body.appendChild(a),a.click(),setTimeout(()=>{URL.revokeObjectURL(r),a.remove()},100)}catch(e){throw console.error("文件下载失败:",e),e}}),e.extractFileNameFromPath=i,e.formatDateTypeSafe=function(e,t){return function(e,t){const n=t||new Date,o=(e,t=2)=>e.toString().padStart(t,"0"),s={year:n.getFullYear(),month:n.getMonth()+1,day:n.getDate(),hours:n.getHours(),minutes:n.getMinutes(),seconds:n.getSeconds(),milliseconds:n.getMilliseconds()},r={YYYY:s.year.toString(),YY:s.year.toString().slice(-2),MM:o(s.month),M:s.month.toString(),DD:o(s.day),D:s.day.toString(),HH:o(s.hours),H:s.hours.toString(),mm:o(s.minutes),m:s.minutes.toString(),ss:o(s.seconds),s:s.seconds.toString(),SSS:o(s.milliseconds,3)};return Object.keys(r).sort((e,t)=>t.length-e.length).reduce((e,t)=>e.replace(new RegExp(t,"g"),r[t]),e)}(e,t)},e.generateNumberRange=(e,t,n=1)=>{const o=[];if(e===t)return[e];e>t&&([e,t]=[t,e]);if(n<=0||n>=t-e)return[e,t];const s=1/n;for(let n=Math.round(e*s);n<=Math.round(t*s);n++)o.push(n/s);return o},e.getElapsedTimeSince=e=>{const t=Date.now();a(e)||(e=t);const n=Math.max(0,t-(c(e)?1e3*e:e));return{hours:Math.floor(n/36e5),minutes:Math.floor(n%36e5/6e4),seconds:Math.floor(n%6e4/1e3)}},e.getFromLocalStorage=e=>{try{return localStorage.getItem(e)}catch(e){return console.warn("无法从本地存储读取:",e),null}},e.getUuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(e){var t=16*Math.random()|0;return("x"==e?t:3&t|8).toString(16)})},e.isMillisecondTimestamp=e=>a(e)&&13===e.toString().length,e.isSecondTimestamp=c,e.isValidTimestamp=a,e.jsonToQueryString=e=>new URLSearchParams(e).toString(),e.parseAJsonFile=e=>new Promise(t=>{if(!e||"application/json"!==e.type)throw new Error("parseAJsonFile: file is not a JSON file.");{const n=new FileReader;n.onload=function(e){try{null===e.target||null===e.target.result?t(null):t(JSON.parse(e.target.result))}catch(e){t(null)}},n.readAsText(e)}}),e.precisionFormat=(e,t,n=!0,o=!0)=>{var s=e<0&&o?-1:1;const r=Math.pow(10,t);return n?Math.round(e*r*s)/r*s:Math.floor(e*r*s)/r*s},e.saveToLocalStorage=(e,t)=>{try{localStorage.setItem(e,t)}catch(e){console.warn("无法保存到本地存储:",e)}},e.showTip=(e,t=2,n)=>new Promise(o=>{const s=document.getElementById("show_tip");s&&document.body.removeChild(s),window.show_tip_timer&&clearTimeout(window.show_tip_timer);const r=document.createElement("div");if(document.body.appendChild(r),r.id="show_tip",Object.assign(r.style,{position:"fixed",maxWidth:"80vw",top:"50%",left:"50%",transform:"translate(-50%, -50%)",lineHeight:"20px",zIndex:h,color:"#fff",backgroundColor:"#303133",borderRadius:"4px",padding:"10px",textAlign:"center",opacity:"0.9",fontSize:"1em"}),n){const{left:e,top:t,offsetX:o=0,offsetY:s=0}=n;Object.assign(r.style,{top:t+s+"px",left:e+o+"px",transform:"none"})}r.innerText=e,window.show_tip_timer=setTimeout(()=>{const e=document.getElementById("show_tip");e&&(document.body.removeChild(e),o())},1e3*t-100)}),e.sleep=e=>new Promise(t=>{setTimeout(()=>{t(!0)},1e3*e)}),e.waitForCondition=function(e,t=10){return new Promise(n=>{const o=()=>{e()?n():setTimeout(o,t)};o()})},e.xhrInterceptor=d});
package/es/count/index.js CHANGED
@@ -33,7 +33,7 @@ const precisionFormat = (num, count, round = true, consistent = true) => {
33
33
  * @param step 步长,默认1
34
34
  * @returns
35
35
  */
36
- const generateNumberRange = (min, max, step = 0.005) => {
36
+ const generateNumberRange = (min, max, step = 1) => {
37
37
  const result = [];
38
38
  // 如果 min 和 max 相等
39
39
  if (min === max) {
@@ -17,4 +17,15 @@ declare const extractFileNameFromPath: (filePath: string) => string;
17
17
  * @throws Error 当URL无效或网络请求失败时抛出错误
18
18
  */
19
19
  declare const downloadSingleFile: (url: string, name?: string) => Promise<void>;
20
- export { extractFileNameFromPath, downloadSingleFile };
20
+ /**
21
+ * 将任意值转换为JSON文件下载
22
+ * @param stringifyCfg JSON.stringify的参数
23
+ * @param fileName 文件名
24
+ */
25
+ declare const downloadObjectAsJson: (stringifyCfg: [value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined], fileName?: string) => void;
26
+ /**
27
+ * 解析一个JSON文件,返回解析后的对象
28
+ * @param file
29
+ */
30
+ declare const parseAJsonFile: (file: File) => Promise<unknown>;
31
+ export { extractFileNameFromPath, downloadSingleFile, downloadObjectAsJson, parseAJsonFile };
package/es/file/index.js CHANGED
@@ -33,7 +33,7 @@ const extractFileNameFromPath = (filePath) => {
33
33
  const downloadSingleFile = (url, name) => __awaiter(void 0, void 0, void 0, function* () {
34
34
  // 验证URL
35
35
  if (!url || !IRegexUtils.validator.isUrl(url)) {
36
- throw new Error('无效的URL');
36
+ throw new Error("无效的URL");
37
37
  }
38
38
  try {
39
39
  // 获取响应
@@ -47,20 +47,20 @@ const downloadSingleFile = (url, name) => __awaiter(void 0, void 0, void 0, func
47
47
  if (!fileName) {
48
48
  fileName = extractFileNameFromPath(url);
49
49
  // 处理查询参数
50
- const queryIndex = fileName.indexOf('?');
50
+ const queryIndex = fileName.indexOf("?");
51
51
  if (queryIndex !== -1) {
52
52
  fileName = fileName.substring(0, queryIndex);
53
53
  }
54
54
  // 如果仍然没有文件名,使用默认名称
55
55
  if (!fileName) {
56
- fileName = 'downloaded_file';
56
+ fileName = "downloaded_file";
57
57
  }
58
58
  }
59
59
  // 获取blob和内容类型
60
60
  const blob = yield response.blob();
61
61
  // 创建下载链接
62
62
  const blobUrl = URL.createObjectURL(blob); // 注意:直接使用原始blob保留MIME类型
63
- const link = document.createElement('a');
63
+ const link = document.createElement("a");
64
64
  link.href = blobUrl;
65
65
  link.download = fileName;
66
66
  // 执行下载
@@ -73,9 +73,57 @@ const downloadSingleFile = (url, name) => __awaiter(void 0, void 0, void 0, func
73
73
  }, 100); // 添加小延迟以确保下载开始
74
74
  }
75
75
  catch (error) {
76
- console.error('文件下载失败:', error);
76
+ console.error("文件下载失败:", error);
77
77
  throw error; // 重新抛出错误以便调用者可以处理
78
78
  }
79
79
  });
80
+ /**
81
+ * 将任意值转换为JSON文件下载
82
+ * @param stringifyCfg JSON.stringify的参数
83
+ * @param fileName 文件名
84
+ */
85
+ const downloadObjectAsJson = (stringifyCfg, fileName) => {
86
+ // 转换为JSON字符串
87
+ let json = JSON.stringify(...stringifyCfg);
88
+ // 创建一个blob对象
89
+ let blob = new Blob([json], { type: "application/json" });
90
+ // 创建一个链接元素
91
+ let link = document.createElement("a");
92
+ // 设置链接的href属性为blob的URL
93
+ link.href = URL.createObjectURL(blob);
94
+ // 设置下载的文件名
95
+ link.download = `${fileName || "data"}.json`;
96
+ // 触发下载
97
+ link.click();
98
+ };
99
+ /**
100
+ * 解析一个JSON文件,返回解析后的对象
101
+ * @param file
102
+ */
103
+ const parseAJsonFile = (file) => {
104
+ return new Promise((resolve) => {
105
+ if (file && file.type === "application/json") {
106
+ const reader = new FileReader();
107
+ reader.onload = function (event) {
108
+ try {
109
+ if (event.target === null || event.target.result === null) {
110
+ resolve(null);
111
+ }
112
+ else {
113
+ resolve(JSON.parse(event.target.result));
114
+ }
115
+ }
116
+ catch (error) {
117
+ resolve(null);
118
+ }
119
+ };
120
+ // 读取文件内容
121
+ reader.readAsText(file);
122
+ }
123
+ else {
124
+ throw new Error("parseAJsonFile: file is not a JSON file.");
125
+ }
126
+ });
127
+ };
80
128
 
81
- export { downloadSingleFile, extractFileNameFromPath };
129
+ export { downloadObjectAsJson, downloadSingleFile, extractFileNameFromPath, parseAJsonFile };
package/es/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { downloadSingleFile, extractFileNameFromPath } from './file/index.js';
1
+ export { downloadObjectAsJson, downloadSingleFile, extractFileNameFromPath, parseAJsonFile } from './file/index.js';
2
2
  export { sleep } from './time/index.js';
3
3
  export { formatDateTypeSafe, getElapsedTimeSince, isMillisecondTimestamp, isSecondTimestamp, isValidTimestamp } from './date/index.js';
4
4
  export { copyToClipboard, getUuid } from './security/index.js';
package/es/xhr/index.js CHANGED
@@ -59,8 +59,18 @@ class XHRInterceptor {
59
59
  xhr.onreadystatechange = function (event) {
60
60
  if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) {
61
61
  try {
62
+ // 部分接口(如 Google 系接口)会在 JSON 前加上 )]}'
63
+ // 这种反 JSON 劫持前缀,需要先剥离掉再解析,否则 JSON.parse 必报错
64
+ let rawText = xhr.responseText;
65
+ const xssiPrefixes = [")]}'", ")]}'\n", "while(1);", "for(;;);"];
66
+ for (const prefix of xssiPrefixes) {
67
+ if (rawText.startsWith(prefix)) {
68
+ rawText = rawText.slice(prefix.length);
69
+ break;
70
+ }
71
+ }
62
72
  // 解析原始响应
63
- const originalData = JSON.parse(xhr.responseText);
73
+ const originalData = JSON.parse(rawText);
64
74
  // 使用回调函数处理响应数据
65
75
  const modifiedData = matchingRule.responseCallback(originalData, requestUrl);
66
76
  // 重写响应属性
@@ -175,6 +185,6 @@ class XHRInterceptor {
175
185
  }
176
186
  }
177
187
  // 创建单例实例
178
- const xhrInterceptor = new XHRInterceptor({ enableLogging: true });
188
+ const xhrInterceptor = new XHRInterceptor({ enableLogging: false });
179
189
 
180
190
  export { XHRInterceptor, xhrInterceptor };
@@ -35,7 +35,7 @@ const precisionFormat = (num, count, round = true, consistent = true) => {
35
35
  * @param step 步长,默认1
36
36
  * @returns
37
37
  */
38
- const generateNumberRange = (min, max, step = 0.005) => {
38
+ const generateNumberRange = (min, max, step = 1) => {
39
39
  const result = [];
40
40
  // 如果 min 和 max 相等
41
41
  if (min === max) {
@@ -17,4 +17,15 @@ declare const extractFileNameFromPath: (filePath: string) => string;
17
17
  * @throws Error 当URL无效或网络请求失败时抛出错误
18
18
  */
19
19
  declare const downloadSingleFile: (url: string, name?: string) => Promise<void>;
20
- export { extractFileNameFromPath, downloadSingleFile };
20
+ /**
21
+ * 将任意值转换为JSON文件下载
22
+ * @param stringifyCfg JSON.stringify的参数
23
+ * @param fileName 文件名
24
+ */
25
+ declare const downloadObjectAsJson: (stringifyCfg: [value: any, replacer?: (string | number)[] | null | undefined, space?: string | number | undefined], fileName?: string) => void;
26
+ /**
27
+ * 解析一个JSON文件,返回解析后的对象
28
+ * @param file
29
+ */
30
+ declare const parseAJsonFile: (file: File) => Promise<unknown>;
31
+ export { extractFileNameFromPath, downloadSingleFile, downloadObjectAsJson, parseAJsonFile };
package/lib/file/index.js CHANGED
@@ -35,7 +35,7 @@ const extractFileNameFromPath = (filePath) => {
35
35
  const downloadSingleFile = (url, name) => tslib_es6.__awaiter(void 0, void 0, void 0, function* () {
36
36
  // 验证URL
37
37
  if (!url || !index.default.validator.isUrl(url)) {
38
- throw new Error('无效的URL');
38
+ throw new Error("无效的URL");
39
39
  }
40
40
  try {
41
41
  // 获取响应
@@ -49,20 +49,20 @@ const downloadSingleFile = (url, name) => tslib_es6.__awaiter(void 0, void 0, vo
49
49
  if (!fileName) {
50
50
  fileName = extractFileNameFromPath(url);
51
51
  // 处理查询参数
52
- const queryIndex = fileName.indexOf('?');
52
+ const queryIndex = fileName.indexOf("?");
53
53
  if (queryIndex !== -1) {
54
54
  fileName = fileName.substring(0, queryIndex);
55
55
  }
56
56
  // 如果仍然没有文件名,使用默认名称
57
57
  if (!fileName) {
58
- fileName = 'downloaded_file';
58
+ fileName = "downloaded_file";
59
59
  }
60
60
  }
61
61
  // 获取blob和内容类型
62
62
  const blob = yield response.blob();
63
63
  // 创建下载链接
64
64
  const blobUrl = URL.createObjectURL(blob); // 注意:直接使用原始blob保留MIME类型
65
- const link = document.createElement('a');
65
+ const link = document.createElement("a");
66
66
  link.href = blobUrl;
67
67
  link.download = fileName;
68
68
  // 执行下载
@@ -75,10 +75,60 @@ const downloadSingleFile = (url, name) => tslib_es6.__awaiter(void 0, void 0, vo
75
75
  }, 100); // 添加小延迟以确保下载开始
76
76
  }
77
77
  catch (error) {
78
- console.error('文件下载失败:', error);
78
+ console.error("文件下载失败:", error);
79
79
  throw error; // 重新抛出错误以便调用者可以处理
80
80
  }
81
81
  });
82
+ /**
83
+ * 将任意值转换为JSON文件下载
84
+ * @param stringifyCfg JSON.stringify的参数
85
+ * @param fileName 文件名
86
+ */
87
+ const downloadObjectAsJson = (stringifyCfg, fileName) => {
88
+ // 转换为JSON字符串
89
+ let json = JSON.stringify(...stringifyCfg);
90
+ // 创建一个blob对象
91
+ let blob = new Blob([json], { type: "application/json" });
92
+ // 创建一个链接元素
93
+ let link = document.createElement("a");
94
+ // 设置链接的href属性为blob的URL
95
+ link.href = URL.createObjectURL(blob);
96
+ // 设置下载的文件名
97
+ link.download = `${fileName || "data"}.json`;
98
+ // 触发下载
99
+ link.click();
100
+ };
101
+ /**
102
+ * 解析一个JSON文件,返回解析后的对象
103
+ * @param file
104
+ */
105
+ const parseAJsonFile = (file) => {
106
+ return new Promise((resolve) => {
107
+ if (file && file.type === "application/json") {
108
+ const reader = new FileReader();
109
+ reader.onload = function (event) {
110
+ try {
111
+ if (event.target === null || event.target.result === null) {
112
+ resolve(null);
113
+ }
114
+ else {
115
+ resolve(JSON.parse(event.target.result));
116
+ }
117
+ }
118
+ catch (error) {
119
+ resolve(null);
120
+ }
121
+ };
122
+ // 读取文件内容
123
+ reader.readAsText(file);
124
+ }
125
+ else {
126
+ throw new Error("parseAJsonFile: file is not a JSON file.");
127
+ }
128
+ });
129
+ };
82
130
 
131
+ exports.downloadObjectAsJson = downloadObjectAsJson;
83
132
  exports.downloadSingleFile = downloadSingleFile;
84
133
  exports.extractFileNameFromPath = extractFileNameFromPath;
134
+ exports.parseAJsonFile = parseAJsonFile;
package/lib/index.js CHANGED
@@ -17,8 +17,10 @@ var showtip = require('./document/showtip.js');
17
17
 
18
18
 
19
19
 
20
+ exports.downloadObjectAsJson = index.downloadObjectAsJson;
20
21
  exports.downloadSingleFile = index.downloadSingleFile;
21
22
  exports.extractFileNameFromPath = index.extractFileNameFromPath;
23
+ exports.parseAJsonFile = index.parseAJsonFile;
22
24
  exports.sleep = index$1.sleep;
23
25
  exports.formatDateTypeSafe = index$2.formatDateTypeSafe;
24
26
  exports.getElapsedTimeSince = index$2.getElapsedTimeSince;
package/lib/xhr/index.js CHANGED
@@ -61,8 +61,18 @@ class XHRInterceptor {
61
61
  xhr.onreadystatechange = function (event) {
62
62
  if (xhr.readyState === 4 && xhr.status >= 200 && xhr.status < 300) {
63
63
  try {
64
+ // 部分接口(如 Google 系接口)会在 JSON 前加上 )]}'
65
+ // 这种反 JSON 劫持前缀,需要先剥离掉再解析,否则 JSON.parse 必报错
66
+ let rawText = xhr.responseText;
67
+ const xssiPrefixes = [")]}'", ")]}'\n", "while(1);", "for(;;);"];
68
+ for (const prefix of xssiPrefixes) {
69
+ if (rawText.startsWith(prefix)) {
70
+ rawText = rawText.slice(prefix.length);
71
+ break;
72
+ }
73
+ }
64
74
  // 解析原始响应
65
- const originalData = JSON.parse(xhr.responseText);
75
+ const originalData = JSON.parse(rawText);
66
76
  // 使用回调函数处理响应数据
67
77
  const modifiedData = matchingRule.responseCallback(originalData, requestUrl);
68
78
  // 重写响应属性
@@ -177,7 +187,7 @@ class XHRInterceptor {
177
187
  }
178
188
  }
179
189
  // 创建单例实例
180
- const xhrInterceptor = new XHRInterceptor({ enableLogging: true });
190
+ const xhrInterceptor = new XHRInterceptor({ enableLogging: false });
181
191
 
182
192
  exports.XHRInterceptor = XHRInterceptor;
183
193
  exports.xhrInterceptor = xhrInterceptor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ziya-utils",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "A javascript tool library.",
5
5
  "main": "./lib/index.js",
6
6
  "browser": "dist/ziya-utils.js",