@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 +1 -0
- package/dist/index.d.ts +2 -11
- package/dist/index.js +1072 -2
- package/package.json +16 -16
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
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
|
|
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,
|
|
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
|
-
|
|
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
|
-
"
|
|
4
|
-
"
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
"
|
|
14
|
-
"
|
|
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"
|
package/dist/index.d.ts.map
DELETED
|
@@ -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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"}
|