npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

great-jsutils

v1.4.4

Published

js工具类 [时间示例演示:https://zhtt.gitee.io/angular-demo/great-ngform6/#/jsutils/time-test](https://zhtt.gitee.io/angular-demo/great-ngform6/#/jsutils/time-test)、

Downloads

147

Readme

jsutils api

js工具类
时间示例演示:https://zhtt.gitee.io/angular-demo/great-ngform6/#/jsutils/time-test

数组示例演示:https://zhtt.gitee.io/angular-demo/great-ngform6/#/jsutils/array-test

友情链接

great-generatorgreat-jsutilsgreat-ngformgreat-zorroutilsgreat-vue

安装

npm i great-jsutils --save

License

请查看 MIT license.

一、数组

import { ArrayUtils } from 'great-jsutils';

添加元素

ArrayUtils.add(array: any, obj: any, {idKey : 'id', pIdKey : 'parentId', childKey : 'children'} = {});

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | array | 被操作的数组 | 是 | Array | | obj | 被添加的元素 | 是 | any | | keys | 主键、子属性对应关系 | 否 | string |

示例1:添加元素

function add01() {
    let data = [{
        'id': 'A', 'type': '1', 'children': [
            {
                'id': 'A01', 'type': '2', 'children': [
                    {'id': 'A01-01', 'type': '3'}
                ]
            },
            {'id': 'A03', 'type': '3'}
        ]
    }];
    let child = {'id': 'A03-01', 'parentId': 'A03'};
    let result = ArrayUtils.add(data, child);
    console.log(result,JSON.stringify(data));
}
function add02() {
    let data = [{
        'orgId': 'A', 'type': '1', 'children': [
            {'orgId': 'A01', 'type': '2'},
            {'orgId': 'A03', 'type': '3'}
        ]
    }];
    let child = {'orgId': 'A03-01', 'parentId': 'A03'};
    let result = ArrayUtils.add(data, child,{idKey:'orgId'});
    console.log(result,JSON.stringify(data));
}
function add03() {
    let data = [{
        'orgId': 'A', 'type': '1', 'items': [
            {'orgId': 'A01', 'type': '2'},
            {'orgId': 'A03', 'type': '3'}
        ]
    }];
    let child = {'orgId': 'A03-01', 'parentId': 'A03'};
    let result = ArrayUtils.add(data, child,{idKey:'orgId',childKey:'items'});
    console.log(result,JSON.stringify(data));
}
function add04() {
    let data = [{
        'id': 'A', 'type': '1', 'children': [
            {'id': 'A03', 'type': '3'}
        ]
    }];
    let keys = {'id': 'key'};
    let child = {'id': 'A03-01', 'parent': {'id': 'A03'}};
    let result = ArrayUtils.add(data, child,{'pIdKey':'parent'});
    console.log(result,JSON.stringify(data));
}

移除元素

ArrayUtils.remove(array,value,key);

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | array | 被操作的数组 | 是 | Array | | value | 需要移除的值 | 是 | any | | keys | 主键、子属性对应关系 | 否 | string |

示例1:移除字符串

//字符串移除,第一个参数是被操作的数组,第二个参数是需要移除的字符串
function testArray(){
    let arr=['a','b','c'];
    ArrayUtils.remove(arr,'b');
    console.log(arr.join(','));//a,c
}

示例2:对象移除

function removeRoot01() {
    let objArr=[{'id':'1','name':'赵云'},{'id':'2','name':'诸葛亮'}];
    ArrayUtils.remove(objArr,{'id':'2'});
    console.log(JSON.stringify(objArr));//[{'id':'1','name':'赵云'}]
}

示例3:对象移除

function removeRoot02() {
    let objArr=[{'userId':'1','name':'赵云'},{'userId':'2','name':'诸葛亮'}];
    ArrayUtils.remove(objArr,{'userId':'2'},{idKey:'userId'});
    console.log(JSON.stringify(objArr));//[{'userId':'1','name':'赵云'}]
}

示例4:子节点移除

function removeChild01() {
    let objArr=[{'id':'1','name':'山东省','children':[{'id':'2','name':'济南市'}]}];
    ArrayUtils.remove(objArr,{'id':'2'});
    console.log(JSON.stringify(objArr));//[{'id':'1','name':'赵云'}]
}
function removeChild02() {
    let objArr=[{'id':'1','name':'山东省','items':[{'id':'2','name':'济南市'}]}];
    ArrayUtils.remove(objArr,{'id':'2'},{childKey:'items'});
    console.log(JSON.stringify(objArr));//[{'id':'1','name':'赵云'}]
}

更新元素

ArrayUtils.update(array,obj,keys);

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | array | 被操作的数组 | 是 | Array | | obj | 需要更新的对象 | 是 | any | | keys | 主键、子属性对应关系 | 否 | string |

示例1:更新根节点中的元素

//字符串移除,第一个参数是被操作的数组,第二个参数是需要更新的对象

function updateRoot01() {
    let obj={'id':'001','name':'001'};
    let array=[{'id':'001','name':'111'}];
    let newArray=ArrayUtils.update(array,obj);
    console.log(JSON.stringify(array));
}

示例2:更新根节点中的元素

import { ArrayUtils } from 'great-jsutils';

function updateRoot02() {
    let obj={'userId':'002','name':'222'};
    let array=[{'userId':'002','name':'111'}];
    let newArray=ArrayUtils.update(array,obj,{idKey:'userId'});
    console.log(JSON.stringify(array));
}

示例3:更新子节点中的元素

import { ArrayUtils } from 'great-jsutils';
function updateChildren01() {
    let obj={'id':'001','name':'001'};
    let array=[{'id':'a','name':'111','children':[{'id':'001','name':'222'}]}];
    ArrayUtils.update(array,obj);
    console.log(JSON.stringify(array));
}

示例4:更新子节点中的元素

import { ArrayUtils } from 'great-jsutils';
function updateChildren02() {
    let obj={'userId':'001','name':'001'};
    let array=[{'userId':'A','name':'A','items':[{'userId':'001','name':'222'}]}];
    ArrayUtils.update(array,obj,{idKey:'userId',childKey:'items'});
    console.log(JSON.stringify(array));
}

**示例5:更新时,增加key


function updateChildren03() {
    let obj={'userId':'001','name':'001','checked':true};
    let array=[{'userId':'A','name':'A','items':[{'userId':'001','name':'222'}]}];
    ArrayUtils.update(array,obj,{idKey:'userId',childKey:'items'},function(oldData,newData){
        return {'checked':newData['checked']};
    });
    console.log(JSON.stringify(array));

}

合并元素

ArrayUtils.merge(array,obj,keys);

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | array | 被操作的数组 | 是 | Array | | obj | 需要更新的对象 | 是 | any | | keys | 主键、子属性对应关系 | 否 | string |

与update类似,这个会增加第二个参数中的新属性

属性替换

ArrayUtils.updateKey(array,keys,function);

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | array | 被操作的数组 | 是 | Array | | keys | 原key与新key的对应关系 | 是 | json | | function | 自定义需要添加的属性 | 否 | string |

示例1:属性替换

import { ArrayUtils } from 'great-jsutils';
//数组中的对象key替换,例如源数据为[{'name':'张三'}]替换为[{'text':'张三'}]
function testArray(){
    let datas=[{'name':'张三','sex':'1'}];
    let keys={'name':'text'};
    let result=ArrayUtils.updateKey(datas,keys);
    console.log(result);//{name: '张三', sex: '1'}
}

示例2:属性替换,并添加新属性

//数组中对象key替换,例如源数据为[{'name':'张三','age':80}]替换为[{'text':'张三','age':80,'ageGroup':'老年人'}];
//这里是根据某些值特征,增加新的属性
function testArray(){
    let datas=[{'name':'张三','sex':'1'}];
    let keys={'name':'text'};
    let result=ArrayUtils.updateKey(data,keys,function(){
        if(data['age']>75){
            return {'ageGroup':'老年人'};
        }
    });
    console.log(result);//[{'text':'张三','age':80,'ageGroup':'老年人'}];
}

获取树节点

ArrayUtils.get(array,obj,keys);

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | array | 被操作的数组 | 是 | Array | | obj | 需要更新的对象 | 是 | any | | keys | 主键、子属性对应关系 | 否 | string |

示例1:根据主键获取

//从树状数组中,根据id的值获取节点数据

function get01() {
    let data = [ {'id': 'A01', 'type': '2'},{'id': 'A03', 'type': '3'}];
    let item = ArrayUtils.get(data, 'A03');
    console.log(item);//{'id': 'A03', 'type': '3'}
}
function get02() {
    let data = [ {'userId': 'A01', 'type': '2'},{'userId': 'A03', 'type': '3'}];
    let item = ArrayUtils.get(data, 'A03',{idKey:'userId'});
    console.log(item);//{'id': 'A03', 'type': '3'}
}
function get03() {
    let data = [ {'userId': 'A01', 'type': '2'},{'userId': 'A03', 'type': '3'}];
    let item = ArrayUtils.get(data, {'id':'A03'});
    console.log(item);//{'id': 'A03', 'type': '3'}
}
function get() {
    let data = [{
        'id': 'A', 'type': '1', 'children': [
            {
                'id': 'A01', 'type': '2', 'children': [
                    {
                        'id': 'A01-01', 'type': '3', 'children': [
                            {'id': 'A01-01-01', 'type': '3-01', 'children': [
                                    {'id': 'A01-01-01', 'type': '3-02'}
                                ]}
                        ]
                    }, {
                        'id': 'A01-02', 'type': '3', 'children': [
                            {'id': 'A01-02-01', 'type': '3-01', 'children': [
                                    {'id': 'A01-02-01-01', 'type': '3-02', 'children': [
                                            {'id': 'A01-02-01-01-01', 'type': '3-02'}
                                        ]}
                                ]}
                        ]
                    }
                ]
            },
            {'id': 'A03', 'type': '3'}
        ]
    }];
    let item = ArrayUtils.get(data, 'A01-02-01-01-01');
    console.log(item);//{ id: 'A01-02-01-01-01', type: '3-02' }
}

示例2:根据主键获取

//从树状数组中,根据id的值获取节点数据
function getTreeNodeById(){
    let arr=[{'id':'A','type':'1','children':[
                {'id':'A01','type':'2','children':[
                    {'id':'A01-01','type':'3','children':[
                        {'id':'A01-01-01','type':'3-01'}
                    ]},
                    {'id':'A01-02','type':'3','children':[
                        {'id':'A01-02-01','type':'3-02'}
                    ]}
                ]},
                {'id':'A03','type':'3'}
            ]}];
    let item=ArrayUtils.get(arr,'A01-02-01','id','children');
    console.log(item);//{ id: 'A01-02-01', type: '3-02' }
}

是否是个有效的数组对象

ArrayUtils.valid(array);

是否是个有效的数组对象,有则返回第一个子元素,否则返回false

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | array | 被操作的数组 | 是 | Array |

示例1:是否是个有效的数组对象

//从树状数组中,根据id的值获取节点数据
function valid(){
    let arr=[{'id':'A','type':'1','children':[
                {'id':'A01','type':'2','children':[
                    {'id':'A01-01','type':'3','children':[
                        {'id':'A01-01-01','type':'3-01'}
                    ]},
                    {'id':'A01-02','type':'3','children':[
                        {'id':'A01-02-01','type':'3-02'}
                    ]}
                ]},
                {'id':'A03','type':'3'}
            ]}];
    let item=ArrayUtils.valid(arr);
    console.log(item);
}

节点向上移动操作

示例一:将第二个元素上移到第2个位置

/**
* 将第二个元素上移2个位置
*/
function move01() {
   let arr=['a','b','c','d','e'];
    //ArrayUtils
    let index=2;
    let size=2;
    ArrayUtils.up(arr,index,{size});
    console.log(arr);
}

示例二:将第二个元素上移到第2个位置

/**
* 将第二个元素下移到第2个位置
*/
function move01() {
   let arr=['a','b','c','d','e'];
    //ArrayUtils
    let index=2;
    let end=2;
    ArrayUtils.up(arr,index,{end});
    console.log(arr);
}

节点向下移动操作

示例一:将第二个元素,移动到第1个位置

/**
* 将第二个元素下移2个位置
*/
function down10() {
    let arr=['a', 'b', 'c', 'd'];
    console.log('移动前',arr);
    let index=2;
    let end=1;
    ArrayUtils.down(arr,index,{end});
    console.log('移动后',arr);
    /**
     * 移动前 [ 'a', 'b', 'c', 'd' ]
     * 移动后 [ 'a', 'c', 'b', 'd' ]
     */
}

示例一:将第二个元素下移到第2个位置

/**
* 将第二个元素下移2个位置
*/
function move01() {
   let arr=['a','b','c','d','e'];
    //ArrayUtils
    let index=2;
    let size=2;
    ArrayUtils.down(arr,index,{size});
    console.log(arr);
}

示例二:将第二个元素下移到第2个位置

/**
* 将第二个元素下移到第2个位置
*/
function move01() {
   let arr=['a','b','c','d','e'];
    //ArrayUtils
    let index=2;
    let end=2;
    ArrayUtils.down(arr,index,{end});
    console.log(arr);
}

将指定索引的节点移到底部

将第二个元素移动到底部

function moveBottom() {
    let arr = ['a', 'b', 'c', 'd', 'e'];
    //ArrayUtils
    let index = 2;
    ArrayUtils.bottom(arr,index);
    console.log(arr);
}

移动对象

function moveBottom2() {
    let arr = [{name:'1'},{name:'2'},{name:'3'},{name:'4'}];
    let index = 2;
    ArrayUtils.bottom(arr,index);
    console.log(arr);
    /**
     * 打印结果:
     * [ { name: '1' }, { name: '2' }, { name: '4' }, { name: '3' } ]
     */
}

将指定索引的节点移到顶部

将第二个元素移动到顶部

function top() {
    let arr = ['a', 'b', 'c', 'd', 'e'];
    //ArrayUtils
    let index = 2;
    ArrayUtils.top(arr,index);
    console.log(arr);
}

移动对象

function top() {
    let arr = [{name:'1'},{name:'2'},{name:'3'},{name:'4'}];
    let index = 2;
    ArrayUtils.top(arr,index);
    console.log(arr);
    /**
     * 打印结果:
     * [ { name: '3' }, { name: '1' }, { name: '2' }, { name: '4' } ]
     */
}

节点位置交换

/**
 * 两个元素交换位子
 * @param arr:被移动的数组
 * @param index1:被移动的元素一
 * @param index2:被移动的元素二
 * @returns {any}
 */
ArrayUtils.swap(arr, index1, index2);

示例:将第一个和第三个进行交换

function swap(){
    let arr = [{name:'1'},{name:'2'},{name:'3'},{name:'4'}];
    ArrayUtils.swap(arr,1,3);
    console.log(arr);
    /**
     * 打印结果:
     * [ { name: '1' }, { name: '4' }, { name: '3' }, { name: '2' } ]
     */
}

二、 加密

示例1:md5

//字符串的加密
import {JsUtilsApi } from 'great-jsutils';
function md5() {
  JsUtilsApi.md5('admin123456')
}

示例2:Base64

//字符串的加密、解密
import {Base64 } from 'great-jsutils';
function base64() {
console.log('base64:',Base64.encode('123'));
console.log('base64:',Base64.decode('MTIz'));
}

示例3:md5File,读取文件内容生成md5值

//字符串的加密、解密
import {JsUtilsApi } from 'great-jsutils';
function md5File() {
    JsUtilsApi.md5File(file).then(
      (md5)=>{ // 成功回调
        this.file.fileMd5 = md5;
      }
    );
}

三、 时间工具类

  • 常量
FORMAT_FULL = 'yyyy-MM-dd hh:mm:ss';
FORMAT_FULL_IE = 'yyyy/MM/dd hh:mm:ss';
FORMAT_FULL_CN = 'yyyy年MM月dd日 hh时mm分ss秒';
FORMAT_YMD = 'yyyy-MM-dd';
FORMAT_YMD_IE = 'yyyy/MM/dd';
FORMAT_YMD_CN = 'yyyy年MM月dd日';
FORMAT_HMS = 'hh:mm:ss';
FORMAT_HMS_CN = 'hh时mm分ss秒';
import { TimeUtils } from 'great-jsutils';

判断是否是日期类型

TimeUtils.isDate(args);

获取某天开始、结束时间 TimeUtils.getDayTime(n:number);

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | n | 获取n天前时间,不传则为当天时间 | 否 | number |

根据传入的数字,获取n天前的开始结束时间,正数则往后推,负数则往前推

import {TimeUtils } from 'great-jsutils';
function testTime(){
    console.log('当天开始、结束时间',TimeUtils.getDayTime());
    //当天开始、结束时间 { start: '2018-08-31 00:00:00', end: '2018-08-31 24:59:59' }
    console.log('获取昨天时间:',TimeUtils.getDayTime(-1));
    console.log('获取前天时间:',TimeUtils.getDayTime(-2));
    console.log('获取明天时间:',TimeUtils.getDayTime(1));
    console.log('获取后天时间:',TimeUtils.getDayTime(1));
}

获取某周开始、结束时间

TimeUtils.getWeekTime(n:number); 

根据传入的数字,获取n周前的开始结束时间,正数则往后推,负数则往前推

import {TimeUtils } from 'great-jsutils';
function testTime(){
    console.log('本周开始、结束时间',TimeUtils.getWeekTime());
    //本周开始、结束时间 { start: '2018-09-17 00:00:00', end: '2018-09-23 24:59:59' }
    console.log('上周开始、结束时间',TimeUtils.getWeekTime(-1));
    //上周开始、结束时间 { start: '2018-09-10 00:00:00', end: '2018-09-16 24:59:59' }
}

获取某月开始、结束时间

 TimeUtils.getMonthTime(integer);

根据传入的数字,获取n月前的开始结束时间,正数则往后推,负数则往前推

import {TimeUtils } from 'great-jsutils';
function testTime(){
    console.log('本月开始、结束时间',TimeUtils.getMonthTime());
    //本月开始、结束时间 { start: '2018-09-01 00:00:00', end: '2018-09-30 24:59:59' }
    console.log('上月开始、结束时间',TimeUtils.getMonthTime(-1));
    //上月开始、结束时间 { start: '2018-08-01 00:00:00', end: '2018-08-31 24:59:59' }
}

获取某季度开始、结束时间

TimeUtils.getQuarterTime(n:number); 

根据传入的数字,获取n月前的开始结束时间,正数则往后推,负数则往前推

import {TimeUtils } from 'great-jsutils';
function testTime(){
    console.log('本季度开始结束时间',TimeUtils.getQuarterTime());
    //本季度开始结束时间 { start: '2018-07-01 00:00:00', end: '2018-09-30 24:59:59' }
    console.log('上季度开始结束时间',TimeUtils.getQuarterTime(-1));
}

获取某年开始、结束时间

TimeUtils.getYearTime(n:number); 

根据传入的数字,获取n年前的开始结束时间,正数则往后推,负数则往前推

import {TimeUtils } from 'great-jsutils';
function testTime(){
    console.log('本年开始结束时间',TimeUtils.getYearTime());
    //本年开始结束时间 { start: '2018-01-01 00:00:00', end: '2018-12-31 24:59:59' }
    console.log('上年开始结束时间',TimeUtils.getYearTime(-1));
}

获取N天内的开始、结束时间

getWinthInDayTime

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | num | 指定天数 | 否 | number |

function getWinthInDayTime(){
    let num1 = -29;// 向前推获取30天内的时间
    let time1 = TimeUtils.getWinthInDayTime(num1);
    console.log(`\n${num1}天内的开始、结束时间:\n`, time1);
    /*
     -29天内的开始、结束时间:
     { start: '2019-03-23 00:00:00', end: '2019-04-21 24:59:59' }
     */

    let num2 = 29; // 向后推,获取30天内的时间
    let time2 = TimeUtils.getWinthInDayTime(num2);
    console.log(`\n${num2}天内的开始、结束时间:\n`, time2);
    /*
     29天内的开始、结束时间:
     { start: '2019-04-21 00:00:00', end: '2019-05-20 24:59:59' }
     */
}

格式化时间 TimeUtils.format(date:Date,format:string)

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | date | 需要格式化的时间 | 否 | Date | | format | 需要转换的格式 | 否 | string |

import {TimeUtils } from 'great-jsutils';
function testTime(){
    console.log('格式化时间(默认的格式化类型):',TimeUtils.format());//当前时间
    //格式化时间(默认的格式化类型): 2018-09-23 17:18:19
    console.log('格式化时间(默认的格式化类型):',TimeUtils.format(new Date()));
    //格式化时间(默认的格式化类型): 2018-09-23 17:18:19
    console.log('格式化时间(根据传入的参数格式):',TimeUtils.format(new Date(),'yyyy-MM-dd hh时'));
    //格式化时间(根据传入的参数格式): 2018-09-23 17时
    console.log('格式化时间(API提供的类型):',TimeUtils.format(new Date(),TimeUtils.FORMAT_YMD));
    //格式化时间(API提供的类型): 2018-09-23
}

生成一个随机时间

/* 获取一个随机时间 */
function random() {
    let date =  TimeUtils.random();
    let dateStr = TimeUtils.format(date);
    console.log(dateStr);
}
random();

根据当前时间,输出早上好、上午好……

function sayHello() {
    let hello =  TimeUtils.sayHello();
    console.log(hello);
}
sayHello();

字符串转时间

function parse(){
    let date = TimeUtils.parse('2019年11年9日 11点11分11秒');
    if(date){
        console.log('parse:',TimeUtils.format(date));
        //parse: 2019-11-09 11:11:11
    }else{
        console.log('null');
    }
}

获取某月最后一天的时间

TimeUtils.getMonthEndDateByDateStr(dateStr);

四、 字符串

import { StringUtils } from 'great-jsutils';

示例1:删除全部空格

import {StringUtils } from 'great-jsutils';
StringUtils.trim(str);

示例2:删除前后空格

import {StringUtils } from 'great-jsutils';
StringUtils.trimAround(str);

五、 json

import { JsonUtils } from 'great-jsutils';

示例1:判断是否为json

import {JsonUtils } from 'great-jsutils';
function json(){
    let str1='123';
    console.log(str1,JsonUtils.isJsonString(str1));
    let str2="{'name':'1'}";
    console.log(str2,JsonUtils.isJsonString(str2));
    let str3="{name:'1'}";
    console.log(str3,JsonUtils.isJsonString(str3));
    let str4="{'name':'xt'}";
    console.log(str4,JsonUtils.isJsonString(str4));
}

示例2:字符串转json

import {JsonUtils } from 'great-jsutils';
let str4="{'name':'xt'}";
JsonUtils.toJson(str4);

示例3:syntaxHighlight

import {JsonUtils } from 'great-jsutils';
let str4="{'name':'xt'}";
JsonUtils.syntaxHighlight(str4);
/**
 * 是否是jsonStr
 */
JsonUtils.isJsonString
/**
 * 转成jsonStr
 */
JsonUtils.toJsonStr
/**
 * 转成json对象
 */
JsonUtils.toJson
/**
 * json转前端实体类
 */
JsonUtils.toClassModel(json,{notes:false})

六、 正则RegexpUtils

import {RegexpUtils} from 'great-jsutils';

1、数字验证

/**
 * 数字验证
 * 验证数字是否是规定的范围格式
 * 例如:是否为指定的小数位数、是否大于某个数字、是否小于某个数字、是否在某个数据范围之间
 */
RegexpUtils.isNumber(str,{
    max:'最大值',
    min:'最小值',
    maxScale:'最大小数位数',
    minScale:'至少小数位数',
    scale:'小数位数'
});

场景示例

let numStr = "123.222";

// 场景一:检查输入的是否为数字
let result1 = RegexpUtils.isNumber(numStr);
console.log(numStr+'是否为数字:', result1);
//打印结果: 123.222是否为数字:true

// 场景二:检查输入的小数是否为三位
let result2 = RegexpUtils.isNumber(numStr,{scale:3});
console.log(numStr+'小数位数:==3',result2);
//打印结果: 123.222小数位数:==3 true

// 场景三:检查小数位数是否多于三位
let result3 = RegexpUtils.isNumber(numStr,{minScale:3});
console.log(numStr+'小数位数:>=3',result3);
//打印结果: 123.222小数位数:>=3 true

// 场景四:检查小数位数的个数是否多于4个、少于5个
let result4 = RegexpUtils.isNumber(numStr,{minScale:4, maxScale:5});
console.log(numStr+'小数位数:4-5',result4);
//打印结果: 123.222小数位数:4-5 false

// 场景五:检查小数位数是否多于5个
let result5 = RegexpUtils.isNumber(numStr,{maxScale:5});
console.log(numStr+'小数位数:<5',result5);
//打印结果: 123.222小数位数:<5 true

// 场景六:检查数字是否大于5
let result6 = RegexpUtils.isNumber(numStr,{min:5});
console.log(numStr+'>5:',result6);
//打印结果: 123.222>5: true

// 场景七:检查数字是否大于5,并且小于200
let result7 = RegexpUtils.isNumber(numStr,{min:5, max:200});
console.log(numStr+'>5 && '+numStr+'<200:',result7);
//打印结果:123.222>5 && 123.222<200: true

// 场景八:检查数字是否小于555
let result8 = RegexpUtils.isNumber(numStr,{max:555});
console.log(numStr+'<555:',result8);
//打印结果: 123.222<555: true

let result9 = RegexpUtils.isNumber(numStr,{});
console.log(numStr+'{}:',result9);
//打印结果: 123.222{}: true

2、字节个数验证

/**
 * 字节个数验证
 * 由于数据库中定义的字段长度为字节长度,
 * 所以中英文混合输入时,为了避免避免输入超长,
 * 需要检查输入数字的字节长度
 */
RegexpUtils.byteLength(str,{
    maxLength:'最大长度',
    minLength:'最小长度',
});

场景示例

let str = '富强prosperity/1/2/3';

let result = RegexpUtils.byteLength(str,{maxLength: 10});
console.log(`${str}字节数<10:`,result);
// 打印结果:富强prosperity/1/2/3字节数<10: false

let result2 = RegexpUtils.byteLength(str,{minLength: 10});
console.log(`${str}字节数>10:`,result2);
// 打印结果:富强prosperity/1/2/3字节数>10: true

let result3 = RegexpUtils.byteLength(str,{minLength: 10, maxLength: 12});
console.log(`${str}字节数>10&&<12:`,result3);
// 打印结果:富强prosperity/1/2/3字节数>10&&<12: false

let result4 = RegexpUtils.byteLength(str,{minLength: 10, maxLength: 20});
console.log(`${str}字节数>10&&<20:`,result4);
// 打印结果:富强prosperity/1/2/3字节数>10&&<20: true

3、匹配中文信息

let str = '富强prosperity 、民主democracy/1/2/3';
console.log(RegexpUtils.matchChinese(str));
// 打印结果:[ '富', '强', '、', '民', '主' ]

4、其他操作

let str = '[email protected]';

// 是否为邮箱
console.log('邮箱:', RegexpUtils.isEmail(str));
// 打印结果:邮箱: true

// 是否为中文
console.log('中文:', RegexpUtils.isChinese(str));
// 打印结果: 中文: false

// 是否为身份证号
console.log('身份证号:', RegexpUtils.isIdentityCard(str));
// 打印结果: 身份证号: false

// 是否为MAC地址
console.log('MAC地址:', RegexpUtils.isMac(str));
// 打印结果: MAC地址: false

// 是否为http地址
console.log('HTTP地址:', RegexpUtils.isUrl(str));
// 打印结果: HTTP地址: false

// 是否为整数
console.log('整数:', RegexpUtils.isInteger(str));
// 打印结果: 整数: false

// 纳税人识别号格式
console.log('整数:', RegexpUtils.isTaxpayerIdentificationNumber(str));
// 打印结果: 整数: false

5、去除空格

// 去除空格
RegexpUtils.trim(str);
// 去除前后空格
RegexpUtils.trimAround(str);
// 去除前空格
RegexpUtils.trimLeft(str);
// 去除后空格
RegexpUtils.trimRight(str);

6、单词转变量

let str= 'hello word';
//首字母大写
RegexpUtils.upperCaseFirst(str);
// 打印 HelloWord

// 首字母转小写
RegexpUtils.lowerCaseFirst(str);

// 小驼峰
RegexpUtils.lowerCamelCase(str);
// 打印 helloWord

7、身份证呈

// 是否为身份证号
RegexpUtils.isIdentityCard(idCard);
// 获取出生日期
RegexpUtils.getBirthdayStrByIdCard(idCard);
// 获取年龄
RegexpUtils.getAgeByIdCard(idCard);
// 获取性别
RegexpUtils.getSexByIdCard(idCard);
// 获取性别、年龄、出生日期
RegexpUtils.getPersonInfoByIdCard(idCard);

七、 对象操作

import {ObjectUtils} from 'great-jsutils';
/**
 * 清除对象中的空值
 */
function obj01(){
    let obj={a:null,b:'',c:2,d:'aa'};
    ObjectUtils.filter(obj);
    console.log('obj\t',obj); //obj   { c: 2, d: 'aa' }
}
/**
 * 清除对象中的空值。
 * 并指定其他需要强制移除的key
 */
function obj02(){
    let obj={a:null,b:'',c:2,d:'aa'};
    let removeKeys=['d'];
    ObjectUtils.filter(obj,{removeKeys});
    console.log('obj\t',obj);//obj   { c: 2}
}
/**
 * 根据指定函数确定需要移除的key
 * 下面示例将删除值长度为2 或 值为b的key
 */
function obj03(){
    let obj={a:'dd',b:'b',c:'ddd',d:'aa'};
    function fun(v){
        return v=='b' || v.length==2;
    }
    ObjectUtils.filter(obj,{fun});
    console.log('obj\t',obj);// { c: 'ddd' }
}

八、 number

1.1随机生成一组整数

默认返回一个小于10的整数,可以指定返回的最大值、最小值,以及返回的个数

import { NumberUtils } from 'great-jsutils';

示例1:随机生成一个小于10的整数

NumberUtils.randomInt();

示例2:随机生成一个小于100的整数

NumberUtils.randomInt({max:100});

示例3:随机生成四个大于等于10,小于100的整数

NumberUtils.randomInt({max:100,min:10,number:4})

1.2随机生成一组浮点数

默认返回一个小于10的浮点数,可以指定返回的最大值、最小值、小数位数,以及返回的个数

示例1:随机生成一个小于10的两位小数的浮点数

NumberUtils.randomInt();

示例2:随机生成一个小于100的两位小数的浮点数

NumberUtils.randomInt({max:100});

示例3:随机生成四个大于等于10,小于100的两位小数的浮点数

NumberUtils.randomInt({max:100,min:10,number:4})

示例4:随机生成四个大于等于10,小于100的三位小数的浮点数

NumberUtils.randomInt({max:100,min:10,number:4,scale3})

1.3 将数字转人民币大写

console.log(NumberUtils.changeToChinese(1200));

1.4 将阿拉伯数字转中文表示方式

console.log(NumberUtils.numberToChinese(12));

1.5 数字相加

console.log(NumberUtils.sum(1.1,1.3));// 2.4
console.log(1.1+1.3);//2.4000000000000004
  • 一组数字相加
console.log(NumberUtils.adds(1.001,1.3,1.4,2.33,12.3103));//18.3413

1.6 数字相减

console.log(NumberUtils.sub(1.1,1.2));

1.7 数字相乘

console.log(NumberUtils.mul(1.1,1.2));

1.8 数字相除

console.log(NumberUtils.div(1.1,1.2));

九、 DataTypeUtils

import {DataTypeUtils} from 'great-jsutils';
/**
 * 获取对象类型
 */
DataTypeUtils.getDataType(o);
/**
 * 是否为空对象
 */
DataTypeUtils.isNull(o);
/**
 * 是否为undefined
 */
DataTypeUtils.isUndefined(o);
/**
 * 是否为对象
 */
DataTypeUtils.isObject(o);
/**
 * 是否为数组
 */
DataTypeUtils.isArray(o);
/**
 * 是否为字符串
 */
DataTypeUtils.isString(o);
/**
 * 是否为数字
 */
DataTypeUtils.isNumber(o);
/**
 * 是否为布尔
 */
DataTypeUtils.isBoolean(o);
/**
 * 是否为函数
 */
DataTypeUtils.isFunction(o);
/**
 * 是否为日期
 */
DataTypeUtils.isDate(o);
/**
 * 是否为正则
 */
DataTypeUtils.isRegExp(o);
/**
 * 是否为错误对象
 */
DataTypeUtils.isError(o);
/**
 * 是否为Symbol对象
 */
DataTypeUtils.isSymbol(o);
/**
 * 是否为promise对象
 */
DataTypeUtils.isPromise(o);
/**
 * 是否为set对象
 */
DataTypeUtils.isSet(o);
/**
 * isFalse
 */
DataTypeUtils.isFalse(o);
/**
 * isTrue
 */
DataTypeUtils.isTrue(o);
/**
 * 是否为空值:符合空值的条件(空字符串、null、undefined、数组长度为0、对象中没有key)
 */
DataTypeUtils.isNullValue(o);

十、 数据生成器:DataGeneratorUtils

import {DataGeneratorUtils} from 'great-jsutils';

1. 生成姓名

1.1、 生成一个姓名

let personName = DataGeneratorUtils.personName();

1.2、 生成多个姓名

let personNames = DataGeneratorUtils.personName({size:8});

2. 生成一个手机号

*2.1、 生成一个手机号

let mobile = DataGeneratorUtils.mobile();

*2.2、 生成多个手机号

let mobiles = DataGeneratorUtils.mobile({size:8});

3. 生成字母

| 参数 | 名称 | 必传 | 参数类型 | ------ | ------ | ------ | ------ | | size | 个数 | 否 | number | | upperCase | 转大写 | 否 | boolean | | length | 长度 | 否 | number | | prefix | 前缀 | 否 | string | | suffix | 后缀 | 否 | string |

*3.1、 生成一个字母,默认为一个且为大写

let letter = DataGeneratorUtils.letter();
console.log(letter);//B

*3.2、 生成多个字母,通过length指定长度为2

let letters = DataGeneratorUtils.letter({length:2});
console.log(letters);//BD

*3.3、 生成多组字母

let letters = DataGeneratorUtils.letter({size:2});
console.log(letters);//['D', 'W']

*3.4、 生成多组字母,且长度为4

let letters = DataGeneratorUtils.letter({size:2, length:4});
console.log(letters);//['DACK', 'BKJA']

*3.5、 生成小写字母

let letters = DataGeneratorUtils.letter({length:4, upperCase:false});
console.log(letters);//aabc

4. 从数组中随机获取一个元素

let personName = DataGeneratorUtils.getElementByArray(array);

5. 生成邮箱

let email = DataGeneratorUtils.email({size:2});

6. 其他

5.1、随机生成整数、小数

可以指定最大数、最小数、生成的个数等

import {NumberUtils} from 'great-jsutils';

5.2、随机生成时间

可以格式化时间、获取一个月内、上下个月、上下个周内等

import {TimeUtils} from 'great-jsutils';

十一、 CommonUtils

1.1、 CommonUtils.isIos();

是否为ios系统

1.2、CommonUtils.isPC();

是否为pc端

1.3、 CommonUtils.browserType();

浏览器类型

1.4、CommonUtils.getRandomColor();

随机生成一个16进制颜色值

1.5、CommonUtils.uuid();

import {CommonUtils} from 'great-jsutils';
CommonUtils.uuid();

生成一个uuid

十二、ValueUtils

import {ValueUtils} from 'great-jsutils';

1.1、空值校验(isNullValue)

let a = [],a1={},a2=null,a3,a4=' ';
console.log('ValueUtils.isNullValue(',a,'):', ValueUtils.isNullValue(a));// 打印:true
console.log('ValueUtils.isNullValue(',a1,'):', ValueUtils.isNullValue(a1));// 打印:true
console.log('ValueUtils.isNullValue(',a2,'):', ValueUtils.isNullValue(a2));// 打印:true
console.log('ValueUtils.isNullValue(',a3,'):', ValueUtils.isNullValue(a3));// 打印:true
console.log('ValueUtils.isNullValue(',a4,'):', ValueUtils.isNullValue(a4));// 打印:false
console.log('ValueUtils.isNullValue(',a4,',true):', ValueUtils.isNullValue(a4, true));// 打印:true

1.2、是否为数字(isNumberValue)

let b="123", b1="a23", b2=23;
console.log('ValueUtils.isNumberValue(',b,'):', ValueUtils.isNumberValue(b)); // 打印:true
console.log('ValueUtils.isNumberValue(',b1,'):', ValueUtils.isNumberValue(b1));// 打印:false
console.log('ValueUtils.isNumberValue(',b2,'):', ValueUtils.isNumberValue(b2));// 打印:true

1.3、是否为空数组(isEmptyArray)

let c = [], c1, c2={}, c3=[1], c4=[{name:'张三'}];
console.log('ValueUtils.isEmptyArray(',c,'):', ValueUtils.isEmptyArray(c));// 打印:true
console.log('ValueUtils.isEmptyArray(',c1,'):', ValueUtils.isEmptyArray(c1));// 打印:false
console.log('ValueUtils.isEmptyArray(',c2,'):', ValueUtils.isEmptyArray(c2));// 打印:false
console.log('ValueUtils.isEmptyArray(',c3,'):', ValueUtils.isEmptyArray(c3));// 打印:false
console.log('ValueUtils.isEmptyArray(',c4,'):', ValueUtils.isEmptyArray(c4));// 打印:false

1.4、是否为非空数组(isNotEmptyArray)

十三 BrowserUtils

// 获取浏览器版本信息
BrowserUtils.getBrowser();

LoadjsUtils加载js文件

LoadjsUtils.dynamicLoads([
    `./assets/ueditor/ueditor.config.js`,
    `./assets/ueditor/ueditor.all.js`,
    `./assets/ueditor/lang/zh-cn/zh-cn.js`
]).then(() => {
});

HttpUtils

HttpUtils.getUrlParam(name)
HttpUtils.getUrlParams(url)
HttpUtils.delParamsUrl(url, name)

SessionStroage

bug修复

2019.0817

| key | value | | ------ | ------ | | 版本 | 1.2.0 | | 升级说明 | 数组移除方法,子节点移除时优化 |

2019.0829

| key | value | | ------ | ------ | | 版本 | 1.2.1 | | 升级说明 | 根据json转model类 |

JsonUtils.toClassModel(jsonStr);

2019.0905

| key | value | | ------ | ------ | | 版本 | 1.2.2 | | 升级说明 | 增加BankCardUtils、AjaxUtils |

JsonUtils.toClassModel(jsonStr);

2019.0929

| key | value | | ------ | ------ | | 版本 | 1.2.4 | | 升级说明 | 小数正则 |

RegexpUtils.isDecimal(num);

2019.1001

| key | value | | ------ | ------ | | 版本 | 1.2.5 | | 升级说明 | 代码格式化 |

HighlightUtils.syntaxHighlight(num);
HighlightUtils.formatFunction(fn,fnName);
HighlightUtils.formatText(num);
HighlightUtils.formatHtml(num);
HighlightUtils.escapeHtml(num);

2019.1004

//深拷贝
ObjectUtils.deepClone

2019.1008

//深拷贝
ObjectUtils.clone
//数据类型
DataTypeUtils.is……

2019.1013

| key | value | | ------ | ------ | | 版本 | 1.2.6 | | 升级说明 | json转实体 |

toClassModel(json,{notes:false})

2019.1026

| key | value | | ------ | ------ | | 版本 | 1.3.1 | | 升级说明 | 生成数字优化 |

toClassModel(json,{notes:false})

2020.0801

| key | value | | ------ | ------ | | 版本 | 1.3.6 | | 升级说明 | 空值判断 |

感谢你的支持,我将持续优化我的服务,希望为你提供更大的帮助!
感谢你的支持
感谢你的支持,我将持续优化我的免费的服务,希望为你提供更大的帮助!
<img src="data:image/png;base64,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%0AgiAIgiDsg3zOCYIgCIIgCCJFIHFOEARBE