ly-utils-lib
v2.11.1
Published
一个功能强大的 JavaScript/TypeScript 工具函数库,提供日期、数组、字符串、对象、Excel、PDF、地图、存储、加密解密、颜色转换、图片处理等常用功能的封装
Downloads
914
Maintainers
Readme
Utils Toolkit
一个功能强大的 JavaScript/TypeScript 工具函数库,提供日期、数组、字符串、对象、Excel、PDF、存储等常用功能的封装。
特性:
- ✅ 完全的 TypeScript 支持
- ✅ 模块化设计,按需导入
- ✅ 零依赖或轻量级依赖
- ✅ 丰富的 API 文档
- ✅ 完善的类型定义
- ✅ 100% 测试覆盖
核心依赖:
- 📅 dayjs - 日期处理
- 🛠️ es-toolkit - 现代 JavaScript 工具库
- 📊 xlsx - Excel 处理
- 📷 html2canvas - 截图功能
- 📄 jspdf - PDF 生成
- 🍪 js-cookie - Cookie 处理
- 🔐 crypto-js - 加密解密
- 🗺️ ol - 地图功能
安装
npm install ly-utils-lib
# 或
yarn add ly-utils-lib
# 或
pnpm add ly-utils-lib快速开始
完整导入
import * as utils from 'ly-utils-lib'
// 使用日期功能
const now = utils.date.now()
const formatted = utils.date.format(now, 'YYYY-MM-DD HH:mm:ss')
// 使用数组功能
const arr = [1, 2, 2, 3]
const unique = utils.array.unique(arr)
// 使用字符串功能
const camel = utils.string.camelCase('hello-world')按需导入(推荐)
// 只导入日期模块
import { format, add, diffDays } from 'ly-utils-lib/date'
// 只导入数组模块
import { unique, chunk, groupBy } from 'ly-utils-lib/array'
// 只导入字符串模块
import { camelCase, uuid, random } from 'ly-utils-lib/string'
// 只导入对象模块
import { pick, omit, merge } from 'ly-utils-lib/object'
// 只导入 Excel 模块
import { exportExcel, importExcel } from 'ly-utils-lib/excel'
// 只导入 PDF 模块
import { captureToPDF, createPDF } from 'ly-utils-lib/pdf'
// 只导入 WebSocket 模块
import { createWebSocket, quickConnect } from 'ly-utils-lib/websocket'
// 只导入 Event 模块
import { createEventBus, waitForEvent } from 'ly-utils-lib/event'模块文档
📅 Date Module - 日期处理
基于 dayjs 封装,提供丰富的日期处理功能。
import {
now,
format,
add,
subtract,
diffDays,
isToday,
isBetween,
getMonthRange,
getWeekRange,
} from 'ly-utils-lib/date'
// 获取当前时间
const current = now()
// 格式化日期
const formatted = format(new Date(), 'YYYY-MM-DD HH:mm:ss')
// 日期计算
const nextWeek = add(new Date(), 7, 'day')
const lastMonth = subtract(new Date(), 1, 'month')
// 日期比较
const diff = diffDays(new Date(), '2024-01-01')
const today = isToday(new Date())
// 获取日期范围
const [monthStart, monthEnd] = getMonthRange()
const [weekStart, weekEnd] = getWeekRange()API 列表:
| 函数 | 说明 | 示例 |
| ------------------------------ | ---------------- | ---------------------------------- |
| now() | 获取当前时间 | now() |
| format(date, formatStr) | 格式化日期 | format(new Date(), 'YYYY-MM-DD') |
| getDate(date) | 获取日期 | getDate() |
| getTime(date) | 获取时间 | getTime() |
| add(date, amount, unit) | 日期加 | add(new Date(), 7, 'day') |
| subtract(date, amount, unit) | 日期减 | subtract(new Date(), 1, 'month') |
| diffDays(date1, date2) | 日期天数差 | diffDays(date1, date2) |
| isToday(date) | 判断是否今天 | isToday(new Date()) |
| isBetween(date, start, end) | 判断是否在范围内 | isBetween(date, start, end) |
| getMonthRange(date) | 获取月份范围 | getMonthRange() |
| getWeekRange(date, startDay) | 获取周范围 | getWeekRange() |
| getQuarterRange(date) | 获取季度范围 | getQuarterRange() |
| getYearRange(date) | 获取年份范围 | getYearRange() |
📊 Array Module - 数组处理
基于 es-toolkit 封装,提供高效的数组处理功能。
import {
unique,
shuffle,
chunk,
groupBy,
arrayToTree,
treeToArray,
paginate,
reduceSum,
average,
maxValue,
minValue,
forEachAsync,
forEachRight,
forEach,
} from 'ly-utils-lib/array'
// 数组去重
const arr = [1, 2, 2, 3, 4, 4]
const uniqueArr = unique(arr) // [1, 2, 3, 4]
// 数组乱序
const shuffled = shuffle([1, 2, 3, 4, 5])
// 数组分块
const chunks = chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]]
// 数组分组
const grouped = groupBy(
[
{ id: 1, type: 'A' },
{ id: 2, type: 'B' },
{ id: 3, type: 'A' },
],
item => item.type
)
// 数组转树
const tree = arrayToTree([
{ id: 1, parentId: null },
{ id: 2, parentId: 1 },
{ id: 3, parentId: 1 },
])
// 树转数组
const flat = treeToArray(tree)
// 分页
const pageData = paginate([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2, 3) // [4, 5, 6]
// 统计
const nums = [1, 2, 3, 4, 5]
const sum = reduceSum(nums) // 15
const avg = average(nums) // 3
const max = maxValue(nums) // 5
const min = minValue(nums) // 1
// 遍历数组(返回原数组)
const result = forEach([1, 2, 3], (value) => {
console.log(value) // 输出 1, 2, 3
})
console.log(result) // [1, 2, 3] (返回原数组)
// 遍历对象
const obj = { a: 1, b: 2, c: 3 }
forEach(obj, (value, key) => {
console.log(key, value) // 输出 a 1, b 2, c 3
})
// 遍历字符串
forEach('hello', (char) => {
console.log(char) // 输出 h, e, l, l, o
})
// 异步遍历
const users = [{ id: 1 }, { id: 2 }, { id: 3 }]
await forEachAsync(users, async (user) => {
await updateUser(user.id)
})
// 异步遍历(带并发限制)
await forEachAsync(
items,
async (item) => await processItem(item),
{ concurrency: 2 }
)
// 从右到左遍历
const arrReverse: number[] = []
forEachRight([1, 2, 3], (value) => {
arrReverse.push(value)
})
console.log(arrReverse) // [3, 2, 1]API 列表:
| 函数 | 说明 | 示例 |
| -------------------------------- | ---------------------- | --------------------------------- |
| unique(arr, key?) | 数组去重 | unique([1, 2, 2, 3]) |
| shuffle(arr) | 数组乱序 | shuffle([1, 2, 3]) |
| chunk(arr, size) | 数组分块 | chunk([1, 2, 3, 4], 2) |
| groupBy(arr, fn) | 数组分组 | groupBy(arr, x => x.type) |
| arrayToTree(arr, options) | 数组转树 | arrayToTree(data) |
| treeToArray(tree, childrenKey) | 树转数组 | treeToArray(tree) |
| paginate(arr, page, pageSize) | 分页 | paginate(arr, 1, 10) |
| reduceSum(arr, mapper) | 求和 | reduceSum([1, 2, 3]) |
| average(arr, mapper) | 平均值 | average([1, 2, 3]) |
| maxValue(arr, mapper) | 最大值 | maxValue([1, 2, 3]) |
| minValue(arr, mapper) | 最小值 | minValue([1, 2, 3]) |
| move(arr, from, to) | 移动元素 | move([1, 2, 3], 0, 2) |
| split(arr, size) | 分割数组 | split([1, 2, 3, 4], 2) |
| forEach(collection, fn) | 遍历(兼容 lodash) | forEach([1, 2], fn) |
| forEachAsync(arr, fn, options?) | 异步遍历数组(支持并发控制) | await forEachAsync(arr, async fn, { concurrency: 2 }) |
| forEachRight(arr, fn) | 从右到左遍历数组 | forEachRight([1, 2, 3], fn) |
| map(collection, fn) | 映射(兼容 lodash) | map([1, 2], x => x * 2) |
| filter(collection, fn) | 过滤(兼容 lodash) | filter([1, 2], x => x > 1) |
| includes(collection, value) | 判断包含(兼容 lodash)| includes([1, 2], 1) |
| find(collection, fn) | 查找(兼容 lodash) | find([1, 2], x => x > 1) |
| findIndex(collection, fn) | 查找索引(兼容 lodash)| findIndex([1, 2], x => x > 1) |
| some(collection, fn) | 判断是否存在(兼容 lodash)| some([1, 2], x => x > 1) |
| indexOf(collection, value) | 查找位置(兼容 lodash)| indexOf([1, 2], 1) |
📝 String Module - 字符串处理
基于 es-toolkit 封装,提供丰富的字符串处理功能。
import {
camelCase,
kebabCase,
snakeCase,
uuid,
shortId,
random,
formatMoney,
hidePhone,
hideEmail,
isPhone,
isEmail,
isUrl,
highlight,
} from 'ly-utils-lib/string'
// 字符串转换
const camel = camelCase('hello-world') // 'helloWorld'
const kebab = kebabCase('helloWorld') // 'hello-world'
const snake = snakeCase('helloWorld') // 'hello_world'
// 生成 ID
const id = uuid() // 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
const short = shortId(6) // 'aB3dE6'
// 生成随机字符串
const randomStr = random(8) // 'aB3dE6fG'
// 格式化金额
const money = formatMoney(1234567.89) // '1,234,567.89'
// 隐藏敏感信息
const phone = hidePhone('13812345678') // '138****5678'
const email = hideEmail('[email protected]') // 'a***[email protected]'
// 验证
const validPhone = isPhone('13812345678') // true
const validEmail = isEmail('[email protected]') // true
const validUrl = isUrl('https://example.com') // true
// 高亮关键词
const highlighted = highlight('Hello World', 'World') // 'Hello <span class="highlight">World</span>'API 列表:
| 函数 | 说明 | 示例 |
| ------------------------------------ | -------------- | -------------------------------- |
| camelCase(str) | 驼峰命名 | camelCase('hello-world') |
| kebabCase(str) | 短横命名 | kebabCase('helloWorld') |
| snakeCase(str) | 蛇形命名 | snakeCase('helloWorld') |
| replace(str, pattern, replacement) | 替换字符串 | replace('hello', 'l', 'L') |
| uuid() | 生成 UUID | uuid() |
| shortId(length) | 生成短 ID | shortId(6) |
| random(length, charset) | 随机字符串 | random(8) |
| formatMoney(amount, decimals, sep) | 格式化金额 | formatMoney(1234.56) |
| hidePhone(phone) | 隐藏手机号 | hidePhone('138****5678') |
| hideEmail(email) | 隐藏邮箱 | hideEmail('a***[email protected]') |
| isPhone(phone) | 验证手机号 | isPhone('13812345678') |
| isEmail(email) | 验证邮箱 | isEmail('[email protected]') |
| isUrl(url) | 验证 URL | isUrl('https://example.com') |
| highlight(text, keyword) | 高亮关键词 | highlight(text, 'keyword') |
| getExtension(filename) | 获取文件扩展名 | getExtension('file.txt') |
| toNumber(str, default) | 转数字 | toNumber('123', 0) |
| toBoolean(str, default) | 转布尔值 | toBoolean('true', false) |
📦 Object Module - 对象处理
基于 es-toolkit 封装,提供强大的对象处理功能。
import {
pick,
omit,
merge,
cloneDeep,
deepMerge,
isEmpty,
isObject,
isArray,
toQueryString,
fromQueryString,
toFormData,
diff,
getDeep,
setDeep,
} from 'ly-utils-lib/object'
// 对象操作
const obj = { name: 'Alice', age: 25, city: 'Beijing' }
const picked = pick(obj, ['name', 'age']) // { name: 'Alice', age: 25 }
const omitted = omit(obj, ['city']) // { name: 'Alice', age: 25 }
// 合并对象
const merged = merge({ a: 1 }, { b: 2 }) // { a: 1, b: 2 }
const deepMerged = deepMerge({ a: { b: 1 } }, { a: { c: 2 } }) // { a: { b: 1, c: 2 } }
// 克隆
const cloned = cloneDeep(obj)
// 判断类型
const empty = isEmpty({}) // true
const isObj = isObject({}) // true
const isArr = isArray([]) // true
// 查询字符串转换
const params = { name: 'Alice', age: '25' }
const qs = toQueryString(params) // 'name=Alice&age=25'
const parsed = fromQueryString(qs) // { name: 'Alice', age: '25' }
// FormData 转换
const formData = toFormData({ name: 'Alice', age: 25 })
// 对象差值
const base = { a: 1, b: 2 }
const changed = { a: 1, b: 3 }
const diffed = diff(changed, base) // { b: 3 }
// 嵌套路径操作
const nested = { user: { name: 'Alice', age: 25 } }
const name = getDeep(nested, 'user.name') // 'Alice'
setDeep(nested, 'user.age', 26)API 列表:
| 函数 | 说明 | 示例 |
| ------------------------------- | ---------------- | --------------------------------- |
| pick(obj, keys) | 选择属性 | pick(obj, ['a', 'b']) |
| omit(obj, keys) | 排除属性 | omit(obj, ['a']) |
| merge(target, ...sources) | 浅合并 | merge({a:1}, {b:2}) |
| deepMerge(target, ...sources) | 深度合并 | deepMerge({a:{b:1}}, {a:{c:2}}) |
| cloneDeep(obj) | 深度克隆 | cloneDeep(obj) |
| isEmpty(obj) | 判断为空 | isEmpty({}) |
| isObject(obj) | 判断对象 | isObject({}) |
| isArray(obj) | 判断数组 | isArray([]) |
| toQueryString(obj) | 对象转查询字符串 | toQueryString({a:1}) |
| fromQueryString(str) | 查询字符串转对象 | fromQueryString('a=1') |
| toFormData(obj) | 对象转 FormData | toFormData({a:1}) |
| getDeep(obj, path, default) | 获取嵌套值 | getDeep(obj, 'a.b.c') |
| setDeep(obj, path, value) | 设置嵌套值 | setDeep(obj, 'a.b', 1) |
| diff(obj, base) | 对象差值 | diff({a:2}, {a:1}) |
| mapValues(obj, mapper) | 映射值 | mapValues(obj, v => v * 2) |
| filter(obj, predicate) | 过滤键值对 | filter(obj, v => v > 0) |
📈 Excel Module - Excel 处理
基于 xlsx 封装,提供 Excel 导入导出功能。
import {
exportExcel,
exportMultiSheetExcel,
importExcel,
importAllSheetsExcel,
exportExcelWithHeaders,
getSheetNames,
} from 'ly-utils-lib/excel'
// 导出 Excel
const data = [
{ name: 'Alice', age: 25, city: 'Beijing' },
{ name: 'Bob', age: 30, city: 'Shanghai' },
]
exportExcel(data, {
filename: 'export.xlsx',
sheetName: 'Users',
header: { name: '姓名', age: '年龄', city: '城市' },
})
// 导出多 Sheet Excel
exportMultiSheetExcel(
[
{
name: 'Users',
data: [{ name: 'Alice', age: 25 }],
header: { name: '姓名', age: '年龄' },
},
{
name: 'Products',
data: [{ product: 'Apple', price: 10 }],
header: { product: '产品', price: '价格' },
},
],
'multi-sheet.xlsx'
)
// 导入 Excel
const fileInput = document.querySelector('input[type="file"]')
const file = fileInput.files[0]
const importedData = await importExcel(file)
// 导入所有 Sheet
const allSheetsData = await importAllSheetsExcel(file)
// 获取 Sheet 列表
const sheetNames = await getSheetNames(file)
// 自定义表头导出
exportExcelWithHeaders(
[{ name: 'Alice', age: 25 }],
[
{ key: 'name', label: '姓名' },
{ key: 'age', label: '年龄' },
],
'custom.xlsx'
)API 列表:
| 函数 | 说明 | 示例 |
| ---------------------------------------------------- | --------------- | ------------------------------------------------------------- |
| exportExcel(data, options) | 导出 Excel | exportExcel(data, {filename: 'test.xlsx'}) |
| exportMultiSheetExcel(sheetsData, filename) | 导出多 Sheet | exportMultiSheetExcel([{name: 'Sheet1', data: []}]) |
| importExcel(file, options) | 导入 Excel | importExcel(file) |
| importAllSheetsExcel(file, options) | 导入所有 Sheet | importAllSheetsExcel(file) |
| exportExcelWithHeaders(data, headers, filename) | 自定义表头导出 | exportExcelWithHeaders(data, headers) |
| getSheetNames(file) | 获取 Sheet 列表 | getSheetNames(file) |
| exportExcelWithColumnWidths(data, widths, options) | 设置列宽导出 | exportExcelWithColumnWidths(data, [{wch: 20}]) |
| exportExcelWithMerges(data, merges, options) | 合并单元格导出 | exportExcelWithMerges(data, [{s: {r:0,c:0}, e: {r:1,c:1}}]) |
📄 PDF Module - PDF 处理
基于 html2canvas 和 jspdf 封装,提供 PDF 生成功能。
import {
captureToPDF,
captureToPDFWithPagination,
captureToImage,
captureToImageDownload,
createPDF,
addTextToPDF,
addImageToPDF,
savePDF,
} from 'ly-utils-lib/pdf'
// 将 DOM 元素转换为 PDF
const element = document.querySelector('.content')
await captureToPDF(element, {
filename: 'document.pdf',
scale: 2,
margin: 10,
})
// 分页导出
await captureToPDFWithPagination(element, {
filename: 'document-paged.pdf',
})
// 截取为图片
const imageData = await captureToImage(element)
await captureToImageDownload(element, 'screenshot.png')
// 手动创建 PDF
const pdf = createPDF({ orientation: 'portrait', format: 'a4' })
// 添加文本
addTextToPDF(pdf, 'Hello World', 10, 10, {
fontSize: 16,
align: 'center',
})
// 添加图片
addImageToPDF(pdf, imageData, 10, 30, 100, 100)
// 保存 PDF
savePDF(pdf, 'custom.pdf')API 列表:
| 函数 | 说明 | 示例 |
| ---------------------------------------------------- | -------------- | ----------------------------------------------- |
| captureToPDF(element, options) | DOM 转 PDF | captureToPDF(element, {filename: 'test.pdf'}) |
| captureToPDFWithPagination(element, options) | 分页导出 | captureToPDFWithPagination(element) |
| captureToImage(element, options) | DOM 转图片 | captureToImage(element) |
| captureToImageDownload(element, filename, options) | DOM 转图片下载 | captureToImageDownload(element, 'pic.png') |
| createPDF(options) | 创建空白 PDF | createPDF({format: 'a4'}) |
| addTextToPDF(pdf, text, x, y, options) | 添加文本 | addTextToPDF(pdf, 'text', 10, 10) |
| addImageToPDF(pdf, imageData, x, y, w, h) | 添加图片 | addImageToPDF(pdf, data, 10, 10, 100, 100) |
| addTableToPDF(pdf, headers, data, options) | 添加表格 | addTableToPDF(pdf, ['A'], [['1']]) |
| addPage(pdf) | 添加新页面 | addPage(pdf) |
| savePDF(pdf, filename) | 保存 PDF | savePDF(pdf, 'doc.pdf') |
| pdfToDataURL(pdf) | PDF 转 DataURL | pdfToDataURL(pdf) |
| pdfToBlob(pdf) | PDF 转 Blob | pdfToBlob(pdf) |
🗺️ Map Module - 地图处理
基于 OpenLayers 封装,提供强大的地图操作功能。
import {
MapInstance,
createOSMLayer,
createGaodeLayer,
createTiandituLayer,
lonLatToXY,
xyToLonLat,
} from 'ly-utils-lib/map'
// 创建地图
const map = new MapInstance({
container: 'map-container',
center: [116.3974, 39.9093], // 北京
zoom: 10,
showScaleLine: true,
showFullScreen: true,
})
// 添加 OSM 图层
const osmLayer = createOSMLayer()
map.addLayer(osmLayer)
// 添加高德地图图层
const gaodeLayer = createGaodeLayer()
map.addLayer(gaodeLayer)
// 添加天地图图层(需要 token)
const tiandituLayer = createTiandituLayer('your-token', 'vec')
map.addLayer(tiandituLayer)
// 添加标记
const marker = map.addMarker({
coordinate: [116.3974, 39.9093],
color: '#ff3333',
radius: 8,
})
// 移除标记
map.removeMarker(marker)
// 设置中心点和缩放
map.setCenter([121.4737, 31.2304]) // 上海
map.setZoom(12)
// 获取中心点
const center = map.getCenter() // [121.4737, 31.2304]
// 获取缩放级别
const zoom = map.getZoom() // 12
// 缩放到指定范围
map.fit([1000000, 6000000, 2000000, 7000000])
// 绘制点
map.startDraw({
type: 'Point',
onDrawEnd: feature => {
console.log('绘制完成', feature)
},
})
// 绘制线
map.startDraw({
type: 'LineString',
onDrawEnd: feature => {
console.log('绘制完成', feature)
},
})
// 绘制面
map.startDraw({
type: 'Polygon',
onDrawEnd: feature => {
console.log('绘制完成', feature)
},
})
// 停止绘制
map.stopDraw()
// 开始编辑
map.startModify()
// 停止编辑
map.stopModify()
// 选择要素
map.startSelect(features => {
console.log('选中的要素:', features)
})
// 停止选择
map.stopSelect()
// 获取所有要素
const features = map.getFeatures()
// 清除所有矢量要素
map.clearFeatures()
// 事件监听
map.on('click', evt => {
console.log('点击位置:', evt.coordinate)
})
map.on('moveend', () => {
console.log('地图移动结束', map.getCenter())
})
// 更新地图大小(容器大小改变时)
map.updateSize()
// 销毁地图
map.destroy()API 列表:
| 类/函数 | 说明 | 示例 |
| ---------------------------------------- | -------------- | ----------------------------------------- |
| new MapInstance(options) | 创建地图实例 | new MapInstance({container: 'map'}) |
| map.setCenter(coord) | 设置中心点 | map.setCenter([116.39, 39.90]) |
| map.getCenter() | 获取中心点 | map.getCenter() |
| map.setZoom(zoom) | 设置缩放级别 | map.setZoom(10) |
| map.getZoom() | 获取缩放级别 | map.getZoom() |
| map.fit(extent) | 缩放到范围 | map.fit([minX, minY, maxX, maxY]) |
| map.addLayer(layer) | 添加图层 | map.addLayer(createOSMLayer()) |
| map.removeLayer(layer) | 移除图层 | map.removeLayer(layer) |
| map.addMarker(options) | 添加标记 | map.addMarker({coordinate: [lon, lat]}) |
| map.removeMarker(feature) | 移除标记 | map.removeMarker(marker) |
| map.clearFeatures() | 清除所有要素 | map.clearFeatures() |
| map.startDraw(options) | 开始绘制 | map.startDraw({type: 'Point'}) |
| map.stopDraw() | 停止绘制 | map.stopDraw() |
| map.startModify() | 开始编辑 | map.startModify() |
| map.stopModify() | 停止编辑 | map.stopModify() |
| map.startSelect(callback) | 开始选择 | map.startSelect((f) => console.log(f)) |
| map.stopSelect() | 停止选择 | map.stopSelect() |
| map.getFeatures() | 获取所有要素 | map.getFeatures() |
| map.getSelectedFeatures() | 获取选中要素 | map.getSelectedFeatures() |
| map.on(event, callback) | 事件监听 | map.on('click', (e) => {}) |
| map.off(event, callback) | 移除监听 | map.off('click', callback) |
| map.updateSize() | 更新地图大小 | map.updateSize() |
| map.destroy() | 销毁地图 | map.destroy() |
| createOSMLayer(name) | 创建 OSM 图层 | createOSMLayer('OSM') |
| createXYZLayer(url, name) | 创建 XYZ 图层 | createXYZLayer(url, 'Custom') |
| createGaodeLayer(name) | 创建高德图层 | createGaodeLayer('高德') |
| createTiandituLayer(token, type, name) | 创建天地图图层 | createTiandituLayer('token', 'vec') |
| createVectorLayer(name) | 创建矢量图层 | createVectorLayer('Vector') |
| lonLatToXY(lon, lat) | 经纬度转投影 | lonLatToXY(116.39, 39.90) |
| xyToLonLat(x, y) | 投影转经纬度 | xyToLonLat(x, y) |
🎯 Event Module - 事件管理
基于 mitt 封装的轻量级事件发布订阅系统,提供类型安全的事件管理。
import {
createEventBus,
getGlobalEventBus,
waitForEvent,
batchSubscribe,
createNamespacedEventBus,
} from 'ly-utils-lib/event'
// 定义事件类型
interface AppEvents {
'user:login': { id: number; name: string }
'user:logout': never
'data:loaded': { data: any[] }
'error': Error
}
// 方式 1: 创建类型化的事件总线
const bus = createEventBus<AppEvents>({ debug: true })
// 订阅事件
const unsubscribe = bus.on('user:login', (user) => {
console.log('User logged in:', user.name)
})
// 订阅一次性事件
bus.once('data:loaded', (data) => {
console.log('Data loaded:', data.data)
})
// 发布事件
bus.emit('user:login', { id: 1, name: 'Alice' })
bus.emit('user:logout')
bus.emit('error', new Error('Something went wrong'))
// 取消订阅
unsubscribe()
// 方式 2: 批量订阅
batchSubscribe(bus, {
'user:login': (user) => console.log('Login:', user),
'user:logout': () => console.log('Logout'),
'error': (error) => console.error('Error:', error),
})
// 方式 3: 等待事件触发
const userData = await waitForEvent<{ id: number; name: string }>(
bus,
'user:login',
5000
)
console.log('User logged in:', userData.name)
// 方式 4: 使用命名空间
const userBus = createNamespacedEventBus('user')
const appBus = createNamespacedEventBus('app')
userBus.emit('login') // 实际事件名: user:login
appBus.emit('ready') // 实际事件名: app:ready
// 方式 5: 使用全局事件总线
const globalBus = getGlobalEventBus({ debug: true })
globalBus.emit('app:ready')API 列表:
创建事件总线
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| createEventBus<E>(options) | 创建事件总线 | createEventBus({debug: true}) |
| getGlobalEventBus<E>(options?) | 获取全局事件总线 | getGlobalEventBus() |
| createNamespacedEventBus<E>(namespace) | 创建命名空间总线 | createNamespacedEventBus('user') |
订阅事件
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| bus.on(event, handler) | 订阅事件 | bus.on('click', handler) |
| bus.once(event, handler) | 订阅一次事件 | bus.once('init', handler) |
| batchSubscribe(bus, events) | 批量订阅 | batchSubscribe(bus, {...}) |
| waitForEvent(bus, event, timeout) | 等待事件触发 | waitForEvent(bus, 'ready', 5000) |
发布事件
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| bus.emit(event, data?) | 发布事件 | bus.emit('click', {x, y}) |
取消订阅
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| bus.off(event, handler?) | 取消订阅 | bus.off('click', handler) |
| bus.clear() | 清空所有监听器 | bus.clear() |
查询方法
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| bus.getListenerCount(event?) | 获取监听器数量 | bus.getListenerCount() |
| bus.getEventNames() | 获取所有事件名 | bus.getEventNames() |
| bus.getListeners(event) | 获取监听器列表 | bus.getListeners('click') |
配置选项
| 选项 | 说明 | 默认值 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| debug | 调试日志 | true |
| prefix | 事件名前缀 | '' |
高级功能
- ✅ 类型安全的事件定义
- ✅ 支持命名空间
- ✅ 支持全局单例
- ✅ 批量订阅/取消
- ✅ 等待事件触发(Promise)
- ✅ 一次性事件
- ✅ 监听器管理
- ✅ 调试日志
🔌 WebSocket Module - WebSocket 工具
提供简化的 WebSocket 连接、消息发送、心跳检测和重连机制。
import {
createWebSocket,
quickConnect,
WebSocketState,
} from 'ly-utils-lib/websocket'
// 方式 1: 使用 createWebSocket
const ws = createWebSocket({
url: 'echo.websocket.org',
autoReconnect: true,
reconnectAttempts: 3,
heartbeatInterval: 30000,
onOpen: (event) => console.log('Connected'),
onMessage: (data, event) => console.log('Received:', data),
onClose: (event) => console.log('Disconnected'),
onError: (event) => console.error('Error:', event),
onReconnect: (attempt) => console.log(`Reconnecting... (${attempt})`),
onHeartbeat: () => console.log('Heartbeat'),
})
// 发送消息
ws.send('Hello, WebSocket!')
ws.send({ type: 'message', content: 'Hello' })
// 检查连接状态
if (ws.isConnected()) {
console.log('Connected')
}
// 断开连接
ws.disconnect()
// 方式 2: 使用 quickConnect
const ws2 = quickConnect('echo.websocket.org', {
onMessage: (data) => console.log('Received:', data),
})
// 重新连接
ws.reconnect()API 列表:
创建客户端
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| createWebSocket(options) | 创建 WebSocket 客户端 | createWebSocket({url: '...'}) |
| quickConnect(url, handlers?) | 快速连接 | quickConnect('...') |
| WebSocketClient | WebSocket 客户端类 | new WebSocketClient({url: '...'}) |
连接管理
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| connect() | 连接 | ws.connect() |
| disconnect() | 断开连接 | ws.disconnect() |
| reconnect() | 重新连接 | ws.reconnect() |
| getState() | 获取连接状态 | ws.getState() |
| isConnected() | 是否已连接 | ws.isConnected() |
| getInstance() | 获取 WebSocket 实例 | ws.getInstance() |
消息发送
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| send(data) | 发送消息(异步) | ws.send('Hello') |
| sendSync(data) | 发送消息(同步) | ws.sendSync('Hello') |
事件处理
| 类/函数 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| on(event, handler) | 设置事件处理器 | ws.on('message', handler) |
| off(event, handler?) | 移除事件处理器 | ws.off('message', handler) |
配置选项
| 选项 | 说明 | 默认值 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| url | WebSocket 地址 | - |
| protocol | 协议 (ws/wss) | 自动检测 |
| protocols | 子协议 | [] |
| autoReconnect | 自动重连 | true |
| reconnectAttempts | 重连次数 | 3 |
| reconnectInterval | 重连间隔(ms) | 3000 |
| heartbeatInterval | 心跳间隔(ms) | 30000 |
| heartbeatMessage | 心跳消息 | 'ping' |
| heartbeatTimeout | 心跳超时(ms) | 5000 |
| connectTimeout | 连接超时(ms) | 10000 |
| debug | 调试日志 | true |
事件处理器
| 事件 | 说明 | 示例 |
| --------------------------------------------- | --------------------- | -------------------------------------- |
| onOpen | 连接成功 | onOpen: (event) => void |
| onMessage | 接收消息 | onMessage: (data, event) => void |
| onClose | 连接关闭 | onClose: (event) => void |
| onError | 错误 | onError: (event) => void |
| onReconnect | 重连开始 | onReconnect: (attempt) => void |
| onReconnectSuccess | 重连成功 | onReconnectSuccess: (attempt) => void|
| onReconnectFailed | 重连失败 | onReconnectFailed: () => void |
| onHeartbeat | 心跳 | onHeartbeat: () => void |
| onHeartbeatTimeout | 心跳超时 | onHeartbeatTimeout: () => void |
💾 Storage Module - 存储处理
基于浏览器 Web Storage API 和 Cookie(使用 js-cookie 封装),提供统一的存储操作功能。
import {
setLocal,
getLocal,
removeLocal,
clearLocal,
setSession,
getSession,
setCookie,
getCookie,
removeCookie,
getAllCookies,
hasCookie,
setCookieJSON,
getCookieJSON,
getCookieSize,
setStorage,
getStorage,
removeStorage,
} from 'ly-utils-lib/storage'
// LocalStorage 操作
setLocal('user', { name: 'Alice', age: 25 })
const user = getLocal<{ name: string; age: number }>('user')
console.log(user?.name) // 'Alice'
// 带过期时间的存储
setLocal('token', 'abc123', { ttl: 3600000 }) // 1小时后过期
const token = getLocal('token')
// SessionStorage 操作
setSession('temp', { data: [1, 2, 3] })
const temp = getSession('temp')
// Cookie 操作(支持对象类型)
setCookie('token', 'abc123', { days: 7, secure: true })
setCookie('user', { name: 'Alice', age: 25 }, { days: 30 }) // 自动序列化对象
const cookieToken = getCookie('token')
// JSON 格式 Cookie
setCookieJSON('config', { theme: 'dark', lang: 'zh-CN' }, { days: 7 })
const config = getCookieJSON<{ theme: string; lang: string }>('config')
// Cookie 工具函数
if (hasCookie('token')) {
console.log('Token exists')
}
const cookieSize = getCookieSize() // 获取 Cookie 数量
const allCookies = getAllCookies() // 获取所有 Cookie
// 统一接口
setStorage('local', 'user', { name: 'Alice' })
setStorage('cookie', 'token', 'abc123', { days: 7 })
const user = getStorage<{ name: string }>('local', 'user')
const token = getStorage('cookie', 'token')
// 清除操作
removeLocal('user')
removeCookie('token')
clearStorage('local')API 列表:
LocalStorage
| 类/函数 | 说明 | 示例 |
| --------------------------------- | --------------- | -------------------------------------- |
| setLocal(key, value, options) | 设置永久缓存 | setLocal('user', {name: 'Alice'}) |
| getLocal<T>(key) | 获取永久缓存 | getLocal<User>('user') |
| removeLocal(key) | 移除永久缓存 | removeLocal('user') |
| clearLocal() | 清除永久缓存 | clearLocal() |
| getLocalKeys() | 获取所有键 | getLocalKeys() |
| getLocalSize() | 获取键数量 | getLocalSize() |
SessionStorage
| 类/函数 | 说明 | 示例 |
| --------------------------------- | --------------- | -------------------------------------- |
| setSession(key, value, options) | 设置临时缓存 | setSession('temp', {data: [1,2,3]}) |
| getSession<T>(key) | 获取临时缓存 | getSession<Data>('temp') |
| removeSession(key) | 移除临时缓存 | removeSession('temp') |
| clearSession() | 清除临时缓存 | clearSession() |
| getSessionKeys() | 获取所有键 | getSessionKeys() |
| getSessionSize() | 获取键数量 | getSessionSize() |
Cookie (基于 js-cookie)
| 类/函数 | 说明 | 示例 |
| --------------------------------- | --------------- | -------------------------------------- |
| setCookie(key, value, options) | 设置 Cookie | setCookie('token', 'abc', {days: 7}) |
| getCookie(key) | 获取 Cookie | getCookie('token') |
| removeCookie(key, options) | 移除 Cookie | removeCookie('token', {path: '/'}) |
| getAllCookies() | 获取所有 Cookie | getAllCookies() |
| hasCookie(key) | 检查 Cookie 是否存在 | hasCookie('token') |
| getCookieJSON<T>(key) | 获取 JSON 格式 Cookie | getCookieJSON<User>('user') |
| setCookieJSON(key, value, options) | 设置 JSON 格式 Cookie | setCookieJSON('config', {}, {days: 7}) |
| getCookieSize() | 获取 Cookie 数量 | getCookieSize() |
统一接口
| 类/函数 | 说明 | 示例 |
| --------------------------------- | --------------- | -------------------------------------- |
| setStorage(type, key, value) | 统一设置存储 | setStorage('local', 'user', {}) |
| getStorage<T>(type, key) | 统一获取存储 | getStorage('local', 'user') |
| removeStorage(type, key) | 统一移除存储 | removeStorage('local', 'user') |
| clearStorage(type) | 统一清除存储 | clearStorage('local') |
Demo
在线演示
查看完整功能的在线演示:
- 完整 Demo: demo/index.html - 包含所有 7 个模块的完整演示
- 地图 Demo: demo/map.html - 专门展示地图模块功能
本地运行
# 克隆项目
git clone https://gitee.com/liyang517/ai-utils.git
cd ai-utils
# 安装依赖
pnpm install
# 构建项目
pnpm build
# 启动开发服务器
pnpm dev然后在浏览器中打开:
- 完整 Demo:
http://localhost:5000/demo/ - 地图 Demo:
http://localhost:5000/demo/map.html
Demo 功能
完整 Demo 包含以下功能:
- 📋 概览 - 项目介绍和快速开始
- 📅 日期模块 - 日期格式化、计算、范围查询
- 📊 数组模块 - 去重、统计、排序、转换
- 📝 字符串模块 - 转换、ID 生成、验证、格式化
- 📦 对象模块 - 操作、合并、查询、深度操作
- 📈 Excel 模块 - 导入导出、多 Sheet 支持
- 📄 PDF 模块 - DOM 转 PDF、自定义 PDF、截图
- 🗺️ 地图模块 - 创建地图、图层切换、绘制、编辑、选择
地图 Demo 专门展示地图功能:
- 多城市快速定位
- OSM 和高德图层切换
- 标记管理(添加、删除)
- 绘制功能(点、线、面、圆形)
- 编辑和选择功能
- 实时状态显示
开发
# 安装依赖
pnpm install
# 构建
pnpm build
# 开发模式
pnpm dev
# 代码检查
pnpm lint
pnpm lint:fix
# 代码格式化
pnpm format目录结构
utils-toolkit/
├── src/
│ ├── index.ts # 主入口
│ └── modules/
│ ├── date/ # 日期模块
│ ├── array/ # 数组模块
│ ├── string/ # 字符串模块
│ ├── object/ # 对象模块
│ ├── excel/ # Excel 模块
│ └── pdf/ # PDF 模块
├── demo/ # 示例
│ └── index.html
├── dist/ # 构建输出
├── package.json
├── tsconfig.json
├── tsup.config.ts
└── README.md贡献
欢迎贡献代码!请先阅读 贡献指南。
许可证
MIT License
版本历史
v0.2.0 (最新)
- 🗺️ 新增 Map 模块,基于 OpenLayers 10.8.0
- ✨ 支持创建地图、添加图层、标记管理
- ✨ 支持绘制功能(点、线、面、圆形)
- ✨ 支持编辑和选择要素
- ✨ 支持 OSM、高德、天地图等多种图层
- ✨ 提供完整的类型定义和 API 文档
- 📝 新增 Map 模块示例页面
v0.1.0
- 🎉 初始版本发布
- ✅ 实现六大核心模块
- ✅ 支持 ESM 和 CJS 双格式
链接
📚 文档
致谢
- dayjs - 轻量级日期处理库
- es-toolkit - 现代工具库
- xlsx - Excel 处理库
- html2canvas - 截图库
- jspdf - PDF 生成库
Made with ❤️ by Your Team
