11
22# ui-utils-kit
33
4- ui-utils-kit 是一个高效的偏业务前端工具函数库 。
4+ ** ui-utils-kit** 是一个偏业务的前端工具函数库 。
55
66[ ![ GitHub Stars] ( https://img.shields.io/github/stars/OFreshman/ui-utils-kit?style=flat&colorA=080f12&colorB=1fa669&logo=GitHub )] ( https://github.com/OFreshman/ui-utils-kit )
77[ ![ NPM Version] ( https://img.shields.io/npm/v/ui-utils-kit?style=flat&colorA=080f12&colorB=1fa669 )] ( https://npmjs.com/package/ui-utils-kit )
@@ -11,12 +11,16 @@ ui-utils-kit 是一个高效的偏业务前端工具函数库。
1111[ ![ License] ( https://img.shields.io/github/license/OFreshman/ui-utils-kit.svg?style=flat&colorA=080f12&colorB=1fa669 )] ( https://github.com/OFreshman/ui-utils-kit/blob/main/LICENSE )
1212
1313---
14- ## 📖changlogs
15- - 2023-10-01
14+ ## 📖changelogs
15+ - 2024-12-06
1616 - 新增 ` tree ` 模块,提供树形数据操作的工具函数。
1717 - 新增 ` business ` 模块,提供 DOM 转图片的工具函数。
1818 - 新增 ` common ` 模块,提供一些常用的业务工具函数。
1919 - 完善文档说明。
20+ - 2025-04-24
21+ - 新增 ` common.createSelfCorrectingClock ` 创建零漂移的自校正实时时钟。
22+ - 新增 ` common.createSelfCorrectingCountdown ` 创建零漂移的自校正倒计时器。
23+ - 完善文档说明。
2024
2125## 📌 简介
2226
@@ -28,6 +32,7 @@ ui-utils-kit 是一个高效的偏业务前端工具函数库。
2832- ** 海报制作**
2933 将 DOM 元素转换为图片(canvas),支持自动下载或返回 Blob 格式数据。
3034 > 针对跨域图片问题,内置 ` html2canvas ` proxy 解决方案。
35+
3136- ** 业务工具类函数**
3237 提供一些常用的业务工具函数,如 JSON 安全解析、敏感信息脱敏等。
3338
@@ -48,7 +53,7 @@ yarn add ui-utils-kit
4853
4954## 🚀 使用方式
5055
51- ui-utils-kit 的工具函数分为三大类 :` tree ` 、` business ` 、` common ` ,支持两种导入方式:
56+ ` ui-utils-kit ` 的工具函数目前分为三大类 :` tree ` 、` business ` 、` common ` ,支持两种导入方式:
5257
5358** 方式一:**
5459``` javascript
@@ -76,6 +81,9 @@ const result = buildTree(nodes);
7681 - ` nodes ` (` Array<TreeNode> ` ):包含 ` id ` 与 ` pid ` 的节点数据数组。
7782 - ` preserveChildren ` (` boolean ` ,可选):是否保留原 ` children ` 属性。
7883
84+ - ** 返回值:**
85+ - ` Array<TreeNode> ` :构建后的树形结构数据。
86+
7987- ** 示例:**
8088 ``` typescript
8189 import { buildTree } from ' ui-utils-kit' ;
@@ -96,6 +104,10 @@ const result = buildTree(nodes);
96104- ** 参数:**
97105 - ` tree ` (` TreeNode ` ):包含 ` id ` 与 ` name ` 、` children ` 的树形结构数据。
98106 - ` node ` (` TreeNode ` ):包含 ` id ` 与 ` pid ` 的节点数据。
107+
108+ - ** 返回值:**
109+ - ` Array<TreeNode> ` :扁平化后的数组。
110+
99111- ** 示例:**
100112 ``` typescript
101113 import { treeToArr } from ' ui-utils-kit' ;
@@ -111,6 +123,10 @@ const result = buildTree(nodes);
111123
112124- ** 参数:**
113125 - ` tree ` (` TreeNode ` ):包含 ` id ` 与 ` name ` 、` children ` 的树形结构数据。
126+
127+ - ** 返回值:**
128+ - ` Array<TreeNode> ` :更新后的节点数组。
129+
114130- ** 示例:**
115131 ``` typescript
116132 import { updateTreeCheckStatus } from ' ui-utils-kit' ;
@@ -128,6 +144,16 @@ const result = buildTree(nodes);
128144
129145** ` tree.searchTreeWithRelations ` ** 根据关键词查找匹配节点,同时返回相关的父子关系。
130146
147+ - ** 参数:**
148+ - ` treeArr (TreeNode[]) ` :树结构的数组,每个节点至少应包含 id, pid, name 属性,表示节点标识、父节点标识及节点名称。
149+ - ` keywords (string) ` :用于匹配节点名称的关键词,支持模糊匹配(即 includes 匹配)。
150+ - ` mark (boolean) ` :是否在匹配的节点上添加 isMatched 属性标记,默认值为 true。
151+ -
152+ - ** 返回值:**
153+ - ` Array<TreeNode> ` :匹配结果数组,
154+ 包含: 名称匹配的节点; 匹配节点的所有父节点; 匹配节点的所有子节点。
155+ 返回顺序为:父节点在前,子节点在后;同一层级节点顺序与原数组一致。。
156+
131157- ** 示例:**
132158 ``` typescript
133159 import { searchTreeWithRelations } from ' ui-utils-kit' ;
@@ -145,7 +171,7 @@ const result = buildTree(nodes);
145171
146172## 🎨 业务函数 (business)
147173
148- ### 1. DOM 转图片
174+ ### 1. DOM 转图片(例如生成海报)
149175
150176** ` captureElementAsImage ` ** 将 DOM 元素转换为图片(canvas),支持自动下载或返回 Blob 格式数据。
151177> ** ⚠️ 注意**
@@ -183,6 +209,8 @@ const result = buildTree(nodes);
183209 .catch (err => console .error (err));
184210 ```
185211
212+ > ! 小程序的话还是推荐canvas 去绘制,然后再结合 ` uni.canvasToTempFilePath` 去转图片,优点是高度自定义。
213+
186214-- -
187215
188216## 🎨 公共通用函数 (common)
@@ -210,12 +238,13 @@ if (err) {
210238 console.log(data.foo); // 42
211239}
212240` ` `
241+
213242### 2. desensitize (value: string, type: " mobile" | " idcard" ): string
214243** 功能描述** :对敏感信息(手机号或身份证号)进行脱敏处理,隐藏中间部分。
215244
216245** 参数**
217246- ` value: string` — 原始字符串,如手机号或身份证号。
218- - ` type: "mobile" \ | "idcard"` — 数据类型," mobile" 脱敏手机号," idcard" 脱敏身份证号。
247+ - ` type: "mobile" | "idcard"` — 数据类型," mobile" 脱敏手机号," idcard" 脱敏身份证号。
219248
220249** 返回值**
221250string — 脱敏后字符串,如果输入非字符串则返回空字符串。
@@ -231,16 +260,15 @@ console.log(desensitize('110105199001011234', 'idcard')); // 输出:110105****
231260### 3. Mutex 类
232261功能描述:模拟互斥锁机制,用于控制异步操作对共享资源的访问,确保同一时刻只有一个操作进入临界区。
233262> ##### 以下是一些应用场景
234- > - 防止按钮重复点击:避免用户多次点击同一按钮导致重复网络请求或状态混乱
235- > - 强制 API 调用顺序:确保一组异步接口按预期顺序依次执行,防止乱序带来的逻辑错误
236- > - 多标签页 localStorage 访问:在多个浏览器标签或窗口同时操作同一 localStorage 时,避免数据竞争和丢失
237- > - 分片上传(Chunked Upload):在大文件上传时,按顺序上传每个分片,确保断点续传或失败重试时不会错乱
238- > - Web Worker 任务同步:在主线程与 Worker 线程之间同步访问共享内存(如 SharedArrayBuffer )时,保证原子性
239-
263+ > - 防止按钮重复点击:避免用户多次点击同一按钮导致重复网络请求或状态混乱。
264+ > - 强制 API 调用顺序:确保一组异步接口按预期顺序依次执行,防止乱序带来的逻辑错误。
265+ > - 多标签页 localStorage 访问:在多个浏览器标签或窗口同时操作同一 localStorage 时,避免数据竞争和丢失。
266+ > - 分片上传(Chunked Upload):在大文件上传时,按顺序上传每个分片,确保断点续传或失败重试时不会错乱。
267+ > - Web Worker 任务同步:在主线程与 Worker 线程之间同步访问共享内存(如 SharedArrayBuffer )时,保证原子性。
240268
241269- 示例
242270
243- ` ` ` typescript
271+ ` ` ` vue
244272<template>
245273 <view>
246274 <button @click="onSubmit" :disabled="isSubmitting">
@@ -250,7 +278,7 @@ console.log(desensitize('110105199001011234', 'idcard')); // 输出:110105****
250278</template>
251279
252280<script setup lang="ts">
253- import Mutex from 'ui-utils-kit' // 假设 Mutex 存放在 utils 目录
281+ import { Mutex } from 'ui-utils-kit'
254282
255283// 状态变量,无需在 setup 中 return,自动暴露给模板使用
256284const isSubmitting = ref(false)
@@ -275,6 +303,88 @@ const onSubmit = async () => {
275303 }
276304}
277305</script>
306+ ` ` `
307+
308+ ### 4. ` createSelfCorrectingClock(interval?: number): SelfCorrectingClock`
309+
310+ ** 功能描述:**
311+ 创建一个“零漂移”(self - correcting)实时时钟管理器。该管理器内部通过动态调节 ` setTimeout` 延迟来消除长时间运行中的累积误差,并在浏览器标签切换或后台恢复后依然保持准确。
312+
313+ ** 参数**
314+ - ` interval?: number` — 更新间隔(毫秒),可选,默认值为 ` 1000` 。
315+
316+ ** 返回值**
317+ ` SelfCorrectingClock` — 一个对象,包含:
318+ ` ` ` ts
319+ interface SelfCorrectingClock {
320+ /** 获取最新的当前时间戳(毫秒) */
321+ getCurrentTime(): number;
322+ /** 停止内部定时器,释放资源 */
323+ stop(): void;
324+ }
325+ ` ` `
326+ - 示例
327+ ` ` ` typescript
328+ import { createSelfCorrectingClock } from 'ui-utils-kit';
329+
330+ // 创建一个每秒更新一次的自校正时钟
331+ const clock = createSelfCorrectingClock(1000);
332+ // 每 5 秒读取并打印一次当前时间戳
333+ const logger = setInterval(() => {
334+ console.log('当前时间戳:', clock.getCurrentTime());
335+ }, 5000);
336+
337+ // …需要停止时,调用 stop() 并清理外部 logger
338+ setTimeout(() => {
339+ clock.stop();
340+ clearInterval(logger);
341+ console.log('时钟已停止');
342+ }, 30_000);
343+ ` ` `
344+
345+ ### 5. ` createSelfCorrectingCountdown(targetTimestamp: number, interval?: number): SelfCorrectingCountdown`
346+
347+ ** 功能描述:** 创建一个“零漂移”自校正倒计时管理器。内部同样通过校正机制消除误差,到达目标时间时自动停止,并允许手动停止
348+
349+ ** 参数**
350+ - ` targetTimestamp: number` — 倒计时结束的目标时间戳(毫秒)。
351+
352+ - ` interval?: number` — 更新间隔(毫秒),可选,默认值为 1000 。
353+
354+ ** 返回值**
355+ ` SelfCorrectingCountdown` — 一个对象,包含:
356+ ` ` ` ts
357+ interface SelfCorrectingCountdown {
358+ /** 获取最新的剩余时间(毫秒) */
359+ getRemainingTime(): number;
360+ /** 停止内部定时器,释放资源 */
361+ stop(): void;
362+ }
363+ ` ` `
364+ - 示例
365+ ` ` ` typescript
366+ import { createSelfCorrectingCountdown } from 'ui-utils-kit';
367+
368+ // 目标时间为当前时间后 10 秒
369+ const target = Date.now() + 10_000;
370+ const countdown = createSelfCorrectingCountdown(target, 1000);
371+
372+ // 每秒读取并打印一次剩余时间
373+ const logger = setInterval(() => {
374+ const left = countdown.getRemainingTime();
375+ console.log('剩余时间(毫秒):', left);
376+ if (left === 0) {
377+ clearInterval(logger);
378+ console.log('倒计时结束');
379+ }
380+ }, 1000);
381+
382+ // 如需提前取消倒计时
383+ // setTimeout(() => {
384+ // countdown.stop();
385+ // clearInterval(logger);
386+ // console.log('倒计时已手动停止');
387+ // }, 5000);
278388
279389` ` `
280390
@@ -295,11 +405,13 @@ type TreeNode = {
295405
296406### ` CheckStatus` 枚举
297407` ` ` typescript
298- enum CheckStatus {
299- Checked = 'Checked',
300- Unchecked = 'Unchecked',
301- HalfChecked = 'HalfChecked',
302- }
408+ export const CheckStatusMap = {
409+ Unchecked: "0",
410+ HalfChecked: "1",
411+ Checked: "2"
412+ } as const;
413+
414+ export type CheckStatus = typeof CheckStatusMap[keyof typeof CheckStatusMap];
303415` ` `
304416
305417-- -
0 commit comments