npm.io
1.1.0 • Published yesterday

lg.tool

Licence
Version
1.1.0
Deps
0
Size
638 kB
Vulns
0
Weekly
0

六哥项目推荐

lg.tool 使用说明

lg.tool 是纯 JS 通用工具库,按功能拆分为多个子模块,支持按需引入。

// 全量引入
import { toObject, createCache, formatDate, debounce, getId, eventBus } from "lg.tool";

// 按需引入子模块
import { toObject, toTreeData } from "lg.tool/data";
import { createCache } from "lg.tool/cache";
import { formatDate, formatSize } from "lg.tool/format";
import { debounce } from "lg.tool/utils";
import { getId, randomInt } from "lg.tool/random";
import { eventBus } from "lg.tool/eventBus";

数据转换(data)
import {
    toObject, toSet, toMap, grouping,
    toBoolean, toNumber, toPromise,
    toBooleanArray, toNumberArray, toStringArray, toPromiseArray,
    toOptions, toAge, splice, distinct, sum,
    forEach, map, filter, find, sort, toTreeData, treeFlat,
    findLink, findLinkR, queryTree
} from "lg.tool/data";

const list = [];
for (let i = 0; i < 11; i++) {
    list.push({ value: i, label: String(i + 1) });
}

// toObject:数组转对象
console.log(toObject(list, 'value'));
console.log(toObject(list, x => x.value));
console.log(toObject(list, 'value', 'label'));
console.log(toObject(list, x => x.value, x => x.label));

// toSet:数组转 Set
console.log(toSet(list));
console.log(toSet(list, 'value'));
console.log(toSet(list, x => x.value));

// toMap:数组转 Map
console.log(toMap(list, 'value'));
console.log(toMap(list, x => x.value));
console.log(toMap(list, 'value', 'label'));
console.log(toMap(list, x => x.value, x => x.label));

// grouping:分组
console.log(grouping(list, 'value'));
console.log(grouping(list, x => x.value % 2));
console.log(grouping(list, 'value', 'label'));
console.log(grouping(list, x => x.value % 2, x => x.label));

// toOptions:转选项数组(用于下拉选择)
console.log(toOptions('a,b,c'));
console.log(toOptions(['a', 'b', 'c']));
console.log(toOptions('a:1,b:2,c:3'));
console.log(toOptions({ a: 1, b: 2, c: 3 }));
console.log(toOptions(list));

// toBoolean:转布尔值
console.log(toBoolean(true));
console.log(toBoolean(1));
console.log(toBoolean(''));
console.log(toBoolean('false'));

// toBooleanArray:转布尔值数组
console.log(toBooleanArray([false, true]));
console.log(toBooleanArray(['false', 'true']));
console.log(toBooleanArray('false,true'));

// toNumber:转数值
console.log(toNumber('1.25'));
console.log(toNumber(1.25));

// toNumberArray:转数值数组
console.log(toNumberArray([1, 2.25]));
console.log(toNumberArray(['1', '2.25']));
console.log(toNumberArray('1,2.25'));

// toPromise:转 Promise
console.log(toPromise(Promise.resolve(1.25)));
console.log(toPromise(1.25));

// toPromiseArray:转 Promise 数组
console.log(toPromiseArray(['https://gitee.com/lgx1992/lg-soar', Promise.resolve('https://gitee.com/lgx1992/lg-soar')]));

// toStringArray:转字符串数组
console.log(toStringArray([1, 2.25]));
console.log(toStringArray(['1', '2.25']));
console.log(toStringArray('1,2.25'));

// toAge:日期转年龄
console.log(toAge(new Date(1992, 3, 5)));
console.log(toAge(new Date(1992, 3, 5).getTime()));
console.log(toAge(new Date(1992, 3, 5), new Date(2025, 3, 10)));

// splice:数组删除(会修改原数组)
const ls1 = [1, 2, 3, 2, 2];
splice(ls1, 2);
console.log(ls1); // [1, 3]

const ls2 = [1, 2, 3, 2, 2];
splice(ls2, (x) => x === 2, false);
console.log(ls2); // [1, 3, 2, 2]

// distinct:数组去重
console.log(distinct([{ id: 1 }, { id: 1 }, { id: 2 }], 'id'));

// sum:求和
console.log(sum([1, 2, 3]));
console.log(sum([{ a: 1 }, { a: 2 }], 'a'));
console.log(sum([{ a: 1, b: 2 }, { a: 2, b: 3 }], ['a', 'b']));

// 树形数据处理
const tree = [
    { id: '1', name: 'A', children: [{ id: '1-1', name: 'A-1' }] },
    { id: '2', name: 'B' }
];
forEach(tree, (x, p, i) => console.log(x.name));
console.log(map(tree, (x, p, i) => ({ ...x, title: x.name })));
console.log(filter(tree, x => x.id.startsWith('1')));
console.log(find(tree, x => x.id === '1-1'));
sort(tree, 'name');

// 扁平数据与树形数据互转
const flat = [{ id: '1', pId: '0' }, { id: '1-1', pId: '1' }];
console.log(toTreeData(flat));
console.log(treeFlat(tree));
console.log(findLink(tree, x => x.id === '1-1'));
console.log(findLinkR(tree, x => x.id === '1-1'));
console.log(queryTree(tree, x => x.id === '1-1'));

缓存(cache)
import { createCache, createStorage } from "lg.tool/cache";

// 内存缓存(刷新丢失)
const cache = createCache({ name: 'user', expires: 60 });
cache.put('id', 1);
console.log(cache.get('id'));      // 1
cache.remove('id');
console.log(cache.get('id', -1));  // -1

// 异步加载(带锁,防止并发重复请求)
const userCache = createCache({
    name: 'user',
    loader: async (key) => fetch(`/api/user/${key}`).then(r => r.json())
});
const user = await userCache.load('1001');

// 持久化存储(基于 localStorage / sessionStorage)
const storage = createStorage({
    name: 'app',
    storage: localStorage,
    expires: 3600
});
storage.setItem('token', 'xxx');
console.log(storage.getItem('token'));

数据字典(dict)
import { dictToMap, dictToLabelMap, dictToMapper, dictToLabel, dictToLabelList } from "lg.tool/dict";

const dict = [
    { value: 1, label: '启用' },
    { value: 0, label: '禁用' }
];

console.log(dictToMap(dict));       // { 1: {...}, 0: {...} }
console.log(dictToLabelMap(dict));  // { 1: '启用', 0: '禁用' }
console.log(dictToMapper(dict));    // { '启用': {...}, '禁用': {...} }
console.log(dictToLabel(dict, 1));  // 启用
console.log(dictToLabelList(dict, '1,0')); // ['启用', '禁用']

文件(file)
import {
    getFileTypeByExt, getFileExtension,
    isImgByName, isImgByType, isImgByFile,
    isFileType, addFileTypeExt
} from "lg.tool/file";

console.log(getFileExtension('test.PNG'));  // png
console.log(getFileTypeByExt('a.jpg'));     // img
console.log(isImgByName('a.jpg'));          // true
console.log(isImgByType('image/png'));      // true
console.log(isFileType('excel', 'a.xlsx')); // true

addFileTypeExt('img', 'heic');
console.log(isImgByName('a.heic'));         // true

格式(format)
import {
    createDateFormatter, createNumberFormatter,
    parseDate, formatDate,
    parseSize, formatSize, formatNumber, formatBigint, formatDuration,
    format
} from "lg.tool/format";

// 日期格式化
console.log(formatDate(new Date(), 'YYYY-MM-DD hh:mm:ss'));
console.log(formatDate('2025-7-19 14:30', 'YYYY年MM月DD日'));

// 自定义日期格式化器
const fmt = createDateFormatter('YYYY-MM-DD');
console.log(fmt(new Date()));

// 数值格式化
console.log(formatNumber(1234567.89, 2));
console.log(formatNumber(1234567.89, { style: 'currency', currency: 'CNY' }));

// 文件大小
console.log(parseSize('1.5MB'));   // 1572864
console.log(formatSize(1572864));  // 1.50MB

// 大数值 / 时长
console.log(formatBigint(123456)); // 12.3456万
console.log(formatDuration(3661)); // 1小时1分钟1秒

// 智能格式化
console.log(format(new Date(), 'date'));
console.log(format(new Date(), 'datetime'));
console.log(format(1234567, 'number'));
console.log(format(123456789, 'bigint'));
console.log(format(1572864, 'file'));

加载器(loader)
import {
    createLockLoader, createBatchLoader,
    createRetryLoader, createDebouncedLoader, createThrottledLoader
} from "lg.tool/loader";

// 防重复加载锁
const lockLoader = createLockLoader();
const user = await lockLoader('userInfo', () => fetchUser());

// 时间窗口合并批量请求
const batchLoader = createBatchLoader({
    loader: (params) => fetchBatch(params),
    responseHandler: (res, param) => res.find(x => x.id === param.id),
    delay: 300
});
const item = await batchLoader({ id: 1 });

// 重试加载器
const retryLoader = createRetryLoader(() => fetchData(), { maxRetries: 3, delay: 1000 });
await retryLoader();

// 防抖 / 节流加载器
const debounced = createDebouncedLoader((params) => search(params), 300);
const throttled = createThrottledLoader((params) => search(params), 1000);

校验器(validator)
import { validator, addRule, getRules } from "lg.tool/validator";

// 基础校验
await validator({
    name: '六哥',
    age: 18,
    phone: '13800138000'
}, {
    name: [{ required: true, msg: '请输入姓名' }, { maxLength: 10, msg: '姓名过长' }],
    age: [{ required: true }, { number: true }, { range: [0, 150] }],
    phone: [{ required: true }, { phone: true }],
    email: [{ email: true, msg: '邮箱格式错误' }]
}).then(() => {
    console.log('校验通过');
}).catch(err => {
    console.log(err.errors);  // 错误信息数组
    console.log(err.detail);  // 按字段归类的错误详情
});

// 自定义规则
addRule('isSix', (value, params) => value === '六哥');

通用函数(utils)
import { debounce } from "lg.tool/utils";

// 函数防抖
const onInput = debounce((value) => {
    console.log('输入内容', value);
}, 500);

onInput('a');
onInput('ab'); // 500ms 后只输出一次 "输入内容 ab"

随机数(random)
import { getId, randomInt, randomString, randomItem, randomColor } from "lg.tool/random";

// 生成随机 ID(基于时间戳 + 随机数)
console.log(getId());           // 例如:lxxabc123
console.log(getId(1000));       // 基于指定索引生成

// 指定范围随机整数
console.log(randomInt(1, 100)); // 1 ~ 100

// 指定长度随机字符串
console.log(randomString(8));   // 默认大小写字母+数字
console.log(randomString(6, '0123456789')); // 纯数字

// 从数组中随机取一项
console.log(randomItem(['a', 'b', 'c']));

// 随机十六进制颜色
console.log(randomColor());     // 例如:#3a7bc5

事件总线(eventBus)
import { eventBus } from "lg.tool/eventBus";

const handler = (data) => {
    console.log('收到事件', data);
};

// 订阅
eventBus.on('my-event', handler);

// 发布
eventBus.emit('my-event', { message: 'hello' });

// 取消订阅
eventBus.off('my-event', handler);

// 查看监听器数量(调试用)
console.log(eventBus.listenerCount('my-event'));

// 清空所有监听
eventBus.clearAll();