feat(playground): ✨ 新增示例项目
This commit is contained in:
@@ -9,19 +9,32 @@
|
||||
|
||||
export type InputValue = string | number | null;
|
||||
export interface InputOptions {
|
||||
min?: number; // 最小值
|
||||
max?: number; // 最大值
|
||||
init?: string | number; // 初始值
|
||||
digits?: number; // 小数位数
|
||||
pattern?: string | RegExp; // 匹配模式
|
||||
required?: boolean; // 是否必填
|
||||
integer?: boolean; // 是否整数
|
||||
number?: boolean; // 是否转成数字
|
||||
text?: boolean; // 是否使用文本模式
|
||||
floor?: boolean; // 是否向下取数
|
||||
ceil?: boolean; // 是否向上取数
|
||||
keepDecimal?: boolean; // 是否保留小数,即使是小数位是0
|
||||
noSign?: boolean; // 不允许输入正负号
|
||||
/** 最小值 */
|
||||
min?: number;
|
||||
/** 最大值 */
|
||||
max?: number;
|
||||
/** 初始值,当输入非法且 required 为 true 时回退到此值 */
|
||||
init?: string | number;
|
||||
/** 小数位数,设置后会对结果进行精度处理 */
|
||||
digits?: number;
|
||||
/** 匹配模式,文本模式下用于校验输入是否匹配该正则 */
|
||||
pattern?: string | RegExp;
|
||||
/** 是否必填,为 true 时非法输入将回退到 init 或 min */
|
||||
required?: boolean;
|
||||
/** 是否取整,为 true 时结果将取整 */
|
||||
integer?: boolean;
|
||||
/** 是否将结果转为数字类型 */
|
||||
number?: boolean;
|
||||
/** 是否使用文本模式,文本模式只做 pattern 校验和必填回退 */
|
||||
text?: boolean;
|
||||
/** 是否向下取整 */
|
||||
floor?: boolean;
|
||||
/** 是否向上取整 */
|
||||
ceil?: boolean;
|
||||
/** 是否保留小数位,为 true 时即使小数位为 0 也会保留指定位数(需配合 digits 使用) */
|
||||
keepDecimal?: boolean;
|
||||
/** 是否不允许输入正负号 */
|
||||
noSign?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,31 +1,80 @@
|
||||
/*
|
||||
* @file \src\knock-test\KnockTest.ts
|
||||
* @description 敲击工具,根据点击的次数、延迟执行回调
|
||||
* @author tsl (randy1924@163.com)
|
||||
* @date 2026-02-09 18:26:16
|
||||
* @lastModified 2026-06-30 10:05:44
|
||||
* @lastModifiedBy tsl (randy1924@163.com)
|
||||
*/
|
||||
import { debounce } from "lodash-es";
|
||||
|
||||
/** 操作项,定义一次敲击阶段的参数 */
|
||||
export class Operation {
|
||||
/** 敲击有效时长(ms),超过该时长未达到指定次数则重置 */
|
||||
duration = 1000;
|
||||
/** 当前操作完成后进入下一操作前的等待时长(ms),等待期间点击会重置 */
|
||||
delay = 1000;
|
||||
/** 当前操作需要敲击的次数 */
|
||||
times = 1;
|
||||
}
|
||||
|
||||
/** KnockTest 配置项 */
|
||||
export class Config {
|
||||
/** 最大等待时间(ms),从首次敲击开始计算,超时未完成所有操作则自动重置 */
|
||||
maxWaitTime = 5000;
|
||||
/** 操作项列表,按顺序执行 */
|
||||
operations: Operation[] = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 敲击测试工具
|
||||
*
|
||||
* 通过按顺序执行多阶段敲击操作来触发回调,类似安卓开发者模式的连续点击触发。
|
||||
*
|
||||
* 状态流转:
|
||||
* - idle(空闲) → 首次敲击进入 knocking
|
||||
* - knocking(敲击中) → 达到指定次数进入 wait
|
||||
* - wait(等待) → 等待延迟结束后回到 idle;等待期间再次敲击则重置
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const kt = new KnockTest({
|
||||
* maxWaitTime: 10000,
|
||||
* operations: [
|
||||
* { duration: 1000, delay: 500, times: 3 }, // 1秒内敲3次
|
||||
* { duration: 1000, delay: 500, times: 2 }, // 然后等待0.5秒后1秒内敲2次
|
||||
* ]
|
||||
* })
|
||||
* kt.addCallback(() => console.log('解锁成功'))
|
||||
* kt.knock() // 在UI点击事件中调用
|
||||
* ```
|
||||
*/
|
||||
export class KnockTest {
|
||||
/** 配置项 */
|
||||
config: Config;
|
||||
/** 当前操作项索引 */
|
||||
index = 0;
|
||||
/** 当前阶段已敲击次数 */
|
||||
times = 0;
|
||||
/**
|
||||
* 空闲状态:"idle",times从0开始计数,进入duration期
|
||||
* duration期间:"knocking",times达到Operation的指定次数后进入delay期
|
||||
* delay期间:"wait",此期间不能点击,如果点击则重置,否则进入下一个空闲状态
|
||||
* 当前状态:
|
||||
* - "idle" 空闲,times从0开始计数,进入duration期
|
||||
* - "knocking" 敲击中,times达到Operation的指定次数后进入delay期
|
||||
* - "wait" 等待,此期间不能点击,如果点击则重置,否则进入下一个空闲状态
|
||||
*/
|
||||
status: "idle" | "knocking" | "wait" = "idle";
|
||||
/** duration 定时器 ID */
|
||||
durationTimerId: number | null = null;
|
||||
/** delay 定时器 ID */
|
||||
delayTimerId: number | null = null;
|
||||
/** 成功回调列表,所有操作完成后依次执行 */
|
||||
callbackList: (() => void)[] = [];
|
||||
/** 最大等待防抖函数,超时自动重置 */
|
||||
maxWaitFun: () => void;
|
||||
|
||||
/**
|
||||
* @param config 配置项,未指定的字段使用默认值
|
||||
*/
|
||||
constructor(config: Config) {
|
||||
const c = new Config();
|
||||
this.config = Object.assign(c, config);
|
||||
@@ -36,10 +85,22 @@ export class KnockTest {
|
||||
}, this.config.maxWaitTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加成功回调,所有操作按序完成后触发
|
||||
* @param cb 回调函数
|
||||
*/
|
||||
addCallback(cb: () => void) {
|
||||
this.callbackList.push(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* 敲击一次,在 UI 点击事件中调用
|
||||
*
|
||||
* 每次调用会使 times + 1,并根据当前状态决定后续行为:
|
||||
* - idle → 开始新的敲击阶段
|
||||
* - knocking → 检查是否达到当前操作指定次数
|
||||
* - wait → 重置所有状态(等待期间不允许敲击)
|
||||
*/
|
||||
knock() {
|
||||
console.log("knock");
|
||||
this.maxWaitFun();
|
||||
@@ -60,6 +121,7 @@ export class KnockTest {
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置所有状态,回到初始空闲状态并清除所有定时器 */
|
||||
private reset() {
|
||||
this.status = "idle";
|
||||
this.times = 0;
|
||||
@@ -75,6 +137,11 @@ export class KnockTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理空闲状态的敲击:启动新的敲击阶段,设置 duration 定时器
|
||||
* 超时未达到指定次数则自动重置
|
||||
* @throws 当操作项列表为空时抛出错误
|
||||
*/
|
||||
private handleIdle() {
|
||||
if (this.config.operations.length === 0) {
|
||||
throw new Error("至少添加一个操作项");
|
||||
@@ -92,10 +159,17 @@ export class KnockTest {
|
||||
this.checkKnock();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理敲击中状态:检查当前敲击次数是否满足操作项要求
|
||||
*/
|
||||
private handleKnocking() {
|
||||
this.checkKnock();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查当前敲击次数是否达到操作项要求,若达到则进入等待状态
|
||||
* 若已完成所有操作项,则触发回调并重置
|
||||
*/
|
||||
private checkKnock() {
|
||||
const operation = this.config.operations[this.index];
|
||||
|
||||
@@ -127,6 +201,9 @@ export class KnockTest {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理等待状态的敲击:等待期间不允许敲击,直接重置
|
||||
*/
|
||||
private handleWait() {
|
||||
if (this.delayTimerId != null) {
|
||||
clearTimeout(this.delayTimerId);
|
||||
|
||||
@@ -1,17 +1,54 @@
|
||||
/*
|
||||
* @file \src\permission\Permission.ts
|
||||
* @description 权限工具
|
||||
* @author tsl (randy1924@163.com)
|
||||
* @date 2023-11-27 13:35:18
|
||||
* @lastModified 2026-06-30 10:06:50
|
||||
* @lastModifiedBy tsl (randy1924@163.com)
|
||||
*/
|
||||
|
||||
/**
|
||||
* 权限工具类
|
||||
*
|
||||
* 用于管理和校验权限字符串格式,权限字符串采用多级分段格式,
|
||||
* 例如 "module:action:resource",默认使用 ":" 作为分隔符,默认 3 级。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const permission = new Permission(['user:read:info', 'admin:write:config'], 3, ':')
|
||||
* permission.isValid('user:read:info') // true
|
||||
* permission.isValid('user:read') // false,级数不足
|
||||
* permission.isValid('user read info') // false,分隔符不匹配
|
||||
* ```
|
||||
*/
|
||||
export class Permission {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/** 权限字符串列表 */
|
||||
list: string[];
|
||||
/** 权限分隔符,默认为 ":" */
|
||||
separator: string;
|
||||
/** 权限级数,默认为 3(如 "module:action:resource") */
|
||||
level: number;
|
||||
|
||||
/**
|
||||
* @param list 权限字符串列表
|
||||
* @param level 权限级数,默认 3
|
||||
* @param separator 分隔符,默认 ":"
|
||||
*/
|
||||
constructor(list: string[], level = 3, separator = ":") {
|
||||
this.list = list;
|
||||
this.level = level;
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验权限字符串格式是否合法
|
||||
*
|
||||
* 检查字符串是否符合指定的级数和分隔符格式,
|
||||
* 例如 level=3、separator=":" 时,"module:action:resource" 合法,"module:action" 不合法。
|
||||
*
|
||||
* @param str 待校验的权限字符串
|
||||
* @returns 是否合法
|
||||
*/
|
||||
isValid(str: string) {
|
||||
const p = new Array(this.level).fill("\\w+?").join(this.separator);
|
||||
// ^\w+?:\w+?:\w+?$
|
||||
|
||||
@@ -3,20 +3,47 @@ import { Duration } from "dayjs/plugin/duration";
|
||||
|
||||
type TimerCallback = (time: string) => void;
|
||||
|
||||
/**
|
||||
* 倒计时工具类
|
||||
*
|
||||
* 基于 dayjs duration 的倒计时,支持步骤监听和完成监听。
|
||||
* 每秒递减一次,并通过 stepEventListener 回调当前格式化时间;
|
||||
* 倒计时归零时触发 countdownEventListener 回调。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const countdown = new Countdown(60000) // 60秒倒计时
|
||||
* countdown.format = 'mm:ss'
|
||||
* countdown.addStepEventListener((time) => console.log('剩余:', time))
|
||||
* countdown.addCountdownEventListener((time) => console.log('倒计时结束:', time))
|
||||
* countdown.start()
|
||||
* ```
|
||||
*/
|
||||
export default class Countdown {
|
||||
/** 定时器 ID,-1 表示未运行 */
|
||||
id = -1;
|
||||
/** dayjs duration 对象,表示剩余时长 */
|
||||
duration: Duration;
|
||||
/** 输出时间格式,默认 "HH:mm:ss" */
|
||||
format = "HH:mm:ss";
|
||||
/**
|
||||
* 倒计时步骤监听器
|
||||
* 倒计时步骤监听器列表
|
||||
*
|
||||
* 每秒触发一次,参数为当前格式化后的剩余时间字符串
|
||||
*/
|
||||
stepEventListenerList = <TimerCallback[]>[];
|
||||
/**
|
||||
* 倒计时完成时间监听器
|
||||
* 倒计时完成监听器列表
|
||||
*
|
||||
* 倒计时归零时触发,参数为最终的格式化时间字符串
|
||||
*/
|
||||
countdownEventListenerList = <TimerCallback[]>[];
|
||||
/** 初始时间(毫秒),用于 restart 时重置 */
|
||||
initialTime = 0;
|
||||
|
||||
/**
|
||||
* @param time 倒计时总时长(毫秒)
|
||||
*/
|
||||
constructor(time: number) {
|
||||
this.initialTime = time;
|
||||
this.duration = dayjs.duration(time);
|
||||
@@ -24,8 +51,11 @@ export default class Countdown {
|
||||
|
||||
/**
|
||||
* 添加倒计时步骤监听器
|
||||
* @param cb
|
||||
* @returns
|
||||
*
|
||||
* 每秒触发一次回调,参数为当前格式化后的剩余时间字符串
|
||||
*
|
||||
* @param cb 步骤回调函数,参数为格式化时间字符串
|
||||
* @returns 若 cb 不是函数则返回 TypeError
|
||||
*/
|
||||
addStepEventListener(cb: TimerCallback) {
|
||||
if (!(cb instanceof Function)) {
|
||||
@@ -35,9 +65,12 @@ export default class Countdown {
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加倒计时完成时间监听器
|
||||
* @param cb
|
||||
* @returns
|
||||
* 添加倒计时完成监听器
|
||||
*
|
||||
* 倒计时归零时触发,参数为最终的格式化时间字符串
|
||||
*
|
||||
* @param cb 完成回调函数,参数为格式化时间字符串
|
||||
* @returns 若 cb 不是函数则返回 TypeError
|
||||
*/
|
||||
addCountdownEventListener(cb: TimerCallback) {
|
||||
if (!(cb instanceof Function)) {
|
||||
@@ -47,7 +80,7 @@ export default class Countdown {
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始倒计时
|
||||
* 开始倒计时,每秒递减一次并触发步骤监听器,归零时自动停止
|
||||
*/
|
||||
start() {
|
||||
this.id = window.setInterval(() => {
|
||||
@@ -63,7 +96,7 @@ export default class Countdown {
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束倒计时
|
||||
* 停止倒计时,清除定时器并触发完成监听器
|
||||
*/
|
||||
stop() {
|
||||
console.log("stop", this.id);
|
||||
@@ -75,7 +108,7 @@ export default class Countdown {
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新开始计时
|
||||
* 重新开始倒计时,重置为初始时间后重新启动
|
||||
*/
|
||||
restart() {
|
||||
clearInterval(this.id);
|
||||
|
||||
@@ -1,19 +1,49 @@
|
||||
type TimerCallback = (time: number) => void;
|
||||
|
||||
/**
|
||||
* 超时定时器
|
||||
*
|
||||
* 基于数值的倒计时器,从 startTime 递减到 endTime,
|
||||
* 每隔 interval 毫秒触发步骤监听器,到达 endTime 时触发完成监听器。
|
||||
*
|
||||
* 与 Countdown 不同的是,TimeoutTimer 使用数值而非 dayjs duration,
|
||||
* 适合不需要格式化输出的纯数值倒计时场景。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // 实例方式
|
||||
* const timer = new TimeoutTimer(10, 0, 1000)
|
||||
* timer.addStepEventListener((time) => console.log('剩余:', time))
|
||||
* timer.addCountdownEventListener((time) => console.log('结束:', time))
|
||||
* timer.start()
|
||||
*
|
||||
* // 静态工厂方式
|
||||
* const timer2 = TimeoutTimer.start(10, 0, 1000,
|
||||
* (time) => console.log('剩余:', time),
|
||||
* (time) => console.log('结束:', time),
|
||||
* )
|
||||
* ```
|
||||
*/
|
||||
export default class TimeoutTimer {
|
||||
/** 起始时间(数值) */
|
||||
startTime = 0;
|
||||
/** 结束时间(数值),倒计时到此值停止 */
|
||||
endTime = 0;
|
||||
/** 递减间隔(毫秒) */
|
||||
interval = 0;
|
||||
/** 当前剩余时间 */
|
||||
time = 0;
|
||||
/** 定时器 ID,-1 表示未运行 */
|
||||
id = -1;
|
||||
/** 步骤监听器列表,每次递减时触发,参数为当前剩余时间 */
|
||||
stepEventListenerList = <TimerCallback[]>[];
|
||||
/** 完成监听器列表,倒计时结束时触发,参数为结束时间 */
|
||||
countdownEventListenerList = <TimerCallback[]>[];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param startTime 起始时间
|
||||
* @param endTime 结束时间
|
||||
* @param interval 间隔(ms)
|
||||
* @param startTime 起始时间(数值)
|
||||
* @param endTime 结束时间(数值),默认 0
|
||||
* @param interval 递减间隔(毫秒),默认 1000
|
||||
*/
|
||||
constructor(startTime = 5, endTime = 0, interval = 1000) {
|
||||
this.startTime = startTime;
|
||||
@@ -22,9 +52,12 @@ export default class TimeoutTimer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 倒计时步骤监听器
|
||||
* @param cb
|
||||
* @returns
|
||||
* 添加步骤监听器
|
||||
*
|
||||
* 每次递减时触发,参数为当前剩余时间
|
||||
*
|
||||
* @param cb 步骤回调函数,参数为当前时间(数值)
|
||||
* @returns 若 cb 不是函数则返回 TypeError
|
||||
*/
|
||||
addStepEventListener(cb: TimerCallback) {
|
||||
if (!(cb instanceof Function)) {
|
||||
@@ -34,9 +67,12 @@ export default class TimeoutTimer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 倒计时完成时间监听器
|
||||
* @param cb
|
||||
* @returns
|
||||
* 添加完成监听器
|
||||
*
|
||||
* 倒计时到达 endTime 时触发,参数为结束时间
|
||||
*
|
||||
* @param cb 完成回调函数,参数为结束时间(数值)
|
||||
* @returns 若 cb 不是函数则返回 TypeError
|
||||
*/
|
||||
addCountdownEventListener(cb: TimerCallback) {
|
||||
if (!(cb instanceof Function)) {
|
||||
@@ -46,13 +82,14 @@ export default class TimeoutTimer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始倒计时
|
||||
* @param startTime
|
||||
* @param endTime
|
||||
* @param interval
|
||||
* @param stepEventListener
|
||||
* @param countdownEventListener
|
||||
* @returns
|
||||
* 静态工厂方法,创建并配置超时定时器
|
||||
*
|
||||
* @param startTime 起始时间(数值)
|
||||
* @param endTime 结束时间(数值),默认 0
|
||||
* @param interval 递减间隔(毫秒),默认 1000
|
||||
* @param stepEventListener 步骤监听器(可选)
|
||||
* @param countdownEventListener 完成监听器(可选)
|
||||
* @returns 配置好的 TimeoutTimer 实例(需手动调用 start)
|
||||
*/
|
||||
static start(
|
||||
startTime: number,
|
||||
@@ -73,7 +110,7 @@ export default class TimeoutTimer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始倒计时
|
||||
* 开始倒计时,从 startTime 递减到 endTime,到达后自动停止
|
||||
*/
|
||||
start() {
|
||||
this.time = this.startTime;
|
||||
@@ -88,7 +125,7 @@ export default class TimeoutTimer {
|
||||
}
|
||||
|
||||
/**
|
||||
* 结束倒计时
|
||||
* 停止倒计时,清除定时器并触发完成监听器
|
||||
*/
|
||||
stop() {
|
||||
console.log("stop", this.id);
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @r-utils/uni-app
|
||||
|
||||
## 2.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 修复vue3未导出
|
||||
|
||||
## 2.0.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@r-utils/uni-app",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.2",
|
||||
"private": false,
|
||||
"description": "uni-app工具库",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,17 +1,56 @@
|
||||
/*
|
||||
* @file \src\printer\index.ts
|
||||
* @description 蓝牙打印工具,最后打印的一步,组合蓝牙信息与打印数据发送
|
||||
* @author tsl (randy1924@163.com)
|
||||
* @date 2026-05-28 11:13:40
|
||||
* @lastModified 2026-06-30 11:02:16
|
||||
* @lastModifiedBy tsl (randy1924@163.com)
|
||||
*/
|
||||
|
||||
import { wait } from "@r-utils/common";
|
||||
import { BluetoothUtils, Device } from "@/bluetooth-utils";
|
||||
|
||||
/** 蓝牙设备完整数据,包含设备信息和所有必需的特征值 ID */
|
||||
type DeviceData = Required<Device>;
|
||||
|
||||
/**
|
||||
* 蓝牙打印机工具类
|
||||
*
|
||||
* 将蓝牙设备信息与打印数据组合,通过 BLE 写入特征值发送 ESC/POS 打印指令。
|
||||
* 支持安卓原生发送和通用 BLE 写入两种方式,自动根据平台选择。
|
||||
* 打印数据会按 size 分包发送,每包之间等待 30ms 以确保数据传输稳定。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const printer = new Printer(device, { size: 80 })
|
||||
* await printer.print(escData) // escData 为 ESC/POS 指令的 number 数组
|
||||
* ```
|
||||
*/
|
||||
export class Printer {
|
||||
/** 蓝牙设备信息,包含 deviceId、服务 ID 和特征值 ID 等 */
|
||||
device: DeviceData;
|
||||
/** 每次写入 BLE 的最大字节数,默认 80 */
|
||||
size = 0;
|
||||
|
||||
/**
|
||||
* @param device 蓝牙设备完整数据(必须包含所有特征值 ID)
|
||||
* @param size 每次写入的最大字节数,默认 80
|
||||
*/
|
||||
constructor(device: DeviceData, { size = 80 } = {}) {
|
||||
this.device = device;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送打印数据
|
||||
*
|
||||
* 根据平台自动选择发送方式:
|
||||
* - 安卓 App 端:使用 BluetoothUtils.sendDataAndroid 原生发送
|
||||
* - 其他平台:通过 BLE 写入特征值发送
|
||||
*
|
||||
* @param data ESC/POS 打印指令数组
|
||||
* @returns 发送结果
|
||||
*/
|
||||
async print(data: number[]) {
|
||||
console.log(
|
||||
data.length,
|
||||
@@ -32,6 +71,14 @@ export class Printer {
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 BLE 写入特征值分包发送打印数据(内部方法)
|
||||
*
|
||||
* 将数据按 size 分包,每包创建 ArrayBuffer 写入 BLE 特征值,
|
||||
* 包间等待 30ms 确保传输稳定,递归发送直到所有数据写完。
|
||||
*
|
||||
* @param data 剩余待发送的打印数据
|
||||
*/
|
||||
async _print(data: number[]): Promise<void> {
|
||||
const size = Math.min(data.length, this.size);
|
||||
if (size === 0) {
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/*
|
||||
* @file \src\request\Request.ts
|
||||
* @description uniapp请求类。建议改用 alova[https://alova.js.org/zh-CN/]
|
||||
* @author tsl (randy1924@163.com)
|
||||
* @date 2026-05-28 11:13:40
|
||||
* @lastModified 2026-06-30 10:14:09
|
||||
* @lastModifiedBy tsl (randy1924@163.com)
|
||||
*/
|
||||
|
||||
export type DataType = string | AnyObject | ArrayBuffer;
|
||||
|
||||
/** 请求配置 */
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/*
|
||||
* @file \src\upload\index.ts
|
||||
* @description uniapp上传文件工具
|
||||
* @author tsl (randy1924@163.com)
|
||||
* @date 2026-05-28 11:13:40
|
||||
* @lastModified 2026-06-30 10:54:55
|
||||
* @lastModifiedBy tsl (randy1924@163.com)
|
||||
*/
|
||||
|
||||
type UploadResponseData = {
|
||||
originalFileName: string;
|
||||
url: string;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* @file /src/vue3/hooks/components.ts
|
||||
* @description
|
||||
* @description uniapp组件hook
|
||||
* @author tsl (randy1924@163.com)
|
||||
* @date 2026-03-19 11:11:11
|
||||
* @lastModified 2026-03-26 09:16:44
|
||||
* @lastModified 2026-06-30 10:55:21
|
||||
* @lastModifiedBy tsl (randy1924@163.com)
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/*
|
||||
* @file /src/hooks/list.ts
|
||||
* @description
|
||||
* @description 列表加载更多Hook
|
||||
* @author tsl (randy1924@163.com)
|
||||
* @date 2026-03-19 11:11:11
|
||||
* @lastModified 2026-03-20 10:43:38
|
||||
* @lastModified 2026-06-30 10:57:44
|
||||
* @lastModifiedBy tsl (randy1924@163.com)
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,9 +1,37 @@
|
||||
/*
|
||||
* @file \src\vue-helper\index.ts
|
||||
* @description vue3 帮助工具
|
||||
* @author tsl (randy1924@163.com)
|
||||
* @date 2026-05-28 11:13:40
|
||||
* @lastModified 2026-06-30 11:00:29
|
||||
* @lastModifiedBy tsl (randy1924@163.com)
|
||||
*/
|
||||
|
||||
import { ComponentPublicInstance } from "vue";
|
||||
|
||||
/** Vue class 对象格式,键为类名,值为布尔值表示是否生效 */
|
||||
type CustomClassObj = Record<string, boolean>;
|
||||
/** Vue class 支持的类型:字符串、字符串数组或对象 */
|
||||
type CustomClass = string | Array<string> | CustomClassObj;
|
||||
/** 分解后的 Vue class 对象,所有类名值为 true */
|
||||
type DistCustomClass = Record<string, true>;
|
||||
|
||||
/**
|
||||
* 将字符串或字符串数组转换为 Vue class 对象
|
||||
*
|
||||
* 将类名字符串或数组转换为 `{ className: true }` 格式的对象,
|
||||
* 适用于 Vue 的 class 绑定。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* createCustomClassObj('foo bar') // { foo: true, bar: true }
|
||||
* createCustomClassObj(['foo', 'bar']) // { foo: true, bar: true }
|
||||
* ```
|
||||
*
|
||||
* @param customClass 类名字符串或字符串数组
|
||||
* @returns 类名对象,所有值为 true
|
||||
* @throws 若 customClass 不是字符串或数组则抛出 TypeError
|
||||
*/
|
||||
export function createCustomClassObj(customClass: string): DistCustomClass;
|
||||
export function createCustomClassObj(
|
||||
customClass: Array<string>,
|
||||
@@ -35,9 +63,21 @@ export function createCustomClassObj(
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换 vue class 为 vue class 对象
|
||||
* @param sourceClass 原始 class
|
||||
* @returns
|
||||
* 转换 Vue class 为 Vue class 对象
|
||||
*
|
||||
* 支持字符串、数组和对象三种 Vue class 格式,统一转换为
|
||||
* `{ className: boolean }` 格式的对象。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* convertCustomClass('foo bar') // { foo: true, bar: true }
|
||||
* convertCustomClass(['foo', 'bar']) // { foo: true, bar: true }
|
||||
* convertCustomClass({ foo: true, bar: false }) // { foo: true, bar: false }
|
||||
* ```
|
||||
*
|
||||
* @param sourceClass 原始 Vue class 值,支持字符串、数组或对象
|
||||
* @returns Vue class 对象
|
||||
* @throws 若 sourceClass 不是有效的 Vue class 则抛出 TypeError
|
||||
*/
|
||||
export function convertCustomClass(sourceClass: CustomClass): CustomClassObj {
|
||||
let customClassObj = <CustomClassObj>{};
|
||||
@@ -66,9 +106,19 @@ export function convertCustomClass(sourceClass: CustomClass): CustomClassObj {
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并 class
|
||||
* @param customClass vue class
|
||||
* @returns
|
||||
* 合并多个 Vue class 值为一个对象
|
||||
*
|
||||
* 将多个 Vue class(字符串、数组或对象)统一转换为对象后合并,
|
||||
* 后面的 class 值会覆盖前面的同名属性。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* mergeClass('foo', ['bar'], { baz: true })
|
||||
* // { foo: true, bar: true, baz: true }
|
||||
* ```
|
||||
*
|
||||
* @param customClass 一个或多个 Vue class 值
|
||||
* @returns 合并后的 Vue class 对象
|
||||
*/
|
||||
export function mergeClass(...customClass: CustomClass[]) {
|
||||
return customClass
|
||||
@@ -77,12 +127,21 @@ export function mergeClass(...customClass: CustomClass[]) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送祖先组件事件
|
||||
* @param thisArg 调用的源组件实例
|
||||
* @param componentName 需要触发事件的组件名
|
||||
* @param eventName 事件名称
|
||||
* @param params 参数
|
||||
* @returns
|
||||
* 向上遍历祖先组件,找到指定名称的组件并触发其事件
|
||||
*
|
||||
* 类似 Vue2 的 dispatch 模式,从当前组件开始沿父组件链向上查找,
|
||||
* 直到找到 componentName 匹配的祖先组件,然后触发其指定事件。
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* dispatch(this, 'FormComponent', 'validate', { field: 'name' })
|
||||
* // 向上查找名为 FormComponent 的祖先组件,触发其 validate 事件
|
||||
* ```
|
||||
*
|
||||
* @param thisArg 调用源的组件实例
|
||||
* @param componentName 目标祖先组件的 componentName 选项值
|
||||
* @param eventName 要触发的事件名称
|
||||
* @param params 传递给事件的参数
|
||||
*/
|
||||
export function dispatch(
|
||||
thisArg: ComponentPublicInstance,
|
||||
|
||||
Reference in New Issue
Block a user