@geyj/web-utils
v1.0.8
Published
Web工具库
Downloads
272
Readme
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('[email protected]')).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 }