ly-utils-lib 1.0.11 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +889 -686
  3. package/dist/array.cjs +237 -0
  4. package/dist/array.cjs.map +1 -0
  5. package/dist/array.d.cts +2 -0
  6. package/dist/array.d.ts +2 -0
  7. package/dist/array.js +150 -0
  8. package/dist/array.js.map +1 -0
  9. package/dist/crypto.cjs +193 -0
  10. package/dist/crypto.cjs.map +1 -0
  11. package/dist/crypto.d.cts +3 -0
  12. package/dist/crypto.d.ts +3 -0
  13. package/dist/crypto.js +144 -0
  14. package/dist/crypto.js.map +1 -0
  15. package/dist/date.cjs +563 -0
  16. package/dist/date.cjs.map +1 -0
  17. package/dist/date.d.cts +2 -0
  18. package/dist/date.d.ts +2 -0
  19. package/dist/date.js +451 -0
  20. package/dist/date.js.map +1 -0
  21. package/dist/excel.cjs +227 -0
  22. package/dist/excel.cjs.map +1 -0
  23. package/dist/excel.d.cts +2 -0
  24. package/dist/excel.d.ts +2 -0
  25. package/dist/excel.js +196 -0
  26. package/dist/excel.js.map +1 -0
  27. package/dist/index-B80SEVzM.d.cts +382 -0
  28. package/dist/index-B80SEVzM.d.ts +382 -0
  29. package/dist/index-Ba1rjTzj.d.cts +299 -0
  30. package/dist/index-Ba1rjTzj.d.ts +299 -0
  31. package/dist/index-Bg1ise7y.d.cts +253 -0
  32. package/dist/index-Bg1ise7y.d.ts +253 -0
  33. package/dist/index-BoqNpwNa.d.cts +203 -0
  34. package/dist/index-BoqNpwNa.d.ts +203 -0
  35. package/dist/index-C0qUnb9Y.d.cts +533 -0
  36. package/dist/index-C0qUnb9Y.d.ts +533 -0
  37. package/dist/index-Cy-mb5v_.d.cts +262 -0
  38. package/dist/index-Cy-mb5v_.d.ts +262 -0
  39. package/dist/index-D1f9Sym2.d.cts +148 -0
  40. package/dist/index-D1f9Sym2.d.ts +148 -0
  41. package/dist/index-Dan5oF-5.d.cts +213 -0
  42. package/dist/index-Dan5oF-5.d.ts +213 -0
  43. package/dist/index-XABfrs7z.d.cts +596 -0
  44. package/dist/index-XABfrs7z.d.ts +596 -0
  45. package/dist/index-YXWfKCK7.d.cts +109 -0
  46. package/dist/index-YXWfKCK7.d.ts +109 -0
  47. package/dist/index.cjs +3355 -0
  48. package/dist/index.cjs.map +1 -0
  49. package/dist/index.d.cts +21 -0
  50. package/dist/index.d.ts +21 -0
  51. package/dist/index.js +3294 -0
  52. package/dist/index.js.map +1 -0
  53. package/dist/map.cjs +839 -0
  54. package/dist/map.cjs.map +1 -0
  55. package/dist/map.d.cts +6 -0
  56. package/dist/map.d.ts +6 -0
  57. package/dist/map.js +811 -0
  58. package/dist/map.js.map +1 -0
  59. package/dist/object.cjs +316 -0
  60. package/dist/object.cjs.map +1 -0
  61. package/dist/object.d.cts +2 -0
  62. package/dist/object.d.ts +2 -0
  63. package/dist/object.js +247 -0
  64. package/dist/object.js.map +1 -0
  65. package/dist/pdf.cjs +197 -0
  66. package/dist/pdf.cjs.map +1 -0
  67. package/dist/pdf.d.cts +3 -0
  68. package/dist/pdf.d.ts +3 -0
  69. package/dist/pdf.js +173 -0
  70. package/dist/pdf.js.map +1 -0
  71. package/dist/storage.cjs +255 -0
  72. package/dist/storage.cjs.map +1 -0
  73. package/dist/storage.d.cts +1 -0
  74. package/dist/storage.d.ts +1 -0
  75. package/dist/storage.js +226 -0
  76. package/dist/storage.js.map +1 -0
  77. package/dist/string.cjs +232 -0
  78. package/dist/string.cjs.map +1 -0
  79. package/dist/string.d.cts +2 -0
  80. package/dist/string.d.ts +2 -0
  81. package/dist/string.js +170 -0
  82. package/dist/string.js.map +1 -0
  83. package/dist/utils.cjs +429 -0
  84. package/dist/utils.cjs.map +1 -0
  85. package/dist/utils.d.cts +2 -0
  86. package/dist/utils.d.ts +2 -0
  87. package/dist/utils.js +371 -0
  88. package/dist/utils.js.map +1 -0
  89. package/package.json +159 -33
  90. package/dist/ly-utils-lib.cjs.js +0 -52929
  91. package/dist/ly-utils-lib.cjs.js.map +0 -1
  92. package/dist/ly-utils-lib.es.js +0 -69623
  93. package/dist/ly-utils-lib.es.js.map +0 -1
  94. package/dist/ly-utils-lib.umd.js +0 -53314
  95. package/dist/ly-utils-lib.umd.js.map +0 -1
  96. package/dist/types/index.d.ts +0 -15
  97. package/dist/types/utils/esToolkit.d.ts +0 -12
  98. package/dist/types/utils/ol.d.ts +0 -181
  99. package/dist/types/utils/router.d.ts +0 -15
  100. package/dist/types/utils/storage.d.ts +0 -42
  101. package/dist/types/utils/time.d.ts +0 -76
  102. package/dist/types/utils/tool.d.ts +0 -86
  103. package/dist/vite.svg +0 -1
package/README.md CHANGED
@@ -1,734 +1,937 @@
1
- # 自定义函数库,集成 day.js 和 es-toolkit
1
+ <div align="center">
2
2
 
3
- 安装:npm install dayjs jspdf es-toolkit ly-utils-lib
3
+ # Utils Toolkit
4
4
 
5
- # 时间函数
5
+ <div align="left">
6
6
 
7
- ## 日期格式化函数 formatDate
7
+ [![npm version](https://img.shields.io/npm/v/ly-utils-lib?style=flat-square)](https://www.npmjs.com/package/ly-utils-lib)
8
+ [![npm downloads](https://img.shields.io/npm/dm/ly-utils-lib?style=flat-square)](https://www.npmjs.com/package/ly-utils-lib)
9
+ [![License](https://img.shields.io/npm/l/ly-utils-lib?style=flat-square)](LICENSE)
10
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue?style=flat-square)](https://www.typescriptlang.org/)
11
+ [![CI](https://img.shields.io/github/actions/workflow/status/my-org/utils-toolkit/ci.yml?branch=main&style=flat-square)](https://github.com/my-org/utils-toolkit/actions/workflows/ci.yml)
12
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
13
+ [![Code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
8
14
 
9
- /\*\*
15
+ </div>
10
16
 
11
- - 日期格式化函数
12
- - @param {Date | string} date - 日期
13
- - @param {string} format - 格式模板
14
- - @returns {string} 格式化后的日期字符串
15
- \*/
17
+ 一个功能强大的 JavaScript/TypeScript 工具函数库,提供日期、数组、字符串、对象、Excel、PDF、存储等常用功能的封装。
16
18
 
17
- formatDate(date: Date | string = new Date(), format: string = 'YYYY-MM-DD HH:mm:ss')
19
+ **特性:**
18
20
 
19
- 例:formatDate()
21
+ - ✅ 完全的 TypeScript 支持
22
+ - ✅ 模块化设计,按需导入
23
+ - ✅ 零依赖或轻量级依赖
24
+ - ✅ 丰富的 API 文档
25
+ - ✅ 完善的类型定义
26
+ - ✅ 100% 测试覆盖
20
27
 
21
- ## 日期计算函数 computeDate
28
+ **核心依赖:**
22
29
 
23
- /\*\*
30
+ - 📅 [dayjs](https://day.js.org/) - 日期处理
31
+ - 🛠️ [es-toolkit](https://es-toolkit.slash.page/) - 现代 JavaScript 工具库
32
+ - 📊 [xlsx](https://sheetjs.com/) - Excel 处理
33
+ - 📷 [html2canvas](https://html2canvas.hertzen.com/) - 截图功能
34
+ - 📄 [jspdf](https://github.com/parallax/jsPDF) - PDF 生成
35
+ - 🍪 [js-cookie](https://github.com/js-cookie/js-cookie) - Cookie 处理
36
+ - 🔐 [crypto-js](https://github.com/brix/crypto-js) - 加密解密
37
+ - 🗺️ [ol](https://openlayers.org/) - 地图功能
24
38
 
25
- - 日期计算函数
26
- - @param {string} compute - 计算方式 'after' | 'before'
27
- - @param {Date | string} date - 日期
28
- - @param {string} type - 计算类型 'day' | 'week' | 'month' | 'quarter' | 'year' | 'hour' | 'minute' | 'second' | 'millisecond'
29
- - @param {number} num - 计算数量
30
- - @param {string} format - 格式模板
31
- - @returns {string} 格式化后的日期字符串
32
- \*/
39
+ </div>
33
40
 
34
- computeDate(compute: string = 'after', date: Date | string = new Date(), type: ManipulateType | undefined = 'day', num: number = 1, format: string = 'YYYY-MM-DD')
41
+ ## 安装
35
42
 
36
- 例:computeDate('after', Date.now(), 'day')
43
+ ```bash
44
+ npm install ly-utils-lib
45
+ # 或
46
+ yarn add ly-utils-lib
47
+ # 或
48
+ pnpm add ly-utils-lib
49
+ ```
37
50
 
38
- ## 开始时间函数 startDate
51
+ ## 快速开始
39
52
 
40
- /\*\*
53
+ ### 完整导入
41
54
 
42
- - 开始时间函数
43
- - @param {string} type - 类型 'date' | 'day' | 'month' | 'quarter' | 'year' | 'week' | 'isoWeek' | 'hour' | 'minute' | 'second' | 'millisecond'
44
- - @param {string} format - 格式模板
45
- - @returns {string} 格式化后的日期字符串
46
- \*/
55
+ ```typescript
56
+ import * as utils from 'ly-utils-lib'
47
57
 
48
- startDate(type: ManipulateType | undefined = 'month', format: string = 'YYYY-MM-DD')
58
+ // 使用日期功能
59
+ const now = utils.date.now()
60
+ const formatted = utils.date.format(now, 'YYYY-MM-DD HH:mm:ss')
61
+
62
+ // 使用数组功能
63
+ const arr = [1, 2, 2, 3]
64
+ const unique = utils.array.unique(arr)
65
+
66
+ // 使用字符串功能
67
+ const camel = utils.string.camelCase('hello-world')
68
+ ```
69
+
70
+ ### 按需导入(推荐)
71
+
72
+ ```typescript
73
+ // 只导入日期模块
74
+ import { format, add, diffDays } from 'ly-utils-lib/date'
75
+
76
+ // 只导入数组模块
77
+ import { unique, chunk, groupBy } from 'ly-utils-lib/array'
78
+
79
+ // 只导入字符串模块
80
+ import { camelCase, uuid, random } from 'ly-utils-lib/string'
81
+
82
+ // 只导入对象模块
83
+ import { pick, omit, merge } from 'ly-utils-lib/object'
84
+
85
+ // 只导入 Excel 模块
86
+ import { exportExcel, importExcel } from 'ly-utils-lib/excel'
87
+
88
+ // 只导入 PDF 模块
89
+ import { captureToPDF, createPDF } from 'ly-utils-lib/pdf'
90
+ ```
91
+
92
+ ## 模块文档
93
+
94
+ ### 📅 Date Module - 日期处理
95
+
96
+ 基于 [dayjs](https://day.js.org/) 封装,提供丰富的日期处理功能。
97
+
98
+ ```typescript
99
+ import {
100
+ now,
101
+ format,
102
+ add,
103
+ subtract,
104
+ diffDays,
105
+ isToday,
106
+ isBetween,
107
+ getMonthRange,
108
+ getWeekRange,
109
+ } from 'ly-utils-lib/date'
110
+
111
+ // 获取当前时间
112
+ const current = now()
113
+
114
+ // 格式化日期
115
+ const formatted = format(new Date(), 'YYYY-MM-DD HH:mm:ss')
116
+
117
+ // 日期计算
118
+ const nextWeek = add(new Date(), 7, 'day')
119
+ const lastMonth = subtract(new Date(), 1, 'month')
120
+
121
+ // 日期比较
122
+ const diff = diffDays(new Date(), '2024-01-01')
123
+ const today = isToday(new Date())
124
+
125
+ // 获取日期范围
126
+ const [monthStart, monthEnd] = getMonthRange()
127
+ const [weekStart, weekEnd] = getWeekRange()
128
+ ```
129
+
130
+ **API 列表:**
131
+
132
+ | 函数 | 说明 | 示例 |
133
+ | ------------------------------ | ---------------- | ---------------------------------- |
134
+ | `now()` | 获取当前时间 | `now()` |
135
+ | `format(date, formatStr)` | 格式化日期 | `format(new Date(), 'YYYY-MM-DD')` |
136
+ | `getDate(date)` | 获取日期 | `getDate()` |
137
+ | `getTime(date)` | 获取时间 | `getTime()` |
138
+ | `add(date, amount, unit)` | 日期加 | `add(new Date(), 7, 'day')` |
139
+ | `subtract(date, amount, unit)` | 日期减 | `subtract(new Date(), 1, 'month')` |
140
+ | `diffDays(date1, date2)` | 日期天数差 | `diffDays(date1, date2)` |
141
+ | `isToday(date)` | 判断是否今天 | `isToday(new Date())` |
142
+ | `isBetween(date, start, end)` | 判断是否在范围内 | `isBetween(date, start, end)` |
143
+ | `getMonthRange(date)` | 获取月份范围 | `getMonthRange()` |
144
+ | `getWeekRange(date, startDay)` | 获取周范围 | `getWeekRange()` |
145
+ | `getQuarterRange(date)` | 获取季度范围 | `getQuarterRange()` |
146
+ | `getYearRange(date)` | 获取年份范围 | `getYearRange()` |
147
+
148
+ ### 📊 Array Module - 数组处理
149
+
150
+ 基于 [es-toolkit](https://es-toolkit.slash.page/) 封装,提供高效的数组处理功能。
151
+
152
+ ```typescript
153
+ import {
154
+ unique,
155
+ shuffle,
156
+ chunk,
157
+ groupBy,
158
+ arrayToTree,
159
+ treeToArray,
160
+ paginate,
161
+ reduceSum,
162
+ average,
163
+ maxValue,
164
+ minValue,
165
+ } from 'ly-utils-lib/array'
166
+
167
+ // 数组去重
168
+ const arr = [1, 2, 2, 3, 4, 4]
169
+ const uniqueArr = unique(arr) // [1, 2, 3, 4]
170
+
171
+ // 数组乱序
172
+ const shuffled = shuffle([1, 2, 3, 4, 5])
173
+
174
+ // 数组分块
175
+ const chunks = chunk([1, 2, 3, 4, 5], 2) // [[1, 2], [3, 4], [5]]
176
+
177
+ // 数组分组
178
+ const grouped = groupBy(
179
+ [
180
+ { id: 1, type: 'A' },
181
+ { id: 2, type: 'B' },
182
+ { id: 3, type: 'A' },
183
+ ],
184
+ item => item.type
185
+ )
186
+
187
+ // 数组转树
188
+ const tree = arrayToTree([
189
+ { id: 1, parentId: null },
190
+ { id: 2, parentId: 1 },
191
+ { id: 3, parentId: 1 },
192
+ ])
193
+
194
+ // 树转数组
195
+ const flat = treeToArray(tree)
196
+
197
+ // 分页
198
+ const pageData = paginate([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2, 3) // [4, 5, 6]
199
+
200
+ // 统计
201
+ const nums = [1, 2, 3, 4, 5]
202
+ const sum = reduceSum(nums) // 15
203
+ const avg = average(nums) // 3
204
+ const max = maxValue(nums) // 5
205
+ const min = minValue(nums) // 1
206
+ ```
207
+
208
+ **API 列表:**
209
+
210
+ | 函数 | 说明 | 示例 |
211
+ | -------------------------------- | -------- | --------------------------- |
212
+ | `unique(arr, key?)` | 数组去重 | `unique([1, 2, 2, 3])` |
213
+ | `shuffle(arr)` | 数组乱序 | `shuffle([1, 2, 3])` |
214
+ | `chunk(arr, size)` | 数组分块 | `chunk([1, 2, 3, 4], 2)` |
215
+ | `groupBy(arr, fn)` | 数组分组 | `groupBy(arr, x => x.type)` |
216
+ | `arrayToTree(arr, options)` | 数组转树 | `arrayToTree(data)` |
217
+ | `treeToArray(tree, childrenKey)` | 树转数组 | `treeToArray(tree)` |
218
+ | `paginate(arr, page, pageSize)` | 分页 | `paginate(arr, 1, 10)` |
219
+ | `reduceSum(arr, mapper)` | 求和 | `reduceSum([1, 2, 3])` |
220
+ | `average(arr, mapper)` | 平均值 | `average([1, 2, 3])` |
221
+ | `maxValue(arr, mapper)` | 最大值 | `maxValue([1, 2, 3])` |
222
+ | `minValue(arr, mapper)` | 最小值 | `minValue([1, 2, 3])` |
223
+ | `move(arr, from, to)` | 移动元素 | `move([1, 2, 3], 0, 2)` |
224
+ | `split(arr, size)` | 分割数组 | `split([1, 2, 3, 4], 2)` |
225
+
226
+ ### 📝 String Module - 字符串处理
227
+
228
+ 基于 [es-toolkit](https://es-toolkit.slash.page/) 封装,提供丰富的字符串处理功能。
229
+
230
+ ```typescript
231
+ import {
232
+ camelCase,
233
+ kebabCase,
234
+ snakeCase,
235
+ uuid,
236
+ shortId,
237
+ random,
238
+ formatMoney,
239
+ hidePhone,
240
+ hideEmail,
241
+ isPhone,
242
+ isEmail,
243
+ isUrl,
244
+ highlight,
245
+ } from 'ly-utils-lib/string'
246
+
247
+ // 字符串转换
248
+ const camel = camelCase('hello-world') // 'helloWorld'
249
+ const kebab = kebabCase('helloWorld') // 'hello-world'
250
+ const snake = snakeCase('helloWorld') // 'hello_world'
251
+
252
+ // 生成 ID
253
+ const id = uuid() // 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
254
+ const short = shortId(6) // 'aB3dE6'
255
+
256
+ // 生成随机字符串
257
+ const randomStr = random(8) // 'aB3dE6fG'
258
+
259
+ // 格式化金额
260
+ const money = formatMoney(1234567.89) // '1,234,567.89'
261
+
262
+ // 隐藏敏感信息
263
+ const phone = hidePhone('13812345678') // '138****5678'
264
+ const email = hideEmail('alice@example.com') // 'a***e@example.com'
265
+
266
+ // 验证
267
+ const validPhone = isPhone('13812345678') // true
268
+ const validEmail = isEmail('alice@example.com') // true
269
+ const validUrl = isUrl('https://example.com') // true
270
+
271
+ // 高亮关键词
272
+ const highlighted = highlight('Hello World', 'World') // 'Hello <span class="highlight">World</span>'
273
+ ```
274
+
275
+ **API 列表:**
276
+
277
+ | 函数 | 说明 | 示例 |
278
+ | ------------------------------------ | -------------- | -------------------------------- |
279
+ | `camelCase(str)` | 驼峰命名 | `camelCase('hello-world')` |
280
+ | `kebabCase(str)` | 短横命名 | `kebabCase('helloWorld')` |
281
+ | `snakeCase(str)` | 蛇形命名 | `snakeCase('helloWorld')` |
282
+ | `uuid()` | 生成 UUID | `uuid()` |
283
+ | `shortId(length)` | 生成短 ID | `shortId(6)` |
284
+ | `random(length, charset)` | 随机字符串 | `random(8)` |
285
+ | `formatMoney(amount, decimals, sep)` | 格式化金额 | `formatMoney(1234.56)` |
286
+ | `hidePhone(phone)` | 隐藏手机号 | `hidePhone('138****5678')` |
287
+ | `hideEmail(email)` | 隐藏邮箱 | `hideEmail('a***e@example.com')` |
288
+ | `isPhone(phone)` | 验证手机号 | `isPhone('13812345678')` |
289
+ | `isEmail(email)` | 验证邮箱 | `isEmail('test@example.com')` |
290
+ | `isUrl(url)` | 验证 URL | `isUrl('https://example.com')` |
291
+ | `highlight(text, keyword)` | 高亮关键词 | `highlight(text, 'keyword')` |
292
+ | `getExtension(filename)` | 获取文件扩展名 | `getExtension('file.txt')` |
293
+ | `toNumber(str, default)` | 转数字 | `toNumber('123', 0)` |
294
+ | `toBoolean(str, default)` | 转布尔值 | `toBoolean('true', false)` |
295
+
296
+ ### 📦 Object Module - 对象处理
297
+
298
+ 基于 [es-toolkit](https://es-toolkit.slash.page/) 封装,提供强大的对象处理功能。
299
+
300
+ ```typescript
301
+ import {
302
+ pick,
303
+ omit,
304
+ merge,
305
+ cloneDeep,
306
+ deepMerge,
307
+ isEmpty,
308
+ isObject,
309
+ isArray,
310
+ toQueryString,
311
+ fromQueryString,
312
+ toFormData,
313
+ diff,
314
+ getDeep,
315
+ setDeep,
316
+ } from 'ly-utils-lib/object'
317
+
318
+ // 对象操作
319
+ const obj = { name: 'Alice', age: 25, city: 'Beijing' }
320
+ const picked = pick(obj, ['name', 'age']) // { name: 'Alice', age: 25 }
321
+ const omitted = omit(obj, ['city']) // { name: 'Alice', age: 25 }
322
+
323
+ // 合并对象
324
+ const merged = merge({ a: 1 }, { b: 2 }) // { a: 1, b: 2 }
325
+ const deepMerged = deepMerge({ a: { b: 1 } }, { a: { c: 2 } }) // { a: { b: 1, c: 2 } }
326
+
327
+ // 克隆
328
+ const cloned = cloneDeep(obj)
329
+
330
+ // 判断类型
331
+ const empty = isEmpty({}) // true
332
+ const isObj = isObject({}) // true
333
+ const isArr = isArray([]) // true
334
+
335
+ // 查询字符串转换
336
+ const params = { name: 'Alice', age: '25' }
337
+ const qs = toQueryString(params) // 'name=Alice&age=25'
338
+ const parsed = fromQueryString(qs) // { name: 'Alice', age: '25' }
339
+
340
+ // FormData 转换
341
+ const formData = toFormData({ name: 'Alice', age: 25 })
342
+
343
+ // 对象差值
344
+ const base = { a: 1, b: 2 }
345
+ const changed = { a: 1, b: 3 }
346
+ const diffed = diff(changed, base) // { b: 3 }
347
+
348
+ // 嵌套路径操作
349
+ const nested = { user: { name: 'Alice', age: 25 } }
350
+ const name = getDeep(nested, 'user.name') // 'Alice'
351
+ setDeep(nested, 'user.age', 26)
352
+ ```
353
+
354
+ **API 列表:**
355
+
356
+ | 函数 | 说明 | 示例 |
357
+ | ------------------------------- | ---------------- | --------------------------------- |
358
+ | `pick(obj, keys)` | 选择属性 | `pick(obj, ['a', 'b'])` |
359
+ | `omit(obj, keys)` | 排除属性 | `omit(obj, ['a'])` |
360
+ | `merge(target, ...sources)` | 浅合并 | `merge({a:1}, {b:2})` |
361
+ | `deepMerge(target, ...sources)` | 深度合并 | `deepMerge({a:{b:1}}, {a:{c:2}})` |
362
+ | `cloneDeep(obj)` | 深度克隆 | `cloneDeep(obj)` |
363
+ | `isEmpty(obj)` | 判断为空 | `isEmpty({})` |
364
+ | `isObject(obj)` | 判断对象 | `isObject({})` |
365
+ | `isArray(obj)` | 判断数组 | `isArray([])` |
366
+ | `toQueryString(obj)` | 对象转查询字符串 | `toQueryString({a:1})` |
367
+ | `fromQueryString(str)` | 查询字符串转对象 | `fromQueryString('a=1')` |
368
+ | `toFormData(obj)` | 对象转 FormData | `toFormData({a:1})` |
369
+ | `getDeep(obj, path, default)` | 获取嵌套值 | `getDeep(obj, 'a.b.c')` |
370
+ | `setDeep(obj, path, value)` | 设置嵌套值 | `setDeep(obj, 'a.b', 1)` |
371
+ | `diff(obj, base)` | 对象差值 | `diff({a:2}, {a:1})` |
372
+ | `mapValues(obj, mapper)` | 映射值 | `mapValues(obj, v => v * 2)` |
373
+ | `filter(obj, predicate)` | 过滤键值对 | `filter(obj, v => v > 0)` |
374
+
375
+ ### 📈 Excel Module - Excel 处理
376
+
377
+ 基于 [xlsx](https://sheetjs.com/) 封装,提供 Excel 导入导出功能。
378
+
379
+ ```typescript
380
+ import {
381
+ exportExcel,
382
+ exportMultiSheetExcel,
383
+ importExcel,
384
+ importAllSheetsExcel,
385
+ exportExcelWithHeaders,
386
+ getSheetNames,
387
+ } from 'ly-utils-lib/excel'
388
+
389
+ // 导出 Excel
390
+ const data = [
391
+ { name: 'Alice', age: 25, city: 'Beijing' },
392
+ { name: 'Bob', age: 30, city: 'Shanghai' },
393
+ ]
394
+
395
+ exportExcel(data, {
396
+ filename: 'export.xlsx',
397
+ sheetName: 'Users',
398
+ header: { name: '姓名', age: '年龄', city: '城市' },
399
+ })
400
+
401
+ // 导出多 Sheet Excel
402
+ exportMultiSheetExcel(
403
+ [
404
+ {
405
+ name: 'Users',
406
+ data: [{ name: 'Alice', age: 25 }],
407
+ header: { name: '姓名', age: '年龄' },
408
+ },
409
+ {
410
+ name: 'Products',
411
+ data: [{ product: 'Apple', price: 10 }],
412
+ header: { product: '产品', price: '价格' },
413
+ },
414
+ ],
415
+ 'multi-sheet.xlsx'
416
+ )
417
+
418
+ // 导入 Excel
419
+ const fileInput = document.querySelector('input[type="file"]')
420
+ const file = fileInput.files[0]
421
+ const importedData = await importExcel(file)
422
+
423
+ // 导入所有 Sheet
424
+ const allSheetsData = await importAllSheetsExcel(file)
425
+
426
+ // 获取 Sheet 列表
427
+ const sheetNames = await getSheetNames(file)
428
+
429
+ // 自定义表头导出
430
+ exportExcelWithHeaders(
431
+ [{ name: 'Alice', age: 25 }],
432
+ [
433
+ { key: 'name', label: '姓名' },
434
+ { key: 'age', label: '年龄' },
435
+ ],
436
+ 'custom.xlsx'
437
+ )
438
+ ```
439
+
440
+ **API 列表:**
441
+
442
+ | 函数 | 说明 | 示例 |
443
+ | ---------------------------------------------------- | --------------- | ------------------------------------------------------------- |
444
+ | `exportExcel(data, options)` | 导出 Excel | `exportExcel(data, {filename: 'test.xlsx'})` |
445
+ | `exportMultiSheetExcel(sheetsData, filename)` | 导出多 Sheet | `exportMultiSheetExcel([{name: 'Sheet1', data: []}])` |
446
+ | `importExcel(file, options)` | 导入 Excel | `importExcel(file)` |
447
+ | `importAllSheetsExcel(file, options)` | 导入所有 Sheet | `importAllSheetsExcel(file)` |
448
+ | `exportExcelWithHeaders(data, headers, filename)` | 自定义表头导出 | `exportExcelWithHeaders(data, headers)` |
449
+ | `getSheetNames(file)` | 获取 Sheet 列表 | `getSheetNames(file)` |
450
+ | `exportExcelWithColumnWidths(data, widths, options)` | 设置列宽导出 | `exportExcelWithColumnWidths(data, [{wch: 20}])` |
451
+ | `exportExcelWithMerges(data, merges, options)` | 合并单元格导出 | `exportExcelWithMerges(data, [{s: {r:0,c:0}, e: {r:1,c:1}}])` |
452
+
453
+ ### 📄 PDF Module - PDF 处理
454
+
455
+ 基于 [html2canvas](https://html2canvas.hertzen.com/) 和 [jspdf](https://github.com/parallax/jsPDF) 封装,提供 PDF 生成功能。
456
+
457
+ ```typescript
458
+ import {
459
+ captureToPDF,
460
+ captureToPDFWithPagination,
461
+ captureToImage,
462
+ captureToImageDownload,
463
+ createPDF,
464
+ addTextToPDF,
465
+ addImageToPDF,
466
+ savePDF,
467
+ } from 'ly-utils-lib/pdf'
468
+
469
+ // 将 DOM 元素转换为 PDF
470
+ const element = document.querySelector('.content')
471
+ await captureToPDF(element, {
472
+ filename: 'document.pdf',
473
+ scale: 2,
474
+ margin: 10,
475
+ })
476
+
477
+ // 分页导出
478
+ await captureToPDFWithPagination(element, {
479
+ filename: 'document-paged.pdf',
480
+ })
481
+
482
+ // 截取为图片
483
+ const imageData = await captureToImage(element)
484
+ await captureToImageDownload(element, 'screenshot.png')
485
+
486
+ // 手动创建 PDF
487
+ const pdf = createPDF({ orientation: 'portrait', format: 'a4' })
488
+
489
+ // 添加文本
490
+ addTextToPDF(pdf, 'Hello World', 10, 10, {
491
+ fontSize: 16,
492
+ align: 'center',
493
+ })
494
+
495
+ // 添加图片
496
+ addImageToPDF(pdf, imageData, 10, 30, 100, 100)
497
+
498
+ // 保存 PDF
499
+ savePDF(pdf, 'custom.pdf')
500
+ ```
501
+
502
+ **API 列表:**
503
+
504
+ | 函数 | 说明 | 示例 |
505
+ | ---------------------------------------------------- | -------------- | ----------------------------------------------- |
506
+ | `captureToPDF(element, options)` | DOM 转 PDF | `captureToPDF(element, {filename: 'test.pdf'})` |
507
+ | `captureToPDFWithPagination(element, options)` | 分页导出 | `captureToPDFWithPagination(element)` |
508
+ | `captureToImage(element, options)` | DOM 转图片 | `captureToImage(element)` |
509
+ | `captureToImageDownload(element, filename, options)` | DOM 转图片下载 | `captureToImageDownload(element, 'pic.png')` |
510
+ | `createPDF(options)` | 创建空白 PDF | `createPDF({format: 'a4'})` |
511
+ | `addTextToPDF(pdf, text, x, y, options)` | 添加文本 | `addTextToPDF(pdf, 'text', 10, 10)` |
512
+ | `addImageToPDF(pdf, imageData, x, y, w, h)` | 添加图片 | `addImageToPDF(pdf, data, 10, 10, 100, 100)` |
513
+ | `addTableToPDF(pdf, headers, data, options)` | 添加表格 | `addTableToPDF(pdf, ['A'], [['1']])` |
514
+ | `addPage(pdf)` | 添加新页面 | `addPage(pdf)` |
515
+ | `savePDF(pdf, filename)` | 保存 PDF | `savePDF(pdf, 'doc.pdf')` |
516
+ | `pdfToDataURL(pdf)` | PDF 转 DataURL | `pdfToDataURL(pdf)` |
517
+ | `pdfToBlob(pdf)` | PDF 转 Blob | `pdfToBlob(pdf)` |
518
+
519
+ ### 🗺️ Map Module - 地图处理
520
+
521
+ 基于 [OpenLayers](https://openlayers.org/) 封装,提供强大的地图操作功能。
522
+
523
+ ```typescript
524
+ import {
525
+ MapInstance,
526
+ createOSMLayer,
527
+ createGaodeLayer,
528
+ createTiandituLayer,
529
+ lonLatToXY,
530
+ xyToLonLat,
531
+ } from 'ly-utils-lib/map'
532
+
533
+ // 创建地图
534
+ const map = new MapInstance({
535
+ container: 'map-container',
536
+ center: [116.3974, 39.9093], // 北京
537
+ zoom: 10,
538
+ showScaleLine: true,
539
+ showFullScreen: true,
540
+ })
541
+
542
+ // 添加 OSM 图层
543
+ const osmLayer = createOSMLayer()
544
+ map.addLayer(osmLayer)
545
+
546
+ // 添加高德地图图层
547
+ const gaodeLayer = createGaodeLayer()
548
+ map.addLayer(gaodeLayer)
549
+
550
+ // 添加天地图图层(需要 token)
551
+ const tiandituLayer = createTiandituLayer('your-token', 'vec')
552
+ map.addLayer(tiandituLayer)
553
+
554
+ // 添加标记
555
+ const marker = map.addMarker({
556
+ coordinate: [116.3974, 39.9093],
557
+ color: '#ff3333',
558
+ radius: 8,
559
+ })
560
+
561
+ // 移除标记
562
+ map.removeMarker(marker)
563
+
564
+ // 设置中心点和缩放
565
+ map.setCenter([121.4737, 31.2304]) // 上海
566
+ map.setZoom(12)
567
+
568
+ // 获取中心点
569
+ const center = map.getCenter() // [121.4737, 31.2304]
570
+
571
+ // 获取缩放级别
572
+ const zoom = map.getZoom() // 12
573
+
574
+ // 缩放到指定范围
575
+ map.fit([1000000, 6000000, 2000000, 7000000])
576
+
577
+ // 绘制点
578
+ map.startDraw({
579
+ type: 'Point',
580
+ onDrawEnd: feature => {
581
+ console.log('绘制完成', feature)
582
+ },
583
+ })
584
+
585
+ // 绘制线
586
+ map.startDraw({
587
+ type: 'LineString',
588
+ onDrawEnd: feature => {
589
+ console.log('绘制完成', feature)
590
+ },
591
+ })
592
+
593
+ // 绘制面
594
+ map.startDraw({
595
+ type: 'Polygon',
596
+ onDrawEnd: feature => {
597
+ console.log('绘制完成', feature)
598
+ },
599
+ })
600
+
601
+ // 停止绘制
602
+ map.stopDraw()
603
+
604
+ // 开始编辑
605
+ map.startModify()
606
+
607
+ // 停止编辑
608
+ map.stopModify()
609
+
610
+ // 选择要素
611
+ map.startSelect(features => {
612
+ console.log('选中的要素:', features)
613
+ })
614
+
615
+ // 停止选择
616
+ map.stopSelect()
617
+
618
+ // 获取所有要素
619
+ const features = map.getFeatures()
620
+
621
+ // 清除所有矢量要素
622
+ map.clearFeatures()
623
+
624
+ // 事件监听
625
+ map.on('click', evt => {
626
+ console.log('点击位置:', evt.coordinate)
627
+ })
628
+
629
+ map.on('moveend', () => {
630
+ console.log('地图移动结束', map.getCenter())
631
+ })
632
+
633
+ // 更新地图大小(容器大小改变时)
634
+ map.updateSize()
635
+
636
+ // 销毁地图
637
+ map.destroy()
638
+ ```
639
+
640
+ **API 列表:**
641
+
642
+ | 类/函数 | 说明 | 示例 |
643
+ | ---------------------------------------- | -------------- | ----------------------------------------- |
644
+ | `new MapInstance(options)` | 创建地图实例 | `new MapInstance({container: 'map'})` |
645
+ | `map.setCenter(coord)` | 设置中心点 | `map.setCenter([116.39, 39.90])` |
646
+ | `map.getCenter()` | 获取中心点 | `map.getCenter()` |
647
+ | `map.setZoom(zoom)` | 设置缩放级别 | `map.setZoom(10)` |
648
+ | `map.getZoom()` | 获取缩放级别 | `map.getZoom()` |
649
+ | `map.fit(extent)` | 缩放到范围 | `map.fit([minX, minY, maxX, maxY])` |
650
+ | `map.addLayer(layer)` | 添加图层 | `map.addLayer(createOSMLayer())` |
651
+ | `map.removeLayer(layer)` | 移除图层 | `map.removeLayer(layer)` |
652
+ | `map.addMarker(options)` | 添加标记 | `map.addMarker({coordinate: [lon, lat]})` |
653
+ | `map.removeMarker(feature)` | 移除标记 | `map.removeMarker(marker)` |
654
+ | `map.clearFeatures()` | 清除所有要素 | `map.clearFeatures()` |
655
+ | `map.startDraw(options)` | 开始绘制 | `map.startDraw({type: 'Point'})` |
656
+ | `map.stopDraw()` | 停止绘制 | `map.stopDraw()` |
657
+ | `map.startModify()` | 开始编辑 | `map.startModify()` |
658
+ | `map.stopModify()` | 停止编辑 | `map.stopModify()` |
659
+ | `map.startSelect(callback)` | 开始选择 | `map.startSelect((f) => console.log(f))` |
660
+ | `map.stopSelect()` | 停止选择 | `map.stopSelect()` |
661
+ | `map.getFeatures()` | 获取所有要素 | `map.getFeatures()` |
662
+ | `map.getSelectedFeatures()` | 获取选中要素 | `map.getSelectedFeatures()` |
663
+ | `map.on(event, callback)` | 事件监听 | `map.on('click', (e) => {})` |
664
+ | `map.off(event, callback)` | 移除监听 | `map.off('click', callback)` |
665
+ | `map.updateSize()` | 更新地图大小 | `map.updateSize()` |
666
+ | `map.destroy()` | 销毁地图 | `map.destroy()` |
667
+ | `createOSMLayer(name)` | 创建 OSM 图层 | `createOSMLayer('OSM')` |
668
+ | `createXYZLayer(url, name)` | 创建 XYZ 图层 | `createXYZLayer(url, 'Custom')` |
669
+ | `createGaodeLayer(name)` | 创建高德图层 | `createGaodeLayer('高德')` |
670
+ | `createTiandituLayer(token, type, name)` | 创建天地图图层 | `createTiandituLayer('token', 'vec')` |
671
+ | `createVectorLayer(name)` | 创建矢量图层 | `createVectorLayer('Vector')` |
672
+ | `lonLatToXY(lon, lat)` | 经纬度转投影 | `lonLatToXY(116.39, 39.90)` |
673
+ | `xyToLonLat(x, y)` | 投影转经纬度 | `xyToLonLat(x, y)` |
674
+
675
+ ### 💾 Storage Module - 存储处理
676
+
677
+ 基于浏览器 Web Storage API 和 Cookie(使用 [js-cookie](https://github.com/js-cookie/js-cookie) 封装),提供统一的存储操作功能。
678
+
679
+ ```typescript
680
+ import {
681
+ setLocal,
682
+ getLocal,
683
+ removeLocal,
684
+ clearLocal,
685
+ setSession,
686
+ getSession,
687
+ setCookie,
688
+ getCookie,
689
+ removeCookie,
690
+ getAllCookies,
691
+ hasCookie,
692
+ setCookieJSON,
693
+ getCookieJSON,
694
+ getCookieSize,
695
+ setStorage,
696
+ getStorage,
697
+ removeStorage,
698
+ } from 'ly-utils-lib/storage'
699
+
700
+ // LocalStorage 操作
701
+ setLocal('user', { name: 'Alice', age: 25 })
702
+ const user = getLocal<{ name: string; age: number }>('user')
703
+ console.log(user?.name) // 'Alice'
704
+
705
+ // 带过期时间的存储
706
+ setLocal('token', 'abc123', { ttl: 3600000 }) // 1小时后过期
707
+ const token = getLocal('token')
708
+
709
+ // SessionStorage 操作
710
+ setSession('temp', { data: [1, 2, 3] })
711
+ const temp = getSession('temp')
712
+
713
+ // Cookie 操作(支持对象类型)
714
+ setCookie('token', 'abc123', { days: 7, secure: true })
715
+ setCookie('user', { name: 'Alice', age: 25 }, { days: 30 }) // 自动序列化对象
716
+ const cookieToken = getCookie('token')
717
+
718
+ // JSON 格式 Cookie
719
+ setCookieJSON('config', { theme: 'dark', lang: 'zh-CN' }, { days: 7 })
720
+ const config = getCookieJSON<{ theme: string; lang: string }>('config')
721
+
722
+ // Cookie 工具函数
723
+ if (hasCookie('token')) {
724
+ console.log('Token exists')
725
+ }
726
+ const cookieSize = getCookieSize() // 获取 Cookie 数量
727
+ const allCookies = getAllCookies() // 获取所有 Cookie
728
+
729
+ // 统一接口
730
+ setStorage('local', 'user', { name: 'Alice' })
731
+ setStorage('cookie', 'token', 'abc123', { days: 7 })
732
+ const user = getStorage<{ name: string }>('local', 'user')
733
+ const token = getStorage('cookie', 'token')
734
+
735
+ // 清除操作
736
+ removeLocal('user')
737
+ removeCookie('token')
738
+ clearStorage('local')
739
+ ```
740
+
741
+ **API 列表:**
742
+
743
+ #### LocalStorage
744
+
745
+ | 类/函数 | 说明 | 示例 |
746
+ | --------------------------------- | --------------- | -------------------------------------- |
747
+ | `setLocal(key, value, options)` | 设置永久缓存 | `setLocal('user', {name: 'Alice'})` |
748
+ | `getLocal<T>(key)` | 获取永久缓存 | `getLocal<User>('user')` |
749
+ | `removeLocal(key)` | 移除永久缓存 | `removeLocal('user')` |
750
+ | `clearLocal()` | 清除永久缓存 | `clearLocal()` |
751
+ | `getLocalKeys()` | 获取所有键 | `getLocalKeys()` |
752
+ | `getLocalSize()` | 获取键数量 | `getLocalSize()` |
753
+
754
+ #### SessionStorage
755
+
756
+ | 类/函数 | 说明 | 示例 |
757
+ | --------------------------------- | --------------- | -------------------------------------- |
758
+ | `setSession(key, value, options)` | 设置临时缓存 | `setSession('temp', {data: [1,2,3]})` |
759
+ | `getSession<T>(key)` | 获取临时缓存 | `getSession<Data>('temp')` |
760
+ | `removeSession(key)` | 移除临时缓存 | `removeSession('temp')` |
761
+ | `clearSession()` | 清除临时缓存 | `clearSession()` |
762
+ | `getSessionKeys()` | 获取所有键 | `getSessionKeys()` |
763
+ | `getSessionSize()` | 获取键数量 | `getSessionSize()` |
764
+
765
+ #### Cookie (基于 js-cookie)
766
+
767
+ | 类/函数 | 说明 | 示例 |
768
+ | --------------------------------- | --------------- | -------------------------------------- |
769
+ | `setCookie(key, value, options)` | 设置 Cookie | `setCookie('token', 'abc', {days: 7})` |
770
+ | `getCookie(key)` | 获取 Cookie | `getCookie('token')` |
771
+ | `removeCookie(key, options)` | 移除 Cookie | `removeCookie('token', {path: '/'})` |
772
+ | `getAllCookies()` | 获取所有 Cookie | `getAllCookies()` |
773
+ | `hasCookie(key)` | 检查 Cookie 是否存在 | `hasCookie('token')` |
774
+ | `getCookieJSON<T>(key)` | 获取 JSON 格式 Cookie | `getCookieJSON<User>('user')` |
775
+ | `setCookieJSON(key, value, options)` | 设置 JSON 格式 Cookie | `setCookieJSON('config', {}, {days: 7})` |
776
+ | `getCookieSize()` | 获取 Cookie 数量 | `getCookieSize()` |
777
+
778
+ #### 统一接口
779
+
780
+ | 类/函数 | 说明 | 示例 |
781
+ | --------------------------------- | --------------- | -------------------------------------- |
782
+ | `setStorage(type, key, value)` | 统一设置存储 | `setStorage('local', 'user', {})` |
783
+ | `getStorage<T>(type, key)` | 统一获取存储 | `getStorage('local', 'user')` |
784
+ | `removeStorage(type, key)` | 统一移除存储 | `removeStorage('local', 'user')` |
785
+ | `clearStorage(type)` | 统一清除存储 | `clearStorage('local')` |
786
+
787
+ ## Demo
788
+
789
+ ### 在线演示
790
+
791
+ 查看完整功能的在线演示:
792
+
793
+ - **完整 Demo**: [demo/index.html](demo/index.html) - 包含所有 7 个模块的完整演示
794
+ - **地图 Demo**: [demo/map.html](demo/map.html) - 专门展示地图模块功能
795
+
796
+ ### 本地运行
797
+
798
+ ```bash
799
+ # 克隆项目
800
+ git clone https://gitee.com/liyang517/ai-utils.git
801
+ cd ai-utils
802
+
803
+ # 安装依赖
804
+ pnpm install
805
+
806
+ # 构建项目
807
+ pnpm build
808
+
809
+ # 启动开发服务器
810
+ pnpm dev
811
+ ```
49
812
 
50
- 例:startDate('day', 'HH:mm')
813
+ 然后在浏览器中打开:
814
+
815
+ - 完整 Demo: `http://localhost:5000/demo/`
816
+ - 地图 Demo: `http://localhost:5000/demo/map.html`
51
817
 
52
- ## 结束时间函数 endDate
818
+ ### Demo 功能
53
819
 
54
- /\*\*
820
+ **完整 Demo** 包含以下功能:
55
821
 
56
- - 结束时间函数
57
- - @param {string} type - 类型 'date' | 'day' | 'month' | 'quarter' | 'year' | 'week' | 'isoWeek' | 'hour' | 'minute' | 'second' | 'millisecond'
58
- - @param {string} format - 格式模板
59
- - @returns {string} 格式化后的日期字符串
60
- \*/
822
+ - 📋 **概览** - 项目介绍和快速开始
823
+ - 📅 **日期模块** - 日期格式化、计算、范围查询
824
+ - 📊 **数组模块** - 去重、统计、排序、转换
825
+ - 📝 **字符串模块** - 转换、ID 生成、验证、格式化
826
+ - 📦 **对象模块** - 操作、合并、查询、深度操作
827
+ - 📈 **Excel 模块** - 导入导出、多 Sheet 支持
828
+ - 📄 **PDF 模块** - DOM 转 PDF、自定义 PDF、截图
829
+ - 🗺️ **地图模块** - 创建地图、图层切换、绘制、编辑、选择
61
830
 
62
- endDate(type: ManipulateType | undefined = 'month', format: string = 'YYYY-MM-DD')
831
+ **地图 Demo** 专门展示地图功能:
63
832
 
64
- 例:endDate('day', 'HH:mm')
833
+ - 多城市快速定位
834
+ - OSM 和高德图层切换
835
+ - 标记管理(添加、删除)
836
+ - 绘制功能(点、线、面、圆形)
837
+ - 编辑和选择功能
838
+ - 实时状态显示
65
839
 
66
- ## 获取时间戳函数 getTimeStamp
840
+ ## 开发
67
841
 
68
- /\*\*
842
+ ```bash
843
+ # 安装依赖
844
+ pnpm install
69
845
 
70
- - 获取时间戳函数
71
- - @param {Date | string} date - 日期
72
- - @returns {number} 时间戳
73
- \*/
846
+ # 构建
847
+ pnpm build
74
848
 
75
- getTimeStamp(date: Date | string = new Date())
849
+ # 开发模式
850
+ pnpm dev
76
851
 
77
- 例:getTimeStamp('2025-12-31')
852
+ # 代码检查
853
+ pnpm lint
854
+ pnpm lint:fix
78
855
 
79
- ## 时间戳格式化函数 formatTimeStamp
856
+ # 代码格式化
857
+ pnpm format
858
+ ```
80
859
 
81
- /\*\*
860
+ ## 目录结构
82
861
 
83
- - 时间戳格式化函数
84
- - @param {number} timeStamp - 时间戳
85
- - @param {string} format - 格式模板
86
- - @returns {string} 格式化后的日期字符串
87
- \*\*/
862
+ ```
863
+ utils-toolkit/
864
+ ├── src/
865
+ │ ├── index.ts # 主入口
866
+ │ └── modules/
867
+ │ ├── date/ # 日期模块
868
+ │ ├── array/ # 数组模块
869
+ │ ├── string/ # 字符串模块
870
+ │ ├── object/ # 对象模块
871
+ │ ├── excel/ # Excel 模块
872
+ │ └── pdf/ # PDF 模块
873
+ ├── demo/ # 示例
874
+ │ └── index.html
875
+ ├── dist/ # 构建输出
876
+ ├── package.json
877
+ ├── tsconfig.json
878
+ ├── tsup.config.ts
879
+ └── README.md
880
+ ```
88
881
 
89
- formatTimeStamp(timeStamp: number = 0, format: string = 'YYYY-MM-DD HH:mm:ss')
882
+ ## 贡献
90
883
 
91
- 例:formatTimeStamp(1767110400, 'YYYY-MM-DD')
884
+ 欢迎贡献代码!请先阅读 [贡献指南](docs/guides/contributing.md)
92
885
 
93
- ## 获取两个日期时间之间的差异函数 getDateDiff
886
+ ---
94
887
 
95
- /\*\*
888
+ ## 许可证
96
889
 
97
- - 获取两个日期时间之间的差异函数
98
- - @param {string} type - 类型 'week' | 'day' | 'month' | 'quarter' | 'year' | 'hour' | 'minute' | 'second' | 'millisecond'
99
- - @param {Date | string} startDate - 起始时间
100
- - @param {Date | string} endDate - 结束时间
101
- - @returns {number} 差异值
102
- \*/
890
+ MIT License
103
891
 
104
- getDateDiff(type: OpUnitType = 'day', startDate: Date | string, endDate: Date | string = new Date())
892
+ ## 版本历史
105
893
 
106
- 例: getDateDiff('day', '2025-12-01', '2025-12-10')
894
+ ### v0.2.0 (最新)
107
895
 
108
- ## 获取一段范围内日期函数 getRangeDate
896
+ - 🗺️ 新增 Map 模块,基于 OpenLayers 10.8.0
897
+ - ✨ 支持创建地图、添加图层、标记管理
898
+ - ✨ 支持绘制功能(点、线、面、圆形)
899
+ - ✨ 支持编辑和选择要素
900
+ - ✨ 支持 OSM、高德、天地图等多种图层
901
+ - ✨ 提供完整的类型定义和 API 文档
902
+ - 📝 新增 Map 模块示例页面
109
903
 
110
- /\*\*
904
+ ### v0.1.0
111
905
 
112
- - 获取一段范围内日期函数
113
- - @param {Date | string} startDate - 起始时间
114
- - @param {Date | string} endDate - 结束时间
115
- - @returns {array} 日期集合
116
- \*/
906
+ - 🎉 初始版本发布
907
+ - 实现六大核心模块
908
+ - 支持 ESM CJS 双格式
117
909
 
118
- getRangeDate(startDate: Date | string, endDate: Date | string): Array<any>
910
+ ## 链接
119
911
 
120
- 例: getRangeDate('2025-12-01', '2025-12-10')
912
+ - [npm](https://www.npmjs.com/package/ly-utils-lib)
913
+ - [GitHub](https://github.com/your-org/utils-toolkit)
914
+ - [Issues](https://github.com/your-org/utils-toolkit/issues)
915
+ - [升级说明](./docs/guides/upgrade.md)
121
916
 
122
- ## 获取相对时间函数 getRelativeTime
917
+ ## 📚 文档
123
918
 
124
- /\*\*
919
+ - [项目结构](./docs/PROJECT_STRUCTURE.md) - 项目目录结构说明
920
+ - [快速开始](./docs/guides/quick-start.md) - 快速上手指南
921
+ - [最佳实践](./docs/guides/best-practices.md) - 使用最佳实践
922
+ - [自动发布](./docs/guides/auto-publish.md) - 自动发布指南
923
+ - [发布指南](./docs/guides/publish-guide.md) - 发布流程说明
924
+ - [提交规范](./docs/guides/commit-convention.md) - Commit 规范
925
+ - [变更日志](./docs/changelog.md) - 版本变更历史
125
926
 
126
- - 获取相对时间函数
127
- - @param {Date | string} date - 日期
128
- - @returns {string} 相对时间描述
129
- \*/
927
+ ## 致谢
130
928
 
131
- getRelativeTime(date: Date | string)
929
+ - [dayjs](https://day.js.org/) - 轻量级日期处理库
930
+ - [es-toolkit](https://es-toolkit.slash.page/) - 现代工具库
931
+ - [xlsx](https://sheetjs.com/) - Excel 处理库
932
+ - [html2canvas](https://html2canvas.hertzen.com/) - 截图库
933
+ - [jspdf](https://github.com/parallax/jsPDF) - PDF 生成库
132
934
 
133
- 例: getRelativeTime('2025-12-10')
935
+ ---
134
936
 
135
- # 缓存函数
136
-
137
- ## 设置永久缓存 setLocal
138
-
139
- /\*\*
140
-
141
- - 设置永久缓存
142
- - @param {string} key - 缓存名称
143
- - @param {string | number | object | Array<any>} value - 缓存内容
144
- \*/
145
-
146
- setLocal(key: string, value: string | number | object | Array<any>)
147
-
148
- 例: setLocal('key', '1234')
149
-
150
- ## 获取永久缓存 getLocal
151
-
152
- /\*\*
153
-
154
- - 获取永久缓存
155
- - @param {string} key - 缓存名称
156
- - @returns {string} 格式化后的value
157
- \*/
158
-
159
- getLocal(key: string)
160
-
161
- 例: getLocal('key')
162
-
163
- ## 移除永久缓存 removeLocal
164
-
165
- /\*\*
166
-
167
- - 移除永久缓存
168
- - @param {string} key - 缓存名称
169
- \*/
170
-
171
- removeLocal(key: string)
172
-
173
- 例: removeLocal('key')
174
-
175
- ## 移除全部永久缓存 clearLocal
176
-
177
- clearLocal()
178
-
179
- 例: clearLocal()
180
-
181
- ## 设置临时缓存 setSession
182
-
183
- /\*\*
184
-
185
- - 设置永久缓存
186
- - @param {string} key - 缓存名称
187
- - @param {string | number | object | Array<any>} value - 缓存内容
188
- \*/
189
-
190
- setSession(key: string, value: string | number | object | Array<any>)
191
-
192
- 例: setSession('key', '1234')
193
-
194
- ## 获取永久缓存 getSession
195
-
196
- /\*\*
197
-
198
- - 获取临时缓存
199
- - @param {string} key - 缓存名称
200
- - @returns {string} 格式化后的value
201
- \*/
202
-
203
- getSession(key: string)
204
-
205
- 例: getSession('key')
206
-
207
- ## 移除永久缓存 removeSession
208
-
209
- /\*\*
210
-
211
- - 移除临时缓存
212
- - @param {string} key - 缓存名称
213
- \*/
214
-
215
- removeSession(key: string)
216
-
217
- 例: removeSession('key')
218
-
219
- ## 移除全部临时缓存 clearSession
220
-
221
- clearSession()
222
-
223
- 例: clearSession()
224
-
225
- # 工具函数
226
-
227
- ## 生成UUID createUUID
228
-
229
- createUUID()
230
-
231
- 例: createUUID()
232
-
233
- ## 导出xlsx文件 exportExcel
234
-
235
- /\*\*
236
-
237
- - 导出xlsx文件
238
- - @param {string} name - 文件名称
239
- - @param {any} title - xlsx表头
240
- - @param {any} data - xlsx数据
241
- - @param {any} cols - xlsx宽度
242
- - @param {any} sheetName - xlsx页签名称
243
- - @returns {Promise<unknown>} 导出是否成功
244
- \*/
245
-
246
- exportExcel(name: string, title: any, data: any, cols: any, sheetName: any = {})
247
-
248
- 例: exportExcel('1111', { id: 'ID' }, [[{ id: 10 }, { id: 11 }]], [{ width: 20 }], ['111'])
249
-
250
- ## 导入xlsx文件 importExcel
251
-
252
- /\*\*
253
-
254
- - 导入xlsx文件
255
- - @param {string} file - xlsx文件
256
- - @returns {Promise<any>} xlsx表格数据
257
- \*/
258
-
259
- importExcel(file: any)
260
-
261
- 例: importExcel(xlsx文件)
262
-
263
- ## 导出xlsx文件 exportPdf
264
-
265
- /\*\*
266
-
267
- - 导出pdf文件
268
- - @param {string} name - 文件名称
269
- - @param {any} dom - 页面dom
270
- - @param {any} type - 是否直接导出
271
- - @returns {Promise<unknown>} 不直接导出返回base64文件
272
- \*/
273
-
274
- exportPdf(name: string, dom: any, type: boolean = true)
275
-
276
- 例: exportPdf('aa.pdf', document.getElementById('aaa'))
277
-
278
- ## 生成图片文件 importImage
279
-
280
- /\*\*
281
-
282
- - 生成图片文件
283
- - @param {any} dom - 页面dom
284
- - @param {string} type - 图片格式
285
- - @returns {Promise<unknown>} base64文件
286
- \*/
287
-
288
- importImage(dom: any, type: string = 'image/jpeg')
289
-
290
- 例: await importImage(document.getElementById('aaa'))
291
-
292
- ## hex 颜色转 rgb 颜色 hexToRgb
293
-
294
- /\*\*
295
-
296
- - hex 颜色转 rgb 颜色
297
- - @param {string} str - hex 颜色
298
- - @returns {string} rgb 颜色
299
- \*/
300
-
301
- hexToRgb(str: string)
302
-
303
- 例: hexToRgb('#ff0000')
304
-
305
- ## rgb 颜色转 Hex 颜色 rgbToHex
306
-
307
- /\*\*
308
-
309
- - rgb 颜色转 Hex 颜色
310
- - @param {number} r - r 颜色
311
- - @param {number} g - g 颜色
312
- - @param {number} b - b 颜色
313
- - @returns {string} hex 颜色
314
- \*/
315
-
316
- rgbToHex(r: number, g: number, b: number)
317
-
318
- 例: rgbToHex(255, 0, 0)
319
-
320
- ## hex 颜色变浅颜色值 getLightColor
321
-
322
- /\*\*
323
-
324
- - hex 颜色变浅颜色值
325
- - @param {string} color - hex 颜色
326
- - @param {number} alpha - 透明度
327
- - @returns {string} hex 颜色
328
- \*/
329
-
330
- getLightColor(color: string, alpha: number)
331
-
332
- 例: getLightColor('#ff0000', 0.1)
333
-
334
- ## hex 颜色变深颜色值 getDarkColor
335
-
336
- /\*\*
337
-
338
- - hex 颜色变深颜色值
339
- - @param {string} color - hex 颜色
340
- - @param {number} alpha - 透明度
341
- - @returns {string} hex 颜色
342
- \*/
343
-
344
- getDarkColor(color: string, alpha: number)
345
-
346
- 例: getDarkColor('#ff0000', 0.1)
347
-
348
- ## 图片转base64 imgToBase64
349
-
350
- /\*\*
351
-
352
- - 图片转base64
353
- - @param {string} url - 图片路径
354
- - @returns {Promise<string>} base64图片内容
355
- \*/
356
-
357
- imgToBase64(url: string)
358
-
359
- 例: await imgToBase64(new URL(`./file1.png`, import.meta.url).href)
360
-
361
- ## base64转文件 base64toFile
362
-
363
- /\*\*
364
-
365
- - base64转文件
366
- - @param {string} url - base64文件
367
- - @param {string} fileName - 文件名称
368
- - @returns {File} 文件
369
- \*/
370
-
371
- base64toFile(url: string, fileName: string)
372
-
373
- 例: base64toFile('base64', 'aa.jpg')
374
-
375
- ## base64转文件 downloadFile
376
-
377
- /\*\*
378
-
379
- - 下载文件
380
- - @param {string} url - 文件路径
381
- - @param {string} fileName - 文件名称
382
- \*/
383
-
384
- downloadFile(url: string, fileName: string)
385
-
386
- 例: downloadFile('url', 'aa.jpg')
387
-
388
- # 地图函数(openLayers)
389
-
390
- ## 创建地图 createMap
391
-
392
- /\*\*
393
-
394
- - 创建地图
395
- - @param {string} container - dom
396
- - @param {string} center - 中心点左边
397
- - @param {number} zoom - 层级
398
- - @param {number} minZoom - 最小层级
399
- - @param {number} maxZoom - 最大层级
400
- - @returns {any} 地图实例
401
- \*/
402
-
403
- createMap(container: string, center: [number, number] = [0, 0], zoom: number = 14, minZoom: number = 3, maxZoom: number = 18)
404
-
405
- 例: createMap()
406
-
407
- ## 创建瓦片图层 createTileLayer
408
-
409
- /\*\*
410
-
411
- - 创建瓦片图层
412
- - @param {string} url - 瓦片路径
413
- - @returns {any} 图层实例
414
- \*/
415
-
416
- createTileLayer(url: string)
417
-
418
- 例: createTileLayer()
419
-
420
- ## 添加图层 addLayer
421
-
422
- /\*\*
423
-
424
- - 添加图层
425
- - @param {any} map - 地图实例
426
- - @param {any} layer -图层实例
427
- \*/
428
-
429
- addLayer(map: any, layer: any)
430
-
431
- 例: addLayer(map, layer)
432
-
433
- ## 显示/隐藏图层 setLayerVisible
434
-
435
- /\*\*
436
-
437
- - 显示/隐藏图层
438
- - @param {any} layer -图层实例
439
- - @param {boolean} type - 显示/隐藏
440
- \*/
441
-
442
- setLayerVisible(layer: any, type: boolean)
443
-
444
- 例: setLayerVisible(layer, true)
445
-
446
- ## 设置层级 setZoom
447
-
448
- /\*\*
449
-
450
- - 设置层级
451
- - @param {any} map - 地图实例
452
- - @param {number} zoom - 层级
453
- \*/
454
-
455
- setZoom(map: any, zoom: number)
456
-
457
- 例: setZoom(map, 11)
458
-
459
- ## 获取层级 getZoom
460
-
461
- /\*\*
462
-
463
- - 获取层级
464
- - @param {any} map - 地图实例
465
- - @returns {number} 图层层级
466
- \*/
467
-
468
- getZoom(map: any)
469
-
470
- 例: getZoom(map, 11)
471
-
472
- ## 设置中心点 setCenter
473
-
474
- /\*\*
475
-
476
- - 设置中心点
477
- - @param {any} map - 地图实例
478
- - @param {any} point - 中心点坐标
479
- \*/
480
-
481
- setCenter(map: any, point: [number, number])
482
-
483
- 例: setCenter(map)
484
-
485
- ## 设置区域中心 setAreaCenter
486
-
487
- /\*\*
488
-
489
- - 设置区域中心
490
- - @param {any} map - 地图实例
491
- - @param {any} point - 中心区域坐标
492
- \*/
493
-
494
- setAreaCenter(map: any, point: any)
495
-
496
- 例: setAreaCenter(map, point)
497
-
498
- ## 设置图层中心 setLayerCenter
499
-
500
- /\*\*
501
-
502
- - 设置图层中心
503
- - @param {any} map - 地图实例
504
- - @param {any} layer - 图层实例
505
- \*/
506
-
507
- setLayerCenter(map: any, layer: any)
508
-
509
- 例: setLayerCenter(map, layer)
510
-
511
- ## 创建图层 createVectorLayer
512
-
513
- /\*\*
514
-
515
- - 创建图层
516
- - @param {number} minZoom - 最小层级
517
- - @param {number} maxZoom - 最大层级
518
- - @param {number} zIndex - 层级
519
- - @returns {any} 矢量图层实例
520
- \*/
521
-
522
- createVectorLayer(minZoom: number = 1, maxZoom: number = 18, zIndex: number = 4)
523
-
524
- 例: createVectorLayer(minZoom, maxZoom, zIndex)
525
-
526
- ## 清空图层资源 clearLayer
527
-
528
- /\*\*
529
-
530
- - 清空图层资源
531
- - @param {number} layer - 图层
532
- \*/
533
-
534
- clearLayer(layer:any)
535
-
536
- 例: clearLayer()
537
-
538
- ## 获取图层元素 getLayerFeature
539
-
540
- /\*\*
541
-
542
- - 获取图层元素
543
- - @param {number} layer - 图层
544
- - @returns {any} 矢量图层元素
545
- \*/
546
-
547
- getLayerFeature(layer:any)
548
-
549
- 例: getLayerFeature()
550
-
551
- ## 创建图层资源 createSource
552
-
553
- /\*\*
554
-
555
- - 创建图层资源
556
- - @returns {any} 图层资源实例
557
- \*/
558
-
559
- createSource()
560
-
561
- 例: createSource()
562
-
563
- ## 设置图层资源 setSource
564
-
565
- /\*\*
566
-
567
- - 设置图层资源
568
- - @param {number} layer - 图层
569
- - @param {number} source - 图层资源
570
- \*/
571
-
572
- setSource(layer: any, source: any)
573
-
574
- 例: setSource()
575
-
576
- ## 创建元素 createFeature
577
-
578
- /\*\*
579
-
580
- - 创建元素
581
- - @param {string} type - 类型 'Point' | 'LineString' | 'Polygon'
582
- - @param {any} data - 数据
583
- - @returns {any} 元素实例
584
- \*/
585
-
586
- createFeature(type: string, data: any)
587
-
588
- 例: createFeature()
589
-
590
- ## 添加元素 addFeature
591
-
592
- /\*\*
593
-
594
- - 添加元素
595
- - @param {any} layer - 图层
596
- - @param {any} feature - 元素
597
- \*/
598
-
599
- addFeature(layer: string, feature: any)
600
-
601
- 例: addFeature()
602
-
603
- ## 删除元素 delFeature
604
-
605
- /\*\*
606
-
607
- - 删除元素
608
- - @param {any} layer - 图层
609
- - @param {any} feature - 元素
610
- \*/
611
-
612
- delFeature(layer: string, feature: any)
613
-
614
- 例: delFeature()
615
-
616
- ## 设置元素样式 setFeatureStyle
617
-
618
- /\*\*
619
-
620
- - 设置元素样式
621
- - @param {string} type - 元素类型 'Point' | 'LineString' | 'Polygon'
622
- - @param {any} feature - 元素
623
- - @param {any} style - 样式
624
- \*/
625
-
626
- setFeatureStyle(type: string, feature: any, style: any)
627
-
628
- 例: setFeatureStyle()
629
-
630
- ## 创建绘制交互 createDraw
631
-
632
- /\*\*
633
-
634
- - 创建绘制交互
635
- - @param {any} map - 地图实例
636
- - @param {string} type - 元素类型 'Point' | 'LineString' | 'Polygon'
637
- - @returns {any} 绘制实例
638
- \*/
639
-
640
- createDraw(map: any, type: any)
641
-
642
- 例: createDraw()
643
-
644
- ## 删除绘制交互 clearDraw
645
-
646
- /\*\*
647
-
648
- - 删除绘制交互
649
- - @param {any} map - 地图实例
650
- - @param {any} draw - 绘制实例
651
- \*/
652
-
653
- clearDraw(map: any, draw: any)
654
-
655
- 例: clearDraw()
656
-
657
- ## 创建选择交互 createModify
658
-
659
- /\*\*
660
-
661
- - 创建修改交互
662
- - @param {any} map - 地图实例
663
- - @param {any} feature - 元素
664
- - @returns {any} 修改实例
665
- \*/
666
-
667
- createModify(map: any, feature: any)
668
-
669
- 例: createModify()
670
-
671
- ## 删除修改交互 clearModify
672
-
673
- /\*\*
674
-
675
- - 删除修改交互
676
- - @param {any} map - 地图实例
677
- - @param {any} modify - 修改实例
678
- \*/
679
-
680
- clearModify(map: any, modify: any)
681
-
682
- 例: clearModify()
683
-
684
- ## 创建选择交互 createSelect
685
-
686
- /\*\*
687
-
688
- - 创建选择交互
689
- - @param {any} map - 地图实例
690
- - @returns {any} 选择实例
691
- \*/
692
-
693
- createSelect(map: any)
694
-
695
- 例: createSelect()
696
-
697
- ## 创建选择交互 clearSelect
698
-
699
- /\*\*
700
-
701
- - 删除选择交互
702
- - @param {any} map - 地图实例
703
- - @param {any} select - 选择实例
704
- \*/
705
-
706
- clearSelect(map: any, select: any)
707
-
708
- 例: clearSelect()
709
-
710
- ## 创建弹框交互 createOverlay
711
-
712
- /\*\*
713
-
714
- - 创建弹框交互
715
- - @param {any} map - 地图实例
716
- - @param {any} container - 容器
717
- - @returns {any} 弹框实例
718
- \*/
719
-
720
- createOverlay(map: any, container: any)
721
-
722
- 例: createOverlay()
723
-
724
- ## 创建弹框交互 hiddenOverlay
725
-
726
- /\*\*
727
-
728
- - 隐藏弹框交互
729
- - @param {any} overlay - 弹框实例
730
- \*/
731
-
732
- hiddenOverlay(overlay: any)
733
-
734
- 例: hiddenOverlay()
937
+ Made with ❤️ by Your Team