1.0.8 • Published 10 months ago

@geyj/web-utils v1.0.8

Weekly downloads
-
License
ISC
Repository
-
Last release
10 months ago

Web工具库

使用

// 安装
npm install @geyj/web-utils
// 引入
import {
    getMonthDays, getWeekDayOfMonthFirstDay, getCalendar, getComplexCalendar,
    gzip, ungzip, compressImage,
    sleep, debounce, throttle,
    getFileType, networkFileToBlob, blobToBase64, downloadBlob, downloadNetworkFile, previewOffice,
    formatThousandth, formatFileSize, formatDuration,
    print,
    getUniqueId,
    listToTree, treeToList, groupByKey,
    isPhone, isEmail, isURL, isNumericString, isIDNumber, isDate,
    observerTargetElement
} from '@geyj/web-utils'

说明

1.日历

test('getMonthDays:2023年12月有31天', () => {
    expect(getMonthDays(2023, 12)).toBe(31);
});

test('getWeekDayOfMonthFirstDay:2023年12月的第一天是星期5', () => {
    expect(getWeekDayOfMonthFirstDay(2023, 12)).toBe(5);
});
const calendar = JSON.stringify([
    [27, 28, 29, 30, 1, 2, 3],
    [4, 5, 6, 7, 8, 9, 10],
    [11, 12, 13, 14, 15, 16, 17],
    [18, 19, 20, 21, 22, 23, 24],
    [25, 26, 27, 28, 29, 30, 31],
    [1, 2, 3, 4, 5, 6, 7]
])
test(`getCalendar:2023年12月日历简易数据是${calendar}`, () => {
    expect(JSON.stringify(getCalendar(2023, 12))).toBe(calendar)
});

2.执行控制

//防抖
debounce(searchHandler, 1000)
//节流
throttle(clickHandler, 3000)
test('sleep:时间间隔应该非常接近于1000ms', async () => {
    const time = 1000;
    const before = new Date().getTime();

    await sleep(time);

    const after = new Date().getTime();
    const difference = after - before;

    expect(difference).toBeGreaterThanOrEqual(time);
});

3.格式化

test('formatThousandth:千分位格式化', () => {
    expect(formatThousandth(12345678.9)).toBe('12,345,678.9');
});

test('formatFileSize:文件尺寸格式化', () => {
    expect(formatFileSize(1023)).toBe('1023B');
    expect(formatFileSize(1024)).toBe('1.00KB');
    expect(formatFileSize(1024 ** 2)).toBe('1.00MB');
    expect(formatFileSize(1024 ** 3)).toBe('1.00GB');
    expect(formatFileSize(1024 ** 4)).toBe('1.00TB');
});

test('formatDuration:时长格式化', () => {
    expect(formatDuration(59)).toBe('59秒');
    expect(formatDuration(60)).toBe('1.00分');
    expect(formatDuration(60 ** 2 - 60)).toBe('59.00分');
    expect(formatDuration(60 ** 2)).toBe('1.00时');
    expect(formatDuration(60 ** 2 * (24 - 1))).toBe('23.00时');
    expect(formatDuration(60 ** 2 * 24)).toBe('1.00天');
});

4.id

test('getUniqueId:获取8位唯一id值', () => {
    expect(getUniqueId().length).toBe(8);
});
test('getUniqueId:1000个id都不一致', () => {
    const idCount = 1000
    const ids = new Set(Array(idCount).fill(null).map(() => getUniqueId()));
    expect(ids.size).toBe(idCount);
});

5.数据结构

describe('listToTree:', () => {
    test('converts a flat list to a tree structure', () => {
        const list = [
            { id: 1, parentId: null, name: 'Root' },
            { id: 2, parentId: 1, name: 'Child 1' },
            { id: 3, parentId: 1, name: 'Child 2' },
            { id: 4, parentId: 2, name: 'Grandchild 1' }
        ];

        const tree = [
            {
                id: 1, parentId: null, name: 'Root', children: [
                    {
                        id: 2, parentId: 1, name: 'Child 1', children: [
                            { id: 4, parentId: 2, name: 'Grandchild 1', children: [] }
                        ]
                    },
                    { id: 3, parentId: 1, name: 'Child 2', children: [] }
                ]
            }
        ];

        expect(listToTree(list, 'parentId', 'id')).toEqual(tree);
    });

    test('handles empty list', () => {
        expect(listToTree([], 'parentId', 'id')).toEqual([]);
    });

    test('handles list with no root elements', () => {
        const list = [
            { id: 2, parentId: 1, name: 'Child 1' },
            { id: 3, parentId: 2, name: 'Child 2' }
        ];

        expect(listToTree(list, 'parentId', 'id')).toEqual([]);
    });
});

describe('treeToList:', () => {
    const treeData = [
        {
            id: 1, children: [
                {
                    id: 2, children: [
                        { id: 5, children: [] },
                        { id: 6, children: [] }
                    ]
                },
                {
                    id: 3, children: [
                        { id: 7, children: [] }
                    ]
                },
                { id: 4, children: [] }
            ]
        }
    ];

    it('converts a tree to a flat list using DFS', () => {
        const expectedListDFS = [
            { id: 1, children: [{ id: 2, children: [{ id: 5, children: [] }, { id: 6, children: [] }] }, { id: 3, children: [{ id: 7, children: [] }] }, { id: 4, children: [] }] },
            { id: 2, children: [{ id: 5, children: [] }, { id: 6, children: [] }] },
            { id: 5, children: [] },
            { id: 6, children: [] },
            { id: 3, children: [{ id: 7, children: [] }] },
            { id: 7, children: [] },
            { id: 4, children: [] }
        ];
        expect(treeToList(treeData, 'dfs')).toEqual(expectedListDFS);
    });

    it('converts a tree to a flat list using BFS', () => {
        const expectedListBFS = [
            { id: 1, children: [{ id: 2, children: [{ id: 5, children: [] }, { id: 6, children: [] }] }, { id: 3, children: [{ id: 7, children: [] }] }, { id: 4, children: [] }] },
            { id: 2, children: [{ id: 5, children: [] }, { id: 6, children: [] }] },
            { id: 3, children: [{ id: 7, children: [] }] },
            { id: 4, children: [] },
            { id: 5, children: [] },
            { id: 6, children: [] },
            { id: 7, children: [] }
        ];
        expect(treeToList(treeData, 'bfs')).toEqual(expectedListBFS);
    });

    it('handles empty tree', () => {
        expect(treeToList([], 'dfs')).toEqual([]);
        expect(treeToList([], 'bfs')).toEqual([]);
    });

    it('handles single node tree', () => {
        const singleNodeTree = [{ id: 1, children: [] }];
        const expectedList = [{ id: 1, children: [] }];
        expect(treeToList(singleNodeTree, 'dfs')).toEqual(expectedList);
        expect(treeToList(singleNodeTree, 'bfs')).toEqual(expectedList);
    });
});

describe('groupByKey:', () => {
    const listData = [
        { category: 'fruit', name: 'apple' },
        { category: 'vegetable', name: 'carrot' },
        { category: 'fruit', name: 'banana' },
        { category: 'vegetable', name: 'spinach' }
    ];

    it('groups items by a specified key', () => {
        const expectedResult = [
            {
                key: 'fruit',
                list: [
                    { category: 'fruit', name: 'apple' },
                    { category: 'fruit', name: 'banana' }
                ]
            },
            {
                key: 'vegetable',
                list: [
                    { category: 'vegetable', name: 'carrot' },
                    { category: 'vegetable', name: 'spinach' }
                ]
            }
        ];
        expect(groupByKey(listData, 'category')).toEqual(expectedResult);
    });

    it('handles empty list', () => {
        expect(groupByKey([], 'category')).toEqual([]);
    });
    it('handles list with items missing the group key', () => {
        const mixedListData = [
            { category: 'fruit', name: 'apple' },
            { name: 'carrot' },
            { category: 'vegetable', name: 'spinach' }
        ];
        const expectedResult = [
            {
                key: 'fruit',
                list: [{ category: 'fruit', name: 'apple' }]
            },
            {
                key: undefined,
                list: [{ name: 'carrot' }]
            },
            {
                key: 'vegetable',
                list: [{ category: 'vegetable', name: 'spinach' }]
            }
        ];
        expect(groupByKey(mixedListData, 'category')).toEqual(expectedResult);
    });
});

6.验证

test('isPhone:验证是否为手机号', () => {
    expect(isPhone('17888888888')).toBe(true);

    expect(isPhone('1788888888')).toBe(false);
    expect(isPhone('07888888888')).toBe(false);
    expect(isPhone('27888888888')).toBe(false);
    expect(isPhone('37888888888')).toBe(false);
    expect(isPhone('0574-88832337')).toBe(false);
});
test('isEmail:验证是否为邮箱', () => {
    expect(isEmail('example@example.com')).toBe(true);

    expect(isEmail('example@')).toBe(false);
    expect(isEmail('@example.com')).toBe(false);
});
test('isURL:验证是URL', () => {
    expect(isURL('http://blog.okoknb.cn')).toBe(true);
    expect(isURL('https://www.blog.okoknb.cn')).toBe(true);
    expect(isURL('https://blog.okoknb.cn/page?id=1')).toBe(true);
    expect(isURL('blog.okoknb.cn')).toBe(true);
    expect(isURL('www.blog.okoknb.cn')).toBe(true);

    expect(isURL('justastring')).toBe(false);
    expect(isURL('http:/example.com')).toBe(false);
    expect(isURL('ftp://example.com')).toBe(false);
});
test('isNumericString:验证是数字字符串', () => {
    expect(isNumericString('1')).toBe(true);
    expect(isNumericString('1.1314')).toBe(true);
    expect(isNumericString('-1')).toBe(true);
    expect(isNumericString('-0')).toBe(true);

    expect(isNumericString('a')).toBe(false);
    expect(isNumericString('-')).toBe(false);
    expect(isNumericString('-a')).toBe(false);
});
test('isIDNumber:验证是否为中国大陆的身份证号码', () => {
    expect(isIDNumber('11010519491231002X')).toBe(true);
    expect(isIDNumber('330283199509092311')).toBe(true);

    expect(isIDNumber('11111111111111111X')).toBe(false);
    expect(isIDNumber('123745532416443411')).toBe(false);
    expect(isIDNumber('111111111111111111')).toBe(false);
    expect(isIDNumber('akiisajdajdlkadjss')).toBe(false);
});
test('isDate:验证是否为YYYY-MM-DD的日期格式', () => {
    expect(isDate('1996-07-04')).toBe(true);
    expect(isDate('0000-00-00')).toBe(true);

    expect(isDate('aaaa-00-00')).toBe(false);
    expect(isDate('1996/07/04')).toBe(false);
    expect(isDate(new Date().toDateString())).toBe(false);
});

6.压缩

describe('gzip | ungzip', () => {
    it('原始字符串通过gzip压缩后的结果,再通过ungzip解压后的结果应该与原始字符串相同', () => {
        console.log(mock().objectArray)
        const str = JSON.stringify(mock().objectArray)
        const gzipStr = gzip(str)
        const ungzipStr = ungzip(gzipStr)
        expect(ungzipStr).toBe(str)
    });
});

describe('compressImage', () => {
    it('压缩后图像文件大小 < 原始图像文件大小', async () => {
        const blob = image
        const compressBlob = await compressImage(blob, { quality:0.2 })
        expect(compressBlob.size).toBeLessThan(blob.size)
    });
});

6.文件

//根据文件名称或Url获取文件类型
console.log(getFileType('xxx.png')) //png
//网络文件转Blob
console.log(await networkFileToBlob('https://xxx.png')) //Blob
//Blob转Base64
console.log(await blobToBase64(Blob)) //base64
//下载Blob
await downloadBlob({ blob,fileName })
//网络文件下载
await downloadNetworkFile({ fileUrl, fileName })

7.打印

print({printDom})

8.观察

const observerCallback = () => {
    console.log('观察body变化后要执行的后续流程')
}
observerTargetElement('body', observerCallback)

9.http

import { useHttpClient, HttpClient } from '@geyj/web-utils'
import router from '@/router'
const httpPhp: HttpClient = useHttpClient({ baseURL: import.meta.env.VITE_PHP_API_BASE_URL })

httpPhp.onResponseError((error) => {
    if (error.response?.status === 401) {
        localStorage.setItem('token', '')
        if (location.hash.includes('/login')) return
        router.replace({ path: '/login', query: { from: '401' } })
    }
})

const httpFront: HttpClient = useHttpClient({ baseURL: import.meta.env.VITE_AI_API_BASE_URL })

export { httpPhp, httpFront }
1.0.8

10 months ago

1.0.7

10 months ago

1.0.6

10 months ago

1.0.5

11 months ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago