@ivujs/i-utils 2.1.5 → 2.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.full.umd.min.js","sources":["../../src/constants/file:/D:/webWorks/i-utils/src/constants/sort.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/math.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/regexp.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/date.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/keycode.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/id-card.ts","../../src/validate/file:/D:/webWorks/i-utils/src/validate/index.ts","../../src/string/file:/D:/webWorks/i-utils/src/string/index.ts","../../src/number/file:/D:/webWorks/i-utils/src/number/index.ts","../../src/array/file:/D:/webWorks/i-utils/src/array/index.ts","../../src/object/file:/D:/webWorks/i-utils/src/object/index.ts","../../src/date/file:/D:/webWorks/i-utils/src/date/index.ts","../../src/math/file:/D:/webWorks/i-utils/src/math/index.ts","../../src/regexp/file:/D:/webWorks/i-utils/src/regexp/index.ts","../../src/file/file:/D:/webWorks/i-utils/src/file/index.ts","../../src/color/file:/D:/webWorks/i-utils/src/color/index.ts","../../src/crypto/base64/file:/D:/webWorks/i-utils/src/crypto/base64/base64.js","../../src/crypto/md5/file:/D:/webWorks/i-utils/src/crypto/md5/md5.js","../../src/crypto/sha256/file:/D:/webWorks/i-utils/src/crypto/sha256/sha256.js","../../src/crypto/sm3/file:/D:/webWorks/i-utils/src/crypto/sm3/sm3.js","../../src/crypto/sm4/file:/D:/webWorks/i-utils/src/crypto/sm4/sm4.js","../../src/crypto/sm4/file:/D:/webWorks/i-utils/src/crypto/sm4/index.ts","../../src/desensitized/file:/D:/webWorks/i-utils/src/desensitized/index.ts","../../src/ID-card/file:/D:/webWorks/i-utils/src/ID-card/index.ts","../../src/pagination/file:/D:/webWorks/i-utils/src/pagination/index.ts","../../src/url/file:/D:/webWorks/i-utils/src/url/index.ts","../../src/cookie/file:/D:/webWorks/i-utils/src/cookie/index.ts","../../src/dom/file:/D:/webWorks/i-utils/src/dom/index.ts","../../src/device/file:/D:/webWorks/i-utils/src/device/index.ts","../../src/clipboard/file:/D:/webWorks/i-utils/src/clipboard/index.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/lang.ts","../../src/crypto/base64/file:/D:/webWorks/i-utils/src/crypto/base64/index.ts","../../src/storage/file:/D:/webWorks/i-utils/src/storage/localStorage.ts","../../src/storage/file:/D:/webWorks/i-utils/src/storage/sessionStorage.ts","../../src/function/file:/D:/webWorks/i-utils/src/function/index.ts","../../src/id/file:/D:/webWorks/i-utils/src/id/index.ts","../../src/keycode/file:/D:/webWorks/i-utils/src/keycode/index.ts","../../src/random/file:/D:/webWorks/i-utils/src/random/index.ts","../../src/storage/file:/D:/webWorks/i-utils/src/storage/index.ts","../../src/crypto/md5/file:/D:/webWorks/i-utils/src/crypto/md5/index.ts","../../src/crypto/sha256/file:/D:/webWorks/i-utils/src/crypto/sha256/index.ts","../../src/crypto/sm3/file:/D:/webWorks/i-utils/src/crypto/sm3/index.ts","../../src/file:/D:/webWorks/i-utils/src/index.ts"],"sourcesContent":["/**\r\n * 排序相关常量配置(全局只读)\r\n *\r\n * DESC: 降序\r\n * - 取值:0\r\n *\r\n * ASC: 升序\r\n * - 取值:1\r\n *\r\n * RANDOM: 随机排序\r\n * - 取值:2\r\n */\r\nexport const SORT: Record<string, number> = {\r\n // 降序\r\n DESC: 0,\r\n // 升序\r\n ASC: 1,\r\n // 随机排序\r\n RANDOM: 2,\r\n} as const;\r\n","/**\r\n * 数学计算相关常量配置(全局只读)\r\n *\r\n * ROUND: 正常四舍五入\r\n * - 取值:0\r\n * - 示例:1.354保留两位是1.35;1.355保留两位是1.36\r\n *\r\n * ROUND_FLOOR: 向下舍出\r\n * - 取值:1\r\n * - 示例:1.354保留两位是1.35;1.355保留两位是1.35\r\n */\r\nexport const MATH: Record<string, any> = {\r\n // 正常四舍五入,如:1.354保留两位是1.35;1.355保留两位是1.36;\r\n ROUND: 0,\r\n // 向下舍出,如:1.354保留两位是1.35;1.355保留两位是1.35;\r\n ROUND_FLOOR: 1,\r\n} as const;\r\n","/**\r\n * 正则表达式相关常量配置(全局只读)\r\n *\r\n * CH: 中文汉字\r\n * EN: 英文字母\r\n * LOWER_CASE: 小写字母\r\n * UPPER_CASE: 大写字母\r\n * CH_NAME: 中文姓名(2-16位)\r\n * EN_NAME: 英文姓名(1-20位)\r\n * NUMBER: 数字(包含正数和负数)\r\n * INTEGER: 整数(包含:0,正整数和负整数)\r\n * DECIMAL: 小数(包含正小数和负小数)\r\n * INT_OR_FLOAT: 正整数或者保留两位小数\r\n * MOBILE: 手机号码(支持+86)\r\n * PHONE: 固定电话号码(比如:0755-1111111)\r\n * EMAIL: 邮箱\r\n * ID_CARD: 一代15位或二代18位身份证\r\n * ID_CARD15: 仅校验一代15位身份证\r\n * ID_CARD18: 仅校验二代18位身份证\r\n * BANK_CARD: 银行卡号\r\n * POST_CODE: 邮政编码\r\n * URL: url地址(可获取主机地址、主机名、端口号、协议、查询参数、hash等信息)\r\n * IP: ip地址\r\n * IP6: IPv6地址\r\n * EXTERNAL: 外链(http、https、mail、tel电话)\r\n */\r\nexport const REGEXP: Record<string, RegExp> = {\r\n // 中文汉字\r\n CH: /^[\\u4E00-\\u9FA5]+$/,\r\n // 英文字母,1个以上\r\n EN: /^[a-zA-Z]+$/,\r\n // 小写字母\r\n LOWER_CASE: /^[a-z]+$/,\r\n // 大写字母\r\n UPPER_CASE: /^[A-Z]+$/,\r\n // 中文姓名,2-16位(支持少数民族姓名间隔符「·」)\r\n CH_NAME: /^[\\u4e00-\\u9fa5·]{2,16}$/,\r\n // 英文姓名,1-20位\r\n EN_NAME: /^[a-zA-Z\\s]{1,20}$/,\r\n // 数字,包含正数和负数\r\n NUMBER: /^([-+])?\\d+(\\.\\d+)?$/,\r\n // 整数,包含:0,正整数和负整数\r\n INTEGER: /^(0|[1-9][0-9]*|-[1-9][0-9]*)$/,\r\n // 小数,包含正小数和负小数\r\n DECIMAL: /^([-+])?\\d+\\.\\d+$/,\r\n // 正整数或者保留两位小数\r\n INT_OR_FLOAT: /(^[1-9][0-9]*$)|(^[1-9][0-9]*\\.[0-9]{1,2}$)|(^0\\.[0-9]{1,2}$)|(^0$)/,\r\n // 手机号码,支持+86\r\n MOBILE: /^(?:(?:\\+|00)86)?1[1-9]\\d{9}$/,\r\n // 固定电话号码,比如:0755-1111111\r\n PHONE: /^(?:(?:\\d{3}-)?\\d{8}|^(?:\\d{4}-)?\\d{7,8})(?:-\\d+)?$/,\r\n // 邮箱\r\n EMAIL: /^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$/,\r\n // 一代15位或二代18位身份证\r\n ID_CARD:\r\n /(^\\d{8}(0\\d|10|11|12)([0-2]\\d|30|31)\\d{3}$)|(^\\d{6}(18|19|20)\\d{2}(0[1-9]|10|11|12)([0-2]\\d|30|31)\\d{3}(\\d|X|x)$)/,\r\n // 仅校验一代15位身份证\r\n ID_CARD15: /(^\\d{8}(0\\d|10|11|12)([0-2]\\d|30|31)\\d{3}$)/,\r\n // 仅校验二代18位身份证\r\n ID_CARD18: /(^\\d{6}(18|19|20)\\d{2}(0[1-9]|10|11|12)([0-2]\\d|30|31)\\d{3}(\\d|X|x)$)/,\r\n // 银行卡号\r\n BANK_CARD: /^[1-9]\\d{9,29}$/,\r\n // 邮政编码\r\n POST_CODE: /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\\d{4}$/,\r\n // url地址,可以获取到主机地址、主机名、端口号、协议、查询参数、hash等信息c\r\n URL: /^(?:(ftp|https?|ftps):\\/\\/)?((?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+(?:[a-zA-Z]{2,6})?)?(?::(\\d+))?(?:\\/([^\\?#]*))?(?:\\?([^#]*))?(?:#(.*))?$/,\r\n // ip地址\r\n IP: /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,\r\n // IPv6地址\r\n IP6: /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|::([0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}|[0-9a-fA-F]{1,4}::([0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4})$/i,\r\n // 是外链,http,https,mail,tel电话\r\n EXTERNAL: /^(http:|https:|ftp:|ftps:|mailto:|tel:)/i,\r\n} as const;\r\n","/**\r\n * 日期相关的多语言常量配置(全局只读)\r\n *\r\n * AM_PM: 上午/下午多语言配置\r\n * - zh: { AM: \"上午\", PM: \"下午\" }\r\n * - en: { AM: \"AM\", PM: \"PM\" }\r\n *\r\n * WEEK: 星期多语言配置\r\n * - zh.FULL: [\"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\"]\r\n * - zh.SHORT: [\"周日\", \"周一\", \"周二\", \"周三\", \"周四\", \"周五\", \"周六\"]\r\n * - zh.MINI: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"]\r\n * - en.FULL: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\r\n * - en.SHORT: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"]\r\n * - en.MINI: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\r\n *\r\n * MONTH: 月份多语言配置\r\n * - zh.FULL: [\"一月\", \"二月\", \"三月\", \"四月\", \"五月\", \"六月\", \"七月\", \"八月\", \"九月\", \"十月\", \"十一月\", \"十二月\"]\r\n * - zh.SHORT: [\"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"七\", \"八\", \"九\", \"十\", \"十一\", \"十二\"]\r\n * - en.FULL: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"]\r\n * - en.SHORT: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\r\n *\r\n * QUARTER: 季度多语言配置\r\n * - zh.FULL: [\"第一季度\", \"第二季度\", \"第三季度\", \"第四季度\"]\r\n * - zh.SHORT: [\"一季度\", \"二季度\", \"三季度\", \"四季度\"]\r\n * - zh.MINI: [\"一\", \"二\", \"三\", \"四\"]\r\n * - en.FULL: [\"quarter 1st\", \"quarter 2nd\", \"quarter 3rd\", \"quarter 4th\"]\r\n * - en.SHORT: [\"Q1th\", \"Q2nd\", \"Q3rd\", \"Q4th\"]\r\n * - en.MINI: [\"Q1\", \"Q2\", \"Q3\", \"Q4\"]\r\n *\r\n * OVER_TIME: 剩余时间单位多语言配置\r\n * - zh: { YEAR: \"年\", MONTH: \"月\", DATE: \"日\", HOUR: \"时\", MINUTE: \"分\", SECOND: \"秒\", MILLISECOND: \"毫秒\", DAY: \"天\", QUARTER: \"季度\" }\r\n * - en: { YEAR: \"year\", MONTH: \"month\", DATE: \"date\", HOUR: \"hour\", MINUTE: \"minute\", SECOND: \"second\", MILLISECOND: \"millisecond\", DAY: \"day\", QUARTER: \"quarter\" }\r\n *\r\n * PASS_TIME: 过去时间描述多语言配置\r\n * - zh: { YEAR: \"年前\", MONTH: \"个月前\", DAY: \"天前\", BEFORE_YESTERDAY: \"前天\", YESTERDAY: \"昨天\", TODAY: \"今天\", HOUR: \"小时前\", MINUTE: \"分钟前\", JUST: \"刚刚\" }\r\n * - en: { YEAR: \" year ago\", MONTH: \" month ago\", DAY: \" day ago\", BEFORE_YESTERDAY: \"before yesterday\", YESTERDAY: \" yesterday\", TODAY: \" today\", HOUR: \" hour ago\", MINUTE: \" minute ago\", JUST: \" just\" }\r\n *\r\n * HOLIDAY: 节假日多语言配置\r\n * - zh: [\"元旦\", \"春节\", \"清明节\", \"劳动节\", \"端午节\", \"中秋节\", \"国庆节\"]\r\n * - en: [\"New Year‘s Day\", \"Spring Festival\", \"Tomb Sweeping Day\", \"Labor Day\", \"Dragon Boat Festival\", \"Mid-Autumn Day\", \"National Day\"]\r\n *\r\n * ZODIAC: 星座多语言配置\r\n * - zh: [\"摩羯座\", \"水瓶座\", \"双鱼座\", \"白羊座\", \"金牛座\", \"双子座\", \"巨蟹座\", \"狮子座\", \"处女座\", \"天秤座\", \"天蝎座\", \"射手座\"]\r\n * - en: [\"Capricorn\", \"Aquarius\", \"Pisces\", \"Aries\", \"Taurus\", \"Gemini\", \"Cancer\", \"Leo\", \"Virgo\", \"Libra\", \"Scorpio\", \"Sagittarius\"]\r\n *\r\n * CHINESE_ZODIAC: 生肖多语言配置\r\n * - zh: [\"鼠\", \"牛\", \"虎\", \"兔\", \"龙\", \"蛇\", \"马\", \"羊\", \"猴\", \"鸡\", \"狗\", \"猪\"]\r\n * - en: [\"Rat\", \"Ox\", \"Tiger\", \"Rabbit\", \"Dragon\", \"Snake\", \"Horse\", \"Goat\", \"Monkey\", \"Rooster\", \"Dog\", \"Pig\"]\r\n *\r\n * HEAVENLY_STEMS: 天干多语言配置\r\n * - zh: [\"甲\", \"乙\", \"丙\", \"丁\", \"戊\", \"己\", \"庚\", \"辛\", \"壬\", \"癸\"]\r\n * - en: [\"Jia\", \"Yi\", \"Bing\", \"Ding\", \"Wu\", \"Ji\", \"Geng\", \"Xin\", \"Ren\", \"Gui\"]\r\n *\r\n * EARTHLY_BRANCHES: 地支多语言配置\r\n * - zh: [\"子\", \"丑\", \"寅\", \"卯\", \"辰\", \"巳\", \"午\", \"未\", \"申\", \"酉\", \"戌\", \"亥\"]\r\n * - en: [\"Zi\", \"Chou\", \"Yin\", \"Mao\", \"Chen\", \"Si\", \"Wu\", \"Wei\", \"Shen\", \"You\", \"Xu\", \"Hai\"]\r\n */\r\nexport const DATE: Record<string, any> = {\r\n // 上午和下午\r\n AM_PM: {\r\n zh: {\r\n AM: \"上午\",\r\n PM: \"下午\",\r\n },\r\n en: {\r\n AM: \"AM\",\r\n PM: \"PM\",\r\n },\r\n },\r\n // 周\r\n WEEK: {\r\n zh: {\r\n FULL: [\"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\"],\r\n SHORT: [\"周日\", \"周一\", \"周二\", \"周三\", \"周四\", \"周五\", \"周六\"],\r\n MINI: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"],\r\n },\r\n en: {\r\n FULL: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\r\n SHORT: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\r\n MINI: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"],\r\n },\r\n },\r\n // 月\r\n MONTH: {\r\n zh: {\r\n FULL: [\"一月\", \"二月\", \"三月\", \"四月\", \"五月\", \"六月\", \"七月\", \"八月\", \"九月\", \"十月\", \"十一月\", \"十二月\"],\r\n SHORT: [\"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"七\", \"八\", \"九\", \"十\", \"十一\", \"十二\"],\r\n },\r\n en: {\r\n FULL: [\r\n \"January\",\r\n \"February\",\r\n \"March\",\r\n \"April\",\r\n \"May\",\r\n \"June\",\r\n \"July\",\r\n \"August\",\r\n \"September\",\r\n \"October\",\r\n \"November\",\r\n \"December\",\r\n ],\r\n SHORT: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"],\r\n },\r\n },\r\n // 季度\r\n QUARTER: {\r\n zh: {\r\n FULL: [\"第一季度\", \"第二季度\", \"第三季度\", \"第四季度\"],\r\n SHORT: [\"一季度\", \"二季度\", \"三季度\", \"四季度\"],\r\n MINI: [\"一\", \"二\", \"三\", \"四\"],\r\n },\r\n en: {\r\n FULL: [\"quarter 1st\", \"quarter 2nd\", \"quarter 3rd\", \"quarter 4th\"],\r\n SHORT: [\"Q1th\", \"Q2nd\", \"Q3rd\", \"Q4th\"],\r\n MINI: [\"Q1\", \"Q2\", \"Q3\", \"Q4\"],\r\n },\r\n },\r\n // 已过日期类型\r\n OVER_TIME: {\r\n zh: {\r\n YEAR: \"年\",\r\n MONTH: \"月\",\r\n DATE: \"日\",\r\n HOUR: \"时\",\r\n MINUTE: \"分\",\r\n SECOND: \"秒\",\r\n MILLISECOND: \"毫秒\",\r\n DAY: \"天\",\r\n QUARTER: \"季度\",\r\n },\r\n en: {\r\n YEAR: \"year\",\r\n MONTH: \"month\",\r\n DATE: \"date\",\r\n HOUR: \"hour\",\r\n MINUTE: \"minute\",\r\n SECOND: \"second\",\r\n MILLISECOND: \"millisecond\",\r\n DAY: \"day\",\r\n QUARTER: \"quarter\",\r\n },\r\n },\r\n // 时间节点\r\n PASS_TIME: {\r\n zh: {\r\n YEAR: \"年前\",\r\n MONTH: \"个月前\",\r\n DAY: \"天前\",\r\n BEFORE_YESTERDAY: \"前天\",\r\n YESTERDAY: \"昨天\",\r\n TODAY: \"今天\",\r\n HOUR: \"小时前\",\r\n MINUTE: \"分钟前\",\r\n JUST: \"刚刚\",\r\n },\r\n en: {\r\n YEAR: \" year ago\",\r\n MONTH: \" month ago\",\r\n DAY: \" day ago\",\r\n BEFORE_YESTERDAY: \"before yesterday\",\r\n YESTERDAY: \" yesterday\",\r\n TODAY: \" today\",\r\n HOUR: \" hour ago\",\r\n MINUTE: \" minute ago\",\r\n JUST: \" just\",\r\n },\r\n },\r\n // 节假日\r\n HOLIDAY: {\r\n zh: [\"元旦\", \"春节\", \"清明节\", \"劳动节\", \"端午节\", \"中秋节\", \"国庆节\"],\r\n en: [\r\n \"New Year‘s Day\",\r\n \"Spring Festival\",\r\n \"Tomb Sweeping Day\",\r\n \"Labor Day\",\r\n \"Dragon Boat Festival\",\r\n \"Mid-Autumn Day\",\r\n \"National Day\",\r\n ],\r\n },\r\n // 星座\r\n ZODIAC: {\r\n zh: [\r\n \"摩羯座\",\r\n \"水瓶座\",\r\n \"双鱼座\",\r\n \"白羊座\",\r\n \"金牛座\",\r\n \"双子座\",\r\n \"巨蟹座\",\r\n \"狮子座\",\r\n \"处女座\",\r\n \"天秤座\",\r\n \"天蝎座\",\r\n \"射手座\",\r\n ],\r\n en: [\r\n \"Capricorn\",\r\n \"Aquarius\",\r\n \"Pisces\",\r\n \"Aries\",\r\n \"Taurus\",\r\n \"Gemini\",\r\n \"Cancer\",\r\n \"Leo\",\r\n \"Virgo\",\r\n \"Libra\",\r\n \"Scorpio\",\r\n \"Sagittarius\",\r\n ],\r\n },\r\n // 生肖\r\n CHINESE_ZODIAC: {\r\n zh: [\"鼠\", \"牛\", \"虎\", \"兔\", \"龙\", \"蛇\", \"马\", \"羊\", \"猴\", \"鸡\", \"狗\", \"猪\"],\r\n en: [\"Rat\", \"Ox\", \"Tiger\", \"Rabbit\", \"Dragon\", \"Snake\", \"Horse\", \"Goat\", \"Monkey\", \"Rooster\", \"Dog\", \"Pig\"],\r\n },\r\n // 天干地支\r\n HEAVENLY_STEMS: {\r\n zh: [\"甲\", \"乙\", \"丙\", \"丁\", \"戊\", \"己\", \"庚\", \"辛\", \"壬\", \"癸\"],\r\n en: [\"Jia\", \"Yi\", \"Bing\", \"Ding\", \"Wu\", \"Ji\", \"Geng\", \"Xin\", \"Ren\", \"Gui\"],\r\n },\r\n EARTHLY_BRANCHES: {\r\n zh: [\"子\", \"丑\", \"寅\", \"卯\", \"辰\", \"巳\", \"午\", \"未\", \"申\", \"酉\", \"戌\", \"亥\"],\r\n en: [\"Zi\", \"Chou\", \"Yin\", \"Mao\", \"Chen\", \"Si\", \"Wu\", \"Wei\", \"Shen\", \"You\", \"Xu\", \"Hai\"],\r\n },\r\n} as const;\r\n","/**\r\n * 键盘码相关常量配置(全局只读)\r\n *\r\n * 字符键:\r\n * - 8: Backspace\r\n * - 9: Tab\r\n * - 13: Enter\r\n * - 16: Shift\r\n * - 17: Ctrl\r\n * - 18: Alt\r\n * - 19: Pause\r\n * - 20: Caps Lock\r\n * - 27: Escape\r\n * - 32: Space\r\n * - 33: Page Up\r\n * - 34: Page Down\r\n * - 35: End\r\n * - 36: Home\r\n * - 37: Left\r\n * - 38: Up\r\n * - 39: Right\r\n * - 40: Down\r\n * - 42: Print Screen\r\n * - 45: Insert\r\n * - 46: Delete\r\n *\r\n * 数字键:\r\n * - 48: 0\r\n * - 49: 1\r\n * - 50: 2\r\n * - 51: 3\r\n * - 52: 4\r\n * - 53: 5\r\n * - 54: 6\r\n * - 55: 7\r\n * - 56: 8\r\n * - 57: 9\r\n *\r\n * 字母键:\r\n * - 65: A\r\n * - 66: B\r\n * - 67: C\r\n * - 68: D\r\n * - 69: E\r\n * - 70: F\r\n * - 71: G\r\n * - 72: H\r\n * - 73: I\r\n * - 74: J\r\n * - 75: K\r\n * - 76: L\r\n * - 77: M\r\n * - 78: N\r\n * - 79: O\r\n * - 80: P\r\n * - 81: Q\r\n * - 82: R\r\n * - 83: S\r\n * - 84: T\r\n * - 85: U\r\n * - 86: V\r\n * - 87: W\r\n * - 88: X\r\n * - 89: Y\r\n * - 90: Z\r\n *\r\n * window 相关键:\r\n * - 91: Windows\r\n * - 93: Right Click\r\n *\r\n * 数字小键盘(Numpad):\r\n * - 96: Numpad 0\r\n * - 97: Numpad 1\r\n * - 98: Numpad 2\r\n * - 99: Numpad 3\r\n * - 100: Numpad 4\r\n * - 101: Numpad 5\r\n * - 102: Numpad 6\r\n * - 103: Numpad 7\r\n * - 104: Numpad 8\r\n * - 105: Numpad 9\r\n * - 106: Numpad *\r\n * - 107: Numpad +\r\n * - 109: Numpad -\r\n * - 110: Numpad .\r\n * - 111: Numpad /\r\n *\r\n * F功能键:\r\n * - 112: F1\r\n * - 113: F2\r\n * - 114: F3\r\n * - 115: F4\r\n * - 116: F5\r\n * - 117: F6\r\n * - 118: F7\r\n * - 119: F8\r\n * - 120: F9\r\n * - 121: F10\r\n * - 122: F11\r\n * - 123: F12\r\n *\r\n * 特殊符号/功能键:\r\n * - 144: Num Lock\r\n * - 145: Scroll Lock\r\n * - 182: My Computer\r\n * - 183: My Calculator\r\n * - 186: ;\r\n * - 187: =\r\n * - 188: ,\r\n * - 189: -\r\n * - 190: .\r\n * - 191: /\r\n * - 192: `\r\n * - 219: [\r\n * - 220: \\\r\n * - 221: ]\r\n * - 222: '\r\n */\r\nexport const KEYCODE: Record<string, string> = {\r\n // 字符键\r\n 8: \"Backspace\",\r\n 9: \"Tab\",\r\n 13: \"Enter\",\r\n 16: \"Shift\",\r\n 17: \"Ctrl\",\r\n 18: \"Alt\",\r\n 19: \"Pause\",\r\n 20: \"Caps Lock\",\r\n 27: \"Escape\",\r\n 32: \"Space\",\r\n 33: \"Page Up\",\r\n 34: \"Page Down\",\r\n 35: \"End\",\r\n 36: \"Home\",\r\n 37: \"Left\",\r\n 38: \"Up\",\r\n 39: \"Right\",\r\n 40: \"Down\",\r\n 42: \"Print Screen\",\r\n 45: \"Insert\",\r\n 46: \"Delete\",\r\n // 数字键\r\n 48: \"0\",\r\n 49: \"1\",\r\n 50: \"2\",\r\n 51: \"3\",\r\n 52: \"4\",\r\n 53: \"5\",\r\n 54: \"6\",\r\n 55: \"7\",\r\n 56: \"8\",\r\n 57: \"9\",\r\n // 字母键\r\n 65: \"A\",\r\n 66: \"B\",\r\n 67: \"C\",\r\n 68: \"D\",\r\n 69: \"E\",\r\n 70: \"F\",\r\n 71: \"G\",\r\n 72: \"H\",\r\n 73: \"I\",\r\n 74: \"J\",\r\n 75: \"K\",\r\n 76: \"L\",\r\n 77: \"M\",\r\n 78: \"N\",\r\n 79: \"O\",\r\n 80: \"P\",\r\n 81: \"Q\",\r\n 82: \"R\",\r\n 83: \"S\",\r\n 84: \"T\",\r\n 85: \"U\",\r\n 86: \"V\",\r\n 87: \"W\",\r\n 88: \"X\",\r\n 89: \"Y\",\r\n 90: \"Z\",\r\n // window\r\n 91: \"Windows\",\r\n 93: \"Right Click\",\r\n // Numpad\r\n 96: \"Numpad 0\",\r\n 97: \"Numpad 1\",\r\n 98: \"Numpad 2\",\r\n 99: \"Numpad 3\",\r\n 100: \"Numpad 4\",\r\n 101: \"Numpad 5\",\r\n 102: \"Numpad 6\",\r\n 103: \"Numpad 7\",\r\n 104: \"Numpad 8\",\r\n 105: \"Numpad 9\",\r\n 106: \"Numpad *\",\r\n 107: \"Numpad +\",\r\n 109: \"Numpad -\",\r\n 110: \"Numpad .\",\r\n 111: \"Numpad /\",\r\n // F功能键\r\n 112: \"F1\",\r\n 113: \"F2\",\r\n 114: \"F3\",\r\n 115: \"F4\",\r\n 116: \"F5\",\r\n 117: \"F6\",\r\n 118: \"F7\",\r\n 119: \"F8\",\r\n 120: \"F9\",\r\n 121: \"F10\",\r\n 122: \"F11\",\r\n 123: \"F12\",\r\n // 特殊符号\r\n 144: \"Num Lock\",\r\n 145: \"Scroll Lock\",\r\n 182: \"My Computer\",\r\n 183: \"My Calculator\",\r\n 186: \";\",\r\n 187: \"=\",\r\n 188: \",\",\r\n 189: \"-\",\r\n 190: \".\",\r\n 191: \"/\",\r\n 192: \"`\",\r\n 219: \"[\",\r\n 220: \"\\\\\",\r\n 221: \"]\",\r\n 222: \"'\",\r\n} as const;\r\n","/**\r\n * 身份证号相关常量配置(全局只读)\r\n *\r\n * PROVINCE: 身份证号前两位对应的省份/地区编码映射\r\n * - 11: 北京\r\n * - 12: 天津\r\n * - 13: 河北\r\n * - 14: 山西\r\n * - 15: 内蒙古\r\n * - 21: 辽宁\r\n * - 22: 吉林\r\n * - 23: 黑龙江\r\n * - 31: 上海\r\n * - 32: 江苏\r\n * - 33: 浙江\r\n * - 34: 安徽\r\n * - 35: 福建\r\n * - 36: 江西\r\n * - 37: 山东\r\n * - 41: 河南\r\n * - 42: 湖北\r\n * - 43: 湖南\r\n * - 44: 广东\r\n * - 45: 广西\r\n * - 46: 海南\r\n * - 50: 重庆\r\n * - 51: 四川\r\n * - 52: 贵州\r\n * - 53: 云南\r\n * - 54: 西藏\r\n * - 61: 陕西\r\n * - 62: 甘肃\r\n * - 63: 青海\r\n * - 64: 宁夏\r\n * - 65: 新疆\r\n * - 71: 台湾\r\n * - 81: 香港\r\n * - 82: 澳门\r\n * - 91: 国外\r\n *\r\n * SEX: 身份证号解析的性别映射\r\n * - MAN: 男\r\n * - WOMAN: 女\r\n */\r\nexport const ID_CARD: Record<string, any> = {\r\n // 身份证号对应的省\r\n PROVINCE: {\r\n 11: \"北京\",\r\n 12: \"天津\",\r\n 13: \"河北\",\r\n 14: \"山西\",\r\n 15: \"内蒙古\",\r\n 21: \"辽宁\",\r\n 22: \"吉林\",\r\n 23: \"黑龙江\",\r\n 31: \"上海\",\r\n 32: \"江苏\",\r\n 33: \"浙江\",\r\n 34: \"安徽\",\r\n 35: \"福建\",\r\n 36: \"江西\",\r\n 37: \"山东\",\r\n 41: \"河南\",\r\n 42: \"湖北\",\r\n 43: \"湖南\",\r\n 44: \"广东\",\r\n 45: \"广西\",\r\n 46: \"海南\",\r\n 50: \"重庆\",\r\n 51: \"四川\",\r\n 52: \"贵州\",\r\n 53: \"云南\",\r\n 54: \"西藏\",\r\n 61: \"陕西\",\r\n 62: \"甘肃\",\r\n 63: \"青海\",\r\n 64: \"宁夏\",\r\n 65: \"新疆\",\r\n 71: \"台湾\",\r\n 81: \"香港\",\r\n 82: \"澳门\",\r\n 91: \"国外\",\r\n },\r\n // 性别\r\n SEX: {\r\n MAN: \"男\",\r\n WOMAN: \"女\",\r\n },\r\n} as const;\r\n","/**\r\n * @module 校验\r\n */\r\n\r\n/**\r\n * 判断是整数\r\n * @param {*} value 参数\r\n * @returns {boolean} result 返回结果\r\n */\r\nexport function isInteger(value: any): boolean {\r\n return Number.isInteger(value);\r\n}\r\n\r\n/**\r\n * 判断是小数\r\n * @param {*} value 参数\r\n * @returns {boolean} result 返回结果\r\n */\r\nexport function isDecimal(value: any): boolean {\r\n return /^\\d+\\.\\d+$/.test(value);\r\n}\r\n\r\n/**\r\n * 判断类型是数字 Number\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNumber(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Number\";\r\n}\r\n\r\n/**\r\n * 判断类型是字符串 String\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isString(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"String\";\r\n}\r\n\r\n/**\r\n * 判断类型是数组 Array\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isArray(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Array\";\r\n}\r\n\r\n/**\r\n * 判断类型是对象 Object\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isObject(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Object\";\r\n}\r\n\r\n/**\r\n * 判断类型是布尔 boolean\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBoolean(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"boolean\";\r\n}\r\n\r\n/**\r\n * 判断类型是日期 Date\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isDate(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Date\";\r\n}\r\n\r\n/**\r\n * 判断类型是函数 Function\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFunction(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Function\";\r\n}\r\n\r\n/**\r\n * 判断类型是函数字符串 FunctionString\r\n * @description 支持普通函数,异步函数,箭头函数\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFunctionString(value: any): boolean {\r\n if (value) {\r\n try {\r\n const fn = new Function(`return ${value}`)();\r\n return typeof fn === \"function\";\r\n } catch (e) {\r\n // 如果发生错误,比如语法错误,那么这不是一个有效的函数\r\n return false;\r\n }\r\n } else {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * 判断类型是异步函数 AsyncFunction\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isAsyncFunction(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"AsyncFunction\";\r\n}\r\n\r\n/**\r\n * 判断类型是 Symbol\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSymbol(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Symbol\";\r\n}\r\n\r\n/**\r\n * 判断类型是正则 RegExp\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isRegExp(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"RegExp\";\r\n}\r\n\r\n/**\r\n * 判断类型是错误 Error\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isError(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Error\";\r\n}\r\n\r\n/**\r\n * 判断类型是 Promise\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isPromise(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Promise\";\r\n}\r\n\r\n/**\r\n *判断类型是 Map\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isMap(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Map\";\r\n}\r\n\r\n/**\r\n * 判断类型是 WeakMap\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isWeakMap(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"WeakMap\";\r\n}\r\n\r\n/**\r\n * 判断类型是 Set\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSet(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Set\";\r\n}\r\n\r\n/**\r\n * 判断类型是 WeakSet\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isWeakSet(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"WeakSet\";\r\n}\r\n\r\n/**\r\n * 判断类型是 BigInt\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBigInt(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"BigInt\";\r\n}\r\n\r\n/**\r\n * 判断类型是 Json\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isJson(value: any): boolean {\r\n try {\r\n JSON.parse(value);\r\n return true;\r\n } catch (error) {\r\n return false;\r\n }\r\n}\r\n\r\n/* 数据值校验 */\r\n/**\r\n * 判断值为真\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isTrue(value: any): boolean {\r\n return !isFalse(value);\r\n}\r\n\r\n/**\r\n * 判断值为假\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFalse(value: any): boolean {\r\n return (\r\n value === undefined ||\r\n value === null ||\r\n value === \"undefined\" ||\r\n value === \"null\" ||\r\n value === 0 ||\r\n value === false ||\r\n isNaN(value)\r\n );\r\n}\r\n\r\n/**\r\n * 判断非数字\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNaN(value: any): boolean {\r\n return (\r\n value == null || // 匹配 null/undefined\r\n typeof value === \"boolean\" || // 布尔值视为非数字\r\n Array.isArray(value) || // 数组视为非数字\r\n value === \"\" || // 空字符串视为非数字\r\n (window && window.isNaN(Number(value))) // 原生isNaN判断(转数字后是否为NaN)\r\n );\r\n}\r\n\r\n/**\r\n * 判断是数字\r\n * @description 等同于isNumber()\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotNaN(value: any): boolean {\r\n return !isNaN(value);\r\n}\r\n\r\n/**\r\n * 判断对象为空\r\n * @description 判断值是否为空,如果对象初始化了值则不为空\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNull(value: any): boolean {\r\n return value === undefined || value === null || value === \"\";\r\n}\r\n\r\n/**\r\n * 判断对象不为空\r\n * @description 判断值是否为空,如果对象初始化了值则不为空\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotNull(value: any): boolean {\r\n return !isNull(value);\r\n}\r\n\r\n/**\r\n * 判断值为空\r\n * @description 判断是否是有意义不为空的值,如果值是{},[]空的数据则为空\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isEmpty(value: any): boolean {\r\n if (isNull(value)) return true;\r\n if (typeof value === \"string\" || Array.isArray(value)) {\r\n return value.length === 0;\r\n }\r\n if (typeof value === \"object\") {\r\n if (value instanceof Map || value instanceof Set) {\r\n return value.size === 0;\r\n }\r\n if (value instanceof Date || value instanceof RegExp || value instanceof Error) {\r\n return false;\r\n }\r\n return Object.keys(value).length === 0;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * 判断值不为空\r\n * @description 判断是否是有意义不为空的值,如果值是{},[]空的数据则为空\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotEmpty(value: any): boolean {\r\n return !isEmpty(value);\r\n}\r\n\r\n/**\r\n * 判断值是空白的\r\n * @description 同时会校验空值,空对象,以及空白符号\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBlank(value: any): boolean {\r\n return isEmpty(value) || /^\\s*$/.test(value);\r\n}\r\n\r\n/**\r\n * 判断值不是空白的\r\n * @description 同时会校验空值,空对象,以及空白符号\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotBlank(value: any): boolean {\r\n return !isBlank(value);\r\n}\r\n\r\n/**\r\n * 判断值是undefined\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isUndefined(value: any): boolean {\r\n return value === undefined;\r\n}\r\n\r\n/**\r\n * 判断值不是undefined\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotUndefined(value: any): boolean {\r\n return !isUndefined(value);\r\n}\r\n\r\n/* 数据比较 */\r\n/**\r\n * 判断两个值是否相等\r\n * @param {*} value1 参数1\r\n * @param {*} value2 参数2\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function equals(value1: any, value2: any): boolean {\r\n return Object.is(value1, value2);\r\n}\r\n\r\n/**\r\n * 判断两个值是否相等(忽略大小写)\r\n * @param {*} value1 参数1\r\n * @param {*} value2 参数2\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function equalsIgnoreCase(value1: any, value2: any): boolean {\r\n return Object.is(value1.toLowerCase(), value2.toLowerCase());\r\n}\r\n\r\n/**\r\n * 深度对比数据\r\n * @description 可以对比任意数据,对象、数组、日期等也可深度对比,对象不区分先后顺序\r\n * @param {*} x 数据1\r\n * @param {*} args 数据2\r\n * @returns {boolean} 返回对比结果\r\n */\r\nexport function deepCompare(x: any, ...args: any[]): boolean {\r\n let leftChain: any[] = [];\r\n let rightChain: any[] = [];\r\n\r\n // 核心对比函数(添加严格类型标注)\r\n const compare2Objects = (xObj: any, yObj: any): boolean => {\r\n // 1. 处理 NaN 特殊场景(NaN === NaN 返回 false,需单独判断)\r\n if (Number.isNaN(xObj) && Number.isNaN(yObj)) {\r\n return true;\r\n }\r\n\r\n // 2. 原始类型/引用同一对象 直接对比\r\n if (xObj === yObj) {\r\n return true;\r\n }\r\n\r\n // 3. 特殊内置对象对比(函数/日期/正则/包装对象)\r\n const typeOfX = typeof xObj;\r\n const typeOfY = typeof yObj;\r\n\r\n // 函数对比:通过 toString 比较内容\r\n if (typeOfX === \"function\" && typeOfY === \"function\") {\r\n return xObj.toString() === yObj.toString();\r\n }\r\n\r\n // 日期对象对比:时间戳一致则相等\r\n if (xObj instanceof Date && yObj instanceof Date) {\r\n return xObj.getTime() === yObj.getTime();\r\n }\r\n\r\n // 正则对象对比:源文本+标志位一致则相等\r\n if (xObj instanceof RegExp && yObj instanceof RegExp) {\r\n return xObj.source === yObj.source && xObj.flags === yObj.flags;\r\n }\r\n\r\n // 字符串/数字包装对象对比\r\n if ((xObj instanceof String && yObj instanceof String) || (xObj instanceof Number && yObj instanceof Number)) {\r\n return xObj.toString() === yObj.toString();\r\n }\r\n\r\n // 4. 非对象类型(排除上述特殊类型后)直接返回 false\r\n if (!(xObj instanceof Object && yObj instanceof Object)) {\r\n return false;\r\n }\r\n\r\n // 5. 原型链/构造函数校验\r\n if (xObj.isPrototypeOf(yObj) || yObj.isPrototypeOf(xObj)) {\r\n return false;\r\n }\r\n if ((xObj as object).constructor !== (yObj as object).constructor) {\r\n return false;\r\n }\r\n if ((xObj as { prototype?: unknown }).prototype !== (yObj as { prototype?: unknown }).prototype) {\r\n return false;\r\n }\r\n\r\n // 6. 循环引用检测(避免无限递归)\r\n if (leftChain.includes(xObj) || rightChain.includes(yObj)) {\r\n return false;\r\n }\r\n\r\n // 7. 遍历对象属性,对比键存在性和类型\r\n const xObjKeys = Object.keys(xObj as object);\r\n const yObjKeys = Object.keys(yObj as object);\r\n\r\n // 先对比属性数量(数量不同直接不相等)\r\n if (xObjKeys.length !== yObjKeys.length) {\r\n return false;\r\n }\r\n\r\n // 遍历所有属性,校验存在性、类型、值\r\n for (const p of yObjKeys) {\r\n if (Object.prototype.hasOwnProperty.call(xObj, p) !== Object.prototype.hasOwnProperty.call(yObj, p)) {\r\n return false;\r\n }\r\n const xProp = (xObj as Record<string, unknown>)[p];\r\n const yProp = (yObj as Record<string, unknown>)[p];\r\n if (typeof xProp !== typeof yProp) {\r\n return false;\r\n }\r\n }\r\n\r\n // 深度对比属性值\r\n for (const p of xObjKeys) {\r\n const xProp = (xObj as Record<string, unknown>)[p];\r\n const yProp = (yObj as Record<string, unknown>)[p];\r\n\r\n if (typeof xProp === \"object\" || typeof xProp === \"function\") {\r\n leftChain.push(xObj);\r\n rightChain.push(yObj);\r\n if (!compare2Objects(xProp, yProp)) {\r\n return false;\r\n }\r\n leftChain.pop();\r\n rightChain.pop();\r\n } else {\r\n if (xProp !== yProp) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n };\r\n\r\n // 边界处理:参数数量不足时的兜底\r\n if (arguments.length < 2) {\r\n console.warn(\"deepCompare 需要至少两个对比参数\");\r\n return true;\r\n }\r\n\r\n // 遍历所有传入的参数(支持对比多个值)\r\n for (const y of args) {\r\n leftChain = [];\r\n rightChain = [];\r\n if (!compare2Objects(x, y)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n","/**\r\n * @module 字符串\r\n */\r\n/* 字符串处理 */\r\nimport { isNull, isNaN } from \"@/validate\";\r\n\r\n/**\r\n * 字符串中是否包含指定的元素\r\n * @param {string} value 包含的元素\r\n * @param {string} str 查找的字符串\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function inString(value: string, str: string): boolean {\r\n return str.includes(value);\r\n}\r\n\r\n/**\r\n * 去除字符串前后位置空格\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function trim(value: string): string {\r\n return value.replace(/(^\\s*)|(\\s*$)/g, \"\");\r\n}\r\n\r\n/**\r\n * 去除字符串开始位置的空格\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function trimStart(value: string): string {\r\n return value.replace(/(^\\s*)/g, \"\");\r\n}\r\n\r\n/**\r\n * 去除字符串结束位置的空格\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function trimEnd(value: string): string {\r\n return value.replace(/(\\s*$)/g, \"\");\r\n}\r\n\r\n/**\r\n * 去除字符串中全部的空格\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function trimAll(value: string): string {\r\n return value.replace(/\\s+/g, \"\");\r\n}\r\n\r\n/**\r\n * 替换所有指定字符串为新的字符串\r\n * @param {string} value 参数\r\n * @param {string} oldSubstr 需要替换的字符串\r\n * @param {string} newSubstr 替换后的字符串\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function replaceAll(value: string, oldSubstr: string, newSubstr: string): string {\r\n return value.replace(new RegExp(oldSubstr, \"gm\"), newSubstr);\r\n}\r\n\r\n/* 字符串转换 */\r\n/**\r\n * 字符串转大写\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toUpperCase(value: string): string {\r\n return String(value).toLocaleUpperCase();\r\n}\r\n\r\n/**\r\n * 字符串转小写\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toLowerCase(value: string): string {\r\n return String(value).toLocaleLowerCase();\r\n}\r\n\r\n/**\r\n * 转为 snake_case 下划线命名\r\n * @description 支持 驼峰命名,短横命名,帕斯卡命名\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toSnakeCase(value: string): string {\r\n // 驼峰\r\n if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n return value.replace(/([A-Z])/g, \"_$1\").toLowerCase();\r\n }\r\n // 短横\r\n else if (value.indexOf(\"-\") > 0) {\r\n return value.replace(/-/g, \"_\").toLowerCase();\r\n }\r\n // 帕斯卡\r\n else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n value = value.charAt(0).toLowerCase() + value.slice(1);\r\n return value.replace(/([A-Z])/g, \"_$1\").toLowerCase();\r\n }\r\n // 不符合格式\r\n else {\r\n throw new TypeError(`toSnakeCase: value should be a string`);\r\n }\r\n}\r\n\r\n/**\r\n * 转为 kebab-case 短横命名\r\n * @description 支持 下划线,驼峰命名,帕斯卡命名\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toKebabCase(value: string): string {\r\n // 下划线\r\n if (value.indexOf(\"_\") > 0) {\r\n return value.replace(/_/g, \"-\").toLowerCase();\r\n }\r\n // 驼峰\r\n else if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n return value.replace(/([A-Z])/g, \"-$1\").toLowerCase();\r\n }\r\n // 帕斯卡\r\n else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n const newStr = value.charAt(0).toLowerCase() + value.slice(1);\r\n return newStr.replace(/([A-Z])/g, \"-$1\").toLowerCase();\r\n }\r\n // 不符合格式\r\n else {\r\n throw new TypeError(\"toKebabCase: value should be a string\");\r\n }\r\n}\r\n\r\n/**\r\n * 转为 camelCase 驼峰命名\r\n * @description 支持 下划线命名,短横命名,帕斯卡命名\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toCamelCase(value: string): string {\r\n // 下划线\r\n if (value.indexOf(\"_\") > 0) {\r\n return value.replace(/\\_(\\w)/g, function (all, letter) {\r\n return letter.toUpperCase();\r\n });\r\n }\r\n // 短横\r\n else if (value.indexOf(\"-\") > 0) {\r\n return value.replace(/\\-(\\w)/g, function (all, letter) {\r\n return letter.toUpperCase();\r\n });\r\n }\r\n // 帕斯卡\r\n else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n return value.charAt(0).toLowerCase() + value.slice(1);\r\n }\r\n // 不符合格式\r\n else {\r\n throw new TypeError(\"toCamelCase: value should be a string\");\r\n }\r\n}\r\n\r\n/**\r\n * 转为 PascalCase 帕斯卡命名\r\n * @description 支持 下划线命名,短横命名,驼峰命名\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toPascalCase(value: string): string {\r\n // 下划线\r\n if (value.indexOf(\"_\") > 0) {\r\n const newStr = value.replace(/\\_(\\w)/g, function (all, letter) {\r\n return letter.toUpperCase();\r\n });\r\n return newStr.charAt(0).toUpperCase() + newStr.slice(1);\r\n }\r\n // 短横\r\n else if (value.indexOf(\"-\") > 0) {\r\n const newStr = value.replace(/\\-(\\w)/g, function (all, letter) {\r\n return letter.toUpperCase();\r\n });\r\n return newStr.charAt(0).toUpperCase() + newStr.slice(1);\r\n }\r\n // 驼峰\r\n else if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n return value.charAt(0).toUpperCase() + value.slice(1);\r\n }\r\n // 不符合格式\r\n else {\r\n throw new TypeError(\"toPascalCase: value should be a string\");\r\n }\r\n}\r\n\r\n/* 字符串格式化 */\r\n\r\n/**\r\n * 数字前补齐0达到指定位数\r\n * @description 相当于原生的 padStart(2,'0')\r\n * @param {number|string} value 补零的数字\r\n * @param {number} maxLength 补齐0后的最大长度,默认2位\r\n * @returns {string} 返回补0后指定位数的字符串\r\n */\r\nexport function padZeroStart(value: string | number, maxLength: number = 2): string {\r\n value = String(value).trim();\r\n if (maxLength < 0) {\r\n throw new TypeError(\"padZeroStart: maxLength should be greater than 0\");\r\n }\r\n if (isNull(value) || isNaN(value)) {\r\n throw new TypeError(\"padZeroStart: value must be a valid number or numeric string\");\r\n }\r\n\r\n // 前面补0\r\n let len = value.toString().length;\r\n while (len < maxLength) {\r\n value = \"0\" + value;\r\n len++;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * 数字后补齐0达到指定位数\r\n * @description 相当于原生的 padEnd(2,'0')\r\n * @param {number|string} value 补零的数字\r\n * @param {number} maxLength 补齐0后的最大长度,默认2位\r\n * @returns {string} 返回补0后指定位数的字符串\r\n */\r\nexport function padZeroEnd(value: string | number, maxLength: number = 2): string {\r\n value = String(value).trim();\r\n if (maxLength < 0) {\r\n throw new TypeError(\"padZeroEnd: maxLength should be greater than 0\");\r\n }\r\n if (isNull(value) || isNaN(value)) {\r\n throw new TypeError(\"padZeroEnd: value must be a valid number or numeric string\");\r\n }\r\n\r\n // 后面补0\r\n let len = value.toString().length;\r\n while (len < maxLength) {\r\n value = value + \"0\";\r\n len++;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * 格式化为标题样式\r\n * @param {string} value 字符串值\r\n * @returns {string} 返回格式化后的标题样式\r\n */\r\nexport function formatTitle(value: string): string {\r\n if (!value) return \"\";\r\n return value\r\n .split(/(?=[A-Z])|[\\.\\-\\s_]/)\r\n .map((s) => s.trim())\r\n .filter((s) => !!s)\r\n .map((s) => toPascalCase(s.toLowerCase()))\r\n .join(\" \");\r\n}\r\n\r\n/**\r\n * 格式化字符串模版\r\n * @param {string} value 字符串值\r\n * @param {Object} data 模版数据\r\n * @returns {string} 返回格式化后的模版字符串\r\n */\r\nexport function formatTemplate(value: string, data: Record<any, any>): string {\r\n if (!value) return \"\";\r\n return Array.from(value.matchAll(/\\{\\{(.+?)\\}\\}/g)).reduce((acc, match) => {\r\n return acc.replace(match[0], data[match[1]]);\r\n }, value);\r\n}\r\n\r\n/**\r\n * 格式化千分位数字\r\n * @description 支持任意数据传参,如果非数字则不会格式化,并返回原数据\r\n * @param {number|string} num 数字\r\n * @returns {string} 返回格式化后的千分位数字\r\n */\r\nexport function formatThousand(num: number | string): string {\r\n if (!parseFloat(String(num))) return String(num);\r\n num = String(num);\r\n const regex = num.indexOf(\".\") > -1 ? /(\\d)(?=(\\d{3})+\\.)/g : /(\\d)(?=(?:\\d{3})+$)/g;\r\n return num.replace(regex, \"$1,\");\r\n}\r\n\r\n/**\r\n * 格式化人民币金额大写\r\n * @param {number|string} money 金额\r\n * @returns {string} 返回金额大写\r\n */\r\nexport function formatRmbChinese(money: number | string): string {\r\n // 汉字的数字\r\n const cnNums = [\"零\", \"壹\", \"贰\", \"叁\", \"肆\", \"伍\", \"陆\", \"柒\", \"捌\", \"玖\"];\r\n // 基本单位\r\n const cnIntRadiance = [\"\", \"拾\", \"佰\", \"仟\"];\r\n // 对应整数部分扩展单位\r\n const cnIntUnits = [\"\", \"万\", \"亿\", \"兆\"];\r\n // 对应小数部分单位\r\n const cnDecUnits = [\"角\", \"分\", \"毫\", \"厘\"];\r\n // 整数金额时后面跟的字符\r\n const cnInteger = \"整\";\r\n // 整型完以后的单位\r\n const cnIntLast = \"元\";\r\n // 最大处理的数字\r\n const maxNum = Number(\"999999999999999.9999\");\r\n // 金额整数部分\r\n let integerNum;\r\n // 金额小数部分\r\n let decimalNum;\r\n // 输出的中文金额字符串\r\n let chineseStr = \"\";\r\n // 分离金额后用的数组,预定义\r\n let parts;\r\n if (money === \"\") {\r\n // 不能用==\r\n return \"\";\r\n }\r\n money = parseFloat(String(money));\r\n if (money >= maxNum) {\r\n // 超出最大处理数字,抛出异常\r\n throw new TypeError(\"formatRmbChinese: calculated number overflow\");\r\n }\r\n if (money === 0) {\r\n chineseStr = cnNums[0] + cnIntLast + cnInteger;\r\n return chineseStr;\r\n }\r\n // 转换为字符串\r\n money = money.toString();\r\n if (money.indexOf(\".\") === -1) {\r\n integerNum = money;\r\n decimalNum = \"\";\r\n } else {\r\n parts = money.split(\".\");\r\n integerNum = parts[0];\r\n decimalNum = parts[1].substr(0, 4);\r\n }\r\n // 获取整型部分转换\r\n if (parseInt(integerNum, 10) > 0) {\r\n let zeroCount = 0;\r\n const IntLen = integerNum.length;\r\n for (let i = 0; i < IntLen; i++) {\r\n const n = integerNum.substr(i, 1);\r\n const p = IntLen - i - 1;\r\n const q = p / 4;\r\n const m = p % 4;\r\n if (n === \"0\") {\r\n zeroCount++;\r\n } else {\r\n if (zeroCount > 0) {\r\n chineseStr += cnNums[0];\r\n }\r\n // 归零\r\n zeroCount = 0;\r\n chineseStr += cnNums[parseInt(n)] + cnIntRadiance[m];\r\n }\r\n if (m === 0 && zeroCount < 4) {\r\n chineseStr += cnIntUnits[q];\r\n }\r\n }\r\n chineseStr += cnIntLast;\r\n }\r\n // 小数部分\r\n if (decimalNum !== \"\") {\r\n const decLen = decimalNum.length;\r\n for (let i = 0; i < decLen; i++) {\r\n const n = decimalNum.substr(i, 1);\r\n if (n !== \"0\") {\r\n chineseStr += cnNums[Number(n)] + cnDecUnits[i];\r\n }\r\n }\r\n }\r\n if (chineseStr === \"\") {\r\n chineseStr += cnNums[0] + cnIntLast + cnInteger;\r\n } else if (decimalNum === \"\") {\r\n chineseStr += cnInteger;\r\n }\r\n return chineseStr;\r\n}\r\n","/**\r\n * @module 数字\r\n */\r\nimport { isNull } from \"@/validate\";\r\n\r\n/**\r\n * 转为数字类型\r\n * @description 解决部分浏览器在转换 '08','09'等是0开头时被默认转8进制问题\r\n * @param {string|number} value 转换的值\r\n * @param {number} radix 进制数,默认10进制\r\n * @returns {number} 返回转换后的数字\r\n */\r\nexport function parseInt(value: string | number, radix: number = 10): number {\r\n if (isNull(value)) {\r\n return 0;\r\n }\r\n return Number.parseInt(String(value), radix);\r\n}\r\n\r\n/**\r\n * 转为小数类型\r\n * @param {string|number} value 转换的值\r\n * @returns {number} 返回转换后的数字\r\n */\r\nexport function parseFloat(value: string | number): number {\r\n if (isNull(value)) {\r\n return 0.0;\r\n }\r\n return Number.parseFloat(String(value));\r\n}\r\n","/**\r\n * @module 数组\r\n */\r\nimport { SORT } from \"@/constants\";\r\nimport { isArray, isEmpty, isNull, isObject } from \"@/validate\";\r\n\r\n/* 数组计算 */\r\n/**\r\n * 数组最小值\r\n * @param {Array} array 数组\r\n * @returns {number} 返回最小值\r\n */\r\nexport function arrayMin(array: any[]): number {\r\n return Math.min.apply(null, array);\r\n}\r\n\r\n/**\r\n * 数组最大值\r\n * @param {array} array 数组\r\n * @returns {number} 返回最大值\r\n */\r\nexport function arrayMax(array: any[]): number {\r\n return Math.max.apply(null, array);\r\n}\r\n\r\n/**\r\n * 数组求和\r\n * @param {Array} array 数组\r\n * @returns {number} 返回和\r\n */\r\nexport function arraySum(array: any[]): number {\r\n return array.reduce(function (pre, cur) {\r\n return pre + cur;\r\n });\r\n}\r\n\r\n/**\r\n * 数组求平均值\r\n * @param {Array} array 数组\r\n * @returns {number} 返回平均数\r\n */\r\nexport function arrayAvg(array: any[]): number {\r\n return arraySum(array) / array.length;\r\n}\r\n\r\n/* 数组比较 */\r\n/**\r\n * 数组中是否包含指定的元素\r\n * @param {string|number} value 元素\r\n * @param {Array} array 查找的数组\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function inArray(value: string | number, array: any[]): boolean {\r\n if (isNull(value)) return false;\r\n return array.includes(value);\r\n}\r\n\r\n/**\r\n * 比较两个数组是否相等\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function arrayEquals(array1: any[], array2: any[]): boolean {\r\n if (array1 === array2) return true;\r\n if (array1.length !== array2.length) return false;\r\n return array1.every((v, i) => v === array2[i]);\r\n}\r\n\r\n/* 数组操作 */\r\n/**\r\n * 生成指定长度的数组\r\n * @param {number} length 长度,默认 0\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayCreate(length: number = 0): number[] {\r\n return [...Array(length).keys()];\r\n}\r\n\r\n/**\r\n * 数组指定位置添加元素\r\n * @description 如果数组为空,则在0位置添加元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @param {*} value 添加的元素\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayInsert(array: any[] = [], index: number = 0, value: any = undefined): any[] {\r\n if (index < 0) return array;\r\n\r\n if (array.length === 0) {\r\n array.push(value);\r\n } else {\r\n if (index > array.length - 1) {\r\n return array;\r\n }\r\n array.splice(index, 0, value);\r\n }\r\n\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置前面添加元素\r\n * @description 如果数组为空,则在0位置添加元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @param {*} value 添加的元素\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayInsertBefore(array: any[] = [], index: number = 0, value: any = undefined): any[] {\r\n if (index < 0) return array;\r\n\r\n if (array.length === 0) {\r\n array.push(value);\r\n } else {\r\n if (index > array.length - 1) {\r\n return array;\r\n }\r\n array.splice(index, 0, value);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置后面添加元素\r\n * @description 如果数组为空,则在0位置添加元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @param {*} value 添加的元素\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayInsertAfter(array: any[] = [], index: number = 0, value: any = undefined): any[] {\r\n if (index < 0) return array;\r\n\r\n if (array.length === 0) {\r\n array.push(value);\r\n } else {\r\n if (index > array.length - 1) {\r\n return array;\r\n }\r\n array.splice(index, 0, array.splice(index, 1, value)[0]);\r\n }\r\n\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置删除元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayRemove(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n array.splice(index, 1);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置前面删除元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayRemoveBefore(array: any[] = [], index: number = 0): any[] {\r\n if (index <= 0 || index > array.length - 1) return array;\r\n\r\n array.splice(index - 1, 1);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置后面删除元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayRemoveAfter(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n array.splice(index + 1, 1);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组置顶\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayTop(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n array.unshift(array.splice(index, 1)[0]);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组置尾\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayBottom(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n array.push(array.splice(index, 1)[0]);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组向上移动\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayUp(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n if (index > 0) {\r\n array.splice(index - 1, 0, array.splice(index, 1)[0]);\r\n } else {\r\n array.push(array.splice(index, 1)[0]);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组向下移动\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayDown(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n if (index < array.length - 1) {\r\n array.splice(index + 1, 0, array.splice(index, 1)[0]);\r\n } else {\r\n array.unshift(array.splice(index, 1)[0]);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组交换元素\r\n * @param {Array} array 数组\r\n * @param {number} sourceIndex 原索引\r\n * @param {number} targetIndex 目标索引\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arraySwap(array: any[], sourceIndex: number, targetIndex: number): any[] {\r\n if (sourceIndex < 0 || targetIndex < 0 || sourceIndex > array.length - 1 || targetIndex > array.length - 1) {\r\n return array;\r\n }\r\n\r\n [array[targetIndex], array[sourceIndex]] = [array[sourceIndex], array[targetIndex]];\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组排序\r\n * @param {Array} array 数组\r\n * @param {number} mode 排序模式,参考常量集合中 数组常量,默认是升序\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arraySort(array: any[], mode: number = SORT.ASC): any[] {\r\n return array.sort((a: any, b: any) => {\r\n switch (mode) {\r\n // 升序\r\n case SORT.ASC:\r\n return a - b;\r\n // 降序\r\n case SORT.DESC:\r\n return b - a;\r\n // 随机\r\n case SORT.RANDOM:\r\n return Math.random() - 0.5;\r\n default:\r\n return 0;\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 数组属性混合排序\r\n * @description 排序默认为asc升序\r\n * @param {Array} array 数组\r\n * @param {Array} props 排序的属性\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arraySortBy(array: any[], props: any[]): any[] {\r\n return array.sort((a, b) => {\r\n for (const item of props) {\r\n // 排序配置\r\n let prop = \"\",\r\n order = \"asc\";\r\n if (isObject(item)) {\r\n prop = item.prop;\r\n order = item.order || \"asc\";\r\n } else {\r\n prop = item;\r\n order = \"asc\";\r\n }\r\n // 排序逻辑\r\n if (a[prop] < b[prop]) {\r\n return order === \"asc\" ? -1 : 1;\r\n }\r\n if (a[prop] > b[prop]) {\r\n return order === \"asc\" ? 1 : -1;\r\n }\r\n }\r\n return 0;\r\n });\r\n}\r\n\r\n/**\r\n * 数组元素去重\r\n * @param {Array} array 数组\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayUnique(array: any[]): any[] {\r\n if (isEmpty(array)) return [];\r\n\r\n return Array.from(new Set(array));\r\n}\r\n\r\n/**\r\n * 数组打乱元素\r\n * @description 可以适用于一些抽奖人员列表打乱顺序\r\n * @param {Array} array 数组\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayShuffle(array: any[]): any[] {\r\n for (let i = 1; i < array.length; i++) {\r\n const random = Math.floor(Math.random() * (i + 1));\r\n [array[random], array[i]] = [array[i], array[random]];\r\n }\r\n return array;\r\n}\r\n\r\n/* 数组转换 */\r\n/**\r\n * 普通数组转树形结构\r\n * @description 包含id和pid属性关系的一维数组,转为children的树形结构\r\n * @param {Array} array 数组\r\n * @param {Object} setting 配置项\r\n * @returns {Array} 返回树形节点\r\n */\r\nexport function arrayToTree(\r\n array: any[],\r\n setting: { key: string; parentKey: string; childrenKey: string } = {\r\n key: \"id\",\r\n parentKey: \"pid\",\r\n childrenKey: \"children\",\r\n },\r\n): any[] {\r\n const key = setting.key,\r\n parentKey = setting.parentKey,\r\n childrenKey = setting.childrenKey;\r\n\r\n // 数组或者key是否为空\r\n if (!array || array.length === 0 || !key || key === \"\") return [];\r\n\r\n // 获得子节点方法\r\n const nodeChildren = function (node: any, childrenKey: string, newChildren?: any) {\r\n if (!node) {\r\n return null;\r\n }\r\n if (typeof newChildren !== \"undefined\") {\r\n node[childrenKey] = newChildren;\r\n }\r\n return node[childrenKey];\r\n };\r\n\r\n // 声明变量\r\n const result = [];\r\n const tempMap: any = {};\r\n for (let i = 0; i < array.length; i++) {\r\n // 如果源数据数组中有children,则需要删除掉,否则会导致和之前的children合并\r\n array[i][childrenKey] && delete array[i][childrenKey];\r\n tempMap[array[i][key]] = array[i];\r\n }\r\n for (let i = 0; i < array.length; i++) {\r\n const parent = tempMap[array[i][parentKey]];\r\n if (parent && array[i][key] !== array[i][parentKey]) {\r\n let children = nodeChildren(parent, childrenKey);\r\n\r\n if (!children) {\r\n children = nodeChildren(parent, childrenKey, []);\r\n }\r\n children.push(array[i]);\r\n } else {\r\n result.push(array[i]);\r\n }\r\n }\r\n\r\n // 返回结果\r\n return result;\r\n}\r\n\r\n/**\r\n * 树形结构转普通数组\r\n * @param {Array} nodes 树形节点\r\n * @param {Object} setting 配置项\r\n * @returns {Array} 返回普通数组\r\n */\r\nexport function treeToArray(nodes: any[], setting: { childrenKey: string } = { childrenKey: \"children\" }): any[] {\r\n const childrenKey = setting.childrenKey;\r\n const result = [];\r\n for (const node of nodes) {\r\n // 删除掉多余空的children\r\n if (node[childrenKey] && !node[childrenKey].length) {\r\n delete node[childrenKey];\r\n }\r\n result.push(node);\r\n // 继续执行\r\n if (node[childrenKey] && node[childrenKey].length) {\r\n const array = treeToArray(node[childrenKey], setting);\r\n array && result.push(...array);\r\n }\r\n }\r\n\r\n // 返回结果\r\n return result;\r\n}\r\n\r\n/* 数组求并集,交集,差集等 */\r\n/**\r\n * 数组求并集\r\n * @description 数组1 和 数组2 合并一起的元素集合\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayUnion(array1: any[], array2: any[]): any[] {\r\n return [...new Set(array1.concat(array2))];\r\n}\r\n\r\n/**\r\n * 数组求交集\r\n * @description 数组1 和 数组2 相同的元素集合\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayIntersect(array1: any[], array2: any[]): any[] {\r\n return [...new Set(array1)].filter((item) => array2.includes(item));\r\n}\r\n\r\n/**\r\n * 数组求差集\r\n * @description 数组1 中不包含 数组2 的元素集合\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayDifference(array1: any[], array2: any[]): any[] {\r\n return [...new Set(array1)].filter((item) => !array2.includes(item));\r\n}\r\n\r\n/**\r\n * 数组求补集\r\n * @description 数组1 和 数组2 不相同的元素集合\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayComplement(array1: any[], array2: any[]): any[] {\r\n return [\r\n ...[...new Set(array1)].filter((item) => !array2.includes(item)),\r\n ...[...new Set(array2)].filter((item) => !array1.includes(item)),\r\n ];\r\n}\r\n","/**\r\n * @module 对象\r\n */\r\nimport { isEmpty, isObject, isArray, isDate, isNumber, isNotNaN, isNaN } from \"@/validate\";\r\n\r\n/* 对象转换 */\r\n/**\r\n * map转object\r\n * @param {Map} map 参数\r\n * @returns {Object} 返回Object\r\n */\r\nexport function mapToObject(map: Map<any, any>): Record<any, any> {\r\n const obj = Object.create(null);\r\n for (const [k, v] of map) {\r\n obj[k] = v;\r\n }\r\n return obj;\r\n}\r\n\r\n/**\r\n * map转json字符串\r\n * @param {Map} map 参数\r\n * @returns {string} 返回Json字符串\r\n */\r\nexport function mapToJson(map: Map<any, any>): string {\r\n return JSON.stringify(mapToObject(map));\r\n}\r\n\r\n/**\r\n * object转map\r\n * @param {Object} obj 参数\r\n * @returns {Map} 返回Map\r\n */\r\nexport function objectToMap(obj: Record<any, any>): Map<any, any> {\r\n const map = new Map();\r\n for (const k of Object.keys(obj)) {\r\n map.set(k, obj[k]);\r\n }\r\n return map;\r\n}\r\n\r\n/**\r\n * json字符串转map\r\n * @param {string} json json字符串\r\n * @returns {Map} 返回Map\r\n */\r\nexport function jsonToMap(json: string): Map<any, any> {\r\n return objectToMap(JSON.parse(json));\r\n}\r\n\r\n/**\r\n * json对象转json字符串\r\n * @param {Object} json json对象\r\n * @param {boolean} replacer 是否处理循环引用\r\n * @returns {string} 返回Json字符串\r\n */\r\nexport function stringifyJson(json: Record<any, any>, replacer: boolean = false): string {\r\n try {\r\n return JSON.stringify(\r\n json,\r\n replacer\r\n ? (key: string, value: any) => {\r\n if (typeof value === \"function\" || typeof value === \"symbol\") {\r\n return String(value);\r\n }\r\n return value;\r\n }\r\n : undefined,\r\n );\r\n } catch (error) {\r\n console.error(\"JSON序列化失败:\", error);\r\n return \"{}\"; // 兜底返回空对象\r\n }\r\n}\r\n\r\n/**\r\n * json字符串转json对象\r\n * @param {string} json json字符串\r\n * @returns {Object} 返回Json对象\r\n */\r\nexport function parseJson(json: string): Record<any, any> | null {\r\n if (isEmpty(json)) return null;\r\n try {\r\n return JSON.parse(json);\r\n } catch (e) {\r\n console.error(e);\r\n return null;\r\n }\r\n}\r\n\r\n/* 数据拷贝,对比,合并等操作 */\r\n/**\r\n * 浅拷贝数据\r\n * @param {*} source 拷贝的数据\r\n * @returns {*} 返回浅拷贝的数据\r\n */\r\nexport function clone(source: any): any {\r\n // 边界处理:null/undefined/原始类型(直接返回,无需拷贝)\r\n if (source === null || typeof source !== \"object\") {\r\n return source;\r\n }\r\n\r\n // 处理数组(用扩展运算符实现浅拷贝,避免Object.assign的索引问题)\r\n if (Array.isArray(source)) {\r\n return [...source];\r\n }\r\n\r\n // 处理普通对象(真正创建新对象,原代码Object.assign(source)等于没拷贝)\r\n if (source.constructor === Object) {\r\n return Object.assign({}, source);\r\n }\r\n\r\n // 处理特殊内置对象(Date/RegExp)\r\n if (source instanceof Date) {\r\n return new Date(source.getTime());\r\n }\r\n if (source instanceof RegExp) {\r\n return new RegExp(source.source, source.flags);\r\n }\r\n\r\n // 其他不可浅拷贝的对象(函数/类实例/Map/Set等,直接返回原对象)\r\n return source;\r\n}\r\n\r\n/**\r\n * 深拷贝数据\r\n * @param {*} source 拷贝的数据\r\n * @returns {*} 返回深拷贝的数据\r\n */\r\nexport function deepClone(source: any): any {\r\n // Object\r\n if (isObject(source)) {\r\n const copy: Record<string, any> = {};\r\n for (const attr in source) {\r\n if (source.hasOwnProperty(attr)) {\r\n copy[attr] = deepClone(source[attr]);\r\n }\r\n }\r\n return copy;\r\n }\r\n\r\n // Array\r\n else if (isArray(source)) {\r\n const copy = [];\r\n for (let i = 0, len = source.length; i < len; i++) {\r\n copy[i] = deepClone(source[i]);\r\n }\r\n return copy;\r\n }\r\n\r\n // Date\r\n else if (isDate(source)) {\r\n const copy = new Date();\r\n copy.setTime(source.getTime());\r\n return copy;\r\n }\r\n\r\n // Other 返回原数据\r\n else {\r\n return source;\r\n }\r\n}\r\n\r\n/**\r\n * 比较两个对象是否相等\r\n * @description 方法只能对比简单的对象,不能包含function,另外对象的属性顺序不一致也是相等的\r\n * @param {Object} obj1 对象1\r\n * @param {Object} obj2 对象2\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function objectEquals(obj1: Record<any, any>, obj2: Record<any, any>): boolean {\r\n // 比较值相等\r\n if (obj1 === obj2) {\r\n return true;\r\n }\r\n // 比较Date\r\n if (obj1 instanceof Date && obj2 instanceof Date) {\r\n return obj1.getTime() === obj2.getTime();\r\n }\r\n // 对象比较引用\r\n if (!obj1 || !obj2 || (typeof obj1 !== \"object\" && typeof obj2 !== \"object\")) {\r\n return obj1 === obj2;\r\n }\r\n // 比较原型\r\n if (obj1.prototype !== obj2.prototype) {\r\n return false;\r\n }\r\n // 比较对象的值\r\n const keys = Object.keys(obj1);\r\n if (keys.length !== Object.keys(obj2).length) {\r\n return false;\r\n } else {\r\n return keys.every((k) => objectEquals(obj1[k], obj2[k]));\r\n }\r\n}\r\n\r\n/**\r\n * 合并对象\r\n * @param {Object} target 目标对象\r\n * @param {Object[]} source 原对象列表\r\n * @returns {Object} 返回合并后的对象\r\n */\r\nexport function merge(target: Record<any, any>, ...source: Record<any, any>[]): any {\r\n if (target == null || typeof target !== \"object\") {\r\n return target;\r\n }\r\n return Object.assign(target, ...source);\r\n}\r\n\r\n/* 根据字符串属性路径操作目标对象 */\r\n/**\r\n * 根据字符串属性路径获取目标对象的值\r\n * @example\r\n * let res = {code:200, data:{rows:[], pages:{current:1,pageSize:20}}}\r\n * this._getValueByPath(res, 'data.pages.pageSize'); // 这里会输出20\r\n * @param {Object} target 目标对象\r\n * @param {string} path 字符串属性路径\r\n * @returns {*} 返回目标对象的值\r\n */\r\nexport function getValueByPath(target: Record<any, any>, path: string = \"data\"): any {\r\n const paths = (path || \"data\").split(\".\");\r\n let current = target;\r\n for (const index in paths) {\r\n const part = paths[index];\r\n // 判断属性是取的数组\r\n const { propName, propIndex = 0, isArray } = _getTargetPathPart(paths[index]);\r\n if (isArray) {\r\n // 获取的数组下标超出实际的长度\r\n if (propIndex < 0 || propIndex >= current[propName].length) {\r\n return;\r\n }\r\n // 逐层向下找到对应属性的值\r\n current = current[propName][propIndex];\r\n }\r\n // 判断属性是取的对象属性\r\n else {\r\n // 如果属性不存在,则返回空的\r\n if (!current || !current.hasOwnProperty(part) || typeof current !== \"object\") {\r\n return;\r\n }\r\n // 逐层向下找到对应属性的值\r\n current = current[part];\r\n }\r\n }\r\n return current;\r\n}\r\n\r\n/**\r\n * 根据字符串属性路径设置目标对象的值\r\n * @example\r\n * let res = {code:200, data:{rows:[], pages:{current:1,pageSize:20}}}\r\n * this._setValueByPath(res, 'data.pages.pageSize', 30); // 打印res对象会发现pageSize的值改为了30\r\n * @param {Object} target 目标对象\r\n * @param {string} path 字符串属性路径\r\n * @param {*} value 值\r\n * @returns {*} 返回修改过后的目标对象\r\n */\r\nexport function setValueByPath(target: Record<any, any>, path: string = \"data\", value: any): Record<any, any> {\r\n const paths = (path || \"data\").split(\".\");\r\n let current = target;\r\n\r\n // 遍历到路径的倒数第二个属性\r\n for (let index = 0; index < paths.length - 1; index++) {\r\n const part = paths[index];\r\n const nextPart = paths[index + 1];\r\n // 判断属性是取的数组\r\n const { propName, propIndex = 0, isArray } = _getTargetPathPart(part);\r\n\r\n if (isArray) {\r\n // 检查当前属性是否存在,若不存在或者不是数组,则创建一个数组\r\n if (!current || !current.hasOwnProperty(propName)) {\r\n current[propName] = [];\r\n }\r\n // 确保数组长度足够容纳指定索引\r\n while (current[propName].length <= propIndex) {\r\n current[propName].push({});\r\n }\r\n // 逐层向下找到对应属性的值\r\n current = current[propName][propIndex];\r\n } else {\r\n // 如果不是数组索引形式,处理普通对象属性,如果是.1.数组形式,则还是返回数组\r\n if (!current || !current.hasOwnProperty(part) || typeof current[part] !== \"object\") {\r\n current[part] = isNaN(nextPart) ? [] : {};\r\n }\r\n // 移动到对象的下一层属性\r\n current = current[part];\r\n }\r\n }\r\n\r\n // 处理最后一个路径部分\r\n const lastPath = paths[paths.length - 1];\r\n const { propName, propIndex = 0, isArray } = _getTargetPathPart(lastPath);\r\n if (isArray) {\r\n // 检查当前属性是否存在,若不存在或者不是数组,则创建一个数组\r\n if (!current.hasOwnProperty(propName) || !Array.isArray(current[propName])) {\r\n current[propName] = [];\r\n }\r\n // 确保数组长度足够容纳指定索引\r\n while (current[propName].length <= propIndex) {\r\n current[propName].push({});\r\n }\r\n // 逐层向下找到对应属性的值\r\n current[propName][propIndex] = value;\r\n } else {\r\n current[lastPath] = value;\r\n }\r\n\r\n // 返回源对象\r\n return target;\r\n}\r\n\r\n/* 内部方法 */\r\n/**\r\n * 获得目标路径的片段\r\n * @param {string} path\r\n * @returns {*} 返回获得到的值\r\n */\r\nfunction _getTargetPathPart(path: string): Record<any, any> {\r\n const pathArrayMatch = path.match(/^(\\w+)\\[(\\d+)]$/);\r\n return {\r\n propName: (pathArrayMatch && pathArrayMatch[1]) || undefined, // 属性名\r\n propIndex: pathArrayMatch ? parseInt(pathArrayMatch[2], 10) : undefined, // 属性数组时候的下标\r\n isArray: !!pathArrayMatch, // 是否是数组\r\n };\r\n}\r\n","/**\r\n * @module 日期\r\n */\r\nimport { isNull, isInteger, isDate, isString } from \"@/validate\";\r\nimport { parseInt } from \"@/number\";\r\nimport { DATE } from \"@/constants\";\r\n\r\n/**\r\n 日期配置类型\r\n @param format 日期格式字符串,支持的占位符如下:\r\n | 占位符 | 说明 | 示例(2025-01-05 08:05:08 周一) |\r\n |--------|-----------------------|---------------------------------|\r\n | yyyy | 4 位年份 | 2025 |\r\n | yy | 2 位年份 | 25 |\r\n | MM | 2 位月份(补 0) | 01 |\r\n | M | 1 位月份(不补 0) | 1 |\r\n | dd | 2 位日期(补 0) | 05 |\r\n | d | 1 位日期(不补 0) | 5 |\r\n | HH | 24 小时制(2 位,补 0) | 08 |\r\n | H | 24 小时制(1 位,不补 0)| 8 |\r\n | hh | 12 小时制(2 位,补 0) | 08 |\r\n | h | 12 小时制(1 位,不补 0)| 8 |\r\n | mm | 2 位分钟(补 0) | 05 |\r\n | m | 1 位分钟(不补 0) | 5 |\r\n | ss | 2 位秒数(补 0) | 08 |\r\n | s | 1 位秒数(不补 0) | 8 |\r\n | SSS | 3 位毫秒(补 0) | 123 |\r\n | S | 1 位毫秒(不补 0) | 1 |\r\n | E | 周几(迷你名) | 一(zh) / Mon(en) |\r\n | EE | 周几(短名) | 周一(zh) / Mon(en) |\r\n | EEE | 周几(全名) | 星期一(zh) / Monday(en) |\r\n | Q | 季度(迷你名) | 1(zh) / 1(en) |\r\n | QQ | 季度(短名) | Q1(zh) / Q1(en) |\r\n | QQQ | 季度(全名) | 第一季度(zh) / Quarter 1(en)|\r\n | a | 上午 / 下午(小写) | am /pm |\r\n | A | 上午 / 下午(大写) | AM / PM |\r\n | aa | 上午 / 下午(中文) | 上午 / 下午 |\r\n | AA | 上午 / 下午(中文大写) | 上午 / 下午 |\r\n @example\r\n yyyy-MM-dd HH:mm:ss → 2025-01-05 08:05:08\r\n yyyy-M-d h:m:s → 2025-1-5 8:5:8\r\n yyyy-MM-dd EE → 2025-01-05 周一\r\n @param lang 语言,可选值:zh(默认)/ en\r\n */\r\nexport interface DateOptions {\r\n format?: string; // 日期格式\r\n lang?: string; // 语言,默认 zh\r\n}\r\n\r\n/* 快捷日期 */\r\n/**\r\n * 今天\r\n *@returns {string} 返回日期字符串\r\n */\r\nexport function today(): string {\r\n return getDate();\r\n}\r\n\r\n/**\r\n * 昨天\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function yesterday(): string {\r\n return toDateString(addDate(new Date(), -1));\r\n}\r\n\r\n/**\r\n * 明天\r\n *@returns {string} 返回日期字符串\r\n */\r\nexport function tomorrow(): string {\r\n return toDateString(addDate(new Date(), +1));\r\n}\r\n\r\n/**\r\n * 上周(7天前日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function lastWeek(date = new Date()): string {\r\n return toDateString(addDate(date, -7));\r\n}\r\n\r\n/**\r\n * 下周(7天后日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function nextWeek(date = new Date()): string {\r\n return toDateString(addDate(date, +7));\r\n}\r\n\r\n/**\r\n * 上个月(30天前日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function lastMonth(date = new Date()): string {\r\n const newDate = addMonth(date, -1);\r\n // 处理跨月边界\r\n if (newDate.getMonth() === date.getMonth()) {\r\n newDate.setDate(0);\r\n }\r\n return toDateString(newDate);\r\n}\r\n\r\n/**\r\n * 下个月(30天后日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function nextMonth(date = new Date()): string {\r\n const newDate = addMonth(date, +1);\r\n // 处理跨月边界\r\n if (newDate.getMonth() === date.getMonth()) {\r\n newDate.setDate(0);\r\n }\r\n return toDateString(newDate);\r\n}\r\n\r\n/**\r\n * 上一年(365天前日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function lastYear(date = new Date()): string {\r\n const newDate = addYear(date, -1);\r\n // 处理跨年边界,闰年2月29日→平年2月28日\r\n if (newDate.getMonth() !== date.getMonth() || newDate.getDate() !== date.getDate()) {\r\n newDate.setDate(28);\r\n }\r\n return toDateString(newDate);\r\n}\r\n\r\n/**\r\n * 下一年(365天后日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function nextYear(date = new Date()): string {\r\n const newDate = addYear(date, +1);\r\n // 处理跨年边界,闰年2月29日→平年2月28日\r\n if (newDate.getMonth() !== date.getMonth() || newDate.getDate() !== date.getDate()) {\r\n newDate.setDate(28);\r\n }\r\n return toDateString(newDate);\r\n}\r\n\r\n/* 判断当前日期 */\r\n/**\r\n * 是否为上午\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isAM(date = new Date()): boolean {\r\n return date.getHours() < 12;\r\n}\r\n\r\n/**\r\n * 是否为下午\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isPM(date = new Date()): boolean {\r\n return date.getHours() >= 12;\r\n}\r\n\r\n/**\r\n * 是否为今天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isToday(date = new Date()): boolean {\r\n // 此刻日期\r\n const nowDate = new Date();\r\n // 判断日期\r\n return ([\"getFullYear\", \"getMonth\", \"getDate\"] as Array<\"getFullYear\" | \"getMonth\" | \"getDate\">).every(\r\n (item) => nowDate[item]() === date[item](),\r\n );\r\n}\r\n\r\n/**\r\n * 是否为昨天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isYesterday(date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const nowTime = Date.now();\r\n const diffTime = nowTime - startTime;\r\n const diffDay = parseInt(diffTime / (1000 * 60 * 60 * 24));\r\n return diffDay === 1;\r\n}\r\n\r\n/**\r\n * 是否为前天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBeforeYesterday(date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const nowTime = Date.now();\r\n const diffTime = nowTime - startTime;\r\n const diffDay = parseInt(diffTime / (1000 * 60 * 60 * 24));\r\n return diffDay === 2;\r\n}\r\n\r\n/**\r\n * 是否为明天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isTomorrow(date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const nowTime = Date.now();\r\n const diffTime = startTime - nowTime;\r\n const diffDay = parseInt(diffTime / (1000 * 60 * 60 * 24));\r\n return diffDay === 1;\r\n}\r\n\r\n/**\r\n * 是否为后天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isAfterTomorrow(date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const nowTime = Date.now();\r\n const time = startTime - nowTime;\r\n const diffDay = parseInt(time / (1000 * 60 * 60 * 24));\r\n return diffDay === 2;\r\n}\r\n\r\n/**\r\n * 是否为工作日\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isWorkday(date = new Date()): boolean {\r\n const dayOfWeek = getDayOfWeek(date);\r\n return dayOfWeek !== 6 && dayOfWeek !== 7;\r\n}\r\n\r\n/**\r\n * 是否为周末(周六和周日)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isWeekend(date = new Date()): boolean {\r\n const dayOfWeek = getDayOfWeek(date);\r\n return dayOfWeek === 6 || dayOfWeek === 7;\r\n}\r\n\r\n/**\r\n * 是否为本周第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFirstDayOfWeek(date = new Date()): boolean {\r\n return getDayOfWeek(date) === 1;\r\n}\r\n\r\n/**\r\n * 是否为本周最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isLastDayOfWeek(date = new Date()): boolean {\r\n return getDayOfWeek(date) === 7;\r\n}\r\n\r\n/**\r\n * 是否为本月第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFirstDayOfMonth(date = new Date()): boolean {\r\n return getDayOfMonth(date) === 1;\r\n}\r\n\r\n/**\r\n * 是否为本月最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isLastDayOfMonth(date = new Date()): boolean {\r\n return getDayOfMonth(date) === getDaysOfMonth(date);\r\n}\r\n\r\n/**\r\n * 是否为本年第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFirstDayOfYear(date = new Date()): boolean {\r\n return getDayOfYear(date) === 1;\r\n}\r\n\r\n/**\r\n * 是否为本年最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isLastDayOfYear(date = new Date()): boolean {\r\n return getDayOfYear(date) === getDaysOfYear(date);\r\n}\r\n\r\n/* 判断年 */\r\n/**\r\n * 是否为闰年\r\n * @description 闰年366天,平年365天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isLeapYear(date = new Date()): boolean {\r\n const year = date.getFullYear();\r\n return (year % 100 !== 0 && year % 4 === 0) || year % 400 === 0;\r\n}\r\n\r\n/**\r\n * 是否为平年\r\n * @description 闰年366天,平年365天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isCommonYear(date = new Date()): boolean {\r\n return !isLeapYear(date);\r\n}\r\n\r\n/* 比较日期区间 */\r\n/**\r\n * 是否在日期之前\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBefore(startDate: Date, endDate: Date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = startDate.getTime();\r\n const endTime = endDate.getTime();\r\n const diffTime = startTime - endTime;\r\n return diffTime < 0;\r\n}\r\n\r\n/**\r\n * 是否在日期之后\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isAfter(startDate: Date, endDate: Date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = startDate.getTime();\r\n const endTime = endDate.getTime();\r\n const diffTime = startTime - endTime;\r\n return diffTime > 0;\r\n}\r\n\r\n/**\r\n * 是否在两个日期之间\r\n * @param {Date} date 要比较的日期\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBetween(date: Date, startDate: Date, endDate: Date): boolean {\r\n const time = date.getTime();\r\n const startTime = startDate.getTime();\r\n const endTime = endDate.getTime();\r\n return time > startTime && time < endTime;\r\n}\r\n\r\n/* 日期是否相同 */\r\n/**\r\n * 两个日期是否为同一天\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSame(startDate: Date, endDate: Date): boolean {\r\n return ([\"getFullYear\", \"getMonth\", \"getDate\"] as Array<\"getFullYear\" | \"getMonth\" | \"getDate\">).every(\r\n (item) => startDate[item]() === endDate[item](),\r\n );\r\n}\r\n\r\n/**\r\n * 两个日期是否为同一周\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameWeek(startDate: Date, endDate: Date): boolean {\r\n const diffDate1 = startDate.getTime() / (24 * 60 * 60 * 1000);\r\n const diffDate2 = endDate.getTime() / (24 * 60 * 60 * 1000);\r\n return parseInt((diffDate1 + 4) / 7) === parseInt((diffDate2 + 4) / 7);\r\n}\r\n\r\n/**\r\n * 两个日期是否为同一个月\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameMonth(startDate: Date, endDate: Date): boolean {\r\n return ([\"getFullYear\", \"getMonth\"] as Array<\"getFullYear\" | \"getMonth\">).every(\r\n (item) => startDate[item]() === endDate[item](),\r\n );\r\n}\r\n\r\n/**\r\n * 两个日期是否为同一年\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameYear(startDate: Date, endDate: Date): boolean {\r\n return ([\"getFullYear\"] as Array<\"getFullYear\">).every((item) => startDate[item]() === endDate[item]());\r\n}\r\n\r\n/* 比较两个日期相同 或 之前/之后 */\r\n/**\r\n * 两个日期是否相同或之前\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameOrBefore(startDate: Date, endDate: Date): boolean {\r\n return isSame(startDate, endDate) || isBefore(startDate, endDate);\r\n}\r\n\r\n/**\r\n * 两个日期是否相同或之后\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameOrAfter(startDate: Date, endDate: Date): boolean {\r\n return isSame(startDate, endDate) || isAfter(startDate, endDate);\r\n}\r\n\r\n/* 获取 日期/时间戳/周/季度 */\r\n/**\r\n * 获得此刻的日期\r\n * @returns {Date} 返回日期\r\n */\r\nexport function getNow(): Date {\r\n return new Date();\r\n}\r\n\r\n/**\r\n * 获得当前日期字符串\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param options 配置项 配置项\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getDate(date: Date = new Date(), options: DateOptions = { format: \"yyyy-MM-dd\" }): string {\r\n const { format } = options;\r\n return toDateString(date, { format });\r\n}\r\n\r\n/**\r\n * 获得当前日期时间字符串\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param options 配置项 配置项\r\n * @returns {string} 返回日期时间字符串\r\n */\r\nexport function getDateTime(date: Date = new Date(), options: DateOptions = { format: \"yyyy-MM-dd HH:mm:ss\" }): string {\r\n const { format } = options;\r\n return toDateString(date, { format });\r\n}\r\n\r\n/**\r\n * 获取当前时间戳\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回时间戳\r\n */\r\nexport function getTimestamp(date: Date = new Date()): number {\r\n return date.getTime();\r\n}\r\n\r\n/**\r\n * 获取当前Unix时间戳\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回Unix时间戳\r\n */\r\nexport function getUnixTimestamp(date: Date = new Date()): number {\r\n return Math.round(date.getTime() / 1000);\r\n}\r\n\r\n/**\r\n * 获得当前日期的对象形式\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {Object} 返回日期的对象形式\r\n */\r\nexport function getDateObject(date: Date = new Date()): {\r\n year: number;\r\n month: number;\r\n date: number;\r\n hours: number;\r\n minutes: number;\r\n seconds: number;\r\n milliseconds: number;\r\n} {\r\n return {\r\n year: date.getFullYear(), // 年\r\n month: date.getMonth() + 1, // 月\r\n date: date.getDate(), // 日\r\n hours: date.getHours(), // 时\r\n minutes: date.getMinutes(), // 分\r\n seconds: date.getSeconds(), // 秒\r\n milliseconds: date.getMilliseconds(), // 毫秒\r\n };\r\n}\r\n\r\n/**\r\n * 获得当前日期的数组形式\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {Object} 返回日期的数组形式\r\n */\r\nexport function getDateArray(date: Date = new Date()): number[] {\r\n return Object.entries(getDateObject(date)).map(([key, value]) => value);\r\n}\r\n\r\n/**\r\n * 获得当前日期是周几\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param options 配置项\r\n * @returns {number|string} 返回周几,会根据语言返回\r\n */\r\nexport function getWeek(date: Date = new Date(), options: DateOptions = { format: \"E\", lang: \"zh\" }): number | string {\r\n const { format, lang = \"zh\" } = options;\r\n // 根据格式化和语言返回对应的周\r\n if (format === \"E\") {\r\n return DATE.WEEK[lang].MINI[date.getDay()];\r\n } else if (format === \"EE\") {\r\n return DATE.WEEK[lang].SHORT[date.getDay()];\r\n } else if (format === \"EEE\") {\r\n return DATE.WEEK[lang].FULL[date.getDay()];\r\n } else {\r\n return getDayOfWeek(date);\r\n }\r\n}\r\n\r\n/**\r\n * 获得当前日期是第几季度\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param options 配置项\r\n * @returns {number|string} 返回第几季度,会根据语言返回\r\n */\r\nexport function getQuarter(\r\n date: Date = new Date(),\r\n options: DateOptions = { format: \"Q\", lang: \"zh\" },\r\n): number | string {\r\n const { format, lang = \"zh\" } = options;\r\n // 根据格式化和语言返回对应的周\r\n const quarterNum = Number(Math.floor((date.getMonth() + 3) / 3));\r\n if (format === \"Q\") {\r\n return DATE.QUARTER[lang].MINI[quarterNum - 1];\r\n } else if (format === \"QQ\") {\r\n return DATE.QUARTER[lang].SHORT[quarterNum - 1];\r\n } else if (format === \"QQQ\") {\r\n return DATE.QUARTER[lang].FULL[quarterNum - 1];\r\n } else {\r\n return quarterNum;\r\n }\r\n}\r\n\r\n/* 当前日期是所在 周/月/年 的第几天 */\r\n/**\r\n * 获得当前日期是所在周的第几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number|string} 返回天数\r\n */\r\nexport function getDayOfWeek(date: Date = new Date()): number | string {\r\n return [7, 1, 2, 3, 4, 5, 6][date.getDay()];\r\n}\r\n\r\n/**\r\n * 获得当前日期是所在月的第几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDayOfMonth(date: Date = new Date()): number {\r\n return date.getDate();\r\n}\r\n\r\n/**\r\n * 获得当前日期是所在年的第几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDayOfYear(date: Date = new Date()): number {\r\n return Math.ceil((date.getTime() - new Date(date.getFullYear().toString()).getTime()) / (24 * 60 * 60 * 1000)) + 1;\r\n}\r\n\r\n/* 当前日期的周是所在 月/年 的第几周 */\r\n/**\r\n * 获得当前日期是所在月的第几周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回周数\r\n */\r\nexport function getWeekOfMonth(date: Date = new Date()): number {\r\n return Math.ceil((date.getDate() + 6 - Number(getDayOfWeek(date))) / 7);\r\n}\r\n\r\n/**\r\n * 获得当前日期是所在年的第几周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回周数\r\n */\r\nexport function getWeekOfYear(date: Date = new Date()): number {\r\n const startDate = new Date(date.getFullYear(), 0, 1);\r\n const startDay = getDayOfWeek(startDate);\r\n const diff = Math.round((date.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000));\r\n return Math.ceil((diff + Number(startDay)) / 7);\r\n}\r\n\r\n/* 当前日期所在 周/月/年 共几天 */\r\n/**\r\n * 获得当前日期所在的周共几天\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDaysOfWeek(): number {\r\n return 7;\r\n}\r\n\r\n/**\r\n * 获得当前日期所在的月共几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDaysOfMonth(date: Date = new Date()): number {\r\n return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();\r\n}\r\n\r\n/**\r\n * 获得当前日期所在的年共几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDaysOfYear(date: Date = new Date()): number {\r\n return isLeapYear(date) ? 366 : 365;\r\n}\r\n\r\n/* 当前周所在 月/年 共几周 */\r\n/**\r\n * 获得当前日期是所在月的第几周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回周数\r\n */\r\nexport function getWeeksOfMonth(date: Date = new Date()): number {\r\n const startDate = new Date(date.getFullYear(), 0, 1);\r\n const startDay = Number(getDayOfWeek(startDate));\r\n const fullDays = isLeapYear(date) ? 366 : 365;\r\n if (startDay === 1) {\r\n return Math.ceil(fullDays / 7);\r\n } else {\r\n return Math.ceil((fullDays - 7 + startDay) / 7);\r\n }\r\n}\r\n\r\n/**\r\n * 获得当前日期是所在年的第几周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回周数\r\n */\r\nexport function getWeeksOfYear(date: Date = new Date()): number {\r\n const startDate = new Date(date.getFullYear(), 0, 1);\r\n const startDay = Number(getDayOfWeek(startDate));\r\n const fullDays = isLeapYear(date) ? 366 : 365;\r\n if (startDay === 1) {\r\n return Math.ceil(fullDays / 7);\r\n } else {\r\n return Math.ceil((fullDays - 7 + startDay) / 7);\r\n }\r\n}\r\n\r\n/* 当前日期所在 周/月/年 的 第一天/最后一天/所有天数数组 */\r\n/**\r\n * 获得当前日期所在周的第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getFirstDateOfWeek(date: Date = new Date()): string {\r\n const weekDay = Number(getDayOfWeek(date));\r\n date.setDate(date.getDate() - weekDay + 1);\r\n return toDateString(date);\r\n}\r\n\r\n/**\r\n * 获得当前日期所在周的最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getLastDateOfWeek(date: Date = new Date()): string {\r\n const weekDay = Number(getDayOfWeek(date));\r\n date.setDate(date.getDate() + (7 - weekDay));\r\n return toDateString(date);\r\n}\r\n\r\n/**\r\n * 获取当前日期所在周的所有日期\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string[]} 返回日期数组\r\n */\r\nexport function getFullDateOfWeek(date: Date = new Date()): string[] {\r\n const array = [];\r\n // 获得当前日期是本周几\r\n const dayOfWeek = date.getDay();\r\n // 根据当前日期获取本周一\r\n const firstDateOfWeek = new Date();\r\n firstDateOfWeek.setDate(date.getDate() - (dayOfWeek === 0 ? 6 : dayOfWeek - 1));\r\n\r\n // 遍历本周日期\r\n for (let i = 0; i < 7; i++) {\r\n const currentDate = new Date(firstDateOfWeek);\r\n currentDate.setDate(currentDate.getDate() + i);\r\n array.push(toDateString(currentDate));\r\n }\r\n\r\n return array;\r\n}\r\n\r\n/**\r\n * 获得当前日期所在月的第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getFirstDateOfMonth(date: Date = new Date()): string {\r\n date.setDate(1);\r\n return toDateString(date);\r\n}\r\n\r\n/**\r\n * 获得当前日期所在月的最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getLastDateOfMonth(date: Date = new Date()): string {\r\n return toDateString(new Date(date.getFullYear(), date.getMonth() + 1, 0));\r\n}\r\n\r\n/**\r\n * 获取当前日期所在月的所有日期\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string[]} 返回日期数组\r\n */\r\nexport function getFullDateOfMonth(date: Date = new Date()): string[] {\r\n const array = [];\r\n // 获得本月第一天\r\n const firstDateOfMonth = new Date(date.getFullYear(), date.getMonth(), 1);\r\n // 获得本月最后一天\r\n const lastDateOfMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0);\r\n // 遍历本月日期\r\n for (let i = 0; i < lastDateOfMonth.getDate(); i++) {\r\n const currentDate = new Date(firstDateOfMonth);\r\n currentDate.setDate(firstDateOfMonth.getDate() + i);\r\n array.push(toDateString(currentDate));\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 获取当前日期所在年的第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getFirstDateOfYear(date: Date = new Date()): string {\r\n return toDateString(new Date(date.getFullYear(), 0, 1));\r\n}\r\n\r\n/**\r\n * 获取当前日期所在年的最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getLastDateOfYear(date: Date = new Date()): string {\r\n return toDateString(new Date(date.getFullYear(), 11, 31));\r\n}\r\n\r\n/**\r\n * 获取当前日期所在年的所有日期\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getFullDateOfYear(date: Date = new Date()): string[] {\r\n const array = [];\r\n // 获得本年第一天\r\n const firstDateOfYear = new Date(date.getFullYear(), 0, 1);\r\n // 获得本年一共多少天\r\n const daysOfYear = getDaysOfYear();\r\n // 遍历本年日期\r\n for (let i = 0; i < daysOfYear; i++) {\r\n const currentDate = new Date(firstDateOfYear);\r\n currentDate.setDate(firstDateOfYear.getDate() + i);\r\n array.push(toDateString(currentDate));\r\n }\r\n return array;\r\n}\r\n\r\n/* 计算两个日期相差 */\r\n/**\r\n * 计算两个日期相差的天数,不满一天为0\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {number} 返回两个日期相差的天数,结果为正数或者负数\r\n */\r\nexport function getDiffDay(startDate: Date, endDate: Date): number {\r\n if (isNull(startDate) || isNull(endDate)) return 0;\r\n const diff = (endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000);\r\n\r\n // 返回\r\n return diff >= 0 ? Math.abs(diff) : diff;\r\n}\r\n\r\n/**\r\n * 计算两个日期相差的周数,不满一周为0\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {number} 返回两个日期相差的周数,结果为正数或者负数\r\n */\r\nexport function getDiffWeek(startDate: Date, endDate: Date): number {\r\n if (isNull(startDate) || isNull(endDate)) return 0;\r\n const diff = (endDate.getTime() - startDate.getTime()) / (7 * 24 * 60 * 60 * 1000);\r\n\r\n // 返回\r\n return diff >= 0 ? Math.abs(diff) : diff;\r\n}\r\n\r\n/**\r\n * 计算两个日期相差的月数,不满一月为0\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {number} 返回两个日期相差的月数,结果为正数或者负数\r\n */\r\nexport function getDiffMonth(startDate: Date, endDate: Date): number {\r\n if (isNull(startDate) || isNull(endDate)) return 0;\r\n const diff = (startDate.getTime() - endDate.getTime()) / (30 * 24 * 60 * 60 * 1000);\r\n\r\n // 返回\r\n return diff >= 0 ? Math.abs(diff) : diff;\r\n}\r\n\r\n/**\r\n * 计算两个日期相差的年数,不满一年为0\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {number} 返回两个日期相差的年数,结果为正数或者负数\r\n */\r\nexport function getDiffYear(startDate: Date, endDate: Date): number {\r\n if (isNull(startDate) || isNull(endDate)) return 0;\r\n const diff = (endDate.getTime() - startDate.getTime()) / (12 * 30 * 24 * 60 * 60 * 1000);\r\n\r\n // 返回\r\n return diff >= 0 ? Math.abs(diff) : diff;\r\n}\r\n\r\n/* 获得两个日期之间 年月日/年月/年 数组 */\r\n/**\r\n * 获得两个日期之间的年月日数组\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {Array} 返回年月日数组\r\n */\r\nexport function getBetweenDates(startDate: Date, endDate: Date): string[] {\r\n if (isNull(startDate) || isNull(endDate)) return [];\r\n\r\n // 计算\r\n const array = [];\r\n while (endDate.getTime() - startDate.getTime() >= 0) {\r\n const year = startDate.getFullYear(),\r\n month = _datePadZero(startDate.getMonth() + 1),\r\n day = _datePadZero(startDate.getDate());\r\n\r\n // 加入数组\r\n array.push(year + \"-\" + month + \"-\" + day);\r\n // 更新日期\r\n startDate.setDate(startDate.getDate() + 1);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 获得两个日期之间的年月数组\r\n * @description 支持:日期字符串,日期对象,时间戳,Unix时间戳\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {Array} 返回年月数组\r\n */\r\nexport function getBetweenMonths(startDate: Date, endDate: Date): string[] {\r\n if (isNull(startDate) || isNull(endDate)) return [];\r\n\r\n // 计算\r\n const array = [];\r\n // 获取时间对象\r\n const min = new Date();\r\n const max = new Date();\r\n // 设置起始时间\r\n min.setFullYear(startDate.getFullYear(), startDate.getMonth() + 1);\r\n // 设置结束时间\r\n max.setFullYear(endDate.getFullYear(), endDate.getMonth() + 1);\r\n\r\n // 复制一份起始时间对象\r\n const curr = min;\r\n // 定义字符串\r\n let str = \"\";\r\n // 起始时间在结束时间之前\r\n while (curr <= max) {\r\n // 获取此时间的月份\r\n const month = curr.getMonth();\r\n // 如果月份为0,也就是代表12月份\r\n if (month === 0) {\r\n str = curr.getFullYear() - 1 + \"-\" + 12;\r\n } else {\r\n // 正常月份\r\n str = curr.getFullYear() + \"-\" + _datePadZero(month);\r\n }\r\n // 将此年月加入数组\r\n array.push(str);\r\n // 更新此时间月份\r\n curr.setMonth(month + 1);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 获得两个日期之间的年数组\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {Array} 返回年数组\r\n */\r\nexport function getBetweenYears(startDate: Date, endDate: Date): number[] {\r\n if (isNull(startDate) || isNull(endDate)) return [];\r\n\r\n // 计算\r\n const array = [];\r\n while (endDate.getTime() - startDate.getTime() >= 0) {\r\n const year = startDate.getFullYear();\r\n\r\n // 加入数组\r\n array.push(year);\r\n // 更新日期\r\n startDate.setFullYear(startDate.getFullYear() + 1);\r\n }\r\n return array;\r\n}\r\n\r\n/* 过去时间和剩余时间的显示 */\r\n/**\r\n * 获得过去时间的字符串显示\r\n * @description 例如:刚刚,1分钟前,1小时前等\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回字符串\r\n */\r\nexport function getPastTime(date: Date, options: DateOptions = { lang: \"zh\" }): string {\r\n const { lang = \"zh\" } = options;\r\n if (isNull(date)) return \"--\";\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const currentTime = Date.now();\r\n const time = currentTime - startTime;\r\n // 年月日时分\r\n const year = parseInt(time / (1000 * 60 * 60 * 24 * 30 * 12));\r\n const month = parseInt(time / (1000 * 60 * 60 * 24 * 30));\r\n const day = parseInt(time / (1000 * 60 * 60 * 24));\r\n const hour = parseInt(time / (1000 * 60 * 60));\r\n const min = parseInt(time / (1000 * 60));\r\n\r\n // 返回结果\r\n if (year) {\r\n return year + DATE.PASS_TIME[lang].YEAR;\r\n } else if (month) {\r\n return month + DATE.PASS_TIME[lang].MONTH;\r\n } else if (day) {\r\n if (day === 1) {\r\n return DATE.PASS_TIME[lang].YESTERDAY;\r\n } else if (day === 2) {\r\n return DATE.PASS_TIME[lang].BEFORE_YESTERDAY;\r\n } else {\r\n return day + DATE.PASS_TIME[lang].DAY;\r\n }\r\n } else if (hour) {\r\n if (hour > 12) {\r\n return DATE.PASS_TIME[lang].TODAY;\r\n } else {\r\n return hour + DATE.PASS_TIME[lang].HOUR;\r\n }\r\n } else if (min) {\r\n return min + DATE.PASS_TIME[lang].MINUTE;\r\n } else {\r\n return DATE.PASS_TIME[lang].JUST;\r\n }\r\n}\r\n\r\n/**\r\n * 获得剩余时间的字符串显示\r\n * @description 例如:1天10小时20分钟30秒\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回字符串\r\n */\r\nexport function getOverTime(date: Date, options: DateOptions = { lang: \"zh\" }): string {\r\n const { lang = \"zh\" } = options;\r\n if (isNull(date)) return \"--\";\r\n\r\n // 计算\r\n const startDate = new Date(); // 开始时间\r\n const t = date.getTime() - startDate.getTime(); // 时间差\r\n let d = 0,\r\n h = 0,\r\n m = 0,\r\n s = 0;\r\n if (t >= 0) {\r\n d = Math.floor(t / 1000 / 3600 / 24);\r\n h = Math.floor((t / 1000 / 60 / 60) % 24);\r\n m = Math.floor((t / 1000 / 60) % 60);\r\n s = Math.floor((t / 1000) % 60);\r\n }\r\n return `${d}${DATE.OVER_TIME[lang].DAY} ${h}${DATE.OVER_TIME[lang].HOUR} ${m}${DATE.OVER_TIME[lang].MINUTE} ${s}${DATE.OVER_TIME[lang].SECOND}`;\r\n}\r\n\r\n/* 通过日期获得 年龄、星座和生肖 */\r\n\r\n/**\r\n * 通过日期获得年龄\r\n * @param {Date} date 日期参数\r\n * @returns {number} 返回周岁年龄\r\n */\r\nexport function getAge(date: Date): number {\r\n let age = 0;\r\n // 传参日期\r\n const dateArray = toDateString(date).split(\"-\");\r\n const birthYear = Number(dateArray[0]);\r\n const birthMonth = Number(dateArray[1]);\r\n const birthDay = Number(dateArray[2]);\r\n // 当前的日期\r\n const nowDate = new Date();\r\n const nowYear = nowDate.getFullYear(),\r\n nowMonth = nowDate.getMonth() + 1,\r\n nowDay = nowDate.getDate();\r\n\r\n // 出生年份需要小于当年,否则是0岁\r\n const diffAge = nowYear - birthYear;\r\n if (diffAge > 0) {\r\n const diffMonth = nowMonth - birthMonth;\r\n const diffDay = nowDay - birthDay;\r\n if (diffMonth === 0) {\r\n if (diffDay < 0) {\r\n age = diffAge - 1;\r\n } else {\r\n age = diffAge;\r\n }\r\n } else {\r\n if (diffMonth < 0) {\r\n age = diffAge - 1;\r\n } else {\r\n age = diffAge;\r\n }\r\n }\r\n }\r\n\r\n // 返回周岁年龄\r\n return age;\r\n}\r\n\r\n/**\r\n * 通过日期获得星座\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回星座\r\n */\r\nexport function getZodiac(date: Date, options: DateOptions = { lang: \"zh\" }): string {\r\n const { lang = \"zh\" } = options;\r\n if (isNull(date)) return \"\";\r\n\r\n // 计算\r\n const days = [20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22];\r\n const month = date.getMonth() + 1;\r\n const day = date.getDate();\r\n return day < days[month - 1] ? DATE.ZODIAC[lang][month - 1] : DATE.ZODIAC[lang][month];\r\n}\r\n\r\n/**\r\n * 通过日期获得生肖\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回生肖\r\n */\r\nexport function getChineseZodiac(date: Date, options: DateOptions = { lang: \"zh\" }): string {\r\n const { lang = \"zh\" } = options;\r\n if (isNull(date)) return \"\";\r\n\r\n // 计算\r\n const year = date.getFullYear();\r\n if (year < 1900) {\r\n return \"未知\";\r\n }\r\n return DATE.CHINESE_ZODIAC[lang][(year - 1900) % DATE.CHINESE_ZODIAC[lang].length];\r\n}\r\n\r\n/* 计算日期加减 年,月,日,时,分,秒,周,季度 */\r\n/**\r\n * 日期加减年\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addYear(date: Date = new Date(), num: number = +1): Date {\r\n date.setFullYear(date.getFullYear() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减月\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addMonth(date: Date = new Date(), num: number = +1): Date {\r\n date.setMonth(date.getMonth() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addDate(date: Date = new Date(), num: number = +1): Date {\r\n date.setDate(date.getDate() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减小时\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addHours(date: Date = new Date(), num: number = +1): Date {\r\n date.setHours(date.getHours() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减分钟\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addMinutes(date: Date = new Date(), num: number = +1): Date {\r\n date.setMinutes(date.getMinutes() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减秒\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addSeconds(date: Date = new Date(), num: number = +1): Date {\r\n date.setSeconds(date.getSeconds() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减毫秒\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+100\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addMillisecond(date: Date = new Date(), num: number = +100): Date {\r\n date.setMilliseconds(date.getMilliseconds() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addWeek(date: Date = new Date(), num: number = +1): Date {\r\n date.setDate(date.getDate() + num * 7);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减季度\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addQuarter(date: Date = new Date(), num: number = +1): Date {\r\n date.setMonth(date.getMonth() + num * 4);\r\n return date;\r\n}\r\n\r\n/* 格式化和解析日期 */\r\n\r\n/**\r\n * UTC 日期对象转本地时区日期对象\r\n * @description 将 UTC 时间的 Date 对象转换为本地时间的 Date 对象(时间戳不变,仅调整时区偏移)\r\n * @param {Date} date UTC 日期对象,默认当前 UTC 时间\r\n * @returns {Date} 本地时区日期对象(时间戳 = UTC时间戳 + 时区偏移毫秒数)\r\n * @example\r\n * // UTC时间:2025-01-26 00:00:00\r\n * const utcDate = new Date('2025-01-26T00:00:00Z');\r\n * const localDate = fromDateUTC(utcDate);\r\n * console.log(toDateString(localDate)); // 2025-01-26 08:00:00(北京本地时间)\r\n */\r\nexport function fromDateUTC(date: Date = new Date()): Date {\r\n return new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000);\r\n}\r\n\r\n/**\r\n * 本地时区日期转 UTC 日期对象\r\n * @description 将本地时间的 Date 对象转换为 UTC 时间的 Date 对象(时间戳不变,仅调整时区偏移)\r\n * @param {Date} date 本地日期对象,默认当前本地时间\r\n * @returns {Date} UTC 日期对象(时间戳 = 本地时间戳 - 时区偏移毫秒数)\r\n * @example\r\n * // 北京本地时间:2025-01-26 08:00:00(东8区)\r\n * const localDate = new Date('2025-01-26 08:00:00');\r\n * const utcDate = toDateUTC(localDate);\r\n * console.log(utcDate.toISOString()); // 2025-01-26T00:00:00.000Z(UTC时间)\r\n */\r\nexport function toDateUTC(date: Date = new Date()): Date {\r\n return new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000);\r\n}\r\n\r\n/**\r\n * 格式化日期为 UTC 字符串(符合 ISO 8601 标准)\r\n * @description 直接输出 UTC 时间的字符串,无需手动转换时区\r\n * @param {Date} date 本地日期对象,默认当前本地时间\r\n * @param {DateOptions} options 格式化配置,默认 yyyy-MM-dd HH:mm:ss\r\n * @returns {string} UTC 日期字符串\r\n * @example\r\n * const localDate = new Date('2025-01-26 08:00:00');\r\n * console.log(toUTCString(localDate)); // 2025-01-26 00:00:00\r\n */\r\nexport function toDateUTCString(date = new Date(), options: DateOptions = { format: \"yyyy-MM-dd HH:mm:ss\" }): string {\r\n const utcDate = toDateUTC(date);\r\n return toDateString(utcDate, options);\r\n}\r\n\r\n/**\r\n * 日期字符串转为日期对象\r\n * @description 支持日期字符串,时间戳,Unix时间戳\r\n * @param {string|number} value 日期参数\r\n * @returns {Date} 返回日期对象\r\n */\r\nexport function toDate(value: string | number): Date {\r\n // 为空抛出异常\r\n if (isNull(value)) {\r\n throw new TypeError(\"toDate: value cannot be null or undefined\");\r\n }\r\n\r\n // 是日期字符串\r\n if (isString(value)) {\r\n return new Date(String(value).replace(/-/g, \"/\"));\r\n }\r\n // 是时间戳\r\n else if (isInteger(value) && String(value).length === 13) {\r\n return new Date(value);\r\n }\r\n // 是unix时间戳\r\n else if (isInteger(value) && String(value).length === 10) {\r\n return new Date(Number(value) * 1000);\r\n }\r\n // 不支持的日期格式\r\n else {\r\n throw new TypeError(`toDate: invalid input type: ${typeof value}, expected string or number`);\r\n }\r\n}\r\n\r\n/**\r\n * 日期对象转为日期字符串\r\n * @description 支持日期字符串,日期对象,时间戳,unix时间戳\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function toDateString(date: Date, options: DateOptions = { format: \"yyyy-MM-dd\", lang: \"zh\" }): string {\r\n const { format = \"yyyy-MM-dd\", lang = \"zh\" } = options;\r\n // 为空抛出异常\r\n if (isNull(date)) {\r\n throw new TypeError(\"toDateString: date cannot be null or undefined\");\r\n }\r\n\r\n // 判断是否是日期对象\r\n if (!isDate(date)) {\r\n throw new TypeError(`toDateString: invalid input type: ${typeof date}, expected Date object`);\r\n }\r\n\r\n // 日期转化替换\r\n const replaceRules: Record<string, (match: string) => string> = {\r\n // 年(yyyy/yy)\r\n \"(y+)\": (match) => {\r\n const year = date.getFullYear().toString();\r\n return match.length === 2 ? year.slice(-2) : year;\r\n },\r\n // 月(M/MM)\r\n \"(M+)\": (match) => {\r\n const month = date.getMonth() + 1;\r\n return match.length === 1 ? month.toString() : _datePadZero(month);\r\n },\r\n // 日(d/dd)\r\n \"(d+)\": (match) => {\r\n const day = date.getDate();\r\n return match.length === 1 ? day.toString() : _datePadZero(day);\r\n },\r\n // 12小时制(h/hh)\r\n \"(h+)\": (match) => {\r\n const hour = date.getHours() % 12 || 12;\r\n return match.length === 1 ? hour.toString() : _datePadZero(hour);\r\n },\r\n // 24小时制(H/HH)\r\n \"(H+)\": (match) => {\r\n const hour = date.getHours();\r\n return match.length === 1 ? hour.toString() : _datePadZero(hour);\r\n },\r\n // 分钟(m/mm)\r\n \"(m+)\": (match) => {\r\n const min = date.getMinutes();\r\n return match.length === 1 ? min.toString() : _datePadZero(min);\r\n },\r\n // 秒(s/ss)\r\n \"(s+)\": (match) => {\r\n const sec = date.getSeconds();\r\n return match.length === 1 ? sec.toString() : _datePadZero(sec);\r\n },\r\n // 毫秒(S/SS/SSS)\r\n \"(S+)\": (match) => {\r\n const ms = date.getMilliseconds();\r\n return ms.toString().padStart(match.length, \"0\").slice(0, match.length);\r\n },\r\n // 上午/下午(a/A/aa/AA)\r\n \"([aA]+)\": (match) => {\r\n const isAm = date.getHours() < 12;\r\n // 多语言处理\r\n if (match.length > 1) {\r\n return isAm ? DATE.AM_PM[lang].AM : DATE.AM_PM[lang].PM;\r\n } else {\r\n return isAm ? match.toLowerCase() : match.toUpperCase();\r\n }\r\n },\r\n // 周(E/EE/EEE)\r\n \"(E+)\": (match) => {\r\n const day = date.getDay();\r\n if (match.length === 1) return DATE.WEEK[lang].MINI[day];\r\n if (match.length === 2) return DATE.WEEK[lang].SHORT[day];\r\n return DATE.WEEK[lang].FULL[day];\r\n },\r\n // 季度(Q/QQ/QQQ)\r\n \"(Q+)\": (match) => {\r\n const quarter = Math.floor((date.getMonth() + 3) / 3) - 1;\r\n if (match.length === 1) return DATE.QUARTER[lang].MINI[quarter];\r\n if (match.length === 2) return DATE.QUARTER[lang].SHORT[quarter];\r\n return DATE.QUARTER[lang].FULL[quarter];\r\n },\r\n };\r\n\r\n // 批量替换格式\r\n let result = format;\r\n Object.entries(replaceRules).forEach(([regStr, replaceFn]) => {\r\n const reg = new RegExp(regStr, \"g\");\r\n result = result.replace(reg, (_, match) => replaceFn(match));\r\n });\r\n\r\n return result;\r\n}\r\n\r\n/* 内部使用的函数 */\r\n/**\r\n * 单个日期数字前自动补齐零为两位\r\n * @param {string|number} value 值\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nfunction _datePadZero(value: string | number): string {\r\n const num = Number(value);\r\n // 数字>9直接转字符串,否则补0\r\n return num > 9 ? String(num) : \"0\" + num;\r\n}\r\n","/**\r\n * @module 数学\r\n */\r\nimport { isNaN } from \"@/validate\";\r\nimport { MATH } from \"@/constants/index.ts\";\r\n\r\n/* 数字计算 */\r\n/**\r\n * 两个数字相加\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function add(arg1: string | number, arg2: string | number): number {\r\n let r1, r2;\r\n try {\r\n r1 = arg1.toString().split(\".\")[1].length;\r\n } catch (e) {\r\n r1 = 0;\r\n }\r\n try {\r\n r2 = arg2.toString().split(\".\")[1].length;\r\n } catch (e) {\r\n r2 = 0;\r\n }\r\n const m = Math.pow(10, Math.max(r1, r2));\r\n return (Number(arg1) * m + Number(arg2) * m) / m;\r\n}\r\n\r\n/**\r\n * 两个数字相减\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function subtract(arg1: string | number, arg2: string | number): number {\r\n let r1, r2;\r\n try {\r\n r1 = arg1.toString().split(\".\")[1].length;\r\n } catch (e) {\r\n r1 = 0;\r\n }\r\n try {\r\n r2 = arg2.toString().split(\".\")[1].length;\r\n } catch (e) {\r\n r2 = 0;\r\n }\r\n const m = Math.pow(10, Math.max(r1, r2));\r\n const n = r1 >= r2 ? r1 : r2;\r\n return Number(((Number(arg1) * m - Number(arg2) * m) / m).toFixed(n));\r\n}\r\n\r\n/**\r\n * 两个数字相乘\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function multiply(arg1: string | number, arg2: string | number): number {\r\n let m = 0;\r\n const s1 = arg1.toString();\r\n const s2 = arg2.toString();\r\n try {\r\n m += s1.split(\".\")[1].length;\r\n } catch (e) {}\r\n try {\r\n m += s2.split(\".\")[1].length;\r\n } catch (e) {}\r\n return (Number(s1.replace(\".\", \"\")) * Number(s2.replace(\".\", \"\"))) / Math.pow(10, m);\r\n}\r\n\r\n/**\r\n * 两个数字相除\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function divide(arg1: string | number, arg2: string | number): number {\r\n let t1 = 0,\r\n t2 = 0;\r\n try {\r\n t1 = arg1.toString().split(\".\")[1].length;\r\n } catch (e) {}\r\n try {\r\n t2 = arg2.toString().split(\".\")[1].length;\r\n } catch (e) {}\r\n const r1 = Number(arg1.toString().replace(\".\", \"\"));\r\n const r2 = Number(arg2.toString().replace(\".\", \"\"));\r\n return (r1 / r2) * Math.pow(10, t2 - t1);\r\n}\r\n\r\n/**\r\n * 两个数字取模\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function modulo(arg1: string | number, arg2: string | number): number {\r\n let t1 = 0,\r\n t2 = 0,\r\n d = 0;\r\n try {\r\n t1 = arg1.toString().split(\".\")[1].length;\r\n } catch (e) {}\r\n try {\r\n t2 = arg2.toString().split(\".\")[1].length;\r\n } catch (e) {}\r\n d = Math.pow(10, Math.max(t1, t2));\r\n return (Math.round(Number(arg1) * d) % Math.round(Number(arg2) * d)) / d;\r\n}\r\n\r\n/**\r\n * 最大公约数\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function gcd(arg1: string | number, arg2: string | number): number {\r\n let a = Math.abs(Number(arg1));\r\n let b = Math.abs(Number(arg2));\r\n while (b !== 0) {\r\n const temp = b;\r\n b = a % b;\r\n a = temp;\r\n }\r\n return a;\r\n}\r\n\r\n/**\r\n * 最小公倍数\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function scm(arg1: string | number, arg2: string | number): number {\r\n const a = Number(arg1);\r\n const b = Number(arg2);\r\n const absA = Math.abs(a);\r\n const absB = Math.abs(b);\r\n if (absA === 0 || absB === 0) {\r\n return 0;\r\n }\r\n return (absA * absB) / gcd(absA, absB);\r\n}\r\n\r\n/* 数字精度 */\r\n/**\r\n * 强制保留小数位数\r\n * @description 默认保留两位小数,解决原生的toFixed()会五舍六入的问题\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @param {number} mode 保留小数模式\r\n * @returns {string} 返回保留后的数字字符串\r\n */\r\nexport function toFixed(num: string | number, decimals: number = 2, mode: number = MATH.ROUND): string {\r\n // 四舍五入\r\n if (mode === MATH.ROUND) {\r\n return _toFixedRound(num, decimals);\r\n }\r\n // 向下舍出\r\n else if (mode === MATH.ROUND_FLOOR) {\r\n return _toFixedFloor(num, decimals);\r\n } else {\r\n throw new TypeError(\"toFixed: mode is MATH.ROUND 0 or MATH.ROUND_FLOOR\");\r\n }\r\n}\r\n\r\n/**\r\n * 尽可能保留小数位数\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @param {number} mode 保留小数模式\r\n * @returns {number} 返回保留后的数字\r\n */\r\nexport function toDecimal(num: string | number, decimals: number = 2, mode: number = MATH.ROUND): number {\r\n // 四舍五入\r\n if (mode === MATH.ROUND) {\r\n return Number(_toDecimalRound(num, decimals));\r\n }\r\n // 向下舍出\r\n else if (mode === MATH.ROUND_FLOOR) {\r\n return Number(_toDecimalFloor(num, decimals));\r\n }\r\n // 错误保留格式\r\n else {\r\n throw new TypeError(\"toDecimal: mode is MATH.ROUND 0 or MATH.ROUND_FLOOR\");\r\n }\r\n}\r\n\r\n/* 内部函数 */\r\n/**\r\n * 四舍五入,强制保留小数位数\r\n * @description 默认保留两位小数,此方法解决原生的toFixed()会五舍六入的问题\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @returns {string} 返回字符串的数字\r\n */\r\nfunction _toFixedRound(num: string | number, decimals: number = 2): string {\r\n if (isNaN(Number(num))) {\r\n // num可能是字符串,先转数字再判断NaN\r\n return \"--\";\r\n }\r\n let s = String(num);\r\n if (!decimals) decimals = 0;\r\n if (s.indexOf(\".\") === -1) s += \".\";\r\n s += new Array(decimals + 1).join(\"0\");\r\n // 正则模板字符串拼接,避免手动拼接字符串的转义问题\r\n const reg = new RegExp(`^(-|\\\\+)?(\\\\d+(\\\\.\\\\d{0,${decimals + 1}})?)\\\\d*$`);\r\n if (reg.test(s)) {\r\n let s1 = \"0\" + RegExp.$2,\r\n b = true;\r\n // 1. 把外层的数字变量 a 改名,避免和内层数组冲突\r\n const decimalLength = RegExp.$3.length;\r\n const pm = RegExp.$1;\r\n\r\n if (decimalLength === decimals + 2) {\r\n // 2. 内层数组用新变量名 digitArr,明确类型为 string[]\r\n const digitArr = s1.match(/\\d/g) as string[];\r\n if (parseInt(digitArr[digitArr.length - 1]) > 4) {\r\n for (let i = digitArr.length - 2; i >= 0; i--) {\r\n // 3. 确保赋值为字符串类型\r\n digitArr[i] = (parseInt(digitArr[i]) + 1).toString();\r\n if (digitArr[i] === \"10\") {\r\n digitArr[i] = \"0\";\r\n b = i !== 1;\r\n } else break;\r\n }\r\n }\r\n s1 = digitArr.join(\"\").replace(new RegExp(`(\\\\d+)(\\\\d{${decimals}})\\\\d$`), \"$1.$2\");\r\n }\r\n if (b) s1 = s1.substr(1);\r\n return (pm + s1).replace(/\\.$/, \"\");\r\n }\r\n return String(num);\r\n}\r\n\r\n/**\r\n * 向下舍出,强制保留小数位数\r\n * @description 默认保留两位小数,此方法相当于强制截取小数位数\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @returns {string} 返回字符串的数字\r\n */\r\nfunction _toFixedFloor(num: string | number, decimals: number = 2): string {\r\n // num可能是字符串,先转数字再判断NaN\r\n const numVal = Number(num);\r\n if (isNaN(numVal)) {\r\n throw new TypeError(`${num} is NaN`);\r\n }\r\n // 校验小数位数范围\r\n if (decimals < 0 || decimals > 20) {\r\n throw new TypeError(\"_toFixedFloor: decimals places must be between 0 and 20\");\r\n }\r\n\r\n // 默认为保留的小数点后两位\r\n const dec = Math.max(0, Math.floor(decimals)); // 确保小数位数为非负整数\r\n const tempNumStr = String(numVal); // 提前转字符串,避免重复转换\r\n const pointIndex = tempNumStr.indexOf(\".\"); // :去掉+1,直接获取小数点位置\r\n // 获取小数点后的个数(需要保证有小数位)\r\n const pointCount = pointIndex > -1 ? tempNumStr.length - pointIndex - 1 : 0;\r\n\r\n // 源数据为整数或者小数点后面小于decimals位的作补零处理\r\n if (pointIndex === -1 || pointCount <= dec) {\r\n // pointIndex === -1 表示无小数点\r\n let tempNumA: string = tempNumStr; // 统一为字符串类型,避免类型混淆\r\n if (pointIndex === -1) {\r\n tempNumA = `${tempNumA}.`;\r\n // 补零到指定小数位\r\n for (let index = 0; index < dec; index++) {\r\n tempNumA = `${tempNumA}0`;\r\n }\r\n } else {\r\n // 补零到指定小数位\r\n for (let index = 0; index < dec - pointCount; index++) {\r\n tempNumA = `${tempNumA}0`;\r\n }\r\n }\r\n return tempNumA;\r\n }\r\n\r\n // 截取当前数据到小数点后decimals位\r\n const [integerPart, decimalPart] = tempNumStr.split(\".\");\r\n return `${integerPart}.${decimalPart.substring(0, dec)}`;\r\n}\r\n\r\n/**\r\n * 四舍五入,尽可能保留小数\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @returns {string} 返回保留后的数字\r\n */\r\nfunction _toDecimalRound(num: string | number, decimals: number = 2): number {\r\n if (isNaN(Number(num))) {\r\n throw new TypeError(`_toDecimalRound: ${num} is not a number`);\r\n }\r\n const n = Math.pow(10, decimals);\r\n return Math.round(Number(num) * n) / n;\r\n}\r\n\r\n/**\r\n * 向下舍入,尽可能保留小数\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @returns {number} 返回保留后的数字\r\n */\r\nfunction _toDecimalFloor(num: string | number, decimals: number = 2): number {\r\n if (isNaN(Number(num))) {\r\n throw new TypeError(`_toDecimalFloor: ${num} is not a number`);\r\n }\r\n const n = Math.pow(10, decimals);\r\n return Math.floor(Number(num) * n) / n;\r\n}\r\n","/**\r\n * @module 正则\r\n */\r\nimport { REGEXP } from \"@/constants\";\r\n\r\n/* 正则校验方法 */\r\n/**\r\n * 正则校验的方法\r\n * @description 类型为REGEXP对应的正则\r\n * @param {string} value 校验的参数\r\n * @param {RegExp} regex 使用的REGEXP中的正则\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function regexpTest(value: string, regex: RegExp): boolean {\r\n return new RegExp(regex).test(value);\r\n}\r\n\r\n/* 常用校验 */\r\n/**\r\n * 是中文\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isChinese(value: string): boolean {\r\n return regexpTest(value, REGEXP.CH);\r\n}\r\n\r\n/**\r\n * 是英文\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isEnglish(value: string): boolean {\r\n return regexpTest(value, REGEXP.EN);\r\n}\r\n\r\n/**\r\n * 是外链\r\n * @description 支持http,https,mail,tel电话\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isExternal(value: string): boolean {\r\n return regexpTest(value, REGEXP.EXTERNAL);\r\n}\r\n\r\n/**\r\n * 是小写字母\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isLowerCase(value: string): boolean {\r\n return regexpTest(value, REGEXP.LOWER_CASE);\r\n}\r\n\r\n/**\r\n * 是大写字母\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isUpperCase(value: string): boolean {\r\n return regexpTest(value, REGEXP.UPPER_CASE);\r\n}\r\n\r\n/**\r\n * 是11位手机号码\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isMobile(value: string): boolean {\r\n return regexpTest(value, REGEXP.MOBILE);\r\n}\r\n\r\n/**\r\n * 是邮箱\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isEmail(value: string): boolean {\r\n return regexpTest(value, REGEXP.EMAIL);\r\n}\r\n\r\n/**\r\n * 是身份证号码(15-18位)\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isIdCard(value: string): boolean {\r\n return regexpTest(value, REGEXP.ID_CARD);\r\n}\r\n\r\n/**\r\n * 是url链接\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isUrl(value: string): boolean {\r\n return regexpTest(value, REGEXP.URL);\r\n}\r\n","/**\r\n * @module 文件\r\n */\r\nimport { isEmpty } from \"@/validate\";\r\n\r\n/* 文件信息处理 */\r\n/**\r\n * 格式化文件大小自动转为 B,KB,MB,GB\r\n * @param {number} size 文件的大小,单位byte字节\r\n * @returns {string} 返回格式化后的字符串\r\n */\r\nexport function formatFileSize(size: number): string {\r\n if (isEmpty(size)) return \"0B\";\r\n if (size < 1024) {\r\n return size + \"B\";\r\n } else if (size < 1024 * 1024) {\r\n return (size / 1024).toFixed(2) + \"KB\";\r\n } else if (size < 1024 * 1024 * 1024) {\r\n return (size / (1024 * 1024)).toFixed(2) + \"MB\";\r\n } else {\r\n return (size / (1024 * 1024 * 1024)).toFixed(2) + \"GB\";\r\n }\r\n}\r\n\r\n/**\r\n * 获得文件名称\r\n * @param {string} fileName 文件的全名称,例如:测试图片.jpg\r\n * @returns {string} 返回文件的名称\r\n */\r\nexport function getFileName(fileName: string): string | undefined {\r\n if (isEmpty(fileName)) return;\r\n return fileName.substring(0, fileName.lastIndexOf(\".\"));\r\n}\r\n\r\n/**\r\n * 获得文件后缀名\r\n * @param {string} value 文件地址路径或者文件全名称,例如:http://xxx.com/mytest.jpg,测试图片.jpg\r\n * @returns {string} 返回文件后缀名\r\n */\r\nexport function getFileSuffix(value: string): string | undefined {\r\n if (isEmpty(value)) return;\r\n return value.substring(value.lastIndexOf(\".\") + 1).toLowerCase();\r\n}\r\n\r\n/* 文件转换 */\r\n/**\r\n * file转blob\r\n * @param {File} file file文件\r\n * @returns {Promise} 返回Promise的blob\r\n */\r\nexport function fileToBlob(file: File): Promise<Blob> {\r\n return new Promise((resolve, reject) => {\r\n // 读取解析文件\r\n const reader = new FileReader();\r\n reader.readAsArrayBuffer(file);\r\n\r\n // 加载成功\r\n reader.onload = (e) => {\r\n const result = e.target?.result as ArrayBuffer;\r\n const blob = new Blob([result], { type: file.type });\r\n resolve(blob);\r\n };\r\n // 加载失败\r\n reader.onerror = function (err) {\r\n console.error(err);\r\n reject(err);\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * file转base64\r\n * @param {File} file file文件\r\n * @returns {Promise} 返回Promise的base64\r\n */\r\nexport function fileToBase64(file: File): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n // 读取解析文件\r\n const reader = new FileReader();\r\n reader.readAsDataURL(file);\r\n\r\n // 加载成功\r\n reader.onload = function (e) {\r\n const result = e.target?.result as string;\r\n resolve(result);\r\n };\r\n // 加载失败\r\n reader.onerror = function (err) {\r\n console.error(err);\r\n reject(err);\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * file转url\r\n * @description 适用于本地上传图片并预览,需要注意 URL.revokeObjectURL(file) 内存释放\r\n * @param {File} file file文件\r\n * @returns {Promise} 返回Promise的url\r\n */\r\nexport function fileToUrl(file: File): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const url = URL.createObjectURL(file);\r\n resolve(url);\r\n } catch (err) {\r\n // 捕捉异常\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * url赚file\r\n * @param {string} url url地址\r\n * @returns {Promise} 返回Promise的file\r\n */\r\nexport function urlToFile(url: string): Promise<File> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n window &&\r\n window.fetch(url).then((res) => {\r\n if (res.status === 200) {\r\n res.blob().then((blob) => {\r\n blobToFile(blob).then((file) => {\r\n resolve(file);\r\n });\r\n });\r\n }\r\n });\r\n } catch (err) {\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * blob转file\r\n * @param {Blob} blob blob数据\r\n * @param {string} fileName 文件名称,默认以时间戳命名\r\n * @returns {Promise} 返回Promise的file\r\n */\r\nexport function blobToFile(blob: Blob, fileName: string = String(Date.now())): Promise<File> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const mime = blob.type;\r\n const fileSuffix = mime.split(\"/\")[1];\r\n const file = new File([blob], `${Date.now()}.${fileSuffix}`, {\r\n type: mime,\r\n lastModified: Date.now(),\r\n });\r\n resolve(file);\r\n } catch (err) {\r\n // 捕捉异常\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * blob转文本\r\n * @param {Blob} blob blob数据\r\n * @returns {Promise} 返回Promise的文本\r\n */\r\nexport function blobToText(blob: Blob): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = function (e) {\r\n const result = e.target?.result as string;\r\n resolve(result);\r\n };\r\n reader.onerror = function (error) {\r\n reject(error);\r\n };\r\n reader.readAsText(blob);\r\n });\r\n}\r\n\r\n/**\r\n * blob转base64\r\n * @param {Blob} blob blob数据\r\n * @returns {Promise} 返回Promise的base64\r\n */\r\nexport function blobToBase64(blob: Blob): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n // 读取解析文件\r\n const reader = new FileReader();\r\n reader.readAsDataURL(blob);\r\n\r\n // 加载成功\r\n reader.onload = function (e) {\r\n const result = e.target?.result as string;\r\n resolve(result);\r\n };\r\n // 加载失败\r\n reader.onerror = function (err) {\r\n console.error(err);\r\n reject(err);\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * base64转file\r\n * @param {string} base64 base64数据\r\n * @param {string} fileName 文件名称,默认以时间戳命名\r\n * @returns {Promise} 返回Promise的file\r\n */\r\nexport function base64ToFile(base64: string, fileName: string = String(Date.now())): Promise<File> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const arr = base64.split(\",\");\r\n const mimeMatch = arr[0] ? arr[0].match(/:(.+?);/) : null;\r\n const mime = mimeMatch ? mimeMatch[1] : \"\";\r\n const fileSuffix = mime.split(\"/\")[1];\r\n const bstr = window.atob(arr[1]);\r\n let n = bstr.length;\r\n const u8arr = new Uint8Array(n);\r\n while (n--) {\r\n u8arr[n] = bstr.charCodeAt(n);\r\n }\r\n resolve(new File([u8arr], `${fileName}.${fileSuffix}`, { type: mime }));\r\n } catch (err) {\r\n // 捕捉异常\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * base64转成blob\r\n * @param {string} base64 base64数据\r\n * @returns {Promise} 返回Promise的blob\r\n */\r\nexport function base64ToBlob(base64: string): Promise<Blob> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const arr = base64.split(\",\");\r\n const mimeMatch = arr[0] ? arr[0].match(/:(.+?);/) : null;\r\n const mime = mimeMatch ? mimeMatch[1] : \"\";\r\n const bstr = window.atob(arr[1]);\r\n let n = bstr.length;\r\n const u8arr = new Uint8Array(n);\r\n\r\n while (n--) {\r\n u8arr[n] = bstr.charCodeAt(n);\r\n }\r\n resolve(new Blob([u8arr], { type: mime }));\r\n } catch (err) {\r\n // 捕捉异常\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 图片url转base64\r\n * @param {string} imgUrl 图片url地址\r\n * @returns {Promise} 返回Promise的base64\r\n */\r\nexport function urlToBase64(imgUrl: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n // 设置图片\r\n const img = new Image();\r\n img.src = imgUrl;\r\n\r\n // 加载成功\r\n img.onload = function () {\r\n // 画图\r\n const canvas = document.createElement(\"canvas\");\r\n const context = canvas.getContext(\"2d\");\r\n canvas.width = img.width;\r\n canvas.height = img.height;\r\n if (context) {\r\n context.drawImage(img, 0, 0, img.width, img.height);\r\n }\r\n // 转为base64\r\n const base64 = canvas.toDataURL(\"image/png\");\r\n resolve(base64);\r\n };\r\n // 加载失败\r\n img.onerror = function (err) {\r\n console.error(err);\r\n reject(err);\r\n };\r\n });\r\n}\r\n\r\n/* 下载文件 */\r\n/**\r\n * 下载blob格式的文件\r\n * @param {Blob} blob blob数据\r\n * @param {string} fileName 下载的文件名,不写后缀名则默认为原文件类型\r\n */\r\nexport function downloadBlobFile(blob: Blob, fileName: string) {\r\n try {\r\n const objUrl = window.URL.createObjectURL(blob);\r\n const link = window.document.createElement(\"a\");\r\n link.download = fileName;\r\n link.href = objUrl;\r\n link.click();\r\n URL.revokeObjectURL(objUrl);\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n}\r\n\r\n/**\r\n * 通过文件url地址下载\r\n * @param {string} fileUrl url文件地址\r\n * @param {string} fileName 下载的文件名,不写后缀名则默认为原文件类型\r\n */\r\nexport function downloadFileUrl(fileUrl: string, fileName: string) {\r\n try {\r\n const link = window.document.createElement(\"a\");\r\n link.download = fileName;\r\n link.href = fileUrl;\r\n link.target = \"_blank\";\r\n // 生成节点点击\r\n window.document.body.appendChild(link);\r\n link.click();\r\n // 点击后移除节点\r\n window.document.body.removeChild(link);\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n}\r\n","/**\r\n * @module 颜色\r\n */\r\n\r\n/**\r\n * rgb颜色转hex\r\n * @param {string} rgb rgb颜色字符串\r\n * @returns {string} 返回生成的hex颜色\r\n */\r\nexport function rgbToHex(rgb: string): string {\r\n const arr = rgb.split(\",\");\r\n const r = parseInt(arr[0].split(\"(\")[1]);\r\n const g = parseInt(arr[1]);\r\n const b = parseInt(arr[2].split(\")\")[0]);\r\n return \"#\" + _hex(r) + _hex(g) + _hex(b);\r\n}\r\n\r\n/**\r\n * rgba颜色转hex\r\n * @param {string} rgba rgba颜色字符串\r\n * @returns {string} 返回生成的hex颜色\r\n */\r\nexport function rgbaToHex(rgba: string): string {\r\n const arr = rgba.split(\",\");\r\n const r = parseInt(arr[0].split(\"(\")[1]);\r\n const g = parseInt(arr[1]);\r\n const b = parseInt(arr[2]);\r\n const a = parseFloat(arr[3].split(\")\")[0]);\r\n\r\n return `#${_hex(Math.round(a * 256 - 1))}${_hex(r)}${_hex(g)}${_hex(b)}`;\r\n}\r\n\r\n/**\r\n * rgba颜色转hsl\r\n * @param {string} rgba rgb颜色字符串\r\n * @returns {string} 返回生成的hsl颜色\r\n */\r\nexport function rgbaToHsl(rgba: string): string {\r\n const arr = rgba.split(\",\");\r\n const r = parseInt(arr[0].split(\"(\")[1]) / 255;\r\n const g = parseInt(arr[1]) / 255;\r\n const b = parseInt(arr[2]) / 255;\r\n const a = parseFloat(arr[3] && arr[3].split(\")\")[0]);\r\n const max = Math.max(r, g, b),\r\n min = Math.min(r, g, b);\r\n let h = 0,\r\n s = 0;\r\n const l = (max + min) / 2;\r\n if (max === min) {\r\n h = s = 0;\r\n } else {\r\n const d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n if (a) {\r\n return `hsla(${Math.round(h * 360)},${Math.round(s * 100)}%,${Math.round(l * 100)}%,${a})`;\r\n }\r\n return `hsl(${Math.round(h * 360)},${Math.round(s * 100)}%,${Math.round(l * 100)}%)`;\r\n}\r\n\r\n/**\r\n * hex颜色转rgb\r\n * @param {string} hex hex颜色字符串\r\n * @returns {string} 返回生成的rgb颜色\r\n */\r\nexport function hexToRgb(hex: string): string {\r\n const color = { r: 0, g: 0, b: 0, o: 0 };\r\n const rgx = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\r\n const hexStr = hex.replace(rgx, function (m, r, g, b) {\r\n return r + r + g + g + b + b;\r\n });\r\n const rgb = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hexStr);\r\n if (!rgb) {\r\n throw new TypeError(`hexToRgb: invalid hex color: ${hex}`);\r\n }\r\n color.r = parseInt(rgb[1], 16);\r\n color.g = parseInt(rgb[2], 16);\r\n color.b = parseInt(rgb[3], 16);\r\n return `rgb(${color.r},${color.g},${color.b})`;\r\n}\r\n\r\n/**\r\n * hex颜色转rgba\r\n * @param {string} hex hex颜色字符串\r\n * @param {number} opacity 透明度\r\n * @returns {string} 返回生成的rgba颜色\r\n */\r\nexport function hexToRgba(hex: string, opacity: number = 1): string {\r\n const color = { r: 0, g: 0, b: 0, o: 0 };\r\n const rgx = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\r\n const hexStr = hex.replace(rgx, function (m, r, g, b) {\r\n return r + r + g + g + b + b;\r\n });\r\n const rgb = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hexStr);\r\n if (!rgb) {\r\n throw new TypeError(`hexToRgba: invalid hex color: ${hex}`);\r\n }\r\n color.r = parseInt(rgb[1], 16);\r\n color.g = parseInt(rgb[2], 16);\r\n color.b = parseInt(rgb[3], 16);\r\n color.o = opacity;\r\n return `rgba(${color.r},${color.g},${color.b},${color.o})`;\r\n}\r\n\r\n/**\r\n * hex颜色转hsl\r\n * @param {string} hex hex颜色字符串\r\n * @returns {string} 返回生成的hsl颜色\r\n */\r\nexport function hexToHsl(hex: string): string {\r\n // 先解析为rgb\r\n const rgx = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\r\n const hexStr = hex.replace(rgx, function (m, r, g, b) {\r\n return r + r + g + g + b + b;\r\n });\r\n const rgb = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hexStr);\r\n if (!rgb) {\r\n throw new TypeError(`hexToHsl: invalid hex color: ${hex}`);\r\n }\r\n\r\n // 再组装为hsl格式\r\n const r = parseInt(rgb[1], 16) / 255;\r\n const g = parseInt(rgb[2], 16) / 255;\r\n const b = parseInt(rgb[3], 16) / 255;\r\n const max = Math.max(r, g, b),\r\n min = Math.min(r, g, b);\r\n let h = 0,\r\n s = 0;\r\n const l = (max + min) / 2;\r\n if (max === min) {\r\n h = s = 0;\r\n } else {\r\n const d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n return `hsl(${Math.round(h * 360)},${Math.round(s * 100)}%,${Math.round(l * 100)}%)`;\r\n}\r\n\r\n/**\r\n * 随机生成hex颜色\r\n * @returns {string} 返回生成的十六进制颜色\r\n */\r\nexport function getDrawHex(): string {\r\n return (\r\n \"#\" +\r\n (function (h) {\r\n return new Array(7 - h.length).join(\"0\") + h;\r\n })(((Math.random() * 0x1000000) << 0).toString(16))\r\n );\r\n}\r\n\r\n/**\r\n * 随机生成rgb颜色\r\n * @returns {string} 返回生成的 rgb 颜色\r\n */\r\nexport function getDrawRgb(): string {\r\n const r = Math.floor(Math.random() * 256);\r\n const g = Math.floor(Math.random() * 256);\r\n const b = Math.floor(Math.random() * 256);\r\n return `rgb(${r},${g},${b})`;\r\n}\r\n\r\n/**\r\n * 随机生成rgba颜色\r\n * @returns {string} 返回生成的 rgba 颜色\r\n */\r\nexport function getDrawRgba(): string {\r\n const r = Math.floor(Math.random() * 256);\r\n const g = Math.floor(Math.random() * 256);\r\n const b = Math.floor(Math.random() * 256);\r\n const a = Number(Math.random()).toFixed(2);\r\n return `rgba(${r},${g},${b},${a})`;\r\n}\r\n\r\n// 内部函数\r\n/**\r\n * 颜色值转换\r\n * @param {number} num 转换的值\r\n * @returns {string} 返回计算\r\n */\r\nfunction _hex(num: number): string {\r\n if (num > 255) {\r\n throw \"'\" + num + \"'' is greater than 255(0xff);\";\r\n }\r\n const str = Number(num).toString(16);\r\n return (\"0\" + str).slice(-2);\r\n}\r\n","/*\r\n * base64加解密\r\n * 高性能、高健壮性、纯JS实现,兼容Node/浏览器/Worker\r\n */\r\n\r\n// 核心常量定义\r\nconst ENCODING_ERROR = \"not a UTF-8 string\";\r\nconst BASE64_ENCODE_CHAR = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\".split(\"\");\r\nconst BASE64_DECODE_CHAR = {};\r\nfor (let i = 0; i < 64; ++i) {\r\n BASE64_DECODE_CHAR[BASE64_ENCODE_CHAR[i]] = i;\r\n}\r\n// 兼容URL安全的Base64\r\nBASE64_DECODE_CHAR[\"-\"] = 62;\r\nBASE64_DECODE_CHAR[\"_\"] = 63;\r\n\r\n// ======================== 精简版环境判断(核心场景全覆盖,保留!)========================\r\nconst isNodeEnv = typeof process === \"object\" && process.versions && process.versions.node;\r\nconst isBrowserEnv = typeof window === \"object\" && typeof window.btoa === \"function\";\r\nconst root = isNodeEnv ? global : typeof self === \"object\" ? self : window;\r\n\r\n// ======================== 核心工具函数(全部保留,原生API更快!)========================\r\n/**\r\n * 清理Base64字符串(移除等号、换行符、非法字符)\r\n */\r\nconst cleanBase64Str = function (base64Str) {\r\n return base64Str\r\n .split(\"=\")[0]\r\n .replace(/[\\r\\n]/g, \"\")\r\n .replace(/[^A-Za-z0-9+/=_-]/g, \"\"); // 过滤非法字符\r\n};\r\n\r\n/**\r\n * UTF-8字符串转字节数组(性能优化版)\r\n */\r\nconst utf8ToBytes = function (str) {\r\n const len = str.length; // 缓存长度,减少属性访问\r\n const bytes = new Array(len * 4); // 预分配最大可能长度(避免频繁扩容)\r\n let byteIndex = 0;\r\n\r\n for (let i = 0; i < len; i++) {\r\n const c = str.charCodeAt(i);\r\n if (c < 0x80) {\r\n bytes[byteIndex++] = c;\r\n } else if (c < 0x800) {\r\n bytes[byteIndex++] = 0xc0 | (c >> 6);\r\n bytes[byteIndex++] = 0x80 | (c & 0x3f);\r\n } else if (c < 0xd800 || c >= 0xe000) {\r\n bytes[byteIndex++] = 0xe0 | (c >> 12);\r\n bytes[byteIndex++] = 0x80 | ((c >> 6) & 0x3f);\r\n bytes[byteIndex++] = 0x80 | (c & 0x3f);\r\n } else {\r\n // 处理代理对\r\n const code = 0x10000 + (((c & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));\r\n bytes[byteIndex++] = 0xf0 | (code >> 18);\r\n bytes[byteIndex++] = 0x80 | ((code >> 12) & 0x3f);\r\n bytes[byteIndex++] = 0x80 | ((code >> 6) & 0x3f);\r\n bytes[byteIndex++] = 0x80 | (code & 0x3f);\r\n }\r\n }\r\n\r\n // 截断数组到实际长度\r\n return bytes.slice(0, byteIndex);\r\n};\r\n\r\n/**\r\n * Base64字符串解码为字节数组(性能优化版)\r\n */\r\nconst decodeAsBytes = function (base64Str) {\r\n // 空值快速返回\r\n if (!base64Str) return [];\r\n\r\n base64Str = cleanBase64Str(base64Str);\r\n const len = base64Str.length;\r\n const count = (len >> 2) << 2;\r\n // 预计算最大长度:3/4 * 总字符数,减少数组扩容\r\n const bytes = new Array(Math.floor((len * 3) / 4));\r\n let byteIndex = 0;\r\n let i = 0; // 把i的作用域提升到函数级,确保后续能访问\r\n\r\n // 4字符转3字节\r\n for (; i < count; ) {\r\n const v1 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v2 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v3 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v4 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n\r\n bytes[byteIndex++] = ((v1 << 2) | (v2 >>> 4)) & 255;\r\n bytes[byteIndex++] = ((v2 << 4) | (v3 >>> 2)) & 255;\r\n bytes[byteIndex++] = ((v3 << 6) | v4) & 255;\r\n }\r\n\r\n // 处理剩余字符(此时i的作用域有效)\r\n const remain = len - count;\r\n if (remain === 2) {\r\n const v1 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v2 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n bytes[byteIndex++] = ((v1 << 2) | (v2 >>> 4)) & 255;\r\n } else if (remain === 3) {\r\n const v1 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v2 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v3 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n bytes[byteIndex++] = ((v1 << 2) | (v2 >>> 4)) & 255;\r\n bytes[byteIndex++] = ((v2 << 4) | (v3 >>> 2)) & 255;\r\n }\r\n\r\n // 截断数组到实际长度\r\n return bytes.slice(0, byteIndex);\r\n};\r\n\r\n/**\r\n * 抽离公共逻辑:字节数组转Base64字符(减少代码冗余)\r\n */\r\nconst bytesToBase64Chars = function (bytes) {\r\n const len = bytes.length;\r\n const count = Math.floor(len / 3) * 3;\r\n const base64Str = new Array(Math.ceil((len * 4) / 3)); // 预分配长度\r\n let strIndex = 0;\r\n\r\n // 3字节转4字符\r\n for (let i = 0; i < count; ) {\r\n const v1 = bytes[i++];\r\n const v2 = bytes[i++];\r\n const v3 = bytes[i++];\r\n\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[v1 >>> 2];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[((v1 << 4) | (v2 >>> 4)) & 63];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[((v2 << 2) | (v3 >>> 6)) & 63];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[v3 & 63];\r\n }\r\n\r\n // 处理剩余字节\r\n const remain = len - count;\r\n if (remain === 1) {\r\n const v1 = bytes[count];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[v1 >>> 2];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[(v1 << 4) & 63];\r\n base64Str[strIndex++] = \"=\";\r\n base64Str[strIndex++] = \"=\";\r\n } else if (remain === 2) {\r\n const v1 = bytes[count];\r\n const v2 = bytes[count + 1];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[v1 >>> 2];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[((v1 << 4) | (v2 >>> 4)) & 63];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[(v2 << 2) & 63];\r\n base64Str[strIndex++] = \"=\";\r\n }\r\n\r\n return base64Str.join(\"\");\r\n};\r\n\r\n/**\r\n * 字节数组编码为Base64字符串(复用公共逻辑)\r\n */\r\nlet encodeFromBytes = function (bytes) {\r\n // 空值快速返回\r\n if (!bytes || bytes.length === 0) return \"\";\r\n return bytesToBase64Chars(bytes);\r\n};\r\n\r\n// ======================== 环境适配的btoa/atob实现(全部保留,原生更快!)=======================\r\nlet btoa = root.btoa;\r\nlet atob = root.atob;\r\nlet utf8Base64Encode;\r\nlet utf8Base64Decode;\r\n// 1. Node.js环境(纯JS实现,不使用require)\r\nif (isNodeEnv) {\r\n // 纯JS版btoa(替代Buffer实现)\r\n btoa = function (str) {\r\n if (!str) return \"\";\r\n const bytes = Array.from(str).map((c) => c.charCodeAt(0));\r\n return bytesToBase64Chars(bytes);\r\n };\r\n\r\n // 纯JS版atob\r\n atob = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n const bytes = decodeAsBytes(base64Str);\r\n return String.fromCharCode.apply(null, bytes);\r\n };\r\n\r\n // 纯JS版UTF8编码/解码(和浏览器环境保持一致)\r\n utf8Base64Encode = function (str) {\r\n if (!str) return \"\";\r\n const bytes = utf8ToBytes(str);\r\n return bytesToBase64Chars(bytes);\r\n };\r\n\r\n utf8Base64Decode = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n\r\n const bytes = decodeAsBytes(base64Str);\r\n const str = [];\r\n const len = bytes.length;\r\n let i = 0;\r\n\r\n while (i < len) {\r\n const b = bytes[i++];\r\n if (b <= 0x7f) {\r\n str.push(String.fromCharCode(b));\r\n continue;\r\n }\r\n\r\n let c, followingChars;\r\n if (b > 0xbf && b <= 0xdf) {\r\n c = b & 0x1f;\r\n followingChars = 1;\r\n } else if (b <= 0xef) {\r\n c = b & 0x0f;\r\n followingChars = 2;\r\n } else if (b <= 0xf7) {\r\n c = b & 0x07;\r\n followingChars = 3;\r\n } else {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n\r\n // 校验后续字节合法性\r\n for (let j = 0; j < followingChars; ++j) {\r\n const byte = bytes[i++];\r\n if (i > len || byte < 0x80 || byte > 0xbf) {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n c = (c << 6) + (byte & 0x3f);\r\n }\r\n\r\n // 校验Unicode范围\r\n if (c >= 0xd800 && c <= 0xdfff) throw new Error(ENCODING_ERROR);\r\n if (c > 0x10ffff) throw new Error(ENCODING_ERROR);\r\n\r\n // 转换为字符\r\n if (c <= 0xffff) {\r\n str.push(String.fromCharCode(c));\r\n } else {\r\n c -= 0x10000;\r\n str.push(String.fromCharCode((c >> 10) + 0xd800), String.fromCharCode((c & 0x3ff) + 0xdc00));\r\n }\r\n }\r\n\r\n return str.join(\"\");\r\n };\r\n\r\n // 2. 无原生btoa/atob的环境(老旧浏览器/Worker)\r\n} else if (!isBrowserEnv) {\r\n // 纯JS版btoa(复用公共逻辑)\r\n btoa = function (str) {\r\n if (!str) return \"\";\r\n const bytes = Array.from(str).map((c) => c.charCodeAt(0));\r\n return bytesToBase64Chars(bytes);\r\n };\r\n\r\n // 纯JS版atob\r\n atob = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n const bytes = decodeAsBytes(base64Str);\r\n return String.fromCharCode.apply(null, bytes);\r\n };\r\n\r\n // 纯JS版UTF8编码/解码\r\n utf8Base64Encode = function (str) {\r\n if (!str) return \"\";\r\n const bytes = utf8ToBytes(str);\r\n return bytesToBase64Chars(bytes);\r\n };\r\n\r\n utf8Base64Decode = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n\r\n const bytes = decodeAsBytes(base64Str);\r\n const str = [];\r\n const len = bytes.length;\r\n let i = 0;\r\n\r\n while (i < len) {\r\n const b = bytes[i++];\r\n if (b <= 0x7f) {\r\n str.push(String.fromCharCode(b));\r\n continue;\r\n }\r\n\r\n let c, followingChars;\r\n if (b > 0xbf && b <= 0xdf) {\r\n c = b & 0x1f;\r\n followingChars = 1;\r\n } else if (b <= 0xef) {\r\n c = b & 0x0f;\r\n followingChars = 2;\r\n } else if (b <= 0xf7) {\r\n c = b & 0x07;\r\n followingChars = 3;\r\n } else {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n\r\n // 校验后续字节合法性\r\n for (let j = 0; j < followingChars; ++j) {\r\n const byte = bytes[i++];\r\n if (i > len || byte < 0x80 || byte > 0xbf) {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n c = (c << 6) + (byte & 0x3f);\r\n }\r\n\r\n // 校验Unicode范围\r\n if (c >= 0xd800 && c <= 0xdfff) throw new Error(ENCODING_ERROR);\r\n if (c > 0x10ffff) throw new Error(ENCODING_ERROR);\r\n\r\n // 转换为字符\r\n if (c <= 0xffff) {\r\n str.push(String.fromCharCode(c));\r\n } else {\r\n c -= 0x10000;\r\n str.push(String.fromCharCode((c >> 10) + 0xd800), String.fromCharCode((c & 0x3ff) + 0xdc00));\r\n }\r\n }\r\n\r\n return str.join(\"\");\r\n };\r\n\r\n // 3. 浏览器原生支持btoa/atob\r\n} else {\r\n utf8Base64Encode = function (str) {\r\n if (!str) return \"\";\r\n\r\n const result = [];\r\n const len = str.length;\r\n for (let i = 0; i < len; i++) {\r\n const charcode = str.charCodeAt(i);\r\n if (charcode < 0x80) {\r\n result.push(String.fromCharCode(charcode));\r\n } else if (charcode < 0x800) {\r\n result.push(String.fromCharCode(0xc0 | (charcode >> 6)), String.fromCharCode(0x80 | (charcode & 0x3f)));\r\n } else if (charcode < 0xd800 || charcode >= 0xe000) {\r\n result.push(\r\n String.fromCharCode(0xe0 | (charcode >> 12)),\r\n String.fromCharCode(0x80 | ((charcode >> 6) & 0x3f)),\r\n String.fromCharCode(0x80 | (charcode & 0x3f)),\r\n );\r\n } else {\r\n const code = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));\r\n result.push(\r\n String.fromCharCode(0xf0 | (code >> 18)),\r\n String.fromCharCode(0x80 | ((code >> 12) & 0x3f)),\r\n String.fromCharCode(0x80 | ((code >> 6) & 0x3f)),\r\n String.fromCharCode(0x80 | (code & 0x3f)),\r\n );\r\n }\r\n }\r\n return btoa(result.join(\"\"));\r\n };\r\n\r\n utf8Base64Decode = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n\r\n const tmpStr = atob(base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\"));\r\n // 替换Unicode转义,避免ESLint控制字符警告\r\n // eslint-disable-next-line no-control-regex\r\n if (!/[^\\u0000-\\u007F]/.test(tmpStr)) {\r\n return tmpStr;\r\n }\r\n\r\n const str = [];\r\n const len = tmpStr.length;\r\n let i = 0;\r\n\r\n while (i < len) {\r\n const b = tmpStr.charCodeAt(i++);\r\n if (b <= 0x7f) {\r\n str.push(String.fromCharCode(b));\r\n continue;\r\n }\r\n\r\n let c, followingChars;\r\n if (b > 0xbf && b <= 0xdf) {\r\n c = b & 0x1f;\r\n followingChars = 1;\r\n } else if (b <= 0xef) {\r\n c = b & 0x0f;\r\n followingChars = 2;\r\n } else if (b <= 0xf7) {\r\n c = b & 0x07;\r\n followingChars = 3;\r\n } else {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n\r\n for (let j = 0; j < followingChars; ++j) {\r\n const byte = tmpStr.charCodeAt(i++);\r\n if (i > len || byte < 0x80 || byte > 0xbf) throw new Error(ENCODING_ERROR);\r\n c = (c << 6) + (byte & 0x3f);\r\n }\r\n\r\n if (c >= 0xd800 && c <= 0xdfff) throw new Error(ENCODING_ERROR);\r\n if (c > 0x10ffff) throw new Error(ENCODING_ERROR);\r\n\r\n if (c <= 0xffff) {\r\n str.push(String.fromCharCode(c));\r\n } else {\r\n c -= 0x10000;\r\n str.push(String.fromCharCode((c >> 10) + 0xd800), String.fromCharCode((c & 0x3ff) + 0xdc00));\r\n }\r\n }\r\n\r\n return str.join(\"\");\r\n };\r\n}\r\n\r\n// ======================== 类型转换工具函数(全部保留)========================\r\n/**\r\n * Uint8Array转Base64字符串\r\n * @param {Uint8Array} uint8Array 字节数组\r\n * @param {boolean} [urlSafe=false] 是否URL安全\r\n * @returns {string} Base64字符串\r\n */\r\nexport const fromUint8Array = function (uint8Array, urlSafe = false) {\r\n if (!(uint8Array instanceof Uint8Array)) {\r\n throw new TypeError(\"fromUint8Array: input must be Uint8Array\");\r\n }\r\n const bytes = Array.from(uint8Array);\r\n let result = bytesToBase64Chars(bytes);\r\n if (urlSafe) {\r\n result = result.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Base64字符串转Uint8Array\r\n * @param {string} base64Str Base64字符串\r\n * @param {boolean} [urlSafe=false] 是否URL安全\r\n * @returns {Uint8Array} 字节数组\r\n */\r\nexport const toUint8Array = function (base64Str, urlSafe = false) {\r\n if (typeof base64Str !== \"string\") {\r\n throw new TypeError(\"toUint8Array: input must be string\");\r\n }\r\n // 处理URL安全字符\r\n if (urlSafe) {\r\n base64Str = base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\");\r\n }\r\n const bytes = decodeAsBytes(base64Str);\r\n return new Uint8Array(bytes);\r\n};\r\n\r\n/**\r\n * 十六进制字符串转Base64字符串\r\n * @param {string} hexStr 十六进制字符串\r\n * @param {boolean} [urlSafe=false] 是否URL安全\r\n * @returns {string} Base64字符串\r\n */\r\nexport const fromHex = function (hexStr, urlSafe = false) {\r\n if (typeof hexStr !== \"string\" || !/^[0-9a-fA-F]+$/.test(hexStr)) {\r\n throw new TypeError(\"fromHex: input must be hex string\");\r\n }\r\n // 补全偶数长度\r\n const str = hexStr.length % 2 ? `0${hexStr}` : hexStr;\r\n const bytes = new Array(str.length / 2);\r\n for (let i = 0; i < bytes.length; i++) {\r\n bytes[i] = parseInt(str.substr(i * 2, 2), 16);\r\n }\r\n let result = bytesToBase64Chars(bytes);\r\n if (urlSafe) {\r\n result = result.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Base64字符串转十六进制字符串\r\n * @param {string} base64Str Base64字符串\r\n * @param {boolean} [urlSafe=false] 是否URL安全\r\n * @returns {string} 十六进制字符串\r\n */\r\nexport const toHex = function (base64Str, urlSafe = false) {\r\n if (typeof base64Str !== \"string\") {\r\n throw new TypeError(\"toHex: input must be string\");\r\n }\r\n // 处理URL安全字符\r\n if (urlSafe) {\r\n base64Str = base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\");\r\n }\r\n const bytes = decodeAsBytes(base64Str);\r\n return Array.from(bytes)\r\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n};\r\n\r\n// ======================== 核心方法(仅删除asciiOnly开关,默认UTF8)========================\r\n/**\r\n * Base64编码(高性能、高健壮性版,默认UTF8)\r\n * @param {string | number[] | Uint8Array | ArrayBuffer} data 待编码数据\r\n * @param {boolean} [urlSafe=false] 是否生成URL安全的Base64\r\n * @returns {string} Base64字符串\r\n */\r\nexport const encode = function (data, urlSafe = false) {\r\n // 空值快速返回\r\n if (data == null) return \"\";\r\n\r\n const notString = typeof data !== \"string\";\r\n let result = \"\";\r\n\r\n if (notString) {\r\n // 处理ArrayBuffer\r\n if (data.constructor === root.ArrayBuffer) {\r\n data = new Uint8Array(data);\r\n }\r\n // 处理字节数组/Uint8Array\r\n result = encodeFromBytes(data);\r\n } else {\r\n // 空字符串快速返回\r\n if (data === \"\") return \"\";\r\n // 强制走UTF8编码(删掉asciiOnly判断,直接用utf8Base64Encode)\r\n result = utf8Base64Encode(data);\r\n }\r\n\r\n // URL安全处理:替换+->-,/->_,去掉=\r\n if (urlSafe) {\r\n result = result.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Base64解码(高性能、高健壮性版,默认UTF8)\r\n * @param {string} base64Str 待解码的Base64字符串\r\n * @returns {string} 解码后的UTF8字符串\r\n */\r\nexport const decode = function (base64Str) {\r\n // 空值快速返回\r\n if (base64Str == null || base64Str === \"\") return \"\";\r\n\r\n // 处理URL安全的Base64\r\n base64Str = base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\");\r\n base64Str = cleanBase64Str(base64Str);\r\n\r\n // 强制走UTF8解码(删掉asciiOnly判断,直接用utf8Base64Decode)\r\n return utf8Base64Decode(base64Str);\r\n};\r\n\r\n// ======================== URL安全专用方法(同步删除asciiOnly开关)========================\r\n/**\r\n * URL安全Base64编码(专用方法,等价于encode(data, true))\r\n * @param {string | number[] | Uint8Array | ArrayBuffer} data 待编码数据\r\n * @returns {string} URL安全的Base64字符串\r\n */\r\nexport const encodeURI = function (data) {\r\n return encode(data, true);\r\n};\r\n\r\n/**\r\n * URL安全Base64解码(专用方法,兼容URL安全字符)\r\n * @param {string} base64Str URL安全的Base64字符串\r\n * @returns {string} 解码后的UTF8字符串\r\n */\r\nexport const decodeURI = function (base64Str) {\r\n return decode(base64Str);\r\n};\r\n","/**\r\n * Add integers, wrapping at 2^32.\r\n * This uses 16-bit operations internally to work around bugs in interpreters.\r\n *\r\n * @param {number} x First integer\r\n * @param {number} y Second integer\r\n * @returns {number} Sum\r\n */\r\nfunction safeAdd(x, y) {\r\n var lsw = (x & 0xffff) + (y & 0xffff);\r\n var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\r\n return (msw << 16) | (lsw & 0xffff);\r\n}\r\n\r\n/**\r\n * Bitwise rotate a 32-bit number to the left.\r\n *\r\n * @param {number} num 32-bit number\r\n * @param {number} cnt Rotation count\r\n * @returns {number} Rotated number\r\n */\r\nfunction bitRotateLeft(num, cnt) {\r\n return (num << cnt) | (num >>> (32 - cnt));\r\n}\r\n\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} q q\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5cmn(q, a, b, x, s, t) {\r\n return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\r\n}\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} c c\r\n * @param {number} d d\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5ff(a, b, c, d, x, s, t) {\r\n return md5cmn((b & c) | (~b & d), a, b, x, s, t);\r\n}\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} c c\r\n * @param {number} d d\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5gg(a, b, c, d, x, s, t) {\r\n return md5cmn((b & d) | (c & ~d), a, b, x, s, t);\r\n}\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} c c\r\n * @param {number} d d\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5hh(a, b, c, d, x, s, t) {\r\n return md5cmn(b ^ c ^ d, a, b, x, s, t);\r\n}\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} c c\r\n * @param {number} d d\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5ii(a, b, c, d, x, s, t) {\r\n return md5cmn(c ^ (b | ~d), a, b, x, s, t);\r\n}\r\n\r\n/**\r\n * Calculate the MD5 of an array of little-endian words, and a bit length.\r\n *\r\n * @param {Array} x Array of little-endian words\r\n * @param {number} len Bit length\r\n * @returns {Array<number>} MD5 Array\r\n */\r\nfunction binlMD5(x, len) {\r\n /* append padding */\r\n x[len >> 5] |= 0x80 << (len % 32);\r\n x[(((len + 64) >>> 9) << 4) + 14] = len;\r\n\r\n var i;\r\n var olda;\r\n var oldb;\r\n var oldc;\r\n var oldd;\r\n var a = 1732584193;\r\n var b = -271733879;\r\n var c = -1732584194;\r\n var d = 271733878;\r\n\r\n for (i = 0; i < x.length; i += 16) {\r\n olda = a;\r\n oldb = b;\r\n oldc = c;\r\n oldd = d;\r\n\r\n a = md5ff(a, b, c, d, x[i], 7, -680876936);\r\n d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);\r\n c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);\r\n b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);\r\n a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);\r\n d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);\r\n c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);\r\n b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);\r\n a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);\r\n d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);\r\n c = md5ff(c, d, a, b, x[i + 10], 17, -42063);\r\n b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);\r\n a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);\r\n d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);\r\n c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);\r\n b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);\r\n\r\n a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);\r\n d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);\r\n c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);\r\n b = md5gg(b, c, d, a, x[i], 20, -373897302);\r\n a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);\r\n d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);\r\n c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);\r\n b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);\r\n a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);\r\n d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);\r\n c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);\r\n b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);\r\n a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);\r\n d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);\r\n c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);\r\n b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);\r\n\r\n a = md5hh(a, b, c, d, x[i + 5], 4, -378558);\r\n d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);\r\n c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);\r\n b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);\r\n a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);\r\n d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);\r\n c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);\r\n b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);\r\n a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);\r\n d = md5hh(d, a, b, c, x[i], 11, -358537222);\r\n c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);\r\n b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);\r\n a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);\r\n d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);\r\n c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);\r\n b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);\r\n\r\n a = md5ii(a, b, c, d, x[i], 6, -198630844);\r\n d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);\r\n c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);\r\n b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);\r\n a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);\r\n d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);\r\n c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);\r\n b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);\r\n a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);\r\n d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);\r\n c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);\r\n b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);\r\n a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);\r\n d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);\r\n c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);\r\n b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);\r\n\r\n a = safeAdd(a, olda);\r\n b = safeAdd(b, oldb);\r\n c = safeAdd(c, oldc);\r\n d = safeAdd(d, oldd);\r\n }\r\n return [a, b, c, d];\r\n}\r\n\r\n/**\r\n * Convert an array of little-endian words to a string\r\n *\r\n * @param {Array<number>} input MD5 Array\r\n * @returns {string} MD5 string\r\n */\r\nfunction binl2rstr(input) {\r\n var i;\r\n var output = \"\";\r\n var length32 = input.length * 32;\r\n for (i = 0; i < length32; i += 8) {\r\n output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff);\r\n }\r\n return output;\r\n}\r\n\r\n/**\r\n * Convert a raw string to an array of little-endian words\r\n * Characters >255 have their high-byte silently ignored.\r\n *\r\n * @param {string} input Raw input string\r\n * @returns {Array<number>} Array of little-endian words\r\n */\r\nfunction rstr2binl(input) {\r\n var i;\r\n var output = [];\r\n output[(input.length >> 2) - 1] = undefined;\r\n for (i = 0; i < output.length; i += 1) {\r\n output[i] = 0;\r\n }\r\n var length8 = input.length * 8;\r\n for (i = 0; i < length8; i += 8) {\r\n output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32);\r\n }\r\n return output;\r\n}\r\n\r\n/**\r\n * Calculate the MD5 of a raw string\r\n *\r\n * @param {string} s Input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction rstrMD5(s) {\r\n return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));\r\n}\r\n\r\n/**\r\n * Calculates the HMAC-MD5 of a key and some data (raw strings)\r\n *\r\n * @param {string} key HMAC key\r\n * @param {string} data Raw input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction rstrHMACMD5(key, data) {\r\n var i;\r\n var bkey = rstr2binl(key);\r\n var ipad = [];\r\n var opad = [];\r\n var hash;\r\n ipad[15] = opad[15] = undefined;\r\n if (bkey.length > 16) {\r\n bkey = binlMD5(bkey, key.length * 8);\r\n }\r\n for (i = 0; i < 16; i += 1) {\r\n ipad[i] = bkey[i] ^ 0x36363636;\r\n opad[i] = bkey[i] ^ 0x5c5c5c5c;\r\n }\r\n hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);\r\n return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));\r\n}\r\n\r\n/**\r\n * Convert a raw string to a hex string\r\n *\r\n * @param {string} input Raw input string\r\n * @returns {string} Hex encoded string\r\n */\r\nfunction rstr2hex(input) {\r\n var hexTab = \"0123456789abcdef\";\r\n var output = \"\";\r\n var x;\r\n var i;\r\n for (i = 0; i < input.length; i += 1) {\r\n x = input.charCodeAt(i);\r\n output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);\r\n }\r\n return output;\r\n}\r\n\r\n/**\r\n * Encode a string as UTF-8\r\n *\r\n * @param {string} input Input string\r\n * @returns {string} UTF8 string\r\n */\r\nfunction str2rstrUTF8(input) {\r\n return unescape(encodeURIComponent(input));\r\n}\r\n\r\n/**\r\n * Encodes input string as raw MD5 string\r\n *\r\n * @param {string} s Input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction rawMD5(s) {\r\n return rstrMD5(str2rstrUTF8(s));\r\n}\r\n/**\r\n * Encodes input string as Hex encoded string\r\n *\r\n * @param {string} s Input string\r\n * @returns {string} Hex encoded string\r\n */\r\nfunction hexMD5(s) {\r\n return rstr2hex(rawMD5(s));\r\n}\r\n/**\r\n * Calculates the raw HMAC-MD5 for the given key and data\r\n *\r\n * @param {string} k HMAC key\r\n * @param {string} d Input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction rawHMACMD5(k, d) {\r\n return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));\r\n}\r\n/**\r\n * Calculates the Hex encoded HMAC-MD5 for the given key and data\r\n *\r\n * @param {string} k HMAC key\r\n * @param {string} d Input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction hexHMACMD5(k, d) {\r\n return rstr2hex(rawHMACMD5(k, d));\r\n}\r\n\r\n/**\r\n * Calculates MD5 value for a given string.\r\n * If a key is provided, calculates the HMAC-MD5 value.\r\n * Returns a Hex encoded string unless the raw argument is given.\r\n *\r\n * @param {string} string Input string\r\n * @param {string} [key] HMAC key\r\n * @param {boolean} [raw] Raw output switch\r\n * @returns {string} MD5 output\r\n */\r\nfunction md5(string, key, raw) {\r\n if (!key) {\r\n if (!raw) {\r\n return hexMD5(string);\r\n }\r\n return rawMD5(string);\r\n }\r\n if (!raw) {\r\n return hexHMACMD5(key, string);\r\n }\r\n return rawHMACMD5(key, string);\r\n}\r\n\r\n/* 以下是内部实现需要的es模块化导出方法 */\r\nexport { md5 };\r\n","/**\r\n * 纯前端 SHA256/SHA224 实现(无 Node.js 依赖,兼容所有浏览器)\r\n * 核心逻辑借鉴 js-sha256,移除所有服务端相关代码,仅保留浏览器环境实现\r\n */\r\n\r\n// ========== 核心常量 ==========\r\nconst ERROR = \"input is invalid type\";\r\nconst HEX_CHARS = \"0123456789abcdef\".split(\"\");\r\nconst EXTRA = [-2147483648, 8388608, 32768, 128];\r\nconst SHIFT = [24, 16, 8, 0];\r\n// SHA256 常量 K\r\nconst K = [\r\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98,\r\n 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\r\n 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8,\r\n 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\r\n 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,\r\n 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\r\n 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,\r\n 0xc67178f2,\r\n];\r\n\r\n// ========== SHA256 核心类 ==========\r\nclass Sha256 {\r\n constructor(is224 = false) {\r\n // 初始化区块数组(仅浏览器环境,无需共享内存)\r\n this.blocks = new Array(17).fill(0);\r\n\r\n // 初始化哈希值(SHA224/SHA256 不同初始值)\r\n if (is224) {\r\n this.h0 = 0xc1059ed8;\r\n this.h1 = 0x367cd507;\r\n this.h2 = 0x3070dd17;\r\n this.h3 = 0xf70e5939;\r\n this.h4 = 0xffc00b31;\r\n this.h5 = 0x68581511;\r\n this.h6 = 0x64f98fa7;\r\n this.h7 = 0xbefa4fa4;\r\n } else {\r\n this.h0 = 0x6a09e667;\r\n this.h1 = 0xbb67ae85;\r\n this.h2 = 0x3c6ef372;\r\n this.h3 = 0xa54ff53a;\r\n this.h4 = 0x510e527f;\r\n this.h5 = 0x9b05688c;\r\n this.h6 = 0x1f83d9ab;\r\n this.h7 = 0x5be0cd19;\r\n }\r\n\r\n // 状态变量初始化\r\n this.block = this.start = this.bytes = this.hBytes = 0;\r\n this.finalized = this.hashed = false;\r\n this.first = true;\r\n this.is224 = is224;\r\n }\r\n\r\n // 更新哈希(处理输入数据)\r\n update(message) {\r\n if (this.finalized) return this;\r\n\r\n // 校验输入类型\r\n let notString = false;\r\n const type = typeof message;\r\n if (type !== \"string\") {\r\n if (type === \"object\") {\r\n if (message === null) throw new Error(ERROR);\r\n // 支持 ArrayBuffer/Uint8Array\r\n if (message.constructor === ArrayBuffer) {\r\n message = new Uint8Array(message);\r\n } else if (!Array.isArray(message) && !ArrayBuffer.isView(message)) {\r\n throw new Error(ERROR);\r\n }\r\n } else {\r\n throw new Error(ERROR);\r\n }\r\n notString = true;\r\n }\r\n\r\n let code,\r\n index = 0,\r\n i,\r\n length = message.length;\r\n const blocks = this.blocks;\r\n\r\n while (index < length) {\r\n if (this.hashed) {\r\n this.hashed = false;\r\n blocks.fill(0);\r\n blocks[0] = this.block;\r\n }\r\n\r\n // 处理字符串/字节数组\r\n if (notString) {\r\n for (i = this.start; index < length && i < 64; ++index) {\r\n blocks[i >>> 2] |= message[index] << SHIFT[i++ & 3];\r\n }\r\n } else {\r\n for (i = this.start; index < length && i < 64; ++index) {\r\n code = message.charCodeAt(index);\r\n // UTF-8 编码处理\r\n if (code < 0x80) {\r\n blocks[i >>> 2] |= code << SHIFT[i++ & 3];\r\n } else if (code < 0x800) {\r\n blocks[i >>> 2] |= (0xc0 | (code >>> 6)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\r\n } else if (code < 0xd800 || code >= 0xe000) {\r\n blocks[i >>> 2] |= (0xe0 | (code >>> 12)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | ((code >>> 6) & 0x3f)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\r\n } else {\r\n // 处理代理对\r\n code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));\r\n blocks[i >>> 2] |= (0xf0 | (code >>> 18)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | ((code >>> 12) & 0x3f)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | ((code >>> 6) & 0x3f)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\r\n }\r\n }\r\n }\r\n\r\n this.lastByteIndex = i;\r\n this.bytes += i - this.start;\r\n\r\n // 区块满 64 字节,进行哈希计算\r\n if (i >= 64) {\r\n this.block = blocks[16];\r\n this.start = i - 64;\r\n this.hash();\r\n this.hashed = true;\r\n } else {\r\n this.start = i;\r\n }\r\n }\r\n\r\n // 处理字节长度溢出\r\n if (this.bytes > 4294967295) {\r\n this.hBytes += (this.bytes / 4294967296) << 0;\r\n this.bytes = this.bytes % 4294967296;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n // 核心哈希计算\r\n hash() {\r\n let a = this.h0,\r\n b = this.h1,\r\n c = this.h2,\r\n d = this.h3;\r\n let e = this.h4,\r\n f = this.h5,\r\n g = this.h6,\r\n h = this.h7;\r\n const blocks = this.blocks;\r\n let j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;\r\n\r\n // 扩展区块\r\n for (j = 16; j < 64; ++j) {\r\n t1 = blocks[j - 15];\r\n s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3);\r\n t1 = blocks[j - 2];\r\n s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10);\r\n blocks[j] = (blocks[j - 16] + s0 + blocks[j - 7] + s1) << 0;\r\n }\r\n\r\n bc = b & c;\r\n // 64 轮哈希计算\r\n for (j = 0; j < 64; j += 4) {\r\n if (this.first) {\r\n if (this.is224) {\r\n ab = 300032;\r\n t1 = blocks[0] - 1413257819;\r\n h = (t1 - 150054599) << 0;\r\n d = (t1 + 24177077) << 0;\r\n } else {\r\n ab = 704751109;\r\n t1 = blocks[0] - 210244248;\r\n h = (t1 - 1521486534) << 0;\r\n d = (t1 + 143694565) << 0;\r\n }\r\n this.first = false;\r\n } else {\r\n s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));\r\n s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));\r\n ab = a & b;\r\n maj = ab ^ (a & c) ^ bc;\r\n ch = (e & f) ^ (~e & g);\r\n t1 = h + s1 + ch + K[j] + blocks[j];\r\n t2 = s0 + maj;\r\n h = (d + t1) << 0;\r\n d = (t1 + t2) << 0;\r\n }\r\n\r\n s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10));\r\n s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7));\r\n da = d & a;\r\n maj = da ^ (d & b) ^ ab;\r\n ch = (h & e) ^ (~h & f);\r\n t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];\r\n t2 = s0 + maj;\r\n g = (c + t1) << 0;\r\n c = (t1 + t2) << 0;\r\n\r\n s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10));\r\n s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7));\r\n cd = c & d;\r\n maj = cd ^ (c & a) ^ da;\r\n ch = (g & h) ^ (~g & e);\r\n t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];\r\n t2 = s0 + maj;\r\n f = (b + t1) << 0;\r\n b = (t1 + t2) << 0;\r\n\r\n s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10));\r\n s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7));\r\n bc = b & c;\r\n maj = bc ^ (b & d) ^ cd;\r\n ch = (f & g) ^ (~f & h);\r\n t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];\r\n t2 = s0 + maj;\r\n e = (a + t1) << 0;\r\n a = (t1 + t2) << 0;\r\n }\r\n\r\n // 更新哈希值\r\n this.h0 = (this.h0 + a) << 0;\r\n this.h1 = (this.h1 + b) << 0;\r\n this.h2 = (this.h2 + c) << 0;\r\n this.h3 = (this.h3 + d) << 0;\r\n this.h4 = (this.h4 + e) << 0;\r\n this.h5 = (this.h5 + f) << 0;\r\n this.h6 = (this.h6 + g) << 0;\r\n this.h7 = (this.h7 + h) << 0;\r\n }\r\n\r\n // 完成哈希计算(补位)\r\n finalize() {\r\n if (this.finalized) return this;\r\n this.finalized = true;\r\n\r\n const blocks = this.blocks;\r\n let i = this.lastByteIndex;\r\n\r\n blocks[16] = this.block;\r\n blocks[i >>> 2] |= EXTRA[i & 3];\r\n this.block = blocks[16];\r\n\r\n // 补位处理\r\n if (i >= 56) {\r\n if (!this.hashed) this.hash();\r\n blocks.fill(0);\r\n blocks[0] = this.block;\r\n }\r\n\r\n // 写入长度信息\r\n blocks[14] = (this.hBytes << 3) | (this.bytes >>> 29);\r\n blocks[15] = this.bytes << 3;\r\n this.hash();\r\n\r\n return this;\r\n }\r\n\r\n // 输出十六进制字符串\r\n hex() {\r\n this.finalize();\r\n\r\n const h0 = this.h0,\r\n h1 = this.h1,\r\n h2 = this.h2,\r\n h3 = this.h3;\r\n const h4 = this.h4,\r\n h5 = this.h5,\r\n h6 = this.h6,\r\n h7 = this.h7;\r\n\r\n let hex = \"\";\r\n // 拼接哈希值为十六进制\r\n hex +=\r\n HEX_CHARS[(h0 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 4) & 0x0f] +\r\n HEX_CHARS[h0 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h1 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 4) & 0x0f] +\r\n HEX_CHARS[h1 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h2 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 4) & 0x0f] +\r\n HEX_CHARS[h2 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h3 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 4) & 0x0f] +\r\n HEX_CHARS[h3 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h4 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 4) & 0x0f] +\r\n HEX_CHARS[h4 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h5 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 4) & 0x0f] +\r\n HEX_CHARS[h5 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h6 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 4) & 0x0f] +\r\n HEX_CHARS[h6 & 0x0f];\r\n\r\n // SHA224 不需要 h7\r\n if (!this.is224) {\r\n hex +=\r\n HEX_CHARS[(h7 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 4) & 0x0f] +\r\n HEX_CHARS[h7 & 0x0f];\r\n }\r\n\r\n return hex;\r\n }\r\n\r\n // 输出字节数组\r\n digest() {\r\n this.finalize();\r\n\r\n const h0 = this.h0,\r\n h1 = this.h1,\r\n h2 = this.h2,\r\n h3 = this.h3;\r\n const h4 = this.h4,\r\n h5 = this.h5,\r\n h6 = this.h6,\r\n h7 = this.h7;\r\n\r\n const arr = [\r\n (h0 >>> 24) & 0xff,\r\n (h0 >>> 16) & 0xff,\r\n (h0 >>> 8) & 0xff,\r\n h0 & 0xff,\r\n (h1 >>> 24) & 0xff,\r\n (h1 >>> 16) & 0xff,\r\n (h1 >>> 8) & 0xff,\r\n h1 & 0xff,\r\n (h2 >>> 24) & 0xff,\r\n (h2 >>> 16) & 0xff,\r\n (h2 >>> 8) & 0xff,\r\n h2 & 0xff,\r\n (h3 >>> 24) & 0xff,\r\n (h3 >>> 16) & 0xff,\r\n (h3 >>> 8) & 0xff,\r\n h3 & 0xff,\r\n (h4 >>> 24) & 0xff,\r\n (h4 >>> 16) & 0xff,\r\n (h4 >>> 8) & 0xff,\r\n h4 & 0xff,\r\n (h5 >>> 24) & 0xff,\r\n (h5 >>> 16) & 0xff,\r\n (h5 >>> 8) & 0xff,\r\n h5 & 0xff,\r\n (h6 >>> 24) & 0xff,\r\n (h6 >>> 16) & 0xff,\r\n (h6 >>> 8) & 0xff,\r\n h6 & 0xff,\r\n ];\r\n\r\n if (!this.is224) {\r\n arr.push((h7 >>> 24) & 0xff, (h7 >>> 16) & 0xff, (h7 >>> 8) & 0xff, h7 & 0xff);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n // 输出二进制原始字符串(raw)\r\n raw() {\r\n this.finalize();\r\n const bytes = this.digest();\r\n let rawStr = \"\";\r\n for (let i = 0; i < bytes.length; i++) {\r\n rawStr += String.fromCharCode(bytes[i]);\r\n }\r\n return rawStr;\r\n }\r\n\r\n // 输出 ArrayBuffer\r\n arrayBuffer() {\r\n this.finalize();\r\n const buffer = new ArrayBuffer(this.is224 ? 28 : 32);\r\n const dataView = new DataView(buffer);\r\n dataView.setUint32(0, this.h0);\r\n dataView.setUint32(4, this.h1);\r\n dataView.setUint32(8, this.h2);\r\n dataView.setUint32(12, this.h3);\r\n dataView.setUint32(16, this.h4);\r\n dataView.setUint32(20, this.h5);\r\n dataView.setUint32(24, this.h6);\r\n if (!this.is224) {\r\n dataView.setUint32(28, this.h7);\r\n }\r\n return buffer;\r\n }\r\n}\r\n\r\n// ========== HMAC-SHA256 实现 ==========\r\nclass HmacSha256 {\r\n constructor(key, is224 = false) {\r\n // 处理密钥\r\n let keyBytes = [];\r\n const type = typeof key;\r\n\r\n if (type === \"string\") {\r\n // 字符串密钥转字节数组\r\n let code,\r\n index = 0,\r\n length = key.length;\r\n for (let i = 0; i < length; ++i) {\r\n code = key.charCodeAt(i);\r\n if (code < 0x80) {\r\n keyBytes[index++] = code;\r\n } else if (code < 0x800) {\r\n keyBytes[index++] = 0xc0 | (code >>> 6);\r\n keyBytes[index++] = 0x80 | (code & 0x3f);\r\n } else if (code < 0xd800 || code >= 0xe000) {\r\n keyBytes[index++] = 0xe0 | (code >>> 12);\r\n keyBytes[index++] = 0x80 | ((code >>> 6) & 0x3f);\r\n keyBytes[index++] = 0x80 | (code & 0x3f);\r\n } else {\r\n code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff));\r\n keyBytes[index++] = 0xf0 | (code >>> 18);\r\n keyBytes[index++] = 0x80 | ((code >>> 12) & 0x3f);\r\n keyBytes[index++] = 0x80 | ((code >>> 6) & 0x3f);\r\n keyBytes[index++] = 0x80 | (code & 0x3f);\r\n }\r\n }\r\n } else if (type === \"object\") {\r\n if (key === null) throw new Error(ERROR);\r\n if (key.constructor === ArrayBuffer) {\r\n keyBytes = Array.from(new Uint8Array(key));\r\n } else if (Array.isArray(key) || ArrayBuffer.isView(key)) {\r\n keyBytes = Array.from(key);\r\n } else {\r\n throw new Error(ERROR);\r\n }\r\n } else {\r\n throw new Error(ERROR);\r\n }\r\n\r\n // 密钥长度超过 64 字节,先哈希\r\n if (keyBytes.length > 64) {\r\n keyBytes = new Sha256(is224).update(keyBytes).digest();\r\n }\r\n\r\n // 生成内外填充\r\n const oKeyPad = [];\r\n const iKeyPad = [];\r\n for (let i = 0; i < 64; ++i) {\r\n const b = keyBytes[i] || 0;\r\n oKeyPad[i] = 0x5c ^ b;\r\n iKeyPad[i] = 0x36 ^ b;\r\n }\r\n\r\n // 初始化 SHA256\r\n this.sha256 = new Sha256(is224);\r\n this.sha256.update(iKeyPad);\r\n this.oKeyPad = oKeyPad;\r\n this.is224 = is224;\r\n this.inner = true;\r\n }\r\n\r\n update(message) {\r\n this.sha256.update(message);\r\n return this;\r\n }\r\n\r\n finalize() {\r\n if (this.inner) {\r\n // 计算内部哈希\r\n const innerHash = this.sha256.digest();\r\n // 初始化外部哈希\r\n this.sha256 = new Sha256(this.is224);\r\n this.sha256.update(this.oKeyPad).update(innerHash);\r\n this.inner = false;\r\n }\r\n this.sha256.finalize();\r\n return this;\r\n }\r\n\r\n hex() {\r\n this.finalize();\r\n return this.sha256.hex();\r\n }\r\n\r\n digest() {\r\n this.finalize();\r\n return this.sha256.digest();\r\n }\r\n\r\n raw() {\r\n this.finalize();\r\n return this.sha256.raw();\r\n }\r\n\r\n arrayBuffer() {\r\n this.finalize();\r\n return this.sha256.arrayBuffer();\r\n }\r\n}\r\n\r\n// ========== 便捷方法封装 ==========\r\nconst createMethod = (is224 = false) => {\r\n const method = (message) => new Sha256(is224).update(message).hex();\r\n method.raw = (message) => new Sha256(is224).update(message).raw();\r\n method.digest = (message) => new Sha256(is224).update(message).digest();\r\n method.arrayBuffer = (message) => new Sha256(is224).update(message).arrayBuffer();\r\n method.create = () => new Sha256(is224);\r\n method.update = (message) => method.create().update(message);\r\n return method;\r\n};\r\nconst createRawMethod = (is224 = false) => {\r\n const method = (message) => new Sha256(is224).update(message).raw();\r\n method.hex = (message) => new Sha256(is224).update(message).hex();\r\n method.digest = (message) => new Sha256(is224).update(message).digest();\r\n method.arrayBuffer = (message) => new Sha256(is224).update(message).arrayBuffer();\r\n method.create = () => new Sha256(is224);\r\n method.update = (message) => method.create().update(message);\r\n return method;\r\n};\r\nconst createHmacMethod = (is224 = false) => {\r\n const method = (key, message) => new HmacSha256(key, is224).update(message).hex();\r\n method.raw = (key, message) => new HmacSha256(key, is224).update(message).raw();\r\n method.digest = (key, message) => new HmacSha256(key, is224).update(message).digest();\r\n method.arrayBuffer = (key, message) => new HmacSha256(key, is224).update(message).arrayBuffer();\r\n method.create = (key) => new HmacSha256(key, is224);\r\n method.update = (key, message) => method.create(key).update(message);\r\n return method;\r\n};\r\nconst createHmacRawMethod = (is224 = false) => {\r\n const method = (key, message) => new HmacSha256(key, is224).update(message).raw();\r\n method.hex = (key, message) => new HmacSha256(key, is224).update(message).hex();\r\n method.digest = (key, message) => new HmacSha256(key, is224).update(message).digest();\r\n method.arrayBuffer = (key, message) => new HmacSha256(key, is224).update(message).arrayBuffer();\r\n method.create = (key) => new HmacSha256(key, is224);\r\n method.update = (key, message) => method.create(key).update(message);\r\n return method;\r\n};\r\n\r\n/* 以下是内部实现需要的es模块化导出方法 */\r\n// SHA256 基础方法\r\nexport const sha256 = createMethod();\r\n// SHA256 基础方法原始值\r\nexport const sha256_raw = createRawMethod();\r\n// HMAC-SHA256\r\nexport const sha256_hmac = createHmacMethod();\r\n// HMAC-SHA256原始值\r\nexport const sha256_hmac_raw = createHmacRawMethod();\r\n\r\n// SHA224 基础方法\r\nexport const sha224 = createMethod(true);\r\n// SHA224 基础方法原始值\r\nexport const sha224_raw = createRawMethod(true);\r\n// HMAC-SHA224\r\nexport const sha224_hmac = createHmacMethod(true);\r\n// HMAC-SHA224原始值\r\nexport const sha224_hmac_raw = createHmacRawMethod(true);\r\n","/**\r\n * SM3 纯函数式实现(无类、无实例,闭包隔离状态)\r\n */\r\n\r\n// 全局常量(只读,无状态)\r\nconst BLOCK_LENGTH = 64;\r\nconst IPAD = new Uint8Array(BLOCK_LENGTH).fill(0x36);\r\nconst OPAD = new Uint8Array(BLOCK_LENGTH).fill(0x5c);\r\nconst IV = new Uint32Array([\r\n 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e,\r\n]);\r\n\r\n// 纯函数:循环左移\r\nfunction rotl(x, n) {\r\n const s = n & 31;\r\n return (x << s) | (x >>> (32 - s));\r\n}\r\n\r\n// 纯函数:字节数组异或\r\nfunction xor(x, y) {\r\n const result = [];\r\n for (let i = x.length - 1; i >= 0; i--) {\r\n result[i] = (x[i] ^ y[i]) & 0xff;\r\n }\r\n return result;\r\n}\r\n\r\n// 纯函数:置换函数 P0\r\nfunction P0(X) {\r\n return X ^ rotl(X, 9) ^ rotl(X, 17);\r\n}\r\n\r\n// 纯函数:置换函数 P1\r\nfunction P1(X) {\r\n return X ^ rotl(X, 15) ^ rotl(X, 23);\r\n}\r\n\r\n// 纯函数:补全16进制字符串\r\nfunction leftPad(input, num) {\r\n if (input.length >= num) return input;\r\n return new Array(num - input.length + 1).join(\"0\") + input;\r\n}\r\n\r\n// 纯函数:字节数组转16进制\r\nfunction arrayToHex(arr) {\r\n return arr\r\n .map((item) => {\r\n item = item.toString(16);\r\n return item.length === 1 ? \"0\" + item : item;\r\n })\r\n .join(\"\");\r\n}\r\n\r\n// 纯函数:16进制转字节数组\r\nfunction hexToArray(hexStr) {\r\n const words = [];\r\n let hexStrLength = hexStr.length;\r\n if (hexStrLength % 2 !== 0) {\r\n hexStr = leftPad(hexStr, hexStrLength + 1);\r\n }\r\n hexStrLength = hexStr.length;\r\n for (let i = 0; i < hexStrLength; i += 2) {\r\n words.push(parseInt(hexStr.substr(i, 2), 16));\r\n }\r\n return words;\r\n}\r\n\r\n// 纯函数:UTF8转字节数组\r\nfunction utf8ToArray(str) {\r\n const arr = [];\r\n for (let i = 0, len = str.length; i < len; i++) {\r\n const point = str.codePointAt(i);\r\n if (point <= 0x007f) {\r\n arr.push(point);\r\n } else if (point <= 0x07ff) {\r\n arr.push(0xc0 | (point >>> 6));\r\n arr.push(0x80 | (point & 0x3f));\r\n } else if (point <= 0xd7ff || (point >= 0xe000 && point <= 0xffff)) {\r\n arr.push(0xe0 | (point >>> 12));\r\n arr.push(0x80 | ((point >>> 6) & 0x3f));\r\n arr.push(0x80 | (point & 0x3f));\r\n } else if (point >= 0x010000 && point <= 0x10ffff) {\r\n i++;\r\n arr.push(0xf0 | ((point >>> 18) & 0x1c));\r\n arr.push(0x80 | ((point >>> 12) & 0x3f));\r\n arr.push(0x80 | ((point >>> 6) & 0x3f));\r\n arr.push(0x80 | (point & 0x3f));\r\n } else {\r\n arr.push(point);\r\n throw new TypeError(\"utf8ToArray: input is not supported in sm3\");\r\n }\r\n }\r\n return arr;\r\n}\r\n\r\n// 核心纯函数:SM3哈希计算(闭包隔离状态)\r\nfunction sm3Core(array) {\r\n // 每次调用都创建全新的局部状态(隔离关键)\r\n let len = array.length * 8;\r\n let k = len % 512;\r\n k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1;\r\n const kArr = new Array((k - 7) / 8).fill(0);\r\n const lenArr = new Array(8).fill(0);\r\n let lenBin = len.toString(2);\r\n for (let i = 7; i >= 0; i--) {\r\n if (lenBin.length > 8) {\r\n const start = lenBin.length - 8;\r\n lenArr[i] = parseInt(lenBin.substr(start), 2);\r\n lenBin = lenBin.substr(0, start);\r\n } else if (lenBin.length > 0) {\r\n lenArr[i] = parseInt(lenBin, 2);\r\n lenBin = \"\";\r\n }\r\n }\r\n const m = new Uint8Array([...array, 0x80, ...kArr, ...lenArr]);\r\n const dataView = new DataView(m.buffer, 0);\r\n const n = m.length / 64;\r\n const V = new Uint32Array(IV); // 全新初始向量(每次调用重新创建)\r\n const W = new Uint32Array(68); // 全新消息扩展数组\r\n const M = new Uint32Array(64); // 全新W'数组\r\n\r\n // 以下计算逻辑和原代码一致,仅操作局部变量\r\n for (let i = 0; i < n; i++) {\r\n W.fill(0);\r\n M.fill(0);\r\n const start = 16 * i;\r\n for (let j = 0; j < 16; j++) {\r\n W[j] = dataView.getUint32((start + j) * 4, false);\r\n }\r\n for (let j = 16; j < 68; j++) {\r\n W[j] = P1(W[j - 16] ^ W[j - 9] ^ rotl(W[j - 3], 15)) ^ rotl(W[j - 13], 7) ^ W[j - 6];\r\n }\r\n for (let j = 0; j < 64; j++) {\r\n M[j] = W[j] ^ W[j + 4];\r\n }\r\n const T1 = 0x79cc4519;\r\n const T2 = 0x7a879d8a;\r\n let A = V[0],\r\n B = V[1],\r\n C = V[2],\r\n D = V[3];\r\n let E = V[4],\r\n F = V[5],\r\n G = V[6],\r\n H = V[7];\r\n let SS1, SS2, TT1, TT2, T;\r\n\r\n for (let j = 0; j < 64; j++) {\r\n T = j <= 15 ? T1 : T2;\r\n SS1 = rotl((rotl(A, 12) + E + rotl(T, j)) & 0xffffffff, 7);\r\n SS2 = SS1 ^ rotl(A, 12);\r\n const FFj = j <= 15 ? A ^ B ^ C : (A & B) | (A & C) | (B & C);\r\n const GGj = j <= 15 ? E ^ F ^ G : (E & F) | (~E & G);\r\n TT1 = (FFj + D + SS2 + M[j]) & 0xffffffff;\r\n TT2 = (GGj + H + SS1 + W[j]) & 0xffffffff;\r\n\r\n D = C;\r\n C = rotl(B, 9);\r\n B = A;\r\n A = TT1;\r\n H = G;\r\n G = rotl(F, 19);\r\n F = E;\r\n E = P0(TT2);\r\n }\r\n V[0] ^= A;\r\n V[1] ^= B;\r\n V[2] ^= C;\r\n V[3] ^= D;\r\n V[4] ^= E;\r\n V[5] ^= F;\r\n V[6] ^= G;\r\n V[7] ^= H;\r\n }\r\n const result = [];\r\n for (let i = 0; i < V.length; i++) {\r\n result.push((V[i] & 0xff000000) >>> 24, (V[i] & 0xff0000) >>> 16, (V[i] & 0xff00) >>> 8, V[i] & 0xff);\r\n }\r\n return result;\r\n}\r\n\r\n// 纯函数:HMAC-SM3计算\r\nfunction encryptHmac(input, key) {\r\n let processedKey = key.length > BLOCK_LENGTH ? sm3Core(key) : [...key];\r\n while (processedKey.length < BLOCK_LENGTH) {\r\n processedKey.push(0);\r\n }\r\n const iPadKey = xor(processedKey, IPAD);\r\n const oPadKey = xor(processedKey, OPAD);\r\n const innerHash = sm3Core([...iPadKey, ...input]);\r\n return sm3Core([...oPadKey, ...innerHash]);\r\n}\r\n\r\n// 对外暴露的核心函数(兼容原调用方式)\r\nfunction encrypt(input, key) {\r\n const inputArr = typeof input === \"string\" ? utf8ToArray(input) : Array.prototype.slice.call(input);\r\n\r\n if (!key) {\r\n const hashArr = sm3Core(inputArr);\r\n return arrayToHex(hashArr);\r\n } else {\r\n const keyArr =\r\n typeof key === \"string\"\r\n ? /^[0-9a-fA-F]+$/.test(key)\r\n ? hexToArray(key)\r\n : utf8ToArray(key)\r\n : Array.prototype.slice.call(key);\r\n const hmacArr = encryptHmac(inputArr, keyArr);\r\n return arrayToHex(hmacArr);\r\n }\r\n}\r\n\r\n/* 以下是内部实现需要的es模块化导出方法 */\r\nexport { encrypt, encryptHmac as encrypt_hmac };\r\n","// ========== 常量定义(规范化,避免魔法值) ==========\r\nconst SM4_MODE_ECB = \"ecb\";\r\nconst SM4_MODE_CBC = \"cbc\";\r\nconst SM4_PADDING = \"pkcs#7\";\r\nconst SM4_OUTPUT_HEX = \"hex\";\r\nconst SM4_OUTPUT_UTF8 = \"utf8\";\r\nconst SM4_OUTPUT_ARRAY = \"array\";\r\nconst SM4_OUTPUT_UINT8ARRAY = \"uint8array\";\r\nconst SM4_OUTPUT_ARRAYBUFFER = \"arraybuffer\";\r\n\r\nconst ENCRYPT = 1;\r\nconst DECRYPT = 0;\r\nconst ROUND_COUNT = 32;\r\nconst BLOCK_SIZE = 16; // 128比特 = 16字节\r\nconst KEY_SIZE = 16; // SM4密钥固定128比特\r\nconst IV_SIZE = 16; // CBC模式IV固定128比特\r\n\r\n// SM4 S盒\r\nconst SBOX = new Uint8Array([\r\n 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, 0x2b, 0x67, 0x9a,\r\n 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef,\r\n 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80,\r\n 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19,\r\n 0xe6, 0x85, 0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d,\r\n 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, 0xd4, 0x00,\r\n 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf, 0x8a, 0xd2, 0x40,\r\n 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,\r\n 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23,\r\n 0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c,\r\n 0x5b, 0x51, 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, 0x0a,\r\n 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, 0x89, 0x69, 0x97, 0x4a,\r\n 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d,\r\n 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,\r\n]);\r\n\r\n// 轮常量 CK\r\nconst CK = new Uint32Array([\r\n 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5,\r\n 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1,\r\n 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed,\r\n 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,\r\n]);\r\n\r\n// 系统参数 FK\r\nconst FK = new Uint32Array([0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]);\r\n\r\n// ========== 工具函数(通用转换) ==========\r\n/**\r\n * 16进制字符串转Uint8Array\r\n * @param {string} str - 16进制字符串\r\n * @returns {Uint8Array} 字节数组\r\n */\r\nfunction hexToUint8Array(str) {\r\n str = str.replace(/\\s+/g, \"\"); // 去除空格\r\n if (str.length % 2 !== 0) throw new TypeError(\"hexToUint8Array: hex string length must be even from sm4\");\r\n\r\n const arr = new Uint8Array(str.length / 2);\r\n for (let i = 0; i < str.length; i += 2) {\r\n arr[i / 2] = parseInt(str.substr(i, 2), 16) & 0xff;\r\n }\r\n return arr;\r\n}\r\n\r\n/**\r\n * Uint8Array转16进制字符串\r\n * @param {Uint8Array} arr - 字节数组\r\n * @returns {string} 16进制字符串\r\n */\r\nfunction uint8ArrayToHex(arr) {\r\n return Array.from(arr)\r\n .map((byte) => {\r\n const hex = byte.toString(16);\r\n return hex.length === 1 ? \"0\" + hex : hex;\r\n })\r\n .join(\"\");\r\n}\r\n\r\n/**\r\n * UTF8字符串转Uint8Array\r\n * @param {string} str - UTF8字符串\r\n * @returns {Uint8Array} 字节数组\r\n */\r\nfunction utf8ToUint8Array(str) {\r\n return new TextEncoder().encode(str);\r\n}\r\n\r\n/**\r\n * Uint8Array转UTF8字符串\r\n * @param {Uint8Array} arr - 字节数组\r\n * @returns {string} UTF8字符串\r\n */\r\nfunction uint8ArrayToUtf8(arr) {\r\n return new TextDecoder(\"utf-8\").decode(arr);\r\n}\r\n\r\n/**\r\n * 统一输入数据格式为Uint8Array\r\n * @param {string|Array|Uint8Array|ArrayBuffer} input - 输入数据\r\n * @param {number} cryptFlag - ENCRYPT/DECRYPT\r\n * @returns {Uint8Array} 标准化后的字节数组\r\n */\r\nfunction normalizeInput(input, cryptFlag) {\r\n if (input instanceof ArrayBuffer) {\r\n return new Uint8Array(input);\r\n }\r\n if (input instanceof Uint8Array) {\r\n return new Uint8Array(input); // 拷贝避免修改原数组\r\n }\r\n if (Array.isArray(input)) {\r\n return new Uint8Array(input);\r\n }\r\n if (typeof input === \"string\") {\r\n if (cryptFlag === ENCRYPT) {\r\n // 加密:字符串按UTF8转字节\r\n return utf8ToUint8Array(input);\r\n } else {\r\n // 解密:字符串按16进制转字节\r\n return hexToUint8Array(input);\r\n }\r\n }\r\n throw new TypeError(`normalizeInput: unsupported input type: ${typeof input} from sm4`);\r\n}\r\n\r\n/**\r\n * 标准化密钥/IV为Uint8Array\r\n * @param {string|Array|Uint8Array|ArrayBuffer} keyOrIv - 密钥/IV\r\n * @param {number} expectedLength - 期望长度(字节)\r\n * @param {string} name - 名称(用于报错)\r\n * @returns {Uint8Array} 标准化后的字节数组\r\n */\r\nfunction normalizeKeyIv(keyOrIv, expectedLength, name) {\r\n let arr;\r\n if (typeof keyOrIv === \"string\") {\r\n arr = hexToUint8Array(keyOrIv);\r\n } else if (keyOrIv instanceof ArrayBuffer) {\r\n arr = new Uint8Array(keyOrIv);\r\n } else if (keyOrIv instanceof Uint8Array) {\r\n arr = keyOrIv;\r\n } else if (Array.isArray(keyOrIv)) {\r\n arr = new Uint8Array(keyOrIv);\r\n } else {\r\n throw new TypeError(`normalizeKeyIv: unsupported ${name} type: ${typeof keyOrIv} from sm4`);\r\n }\r\n\r\n if (arr.length !== expectedLength) {\r\n throw new TypeError(\r\n `normalizeKeyIv: ${name} must be ${expectedLength * 8} bits (${expectedLength} bytes) from sm4`,\r\n );\r\n }\r\n return arr;\r\n}\r\n\r\n// ========== SM4核心函数 ==========\r\n/**\r\n * 32比特循环左移\r\n * @param {number} x - 32比特无符号整数\r\n * @param {number} n - 移位位数\r\n * @returns {number} 移位结果\r\n */\r\nfunction rotl32(x, n) {\r\n const s = n & 31;\r\n return ((x << s) | (x >>> (32 - s))) >>> 0; // >>>0 确保无符号\r\n}\r\n\r\n/**\r\n * 非线性变换(字节替换)\r\n * @param {number} a - 32比特无符号整数\r\n * @returns {number} 替换结果\r\n */\r\nfunction byteSub(a) {\r\n return (\r\n ((SBOX[(a >>> 24) & 0xff] << 24) |\r\n (SBOX[(a >>> 16) & 0xff] << 16) |\r\n (SBOX[(a >>> 8) & 0xff] << 8) |\r\n SBOX[a & 0xff]) >>>\r\n 0\r\n );\r\n}\r\n\r\n/**\r\n * 线性变换(加密/解密用)\r\n * @param {number} b - 32比特无符号整数\r\n * @returns {number} 变换结果\r\n */\r\nfunction linearTransformEnc(b) {\r\n return (b ^ rotl32(b, 2) ^ rotl32(b, 10) ^ rotl32(b, 18) ^ rotl32(b, 24)) >>> 0;\r\n}\r\n\r\n/**\r\n * 线性变换(密钥扩展用)\r\n * @param {number} b - 32比特无符号整数\r\n * @returns {number} 变换结果\r\n */\r\nfunction linearTransformKey(b) {\r\n return (b ^ rotl32(b, 13) ^ rotl32(b, 23)) >>> 0;\r\n}\r\n\r\n/**\r\n * SM4单块加密/解密(128比特)\r\n * @param {Uint8Array} inputBlock - 输入块(16字节)\r\n * @param {Uint8Array} outputBlock - 输出块(16字节)\r\n * @param {Uint32Array} roundKeys - 轮密钥(32个32比特)\r\n */\r\nfunction sm4BlockCrypt(inputBlock, outputBlock, roundKeys) {\r\n // 确保输入块是16字节\r\n if (inputBlock.length !== BLOCK_SIZE) {\r\n throw new TypeError(`sm4BlockCrypt: input block must be ${BLOCK_SIZE} bytes for block crypt from sm4`);\r\n }\r\n\r\n // 字节数组转32比特字数组(4个字,共128比特)\r\n const x = new Uint32Array(4);\r\n for (let i = 0; i < 4; i++) {\r\n const offset = 4 * i;\r\n x[i] =\r\n ((inputBlock[offset] << 24) |\r\n (inputBlock[offset + 1] << 16) |\r\n (inputBlock[offset + 2] << 8) |\r\n inputBlock[offset + 3]) >>>\r\n 0;\r\n }\r\n\r\n // 32轮加密\r\n for (let r = 0; r < ROUND_COUNT; r += 4) {\r\n let mid = (x[1] ^ x[2] ^ x[3] ^ roundKeys[r]) >>> 0;\r\n x[0] ^= linearTransformEnc(byteSub(mid));\r\n\r\n mid = (x[2] ^ x[3] ^ x[0] ^ roundKeys[r + 1]) >>> 0;\r\n x[1] ^= linearTransformEnc(byteSub(mid));\r\n\r\n mid = (x[3] ^ x[0] ^ x[1] ^ roundKeys[r + 2]) >>> 0;\r\n x[2] ^= linearTransformEnc(byteSub(mid));\r\n\r\n mid = (x[0] ^ x[1] ^ x[2] ^ roundKeys[r + 3]) >>> 0;\r\n x[3] ^= linearTransformEnc(byteSub(mid));\r\n }\r\n\r\n // 反序输出\r\n for (let j = 0; j < BLOCK_SIZE; j += 4) {\r\n const wordIdx = 3 - j / 4;\r\n outputBlock[j] = (x[wordIdx] >>> 24) & 0xff;\r\n outputBlock[j + 1] = (x[wordIdx] >>> 16) & 0xff;\r\n outputBlock[j + 2] = (x[wordIdx] >>> 8) & 0xff;\r\n outputBlock[j + 3] = x[wordIdx] & 0xff;\r\n }\r\n}\r\n\r\n/**\r\n * SM4密钥扩展算法\r\n * @param {Uint8Array} key - 16字节密钥\r\n * @param {Uint32Array} roundKeys - 输出轮密钥(32个32比特)\r\n * @param {number} cryptFlag - ENCRYPT/DECRYPT\r\n */\r\nfunction sm4KeyExpansion(key, roundKeys, cryptFlag) {\r\n // 密钥转32比特字数组\r\n const x = new Uint32Array(4);\r\n for (let i = 0; i < 4; i++) {\r\n const offset = 4 * i;\r\n x[i] = ((key[offset] << 24) | (key[offset + 1] << 16) | (key[offset + 2] << 8) | key[offset + 3]) >>> 0;\r\n }\r\n\r\n // 与系统参数异或\r\n x[0] ^= FK[0];\r\n x[1] ^= FK[1];\r\n x[2] ^= FK[2];\r\n x[3] ^= FK[3];\r\n\r\n // 生成轮密钥\r\n for (let r = 0; r < ROUND_COUNT; r += 4) {\r\n let mid = (x[1] ^ x[2] ^ x[3] ^ CK[r]) >>> 0;\r\n roundKeys[r] = x[0] ^= linearTransformKey(byteSub(mid));\r\n\r\n mid = (x[2] ^ x[3] ^ x[0] ^ CK[r + 1]) >>> 0;\r\n roundKeys[r + 1] = x[1] ^= linearTransformKey(byteSub(mid));\r\n\r\n mid = (x[3] ^ x[0] ^ x[1] ^ CK[r + 2]) >>> 0;\r\n roundKeys[r + 2] = x[2] ^= linearTransformKey(byteSub(mid));\r\n\r\n mid = (x[0] ^ x[1] ^ x[2] ^ CK[r + 3]) >>> 0;\r\n roundKeys[r + 3] = x[3] ^= linearTransformKey(byteSub(mid));\r\n }\r\n\r\n // 解密时轮密钥反序\r\n if (cryptFlag === DECRYPT) {\r\n for (let r = 0; r < 16; r++) {\r\n const temp = roundKeys[r];\r\n roundKeys[r] = roundKeys[31 - r];\r\n roundKeys[31 - r] = temp;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * PKCS#7填充\r\n * @param {Uint8Array} data - 原始数据\r\n * @returns {Uint8Array} 填充后的数据\r\n */\r\nfunction pkcs7Pad(data) {\r\n const paddingCount = BLOCK_SIZE - (data.length % BLOCK_SIZE);\r\n const padded = new Uint8Array(data.length + paddingCount);\r\n padded.set(data);\r\n for (let i = 0; i < paddingCount; i++) {\r\n padded[data.length + i] = paddingCount & 0xff;\r\n }\r\n return padded;\r\n}\r\n\r\n/**\r\n * PKCS#7去填充\r\n * @param {Uint8Array} data - 填充后的数据\r\n * @returns {Uint8Array} 去填充后的数据\r\n */\r\nfunction pkcs7Unpad(data) {\r\n const paddingCount = data[data.length - 1] & 0xff;\r\n // 验证填充合法性\r\n for (let i = 1; i <= paddingCount; i++) {\r\n if (data[data.length - i] !== paddingCount) {\r\n throw new TypeError(\"pkcs7Unpad: invalid PKCS#7 padding from sm4\");\r\n }\r\n }\r\n return data.subarray(0, data.length - paddingCount);\r\n}\r\n\r\n/**\r\n * SM4主函数\r\n * @param {string|Array|Uint8Array|ArrayBuffer} inputData - 输入数据\r\n * @param {string|Array|Uint8Array|ArrayBuffer} key - 16字节密钥\r\n * @param {number} cryptFlag - ENCRYPT/DECRYPT\r\n * @param {Object} [options] - 选项\r\n * @param {string} [options.mode=ecb] - 模式:ecb/cbc\r\n * @param {string|Array|Uint8Array|ArrayBuffer} [options.iv] - CBC模式IV(16字节)\r\n * @param {string} [options.padding=pkcs#7] - 填充方式:pkcs#7\r\n * @param {string} [options.output] - 输出格式:hex/utf8/array/uint8array/arraybuffer\r\n * @returns {string|Array|Uint8Array|ArrayBuffer} 输出数据\r\n */\r\nfunction sm4Core(inputData, key, cryptFlag, options = {}) {\r\n // 默认参数(加密和解密默认输出都为hex,避免格式不匹配)\r\n const {\r\n mode = SM4_MODE_ECB,\r\n iv = [],\r\n padding = SM4_PADDING,\r\n output = SM4_OUTPUT_HEX, // 统一默认hex格式\r\n } = options;\r\n\r\n // 校验模式\r\n if (![SM4_MODE_ECB, SM4_MODE_CBC].includes(mode)) {\r\n throw new TypeError(`sm4Core: unsupported mode: ${mode}, only 'ecb' and 'cbc' are supported from sm4`);\r\n }\r\n\r\n // 标准化输入、密钥、IV\r\n const input = normalizeInput(inputData, cryptFlag);\r\n const keyBytes = normalizeKeyIv(key, KEY_SIZE, \"key\");\r\n let ivBytes = new Uint8Array(IV_SIZE);\r\n if (mode === SM4_MODE_CBC) {\r\n ivBytes = normalizeKeyIv(iv, IV_SIZE, \"IV\");\r\n }\r\n\r\n // 填充(仅加密时)\r\n let processedInput = input;\r\n if (padding === SM4_PADDING && cryptFlag === ENCRYPT) {\r\n processedInput = pkcs7Pad(input);\r\n // 确保填充后是16字节的倍数\r\n if (processedInput.length % BLOCK_SIZE !== 0) {\r\n throw new TypeError(\"sm4Core: PKCS7 padding failed: data length is not multiple of block size from sm4\");\r\n }\r\n }\r\n\r\n // 生成轮密钥\r\n const roundKeys = new Uint32Array(ROUND_COUNT);\r\n sm4KeyExpansion(keyBytes, roundKeys, cryptFlag);\r\n\r\n // 初始化输出缓冲区\r\n const outputData = new Uint8Array(processedInput.length);\r\n let lastVector = new Uint8Array(ivBytes); // CBC模式向量\r\n let point = 0;\r\n\r\n // 分块处理(严格按16字节分块)\r\n while (point < processedInput.length) {\r\n const inputBlock = processedInput.subarray(point, point + BLOCK_SIZE);\r\n const outputBlock = new Uint8Array(BLOCK_SIZE);\r\n\r\n if (mode === SM4_MODE_CBC) {\r\n if (cryptFlag === ENCRYPT) {\r\n // CBC加密:输入块与前向量异或\r\n const xorBlock = new Uint8Array(BLOCK_SIZE);\r\n for (let i = 0; i < BLOCK_SIZE; i++) {\r\n xorBlock[i] = (inputBlock[i] ^ lastVector[i]) & 0xff;\r\n }\r\n sm4BlockCrypt(xorBlock, outputBlock, roundKeys);\r\n } else {\r\n // CBC解密:先加密再异或\r\n sm4BlockCrypt(inputBlock, outputBlock, roundKeys);\r\n for (let i = 0; i < BLOCK_SIZE; i++) {\r\n outputBlock[i] = (outputBlock[i] ^ lastVector[i]) & 0xff;\r\n }\r\n }\r\n // 更新向量\r\n lastVector = cryptFlag === ENCRYPT ? outputBlock : inputBlock;\r\n } else {\r\n // ECB模式(严格调用块加密)\r\n sm4BlockCrypt(inputBlock, outputBlock, roundKeys);\r\n }\r\n\r\n // 写入输出\r\n outputData.set(outputBlock, point);\r\n point += BLOCK_SIZE;\r\n }\r\n\r\n // 去填充(仅解密时)\r\n let finalOutput = outputData;\r\n if (padding === SM4_PADDING && cryptFlag === DECRYPT) {\r\n finalOutput = pkcs7Unpad(outputData);\r\n }\r\n\r\n // 转换输出格式(解密时如果输出是utf8,先转hex再转utf8)\r\n if (cryptFlag === DECRYPT && output === SM4_OUTPUT_UTF8) {\r\n return uint8ArrayToUtf8(finalOutput);\r\n }\r\n\r\n switch (output) {\r\n case SM4_OUTPUT_HEX:\r\n return uint8ArrayToHex(finalOutput);\r\n case SM4_OUTPUT_ARRAY:\r\n return Array.from(finalOutput);\r\n case SM4_OUTPUT_UINT8ARRAY:\r\n return finalOutput;\r\n case SM4_OUTPUT_ARRAYBUFFER:\r\n return finalOutput.buffer;\r\n default:\r\n throw new TypeError(`sm4Core: unsupported output format: ${output} from sm4`);\r\n }\r\n}\r\n\r\n// ========== 便捷API(函数式,符合设计准则) ==========\r\n/**\r\n * 生成 SM4 CBC 模式专用的安全随机 IV(16字节)\r\n * @param {string} [outputFormat=SM4_OUTPUT_HEX] - 输出格式:hex/uint8array/array/arraybuffer\r\n * @returns {string|Uint8Array|Array|ArrayBuffer} 随机IV\r\n */\r\nexport function generateIv(outputFormat = SM4_OUTPUT_HEX) {\r\n // 1. 校验浏览器是否支持 crypto\r\n if (!window?.crypto?.getRandomValues) {\r\n throw new TypeError(\"generateIv: your browser does not support secure random generation (crypto API) from sm4\");\r\n }\r\n\r\n // 2. 生成 16 字节安全随机数\r\n const ivUint8 = new Uint8Array(IV_SIZE);\r\n window.crypto.getRandomValues(ivUint8);\r\n\r\n // 3. 用导出的常量做格式判断,新增 ArrayBuffer 支持\r\n switch (outputFormat) {\r\n case SM4_OUTPUT_UINT8ARRAY:\r\n return ivUint8;\r\n case SM4_OUTPUT_ARRAY:\r\n return Array.from(ivUint8).map((byte) => Number(byte));\r\n case SM4_OUTPUT_ARRAYBUFFER: // 新增:支持 ArrayBuffer 格式\r\n return ivUint8.buffer;\r\n case SM4_OUTPUT_HEX:\r\n default:\r\n return Array.from(ivUint8)\r\n .map((byte) => {\r\n const hex = byte.toString(16);\r\n return hex.length === 1 ? `0${hex}` : hex;\r\n })\r\n .join(\"\");\r\n }\r\n}\r\n\r\n/**\r\n * 生成 SM4 标准密钥(16字节/32位16进制字符串)\r\n * @param {string} [outputFormat=SM4_OUTPUT_HEX] - 输出格式:hex/uint8array/array/arraybuffer\r\n * @returns {string|Uint8Array|number[]|ArrayBuffer} 16字节SM4密钥\r\n */\r\nexport function generateKey(outputFormat = SM4_OUTPUT_HEX) {\r\n // 校验浏览器/Node环境的安全随机数API\r\n if (!window?.crypto?.getRandomValues && !global?.crypto?.getRandomValues) {\r\n throw new TypeError(\r\n \"generateKey: the current environment does not support secure random number generation. please upgrade your browser/Node.js from sm4\",\r\n );\r\n }\r\n\r\n // 生成16字节随机数(SM4密钥固定16字节)\r\n const cryptoObj = window?.crypto || global?.crypto;\r\n const keyUint8 = new Uint8Array(16);\r\n cryptoObj.getRandomValues(keyUint8);\r\n\r\n // 按格式返回(用常量替代硬编码字符串,新增 ArrayBuffer 支持)\r\n switch (outputFormat) {\r\n case SM4_OUTPUT_UINT8ARRAY:\r\n return keyUint8;\r\n case SM4_OUTPUT_ARRAY:\r\n return Array.from(keyUint8).map((byte) => Number(byte));\r\n case SM4_OUTPUT_ARRAYBUFFER: // 新增:支持 ArrayBuffer 格式\r\n return keyUint8.buffer;\r\n case SM4_OUTPUT_HEX:\r\n default:\r\n return Array.from(keyUint8)\r\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n }\r\n}\r\n\r\n/**\r\n * SM4加密\r\n * @param {string|Array|Uint8Array|ArrayBuffer} input - 输入数据(字符串/字节)\r\n * @param {string|Array|Uint8Array|ArrayBuffer} key - 16字节密钥\r\n * @param {Object} [options] - 选项\r\n * @returns {string|Array|Uint8Array|ArrayBuffer} 加密结果\r\n */\r\nexport function encrypt(input, key, options = {}) {\r\n return sm4Core(input, key, ENCRYPT, options);\r\n}\r\n\r\n/**\r\n * SM4解密\r\n * @param {string|Array|Uint8Array|ArrayBuffer} input - 加密数据(16进制字符串/字节)\r\n * @param {string|Array|Uint8Array|ArrayBuffer} key - 16字节密钥\r\n * @param {Object} [options] - 选项\r\n * @returns {string|Array|Uint8Array|ArrayBuffer} 解密结果\r\n */\r\nexport function decrypt(input, key, options = {}) {\r\n // 解密时如果没传output,默认按加密的output格式(hex)处理,再转utf8\r\n const finalOptions = {\r\n output: SM4_OUTPUT_UTF8, // 解密默认返回utf8字符串\r\n ...options,\r\n };\r\n return sm4Core(input, key, DECRYPT, finalOptions);\r\n}\r\n// 导出模式\r\nexport const MODE = {\r\n ECB: SM4_MODE_ECB,\r\n CBC: SM4_MODE_CBC,\r\n};\r\n// 导出填充\r\nexport const PADDING = SM4_PADDING;\r\n// 导出输出模式\r\nexport const OUTPUT = {\r\n HEX: SM4_OUTPUT_HEX,\r\n UTF8: SM4_OUTPUT_UTF8,\r\n ARRAY: SM4_OUTPUT_ARRAY,\r\n UINT8ARRAY: SM4_OUTPUT_UINT8ARRAY,\r\n ARRAYBUFFER: SM4_OUTPUT_ARRAYBUFFER,\r\n};\r\n","import * as sm4 from \"./sm4.js\";\r\n\r\n/**\r\n * sm4传参和返回的类型,不管是传参还是返回值固定是这几个\r\n */\r\nexport type SM4DataType = string | Uint8Array | ArrayBuffer | number[];\r\n/**\r\n * sm4通用配置\r\n */\r\nexport interface SM4Options {\r\n // 加密模式:ecb/cbc(默认ecb)\r\n mode?: keyof typeof sm4.MODE;\r\n // IV初始向量:仅CBC模式需要,ECB模式不用传\r\n iv?: SM4DataType;\r\n // 填充规则:固定pkcs#7,不用改\r\n padding?: \"pkcs#7\";\r\n // 输出格式:hex/utf8/array/uint8array/arraybuffer(加密默认hex,解密默认utf8)\r\n output?: keyof typeof sm4.OUTPUT;\r\n}\r\n\r\n/**\r\n * sm4 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @param {Object} options 配置\r\n * @returns {string} 加密后的字符串\r\n */\r\nexport function sm4Encrypt(\r\n str: string,\r\n key: SM4DataType,\r\n options?: SM4Options, // 改用互斥联合类型\r\n): SM4DataType {\r\n _validateSM4Options(options, \"encrypt\");\r\n return sm4.encrypt(str, key, options);\r\n}\r\n\r\n/**\r\n * sm4 解密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @param {Object} options 配置\r\n * @returns {string} 解密后的数据\r\n */\r\nexport function sm4Decrypt(\r\n str: string,\r\n key: SM4DataType,\r\n options?: SM4Options, // 解密也改为可选(和加密保持一致,更易用)\r\n): SM4DataType {\r\n _validateSM4Options(options, \"decrypt\");\r\n return sm4.decrypt(str, key, options);\r\n}\r\n\r\n/**\r\n * 生成sm4的key\r\n * @param {string} inputFormat 输入类型 可以任意字符串,其中固定的uint8array、array、hex这3个字符串,会对应生成类型数据\r\n * @returns {SM4DataType} 生成的key\r\n */\r\nexport const generateSM4Key = sm4.generateKey as (inputFormat?: string) => SM4DataType;\r\n\r\n/**\r\n * 生成sm4的iv\r\n * @param {string} inputFormat 输入类型 可以任意字符串,其中固定的uint8array、array、hex这3个字符串,会对应生成类型数据\r\n * @returns {SM4DataType} 生成的iv\r\n */\r\nexport const generateSM4Iv = sm4.generateIv as (inputFormat?: string) => SM4DataType;\r\n\r\n/**\r\n * 校验SM4配置参数的合法性\r\n * @param options 配置项\r\n * @param operation 操作类型(encrypt/decrypt)\r\n */\r\nfunction _validateSM4Options(options: SM4Options = {}, operation: \"encrypt\" | \"decrypt\") {\r\n const { mode = sm4.MODE.ECB, iv } = options;\r\n\r\n // 1. 校验模式是否合法\r\n const validModes = Object.values(sm4.MODE);\r\n if (!validModes.includes(mode)) {\r\n throw new TypeError(\r\n `sm4${operation}:unsupported encryption mode \"${mode}\", supports only ${validModes.join(\"/\")}`,\r\n );\r\n }\r\n\r\n // 2. CBC模式必须传IV\r\n if (mode === sm4.MODE.CBC && !iv) {\r\n throw new TypeError(`sm4${operation}:the CBC mode must be inputted with an IV (initialization vector)`);\r\n }\r\n\r\n // 3. ECB模式禁止传IV(避免误用)\r\n if (mode === sm4.MODE.ECB && iv !== undefined) {\r\n throw new TypeError(\r\n `sm4${operation}: the ECB mode does not require an IV to be passed in. Please do not pass the iv parameter`,\r\n );\r\n }\r\n\r\n // 4. 校验IV长度(如果传了IV)\r\n if (iv) {\r\n let ivLength: number;\r\n if (typeof iv === \"string\") {\r\n // hex字符串:16字节对应32位hex\r\n ivLength = iv.length === 32 ? 16 : iv.length;\r\n } else if (iv instanceof ArrayBuffer) {\r\n ivLength = iv.byteLength;\r\n } else if (iv instanceof Uint8Array) {\r\n ivLength = iv.length;\r\n } else if (Array.isArray(iv)) {\r\n ivLength = iv.length;\r\n } else {\r\n ivLength = 0;\r\n }\r\n\r\n if (ivLength !== 16) {\r\n throw new TypeError(`sm4${operation}:IV must be 16 bytes in length, and the current length is ${ivLength}`);\r\n }\r\n }\r\n\r\n // 5. 校验填充模式(仅允许pkcs#7)\r\n if (options.padding && options.padding !== String(sm4.PADDING)) {\r\n throw new TypeError(\r\n `sm4${operation}: only pkcs#7 padding mode is supported, currently being input ${String(options.padding)}`,\r\n );\r\n }\r\n}\r\n\r\n// sm4的配置\r\nexport const SM4 = {\r\n // sm4的模式\r\n MODE: sm4.MODE,\r\n // sm4的填充\r\n PADDING: sm4.PADDING,\r\n // sm4的输出\r\n OUTPUT: sm4.OUTPUT,\r\n};\r\n","/**\r\n * @module 脱敏\r\n */\r\n/**\r\n * 指定位置的字符串转为星号\r\n * @param {string|number} value 字符串参数\r\n * @param {number} start 转换开始位置\r\n * @param {number} len 显示星号的长度\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOf(value: string, start: number, len: number): string {\r\n value = String(value);\r\n if (start > value.length) return value;\r\n // len小于0和len大于剩余长度\r\n let startStr = \"\";\r\n if (len < 0) len = 0;\r\n if (len > value.length - start) {\r\n len = value.length - start;\r\n }\r\n startStr = String().padEnd(len, \"*\");\r\n return value.substring(0, start) + startStr + value.substring(start + len);\r\n}\r\n\r\n/**\r\n * 姓名中间转为星号\r\n * @param {string} value 姓名\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOfName(value: string): string {\r\n if (value.length === 2) {\r\n return formatStartOf(value, 1, 1);\r\n } else if (value.length > 2) {\r\n return formatStartOf(value, 1, value.length - 2);\r\n } else {\r\n return value;\r\n }\r\n}\r\n\r\n/**\r\n * 手机号码固定位数转为星号\r\n * @param {string} value 手机号码\r\n * @param {number} start 前缀长度,默认3位\r\n * @param {number} len 显示星号的长度,默认4位\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOfMobile(value: string, start: number = 3, len: number = 4): string {\r\n return formatStartOf(value, start, len);\r\n}\r\n\r\n/**\r\n * 身份证号码固定位数转为星号\r\n * @param {string} value 身份证号码\r\n * @param {number} start 前缀长度,默认4位\r\n * @param {number} len 显示星号的长度,默认8位\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOfIDCard(value: string, start: number = 4, len: number = 8): string {\r\n return formatStartOf(value, start, len);\r\n}\r\n\r\n/**\r\n * 银行卡号固定位数转为星号\r\n * @param {string} value 银行卡号\r\n * @param {number} start 前缀长度,默认4位\r\n * @param {number} len 显示星号的长度,默认10位\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOfBankCard(value: string, start: number = 4, len: number = 11): string {\r\n return formatStartOf(value, start, len);\r\n}\r\n","/**\r\n * @module 身份证号码\r\n */\r\nimport { isNull } from \"@/validate\";\r\nimport { toDate, getAge } from \"@/date\";\r\nimport { ID_CARD } from \"@/constants\";\r\n\r\n/**\r\n * 根据身份证号码获取信息\r\n * @description 能获取到 籍贯,出生日期,年龄,性别\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {Object} 返回身份证信息对象\r\n */\r\nexport function getInfoByIDCard(idCard: string):\r\n | {\r\n province: string | undefined;\r\n birthday: string | undefined;\r\n age: number | undefined;\r\n sex: string | undefined;\r\n }\r\n | undefined {\r\n if (isNull(idCard)) return;\r\n return {\r\n // 省份\r\n province: getProvinceByIDCard(idCard),\r\n // 生日\r\n birthday: getBirthdayByIDCard(idCard),\r\n // 年龄\r\n age: getAgeByIDCard(idCard),\r\n // 性别\r\n sex: getSexByIDCard(idCard),\r\n };\r\n}\r\n\r\n/**\r\n * 根据身份证号码获得生日\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {string} 返回生日\r\n */\r\nexport function getBirthdayByIDCard(idCard: string): string | undefined {\r\n if (isNull(idCard)) return;\r\n // 15位身份证\r\n if (idCard.length === 15) {\r\n return \"19\" + idCard.substring(6, 8) + \"-\" + idCard.substring(8, 10) + \"-\" + idCard.substring(10, 12);\r\n }\r\n // 18位身份证\r\n if (idCard.length === 18) {\r\n return idCard.substring(6, 10) + \"-\" + idCard.substring(10, 12) + \"-\" + idCard.substring(12, 14);\r\n }\r\n}\r\n\r\n/**\r\n * 根据身份证号码获得年龄\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {number} 返回年龄\r\n */\r\nexport function getAgeByIDCard(idCard: string): number | undefined {\r\n if (isNull(idCard)) return;\r\n const birthday = getBirthdayByIDCard(idCard);\r\n if (birthday) {\r\n return getAge(toDate(String(birthday))!);\r\n }\r\n}\r\n\r\n/**\r\n * 根据身份证号码获得性别\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {string} 返回性别\r\n */\r\nexport function getSexByIDCard(idCard: string): string | undefined {\r\n if (isNull(idCard)) return;\r\n // 15位身份证\r\n if (idCard.length === 15) {\r\n return Number(idCard.substring(14)) % 2 === 0 ? (ID_CARD.SEX.WOMAN as string) : (ID_CARD.SEX.MAN as string);\r\n }\r\n // 18位身份证\r\n if (idCard.length === 18) {\r\n return Number(idCard.substring(16, 17)) % 2 === 0 ? (ID_CARD.SEX.WOMAN as string) : (ID_CARD.SEX.MAN as string);\r\n }\r\n}\r\n\r\n/**\r\n * 根据身份证号码获得省份\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {string} 返回省份\r\n */\r\nexport function getProvinceByIDCard(idCard: string): string | undefined {\r\n if (isNull(idCard)) return;\r\n const prefix = idCard.substring(0, 2);\r\n if (prefix) {\r\n return ID_CARD.PROVINCE[prefix];\r\n }\r\n}\r\n","/**\r\n * @module 分页\r\n */\r\n/**\r\n * 获得分页起始数\r\n * @param {Object} pagination 分页参数\r\n * @returns {Array} 返回起始数\r\n */\r\nexport function getLimit(\r\n pagination: { page: number; pageSize: number; total: number; totalPage: number; pagerCount: number } = {\r\n page: 1,\r\n pageSize: 10,\r\n total: 0,\r\n totalPage: 0,\r\n pagerCount: 7,\r\n },\r\n): number[] {\r\n return [pagination.pageSize * (pagination.page - 1), pagination.pageSize * pagination.page];\r\n}\r\n\r\n/**\r\n * 获得总条数\r\n * @param {Object} pagination 分页参数\r\n * @returns {number} 返回总条数\r\n */\r\nexport function getTotalPage(\r\n pagination: { page: number; pageSize: number; total: number; totalPage: number; pagerCount: number } = {\r\n page: 1,\r\n pageSize: 10,\r\n total: 0,\r\n totalPage: 0,\r\n pagerCount: 7,\r\n },\r\n): number {\r\n return Math.ceil((pagination.total || 0) / (pagination.pageSize || 0));\r\n}\r\n\r\n/**\r\n * 获得彩虹分页器\r\n * @param {Object} pagination 分页参数\r\n * @param {Function} callback 回调函数\r\n * @returns {Promise} 返回彩虹分页器数据\r\n */\r\nexport function getRainbowPager(\r\n pagination: { page: number; pageSize: number; total: number; totalPage: number; pagerCount: number } = {\r\n page: 1,\r\n pageSize: 10,\r\n total: 0,\r\n totalPage: 0,\r\n pagerCount: 7,\r\n },\r\n callback: (pager: number[]) => void,\r\n): Promise<number[]> {\r\n return new Promise((resolve) => {\r\n // 分页参数\r\n const page = pagination.page || 1;\r\n const totalPage = pagination.totalPage > 0 ? pagination.totalPage : getTotalPage(pagination);\r\n const pagerCount = pagination.pagerCount || 7;\r\n\r\n // 计算参数\r\n const isEven = (pagerCount & 1) === 0;\r\n const left = pagerCount >> 1;\r\n let right = pagerCount >> 1;\r\n let pagerLength = pagerCount;\r\n\r\n // 计算生成的分页器数量\r\n if (isEven) {\r\n right++;\r\n }\r\n if (totalPage < pagerCount) {\r\n pagerLength = totalPage;\r\n }\r\n\r\n // 分页器数组\r\n const pager = new Array(pagerLength);\r\n\r\n // 生成分页器\r\n if (totalPage >= pagerCount) {\r\n if (page <= left) {\r\n for (let i = 0; i < pager.length; i++) {\r\n pager[i] = i + 1;\r\n }\r\n } else if (page > totalPage - right) {\r\n for (let i = 0; i < pager.length; i++) {\r\n pager[i] = i + totalPage - pagerCount + 1;\r\n }\r\n } else {\r\n for (let i = 0; i < pager.length; i++) {\r\n pager[i] = i + page - left + (isEven ? 1 : 0);\r\n }\r\n }\r\n } else {\r\n for (let i = 0; i < pager.length; i++) {\r\n pager[i] = i + 1;\r\n }\r\n }\r\n\r\n // 支持回调函数和Promise\r\n callback && callback(pager);\r\n resolve(pager);\r\n });\r\n}\r\n\r\n/**\r\n * 获得上一页\r\n * @param {Object} pagination 分页参数\r\n * @param {Function} callback 回调函数\r\n * @returns {Promise} 返回上一页\r\n */\r\nexport function getPrevPage(\r\n pagination = { page: 1, pageSize: 10, total: 0, totalPage: 0, pagerCount: 7 },\r\n callback: (page: number) => void,\r\n): Promise<number> {\r\n return new Promise((resolve) => {\r\n if (pagination.page > 1) {\r\n pagination.page--;\r\n } else {\r\n pagination.page = 1;\r\n }\r\n\r\n // 支持回调函数和Promise\r\n callback && callback(pagination.page);\r\n resolve(pagination.page);\r\n });\r\n}\r\n\r\n/**\r\n * 获得下一页\r\n * @description 最后一页会根据totalPage参数判断,如果不传此参数,则会根据参数中pageSize和total重新计算总页数\r\n * @param {Object} pagination 分页参数\r\n * @param {Function} callback 回调函数\r\n * @returns {Promise} 返回下一页\r\n */\r\nexport function getNextPage(\r\n pagination = { page: 1, pageSize: 10, total: 0, totalPage: 0, pagerCount: 7 },\r\n callback: (page: number) => void,\r\n): Promise<number> {\r\n return new Promise((resolve) => {\r\n // 获得总页数,如果没有传totalPage,则需要根据传的pageSize和total计算\r\n const totalPage = pagination.totalPage > 0 ? pagination.totalPage : getTotalPage(pagination);\r\n\r\n // 计算当前页大于0和小与0的情况\r\n if (pagination.page > 0) {\r\n if (pagination.page < totalPage) {\r\n pagination.page++;\r\n } else {\r\n pagination.page = totalPage;\r\n }\r\n } else {\r\n pagination.page = 1;\r\n }\r\n\r\n // 支持回调函数和Promise\r\n callback && callback(pagination.page);\r\n resolve(pagination.page);\r\n });\r\n}\r\n","/**\r\n * @module 浏览器Url\r\n */\r\nimport { REGEXP } from \"@/constants\";\r\nimport { isArray } from \"@/validate\";\r\nimport { arrayInsertAfter, arrayInsertBefore } from \"@/array\";\r\n\r\n/**\r\n * 获得协议名\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回协议名\r\n */\r\nexport function getProtocol(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[1];\r\n }\r\n}\r\n\r\n/**\r\n * 获得主机地址\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回主机地址\r\n */\r\nexport function getHost(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return (match[2] || \"\") + (match[3] ? \":\" + match[3] : \"\");\r\n }\r\n}\r\n\r\n/**\r\n * 获得主机名称\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回主机名称\r\n */\r\nexport function getHostName(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[2];\r\n }\r\n}\r\n\r\n/**\r\n * 获得端口号\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回端口号\r\n */\r\nexport function getPort(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n\r\n if (match) {\r\n return match[3];\r\n }\r\n}\r\n\r\n/**\r\n * 获得地址路径\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回地址路径\r\n */\r\nexport function getUrlPath(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[4];\r\n }\r\n}\r\n\r\n/**\r\n * 获得hash字符串\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回hash字符串\r\n */\r\nexport function getUrlHash(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[6];\r\n }\r\n}\r\n\r\n/**\r\n * 获得查询参数字符串\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function getSearchString(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[5];\r\n }\r\n}\r\n\r\n/**\r\n * 查询参数字符串中是否包含某个参数\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function hasSearchParam(url: string = window.location.href, name: string): boolean {\r\n const params = parseSearchParam(url);\r\n return params[name] !== undefined;\r\n}\r\n\r\n/**\r\n * 查询参数字符串中获得某个参数的值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @returns {string} 返回查询到的值\r\n */\r\nexport function getSearchParam(url: string = window.location.href, name = \"\"): string | undefined {\r\n name = name.replace(/[[\\]]/g, \"\\\\$&\");\r\n url = getSearchString(url) || \"\";\r\n const reg = new RegExp(\"(^|&)\" + name + \"=([^&]*)(&|$)\");\r\n const match = url.substring(0).match(reg);\r\n if (match) {\r\n return decodeURIComponent(match[2]);\r\n }\r\n}\r\n\r\n/**\r\n * 查询参数字符串中设置某个参数的值\r\n * @param {string} name 参数名\r\n * @param {string|number|Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function setSearchParam(\r\n url = window.location.href,\r\n name = \"\",\r\n value: string | number | number[] | string[],\r\n): string {\r\n const params: Record<string, any> = parseSearchParam(url);\r\n params[name] = value;\r\n // 返回替换后的url\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + stringifySearchParam(params));\r\n}\r\n\r\n/**\r\n * 查询参数字符串转为对象\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {Object} 返回参数对象\r\n */\r\nexport function parseSearchParam(url: string = window.location.href): Record<string, any> {\r\n const searchString = getSearchString(url) || \"\";\r\n const searchArr = searchString.split(\"&\");\r\n const param: Record<string, any> = {};\r\n for (let i = 0; i < searchArr.length; i++) {\r\n const arr = searchArr[i].split(\"=\");\r\n param[decodeURIComponent(arr[0])] = decodeURIComponent(arr[1] || \"\");\r\n }\r\n return param;\r\n}\r\n\r\n/**\r\n * 对象转为查询参数字符串\r\n * @param {Object} params 参数对象\r\n * @param {string} url url地址,如果不为空,则会拼接好查询参数字符串的url地址\r\n * @returns {string} 返回参数字符串\r\n */\r\nexport function stringifySearchParam(params: Record<string, any>, url: string = \"\"): string {\r\n if (typeof params !== \"object\") return params;\r\n\r\n const arr = [];\r\n for (const key in params) {\r\n const value = params[key];\r\n if (isArray(value)) {\r\n for (let i = 0; i < value.length; ++i) {\r\n arr.push(encodeURIComponent(key + \"[\" + i + \"]\") + \"=\" + encodeURIComponent(value[i]));\r\n }\r\n } else {\r\n arr.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(params[key]));\r\n }\r\n }\r\n // 如果url不为空,则会返回拼接好url字符串\r\n if (url) {\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + arr.join(\"&\"));\r\n } else {\r\n return arr.join(\"&\");\r\n }\r\n}\r\n\r\n/**\r\n * 查询参数字符串中在最前面追加新参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @param {string|number|Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function prependSearchParam(\r\n url: string = window.location.href,\r\n name: string,\r\n value: string | number | number[] | string[],\r\n): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\") || [];\r\n if (Array.isArray(value)) {\r\n const arr = [];\r\n for (let i = 0; i < value.length; i++) {\r\n arr.push(`${encodeURIComponent(name)}[${i}]=${encodeURIComponent(value[i])}`);\r\n }\r\n searchArr.unshift(...arr);\r\n } else {\r\n searchArr.unshift(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`);\r\n }\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + searchArr.join(\"&\"));\r\n}\r\n\r\n/**\r\n * 查询参数字符串中在某个参数的前面追加新参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @param {string|number|Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @param {string} beforeParam 在前面追加参数的名称\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function prependToSearchParam(\r\n url: string = window.location.href,\r\n beforeParam: string,\r\n name: string,\r\n value: string | number | number[] | string[],\r\n): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\");\r\n const beforeIndex = searchArr.findIndex((v) => v.includes(beforeParam));\r\n const beforeArr = arrayInsertBefore(searchArr, beforeIndex, `${name}=${value}`);\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + beforeArr.join(\"&\"));\r\n}\r\n\r\n/**\r\n * 查询参数字符串中在最后面追加新参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @param {string,number,Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function appendSearchParam(\r\n url: string = window.location.href,\r\n name: string,\r\n value: string | number | number[] | string[],\r\n): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\");\r\n searchArr.push(`${name}=${value}`);\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + searchArr.join(\"&\"));\r\n}\r\n\r\n/**\r\n * 查询参数字符串中在某个参数的后面追加新参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @param {string,number,Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @param {string} afterName 在后面追加参数的名称\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function appendToSearchParam(\r\n url: string = window.location.href,\r\n afterName: string,\r\n name: string,\r\n value: string | number | number[] | string[],\r\n): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\");\r\n const beforeIndex = searchArr.findIndex((v) => v.includes(afterName));\r\n const afterArr = arrayInsertAfter(searchArr, beforeIndex, `${name}=${value}`);\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + afterArr.join(\"&\"));\r\n}\r\n\r\n/**\r\n * 查询参数字符串中移除某个参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function removeSearchParam(url: string = window.location.href, name: string): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\");\r\n const delIndex = searchArr.findIndex((v) => v.includes(name));\r\n if (delIndex > -1) {\r\n searchArr.splice(delIndex, 1);\r\n }\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + searchArr.join(\"&\"));\r\n}\r\n","/**\r\n * @module 浏览器Cookie\r\n */\r\nimport { isEmpty } from \"@/validate\";\r\n\r\n/**\r\n * 浏览器是否支持 Cookie\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isSupportCookie(): boolean {\r\n return window.navigator.cookieEnabled;\r\n}\r\n\r\n/* cookie存储 */\r\n/**\r\n * 通过name获取cookie\r\n * @param {string} name 参数name\r\n * @returns {string} 返回获取的值\r\n */\r\nexport function getCookie(name: string): string {\r\n if (typeof document == \"undefined\") return \"\";\r\n // cookie中每个分号后面是有个空格的,需要替换掉\r\n const arr = document.cookie ? document.cookie.replace(/\\s/g, \"\").split(\";\") : [];\r\n for (const i in arr) {\r\n const tempArr = arr[i].split(\"=\");\r\n if (tempArr[0] === name) {\r\n return decodeURIComponent(tempArr[1]);\r\n }\r\n }\r\n return \"\";\r\n}\r\n\r\n/**\r\n * 通过name设置cookie\r\n * 注:timestamp参数不填,则默认为session级别,浏览器关闭即cookie过期\r\n * @param {string} name 参数name\r\n * @param {string} value 设置的value\r\n * @param {number} timestamp 过期的时间戳值,默认为一天,设置一天过期则为:24*60*60*1000\r\n */\r\nexport function setCookie(name: string, value: string, timestamp: number = 24 * 60 * 60 * 1000) {\r\n if (typeof document == \"undefined\") return;\r\n document.cookie = name + \"=\" + value + \";expires=\" + new Date(Date.now() + timestamp);\r\n}\r\n\r\n/**\r\n * 通过name删除cookie\r\n * @param {string} name 参数name\r\n */\r\nexport function removeCookie(name: string) {\r\n if (isEmpty(name)) return;\r\n setCookie(name, \"\", -1);\r\n}\r\n\r\n/**\r\n * 清空当前站点域名的cookie\r\n * @param {string} domain 域名地址,默认是当前站点域名\r\n */\r\nexport function clearCookie(domain: string = document.domain) {\r\n const names = document.cookie.match(/[^ =;]+(?==)/g) || [];\r\n if (names && names.length > 0) {\r\n for (let i = names.length; i--; ) {\r\n document.cookie =\r\n names[i] + \"=0;path=/;\" + domain ? \"domain=\" + domain + \";\" : \"\" + \"expires=\" + new Date(0).toUTCString();\r\n }\r\n }\r\n}\r\n","/**\r\n * @module 浏览器Dom\r\n */\r\n/* Class操作 */\r\n/**\r\n * 判断元素包含某个类名\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} className 类名\r\n * @return {boolean} 返回true和false\r\n */\r\nexport function hasClass(elem: HTMLElement, className: string): boolean {\r\n return elem.className.indexOf(className) > 0;\r\n}\r\n\r\n/**\r\n * 元素添加类名\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} className 类名\r\n */\r\nexport function addClass(elem: HTMLElement, className: string) {\r\n if (!hasClass(elem, className)) {\r\n elem.className += \" \" + className;\r\n }\r\n}\r\n\r\n/**\r\n * 元素删除类名\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} className 类名\r\n */\r\nexport function removeClass(elem: HTMLElement, className: string) {\r\n if (hasClass(elem, className)) {\r\n elem.className = elem.className.replace(new RegExp(className, \"gm\"), \"\");\r\n }\r\n}\r\n\r\n/**\r\n * 元素替换类名\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} newClassName 新的类名\r\n * @param {string} oldClassName 被替换掉的旧类名\r\n */\r\nexport function replaceClass(elem: HTMLElement, newClassName: string, oldClassName: string) {\r\n removeClass(elem, oldClassName);\r\n addClass(elem, newClassName);\r\n}\r\n\r\n/* Style操作 */\r\n/**\r\n * 添加元素的style样式\r\n * @param {HTMLElement} elem 元素\r\n * @param {Object} styles 样式属性集合\r\n */\r\n\r\nexport function addStyle(elem: HTMLElement, styles: Record<string, string> = {}) {\r\n if (!elem) return;\r\n for (const [key, value] of Object.entries(styles)) {\r\n elem.style.setProperty(key, value);\r\n }\r\n}\r\n\r\n/**\r\n * 获取元素的style样式\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} name 属性\r\n * @returns {string|undefined} 返回样式的值\r\n */\r\nexport function getStyle(elem: HTMLElement, name: string): string | unknown {\r\n if (!elem) return;\r\n return elem.style.getPropertyValue(name);\r\n}\r\n\r\n/**\r\n * 删除元素的style样式\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} name 属性\r\n */\r\nexport function removeStyle(elem: HTMLElement, name: string) {\r\n if (!elem) return;\r\n elem.style.removeProperty(name);\r\n}\r\n\r\n/* Html转码 */\r\n/**\r\n * html标签转义\r\n * @param {string} htmlStr html字符串\r\n * @returns {string} 返回转义后的字符串\r\n */\r\nexport function htmlEncode(htmlStr: string): string {\r\n const temp = {\r\n \"<\": \"&lt;\",\r\n \">\": \"&gt;\",\r\n \"&\": \"&amp;\",\r\n \"(\": \"&#40;\",\r\n \")\": \"&#41;\",\r\n \"/\": \"&#47;\",\r\n \" \": \"&nbsp;\",\r\n '\"': \"&quot;\",\r\n \"'\": \"&#39;\",\r\n } as const;\r\n return htmlStr.replace(/[<>&|()\\/ '\"]/g, function (c: string) {\r\n return (temp as any)[c];\r\n });\r\n}\r\n\r\n/**\r\n * html标签解码\r\n * @param {string} htmlStr html字符串\r\n * @returns {string} 返回解析后的字符串\r\n */\r\nexport function htmlDecode(htmlStr: string): string {\r\n const temp = {\r\n \"&lt;\": \"<\",\r\n \"&gt;\": \">\",\r\n \"&amp;\": \"&\",\r\n \"&#40;\": \"(\",\r\n \"&#41;\": \")\",\r\n \"&#47;\": \"/\",\r\n \"&nbsp;\": \" \",\r\n \"&quot;\": '\"',\r\n \"&#39;\": \"'\",\r\n } as const;\r\n return htmlStr.replace(/(&lt;|&gt;|&amp;|&#40;|&#41;|&#47;|&nbsp;|&quot;|&#39;)/gi, function (all, t) {\r\n return (temp as any)[t];\r\n });\r\n}\r\n","/**\r\n * @module 浏览器Device\r\n */\r\n/* 浏览器信息 */\r\n/**\r\n * 获取浏览器信息\r\n * @description 会获取到浏览器对应的名称以及版本\r\n * @returns {Object} 返回浏览器信息\r\n */\r\nexport function getBrowserInfo(): { name: string; version: string } | undefined {\r\n const ua = window && window.navigator.userAgent.toLowerCase();\r\n\r\n // ie\r\n const ie = ua.match(/rv:([\\d.]+)\\) like gecko/) || ua.match(/msie ([\\d\\.]+)/);\r\n // edge\r\n const edge = ua.match(/edg\\/([\\d\\.]+)/);\r\n // firefox\r\n const firefox = ua.match(/firefox\\/([\\d\\.]+)/);\r\n // opera\r\n const opera = ua.match(/(?:opera|opr).([\\d\\.]+)/);\r\n // chrome\r\n const chrome = ua.match(/chrome\\/([\\d\\.]+)/);\r\n // safari\r\n const safari = ua.match(/version\\/([\\d\\.]+).*safari/);\r\n\r\n // 判断类型\r\n if (ie) return { name: \"ie\", version: ie[1] };\r\n else if (edge) return { name: \"edge\", version: edge[1] };\r\n else if (firefox) return { name: \"firefox\", version: firefox[1] };\r\n else if (opera) return { name: \"opera\", version: opera[1] };\r\n else if (chrome) return { name: \"chrome\", version: chrome[1] };\r\n else if (safari) return { name: \"safari\", version: safari[1] };\r\n else return;\r\n}\r\n\r\n/* 设备类型 */\r\n/**\r\n * 判断是pc端\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isPc(): boolean {\r\n return !isPhone();\r\n}\r\n\r\n/**\r\n * 判断是手机端\r\n * @description 包含 android、iphone、黑莓手机、微软手机 等多种操作系统机型\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isPhone(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /Android|webOS|iPhone|iPod|BlackBerry|Windows Phone|IEMobile/i.test(ua);\r\n}\r\n\r\n/* 操作系统类型 */\r\n/**\r\n * 判断是 android\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isAndroid(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /Android|BlackBerry/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 ios\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isIos(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /iPhone|iPad|iPod|iOS/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 windows phone\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isWindowsPhone(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /Windows Phone/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 windows\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isWindows(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /win/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 linux\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isLinux(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /linux/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 Mac\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isMac(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /mac/i.test(ua);\r\n}\r\n\r\n/* 苹果设备类型 */\r\n/**\r\n * 判断是iphone\r\n *@returns {boolean} 返回true和false\r\n */\r\nexport function isIphone(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /iPhone/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是ipad\r\n *@return {boolean} 返回true和false\r\n */\r\nexport function isIpad(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /iPod/i.test(ua);\r\n}\r\n\r\n/* 手机浏览器类型 */\r\n/**\r\n * 判断是微信内置浏览器\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isWeixin(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /MicroMessenger/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是QQ内置浏览器\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isQQ(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /QQ/i.test(ua);\r\n}\r\n","/**\r\n * @module 浏览器Clipboard\r\n */\r\n\r\nimport { blobToText } from \"@/file\";\r\n\r\n/**\r\n * 获得剪切板数据\r\n * @description 获得的剪切板的数据是会返回多个可用的MIME类型,比如是纯文本就返回一个['text/plain'],是复制的html则会返回两个可用的['text/plain','text/html'],是复制的图片则是['image/png']\r\n * @returns {Promise} 返回剪切板的数据,是数组形式,如果是文本则是字符串,否则是blob数据\r\n */\r\nexport function getClipboard(): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n if (window.navigator.clipboard) {\r\n window.navigator.clipboard.read().then((clipboardItems) => {\r\n const list: any[] = [];\r\n for (const item of clipboardItems) {\r\n for (const type of item.types) {\r\n item.getType(type).then(async (blob) => {\r\n // 文本类型,可以直接输出为字符串\r\n if (blob.type.includes(\"text\")) {\r\n const text = await blobToText(blob);\r\n list.push({ type: blob.type, data: text });\r\n }\r\n // 图片和其他文件类型,返回blob对象\r\n else {\r\n list.push({ type: blob.type, data: blob });\r\n }\r\n });\r\n }\r\n }\r\n resolve(list);\r\n });\r\n } else {\r\n console.warn(\"not support navigator clipboard!\");\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 获得剪切板文本\r\n * @returns {Promise} 返回剪切板文本\r\n */\r\nexport function getClipboardText(): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n if (window && window.navigator) {\r\n window.navigator.clipboard\r\n .readText()\r\n .then((text) => {\r\n resolve(text);\r\n })\r\n .catch((error) => {\r\n reject(error);\r\n });\r\n } else {\r\n console.warn(\"not support navigator clipboard!\");\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 设置剪切板数据\r\n * @description 可以设置文本或者blob类型的数据\r\n * @param {string|Blob} data 写入的数据,可以是文本或blob数据\r\n * @returns {Promise} 返回结果\r\n */\r\nexport function setClipboard(data: string | Blob): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n // 现代浏览器\r\n if (window && window.navigator) {\r\n let clipboardItem = null;\r\n // 是文本类型\r\n if (typeof data === \"string\") {\r\n const blob = new Blob([data], { type: \"text/plain\" });\r\n clipboardItem = new window.ClipboardItem({\r\n [\"text/plain\"]: blob,\r\n });\r\n }\r\n // 其他文件类型\r\n else {\r\n clipboardItem = new window.ClipboardItem({ [data.type]: data });\r\n }\r\n\r\n // 写入到剪切板中\r\n window.navigator.clipboard.write([clipboardItem]).then(\r\n (success) => {\r\n resolve(true);\r\n },\r\n (failed) => {\r\n reject(false);\r\n },\r\n );\r\n } else {\r\n console.warn(\"not support navigator clipboard!\");\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 设置剪切板文本\r\n * @param {string} text 写入的文本\r\n * @returns {Promise} 返回结果\r\n */\r\nexport function setClipboardText(text: string): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n // 现代浏览器\r\n if (window && window.navigator) {\r\n window.navigator.clipboard.writeText(text).then(\r\n (success) => {\r\n resolve(true);\r\n },\r\n (failed) => {\r\n reject(false);\r\n },\r\n );\r\n } else {\r\n console.warn(\"not support navigator clipboard!\");\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 清空剪切板\r\n * @returns {Promise} 返回结果\r\n */\r\nexport function clearClipboard(): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n setClipboardText(\"\")\r\n .then(() => resolve(true))\r\n .catch(reject);\r\n });\r\n}\r\n","/**\r\n * 语言相关常量配置(全局只读)\r\n *\r\n * ZH: 中文\r\n * - zh\r\n *\r\n * EN: 英文\r\n * - en\r\n */\r\nexport const LANG: Record<string, any> = {\r\n // 中文\r\n ZH: \"zh\",\r\n // 英文\r\n EN: \"en\",\r\n} as const;\r\n","import * as Base64 from \"./base64.js\";\r\n/**\r\n * Base64编码\r\n * @param str 待编码的UTF8字符串\r\n * @param urlSafe 是否生成URL安全的Base64(默认false)\r\n * @returns Base64字符串\r\n */\r\nexport function base64Encode(str: string, urlSafe: boolean = false): string {\r\n return Base64.encode(str, urlSafe);\r\n}\r\n\r\n/**\r\n * Base64解码\r\n * @param str 待解码的Base64字符串\r\n * @returns 解码后的UTF8字符串\r\n */\r\nexport function base64Decode(str: string): string {\r\n return Base64.decode(str);\r\n}\r\n\r\n/**\r\n * URL安全Base64编码\r\n * @param str 待编码的UTF8字符串\r\n * @returns URL安全的Base64字符串\r\n */\r\nexport function base64EncodeURI(str: string): string {\r\n return Base64.encodeURI(str);\r\n}\r\n\r\n/**\r\n * URL安全Base64解码\r\n * @param str 待解码的URL安全Base64字符串\r\n * @returns 解码后的UTF8字符串\r\n */\r\nexport function base64DecodeURI(str: string): string {\r\n return Base64.decodeURI(str);\r\n}\r\n\r\n/**\r\n * Uint8Array转Base64字符串\r\n * @param uint8Array 待编码的字节数组\r\n * @param urlSafe 是否生成URL安全的Base64(默认false)\r\n * @returns Base64字符串\r\n */\r\nexport function base64FromUint8Array(uint8Array: Uint8Array, urlSafe: boolean = false): string {\r\n return Base64.fromUint8Array(uint8Array, urlSafe);\r\n}\r\n\r\n/**\r\n * Base64字符串转Uint8Array\r\n * @param base64Str 待解码的Base64字符串\r\n * @param urlSafe 是否为URL安全的Base64(默认false)\r\n * @returns 解码后的字节数组\r\n */\r\nexport function base64ToUint8Array(base64Str: string, urlSafe: boolean = false): Uint8Array {\r\n return Base64.toUint8Array(base64Str, urlSafe);\r\n}\r\n\r\n/**\r\n * 十六进制字符串转Base64字符串\r\n * @param hexStr 待编码的十六进制字符串\r\n * @param urlSafe 是否生成URL安全的Base64(默认false)\r\n * @returns Base64字符串\r\n */\r\nexport function base64FromHex(hexStr: string, urlSafe: boolean = false): string {\r\n return Base64.fromHex(hexStr, urlSafe);\r\n}\r\n\r\n/**\r\n * Base64字符串转十六进制字符串\r\n * @param base64Str 待解码的Base64字符串\r\n * @param urlSafe 是否为URL安全的Base64(默认false)\r\n * @returns 解码后的十六进制字符串\r\n */\r\nexport function base64ToHex(base64Str: string, urlSafe: boolean = false): string {\r\n return Base64.toHex(base64Str, urlSafe);\r\n}\r\n","/* localStorage存储 */\r\n/**\r\n * 通过key从localStorage缓存中获取数据\r\n * @param {string} key key值\r\n * @returns {string} 返回数据\r\n */\r\nexport function getLocalStorage(key: string): string | undefined {\r\n return (window && window.localStorage.getItem(key)) || undefined;\r\n}\r\n\r\n/**\r\n * 设置localStorage缓存数据\r\n * @param {string} key key值\r\n * @param {string} value value值\r\n */\r\nexport function setLocalStorage(key: string, value: string): void {\r\n window && window.localStorage.setItem(key, value);\r\n}\r\n\r\n/**\r\n * 通过key从localStorage缓存中删除数据\r\n * @param {string} key key值\r\n */\r\nexport function removeLocalStorage(key: string): void {\r\n window && window.localStorage.removeItem(key);\r\n}\r\n\r\n/**\r\n * 清空localStorage缓存中所有数据\r\n */\r\nexport function clearLocalStorage(): void {\r\n window && window.localStorage.clear();\r\n}\r\n","/* sessionStorage存储 */\r\n/**\r\n * 通过key从sessionStorage缓存中获取数据\r\n * @param {string} key key值\r\n * @returns {string} 返回数据\r\n */\r\nexport function getSessionStorage(key: string): string | undefined {\r\n return (window && window.sessionStorage.getItem(key)) || undefined;\r\n}\r\n\r\n/**\r\n * 设置sessionStorage缓存数据\r\n * @param {string} key key值\r\n * @param {string} value value值\r\n */\r\nexport function setSessionStorage(key: string, value: string): void {\r\n window && window.sessionStorage.setItem(key, value);\r\n}\r\n\r\n/**\r\n * 通过key从sessionStorage缓存中删除数据\r\n * @param {string} key key值\r\n */\r\nexport function removeSessionStorage(key: string): void {\r\n window && window.sessionStorage.removeItem(key);\r\n}\r\n\r\n/**\r\n * 清空sessionStorage缓存中所有数据\r\n */\r\nexport function clearSessionStorage(): void {\r\n window && window.sessionStorage.clear();\r\n}\r\n","/**\r\n * @module 函数\r\n */\r\n/**\r\n * 防抖函数\r\n * @description 事件执行后,在延迟时间内如果再次执行,会清空定时器重新延迟执行,举例:用户在输入框进行输入搜索,最终是会获取到最后一次输入,节约请求资源\r\n * @param {Function} fn 目标函数\r\n * @param {number} delay 延迟时间,单位毫秒,默认 1*1000 毫秒\r\n * @param {boolean} immediate 是否立即执行,默认true\r\n * @returns {Function} 返回function()\r\n */\r\nexport function debounce<T extends (...args: any[]) => any>(\r\n fn: T,\r\n delay: number = 1000,\r\n immediate: boolean = true,\r\n): (...args: Parameters<T>) => ReturnType<T> | void {\r\n // 定时器\r\n let timer: ReturnType<typeof setTimeout> | null = null;\r\n return function (this: ThisParameterType<T>, ...args: Parameters<T>) {\r\n // 先关闭定时器\r\n if (timer) clearTimeout(timer);\r\n\r\n // 立即执行判断\r\n if (immediate) {\r\n // 如果需要立即执行\r\n // 开启新定时器防止短时间内再次触发\r\n const canExecute = !timer;\r\n timer = setTimeout(() => {\r\n timer = null;\r\n }, delay);\r\n if (canExecute) fn.apply(this, args);\r\n }\r\n // 如果不需要立即执行\r\n else {\r\n // 每次触发开启新定时器即可\r\n timer = setTimeout(() => {\r\n fn.apply(this, args);\r\n }, delay);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * 节流函数\r\n * @description 高频触发时,在指定时间间隔内只执行一次,举例:监听页面滚动,不会频繁触发,只会在固定时间内获取一次\r\n * @param {Function} fn 目标函数\r\n * @param {number} interval 时间间隔,单位毫秒,默认1000毫秒\r\n * @returns {Function} 返回function()\r\n */\r\nexport function throttle<T extends (...args: any[]) => any>(\r\n fn: T,\r\n interval: number = 1000,\r\n): (...args: Parameters<T>) => ReturnType<T> | void {\r\n // 定时器\r\n let timer: ReturnType<typeof setTimeout> | null = null;\r\n return function (this: ThisParameterType<T>, ...args: Parameters<T>) {\r\n // 有定时器则返回\r\n if (timer) return;\r\n timer = setTimeout(() => {\r\n timer = null;\r\n fn.apply(this, args);\r\n }, interval);\r\n };\r\n}\r\n\r\n/**\r\n * 睡眠延迟执行\r\n * @description 需要配合 async/await 来达到延迟效果\r\n * @param {number} delay 延迟时间,单位毫秒,默认1000毫秒\r\n */\r\nexport function sleep(delay = 1000) {\r\n return new Promise((resolve) => setTimeout(resolve, delay));\r\n}\r\n","/**\r\n * @module 生成Id\r\n */\r\n/**\r\n * 生成UUID\r\n * @param {Number} len 生成的长度,默认32位\r\n * @param {Number} radix 进制数,默认16进制\r\n * @example\r\n * getUUID() // 输出:0a559343dbbf0e7e6c1de90163e7aa0a\r\n * @returns {String} 返回字符串\r\n */\r\nexport function getUUID(len: number = 32, radix: number = 16): string {\r\n const CHARS = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\".split(\"\");\r\n const uuid = [];\r\n let i = 0;\r\n radix = radix || CHARS.length;\r\n if (len) {\r\n for (i = 0; i < len; i++) uuid[i] = CHARS[0 | (Math.random() * radix)];\r\n } else {\r\n let r;\r\n uuid[8] = uuid[13] = uuid[18] = uuid[23] = \"-\";\r\n uuid[14] = \"4\";\r\n for (i = 0; i < 36; i++) {\r\n if (!uuid[i]) {\r\n r = 0 | (Math.random() * 16);\r\n uuid[i] = CHARS[i === 19 ? (r & 0x3) | 0x8 : r];\r\n }\r\n }\r\n }\r\n return uuid.join(\"\");\r\n}\r\n\r\n/**\r\n * 生成GUID\r\n * @example\r\n * getGUID() // 输出:275ec770-0853-6767-4875-7b270220ce9c\r\n * @returns {String} 返回字符串\r\n */\r\nexport function getGUID(): string {\r\n const s4 = function () {\r\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\r\n };\r\n return s4() + s4() + \"-\" + s4() + \"-\" + s4() + \"-\" + s4() + \"-\" + s4() + s4() + s4();\r\n}\r\n","/**\r\n * @module 键盘\r\n */\r\nimport { KEYCODE } from \"@/constants\";\r\n\r\n/**\r\n * 根据keycode获得键名\r\n * @param {number} keycode 键值\r\n * @returns {string} 返回键名\r\n */\r\nexport function getKeyName(keycode: number): string {\r\n return KEYCODE[keycode];\r\n}\r\n\r\n/**\r\n * 根据keyname获得键值\r\n * @param {string} keyname\r\n * @returns {string} 返回键值\r\n */\r\nexport function getKeyCode(keyname: string): string | undefined {\r\n for (const key in KEYCODE) {\r\n if (KEYCODE[key] === keyname) {\r\n return key;\r\n }\r\n }\r\n}\r\n","/**\r\n * @module 随机数\r\n */\r\n/**\r\n * 生成指定大小的随机整数\r\n * @description n和m参数表示最小和最大范围值,默认0-9之间范围\r\n * @param {number} min 随机数的最小值,默认 0\r\n * @param {number} max 随机数的最大值,默认 9\r\n * @returns {number} 返回指定大小的随机整数\r\n */\r\nexport function getRandom(min: number = 0, max: number = 9): number {\r\n return Math.floor(Math.random() * (max - min + 1) + min);\r\n}\r\n\r\n/**\r\n * 生成固定位数的随机整数\r\n * @description 默认是1,代表生成0-9之间一位,如果是2,则生成10-99之间两位,以此类推\r\n * @param {number} len 固定的位数\r\n * @returns {number} 返回固定位数的随机数\r\n */\r\nexport function getRandomDigit(len: number = 1): number {\r\n return Math.floor((Math.random() + Math.floor(Math.random() * 9 + 1)) * Math.pow(10, len - 1));\r\n}\r\n","/**\r\n * @module 浏览器Storage\r\n */\r\n/**\r\n * 浏览器是否支持 Storage\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isSupportStorage(): boolean {\r\n return !!(window.localStorage && window.sessionStorage);\r\n}\r\n\r\n/**\r\n * 导出localStorage和sessionStorage\r\n */\r\nexport * from \"./localStorage\";\r\nexport * from \"./sessionStorage\";\r\n","import * as MD5 from \"./md5.js\";\r\n\r\n/**\r\n * md5 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的十六进制字符串\r\n */\r\nexport function md5(str: string): string {\r\n return MD5.md5(str);\r\n}\r\n\r\n/**\r\n * md5 加密\r\n * @param {string} str 字符串\r\n * @returns {*} 返回加密后的二进制原始值\r\n */\r\nexport function md5Raw(str: string): any {\r\n return MD5.md5(str, undefined, true);\r\n}\r\n\r\n/**\r\n * md5_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的十六进制字符串\r\n */\r\nexport function md5Hmac(str: string, key: string): string {\r\n if (!str || !key) {\r\n throw new TypeError(\"md5Hmac: missing str or key\");\r\n }\r\n return MD5.md5(str, key, false);\r\n}\r\n\r\n/**\r\n * md5_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的二进制原始值\r\n */\r\nexport function md5HmacRaw(str: string, key: string): any {\r\n if (!str || !key) {\r\n throw new TypeError(\"md5HmacRaw: missing str or key\");\r\n }\r\n return MD5.md5(str, key, true);\r\n}\r\n","import * as SHA256 from \"./sha256.js\";\r\n\r\n// sha256\r\n/**\r\n * sha256 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sha256(str: string): string {\r\n return SHA256.sha256(str);\r\n}\r\n\r\n/**\r\n * sha256_raw 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的原始值\r\n */\r\nexport function sha256Raw(str: string): any {\r\n return SHA256.sha256_raw(str);\r\n}\r\n\r\n/**\r\n * sha256_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sha256Hmac(str: string, key: string): string {\r\n if (!str || !key) {\r\n throw new TypeError(\"sha256Hmac: missing str or key\");\r\n }\r\n return SHA256.sha256_hmac(key, str);\r\n}\r\n\r\n/**\r\n * sha256_hmac_raw 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的原始值\r\n */\r\nexport function sha256HmacRaw(str: string, key: string): any {\r\n if (!str || !key) {\r\n throw new TypeError(\"sha256HmacRaw: missing str or key\");\r\n }\r\n return SHA256.sha256_hmac_raw(key, str);\r\n}\r\n\r\n// sha224\r\n/**\r\n * sha224 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sha224(str: string): string {\r\n return SHA256.sha224(str);\r\n}\r\n\r\n/**\r\n * sha224_raw 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的原始值\r\n */\r\nexport function sha224Raw(str: string): any {\r\n return SHA256.sha224_raw(str);\r\n}\r\n\r\n/**\r\n * sha224_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sha224Hmac(str: string, key: string): string {\r\n if (!str || !key) {\r\n throw new TypeError(\"sha224Hmac: missing str or key\");\r\n }\r\n return SHA256.sha224_hmac(key, str);\r\n}\r\n\r\n/**\r\n * sha224_hmac_raw 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的原始值\r\n */\r\nexport function sha224HmacRaw(str: string, key: string): any {\r\n if (!str || !key) {\r\n throw new TypeError(\"sha224HmacRaw: missing str or key\");\r\n }\r\n return SHA256.sha224_hmac_raw(key, str);\r\n}\r\n","import * as sm3 from \"./sm3.js\";\r\n\r\n/**\r\n * sm3 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sm3Encrypt(str: string): string {\r\n return sm3.encrypt(str);\r\n}\r\n/**\r\n * sm3_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 配置\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sm3EncryptHmac(str: string, key: string): string {\r\n if (!str || !key) {\r\n throw new TypeError(\"sm3EncryptHmac: missing str or key\");\r\n }\r\n return sm3.encrypt(str, key);\r\n}\r\n","// 测试加载\r\nexport function testLoaded(): void {\r\n console.log(\"loaded successfully!\");\r\n}\r\n\r\n// 常量集合\r\nexport * from \"@/constants\";\r\n\r\n// 字符串\r\nexport * from \"@/string\";\r\n// 数字\r\nexport * from \"@/number\";\r\n// 数组\r\nexport * from \"@/array\";\r\n// 对象\r\nexport * from \"@/object\";\r\n// 函数\r\nexport * from \"@/function\";\r\n// 日期\r\nexport * from \"@/date/index.js\";\r\n// 数学\r\nexport * from \"@/math\";\r\n// 正则\r\nexport * from \"@/regexp\";\r\n// 随机数\r\nexport * from \"@/random\";\r\n\r\n// 文件\r\nexport * from \"@/file\";\r\n// 颜色\r\nexport * from \"@/color\";\r\n// 校验\r\nexport * from \"@/validate\";\r\n// 键盘\r\nexport * from \"@/keycode\";\r\n\r\n// 生成id\r\nexport * from \"@/id\";\r\n\r\n// 加解密算法\r\nexport * from \"@/crypto\";\r\n// 脱敏\r\nexport * from \"@/desensitized\";\r\n// 身份证号码\r\nexport * from \"@/ID-card\";\r\n// 分页\r\nexport * from \"@/pagination\";\r\n\r\n// 浏览器 Url\r\nexport * from \"@/url\";\r\n// 浏览器 Cookie\r\nexport * from \"@/cookie\";\r\n// 浏览器 Storage\r\nexport * from \"@/storage\";\r\n// 浏览器 Dom\r\nexport * from \"@/dom\";\r\n// 浏览器 Device\r\nexport * from \"@/device\";\r\n// 浏览器 Clipboard\r\nexport * from \"@/clipboard\";\r\n"],"names":["SORT","DESC","ASC","RANDOM","MATH","ROUND","ROUND_FLOOR","REGEXP","CH","EN","LOWER_CASE","UPPER_CASE","CH_NAME","EN_NAME","NUMBER","INTEGER","DECIMAL","INT_OR_FLOAT","MOBILE","PHONE","EMAIL","ID_CARD","ID_CARD15","ID_CARD18","BANK_CARD","POST_CODE","URL","IP","IP6","EXTERNAL","DATE","AM_PM","zh","AM","PM","en","WEEK","FULL","SHORT","MINI","MONTH","QUARTER","OVER_TIME","YEAR","HOUR","MINUTE","SECOND","MILLISECOND","DAY","PASS_TIME","BEFORE_YESTERDAY","YESTERDAY","TODAY","JUST","HOLIDAY","ZODIAC","CHINESE_ZODIAC","HEAVENLY_STEMS","EARTHLY_BRANCHES","KEYCODE","PROVINCE","SEX","MAN","WOMAN","isInteger","value","Number","isString","Object","prototype","toString","call","slice","isArray","isObject","isDate","isFalse","isNaN","Array","window","isNull","isEmpty","length","Map","Set","size","Date","RegExp","Error","keys","isBlank","test","isUndefined","undefined","toPascalCase","indexOf","newStr","replace","all","letter","toUpperCase","charAt","TypeError","parseInt","radix","String","arraySum","array","reduce","pre","cur","arrayInsertBefore","index","push","splice","arrayInsertAfter","mapToObject","map","obj","create","k","v","objectToMap","set","_getTargetPathPart","path","pathArrayMatch","match","propName","propIndex","isLeapYear","date","year","getFullYear","isBefore","startDate","endDate","getTime","isAfter","isSame","every","item","getDate","options","format","toDateString","getDateObject","month","getMonth","hours","getHours","minutes","getMinutes","seconds","getSeconds","milliseconds","getMilliseconds","getDayOfWeek","getDay","getDayOfMonth","getDayOfYear","Math","ceil","getDaysOfMonth","getDaysOfYear","getAge","age","dateArray","split","birthYear","birthMonth","birthDay","nowDate","nowYear","nowMonth","nowDay","diffAge","diffMonth","addYear","num","setFullYear","addMonth","setMonth","addDate","setDate","toDateUTC","getTimezoneOffset","toDate","lang","replaceRules","_datePadZero","day","hour","min","sec","padStart","isAm","toLowerCase","quarter","floor","result","entries","forEach","regStr","replaceFn","reg","_","gcd","arg1","arg2","a","abs","b","temp","regexpTest","regex","blobToFile","blob","fileName","now","Promise","resolve","reject","mime","type","fileSuffix","File","lastModified","err","console","error","blobToText","reader","FileReader","onload","e","target","onerror","readAsText","_hex","ENCODING_ERROR","BASE64_ENCODE_CHAR","BASE64_DECODE_CHAR","i","isNodeEnv","process","versions","node","isBrowserEnv","btoa","root","global","self","cleanBase64Str","base64Str","utf8ToBytes","str","len","bytes","byteIndex","c","charCodeAt","code","decodeAsBytes","count","v1","v2","v3","v4","remain","bytesToBase64Chars","strIndex","join","utf8Base64Encode","utf8Base64Decode","atob","from","fromCharCode","apply","followingChars","j","byte","charcode","tmpStr","encode","data","urlSafe","constructor","ArrayBuffer","Uint8Array","decode","safeAdd","x","y","lsw","md5cmn","q","s","t","cnt","md5ff","d","md5gg","md5hh","md5ii","binlMD5","olda","oldb","oldc","oldd","binl2rstr","input","output","length32","rstr2binl","length8","rstr2hex","hexTab","str2rstrUTF8","unescape","encodeURIComponent","rawMD5","rstrMD5","rawHMACMD5","key","hash","bkey","ipad","opad","concat","rstrHMACMD5","md5","string","raw","ERROR","HEX_CHARS","EXTRA","SHIFT","K","Sha256","is224","this","blocks","fill","h0","h1","h2","h3","h4","h5","h6","h7","block","start","hBytes","finalized","hashed","first","update","message","notString","isView","lastByteIndex","f","g","h","s0","s1","maj","t1","t2","ch","ab","da","cd","bc","finalize","hex","digest","arr","rawStr","arrayBuffer","buffer","dataView","DataView","setUint32","HmacSha256","keyBytes","oKeyPad","iKeyPad","sha256","inner","innerHash","createMethod","method","createRawMethod","createHmacMethod","createHmacRawMethod","sha256_raw","sha256_hmac","sha256_hmac_raw","sha224","sha224_raw","sha224_hmac","sha224_hmac_raw","BLOCK_LENGTH","IPAD","OPAD","IV","Uint32Array","rotl","n","xor","P0","X","arrayToHex","hexToArray","hexStr","words","hexStrLength","substr","utf8ToArray","point","codePointAt","sm3Core","kArr","lenArr","lenBin","m","V","W","M","getUint32","T1","T2","SS1","SS2","TT1","TT2","T","A","B","C","D","E","F","G","H","GGj","encrypt","inputArr","hmacArr","processedKey","iPadKey","oPadKey","encryptHmac","SM4_MODE_ECB","SM4_MODE_CBC","SM4_PADDING","SM4_OUTPUT_HEX","SM4_OUTPUT_UTF8","SM4_OUTPUT_ARRAY","SM4_OUTPUT_UINT8ARRAY","SM4_OUTPUT_ARRAYBUFFER","ENCRYPT","DECRYPT","ROUND_COUNT","BLOCK_SIZE","KEY_SIZE","IV_SIZE","SBOX","CK","FK","hexToUint8Array","normalizeInput","cryptFlag","TextEncoder","normalizeKeyIv","keyOrIv","expectedLength","name","rotl32","byteSub","linearTransformEnc","linearTransformKey","sm4BlockCrypt","inputBlock","outputBlock","roundKeys","offset","r","mid","wordIdx","sm4Core","inputData","mode","iv","padding","includes","ivBytes","processedInput","paddingCount","padded","pkcs7Pad","sm4KeyExpansion","outputData","lastVector","subarray","xorBlock","finalOutput","pkcs7Unpad","TextDecoder","uint8ArrayToHex","MODE","ECB","CBC","PADDING","generateSM4Key","outputFormat","crypto","getRandomValues","cryptoObj","keyUint8","generateSM4Iv","ivUint8","_validateSM4Options","operation","sm4.MODE","validModes","values","ivLength","byteLength","sm4.PADDING","SM4","OUTPUT","HEX","UTF8","ARRAY","UINT8ARRAY","ARRAYBUFFER","formatStartOf","startStr","padEnd","substring","getBirthdayByIDCard","idCard","getAgeByIDCard","birthday","getSexByIDCard","getProvinceByIDCard","prefix","getTotalPage","pagination","page","pageSize","total","totalPage","pagerCount","getSearchString","url","location","href","parseSearchParam","searchArr","param","decodeURIComponent","stringifySearchParam","params","setCookie","timestamp","document","cookie","hasClass","elem","className","addClass","removeClass","isPhone","ua","navigator","userAgent","setClipboardText","text","clipboard","writeText","then","success","failed","warn","ZH","r1","r2","pow","max","setHours","setMilliseconds","setMinutes","setSeconds","styles","style","setProperty","afterName","beforeIndex","findIndex","afterArr","array1","array2","filter","unshift","random","sort","props","prop","order","sourceIndex","targetIndex","setting","parentKey","childrenKey","nodeChildren","newChildren","tempMap","parent","children","Base64.decode","Base64.encode","Base64.fromHex","uint8Array","Base64.fromUint8Array","base64","mimeMatch","bstr","u8arr","Blob","Base64.toHex","Base64.toUint8Array","readAsDataURL","catch","domain","names","toUTCString","localStorage","clear","sessionStorage","source","assign","flags","fn","delay","immediate","timer","args","clearTimeout","canExecute","setTimeout","deepClone","copy","attr","hasOwnProperty","setTime","leftChain","rightChain","compare2Objects","xObj","yObj","isPrototypeOf","xObjKeys","yObjKeys","p","xProp","yProp","pop","arguments","objUrl","createObjectURL","link","createElement","download","click","revokeObjectURL","fileUrl","body","appendChild","removeChild","value1","value2","is","file","readAsArrayBuffer","toFixed","money","cnNums","cnIntRadiance","cnIntUnits","cnDecUnits","maxNum","integerNum","decimalNum","parts","chineseStr","parseFloat","zeroCount","IntLen","decLen","matchAll","acc","trim","curr","ie","edge","firefox","opera","chrome","safari","version","read","clipboardItems","list","types","getType","async","readText","tempArr","diff","lastIndexOf","weekDay","firstDateOfMonth","lastDateOfMonth","currentDate","dayOfWeek","firstDateOfWeek","firstDateOfYear","daysOfYear","s4","province","sex","keyname","keycode","getItem","callback","startTime","time","quarterNum","isEven","left","right","pagerLength","pager","getPropertyValue","CHARS","uuid","round","paths","current","part","startDay","fullDays","rgb","exec","l","color","opacity","o","htmlStr","endTime","Function","JSON","parse","diffDate1","diffDate2","cookieEnabled","json","newDate","stringify","MD5.md5","s2","objectEquals","obj1","obj2","maxLength","beforeParam","beforeArr","removeItem","delIndex","removeProperty","oldSubstr","newSubstr","newClassName","oldClassName","rgba","absA","absB","clipboardItem","ClipboardItem","write","setItem","nextPart","lastPath","SHA256.sha224","SHA256.sha224_hmac","SHA256.sha224_hmac_raw","SHA256.sha224_raw","SHA256.sha256","SHA256.sha256_hmac","SHA256.sha256_hmac_raw","SHA256.sha256_raw","sm3.encrypt","finalOptions","sm4.decrypt","sm4.encrypt","replacer","log","interval","decimals","_toDecimalRound","_toDecimalFloor","$2","decimalLength","$3","pm","$1","digitArr","_toFixedRound","numVal","dec","tempNumStr","pointIndex","pointCount","tempNumA","integerPart","decimalPart","_toFixedFloor","toLocaleLowerCase","toLocaleUpperCase","treeToArray","nodes","imgUrl","img","Image","src","canvas","context","getContext","width","height","drawImage","toDataURL","fetch","res","status"],"mappings":"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"}
1
+ {"version":3,"file":"index.full.umd.min.js","sources":["../../src/constants/file:/D:/webWorks/i-utils/src/constants/sort.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/math.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/regexp.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/date.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/keycode.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/id-card.ts","../../src/validate/file:/D:/webWorks/i-utils/src/validate/index.ts","../../src/string/file:/D:/webWorks/i-utils/src/string/index.ts","../../src/number/file:/D:/webWorks/i-utils/src/number/index.ts","../../src/array/file:/D:/webWorks/i-utils/src/array/index.ts","../../src/object/file:/D:/webWorks/i-utils/src/object/index.ts","../../src/date/file:/D:/webWorks/i-utils/src/date/index.ts","../../src/math/file:/D:/webWorks/i-utils/src/math/index.ts","../../src/regexp/file:/D:/webWorks/i-utils/src/regexp/index.ts","../../src/file/file:/D:/webWorks/i-utils/src/file/index.ts","../../src/color/file:/D:/webWorks/i-utils/src/color/index.ts","../../src/crypto/base64/file:/D:/webWorks/i-utils/src/crypto/base64/base64.js","../../src/crypto/md5/file:/D:/webWorks/i-utils/src/crypto/md5/md5.js","../../src/crypto/sha256/file:/D:/webWorks/i-utils/src/crypto/sha256/sha256.js","../../src/crypto/sm3/file:/D:/webWorks/i-utils/src/crypto/sm3/sm3.js","../../src/crypto/sm4/file:/D:/webWorks/i-utils/src/crypto/sm4/sm4.js","../../src/crypto/sm4/file:/D:/webWorks/i-utils/src/crypto/sm4/index.ts","../../src/desensitized/file:/D:/webWorks/i-utils/src/desensitized/index.ts","../../src/ID-card/file:/D:/webWorks/i-utils/src/ID-card/index.ts","../../src/pagination/file:/D:/webWorks/i-utils/src/pagination/index.ts","../../src/url/file:/D:/webWorks/i-utils/src/url/index.ts","../../src/cookie/file:/D:/webWorks/i-utils/src/cookie/index.ts","../../src/dom/file:/D:/webWorks/i-utils/src/dom/index.ts","../../src/device/file:/D:/webWorks/i-utils/src/device/index.ts","../../src/clipboard/file:/D:/webWorks/i-utils/src/clipboard/index.ts","../../src/constants/file:/D:/webWorks/i-utils/src/constants/lang.ts","../../src/crypto/base64/file:/D:/webWorks/i-utils/src/crypto/base64/index.ts","../../src/storage/file:/D:/webWorks/i-utils/src/storage/localStorage.ts","../../src/storage/file:/D:/webWorks/i-utils/src/storage/sessionStorage.ts","../../src/function/file:/D:/webWorks/i-utils/src/function/index.ts","../../src/id/file:/D:/webWorks/i-utils/src/id/index.ts","../../src/keycode/file:/D:/webWorks/i-utils/src/keycode/index.ts","../../src/random/file:/D:/webWorks/i-utils/src/random/index.ts","../../src/storage/file:/D:/webWorks/i-utils/src/storage/index.ts","../../src/crypto/md5/file:/D:/webWorks/i-utils/src/crypto/md5/index.ts","../../src/crypto/sha256/file:/D:/webWorks/i-utils/src/crypto/sha256/index.ts","../../src/crypto/sm3/file:/D:/webWorks/i-utils/src/crypto/sm3/index.ts","../../src/file:/D:/webWorks/i-utils/src/index.ts"],"sourcesContent":["/**\r\n * 排序相关常量配置(全局只读)\r\n *\r\n * DESC: 降序\r\n * - 取值:0\r\n *\r\n * ASC: 升序\r\n * - 取值:1\r\n *\r\n * RANDOM: 随机排序\r\n * - 取值:2\r\n */\r\nexport const SORT: Record<string, number> = {\r\n // 降序\r\n DESC: 0,\r\n // 升序\r\n ASC: 1,\r\n // 随机排序\r\n RANDOM: 2,\r\n} as const;\r\n","/**\r\n * 数学计算相关常量配置(全局只读)\r\n *\r\n * ROUND: 正常四舍五入\r\n * - 取值:0\r\n * - 示例:1.354保留两位是1.35;1.355保留两位是1.36\r\n *\r\n * ROUND_FLOOR: 向下舍出\r\n * - 取值:1\r\n * - 示例:1.354保留两位是1.35;1.355保留两位是1.35\r\n */\r\nexport const MATH: Record<string, any> = {\r\n // 正常四舍五入,如:1.354保留两位是1.35;1.355保留两位是1.36;\r\n ROUND: 0,\r\n // 向下舍出,如:1.354保留两位是1.35;1.355保留两位是1.35;\r\n ROUND_FLOOR: 1,\r\n} as const;\r\n","/**\r\n * 正则表达式相关常量配置(全局只读)\r\n *\r\n * CH: 中文汉字\r\n * EN: 英文字母\r\n * LOWER_CASE: 小写字母\r\n * UPPER_CASE: 大写字母\r\n * CH_NAME: 中文姓名(2-16位)\r\n * EN_NAME: 英文姓名(1-20位)\r\n * NUMBER: 数字(包含正数和负数)\r\n * INTEGER: 整数(包含:0,正整数和负整数)\r\n * DECIMAL: 小数(包含正小数和负小数)\r\n * INT_OR_FLOAT: 正整数或者保留两位小数\r\n * MOBILE: 手机号码(支持+86)\r\n * PHONE: 固定电话号码(比如:0755-1111111)\r\n * EMAIL: 邮箱\r\n * ID_CARD: 一代15位或二代18位身份证\r\n * ID_CARD15: 仅校验一代15位身份证\r\n * ID_CARD18: 仅校验二代18位身份证\r\n * BANK_CARD: 银行卡号\r\n * POST_CODE: 邮政编码\r\n * URL: url地址(可获取主机地址、主机名、端口号、协议、查询参数、hash等信息)\r\n * IP: ip地址\r\n * IP6: IPv6地址\r\n * EXTERNAL: 外链(http、https、mail、tel电话)\r\n */\r\nexport const REGEXP: Record<string, RegExp> = {\r\n // 中文汉字\r\n CH: /^[\\u4E00-\\u9FA5]+$/,\r\n // 英文字母,1个以上\r\n EN: /^[a-zA-Z]+$/,\r\n // 小写字母\r\n LOWER_CASE: /^[a-z]+$/,\r\n // 大写字母\r\n UPPER_CASE: /^[A-Z]+$/,\r\n // 中文姓名,2-16位(支持少数民族姓名间隔符「·」)\r\n CH_NAME: /^[\\u4e00-\\u9fa5·]{2,16}$/,\r\n // 英文姓名,1-20位\r\n EN_NAME: /^[a-zA-Z\\s]{1,20}$/,\r\n // 数字,包含正数和负数\r\n NUMBER: /^([-+])?\\d+(\\.\\d+)?$/,\r\n // 整数,包含:0,正整数和负整数\r\n INTEGER: /^(0|[1-9][0-9]*|-[1-9][0-9]*)$/,\r\n // 小数,包含正小数和负小数\r\n DECIMAL: /^([-+])?\\d+\\.\\d+$/,\r\n // 正整数或者保留两位小数\r\n INT_OR_FLOAT: /(^[1-9][0-9]*$)|(^[1-9][0-9]*\\.[0-9]{1,2}$)|(^0\\.[0-9]{1,2}$)|(^0$)/,\r\n // 手机号码,支持+86\r\n MOBILE: /^(?:(?:\\+|00)86)?1[1-9]\\d{9}$/,\r\n // 固定电话号码,比如:0755-1111111\r\n PHONE: /^(?:(?:\\d{3}-)?\\d{8}|^(?:\\d{4}-)?\\d{7,8})(?:-\\d+)?$/,\r\n // 邮箱\r\n EMAIL: /^[\\w-]+(\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$/,\r\n // 一代15位或二代18位身份证\r\n ID_CARD:\r\n /(^\\d{8}(0\\d|10|11|12)([0-2]\\d|30|31)\\d{3}$)|(^\\d{6}(18|19|20)\\d{2}(0[1-9]|10|11|12)([0-2]\\d|30|31)\\d{3}(\\d|X|x)$)/,\r\n // 仅校验一代15位身份证\r\n ID_CARD15: /(^\\d{8}(0\\d|10|11|12)([0-2]\\d|30|31)\\d{3}$)/,\r\n // 仅校验二代18位身份证\r\n ID_CARD18: /(^\\d{6}(18|19|20)\\d{2}(0[1-9]|10|11|12)([0-2]\\d|30|31)\\d{3}(\\d|X|x)$)/,\r\n // 银行卡号\r\n BANK_CARD: /^[1-9]\\d{9,29}$/,\r\n // 邮政编码\r\n POST_CODE: /^(0[1-7]|1[0-356]|2[0-7]|3[0-6]|4[0-7]|5[1-7]|6[1-7]|7[0-5]|8[013-6])\\d{4}$/,\r\n // url地址,可以获取到主机地址、主机名、端口号、协议、查询参数、hash等信息c\r\n URL: /^(?:(ftp|https?|ftps):\\/\\/)?((?:\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+(?:[a-zA-Z]{2,6})?)?(?::(\\d+))?(?:\\/([^\\?#]*))?(?:\\?([^#]*))?(?:#(.*))?$/,\r\n // ip地址\r\n IP: /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,\r\n // IPv6地址\r\n IP6: /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|::([0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4}|[0-9a-fA-F]{1,4}::([0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4})$/i,\r\n // 是外链,http,https,mail,tel电话\r\n EXTERNAL: /^(http:|https:|ftp:|ftps:|mailto:|tel:)/i,\r\n} as const;\r\n","/**\r\n * 日期相关的多语言常量配置(全局只读)\r\n *\r\n * AM_PM: 上午/下午多语言配置\r\n * - zh: { AM: \"上午\", PM: \"下午\" }\r\n * - en: { AM: \"AM\", PM: \"PM\" }\r\n *\r\n * WEEK: 星期多语言配置\r\n * - zh.FULL: [\"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\"]\r\n * - zh.SHORT: [\"周日\", \"周一\", \"周二\", \"周三\", \"周四\", \"周五\", \"周六\"]\r\n * - zh.MINI: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"]\r\n * - en.FULL: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"]\r\n * - en.SHORT: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"]\r\n * - en.MINI: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"]\r\n *\r\n * MONTH: 月份多语言配置\r\n * - zh.FULL: [\"一月\", \"二月\", \"三月\", \"四月\", \"五月\", \"六月\", \"七月\", \"八月\", \"九月\", \"十月\", \"十一月\", \"十二月\"]\r\n * - zh.SHORT: [\"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"七\", \"八\", \"九\", \"十\", \"十一\", \"十二\"]\r\n * - en.FULL: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"]\r\n * - en.SHORT: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\r\n *\r\n * QUARTER: 季度多语言配置\r\n * - zh.FULL: [\"第一季度\", \"第二季度\", \"第三季度\", \"第四季度\"]\r\n * - zh.SHORT: [\"一季度\", \"二季度\", \"三季度\", \"四季度\"]\r\n * - zh.MINI: [\"一\", \"二\", \"三\", \"四\"]\r\n * - en.FULL: [\"quarter 1st\", \"quarter 2nd\", \"quarter 3rd\", \"quarter 4th\"]\r\n * - en.SHORT: [\"Q1th\", \"Q2nd\", \"Q3rd\", \"Q4th\"]\r\n * - en.MINI: [\"Q1\", \"Q2\", \"Q3\", \"Q4\"]\r\n *\r\n * OVER_TIME: 剩余时间单位多语言配置\r\n * - zh: { YEAR: \"年\", MONTH: \"月\", DATE: \"日\", HOUR: \"时\", MINUTE: \"分\", SECOND: \"秒\", MILLISECOND: \"毫秒\", DAY: \"天\", QUARTER: \"季度\" }\r\n * - en: { YEAR: \"year\", MONTH: \"month\", DATE: \"date\", HOUR: \"hour\", MINUTE: \"minute\", SECOND: \"second\", MILLISECOND: \"millisecond\", DAY: \"day\", QUARTER: \"quarter\" }\r\n *\r\n * PASS_TIME: 过去时间描述多语言配置\r\n * - zh: { YEAR: \"年前\", MONTH: \"个月前\", DAY: \"天前\", BEFORE_YESTERDAY: \"前天\", YESTERDAY: \"昨天\", TODAY: \"今天\", HOUR: \"小时前\", MINUTE: \"分钟前\", JUST: \"刚刚\" }\r\n * - en: { YEAR: \" year ago\", MONTH: \" month ago\", DAY: \" day ago\", BEFORE_YESTERDAY: \"before yesterday\", YESTERDAY: \" yesterday\", TODAY: \" today\", HOUR: \" hour ago\", MINUTE: \" minute ago\", JUST: \" just\" }\r\n *\r\n * HOLIDAY: 节假日多语言配置\r\n * - zh: [\"元旦\", \"春节\", \"清明节\", \"劳动节\", \"端午节\", \"中秋节\", \"国庆节\"]\r\n * - en: [\"New Year‘s Day\", \"Spring Festival\", \"Tomb Sweeping Day\", \"Labor Day\", \"Dragon Boat Festival\", \"Mid-Autumn Day\", \"National Day\"]\r\n *\r\n * ZODIAC: 星座多语言配置\r\n * - zh: [\"摩羯座\", \"水瓶座\", \"双鱼座\", \"白羊座\", \"金牛座\", \"双子座\", \"巨蟹座\", \"狮子座\", \"处女座\", \"天秤座\", \"天蝎座\", \"射手座\"]\r\n * - en: [\"Capricorn\", \"Aquarius\", \"Pisces\", \"Aries\", \"Taurus\", \"Gemini\", \"Cancer\", \"Leo\", \"Virgo\", \"Libra\", \"Scorpio\", \"Sagittarius\"]\r\n *\r\n * CHINESE_ZODIAC: 生肖多语言配置\r\n * - zh: [\"鼠\", \"牛\", \"虎\", \"兔\", \"龙\", \"蛇\", \"马\", \"羊\", \"猴\", \"鸡\", \"狗\", \"猪\"]\r\n * - en: [\"Rat\", \"Ox\", \"Tiger\", \"Rabbit\", \"Dragon\", \"Snake\", \"Horse\", \"Goat\", \"Monkey\", \"Rooster\", \"Dog\", \"Pig\"]\r\n *\r\n * HEAVENLY_STEMS: 天干多语言配置\r\n * - zh: [\"甲\", \"乙\", \"丙\", \"丁\", \"戊\", \"己\", \"庚\", \"辛\", \"壬\", \"癸\"]\r\n * - en: [\"Jia\", \"Yi\", \"Bing\", \"Ding\", \"Wu\", \"Ji\", \"Geng\", \"Xin\", \"Ren\", \"Gui\"]\r\n *\r\n * EARTHLY_BRANCHES: 地支多语言配置\r\n * - zh: [\"子\", \"丑\", \"寅\", \"卯\", \"辰\", \"巳\", \"午\", \"未\", \"申\", \"酉\", \"戌\", \"亥\"]\r\n * - en: [\"Zi\", \"Chou\", \"Yin\", \"Mao\", \"Chen\", \"Si\", \"Wu\", \"Wei\", \"Shen\", \"You\", \"Xu\", \"Hai\"]\r\n */\r\nexport const DATE: Record<string, any> = {\r\n // 上午和下午\r\n AM_PM: {\r\n zh: {\r\n AM: \"上午\",\r\n PM: \"下午\",\r\n },\r\n en: {\r\n AM: \"AM\",\r\n PM: \"PM\",\r\n },\r\n },\r\n // 周\r\n WEEK: {\r\n zh: {\r\n FULL: [\"星期日\", \"星期一\", \"星期二\", \"星期三\", \"星期四\", \"星期五\", \"星期六\"],\r\n SHORT: [\"周日\", \"周一\", \"周二\", \"周三\", \"周四\", \"周五\", \"周六\"],\r\n MINI: [\"日\", \"一\", \"二\", \"三\", \"四\", \"五\", \"六\"],\r\n },\r\n en: {\r\n FULL: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\r\n SHORT: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\r\n MINI: [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"],\r\n },\r\n },\r\n // 月\r\n MONTH: {\r\n zh: {\r\n FULL: [\"一月\", \"二月\", \"三月\", \"四月\", \"五月\", \"六月\", \"七月\", \"八月\", \"九月\", \"十月\", \"十一月\", \"十二月\"],\r\n SHORT: [\"一\", \"二\", \"三\", \"四\", \"五\", \"六\", \"七\", \"八\", \"九\", \"十\", \"十一\", \"十二\"],\r\n },\r\n en: {\r\n FULL: [\r\n \"January\",\r\n \"February\",\r\n \"March\",\r\n \"April\",\r\n \"May\",\r\n \"June\",\r\n \"July\",\r\n \"August\",\r\n \"September\",\r\n \"October\",\r\n \"November\",\r\n \"December\",\r\n ],\r\n SHORT: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"],\r\n },\r\n },\r\n // 季度\r\n QUARTER: {\r\n zh: {\r\n FULL: [\"第一季度\", \"第二季度\", \"第三季度\", \"第四季度\"],\r\n SHORT: [\"一季度\", \"二季度\", \"三季度\", \"四季度\"],\r\n MINI: [\"一\", \"二\", \"三\", \"四\"],\r\n },\r\n en: {\r\n FULL: [\"quarter 1st\", \"quarter 2nd\", \"quarter 3rd\", \"quarter 4th\"],\r\n SHORT: [\"Q1th\", \"Q2nd\", \"Q3rd\", \"Q4th\"],\r\n MINI: [\"Q1\", \"Q2\", \"Q3\", \"Q4\"],\r\n },\r\n },\r\n // 已过日期类型\r\n OVER_TIME: {\r\n zh: {\r\n YEAR: \"年\",\r\n MONTH: \"月\",\r\n DATE: \"日\",\r\n HOUR: \"时\",\r\n MINUTE: \"分\",\r\n SECOND: \"秒\",\r\n MILLISECOND: \"毫秒\",\r\n DAY: \"天\",\r\n QUARTER: \"季度\",\r\n },\r\n en: {\r\n YEAR: \"year\",\r\n MONTH: \"month\",\r\n DATE: \"date\",\r\n HOUR: \"hour\",\r\n MINUTE: \"minute\",\r\n SECOND: \"second\",\r\n MILLISECOND: \"millisecond\",\r\n DAY: \"day\",\r\n QUARTER: \"quarter\",\r\n },\r\n },\r\n // 时间节点\r\n PASS_TIME: {\r\n zh: {\r\n YEAR: \"年前\",\r\n MONTH: \"个月前\",\r\n DAY: \"天前\",\r\n BEFORE_YESTERDAY: \"前天\",\r\n YESTERDAY: \"昨天\",\r\n TODAY: \"今天\",\r\n HOUR: \"小时前\",\r\n MINUTE: \"分钟前\",\r\n JUST: \"刚刚\",\r\n },\r\n en: {\r\n YEAR: \" year ago\",\r\n MONTH: \" month ago\",\r\n DAY: \" day ago\",\r\n BEFORE_YESTERDAY: \"before yesterday\",\r\n YESTERDAY: \" yesterday\",\r\n TODAY: \" today\",\r\n HOUR: \" hour ago\",\r\n MINUTE: \" minute ago\",\r\n JUST: \" just\",\r\n },\r\n },\r\n // 节假日\r\n HOLIDAY: {\r\n zh: [\"元旦\", \"春节\", \"清明节\", \"劳动节\", \"端午节\", \"中秋节\", \"国庆节\"],\r\n en: [\r\n \"New Year‘s Day\",\r\n \"Spring Festival\",\r\n \"Tomb Sweeping Day\",\r\n \"Labor Day\",\r\n \"Dragon Boat Festival\",\r\n \"Mid-Autumn Day\",\r\n \"National Day\",\r\n ],\r\n },\r\n // 星座\r\n ZODIAC: {\r\n zh: [\r\n \"摩羯座\",\r\n \"水瓶座\",\r\n \"双鱼座\",\r\n \"白羊座\",\r\n \"金牛座\",\r\n \"双子座\",\r\n \"巨蟹座\",\r\n \"狮子座\",\r\n \"处女座\",\r\n \"天秤座\",\r\n \"天蝎座\",\r\n \"射手座\",\r\n ],\r\n en: [\r\n \"Capricorn\",\r\n \"Aquarius\",\r\n \"Pisces\",\r\n \"Aries\",\r\n \"Taurus\",\r\n \"Gemini\",\r\n \"Cancer\",\r\n \"Leo\",\r\n \"Virgo\",\r\n \"Libra\",\r\n \"Scorpio\",\r\n \"Sagittarius\",\r\n ],\r\n },\r\n // 生肖\r\n CHINESE_ZODIAC: {\r\n zh: [\"鼠\", \"牛\", \"虎\", \"兔\", \"龙\", \"蛇\", \"马\", \"羊\", \"猴\", \"鸡\", \"狗\", \"猪\"],\r\n en: [\"Rat\", \"Ox\", \"Tiger\", \"Rabbit\", \"Dragon\", \"Snake\", \"Horse\", \"Goat\", \"Monkey\", \"Rooster\", \"Dog\", \"Pig\"],\r\n },\r\n // 天干地支\r\n HEAVENLY_STEMS: {\r\n zh: [\"甲\", \"乙\", \"丙\", \"丁\", \"戊\", \"己\", \"庚\", \"辛\", \"壬\", \"癸\"],\r\n en: [\"Jia\", \"Yi\", \"Bing\", \"Ding\", \"Wu\", \"Ji\", \"Geng\", \"Xin\", \"Ren\", \"Gui\"],\r\n },\r\n EARTHLY_BRANCHES: {\r\n zh: [\"子\", \"丑\", \"寅\", \"卯\", \"辰\", \"巳\", \"午\", \"未\", \"申\", \"酉\", \"戌\", \"亥\"],\r\n en: [\"Zi\", \"Chou\", \"Yin\", \"Mao\", \"Chen\", \"Si\", \"Wu\", \"Wei\", \"Shen\", \"You\", \"Xu\", \"Hai\"],\r\n },\r\n} as const;\r\n","/**\r\n * 键盘码相关常量配置(全局只读)\r\n *\r\n * 字符键:\r\n * - 8: Backspace\r\n * - 9: Tab\r\n * - 13: Enter\r\n * - 16: Shift\r\n * - 17: Ctrl\r\n * - 18: Alt\r\n * - 19: Pause\r\n * - 20: Caps Lock\r\n * - 27: Escape\r\n * - 32: Space\r\n * - 33: Page Up\r\n * - 34: Page Down\r\n * - 35: End\r\n * - 36: Home\r\n * - 37: Left\r\n * - 38: Up\r\n * - 39: Right\r\n * - 40: Down\r\n * - 42: Print Screen\r\n * - 45: Insert\r\n * - 46: Delete\r\n *\r\n * 数字键:\r\n * - 48: 0\r\n * - 49: 1\r\n * - 50: 2\r\n * - 51: 3\r\n * - 52: 4\r\n * - 53: 5\r\n * - 54: 6\r\n * - 55: 7\r\n * - 56: 8\r\n * - 57: 9\r\n *\r\n * 字母键:\r\n * - 65: A\r\n * - 66: B\r\n * - 67: C\r\n * - 68: D\r\n * - 69: E\r\n * - 70: F\r\n * - 71: G\r\n * - 72: H\r\n * - 73: I\r\n * - 74: J\r\n * - 75: K\r\n * - 76: L\r\n * - 77: M\r\n * - 78: N\r\n * - 79: O\r\n * - 80: P\r\n * - 81: Q\r\n * - 82: R\r\n * - 83: S\r\n * - 84: T\r\n * - 85: U\r\n * - 86: V\r\n * - 87: W\r\n * - 88: X\r\n * - 89: Y\r\n * - 90: Z\r\n *\r\n * window 相关键:\r\n * - 91: Windows\r\n * - 93: Right Click\r\n *\r\n * 数字小键盘(Numpad):\r\n * - 96: Numpad 0\r\n * - 97: Numpad 1\r\n * - 98: Numpad 2\r\n * - 99: Numpad 3\r\n * - 100: Numpad 4\r\n * - 101: Numpad 5\r\n * - 102: Numpad 6\r\n * - 103: Numpad 7\r\n * - 104: Numpad 8\r\n * - 105: Numpad 9\r\n * - 106: Numpad *\r\n * - 107: Numpad +\r\n * - 109: Numpad -\r\n * - 110: Numpad .\r\n * - 111: Numpad /\r\n *\r\n * F功能键:\r\n * - 112: F1\r\n * - 113: F2\r\n * - 114: F3\r\n * - 115: F4\r\n * - 116: F5\r\n * - 117: F6\r\n * - 118: F7\r\n * - 119: F8\r\n * - 120: F9\r\n * - 121: F10\r\n * - 122: F11\r\n * - 123: F12\r\n *\r\n * 特殊符号/功能键:\r\n * - 144: Num Lock\r\n * - 145: Scroll Lock\r\n * - 182: My Computer\r\n * - 183: My Calculator\r\n * - 186: ;\r\n * - 187: =\r\n * - 188: ,\r\n * - 189: -\r\n * - 190: .\r\n * - 191: /\r\n * - 192: `\r\n * - 219: [\r\n * - 220: \\\r\n * - 221: ]\r\n * - 222: '\r\n */\r\nexport const KEYCODE: Record<string, string> = {\r\n // 字符键\r\n 8: \"Backspace\",\r\n 9: \"Tab\",\r\n 13: \"Enter\",\r\n 16: \"Shift\",\r\n 17: \"Ctrl\",\r\n 18: \"Alt\",\r\n 19: \"Pause\",\r\n 20: \"Caps Lock\",\r\n 27: \"Escape\",\r\n 32: \"Space\",\r\n 33: \"Page Up\",\r\n 34: \"Page Down\",\r\n 35: \"End\",\r\n 36: \"Home\",\r\n 37: \"Left\",\r\n 38: \"Up\",\r\n 39: \"Right\",\r\n 40: \"Down\",\r\n 42: \"Print Screen\",\r\n 45: \"Insert\",\r\n 46: \"Delete\",\r\n // 数字键\r\n 48: \"0\",\r\n 49: \"1\",\r\n 50: \"2\",\r\n 51: \"3\",\r\n 52: \"4\",\r\n 53: \"5\",\r\n 54: \"6\",\r\n 55: \"7\",\r\n 56: \"8\",\r\n 57: \"9\",\r\n // 字母键\r\n 65: \"A\",\r\n 66: \"B\",\r\n 67: \"C\",\r\n 68: \"D\",\r\n 69: \"E\",\r\n 70: \"F\",\r\n 71: \"G\",\r\n 72: \"H\",\r\n 73: \"I\",\r\n 74: \"J\",\r\n 75: \"K\",\r\n 76: \"L\",\r\n 77: \"M\",\r\n 78: \"N\",\r\n 79: \"O\",\r\n 80: \"P\",\r\n 81: \"Q\",\r\n 82: \"R\",\r\n 83: \"S\",\r\n 84: \"T\",\r\n 85: \"U\",\r\n 86: \"V\",\r\n 87: \"W\",\r\n 88: \"X\",\r\n 89: \"Y\",\r\n 90: \"Z\",\r\n // window\r\n 91: \"Windows\",\r\n 93: \"Right Click\",\r\n // Numpad\r\n 96: \"Numpad 0\",\r\n 97: \"Numpad 1\",\r\n 98: \"Numpad 2\",\r\n 99: \"Numpad 3\",\r\n 100: \"Numpad 4\",\r\n 101: \"Numpad 5\",\r\n 102: \"Numpad 6\",\r\n 103: \"Numpad 7\",\r\n 104: \"Numpad 8\",\r\n 105: \"Numpad 9\",\r\n 106: \"Numpad *\",\r\n 107: \"Numpad +\",\r\n 109: \"Numpad -\",\r\n 110: \"Numpad .\",\r\n 111: \"Numpad /\",\r\n // F功能键\r\n 112: \"F1\",\r\n 113: \"F2\",\r\n 114: \"F3\",\r\n 115: \"F4\",\r\n 116: \"F5\",\r\n 117: \"F6\",\r\n 118: \"F7\",\r\n 119: \"F8\",\r\n 120: \"F9\",\r\n 121: \"F10\",\r\n 122: \"F11\",\r\n 123: \"F12\",\r\n // 特殊符号\r\n 144: \"Num Lock\",\r\n 145: \"Scroll Lock\",\r\n 182: \"My Computer\",\r\n 183: \"My Calculator\",\r\n 186: \";\",\r\n 187: \"=\",\r\n 188: \",\",\r\n 189: \"-\",\r\n 190: \".\",\r\n 191: \"/\",\r\n 192: \"`\",\r\n 219: \"[\",\r\n 220: \"\\\\\",\r\n 221: \"]\",\r\n 222: \"'\",\r\n} as const;\r\n","/**\r\n * 身份证号相关常量配置(全局只读)\r\n *\r\n * PROVINCE: 身份证号前两位对应的省份/地区编码映射\r\n * - 11: 北京\r\n * - 12: 天津\r\n * - 13: 河北\r\n * - 14: 山西\r\n * - 15: 内蒙古\r\n * - 21: 辽宁\r\n * - 22: 吉林\r\n * - 23: 黑龙江\r\n * - 31: 上海\r\n * - 32: 江苏\r\n * - 33: 浙江\r\n * - 34: 安徽\r\n * - 35: 福建\r\n * - 36: 江西\r\n * - 37: 山东\r\n * - 41: 河南\r\n * - 42: 湖北\r\n * - 43: 湖南\r\n * - 44: 广东\r\n * - 45: 广西\r\n * - 46: 海南\r\n * - 50: 重庆\r\n * - 51: 四川\r\n * - 52: 贵州\r\n * - 53: 云南\r\n * - 54: 西藏\r\n * - 61: 陕西\r\n * - 62: 甘肃\r\n * - 63: 青海\r\n * - 64: 宁夏\r\n * - 65: 新疆\r\n * - 71: 台湾\r\n * - 81: 香港\r\n * - 82: 澳门\r\n * - 91: 国外\r\n *\r\n * SEX: 身份证号解析的性别映射\r\n * - MAN: 男\r\n * - WOMAN: 女\r\n */\r\nexport const ID_CARD: Record<string, any> = {\r\n // 身份证号对应的省\r\n PROVINCE: {\r\n 11: \"北京\",\r\n 12: \"天津\",\r\n 13: \"河北\",\r\n 14: \"山西\",\r\n 15: \"内蒙古\",\r\n 21: \"辽宁\",\r\n 22: \"吉林\",\r\n 23: \"黑龙江\",\r\n 31: \"上海\",\r\n 32: \"江苏\",\r\n 33: \"浙江\",\r\n 34: \"安徽\",\r\n 35: \"福建\",\r\n 36: \"江西\",\r\n 37: \"山东\",\r\n 41: \"河南\",\r\n 42: \"湖北\",\r\n 43: \"湖南\",\r\n 44: \"广东\",\r\n 45: \"广西\",\r\n 46: \"海南\",\r\n 50: \"重庆\",\r\n 51: \"四川\",\r\n 52: \"贵州\",\r\n 53: \"云南\",\r\n 54: \"西藏\",\r\n 61: \"陕西\",\r\n 62: \"甘肃\",\r\n 63: \"青海\",\r\n 64: \"宁夏\",\r\n 65: \"新疆\",\r\n 71: \"台湾\",\r\n 81: \"香港\",\r\n 82: \"澳门\",\r\n 91: \"国外\",\r\n },\r\n // 性别\r\n SEX: {\r\n MAN: \"男\",\r\n WOMAN: \"女\",\r\n },\r\n} as const;\r\n","/**\r\n * @module 校验\r\n */\r\n\r\n/**\r\n * 判断是整数\r\n * @param {*} value 参数\r\n * @returns {boolean} result 返回结果\r\n */\r\nexport function isInteger(value: any): boolean {\r\n return Number.isInteger(value);\r\n}\r\n\r\n/**\r\n * 判断是小数\r\n * @param {*} value 参数\r\n * @returns {boolean} result 返回结果\r\n */\r\nexport function isDecimal(value: any): boolean {\r\n return /^\\d+\\.\\d+$/.test(value);\r\n}\r\n\r\n/**\r\n * 判断类型是数字 Number\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNumber(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Number\";\r\n}\r\n\r\n/**\r\n * 判断类型是字符串 String\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isString(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"String\";\r\n}\r\n\r\n/**\r\n * 判断类型是数组 Array\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isArray(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Array\";\r\n}\r\n\r\n/**\r\n * 判断类型是对象 Object\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isObject(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Object\";\r\n}\r\n\r\n/**\r\n * 判断类型是布尔 boolean\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBoolean(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"boolean\";\r\n}\r\n\r\n/**\r\n * 判断类型是日期 Date\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isDate(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Date\";\r\n}\r\n\r\n/**\r\n * 判断类型是函数 Function\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFunction(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Function\";\r\n}\r\n\r\n/**\r\n * 判断类型是函数字符串 FunctionString\r\n * @description 支持普通函数,异步函数,箭头函数\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFunctionString(value: any): boolean {\r\n if (value) {\r\n try {\r\n const fn = new Function(`return ${value}`)();\r\n return typeof fn === \"function\";\r\n } catch (e) {\r\n // 如果发生错误,比如语法错误,那么这不是一个有效的函数\r\n return false;\r\n }\r\n } else {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * 判断类型是异步函数 AsyncFunction\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isAsyncFunction(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"AsyncFunction\";\r\n}\r\n\r\n/**\r\n * 判断类型是 Symbol\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSymbol(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Symbol\";\r\n}\r\n\r\n/**\r\n * 判断类型是正则 RegExp\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isRegExp(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"RegExp\";\r\n}\r\n\r\n/**\r\n * 判断类型是错误 Error\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isError(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Error\";\r\n}\r\n\r\n/**\r\n * 判断类型是 Promise\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isPromise(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Promise\";\r\n}\r\n\r\n/**\r\n *判断类型是 Map\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isMap(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Map\";\r\n}\r\n\r\n/**\r\n * 判断类型是 WeakMap\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isWeakMap(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"WeakMap\";\r\n}\r\n\r\n/**\r\n * 判断类型是 Set\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSet(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"Set\";\r\n}\r\n\r\n/**\r\n * 判断类型是 WeakSet\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isWeakSet(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"WeakSet\";\r\n}\r\n\r\n/**\r\n * 判断类型是 BigInt\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBigInt(value: any): boolean {\r\n return Object.prototype.toString.call(value).slice(8, -1) === \"BigInt\";\r\n}\r\n\r\n/**\r\n * 判断类型是 Json\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isJson(value: any): boolean {\r\n try {\r\n JSON.parse(value);\r\n return true;\r\n } catch (error) {\r\n return false;\r\n }\r\n}\r\n\r\n/* 数据值校验 */\r\n/**\r\n * 判断值为真\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isTrue(value: any): boolean {\r\n return !isFalse(value);\r\n}\r\n\r\n/**\r\n * 判断值为假\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFalse(value: any): boolean {\r\n return (\r\n value === undefined ||\r\n value === null ||\r\n value === \"undefined\" ||\r\n value === \"null\" ||\r\n value === 0 ||\r\n value === false ||\r\n isNaN(value)\r\n );\r\n}\r\n\r\n/**\r\n * 判断非数字\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNaN(value: any): boolean {\r\n return (\r\n value == null || typeof value === \"boolean\" || Array.isArray(value) || value === \"\" || Number.isNaN(Number(value))\r\n );\r\n}\r\n\r\n/**\r\n * 判断是数字\r\n * @description 等同于isNumber()\r\n * @param {*} value 参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotNaN(value: any): boolean {\r\n return !isNaN(value);\r\n}\r\n\r\n/**\r\n * 判断对象为空\r\n * @description 判断值是否为空,如果对象初始化了值则不为空\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNull(value: any): boolean {\r\n return value === undefined || value === null || value === \"\";\r\n}\r\n\r\n/**\r\n * 判断对象不为空\r\n * @description 判断值是否为空,如果对象初始化了值则不为空\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotNull(value: any): boolean {\r\n return !isNull(value);\r\n}\r\n\r\n/**\r\n * 判断值为空\r\n * @description 判断是否是有意义不为空的值,如果值是{},[]空的数据则为空\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isEmpty(value: any): boolean {\r\n if (isNull(value)) return true;\r\n if (typeof value === \"string\" || Array.isArray(value)) {\r\n return value.length === 0;\r\n }\r\n if (typeof value === \"object\") {\r\n if (value instanceof Map || value instanceof Set) {\r\n return value.size === 0;\r\n }\r\n if (value instanceof Date || value instanceof RegExp || value instanceof Error) {\r\n return false;\r\n }\r\n return Object.keys(value).length === 0;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * 判断值不为空\r\n * @description 判断是否是有意义不为空的值,如果值是{},[]空的数据则为空\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotEmpty(value: any): boolean {\r\n return !isEmpty(value);\r\n}\r\n\r\n/**\r\n * 判断值是空白的\r\n * @description 同时会校验空值,空对象,以及空白符号\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBlank(value: any): boolean {\r\n return isEmpty(value) || /^\\s*$/.test(value);\r\n}\r\n\r\n/**\r\n * 判断值不是空白的\r\n * @description 同时会校验空值,空对象,以及空白符号\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotBlank(value: any): boolean {\r\n return !isBlank(value);\r\n}\r\n\r\n/**\r\n * 判断值是undefined\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isUndefined(value: any): boolean {\r\n return value === undefined;\r\n}\r\n\r\n/**\r\n * 判断值不是undefined\r\n * @param {*} value 校验的参数\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isNotUndefined(value: any): boolean {\r\n return !isUndefined(value);\r\n}\r\n\r\n/* 数据比较 */\r\n/**\r\n * 判断两个值是否相等\r\n * @param {*} value1 参数1\r\n * @param {*} value2 参数2\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function equals(value1: any, value2: any): boolean {\r\n return Object.is(value1, value2);\r\n}\r\n\r\n/**\r\n * 判断两个值是否相等(忽略大小写)\r\n * @param {*} value1 参数1\r\n * @param {*} value2 参数2\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function equalsIgnoreCase(value1: any, value2: any): boolean {\r\n return Object.is(value1.toLowerCase(), value2.toLowerCase());\r\n}\r\n\r\n/**\r\n * 深度对比数据\r\n * @description 可以对比任意数据,对象、数组、日期等也可深度对比,对象不区分先后顺序\r\n * @param {*} x 数据1\r\n * @param {*} args 数据2\r\n * @returns {boolean} 返回对比结果\r\n */\r\nexport function deepCompare(x: any, ...args: any[]): boolean {\r\n let leftChain: any[] = [];\r\n let rightChain: any[] = [];\r\n\r\n // 核心对比函数(添加严格类型标注)\r\n const compare2Objects = (xObj: any, yObj: any): boolean => {\r\n // 1. 处理 NaN 特殊场景(NaN === NaN 返回 false,需单独判断)\r\n if (Number.isNaN(xObj) && Number.isNaN(yObj)) {\r\n return true;\r\n }\r\n\r\n // 2. 原始类型/引用同一对象 直接对比\r\n if (xObj === yObj) {\r\n return true;\r\n }\r\n\r\n // 3. 特殊内置对象对比(函数/日期/正则/包装对象)\r\n const typeOfX = typeof xObj;\r\n const typeOfY = typeof yObj;\r\n\r\n // 函数对比:通过 toString 比较内容\r\n if (typeOfX === \"function\" && typeOfY === \"function\") {\r\n return xObj.toString() === yObj.toString();\r\n }\r\n\r\n // 日期对象对比:时间戳一致则相等\r\n if (xObj instanceof Date && yObj instanceof Date) {\r\n return xObj.getTime() === yObj.getTime();\r\n }\r\n\r\n // 正则对象对比:源文本+标志位一致则相等\r\n if (xObj instanceof RegExp && yObj instanceof RegExp) {\r\n return xObj.source === yObj.source && xObj.flags === yObj.flags;\r\n }\r\n\r\n // 字符串/数字包装对象对比\r\n if ((xObj instanceof String && yObj instanceof String) || (xObj instanceof Number && yObj instanceof Number)) {\r\n return xObj.toString() === yObj.toString();\r\n }\r\n\r\n // 4. 非对象类型(排除上述特殊类型后)直接返回 false\r\n if (!(xObj instanceof Object && yObj instanceof Object)) {\r\n return false;\r\n }\r\n\r\n // 5. 原型链/构造函数校验\r\n if (xObj.isPrototypeOf(yObj) || yObj.isPrototypeOf(xObj)) {\r\n return false;\r\n }\r\n if ((xObj as object).constructor !== (yObj as object).constructor) {\r\n return false;\r\n }\r\n if ((xObj as { prototype?: unknown }).prototype !== (yObj as { prototype?: unknown }).prototype) {\r\n return false;\r\n }\r\n\r\n // 6. 循环引用检测(避免无限递归)\r\n if (leftChain.includes(xObj) || rightChain.includes(yObj)) {\r\n return false;\r\n }\r\n\r\n // 7. 遍历对象属性,对比键存在性和类型\r\n const xObjKeys = Object.keys(xObj as object);\r\n const yObjKeys = Object.keys(yObj as object);\r\n\r\n // 先对比属性数量(数量不同直接不相等)\r\n if (xObjKeys.length !== yObjKeys.length) {\r\n return false;\r\n }\r\n\r\n // 遍历所有属性,校验存在性、类型、值\r\n for (const p of yObjKeys) {\r\n if (Object.prototype.hasOwnProperty.call(xObj, p) !== Object.prototype.hasOwnProperty.call(yObj, p)) {\r\n return false;\r\n }\r\n const xProp = (xObj as Record<string, unknown>)[p];\r\n const yProp = (yObj as Record<string, unknown>)[p];\r\n if (typeof xProp !== typeof yProp) {\r\n return false;\r\n }\r\n }\r\n\r\n // 深度对比属性值\r\n for (const p of xObjKeys) {\r\n const xProp = (xObj as Record<string, unknown>)[p];\r\n const yProp = (yObj as Record<string, unknown>)[p];\r\n\r\n if (typeof xProp === \"object\" || typeof xProp === \"function\") {\r\n leftChain.push(xObj);\r\n rightChain.push(yObj);\r\n if (!compare2Objects(xProp, yProp)) {\r\n return false;\r\n }\r\n leftChain.pop();\r\n rightChain.pop();\r\n } else {\r\n if (xProp !== yProp) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n };\r\n\r\n // 边界处理:参数数量不足时的兜底\r\n if (arguments.length < 2) {\r\n console.warn(\"deepCompare 需要至少两个对比参数\");\r\n return true;\r\n }\r\n\r\n // 遍历所有传入的参数(支持对比多个值)\r\n for (const y of args) {\r\n leftChain = [];\r\n rightChain = [];\r\n if (!compare2Objects(x, y)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n","/**\r\n * @module 字符串\r\n */\r\n/* 字符串处理 */\r\nimport { isNull, isNaN } from \"@/validate\";\r\n\r\n/**\r\n * 字符串中是否包含指定的元素\r\n * @param {string} value 包含的元素\r\n * @param {string} str 查找的字符串\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function inString(value: string, str: string): boolean {\r\n return str.includes(value);\r\n}\r\n\r\n/**\r\n * 去除字符串前后位置空格\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function trim(value: string): string {\r\n return value.replace(/(^\\s*)|(\\s*$)/g, \"\");\r\n}\r\n\r\n/**\r\n * 去除字符串开始位置的空格\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function trimStart(value: string): string {\r\n return value.replace(/(^\\s*)/g, \"\");\r\n}\r\n\r\n/**\r\n * 去除字符串结束位置的空格\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function trimEnd(value: string): string {\r\n return value.replace(/(\\s*$)/g, \"\");\r\n}\r\n\r\n/**\r\n * 去除字符串中全部的空格\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function trimAll(value: string): string {\r\n return value.replace(/\\s+/g, \"\");\r\n}\r\n\r\n/**\r\n * 替换所有指定字符串为新的字符串\r\n * @param {string} value 参数\r\n * @param {string} oldSubstr 需要替换的字符串\r\n * @param {string} newSubstr 替换后的字符串\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function replaceAll(value: string, oldSubstr: string, newSubstr: string): string {\r\n return value.replace(new RegExp(oldSubstr, \"gm\"), newSubstr);\r\n}\r\n\r\n/* 字符串转换 */\r\n/**\r\n * 字符串转大写\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toUpperCase(value: string): string {\r\n return String(value).toLocaleUpperCase();\r\n}\r\n\r\n/**\r\n * 字符串转小写\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toLowerCase(value: string): string {\r\n return String(value).toLocaleLowerCase();\r\n}\r\n\r\n/**\r\n * 转为 snake_case 下划线命名\r\n * @description 支持 驼峰命名,短横命名,帕斯卡命名\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toSnakeCase(value: string): string {\r\n // 驼峰\r\n if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n return value.replace(/([A-Z])/g, \"_$1\").toLowerCase();\r\n }\r\n // 短横\r\n else if (value.indexOf(\"-\") > 0) {\r\n return value.replace(/-/g, \"_\").toLowerCase();\r\n }\r\n // 帕斯卡\r\n else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n value = value.charAt(0).toLowerCase() + value.slice(1);\r\n return value.replace(/([A-Z])/g, \"_$1\").toLowerCase();\r\n }\r\n // 不符合格式\r\n else {\r\n throw new TypeError(`toSnakeCase: value should be a string`);\r\n }\r\n}\r\n\r\n/**\r\n * 转为 kebab-case 短横命名\r\n * @description 支持 下划线,驼峰命名,帕斯卡命名\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toKebabCase(value: string): string {\r\n // 下划线\r\n if (value.indexOf(\"_\") > 0) {\r\n return value.replace(/_/g, \"-\").toLowerCase();\r\n }\r\n // 驼峰\r\n else if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n return value.replace(/([A-Z])/g, \"-$1\").toLowerCase();\r\n }\r\n // 帕斯卡\r\n else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n const newStr = value.charAt(0).toLowerCase() + value.slice(1);\r\n return newStr.replace(/([A-Z])/g, \"-$1\").toLowerCase();\r\n }\r\n // 不符合格式\r\n else {\r\n throw new TypeError(\"toKebabCase: value should be a string\");\r\n }\r\n}\r\n\r\n/**\r\n * 转为 camelCase 驼峰命名\r\n * @description 支持 下划线命名,短横命名,帕斯卡命名\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toCamelCase(value: string): string {\r\n // 下划线\r\n if (value.indexOf(\"_\") > 0) {\r\n return value.replace(/\\_(\\w)/g, function (all, letter) {\r\n return letter.toUpperCase();\r\n });\r\n }\r\n // 短横\r\n else if (value.indexOf(\"-\") > 0) {\r\n return value.replace(/\\-(\\w)/g, function (all, letter) {\r\n return letter.toUpperCase();\r\n });\r\n }\r\n // 帕斯卡\r\n else if (/^[A-Z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n return value.charAt(0).toLowerCase() + value.slice(1);\r\n }\r\n // 不符合格式\r\n else {\r\n throw new TypeError(\"toCamelCase: value should be a string\");\r\n }\r\n}\r\n\r\n/**\r\n * 转为 PascalCase 帕斯卡命名\r\n * @description 支持 下划线命名,短横命名,驼峰命名\r\n * @param {string} value 参数\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nexport function toPascalCase(value: string): string {\r\n // 下划线\r\n if (value.indexOf(\"_\") > 0) {\r\n const newStr = value.replace(/\\_(\\w)/g, function (all, letter) {\r\n return letter.toUpperCase();\r\n });\r\n return newStr.charAt(0).toUpperCase() + newStr.slice(1);\r\n }\r\n // 短横\r\n else if (value.indexOf(\"-\") > 0) {\r\n const newStr = value.replace(/\\-(\\w)/g, function (all, letter) {\r\n return letter.toUpperCase();\r\n });\r\n return newStr.charAt(0).toUpperCase() + newStr.slice(1);\r\n }\r\n // 驼峰\r\n else if (/^[a-z]$/.test(value.charAt(0)) && !(value.indexOf(\"-\") > 0 || value.indexOf(\"_\") > 0)) {\r\n return value.charAt(0).toUpperCase() + value.slice(1);\r\n }\r\n // 不符合格式\r\n else {\r\n throw new TypeError(\"toPascalCase: value should be a string\");\r\n }\r\n}\r\n\r\n/* 字符串格式化 */\r\n\r\n/**\r\n * 数字前补齐0达到指定位数\r\n * @description 相当于原生的 padStart(2,'0')\r\n * @param {number|string} value 补零的数字\r\n * @param {number} maxLength 补齐0后的最大长度,默认2位\r\n * @returns {string} 返回补0后指定位数的字符串\r\n */\r\nexport function padZeroStart(value: string | number, maxLength: number = 2): string {\r\n value = String(value).trim();\r\n if (maxLength < 0) {\r\n throw new TypeError(\"padZeroStart: maxLength should be greater than 0\");\r\n }\r\n if (isNull(value) || isNaN(value)) {\r\n throw new TypeError(\"padZeroStart: value must be a valid number or numeric string\");\r\n }\r\n\r\n // 前面补0\r\n let len = value.toString().length;\r\n while (len < maxLength) {\r\n value = \"0\" + value;\r\n len++;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * 数字后补齐0达到指定位数\r\n * @description 相当于原生的 padEnd(2,'0')\r\n * @param {number|string} value 补零的数字\r\n * @param {number} maxLength 补齐0后的最大长度,默认2位\r\n * @returns {string} 返回补0后指定位数的字符串\r\n */\r\nexport function padZeroEnd(value: string | number, maxLength: number = 2): string {\r\n value = String(value).trim();\r\n if (maxLength < 0) {\r\n throw new TypeError(\"padZeroEnd: maxLength should be greater than 0\");\r\n }\r\n if (isNull(value) || isNaN(value)) {\r\n throw new TypeError(\"padZeroEnd: value must be a valid number or numeric string\");\r\n }\r\n\r\n // 后面补0\r\n let len = value.toString().length;\r\n while (len < maxLength) {\r\n value = value + \"0\";\r\n len++;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * 格式化为标题样式\r\n * @param {string} value 字符串值\r\n * @returns {string} 返回格式化后的标题样式\r\n */\r\nexport function formatTitle(value: string): string {\r\n if (!value) return \"\";\r\n return value\r\n .split(/(?=[A-Z])|[\\.\\-\\s_]/)\r\n .map((s) => s.trim())\r\n .filter((s) => !!s)\r\n .map((s) => toPascalCase(s.toLowerCase()))\r\n .join(\" \");\r\n}\r\n\r\n/**\r\n * 格式化字符串模版\r\n * @param {string} value 字符串值\r\n * @param {Object} data 模版数据\r\n * @returns {string} 返回格式化后的模版字符串\r\n */\r\nexport function formatTemplate(value: string, data: Record<any, any>): string {\r\n if (!value) return \"\";\r\n return Array.from(value.matchAll(/\\{\\{(.+?)\\}\\}/g)).reduce((acc, match) => {\r\n return acc.replace(match[0], data[match[1]]);\r\n }, value);\r\n}\r\n\r\n/**\r\n * 格式化千分位数字\r\n * @description 支持任意数据传参,如果非数字则不会格式化,并返回原数据\r\n * @param {number|string} num 数字\r\n * @returns {string} 返回格式化后的千分位数字\r\n */\r\nexport function formatThousand(num: number | string): string {\r\n if (!parseFloat(String(num))) return String(num);\r\n num = String(num);\r\n const regex = num.indexOf(\".\") > -1 ? /(\\d)(?=(\\d{3})+\\.)/g : /(\\d)(?=(?:\\d{3})+$)/g;\r\n return num.replace(regex, \"$1,\");\r\n}\r\n\r\n/**\r\n * 格式化人民币金额大写\r\n * @param {number|string} money 金额\r\n * @returns {string} 返回金额大写\r\n */\r\nexport function formatRmbChinese(money: number | string): string {\r\n // 汉字的数字\r\n const cnNums = [\"零\", \"壹\", \"贰\", \"叁\", \"肆\", \"伍\", \"陆\", \"柒\", \"捌\", \"玖\"];\r\n // 基本单位\r\n const cnIntRadiance = [\"\", \"拾\", \"佰\", \"仟\"];\r\n // 对应整数部分扩展单位\r\n const cnIntUnits = [\"\", \"万\", \"亿\", \"兆\"];\r\n // 对应小数部分单位\r\n const cnDecUnits = [\"角\", \"分\", \"毫\", \"厘\"];\r\n // 整数金额时后面跟的字符\r\n const cnInteger = \"整\";\r\n // 整型完以后的单位\r\n const cnIntLast = \"元\";\r\n // 最大处理的数字\r\n const maxNum = Number(\"999999999999999.9999\");\r\n // 金额整数部分\r\n let integerNum;\r\n // 金额小数部分\r\n let decimalNum;\r\n // 输出的中文金额字符串\r\n let chineseStr = \"\";\r\n // 分离金额后用的数组,预定义\r\n let parts;\r\n if (money === \"\") {\r\n // 不能用==\r\n return \"\";\r\n }\r\n money = parseFloat(String(money));\r\n if (money >= maxNum) {\r\n // 超出最大处理数字,抛出异常\r\n throw new TypeError(\"formatRmbChinese: calculated number overflow\");\r\n }\r\n if (money === 0) {\r\n chineseStr = cnNums[0] + cnIntLast + cnInteger;\r\n return chineseStr;\r\n }\r\n // 转换为字符串\r\n money = money.toString();\r\n if (money.indexOf(\".\") === -1) {\r\n integerNum = money;\r\n decimalNum = \"\";\r\n } else {\r\n parts = money.split(\".\");\r\n integerNum = parts[0];\r\n decimalNum = parts[1].substr(0, 4);\r\n }\r\n // 获取整型部分转换\r\n if (parseInt(integerNum, 10) > 0) {\r\n let zeroCount = 0;\r\n const IntLen = integerNum.length;\r\n for (let i = 0; i < IntLen; i++) {\r\n const n = integerNum.substr(i, 1);\r\n const p = IntLen - i - 1;\r\n const q = p / 4;\r\n const m = p % 4;\r\n if (n === \"0\") {\r\n zeroCount++;\r\n } else {\r\n if (zeroCount > 0) {\r\n chineseStr += cnNums[0];\r\n }\r\n // 归零\r\n zeroCount = 0;\r\n chineseStr += cnNums[parseInt(n)] + cnIntRadiance[m];\r\n }\r\n if (m === 0 && zeroCount < 4) {\r\n chineseStr += cnIntUnits[q];\r\n }\r\n }\r\n chineseStr += cnIntLast;\r\n }\r\n // 小数部分\r\n if (decimalNum !== \"\") {\r\n const decLen = decimalNum.length;\r\n for (let i = 0; i < decLen; i++) {\r\n const n = decimalNum.substr(i, 1);\r\n if (n !== \"0\") {\r\n chineseStr += cnNums[Number(n)] + cnDecUnits[i];\r\n }\r\n }\r\n }\r\n if (chineseStr === \"\") {\r\n chineseStr += cnNums[0] + cnIntLast + cnInteger;\r\n } else if (decimalNum === \"\") {\r\n chineseStr += cnInteger;\r\n }\r\n return chineseStr;\r\n}\r\n","/**\r\n * @module 数字\r\n */\r\nimport { isNull } from \"@/validate\";\r\n\r\n/**\r\n * 转为数字类型\r\n * @description 解决部分浏览器在转换 '08','09'等是0开头时被默认转8进制问题\r\n * @param {string|number} value 转换的值\r\n * @param {number} radix 进制数,默认10进制\r\n * @returns {number} 返回转换后的数字\r\n */\r\nexport function parseInt(value: string | number, radix: number = 10): number {\r\n if (isNull(value)) {\r\n return 0;\r\n }\r\n return Number.parseInt(String(value), radix);\r\n}\r\n\r\n/**\r\n * 转为小数类型\r\n * @param {string|number} value 转换的值\r\n * @returns {number} 返回转换后的数字\r\n */\r\nexport function parseFloat(value: string | number): number {\r\n if (isNull(value)) {\r\n return 0.0;\r\n }\r\n return Number.parseFloat(String(value));\r\n}\r\n","/**\r\n * @module 数组\r\n */\r\nimport { SORT } from \"@/constants\";\r\nimport { isArray, isEmpty, isNull, isObject } from \"@/validate\";\r\n\r\n/* 数组计算 */\r\n/**\r\n * 数组最小值\r\n * @param {Array} array 数组\r\n * @returns {number} 返回最小值\r\n */\r\nexport function arrayMin(array: any[]): number {\r\n return Math.min.apply(null, array);\r\n}\r\n\r\n/**\r\n * 数组最大值\r\n * @param {array} array 数组\r\n * @returns {number} 返回最大值\r\n */\r\nexport function arrayMax(array: any[]): number {\r\n return Math.max.apply(null, array);\r\n}\r\n\r\n/**\r\n * 数组求和\r\n * @param {Array} array 数组\r\n * @returns {number} 返回和\r\n */\r\nexport function arraySum(array: any[]): number {\r\n return array.reduce(function (pre, cur) {\r\n return pre + cur;\r\n });\r\n}\r\n\r\n/**\r\n * 数组求平均值\r\n * @param {Array} array 数组\r\n * @returns {number} 返回平均数\r\n */\r\nexport function arrayAvg(array: any[]): number {\r\n return arraySum(array) / array.length;\r\n}\r\n\r\n/* 数组比较 */\r\n/**\r\n * 数组中是否包含指定的元素\r\n * @param {string|number} value 元素\r\n * @param {Array} array 查找的数组\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function inArray(value: string | number, array: any[]): boolean {\r\n if (isNull(value)) return false;\r\n return array.includes(value);\r\n}\r\n\r\n/**\r\n * 比较两个数组是否相等\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function arrayEquals(array1: any[], array2: any[]): boolean {\r\n if (array1 === array2) return true;\r\n if (array1.length !== array2.length) return false;\r\n return array1.every((v, i) => v === array2[i]);\r\n}\r\n\r\n/* 数组操作 */\r\n/**\r\n * 生成指定长度的数组\r\n * @param {number} length 长度,默认 0\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayCreate(length: number = 0): number[] {\r\n return [...Array(length).keys()];\r\n}\r\n\r\n/**\r\n * 数组指定位置添加元素\r\n * @description 如果数组为空,则在0位置添加元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @param {*} value 添加的元素\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayInsert(array: any[] = [], index: number = 0, value: any = undefined): any[] {\r\n if (index < 0) return array;\r\n\r\n if (array.length === 0) {\r\n array.push(value);\r\n } else {\r\n if (index > array.length - 1) {\r\n return array;\r\n }\r\n array.splice(index, 0, value);\r\n }\r\n\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置前面添加元素\r\n * @description 如果数组为空,则在0位置添加元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @param {*} value 添加的元素\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayInsertBefore(array: any[] = [], index: number = 0, value: any = undefined): any[] {\r\n if (index < 0) return array;\r\n\r\n if (array.length === 0) {\r\n array.push(value);\r\n } else {\r\n if (index > array.length - 1) {\r\n return array;\r\n }\r\n array.splice(index, 0, value);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置后面添加元素\r\n * @description 如果数组为空,则在0位置添加元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @param {*} value 添加的元素\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayInsertAfter(array: any[] = [], index: number = 0, value: any = undefined): any[] {\r\n if (index < 0) return array;\r\n\r\n if (array.length === 0) {\r\n array.push(value);\r\n } else {\r\n if (index > array.length - 1) {\r\n return array;\r\n }\r\n array.splice(index, 0, array.splice(index, 1, value)[0]);\r\n }\r\n\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置删除元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayRemove(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n array.splice(index, 1);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置前面删除元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayRemoveBefore(array: any[] = [], index: number = 0): any[] {\r\n if (index <= 0 || index > array.length - 1) return array;\r\n\r\n array.splice(index - 1, 1);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组指定位置后面删除元素\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayRemoveAfter(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n array.splice(index + 1, 1);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组置顶\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayTop(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n array.unshift(array.splice(index, 1)[0]);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组置尾\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayBottom(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n array.push(array.splice(index, 1)[0]);\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组向上移动\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayUp(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n if (index > 0) {\r\n array.splice(index - 1, 0, array.splice(index, 1)[0]);\r\n } else {\r\n array.push(array.splice(index, 1)[0]);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组向下移动\r\n * @param {Array} array 数组\r\n * @param {number} index 下标位置,默认0\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayDown(array: any[] = [], index: number = 0): any[] {\r\n if (index < 0 || index > array.length - 1) return array;\r\n\r\n if (index < array.length - 1) {\r\n array.splice(index + 1, 0, array.splice(index, 1)[0]);\r\n } else {\r\n array.unshift(array.splice(index, 1)[0]);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组交换元素\r\n * @param {Array} array 数组\r\n * @param {number} sourceIndex 原索引\r\n * @param {number} targetIndex 目标索引\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arraySwap(array: any[], sourceIndex: number, targetIndex: number): any[] {\r\n if (sourceIndex < 0 || targetIndex < 0 || sourceIndex > array.length - 1 || targetIndex > array.length - 1) {\r\n return array;\r\n }\r\n\r\n [array[targetIndex], array[sourceIndex]] = [array[sourceIndex], array[targetIndex]];\r\n return array;\r\n}\r\n\r\n/**\r\n * 数组排序\r\n * @param {Array} array 数组\r\n * @param {number} mode 排序模式,参考常量集合中 数组常量,默认是升序\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arraySort(array: any[], mode: number = SORT.ASC): any[] {\r\n return array.sort((a: any, b: any) => {\r\n switch (mode) {\r\n // 升序\r\n case SORT.ASC:\r\n return a - b;\r\n // 降序\r\n case SORT.DESC:\r\n return b - a;\r\n // 随机\r\n case SORT.RANDOM:\r\n return Math.random() - 0.5;\r\n default:\r\n return 0;\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 数组属性混合排序\r\n * @description 排序默认为asc升序\r\n * @param {Array} array 数组\r\n * @param {Array} props 排序的属性\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arraySortBy(array: any[], props: any[]): any[] {\r\n return array.sort((a, b) => {\r\n for (const item of props) {\r\n // 排序配置\r\n let prop = \"\",\r\n order = \"asc\";\r\n if (isObject(item)) {\r\n prop = item.prop;\r\n order = item.order || \"asc\";\r\n } else {\r\n prop = item;\r\n order = \"asc\";\r\n }\r\n // 排序逻辑\r\n if (a[prop] < b[prop]) {\r\n return order === \"asc\" ? -1 : 1;\r\n }\r\n if (a[prop] > b[prop]) {\r\n return order === \"asc\" ? 1 : -1;\r\n }\r\n }\r\n return 0;\r\n });\r\n}\r\n\r\n/**\r\n * 数组元素去重\r\n * @param {Array} array 数组\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayUnique(array: any[]): any[] {\r\n if (isEmpty(array)) return [];\r\n\r\n return Array.from(new Set(array));\r\n}\r\n\r\n/**\r\n * 数组打乱元素\r\n * @description 可以适用于一些抽奖人员列表打乱顺序\r\n * @param {Array} array 数组\r\n * @returns {Array} 返回操作后的数组\r\n */\r\nexport function arrayShuffle(array: any[]): any[] {\r\n for (let i = 1; i < array.length; i++) {\r\n const random = Math.floor(Math.random() * (i + 1));\r\n [array[random], array[i]] = [array[i], array[random]];\r\n }\r\n return array;\r\n}\r\n\r\n/* 数组转换 */\r\n/**\r\n * 普通数组转树形结构\r\n * @description 包含id和pid属性关系的一维数组,转为children的树形结构\r\n * @param {Array} array 数组\r\n * @param {Object} setting 配置项\r\n * @returns {Array} 返回树形节点\r\n */\r\nexport function arrayToTree(\r\n array: any[],\r\n setting: { key: string; parentKey: string; childrenKey: string } = {\r\n key: \"id\",\r\n parentKey: \"pid\",\r\n childrenKey: \"children\",\r\n },\r\n): any[] {\r\n const key = setting.key,\r\n parentKey = setting.parentKey,\r\n childrenKey = setting.childrenKey;\r\n\r\n // 数组或者key是否为空\r\n if (!array || array.length === 0 || !key || key === \"\") return [];\r\n\r\n // 获得子节点方法\r\n const nodeChildren = function (node: any, childrenKey: string, newChildren?: any) {\r\n if (!node) {\r\n return null;\r\n }\r\n if (typeof newChildren !== \"undefined\") {\r\n node[childrenKey] = newChildren;\r\n }\r\n return node[childrenKey];\r\n };\r\n\r\n // 声明变量\r\n const result = [];\r\n const tempMap: any = {};\r\n for (let i = 0; i < array.length; i++) {\r\n // 如果源数据数组中有children,则需要删除掉,否则会导致和之前的children合并\r\n array[i][childrenKey] && delete array[i][childrenKey];\r\n tempMap[array[i][key]] = array[i];\r\n }\r\n for (let i = 0; i < array.length; i++) {\r\n const parent = tempMap[array[i][parentKey]];\r\n if (parent && array[i][key] !== array[i][parentKey]) {\r\n let children = nodeChildren(parent, childrenKey);\r\n\r\n if (!children) {\r\n children = nodeChildren(parent, childrenKey, []);\r\n }\r\n children.push(array[i]);\r\n } else {\r\n result.push(array[i]);\r\n }\r\n }\r\n\r\n // 返回结果\r\n return result;\r\n}\r\n\r\n/**\r\n * 树形结构转普通数组\r\n * @param {Array} nodes 树形节点\r\n * @param {Object} setting 配置项\r\n * @returns {Array} 返回普通数组\r\n */\r\nexport function treeToArray(nodes: any[], setting: { childrenKey: string } = { childrenKey: \"children\" }): any[] {\r\n const childrenKey = setting.childrenKey;\r\n const result = [];\r\n for (const node of nodes) {\r\n // 删除掉多余空的children\r\n if (node[childrenKey] && !node[childrenKey].length) {\r\n delete node[childrenKey];\r\n }\r\n result.push(node);\r\n // 继续执行\r\n if (node[childrenKey] && node[childrenKey].length) {\r\n const array = treeToArray(node[childrenKey], setting);\r\n array && result.push(...array);\r\n }\r\n }\r\n\r\n // 返回结果\r\n return result;\r\n}\r\n\r\n/* 数组求并集,交集,差集等 */\r\n/**\r\n * 数组求并集\r\n * @description 数组1 和 数组2 合并一起的元素集合\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayUnion(array1: any[], array2: any[]): any[] {\r\n return [...new Set(array1.concat(array2))];\r\n}\r\n\r\n/**\r\n * 数组求交集\r\n * @description 数组1 和 数组2 相同的元素集合\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayIntersect(array1: any[], array2: any[]): any[] {\r\n return [...new Set(array1)].filter((item) => array2.includes(item));\r\n}\r\n\r\n/**\r\n * 数组求差集\r\n * @description 数组1 中不包含 数组2 的元素集合\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayDifference(array1: any[], array2: any[]): any[] {\r\n return [...new Set(array1)].filter((item) => !array2.includes(item));\r\n}\r\n\r\n/**\r\n * 数组求补集\r\n * @description 数组1 和 数组2 不相同的元素集合\r\n * @param {Array} array1 数组1\r\n * @param {Array} array2 数组2\r\n * @returns {Array} 返回数组\r\n */\r\nexport function arrayComplement(array1: any[], array2: any[]): any[] {\r\n return [\r\n ...[...new Set(array1)].filter((item) => !array2.includes(item)),\r\n ...[...new Set(array2)].filter((item) => !array1.includes(item)),\r\n ];\r\n}\r\n","/**\r\n * @module 对象\r\n */\r\nimport { isEmpty, isObject, isArray, isDate, isNumber, isNotNaN, isNaN } from \"@/validate\";\r\n\r\n/* 对象转换 */\r\n/**\r\n * map转object\r\n * @param {Map} map 参数\r\n * @returns {Object} 返回Object\r\n */\r\nexport function mapToObject(map: Map<any, any>): Record<any, any> {\r\n const obj = Object.create(null);\r\n for (const [k, v] of map) {\r\n obj[k] = v;\r\n }\r\n return obj;\r\n}\r\n\r\n/**\r\n * map转json字符串\r\n * @param {Map} map 参数\r\n * @returns {string} 返回Json字符串\r\n */\r\nexport function mapToJson(map: Map<any, any>): string {\r\n return JSON.stringify(mapToObject(map));\r\n}\r\n\r\n/**\r\n * object转map\r\n * @param {Object} obj 参数\r\n * @returns {Map} 返回Map\r\n */\r\nexport function objectToMap(obj: Record<any, any>): Map<any, any> {\r\n const map = new Map();\r\n for (const k of Object.keys(obj)) {\r\n map.set(k, obj[k]);\r\n }\r\n return map;\r\n}\r\n\r\n/**\r\n * json字符串转map\r\n * @param {string} json json字符串\r\n * @returns {Map} 返回Map\r\n */\r\nexport function jsonToMap(json: string): Map<any, any> {\r\n return objectToMap(JSON.parse(json));\r\n}\r\n\r\n/**\r\n * json对象转json字符串\r\n * @param {Object} json json对象\r\n * @param {boolean} replacer 是否处理循环引用\r\n * @returns {string} 返回Json字符串\r\n */\r\nexport function stringifyJson(json: Record<any, any>, replacer: boolean = false): string {\r\n try {\r\n return JSON.stringify(\r\n json,\r\n replacer\r\n ? (key: string, value: any) => {\r\n if (typeof value === \"function\" || typeof value === \"symbol\") {\r\n return String(value);\r\n }\r\n return value;\r\n }\r\n : undefined,\r\n );\r\n } catch (error) {\r\n console.error(\"JSON序列化失败:\", error);\r\n return \"{}\"; // 兜底返回空对象\r\n }\r\n}\r\n\r\n/**\r\n * json字符串转json对象\r\n * @param {string} json json字符串\r\n * @returns {Object} 返回Json对象\r\n */\r\nexport function parseJson(json: string): Record<any, any> | null {\r\n if (isEmpty(json)) return null;\r\n try {\r\n return JSON.parse(json);\r\n } catch (e) {\r\n console.error(e);\r\n return null;\r\n }\r\n}\r\n\r\n/* 数据拷贝,对比,合并等操作 */\r\n/**\r\n * 浅拷贝数据\r\n * @param {*} source 拷贝的数据\r\n * @returns {*} 返回浅拷贝的数据\r\n */\r\nexport function clone(source: any): any {\r\n // 边界处理:null/undefined/原始类型(直接返回,无需拷贝)\r\n if (source === null || typeof source !== \"object\") {\r\n return source;\r\n }\r\n\r\n // 处理数组(用扩展运算符实现浅拷贝,避免Object.assign的索引问题)\r\n if (Array.isArray(source)) {\r\n return [...source];\r\n }\r\n\r\n // 处理普通对象(真正创建新对象,原代码Object.assign(source)等于没拷贝)\r\n if (source.constructor === Object) {\r\n return Object.assign({}, source);\r\n }\r\n\r\n // 处理特殊内置对象(Date/RegExp)\r\n if (source instanceof Date) {\r\n return new Date(source.getTime());\r\n }\r\n if (source instanceof RegExp) {\r\n return new RegExp(source.source, source.flags);\r\n }\r\n\r\n // 其他不可浅拷贝的对象(函数/类实例/Map/Set等,直接返回原对象)\r\n return source;\r\n}\r\n\r\n/**\r\n * 深拷贝数据\r\n * @param {*} source 拷贝的数据\r\n * @returns {*} 返回深拷贝的数据\r\n */\r\nexport function deepClone(source: any): any {\r\n // Object\r\n if (isObject(source)) {\r\n const copy: Record<string, any> = {};\r\n for (const attr in source) {\r\n if (source.hasOwnProperty(attr)) {\r\n copy[attr] = deepClone(source[attr]);\r\n }\r\n }\r\n return copy;\r\n }\r\n\r\n // Array\r\n else if (isArray(source)) {\r\n const copy = [];\r\n for (let i = 0, len = source.length; i < len; i++) {\r\n copy[i] = deepClone(source[i]);\r\n }\r\n return copy;\r\n }\r\n\r\n // Date\r\n else if (isDate(source)) {\r\n const copy = new Date();\r\n copy.setTime(source.getTime());\r\n return copy;\r\n }\r\n\r\n // Other 返回原数据\r\n else {\r\n return source;\r\n }\r\n}\r\n\r\n/**\r\n * 比较两个对象是否相等\r\n * @description 方法只能对比简单的对象,不能包含function,另外对象的属性顺序不一致也是相等的\r\n * @param {Object} obj1 对象1\r\n * @param {Object} obj2 对象2\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function objectEquals(obj1: Record<any, any>, obj2: Record<any, any>): boolean {\r\n // 比较值相等\r\n if (obj1 === obj2) {\r\n return true;\r\n }\r\n // 比较Date\r\n if (obj1 instanceof Date && obj2 instanceof Date) {\r\n return obj1.getTime() === obj2.getTime();\r\n }\r\n // 对象比较引用\r\n if (!obj1 || !obj2 || (typeof obj1 !== \"object\" && typeof obj2 !== \"object\")) {\r\n return obj1 === obj2;\r\n }\r\n // 比较原型\r\n if (obj1.prototype !== obj2.prototype) {\r\n return false;\r\n }\r\n // 比较对象的值\r\n const keys = Object.keys(obj1);\r\n if (keys.length !== Object.keys(obj2).length) {\r\n return false;\r\n } else {\r\n return keys.every((k) => objectEquals(obj1[k], obj2[k]));\r\n }\r\n}\r\n\r\n/**\r\n * 合并对象\r\n * @param {Object} target 目标对象\r\n * @param {Object[]} source 原对象列表\r\n * @returns {Object} 返回合并后的对象\r\n */\r\nexport function merge(target: Record<any, any>, ...source: Record<any, any>[]): any {\r\n if (target == null || typeof target !== \"object\") {\r\n return target;\r\n }\r\n return Object.assign(target, ...source);\r\n}\r\n\r\n/* 根据字符串属性路径操作目标对象 */\r\n/**\r\n * 根据字符串属性路径获取目标对象的值\r\n * @example\r\n * let res = {code:200, data:{rows:[], pages:{current:1,pageSize:20}}}\r\n * this._getValueByPath(res, 'data.pages.pageSize'); // 这里会输出20\r\n * @param {Object} target 目标对象\r\n * @param {string} path 字符串属性路径\r\n * @returns {*} 返回目标对象的值\r\n */\r\nexport function getValueByPath(target: Record<any, any>, path: string = \"data\"): any {\r\n const paths = (path || \"data\").split(\".\");\r\n let current = target;\r\n for (const index in paths) {\r\n const part = paths[index];\r\n // 判断属性是取的数组\r\n const { propName, propIndex = 0, isArray } = _getTargetPathPart(paths[index]);\r\n if (isArray) {\r\n // 获取的数组下标超出实际的长度\r\n if (propIndex < 0 || propIndex >= current[propName].length) {\r\n return;\r\n }\r\n // 逐层向下找到对应属性的值\r\n current = current[propName][propIndex];\r\n }\r\n // 判断属性是取的对象属性\r\n else {\r\n // 如果属性不存在,则返回空的\r\n if (!current || !current.hasOwnProperty(part) || typeof current !== \"object\") {\r\n return;\r\n }\r\n // 逐层向下找到对应属性的值\r\n current = current[part];\r\n }\r\n }\r\n return current;\r\n}\r\n\r\n/**\r\n * 根据字符串属性路径设置目标对象的值\r\n * @example\r\n * let res = {code:200, data:{rows:[], pages:{current:1,pageSize:20}}}\r\n * this._setValueByPath(res, 'data.pages.pageSize', 30); // 打印res对象会发现pageSize的值改为了30\r\n * @param {Object} target 目标对象\r\n * @param {string} path 字符串属性路径\r\n * @param {*} value 值\r\n * @returns {*} 返回修改过后的目标对象\r\n */\r\nexport function setValueByPath(target: Record<any, any>, path: string = \"data\", value: any): Record<any, any> {\r\n const paths = (path || \"data\").split(\".\");\r\n let current = target;\r\n\r\n // 遍历到路径的倒数第二个属性\r\n for (let index = 0; index < paths.length - 1; index++) {\r\n const part = paths[index];\r\n const nextPart = paths[index + 1];\r\n // 判断属性是取的数组\r\n const { propName, propIndex = 0, isArray } = _getTargetPathPart(part);\r\n\r\n if (isArray) {\r\n // 检查当前属性是否存在,若不存在或者不是数组,则创建一个数组\r\n if (!current || !current.hasOwnProperty(propName)) {\r\n current[propName] = [];\r\n }\r\n // 确保数组长度足够容纳指定索引\r\n while (current[propName].length <= propIndex) {\r\n current[propName].push({});\r\n }\r\n // 逐层向下找到对应属性的值\r\n current = current[propName][propIndex];\r\n } else {\r\n // 如果不是数组索引形式,处理普通对象属性,如果是.1.数组形式,则还是返回数组\r\n if (!current || !current.hasOwnProperty(part) || typeof current[part] !== \"object\") {\r\n current[part] = isNaN(nextPart) ? [] : {};\r\n }\r\n // 移动到对象的下一层属性\r\n current = current[part];\r\n }\r\n }\r\n\r\n // 处理最后一个路径部分\r\n const lastPath = paths[paths.length - 1];\r\n const { propName, propIndex = 0, isArray } = _getTargetPathPart(lastPath);\r\n if (isArray) {\r\n // 检查当前属性是否存在,若不存在或者不是数组,则创建一个数组\r\n if (!current.hasOwnProperty(propName) || !Array.isArray(current[propName])) {\r\n current[propName] = [];\r\n }\r\n // 确保数组长度足够容纳指定索引\r\n while (current[propName].length <= propIndex) {\r\n current[propName].push({});\r\n }\r\n // 逐层向下找到对应属性的值\r\n current[propName][propIndex] = value;\r\n } else {\r\n current[lastPath] = value;\r\n }\r\n\r\n // 返回源对象\r\n return target;\r\n}\r\n\r\n/* 内部方法 */\r\n/**\r\n * 获得目标路径的片段\r\n * @param {string} path\r\n * @returns {*} 返回获得到的值\r\n */\r\nfunction _getTargetPathPart(path: string): Record<any, any> {\r\n const pathArrayMatch = path.match(/^(\\w+)\\[(\\d+)]$/);\r\n return {\r\n propName: (pathArrayMatch && pathArrayMatch[1]) || undefined, // 属性名\r\n propIndex: pathArrayMatch ? parseInt(pathArrayMatch[2], 10) : undefined, // 属性数组时候的下标\r\n isArray: !!pathArrayMatch, // 是否是数组\r\n };\r\n}\r\n","/**\r\n * @module 日期\r\n */\r\nimport { isNull, isInteger, isDate, isString } from \"@/validate\";\r\nimport { parseInt } from \"@/number\";\r\nimport { DATE } from \"@/constants\";\r\n\r\n/**\r\n 日期配置类型\r\n @param format 日期格式字符串,支持的占位符如下:\r\n | 占位符 | 说明 | 示例(2025-01-05 08:05:08 周一) |\r\n |--------|-----------------------|---------------------------------|\r\n | yyyy | 4 位年份 | 2025 |\r\n | yy | 2 位年份 | 25 |\r\n | MM | 2 位月份(补 0) | 01 |\r\n | M | 1 位月份(不补 0) | 1 |\r\n | dd | 2 位日期(补 0) | 05 |\r\n | d | 1 位日期(不补 0) | 5 |\r\n | HH | 24 小时制(2 位,补 0) | 08 |\r\n | H | 24 小时制(1 位,不补 0)| 8 |\r\n | hh | 12 小时制(2 位,补 0) | 08 |\r\n | h | 12 小时制(1 位,不补 0)| 8 |\r\n | mm | 2 位分钟(补 0) | 05 |\r\n | m | 1 位分钟(不补 0) | 5 |\r\n | ss | 2 位秒数(补 0) | 08 |\r\n | s | 1 位秒数(不补 0) | 8 |\r\n | SSS | 3 位毫秒(补 0) | 123 |\r\n | S | 1 位毫秒(不补 0) | 1 |\r\n | E | 周几(迷你名) | 一(zh) / Mon(en) |\r\n | EE | 周几(短名) | 周一(zh) / Mon(en) |\r\n | EEE | 周几(全名) | 星期一(zh) / Monday(en) |\r\n | Q | 季度(迷你名) | 1(zh) / 1(en) |\r\n | QQ | 季度(短名) | Q1(zh) / Q1(en) |\r\n | QQQ | 季度(全名) | 第一季度(zh) / Quarter 1(en)|\r\n | a | 上午 / 下午(小写) | am /pm |\r\n | A | 上午 / 下午(大写) | AM / PM |\r\n | aa | 上午 / 下午(中文) | 上午 / 下午 |\r\n | AA | 上午 / 下午(中文大写) | 上午 / 下午 |\r\n @example\r\n yyyy-MM-dd HH:mm:ss → 2025-01-05 08:05:08\r\n yyyy-M-d h:m:s → 2025-1-5 8:5:8\r\n yyyy-MM-dd EE → 2025-01-05 周一\r\n @param lang 语言,可选值:zh(默认)/ en\r\n */\r\nexport interface DateOptions {\r\n format?: string; // 日期格式\r\n lang?: string; // 语言,默认 zh\r\n}\r\n\r\n/* 快捷日期 */\r\n/**\r\n * 今天\r\n *@returns {string} 返回日期字符串\r\n */\r\nexport function today(): string {\r\n return getDate();\r\n}\r\n\r\n/**\r\n * 昨天\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function yesterday(): string {\r\n return toDateString(addDate(new Date(), -1));\r\n}\r\n\r\n/**\r\n * 明天\r\n *@returns {string} 返回日期字符串\r\n */\r\nexport function tomorrow(): string {\r\n return toDateString(addDate(new Date(), +1));\r\n}\r\n\r\n/**\r\n * 上周(7天前日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function lastWeek(date = new Date()): string {\r\n return toDateString(addDate(date, -7));\r\n}\r\n\r\n/**\r\n * 下周(7天后日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function nextWeek(date = new Date()): string {\r\n return toDateString(addDate(date, +7));\r\n}\r\n\r\n/**\r\n * 上个月(30天前日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function lastMonth(date = new Date()): string {\r\n const newDate = addMonth(date, -1);\r\n // 处理跨月边界\r\n if (newDate.getMonth() === date.getMonth()) {\r\n newDate.setDate(0);\r\n }\r\n return toDateString(newDate);\r\n}\r\n\r\n/**\r\n * 下个月(30天后日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function nextMonth(date = new Date()): string {\r\n const newDate = addMonth(date, +1);\r\n // 处理跨月边界\r\n if (newDate.getMonth() === date.getMonth()) {\r\n newDate.setDate(0);\r\n }\r\n return toDateString(newDate);\r\n}\r\n\r\n/**\r\n * 上一年(365天前日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function lastYear(date = new Date()): string {\r\n const newDate = addYear(date, -1);\r\n // 处理跨年边界,闰年2月29日→平年2月28日\r\n if (newDate.getMonth() !== date.getMonth() || newDate.getDate() !== date.getDate()) {\r\n newDate.setDate(28);\r\n }\r\n return toDateString(newDate);\r\n}\r\n\r\n/**\r\n * 下一年(365天后日期)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function nextYear(date = new Date()): string {\r\n const newDate = addYear(date, +1);\r\n // 处理跨年边界,闰年2月29日→平年2月28日\r\n if (newDate.getMonth() !== date.getMonth() || newDate.getDate() !== date.getDate()) {\r\n newDate.setDate(28);\r\n }\r\n return toDateString(newDate);\r\n}\r\n\r\n/* 判断当前日期 */\r\n/**\r\n * 是否为上午\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isAM(date = new Date()): boolean {\r\n return date.getHours() < 12;\r\n}\r\n\r\n/**\r\n * 是否为下午\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isPM(date = new Date()): boolean {\r\n return date.getHours() >= 12;\r\n}\r\n\r\n/**\r\n * 是否为今天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isToday(date = new Date()): boolean {\r\n // 此刻日期\r\n const nowDate = new Date();\r\n // 判断日期\r\n return ([\"getFullYear\", \"getMonth\", \"getDate\"] as Array<\"getFullYear\" | \"getMonth\" | \"getDate\">).every(\r\n (item) => nowDate[item]() === date[item](),\r\n );\r\n}\r\n\r\n/**\r\n * 是否为昨天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isYesterday(date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const nowTime = Date.now();\r\n const diffTime = nowTime - startTime;\r\n const diffDay = parseInt(diffTime / (1000 * 60 * 60 * 24));\r\n return diffDay === 1;\r\n}\r\n\r\n/**\r\n * 是否为前天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBeforeYesterday(date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const nowTime = Date.now();\r\n const diffTime = nowTime - startTime;\r\n const diffDay = parseInt(diffTime / (1000 * 60 * 60 * 24));\r\n return diffDay === 2;\r\n}\r\n\r\n/**\r\n * 是否为明天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isTomorrow(date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const nowTime = Date.now();\r\n const diffTime = startTime - nowTime;\r\n const diffDay = parseInt(diffTime / (1000 * 60 * 60 * 24));\r\n return diffDay === 1;\r\n}\r\n\r\n/**\r\n * 是否为后天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isAfterTomorrow(date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const nowTime = Date.now();\r\n const time = startTime - nowTime;\r\n const diffDay = parseInt(time / (1000 * 60 * 60 * 24));\r\n return diffDay === 2;\r\n}\r\n\r\n/**\r\n * 是否为工作日\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isWorkday(date = new Date()): boolean {\r\n const dayOfWeek = getDayOfWeek(date);\r\n return dayOfWeek !== 6 && dayOfWeek !== 7;\r\n}\r\n\r\n/**\r\n * 是否为周末(周六和周日)\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isWeekend(date = new Date()): boolean {\r\n const dayOfWeek = getDayOfWeek(date);\r\n return dayOfWeek === 6 || dayOfWeek === 7;\r\n}\r\n\r\n/**\r\n * 是否为本周第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFirstDayOfWeek(date = new Date()): boolean {\r\n return getDayOfWeek(date) === 1;\r\n}\r\n\r\n/**\r\n * 是否为本周最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isLastDayOfWeek(date = new Date()): boolean {\r\n return getDayOfWeek(date) === 7;\r\n}\r\n\r\n/**\r\n * 是否为本月第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFirstDayOfMonth(date = new Date()): boolean {\r\n return getDayOfMonth(date) === 1;\r\n}\r\n\r\n/**\r\n * 是否为本月最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isLastDayOfMonth(date = new Date()): boolean {\r\n return getDayOfMonth(date) === getDaysOfMonth(date);\r\n}\r\n\r\n/**\r\n * 是否为本年第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isFirstDayOfYear(date = new Date()): boolean {\r\n return getDayOfYear(date) === 1;\r\n}\r\n\r\n/**\r\n * 是否为本年最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isLastDayOfYear(date = new Date()): boolean {\r\n return getDayOfYear(date) === getDaysOfYear(date);\r\n}\r\n\r\n/* 判断年 */\r\n/**\r\n * 是否为闰年\r\n * @description 闰年366天,平年365天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isLeapYear(date = new Date()): boolean {\r\n const year = date.getFullYear();\r\n return (year % 100 !== 0 && year % 4 === 0) || year % 400 === 0;\r\n}\r\n\r\n/**\r\n * 是否为平年\r\n * @description 闰年366天,平年365天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isCommonYear(date = new Date()): boolean {\r\n return !isLeapYear(date);\r\n}\r\n\r\n/* 比较日期区间 */\r\n/**\r\n * 是否在日期之前\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBefore(startDate: Date, endDate: Date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = startDate.getTime();\r\n const endTime = endDate.getTime();\r\n const diffTime = startTime - endTime;\r\n return diffTime < 0;\r\n}\r\n\r\n/**\r\n * 是否在日期之后\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期,默认当前日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isAfter(startDate: Date, endDate: Date = new Date()): boolean {\r\n // 计算时间差\r\n const startTime = startDate.getTime();\r\n const endTime = endDate.getTime();\r\n const diffTime = startTime - endTime;\r\n return diffTime > 0;\r\n}\r\n\r\n/**\r\n * 是否在两个日期之间\r\n * @param {Date} date 要比较的日期\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isBetween(date: Date, startDate: Date, endDate: Date): boolean {\r\n const time = date.getTime();\r\n const startTime = startDate.getTime();\r\n const endTime = endDate.getTime();\r\n return time > startTime && time < endTime;\r\n}\r\n\r\n/* 日期是否相同 */\r\n/**\r\n * 两个日期是否为同一天\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSame(startDate: Date, endDate: Date): boolean {\r\n return ([\"getFullYear\", \"getMonth\", \"getDate\"] as Array<\"getFullYear\" | \"getMonth\" | \"getDate\">).every(\r\n (item) => startDate[item]() === endDate[item](),\r\n );\r\n}\r\n\r\n/**\r\n * 两个日期是否为同一周\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameWeek(startDate: Date, endDate: Date): boolean {\r\n const diffDate1 = startDate.getTime() / (24 * 60 * 60 * 1000);\r\n const diffDate2 = endDate.getTime() / (24 * 60 * 60 * 1000);\r\n return parseInt((diffDate1 + 4) / 7) === parseInt((diffDate2 + 4) / 7);\r\n}\r\n\r\n/**\r\n * 两个日期是否为同一个月\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameMonth(startDate: Date, endDate: Date): boolean {\r\n return ([\"getFullYear\", \"getMonth\"] as Array<\"getFullYear\" | \"getMonth\">).every(\r\n (item) => startDate[item]() === endDate[item](),\r\n );\r\n}\r\n\r\n/**\r\n * 两个日期是否为同一年\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameYear(startDate: Date, endDate: Date): boolean {\r\n return ([\"getFullYear\"] as Array<\"getFullYear\">).every((item) => startDate[item]() === endDate[item]());\r\n}\r\n\r\n/* 比较两个日期相同 或 之前/之后 */\r\n/**\r\n * 两个日期是否相同或之前\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameOrBefore(startDate: Date, endDate: Date): boolean {\r\n return isSame(startDate, endDate) || isBefore(startDate, endDate);\r\n}\r\n\r\n/**\r\n * 两个日期是否相同或之后\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function isSameOrAfter(startDate: Date, endDate: Date): boolean {\r\n return isSame(startDate, endDate) || isAfter(startDate, endDate);\r\n}\r\n\r\n/* 获取 日期/时间戳/周/季度 */\r\n/**\r\n * 获得此刻的日期\r\n * @returns {Date} 返回日期\r\n */\r\nexport function getNow(): Date {\r\n return new Date();\r\n}\r\n\r\n/**\r\n * 获得当前日期字符串\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param options 配置项 配置项\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getDate(date: Date = new Date(), options: DateOptions = { format: \"yyyy-MM-dd\" }): string {\r\n const { format } = options;\r\n return toDateString(date, { format });\r\n}\r\n\r\n/**\r\n * 获得当前日期时间字符串\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param options 配置项 配置项\r\n * @returns {string} 返回日期时间字符串\r\n */\r\nexport function getDateTime(date: Date = new Date(), options: DateOptions = { format: \"yyyy-MM-dd HH:mm:ss\" }): string {\r\n const { format } = options;\r\n return toDateString(date, { format });\r\n}\r\n\r\n/**\r\n * 获取当前时间戳\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回时间戳\r\n */\r\nexport function getTimestamp(date: Date = new Date()): number {\r\n return date.getTime();\r\n}\r\n\r\n/**\r\n * 获取当前Unix时间戳\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回Unix时间戳\r\n */\r\nexport function getUnixTimestamp(date: Date = new Date()): number {\r\n return Math.round(date.getTime() / 1000);\r\n}\r\n\r\n/**\r\n * 获得当前日期的对象形式\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {Object} 返回日期的对象形式\r\n */\r\nexport function getDateObject(date: Date = new Date()): {\r\n year: number;\r\n month: number;\r\n date: number;\r\n hours: number;\r\n minutes: number;\r\n seconds: number;\r\n milliseconds: number;\r\n} {\r\n return {\r\n year: date.getFullYear(), // 年\r\n month: date.getMonth() + 1, // 月\r\n date: date.getDate(), // 日\r\n hours: date.getHours(), // 时\r\n minutes: date.getMinutes(), // 分\r\n seconds: date.getSeconds(), // 秒\r\n milliseconds: date.getMilliseconds(), // 毫秒\r\n };\r\n}\r\n\r\n/**\r\n * 获得当前日期的数组形式\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {Object} 返回日期的数组形式\r\n */\r\nexport function getDateArray(date: Date = new Date()): number[] {\r\n return Object.entries(getDateObject(date)).map(([key, value]) => value);\r\n}\r\n\r\n/**\r\n * 获得当前日期是周几\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param options 配置项\r\n * @returns {number|string} 返回周几,会根据语言返回\r\n */\r\nexport function getWeek(date: Date = new Date(), options: DateOptions = { format: \"E\", lang: \"zh\" }): number | string {\r\n const { format, lang = \"zh\" } = options;\r\n // 根据格式化和语言返回对应的周\r\n if (format === \"E\") {\r\n return DATE.WEEK[lang].MINI[date.getDay()];\r\n } else if (format === \"EE\") {\r\n return DATE.WEEK[lang].SHORT[date.getDay()];\r\n } else if (format === \"EEE\") {\r\n return DATE.WEEK[lang].FULL[date.getDay()];\r\n } else {\r\n return getDayOfWeek(date);\r\n }\r\n}\r\n\r\n/**\r\n * 获得当前日期是第几季度\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param options 配置项\r\n * @returns {number|string} 返回第几季度,会根据语言返回\r\n */\r\nexport function getQuarter(\r\n date: Date = new Date(),\r\n options: DateOptions = { format: \"Q\", lang: \"zh\" },\r\n): number | string {\r\n const { format, lang = \"zh\" } = options;\r\n // 根据格式化和语言返回对应的周\r\n const quarterNum = Number(Math.floor((date.getMonth() + 3) / 3));\r\n if (format === \"Q\") {\r\n return DATE.QUARTER[lang].MINI[quarterNum - 1];\r\n } else if (format === \"QQ\") {\r\n return DATE.QUARTER[lang].SHORT[quarterNum - 1];\r\n } else if (format === \"QQQ\") {\r\n return DATE.QUARTER[lang].FULL[quarterNum - 1];\r\n } else {\r\n return quarterNum;\r\n }\r\n}\r\n\r\n/* 当前日期是所在 周/月/年 的第几天 */\r\n/**\r\n * 获得当前日期是所在周的第几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number|string} 返回天数\r\n */\r\nexport function getDayOfWeek(date: Date = new Date()): number | string {\r\n return [7, 1, 2, 3, 4, 5, 6][date.getDay()];\r\n}\r\n\r\n/**\r\n * 获得当前日期是所在月的第几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDayOfMonth(date: Date = new Date()): number {\r\n return date.getDate();\r\n}\r\n\r\n/**\r\n * 获得当前日期是所在年的第几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDayOfYear(date: Date = new Date()): number {\r\n return Math.ceil((date.getTime() - new Date(date.getFullYear().toString()).getTime()) / (24 * 60 * 60 * 1000)) + 1;\r\n}\r\n\r\n/* 当前日期的周是所在 月/年 的第几周 */\r\n/**\r\n * 获得当前日期是所在月的第几周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回周数\r\n */\r\nexport function getWeekOfMonth(date: Date = new Date()): number {\r\n return Math.ceil((date.getDate() + 6 - Number(getDayOfWeek(date))) / 7);\r\n}\r\n\r\n/**\r\n * 获得当前日期是所在年的第几周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回周数\r\n */\r\nexport function getWeekOfYear(date: Date = new Date()): number {\r\n const startDate = new Date(date.getFullYear(), 0, 1);\r\n const startDay = getDayOfWeek(startDate);\r\n const diff = Math.round((date.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000));\r\n return Math.ceil((diff + Number(startDay)) / 7);\r\n}\r\n\r\n/* 当前日期所在 周/月/年 共几天 */\r\n/**\r\n * 获得当前日期所在的周共几天\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDaysOfWeek(): number {\r\n return 7;\r\n}\r\n\r\n/**\r\n * 获得当前日期所在的月共几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDaysOfMonth(date: Date = new Date()): number {\r\n return new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();\r\n}\r\n\r\n/**\r\n * 获得当前日期所在的年共几天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回天数\r\n */\r\nexport function getDaysOfYear(date: Date = new Date()): number {\r\n return isLeapYear(date) ? 366 : 365;\r\n}\r\n\r\n/* 当前周所在 月/年 共几周 */\r\n/**\r\n * 获得当前日期是所在月的第几周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回周数\r\n */\r\nexport function getWeeksOfMonth(date: Date = new Date()): number {\r\n const startDate = new Date(date.getFullYear(), 0, 1);\r\n const startDay = Number(getDayOfWeek(startDate));\r\n const fullDays = isLeapYear(date) ? 366 : 365;\r\n if (startDay === 1) {\r\n return Math.ceil(fullDays / 7);\r\n } else {\r\n return Math.ceil((fullDays - 7 + startDay) / 7);\r\n }\r\n}\r\n\r\n/**\r\n * 获得当前日期是所在年的第几周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {number} 返回周数\r\n */\r\nexport function getWeeksOfYear(date: Date = new Date()): number {\r\n const startDate = new Date(date.getFullYear(), 0, 1);\r\n const startDay = Number(getDayOfWeek(startDate));\r\n const fullDays = isLeapYear(date) ? 366 : 365;\r\n if (startDay === 1) {\r\n return Math.ceil(fullDays / 7);\r\n } else {\r\n return Math.ceil((fullDays - 7 + startDay) / 7);\r\n }\r\n}\r\n\r\n/* 当前日期所在 周/月/年 的 第一天/最后一天/所有天数数组 */\r\n/**\r\n * 获得当前日期所在周的第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getFirstDateOfWeek(date: Date = new Date()): string {\r\n const weekDay = Number(getDayOfWeek(date));\r\n date.setDate(date.getDate() - weekDay + 1);\r\n return toDateString(date);\r\n}\r\n\r\n/**\r\n * 获得当前日期所在周的最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getLastDateOfWeek(date: Date = new Date()): string {\r\n const weekDay = Number(getDayOfWeek(date));\r\n date.setDate(date.getDate() + (7 - weekDay));\r\n return toDateString(date);\r\n}\r\n\r\n/**\r\n * 获取当前日期所在周的所有日期\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string[]} 返回日期数组\r\n */\r\nexport function getFullDateOfWeek(date: Date = new Date()): string[] {\r\n const array = [];\r\n // 获得当前日期是本周几\r\n const dayOfWeek = date.getDay();\r\n // 根据当前日期获取本周一\r\n const firstDateOfWeek = new Date();\r\n firstDateOfWeek.setDate(date.getDate() - (dayOfWeek === 0 ? 6 : dayOfWeek - 1));\r\n\r\n // 遍历本周日期\r\n for (let i = 0; i < 7; i++) {\r\n const currentDate = new Date(firstDateOfWeek);\r\n currentDate.setDate(currentDate.getDate() + i);\r\n array.push(toDateString(currentDate));\r\n }\r\n\r\n return array;\r\n}\r\n\r\n/**\r\n * 获得当前日期所在月的第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getFirstDateOfMonth(date: Date = new Date()): string {\r\n date.setDate(1);\r\n return toDateString(date);\r\n}\r\n\r\n/**\r\n * 获得当前日期所在月的最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getLastDateOfMonth(date: Date = new Date()): string {\r\n return toDateString(new Date(date.getFullYear(), date.getMonth() + 1, 0));\r\n}\r\n\r\n/**\r\n * 获取当前日期所在月的所有日期\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string[]} 返回日期数组\r\n */\r\nexport function getFullDateOfMonth(date: Date = new Date()): string[] {\r\n const array = [];\r\n // 获得本月第一天\r\n const firstDateOfMonth = new Date(date.getFullYear(), date.getMonth(), 1);\r\n // 获得本月最后一天\r\n const lastDateOfMonth = new Date(date.getFullYear(), date.getMonth() + 1, 0);\r\n // 遍历本月日期\r\n for (let i = 0; i < lastDateOfMonth.getDate(); i++) {\r\n const currentDate = new Date(firstDateOfMonth);\r\n currentDate.setDate(firstDateOfMonth.getDate() + i);\r\n array.push(toDateString(currentDate));\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 获取当前日期所在年的第一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getFirstDateOfYear(date: Date = new Date()): string {\r\n return toDateString(new Date(date.getFullYear(), 0, 1));\r\n}\r\n\r\n/**\r\n * 获取当前日期所在年的最后一天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getLastDateOfYear(date: Date = new Date()): string {\r\n return toDateString(new Date(date.getFullYear(), 11, 31));\r\n}\r\n\r\n/**\r\n * 获取当前日期所在年的所有日期\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function getFullDateOfYear(date: Date = new Date()): string[] {\r\n const array = [];\r\n // 获得本年第一天\r\n const firstDateOfYear = new Date(date.getFullYear(), 0, 1);\r\n // 获得本年一共多少天\r\n const daysOfYear = getDaysOfYear();\r\n // 遍历本年日期\r\n for (let i = 0; i < daysOfYear; i++) {\r\n const currentDate = new Date(firstDateOfYear);\r\n currentDate.setDate(firstDateOfYear.getDate() + i);\r\n array.push(toDateString(currentDate));\r\n }\r\n return array;\r\n}\r\n\r\n/* 计算两个日期相差 */\r\n/**\r\n * 计算两个日期相差的天数,不满一天为0\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {number} 返回两个日期相差的天数,结果为正数或者负数\r\n */\r\nexport function getDiffDay(startDate: Date, endDate: Date): number {\r\n if (isNull(startDate) || isNull(endDate)) return 0;\r\n const diff = (endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000);\r\n\r\n // 返回\r\n return diff >= 0 ? Math.abs(diff) : diff;\r\n}\r\n\r\n/**\r\n * 计算两个日期相差的周数,不满一周为0\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {number} 返回两个日期相差的周数,结果为正数或者负数\r\n */\r\nexport function getDiffWeek(startDate: Date, endDate: Date): number {\r\n if (isNull(startDate) || isNull(endDate)) return 0;\r\n const diff = (endDate.getTime() - startDate.getTime()) / (7 * 24 * 60 * 60 * 1000);\r\n\r\n // 返回\r\n return diff >= 0 ? Math.abs(diff) : diff;\r\n}\r\n\r\n/**\r\n * 计算两个日期相差的月数,不满一月为0\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {number} 返回两个日期相差的月数,结果为正数或者负数\r\n */\r\nexport function getDiffMonth(startDate: Date, endDate: Date): number {\r\n if (isNull(startDate) || isNull(endDate)) return 0;\r\n const diff = (startDate.getTime() - endDate.getTime()) / (30 * 24 * 60 * 60 * 1000);\r\n\r\n // 返回\r\n return diff >= 0 ? Math.abs(diff) : diff;\r\n}\r\n\r\n/**\r\n * 计算两个日期相差的年数,不满一年为0\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {number} 返回两个日期相差的年数,结果为正数或者负数\r\n */\r\nexport function getDiffYear(startDate: Date, endDate: Date): number {\r\n if (isNull(startDate) || isNull(endDate)) return 0;\r\n const diff = (endDate.getTime() - startDate.getTime()) / (12 * 30 * 24 * 60 * 60 * 1000);\r\n\r\n // 返回\r\n return diff >= 0 ? Math.abs(diff) : diff;\r\n}\r\n\r\n/* 获得两个日期之间 年月日/年月/年 数组 */\r\n/**\r\n * 获得两个日期之间的年月日数组\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {Array} 返回年月日数组\r\n */\r\nexport function getBetweenDates(startDate: Date, endDate: Date): string[] {\r\n if (isNull(startDate) || isNull(endDate)) return [];\r\n\r\n // 计算\r\n const array = [];\r\n while (endDate.getTime() - startDate.getTime() >= 0) {\r\n const year = startDate.getFullYear(),\r\n month = _datePadZero(startDate.getMonth() + 1),\r\n day = _datePadZero(startDate.getDate());\r\n\r\n // 加入数组\r\n array.push(year + \"-\" + month + \"-\" + day);\r\n // 更新日期\r\n startDate.setDate(startDate.getDate() + 1);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 获得两个日期之间的年月数组\r\n * @description 支持:日期字符串,日期对象,时间戳,Unix时间戳\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {Array} 返回年月数组\r\n */\r\nexport function getBetweenMonths(startDate: Date, endDate: Date): string[] {\r\n if (isNull(startDate) || isNull(endDate)) return [];\r\n\r\n // 计算\r\n const array = [];\r\n // 获取时间对象\r\n const min = new Date();\r\n const max = new Date();\r\n // 设置起始时间\r\n min.setFullYear(startDate.getFullYear(), startDate.getMonth() + 1);\r\n // 设置结束时间\r\n max.setFullYear(endDate.getFullYear(), endDate.getMonth() + 1);\r\n\r\n // 复制一份起始时间对象\r\n const curr = min;\r\n // 定义字符串\r\n let str = \"\";\r\n // 起始时间在结束时间之前\r\n while (curr <= max) {\r\n // 获取此时间的月份\r\n const month = curr.getMonth();\r\n // 如果月份为0,也就是代表12月份\r\n if (month === 0) {\r\n str = curr.getFullYear() - 1 + \"-\" + 12;\r\n } else {\r\n // 正常月份\r\n str = curr.getFullYear() + \"-\" + _datePadZero(month);\r\n }\r\n // 将此年月加入数组\r\n array.push(str);\r\n // 更新此时间月份\r\n curr.setMonth(month + 1);\r\n }\r\n return array;\r\n}\r\n\r\n/**\r\n * 获得两个日期之间的年数组\r\n * @param {Date} startDate 开始日期\r\n * @param {Date} endDate 结束日期\r\n * @returns {Array} 返回年数组\r\n */\r\nexport function getBetweenYears(startDate: Date, endDate: Date): number[] {\r\n if (isNull(startDate) || isNull(endDate)) return [];\r\n\r\n // 计算\r\n const array = [];\r\n while (endDate.getTime() - startDate.getTime() >= 0) {\r\n const year = startDate.getFullYear();\r\n\r\n // 加入数组\r\n array.push(year);\r\n // 更新日期\r\n startDate.setFullYear(startDate.getFullYear() + 1);\r\n }\r\n return array;\r\n}\r\n\r\n/* 过去时间和剩余时间的显示 */\r\n/**\r\n * 获得过去时间的字符串显示\r\n * @description 例如:刚刚,1分钟前,1小时前等\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回字符串\r\n */\r\nexport function getPastTime(date: Date, options: DateOptions = { lang: \"zh\" }): string {\r\n const { lang = \"zh\" } = options;\r\n if (isNull(date)) return \"--\";\r\n // 计算时间差\r\n const startTime = date.getTime();\r\n const currentTime = Date.now();\r\n const time = currentTime - startTime;\r\n // 年月日时分\r\n const year = parseInt(time / (1000 * 60 * 60 * 24 * 30 * 12));\r\n const month = parseInt(time / (1000 * 60 * 60 * 24 * 30));\r\n const day = parseInt(time / (1000 * 60 * 60 * 24));\r\n const hour = parseInt(time / (1000 * 60 * 60));\r\n const min = parseInt(time / (1000 * 60));\r\n\r\n // 返回结果\r\n if (year) {\r\n return year + DATE.PASS_TIME[lang].YEAR;\r\n } else if (month) {\r\n return month + DATE.PASS_TIME[lang].MONTH;\r\n } else if (day) {\r\n if (day === 1) {\r\n return DATE.PASS_TIME[lang].YESTERDAY;\r\n } else if (day === 2) {\r\n return DATE.PASS_TIME[lang].BEFORE_YESTERDAY;\r\n } else {\r\n return day + DATE.PASS_TIME[lang].DAY;\r\n }\r\n } else if (hour) {\r\n if (hour > 12) {\r\n return DATE.PASS_TIME[lang].TODAY;\r\n } else {\r\n return hour + DATE.PASS_TIME[lang].HOUR;\r\n }\r\n } else if (min) {\r\n return min + DATE.PASS_TIME[lang].MINUTE;\r\n } else {\r\n return DATE.PASS_TIME[lang].JUST;\r\n }\r\n}\r\n\r\n/**\r\n * 获得剩余时间的字符串显示\r\n * @description 例如:1天10小时20分钟30秒\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回字符串\r\n */\r\nexport function getOverTime(date: Date, options: DateOptions = { lang: \"zh\" }): string {\r\n const { lang = \"zh\" } = options;\r\n if (isNull(date)) return \"--\";\r\n\r\n // 计算\r\n const startDate = new Date(); // 开始时间\r\n const t = date.getTime() - startDate.getTime(); // 时间差\r\n let d = 0,\r\n h = 0,\r\n m = 0,\r\n s = 0;\r\n if (t >= 0) {\r\n d = Math.floor(t / 1000 / 3600 / 24);\r\n h = Math.floor((t / 1000 / 60 / 60) % 24);\r\n m = Math.floor((t / 1000 / 60) % 60);\r\n s = Math.floor((t / 1000) % 60);\r\n }\r\n return `${d}${DATE.OVER_TIME[lang].DAY} ${h}${DATE.OVER_TIME[lang].HOUR} ${m}${DATE.OVER_TIME[lang].MINUTE} ${s}${DATE.OVER_TIME[lang].SECOND}`;\r\n}\r\n\r\n/* 通过日期获得 年龄、星座和生肖 */\r\n\r\n/**\r\n * 通过日期获得年龄\r\n * @param {Date} date 日期参数\r\n * @returns {number} 返回周岁年龄\r\n */\r\nexport function getAge(date: Date): number {\r\n let age = 0;\r\n // 传参日期\r\n const dateArray = toDateString(date).split(\"-\");\r\n const birthYear = Number(dateArray[0]);\r\n const birthMonth = Number(dateArray[1]);\r\n const birthDay = Number(dateArray[2]);\r\n // 当前的日期\r\n const nowDate = new Date();\r\n const nowYear = nowDate.getFullYear(),\r\n nowMonth = nowDate.getMonth() + 1,\r\n nowDay = nowDate.getDate();\r\n\r\n // 出生年份需要小于当年,否则是0岁\r\n const diffAge = nowYear - birthYear;\r\n if (diffAge > 0) {\r\n const diffMonth = nowMonth - birthMonth;\r\n const diffDay = nowDay - birthDay;\r\n if (diffMonth === 0) {\r\n if (diffDay < 0) {\r\n age = diffAge - 1;\r\n } else {\r\n age = diffAge;\r\n }\r\n } else {\r\n if (diffMonth < 0) {\r\n age = diffAge - 1;\r\n } else {\r\n age = diffAge;\r\n }\r\n }\r\n }\r\n\r\n // 返回周岁年龄\r\n return age;\r\n}\r\n\r\n/**\r\n * 通过日期获得星座\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回星座\r\n */\r\nexport function getZodiac(date: Date, options: DateOptions = { lang: \"zh\" }): string {\r\n const { lang = \"zh\" } = options;\r\n if (isNull(date)) return \"\";\r\n\r\n // 计算\r\n const days = [20, 19, 21, 20, 21, 22, 23, 23, 23, 24, 23, 22];\r\n const month = date.getMonth() + 1;\r\n const day = date.getDate();\r\n return day < days[month - 1] ? DATE.ZODIAC[lang][month - 1] : DATE.ZODIAC[lang][month];\r\n}\r\n\r\n/**\r\n * 通过日期获得生肖\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回生肖\r\n */\r\nexport function getChineseZodiac(date: Date, options: DateOptions = { lang: \"zh\" }): string {\r\n const { lang = \"zh\" } = options;\r\n if (isNull(date)) return \"\";\r\n\r\n // 计算\r\n const year = date.getFullYear();\r\n if (year < 1900) {\r\n return \"未知\";\r\n }\r\n return DATE.CHINESE_ZODIAC[lang][(year - 1900) % DATE.CHINESE_ZODIAC[lang].length];\r\n}\r\n\r\n/* 计算日期加减 年,月,日,时,分,秒,周,季度 */\r\n/**\r\n * 日期加减年\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addYear(date: Date = new Date(), num: number = +1): Date {\r\n date.setFullYear(date.getFullYear() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减月\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addMonth(date: Date = new Date(), num: number = +1): Date {\r\n date.setMonth(date.getMonth() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减天\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addDate(date: Date = new Date(), num: number = +1): Date {\r\n date.setDate(date.getDate() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减小时\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addHours(date: Date = new Date(), num: number = +1): Date {\r\n date.setHours(date.getHours() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减分钟\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addMinutes(date: Date = new Date(), num: number = +1): Date {\r\n date.setMinutes(date.getMinutes() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减秒\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addSeconds(date: Date = new Date(), num: number = +1): Date {\r\n date.setSeconds(date.getSeconds() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减毫秒\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+100\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addMillisecond(date: Date = new Date(), num: number = +100): Date {\r\n date.setMilliseconds(date.getMilliseconds() + num);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减周\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addWeek(date: Date = new Date(), num: number = +1): Date {\r\n date.setDate(date.getDate() + num * 7);\r\n return date;\r\n}\r\n\r\n/**\r\n * 日期加减季度\r\n * @param {Date} date 日期参数,默认当前日期\r\n * @param {number} num 加减数量,用正数和负数表示;默认+1\r\n * @returns {Date} 返回加减后的日期\r\n */\r\nexport function addQuarter(date: Date = new Date(), num: number = +1): Date {\r\n date.setMonth(date.getMonth() + num * 4);\r\n return date;\r\n}\r\n\r\n/* 格式化和解析日期 */\r\n\r\n/**\r\n * UTC 日期对象转本地时区日期对象\r\n * @description 将 UTC 时间的 Date 对象转换为本地时间的 Date 对象(时间戳不变,仅调整时区偏移)\r\n * @param {Date} date UTC 日期对象,默认当前 UTC 时间\r\n * @returns {Date} 本地时区日期对象(时间戳 = UTC时间戳 + 时区偏移毫秒数)\r\n * @example\r\n * // UTC时间:2025-01-26 00:00:00\r\n * const utcDate = new Date('2025-01-26T00:00:00Z');\r\n * const localDate = fromDateUTC(utcDate);\r\n * console.log(toDateString(localDate)); // 2025-01-26 08:00:00(北京本地时间)\r\n */\r\nexport function fromDateUTC(date: Date = new Date()): Date {\r\n return new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000);\r\n}\r\n\r\n/**\r\n * 本地时区日期转 UTC 日期对象\r\n * @description 将本地时间的 Date 对象转换为 UTC 时间的 Date 对象(时间戳不变,仅调整时区偏移)\r\n * @param {Date} date 本地日期对象,默认当前本地时间\r\n * @returns {Date} UTC 日期对象(时间戳 = 本地时间戳 - 时区偏移毫秒数)\r\n * @example\r\n * // 北京本地时间:2025-01-26 08:00:00(东8区)\r\n * const localDate = new Date('2025-01-26 08:00:00');\r\n * const utcDate = toDateUTC(localDate);\r\n * console.log(utcDate.toISOString()); // 2025-01-26T00:00:00.000Z(UTC时间)\r\n */\r\nexport function toDateUTC(date: Date = new Date()): Date {\r\n return new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000);\r\n}\r\n\r\n/**\r\n * 格式化日期为 UTC 字符串(符合 ISO 8601 标准)\r\n * @description 直接输出 UTC 时间的字符串,无需手动转换时区\r\n * @param {Date} date 本地日期对象,默认当前本地时间\r\n * @param {DateOptions} options 格式化配置,默认 yyyy-MM-dd HH:mm:ss\r\n * @returns {string} UTC 日期字符串\r\n * @example\r\n * const localDate = new Date('2025-01-26 08:00:00');\r\n * console.log(toUTCString(localDate)); // 2025-01-26 00:00:00\r\n */\r\nexport function toDateUTCString(date = new Date(), options: DateOptions = { format: \"yyyy-MM-dd HH:mm:ss\" }): string {\r\n const utcDate = toDateUTC(date);\r\n return toDateString(utcDate, options);\r\n}\r\n\r\n/**\r\n * 日期字符串转为日期对象\r\n * @description 支持日期字符串,时间戳,Unix时间戳\r\n * @param {string|number} value 日期参数\r\n * @returns {Date} 返回日期对象\r\n */\r\nexport function toDate(value: string | number): Date {\r\n // 为空抛出异常\r\n if (isNull(value)) {\r\n throw new TypeError(\"toDate: value cannot be null or undefined\");\r\n }\r\n\r\n // 是日期字符串\r\n if (isString(value)) {\r\n return new Date(String(value).replace(/-/g, \"/\"));\r\n }\r\n // 是时间戳\r\n else if (isInteger(value) && String(value).length === 13) {\r\n return new Date(value);\r\n }\r\n // 是unix时间戳\r\n else if (isInteger(value) && String(value).length === 10) {\r\n return new Date(Number(value) * 1000);\r\n }\r\n // 不支持的日期格式\r\n else {\r\n throw new TypeError(`toDate: invalid input type: ${typeof value}, expected string or number`);\r\n }\r\n}\r\n\r\n/**\r\n * 日期对象转为日期字符串\r\n * @description 支持日期字符串,日期对象,时间戳,unix时间戳\r\n * @param {Date} date 日期参数\r\n * @param options 配置项\r\n * @returns {string} 返回日期字符串\r\n */\r\nexport function toDateString(date: Date, options: DateOptions = { format: \"yyyy-MM-dd\", lang: \"zh\" }): string {\r\n const { format = \"yyyy-MM-dd\", lang = \"zh\" } = options;\r\n // 为空抛出异常\r\n if (isNull(date)) {\r\n throw new TypeError(\"toDateString: date cannot be null or undefined\");\r\n }\r\n\r\n // 判断是否是日期对象\r\n if (!isDate(date)) {\r\n throw new TypeError(`toDateString: invalid input type: ${typeof date}, expected Date object`);\r\n }\r\n\r\n // 日期转化替换\r\n const replaceRules: Record<string, (match: string) => string> = {\r\n // 年(yyyy/yy)\r\n \"(y+)\": (match) => {\r\n const year = date.getFullYear().toString();\r\n return match.length === 2 ? year.slice(-2) : year;\r\n },\r\n // 月(M/MM)\r\n \"(M+)\": (match) => {\r\n const month = date.getMonth() + 1;\r\n return match.length === 1 ? month.toString() : _datePadZero(month);\r\n },\r\n // 日(d/dd)\r\n \"(d+)\": (match) => {\r\n const day = date.getDate();\r\n return match.length === 1 ? day.toString() : _datePadZero(day);\r\n },\r\n // 12小时制(h/hh)\r\n \"(h+)\": (match) => {\r\n const hour = date.getHours() % 12 || 12;\r\n return match.length === 1 ? hour.toString() : _datePadZero(hour);\r\n },\r\n // 24小时制(H/HH)\r\n \"(H+)\": (match) => {\r\n const hour = date.getHours();\r\n return match.length === 1 ? hour.toString() : _datePadZero(hour);\r\n },\r\n // 分钟(m/mm)\r\n \"(m+)\": (match) => {\r\n const min = date.getMinutes();\r\n return match.length === 1 ? min.toString() : _datePadZero(min);\r\n },\r\n // 秒(s/ss)\r\n \"(s+)\": (match) => {\r\n const sec = date.getSeconds();\r\n return match.length === 1 ? sec.toString() : _datePadZero(sec);\r\n },\r\n // 毫秒(S/SS/SSS)\r\n \"(S+)\": (match) => {\r\n const ms = date.getMilliseconds();\r\n return ms.toString().padStart(match.length, \"0\").slice(0, match.length);\r\n },\r\n // 上午/下午(a/A/aa/AA)\r\n \"([aA]+)\": (match) => {\r\n const isAm = date.getHours() < 12;\r\n // 多语言处理\r\n if (match.length > 1) {\r\n return isAm ? DATE.AM_PM[lang].AM : DATE.AM_PM[lang].PM;\r\n } else {\r\n return isAm ? match.toLowerCase() : match.toUpperCase();\r\n }\r\n },\r\n // 周(E/EE/EEE)\r\n \"(E+)\": (match) => {\r\n const day = date.getDay();\r\n if (match.length === 1) return DATE.WEEK[lang].MINI[day];\r\n if (match.length === 2) return DATE.WEEK[lang].SHORT[day];\r\n return DATE.WEEK[lang].FULL[day];\r\n },\r\n // 季度(Q/QQ/QQQ)\r\n \"(Q+)\": (match) => {\r\n const quarter = Math.floor((date.getMonth() + 3) / 3) - 1;\r\n if (match.length === 1) return DATE.QUARTER[lang].MINI[quarter];\r\n if (match.length === 2) return DATE.QUARTER[lang].SHORT[quarter];\r\n return DATE.QUARTER[lang].FULL[quarter];\r\n },\r\n };\r\n\r\n // 批量替换格式\r\n let result = format;\r\n Object.entries(replaceRules).forEach(([regStr, replaceFn]) => {\r\n const reg = new RegExp(regStr, \"g\");\r\n result = result.replace(reg, (_, match) => replaceFn(match));\r\n });\r\n\r\n return result;\r\n}\r\n\r\n/* 内部使用的函数 */\r\n/**\r\n * 单个日期数字前自动补齐零为两位\r\n * @param {string|number} value 值\r\n * @returns {string} 返回处理后的字符串\r\n */\r\nfunction _datePadZero(value: string | number): string {\r\n const num = Number(value);\r\n // 数字>9直接转字符串,否则补0\r\n return num > 9 ? String(num) : \"0\" + num;\r\n}\r\n","/**\r\n * @module 数学\r\n */\r\nimport { isNaN } from \"@/validate\";\r\nimport { MATH } from \"@/constants/index.ts\";\r\n\r\n/* 数字计算 */\r\n/**\r\n * 两个数字相加\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function add(arg1: string | number, arg2: string | number): number {\r\n let r1, r2;\r\n try {\r\n r1 = arg1.toString().split(\".\")[1].length;\r\n } catch (e) {\r\n r1 = 0;\r\n }\r\n try {\r\n r2 = arg2.toString().split(\".\")[1].length;\r\n } catch (e) {\r\n r2 = 0;\r\n }\r\n const m = Math.pow(10, Math.max(r1, r2));\r\n return (Number(arg1) * m + Number(arg2) * m) / m;\r\n}\r\n\r\n/**\r\n * 两个数字相减\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function subtract(arg1: string | number, arg2: string | number): number {\r\n let r1, r2;\r\n try {\r\n r1 = arg1.toString().split(\".\")[1].length;\r\n } catch (e) {\r\n r1 = 0;\r\n }\r\n try {\r\n r2 = arg2.toString().split(\".\")[1].length;\r\n } catch (e) {\r\n r2 = 0;\r\n }\r\n const m = Math.pow(10, Math.max(r1, r2));\r\n const n = r1 >= r2 ? r1 : r2;\r\n return Number(((Number(arg1) * m - Number(arg2) * m) / m).toFixed(n));\r\n}\r\n\r\n/**\r\n * 两个数字相乘\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function multiply(arg1: string | number, arg2: string | number): number {\r\n let m = 0;\r\n const s1 = arg1.toString();\r\n const s2 = arg2.toString();\r\n try {\r\n m += s1.split(\".\")[1].length;\r\n } catch (e) {}\r\n try {\r\n m += s2.split(\".\")[1].length;\r\n } catch (e) {}\r\n return (Number(s1.replace(\".\", \"\")) * Number(s2.replace(\".\", \"\"))) / Math.pow(10, m);\r\n}\r\n\r\n/**\r\n * 两个数字相除\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function divide(arg1: string | number, arg2: string | number): number {\r\n let t1 = 0,\r\n t2 = 0;\r\n try {\r\n t1 = arg1.toString().split(\".\")[1].length;\r\n } catch (e) {}\r\n try {\r\n t2 = arg2.toString().split(\".\")[1].length;\r\n } catch (e) {}\r\n const r1 = Number(arg1.toString().replace(\".\", \"\"));\r\n const r2 = Number(arg2.toString().replace(\".\", \"\"));\r\n return (r1 / r2) * Math.pow(10, t2 - t1);\r\n}\r\n\r\n/**\r\n * 两个数字取模\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function modulo(arg1: string | number, arg2: string | number): number {\r\n let t1 = 0,\r\n t2 = 0,\r\n d = 0;\r\n try {\r\n t1 = arg1.toString().split(\".\")[1].length;\r\n } catch (e) {}\r\n try {\r\n t2 = arg2.toString().split(\".\")[1].length;\r\n } catch (e) {}\r\n d = Math.pow(10, Math.max(t1, t2));\r\n return (Math.round(Number(arg1) * d) % Math.round(Number(arg2) * d)) / d;\r\n}\r\n\r\n/**\r\n * 最大公约数\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function gcd(arg1: string | number, arg2: string | number): number {\r\n let a = Math.abs(Number(arg1));\r\n let b = Math.abs(Number(arg2));\r\n while (b !== 0) {\r\n const temp = b;\r\n b = a % b;\r\n a = temp;\r\n }\r\n return a;\r\n}\r\n\r\n/**\r\n * 最小公倍数\r\n * @param {string|number} arg1 第一个数字\r\n * @param {string|number} arg2 第二个数字\r\n * @returns {number} 返回计算后的数字\r\n */\r\nexport function scm(arg1: string | number, arg2: string | number): number {\r\n const a = Number(arg1);\r\n const b = Number(arg2);\r\n const absA = Math.abs(a);\r\n const absB = Math.abs(b);\r\n if (absA === 0 || absB === 0) {\r\n return 0;\r\n }\r\n return (absA * absB) / gcd(absA, absB);\r\n}\r\n\r\n/* 数字精度 */\r\n/**\r\n * 强制保留小数位数\r\n * @description 默认保留两位小数,解决原生的toFixed()会五舍六入的问题\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @param {number} mode 保留小数模式\r\n * @returns {string} 返回保留后的数字字符串\r\n */\r\nexport function toFixed(num: string | number, decimals: number = 2, mode: number = MATH.ROUND): string {\r\n // 四舍五入\r\n if (mode === MATH.ROUND) {\r\n return _toFixedRound(num, decimals);\r\n }\r\n // 向下舍出\r\n else if (mode === MATH.ROUND_FLOOR) {\r\n return _toFixedFloor(num, decimals);\r\n } else {\r\n throw new TypeError(\"toFixed: mode is MATH.ROUND 0 or MATH.ROUND_FLOOR\");\r\n }\r\n}\r\n\r\n/**\r\n * 尽可能保留小数位数\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @param {number} mode 保留小数模式\r\n * @returns {number} 返回保留后的数字\r\n */\r\nexport function toDecimal(num: string | number, decimals: number = 2, mode: number = MATH.ROUND): number {\r\n // 四舍五入\r\n if (mode === MATH.ROUND) {\r\n return Number(_toDecimalRound(num, decimals));\r\n }\r\n // 向下舍出\r\n else if (mode === MATH.ROUND_FLOOR) {\r\n return Number(_toDecimalFloor(num, decimals));\r\n }\r\n // 错误保留格式\r\n else {\r\n throw new TypeError(\"toDecimal: mode is MATH.ROUND 0 or MATH.ROUND_FLOOR\");\r\n }\r\n}\r\n\r\n/* 内部函数 */\r\n/**\r\n * 四舍五入,强制保留小数位数\r\n * @description 默认保留两位小数,此方法解决原生的toFixed()会五舍六入的问题\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @returns {string} 返回字符串的数字\r\n */\r\nfunction _toFixedRound(num: string | number, decimals: number = 2): string {\r\n if (isNaN(Number(num))) {\r\n // num可能是字符串,先转数字再判断NaN\r\n return \"--\";\r\n }\r\n let s = String(num);\r\n if (!decimals) decimals = 0;\r\n if (s.indexOf(\".\") === -1) s += \".\";\r\n s += new Array(decimals + 1).join(\"0\");\r\n // 正则模板字符串拼接,避免手动拼接字符串的转义问题\r\n const reg = new RegExp(`^(-|\\\\+)?(\\\\d+(\\\\.\\\\d{0,${decimals + 1}})?)\\\\d*$`);\r\n if (reg.test(s)) {\r\n let s1 = \"0\" + RegExp.$2,\r\n b = true;\r\n // 1. 把外层的数字变量 a 改名,避免和内层数组冲突\r\n const decimalLength = RegExp.$3.length;\r\n const pm = RegExp.$1;\r\n\r\n if (decimalLength === decimals + 2) {\r\n // 2. 内层数组用新变量名 digitArr,明确类型为 string[]\r\n const digitArr = s1.match(/\\d/g) as string[];\r\n if (parseInt(digitArr[digitArr.length - 1]) > 4) {\r\n for (let i = digitArr.length - 2; i >= 0; i--) {\r\n // 3. 确保赋值为字符串类型\r\n digitArr[i] = (parseInt(digitArr[i]) + 1).toString();\r\n if (digitArr[i] === \"10\") {\r\n digitArr[i] = \"0\";\r\n b = i !== 1;\r\n } else break;\r\n }\r\n }\r\n s1 = digitArr.join(\"\").replace(new RegExp(`(\\\\d+)(\\\\d{${decimals}})\\\\d$`), \"$1.$2\");\r\n }\r\n if (b) s1 = s1.substr(1);\r\n return (pm + s1).replace(/\\.$/, \"\");\r\n }\r\n return String(num);\r\n}\r\n\r\n/**\r\n * 向下舍出,强制保留小数位数\r\n * @description 默认保留两位小数,此方法相当于强制截取小数位数\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @returns {string} 返回字符串的数字\r\n */\r\nfunction _toFixedFloor(num: string | number, decimals: number = 2): string {\r\n // num可能是字符串,先转数字再判断NaN\r\n const numVal = Number(num);\r\n if (isNaN(numVal)) {\r\n throw new TypeError(`${num} is NaN`);\r\n }\r\n // 校验小数位数范围\r\n if (decimals < 0 || decimals > 20) {\r\n throw new TypeError(\"_toFixedFloor: decimals places must be between 0 and 20\");\r\n }\r\n\r\n // 默认为保留的小数点后两位\r\n const dec = Math.max(0, Math.floor(decimals)); // 确保小数位数为非负整数\r\n const tempNumStr = String(numVal); // 提前转字符串,避免重复转换\r\n const pointIndex = tempNumStr.indexOf(\".\"); // :去掉+1,直接获取小数点位置\r\n // 获取小数点后的个数(需要保证有小数位)\r\n const pointCount = pointIndex > -1 ? tempNumStr.length - pointIndex - 1 : 0;\r\n\r\n // 源数据为整数或者小数点后面小于decimals位的作补零处理\r\n if (pointIndex === -1 || pointCount <= dec) {\r\n // pointIndex === -1 表示无小数点\r\n let tempNumA: string = tempNumStr; // 统一为字符串类型,避免类型混淆\r\n if (pointIndex === -1) {\r\n tempNumA = `${tempNumA}.`;\r\n // 补零到指定小数位\r\n for (let index = 0; index < dec; index++) {\r\n tempNumA = `${tempNumA}0`;\r\n }\r\n } else {\r\n // 补零到指定小数位\r\n for (let index = 0; index < dec - pointCount; index++) {\r\n tempNumA = `${tempNumA}0`;\r\n }\r\n }\r\n return tempNumA;\r\n }\r\n\r\n // 截取当前数据到小数点后decimals位\r\n const [integerPart, decimalPart] = tempNumStr.split(\".\");\r\n return `${integerPart}.${decimalPart.substring(0, dec)}`;\r\n}\r\n\r\n/**\r\n * 四舍五入,尽可能保留小数\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @returns {string} 返回保留后的数字\r\n */\r\nfunction _toDecimalRound(num: string | number, decimals: number = 2): number {\r\n if (isNaN(Number(num))) {\r\n throw new TypeError(`_toDecimalRound: ${num} is not a number`);\r\n }\r\n const n = Math.pow(10, decimals);\r\n return Math.round(Number(num) * n) / n;\r\n}\r\n\r\n/**\r\n * 向下舍入,尽可能保留小数\r\n * @param {string|number} num 数字\r\n * @param {number} decimals 保留小数的位数,默认2位\r\n * @returns {number} 返回保留后的数字\r\n */\r\nfunction _toDecimalFloor(num: string | number, decimals: number = 2): number {\r\n if (isNaN(Number(num))) {\r\n throw new TypeError(`_toDecimalFloor: ${num} is not a number`);\r\n }\r\n const n = Math.pow(10, decimals);\r\n return Math.floor(Number(num) * n) / n;\r\n}\r\n","/**\r\n * @module 正则\r\n */\r\nimport { REGEXP } from \"@/constants\";\r\n\r\n/* 正则校验方法 */\r\n/**\r\n * 正则校验的方法\r\n * @description 类型为REGEXP对应的正则\r\n * @param {string} value 校验的参数\r\n * @param {RegExp} regex 使用的REGEXP中的正则\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function regexpTest(value: string, regex: RegExp): boolean {\r\n return new RegExp(regex).test(value);\r\n}\r\n\r\n/* 常用校验 */\r\n/**\r\n * 是中文\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isChinese(value: string): boolean {\r\n return regexpTest(value, REGEXP.CH);\r\n}\r\n\r\n/**\r\n * 是英文\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isEnglish(value: string): boolean {\r\n return regexpTest(value, REGEXP.EN);\r\n}\r\n\r\n/**\r\n * 是外链\r\n * @description 支持http,https,mail,tel电话\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isExternal(value: string): boolean {\r\n return regexpTest(value, REGEXP.EXTERNAL);\r\n}\r\n\r\n/**\r\n * 是小写字母\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isLowerCase(value: string): boolean {\r\n return regexpTest(value, REGEXP.LOWER_CASE);\r\n}\r\n\r\n/**\r\n * 是大写字母\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isUpperCase(value: string): boolean {\r\n return regexpTest(value, REGEXP.UPPER_CASE);\r\n}\r\n\r\n/**\r\n * 是11位手机号码\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isMobile(value: string): boolean {\r\n return regexpTest(value, REGEXP.MOBILE);\r\n}\r\n\r\n/**\r\n * 是邮箱\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isEmail(value: string): boolean {\r\n return regexpTest(value, REGEXP.EMAIL);\r\n}\r\n\r\n/**\r\n * 是身份证号码(15-18位)\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isIdCard(value: string): boolean {\r\n return regexpTest(value, REGEXP.ID_CARD);\r\n}\r\n\r\n/**\r\n * 是url链接\r\n * @param {string} value 校验的参数\r\n * @returns {boolean} 返回校验的结果\r\n */\r\nexport function isUrl(value: string): boolean {\r\n return regexpTest(value, REGEXP.URL);\r\n}\r\n","/**\r\n * @module 文件\r\n */\r\nimport { isEmpty } from \"@/validate\";\r\n\r\n/* 文件信息处理 */\r\n/**\r\n * 格式化文件大小自动转为 B,KB,MB,GB\r\n * @param {number} size 文件的大小,单位byte字节\r\n * @returns {string} 返回格式化后的字符串\r\n */\r\nexport function formatFileSize(size: number): string {\r\n if (isEmpty(size)) return \"0B\";\r\n if (size < 1024) {\r\n return size + \"B\";\r\n } else if (size < 1024 * 1024) {\r\n return (size / 1024).toFixed(2) + \"KB\";\r\n } else if (size < 1024 * 1024 * 1024) {\r\n return (size / (1024 * 1024)).toFixed(2) + \"MB\";\r\n } else {\r\n return (size / (1024 * 1024 * 1024)).toFixed(2) + \"GB\";\r\n }\r\n}\r\n\r\n/**\r\n * 获得文件名称\r\n * @param {string} fileName 文件的全名称,例如:测试图片.jpg\r\n * @returns {string} 返回文件的名称\r\n */\r\nexport function getFileName(fileName: string): string | undefined {\r\n if (isEmpty(fileName)) return;\r\n return fileName.substring(0, fileName.lastIndexOf(\".\"));\r\n}\r\n\r\n/**\r\n * 获得文件后缀名\r\n * @param {string} value 文件地址路径或者文件全名称,例如:http://xxx.com/mytest.jpg,测试图片.jpg\r\n * @returns {string} 返回文件后缀名\r\n */\r\nexport function getFileSuffix(value: string): string | undefined {\r\n if (isEmpty(value)) return;\r\n return value.substring(value.lastIndexOf(\".\") + 1).toLowerCase();\r\n}\r\n\r\n/* 文件转换 */\r\n/**\r\n * file转blob\r\n * @param {File} file file文件\r\n * @returns {Promise} 返回Promise的blob\r\n */\r\nexport function fileToBlob(file: File): Promise<Blob> {\r\n return new Promise((resolve, reject) => {\r\n // 读取解析文件\r\n const reader = new FileReader();\r\n reader.readAsArrayBuffer(file);\r\n\r\n // 加载成功\r\n reader.onload = (e) => {\r\n const result = e.target?.result as ArrayBuffer;\r\n const blob = new Blob([result], { type: file.type });\r\n resolve(blob);\r\n };\r\n // 加载失败\r\n reader.onerror = function (err) {\r\n console.error(err);\r\n reject(err);\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * file转base64\r\n * @param {File} file file文件\r\n * @returns {Promise} 返回Promise的base64\r\n */\r\nexport function fileToBase64(file: File): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n // 读取解析文件\r\n const reader = new FileReader();\r\n reader.readAsDataURL(file);\r\n\r\n // 加载成功\r\n reader.onload = function (e) {\r\n const result = e.target?.result as string;\r\n resolve(result);\r\n };\r\n // 加载失败\r\n reader.onerror = function (err) {\r\n console.error(err);\r\n reject(err);\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * file转url\r\n * @description 适用于本地上传图片并预览,需要注意 URL.revokeObjectURL(file) 内存释放\r\n * @param {File} file file文件\r\n * @returns {Promise} 返回Promise的url\r\n */\r\nexport function fileToUrl(file: File): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const url = URL.createObjectURL(file);\r\n resolve(url);\r\n } catch (err) {\r\n // 捕捉异常\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * url赚file\r\n * @param {string} url url地址\r\n * @returns {Promise} 返回Promise的file\r\n */\r\nexport function urlToFile(url: string): Promise<File> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n window &&\r\n window.fetch(url).then((res) => {\r\n if (res.status === 200) {\r\n res.blob().then((blob) => {\r\n blobToFile(blob).then((file) => {\r\n resolve(file);\r\n });\r\n });\r\n }\r\n });\r\n } catch (err) {\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * blob转file\r\n * @param {Blob} blob blob数据\r\n * @param {string} fileName 文件名称,默认以时间戳命名\r\n * @returns {Promise} 返回Promise的file\r\n */\r\nexport function blobToFile(blob: Blob, fileName: string = String(Date.now())): Promise<File> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const mime = blob.type;\r\n const fileSuffix = mime.split(\"/\")[1];\r\n const file = new File([blob], `${Date.now()}.${fileSuffix}`, {\r\n type: mime,\r\n lastModified: Date.now(),\r\n });\r\n resolve(file);\r\n } catch (err) {\r\n // 捕捉异常\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * blob转文本\r\n * @param {Blob} blob blob数据\r\n * @returns {Promise} 返回Promise的文本\r\n */\r\nexport function blobToText(blob: Blob): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n const reader = new FileReader();\r\n reader.onload = function (e) {\r\n const result = e.target?.result as string;\r\n resolve(result);\r\n };\r\n reader.onerror = function (error) {\r\n reject(error);\r\n };\r\n reader.readAsText(blob);\r\n });\r\n}\r\n\r\n/**\r\n * blob转base64\r\n * @param {Blob} blob blob数据\r\n * @returns {Promise} 返回Promise的base64\r\n */\r\nexport function blobToBase64(blob: Blob): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n // 读取解析文件\r\n const reader = new FileReader();\r\n reader.readAsDataURL(blob);\r\n\r\n // 加载成功\r\n reader.onload = function (e) {\r\n const result = e.target?.result as string;\r\n resolve(result);\r\n };\r\n // 加载失败\r\n reader.onerror = function (err) {\r\n console.error(err);\r\n reject(err);\r\n };\r\n });\r\n}\r\n\r\n/**\r\n * base64转file\r\n * @param {string} base64 base64数据\r\n * @param {string} fileName 文件名称,默认以时间戳命名\r\n * @returns {Promise} 返回Promise的file\r\n */\r\nexport function base64ToFile(base64: string, fileName: string = String(Date.now())): Promise<File> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const arr = base64.split(\",\");\r\n const mimeMatch = arr[0] ? arr[0].match(/:(.+?);/) : null;\r\n const mime = mimeMatch ? mimeMatch[1] : \"\";\r\n const fileSuffix = mime.split(\"/\")[1];\r\n const bstr = window.atob(arr[1]);\r\n let n = bstr.length;\r\n const u8arr = new Uint8Array(n);\r\n while (n--) {\r\n u8arr[n] = bstr.charCodeAt(n);\r\n }\r\n resolve(new File([u8arr], `${fileName}.${fileSuffix}`, { type: mime }));\r\n } catch (err) {\r\n // 捕捉异常\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * base64转成blob\r\n * @param {string} base64 base64数据\r\n * @returns {Promise} 返回Promise的blob\r\n */\r\nexport function base64ToBlob(base64: string): Promise<Blob> {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n const arr = base64.split(\",\");\r\n const mimeMatch = arr[0] ? arr[0].match(/:(.+?);/) : null;\r\n const mime = mimeMatch ? mimeMatch[1] : \"\";\r\n const bstr = window.atob(arr[1]);\r\n let n = bstr.length;\r\n const u8arr = new Uint8Array(n);\r\n\r\n while (n--) {\r\n u8arr[n] = bstr.charCodeAt(n);\r\n }\r\n resolve(new Blob([u8arr], { type: mime }));\r\n } catch (err) {\r\n // 捕捉异常\r\n console.error(err);\r\n reject(err);\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 图片url转base64\r\n * @param {string} imgUrl 图片url地址\r\n * @returns {Promise} 返回Promise的base64\r\n */\r\nexport function urlToBase64(imgUrl: string): Promise<string> {\r\n return new Promise((resolve, reject) => {\r\n // 设置图片\r\n const img = new Image();\r\n img.src = imgUrl;\r\n\r\n // 加载成功\r\n img.onload = function () {\r\n // 画图\r\n const canvas = document.createElement(\"canvas\");\r\n const context = canvas.getContext(\"2d\");\r\n canvas.width = img.width;\r\n canvas.height = img.height;\r\n if (context) {\r\n context.drawImage(img, 0, 0, img.width, img.height);\r\n }\r\n // 转为base64\r\n const base64 = canvas.toDataURL(\"image/png\");\r\n resolve(base64);\r\n };\r\n // 加载失败\r\n img.onerror = function (err) {\r\n console.error(err);\r\n reject(err);\r\n };\r\n });\r\n}\r\n\r\n/* 下载文件 */\r\n/**\r\n * 下载blob格式的文件\r\n * @param {Blob} blob blob数据\r\n * @param {string} fileName 下载的文件名,不写后缀名则默认为原文件类型\r\n */\r\nexport function downloadBlobFile(blob: Blob, fileName: string) {\r\n try {\r\n const objUrl = window.URL.createObjectURL(blob);\r\n const link = window.document.createElement(\"a\");\r\n link.download = fileName;\r\n link.href = objUrl;\r\n link.click();\r\n URL.revokeObjectURL(objUrl);\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n}\r\n\r\n/**\r\n * 通过文件url地址下载\r\n * @param {string} fileUrl url文件地址\r\n * @param {string} fileName 下载的文件名,不写后缀名则默认为原文件类型\r\n */\r\nexport function downloadFileUrl(fileUrl: string, fileName: string) {\r\n try {\r\n const link = window.document.createElement(\"a\");\r\n link.download = fileName;\r\n link.href = fileUrl;\r\n link.target = \"_blank\";\r\n // 生成节点点击\r\n window.document.body.appendChild(link);\r\n link.click();\r\n // 点击后移除节点\r\n window.document.body.removeChild(link);\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n}\r\n","/**\r\n * @module 颜色\r\n */\r\n\r\n/**\r\n * rgb颜色转hex\r\n * @param {string} rgb rgb颜色字符串\r\n * @returns {string} 返回生成的hex颜色\r\n */\r\nexport function rgbToHex(rgb: string): string {\r\n const arr = rgb.split(\",\");\r\n const r = parseInt(arr[0].split(\"(\")[1]);\r\n const g = parseInt(arr[1]);\r\n const b = parseInt(arr[2].split(\")\")[0]);\r\n return \"#\" + _hex(r) + _hex(g) + _hex(b);\r\n}\r\n\r\n/**\r\n * rgba颜色转hex\r\n * @param {string} rgba rgba颜色字符串\r\n * @returns {string} 返回生成的hex颜色\r\n */\r\nexport function rgbaToHex(rgba: string): string {\r\n const arr = rgba.split(\",\");\r\n const r = parseInt(arr[0].split(\"(\")[1]);\r\n const g = parseInt(arr[1]);\r\n const b = parseInt(arr[2]);\r\n const a = parseFloat(arr[3].split(\")\")[0]);\r\n\r\n return `#${_hex(Math.round(a * 256 - 1))}${_hex(r)}${_hex(g)}${_hex(b)}`;\r\n}\r\n\r\n/**\r\n * rgba颜色转hsl\r\n * @param {string} rgba rgb颜色字符串\r\n * @returns {string} 返回生成的hsl颜色\r\n */\r\nexport function rgbaToHsl(rgba: string): string {\r\n const arr = rgba.split(\",\");\r\n const r = parseInt(arr[0].split(\"(\")[1]) / 255;\r\n const g = parseInt(arr[1]) / 255;\r\n const b = parseInt(arr[2]) / 255;\r\n const a = parseFloat(arr[3] && arr[3].split(\")\")[0]);\r\n const max = Math.max(r, g, b),\r\n min = Math.min(r, g, b);\r\n let h = 0,\r\n s = 0;\r\n const l = (max + min) / 2;\r\n if (max === min) {\r\n h = s = 0;\r\n } else {\r\n const d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n if (a) {\r\n return `hsla(${Math.round(h * 360)},${Math.round(s * 100)}%,${Math.round(l * 100)}%,${a})`;\r\n }\r\n return `hsl(${Math.round(h * 360)},${Math.round(s * 100)}%,${Math.round(l * 100)}%)`;\r\n}\r\n\r\n/**\r\n * hex颜色转rgb\r\n * @param {string} hex hex颜色字符串\r\n * @returns {string} 返回生成的rgb颜色\r\n */\r\nexport function hexToRgb(hex: string): string {\r\n const color = { r: 0, g: 0, b: 0, o: 0 };\r\n const rgx = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\r\n const hexStr = hex.replace(rgx, function (m, r, g, b) {\r\n return r + r + g + g + b + b;\r\n });\r\n const rgb = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hexStr);\r\n if (!rgb) {\r\n throw new TypeError(`hexToRgb: invalid hex color: ${hex}`);\r\n }\r\n color.r = parseInt(rgb[1], 16);\r\n color.g = parseInt(rgb[2], 16);\r\n color.b = parseInt(rgb[3], 16);\r\n return `rgb(${color.r},${color.g},${color.b})`;\r\n}\r\n\r\n/**\r\n * hex颜色转rgba\r\n * @param {string} hex hex颜色字符串\r\n * @param {number} opacity 透明度\r\n * @returns {string} 返回生成的rgba颜色\r\n */\r\nexport function hexToRgba(hex: string, opacity: number = 1): string {\r\n const color = { r: 0, g: 0, b: 0, o: 0 };\r\n const rgx = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\r\n const hexStr = hex.replace(rgx, function (m, r, g, b) {\r\n return r + r + g + g + b + b;\r\n });\r\n const rgb = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hexStr);\r\n if (!rgb) {\r\n throw new TypeError(`hexToRgba: invalid hex color: ${hex}`);\r\n }\r\n color.r = parseInt(rgb[1], 16);\r\n color.g = parseInt(rgb[2], 16);\r\n color.b = parseInt(rgb[3], 16);\r\n color.o = opacity;\r\n return `rgba(${color.r},${color.g},${color.b},${color.o})`;\r\n}\r\n\r\n/**\r\n * hex颜色转hsl\r\n * @param {string} hex hex颜色字符串\r\n * @returns {string} 返回生成的hsl颜色\r\n */\r\nexport function hexToHsl(hex: string): string {\r\n // 先解析为rgb\r\n const rgx = /^#?([a-f\\d])([a-f\\d])([a-f\\d])$/i;\r\n const hexStr = hex.replace(rgx, function (m, r, g, b) {\r\n return r + r + g + g + b + b;\r\n });\r\n const rgb = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hexStr);\r\n if (!rgb) {\r\n throw new TypeError(`hexToHsl: invalid hex color: ${hex}`);\r\n }\r\n\r\n // 再组装为hsl格式\r\n const r = parseInt(rgb[1], 16) / 255;\r\n const g = parseInt(rgb[2], 16) / 255;\r\n const b = parseInt(rgb[3], 16) / 255;\r\n const max = Math.max(r, g, b),\r\n min = Math.min(r, g, b);\r\n let h = 0,\r\n s = 0;\r\n const l = (max + min) / 2;\r\n if (max === min) {\r\n h = s = 0;\r\n } else {\r\n const d = max - min;\r\n s = l > 0.5 ? d / (2 - max - min) : d / (max + min);\r\n switch (max) {\r\n case r:\r\n h = (g - b) / d + (g < b ? 6 : 0);\r\n break;\r\n case g:\r\n h = (b - r) / d + 2;\r\n break;\r\n case b:\r\n h = (r - g) / d + 4;\r\n break;\r\n }\r\n h /= 6;\r\n }\r\n return `hsl(${Math.round(h * 360)},${Math.round(s * 100)}%,${Math.round(l * 100)}%)`;\r\n}\r\n\r\n/**\r\n * 随机生成hex颜色\r\n * @returns {string} 返回生成的十六进制颜色\r\n */\r\nexport function getDrawHex(): string {\r\n return (\r\n \"#\" +\r\n (function (h) {\r\n return new Array(7 - h.length).join(\"0\") + h;\r\n })(((Math.random() * 0x1000000) << 0).toString(16))\r\n );\r\n}\r\n\r\n/**\r\n * 随机生成rgb颜色\r\n * @returns {string} 返回生成的 rgb 颜色\r\n */\r\nexport function getDrawRgb(): string {\r\n const r = Math.floor(Math.random() * 256);\r\n const g = Math.floor(Math.random() * 256);\r\n const b = Math.floor(Math.random() * 256);\r\n return `rgb(${r},${g},${b})`;\r\n}\r\n\r\n/**\r\n * 随机生成rgba颜色\r\n * @returns {string} 返回生成的 rgba 颜色\r\n */\r\nexport function getDrawRgba(): string {\r\n const r = Math.floor(Math.random() * 256);\r\n const g = Math.floor(Math.random() * 256);\r\n const b = Math.floor(Math.random() * 256);\r\n const a = Number(Math.random()).toFixed(2);\r\n return `rgba(${r},${g},${b},${a})`;\r\n}\r\n\r\n// 内部函数\r\n/**\r\n * 颜色值转换\r\n * @param {number} num 转换的值\r\n * @returns {string} 返回计算\r\n */\r\nfunction _hex(num: number): string {\r\n if (num > 255) {\r\n throw \"'\" + num + \"'' is greater than 255(0xff);\";\r\n }\r\n const str = Number(num).toString(16);\r\n return (\"0\" + str).slice(-2);\r\n}\r\n","/*\r\n * base64加解密\r\n * 高性能、高健壮性、纯JS实现,兼容Node/浏览器/Worker\r\n */\r\n\r\n// 核心常量定义\r\nconst ENCODING_ERROR = \"not a UTF-8 string\";\r\nconst BASE64_ENCODE_CHAR = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\".split(\"\");\r\nconst BASE64_DECODE_CHAR = {};\r\nfor (let i = 0; i < 64; ++i) {\r\n BASE64_DECODE_CHAR[BASE64_ENCODE_CHAR[i]] = i;\r\n}\r\n// 兼容URL安全的Base64\r\nBASE64_DECODE_CHAR[\"-\"] = 62;\r\nBASE64_DECODE_CHAR[\"_\"] = 63;\r\n\r\n// ======================== 精简版环境判断(核心场景全覆盖,保留!)========================\r\nconst isNodeEnv = typeof process === \"object\" && process.versions && process.versions.node;\r\nconst isBrowserEnv = typeof window === \"object\" && typeof window.btoa === \"function\";\r\nconst root = isNodeEnv ? global : typeof self === \"object\" ? self : window;\r\n\r\n// ======================== 核心工具函数(全部保留,原生API更快!)========================\r\n/**\r\n * 清理Base64字符串(移除等号、换行符、非法字符)\r\n */\r\nconst cleanBase64Str = function (base64Str) {\r\n return base64Str\r\n .split(\"=\")[0]\r\n .replace(/[\\r\\n]/g, \"\")\r\n .replace(/[^A-Za-z0-9+/=_-]/g, \"\"); // 过滤非法字符\r\n};\r\n\r\n/**\r\n * UTF-8字符串转字节数组(性能优化版)\r\n */\r\nconst utf8ToBytes = function (str) {\r\n const len = str.length; // 缓存长度,减少属性访问\r\n const bytes = new Array(len * 4); // 预分配最大可能长度(避免频繁扩容)\r\n let byteIndex = 0;\r\n\r\n for (let i = 0; i < len; i++) {\r\n const c = str.charCodeAt(i);\r\n if (c < 0x80) {\r\n bytes[byteIndex++] = c;\r\n } else if (c < 0x800) {\r\n bytes[byteIndex++] = 0xc0 | (c >> 6);\r\n bytes[byteIndex++] = 0x80 | (c & 0x3f);\r\n } else if (c < 0xd800 || c >= 0xe000) {\r\n bytes[byteIndex++] = 0xe0 | (c >> 12);\r\n bytes[byteIndex++] = 0x80 | ((c >> 6) & 0x3f);\r\n bytes[byteIndex++] = 0x80 | (c & 0x3f);\r\n } else {\r\n // 处理代理对\r\n const code = 0x10000 + (((c & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));\r\n bytes[byteIndex++] = 0xf0 | (code >> 18);\r\n bytes[byteIndex++] = 0x80 | ((code >> 12) & 0x3f);\r\n bytes[byteIndex++] = 0x80 | ((code >> 6) & 0x3f);\r\n bytes[byteIndex++] = 0x80 | (code & 0x3f);\r\n }\r\n }\r\n\r\n // 截断数组到实际长度\r\n return bytes.slice(0, byteIndex);\r\n};\r\n\r\n/**\r\n * Base64字符串解码为字节数组(性能优化版)\r\n */\r\nconst decodeAsBytes = function (base64Str) {\r\n // 空值快速返回\r\n if (!base64Str) return [];\r\n\r\n base64Str = cleanBase64Str(base64Str);\r\n const len = base64Str.length;\r\n const count = (len >> 2) << 2;\r\n // 预计算最大长度:3/4 * 总字符数,减少数组扩容\r\n const bytes = new Array(Math.floor((len * 3) / 4));\r\n let byteIndex = 0;\r\n let i = 0; // 把i的作用域提升到函数级,确保后续能访问\r\n\r\n // 4字符转3字节\r\n for (; i < count; ) {\r\n const v1 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v2 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v3 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v4 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n\r\n bytes[byteIndex++] = ((v1 << 2) | (v2 >>> 4)) & 255;\r\n bytes[byteIndex++] = ((v2 << 4) | (v3 >>> 2)) & 255;\r\n bytes[byteIndex++] = ((v3 << 6) | v4) & 255;\r\n }\r\n\r\n // 处理剩余字符(此时i的作用域有效)\r\n const remain = len - count;\r\n if (remain === 2) {\r\n const v1 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v2 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n bytes[byteIndex++] = ((v1 << 2) | (v2 >>> 4)) & 255;\r\n } else if (remain === 3) {\r\n const v1 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v2 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n const v3 = BASE64_DECODE_CHAR[base64Str.charAt(i++)] || 0;\r\n bytes[byteIndex++] = ((v1 << 2) | (v2 >>> 4)) & 255;\r\n bytes[byteIndex++] = ((v2 << 4) | (v3 >>> 2)) & 255;\r\n }\r\n\r\n // 截断数组到实际长度\r\n return bytes.slice(0, byteIndex);\r\n};\r\n\r\n/**\r\n * 抽离公共逻辑:字节数组转Base64字符(减少代码冗余)\r\n */\r\nconst bytesToBase64Chars = function (bytes) {\r\n const len = bytes.length;\r\n const count = Math.floor(len / 3) * 3;\r\n const base64Str = new Array(Math.ceil((len * 4) / 3)); // 预分配长度\r\n let strIndex = 0;\r\n\r\n // 3字节转4字符\r\n for (let i = 0; i < count; ) {\r\n const v1 = bytes[i++];\r\n const v2 = bytes[i++];\r\n const v3 = bytes[i++];\r\n\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[v1 >>> 2];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[((v1 << 4) | (v2 >>> 4)) & 63];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[((v2 << 2) | (v3 >>> 6)) & 63];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[v3 & 63];\r\n }\r\n\r\n // 处理剩余字节\r\n const remain = len - count;\r\n if (remain === 1) {\r\n const v1 = bytes[count];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[v1 >>> 2];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[(v1 << 4) & 63];\r\n base64Str[strIndex++] = \"=\";\r\n base64Str[strIndex++] = \"=\";\r\n } else if (remain === 2) {\r\n const v1 = bytes[count];\r\n const v2 = bytes[count + 1];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[v1 >>> 2];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[((v1 << 4) | (v2 >>> 4)) & 63];\r\n base64Str[strIndex++] = BASE64_ENCODE_CHAR[(v2 << 2) & 63];\r\n base64Str[strIndex++] = \"=\";\r\n }\r\n\r\n return base64Str.join(\"\");\r\n};\r\n\r\n/**\r\n * 字节数组编码为Base64字符串(复用公共逻辑)\r\n */\r\nlet encodeFromBytes = function (bytes) {\r\n // 空值快速返回\r\n if (!bytes || bytes.length === 0) return \"\";\r\n return bytesToBase64Chars(bytes);\r\n};\r\n\r\n// ======================== 环境适配的btoa/atob实现(全部保留,原生更快!)=======================\r\nlet btoa = root.btoa;\r\nlet atob = root.atob;\r\nlet utf8Base64Encode;\r\nlet utf8Base64Decode;\r\n// 1. Node.js环境(纯JS实现,不使用require)\r\nif (isNodeEnv) {\r\n // 纯JS版btoa(替代Buffer实现)\r\n btoa = function (str) {\r\n if (!str) return \"\";\r\n const bytes = Array.from(str).map((c) => c.charCodeAt(0));\r\n return bytesToBase64Chars(bytes);\r\n };\r\n\r\n // 纯JS版atob\r\n atob = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n const bytes = decodeAsBytes(base64Str);\r\n return String.fromCharCode.apply(null, bytes);\r\n };\r\n\r\n // 纯JS版UTF8编码/解码(和浏览器环境保持一致)\r\n utf8Base64Encode = function (str) {\r\n if (!str) return \"\";\r\n const bytes = utf8ToBytes(str);\r\n return bytesToBase64Chars(bytes);\r\n };\r\n\r\n utf8Base64Decode = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n\r\n const bytes = decodeAsBytes(base64Str);\r\n const str = [];\r\n const len = bytes.length;\r\n let i = 0;\r\n\r\n while (i < len) {\r\n const b = bytes[i++];\r\n if (b <= 0x7f) {\r\n str.push(String.fromCharCode(b));\r\n continue;\r\n }\r\n\r\n let c, followingChars;\r\n if (b > 0xbf && b <= 0xdf) {\r\n c = b & 0x1f;\r\n followingChars = 1;\r\n } else if (b <= 0xef) {\r\n c = b & 0x0f;\r\n followingChars = 2;\r\n } else if (b <= 0xf7) {\r\n c = b & 0x07;\r\n followingChars = 3;\r\n } else {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n\r\n // 校验后续字节合法性\r\n for (let j = 0; j < followingChars; ++j) {\r\n const byte = bytes[i++];\r\n if (i > len || byte < 0x80 || byte > 0xbf) {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n c = (c << 6) + (byte & 0x3f);\r\n }\r\n\r\n // 校验Unicode范围\r\n if (c >= 0xd800 && c <= 0xdfff) throw new Error(ENCODING_ERROR);\r\n if (c > 0x10ffff) throw new Error(ENCODING_ERROR);\r\n\r\n // 转换为字符\r\n if (c <= 0xffff) {\r\n str.push(String.fromCharCode(c));\r\n } else {\r\n c -= 0x10000;\r\n str.push(String.fromCharCode((c >> 10) + 0xd800), String.fromCharCode((c & 0x3ff) + 0xdc00));\r\n }\r\n }\r\n\r\n return str.join(\"\");\r\n };\r\n\r\n // 2. 无原生btoa/atob的环境(老旧浏览器/Worker)\r\n} else if (!isBrowserEnv) {\r\n // 纯JS版btoa(复用公共逻辑)\r\n btoa = function (str) {\r\n if (!str) return \"\";\r\n const bytes = Array.from(str).map((c) => c.charCodeAt(0));\r\n return bytesToBase64Chars(bytes);\r\n };\r\n\r\n // 纯JS版atob\r\n atob = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n const bytes = decodeAsBytes(base64Str);\r\n return String.fromCharCode.apply(null, bytes);\r\n };\r\n\r\n // 纯JS版UTF8编码/解码\r\n utf8Base64Encode = function (str) {\r\n if (!str) return \"\";\r\n const bytes = utf8ToBytes(str);\r\n return bytesToBase64Chars(bytes);\r\n };\r\n\r\n utf8Base64Decode = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n\r\n const bytes = decodeAsBytes(base64Str);\r\n const str = [];\r\n const len = bytes.length;\r\n let i = 0;\r\n\r\n while (i < len) {\r\n const b = bytes[i++];\r\n if (b <= 0x7f) {\r\n str.push(String.fromCharCode(b));\r\n continue;\r\n }\r\n\r\n let c, followingChars;\r\n if (b > 0xbf && b <= 0xdf) {\r\n c = b & 0x1f;\r\n followingChars = 1;\r\n } else if (b <= 0xef) {\r\n c = b & 0x0f;\r\n followingChars = 2;\r\n } else if (b <= 0xf7) {\r\n c = b & 0x07;\r\n followingChars = 3;\r\n } else {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n\r\n // 校验后续字节合法性\r\n for (let j = 0; j < followingChars; ++j) {\r\n const byte = bytes[i++];\r\n if (i > len || byte < 0x80 || byte > 0xbf) {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n c = (c << 6) + (byte & 0x3f);\r\n }\r\n\r\n // 校验Unicode范围\r\n if (c >= 0xd800 && c <= 0xdfff) throw new Error(ENCODING_ERROR);\r\n if (c > 0x10ffff) throw new Error(ENCODING_ERROR);\r\n\r\n // 转换为字符\r\n if (c <= 0xffff) {\r\n str.push(String.fromCharCode(c));\r\n } else {\r\n c -= 0x10000;\r\n str.push(String.fromCharCode((c >> 10) + 0xd800), String.fromCharCode((c & 0x3ff) + 0xdc00));\r\n }\r\n }\r\n\r\n return str.join(\"\");\r\n };\r\n\r\n // 3. 浏览器原生支持btoa/atob\r\n} else {\r\n utf8Base64Encode = function (str) {\r\n if (!str) return \"\";\r\n\r\n const result = [];\r\n const len = str.length;\r\n for (let i = 0; i < len; i++) {\r\n const charcode = str.charCodeAt(i);\r\n if (charcode < 0x80) {\r\n result.push(String.fromCharCode(charcode));\r\n } else if (charcode < 0x800) {\r\n result.push(String.fromCharCode(0xc0 | (charcode >> 6)), String.fromCharCode(0x80 | (charcode & 0x3f)));\r\n } else if (charcode < 0xd800 || charcode >= 0xe000) {\r\n result.push(\r\n String.fromCharCode(0xe0 | (charcode >> 12)),\r\n String.fromCharCode(0x80 | ((charcode >> 6) & 0x3f)),\r\n String.fromCharCode(0x80 | (charcode & 0x3f)),\r\n );\r\n } else {\r\n const code = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));\r\n result.push(\r\n String.fromCharCode(0xf0 | (code >> 18)),\r\n String.fromCharCode(0x80 | ((code >> 12) & 0x3f)),\r\n String.fromCharCode(0x80 | ((code >> 6) & 0x3f)),\r\n String.fromCharCode(0x80 | (code & 0x3f)),\r\n );\r\n }\r\n }\r\n return btoa(result.join(\"\"));\r\n };\r\n\r\n utf8Base64Decode = function (base64Str) {\r\n if (!base64Str) return \"\";\r\n\r\n const tmpStr = atob(base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\"));\r\n // 替换Unicode转义,避免ESLint控制字符警告\r\n // eslint-disable-next-line no-control-regex\r\n if (!/[^\\u0000-\\u007F]/.test(tmpStr)) {\r\n return tmpStr;\r\n }\r\n\r\n const str = [];\r\n const len = tmpStr.length;\r\n let i = 0;\r\n\r\n while (i < len) {\r\n const b = tmpStr.charCodeAt(i++);\r\n if (b <= 0x7f) {\r\n str.push(String.fromCharCode(b));\r\n continue;\r\n }\r\n\r\n let c, followingChars;\r\n if (b > 0xbf && b <= 0xdf) {\r\n c = b & 0x1f;\r\n followingChars = 1;\r\n } else if (b <= 0xef) {\r\n c = b & 0x0f;\r\n followingChars = 2;\r\n } else if (b <= 0xf7) {\r\n c = b & 0x07;\r\n followingChars = 3;\r\n } else {\r\n throw new Error(ENCODING_ERROR);\r\n }\r\n\r\n for (let j = 0; j < followingChars; ++j) {\r\n const byte = tmpStr.charCodeAt(i++);\r\n if (i > len || byte < 0x80 || byte > 0xbf) throw new Error(ENCODING_ERROR);\r\n c = (c << 6) + (byte & 0x3f);\r\n }\r\n\r\n if (c >= 0xd800 && c <= 0xdfff) throw new Error(ENCODING_ERROR);\r\n if (c > 0x10ffff) throw new Error(ENCODING_ERROR);\r\n\r\n if (c <= 0xffff) {\r\n str.push(String.fromCharCode(c));\r\n } else {\r\n c -= 0x10000;\r\n str.push(String.fromCharCode((c >> 10) + 0xd800), String.fromCharCode((c & 0x3ff) + 0xdc00));\r\n }\r\n }\r\n\r\n return str.join(\"\");\r\n };\r\n}\r\n\r\n// ======================== 类型转换工具函数(全部保留)========================\r\n/**\r\n * Uint8Array转Base64字符串\r\n * @param {Uint8Array} uint8Array 字节数组\r\n * @param {boolean} [urlSafe=false] 是否URL安全\r\n * @returns {string} Base64字符串\r\n */\r\nexport const fromUint8Array = function (uint8Array, urlSafe = false) {\r\n if (!(uint8Array instanceof Uint8Array)) {\r\n throw new TypeError(\"fromUint8Array: input must be Uint8Array\");\r\n }\r\n const bytes = Array.from(uint8Array);\r\n let result = bytesToBase64Chars(bytes);\r\n if (urlSafe) {\r\n result = result.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Base64字符串转Uint8Array\r\n * @param {string} base64Str Base64字符串\r\n * @param {boolean} [urlSafe=false] 是否URL安全\r\n * @returns {Uint8Array} 字节数组\r\n */\r\nexport const toUint8Array = function (base64Str, urlSafe = false) {\r\n if (typeof base64Str !== \"string\") {\r\n throw new TypeError(\"toUint8Array: input must be string\");\r\n }\r\n // 处理URL安全字符\r\n if (urlSafe) {\r\n base64Str = base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\");\r\n }\r\n const bytes = decodeAsBytes(base64Str);\r\n return new Uint8Array(bytes);\r\n};\r\n\r\n/**\r\n * 十六进制字符串转Base64字符串\r\n * @param {string} hexStr 十六进制字符串\r\n * @param {boolean} [urlSafe=false] 是否URL安全\r\n * @returns {string} Base64字符串\r\n */\r\nexport const fromHex = function (hexStr, urlSafe = false) {\r\n if (typeof hexStr !== \"string\" || !/^[0-9a-fA-F]+$/.test(hexStr)) {\r\n throw new TypeError(\"fromHex: input must be hex string\");\r\n }\r\n // 补全偶数长度\r\n const str = hexStr.length % 2 ? `0${hexStr}` : hexStr;\r\n const bytes = new Array(str.length / 2);\r\n for (let i = 0; i < bytes.length; i++) {\r\n bytes[i] = parseInt(str.substr(i * 2, 2), 16);\r\n }\r\n let result = bytesToBase64Chars(bytes);\r\n if (urlSafe) {\r\n result = result.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Base64字符串转十六进制字符串\r\n * @param {string} base64Str Base64字符串\r\n * @param {boolean} [urlSafe=false] 是否URL安全\r\n * @returns {string} 十六进制字符串\r\n */\r\nexport const toHex = function (base64Str, urlSafe = false) {\r\n if (typeof base64Str !== \"string\") {\r\n throw new TypeError(\"toHex: input must be string\");\r\n }\r\n // 处理URL安全字符\r\n if (urlSafe) {\r\n base64Str = base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\");\r\n }\r\n const bytes = decodeAsBytes(base64Str);\r\n return Array.from(bytes)\r\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n};\r\n\r\n// ======================== 核心方法(仅删除asciiOnly开关,默认UTF8)========================\r\n/**\r\n * Base64编码(高性能、高健壮性版,默认UTF8)\r\n * @param {string | number[] | Uint8Array | ArrayBuffer} data 待编码数据\r\n * @param {boolean} [urlSafe=false] 是否生成URL安全的Base64\r\n * @returns {string} Base64字符串\r\n */\r\nexport const encode = function (data, urlSafe = false) {\r\n // 空值快速返回\r\n if (data == null) return \"\";\r\n\r\n const notString = typeof data !== \"string\";\r\n let result = \"\";\r\n\r\n if (notString) {\r\n // 处理ArrayBuffer\r\n if (data.constructor === root.ArrayBuffer) {\r\n data = new Uint8Array(data);\r\n }\r\n // 处理字节数组/Uint8Array\r\n result = encodeFromBytes(data);\r\n } else {\r\n // 空字符串快速返回\r\n if (data === \"\") return \"\";\r\n // 强制走UTF8编码(删掉asciiOnly判断,直接用utf8Base64Encode)\r\n result = utf8Base64Encode(data);\r\n }\r\n\r\n // URL安全处理:替换+->-,/->_,去掉=\r\n if (urlSafe) {\r\n result = result.replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=/g, \"\");\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Base64解码(高性能、高健壮性版,默认UTF8)\r\n * @param {string} base64Str 待解码的Base64字符串\r\n * @returns {string} 解码后的UTF8字符串\r\n */\r\nexport const decode = function (base64Str) {\r\n // 空值快速返回\r\n if (base64Str == null || base64Str === \"\") return \"\";\r\n\r\n // 处理URL安全的Base64\r\n base64Str = base64Str.replace(/-/g, \"+\").replace(/_/g, \"/\");\r\n base64Str = cleanBase64Str(base64Str);\r\n\r\n // 强制走UTF8解码(删掉asciiOnly判断,直接用utf8Base64Decode)\r\n return utf8Base64Decode(base64Str);\r\n};\r\n\r\n// ======================== URL安全专用方法(同步删除asciiOnly开关)========================\r\n/**\r\n * URL安全Base64编码(专用方法,等价于encode(data, true))\r\n * @param {string | number[] | Uint8Array | ArrayBuffer} data 待编码数据\r\n * @returns {string} URL安全的Base64字符串\r\n */\r\nexport const encodeURI = function (data) {\r\n return encode(data, true);\r\n};\r\n\r\n/**\r\n * URL安全Base64解码(专用方法,兼容URL安全字符)\r\n * @param {string} base64Str URL安全的Base64字符串\r\n * @returns {string} 解码后的UTF8字符串\r\n */\r\nexport const decodeURI = function (base64Str) {\r\n return decode(base64Str);\r\n};\r\n","/**\r\n * Add integers, wrapping at 2^32.\r\n * This uses 16-bit operations internally to work around bugs in interpreters.\r\n *\r\n * @param {number} x First integer\r\n * @param {number} y Second integer\r\n * @returns {number} Sum\r\n */\r\nfunction safeAdd(x, y) {\r\n var lsw = (x & 0xffff) + (y & 0xffff);\r\n var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\r\n return (msw << 16) | (lsw & 0xffff);\r\n}\r\n\r\n/**\r\n * Bitwise rotate a 32-bit number to the left.\r\n *\r\n * @param {number} num 32-bit number\r\n * @param {number} cnt Rotation count\r\n * @returns {number} Rotated number\r\n */\r\nfunction bitRotateLeft(num, cnt) {\r\n return (num << cnt) | (num >>> (32 - cnt));\r\n}\r\n\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} q q\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5cmn(q, a, b, x, s, t) {\r\n return safeAdd(bitRotateLeft(safeAdd(safeAdd(a, q), safeAdd(x, t)), s), b);\r\n}\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} c c\r\n * @param {number} d d\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5ff(a, b, c, d, x, s, t) {\r\n return md5cmn((b & c) | (~b & d), a, b, x, s, t);\r\n}\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} c c\r\n * @param {number} d d\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5gg(a, b, c, d, x, s, t) {\r\n return md5cmn((b & d) | (c & ~d), a, b, x, s, t);\r\n}\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} c c\r\n * @param {number} d d\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5hh(a, b, c, d, x, s, t) {\r\n return md5cmn(b ^ c ^ d, a, b, x, s, t);\r\n}\r\n/**\r\n * Basic operation the algorithm uses.\r\n *\r\n * @param {number} a a\r\n * @param {number} b b\r\n * @param {number} c c\r\n * @param {number} d d\r\n * @param {number} x x\r\n * @param {number} s s\r\n * @param {number} t t\r\n * @returns {number} Result\r\n */\r\nfunction md5ii(a, b, c, d, x, s, t) {\r\n return md5cmn(c ^ (b | ~d), a, b, x, s, t);\r\n}\r\n\r\n/**\r\n * Calculate the MD5 of an array of little-endian words, and a bit length.\r\n *\r\n * @param {Array} x Array of little-endian words\r\n * @param {number} len Bit length\r\n * @returns {Array<number>} MD5 Array\r\n */\r\nfunction binlMD5(x, len) {\r\n /* append padding */\r\n x[len >> 5] |= 0x80 << (len % 32);\r\n x[(((len + 64) >>> 9) << 4) + 14] = len;\r\n\r\n var i;\r\n var olda;\r\n var oldb;\r\n var oldc;\r\n var oldd;\r\n var a = 1732584193;\r\n var b = -271733879;\r\n var c = -1732584194;\r\n var d = 271733878;\r\n\r\n for (i = 0; i < x.length; i += 16) {\r\n olda = a;\r\n oldb = b;\r\n oldc = c;\r\n oldd = d;\r\n\r\n a = md5ff(a, b, c, d, x[i], 7, -680876936);\r\n d = md5ff(d, a, b, c, x[i + 1], 12, -389564586);\r\n c = md5ff(c, d, a, b, x[i + 2], 17, 606105819);\r\n b = md5ff(b, c, d, a, x[i + 3], 22, -1044525330);\r\n a = md5ff(a, b, c, d, x[i + 4], 7, -176418897);\r\n d = md5ff(d, a, b, c, x[i + 5], 12, 1200080426);\r\n c = md5ff(c, d, a, b, x[i + 6], 17, -1473231341);\r\n b = md5ff(b, c, d, a, x[i + 7], 22, -45705983);\r\n a = md5ff(a, b, c, d, x[i + 8], 7, 1770035416);\r\n d = md5ff(d, a, b, c, x[i + 9], 12, -1958414417);\r\n c = md5ff(c, d, a, b, x[i + 10], 17, -42063);\r\n b = md5ff(b, c, d, a, x[i + 11], 22, -1990404162);\r\n a = md5ff(a, b, c, d, x[i + 12], 7, 1804603682);\r\n d = md5ff(d, a, b, c, x[i + 13], 12, -40341101);\r\n c = md5ff(c, d, a, b, x[i + 14], 17, -1502002290);\r\n b = md5ff(b, c, d, a, x[i + 15], 22, 1236535329);\r\n\r\n a = md5gg(a, b, c, d, x[i + 1], 5, -165796510);\r\n d = md5gg(d, a, b, c, x[i + 6], 9, -1069501632);\r\n c = md5gg(c, d, a, b, x[i + 11], 14, 643717713);\r\n b = md5gg(b, c, d, a, x[i], 20, -373897302);\r\n a = md5gg(a, b, c, d, x[i + 5], 5, -701558691);\r\n d = md5gg(d, a, b, c, x[i + 10], 9, 38016083);\r\n c = md5gg(c, d, a, b, x[i + 15], 14, -660478335);\r\n b = md5gg(b, c, d, a, x[i + 4], 20, -405537848);\r\n a = md5gg(a, b, c, d, x[i + 9], 5, 568446438);\r\n d = md5gg(d, a, b, c, x[i + 14], 9, -1019803690);\r\n c = md5gg(c, d, a, b, x[i + 3], 14, -187363961);\r\n b = md5gg(b, c, d, a, x[i + 8], 20, 1163531501);\r\n a = md5gg(a, b, c, d, x[i + 13], 5, -1444681467);\r\n d = md5gg(d, a, b, c, x[i + 2], 9, -51403784);\r\n c = md5gg(c, d, a, b, x[i + 7], 14, 1735328473);\r\n b = md5gg(b, c, d, a, x[i + 12], 20, -1926607734);\r\n\r\n a = md5hh(a, b, c, d, x[i + 5], 4, -378558);\r\n d = md5hh(d, a, b, c, x[i + 8], 11, -2022574463);\r\n c = md5hh(c, d, a, b, x[i + 11], 16, 1839030562);\r\n b = md5hh(b, c, d, a, x[i + 14], 23, -35309556);\r\n a = md5hh(a, b, c, d, x[i + 1], 4, -1530992060);\r\n d = md5hh(d, a, b, c, x[i + 4], 11, 1272893353);\r\n c = md5hh(c, d, a, b, x[i + 7], 16, -155497632);\r\n b = md5hh(b, c, d, a, x[i + 10], 23, -1094730640);\r\n a = md5hh(a, b, c, d, x[i + 13], 4, 681279174);\r\n d = md5hh(d, a, b, c, x[i], 11, -358537222);\r\n c = md5hh(c, d, a, b, x[i + 3], 16, -722521979);\r\n b = md5hh(b, c, d, a, x[i + 6], 23, 76029189);\r\n a = md5hh(a, b, c, d, x[i + 9], 4, -640364487);\r\n d = md5hh(d, a, b, c, x[i + 12], 11, -421815835);\r\n c = md5hh(c, d, a, b, x[i + 15], 16, 530742520);\r\n b = md5hh(b, c, d, a, x[i + 2], 23, -995338651);\r\n\r\n a = md5ii(a, b, c, d, x[i], 6, -198630844);\r\n d = md5ii(d, a, b, c, x[i + 7], 10, 1126891415);\r\n c = md5ii(c, d, a, b, x[i + 14], 15, -1416354905);\r\n b = md5ii(b, c, d, a, x[i + 5], 21, -57434055);\r\n a = md5ii(a, b, c, d, x[i + 12], 6, 1700485571);\r\n d = md5ii(d, a, b, c, x[i + 3], 10, -1894986606);\r\n c = md5ii(c, d, a, b, x[i + 10], 15, -1051523);\r\n b = md5ii(b, c, d, a, x[i + 1], 21, -2054922799);\r\n a = md5ii(a, b, c, d, x[i + 8], 6, 1873313359);\r\n d = md5ii(d, a, b, c, x[i + 15], 10, -30611744);\r\n c = md5ii(c, d, a, b, x[i + 6], 15, -1560198380);\r\n b = md5ii(b, c, d, a, x[i + 13], 21, 1309151649);\r\n a = md5ii(a, b, c, d, x[i + 4], 6, -145523070);\r\n d = md5ii(d, a, b, c, x[i + 11], 10, -1120210379);\r\n c = md5ii(c, d, a, b, x[i + 2], 15, 718787259);\r\n b = md5ii(b, c, d, a, x[i + 9], 21, -343485551);\r\n\r\n a = safeAdd(a, olda);\r\n b = safeAdd(b, oldb);\r\n c = safeAdd(c, oldc);\r\n d = safeAdd(d, oldd);\r\n }\r\n return [a, b, c, d];\r\n}\r\n\r\n/**\r\n * Convert an array of little-endian words to a string\r\n *\r\n * @param {Array<number>} input MD5 Array\r\n * @returns {string} MD5 string\r\n */\r\nfunction binl2rstr(input) {\r\n var i;\r\n var output = \"\";\r\n var length32 = input.length * 32;\r\n for (i = 0; i < length32; i += 8) {\r\n output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xff);\r\n }\r\n return output;\r\n}\r\n\r\n/**\r\n * Convert a raw string to an array of little-endian words\r\n * Characters >255 have their high-byte silently ignored.\r\n *\r\n * @param {string} input Raw input string\r\n * @returns {Array<number>} Array of little-endian words\r\n */\r\nfunction rstr2binl(input) {\r\n var i;\r\n var output = [];\r\n output[(input.length >> 2) - 1] = undefined;\r\n for (i = 0; i < output.length; i += 1) {\r\n output[i] = 0;\r\n }\r\n var length8 = input.length * 8;\r\n for (i = 0; i < length8; i += 8) {\r\n output[i >> 5] |= (input.charCodeAt(i / 8) & 0xff) << (i % 32);\r\n }\r\n return output;\r\n}\r\n\r\n/**\r\n * Calculate the MD5 of a raw string\r\n *\r\n * @param {string} s Input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction rstrMD5(s) {\r\n return binl2rstr(binlMD5(rstr2binl(s), s.length * 8));\r\n}\r\n\r\n/**\r\n * Calculates the HMAC-MD5 of a key and some data (raw strings)\r\n *\r\n * @param {string} key HMAC key\r\n * @param {string} data Raw input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction rstrHMACMD5(key, data) {\r\n var i;\r\n var bkey = rstr2binl(key);\r\n var ipad = [];\r\n var opad = [];\r\n var hash;\r\n ipad[15] = opad[15] = undefined;\r\n if (bkey.length > 16) {\r\n bkey = binlMD5(bkey, key.length * 8);\r\n }\r\n for (i = 0; i < 16; i += 1) {\r\n ipad[i] = bkey[i] ^ 0x36363636;\r\n opad[i] = bkey[i] ^ 0x5c5c5c5c;\r\n }\r\n hash = binlMD5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);\r\n return binl2rstr(binlMD5(opad.concat(hash), 512 + 128));\r\n}\r\n\r\n/**\r\n * Convert a raw string to a hex string\r\n *\r\n * @param {string} input Raw input string\r\n * @returns {string} Hex encoded string\r\n */\r\nfunction rstr2hex(input) {\r\n var hexTab = \"0123456789abcdef\";\r\n var output = \"\";\r\n var x;\r\n var i;\r\n for (i = 0; i < input.length; i += 1) {\r\n x = input.charCodeAt(i);\r\n output += hexTab.charAt((x >>> 4) & 0x0f) + hexTab.charAt(x & 0x0f);\r\n }\r\n return output;\r\n}\r\n\r\n/**\r\n * Encode a string as UTF-8\r\n *\r\n * @param {string} input Input string\r\n * @returns {string} UTF8 string\r\n */\r\nfunction str2rstrUTF8(input) {\r\n return unescape(encodeURIComponent(input));\r\n}\r\n\r\n/**\r\n * Encodes input string as raw MD5 string\r\n *\r\n * @param {string} s Input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction rawMD5(s) {\r\n return rstrMD5(str2rstrUTF8(s));\r\n}\r\n/**\r\n * Encodes input string as Hex encoded string\r\n *\r\n * @param {string} s Input string\r\n * @returns {string} Hex encoded string\r\n */\r\nfunction hexMD5(s) {\r\n return rstr2hex(rawMD5(s));\r\n}\r\n/**\r\n * Calculates the raw HMAC-MD5 for the given key and data\r\n *\r\n * @param {string} k HMAC key\r\n * @param {string} d Input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction rawHMACMD5(k, d) {\r\n return rstrHMACMD5(str2rstrUTF8(k), str2rstrUTF8(d));\r\n}\r\n/**\r\n * Calculates the Hex encoded HMAC-MD5 for the given key and data\r\n *\r\n * @param {string} k HMAC key\r\n * @param {string} d Input string\r\n * @returns {string} Raw MD5 string\r\n */\r\nfunction hexHMACMD5(k, d) {\r\n return rstr2hex(rawHMACMD5(k, d));\r\n}\r\n\r\n/**\r\n * Calculates MD5 value for a given string.\r\n * If a key is provided, calculates the HMAC-MD5 value.\r\n * Returns a Hex encoded string unless the raw argument is given.\r\n *\r\n * @param {string} string Input string\r\n * @param {string} [key] HMAC key\r\n * @param {boolean} [raw] Raw output switch\r\n * @returns {string} MD5 output\r\n */\r\nfunction md5(string, key, raw) {\r\n if (!key) {\r\n if (!raw) {\r\n return hexMD5(string);\r\n }\r\n return rawMD5(string);\r\n }\r\n if (!raw) {\r\n return hexHMACMD5(key, string);\r\n }\r\n return rawHMACMD5(key, string);\r\n}\r\n\r\n/* 以下是内部实现需要的es模块化导出方法 */\r\nexport { md5 };\r\n","/**\r\n * 纯前端 SHA256/SHA224 实现(无 Node.js 依赖,兼容所有浏览器)\r\n * 核心逻辑借鉴 js-sha256,移除所有服务端相关代码,仅保留浏览器环境实现\r\n */\r\n\r\n// ========== 核心常量 ==========\r\nconst ERROR = \"input is invalid type\";\r\nconst HEX_CHARS = \"0123456789abcdef\".split(\"\");\r\nconst EXTRA = [-2147483648, 8388608, 32768, 128];\r\nconst SHIFT = [24, 16, 8, 0];\r\n// SHA256 常量 K\r\nconst K = [\r\n 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98,\r\n 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,\r\n 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8,\r\n 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\r\n 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,\r\n 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,\r\n 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,\r\n 0xc67178f2,\r\n];\r\n\r\n// ========== SHA256 核心类 ==========\r\nclass Sha256 {\r\n constructor(is224 = false) {\r\n // 初始化区块数组(仅浏览器环境,无需共享内存)\r\n this.blocks = new Array(17).fill(0);\r\n\r\n // 初始化哈希值(SHA224/SHA256 不同初始值)\r\n if (is224) {\r\n this.h0 = 0xc1059ed8;\r\n this.h1 = 0x367cd507;\r\n this.h2 = 0x3070dd17;\r\n this.h3 = 0xf70e5939;\r\n this.h4 = 0xffc00b31;\r\n this.h5 = 0x68581511;\r\n this.h6 = 0x64f98fa7;\r\n this.h7 = 0xbefa4fa4;\r\n } else {\r\n this.h0 = 0x6a09e667;\r\n this.h1 = 0xbb67ae85;\r\n this.h2 = 0x3c6ef372;\r\n this.h3 = 0xa54ff53a;\r\n this.h4 = 0x510e527f;\r\n this.h5 = 0x9b05688c;\r\n this.h6 = 0x1f83d9ab;\r\n this.h7 = 0x5be0cd19;\r\n }\r\n\r\n // 状态变量初始化\r\n this.block = this.start = this.bytes = this.hBytes = 0;\r\n this.finalized = this.hashed = false;\r\n this.first = true;\r\n this.is224 = is224;\r\n }\r\n\r\n // 更新哈希(处理输入数据)\r\n update(message) {\r\n if (this.finalized) return this;\r\n\r\n // 校验输入类型\r\n let notString = false;\r\n const type = typeof message;\r\n if (type !== \"string\") {\r\n if (type === \"object\") {\r\n if (message === null) throw new Error(ERROR);\r\n // 支持 ArrayBuffer/Uint8Array\r\n if (message.constructor === ArrayBuffer) {\r\n message = new Uint8Array(message);\r\n } else if (!Array.isArray(message) && !ArrayBuffer.isView(message)) {\r\n throw new Error(ERROR);\r\n }\r\n } else {\r\n throw new Error(ERROR);\r\n }\r\n notString = true;\r\n }\r\n\r\n let code,\r\n index = 0,\r\n i,\r\n length = message.length;\r\n const blocks = this.blocks;\r\n\r\n while (index < length) {\r\n if (this.hashed) {\r\n this.hashed = false;\r\n blocks.fill(0);\r\n blocks[0] = this.block;\r\n }\r\n\r\n // 处理字符串/字节数组\r\n if (notString) {\r\n for (i = this.start; index < length && i < 64; ++index) {\r\n blocks[i >>> 2] |= message[index] << SHIFT[i++ & 3];\r\n }\r\n } else {\r\n for (i = this.start; index < length && i < 64; ++index) {\r\n code = message.charCodeAt(index);\r\n // UTF-8 编码处理\r\n if (code < 0x80) {\r\n blocks[i >>> 2] |= code << SHIFT[i++ & 3];\r\n } else if (code < 0x800) {\r\n blocks[i >>> 2] |= (0xc0 | (code >>> 6)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\r\n } else if (code < 0xd800 || code >= 0xe000) {\r\n blocks[i >>> 2] |= (0xe0 | (code >>> 12)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | ((code >>> 6) & 0x3f)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\r\n } else {\r\n // 处理代理对\r\n code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));\r\n blocks[i >>> 2] |= (0xf0 | (code >>> 18)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | ((code >>> 12) & 0x3f)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | ((code >>> 6) & 0x3f)) << SHIFT[i++ & 3];\r\n blocks[i >>> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];\r\n }\r\n }\r\n }\r\n\r\n this.lastByteIndex = i;\r\n this.bytes += i - this.start;\r\n\r\n // 区块满 64 字节,进行哈希计算\r\n if (i >= 64) {\r\n this.block = blocks[16];\r\n this.start = i - 64;\r\n this.hash();\r\n this.hashed = true;\r\n } else {\r\n this.start = i;\r\n }\r\n }\r\n\r\n // 处理字节长度溢出\r\n if (this.bytes > 4294967295) {\r\n this.hBytes += (this.bytes / 4294967296) << 0;\r\n this.bytes = this.bytes % 4294967296;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n // 核心哈希计算\r\n hash() {\r\n let a = this.h0,\r\n b = this.h1,\r\n c = this.h2,\r\n d = this.h3;\r\n let e = this.h4,\r\n f = this.h5,\r\n g = this.h6,\r\n h = this.h7;\r\n const blocks = this.blocks;\r\n let j, s0, s1, maj, t1, t2, ch, ab, da, cd, bc;\r\n\r\n // 扩展区块\r\n for (j = 16; j < 64; ++j) {\r\n t1 = blocks[j - 15];\r\n s0 = ((t1 >>> 7) | (t1 << 25)) ^ ((t1 >>> 18) | (t1 << 14)) ^ (t1 >>> 3);\r\n t1 = blocks[j - 2];\r\n s1 = ((t1 >>> 17) | (t1 << 15)) ^ ((t1 >>> 19) | (t1 << 13)) ^ (t1 >>> 10);\r\n blocks[j] = (blocks[j - 16] + s0 + blocks[j - 7] + s1) << 0;\r\n }\r\n\r\n bc = b & c;\r\n // 64 轮哈希计算\r\n for (j = 0; j < 64; j += 4) {\r\n if (this.first) {\r\n if (this.is224) {\r\n ab = 300032;\r\n t1 = blocks[0] - 1413257819;\r\n h = (t1 - 150054599) << 0;\r\n d = (t1 + 24177077) << 0;\r\n } else {\r\n ab = 704751109;\r\n t1 = blocks[0] - 210244248;\r\n h = (t1 - 1521486534) << 0;\r\n d = (t1 + 143694565) << 0;\r\n }\r\n this.first = false;\r\n } else {\r\n s0 = ((a >>> 2) | (a << 30)) ^ ((a >>> 13) | (a << 19)) ^ ((a >>> 22) | (a << 10));\r\n s1 = ((e >>> 6) | (e << 26)) ^ ((e >>> 11) | (e << 21)) ^ ((e >>> 25) | (e << 7));\r\n ab = a & b;\r\n maj = ab ^ (a & c) ^ bc;\r\n ch = (e & f) ^ (~e & g);\r\n t1 = h + s1 + ch + K[j] + blocks[j];\r\n t2 = s0 + maj;\r\n h = (d + t1) << 0;\r\n d = (t1 + t2) << 0;\r\n }\r\n\r\n s0 = ((d >>> 2) | (d << 30)) ^ ((d >>> 13) | (d << 19)) ^ ((d >>> 22) | (d << 10));\r\n s1 = ((h >>> 6) | (h << 26)) ^ ((h >>> 11) | (h << 21)) ^ ((h >>> 25) | (h << 7));\r\n da = d & a;\r\n maj = da ^ (d & b) ^ ab;\r\n ch = (h & e) ^ (~h & f);\r\n t1 = g + s1 + ch + K[j + 1] + blocks[j + 1];\r\n t2 = s0 + maj;\r\n g = (c + t1) << 0;\r\n c = (t1 + t2) << 0;\r\n\r\n s0 = ((c >>> 2) | (c << 30)) ^ ((c >>> 13) | (c << 19)) ^ ((c >>> 22) | (c << 10));\r\n s1 = ((g >>> 6) | (g << 26)) ^ ((g >>> 11) | (g << 21)) ^ ((g >>> 25) | (g << 7));\r\n cd = c & d;\r\n maj = cd ^ (c & a) ^ da;\r\n ch = (g & h) ^ (~g & e);\r\n t1 = f + s1 + ch + K[j + 2] + blocks[j + 2];\r\n t2 = s0 + maj;\r\n f = (b + t1) << 0;\r\n b = (t1 + t2) << 0;\r\n\r\n s0 = ((b >>> 2) | (b << 30)) ^ ((b >>> 13) | (b << 19)) ^ ((b >>> 22) | (b << 10));\r\n s1 = ((f >>> 6) | (f << 26)) ^ ((f >>> 11) | (f << 21)) ^ ((f >>> 25) | (f << 7));\r\n bc = b & c;\r\n maj = bc ^ (b & d) ^ cd;\r\n ch = (f & g) ^ (~f & h);\r\n t1 = e + s1 + ch + K[j + 3] + blocks[j + 3];\r\n t2 = s0 + maj;\r\n e = (a + t1) << 0;\r\n a = (t1 + t2) << 0;\r\n }\r\n\r\n // 更新哈希值\r\n this.h0 = (this.h0 + a) << 0;\r\n this.h1 = (this.h1 + b) << 0;\r\n this.h2 = (this.h2 + c) << 0;\r\n this.h3 = (this.h3 + d) << 0;\r\n this.h4 = (this.h4 + e) << 0;\r\n this.h5 = (this.h5 + f) << 0;\r\n this.h6 = (this.h6 + g) << 0;\r\n this.h7 = (this.h7 + h) << 0;\r\n }\r\n\r\n // 完成哈希计算(补位)\r\n finalize() {\r\n if (this.finalized) return this;\r\n this.finalized = true;\r\n\r\n const blocks = this.blocks;\r\n let i = this.lastByteIndex;\r\n\r\n blocks[16] = this.block;\r\n blocks[i >>> 2] |= EXTRA[i & 3];\r\n this.block = blocks[16];\r\n\r\n // 补位处理\r\n if (i >= 56) {\r\n if (!this.hashed) this.hash();\r\n blocks.fill(0);\r\n blocks[0] = this.block;\r\n }\r\n\r\n // 写入长度信息\r\n blocks[14] = (this.hBytes << 3) | (this.bytes >>> 29);\r\n blocks[15] = this.bytes << 3;\r\n this.hash();\r\n\r\n return this;\r\n }\r\n\r\n // 输出十六进制字符串\r\n hex() {\r\n this.finalize();\r\n\r\n const h0 = this.h0,\r\n h1 = this.h1,\r\n h2 = this.h2,\r\n h3 = this.h3;\r\n const h4 = this.h4,\r\n h5 = this.h5,\r\n h6 = this.h6,\r\n h7 = this.h7;\r\n\r\n let hex = \"\";\r\n // 拼接哈希值为十六进制\r\n hex +=\r\n HEX_CHARS[(h0 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h0 >>> 4) & 0x0f] +\r\n HEX_CHARS[h0 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h1 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h1 >>> 4) & 0x0f] +\r\n HEX_CHARS[h1 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h2 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h2 >>> 4) & 0x0f] +\r\n HEX_CHARS[h2 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h3 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h3 >>> 4) & 0x0f] +\r\n HEX_CHARS[h3 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h4 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h4 >>> 4) & 0x0f] +\r\n HEX_CHARS[h4 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h5 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h5 >>> 4) & 0x0f] +\r\n HEX_CHARS[h5 & 0x0f];\r\n\r\n hex +=\r\n HEX_CHARS[(h6 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h6 >>> 4) & 0x0f] +\r\n HEX_CHARS[h6 & 0x0f];\r\n\r\n // SHA224 不需要 h7\r\n if (!this.is224) {\r\n hex +=\r\n HEX_CHARS[(h7 >>> 28) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 24) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 20) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 16) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 12) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 8) & 0x0f] +\r\n HEX_CHARS[(h7 >>> 4) & 0x0f] +\r\n HEX_CHARS[h7 & 0x0f];\r\n }\r\n\r\n return hex;\r\n }\r\n\r\n // 输出字节数组\r\n digest() {\r\n this.finalize();\r\n\r\n const h0 = this.h0,\r\n h1 = this.h1,\r\n h2 = this.h2,\r\n h3 = this.h3;\r\n const h4 = this.h4,\r\n h5 = this.h5,\r\n h6 = this.h6,\r\n h7 = this.h7;\r\n\r\n const arr = [\r\n (h0 >>> 24) & 0xff,\r\n (h0 >>> 16) & 0xff,\r\n (h0 >>> 8) & 0xff,\r\n h0 & 0xff,\r\n (h1 >>> 24) & 0xff,\r\n (h1 >>> 16) & 0xff,\r\n (h1 >>> 8) & 0xff,\r\n h1 & 0xff,\r\n (h2 >>> 24) & 0xff,\r\n (h2 >>> 16) & 0xff,\r\n (h2 >>> 8) & 0xff,\r\n h2 & 0xff,\r\n (h3 >>> 24) & 0xff,\r\n (h3 >>> 16) & 0xff,\r\n (h3 >>> 8) & 0xff,\r\n h3 & 0xff,\r\n (h4 >>> 24) & 0xff,\r\n (h4 >>> 16) & 0xff,\r\n (h4 >>> 8) & 0xff,\r\n h4 & 0xff,\r\n (h5 >>> 24) & 0xff,\r\n (h5 >>> 16) & 0xff,\r\n (h5 >>> 8) & 0xff,\r\n h5 & 0xff,\r\n (h6 >>> 24) & 0xff,\r\n (h6 >>> 16) & 0xff,\r\n (h6 >>> 8) & 0xff,\r\n h6 & 0xff,\r\n ];\r\n\r\n if (!this.is224) {\r\n arr.push((h7 >>> 24) & 0xff, (h7 >>> 16) & 0xff, (h7 >>> 8) & 0xff, h7 & 0xff);\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n // 输出二进制原始字符串(raw)\r\n raw() {\r\n this.finalize();\r\n const bytes = this.digest();\r\n let rawStr = \"\";\r\n for (let i = 0; i < bytes.length; i++) {\r\n rawStr += String.fromCharCode(bytes[i]);\r\n }\r\n return rawStr;\r\n }\r\n\r\n // 输出 ArrayBuffer\r\n arrayBuffer() {\r\n this.finalize();\r\n const buffer = new ArrayBuffer(this.is224 ? 28 : 32);\r\n const dataView = new DataView(buffer);\r\n dataView.setUint32(0, this.h0);\r\n dataView.setUint32(4, this.h1);\r\n dataView.setUint32(8, this.h2);\r\n dataView.setUint32(12, this.h3);\r\n dataView.setUint32(16, this.h4);\r\n dataView.setUint32(20, this.h5);\r\n dataView.setUint32(24, this.h6);\r\n if (!this.is224) {\r\n dataView.setUint32(28, this.h7);\r\n }\r\n return buffer;\r\n }\r\n}\r\n\r\n// ========== HMAC-SHA256 实现 ==========\r\nclass HmacSha256 {\r\n constructor(key, is224 = false) {\r\n // 处理密钥\r\n let keyBytes = [];\r\n const type = typeof key;\r\n\r\n if (type === \"string\") {\r\n // 字符串密钥转字节数组\r\n let code,\r\n index = 0,\r\n length = key.length;\r\n for (let i = 0; i < length; ++i) {\r\n code = key.charCodeAt(i);\r\n if (code < 0x80) {\r\n keyBytes[index++] = code;\r\n } else if (code < 0x800) {\r\n keyBytes[index++] = 0xc0 | (code >>> 6);\r\n keyBytes[index++] = 0x80 | (code & 0x3f);\r\n } else if (code < 0xd800 || code >= 0xe000) {\r\n keyBytes[index++] = 0xe0 | (code >>> 12);\r\n keyBytes[index++] = 0x80 | ((code >>> 6) & 0x3f);\r\n keyBytes[index++] = 0x80 | (code & 0x3f);\r\n } else {\r\n code = 0x10000 + (((code & 0x3ff) << 10) | (key.charCodeAt(++i) & 0x3ff));\r\n keyBytes[index++] = 0xf0 | (code >>> 18);\r\n keyBytes[index++] = 0x80 | ((code >>> 12) & 0x3f);\r\n keyBytes[index++] = 0x80 | ((code >>> 6) & 0x3f);\r\n keyBytes[index++] = 0x80 | (code & 0x3f);\r\n }\r\n }\r\n } else if (type === \"object\") {\r\n if (key === null) throw new Error(ERROR);\r\n if (key.constructor === ArrayBuffer) {\r\n keyBytes = Array.from(new Uint8Array(key));\r\n } else if (Array.isArray(key) || ArrayBuffer.isView(key)) {\r\n keyBytes = Array.from(key);\r\n } else {\r\n throw new Error(ERROR);\r\n }\r\n } else {\r\n throw new Error(ERROR);\r\n }\r\n\r\n // 密钥长度超过 64 字节,先哈希\r\n if (keyBytes.length > 64) {\r\n keyBytes = new Sha256(is224).update(keyBytes).digest();\r\n }\r\n\r\n // 生成内外填充\r\n const oKeyPad = [];\r\n const iKeyPad = [];\r\n for (let i = 0; i < 64; ++i) {\r\n const b = keyBytes[i] || 0;\r\n oKeyPad[i] = 0x5c ^ b;\r\n iKeyPad[i] = 0x36 ^ b;\r\n }\r\n\r\n // 初始化 SHA256\r\n this.sha256 = new Sha256(is224);\r\n this.sha256.update(iKeyPad);\r\n this.oKeyPad = oKeyPad;\r\n this.is224 = is224;\r\n this.inner = true;\r\n }\r\n\r\n update(message) {\r\n this.sha256.update(message);\r\n return this;\r\n }\r\n\r\n finalize() {\r\n if (this.inner) {\r\n // 计算内部哈希\r\n const innerHash = this.sha256.digest();\r\n // 初始化外部哈希\r\n this.sha256 = new Sha256(this.is224);\r\n this.sha256.update(this.oKeyPad).update(innerHash);\r\n this.inner = false;\r\n }\r\n this.sha256.finalize();\r\n return this;\r\n }\r\n\r\n hex() {\r\n this.finalize();\r\n return this.sha256.hex();\r\n }\r\n\r\n digest() {\r\n this.finalize();\r\n return this.sha256.digest();\r\n }\r\n\r\n raw() {\r\n this.finalize();\r\n return this.sha256.raw();\r\n }\r\n\r\n arrayBuffer() {\r\n this.finalize();\r\n return this.sha256.arrayBuffer();\r\n }\r\n}\r\n\r\n// ========== 便捷方法封装 ==========\r\nconst createMethod = (is224 = false) => {\r\n const method = (message) => new Sha256(is224).update(message).hex();\r\n method.raw = (message) => new Sha256(is224).update(message).raw();\r\n method.digest = (message) => new Sha256(is224).update(message).digest();\r\n method.arrayBuffer = (message) => new Sha256(is224).update(message).arrayBuffer();\r\n method.create = () => new Sha256(is224);\r\n method.update = (message) => method.create().update(message);\r\n return method;\r\n};\r\nconst createRawMethod = (is224 = false) => {\r\n const method = (message) => new Sha256(is224).update(message).raw();\r\n method.hex = (message) => new Sha256(is224).update(message).hex();\r\n method.digest = (message) => new Sha256(is224).update(message).digest();\r\n method.arrayBuffer = (message) => new Sha256(is224).update(message).arrayBuffer();\r\n method.create = () => new Sha256(is224);\r\n method.update = (message) => method.create().update(message);\r\n return method;\r\n};\r\nconst createHmacMethod = (is224 = false) => {\r\n const method = (key, message) => new HmacSha256(key, is224).update(message).hex();\r\n method.raw = (key, message) => new HmacSha256(key, is224).update(message).raw();\r\n method.digest = (key, message) => new HmacSha256(key, is224).update(message).digest();\r\n method.arrayBuffer = (key, message) => new HmacSha256(key, is224).update(message).arrayBuffer();\r\n method.create = (key) => new HmacSha256(key, is224);\r\n method.update = (key, message) => method.create(key).update(message);\r\n return method;\r\n};\r\nconst createHmacRawMethod = (is224 = false) => {\r\n const method = (key, message) => new HmacSha256(key, is224).update(message).raw();\r\n method.hex = (key, message) => new HmacSha256(key, is224).update(message).hex();\r\n method.digest = (key, message) => new HmacSha256(key, is224).update(message).digest();\r\n method.arrayBuffer = (key, message) => new HmacSha256(key, is224).update(message).arrayBuffer();\r\n method.create = (key) => new HmacSha256(key, is224);\r\n method.update = (key, message) => method.create(key).update(message);\r\n return method;\r\n};\r\n\r\n/* 以下是内部实现需要的es模块化导出方法 */\r\n// SHA256 基础方法\r\nexport const sha256 = createMethod();\r\n// SHA256 基础方法原始值\r\nexport const sha256_raw = createRawMethod();\r\n// HMAC-SHA256\r\nexport const sha256_hmac = createHmacMethod();\r\n// HMAC-SHA256原始值\r\nexport const sha256_hmac_raw = createHmacRawMethod();\r\n\r\n// SHA224 基础方法\r\nexport const sha224 = createMethod(true);\r\n// SHA224 基础方法原始值\r\nexport const sha224_raw = createRawMethod(true);\r\n// HMAC-SHA224\r\nexport const sha224_hmac = createHmacMethod(true);\r\n// HMAC-SHA224原始值\r\nexport const sha224_hmac_raw = createHmacRawMethod(true);\r\n","/**\r\n * SM3 纯函数式实现(无类、无实例,闭包隔离状态)\r\n */\r\n\r\n// 全局常量(只读,无状态)\r\nconst BLOCK_LENGTH = 64;\r\nconst IPAD = new Uint8Array(BLOCK_LENGTH).fill(0x36);\r\nconst OPAD = new Uint8Array(BLOCK_LENGTH).fill(0x5c);\r\nconst IV = new Uint32Array([\r\n 0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e,\r\n]);\r\n\r\n// 纯函数:循环左移\r\nfunction rotl(x, n) {\r\n const s = n & 31;\r\n return (x << s) | (x >>> (32 - s));\r\n}\r\n\r\n// 纯函数:字节数组异或\r\nfunction xor(x, y) {\r\n const result = [];\r\n for (let i = x.length - 1; i >= 0; i--) {\r\n result[i] = (x[i] ^ y[i]) & 0xff;\r\n }\r\n return result;\r\n}\r\n\r\n// 纯函数:置换函数 P0\r\nfunction P0(X) {\r\n return X ^ rotl(X, 9) ^ rotl(X, 17);\r\n}\r\n\r\n// 纯函数:置换函数 P1\r\nfunction P1(X) {\r\n return X ^ rotl(X, 15) ^ rotl(X, 23);\r\n}\r\n\r\n// 纯函数:补全16进制字符串\r\nfunction leftPad(input, num) {\r\n if (input.length >= num) return input;\r\n return new Array(num - input.length + 1).join(\"0\") + input;\r\n}\r\n\r\n// 纯函数:字节数组转16进制\r\nfunction arrayToHex(arr) {\r\n return arr\r\n .map((item) => {\r\n item = item.toString(16);\r\n return item.length === 1 ? \"0\" + item : item;\r\n })\r\n .join(\"\");\r\n}\r\n\r\n// 纯函数:16进制转字节数组\r\nfunction hexToArray(hexStr) {\r\n const words = [];\r\n let hexStrLength = hexStr.length;\r\n if (hexStrLength % 2 !== 0) {\r\n hexStr = leftPad(hexStr, hexStrLength + 1);\r\n }\r\n hexStrLength = hexStr.length;\r\n for (let i = 0; i < hexStrLength; i += 2) {\r\n words.push(parseInt(hexStr.substr(i, 2), 16));\r\n }\r\n return words;\r\n}\r\n\r\n// 纯函数:UTF8转字节数组\r\nfunction utf8ToArray(str) {\r\n const arr = [];\r\n for (let i = 0, len = str.length; i < len; i++) {\r\n const point = str.codePointAt(i);\r\n if (point <= 0x007f) {\r\n arr.push(point);\r\n } else if (point <= 0x07ff) {\r\n arr.push(0xc0 | (point >>> 6));\r\n arr.push(0x80 | (point & 0x3f));\r\n } else if (point <= 0xd7ff || (point >= 0xe000 && point <= 0xffff)) {\r\n arr.push(0xe0 | (point >>> 12));\r\n arr.push(0x80 | ((point >>> 6) & 0x3f));\r\n arr.push(0x80 | (point & 0x3f));\r\n } else if (point >= 0x010000 && point <= 0x10ffff) {\r\n i++;\r\n arr.push(0xf0 | ((point >>> 18) & 0x1c));\r\n arr.push(0x80 | ((point >>> 12) & 0x3f));\r\n arr.push(0x80 | ((point >>> 6) & 0x3f));\r\n arr.push(0x80 | (point & 0x3f));\r\n } else {\r\n arr.push(point);\r\n throw new TypeError(\"utf8ToArray: input is not supported in sm3\");\r\n }\r\n }\r\n return arr;\r\n}\r\n\r\n// 核心纯函数:SM3哈希计算(闭包隔离状态)\r\nfunction sm3Core(array) {\r\n // 每次调用都创建全新的局部状态(隔离关键)\r\n let len = array.length * 8;\r\n let k = len % 512;\r\n k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1;\r\n const kArr = new Array((k - 7) / 8).fill(0);\r\n const lenArr = new Array(8).fill(0);\r\n let lenBin = len.toString(2);\r\n for (let i = 7; i >= 0; i--) {\r\n if (lenBin.length > 8) {\r\n const start = lenBin.length - 8;\r\n lenArr[i] = parseInt(lenBin.substr(start), 2);\r\n lenBin = lenBin.substr(0, start);\r\n } else if (lenBin.length > 0) {\r\n lenArr[i] = parseInt(lenBin, 2);\r\n lenBin = \"\";\r\n }\r\n }\r\n const m = new Uint8Array([...array, 0x80, ...kArr, ...lenArr]);\r\n const dataView = new DataView(m.buffer, 0);\r\n const n = m.length / 64;\r\n const V = new Uint32Array(IV); // 全新初始向量(每次调用重新创建)\r\n const W = new Uint32Array(68); // 全新消息扩展数组\r\n const M = new Uint32Array(64); // 全新W'数组\r\n\r\n // 以下计算逻辑和原代码一致,仅操作局部变量\r\n for (let i = 0; i < n; i++) {\r\n W.fill(0);\r\n M.fill(0);\r\n const start = 16 * i;\r\n for (let j = 0; j < 16; j++) {\r\n W[j] = dataView.getUint32((start + j) * 4, false);\r\n }\r\n for (let j = 16; j < 68; j++) {\r\n W[j] = P1(W[j - 16] ^ W[j - 9] ^ rotl(W[j - 3], 15)) ^ rotl(W[j - 13], 7) ^ W[j - 6];\r\n }\r\n for (let j = 0; j < 64; j++) {\r\n M[j] = W[j] ^ W[j + 4];\r\n }\r\n const T1 = 0x79cc4519;\r\n const T2 = 0x7a879d8a;\r\n let A = V[0],\r\n B = V[1],\r\n C = V[2],\r\n D = V[3];\r\n let E = V[4],\r\n F = V[5],\r\n G = V[6],\r\n H = V[7];\r\n let SS1, SS2, TT1, TT2, T;\r\n\r\n for (let j = 0; j < 64; j++) {\r\n T = j <= 15 ? T1 : T2;\r\n SS1 = rotl((rotl(A, 12) + E + rotl(T, j)) & 0xffffffff, 7);\r\n SS2 = SS1 ^ rotl(A, 12);\r\n const FFj = j <= 15 ? A ^ B ^ C : (A & B) | (A & C) | (B & C);\r\n const GGj = j <= 15 ? E ^ F ^ G : (E & F) | (~E & G);\r\n TT1 = (FFj + D + SS2 + M[j]) & 0xffffffff;\r\n TT2 = (GGj + H + SS1 + W[j]) & 0xffffffff;\r\n\r\n D = C;\r\n C = rotl(B, 9);\r\n B = A;\r\n A = TT1;\r\n H = G;\r\n G = rotl(F, 19);\r\n F = E;\r\n E = P0(TT2);\r\n }\r\n V[0] ^= A;\r\n V[1] ^= B;\r\n V[2] ^= C;\r\n V[3] ^= D;\r\n V[4] ^= E;\r\n V[5] ^= F;\r\n V[6] ^= G;\r\n V[7] ^= H;\r\n }\r\n const result = [];\r\n for (let i = 0; i < V.length; i++) {\r\n result.push((V[i] & 0xff000000) >>> 24, (V[i] & 0xff0000) >>> 16, (V[i] & 0xff00) >>> 8, V[i] & 0xff);\r\n }\r\n return result;\r\n}\r\n\r\n// 纯函数:HMAC-SM3计算\r\nfunction encryptHmac(input, key) {\r\n let processedKey = key.length > BLOCK_LENGTH ? sm3Core(key) : [...key];\r\n while (processedKey.length < BLOCK_LENGTH) {\r\n processedKey.push(0);\r\n }\r\n const iPadKey = xor(processedKey, IPAD);\r\n const oPadKey = xor(processedKey, OPAD);\r\n const innerHash = sm3Core([...iPadKey, ...input]);\r\n return sm3Core([...oPadKey, ...innerHash]);\r\n}\r\n\r\n// 对外暴露的核心函数(兼容原调用方式)\r\nfunction encrypt(input, key) {\r\n const inputArr = typeof input === \"string\" ? utf8ToArray(input) : Array.prototype.slice.call(input);\r\n\r\n if (!key) {\r\n const hashArr = sm3Core(inputArr);\r\n return arrayToHex(hashArr);\r\n } else {\r\n const keyArr =\r\n typeof key === \"string\"\r\n ? /^[0-9a-fA-F]+$/.test(key)\r\n ? hexToArray(key)\r\n : utf8ToArray(key)\r\n : Array.prototype.slice.call(key);\r\n const hmacArr = encryptHmac(inputArr, keyArr);\r\n return arrayToHex(hmacArr);\r\n }\r\n}\r\n\r\n/* 以下是内部实现需要的es模块化导出方法 */\r\nexport { encrypt, encryptHmac as encrypt_hmac };\r\n","// ========== 常量定义(规范化,避免魔法值) ==========\r\nconst SM4_MODE_ECB = \"ecb\";\r\nconst SM4_MODE_CBC = \"cbc\";\r\nconst SM4_PADDING = \"pkcs#7\";\r\nconst SM4_OUTPUT_HEX = \"hex\";\r\nconst SM4_OUTPUT_UTF8 = \"utf8\";\r\nconst SM4_OUTPUT_ARRAY = \"array\";\r\nconst SM4_OUTPUT_UINT8ARRAY = \"uint8array\";\r\nconst SM4_OUTPUT_ARRAYBUFFER = \"arraybuffer\";\r\n\r\nconst ENCRYPT = 1;\r\nconst DECRYPT = 0;\r\nconst ROUND_COUNT = 32;\r\nconst BLOCK_SIZE = 16; // 128比特 = 16字节\r\nconst KEY_SIZE = 16; // SM4密钥固定128比特\r\nconst IV_SIZE = 16; // CBC模式IV固定128比特\r\n\r\n// SM4 S盒\r\nconst SBOX = new Uint8Array([\r\n 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, 0x2b, 0x67, 0x9a,\r\n 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef,\r\n 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80,\r\n 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19,\r\n 0xe6, 0x85, 0x4f, 0xa8, 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d,\r\n 0x35, 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, 0xd4, 0x00,\r\n 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, 0xea, 0xbf, 0x8a, 0xd2, 0x40,\r\n 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55,\r\n 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23,\r\n 0xab, 0x0d, 0x53, 0x4e, 0x6f, 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c,\r\n 0x5b, 0x51, 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, 0x0a,\r\n 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, 0x89, 0x69, 0x97, 0x4a,\r\n 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d,\r\n 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,\r\n]);\r\n\r\n// 轮常量 CK\r\nconst CK = new Uint32Array([\r\n 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, 0xe0e7eef5,\r\n 0xfc030a11, 0x181f262d, 0x343b4249, 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, 0xc0c7ced5, 0xdce3eaf1,\r\n 0xf8ff060d, 0x141b2229, 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed,\r\n 0xf4fb0209, 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279,\r\n]);\r\n\r\n// 系统参数 FK\r\nconst FK = new Uint32Array([0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc]);\r\n\r\n// ========== 工具函数(通用转换) ==========\r\n/**\r\n * 16进制字符串转Uint8Array\r\n * @param {string} str - 16进制字符串\r\n * @returns {Uint8Array} 字节数组\r\n */\r\nfunction hexToUint8Array(str) {\r\n str = str.replace(/\\s+/g, \"\"); // 去除空格\r\n if (str.length % 2 !== 0) throw new TypeError(\"hexToUint8Array: hex string length must be even from sm4\");\r\n\r\n const arr = new Uint8Array(str.length / 2);\r\n for (let i = 0; i < str.length; i += 2) {\r\n arr[i / 2] = parseInt(str.substr(i, 2), 16) & 0xff;\r\n }\r\n return arr;\r\n}\r\n\r\n/**\r\n * Uint8Array转16进制字符串\r\n * @param {Uint8Array} arr - 字节数组\r\n * @returns {string} 16进制字符串\r\n */\r\nfunction uint8ArrayToHex(arr) {\r\n return Array.from(arr)\r\n .map((byte) => {\r\n const hex = byte.toString(16);\r\n return hex.length === 1 ? \"0\" + hex : hex;\r\n })\r\n .join(\"\");\r\n}\r\n\r\n/**\r\n * UTF8字符串转Uint8Array\r\n * @param {string} str - UTF8字符串\r\n * @returns {Uint8Array} 字节数组\r\n */\r\nfunction utf8ToUint8Array(str) {\r\n return new TextEncoder().encode(str);\r\n}\r\n\r\n/**\r\n * Uint8Array转UTF8字符串\r\n * @param {Uint8Array} arr - 字节数组\r\n * @returns {string} UTF8字符串\r\n */\r\nfunction uint8ArrayToUtf8(arr) {\r\n return new TextDecoder(\"utf-8\").decode(arr);\r\n}\r\n\r\n/**\r\n * 统一输入数据格式为Uint8Array\r\n * @param {string|Array|Uint8Array|ArrayBuffer} input - 输入数据\r\n * @param {number} cryptFlag - ENCRYPT/DECRYPT\r\n * @returns {Uint8Array} 标准化后的字节数组\r\n */\r\nfunction normalizeInput(input, cryptFlag) {\r\n if (input instanceof ArrayBuffer) {\r\n return new Uint8Array(input);\r\n }\r\n if (input instanceof Uint8Array) {\r\n return new Uint8Array(input); // 拷贝避免修改原数组\r\n }\r\n if (Array.isArray(input)) {\r\n return new Uint8Array(input);\r\n }\r\n if (typeof input === \"string\") {\r\n if (cryptFlag === ENCRYPT) {\r\n // 加密:字符串按UTF8转字节\r\n return utf8ToUint8Array(input);\r\n } else {\r\n // 解密:字符串按16进制转字节\r\n return hexToUint8Array(input);\r\n }\r\n }\r\n throw new TypeError(`normalizeInput: unsupported input type: ${typeof input} from sm4`);\r\n}\r\n\r\n/**\r\n * 标准化密钥/IV为Uint8Array\r\n * @param {string|Array|Uint8Array|ArrayBuffer} keyOrIv - 密钥/IV\r\n * @param {number} expectedLength - 期望长度(字节)\r\n * @param {string} name - 名称(用于报错)\r\n * @returns {Uint8Array} 标准化后的字节数组\r\n */\r\nfunction normalizeKeyIv(keyOrIv, expectedLength, name) {\r\n let arr;\r\n if (typeof keyOrIv === \"string\") {\r\n arr = hexToUint8Array(keyOrIv);\r\n } else if (keyOrIv instanceof ArrayBuffer) {\r\n arr = new Uint8Array(keyOrIv);\r\n } else if (keyOrIv instanceof Uint8Array) {\r\n arr = keyOrIv;\r\n } else if (Array.isArray(keyOrIv)) {\r\n arr = new Uint8Array(keyOrIv);\r\n } else {\r\n throw new TypeError(`normalizeKeyIv: unsupported ${name} type: ${typeof keyOrIv} from sm4`);\r\n }\r\n\r\n if (arr.length !== expectedLength) {\r\n throw new TypeError(\r\n `normalizeKeyIv: ${name} must be ${expectedLength * 8} bits (${expectedLength} bytes) from sm4`,\r\n );\r\n }\r\n return arr;\r\n}\r\n\r\n// ========== SM4核心函数 ==========\r\n/**\r\n * 32比特循环左移\r\n * @param {number} x - 32比特无符号整数\r\n * @param {number} n - 移位位数\r\n * @returns {number} 移位结果\r\n */\r\nfunction rotl32(x, n) {\r\n const s = n & 31;\r\n return ((x << s) | (x >>> (32 - s))) >>> 0; // >>>0 确保无符号\r\n}\r\n\r\n/**\r\n * 非线性变换(字节替换)\r\n * @param {number} a - 32比特无符号整数\r\n * @returns {number} 替换结果\r\n */\r\nfunction byteSub(a) {\r\n return (\r\n ((SBOX[(a >>> 24) & 0xff] << 24) |\r\n (SBOX[(a >>> 16) & 0xff] << 16) |\r\n (SBOX[(a >>> 8) & 0xff] << 8) |\r\n SBOX[a & 0xff]) >>>\r\n 0\r\n );\r\n}\r\n\r\n/**\r\n * 线性变换(加密/解密用)\r\n * @param {number} b - 32比特无符号整数\r\n * @returns {number} 变换结果\r\n */\r\nfunction linearTransformEnc(b) {\r\n return (b ^ rotl32(b, 2) ^ rotl32(b, 10) ^ rotl32(b, 18) ^ rotl32(b, 24)) >>> 0;\r\n}\r\n\r\n/**\r\n * 线性变换(密钥扩展用)\r\n * @param {number} b - 32比特无符号整数\r\n * @returns {number} 变换结果\r\n */\r\nfunction linearTransformKey(b) {\r\n return (b ^ rotl32(b, 13) ^ rotl32(b, 23)) >>> 0;\r\n}\r\n\r\n/**\r\n * SM4单块加密/解密(128比特)\r\n * @param {Uint8Array} inputBlock - 输入块(16字节)\r\n * @param {Uint8Array} outputBlock - 输出块(16字节)\r\n * @param {Uint32Array} roundKeys - 轮密钥(32个32比特)\r\n */\r\nfunction sm4BlockCrypt(inputBlock, outputBlock, roundKeys) {\r\n // 确保输入块是16字节\r\n if (inputBlock.length !== BLOCK_SIZE) {\r\n throw new TypeError(`sm4BlockCrypt: input block must be ${BLOCK_SIZE} bytes for block crypt from sm4`);\r\n }\r\n\r\n // 字节数组转32比特字数组(4个字,共128比特)\r\n const x = new Uint32Array(4);\r\n for (let i = 0; i < 4; i++) {\r\n const offset = 4 * i;\r\n x[i] =\r\n ((inputBlock[offset] << 24) |\r\n (inputBlock[offset + 1] << 16) |\r\n (inputBlock[offset + 2] << 8) |\r\n inputBlock[offset + 3]) >>>\r\n 0;\r\n }\r\n\r\n // 32轮加密\r\n for (let r = 0; r < ROUND_COUNT; r += 4) {\r\n let mid = (x[1] ^ x[2] ^ x[3] ^ roundKeys[r]) >>> 0;\r\n x[0] ^= linearTransformEnc(byteSub(mid));\r\n\r\n mid = (x[2] ^ x[3] ^ x[0] ^ roundKeys[r + 1]) >>> 0;\r\n x[1] ^= linearTransformEnc(byteSub(mid));\r\n\r\n mid = (x[3] ^ x[0] ^ x[1] ^ roundKeys[r + 2]) >>> 0;\r\n x[2] ^= linearTransformEnc(byteSub(mid));\r\n\r\n mid = (x[0] ^ x[1] ^ x[2] ^ roundKeys[r + 3]) >>> 0;\r\n x[3] ^= linearTransformEnc(byteSub(mid));\r\n }\r\n\r\n // 反序输出\r\n for (let j = 0; j < BLOCK_SIZE; j += 4) {\r\n const wordIdx = 3 - j / 4;\r\n outputBlock[j] = (x[wordIdx] >>> 24) & 0xff;\r\n outputBlock[j + 1] = (x[wordIdx] >>> 16) & 0xff;\r\n outputBlock[j + 2] = (x[wordIdx] >>> 8) & 0xff;\r\n outputBlock[j + 3] = x[wordIdx] & 0xff;\r\n }\r\n}\r\n\r\n/**\r\n * SM4密钥扩展算法\r\n * @param {Uint8Array} key - 16字节密钥\r\n * @param {Uint32Array} roundKeys - 输出轮密钥(32个32比特)\r\n * @param {number} cryptFlag - ENCRYPT/DECRYPT\r\n */\r\nfunction sm4KeyExpansion(key, roundKeys, cryptFlag) {\r\n // 密钥转32比特字数组\r\n const x = new Uint32Array(4);\r\n for (let i = 0; i < 4; i++) {\r\n const offset = 4 * i;\r\n x[i] = ((key[offset] << 24) | (key[offset + 1] << 16) | (key[offset + 2] << 8) | key[offset + 3]) >>> 0;\r\n }\r\n\r\n // 与系统参数异或\r\n x[0] ^= FK[0];\r\n x[1] ^= FK[1];\r\n x[2] ^= FK[2];\r\n x[3] ^= FK[3];\r\n\r\n // 生成轮密钥\r\n for (let r = 0; r < ROUND_COUNT; r += 4) {\r\n let mid = (x[1] ^ x[2] ^ x[3] ^ CK[r]) >>> 0;\r\n roundKeys[r] = x[0] ^= linearTransformKey(byteSub(mid));\r\n\r\n mid = (x[2] ^ x[3] ^ x[0] ^ CK[r + 1]) >>> 0;\r\n roundKeys[r + 1] = x[1] ^= linearTransformKey(byteSub(mid));\r\n\r\n mid = (x[3] ^ x[0] ^ x[1] ^ CK[r + 2]) >>> 0;\r\n roundKeys[r + 2] = x[2] ^= linearTransformKey(byteSub(mid));\r\n\r\n mid = (x[0] ^ x[1] ^ x[2] ^ CK[r + 3]) >>> 0;\r\n roundKeys[r + 3] = x[3] ^= linearTransformKey(byteSub(mid));\r\n }\r\n\r\n // 解密时轮密钥反序\r\n if (cryptFlag === DECRYPT) {\r\n for (let r = 0; r < 16; r++) {\r\n const temp = roundKeys[r];\r\n roundKeys[r] = roundKeys[31 - r];\r\n roundKeys[31 - r] = temp;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * PKCS#7填充\r\n * @param {Uint8Array} data - 原始数据\r\n * @returns {Uint8Array} 填充后的数据\r\n */\r\nfunction pkcs7Pad(data) {\r\n const paddingCount = BLOCK_SIZE - (data.length % BLOCK_SIZE);\r\n const padded = new Uint8Array(data.length + paddingCount);\r\n padded.set(data);\r\n for (let i = 0; i < paddingCount; i++) {\r\n padded[data.length + i] = paddingCount & 0xff;\r\n }\r\n return padded;\r\n}\r\n\r\n/**\r\n * PKCS#7去填充\r\n * @param {Uint8Array} data - 填充后的数据\r\n * @returns {Uint8Array} 去填充后的数据\r\n */\r\nfunction pkcs7Unpad(data) {\r\n const paddingCount = data[data.length - 1] & 0xff;\r\n // 验证填充合法性\r\n for (let i = 1; i <= paddingCount; i++) {\r\n if (data[data.length - i] !== paddingCount) {\r\n throw new TypeError(\"pkcs7Unpad: invalid PKCS#7 padding from sm4\");\r\n }\r\n }\r\n return data.subarray(0, data.length - paddingCount);\r\n}\r\n\r\n/**\r\n * SM4主函数\r\n * @param {string|Array|Uint8Array|ArrayBuffer} inputData - 输入数据\r\n * @param {string|Array|Uint8Array|ArrayBuffer} key - 16字节密钥\r\n * @param {number} cryptFlag - ENCRYPT/DECRYPT\r\n * @param {Object} [options] - 选项\r\n * @param {string} [options.mode=ecb] - 模式:ecb/cbc\r\n * @param {string|Array|Uint8Array|ArrayBuffer} [options.iv] - CBC模式IV(16字节)\r\n * @param {string} [options.padding=pkcs#7] - 填充方式:pkcs#7\r\n * @param {string} [options.output] - 输出格式:hex/utf8/array/uint8array/arraybuffer\r\n * @returns {string|Array|Uint8Array|ArrayBuffer} 输出数据\r\n */\r\nfunction sm4Core(inputData, key, cryptFlag, options = {}) {\r\n // 默认参数(加密和解密默认输出都为hex,避免格式不匹配)\r\n const {\r\n mode = SM4_MODE_ECB,\r\n iv = [],\r\n padding = SM4_PADDING,\r\n output = SM4_OUTPUT_HEX, // 统一默认hex格式\r\n } = options;\r\n\r\n // 校验模式\r\n if (![SM4_MODE_ECB, SM4_MODE_CBC].includes(mode)) {\r\n throw new TypeError(`sm4Core: unsupported mode: ${mode}, only 'ecb' and 'cbc' are supported from sm4`);\r\n }\r\n\r\n // 标准化输入、密钥、IV\r\n const input = normalizeInput(inputData, cryptFlag);\r\n const keyBytes = normalizeKeyIv(key, KEY_SIZE, \"key\");\r\n let ivBytes = new Uint8Array(IV_SIZE);\r\n if (mode === SM4_MODE_CBC) {\r\n ivBytes = normalizeKeyIv(iv, IV_SIZE, \"IV\");\r\n }\r\n\r\n // 填充(仅加密时)\r\n let processedInput = input;\r\n if (padding === SM4_PADDING && cryptFlag === ENCRYPT) {\r\n processedInput = pkcs7Pad(input);\r\n // 确保填充后是16字节的倍数\r\n if (processedInput.length % BLOCK_SIZE !== 0) {\r\n throw new TypeError(\"sm4Core: PKCS7 padding failed: data length is not multiple of block size from sm4\");\r\n }\r\n }\r\n\r\n // 生成轮密钥\r\n const roundKeys = new Uint32Array(ROUND_COUNT);\r\n sm4KeyExpansion(keyBytes, roundKeys, cryptFlag);\r\n\r\n // 初始化输出缓冲区\r\n const outputData = new Uint8Array(processedInput.length);\r\n let lastVector = new Uint8Array(ivBytes); // CBC模式向量\r\n let point = 0;\r\n\r\n // 分块处理(严格按16字节分块)\r\n while (point < processedInput.length) {\r\n const inputBlock = processedInput.subarray(point, point + BLOCK_SIZE);\r\n const outputBlock = new Uint8Array(BLOCK_SIZE);\r\n\r\n if (mode === SM4_MODE_CBC) {\r\n if (cryptFlag === ENCRYPT) {\r\n // CBC加密:输入块与前向量异或\r\n const xorBlock = new Uint8Array(BLOCK_SIZE);\r\n for (let i = 0; i < BLOCK_SIZE; i++) {\r\n xorBlock[i] = (inputBlock[i] ^ lastVector[i]) & 0xff;\r\n }\r\n sm4BlockCrypt(xorBlock, outputBlock, roundKeys);\r\n } else {\r\n // CBC解密:先加密再异或\r\n sm4BlockCrypt(inputBlock, outputBlock, roundKeys);\r\n for (let i = 0; i < BLOCK_SIZE; i++) {\r\n outputBlock[i] = (outputBlock[i] ^ lastVector[i]) & 0xff;\r\n }\r\n }\r\n // 更新向量\r\n lastVector = cryptFlag === ENCRYPT ? outputBlock : inputBlock;\r\n } else {\r\n // ECB模式(严格调用块加密)\r\n sm4BlockCrypt(inputBlock, outputBlock, roundKeys);\r\n }\r\n\r\n // 写入输出\r\n outputData.set(outputBlock, point);\r\n point += BLOCK_SIZE;\r\n }\r\n\r\n // 去填充(仅解密时)\r\n let finalOutput = outputData;\r\n if (padding === SM4_PADDING && cryptFlag === DECRYPT) {\r\n finalOutput = pkcs7Unpad(outputData);\r\n }\r\n\r\n // 转换输出格式(解密时如果输出是utf8,先转hex再转utf8)\r\n if (cryptFlag === DECRYPT && output === SM4_OUTPUT_UTF8) {\r\n return uint8ArrayToUtf8(finalOutput);\r\n }\r\n\r\n switch (output) {\r\n case SM4_OUTPUT_HEX:\r\n return uint8ArrayToHex(finalOutput);\r\n case SM4_OUTPUT_ARRAY:\r\n return Array.from(finalOutput);\r\n case SM4_OUTPUT_UINT8ARRAY:\r\n return finalOutput;\r\n case SM4_OUTPUT_ARRAYBUFFER:\r\n return finalOutput.buffer;\r\n default:\r\n throw new TypeError(`sm4Core: unsupported output format: ${output} from sm4`);\r\n }\r\n}\r\n\r\n// ========== 便捷API(函数式,符合设计准则) ==========\r\n/**\r\n * 生成 SM4 CBC 模式专用的安全随机 IV(16字节)\r\n * @param {string} [outputFormat=SM4_OUTPUT_HEX] - 输出格式:hex/uint8array/array/arraybuffer\r\n * @returns {string|Uint8Array|Array|ArrayBuffer} 随机IV\r\n */\r\nexport function generateIv(outputFormat = SM4_OUTPUT_HEX) {\r\n // 1. 校验浏览器是否支持 crypto\r\n if (!window?.crypto?.getRandomValues) {\r\n throw new TypeError(\"generateIv: your browser does not support secure random generation (crypto API) from sm4\");\r\n }\r\n\r\n // 2. 生成 16 字节安全随机数\r\n const ivUint8 = new Uint8Array(IV_SIZE);\r\n window.crypto.getRandomValues(ivUint8);\r\n\r\n // 3. 用导出的常量做格式判断,新增 ArrayBuffer 支持\r\n switch (outputFormat) {\r\n case SM4_OUTPUT_UINT8ARRAY:\r\n return ivUint8;\r\n case SM4_OUTPUT_ARRAY:\r\n return Array.from(ivUint8).map((byte) => Number(byte));\r\n case SM4_OUTPUT_ARRAYBUFFER: // 新增:支持 ArrayBuffer 格式\r\n return ivUint8.buffer;\r\n case SM4_OUTPUT_HEX:\r\n default:\r\n return Array.from(ivUint8)\r\n .map((byte) => {\r\n const hex = byte.toString(16);\r\n return hex.length === 1 ? `0${hex}` : hex;\r\n })\r\n .join(\"\");\r\n }\r\n}\r\n\r\n/**\r\n * 生成 SM4 标准密钥(16字节/32位16进制字符串)\r\n * @param {string} [outputFormat=SM4_OUTPUT_HEX] - 输出格式:hex/uint8array/array/arraybuffer\r\n * @returns {string|Uint8Array|number[]|ArrayBuffer} 16字节SM4密钥\r\n */\r\nexport function generateKey(outputFormat = SM4_OUTPUT_HEX) {\r\n // 校验浏览器/Node环境的安全随机数API\r\n if (!window?.crypto?.getRandomValues && !global?.crypto?.getRandomValues) {\r\n throw new TypeError(\r\n \"generateKey: the current environment does not support secure random number generation. please upgrade your browser/Node.js from sm4\",\r\n );\r\n }\r\n\r\n // 生成16字节随机数(SM4密钥固定16字节)\r\n const cryptoObj = window?.crypto || global?.crypto;\r\n const keyUint8 = new Uint8Array(16);\r\n cryptoObj.getRandomValues(keyUint8);\r\n\r\n // 按格式返回(用常量替代硬编码字符串,新增 ArrayBuffer 支持)\r\n switch (outputFormat) {\r\n case SM4_OUTPUT_UINT8ARRAY:\r\n return keyUint8;\r\n case SM4_OUTPUT_ARRAY:\r\n return Array.from(keyUint8).map((byte) => Number(byte));\r\n case SM4_OUTPUT_ARRAYBUFFER: // 新增:支持 ArrayBuffer 格式\r\n return keyUint8.buffer;\r\n case SM4_OUTPUT_HEX:\r\n default:\r\n return Array.from(keyUint8)\r\n .map((byte) => byte.toString(16).padStart(2, \"0\"))\r\n .join(\"\");\r\n }\r\n}\r\n\r\n/**\r\n * SM4加密\r\n * @param {string|Array|Uint8Array|ArrayBuffer} input - 输入数据(字符串/字节)\r\n * @param {string|Array|Uint8Array|ArrayBuffer} key - 16字节密钥\r\n * @param {Object} [options] - 选项\r\n * @returns {string|Array|Uint8Array|ArrayBuffer} 加密结果\r\n */\r\nexport function encrypt(input, key, options = {}) {\r\n return sm4Core(input, key, ENCRYPT, options);\r\n}\r\n\r\n/**\r\n * SM4解密\r\n * @param {string|Array|Uint8Array|ArrayBuffer} input - 加密数据(16进制字符串/字节)\r\n * @param {string|Array|Uint8Array|ArrayBuffer} key - 16字节密钥\r\n * @param {Object} [options] - 选项\r\n * @returns {string|Array|Uint8Array|ArrayBuffer} 解密结果\r\n */\r\nexport function decrypt(input, key, options = {}) {\r\n // 解密时如果没传output,默认按加密的output格式(hex)处理,再转utf8\r\n const finalOptions = {\r\n output: SM4_OUTPUT_UTF8, // 解密默认返回utf8字符串\r\n ...options,\r\n };\r\n return sm4Core(input, key, DECRYPT, finalOptions);\r\n}\r\n// 导出模式\r\nexport const MODE = {\r\n ECB: SM4_MODE_ECB,\r\n CBC: SM4_MODE_CBC,\r\n};\r\n// 导出填充\r\nexport const PADDING = SM4_PADDING;\r\n// 导出输出模式\r\nexport const OUTPUT = {\r\n HEX: SM4_OUTPUT_HEX,\r\n UTF8: SM4_OUTPUT_UTF8,\r\n ARRAY: SM4_OUTPUT_ARRAY,\r\n UINT8ARRAY: SM4_OUTPUT_UINT8ARRAY,\r\n ARRAYBUFFER: SM4_OUTPUT_ARRAYBUFFER,\r\n};\r\n","import * as sm4 from \"./sm4.js\";\r\n\r\n/**\r\n * sm4传参和返回的类型,不管是传参还是返回值固定是这几个\r\n */\r\nexport type SM4DataType = string | Uint8Array | ArrayBuffer | number[];\r\n/**\r\n * sm4通用配置\r\n */\r\nexport interface SM4Options {\r\n // 加密模式:ecb/cbc(默认ecb)\r\n mode?: keyof typeof sm4.MODE;\r\n // IV初始向量:仅CBC模式需要,ECB模式不用传\r\n iv?: SM4DataType;\r\n // 填充规则:固定pkcs#7,不用改\r\n padding?: \"pkcs#7\";\r\n // 输出格式:hex/utf8/array/uint8array/arraybuffer(加密默认hex,解密默认utf8)\r\n output?: keyof typeof sm4.OUTPUT;\r\n}\r\n\r\n/**\r\n * sm4 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @param {Object} options 配置\r\n * @returns {string} 加密后的字符串\r\n */\r\nexport function sm4Encrypt(\r\n str: string,\r\n key: SM4DataType,\r\n options?: SM4Options, // 改用互斥联合类型\r\n): SM4DataType {\r\n _validateSM4Options(options, \"encrypt\");\r\n return sm4.encrypt(str, key, options);\r\n}\r\n\r\n/**\r\n * sm4 解密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @param {Object} options 配置\r\n * @returns {string} 解密后的数据\r\n */\r\nexport function sm4Decrypt(\r\n str: string,\r\n key: SM4DataType,\r\n options?: SM4Options, // 解密也改为可选(和加密保持一致,更易用)\r\n): SM4DataType {\r\n _validateSM4Options(options, \"decrypt\");\r\n return sm4.decrypt(str, key, options);\r\n}\r\n\r\n/**\r\n * 生成sm4的key\r\n * @param {string} inputFormat 输入类型 可以任意字符串,其中固定的uint8array、array、hex这3个字符串,会对应生成类型数据\r\n * @returns {SM4DataType} 生成的key\r\n */\r\nexport const generateSM4Key = sm4.generateKey as (inputFormat?: string) => SM4DataType;\r\n\r\n/**\r\n * 生成sm4的iv\r\n * @param {string} inputFormat 输入类型 可以任意字符串,其中固定的uint8array、array、hex这3个字符串,会对应生成类型数据\r\n * @returns {SM4DataType} 生成的iv\r\n */\r\nexport const generateSM4Iv = sm4.generateIv as (inputFormat?: string) => SM4DataType;\r\n\r\n/**\r\n * 校验SM4配置参数的合法性\r\n * @param options 配置项\r\n * @param operation 操作类型(encrypt/decrypt)\r\n */\r\nfunction _validateSM4Options(options: SM4Options = {}, operation: \"encrypt\" | \"decrypt\") {\r\n const { mode = sm4.MODE.ECB, iv } = options;\r\n\r\n // 1. 校验模式是否合法\r\n const validModes = Object.values(sm4.MODE);\r\n if (!validModes.includes(mode)) {\r\n throw new TypeError(\r\n `sm4${operation}:unsupported encryption mode \"${mode}\", supports only ${validModes.join(\"/\")}`,\r\n );\r\n }\r\n\r\n // 2. CBC模式必须传IV\r\n if (mode === sm4.MODE.CBC && !iv) {\r\n throw new TypeError(`sm4${operation}:the CBC mode must be inputted with an IV (initialization vector)`);\r\n }\r\n\r\n // 3. ECB模式禁止传IV(避免误用)\r\n if (mode === sm4.MODE.ECB && iv !== undefined) {\r\n throw new TypeError(\r\n `sm4${operation}: the ECB mode does not require an IV to be passed in. Please do not pass the iv parameter`,\r\n );\r\n }\r\n\r\n // 4. 校验IV长度(如果传了IV)\r\n if (iv) {\r\n let ivLength: number;\r\n if (typeof iv === \"string\") {\r\n // hex字符串:16字节对应32位hex\r\n ivLength = iv.length === 32 ? 16 : iv.length;\r\n } else if (iv instanceof ArrayBuffer) {\r\n ivLength = iv.byteLength;\r\n } else if (iv instanceof Uint8Array) {\r\n ivLength = iv.length;\r\n } else if (Array.isArray(iv)) {\r\n ivLength = iv.length;\r\n } else {\r\n ivLength = 0;\r\n }\r\n\r\n if (ivLength !== 16) {\r\n throw new TypeError(`sm4${operation}:IV must be 16 bytes in length, and the current length is ${ivLength}`);\r\n }\r\n }\r\n\r\n // 5. 校验填充模式(仅允许pkcs#7)\r\n if (options.padding && options.padding !== String(sm4.PADDING)) {\r\n throw new TypeError(\r\n `sm4${operation}: only pkcs#7 padding mode is supported, currently being input ${String(options.padding)}`,\r\n );\r\n }\r\n}\r\n\r\n// sm4的配置\r\nexport const SM4 = {\r\n // sm4的模式\r\n MODE: sm4.MODE,\r\n // sm4的填充\r\n PADDING: sm4.PADDING,\r\n // sm4的输出\r\n OUTPUT: sm4.OUTPUT,\r\n};\r\n","/**\r\n * @module 脱敏\r\n */\r\n/**\r\n * 指定位置的字符串转为星号\r\n * @param {string|number} value 字符串参数\r\n * @param {number} start 转换开始位置\r\n * @param {number} len 显示星号的长度\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOf(value: string, start: number, len: number): string {\r\n value = String(value);\r\n if (start > value.length) return value;\r\n // len小于0和len大于剩余长度\r\n let startStr = \"\";\r\n if (len < 0) len = 0;\r\n if (len > value.length - start) {\r\n len = value.length - start;\r\n }\r\n startStr = String().padEnd(len, \"*\");\r\n return value.substring(0, start) + startStr + value.substring(start + len);\r\n}\r\n\r\n/**\r\n * 姓名中间转为星号\r\n * @param {string} value 姓名\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOfName(value: string): string {\r\n if (value.length === 2) {\r\n return formatStartOf(value, 1, 1);\r\n } else if (value.length > 2) {\r\n return formatStartOf(value, 1, value.length - 2);\r\n } else {\r\n return value;\r\n }\r\n}\r\n\r\n/**\r\n * 手机号码固定位数转为星号\r\n * @param {string} value 手机号码\r\n * @param {number} start 前缀长度,默认3位\r\n * @param {number} len 显示星号的长度,默认4位\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOfMobile(value: string, start: number = 3, len: number = 4): string {\r\n return formatStartOf(value, start, len);\r\n}\r\n\r\n/**\r\n * 身份证号码固定位数转为星号\r\n * @param {string} value 身份证号码\r\n * @param {number} start 前缀长度,默认4位\r\n * @param {number} len 显示星号的长度,默认8位\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOfIDCard(value: string, start: number = 4, len: number = 8): string {\r\n return formatStartOf(value, start, len);\r\n}\r\n\r\n/**\r\n * 银行卡号固定位数转为星号\r\n * @param {string} value 银行卡号\r\n * @param {number} start 前缀长度,默认4位\r\n * @param {number} len 显示星号的长度,默认10位\r\n * @returns {string} 返回转化后字符串\r\n */\r\nexport function formatStartOfBankCard(value: string, start: number = 4, len: number = 11): string {\r\n return formatStartOf(value, start, len);\r\n}\r\n","/**\r\n * @module 身份证号码\r\n */\r\nimport { isNull } from \"@/validate\";\r\nimport { toDate, getAge } from \"@/date\";\r\nimport { ID_CARD } from \"@/constants\";\r\n\r\n/**\r\n * 根据身份证号码获取信息\r\n * @description 能获取到 籍贯,出生日期,年龄,性别\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {Object} 返回身份证信息对象\r\n */\r\nexport function getInfoByIDCard(idCard: string):\r\n | {\r\n province: string | undefined;\r\n birthday: string | undefined;\r\n age: number | undefined;\r\n sex: string | undefined;\r\n }\r\n | undefined {\r\n if (isNull(idCard)) return;\r\n return {\r\n // 省份\r\n province: getProvinceByIDCard(idCard),\r\n // 生日\r\n birthday: getBirthdayByIDCard(idCard),\r\n // 年龄\r\n age: getAgeByIDCard(idCard),\r\n // 性别\r\n sex: getSexByIDCard(idCard),\r\n };\r\n}\r\n\r\n/**\r\n * 根据身份证号码获得生日\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {string} 返回生日\r\n */\r\nexport function getBirthdayByIDCard(idCard: string): string | undefined {\r\n if (isNull(idCard)) return;\r\n // 15位身份证\r\n if (idCard.length === 15) {\r\n return \"19\" + idCard.substring(6, 8) + \"-\" + idCard.substring(8, 10) + \"-\" + idCard.substring(10, 12);\r\n }\r\n // 18位身份证\r\n if (idCard.length === 18) {\r\n return idCard.substring(6, 10) + \"-\" + idCard.substring(10, 12) + \"-\" + idCard.substring(12, 14);\r\n }\r\n}\r\n\r\n/**\r\n * 根据身份证号码获得年龄\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {number} 返回年龄\r\n */\r\nexport function getAgeByIDCard(idCard: string): number | undefined {\r\n if (isNull(idCard)) return;\r\n const birthday = getBirthdayByIDCard(idCard);\r\n if (birthday) {\r\n return getAge(toDate(String(birthday))!);\r\n }\r\n}\r\n\r\n/**\r\n * 根据身份证号码获得性别\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {string} 返回性别\r\n */\r\nexport function getSexByIDCard(idCard: string): string | undefined {\r\n if (isNull(idCard)) return;\r\n // 15位身份证\r\n if (idCard.length === 15) {\r\n return Number(idCard.substring(14)) % 2 === 0 ? (ID_CARD.SEX.WOMAN as string) : (ID_CARD.SEX.MAN as string);\r\n }\r\n // 18位身份证\r\n if (idCard.length === 18) {\r\n return Number(idCard.substring(16, 17)) % 2 === 0 ? (ID_CARD.SEX.WOMAN as string) : (ID_CARD.SEX.MAN as string);\r\n }\r\n}\r\n\r\n/**\r\n * 根据身份证号码获得省份\r\n * @param {string} idCard 身份证号码,支持一代15位和二代18位\r\n * @returns {string} 返回省份\r\n */\r\nexport function getProvinceByIDCard(idCard: string): string | undefined {\r\n if (isNull(idCard)) return;\r\n const prefix = idCard.substring(0, 2);\r\n if (prefix) {\r\n return ID_CARD.PROVINCE[prefix];\r\n }\r\n}\r\n","/**\r\n * @module 分页\r\n */\r\n/**\r\n * 获得分页起始数\r\n * @param {Object} pagination 分页参数\r\n * @returns {Array} 返回起始数\r\n */\r\nexport function getLimit(\r\n pagination: { page: number; pageSize: number; total: number; totalPage: number; pagerCount: number } = {\r\n page: 1,\r\n pageSize: 10,\r\n total: 0,\r\n totalPage: 0,\r\n pagerCount: 7,\r\n },\r\n): number[] {\r\n return [pagination.pageSize * (pagination.page - 1), pagination.pageSize * pagination.page];\r\n}\r\n\r\n/**\r\n * 获得总条数\r\n * @param {Object} pagination 分页参数\r\n * @returns {number} 返回总条数\r\n */\r\nexport function getTotalPage(\r\n pagination: { page: number; pageSize: number; total: number; totalPage: number; pagerCount: number } = {\r\n page: 1,\r\n pageSize: 10,\r\n total: 0,\r\n totalPage: 0,\r\n pagerCount: 7,\r\n },\r\n): number {\r\n return Math.ceil((pagination.total || 0) / (pagination.pageSize || 0));\r\n}\r\n\r\n/**\r\n * 获得彩虹分页器\r\n * @param {Object} pagination 分页参数\r\n * @param {Function} callback 回调函数\r\n * @returns {Promise} 返回彩虹分页器数据\r\n */\r\nexport function getRainbowPager(\r\n pagination: { page: number; pageSize: number; total: number; totalPage: number; pagerCount: number } = {\r\n page: 1,\r\n pageSize: 10,\r\n total: 0,\r\n totalPage: 0,\r\n pagerCount: 7,\r\n },\r\n callback: (pager: number[]) => void,\r\n): Promise<number[]> {\r\n return new Promise((resolve) => {\r\n // 分页参数\r\n const page = pagination.page || 1;\r\n const totalPage = pagination.totalPage > 0 ? pagination.totalPage : getTotalPage(pagination);\r\n const pagerCount = pagination.pagerCount || 7;\r\n\r\n // 计算参数\r\n const isEven = (pagerCount & 1) === 0;\r\n const left = pagerCount >> 1;\r\n let right = pagerCount >> 1;\r\n let pagerLength = pagerCount;\r\n\r\n // 计算生成的分页器数量\r\n if (isEven) {\r\n right++;\r\n }\r\n if (totalPage < pagerCount) {\r\n pagerLength = totalPage;\r\n }\r\n\r\n // 分页器数组\r\n const pager = new Array(pagerLength);\r\n\r\n // 生成分页器\r\n if (totalPage >= pagerCount) {\r\n if (page <= left) {\r\n for (let i = 0; i < pager.length; i++) {\r\n pager[i] = i + 1;\r\n }\r\n } else if (page > totalPage - right) {\r\n for (let i = 0; i < pager.length; i++) {\r\n pager[i] = i + totalPage - pagerCount + 1;\r\n }\r\n } else {\r\n for (let i = 0; i < pager.length; i++) {\r\n pager[i] = i + page - left + (isEven ? 1 : 0);\r\n }\r\n }\r\n } else {\r\n for (let i = 0; i < pager.length; i++) {\r\n pager[i] = i + 1;\r\n }\r\n }\r\n\r\n // 支持回调函数和Promise\r\n callback && callback(pager);\r\n resolve(pager);\r\n });\r\n}\r\n\r\n/**\r\n * 获得上一页\r\n * @param {Object} pagination 分页参数\r\n * @param {Function} callback 回调函数\r\n * @returns {Promise} 返回上一页\r\n */\r\nexport function getPrevPage(\r\n pagination = { page: 1, pageSize: 10, total: 0, totalPage: 0, pagerCount: 7 },\r\n callback: (page: number) => void,\r\n): Promise<number> {\r\n return new Promise((resolve) => {\r\n if (pagination.page > 1) {\r\n pagination.page--;\r\n } else {\r\n pagination.page = 1;\r\n }\r\n\r\n // 支持回调函数和Promise\r\n callback && callback(pagination.page);\r\n resolve(pagination.page);\r\n });\r\n}\r\n\r\n/**\r\n * 获得下一页\r\n * @description 最后一页会根据totalPage参数判断,如果不传此参数,则会根据参数中pageSize和total重新计算总页数\r\n * @param {Object} pagination 分页参数\r\n * @param {Function} callback 回调函数\r\n * @returns {Promise} 返回下一页\r\n */\r\nexport function getNextPage(\r\n pagination = { page: 1, pageSize: 10, total: 0, totalPage: 0, pagerCount: 7 },\r\n callback: (page: number) => void,\r\n): Promise<number> {\r\n return new Promise((resolve) => {\r\n // 获得总页数,如果没有传totalPage,则需要根据传的pageSize和total计算\r\n const totalPage = pagination.totalPage > 0 ? pagination.totalPage : getTotalPage(pagination);\r\n\r\n // 计算当前页大于0和小与0的情况\r\n if (pagination.page > 0) {\r\n if (pagination.page < totalPage) {\r\n pagination.page++;\r\n } else {\r\n pagination.page = totalPage;\r\n }\r\n } else {\r\n pagination.page = 1;\r\n }\r\n\r\n // 支持回调函数和Promise\r\n callback && callback(pagination.page);\r\n resolve(pagination.page);\r\n });\r\n}\r\n","/**\r\n * @module 浏览器Url\r\n */\r\nimport { REGEXP } from \"@/constants\";\r\nimport { isArray } from \"@/validate\";\r\nimport { arrayInsertAfter, arrayInsertBefore } from \"@/array\";\r\n\r\n/**\r\n * 获得协议名\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回协议名\r\n */\r\nexport function getProtocol(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[1];\r\n }\r\n}\r\n\r\n/**\r\n * 获得主机地址\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回主机地址\r\n */\r\nexport function getHost(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return (match[2] || \"\") + (match[3] ? \":\" + match[3] : \"\");\r\n }\r\n}\r\n\r\n/**\r\n * 获得主机名称\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回主机名称\r\n */\r\nexport function getHostName(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[2];\r\n }\r\n}\r\n\r\n/**\r\n * 获得端口号\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回端口号\r\n */\r\nexport function getPort(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n\r\n if (match) {\r\n return match[3];\r\n }\r\n}\r\n\r\n/**\r\n * 获得地址路径\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回地址路径\r\n */\r\nexport function getUrlPath(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[4];\r\n }\r\n}\r\n\r\n/**\r\n * 获得hash字符串\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回hash字符串\r\n */\r\nexport function getUrlHash(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[6];\r\n }\r\n}\r\n\r\n/**\r\n * 获得查询参数字符串\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function getSearchString(url: string = window.location.href): string | undefined {\r\n const match = url.match(REGEXP.URL);\r\n if (match) {\r\n return match[5];\r\n }\r\n}\r\n\r\n/**\r\n * 查询参数字符串中是否包含某个参数\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @returns {boolean} 返回结果\r\n */\r\nexport function hasSearchParam(url: string = window.location.href, name: string): boolean {\r\n const params = parseSearchParam(url);\r\n return params[name] !== undefined;\r\n}\r\n\r\n/**\r\n * 查询参数字符串中获得某个参数的值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @returns {string} 返回查询到的值\r\n */\r\nexport function getSearchParam(url: string = window.location.href, name = \"\"): string | undefined {\r\n name = name.replace(/[[\\]]/g, \"\\\\$&\");\r\n url = getSearchString(url) || \"\";\r\n const reg = new RegExp(\"(^|&)\" + name + \"=([^&]*)(&|$)\");\r\n const match = url.substring(0).match(reg);\r\n if (match) {\r\n return decodeURIComponent(match[2]);\r\n }\r\n}\r\n\r\n/**\r\n * 查询参数字符串中设置某个参数的值\r\n * @param {string} name 参数名\r\n * @param {string|number|Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function setSearchParam(\r\n url = window.location.href,\r\n name = \"\",\r\n value: string | number | number[] | string[],\r\n): string {\r\n const params: Record<string, any> = parseSearchParam(url);\r\n params[name] = value;\r\n // 返回替换后的url\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + stringifySearchParam(params));\r\n}\r\n\r\n/**\r\n * 查询参数字符串转为对象\r\n * @param {string} url url地址,默认当前url地址\r\n * @returns {Object} 返回参数对象\r\n */\r\nexport function parseSearchParam(url: string = window.location.href): Record<string, any> {\r\n const searchString = getSearchString(url) || \"\";\r\n const searchArr = searchString.split(\"&\");\r\n const param: Record<string, any> = {};\r\n for (let i = 0; i < searchArr.length; i++) {\r\n const arr = searchArr[i].split(\"=\");\r\n param[decodeURIComponent(arr[0])] = decodeURIComponent(arr[1] || \"\");\r\n }\r\n return param;\r\n}\r\n\r\n/**\r\n * 对象转为查询参数字符串\r\n * @param {Object} params 参数对象\r\n * @param {string} url url地址,如果不为空,则会拼接好查询参数字符串的url地址\r\n * @returns {string} 返回参数字符串\r\n */\r\nexport function stringifySearchParam(params: Record<string, any>, url: string = \"\"): string {\r\n if (typeof params !== \"object\") return params;\r\n\r\n const arr = [];\r\n for (const key in params) {\r\n const value = params[key];\r\n if (isArray(value)) {\r\n for (let i = 0; i < value.length; ++i) {\r\n arr.push(encodeURIComponent(key + \"[\" + i + \"]\") + \"=\" + encodeURIComponent(value[i]));\r\n }\r\n } else {\r\n arr.push(encodeURIComponent(key) + \"=\" + encodeURIComponent(params[key]));\r\n }\r\n }\r\n // 如果url不为空,则会返回拼接好url字符串\r\n if (url) {\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + arr.join(\"&\"));\r\n } else {\r\n return arr.join(\"&\");\r\n }\r\n}\r\n\r\n/**\r\n * 查询参数字符串中在最前面追加新参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @param {string|number|Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function prependSearchParam(\r\n url: string = window.location.href,\r\n name: string,\r\n value: string | number | number[] | string[],\r\n): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\") || [];\r\n if (Array.isArray(value)) {\r\n const arr = [];\r\n for (let i = 0; i < value.length; i++) {\r\n arr.push(`${encodeURIComponent(name)}[${i}]=${encodeURIComponent(value[i])}`);\r\n }\r\n searchArr.unshift(...arr);\r\n } else {\r\n searchArr.unshift(`${encodeURIComponent(name)}=${encodeURIComponent(value)}`);\r\n }\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + searchArr.join(\"&\"));\r\n}\r\n\r\n/**\r\n * 查询参数字符串中在某个参数的前面追加新参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @param {string|number|Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @param {string} beforeParam 在前面追加参数的名称\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function prependToSearchParam(\r\n url: string = window.location.href,\r\n beforeParam: string,\r\n name: string,\r\n value: string | number | number[] | string[],\r\n): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\");\r\n const beforeIndex = searchArr.findIndex((v) => v.includes(beforeParam));\r\n const beforeArr = arrayInsertBefore(searchArr, beforeIndex, `${name}=${value}`);\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + beforeArr.join(\"&\"));\r\n}\r\n\r\n/**\r\n * 查询参数字符串中在最后面追加新参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @param {string,number,Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function appendSearchParam(\r\n url: string = window.location.href,\r\n name: string,\r\n value: string | number | number[] | string[],\r\n): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\");\r\n searchArr.push(`${name}=${value}`);\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + searchArr.join(\"&\"));\r\n}\r\n\r\n/**\r\n * 查询参数字符串中在某个参数的后面追加新参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @param {string,number,Array} value 参数值,如果是数组,则解析为:&ids[0]=1&ids[2]=2\r\n * @param {string} afterName 在后面追加参数的名称\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function appendToSearchParam(\r\n url: string = window.location.href,\r\n afterName: string,\r\n name: string,\r\n value: string | number | number[] | string[],\r\n): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\");\r\n const beforeIndex = searchArr.findIndex((v) => v.includes(afterName));\r\n const afterArr = arrayInsertAfter(searchArr, beforeIndex, `${name}=${value}`);\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + afterArr.join(\"&\"));\r\n}\r\n\r\n/**\r\n * 查询参数字符串中移除某个参数和值\r\n * @param {string} url url地址,默认当前url地址\r\n * @param {string} name 参数名\r\n * @returns {string} 返回查询参数字符串\r\n */\r\nexport function removeSearchParam(url: string = window.location.href, name: string): string {\r\n const searchArr = (getSearchString(url) || \"\").split(\"&\");\r\n const delIndex = searchArr.findIndex((v) => v.includes(name));\r\n if (delIndex > -1) {\r\n searchArr.splice(delIndex, 1);\r\n }\r\n return url.replace(/(\\?.+?)(?=#|$)/, \"?\" + searchArr.join(\"&\"));\r\n}\r\n","/**\r\n * @module 浏览器Cookie\r\n */\r\nimport { isEmpty } from \"@/validate\";\r\n\r\n/**\r\n * 浏览器是否支持 Cookie\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isSupportCookie(): boolean {\r\n return window.navigator.cookieEnabled;\r\n}\r\n\r\n/* cookie存储 */\r\n/**\r\n * 通过name获取cookie\r\n * @param {string} name 参数name\r\n * @returns {string} 返回获取的值\r\n */\r\nexport function getCookie(name: string): string {\r\n if (typeof document == \"undefined\") return \"\";\r\n // cookie中每个分号后面是有个空格的,需要替换掉\r\n const arr = document.cookie ? document.cookie.replace(/\\s/g, \"\").split(\";\") : [];\r\n for (const i in arr) {\r\n const tempArr = arr[i].split(\"=\");\r\n if (tempArr[0] === name) {\r\n return decodeURIComponent(tempArr[1]);\r\n }\r\n }\r\n return \"\";\r\n}\r\n\r\n/**\r\n * 通过name设置cookie\r\n * 注:timestamp参数不填,则默认为session级别,浏览器关闭即cookie过期\r\n * @param {string} name 参数name\r\n * @param {string} value 设置的value\r\n * @param {number} timestamp 过期的时间戳值,默认为一天,设置一天过期则为:24*60*60*1000\r\n */\r\nexport function setCookie(name: string, value: string, timestamp: number = 24 * 60 * 60 * 1000) {\r\n if (typeof document == \"undefined\") return;\r\n document.cookie = name + \"=\" + value + \";expires=\" + new Date(Date.now() + timestamp);\r\n}\r\n\r\n/**\r\n * 通过name删除cookie\r\n * @param {string} name 参数name\r\n */\r\nexport function removeCookie(name: string) {\r\n if (isEmpty(name)) return;\r\n setCookie(name, \"\", -1);\r\n}\r\n\r\n/**\r\n * 清空当前站点域名的cookie\r\n * @param {string} domain 域名地址,默认是当前站点域名\r\n */\r\nexport function clearCookie(domain: string = document.domain) {\r\n const names = document.cookie.match(/[^ =;]+(?==)/g) || [];\r\n if (names && names.length > 0) {\r\n for (let i = names.length; i--; ) {\r\n document.cookie =\r\n names[i] + \"=0;path=/;\" + domain ? \"domain=\" + domain + \";\" : \"\" + \"expires=\" + new Date(0).toUTCString();\r\n }\r\n }\r\n}\r\n","/**\r\n * @module 浏览器Dom\r\n */\r\n/* Class操作 */\r\n/**\r\n * 判断元素包含某个类名\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} className 类名\r\n * @return {boolean} 返回true和false\r\n */\r\nexport function hasClass(elem: HTMLElement, className: string): boolean {\r\n return elem.className.indexOf(className) > 0;\r\n}\r\n\r\n/**\r\n * 元素添加类名\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} className 类名\r\n */\r\nexport function addClass(elem: HTMLElement, className: string) {\r\n if (!hasClass(elem, className)) {\r\n elem.className += \" \" + className;\r\n }\r\n}\r\n\r\n/**\r\n * 元素删除类名\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} className 类名\r\n */\r\nexport function removeClass(elem: HTMLElement, className: string) {\r\n if (hasClass(elem, className)) {\r\n elem.className = elem.className.replace(new RegExp(className, \"gm\"), \"\");\r\n }\r\n}\r\n\r\n/**\r\n * 元素替换类名\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} newClassName 新的类名\r\n * @param {string} oldClassName 被替换掉的旧类名\r\n */\r\nexport function replaceClass(elem: HTMLElement, newClassName: string, oldClassName: string) {\r\n removeClass(elem, oldClassName);\r\n addClass(elem, newClassName);\r\n}\r\n\r\n/* Style操作 */\r\n/**\r\n * 添加元素的style样式\r\n * @param {HTMLElement} elem 元素\r\n * @param {Object} styles 样式属性集合\r\n */\r\n\r\nexport function addStyle(elem: HTMLElement, styles: Record<string, string> = {}) {\r\n if (!elem) return;\r\n for (const [key, value] of Object.entries(styles)) {\r\n elem.style.setProperty(key, value);\r\n }\r\n}\r\n\r\n/**\r\n * 获取元素的style样式\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} name 属性\r\n * @returns {string|undefined} 返回样式的值\r\n */\r\nexport function getStyle(elem: HTMLElement, name: string): string | unknown {\r\n if (!elem) return;\r\n return elem.style.getPropertyValue(name);\r\n}\r\n\r\n/**\r\n * 删除元素的style样式\r\n * @param {HTMLElement} elem 元素\r\n * @param {string} name 属性\r\n */\r\nexport function removeStyle(elem: HTMLElement, name: string) {\r\n if (!elem) return;\r\n elem.style.removeProperty(name);\r\n}\r\n\r\n/* Html转码 */\r\n/**\r\n * html标签转义\r\n * @param {string} htmlStr html字符串\r\n * @returns {string} 返回转义后的字符串\r\n */\r\nexport function htmlEncode(htmlStr: string): string {\r\n const temp = {\r\n \"<\": \"&lt;\",\r\n \">\": \"&gt;\",\r\n \"&\": \"&amp;\",\r\n \"(\": \"&#40;\",\r\n \")\": \"&#41;\",\r\n \"/\": \"&#47;\",\r\n \" \": \"&nbsp;\",\r\n '\"': \"&quot;\",\r\n \"'\": \"&#39;\",\r\n } as const;\r\n return htmlStr.replace(/[<>&|()\\/ '\"]/g, function (c: string) {\r\n return (temp as any)[c];\r\n });\r\n}\r\n\r\n/**\r\n * html标签解码\r\n * @param {string} htmlStr html字符串\r\n * @returns {string} 返回解析后的字符串\r\n */\r\nexport function htmlDecode(htmlStr: string): string {\r\n const temp = {\r\n \"&lt;\": \"<\",\r\n \"&gt;\": \">\",\r\n \"&amp;\": \"&\",\r\n \"&#40;\": \"(\",\r\n \"&#41;\": \")\",\r\n \"&#47;\": \"/\",\r\n \"&nbsp;\": \" \",\r\n \"&quot;\": '\"',\r\n \"&#39;\": \"'\",\r\n } as const;\r\n return htmlStr.replace(/(&lt;|&gt;|&amp;|&#40;|&#41;|&#47;|&nbsp;|&quot;|&#39;)/gi, function (all, t) {\r\n return (temp as any)[t];\r\n });\r\n}\r\n","/**\r\n * @module 浏览器Device\r\n */\r\n/* 浏览器信息 */\r\n/**\r\n * 获取浏览器信息\r\n * @description 会获取到浏览器对应的名称以及版本\r\n * @returns {Object} 返回浏览器信息\r\n */\r\nexport function getBrowserInfo(): { name: string; version: string } | undefined {\r\n const ua = window && window.navigator.userAgent.toLowerCase();\r\n\r\n // ie\r\n const ie = ua.match(/rv:([\\d.]+)\\) like gecko/) || ua.match(/msie ([\\d\\.]+)/);\r\n // edge\r\n const edge = ua.match(/edg\\/([\\d\\.]+)/);\r\n // firefox\r\n const firefox = ua.match(/firefox\\/([\\d\\.]+)/);\r\n // opera\r\n const opera = ua.match(/(?:opera|opr).([\\d\\.]+)/);\r\n // chrome\r\n const chrome = ua.match(/chrome\\/([\\d\\.]+)/);\r\n // safari\r\n const safari = ua.match(/version\\/([\\d\\.]+).*safari/);\r\n\r\n // 判断类型\r\n if (ie) return { name: \"ie\", version: ie[1] };\r\n else if (edge) return { name: \"edge\", version: edge[1] };\r\n else if (firefox) return { name: \"firefox\", version: firefox[1] };\r\n else if (opera) return { name: \"opera\", version: opera[1] };\r\n else if (chrome) return { name: \"chrome\", version: chrome[1] };\r\n else if (safari) return { name: \"safari\", version: safari[1] };\r\n else return;\r\n}\r\n\r\n/* 设备类型 */\r\n/**\r\n * 判断是pc端\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isPc(): boolean {\r\n return !isPhone();\r\n}\r\n\r\n/**\r\n * 判断是手机端\r\n * @description 包含 android、iphone、黑莓手机、微软手机 等多种操作系统机型\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isPhone(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /Android|webOS|iPhone|iPod|BlackBerry|Windows Phone|IEMobile/i.test(ua);\r\n}\r\n\r\n/* 操作系统类型 */\r\n/**\r\n * 判断是 android\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isAndroid(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /Android|BlackBerry/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 ios\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isIos(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /iPhone|iPad|iPod|iOS/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 windows phone\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isWindowsPhone(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /Windows Phone/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 windows\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isWindows(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /win/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 linux\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isLinux(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /linux/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是 Mac\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isMac(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /mac/i.test(ua);\r\n}\r\n\r\n/* 苹果设备类型 */\r\n/**\r\n * 判断是iphone\r\n *@returns {boolean} 返回true和false\r\n */\r\nexport function isIphone(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /iPhone/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是ipad\r\n *@return {boolean} 返回true和false\r\n */\r\nexport function isIpad(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /iPod/i.test(ua);\r\n}\r\n\r\n/* 手机浏览器类型 */\r\n/**\r\n * 判断是微信内置浏览器\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isWeixin(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /MicroMessenger/i.test(ua);\r\n}\r\n\r\n/**\r\n * 判断是QQ内置浏览器\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isQQ(): boolean {\r\n const ua = window && window.navigator.userAgent;\r\n return /QQ/i.test(ua);\r\n}\r\n","/**\r\n * @module 浏览器Clipboard\r\n */\r\n\r\nimport { blobToText } from \"@/file\";\r\n\r\n/**\r\n * 获得剪切板数据\r\n * @description 获得的剪切板的数据是会返回多个可用的MIME类型,比如是纯文本就返回一个['text/plain'],是复制的html则会返回两个可用的['text/plain','text/html'],是复制的图片则是['image/png']\r\n * @returns {Promise} 返回剪切板的数据,是数组形式,如果是文本则是字符串,否则是blob数据\r\n */\r\nexport function getClipboard(): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n if (window.navigator.clipboard) {\r\n window.navigator.clipboard.read().then((clipboardItems) => {\r\n const list: any[] = [];\r\n for (const item of clipboardItems) {\r\n for (const type of item.types) {\r\n item.getType(type).then(async (blob) => {\r\n // 文本类型,可以直接输出为字符串\r\n if (blob.type.includes(\"text\")) {\r\n const text = await blobToText(blob);\r\n list.push({ type: blob.type, data: text });\r\n }\r\n // 图片和其他文件类型,返回blob对象\r\n else {\r\n list.push({ type: blob.type, data: blob });\r\n }\r\n });\r\n }\r\n }\r\n resolve(list);\r\n });\r\n } else {\r\n console.warn(\"not support navigator clipboard!\");\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 获得剪切板文本\r\n * @returns {Promise} 返回剪切板文本\r\n */\r\nexport function getClipboardText(): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n if (window && window.navigator) {\r\n window.navigator.clipboard\r\n .readText()\r\n .then((text) => {\r\n resolve(text);\r\n })\r\n .catch((error) => {\r\n reject(error);\r\n });\r\n } else {\r\n console.warn(\"not support navigator clipboard!\");\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 设置剪切板数据\r\n * @description 可以设置文本或者blob类型的数据\r\n * @param {string|Blob} data 写入的数据,可以是文本或blob数据\r\n * @returns {Promise} 返回结果\r\n */\r\nexport function setClipboard(data: string | Blob): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n // 现代浏览器\r\n if (window && window.navigator) {\r\n let clipboardItem = null;\r\n // 是文本类型\r\n if (typeof data === \"string\") {\r\n const blob = new Blob([data], { type: \"text/plain\" });\r\n clipboardItem = new window.ClipboardItem({\r\n [\"text/plain\"]: blob,\r\n });\r\n }\r\n // 其他文件类型\r\n else {\r\n clipboardItem = new window.ClipboardItem({ [data.type]: data });\r\n }\r\n\r\n // 写入到剪切板中\r\n window.navigator.clipboard.write([clipboardItem]).then(\r\n (success) => {\r\n resolve(true);\r\n },\r\n (failed) => {\r\n reject(false);\r\n },\r\n );\r\n } else {\r\n console.warn(\"not support navigator clipboard!\");\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 设置剪切板文本\r\n * @param {string} text 写入的文本\r\n * @returns {Promise} 返回结果\r\n */\r\nexport function setClipboardText(text: string): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n // 现代浏览器\r\n if (window && window.navigator) {\r\n window.navigator.clipboard.writeText(text).then(\r\n (success) => {\r\n resolve(true);\r\n },\r\n (failed) => {\r\n reject(false);\r\n },\r\n );\r\n } else {\r\n console.warn(\"not support navigator clipboard!\");\r\n }\r\n });\r\n}\r\n\r\n/**\r\n * 清空剪切板\r\n * @returns {Promise} 返回结果\r\n */\r\nexport function clearClipboard(): Promise<any> {\r\n return new Promise((resolve, reject) => {\r\n setClipboardText(\"\")\r\n .then(() => resolve(true))\r\n .catch(reject);\r\n });\r\n}\r\n","/**\r\n * 语言相关常量配置(全局只读)\r\n *\r\n * ZH: 中文\r\n * - zh\r\n *\r\n * EN: 英文\r\n * - en\r\n */\r\nexport const LANG: Record<string, any> = {\r\n // 中文\r\n ZH: \"zh\",\r\n // 英文\r\n EN: \"en\",\r\n} as const;\r\n","import * as Base64 from \"./base64.js\";\r\n/**\r\n * Base64编码\r\n * @param str 待编码的UTF8字符串\r\n * @param urlSafe 是否生成URL安全的Base64(默认false)\r\n * @returns Base64字符串\r\n */\r\nexport function base64Encode(str: string, urlSafe: boolean = false): string {\r\n return Base64.encode(str, urlSafe);\r\n}\r\n\r\n/**\r\n * Base64解码\r\n * @param str 待解码的Base64字符串\r\n * @returns 解码后的UTF8字符串\r\n */\r\nexport function base64Decode(str: string): string {\r\n return Base64.decode(str);\r\n}\r\n\r\n/**\r\n * URL安全Base64编码\r\n * @param str 待编码的UTF8字符串\r\n * @returns URL安全的Base64字符串\r\n */\r\nexport function base64EncodeURI(str: string): string {\r\n return Base64.encodeURI(str);\r\n}\r\n\r\n/**\r\n * URL安全Base64解码\r\n * @param str 待解码的URL安全Base64字符串\r\n * @returns 解码后的UTF8字符串\r\n */\r\nexport function base64DecodeURI(str: string): string {\r\n return Base64.decodeURI(str);\r\n}\r\n\r\n/**\r\n * Uint8Array转Base64字符串\r\n * @param uint8Array 待编码的字节数组\r\n * @param urlSafe 是否生成URL安全的Base64(默认false)\r\n * @returns Base64字符串\r\n */\r\nexport function base64FromUint8Array(uint8Array: Uint8Array, urlSafe: boolean = false): string {\r\n return Base64.fromUint8Array(uint8Array, urlSafe);\r\n}\r\n\r\n/**\r\n * Base64字符串转Uint8Array\r\n * @param base64Str 待解码的Base64字符串\r\n * @param urlSafe 是否为URL安全的Base64(默认false)\r\n * @returns 解码后的字节数组\r\n */\r\nexport function base64ToUint8Array(base64Str: string, urlSafe: boolean = false): Uint8Array {\r\n return Base64.toUint8Array(base64Str, urlSafe);\r\n}\r\n\r\n/**\r\n * 十六进制字符串转Base64字符串\r\n * @param hexStr 待编码的十六进制字符串\r\n * @param urlSafe 是否生成URL安全的Base64(默认false)\r\n * @returns Base64字符串\r\n */\r\nexport function base64FromHex(hexStr: string, urlSafe: boolean = false): string {\r\n return Base64.fromHex(hexStr, urlSafe);\r\n}\r\n\r\n/**\r\n * Base64字符串转十六进制字符串\r\n * @param base64Str 待解码的Base64字符串\r\n * @param urlSafe 是否为URL安全的Base64(默认false)\r\n * @returns 解码后的十六进制字符串\r\n */\r\nexport function base64ToHex(base64Str: string, urlSafe: boolean = false): string {\r\n return Base64.toHex(base64Str, urlSafe);\r\n}\r\n","/* localStorage存储 */\r\n/**\r\n * 通过key从localStorage缓存中获取数据\r\n * @param {string} key key值\r\n * @returns {string} 返回数据\r\n */\r\nexport function getLocalStorage(key: string): string | undefined {\r\n return (window && window.localStorage.getItem(key)) || undefined;\r\n}\r\n\r\n/**\r\n * 设置localStorage缓存数据\r\n * @param {string} key key值\r\n * @param {string} value value值\r\n */\r\nexport function setLocalStorage(key: string, value: string): void {\r\n window && window.localStorage.setItem(key, value);\r\n}\r\n\r\n/**\r\n * 通过key从localStorage缓存中删除数据\r\n * @param {string} key key值\r\n */\r\nexport function removeLocalStorage(key: string): void {\r\n window && window.localStorage.removeItem(key);\r\n}\r\n\r\n/**\r\n * 清空localStorage缓存中所有数据\r\n */\r\nexport function clearLocalStorage(): void {\r\n window && window.localStorage.clear();\r\n}\r\n","/* sessionStorage存储 */\r\n/**\r\n * 通过key从sessionStorage缓存中获取数据\r\n * @param {string} key key值\r\n * @returns {string} 返回数据\r\n */\r\nexport function getSessionStorage(key: string): string | undefined {\r\n return (window && window.sessionStorage.getItem(key)) || undefined;\r\n}\r\n\r\n/**\r\n * 设置sessionStorage缓存数据\r\n * @param {string} key key值\r\n * @param {string} value value值\r\n */\r\nexport function setSessionStorage(key: string, value: string): void {\r\n window && window.sessionStorage.setItem(key, value);\r\n}\r\n\r\n/**\r\n * 通过key从sessionStorage缓存中删除数据\r\n * @param {string} key key值\r\n */\r\nexport function removeSessionStorage(key: string): void {\r\n window && window.sessionStorage.removeItem(key);\r\n}\r\n\r\n/**\r\n * 清空sessionStorage缓存中所有数据\r\n */\r\nexport function clearSessionStorage(): void {\r\n window && window.sessionStorage.clear();\r\n}\r\n","/**\r\n * @module 函数\r\n */\r\n/**\r\n * 防抖函数\r\n * @description 事件执行后,在延迟时间内如果再次执行,会清空定时器重新延迟执行,举例:用户在输入框进行输入搜索,最终是会获取到最后一次输入,节约请求资源\r\n * @param {Function} fn 目标函数\r\n * @param {number} delay 延迟时间,单位毫秒,默认 1*1000 毫秒\r\n * @param {boolean} immediate 是否立即执行,默认true\r\n * @returns {Function} 返回function()\r\n */\r\nexport function debounce<T extends (...args: any[]) => any>(\r\n fn: T,\r\n delay: number = 1000,\r\n immediate: boolean = true,\r\n): (...args: Parameters<T>) => ReturnType<T> | void {\r\n // 定时器\r\n let timer: ReturnType<typeof setTimeout> | null = null;\r\n return function (this: ThisParameterType<T>, ...args: Parameters<T>) {\r\n // 先关闭定时器\r\n if (timer) clearTimeout(timer);\r\n\r\n // 立即执行判断\r\n if (immediate) {\r\n // 如果需要立即执行\r\n // 开启新定时器防止短时间内再次触发\r\n const canExecute = !timer;\r\n timer = setTimeout(() => {\r\n timer = null;\r\n }, delay);\r\n if (canExecute) fn.apply(this, args);\r\n }\r\n // 如果不需要立即执行\r\n else {\r\n // 每次触发开启新定时器即可\r\n timer = setTimeout(() => {\r\n fn.apply(this, args);\r\n }, delay);\r\n }\r\n };\r\n}\r\n\r\n/**\r\n * 节流函数\r\n * @description 高频触发时,在指定时间间隔内只执行一次,举例:监听页面滚动,不会频繁触发,只会在固定时间内获取一次\r\n * @param {Function} fn 目标函数\r\n * @param {number} interval 时间间隔,单位毫秒,默认1000毫秒\r\n * @returns {Function} 返回function()\r\n */\r\nexport function throttle<T extends (...args: any[]) => any>(\r\n fn: T,\r\n interval: number = 1000,\r\n): (...args: Parameters<T>) => ReturnType<T> | void {\r\n // 定时器\r\n let timer: ReturnType<typeof setTimeout> | null = null;\r\n return function (this: ThisParameterType<T>, ...args: Parameters<T>) {\r\n // 有定时器则返回\r\n if (timer) return;\r\n timer = setTimeout(() => {\r\n timer = null;\r\n fn.apply(this, args);\r\n }, interval);\r\n };\r\n}\r\n\r\n/**\r\n * 睡眠延迟执行\r\n * @description 需要配合 async/await 来达到延迟效果\r\n * @param {number} delay 延迟时间,单位毫秒,默认1000毫秒\r\n */\r\nexport function sleep(delay = 1000) {\r\n return new Promise((resolve) => setTimeout(resolve, delay));\r\n}\r\n","/**\r\n * @module 生成Id\r\n */\r\n/**\r\n * 生成UUID\r\n * @param {Number} len 生成的长度,默认32位\r\n * @param {Number} radix 进制数,默认16进制\r\n * @example\r\n * getUUID() // 输出:0a559343dbbf0e7e6c1de90163e7aa0a\r\n * @returns {String} 返回字符串\r\n */\r\nexport function getUUID(len: number = 32, radix: number = 16): string {\r\n const CHARS = \"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\".split(\"\");\r\n const uuid = [];\r\n let i = 0;\r\n radix = radix || CHARS.length;\r\n if (len) {\r\n for (i = 0; i < len; i++) uuid[i] = CHARS[0 | (Math.random() * radix)];\r\n } else {\r\n let r;\r\n uuid[8] = uuid[13] = uuid[18] = uuid[23] = \"-\";\r\n uuid[14] = \"4\";\r\n for (i = 0; i < 36; i++) {\r\n if (!uuid[i]) {\r\n r = 0 | (Math.random() * 16);\r\n uuid[i] = CHARS[i === 19 ? (r & 0x3) | 0x8 : r];\r\n }\r\n }\r\n }\r\n return uuid.join(\"\");\r\n}\r\n\r\n/**\r\n * 生成GUID\r\n * @example\r\n * getGUID() // 输出:275ec770-0853-6767-4875-7b270220ce9c\r\n * @returns {String} 返回字符串\r\n */\r\nexport function getGUID(): string {\r\n const s4 = function () {\r\n return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);\r\n };\r\n return s4() + s4() + \"-\" + s4() + \"-\" + s4() + \"-\" + s4() + \"-\" + s4() + s4() + s4();\r\n}\r\n","/**\r\n * @module 键盘\r\n */\r\nimport { KEYCODE } from \"@/constants\";\r\n\r\n/**\r\n * 根据keycode获得键名\r\n * @param {number} keycode 键值\r\n * @returns {string} 返回键名\r\n */\r\nexport function getKeyName(keycode: number): string {\r\n return KEYCODE[keycode];\r\n}\r\n\r\n/**\r\n * 根据keyname获得键值\r\n * @param {string} keyname\r\n * @returns {string} 返回键值\r\n */\r\nexport function getKeyCode(keyname: string): string | undefined {\r\n for (const key in KEYCODE) {\r\n if (KEYCODE[key] === keyname) {\r\n return key;\r\n }\r\n }\r\n}\r\n","/**\r\n * @module 随机数\r\n */\r\n/**\r\n * 生成指定大小的随机整数\r\n * @description n和m参数表示最小和最大范围值,默认0-9之间范围\r\n * @param {number} min 随机数的最小值,默认 0\r\n * @param {number} max 随机数的最大值,默认 9\r\n * @returns {number} 返回指定大小的随机整数\r\n */\r\nexport function getRandom(min: number = 0, max: number = 9): number {\r\n return Math.floor(Math.random() * (max - min + 1) + min);\r\n}\r\n\r\n/**\r\n * 生成固定位数的随机整数\r\n * @description 默认是1,代表生成0-9之间一位,如果是2,则生成10-99之间两位,以此类推\r\n * @param {number} len 固定的位数\r\n * @returns {number} 返回固定位数的随机数\r\n */\r\nexport function getRandomDigit(len: number = 1): number {\r\n return Math.floor((Math.random() + Math.floor(Math.random() * 9 + 1)) * Math.pow(10, len - 1));\r\n}\r\n","/**\r\n * @module 浏览器Storage\r\n */\r\n/**\r\n * 浏览器是否支持 Storage\r\n * @returns {boolean} 返回true和false\r\n */\r\nexport function isSupportStorage(): boolean {\r\n return !!(window.localStorage && window.sessionStorage);\r\n}\r\n\r\n/**\r\n * 导出localStorage和sessionStorage\r\n */\r\nexport * from \"./localStorage\";\r\nexport * from \"./sessionStorage\";\r\n","import * as MD5 from \"./md5.js\";\r\n\r\n/**\r\n * md5 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的十六进制字符串\r\n */\r\nexport function md5(str: string): string {\r\n return MD5.md5(str);\r\n}\r\n\r\n/**\r\n * md5 加密\r\n * @param {string} str 字符串\r\n * @returns {*} 返回加密后的二进制原始值\r\n */\r\nexport function md5Raw(str: string): any {\r\n return MD5.md5(str, undefined, true);\r\n}\r\n\r\n/**\r\n * md5_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的十六进制字符串\r\n */\r\nexport function md5Hmac(str: string, key: string): string {\r\n if (!str || !key) {\r\n throw new TypeError(\"md5Hmac: missing str or key\");\r\n }\r\n return MD5.md5(str, key, false);\r\n}\r\n\r\n/**\r\n * md5_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的二进制原始值\r\n */\r\nexport function md5HmacRaw(str: string, key: string): any {\r\n if (!str || !key) {\r\n throw new TypeError(\"md5HmacRaw: missing str or key\");\r\n }\r\n return MD5.md5(str, key, true);\r\n}\r\n","import * as SHA256 from \"./sha256.js\";\r\n\r\n// sha256\r\n/**\r\n * sha256 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sha256(str: string): string {\r\n return SHA256.sha256(str);\r\n}\r\n\r\n/**\r\n * sha256_raw 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的原始值\r\n */\r\nexport function sha256Raw(str: string): any {\r\n return SHA256.sha256_raw(str);\r\n}\r\n\r\n/**\r\n * sha256_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sha256Hmac(str: string, key: string): string {\r\n if (!str || !key) {\r\n throw new TypeError(\"sha256Hmac: missing str or key\");\r\n }\r\n return SHA256.sha256_hmac(key, str);\r\n}\r\n\r\n/**\r\n * sha256_hmac_raw 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的原始值\r\n */\r\nexport function sha256HmacRaw(str: string, key: string): any {\r\n if (!str || !key) {\r\n throw new TypeError(\"sha256HmacRaw: missing str or key\");\r\n }\r\n return SHA256.sha256_hmac_raw(key, str);\r\n}\r\n\r\n// sha224\r\n/**\r\n * sha224 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sha224(str: string): string {\r\n return SHA256.sha224(str);\r\n}\r\n\r\n/**\r\n * sha224_raw 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的原始值\r\n */\r\nexport function sha224Raw(str: string): any {\r\n return SHA256.sha224_raw(str);\r\n}\r\n\r\n/**\r\n * sha224_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sha224Hmac(str: string, key: string): string {\r\n if (!str || !key) {\r\n throw new TypeError(\"sha224Hmac: missing str or key\");\r\n }\r\n return SHA256.sha224_hmac(key, str);\r\n}\r\n\r\n/**\r\n * sha224_hmac_raw 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 秘钥\r\n * @returns {string} 返回加密后的原始值\r\n */\r\nexport function sha224HmacRaw(str: string, key: string): any {\r\n if (!str || !key) {\r\n throw new TypeError(\"sha224HmacRaw: missing str or key\");\r\n }\r\n return SHA256.sha224_hmac_raw(key, str);\r\n}\r\n","import * as sm3 from \"./sm3.js\";\r\n\r\n/**\r\n * sm3 加密\r\n * @param {string} str 字符串\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sm3Encrypt(str: string): string {\r\n return sm3.encrypt(str);\r\n}\r\n/**\r\n * sm3_hmac 加密\r\n * @param {string} str 字符串\r\n * @param {string} key 配置\r\n * @returns {string} 返回加密后的字符串\r\n */\r\nexport function sm3EncryptHmac(str: string, key: string): string {\r\n if (!str || !key) {\r\n throw new TypeError(\"sm3EncryptHmac: missing str or key\");\r\n }\r\n return sm3.encrypt(str, key);\r\n}\r\n","// 测试加载\r\nexport function testLoaded(): void {\r\n console.log(\"loaded successfully!\");\r\n}\r\n\r\n// 常量集合\r\nexport * from \"@/constants\";\r\n\r\n// 字符串\r\nexport * from \"@/string\";\r\n// 数字\r\nexport * from \"@/number\";\r\n// 数组\r\nexport * from \"@/array\";\r\n// 对象\r\nexport * from \"@/object\";\r\n// 函数\r\nexport * from \"@/function\";\r\n// 日期\r\nexport * from \"@/date/index.js\";\r\n// 数学\r\nexport * from \"@/math\";\r\n// 正则\r\nexport * from \"@/regexp\";\r\n// 随机数\r\nexport * from \"@/random\";\r\n\r\n// 文件\r\nexport * from \"@/file\";\r\n// 颜色\r\nexport * from \"@/color\";\r\n// 校验\r\nexport * from \"@/validate\";\r\n// 键盘\r\nexport * from \"@/keycode\";\r\n\r\n// 生成id\r\nexport * from \"@/id\";\r\n\r\n// 加解密算法\r\nexport * from \"@/crypto\";\r\n// 脱敏\r\nexport * from \"@/desensitized\";\r\n// 身份证号码\r\nexport * from \"@/ID-card\";\r\n// 分页\r\nexport * from \"@/pagination\";\r\n\r\n// 浏览器 Url\r\nexport * from \"@/url\";\r\n// 浏览器 Cookie\r\nexport * from \"@/cookie\";\r\n// 浏览器 Storage\r\nexport * from \"@/storage\";\r\n// 浏览器 Dom\r\nexport * from \"@/dom\";\r\n// 浏览器 Device\r\nexport * from \"@/device\";\r\n// 浏览器 Clipboard\r\nexport * from \"@/clipboard\";\r\n"],"names":["SORT","DESC","ASC","RANDOM","MATH","ROUND","ROUND_FLOOR","REGEXP","CH","EN","LOWER_CASE","UPPER_CASE","CH_NAME","EN_NAME","NUMBER","INTEGER","DECIMAL","INT_OR_FLOAT","MOBILE","PHONE","EMAIL","ID_CARD","ID_CARD15","ID_CARD18","BANK_CARD","POST_CODE","URL","IP","IP6","EXTERNAL","DATE","AM_PM","zh","AM","PM","en","WEEK","FULL","SHORT","MINI","MONTH","QUARTER","OVER_TIME","YEAR","HOUR","MINUTE","SECOND","MILLISECOND","DAY","PASS_TIME","BEFORE_YESTERDAY","YESTERDAY","TODAY","JUST","HOLIDAY","ZODIAC","CHINESE_ZODIAC","HEAVENLY_STEMS","EARTHLY_BRANCHES","KEYCODE","PROVINCE","SEX","MAN","WOMAN","isInteger","value","Number","isString","Object","prototype","toString","call","slice","isArray","isObject","isDate","isFalse","isNaN","Array","isNull","isEmpty","length","Map","Set","size","Date","RegExp","Error","keys","isBlank","test","isUndefined","undefined","toPascalCase","indexOf","newStr","replace","all","letter","toUpperCase","charAt","TypeError","parseInt","radix","String","arraySum","array","reduce","pre","cur","arrayInsertBefore","index","push","splice","arrayInsertAfter","mapToObject","map","obj","create","k","v","objectToMap","set","_getTargetPathPart","path","pathArrayMatch","match","propName","propIndex","isLeapYear","date","year","getFullYear","isBefore","startDate","endDate","getTime","isAfter","isSame","every","item","getDate","options","format","toDateString","getDateObject","month","getMonth","hours","getHours","minutes","getMinutes","seconds","getSeconds","milliseconds","getMilliseconds","getDayOfWeek","getDay","getDayOfMonth","getDayOfYear","Math","ceil","getDaysOfMonth","getDaysOfYear","getAge","age","dateArray","split","birthYear","birthMonth","birthDay","nowDate","nowYear","nowMonth","nowDay","diffAge","diffMonth","addYear","num","setFullYear","addMonth","setMonth","addDate","setDate","toDateUTC","getTimezoneOffset","toDate","lang","replaceRules","_datePadZero","day","hour","min","sec","padStart","isAm","toLowerCase","quarter","floor","result","entries","forEach","regStr","replaceFn","reg","_","gcd","arg1","arg2","a","abs","b","temp","regexpTest","regex","blobToFile","blob","fileName","now","Promise","resolve","reject","mime","type","fileSuffix","File","lastModified","err","console","error","blobToText","reader","FileReader","onload","e","target","onerror","readAsText","_hex","ENCODING_ERROR","BASE64_ENCODE_CHAR","BASE64_DECODE_CHAR","i","isNodeEnv","process","versions","node","isBrowserEnv","window","btoa","root","global","self","cleanBase64Str","base64Str","utf8ToBytes","str","len","bytes","byteIndex","c","charCodeAt","code","decodeAsBytes","count","v1","v2","v3","v4","remain","bytesToBase64Chars","strIndex","join","utf8Base64Encode","utf8Base64Decode","atob","from","fromCharCode","apply","followingChars","j","byte","charcode","tmpStr","encode","data","urlSafe","constructor","ArrayBuffer","Uint8Array","decode","safeAdd","x","y","lsw","md5cmn","q","s","t","cnt","md5ff","d","md5gg","md5hh","md5ii","binlMD5","olda","oldb","oldc","oldd","binl2rstr","input","output","length32","rstr2binl","length8","rstr2hex","hexTab","str2rstrUTF8","unescape","encodeURIComponent","rawMD5","rstrMD5","rawHMACMD5","key","hash","bkey","ipad","opad","concat","rstrHMACMD5","md5","string","raw","ERROR","HEX_CHARS","EXTRA","SHIFT","K","Sha256","is224","this","blocks","fill","h0","h1","h2","h3","h4","h5","h6","h7","block","start","hBytes","finalized","hashed","first","update","message","notString","isView","lastByteIndex","f","g","h","s0","s1","maj","t1","t2","ch","ab","da","cd","bc","finalize","hex","digest","arr","rawStr","arrayBuffer","buffer","dataView","DataView","setUint32","HmacSha256","keyBytes","oKeyPad","iKeyPad","sha256","inner","innerHash","createMethod","method","createRawMethod","createHmacMethod","createHmacRawMethod","sha256_raw","sha256_hmac","sha256_hmac_raw","sha224","sha224_raw","sha224_hmac","sha224_hmac_raw","BLOCK_LENGTH","IPAD","OPAD","IV","Uint32Array","rotl","n","xor","P0","X","arrayToHex","hexToArray","hexStr","words","hexStrLength","substr","utf8ToArray","point","codePointAt","sm3Core","kArr","lenArr","lenBin","m","V","W","M","getUint32","T1","T2","SS1","SS2","TT1","TT2","T","A","B","C","D","E","F","G","H","GGj","encrypt","inputArr","hmacArr","processedKey","iPadKey","oPadKey","encryptHmac","SM4_MODE_ECB","SM4_MODE_CBC","SM4_PADDING","SM4_OUTPUT_HEX","SM4_OUTPUT_UTF8","SM4_OUTPUT_ARRAY","SM4_OUTPUT_UINT8ARRAY","SM4_OUTPUT_ARRAYBUFFER","ENCRYPT","DECRYPT","ROUND_COUNT","BLOCK_SIZE","KEY_SIZE","IV_SIZE","SBOX","CK","FK","hexToUint8Array","normalizeInput","cryptFlag","TextEncoder","normalizeKeyIv","keyOrIv","expectedLength","name","rotl32","byteSub","linearTransformEnc","linearTransformKey","sm4BlockCrypt","inputBlock","outputBlock","roundKeys","offset","r","mid","wordIdx","sm4Core","inputData","mode","iv","padding","includes","ivBytes","processedInput","paddingCount","padded","pkcs7Pad","sm4KeyExpansion","outputData","lastVector","subarray","xorBlock","finalOutput","pkcs7Unpad","TextDecoder","uint8ArrayToHex","MODE","ECB","CBC","PADDING","generateSM4Key","outputFormat","crypto","getRandomValues","cryptoObj","keyUint8","generateSM4Iv","ivUint8","_validateSM4Options","operation","sm4.MODE","validModes","values","ivLength","byteLength","sm4.PADDING","SM4","OUTPUT","HEX","UTF8","ARRAY","UINT8ARRAY","ARRAYBUFFER","formatStartOf","startStr","padEnd","substring","getBirthdayByIDCard","idCard","getAgeByIDCard","birthday","getSexByIDCard","getProvinceByIDCard","prefix","getTotalPage","pagination","page","pageSize","total","totalPage","pagerCount","getSearchString","url","location","href","parseSearchParam","searchArr","param","decodeURIComponent","stringifySearchParam","params","setCookie","timestamp","document","cookie","hasClass","elem","className","addClass","removeClass","isPhone","ua","navigator","userAgent","setClipboardText","text","clipboard","writeText","then","success","failed","warn","ZH","r1","r2","pow","max","setHours","setMilliseconds","setMinutes","setSeconds","styles","style","setProperty","afterName","beforeIndex","findIndex","afterArr","array1","array2","filter","unshift","random","sort","props","prop","order","sourceIndex","targetIndex","setting","parentKey","childrenKey","nodeChildren","newChildren","tempMap","parent","children","Base64.decode","Base64.encode","Base64.fromHex","uint8Array","Base64.fromUint8Array","base64","mimeMatch","bstr","u8arr","Blob","Base64.toHex","Base64.toUint8Array","readAsDataURL","catch","domain","names","toUTCString","localStorage","clear","sessionStorage","source","assign","flags","fn","delay","immediate","timer","args","clearTimeout","canExecute","setTimeout","deepClone","copy","attr","hasOwnProperty","setTime","leftChain","rightChain","compare2Objects","xObj","yObj","isPrototypeOf","xObjKeys","yObjKeys","p","xProp","yProp","pop","arguments","objUrl","createObjectURL","link","createElement","download","click","revokeObjectURL","fileUrl","body","appendChild","removeChild","value1","value2","is","file","readAsArrayBuffer","toFixed","money","cnNums","cnIntRadiance","cnIntUnits","cnDecUnits","maxNum","integerNum","decimalNum","parts","chineseStr","parseFloat","zeroCount","IntLen","decLen","matchAll","acc","trim","curr","ie","edge","firefox","opera","chrome","safari","version","read","clipboardItems","list","types","getType","async","readText","tempArr","diff","lastIndexOf","weekDay","firstDateOfMonth","lastDateOfMonth","currentDate","dayOfWeek","firstDateOfWeek","firstDateOfYear","daysOfYear","s4","province","sex","keyname","keycode","getItem","callback","startTime","time","quarterNum","isEven","left","right","pagerLength","pager","getPropertyValue","CHARS","uuid","round","paths","current","part","startDay","fullDays","rgb","exec","l","color","opacity","o","htmlStr","endTime","Function","JSON","parse","diffDate1","diffDate2","cookieEnabled","json","newDate","stringify","MD5.md5","s2","objectEquals","obj1","obj2","maxLength","beforeParam","beforeArr","removeItem","delIndex","removeProperty","oldSubstr","newSubstr","newClassName","oldClassName","rgba","absA","absB","clipboardItem","ClipboardItem","write","setItem","nextPart","lastPath","SHA256.sha224","SHA256.sha224_hmac","SHA256.sha224_hmac_raw","SHA256.sha224_raw","SHA256.sha256","SHA256.sha256_hmac","SHA256.sha256_hmac_raw","SHA256.sha256_raw","sm3.encrypt","finalOptions","sm4.decrypt","sm4.encrypt","replacer","log","interval","decimals","_toDecimalRound","_toDecimalFloor","$2","decimalLength","$3","pm","$1","digitArr","_toFixedRound","numVal","dec","tempNumStr","pointIndex","pointCount","tempNumA","integerPart","decimalPart","_toFixedFloor","toLocaleLowerCase","toLocaleUpperCase","treeToArray","nodes","imgUrl","img","Image","src","canvas","context","getContext","width","height","drawImage","toDataURL","fetch","res","status"],"mappings":"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"}