diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c22099..cbd069c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### 🚀v1.3.0 增加范围数字/直线路径/打组方法/IP地址验证 +➕: Generate.rangeNumber 范围数字 +➕: Generate.straightLinePath 直线路径 +➕: group 打组方法 +➕: isIPAddress IP地址验证 + ### 🚀v1.2.9 修复获取随机数(整数)最小值控制 🔧: 修复获取随机数(整数)最小值控制 diff --git a/README.md b/README.md index 04605ca..95dbf24 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,9 @@ export default { ```js console.log('深克隆', cloneDeep({ /** 需要克隆的对象 */ })); console.log('执行时间', executionTime(() => { /** 要做的事情 */ })); +console.log('防抖', antiShake(() => { /** 要做的事情 */ }, 1000)()); +console.log('节流', throttle(() => { /** 要做的事情 */ }, 1000)()); +console.log('打组', group([1, 2, 3, 4, 5], (item, index) => item % 3)); ``` @@ -109,6 +112,16 @@ console.log('字节转换',Convertor.byteFormat(1099511627776,2)); ``` +#### Generate 生成模块 +包含一些生成的方法. + +以下是相关示例: +```js +console.log('范围数字', Generate.rangeNumber(1, 7)); // [ 1, 2, 3, 4, 5, 6 ] +console.log('直线路径', Generate.straightLinePath(v2(0, 0), v2(0, 2), v2(2, 2))); // [{ x: 0, y: 0 },{ x: 0, y: 1 },{ x: 0, y: 2 },{ x: 1, y: 2 },{ x: 2, y: 2 }] + +``` + #### Map 地图模块 包含一些与地图的方法. @@ -175,6 +188,7 @@ console.log('随机一个长度为10的只有大小写的字母字符串', Rando console.log('全局唯一标识符(uuid)', Randoms.uuid()); // 数据格式 [{name:string,weight:number}] weight 支持自定义在第二个参数中 console.log('按权重获取随机索引', Randoms.getRandomIndexByWeight(prizes)); +console.log('随机获取颜色', Randoms.getRandomColor()); ``` @@ -212,6 +226,7 @@ console.log('像身份证号', '622924198810193427'.likeIDCardNumber); console.log('是否是身份证号码', '622924198810193427'.isCitizenIdentificationNumber); console.log('密码规则校验', 'abc123'.passwordRules(PasswordRuleEnum.SmallNumber, 6, 20)); console.log('判断版本是否相等', '1.0.0'.versionComparison('1.0.0')); +console.log('是否是IP地址', Verify.isIPAddress('244.255.123.1')); ``` diff --git a/index.d.ts b/index.d.ts index 09bb42b..d825f73 100644 --- a/index.d.ts +++ b/index.d.ts @@ -8,3 +8,4 @@ export * from './lib/verify.js'; export * from './lib/market.js'; export * from './lib/animation.js'; export * from './lib/picture.js'; +export * from './lib/generate.js'; diff --git a/index.js b/index.js index 09bb42b..d825f73 100644 --- a/index.js +++ b/index.js @@ -8,3 +8,4 @@ export * from './lib/verify.js'; export * from './lib/market.js'; export * from './lib/animation.js'; export * from './lib/picture.js'; +export * from './lib/generate.js'; diff --git a/package.json b/package.json index 471573d..d37538f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@3r/tool", - "version": "1.2.9", + "version": "1.3.0", "description": "🏃‍包含一些常用方法例如对象深克隆/数组交集、并集、差集/二维向量点乘、叉乘/股票KDJ、MACD、RSI、BOLL/验证为空、车牌号、邮箱、身份证、统一社会信用代码、手机号、版本对比/转换日期、星座、身份证解析、字节...持续更新整合", "main": "index.js", "type": "module", diff --git a/src/index.ts b/src/index.ts index 3cc6083..a03bd06 100644 --- a/src/index.ts +++ b/src/index.ts @@ -8,3 +8,4 @@ export * from './lib/verify.js' export * from './lib/market.js' export * from './lib/animation.js' export * from './lib/picture.js' +export * from './lib/generate.js' diff --git a/src/lib/common.ts b/src/lib/common.ts index caa6889..27c37b3 100644 --- a/src/lib/common.ts +++ b/src/lib/common.ts @@ -61,3 +61,20 @@ export function throttle(fn: () => void, delay: number) { }, delay) } } + +/** + * 打组方法 + * 例: + * group([1,2,3,4,5],(item,index)=> item % 3) => [ [ 3 ], [ 1, 4 ], [ 2, 5 ] ] + * @param arr + * @param func + * @returns + */ +export function group(arr: Array, func: (item: T, index: number) => any) { + const tmpDict: any = {} + for (let i = 0; i < arr.length; i++) { + if (!tmpDict[func(arr[i], i)]) tmpDict[func(arr[i], i)] = [] + tmpDict[func(arr[i], i)].push(arr[i]) + } + return Object.values(tmpDict) +} diff --git a/src/lib/generate.ts b/src/lib/generate.ts new file mode 100644 index 0000000..f11b87f --- /dev/null +++ b/src/lib/generate.ts @@ -0,0 +1,41 @@ +import { Vector2 } from '../lib/vertor2.js' +/** + * 生成 + */ +export class Generate { + /** 生成范围数字 例如 1 - 7) [1,2,3,4,5,6] or [7,6,5,4,3,2] + * @param start + * @param end + * @param step + */ + static rangeNumber(start: number, end: number, step = 1) { + const nums = [] + if (end > start) { + for (let i = start; i < end; i += step) { + nums.push(i) + } + } else { + for (let i = start; i > end; i -= step) { + nums.push(i) + } + } + return nums + } + /** 通过一些坐标点生成直线路径 [start,...,end] + */ + static straightLinePath(...points: Array) { + let path: Vector2[] = [] + for (let i = 1; i < points.length; i++) { + const start = points[i - 1] + const end = points[i] + if (start.x === end.x) { + path = path.concat(Generate.rangeNumber(start.y, end.y).map(n => Object({ x: start.x, y: n }))) + } + if (start.y === end.y) { + path = path.concat(Generate.rangeNumber(start.x, end.x).map(n => Object({ x: n, y: start.y }))) + } + } + path.push(points[points.length - 1]) + return path + } +} diff --git a/src/lib/verify.ts b/src/lib/verify.ts index 590a149..d27d56b 100644 --- a/src/lib/verify.ts +++ b/src/lib/verify.ts @@ -18,13 +18,29 @@ export enum PasswordRuleEnum { * 验证拓展类 */ export class Verify { + /** 像是社会统一信用代码正则 */ + static readonly LIKE_USCI_REGEXP = /[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}/ + /** IP地址验证正则 */ + static readonly IP_ADDRESS_REGEXP = /^(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|[1-9])\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)\.(1\d{2}|2[0-4]\d|25[0-5]|[1-9]\d|\d)$/ + /** 手机号码正则表达式 */ + static readonly PHONE_NUMBER_REGEXP = /^1[3456789]\d{9}$/ + /** 电话号码正则表达式 */ + static readonly TELL_PHONE_NUMBER_REGEXP = /^\d{3}-\d{7,8}|\d{4}-\d{7,8}$/ + /** 电子邮箱正则 */ + static readonly EMAIL_REGEXP = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/ + /** 油车车牌正则 */ + static readonly VEHICLE_NUMBER_REGEXO = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/ + /** 电车车牌正则 */ + static readonly ELECTRIC_VEHICLE_NUMBER_REGEXO = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DABCEFGHJK]$)|([DABCEFGHJK][A-HJ-NP-Z0-9][0-9]{4}$))/ + /** 像是身份证号码正则 */ + static readonly LIKE_ID_CARD_NUMBER_REGEXO = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/ /** * 像是社会统一信用代码 * @param usci 社会统一信用代码 * @returns */ static likeUsci(usci: string): boolean { - return /[0-9A-HJ-NPQRTUWXY]{2}\d{6}[0-9A-HJ-NPQRTUWXY]{10}/.test(usci) + return Verify.LIKE_USCI_REGEXP.test(usci) } /** @@ -43,7 +59,7 @@ export class Verify { * @returns */ static isPhoneNumber(phoneNumber: string): boolean { - return /^1[3456789]\d{9}$/.test(phoneNumber) + return Verify.PHONE_NUMBER_REGEXP.test(phoneNumber) } /** @@ -52,7 +68,7 @@ export class Verify { * @returns */ static isTellPhoneNumber(tellPhoneNumber: string): boolean { - return /^\d{3}-\d{7,8}|\d{4}-\d{7,8}$/.test(tellPhoneNumber) + return Verify.TELL_PHONE_NUMBER_REGEXP.test(tellPhoneNumber) } /** @@ -61,7 +77,7 @@ export class Verify { * @returns */ static isEmail(email: string): boolean { - return /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(email) + return Verify.EMAIL_REGEXP.test(email) } /** @@ -160,8 +176,8 @@ export class Verify { * @returns */ static isVehicleNumber(vehicleNumber: string) { - if (vehicleNumber.length === 7) return /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳]{1}$/.test(vehicleNumber) - if (vehicleNumber.length === 8) return /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}(([0-9]{5}[DABCEFGHJK]$)|([DABCEFGHJK][A-HJ-NP-Z0-9][0-9]{4}$))/.test(vehicleNumber) // 2021年新能源车牌不止有DF + if (vehicleNumber.length === 7) return Verify.VEHICLE_NUMBER_REGEXO.test(vehicleNumber) + if (vehicleNumber.length === 8) return Verify.ELECTRIC_VEHICLE_NUMBER_REGEXO.test(vehicleNumber) // 2021年新能源车牌不止有DF return false } @@ -171,7 +187,7 @@ export class Verify { * @returns */ static likeIDCardNumber(num: string): boolean { - return /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(num) + return Verify.LIKE_ID_CARD_NUMBER_REGEXO.test(num) } /** @@ -226,6 +242,15 @@ export class Verify { } return 0 } + + /** + * IP地址验证 + * @param ipaddr 验证ip + * @returns + */ + static isIPAddress(ipaddr: string) { + return Verify.IP_ADDRESS_REGEXP.test(ipaddr) + } } const ignorePrototype = ['passwordRules', 'versionComparison']; @@ -292,6 +317,11 @@ declare global { * 是否是身份证号码 */ isCitizenIdentificationNumber: boolean; + + /** + * 是否是IP地址 IPv4 + */ + isIPAddress: boolean; /** * 密码规则校验 * @param rule 规则 diff --git a/test/common.test.js b/test/common.test.js index c738e48..1e04a40 100644 --- a/test/common.test.js +++ b/test/common.test.js @@ -1,4 +1,4 @@ -import { cloneDeep, v2, executionTime, throttle, antiShake } from "../index.js"; +import { cloneDeep, v2, executionTime, throttle, antiShake, group } from "../index.js"; let description = function () { return ['#### Common 常用模块', '包含一些常用的方法.', '', '以下是相关示例:'] } @@ -8,6 +8,7 @@ let run = function () { console.log('执行时间', executionTime(() => { /** 要做的事情 */ })); console.log('防抖', antiShake(() => { /** 要做的事情 */ }, 1000)()); console.log('节流', throttle(() => { /** 要做的事情 */ }, 1000)()); + console.log('打组', group([1, 2, 3, 4, 5], (item, index) => item % 3)); } try { jest.useFakeTimers(); @@ -75,6 +76,9 @@ try { jest.advanceTimersByTime(3000) expect(fn).toHaveBeenCalledTimes(0) }) + it('打组', function () { + expect(group([1, 2, 3, 4, 5], (item, index) => item % 3)).toEqual([[3], [1, 4], [2, 5]]) + }) }) } catch (error) { console.log(error); diff --git a/test/generate.test.js b/test/generate.test.js new file mode 100644 index 0000000..0289723 --- /dev/null +++ b/test/generate.test.js @@ -0,0 +1,30 @@ +import { Generate, v2 } from "../index.js"; + +let description = function () { + return ['#### Generate 生成模块', '包含一些生成的方法.', '', '以下是相关示例:'] +} + +let run = function () { + console.log('范围数字', Generate.rangeNumber(1, 7)); // [ 1, 2, 3, 4, 5, 6 ] + console.log('直线路径', Generate.straightLinePath(v2(0, 0), v2(0, 2), v2(2, 2))); // [{ x: 0, y: 0 },{ x: 0, y: 1 },{ x: 0, y: 2 },{ x: 1, y: 2 },{ x: 2, y: 2 }] +} +try { + describe('生成模块', function () { + it('范围数字', function () { + expect(Generate.rangeNumber(1, 7)).toEqual([1, 2, 3, 4, 5, 6]) + expect(Generate.rangeNumber(7, 1)).toEqual([7, 6, 5, 4, 3, 2]) + }) + it('直线路径', function () { + expect(Generate.straightLinePath(v2(0, 0), v2(0, 2), v2(2, 2))).toEqual([{ x: 0, y: 0 }, { x: 0, y: 1 }, { x: 0, y: 2 }, { x: 1, y: 2 }, { x: 2, y: 2 }]) + }) + }) +} catch (error) { + // describe is not defined 无需理会 调用方式不一致 +} + + + +export { + run, + description +} \ No newline at end of file diff --git a/test/verify.test.js b/test/verify.test.js index ea35684..c33137a 100644 --- a/test/verify.test.js +++ b/test/verify.test.js @@ -34,6 +34,7 @@ let run = function () { console.log('是否是身份证号码', '622924198810193427'.isCitizenIdentificationNumber); console.log('密码规则校验', 'abc123'.passwordRules(PasswordRuleEnum.SmallNumber, 6, 20)); console.log('判断版本是否相等', '1.0.0'.versionComparison('1.0.0')); + console.log('是否是IP地址', Verify.isIPAddress('244.255.123.1')); } try { @@ -123,6 +124,10 @@ try { expect('1.2.1'.versionComparison('1.1.2')).toEqual(1) expect('1.2.1.1'.versionComparison('1.1.2.1')).toEqual(1) }); + it('是否是IP地址', function () { + expect('244.255.123.1'.isIPAddress).toEqual(true) + expect('244.256.123.1'.isIPAddress).toEqual(false) + }); }) } catch (error) { // describe is not defined 无需理会 调用方式不一致