@jhqn/utils-core 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,2 +1,3 @@
1
1
  # utils
2
+
2
3
  A collection of tool functions🧷
package/dist/index.d.ts CHANGED
@@ -4,7 +4,6 @@
4
4
  /// <reference types="dayjs/plugin/customParseFormat" />
5
5
  /// <reference types="dayjs/plugin/objectSupport" />
6
6
 
7
- import { detect as detect$1 } from "detect-browser-es";
8
7
  import dayjs, { ConfigType, Dayjs } from "dayjs";
9
8
 
10
9
  //#region types/index.d.ts
@@ -425,13 +424,6 @@ declare const hideEmail: (email: UnDef<string>) => string;
425
424
  */
426
425
  declare const hideBankCard: (bankCard: UnDef<string>) => string;
427
426
  //#endregion
428
- //#region src/detect.d.ts
429
- /**
430
- * 检测浏览器环境
431
- * @deprecated 下个版本移除,请直接使用 `detect-browser-es` 包
432
- */
433
- declare const detect: typeof detect$1;
434
- //#endregion
435
427
  //#region src/dom.d.ts
436
428
  /**
437
429
  * 判断是否是浏览器环境
@@ -675,7 +667,7 @@ declare const getMockDataList: <T>(data: T[], total: number, code?: number, mess
675
667
  * 检测变量类型
676
668
  * @param {any} val 检测的目标
677
669
  */
678
- declare const getVariableType: (val: any) => string | undefined;
670
+ declare const getVariableType: (val: any) => string;
679
671
  /**
680
672
  * 是否是数字
681
673
  * @param {any} val 检测的目标
@@ -903,5 +895,4 @@ declare const isValidArrRes: (res: Res<any[]>, code?: number) => boolean;
903
895
  */
904
896
  declare const isValidPageRes: (res: PageRes, code?: number) => boolean;
905
897
  //#endregion
906
- export { type Dayjs, type Dict, type HostEnv, type MaybeArray, type NullOrUndefinable, type Nullable, type Numeric, type PageReq, type PageRes, type PageResData, type PartialBy, type Res, type UnDef, type Undefinable, type VK, attachFmt, camel2Kebab, camel2Pascal, camel2Snake, camel2Title, checkImg, cnIdCard15Re, cnIdCard18Re, cnPhoneRE, cnTelRE, cnTelRE2, cnUSCIRE, currencyFmt, dateDuration, dateFmt, dayjs, detect, emailRE, filterObj, fixiOSInputAutoZoomIn, getBaseAttachUrl, getCodeOfDate, getCodeOfHour, getCodeOfMonth, getHostEnv, getMockData, getMockDataList, getVariableType, hideBankCard, hideCardNo, hideEmail, hideFirstName, hideHead, hideMiddle, hidePhone, hideSurname, hideTail, hideThird, inBrowser, isArrStr, isArray, isBigInt, isBlob, isBoolean, isDate, isDef, isEmail, isEmpty, isError, isFile, isFunction, isIdCard, isJSONStr, isMap, isNull, isNumber, isNumeric, isObject, isPhone, isPromise, isRegExp, isSet, isString, isSymbol, isTel, isURL, isUSCI, isUndefined, isValidArrRes, isValidFileType, isValidKey, isValidPageRes, isValidRes, isValidResCode, isWeakMap, isWeakSet, jClear, jDebug, jError, jGroup, jGroupC, jGroupE, jInfo, jLog, jLogDedupe, jLogOnce, jTime, jTimeEnd, jWarn, kebab2Camel, kebab2Pascal, kebab2Snake, kebab2Title, naturalSort, naturalSortBy, nonASCII, parseJSON, parseToJSON, pascal2Camel, pascal2Kebab, pascal2Snake, pascal2Title, recoverFile, replacer, resUrl, reviver, setBaseAttachUrl, snake2Camel, snake2Kebab, snake2Pascal, snake2Title, stringifyJSON, title2Camel, title2Kebab, title2Pascal, title2Snake, toThousands, userAgent, waitTime };
907
- //# sourceMappingURL=index.d.ts.map
898
+ export { type Dayjs, type Dict, type HostEnv, type MaybeArray, type NullOrUndefinable, type Nullable, type Numeric, type PageReq, type PageRes, type PageResData, type PartialBy, type Res, type UnDef, type Undefinable, type VK, attachFmt, camel2Kebab, camel2Pascal, camel2Snake, camel2Title, checkImg, cnIdCard15Re, cnIdCard18Re, cnPhoneRE, cnTelRE, cnTelRE2, cnUSCIRE, currencyFmt, dateDuration, dateFmt, dayjs, emailRE, filterObj, fixiOSInputAutoZoomIn, getBaseAttachUrl, getCodeOfDate, getCodeOfHour, getCodeOfMonth, getHostEnv, getMockData, getMockDataList, getVariableType, hideBankCard, hideCardNo, hideEmail, hideFirstName, hideHead, hideMiddle, hidePhone, hideSurname, hideTail, hideThird, inBrowser, isArrStr, isArray, isBigInt, isBlob, isBoolean, isDate, isDef, isEmail, isEmpty, isError, isFile, isFunction, isIdCard, isJSONStr, isMap, isNull, isNumber, isNumeric, isObject, isPhone, isPromise, isRegExp, isSet, isString, isSymbol, isTel, isURL, isUSCI, isUndefined, isValidArrRes, isValidFileType, isValidKey, isValidPageRes, isValidRes, isValidResCode, isWeakMap, isWeakSet, jClear, jDebug, jError, jGroup, jGroupC, jGroupE, jInfo, jLog, jLogDedupe, jLogOnce, jTime, jTimeEnd, jWarn, kebab2Camel, kebab2Pascal, kebab2Snake, kebab2Title, naturalSort, naturalSortBy, nonASCII, parseJSON, parseToJSON, pascal2Camel, pascal2Kebab, pascal2Snake, pascal2Title, recoverFile, replacer, resUrl, reviver, setBaseAttachUrl, snake2Camel, snake2Kebab, snake2Pascal, snake2Title, stringifyJSON, title2Camel, title2Kebab, title2Pascal, title2Snake, toThousands, userAgent, waitTime };
package/dist/index.js CHANGED
@@ -1,2 +1,1072 @@
1
- import{detect as e}from"detect-browser-es";import t from"dayjs";import n from"dayjs/locale/zh-cn.js";import r from"dayjs/plugin/customParseFormat.js";import i from"dayjs/plugin/duration.js";import a from"dayjs/plugin/localeData.js";import o from"dayjs/plugin/objectSupport.js";import s from"dayjs/plugin/relativeTime.js";const c=e=>e.replace(/_([a-z])/g,(e,t)=>`-${t.toLowerCase()}`),l=e=>e.replace(/_([a-z])/g,(e,t)=>t.toUpperCase()).replace(/^[a-z]/,e=>e.toUpperCase()),ee=e=>e.replace(/(_([a-z]))/g,e=>e[1].toUpperCase()),te=e=>e.replace(/_([a-z])/g,(e,t)=>` ${t.toUpperCase()}`).replace(/^[a-z]/,e=>e.toUpperCase()),ne=e=>e.replace(/-([a-z])/g,(e,t)=>`_${t.toLowerCase()}`),re=e=>e.replace(/-([a-z])/g,(e,t)=>t.toUpperCase()).replace(/^[a-z]/,e=>e.toUpperCase()),ie=e=>{let[t,...n]=e.split(`-`);return[t,...n.map(e=>e.replace(/^[a-z]/,e[0].toUpperCase()))].join(``)},ae=e=>e.replace(/-([a-z])/g,(e,t)=>` ${t.toUpperCase()}`).replace(/^[a-z]/,e=>e.toUpperCase()),oe=e=>e.replace(/([A-Z])/g,(e,t)=>`_${t.toLowerCase()}`).replace(/^_/,``),u=e=>e.replace(/([A-Z])/g,(e,t)=>`-${t.toLowerCase()}`).replace(/^-/,``),d=e=>e.replace(/^[A-Z]/,e=>e.toLowerCase()),se=e=>e.replace(/([A-Z])/g,(e,t)=>` ${t}`).replace(/^ /,``),ce=e=>e.replace(/([A-Z])/g,(e,t)=>`_${t.toLowerCase()}`),le=e=>e.replace(/([A-Z])/g,(e,t)=>`-${t.toLowerCase()}`),ue=e=>e.replace(/(^[a-z])|(\s+[a-z])/g,e=>e.toUpperCase()),de=e=>e.replace(/([A-Z])/g,(e,t)=>` ${t}`).replace(/^[a-z]/,e=>e.toUpperCase()),fe=e=>e.replace(/([A-Z])/g,e=>e.toLowerCase()).replace(/ /g,`_`),pe=e=>e.replace(/([A-Z])/g,e=>e.toLowerCase()).replace(/ /g,`-`),me=e=>e.replace(/ /g,``),he=e=>e.replace(/ /g,``).replace(/^[A-Z]/,e=>e.toLowerCase()),f=`color: white; padding: 1px 2px;`,p=(...e)=>__DEV__?console.log.bind(console,`%c[${e.length===1?`LOG`:`%s`}]`,`${f} background: seagreen;`)(...e):()=>{},ge=(...e)=>console.log.bind(console,`%c[${e.length===1?`DEBUG`:`%s`}]`,`${f} background: linear-gradient(LightSalmon, Tomato); border-radius: 2px; font-weight: bold; border-top: 2px solid Crimson; border-bottom: 2px solid Crimson;`)(...e),m=(...e)=>console.warn.bind(console,`%c[${e.length===1?`WARN`:`%s`}]`,`${f} background: tomato;`)(...e),_e=(...e)=>console.error.bind(console,`%c[${e.length===1?`ERROR`:`%s`}]`,`${f} background: crimson;`)(...e),ve=(...e)=>console.info.bind(console,`%c[${e.length===1?`INFO`:`%s`}]`,`${f} background: dodgerblue;`)(...e),ye=console.group.bind(console,`%c[%s]`,`${f} background: slateblue;`),be=console.groupCollapsed.bind(console,`%c[%s]`,`${f} background: slateblue;`),xe=console.groupEnd.bind(console),Se=e=>console.time(`[${e}]`),Ce=e=>console.timeEnd(`[${e}]`),we=console.clear.bind(console);let h;const Te=(...e)=>{e.length!==0&&(e.length>0&&h&&JSON.stringify(e)===JSON.stringify(h)||(p(...e),h=e))};let Ee=!1;const De=(...e)=>{Ee||=(p(...e),!0)},g=e=>(Object.prototype.toString.call(e).match(/\[object (\S*)\]/)?.[1])?.toLocaleLowerCase(),Oe=e=>g(e)===`number`,ke=e=>g(e)===`bigint`,Ae=e=>g(e)===`string`,je=e=>g(e)===`boolean`,_=e=>g(e)===`null`,v=e=>g(e)===`undefined`,Me=e=>g(e)===`symbol`,y=e=>g(e)===`object`,b=e=>g(e)===`array`,x=e=>g(e)===`function`,S=e=>g(e)===`date`,Ne=e=>g(e)===`regexp`,Pe=e=>g(e)===`promise`,C=e=>g(e)===`set`,w=e=>g(e)===`map`,Fe=e=>g(e)===`weakset`,Ie=e=>g(e)===`weakmap`,Le=e=>g(e)===`file`,Re=e=>g(e)===`blob`,ze=e=>g(e)===`url`,Be=e=>g(e)===`error`,T=e=>!_(e)&&!v(e),E=e=>{if(T(e))try{return JSON.parse(e),!0}catch(e){return m(`Failed to parse invalid string`,e),!1}return!1},D=e=>{if(T(e))try{return Array.isArray(JSON.parse(e))}catch(e){return m(`Failed to parse invalid string`,e),!1}return!1},Ve=(e,t)=>e in t,He=e=>!T(e)||e===``||b(e)&&e.length===0||y(e)&&Object.keys(e).length===0||w(e)&&e.size===0||C(e)&&e.size===0,O=/^1[3-9]\d{9}$/,k=/^0\d{2,3}-?\d{7,8}$/,A=/^\(0\d{2,3}\)\d{7,8}$/,j=/^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/,M=/^[1-9]\d{7}(?:0[1-9]|10|11|12)(?:[0-2][1-9]|10|20|30|31)\d{2}[\dX]$/i,N=/^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|1[0-2])(?:[0-2][1-9]|10|20|30|31)\d{3}[\dX]$/i,P=/^[a-z\d](?:\w|-)+@[a-z\d]+\.[a-z]{2,5}$/i,Ue=e=>T(e)?j.test(e):!1,F=e=>T(e)?O.test(e.toString()):!1,We=e=>{if(!T(e))return!1;let t=e.toString().replaceAll(` `,``);return k.test(t)||A.test(t)},Ge=e=>T(e)?P.test(e):!1,I=(e,t=!0)=>T(e)?N.test(e)||(t?M.test(e):!1):!1,Ke=e=>T(e)?typeof e==`number`||/^\d+(?:\.\d+)?$/.test(e):!1,qe=e=>/\.(?:jpg|jpeg|png|gif)$/.test((e||``).toLowerCase()),Je=e=>/[^\x20-\x7E]/.test(e),Ye=(e,t)=>{if(t===`*`)return!0;let n=e.type,r=e.name;function i(e){return e.startsWith(`.`)?r.endsWith(e):e.endsWith(`/*`)?n.startsWith(e.replace(`/*`,``)):e.includes(`/`)?n===e:!1}let a=t.split(`,`).map(e=>e.trim());return a.length>1?a.some(i):i(t)},L=(e,t=200)=>e.code===t,Xe=(e,t)=>L(e,t)&&T(e.data),Ze=(e,t)=>L(e,t)&&Array.isArray(e.data),Qe=(e,t)=>L(e,t)&&T(e.data)&&Array.isArray(e.data.list||e.data.records),R=e=>{if(!T(e))return``;let t=e.length;return t<=2?`*`.repeat(t):e[0]+`*`.repeat(t-2)+e[t-1]},$e=e=>{if(!T(e))return``;let t=e.length;if(t<=2)return`*`.repeat(t);let n=Math.round(t/3);return e.slice(0,n)+`*`.repeat(t-2*n)+e.slice(t-n)},z=(e,t)=>{if(!T(e))return``;let n=e.length;if(n<=1)return`*`.repeat(n);let r=t===void 0?n-1:Math.max(Math.min(n,t),0);return`*`.repeat(r)+e.substring(r)},B=(e,t)=>{if(!T(e))return``;let n=e.length;if(n<=1)return`*`.repeat(n);let r=t===void 0?n-1:Math.max(Math.min(n,t),0);return e.substring(0,n-r)+`*`.repeat(r)},et=e=>{if(e){let t=e.replaceAll(` `,``);return F(t)?t.replace(/^(\d{3})\d{4}(\d{4})$/,`$1****$2`):k.test(t)?t.replace(/^(0\d{2,3})-?\d{3,4}(\d{4})$/,`$1****$2`):A.test(t)?t.replace(/^\((0\d{2,3})\)\d{3,4}(\d{4})$/,`$1****$2`):e}return``},tt=(e,t=!0)=>e?I(e,!1)?t?R(e):e.replace(/^(.)\d{3}(.{8})\d{5}(.)$/,`$1***$2*****$3`):e:``,nt=e=>z(e,1),rt=e=>B(e),it=e=>{if(e){if(!e.includes(`@`))return e;let t=e.split(`@`),n=t[0],r=t[1];if(!n||!r)return e;let i=n.length,a;return a=i<=3?`${n}***`:B(n,3),`${a}@${r}`}return``},at=e=>{if(e){let t=e.length;return t<=10?e:e.substring(0,6)+`*`.repeat(t-10)+e.substring(t-4,t)}return``},ot=e;let V;function st(e){V=e}function H(){return V}function ct(e,t){return E(e)?JSON.parse(e,t):null}function U(e,t=G){return E(e)?JSON.parse(e,t):null}function lt(e,t=W){return JSON.stringify(e,t)}function W(e,t){return w(t)?{dataType:`Map`,value:[...t]}:C(t)?{dataType:`Set`,value:[...t]}:S(t)?{dataType:`Date`,value:t.toISOString()}:t}function G(e,t){if(typeof t==`object`&&t){if(t.dataType===`Map`)return new Map(t.value);if(t.dataType===`Set`)return new Set(t.value);if(t.dataType===`Date`)return new Date(t.value)}return t}const ut=(e,t,n=!1)=>Object.fromEntries(Object.entries(e).filter(([e])=>n?!t.includes(e):t.includes(e))),dt=e=>{let t=e.toString().split(`.`),n=t[0]?.replace(/(\d)(?=(?:\d{3})+$)/g,`$1,`);return t.length>1?`${n}.${t[1]}`:n},ft=(e,t=2)=>{if(!T(e))return``;let n=Number(e);return Number.isNaN(n)?``:new Intl.NumberFormat(`zh-CN`,{style:`currency`,currency:`CNY`,maximumFractionDigits:t}).format(n)};t.extend(a).locale(`zh-cn`,n),t.extend(i),t.extend(s),t.extend(r),t.extend(o);const K=(e,n=`YYYY-MM-DD HH:mm:ss`)=>{let r=t(e),i=n;return!T(e)||!r.isValid()?``:(n===`date`&&(i=`YYYY-MM-DD`),n===`datetime`&&(i=`YYYY-MM-DD HH:mm:ss`),r.format(i))},pt=(e,n)=>{let r=t(e),i=t(n);if(!T(e)||!r.isValid()||!T(n)||!i.isValid())return``;let a=t.duration(i.diff(r)),o=a.years(),s=a.months(),c=a.days(),l=[o===0?``:`Y年`,s===0?``:`M个月`,c===0?``:`${c<10&&(o!==0||s!==0)?`零`:``}D天`].join(``);return a.format(l)},q=e=>{if(!T(e))return;if(/^https?:\/\//.test(e)||e.startsWith(`blob:`)||e.startsWith(`data:`))return e;let t=H();if(!T(t))throw Error(`请先使用 setBaseAttachUrl 设置文件基本路径`);return`${t}/${e}`.replace(/([^:]\/)\/+/g,`$1`)},J=e=>{let{uri:t,url:n,...r}=e,i=t||n;return{...r,url:q(i),content:q(i),uri:i||``,status:`done`,percent:100}},mt=e=>{let t=[],n=Object.prototype.toString.call(e);if(!e)t=[];else if(Array.isArray(e))t=e.filter(Boolean);else if(typeof e==`string`)if(D(e))t=(U(e)||[]).filter(Boolean);else{let n=U(e);t=Object.prototype.toString.call(n)===`[object Object]`?[n].filter(Boolean):[{id:e,name:`name`,uri:e,group:`default`}]}else n===`[object Object]`&&(t=[e]);return t.map(J)},ht=e=>e.every(e=>typeof e==`number`),gt=e=>e.every(e=>typeof e==`string`),Y=e=>{if(ht(e))return[...e].sort((e,t)=>e-t);if(gt(e))return[...e].sort((e,t)=>e.localeCompare(t,`zh-CN`)).sort((e,t)=>e.length-t.length);let t=[...e].sort(),n=t.filter(e=>T(e)),r=t.filter(e=>!T(e));return Y(n).concat(r)},_t=(e,t)=>[...e].sort((e,n)=>Y([e[t],n[t]])[0]===e[t]?-1:1),X=typeof window<`u`,vt=(e=100)=>new Promise(t=>{setTimeout(()=>{t(!0)},e)}),yt=()=>{if(CSS.supports(`(font:-apple-system-body) and (-webkit-touch-callout:none) and (-webkit-tap-highlight-color:hotpink)`)){let e=document.querySelector(`meta[name="viewport"]`);e!==null&&(e.content=`${e.content}, user-scalable=no`)}},Z=X?window.navigator.userAgent:``,Q=()=>{let e=Z.toLowerCase();return{zlb:e.includes(`@zlb`),zyd:e.includes(`saas`),zzd:e.includes(`zhejiang`)||e.includes(`tauruszjd`)||e.includes(`dingtalk-win`),dd:e.includes(`taurusapp`),wx:e.includes(`micromessenger`),zfb:e.includes(`alipay`),mini:e.includes(`miniprogram`)}},$=e=>Math.abs(new Date(e).getTime()^1111),bt=()=>$(`${K(new Date,`YYYY-MM-DD HH`)}:00:00`),xt=()=>$(K(new Date,`date`)),St=()=>$(K(t().endOf(`month`),`date`)),Ct=(e,t=200,n=`success`)=>({data:e,code:t,message:n}),wt=(e,t,n=200,r=`success`,i={})=>({data:{records:e,list:e,total:t,...i},code:n,message:r});export{mt as attachFmt,le as camel2Kebab,ue as camel2Pascal,ce as camel2Snake,de as camel2Title,qe as checkImg,M as cnIdCard15Re,N as cnIdCard18Re,O as cnPhoneRE,k as cnTelRE,A as cnTelRE2,j as cnUSCIRE,ft as currencyFmt,pt as dateDuration,K as dateFmt,t as dayjs,ot as detect,P as emailRE,ut as filterObj,yt as fixiOSInputAutoZoomIn,H as getBaseAttachUrl,xt as getCodeOfDate,bt as getCodeOfHour,St as getCodeOfMonth,Q as getHostEnv,Ct as getMockData,wt as getMockDataList,g as getVariableType,at as hideBankCard,tt as hideCardNo,it as hideEmail,rt as hideFirstName,z as hideHead,R as hideMiddle,et as hidePhone,nt as hideSurname,B as hideTail,$e as hideThird,X as inBrowser,D as isArrStr,b as isArray,ke as isBigInt,Re as isBlob,je as isBoolean,S as isDate,T as isDef,Ge as isEmail,He as isEmpty,Be as isError,Le as isFile,x as isFunction,I as isIdCard,E as isJSONStr,w as isMap,_ as isNull,Oe as isNumber,Ke as isNumeric,y as isObject,F as isPhone,Pe as isPromise,Ne as isRegExp,C as isSet,Ae as isString,Me as isSymbol,We as isTel,ze as isURL,Ue as isUSCI,v as isUndefined,Ze as isValidArrRes,Ye as isValidFileType,Ve as isValidKey,Qe as isValidPageRes,Xe as isValidRes,L as isValidResCode,Ie as isWeakMap,Fe as isWeakSet,we as jClear,ge as jDebug,_e as jError,ye as jGroup,be as jGroupC,xe as jGroupE,ve as jInfo,p as jLog,Te as jLogDedupe,De as jLogOnce,Se as jTime,Ce as jTimeEnd,m as jWarn,ie as kebab2Camel,re as kebab2Pascal,ne as kebab2Snake,ae as kebab2Title,Y as naturalSort,_t as naturalSortBy,Je as nonASCII,U as parseJSON,ct as parseToJSON,d as pascal2Camel,u as pascal2Kebab,oe as pascal2Snake,se as pascal2Title,J as recoverFile,W as replacer,q as resUrl,G as reviver,st as setBaseAttachUrl,ee as snake2Camel,c as snake2Kebab,l as snake2Pascal,te as snake2Title,lt as stringifyJSON,he as title2Camel,pe as title2Kebab,me as title2Pascal,fe as title2Snake,dt as toThousands,Z as userAgent,vt as waitTime};
2
- //# sourceMappingURL=index.js.map
1
+ import dayjs from "dayjs";
2
+ import zhCN from "dayjs/locale/zh-cn.js";
3
+ import customParseFormat from "dayjs/plugin/customParseFormat.js";
4
+ import duration from "dayjs/plugin/duration.js";
5
+ import localeData from "dayjs/plugin/localeData.js";
6
+ import objectSupport from "dayjs/plugin/objectSupport.js";
7
+ import relativeTime from "dayjs/plugin/relativeTime.js";
8
+
9
+ //#region src/case.ts
10
+ /**
11
+ * snake2Kebab
12
+ * @param {string} str 字符串
13
+ * @returns {string} 转换后的字符串
14
+ * @example snake2Kebab('hello_world') // hello_world => hello-world
15
+ */
16
+ const snake2Kebab = (str) => str.replace(/_([a-z])/g, (_, letter) => `-${letter.toLowerCase()}`);
17
+ /**
18
+ * snake2Pascal
19
+ * @param {string} str 字符串
20
+ * @returns {string} 转换后的字符串
21
+ * @example snake2Pascal('hello_world') // hello_world => HelloWorld
22
+ */
23
+ const snake2Pascal = (str) => str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/^[a-z]/, (letter) => letter.toUpperCase());
24
+ /**
25
+ * snake2Camel
26
+ * @param {string} str 字符串
27
+ * @returns {string} 转换后的字符串
28
+ * @example snake2Camel('hello_world') // hello_world => helloWorld
29
+ */
30
+ const snake2Camel = (str) => str.replace(/(_([a-z]))/g, (match) => match[1].toUpperCase());
31
+ /**
32
+ * snake2Title
33
+ * @param {string} str 字符串
34
+ * @returns {string} 转换后的字符串
35
+ * @example snake2Title('hello_world') // hello_world => Hello World
36
+ */
37
+ const snake2Title = (str) => str.replace(/_([a-z])/g, (_, letter) => ` ${letter.toUpperCase()}`).replace(/^[a-z]/, (letter) => letter.toUpperCase());
38
+ /**
39
+ * kebab2Snake
40
+ * @param {string} str 字符串
41
+ * @returns {string} 转换后的字符串
42
+ * @example kebab2Snake('hello-world') // hello-world => hello_world
43
+ */
44
+ const kebab2Snake = (str) => str.replace(/-([a-z])/g, (_, letter) => `_${letter.toLowerCase()}`);
45
+ /**
46
+ * kebab2Pascal
47
+ * @param {string} str 字符串
48
+ * @returns {string} 转换后的字符串
49
+ * @example kebab2Pascal('hello-world') // hello-world => HelloWorld
50
+ */
51
+ const kebab2Pascal = (str) => str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/^[a-z]/, (letter) => letter.toUpperCase());
52
+ /**
53
+ * kebab2Camel
54
+ * @param {string} str 字符串
55
+ * @returns {string} 转换后的字符串
56
+ * @example kebab2Camel('hello-world') // hello-world => helloWorld
57
+ */
58
+ const kebab2Camel = (str) => {
59
+ const [first, ...rest] = str.split("-");
60
+ return [first, ...rest.map((s) => s.replace(/^[a-z]/, s[0].toUpperCase()))].join("");
61
+ };
62
+ /**
63
+ * kebab2Title
64
+ * @param {string} str 字符串
65
+ * @returns {string} 转换后的字符串
66
+ * @example kebab2Title('hello-world') // hello-world => Hello World
67
+ */
68
+ const kebab2Title = (str) => str.replace(/-([a-z])/g, (_, letter) => ` ${letter.toUpperCase()}`).replace(/^[a-z]/, (letter) => letter.toUpperCase());
69
+ /**
70
+ * pascal2Snake
71
+ * @param {string} str 字符串
72
+ * @returns {string} 转换后的字符串
73
+ * @example pascal2Snake('HelloWorld') // HelloWorld => hello_world
74
+ */
75
+ const pascal2Snake = (str) => str.replace(/([A-Z])/g, (_, letter) => `_${letter.toLowerCase()}`).replace(/^_/, "");
76
+ /**
77
+ * pascal2Kebab
78
+ * @param {string} str 字符串
79
+ * @returns {string} 转换后的字符串
80
+ * @example pascal2Kebab('HelloWorld') // HelloWorld => hello-world
81
+ */
82
+ const pascal2Kebab = (str) => str.replace(/([A-Z])/g, (_, letter) => `-${letter.toLowerCase()}`).replace(/^-/, "");
83
+ /**
84
+ * pascal2Camel
85
+ * @param {string} str 字符串
86
+ * @returns {string} 转换后的字符串
87
+ * @example pascal2Camel('HelloWorld') // HelloWorld => helloWorld
88
+ */
89
+ const pascal2Camel = (str) => str.replace(/^[A-Z]/, (letter) => letter.toLowerCase());
90
+ /**
91
+ * pascal2Title
92
+ * @param {string} str 字符串
93
+ * @returns {string} 转换后的字符串
94
+ * @example pascal2Title('HelloWorld') // HelloWorld => Hello World
95
+ */
96
+ const pascal2Title = (str) => str.replace(/([A-Z])/g, (_, letter) => ` ${letter}`).replace(/^ /, "");
97
+ /**
98
+ * camel2Snake
99
+ * @param {string} str 字符串
100
+ * @returns {string} 转换后的字符串
101
+ * @example camel2Snake('helloWorld') // helloWorld => hello_world
102
+ */
103
+ const camel2Snake = (str) => str.replace(/([A-Z])/g, (_, letter) => `_${letter.toLowerCase()}`);
104
+ /**
105
+ * camel2Kebab
106
+ * @param {string} str 字符串
107
+ * @returns {string} 转换后的字符串
108
+ * @example camel2Kebab('helloWorld') // helloWorld => hello-world
109
+ */
110
+ const camel2Kebab = (str) => str.replace(/([A-Z])/g, (_, letter) => `-${letter.toLowerCase()}`);
111
+ /**
112
+ * camel2Pascal
113
+ * @param {string} str 字符串
114
+ * @returns {string} 转换后的字符串
115
+ * @example camel2Pascal('helloWorld') // helloWorld => HelloWorld
116
+ */
117
+ const camel2Pascal = (str) => str.replace(/(^[a-z])|(\s+[a-z])/g, (match) => match.toUpperCase());
118
+ /**
119
+ * camel2Title
120
+ * @param {string} str 字符串
121
+ * @returns {string} 转换后的字符串
122
+ * @example camel2Title('helloWorld') // helloWorld => Hello World
123
+ */
124
+ const camel2Title = (str) => str.replace(/([A-Z])/g, (_, letter) => ` ${letter}`).replace(/^[a-z]/, (match) => match.toUpperCase());
125
+ /**
126
+ * title2Snake
127
+ * @param {string} str 字符串
128
+ * @returns {string} 转换后的字符串
129
+ * @example title2Snake('Hello World') // Hello World => hello_world
130
+ */
131
+ const title2Snake = (str) => str.replace(/([A-Z])/g, (match) => match.toLowerCase()).replace(/ /g, "_");
132
+ /**
133
+ * title2Kebab
134
+ * @param {string} str 字符串
135
+ * @returns {string} 转换后的字符串
136
+ * @example title2Kebab('Hello World') // Hello World => hello-world
137
+ */
138
+ const title2Kebab = (str) => str.replace(/([A-Z])/g, (match) => match.toLowerCase()).replace(/ /g, "-");
139
+ /**
140
+ * title2Pascal
141
+ * @param {string} str 字符串
142
+ * @returns {string} 转换后的字符串
143
+ * @example title2Pascal('Hello World') // Hello World => HelloWorld
144
+ */
145
+ const title2Pascal = (str) => str.replace(/ /g, "");
146
+ /**
147
+ * title2Camel
148
+ * @param {string} str 字符串
149
+ * @returns {string} 转换后的字符串
150
+ * @example title2Camel('Hello World') // Hello World => helloWorld
151
+ */
152
+ const title2Camel = (str) => str.replace(/ /g, "").replace(/^[A-Z]/, (match) => match.toLowerCase());
153
+
154
+ //#endregion
155
+ //#region src/console/log-common.ts
156
+ const sharedStyle = "color: white; padding: 1px 2px;";
157
+ /**
158
+ * jade console.log
159
+ * only for development
160
+ * @param {...any} args
161
+ */
162
+ const jLog = (...args) => __DEV__ ? console.log.bind(console, `%c[${args.length === 1 ? "LOG" : "%s"}]`, `${sharedStyle} background: seagreen;`)(...args) : () => {};
163
+ /**
164
+ * jade console.debug
165
+ * @param {...any} args
166
+ */
167
+ const jDebug = (...args) => console.log.bind(console, `%c[${args.length === 1 ? "DEBUG" : "%s"}]`, `${sharedStyle} background: linear-gradient(LightSalmon, Tomato); border-radius: 2px; font-weight: bold; border-top: 2px solid Crimson; border-bottom: 2px solid Crimson;`)(...args);
168
+ /**
169
+ * jade console.warn
170
+ */
171
+ const jWarn = (...args) => console.warn.bind(console, `%c[${args.length === 1 ? "WARN" : "%s"}]`, `${sharedStyle} background: tomato;`)(...args);
172
+ /**
173
+ * jade console.error
174
+ */
175
+ const jError = (...args) => console.error.bind(console, `%c[${args.length === 1 ? "ERROR" : "%s"}]`, `${sharedStyle} background: crimson;`)(...args);
176
+ /**
177
+ * jade console.info
178
+ * @param {...any} args
179
+ */
180
+ const jInfo = (...args) => console.info.bind(console, `%c[${args.length === 1 ? "INFO" : "%s"}]`, `${sharedStyle} background: dodgerblue;`)(...args);
181
+ /**
182
+ * jade console.group
183
+ */
184
+ const jGroup = console.group.bind(console, "%c[%s]", `${sharedStyle} background: slateblue;`);
185
+ /**
186
+ * jade console.groupCollapsed
187
+ */
188
+ const jGroupC = console.groupCollapsed.bind(console, "%c[%s]", `${sharedStyle} background: slateblue;`);
189
+ /**
190
+ * jade console.groupEnd
191
+ */
192
+ const jGroupE = console.groupEnd.bind(console);
193
+ /**
194
+ * jade console.time
195
+ * @param str
196
+ */
197
+ const jTime = (str) => console.time(`[${str}]`);
198
+ /**
199
+ * jade console.timeEnd
200
+ * @param str
201
+ */
202
+ const jTimeEnd = (str) => console.timeEnd(`[${str}]`);
203
+ /**
204
+ * jade console.clear
205
+ */
206
+ const jClear = console.clear.bind(console);
207
+
208
+ //#endregion
209
+ //#region src/console/log-dedupe.ts
210
+ let prevValue;
211
+ /**
212
+ * 不连续打印相同的值
213
+ * @param args
214
+ */
215
+ const jLogDedupe = (...args) => {
216
+ if (args.length === 0) return;
217
+ if (args.length > 0 && prevValue && JSON.stringify(args) === JSON.stringify(prevValue)) return;
218
+ jLog(...args);
219
+ prevValue = args;
220
+ };
221
+
222
+ //#endregion
223
+ //#region src/console/log-once.ts
224
+ let logged = false;
225
+ /**
226
+ * 只打印一次
227
+ * @param args
228
+ */
229
+ const jLogOnce = (...args) => {
230
+ if (logged) return;
231
+ jLog(...args);
232
+ logged = true;
233
+ };
234
+
235
+ //#endregion
236
+ //#region src/validate/core.ts
237
+ /**
238
+ * 检测变量类型
239
+ * @param {any} val 检测的目标
240
+ */
241
+ const getVariableType = (val) => Object.prototype.toString.call(val).toLocaleLowerCase().slice(8, -1);
242
+ /**
243
+ * 是否是数字
244
+ * @param {any} val 检测的目标
245
+ */
246
+ const isNumber = (val) => typeof val === "number";
247
+ /**
248
+ * 是否是任意精度整数
249
+ * @param {any} val 检测的目标
250
+ */
251
+ const isBigInt = (val) => typeof val === "bigint";
252
+ /**
253
+ * 是否是字符串
254
+ * @param {any} val 检测的目标
255
+ */
256
+ const isString = (val) => typeof val === "string";
257
+ /**
258
+ * 是否是布尔值
259
+ * @param {any} val 检测的目标
260
+ */
261
+ const isBoolean = (val) => typeof val === "boolean";
262
+ /**
263
+ * 是否是null
264
+ * @param {any} val 检测的目标
265
+ */
266
+ const isNull = (val) => val === null;
267
+ /**
268
+ * 是否是undefined
269
+ * @param {any} val 检测的目标
270
+ */
271
+ const isUndefined = (val) => typeof val === "undefined";
272
+ /**
273
+ * 是否是symbol
274
+ * @param {any} val 检测的目标
275
+ */
276
+ const isSymbol = (val) => typeof val === "symbol";
277
+ /**
278
+ * 是否是对象
279
+ * @param {any} val 检测的目标
280
+ */
281
+ const isObject = (val) => getVariableType(val) === "object";
282
+ /**
283
+ * 是否是数组
284
+ * @param {any} val 检测的目标
285
+ */
286
+ const isArray = (val) => Array.isArray(val);
287
+ /**
288
+ * 是否是函数,但也有可能是Class
289
+ * @param {any} val 检测的目标
290
+ */
291
+ const isFunction = (val) => getVariableType(val) === "function";
292
+ /**
293
+ * 是否是日期
294
+ * @param {any} val 检测的目标
295
+ */
296
+ const isDate = (val) => val instanceof Date;
297
+ /**
298
+ * 是否是正则
299
+ * @param {any} val 检测的目标
300
+ */
301
+ const isRegExp = (val) => getVariableType(val) === "regexp";
302
+ /**
303
+ * 是否是期望(Promise)
304
+ * @param {any} val 检测的目标
305
+ */
306
+ const isPromise = (val) => getVariableType(val) === "promise";
307
+ /**
308
+ * 是否是集合(Set)
309
+ * @param {any} val 检测的目标
310
+ */
311
+ const isSet = (val) => getVariableType(val) === "set";
312
+ /**
313
+ * 是否是映射(Map)
314
+ * @param {any} val 检测的目标
315
+ */
316
+ const isMap = (val) => getVariableType(val) === "map";
317
+ /**
318
+ * 是否是弱集合(WeakSet)
319
+ * @param {any} val 检测的目标
320
+ */
321
+ const isWeakSet = (val) => getVariableType(val) === "weakset";
322
+ /**
323
+ * 是否是弱映射(WeakMap)
324
+ * @param {any} val 检测的目标
325
+ */
326
+ const isWeakMap = (val) => getVariableType(val) === "weakmap";
327
+ /**
328
+ * 是否是File
329
+ * @param {any} val 检测的目标
330
+ */
331
+ const isFile = (val) => getVariableType(val) === "file";
332
+ /**
333
+ * 是否是Blob
334
+ * @param {any} val 检测的目标
335
+ */
336
+ const isBlob = (val) => getVariableType(val) === "blob";
337
+ /**
338
+ * 是否是URL
339
+ * @param {any} val 检测的目标
340
+ */
341
+ const isURL = (val) => getVariableType(val) === "url";
342
+ /**
343
+ * 是否是错误(Error)
344
+ * @param {any} val 检测的目标
345
+ */
346
+ const isError = (val) => getVariableType(val) === "error";
347
+ /**
348
+ * 是否既不是 null 也不是 undefined
349
+ * @param {any} val 检测的目标
350
+ */
351
+ const isDef = (val) => !isNull(val) && !isUndefined(val);
352
+ /**
353
+ * 判断是否合法JSON字符串
354
+ * @param str
355
+ */
356
+ const isJSONStr = (str) => {
357
+ if (isDef(str)) try {
358
+ JSON.parse(str);
359
+ return true;
360
+ } catch (e) {
361
+ jWarn("Failed to parse invalid string", e);
362
+ return false;
363
+ }
364
+ return false;
365
+ };
366
+ /**
367
+ * 判断是否合法JSON数组字符串
368
+ * @param str
369
+ */
370
+ const isArrStr = (str) => {
371
+ if (isDef(str)) try {
372
+ return Array.isArray(JSON.parse(str));
373
+ } catch (e) {
374
+ jWarn("Failed to parse invalid string", e);
375
+ return false;
376
+ }
377
+ return false;
378
+ };
379
+ /**
380
+ * 判断是否有效的key
381
+ * @param {string | number | symbol} key 键名
382
+ * @param {object} object 对象
383
+ * @example
384
+ *
385
+ * ```ts
386
+ * const obj = { a: 1, b: 2 }
387
+ * isValidKey('a', obj) // true
388
+ * ```
389
+ * @returns {boolean} boolean
390
+ */
391
+ const isValidKey = (key, object) => key in object;
392
+ /**
393
+ * 是否是空值/空数组/空对象 null undefined '' [] {} Set Map
394
+ * @param val
395
+ */
396
+ const isEmpty = (val) => {
397
+ return !isDef(val) || val === "" || isArray(val) && val.length === 0 || isObject(val) && Object.keys(val).length === 0 || isMap(val) && val.size === 0 || isSet(val) && val.size === 0;
398
+ };
399
+
400
+ //#endregion
401
+ //#region src/validate/form.ts
402
+ const cnPhoneRE = /^1[3-9]\d{9}$/;
403
+ const cnTelRE = /^0\d{2,3}-?\d{7,8}$/;
404
+ const cnTelRE2 = /^\(0\d{2,3}\)\d{7,8}$/;
405
+ const cnUSCIRE = /^[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/;
406
+ const cnIdCard15Re = /^[1-9]\d{7}(?:0[1-9]|10|11|12)(?:[0-2][1-9]|10|20|30|31)\d{2}[\dX]$/i;
407
+ const cnIdCard18Re = /^[1-9]\d{5}(?:18|19|20)\d{2}(?:0[1-9]|1[0-2])(?:[0-2][1-9]|10|20|30|31)\d{3}[\dX]$/i;
408
+ const emailRE = /^[a-z\d](?:\w|-)+@[a-z\d]+\.[a-z]{2,5}$/i;
409
+ /**
410
+ * 是否是[统一社会信用代码](https://zh.wikipedia.org/zh-cn/%E7%BB%9F%E4%B8%80%E7%A4%BE%E4%BC%9A%E4%BF%A1%E7%94%A8%E4%BB%A3%E7%A0%81)
411
+ * @example
412
+ * ```ts
413
+ * isUSCI('91350100M000100Y43') // true
414
+ * ```
415
+ * @param {UnDef<string>} val - 待校验的值
416
+ * @returns {boolean} 是否是统一社会信用代码
417
+ */
418
+ const isUSCI = (val) => {
419
+ if (!isDef(val)) return false;
420
+ return cnUSCIRE.test(val);
421
+ };
422
+ /**
423
+ * 是否是中国手机号
424
+ * @param val
425
+ */
426
+ const isPhone = (val) => {
427
+ if (!isDef(val)) return false;
428
+ return cnPhoneRE.test(val.toString());
429
+ };
430
+ /**
431
+ * 是否是中国座机号
432
+ * @param val
433
+ */
434
+ const isTel = (val) => {
435
+ if (!isDef(val)) return false;
436
+ const valStr = val.toString().replaceAll(" ", "");
437
+ return cnTelRE.test(valStr) || cnTelRE2.test(valStr);
438
+ };
439
+ /**
440
+ * 是否是邮箱
441
+ * @param val
442
+ */
443
+ const isEmail = (val) => {
444
+ if (!isDef(val)) return false;
445
+ return emailRE.test(val);
446
+ };
447
+ /**
448
+ * 是否是身份证
449
+ * @param {string|null|undefined} val 身份证号
450
+ * @param {boolean} compatible 兼容15位
451
+ */
452
+ const isIdCard = (val, compatible = true) => {
453
+ if (!isDef(val)) return false;
454
+ return cnIdCard18Re.test(val) || (compatible ? cnIdCard15Re.test(val) : false);
455
+ };
456
+ /**
457
+ * 是否是数字或字符
458
+ * @param val
459
+ */
460
+ const isNumeric = (val) => {
461
+ if (isDef(val)) return typeof val === "number" || /^\d+(?:\.\d+)?$/.test(val);
462
+ return false;
463
+ };
464
+ /**
465
+ * 是否是需要的图片格式
466
+ * @param ext
467
+ */
468
+ const checkImg = (ext) => {
469
+ return /\.(?:jpg|jpeg|png|gif)$/.test((ext || "").toLowerCase());
470
+ };
471
+ /**
472
+ * 包含非ASCII字符
473
+ * @param text
474
+ */
475
+ const nonASCII = (text) => /[^\x20-\x7E]/.test(text);
476
+ /**
477
+ * 校验文件类型
478
+ * 1. XXX/YYY 2. .xxx 3. XXX/* 4.*
479
+ * @param {File} file 需要校验的文件
480
+ * @param {string} type 文件类型, 与input.accept一致
481
+ */
482
+ const isValidFileType = (file, type) => {
483
+ if (type === "*") return true;
484
+ const fileType = file.type;
485
+ const fileName = file.name;
486
+ /**
487
+ * 校验
488
+ * @param item
489
+ */
490
+ function validate(item) {
491
+ if (item.startsWith(".")) return fileName.endsWith(item);
492
+ if (item.endsWith("/*")) return fileType.startsWith(item.replace("/*", ""));
493
+ if (item.includes("/")) return fileType === item;
494
+ return false;
495
+ }
496
+ const typeArrStr = type.split(",").map((item) => item.trim());
497
+ if (typeArrStr.length > 1) return typeArrStr.some(validate);
498
+ return validate(type);
499
+ };
500
+
501
+ //#endregion
502
+ //#region src/validate/request.ts
503
+ /**
504
+ * 校验接口返回code
505
+ * @param res
506
+ * @param code
507
+ */
508
+ const isValidResCode = (res, code = 200) => res.code === code;
509
+ /**
510
+ * 校验接口返回内容
511
+ * @param res
512
+ * @param code
513
+ */
514
+ const isValidRes = (res, code) => isValidResCode(res, code) && isDef(res.data);
515
+ /**
516
+ * 校验接口数组返回内容
517
+ * @param res
518
+ * @param code
519
+ */
520
+ const isValidArrRes = (res, code) => isValidResCode(res, code) && Array.isArray(res.data);
521
+ /**
522
+ * 校验接口分页返回内容
523
+ * @param res
524
+ * @param code
525
+ */
526
+ const isValidPageRes = (res, code) => isValidResCode(res, code) && isDef(res.data) && Array.isArray(res.data.list || res.data.records);
527
+
528
+ //#endregion
529
+ //#region src/desensitize.ts
530
+ /**
531
+ * 隐藏中间部分
532
+ * @param {string} str 需要隐藏的字符串
533
+ * @returns {string} 隐藏后的字符串
534
+ * @example
535
+ * ```ts
536
+ * hideMiddle('A') // '*'
537
+ * hideMiddle('AB') // '**'
538
+ * hideMiddle('ABC') // 'A*C'
539
+ * hideMiddle('ABCD') // 'A**D'
540
+ * hideMiddle('ABCDE') // 'A***E'
541
+ * ```
542
+ */
543
+ const hideMiddle = (str) => {
544
+ if (!isDef(str)) return "";
545
+ const len = str.length;
546
+ if (len <= 2) return "*".repeat(len);
547
+ return str[0] + "*".repeat(len - 2) + str[len - 1];
548
+ };
549
+ /**
550
+ * 隐藏首尾仅保留中间3分之1
551
+ * @param {string} str 需要隐藏的字符串
552
+ * @returns {string} 隐藏后的字符串
553
+ * @example
554
+ * ```ts
555
+ * hideThird('A') // '*'
556
+ * hideThird('AB') // '**'
557
+ * hideThird('ABC') // 'A*C'
558
+ * hideThird('ABCD') // 'A**D'
559
+ * hideThird('ABCDE') // 'AB*DE'
560
+ * ```
561
+ */
562
+ const hideThird = (str) => {
563
+ if (!isDef(str)) return "";
564
+ const len = str.length;
565
+ if (len <= 2) return "*".repeat(len);
566
+ const partLen = Math.round(len / 3);
567
+ return str.slice(0, partLen) + "*".repeat(len - 2 * partLen) + str.slice(len - partLen);
568
+ };
569
+ /**
570
+ * 隐藏首部
571
+ * @param {string} str 需要隐藏的字符串
572
+ * @param {number} count 隐藏的字符数
573
+ * @returns {string} 隐藏后的字符串
574
+ * @example
575
+ * ```ts
576
+ * hideHead('A') // '*'
577
+ * hideHead('AB') // '*B'
578
+ * hideHead('ABC') // '**C'
579
+ * hideHead('ABC', 1) // '*BC'
580
+ * ```
581
+ */
582
+ const hideHead = (str, count) => {
583
+ if (!isDef(str)) return "";
584
+ const len = str.length;
585
+ if (len <= 1) return "*".repeat(len);
586
+ const cnt = count !== void 0 ? Math.max(Math.min(len, count), 0) : len - 1;
587
+ return "*".repeat(cnt) + str.substring(cnt);
588
+ };
589
+ /**
590
+ * 隐藏尾部
591
+ * @param {string} str 需要隐藏的字符串
592
+ * @param {number} count 隐藏的字符数
593
+ * @returns {string} 隐藏后的字符串
594
+ * @example
595
+ * ```ts
596
+ * hideTail('A') // '*'
597
+ * hideTail('AB') // 'A*'
598
+ * hideTail('ABC') // 'A**'
599
+ * hideTail('ABC', 1) // 'AB*'
600
+ * ```
601
+ */
602
+ const hideTail = (str, count) => {
603
+ if (!isDef(str)) return "";
604
+ const len = str.length;
605
+ if (len <= 1) return "*".repeat(len);
606
+ const cnt = count !== void 0 ? Math.max(Math.min(len, count), 0) : len - 1;
607
+ return str.substring(0, len - cnt) + "*".repeat(cnt);
608
+ };
609
+ /**
610
+ * 隐藏手机号/座机号
611
+ * @param {string} phone 手机号/座机号
612
+ * @returns {string} 隐藏后的手机号/座机号
613
+ * @example
614
+ * ```ts
615
+ * hidePhone('13800138000') // '138****8000'
616
+ * hidePhone('010-12345678') // '010****5678'
617
+ * hidePhone('(010)12345678') // '(010)****5678'
618
+ * ```
619
+ */
620
+ const hidePhone = (phone) => {
621
+ if (phone) {
622
+ const phoneStr = phone.replaceAll(" ", "");
623
+ if (isPhone(phoneStr)) return phoneStr.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2");
624
+ if (cnTelRE.test(phoneStr)) return phoneStr.replace(/^(0\d{2,3})-?\d{3,4}(\d{4})$/, "$1****$2");
625
+ if (cnTelRE2.test(phoneStr)) return phoneStr.replace(/^\((0\d{2,3})\)\d{3,4}(\d{4})$/, "$1****$2");
626
+ return phone;
627
+ }
628
+ return "";
629
+ };
630
+ /**
631
+ * 隐藏身份证号
632
+ * @param {string} cardNo 身份证号
633
+ * @param {boolean} strong 是否强化隐藏
634
+ * @returns {string} 隐藏后的身份证号
635
+ * @example
636
+ * ```ts
637
+ * hideCardNo('33072319641008384x') // '3****************x'
638
+ * hideCardNo('33072319641008384x', false) // '3***23196410*****x'
639
+ * ```
640
+ */
641
+ const hideCardNo = (cardNo, strong = true) => {
642
+ if (cardNo) {
643
+ if (isIdCard(cardNo, false)) return strong ? hideMiddle(cardNo) : cardNo.replace(/^(.)\d{3}(.{8})\d{5}(.)$/, "$1***$2*****$3");
644
+ return cardNo;
645
+ }
646
+ return "";
647
+ };
648
+ /**
649
+ * 隐藏姓氏
650
+ * @param {string} name 姓名
651
+ * @returns {string} 隐藏后的姓名
652
+ * @example
653
+ * ```ts
654
+ * hideSurname('张三') // '*三'
655
+ * hideSurname('司马懿') // '*马懿'
656
+ * ```
657
+ */
658
+ const hideSurname = (name) => {
659
+ return hideHead(name, 1);
660
+ };
661
+ /**
662
+ * 隐藏名字
663
+ * @param {string} name 姓名
664
+ * @returns {string} 隐藏后的姓名
665
+ * @example
666
+ * ```ts
667
+ * hideFirstName('张三') // '张*'
668
+ * hideFirstName('司马懿') // '司马*'
669
+ * ```
670
+ */
671
+ const hideFirstName = (name) => {
672
+ return hideTail(name);
673
+ };
674
+ /**
675
+ * 隐藏邮箱
676
+ * @param {string} email 邮箱
677
+ * @returns {string} 隐藏后的邮箱
678
+ * @example
679
+ * ```ts
680
+ * hideEmail('example@hotmail.com') // 'exam***@hotmail.com'
681
+ * ```
682
+ */
683
+ const hideEmail = (email) => {
684
+ if (email) {
685
+ if (!email.includes("@")) return email;
686
+ const arr = email.split("@");
687
+ const name = arr[0];
688
+ const domain = arr[1];
689
+ if (!name || !domain) return email;
690
+ const len = name.length;
691
+ let newName;
692
+ if (len <= 3) newName = `${name}***`;
693
+ else newName = hideTail(name, 3);
694
+ return `${newName}@${domain}`;
695
+ }
696
+ return "";
697
+ };
698
+ /**
699
+ * 隐藏银行卡号
700
+ * @param {string} bankCard 银行卡号
701
+ * @returns {string} 隐藏后的银行卡号
702
+ * @example
703
+ * ```ts
704
+ * hideBankCard('6222021001123456789') // '622202********6789'
705
+ * ```
706
+ */
707
+ const hideBankCard = (bankCard) => {
708
+ if (bankCard) {
709
+ const len = bankCard.length;
710
+ if (len <= 10) return bankCard;
711
+ return bankCard.substring(0, 6) + "*".repeat(len - 10) + bankCard.substring(len - 4, len);
712
+ }
713
+ return "";
714
+ };
715
+
716
+ //#endregion
717
+ //#region src/format/baseAttachUrl.ts
718
+ /**
719
+ * 文件基本路径
720
+ */
721
+ let __BASE_ATTACH_URL__;
722
+ /**
723
+ * 设置文件基本路径
724
+ * @param baseUrl
725
+ */
726
+ function setBaseAttachUrl(baseUrl) {
727
+ __BASE_ATTACH_URL__ = baseUrl;
728
+ }
729
+ /**
730
+ * 获取文件基本路径
731
+ */
732
+ function getBaseAttachUrl() {
733
+ return __BASE_ATTACH_URL__;
734
+ }
735
+
736
+ //#endregion
737
+ //#region src/format/core.ts
738
+ /**
739
+ * JSON 字符串转对象
740
+ * @template T - 解析数据类型
741
+ * @param {string} str - JSON字符串
742
+ * @param {(this: any, key: string, value: any) => any} reviverFn - 解析函数
743
+ * @returns {Nullable<T>} 解析后的对象
744
+ * @deprecated 请使用 `parseJSON`
745
+ */
746
+ function parseToJSON(str, reviverFn) {
747
+ return isJSONStr(str) ? JSON.parse(str, reviverFn) : null;
748
+ }
749
+ /**
750
+ * JSON 字符串转对象
751
+ * @alias parseToJSON
752
+ * @template T - 解析数据类型
753
+ * @param {string} str - JSON字符串
754
+ * @param {(this: any, key: string, value: any) => any} reviverFn - 解析函数
755
+ * @returns {Nullable<T>} 解析后的对象
756
+ */
757
+ function parseJSON(str, reviverFn = reviver) {
758
+ return isJSONStr(str) ? JSON.parse(str, reviverFn) : null;
759
+ }
760
+ /**
761
+ * 对象转 JSON 字符串
762
+ * @param {any} value - 对象
763
+ * @param {(this: any, key: string, value: any) => any} replacerFn - 替换函数
764
+ * @returns {string} JSON 字符串
765
+ */
766
+ function stringifyJSON(value, replacerFn = replacer) {
767
+ return JSON.stringify(value, replacerFn);
768
+ }
769
+ /**
770
+ * JSON.stringify() second param
771
+ * @param _key
772
+ * @param value
773
+ */
774
+ function replacer(_key, value) {
775
+ if (isMap(value)) return {
776
+ dataType: "Map",
777
+ value: [...value]
778
+ };
779
+ if (isSet(value)) return {
780
+ dataType: "Set",
781
+ value: [...value]
782
+ };
783
+ if (isDate(value)) return {
784
+ dataType: "Date",
785
+ value: value.toISOString()
786
+ };
787
+ return value;
788
+ }
789
+ /**
790
+ * JSON.parse() second param
791
+ * @param _key
792
+ * @param value
793
+ */
794
+ function reviver(_key, value) {
795
+ if (typeof value === "object" && value !== null) {
796
+ if (value.dataType === "Map") return new Map(value.value);
797
+ if (value.dataType === "Set") return new Set(value.value);
798
+ if (value.dataType === "Date") return new Date(value.value);
799
+ }
800
+ return value;
801
+ }
802
+ /**
803
+ * 过滤obj中仅包括keys的部分
804
+ * @param {Record<string,any>} obj 对象
805
+ * @param {string[]} keys 属性
806
+ * @param {boolean} reverse 为true时过滤取反
807
+ */
808
+ const filterObj = (obj, keys, reverse = false) => Object.fromEntries(Object.entries(obj).filter(([key]) => reverse ? !keys.includes(key) : keys.includes(key)));
809
+
810
+ //#endregion
811
+ //#region src/format/currency.ts
812
+ /**
813
+ * 千位分隔符
814
+ * @param num
815
+ */
816
+ const toThousands = (num) => {
817
+ const arr = num.toString().split(".");
818
+ const integer = arr[0]?.replace(/(\d)(?=(?:\d{3})+$)/g, "$1,");
819
+ if (arr.length > 1) return `${integer}.${arr[1]}`;
820
+ return integer;
821
+ };
822
+ /**
823
+ * 货币格式化
824
+ * @param {number | string | bigint} currency - 金额
825
+ * @param {number} [maximumFractionDigits] - 小数位数
826
+ */
827
+ const currencyFmt = (currency, maximumFractionDigits = 2) => {
828
+ if (!isDef(currency)) return "";
829
+ const num = Number(currency);
830
+ if (Number.isNaN(num)) return "";
831
+ return new Intl.NumberFormat("zh-CN", {
832
+ style: "currency",
833
+ currency: "CNY",
834
+ maximumFractionDigits
835
+ }).format(num);
836
+ };
837
+
838
+ //#endregion
839
+ //#region src/format/dayjs.ts
840
+ dayjs.extend(localeData).locale("zh-cn", zhCN);
841
+ dayjs.extend(duration);
842
+ dayjs.extend(relativeTime);
843
+ dayjs.extend(customParseFormat);
844
+ dayjs.extend(objectSupport);
845
+ /**
846
+ * 格式化时间
847
+ * @param {import('dayjs').ConfigType} date 时间
848
+ * @param {string} format 格式
849
+ * @returns {string} 格式化后的时间
850
+ */
851
+ const dateFmt = (date, format = "YYYY-MM-DD HH:mm:ss") => {
852
+ const dd = dayjs(date);
853
+ let fmt = format;
854
+ if (!isDef(date) || !dd.isValid()) return "";
855
+ if (format === "date") fmt = "YYYY-MM-DD";
856
+ if (format === "datetime") fmt = "YYYY-MM-DD HH:mm:ss";
857
+ return dd.format(fmt);
858
+ };
859
+ /**
860
+ * 格式化时间间隔
861
+ * @param {import('dayjs').ConfigType} start 开始时间
862
+ * @param {import('dayjs').ConfigType} end 结束时间
863
+ */
864
+ const dateDuration = (start, end) => {
865
+ const startDay = dayjs(start);
866
+ const endDay = dayjs(end);
867
+ if (!isDef(start) || !startDay.isValid() || !isDef(end) || !endDay.isValid()) return "";
868
+ const dd = dayjs.duration(endDay.diff(startDay));
869
+ const year = dd.years();
870
+ const month = dd.months();
871
+ const day = dd.days();
872
+ const format = [
873
+ year === 0 ? "" : "Y年",
874
+ month === 0 ? "" : "M个月",
875
+ day === 0 ? "" : `${day < 10 && (year !== 0 || month !== 0) ? "零" : ""}D天`
876
+ ].join("");
877
+ return dd.format(format);
878
+ };
879
+
880
+ //#endregion
881
+ //#region src/format/resource.ts
882
+ /**
883
+ * 获取文件完整地址
884
+ * @param url
885
+ */
886
+ const resUrl = (url) => {
887
+ if (!isDef(url)) return void 0;
888
+ if (/^https?:\/\//.test(url) || url.startsWith("blob:") || url.startsWith("data:")) return url;
889
+ const baseUrl = getBaseAttachUrl();
890
+ if (!isDef(baseUrl)) throw new Error("请先使用 setBaseAttachUrl 设置文件基本路径");
891
+ return `${baseUrl}/${url}`.replace(/([^:]\/)\/+/g, "$1");
892
+ };
893
+ /**
894
+ * 统一文件字段内容
895
+ * @param resource
896
+ */
897
+ const recoverFile = (resource) => {
898
+ const { uri, url, ...item } = resource;
899
+ const validUrl = uri || url;
900
+ return {
901
+ ...item,
902
+ url: resUrl(validUrl),
903
+ content: resUrl(validUrl),
904
+ uri: validUrl || "",
905
+ status: "done",
906
+ percent: 100
907
+ };
908
+ };
909
+ /**
910
+ * 附件格式
911
+ * @param data
912
+ */
913
+ const attachFmt = (data) => {
914
+ let attachList = [];
915
+ const prototype = Object.prototype.toString.call(data);
916
+ if (!data) attachList = [];
917
+ else if (Array.isArray(data)) attachList = data.filter(Boolean);
918
+ else if (typeof data === "string") if (isArrStr(data)) attachList = (parseJSON(data) || []).filter(Boolean);
919
+ else {
920
+ const jsonData = parseJSON(data);
921
+ if (Object.prototype.toString.call(jsonData) === "[object Object]") attachList = [jsonData].filter(Boolean);
922
+ else attachList = [{
923
+ id: data,
924
+ name: "name",
925
+ uri: data,
926
+ group: "default"
927
+ }];
928
+ }
929
+ else if (prototype === "[object Object]") attachList = [data];
930
+ return attachList.map(recoverFile);
931
+ };
932
+
933
+ //#endregion
934
+ //#region src/format/sort.ts
935
+ /**
936
+ * 判断是否为数字数组
937
+ * @param {UnDef<string>[] | UnDef<number>[]} arr - 数字或字符串数组
938
+ * @returns {boolean} - 是否为数字数组
939
+ */
940
+ const isNumberArray = (arr) => arr.every((item) => typeof item === "number");
941
+ /**
942
+ * 判断是否为字符串数组
943
+ * @param {UnDef<string>[] | UnDef<number>[]} arr - 数字或字符串数组
944
+ * @returns {boolean} - 是否为字符串数组
945
+ */
946
+ const isStringArray = (arr) => arr.every((item) => typeof item === "string");
947
+ /**
948
+ * 自然排序
949
+ * @param {UnDef<string>[] | UnDef<number>[]} arr - 数字或字符串数组
950
+ * @returns {UnDef<string>[] | UnDef<number>[]} - 排序后的数组
951
+ */
952
+ const naturalSort = (arr) => {
953
+ if (isNumberArray(arr)) return [...arr].sort((a, b) => a - b);
954
+ if (isStringArray(arr)) return [...arr].sort((a, b) => a.localeCompare(b, "zh-CN")).sort((a, b) => a.length - b.length);
955
+ const newArr = [...arr].sort();
956
+ const validArr = newArr.filter((a) => isDef(a));
957
+ const invalidArr = newArr.filter((a) => !isDef(a));
958
+ return naturalSort(validArr).concat(invalidArr);
959
+ };
960
+ /**
961
+ * 根据 key 自然排序
962
+ * @param arr - 数组
963
+ * @param {string} key - 键名
964
+ * @returns {any[]} - 排序后的数组
965
+ */
966
+ const naturalSortBy = (arr, key) => {
967
+ return [...arr].sort((a, b) => naturalSort([a[key], b[key]])[0] === a[key] ? -1 : 1);
968
+ };
969
+
970
+ //#endregion
971
+ //#region src/dom.ts
972
+ /**
973
+ * 判断是否是浏览器环境
974
+ */
975
+ const inBrowser = typeof window !== "undefined";
976
+ /**
977
+ * 等待一段时间
978
+ * @param time
979
+ */
980
+ const waitTime = (time = 100) => {
981
+ return new Promise((resolve) => {
982
+ setTimeout(() => {
983
+ resolve(true);
984
+ }, time);
985
+ });
986
+ };
987
+ /**
988
+ * 防止 iOS 因输入框字体小于16px 而在 focus 时页面缩放变大需要手动回正的情况。
989
+ * iOS 10+ 允许 pinch-zoom, 即使 viewport 是不可伸缩的。
990
+ * 只对这些浏览器添加额外规则
991
+ */
992
+ const fixiOSInputAutoZoomIn = () => {
993
+ if (CSS.supports("(font:-apple-system-body) and (-webkit-touch-callout:none) and (-webkit-tap-highlight-color:hotpink)")) {
994
+ const viewport = document.querySelector("meta[name=\"viewport\"]");
995
+ if (viewport !== null) viewport.content = `${viewport.content}, user-scalable=no`;
996
+ }
997
+ };
998
+ /**
999
+ * 用户代理
1000
+ */
1001
+ const userAgent = inBrowser ? window.navigator.userAgent : "";
1002
+ /**
1003
+ * 获取宿主环境信息
1004
+ * @returns {HostEnv} 宿主环境信息
1005
+ * @example
1006
+ * const hostEnv = getHostEnv()
1007
+ * hostEnv.zlb // 浙里办
1008
+ * hostEnv.zyd // 专有钉
1009
+ * hostEnv.zzd // 浙政钉
1010
+ * hostEnv.dd // 钉钉/专有钉/浙政钉
1011
+ * hostEnv.wx // 微信
1012
+ * hostEnv.zfb // 支付宝
1013
+ * hostEnv.mini // 小程序
1014
+ */
1015
+ const getHostEnv = () => {
1016
+ const ua = userAgent.toLowerCase();
1017
+ return {
1018
+ zlb: ua.includes("@zlb"),
1019
+ zyd: ua.includes("saas"),
1020
+ zzd: ua.includes("zhejiang") || ua.includes("tauruszjd") || ua.includes("dingtalk-win"),
1021
+ dd: ua.includes("taurusapp"),
1022
+ wx: ua.includes("micromessenger"),
1023
+ zfb: ua.includes("alipay"),
1024
+ mini: ua.includes("miniprogram")
1025
+ };
1026
+ };
1027
+ /**
1028
+ * 异或值
1029
+ */
1030
+ const XOR_VAL = 1111;
1031
+ /**
1032
+ * 获取某个时间戳的异或值的绝对值,在某个时间段内获取的值是唯一的
1033
+ * @param time
1034
+ */
1035
+ const getCodeOfTime = (time) => Math.abs(new Date(time).getTime() ^ XOR_VAL);
1036
+ /**
1037
+ * 获取当小时的时间戳的异或值的绝对值, 当小时内获取的值是唯一的
1038
+ */
1039
+ const getCodeOfHour = () => getCodeOfTime(`${dateFmt(/* @__PURE__ */ new Date(), "YYYY-MM-DD HH")}:00:00`);
1040
+ /**
1041
+ * 获取当天的时间戳的异或值的绝对值, 当天内获取的值是唯一的
1042
+ */
1043
+ const getCodeOfDate = () => getCodeOfTime(dateFmt(/* @__PURE__ */ new Date(), "date"));
1044
+ /**
1045
+ * 获取当月的时间戳的异或值的绝对值, 当月内获取的值是唯一的
1046
+ */
1047
+ const getCodeOfMonth = () => getCodeOfTime(dateFmt(dayjs().endOf("month"), "date"));
1048
+
1049
+ //#endregion
1050
+ //#region src/mock.ts
1051
+ const getMockData = (data, code = 200, message = "success") => {
1052
+ return {
1053
+ data,
1054
+ code,
1055
+ message
1056
+ };
1057
+ };
1058
+ const getMockDataList = (data, total, code = 200, message = "success", options = {}) => {
1059
+ return {
1060
+ data: {
1061
+ records: data,
1062
+ list: data,
1063
+ total,
1064
+ ...options
1065
+ },
1066
+ code,
1067
+ message
1068
+ };
1069
+ };
1070
+
1071
+ //#endregion
1072
+ export { attachFmt, camel2Kebab, camel2Pascal, camel2Snake, camel2Title, checkImg, cnIdCard15Re, cnIdCard18Re, cnPhoneRE, cnTelRE, cnTelRE2, cnUSCIRE, currencyFmt, dateDuration, dateFmt, dayjs, emailRE, filterObj, fixiOSInputAutoZoomIn, getBaseAttachUrl, getCodeOfDate, getCodeOfHour, getCodeOfMonth, getHostEnv, getMockData, getMockDataList, getVariableType, hideBankCard, hideCardNo, hideEmail, hideFirstName, hideHead, hideMiddle, hidePhone, hideSurname, hideTail, hideThird, inBrowser, isArrStr, isArray, isBigInt, isBlob, isBoolean, isDate, isDef, isEmail, isEmpty, isError, isFile, isFunction, isIdCard, isJSONStr, isMap, isNull, isNumber, isNumeric, isObject, isPhone, isPromise, isRegExp, isSet, isString, isSymbol, isTel, isURL, isUSCI, isUndefined, isValidArrRes, isValidFileType, isValidKey, isValidPageRes, isValidRes, isValidResCode, isWeakMap, isWeakSet, jClear, jDebug, jError, jGroup, jGroupC, jGroupE, jInfo, jLog, jLogDedupe, jLogOnce, jTime, jTimeEnd, jWarn, kebab2Camel, kebab2Pascal, kebab2Snake, kebab2Title, naturalSort, naturalSortBy, nonASCII, parseJSON, parseToJSON, pascal2Camel, pascal2Kebab, pascal2Snake, pascal2Title, recoverFile, replacer, resUrl, reviver, setBaseAttachUrl, snake2Camel, snake2Kebab, snake2Pascal, snake2Title, stringifyJSON, title2Camel, title2Kebab, title2Pascal, title2Snake, toThousands, userAgent, waitTime };
package/package.json CHANGED
@@ -1,23 +1,29 @@
1
1
  {
2
2
  "name": "@jhqn/utils-core",
3
- "type": "module",
4
- "version": "0.3.4",
5
- "author": "jade-gjz <jiangang.zhang@jaderd.com>",
6
- "license": "MIT",
3
+ "version": "0.4.0",
4
+ "keywords": [
5
+ "jade",
6
+ "utils"
7
+ ],
7
8
  "homepage": "https://github.com/jaderd-jh/utils/tree/main/packages/core#readme",
9
+ "bugs": {
10
+ "url": "https://github.com/jaderd-jh/utils/issues"
11
+ },
12
+ "license": "MIT",
13
+ "author": "jade-gjz <jiangang.zhang@jaderd.com>",
8
14
  "repository": {
9
15
  "type": "git",
10
16
  "url": "https://github.com/jaderd-jh/utils",
11
17
  "directory": "packages/core"
12
18
  },
13
- "bugs": {
14
- "url": "https://github.com/jaderd-jh/utils/issues"
15
- },
16
- "keywords": [
17
- "jade",
18
- "utils"
19
+ "files": [
20
+ "dist"
19
21
  ],
22
+ "type": "module",
20
23
  "sideEffects": false,
24
+ "main": "dist/index.js",
25
+ "module": "dist/index.js",
26
+ "types": "dist/index.d.ts",
21
27
  "exports": {
22
28
  ".": {
23
29
  "import": {
@@ -26,12 +32,6 @@
26
32
  }
27
33
  }
28
34
  },
29
- "main": "dist/index.js",
30
- "module": "dist/index.js",
31
- "types": "dist/index.d.ts",
32
- "files": [
33
- "dist"
34
- ],
35
35
  "dependencies": {
36
36
  "dayjs": "^1.11.19",
37
37
  "detect-browser-es": "0.1.1"
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","names":["HostEnv","VantUploadFileStatus","AntdUploadFileStatus","ElementPlusUploadFileStatus","Resource"],"sources":["../types/index.ts","../types/dom.d.ts","../src/case.ts","../src/console/log-common.ts","../src/console/log-dedupe.ts","../src/console/log-once.ts","../src/desensitize.ts","../src/detect.ts","../src/dom.ts","../src/format/baseAttachUrl.ts","../src/format/core.ts","../src/format/currency.ts","../src/format/dayjs.ts","../types/upload.d.ts","../src/format/resource.ts","../src/format/sort.ts","../src/mock.ts","../src/validate/core.ts","../src/validate/form.ts","../src/validate/request.ts"],"sourcesContent":["export interface HostEnv {\n /**\n * 是否是浙里办\n */\n readonly zlb: boolean\n /**\n * 是否是专有钉\n */\n readonly zyd: boolean\n /**\n * 是否是浙政钉\n */\n readonly zzd: boolean\n /**\n * 是否是钉钉/专有钉/浙政钉\n */\n readonly dd: boolean\n /**\n * 是否是微信\n */\n readonly wx: boolean\n /**\n * 是否是支付宝\n */\n readonly zfb: boolean\n /**\n * 是否是小程序\n */\n readonly mini: boolean\n}\n","type VantUploadFileStatus = '' | 'uploading' | 'done' | 'failed'\ntype AntdUploadFileStatus = 'removed' | 'uploading' | 'done' | 'error'\ntype ElementPlusUploadFileStatus = 'ready' | 'uploading' | 'success' | 'fail'\n\nexport interface Resource {\n /** origin */\n group: string\n id: string\n name: string\n uri: string\n /** extend */\n url?: string\n size?: number\n uid?: string\n status?: VantUploadFileStatus | AntdUploadFileStatus | ElementPlusUploadFileStatus\n /** vant */\n objectUrl?: string\n content?: string\n isImage?: boolean\n message?: string\n deletable?: boolean\n reupload?: boolean\n /** antd */\n fileName?: string\n percent?: number\n thumbUrl?: string\n /** element-plus */\n percentage?: number\n}\n"],"mappings":"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"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","names":["prevValue: any","newName: string","detectBrowser","__BASE_ATTACH_URL__: string","attachList: Resource[]","viewport: Nullable<HTMLMetaElement>"],"sources":["../src/case.ts","../src/console/log-common.ts","../src/console/log-dedupe.ts","../src/console/log-once.ts","../src/validate/core.ts","../src/validate/form.ts","../src/validate/request.ts","../src/desensitize.ts","../src/detect.ts","../src/format/baseAttachUrl.ts","../src/format/core.ts","../src/format/currency.ts","../src/format/dayjs.ts","../src/format/resource.ts","../src/format/sort.ts","../src/dom.ts","../src/mock.ts"],"sourcesContent":["/**\n * snake2Kebab\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example snake2Kebab('hello_world') // hello_world => hello-world\n */\nexport const snake2Kebab = (str: string) => str.replace(/_([a-z])/g, (_, letter) => `-${letter.toLowerCase()}`)\n\n/**\n * snake2Pascal\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example snake2Pascal('hello_world') // hello_world => HelloWorld\n */\nexport const snake2Pascal = (str: string) =>\n str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/^[a-z]/, letter => letter.toUpperCase())\n\n/**\n * snake2Camel\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example snake2Camel('hello_world') // hello_world => helloWorld\n */\nexport const snake2Camel = (str: string) => str.replace(/(_([a-z]))/g, match => match[1]!.toUpperCase())\n\n/**\n * snake2Title\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example snake2Title('hello_world') // hello_world => Hello World\n */\nexport const snake2Title = (str: string) =>\n str.replace(/_([a-z])/g, (_, letter) => ` ${letter.toUpperCase()}`).replace(/^[a-z]/, letter => letter.toUpperCase())\n\n/**\n * kebab2Snake\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example kebab2Snake('hello-world') // hello-world => hello_world\n */\nexport const kebab2Snake = (str: string) => str.replace(/-([a-z])/g, (_, letter) => `_${letter.toLowerCase()}`)\n\n/**\n * kebab2Pascal\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example kebab2Pascal('hello-world') // hello-world => HelloWorld\n */\nexport const kebab2Pascal = (str: string) =>\n str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()).replace(/^[a-z]/, letter => letter.toUpperCase())\n\n/**\n * kebab2Camel\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example kebab2Camel('hello-world') // hello-world => helloWorld\n */\nexport const kebab2Camel = (str: string) => {\n const [first, ...rest] = str.split('-')\n return [first, ...rest.map(s => s.replace(/^[a-z]/, s[0]!.toUpperCase()))].join('')\n}\n\n/**\n * kebab2Title\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example kebab2Title('hello-world') // hello-world => Hello World\n */\nexport const kebab2Title = (str: string) =>\n str.replace(/-([a-z])/g, (_, letter) => ` ${letter.toUpperCase()}`).replace(/^[a-z]/, letter => letter.toUpperCase())\n\n/**\n * pascal2Snake\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example pascal2Snake('HelloWorld') // HelloWorld => hello_world\n */\nexport const pascal2Snake = (str: string) =>\n str.replace(/([A-Z])/g, (_, letter) => `_${letter.toLowerCase()}`).replace(/^_/, '')\n\n/**\n * pascal2Kebab\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example pascal2Kebab('HelloWorld') // HelloWorld => hello-world\n */\nexport const pascal2Kebab = (str: string) =>\n str.replace(/([A-Z])/g, (_, letter) => `-${letter.toLowerCase()}`).replace(/^-/, '')\n\n/**\n * pascal2Camel\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example pascal2Camel('HelloWorld') // HelloWorld => helloWorld\n */\nexport const pascal2Camel = (str: string) => str.replace(/^[A-Z]/, letter => letter.toLowerCase())\n\n/**\n * pascal2Title\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example pascal2Title('HelloWorld') // HelloWorld => Hello World\n */\nexport const pascal2Title = (str: string) => str.replace(/([A-Z])/g, (_, letter) => ` ${letter}`).replace(/^ /, '')\n\n/**\n * camel2Snake\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example camel2Snake('helloWorld') // helloWorld => hello_world\n */\nexport const camel2Snake = (str: string) => str.replace(/([A-Z])/g, (_, letter) => `_${letter.toLowerCase()}`)\n\n/**\n * camel2Kebab\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example camel2Kebab('helloWorld') // helloWorld => hello-world\n */\nexport const camel2Kebab = (str: string) => str.replace(/([A-Z])/g, (_, letter) => `-${letter.toLowerCase()}`)\n\n/**\n * camel2Pascal\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example camel2Pascal('helloWorld') // helloWorld => HelloWorld\n */\nexport const camel2Pascal = (str: string) => str.replace(/(^[a-z])|(\\s+[a-z])/g, match => match.toUpperCase())\n\n/**\n * camel2Title\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example camel2Title('helloWorld') // helloWorld => Hello World\n */\nexport const camel2Title = (str: string) =>\n str.replace(/([A-Z])/g, (_, letter) => ` ${letter}`).replace(/^[a-z]/, match => match.toUpperCase())\n\n/**\n * title2Snake\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example title2Snake('Hello World') // Hello World => hello_world\n */\nexport const title2Snake = (str: string) => str.replace(/([A-Z])/g, match => match.toLowerCase()).replace(/ /g, '_')\n\n/**\n * title2Kebab\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example title2Kebab('Hello World') // Hello World => hello-world\n */\nexport const title2Kebab = (str: string) => str.replace(/([A-Z])/g, match => match.toLowerCase()).replace(/ /g, '-')\n\n/**\n * title2Pascal\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example title2Pascal('Hello World') // Hello World => HelloWorld\n */\nexport const title2Pascal = (str: string) => str.replace(/ /g, '')\n\n/**\n * title2Camel\n * @param {string} str 字符串\n * @returns {string} 转换后的字符串\n * @example title2Camel('Hello World') // Hello World => helloWorld\n */\nexport const title2Camel = (str: string) => str.replace(/ /g, '').replace(/^[A-Z]/, match => match.toLowerCase())\n","/* eslint-disable no-console */\nconst sharedStyle = 'color: white; padding: 1px 2px;'\n\n/**\n * jade console.log\n * only for development\n * @param {...any} args\n */\nexport const jLog = (...args: any[]) =>\n __DEV__\n ? console.log.bind(\n console,\n `%c[${args.length === 1 ? 'LOG' : '%s'}]`,\n `${sharedStyle} background: seagreen;`\n )(...args)\n : () => {}\n\n/**\n * jade console.debug\n * @param {...any} args\n */\nexport const jDebug = (...args: any[]) =>\n console.log.bind(\n console,\n `%c[${args.length === 1 ? 'DEBUG' : '%s'}]`,\n `${sharedStyle} background: linear-gradient(LightSalmon, Tomato); border-radius: 2px; font-weight: bold; border-top: 2px solid Crimson; border-bottom: 2px solid Crimson;`\n )(...args)\n\n/**\n * jade console.warn\n */\nexport const jWarn = (...args: any[]) =>\n console.warn.bind(console, `%c[${args.length === 1 ? 'WARN' : '%s'}]`, `${sharedStyle} background: tomato;`)(...args)\n\n/**\n * jade console.error\n */\nexport const jError = (...args: any[]) =>\n console.error.bind(\n console,\n `%c[${args.length === 1 ? 'ERROR' : '%s'}]`,\n `${sharedStyle} background: crimson;`\n )(...args)\n\n/**\n * jade console.info\n * @param {...any} args\n */\nexport const jInfo = (...args: any[]) =>\n console.info.bind(\n console,\n `%c[${args.length === 1 ? 'INFO' : '%s'}]`,\n `${sharedStyle} background: dodgerblue;`\n )(...args)\n\n/**\n * jade console.group\n */\nexport const jGroup = console.group.bind(console, '%c[%s]', `${sharedStyle} background: slateblue;`)\n\n/**\n * jade console.groupCollapsed\n */\nexport const jGroupC = console.groupCollapsed.bind(console, '%c[%s]', `${sharedStyle} background: slateblue;`)\n\n/**\n * jade console.groupEnd\n */\nexport const jGroupE = console.groupEnd.bind(console)\n\n/**\n * jade console.time\n * @param str\n */\nexport const jTime = (str: string) => console.time(`[${str}]`)\n\n/**\n * jade console.timeEnd\n * @param str\n */\nexport const jTimeEnd = (str: string) => console.timeEnd(`[${str}]`)\n\n/**\n * jade console.clear\n */\nexport const jClear = console.clear.bind(console)\n","import { jLog } from './log-common'\n\nlet prevValue: any\n\n/**\n * 不连续打印相同的值\n * @param args\n */\nexport const jLogDedupe = (...args: any[]) => {\n if (args.length === 0) return\n if (args.length > 0 && prevValue && JSON.stringify(args) === JSON.stringify(prevValue)) return\n jLog(...args)\n prevValue = args\n}\n","import { jLog } from './log-common'\n\nlet logged = false\n\n/**\n * 只打印一次\n * @param args\n */\nexport const jLogOnce = (...args: any[]) => {\n if (logged) return\n jLog(...args)\n logged = true\n}\n","import type { Numeric, UnDef } from '../../types'\nimport { jWarn } from '../console'\n\n/**\n * 检测变量类型\n * @param {any} val 检测的目标\n */\nexport const getVariableType = (val: any) => {\n const value = Object.prototype.toString.call(val)\n const result = value.match(/\\[object (\\S*)\\]/)?.[1]\n return result?.toLocaleLowerCase()\n}\n\n/**\n * 是否是数字\n * @param {any} val 检测的目标\n */\nexport const isNumber = (val: any): val is number => getVariableType(val) === 'number'\n\n/**\n * 是否是任意精度整数\n * @param {any} val 检测的目标\n */\nexport const isBigInt = (val: any): val is bigint => getVariableType(val) === 'bigint'\n\n/**\n * 是否是字符串\n * @param {any} val 检测的目标\n */\nexport const isString = (val: any): val is string => getVariableType(val) === 'string'\n\n/**\n * 是否是布尔值\n * @param {any} val 检测的目标\n */\nexport const isBoolean = (val: any): val is boolean => getVariableType(val) === 'boolean'\n\n/**\n * 是否是null\n * @param {any} val 检测的目标\n */\nexport const isNull = (val: any): val is null => getVariableType(val) === 'null'\n\n/**\n * 是否是undefined\n * @param {any} val 检测的目标\n */\nexport const isUndefined = (val: any): val is undefined => getVariableType(val) === 'undefined'\n\n/**\n * 是否是symbol\n * @param {any} val 检测的目标\n */\nexport const isSymbol = (val: any): val is symbol => getVariableType(val) === 'symbol'\n\n/**\n * 是否是对象\n * @param {any} val 检测的目标\n */\nexport const isObject = (val: any): val is Record<any, any> => getVariableType(val) === 'object'\n\n/**\n * 是否是数组\n * @param {any} val 检测的目标\n */\nexport const isArray = (val: any): val is Array<any> => getVariableType(val) === 'array'\n\n/**\n * 是否是函数,但也有可能是Class\n * @param {any} val 检测的目标\n */\n// eslint-disable-next-line ts/no-unsafe-function-type\nexport const isFunction = (val: any): val is Function => getVariableType(val) === 'function'\n\n/**\n * 是否是日期\n * @param {any} val 检测的目标\n */\nexport const isDate = (val: any): val is Date => getVariableType(val) === 'date'\n\n/**\n * 是否是正则\n * @param {any} val 检测的目标\n */\nexport const isRegExp = (val: any): val is RegExp => getVariableType(val) === 'regexp'\n\n/**\n * 是否是期望(Promise)\n * @param {any} val 检测的目标\n */\nexport const isPromise = (val: any): val is Promise<any> => getVariableType(val) === 'promise'\n\n/**\n * 是否是集合(Set)\n * @param {any} val 检测的目标\n */\nexport const isSet = (val: any): val is Set<any> => getVariableType(val) === 'set'\n\n/**\n * 是否是映射(Map)\n * @param {any} val 检测的目标\n */\nexport const isMap = (val: any): val is Map<any, any> => getVariableType(val) === 'map'\n\n/**\n * 是否是弱集合(WeakSet)\n * @param {any} val 检测的目标\n */\nexport const isWeakSet = (val: any): val is WeakSet<any> => getVariableType(val) === 'weakset'\n\n/**\n * 是否是弱映射(WeakMap)\n * @param {any} val 检测的目标\n */\nexport const isWeakMap = (val: any): val is WeakMap<any, any> => getVariableType(val) === 'weakmap'\n\n/**\n * 是否是File\n * @param {any} val 检测的目标\n */\nexport const isFile = (val: any): val is File => getVariableType(val) === 'file'\n\n/**\n * 是否是Blob\n * @param {any} val 检测的目标\n */\nexport const isBlob = (val: any): val is Blob => getVariableType(val) === 'blob'\n\n/**\n * 是否是URL\n * @param {any} val 检测的目标\n */\nexport const isURL = (val: any): val is URL => getVariableType(val) === 'url'\n\n/**\n * 是否是错误(Error)\n * @param {any} val 检测的目标\n */\nexport const isError = (val: any): val is Error => getVariableType(val) === 'error'\n\n/**\n * 是否既不是 null 也不是 undefined\n * @param {any} val 检测的目标\n */\nexport const isDef = <T>(val: T): val is NonNullable<T> => !isNull(val) && !isUndefined(val)\n\n/**\n * 判断是否合法JSON字符串\n * @param str\n */\nexport const isJSONStr = (str: UnDef<string>) => {\n if (isDef(str)) {\n try {\n JSON.parse(str)\n return true\n } catch (e) {\n jWarn('Failed to parse invalid string', e)\n return false\n }\n }\n return false\n}\n\n/**\n * 判断是否合法JSON数组字符串\n * @param str\n */\nexport const isArrStr = (str: UnDef<string>) => {\n if (isDef(str)) {\n try {\n return Array.isArray(JSON.parse(str))\n } catch (e) {\n jWarn('Failed to parse invalid string', e)\n return false\n }\n }\n return false\n}\n\n/**\n * 判断是否有效的key\n * @param {string | number | symbol} key 键名\n * @param {object} object 对象\n * @example\n *\n * ```ts\n * const obj = { a: 1, b: 2 }\n * isValidKey('a', obj) // true\n * ```\n * @returns {boolean} boolean\n */\nexport const isValidKey = (key: string | number | symbol, object: object): key is keyof typeof object => key in object\n\n/**\n * 是否是空值/空数组/空对象 null undefined '' [] {} Set Map\n * @param val\n */\nexport const isEmpty = (val: UnDef<Numeric | boolean | Record<any, any> | Array<any> | Set<any> | Map<any, any>>) => {\n return (\n !isDef(val) ||\n val === '' ||\n (isArray(val) && val.length === 0) ||\n (isObject(val) && Object.keys(val).length === 0) ||\n (isMap(val) && val.size === 0) ||\n (isSet(val) && val.size === 0)\n )\n}\n","import type { Numeric, UnDef } from '../../types'\nimport { isDef } from './core'\n\nexport const cnPhoneRE = /^1[3-9]\\d{9}$/\nexport const cnTelRE = /^0\\d{2,3}-?\\d{7,8}$/\nexport const cnTelRE2 = /^\\(0\\d{2,3}\\)\\d{7,8}$/\nexport const cnUSCIRE = /^[0-9A-HJ-NPQRTUWXY]{2}\\d{6}[0-9A-HJ-NPQRTUWXY]{10}$/\nexport const cnIdCard15Re = /^[1-9]\\d{7}(?:0[1-9]|10|11|12)(?:[0-2][1-9]|10|20|30|31)\\d{2}[\\dX]$/i\nexport const cnIdCard18Re = /^[1-9]\\d{5}(?:18|19|20)\\d{2}(?:0[1-9]|1[0-2])(?:[0-2][1-9]|10|20|30|31)\\d{3}[\\dX]$/i\nexport const emailRE = /^[a-z\\d](?:\\w|-)+@[a-z\\d]+\\.[a-z]{2,5}$/i\n\n/**\n * 是否是[统一社会信用代码](https://zh.wikipedia.org/zh-cn/%E7%BB%9F%E4%B8%80%E7%A4%BE%E4%BC%9A%E4%BF%A1%E7%94%A8%E4%BB%A3%E7%A0%81)\n * @example\n * ```ts\n * isUSCI('91350100M000100Y43') // true\n * ```\n * @param {UnDef<string>} val - 待校验的值\n * @returns {boolean} 是否是统一社会信用代码\n */\nexport const isUSCI = (val: UnDef<string>): boolean => {\n if (!isDef(val)) return false\n return cnUSCIRE.test(val)\n}\n\n/**\n * 是否是中国手机号\n * @param val\n */\nexport const isPhone = (val: UnDef<Numeric>) => {\n if (!isDef(val)) return false\n return cnPhoneRE.test(val.toString())\n}\n\n/**\n * 是否是中国座机号\n * @param val\n */\nexport const isTel = (val: UnDef<Numeric>) => {\n if (!isDef(val)) return false\n const valStr = val.toString().replaceAll(' ', '')\n return cnTelRE.test(valStr) || cnTelRE2.test(valStr)\n}\n\n/**\n * 是否是邮箱\n * @param val\n */\nexport const isEmail = (val: UnDef<string>) => {\n if (!isDef(val)) return false\n return emailRE.test(val)\n}\n\n/**\n * 是否是身份证\n * @param {string|null|undefined} val 身份证号\n * @param {boolean} compatible 兼容15位\n */\nexport const isIdCard = (val: UnDef<string>, compatible = true) => {\n if (!isDef(val)) return false\n return cnIdCard18Re.test(val) || (compatible ? cnIdCard15Re.test(val) : false)\n}\n\n/**\n * 是否是数字或字符\n * @param val\n */\nexport const isNumeric = (val: UnDef<Numeric>): val is string => {\n if (isDef(val)) return typeof val === 'number' || /^\\d+(?:\\.\\d+)?$/.test(val)\n return false\n}\n\n/**\n * 是否是需要的图片格式\n * @param ext\n */\nexport const checkImg = (ext?: string) => {\n return /\\.(?:jpg|jpeg|png|gif)$/.test((ext || '').toLowerCase())\n}\n\n/**\n * 包含非ASCII字符\n * @param text\n */\nexport const nonASCII = (text: string) => /[^\\x20-\\x7E]/.test(text)\n\n/**\n * 校验文件类型\n * 1. XXX/YYY 2. .xxx 3. XXX/* 4.*\n * @param {File} file 需要校验的文件\n * @param {string} type 文件类型, 与input.accept一致\n */\nexport const isValidFileType = (file: File, type: string) => {\n if (type === '*') return true\n\n const fileType = file.type\n const fileName = file.name\n\n /**\n * 校验\n * @param item\n */\n function validate(item: string) {\n if (item.startsWith('.')) {\n return fileName.endsWith(item)\n }\n if (item.endsWith('/*')) {\n return fileType.startsWith(item.replace('/*', ''))\n }\n if (item.includes('/')) {\n return fileType === item\n }\n return false\n }\n\n const typeArrStr = type.split(',').map(item => item.trim())\n if (typeArrStr.length > 1) {\n return typeArrStr.some(validate)\n }\n return validate(type)\n}\n","import type { PageRes, Res } from '../../types'\nimport { isDef } from './core'\n\n/**\n * 校验接口返回code\n * @param res\n * @param code\n */\nexport const isValidResCode = (res: Res, code = 200) => res.code === code\n\n/**\n * 校验接口返回内容\n * @param res\n * @param code\n */\nexport const isValidRes = (res: Res, code?: number) => isValidResCode(res, code) && isDef(res.data)\n\n/**\n * 校验接口数组返回内容\n * @param res\n * @param code\n */\nexport const isValidArrRes = (res: Res<any[]>, code?: number) => isValidResCode(res, code) && Array.isArray(res.data)\n\n/**\n * 校验接口分页返回内容\n * @param res\n * @param code\n */\nexport const isValidPageRes = (res: PageRes, code?: number) =>\n isValidResCode(res, code) && isDef(res.data) && Array.isArray(res.data.list || res.data.records)\n","import type { UnDef } from '../types'\nimport { cnTelRE, cnTelRE2, isDef, isIdCard, isPhone } from './validate'\n\n/**\n * 隐藏中间部分\n * @param {string} str 需要隐藏的字符串\n * @returns {string} 隐藏后的字符串\n * @example\n * ```ts\n * hideMiddle('A') // '*'\n * hideMiddle('AB') // '**'\n * hideMiddle('ABC') // 'A*C'\n * hideMiddle('ABCD') // 'A**D'\n * hideMiddle('ABCDE') // 'A***E'\n * ```\n */\nexport const hideMiddle = (str: UnDef<string>): string => {\n if (!isDef(str)) return ''\n const len = str.length\n if (len <= 2) return '*'.repeat(len)\n return str[0] + '*'.repeat(len - 2) + str[len - 1]\n}\n\n/**\n * 隐藏首尾仅保留中间3分之1\n * @param {string} str 需要隐藏的字符串\n * @returns {string} 隐藏后的字符串\n * @example\n * ```ts\n * hideThird('A') // '*'\n * hideThird('AB') // '**'\n * hideThird('ABC') // 'A*C'\n * hideThird('ABCD') // 'A**D'\n * hideThird('ABCDE') // 'AB*DE'\n * ```\n */\nexport const hideThird = (str: UnDef<string>): string => {\n if (!isDef(str)) return ''\n const len = str.length\n if (len <= 2) return '*'.repeat(len)\n const partLen = Math.round(len / 3)\n return str.slice(0, partLen) + '*'.repeat(len - 2 * partLen) + str.slice(len - partLen)\n}\n\n/**\n * 隐藏首部\n * @param {string} str 需要隐藏的字符串\n * @param {number} count 隐藏的字符数\n * @returns {string} 隐藏后的字符串\n * @example\n * ```ts\n * hideHead('A') // '*'\n * hideHead('AB') // '*B'\n * hideHead('ABC') // '**C'\n * hideHead('ABC', 1) // '*BC'\n * ```\n */\nexport const hideHead = (str: UnDef<string>, count?: number): string => {\n if (!isDef(str)) return ''\n const len = str.length\n if (len <= 1) return '*'.repeat(len)\n const cnt = count !== undefined ? Math.max(Math.min(len, count), 0) : len - 1\n return '*'.repeat(cnt) + str.substring(cnt)\n}\n\n/**\n * 隐藏尾部\n * @param {string} str 需要隐藏的字符串\n * @param {number} count 隐藏的字符数\n * @returns {string} 隐藏后的字符串\n * @example\n * ```ts\n * hideTail('A') // '*'\n * hideTail('AB') // 'A*'\n * hideTail('ABC') // 'A**'\n * hideTail('ABC', 1) // 'AB*'\n * ```\n */\nexport const hideTail = (str: UnDef<string>, count?: number): string => {\n if (!isDef(str)) return ''\n const len = str.length\n if (len <= 1) return '*'.repeat(len)\n const cnt = count !== undefined ? Math.max(Math.min(len, count), 0) : len - 1\n return str.substring(0, len - cnt) + '*'.repeat(cnt)\n}\n\n/**\n * 隐藏手机号/座机号\n * @param {string} phone 手机号/座机号\n * @returns {string} 隐藏后的手机号/座机号\n * @example\n * ```ts\n * hidePhone('13800138000') // '138****8000'\n * hidePhone('010-12345678') // '010****5678'\n * hidePhone('(010)12345678') // '(010)****5678'\n * ```\n */\nexport const hidePhone = (phone: UnDef<string>): string => {\n if (phone) {\n const phoneStr = phone.replaceAll(' ', '') // remove all blanks\n if (isPhone(phoneStr)) {\n return phoneStr.replace(/^(\\d{3})\\d{4}(\\d{4})$/, '$1****$2')\n }\n if (cnTelRE.test(phoneStr)) {\n // eslint-disable-next-line regexp/no-misleading-capturing-group\n return phoneStr.replace(/^(0\\d{2,3})-?\\d{3,4}(\\d{4})$/, '$1****$2')\n }\n if (cnTelRE2.test(phoneStr)) {\n return phoneStr.replace(/^\\((0\\d{2,3})\\)\\d{3,4}(\\d{4})$/, '$1****$2')\n }\n return phone\n }\n return ''\n}\n\n/**\n * 隐藏身份证号\n * @param {string} cardNo 身份证号\n * @param {boolean} strong 是否强化隐藏\n * @returns {string} 隐藏后的身份证号\n * @example\n * ```ts\n * hideCardNo('33072319641008384x') // '3****************x'\n * hideCardNo('33072319641008384x', false) // '3***23196410*****x'\n * ```\n */\nexport const hideCardNo = (cardNo: UnDef<string>, strong: boolean = true): string => {\n if (cardNo) {\n if (isIdCard(cardNo, false)) {\n return strong ? hideMiddle(cardNo) : cardNo.replace(/^(.)\\d{3}(.{8})\\d{5}(.)$/, '$1***$2*****$3')\n }\n return cardNo\n }\n return ''\n}\n\n/**\n * 隐藏姓氏\n * @param {string} name 姓名\n * @returns {string} 隐藏后的姓名\n * @example\n * ```ts\n * hideSurname('张三') // '*三'\n * hideSurname('司马懿') // '*马懿'\n * ```\n */\nexport const hideSurname = (name: UnDef<string>): string => {\n return hideHead(name, 1)\n}\n\n/**\n * 隐藏名字\n * @param {string} name 姓名\n * @returns {string} 隐藏后的姓名\n * @example\n * ```ts\n * hideFirstName('张三') // '张*'\n * hideFirstName('司马懿') // '司马*'\n * ```\n */\nexport const hideFirstName = (name: UnDef<string>): string => {\n return hideTail(name)\n}\n\n/**\n * 隐藏邮箱\n * @param {string} email 邮箱\n * @returns {string} 隐藏后的邮箱\n * @example\n * ```ts\n * hideEmail('example@hotmail.com') // 'exam***@hotmail.com'\n * ```\n */\nexport const hideEmail = (email: UnDef<string>): string => {\n if (email) {\n if (!email.includes('@')) return email\n\n const arr = email.split('@')\n const name = arr[0]\n const domain = arr[1]\n\n if (!name || !domain) return email\n\n const len = name.length\n\n let newName: string\n if (len <= 3) {\n newName = `${name}***`\n } else {\n newName = hideTail(name, 3)\n }\n\n return `${newName}@${domain}`\n }\n return ''\n}\n\n/**\n * 隐藏银行卡号\n * @param {string} bankCard 银行卡号\n * @returns {string} 隐藏后的银行卡号\n * @example\n * ```ts\n * hideBankCard('6222021001123456789') // '622202********6789'\n * ```\n */\nexport const hideBankCard = (bankCard: UnDef<string>): string => {\n if (bankCard) {\n const len = bankCard.length\n if (len <= 10) return bankCard\n return bankCard.substring(0, 6) + '*'.repeat(len - 10) + bankCard.substring(len - 4, len)\n }\n return ''\n}\n","import { detect as detectBrowser } from 'detect-browser-es'\n\n/**\n * 检测浏览器环境\n * @deprecated 下个版本移除,请直接使用 `detect-browser-es` 包\n */\nexport const detect = detectBrowser\n","/**\n * 文件基本路径\n */\nlet __BASE_ATTACH_URL__: string\n\n/**\n * 设置文件基本路径\n * @param baseUrl\n */\nexport function setBaseAttachUrl(baseUrl: string) {\n __BASE_ATTACH_URL__ = baseUrl\n}\n\n/**\n * 获取文件基本路径\n */\nexport function getBaseAttachUrl() {\n return __BASE_ATTACH_URL__\n}\n","import type { Nullable } from '../../types'\nimport { isDate, isJSONStr, isMap, isSet } from '../validate'\n\n/**\n * JSON 字符串转对象\n * @template T - 解析数据类型\n * @param {string} str - JSON字符串\n * @param {(this: any, key: string, value: any) => any} reviverFn - 解析函数\n * @returns {Nullable<T>} 解析后的对象\n * @deprecated 请使用 `parseJSON`\n */\nexport function parseToJSON<T = any>(\n str: string,\n reviverFn?: (this: any, key: string, value: any) => any\n): Nullable<T> {\n return isJSONStr(str) ? JSON.parse(str, reviverFn) : null\n}\n\n/**\n * JSON 字符串转对象\n * @alias parseToJSON\n * @template T - 解析数据类型\n * @param {string} str - JSON字符串\n * @param {(this: any, key: string, value: any) => any} reviverFn - 解析函数\n * @returns {Nullable<T>} 解析后的对象\n */\nexport function parseJSON<T = any>(\n str: string,\n reviverFn: (this: any, key: string, value: any) => any = reviver\n): Nullable<T> {\n return isJSONStr(str) ? JSON.parse(str, reviverFn) : null\n}\n\n/**\n * 对象转 JSON 字符串\n * @param {any} value - 对象\n * @param {(this: any, key: string, value: any) => any} replacerFn - 替换函数\n * @returns {string} JSON 字符串\n */\nexport function stringifyJSON(value: any, replacerFn: (this: any, key: string, value: any) => any = replacer): string {\n return JSON.stringify(value, replacerFn)\n}\n\n/**\n * JSON.stringify() second param\n * @param _key\n * @param value\n */\nexport function replacer(_key: any, value: any) {\n if (isMap(value)) {\n return {\n dataType: 'Map',\n value: [...value],\n }\n }\n if (isSet(value)) {\n return {\n dataType: 'Set',\n value: [...value],\n }\n }\n if (isDate(value)) {\n return {\n dataType: 'Date',\n value: value.toISOString(),\n }\n }\n return value\n}\n\n/**\n * JSON.parse() second param\n * @param _key\n * @param value\n */\nexport function reviver(_key: any, value: any) {\n if (typeof value === 'object' && value !== null) {\n if (value.dataType === 'Map') {\n return new Map(value.value)\n }\n if (value.dataType === 'Set') {\n return new Set(value.value)\n }\n if (value.dataType === 'Date') {\n return new Date(value.value)\n }\n }\n return value\n}\n\n/**\n * 过滤obj中仅包括keys的部分\n * @param {Record<string,any>} obj 对象\n * @param {string[]} keys 属性\n * @param {boolean} reverse 为true时过滤取反\n */\nexport const filterObj = (obj: Record<string, any>, keys: string[], reverse: boolean = false) =>\n Object.fromEntries(Object.entries(obj).filter(([key]) => (reverse ? !keys.includes(key) : keys.includes(key))))\n","import type { Numeric, UnDef } from '../../types'\nimport { isDef } from '../validate'\n\n/**\n * 千位分隔符\n * @param num\n */\nexport const toThousands = (num: number) => {\n const arr = num.toString().split('.')\n const integer = arr[0]?.replace(/(\\d)(?=(?:\\d{3})+$)/g, '$1,')\n if (arr.length > 1) return `${integer}.${arr[1]}`\n return integer\n}\n\n/**\n * 货币格式化\n * @param {number | string | bigint} currency - 金额\n * @param {number} [maximumFractionDigits] - 小数位数\n */\nexport const currencyFmt = (currency: UnDef<Numeric | bigint>, maximumFractionDigits: number = 2) => {\n if (!isDef(currency)) return ''\n const num = Number(currency)\n if (Number.isNaN(num)) return ''\n return new Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY', maximumFractionDigits }).format(num)\n}\n","import type { ConfigType, Dayjs } from 'dayjs'\nimport dayjs from 'dayjs'\nimport zhCN from 'dayjs/locale/zh-cn.js'\nimport customParseFormat from 'dayjs/plugin/customParseFormat.js'\nimport duration from 'dayjs/plugin/duration.js'\nimport localeData from 'dayjs/plugin/localeData.js'\nimport objectSupport from 'dayjs/plugin/objectSupport.js'\nimport relativeTime from 'dayjs/plugin/relativeTime.js'\nimport { isDef } from '../validate'\n\ndayjs.extend(localeData).locale('zh-cn', zhCN)\ndayjs.extend(duration)\ndayjs.extend(relativeTime)\ndayjs.extend(customParseFormat)\ndayjs.extend(objectSupport)\n\nexport { dayjs }\nexport type { Dayjs }\n\n/**\n * 格式化时间\n * @param {import('dayjs').ConfigType} date 时间\n * @param {string} format 格式\n * @returns {string} 格式化后的时间\n */\nexport const dateFmt = (date: ConfigType, format: string | 'date' | 'datetime' = 'YYYY-MM-DD HH:mm:ss'): string => {\n const dd = dayjs(date)\n let fmt = format\n if (!isDef(date) || !dd.isValid()) return ''\n if (format === 'date') fmt = 'YYYY-MM-DD'\n if (format === 'datetime') fmt = 'YYYY-MM-DD HH:mm:ss'\n\n return dd.format(fmt)\n}\n\n/**\n * 格式化时间间隔\n * @param {import('dayjs').ConfigType} start 开始时间\n * @param {import('dayjs').ConfigType} end 结束时间\n */\nexport const dateDuration = (start: ConfigType, end: ConfigType) => {\n const startDay = dayjs(start)\n const endDay = dayjs(end)\n if (!isDef(start) || !startDay.isValid() || !isDef(end) || !endDay.isValid()) return ''\n\n const dd = dayjs.duration(endDay.diff(startDay))\n\n const year = dd.years()\n const month = dd.months()\n const day = dd.days()\n const format = [\n year === 0 ? '' : 'Y年',\n month === 0 ? '' : 'M个月',\n day === 0 ? '' : `${day < 10 && (year !== 0 || month !== 0) ? '零' : ''}D天`,\n ].join('')\n\n return dd.format(format)\n}\n","import type { MaybeArray, UnDef, Undefinable } from '../../types'\nimport type { Resource } from '../../types/upload'\nimport { isArrStr, isDef } from '../validate'\nimport { getBaseAttachUrl } from './baseAttachUrl'\nimport { parseJSON } from './core'\n\n/**\n * 获取文件完整地址\n * @param url\n */\nexport const resUrl = (url: Undefinable<string>) => {\n if (!isDef(url)) return undefined\n if (/^https?:\\/\\//.test(url) || url.startsWith('blob:') || url.startsWith('data:')) {\n return url\n }\n const baseUrl = getBaseAttachUrl()\n if (!isDef(baseUrl)) {\n throw new Error('请先使用 setBaseAttachUrl 设置文件基本路径')\n }\n return `${baseUrl}/${url}`.replace(/([^:]\\/)\\/+/g, '$1')\n}\n\n/**\n * 统一文件字段内容\n * @param resource\n */\nexport const recoverFile = (resource: Resource) => {\n const { uri, url, ...item } = resource\n const validUrl = uri || url\n return {\n ...item,\n url: resUrl(validUrl),\n content: resUrl(validUrl),\n uri: validUrl || '',\n status: 'done',\n percent: 100,\n }\n}\n\n/**\n * 附件格式\n * @param data\n */\nexport const attachFmt = (data: UnDef<MaybeArray<Resource>> | string) => {\n let attachList: Resource[] = []\n const prototype = Object.prototype.toString.call(data)\n // null 或 undefined\n if (!data) {\n attachList = []\n // Upload.Resource[]\n } else if (Array.isArray(data)) {\n attachList = data.filter(Boolean)\n // 字符串\n } else if (typeof data === 'string') {\n // Upload.Resource[] string\n if (isArrStr(data)) {\n attachList = (parseJSON<Resource[]>(data) || []).filter(Boolean)\n } else {\n const jsonData = parseJSON<Resource | string>(data)\n const prototypeJson = Object.prototype.toString.call(jsonData)\n // Upload.Resource string\n if (prototypeJson === '[object Object]') attachList = [jsonData as Resource].filter(Boolean)\n // 单个uri string\n else attachList = [{ id: data, name: 'name', uri: data, group: 'default' }]\n }\n // Upload.Resource\n } else if (prototype === '[object Object]') {\n attachList = [data]\n }\n return attachList.map(recoverFile)\n}\n","import type { Numeric, UnDef } from '../../types'\nimport { isDef } from '../validate'\n\n/**\n * 判断是否为数字数组\n * @param {UnDef<string>[] | UnDef<number>[]} arr - 数字或字符串数组\n * @returns {boolean} - 是否为数字数组\n */\nconst isNumberArray = (arr: UnDef<string>[] | UnDef<number>[]): arr is number[] =>\n arr.every(item => typeof item === 'number')\n\n/**\n * 判断是否为字符串数组\n * @param {UnDef<string>[] | UnDef<number>[]} arr - 数字或字符串数组\n * @returns {boolean} - 是否为字符串数组\n */\nconst isStringArray = (arr: UnDef<string>[] | UnDef<number>[]): arr is string[] =>\n arr.every(item => typeof item === 'string')\n\n/**\n * 自然排序\n * @param {UnDef<string>[] | UnDef<number>[]} arr - 数字或字符串数组\n * @returns {UnDef<string>[] | UnDef<number>[]} - 排序后的数组\n */\nexport const naturalSort = (arr: UnDef<string>[] | UnDef<number>[]): UnDef<string>[] | UnDef<number>[] => {\n if (isNumberArray(arr)) return [...arr].sort((a, b) => a - b)\n if (isStringArray(arr)) {\n return [...arr].sort((a, b) => a.localeCompare(b, 'zh-CN')).sort((a, b) => a.length - b.length)\n }\n const newArr = [...arr].sort()\n const validArr = newArr.filter(a => isDef(a)) as string[] | number[]\n const invalidArr = newArr.filter(a => !isDef(a)) as (null | undefined)[]\n // @ts-expect-error ...\n return naturalSort(validArr as UnDef<string>[] | UnDef<number>[]).concat(invalidArr)\n}\n\n/**\n * 根据 key 自然排序\n * @param arr - 数组\n * @param {string} key - 键名\n * @returns {any[]} - 排序后的数组\n */\nexport const naturalSortBy = <T extends Record<string, UnDef<Numeric>>>(arr: T[], key: keyof T): T[] => {\n // @ts-expect-error ...\n return [...arr].sort((a, b) => (naturalSort([a[key], b[key]])[0] === a[key] ? -1 : 1))\n}\n","import type { Nullable } from '../types'\nimport type { HostEnv } from '../types/dom'\nimport { dateFmt, dayjs } from './format'\n\n/**\n * 判断是否是浏览器环境\n */\nexport const inBrowser = typeof window !== 'undefined'\n\n/**\n * 等待一段时间\n * @param time\n */\nexport const waitTime = (time = 100) => {\n return new Promise(resolve => {\n setTimeout(() => {\n resolve(true)\n }, time)\n })\n}\n\n/**\n * 防止 iOS 因输入框字体小于16px 而在 focus 时页面缩放变大需要手动回正的情况。\n * iOS 10+ 允许 pinch-zoom, 即使 viewport 是不可伸缩的。\n * 只对这些浏览器添加额外规则\n */\nexport const fixiOSInputAutoZoomIn = () => {\n if (\n CSS.supports('(font:-apple-system-body) and (-webkit-touch-callout:none) and (-webkit-tap-highlight-color:hotpink)')\n ) {\n const viewport: Nullable<HTMLMetaElement> = document.querySelector('meta[name=\"viewport\"]')\n if (viewport !== null) {\n viewport.content = `${viewport.content}, user-scalable=no`\n }\n }\n}\n\n/**\n * 用户代理\n */\nexport const userAgent = inBrowser ? window.navigator.userAgent : ''\n\n/**\n * 获取宿主环境信息\n * @returns {HostEnv} 宿主环境信息\n * @example\n * const hostEnv = getHostEnv()\n * hostEnv.zlb // 浙里办\n * hostEnv.zyd // 专有钉\n * hostEnv.zzd // 浙政钉\n * hostEnv.dd // 钉钉/专有钉/浙政钉\n * hostEnv.wx // 微信\n * hostEnv.zfb // 支付宝\n * hostEnv.mini // 小程序\n */\nexport const getHostEnv = () => {\n const ua = userAgent.toLowerCase()\n\n const zlb = ua.includes('@zlb') // 浙里办\n const zyd = ua.includes('saas') // 专有钉\n const zzd = ua.includes('zhejiang') || ua.includes('tauruszjd') || ua.includes('dingtalk-win') // 浙政钉\n const dd = ua.includes('taurusapp') // 钉钉/专有钉/浙政钉\n const wx = ua.includes('micromessenger') // 微信\n const zfb = ua.includes('alipay') // 支付宝\n const mini = ua.includes('miniprogram') // 小程序\n\n const info: HostEnv = {\n zlb,\n zyd,\n zzd,\n dd,\n wx,\n zfb,\n mini,\n }\n\n return info\n}\n\n/**\n * 异或值\n */\nconst XOR_VAL = 1111\n\n/**\n * 获取某个时间戳的异或值的绝对值,在某个时间段内获取的值是唯一的\n * @param time\n */\nconst getCodeOfTime = (time: string) => Math.abs(new Date(time).getTime() ^ XOR_VAL)\n\n/**\n * 获取当小时的时间戳的异或值的绝对值, 当小时内获取的值是唯一的\n */\nexport const getCodeOfHour = () => getCodeOfTime(`${dateFmt(new Date(), 'YYYY-MM-DD HH')}:00:00`)\n\n/**\n * 获取当天的时间戳的异或值的绝对值, 当天内获取的值是唯一的\n */\nexport const getCodeOfDate = () => getCodeOfTime(dateFmt(new Date(), 'date'))\n\n/**\n * 获取当月的时间戳的异或值的绝对值, 当月内获取的值是唯一的\n */\nexport const getCodeOfMonth = () => getCodeOfTime(dateFmt(dayjs().endOf('month'), 'date'))\n","import type { PageRes, PageResData, Res } from '../types'\n\nexport const getMockData = <T>(data: T, code = 200, message = 'success'): Res<T> => {\n return { data, code, message }\n}\n\nexport const getMockDataList = <T>(\n data: T[],\n total: number,\n code = 200,\n message = 'success',\n options: Partial<PageResData<T>> = {}\n): PageRes<T> => {\n return { data: { records: data, list: data, total, ...options }, code, message } as PageRes<T>\n}\n"],"mappings":"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"}