ziya-utils 1.1.2 → 1.1.4

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.
Files changed (48) hide show
  1. package/README.md +35 -13
  2. package/README.zh-CN.md +42 -0
  3. package/dist/ziya-utils.js +1 -1
  4. package/es/async/index.d.ts +20 -0
  5. package/es/count/index.d.ts +25 -0
  6. package/es/count/index.js +30 -0
  7. package/es/date/index.d.ts +10 -2
  8. package/es/date/index.js +66 -19
  9. package/es/document/index.d.ts +7 -0
  10. package/es/file/index.d.ts +1 -1
  11. package/es/file/index.js +50 -58
  12. package/es/form/index.d.ts +15 -0
  13. package/es/form/index.js +51 -0
  14. package/es/index.d.ts +3 -0
  15. package/es/index.js +5 -2
  16. package/es/loger/index.d.ts +7 -0
  17. package/es/node_modules/tslib/tslib.es6.js +1 -43
  18. package/es/regexp/index.d.ts +1 -1
  19. package/es/regexp/index.js +20 -30
  20. package/es/security/index.d.ts +11 -3
  21. package/es/security/index.js +41 -4
  22. package/es/time/index.d.ts +1 -1
  23. package/es/time/index.js +4 -4
  24. package/es/xhr/index.d.ts +74 -0
  25. package/es/xhr/index.js +172 -0
  26. package/lib/async/index.d.ts +20 -0
  27. package/lib/count/index.d.ts +25 -0
  28. package/lib/count/index.js +32 -0
  29. package/lib/date/index.d.ts +10 -2
  30. package/lib/date/index.js +66 -18
  31. package/lib/document/index.d.ts +7 -0
  32. package/lib/file/index.d.ts +1 -1
  33. package/lib/file/index.js +49 -57
  34. package/lib/form/index.d.ts +15 -0
  35. package/lib/form/index.js +53 -0
  36. package/lib/index.d.ts +3 -0
  37. package/lib/index.js +9 -0
  38. package/lib/loger/index.d.ts +7 -0
  39. package/lib/node_modules/tslib/tslib.es6.js +0 -44
  40. package/lib/regexp/index.d.ts +1 -1
  41. package/lib/regexp/index.js +20 -30
  42. package/lib/security/index.d.ts +11 -3
  43. package/lib/security/index.js +41 -3
  44. package/lib/time/index.d.ts +1 -1
  45. package/lib/time/index.js +4 -4
  46. package/lib/xhr/index.d.ts +74 -0
  47. package/lib/xhr/index.js +175 -0
  48. package/package.json +17 -3
package/README.md CHANGED
@@ -1,20 +1,42 @@
1
- ### Ziya-Utils
2
- > 一个 Javascript 常用工具库。
1
+ <p align="center">
2
+ <a href="https://www.npmjs.com/package/ziya-utils">
3
+ Ziya-Utils
4
+ </a>
5
+ </p>
3
6
 
4
- ## 安装
7
+
8
+ <div align="center">
9
+
10
+ A Javascript common tool library.
11
+
12
+ [![NPM version][image-1]][1]
13
+ [![NPM downloads][image-2]][2]
14
+ ![gzip size](https://img.badgesize.io/https://unpkg.com/ziya-utils/dist/ziya-utils.js?label=gzip%20size&compression=gzip)
15
+ ![npm license](https://img.shields.io/npm/l/ziya-utils)
16
+
17
+ English | [简体中文](README.zh-CN.md)
18
+
19
+ </div>
20
+
21
+ ## 📦 Install
5
22
 
6
23
  ```bash
7
- $ npm install --save ziya-utils
8
- # or
9
- $ yarn add ziya-utils
10
- # or
11
- $ pnpm add ziya-utils
12
- # or
13
- $ bun add ziya-utils
24
+ $ npm install --save ziya-utils
25
+ # or
26
+ $ yarn add ziya-utils
27
+ # or
28
+ $ pnpm add ziya-utils
29
+ # or
30
+ $ bun add ziya-utils
14
31
  ```
15
32
 
16
- ## 使用
17
- ```js
18
- import { getUuid } from "ziya-utils";
33
+ ## 🔨 Usage
34
+
35
+ ```ts
36
+ import { getUuid } from "ziya-utils";
19
37
  ```
20
38
 
39
+ [1]: https://www.npmjs.com/package/ziya-utils
40
+ [2]: https://npmjs.org/package/ziya-utils
41
+ [image-1]: https://img.shields.io/npm/v/ziya-utils.svg?style=flat
42
+ [image-2]: https://img.shields.io/npm/dw/ziya-utils.svg?style=flat
@@ -0,0 +1,42 @@
1
+ <p align="center">
2
+ <a href="https://www.npmjs.com/package/ziya-utils">
3
+ Ziya-Utils
4
+ </a>
5
+ </p>
6
+
7
+
8
+ <div align="center">
9
+
10
+ 一个 Javascript 常用工具库。
11
+
12
+ [![NPM version][image-1]][1]
13
+ [![NPM downloads][image-2]][2]
14
+ ![gzip size](https://img.badgesize.io/https://unpkg.com/ziya-utils/dist/ziya-utils.js?label=gzip%20size&compression=gzip)
15
+ ![npm license](https://img.shields.io/npm/l/ziya-utils)
16
+
17
+ [English](README.md) | 简体中文
18
+
19
+ </div>
20
+
21
+ ## 📦 安装
22
+
23
+ ```bash
24
+ $ npm install --save ziya-utils
25
+ # or
26
+ $ yarn add ziya-utils
27
+ # or
28
+ $ pnpm add ziya-utils
29
+ # or
30
+ $ bun add ziya-utils
31
+ ```
32
+
33
+ ## 🔨 使用
34
+
35
+ ```ts
36
+ import { getUuid } from "ziya-utils";
37
+ ```
38
+
39
+ [1]: https://www.npmjs.com/package/ziya-utils
40
+ [2]: https://npmjs.org/package/ziya-utils
41
+ [image-1]: https://img.shields.io/npm/v/ziya-utils.svg?style=flat
42
+ [image-2]: https://img.shields.io/npm/dw/ziya-utils.svg?style=flat
@@ -1 +1 @@
1
- !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ZiyaUtils={})}(this,function(t){"use strict";var e=function(t,n){return e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&(t[n]=e[n])},e(t,n)};function n(t,e,n,r){return new(n||(n=Promise))(function(o,i){function u(t){try{s(r.next(t))}catch(t){i(t)}}function a(t){try{s(r.throw(t))}catch(t){i(t)}}function s(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n(function(t){t(e)})).then(u,a)}s((r=r.apply(t,e||[])).next())})}function r(t,e){var n,r,o,i,u={label:0,sent:function(){if(1&o[0])throw o[1];return o[1]},trys:[],ops:[]};return i={next:a(0),throw:a(1),return:a(2)},"function"==typeof Symbol&&(i[Symbol.iterator]=function(){return this}),i;function a(a){return function(s){return function(a){if(n)throw new TypeError("Generator is already executing.");for(;i&&(i=0,a[0]&&(u=0)),u;)try{if(n=1,r&&(o=2&a[0]?r.return:a[0]?r.throw||((o=r.return)&&o.call(r),0):r.next)&&!(o=o.call(r,a[1])).done)return o;switch(r=0,o&&(a=[2&a[0],o.value]),a[0]){case 0:case 1:o=a;break;case 4:return u.label++,{value:a[1],done:!1};case 5:u.label++,r=a[1],a=[0];continue;case 7:a=u.ops.pop(),u.trys.pop();continue;default:if(!(o=u.trys,(o=o.length>0&&o[o.length-1])||6!==a[0]&&2!==a[0])){u=0;continue}if(3===a[0]&&(!o||a[1]>o[0]&&a[1]<o[3])){u.label=a[1];break}if(6===a[0]&&u.label<o[1]){u.label=o[1],o=a;break}if(o&&u.label<o[2]){u.label=o[2],u.ops.push(a);break}o[2]&&u.ops.pop(),u.trys.pop();continue}a=e.call(t,u)}catch(t){a=[6,t],r=0}finally{n=o=0}if(5&a[0])throw a[1];return{value:a[0]?a[1]:void 0,done:!0}}([a,s])}}}"function"==typeof SuppressedError&&SuppressedError;var o={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]+$/},i=function(t){function n(){return null!==t&&t.apply(this,arguments)||this}return function(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Class extends value "+String(n)+" is not a constructor or null");function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}(n,t),n.isPhone=function(t){return o.PHONE.test(t)},n.isEmail=function(t){return o.EMAIL.test(t)},n.isIdCard=function(t){return o.ID_CARD.test(t)},n.isUrl=function(t){return o.URL.test(t)},n.isIpv4=function(t){return o.IPV4.test(t)},n.isStrongPassword=function(t){return o.STRONG_PASSWORD.test(t)},n.isChinese=function(t){return o.CHINESE.test(t)},n}(function(){}),u={patterns:o,validator:i},a=function(t){if(!t)return"";var e=Math.max(t.lastIndexOf("/"),t.lastIndexOf("\\"));return-1===e?t:t.slice(e+1)};function s(t){if("string"==typeof t){if(!/^\d+$/.test(t))return!1;t=Number(t)}if("number"!=typeof t||isNaN(t))return!1;var e=41024448e5;return 13===t.toString().length?t>=0&&t<=e:10===t.toString().length&&(t>=0&&t<=4102444800)}var c=function(t){return s(t)&&10===t.toString().length};t.RegexPatterns=o,t.RegexValidator=i,t.downloadSingleFile=function(t,e){return n(void 0,void 0,void 0,function(){var n,o,i,s,c,f,l;return r(this,function(r){switch(r.label){case 0:if(!t||!u.validator.isUrl(t))throw new Error("无效的URL");r.label=1;case 1:return r.trys.push([1,4,,5]),[4,fetch(t)];case 2:if(!(n=r.sent()).ok)throw new Error("下载失败: ".concat(n.status," ").concat(n.statusText));return(o=e)||(o=a(t),-1!==(i=o.indexOf("?"))&&(o=o.substring(0,i)),o||(o="downloaded_file")),[4,n.blob()];case 3:return s=r.sent(),c=URL.createObjectURL(s),(f=document.createElement("a")).href=c,f.download=o,document.body.appendChild(f),f.click(),setTimeout(function(){URL.revokeObjectURL(c),f.remove()},100),[3,5];case 4:throw l=r.sent(),console.error("文件下载失败:",l),l;case 5:return[2]}})})},t.extractFileNameFromPath=a,t.getElapsedTimeSince=function(t){var e=Date.now();s(t)||(t=e);var n=Math.max(0,e-(c(t)?1e3*t:t));return{hours:Math.floor(n/36e5),minutes:Math.floor(n%36e5/6e4),seconds:Math.floor(n%6e4/1e3)}},t.getUuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var e=16*Math.random()|0;return("x"==t?e:3&e|8).toString(16)})},t.isMillisecondTimestamp=function(t){return s(t)&&13===t.toString().length},t.isSecondTimestamp=c,t.isValidTimestamp=s,t.sleep=function(t){return new Promise(function(e){setTimeout(function(){e(!0)},1e3*t)})}});
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).ZiyaUtils={})}(this,function(t){"use strict";function e(t,e,n,o){return new(n||(n=Promise))(function(i,s){function r(t){try{c(o.next(t))}catch(t){s(t)}}function a(t){try{c(o.throw(t))}catch(t){s(t)}}function c(t){var e;t.done?i(t.value):(e=t.value,e instanceof n?e:new n(function(t){t(e)})).then(r,a)}c((o=o.apply(t,e||[])).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 i extends o{static isPhone(t){return n.PHONE.test(t)}static isEmail(t){return n.EMAIL.test(t)}static isIdCard(t){return n.ID_CARD.test(t)}static isUrl(t){return n.URL.test(t)}static isIpv4(t){return n.IPV4.test(t)}static isStrongPassword(t){return n.STRONG_PASSWORD.test(t)}static isChinese(t){return n.CHINESE.test(t)}}var s={patterns:n,validator:i};const r=t=>{if(!t)return"";const e=Math.max(t.lastIndexOf("/"),t.lastIndexOf("\\"));return-1===e?t:t.slice(e+1)};function a(t){if("string"==typeof t){if(!/^\d+$/.test(t))return!1;t=Number(t)}if("number"!=typeof t||isNaN(t))return!1;const e=41024448e5;return 13===t.toString().length?t>=0&&t<=e:10===t.toString().length&&(t>=0&&t<=4102444800)}const c=t=>a(t)&&10===t.toString().length;class l{constructor(t={}){var e;this.interceptRules=[],this.isActive=!1,this.originalXMLHttpRequest=window.XMLHttpRequest,this.enableLogging=null===(e=t.enableLogging)||void 0===e||e}start(){if(this.isActive)return void this.log("拦截器已经启动");const t=this;window.XMLHttpRequest=function(){const n=new t.originalXMLHttpRequest;let o="";const i=n.open;n.open=function(t,e,n=!0,s,r){return o="string"==typeof e?e:e.toString(),i.call(this,t,e,n,s,r)};const s=n.send;return n.send=function(i){const r=t.findMatchingRule(o);if(!r)return s.call(this,i);const a=n.onreadystatechange;return n.onreadystatechange=function(i){return e(this,void 0,void 0,function*(){if(4===n.readyState&&n.status>=200&&n.status<300)try{const e=JSON.parse(n.responseText),i=yield r.responseCallback(e);Object.defineProperty(n,"responseText",{writable:!0,configurable:!0,value:JSON.stringify(i)}),Object.defineProperty(n,"response",{writable:!0,configurable:!0,value:JSON.stringify(i)}),t.log(`已拦截并修改响应: ${o}`)}catch(e){t.log("拦截器处理失败:",e)}a&&a.call(this,i)})},s.call(this,i)},n},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(t){this.interceptRules=[...t],this.log("已设置拦截规则:",t.map(t=>t.url))}addRule(t,e){this.interceptRules.push({url:t,responseCallback:e}),this.log(`已添加拦截规则: ${t}`)}removeRule(t){const e=this.interceptRules.length;this.interceptRules=this.interceptRules.filter(e=>e.url!==t);const n=this.interceptRules.length<e;return n?this.log(`已移除拦截规则: ${t}`):this.log(`未找到拦截规则: ${t}`),n}clearRules(){this.interceptRules=[],this.log("已清除所有拦截规则")}getRules(){return[...this.interceptRules]}getStatus(){return{isActive:this.isActive,rulesCount:this.interceptRules.length}}findMatchingRule(t){return this.interceptRules.find(e=>t.includes(e.url))}log(t,...e){this.enableLogging&&console.log(`[XHRInterceptor] ${t}`,...e)}}const u=new l({enableLogging:!0});t.RegexPatterns=n,t.RegexValidator=i,t.XHRInterceptor=l,t.copyToClipboard=function(t){return e(this,void 0,void 0,function*(){try{var e=JSON.stringify(t);if(navigator.clipboard&&(window.isSecureContext||"https:"===location.protocol||"localhost"===location.hostname))return yield navigator.clipboard.writeText(e),!0;var n=document.createElement("textarea");n.value=e,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(t){return console.error("复制失败:",t),!1}})},t.createFormData=function(t){const e=new FormData;if("string"==typeof t){const n=new URLSearchParams(t);for(const[t,o]of n)e.append(t,o)}else"object"==typeof t&&null!==t&&Object.keys(t).forEach(n=>{const o=t[n];null!=o?Array.isArray(o)?o.forEach(t=>e.append(n,String(t))):o instanceof File||o instanceof Blob?e.append(n,o):"object"==typeof o?e.append(n,JSON.stringify(o)):e.append(n,String(o)):e.append(n,"")});return e},t.downloadSingleFile=(t,n)=>e(void 0,void 0,void 0,function*(){if(!t||!s.validator.isUrl(t))throw new Error("无效的URL");try{const e=yield fetch(t);if(!e.ok)throw new Error(`下载失败: ${e.status} ${e.statusText}`);let o=n;if(!o){o=r(t);const e=o.indexOf("?");-1!==e&&(o=o.substring(0,e)),o||(o="downloaded_file")}const i=yield e.blob(),s=URL.createObjectURL(i),a=document.createElement("a");a.href=s,a.download=o,document.body.appendChild(a),a.click(),setTimeout(()=>{URL.revokeObjectURL(s),a.remove()},100)}catch(t){throw console.error("文件下载失败:",t),t}}),t.extractFileNameFromPath=r,t.formatDateTypeSafe=function(t,e){return function(t,e){const n=e||new Date,o=(t,e=2)=>t.toString().padStart(e,"0"),i={year:n.getFullYear(),month:n.getMonth()+1,day:n.getDate(),hours:n.getHours(),minutes:n.getMinutes(),seconds:n.getSeconds(),milliseconds:n.getMilliseconds()},s={YYYY:i.year.toString(),YY:i.year.toString().slice(-2),MM:o(i.month),M:i.month.toString(),DD:o(i.day),D:i.day.toString(),HH:o(i.hours),H:i.hours.toString(),mm:o(i.minutes),m:i.minutes.toString(),ss:o(i.seconds),s:i.seconds.toString(),SSS:o(i.milliseconds,3)};return Object.keys(s).sort((t,e)=>e.length-t.length).reduce((t,e)=>t.replace(new RegExp(e,"g"),s[e]),t)}(t,e)},t.getElapsedTimeSince=t=>{const e=Date.now();a(t)||(t=e);const n=Math.max(0,e-(c(t)?1e3*t:t));return{hours:Math.floor(n/36e5),minutes:Math.floor(n%36e5/6e4),seconds:Math.floor(n%6e4/1e3)}},t.getUuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var e=16*Math.random()|0;return("x"==t?e:3&e|8).toString(16)})},t.isMillisecondTimestamp=t=>a(t)&&13===t.toString().length,t.isSecondTimestamp=c,t.isValidTimestamp=a,t.precisionFormat=function(t,e,n=!0,o=!0){var i=t<0&&o?-1:1;const s=Math.pow(10,e);return n?Math.round(t*s*i)/s*i:Math.floor(t*s*i)/s*i},t.sleep=t=>new Promise(e=>{setTimeout(()=>{e(!0)},1e3*t)}),t.xhrInterceptor=u});
@@ -0,0 +1,20 @@
1
+ type CheckFunction<T = any> = () => T | null | undefined | false;
2
+ type InitFunction<T = any, R = any> = (checkResult: T) => R | Promise<R>;
3
+ interface AsyncTaskOptions {
4
+ /** 检查间隔时间(秒),默认 1 秒 */
5
+ duration?: number;
6
+ /** 最大等待时间(秒),超时后会 reject */
7
+ timeout?: number;
8
+ /** 是否立即执行一次检查,默认 false */
9
+ immediate?: boolean;
10
+ }
11
+ /**
12
+ * 创建异步任务,定时检查条件直到满足后执行初始化函数
13
+ * @param checkFun 检查函数,返回 true 值时表示条件满足
14
+ * @param initFun 初始化函数,在条件满足后执行
15
+ * @param options 配置选项
16
+ * @returns Promise,resolve 初始化函数的返回值
17
+ */
18
+ declare function createAsyncTask<T, R>(checkFun?: CheckFunction<T>, initFun?: InitFunction<T, R>, options?: AsyncTaskOptions): Promise<R>;
19
+ export { createAsyncTask };
20
+ export type { CheckFunction, InitFunction, AsyncTaskOptions };
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @fileoverview 数值模块
3
+ * @created 2025-04-2
4
+ * @author glk
5
+ */
6
+ /**
7
+ * 数值的精度控制
8
+ * @param num 源数值,可以为负
9
+ * @param count 保留几位有效数字
10
+ * @param round 是否四舍五入
11
+ * @param consistent 是否保持一致性
12
+ * @example
13
+ * formatDecimals(0.15, 1, false, false) // 0.1
14
+ * formatDecimals(0.15, 1, false, true) // 0.1
15
+ * formatDecimals(0.15, 1, true, false) // 0.2
16
+ * formatDecimals(0.15, 1, true, true) // 0.2
17
+ *
18
+ * formatDecimals(-0.15, 1, false, true) // -0.1
19
+ * formatDecimals(-0.15, 1, false, false) // -0.2
20
+ * formatDecimals(-0.15, 1, true, true) // -0.2
21
+ * formatDecimals(-0.15, 1, true, false) // -0.1
22
+ * @returns
23
+ */
24
+ declare function precisionFormat(num: number, count: number, round?: boolean, consistent?: boolean): number;
25
+ export { precisionFormat };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @fileoverview 数值模块
3
+ * @created 2025-04-2
4
+ * @author glk
5
+ */
6
+ /**
7
+ * 数值的精度控制
8
+ * @param num 源数值,可以为负
9
+ * @param count 保留几位有效数字
10
+ * @param round 是否四舍五入
11
+ * @param consistent 是否保持一致性
12
+ * @example
13
+ * formatDecimals(0.15, 1, false, false) // 0.1
14
+ * formatDecimals(0.15, 1, false, true) // 0.1
15
+ * formatDecimals(0.15, 1, true, false) // 0.2
16
+ * formatDecimals(0.15, 1, true, true) // 0.2
17
+ *
18
+ * formatDecimals(-0.15, 1, false, true) // -0.1
19
+ * formatDecimals(-0.15, 1, false, false) // -0.2
20
+ * formatDecimals(-0.15, 1, true, true) // -0.2
21
+ * formatDecimals(-0.15, 1, true, false) // -0.1
22
+ * @returns
23
+ */
24
+ function precisionFormat(num, count, round = true, consistent = true) {
25
+ var sign = num < 0 ? (consistent ? -1 : 1) : 1;
26
+ const val = Math.pow(10, count);
27
+ return round ? (Math.round(num * val * sign) / val) * sign : (Math.floor(num * val * sign) / val) * sign;
28
+ }
29
+
30
+ export { precisionFormat };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview 日期模块
3
- * @date 2025-04-02
3
+ * @created 2025-04-02
4
4
  * @author glk
5
5
  */
6
6
  /**
@@ -31,4 +31,12 @@ declare const getElapsedTimeSince: (timestamp: number) => {
31
31
  minutes: number;
32
32
  seconds: number;
33
33
  };
34
- export { isValidTimestamp, isSecondTimestamp, isMillisecondTimestamp, getElapsedTimeSince, };
34
+ type DateFormatTemplate = 'YYYY-MM-DD' | 'YYYY/MM/DD' | 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY-MM-DD HH:mm:ss' | 'HH:mm:ss' | 'HH:mm' | string;
35
+ /**
36
+ * 类型安全的日期格式化函数
37
+ * @param format 格式字符串或预定义模板
38
+ * @param date 可选的日期对象
39
+ * @returns 格式化后的日期字符串
40
+ */
41
+ declare function formatDateTypeSafe(format: DateFormatTemplate, date?: Date): string;
42
+ export { isValidTimestamp, isSecondTimestamp, isMillisecondTimestamp, getElapsedTimeSince, formatDateTypeSafe, };
package/es/date/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview 日期模块
3
- * @date 2025-04-02
3
+ * @created 2025-04-02
4
4
  * @author glk
5
5
  */
6
6
  /**
@@ -23,9 +23,9 @@ function isValidTimestamp(timestamp) {
23
23
  }
24
24
  // 检查时间戳范围是否合理
25
25
  // 时间戳下限:1970年1月1日
26
- var minTimestamp = 0;
26
+ const minTimestamp = 0;
27
27
  // 时间戳上限:设置为一个合理的未来日期,例如2100年1月1日
28
- var maxTimestamp = 4102444800000; // 2100-01-01的毫秒时间戳
28
+ const maxTimestamp = 4102444800000; // 2100-01-01的毫秒时间戳
29
29
  // 检查时间戳是否为13位(毫秒级)或10位(秒级)
30
30
  if (timestamp.toString().length === 13) {
31
31
  // 毫秒级时间戳
@@ -43,39 +43,86 @@ function isValidTimestamp(timestamp) {
43
43
  * @param timestamp
44
44
  * @returns
45
45
  */
46
- var isSecondTimestamp = function (timestamp) {
47
- return isValidTimestamp(timestamp) && timestamp.toString().length === 10;
48
- };
46
+ const isSecondTimestamp = (timestamp) => isValidTimestamp(timestamp) && timestamp.toString().length === 10;
49
47
  /**
50
48
  * 是不是毫秒级时间戳
51
49
  * @param timestamp
52
50
  * @returns
53
51
  */
54
- var isMillisecondTimestamp = function (timestamp) {
55
- return isValidTimestamp(timestamp) && timestamp.toString().length === 13;
56
- };
52
+ const isMillisecondTimestamp = (timestamp) => isValidTimestamp(timestamp) && timestamp.toString().length === 13;
57
53
  /**
58
54
  * 计算传入时间戳和当前时间的时间差
59
55
  * @param timestamp 时间戳
60
56
  * @returns
61
57
  */
62
- var getElapsedTimeSince = function (timestamp) {
63
- var now = Date.now();
58
+ const getElapsedTimeSince = (timestamp) => {
59
+ const now = Date.now();
64
60
  if (!isValidTimestamp(timestamp)) {
65
61
  timestamp = now;
66
62
  }
67
- var diff = Math.max(0, now - (isSecondTimestamp(timestamp) ? timestamp * 1000 : timestamp));
63
+ const diff = Math.max(0, now - (isSecondTimestamp(timestamp) ? timestamp * 1000 : timestamp));
68
64
  // 计算小时
69
- var hours = Math.floor(diff / (1000 * 60 * 60));
65
+ const hours = Math.floor(diff / (1000 * 60 * 60));
70
66
  // 计算分钟
71
- var minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
67
+ const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
72
68
  // 计算秒
73
- var seconds = Math.floor((diff % (1000 * 60)) / 1000);
69
+ const seconds = Math.floor((diff % (1000 * 60)) / 1000);
74
70
  return {
75
- hours: hours,
76
- minutes: minutes,
77
- seconds: seconds,
71
+ hours,
72
+ minutes,
73
+ seconds,
78
74
  };
79
75
  };
76
+ /**
77
+ * 日期格式化
78
+ * @param format 格式字符串
79
+ * @param date 可选的日期对象,默认为当前时间
80
+ * @returns 格式化后的日期字符串
81
+ */
82
+ function formatDateAdvanced(format, date) {
83
+ const targetDate = date || new Date();
84
+ // 类型安全的数字格式化
85
+ const pad = (num, length = 2) => num.toString().padStart(length, "0");
86
+ // 获取各个时间组件
87
+ const components = {
88
+ year: targetDate.getFullYear(),
89
+ month: targetDate.getMonth() + 1,
90
+ day: targetDate.getDate(),
91
+ hours: targetDate.getHours(),
92
+ minutes: targetDate.getMinutes(),
93
+ seconds: targetDate.getSeconds(),
94
+ milliseconds: targetDate.getMilliseconds()
95
+ };
96
+ // 格式化映射表
97
+ const formatMap = {
98
+ 'YYYY': components.year.toString(),
99
+ 'YY': components.year.toString().slice(-2),
100
+ 'MM': pad(components.month),
101
+ 'M': components.month.toString(),
102
+ 'DD': pad(components.day),
103
+ 'D': components.day.toString(),
104
+ 'HH': pad(components.hours),
105
+ 'H': components.hours.toString(),
106
+ 'mm': pad(components.minutes),
107
+ 'm': components.minutes.toString(),
108
+ 'ss': pad(components.seconds),
109
+ 's': components.seconds.toString(),
110
+ 'SSS': pad(components.milliseconds, 3)
111
+ };
112
+ // 按照键的长度排序,避免短键替换长键的问题
113
+ const sortedKeys = Object.keys(formatMap).sort((a, b) => b.length - a.length);
114
+ return sortedKeys.reduce((result, key) => {
115
+ return result.replace(new RegExp(key, 'g'), formatMap[key]);
116
+ }, format);
117
+ }
118
+ /**
119
+ * 类型安全的日期格式化函数
120
+ * @param format 格式字符串或预定义模板
121
+ * @param date 可选的日期对象
122
+ * @returns 格式化后的日期字符串
123
+ */
124
+ function formatDateTypeSafe(format, date) {
125
+ return formatDateAdvanced(format, date);
126
+ }
80
127
 
81
- export { getElapsedTimeSince, isMillisecondTimestamp, isSecondTimestamp, isValidTimestamp };
128
+ export { formatDateTypeSafe, getElapsedTimeSince, isMillisecondTimestamp, isSecondTimestamp, isValidTimestamp };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @fileoverview Document模块
3
+ * @created 2025-04-02
4
+ * @author glk
5
+ */
6
+ declare function addStyleStr(styStr?: string): HTMLStyleElement;
7
+ export { addStyleStr };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @fileoverview 文件模块
3
- * @date 2025-04-2
3
+ * @created 2025-04-2
4
4
  * @author glk
5
5
  */
6
6
  /**
package/es/file/index.js CHANGED
@@ -1,9 +1,9 @@
1
- import { __awaiter, __generator } from '../node_modules/tslib/tslib.es6.js';
1
+ import { __awaiter } from '../node_modules/tslib/tslib.es6.js';
2
2
  import IRegexUtils from '../regexp/index.js';
3
3
 
4
4
  /**
5
5
  * @fileoverview 文件模块
6
- * @date 2025-04-2
6
+ * @created 2025-04-2
7
7
  * @author glk
8
8
  */
9
9
  /**
@@ -11,12 +11,12 @@ import IRegexUtils from '../regexp/index.js';
11
11
  * @param filePath 文件路径字符串
12
12
  * @returns 提取的文件名,如果路径为空则返回空字符串,如果路径中没有分隔符则返回原字符串
13
13
  */
14
- var extractFileNameFromPath = function (filePath) {
14
+ const extractFileNameFromPath = (filePath) => {
15
15
  if (!filePath) {
16
16
  return "";
17
17
  }
18
18
  // 同时支持 Unix/Linux/Mac (/) 和 Windows (\) 风格的路径
19
- var lastSlashIndex = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
19
+ const lastSlashIndex = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
20
20
  // 如果找不到分隔符,则整个字符串就是文件名
21
21
  if (lastSlashIndex === -1) {
22
22
  return filePath;
@@ -30,60 +30,52 @@ var extractFileNameFromPath = function (filePath) {
30
30
  * @returns Promise<void>
31
31
  * @throws Error 当URL无效或网络请求失败时抛出错误
32
32
  */
33
- var downloadSingleFile = function (url, name) { return __awaiter(void 0, void 0, void 0, function () {
34
- var response, fileName, queryIndex, blob, blobUrl_1, link_1, error_1;
35
- return __generator(this, function (_a) {
36
- switch (_a.label) {
37
- case 0:
38
- // 验证URL
39
- if (!url || !IRegexUtils.validator.isUrl(url)) {
40
- throw new Error('无效的URL');
41
- }
42
- _a.label = 1;
43
- case 1:
44
- _a.trys.push([1, 4, , 5]);
45
- return [4 /*yield*/, fetch(url)];
46
- case 2:
47
- response = _a.sent();
48
- // 检查响应状态
49
- if (!response.ok) {
50
- throw new Error("\u4E0B\u8F7D\u5931\u8D25: ".concat(response.status, " ").concat(response.statusText));
51
- }
52
- fileName = name;
53
- if (!fileName) {
54
- fileName = extractFileNameFromPath(url);
55
- queryIndex = fileName.indexOf('?');
56
- if (queryIndex !== -1) {
57
- fileName = fileName.substring(0, queryIndex);
58
- }
59
- // 如果仍然没有文件名,使用默认名称
60
- if (!fileName) {
61
- fileName = 'downloaded_file';
62
- }
63
- }
64
- return [4 /*yield*/, response.blob()];
65
- case 3:
66
- blob = _a.sent();
67
- blobUrl_1 = URL.createObjectURL(blob);
68
- link_1 = document.createElement('a');
69
- link_1.href = blobUrl_1;
70
- link_1.download = fileName;
71
- // 执行下载
72
- document.body.appendChild(link_1);
73
- link_1.click();
74
- // 清理
75
- setTimeout(function () {
76
- URL.revokeObjectURL(blobUrl_1);
77
- link_1.remove();
78
- }, 100); // 添加小延迟以确保下载开始
79
- return [3 /*break*/, 5];
80
- case 4:
81
- error_1 = _a.sent();
82
- console.error('文件下载失败:', error_1);
83
- throw error_1; // 重新抛出错误以便调用者可以处理
84
- case 5: return [2 /*return*/];
33
+ const downloadSingleFile = (url, name) => __awaiter(void 0, void 0, void 0, function* () {
34
+ // 验证URL
35
+ if (!url || !IRegexUtils.validator.isUrl(url)) {
36
+ throw new Error('无效的URL');
37
+ }
38
+ try {
39
+ // 获取响应
40
+ const response = yield fetch(url);
41
+ // 检查响应状态
42
+ if (!response.ok) {
43
+ throw new Error(`下载失败: ${response.status} ${response.statusText}`);
44
+ }
45
+ // 获取文件名 - 优先使用提供的名称,否则从URL中提取
46
+ let fileName = name;
47
+ if (!fileName) {
48
+ fileName = extractFileNameFromPath(url);
49
+ // 处理查询参数
50
+ const queryIndex = fileName.indexOf('?');
51
+ if (queryIndex !== -1) {
52
+ fileName = fileName.substring(0, queryIndex);
53
+ }
54
+ // 如果仍然没有文件名,使用默认名称
55
+ if (!fileName) {
56
+ fileName = 'downloaded_file';
57
+ }
85
58
  }
86
- });
87
- }); };
59
+ // 获取blob和内容类型
60
+ const blob = yield response.blob();
61
+ // 创建下载链接
62
+ const blobUrl = URL.createObjectURL(blob); // 注意:直接使用原始blob保留MIME类型
63
+ const link = document.createElement('a');
64
+ link.href = blobUrl;
65
+ link.download = fileName;
66
+ // 执行下载
67
+ document.body.appendChild(link);
68
+ link.click();
69
+ // 清理
70
+ setTimeout(() => {
71
+ URL.revokeObjectURL(blobUrl);
72
+ link.remove();
73
+ }, 100); // 添加小延迟以确保下载开始
74
+ }
75
+ catch (error) {
76
+ console.error('文件下载失败:', error);
77
+ throw error; // 重新抛出错误以便调用者可以处理
78
+ }
79
+ });
88
80
 
89
81
  export { downloadSingleFile, extractFileNameFromPath };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @fileoverview 表单模块
3
+ * @created 2025-04-02
4
+ * @author glk
5
+ */
6
+ type FormDataValue = string | number | boolean | File | Blob | null | undefined;
7
+ type FormDataInput = string | Record<string, FormDataValue | FormDataValue[] | Record<string, any>>;
8
+ /**
9
+ * 将数据转换为 FormData 对象
10
+ * @param data 要转换的数据,可以是查询字符串或对象
11
+ * @returns FormData 对象
12
+ */
13
+ declare function createFormData(data: FormDataInput): FormData;
14
+ export { createFormData };
15
+ export type { FormDataInput, FormDataValue };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @fileoverview 表单模块
3
+ * @created 2025-04-02
4
+ * @author glk
5
+ */
6
+ /**
7
+ * 将数据转换为 FormData 对象
8
+ * @param data 要转换的数据,可以是查询字符串或对象
9
+ * @returns FormData 对象
10
+ */
11
+ function createFormData(data) {
12
+ const formData = new FormData();
13
+ if (typeof data === "string") {
14
+ // 处理查询字符串
15
+ const params = new URLSearchParams(data);
16
+ for (const [key, value] of params) {
17
+ formData.append(key, value);
18
+ }
19
+ }
20
+ else if (typeof data === "object" && data !== null) {
21
+ // 处理对象
22
+ Object.keys(data).forEach((key) => {
23
+ const value = data[key];
24
+ if (value !== null && value !== undefined) {
25
+ if (Array.isArray(value)) {
26
+ // 数组:每个元素单独添加
27
+ value.forEach((item) => formData.append(key, String(item)));
28
+ }
29
+ else if (value instanceof File || value instanceof Blob) {
30
+ // 文件或Blob直接添加
31
+ formData.append(key, value);
32
+ }
33
+ else if (typeof value === "object") {
34
+ // 对象直接转字符串
35
+ formData.append(key, JSON.stringify(value));
36
+ }
37
+ else {
38
+ // 其他类型转为字符串
39
+ formData.append(key, String(value));
40
+ }
41
+ }
42
+ else {
43
+ // null 或 undefined 转为空字符串
44
+ formData.append(key, "");
45
+ }
46
+ });
47
+ }
48
+ return formData;
49
+ }
50
+
51
+ export { createFormData };
package/es/index.d.ts CHANGED
@@ -3,3 +3,6 @@ export * from "./time";
3
3
  export * from "./date";
4
4
  export * from "./security";
5
5
  export * from "./regexp";
6
+ export * from "./form";
7
+ export * from "./count";
8
+ export * from "./xhr";
package/es/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  export { downloadSingleFile, extractFileNameFromPath } from './file/index.js';
2
2
  export { sleep } from './time/index.js';
3
- export { getElapsedTimeSince, isMillisecondTimestamp, isSecondTimestamp, isValidTimestamp } from './date/index.js';
4
- export { getUuid } from './security/index.js';
3
+ export { formatDateTypeSafe, getElapsedTimeSince, isMillisecondTimestamp, isSecondTimestamp, isValidTimestamp } from './date/index.js';
4
+ export { copyToClipboard, getUuid } from './security/index.js';
5
5
  export { RegexPatterns, RegexValidator } from './regexp/index.js';
6
+ export { createFormData } from './form/index.js';
7
+ export { precisionFormat } from './count/index.js';
8
+ export { XHRInterceptor, xhrInterceptor } from './xhr/index.js';
@@ -0,0 +1,7 @@
1
+ declare const loger: {
2
+ info: (...args: any[]) => void;
3
+ error: (...args: any[]) => void;
4
+ warn: (...args: any[]) => void;
5
+ debug: (...args: any[]) => void;
6
+ };
7
+ export { loger };