375 lines
7.2 KiB
JavaScript
375 lines
7.2 KiB
JavaScript
/**
|
|
* 限制数字大小
|
|
* @param {*} num
|
|
* @param {*} min
|
|
* @param {*} max
|
|
* @returns
|
|
*/
|
|
export const limitNumber = (num, min = 0, max = 100) => {
|
|
const number = parseInt(num);
|
|
if (Number.isNaN(number) || number < min) {
|
|
return min;
|
|
} else if (number > max) {
|
|
return max;
|
|
}
|
|
return number;
|
|
};
|
|
|
|
export const limitFloat = (num, min = 0, max = 100) => {
|
|
const number = parseFloat(num);
|
|
if (Number.isNaN(number) || number < min) {
|
|
return min;
|
|
} else if (number > max) {
|
|
return max;
|
|
}
|
|
return number;
|
|
};
|
|
|
|
/**
|
|
* 匹配是否为数组中的值
|
|
* @param {*} arr
|
|
* @param {*} val
|
|
* @returns
|
|
*/
|
|
export const matchValue = (arr, val) => {
|
|
if (arr.length === 0 || arr.includes(val)) {
|
|
return val;
|
|
}
|
|
return arr[0];
|
|
};
|
|
|
|
/**
|
|
* 等待
|
|
* @param {*} delay
|
|
* @returns
|
|
*/
|
|
export const sleep = (delay) =>
|
|
new Promise((resolve) => {
|
|
const timer = setTimeout(() => {
|
|
clearTimeout(timer);
|
|
resolve();
|
|
}, delay);
|
|
});
|
|
|
|
/**
|
|
* 防抖函数
|
|
* @param {*} func
|
|
* @param {*} delay
|
|
* @returns
|
|
*/
|
|
export const debounce = (func, delay = 200) => {
|
|
let timer = null;
|
|
return (...args) => {
|
|
timer && clearTimeout(timer);
|
|
timer = setTimeout(() => {
|
|
func(...args);
|
|
clearTimeout(timer);
|
|
timer = null;
|
|
}, delay);
|
|
};
|
|
};
|
|
|
|
/**
|
|
* 节流函数
|
|
* @param {*} func
|
|
* @param {*} delay
|
|
* @returns
|
|
*/
|
|
export const throttle = (func, delay = 200) => {
|
|
let timer = null;
|
|
let cache = null;
|
|
return (...args) => {
|
|
if (!timer) {
|
|
func(...args);
|
|
cache = null;
|
|
timer = setTimeout(() => {
|
|
if (cache) {
|
|
func(...cache);
|
|
cache = null;
|
|
}
|
|
clearTimeout(timer);
|
|
timer = null;
|
|
}, delay);
|
|
} else {
|
|
cache = args;
|
|
}
|
|
};
|
|
};
|
|
|
|
/**
|
|
* 判断字符串全是某个字符
|
|
* @param {*} s
|
|
* @param {*} c
|
|
* @param {*} i
|
|
* @returns
|
|
*/
|
|
export const isAllchar = (s, c, i = 0) => {
|
|
while (i < s.length) {
|
|
if (s[i] !== c) {
|
|
return false;
|
|
}
|
|
i++;
|
|
}
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* 字符串通配符(*)匹配
|
|
* @param {*} s
|
|
* @param {*} p
|
|
* @returns
|
|
*/
|
|
export const isMatch = (s, p) => {
|
|
if (s.length === 0 || p.length === 0) {
|
|
return false;
|
|
}
|
|
|
|
p = "*" + p + "*";
|
|
|
|
let [sIndex, pIndex] = [0, 0];
|
|
let [sRecord, pRecord] = [-1, -1];
|
|
while (sIndex < s.length && pRecord < p.length) {
|
|
if (p[pIndex] === "*") {
|
|
pIndex++;
|
|
[sRecord, pRecord] = [sIndex, pIndex];
|
|
} else if (s[sIndex] === p[pIndex]) {
|
|
sIndex++;
|
|
pIndex++;
|
|
} else if (sRecord + 1 < s.length) {
|
|
sRecord++;
|
|
[sIndex, pIndex] = [sRecord, pRecord];
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (p.length === pIndex) {
|
|
return true;
|
|
}
|
|
|
|
return isAllchar(p, "*", pIndex);
|
|
};
|
|
|
|
/**
|
|
* 类型检查
|
|
* @param {*} o
|
|
* @returns
|
|
*/
|
|
export const type = (o) => {
|
|
const s = Object.prototype.toString.call(o);
|
|
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
|
|
};
|
|
|
|
/**
|
|
* sha256
|
|
* @param {*} text
|
|
* @returns
|
|
*/
|
|
export const sha256 = async (text, salt) => {
|
|
const data = new TextEncoder().encode(text + salt);
|
|
const digest = await crypto.subtle.digest({ name: "SHA-256" }, data);
|
|
return [...new Uint8Array(digest)]
|
|
.map((b) => b.toString(16).padStart(2, "0"))
|
|
.join("");
|
|
};
|
|
|
|
/**
|
|
* 生成随机事件名称
|
|
* @returns
|
|
*/
|
|
export const genEventName = () => `kiss-${btoa(Math.random()).slice(3, 11)}`;
|
|
|
|
/**
|
|
* 判断两个 Set 是否相同
|
|
* @param {*} a
|
|
* @param {*} b
|
|
* @returns
|
|
*/
|
|
export const isSameSet = (a, b) => {
|
|
const s = new Set([...a, ...b]);
|
|
return s.size === a.size && s.size === b.size;
|
|
};
|
|
|
|
/**
|
|
* 去掉字符串末尾某个字符
|
|
* @param {*} s
|
|
* @param {*} c
|
|
* @param {*} count
|
|
* @returns
|
|
*/
|
|
export const removeEndchar = (s, c, count = 1) => {
|
|
if (!s) return "";
|
|
|
|
let i = s.length;
|
|
while (i > s.length - count && s[i - 1] === c) {
|
|
i--;
|
|
}
|
|
return s.slice(0, i);
|
|
};
|
|
|
|
/**
|
|
* 匹配字符串及语言标识
|
|
* @param {*} str
|
|
* @param {*} sign
|
|
* @returns
|
|
*/
|
|
export const matchInputStr = (str, sign) => {
|
|
switch (sign) {
|
|
case "//":
|
|
return str.match(/\/\/([\w-]+)\s+([^]+)/);
|
|
case "\\":
|
|
return str.match(/\\([\w-]+)\s+([^]+)/);
|
|
case "\\\\":
|
|
return str.match(/\\\\([\w-]+)\s+([^]+)/);
|
|
case ">":
|
|
return str.match(/>([\w-]+)\s+([^]+)/);
|
|
case ">>":
|
|
return str.match(/>>([\w-]+)\s+([^]+)/);
|
|
default:
|
|
}
|
|
return str.match(/\/([\w-]+)\s+([^]+)/);
|
|
};
|
|
|
|
/**
|
|
* 判断是否英文单词
|
|
* @param {*} str
|
|
* @returns
|
|
*/
|
|
export const isValidWord = (str) => {
|
|
const regex = /^[a-zA-Z-]+$/;
|
|
return regex.test(str);
|
|
};
|
|
|
|
/**
|
|
* blob转为base64
|
|
* @param {*} blob
|
|
* @returns
|
|
*/
|
|
export const blobToBase64 = (blob) => {
|
|
return new Promise((resolve) => {
|
|
const reader = new FileReader();
|
|
reader.onloadend = () => resolve(reader.result);
|
|
reader.readAsDataURL(blob);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* 获取html内的文本
|
|
* @param {*} htmlStr
|
|
* @param {*} skipTag
|
|
* @returns
|
|
*/
|
|
export const getHtmlText = (htmlStr, skipTag = "") => {
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(htmlStr, "text/html");
|
|
|
|
if (skipTag) {
|
|
doc.querySelectorAll(skipTag).forEach((el) => el.remove());
|
|
}
|
|
|
|
return doc.body.innerText.trim();
|
|
};
|
|
|
|
/**
|
|
* 解析JSON字符串对象
|
|
* @param {*} str
|
|
* @returns
|
|
*/
|
|
export const parseJsonObj = (str) => {
|
|
if (!str || type(str) !== "string") {
|
|
return {};
|
|
}
|
|
|
|
try {
|
|
if (str.trim()[0] !== "{") {
|
|
str = `{${str}}`;
|
|
}
|
|
return JSON.parse(str);
|
|
} catch (err) {
|
|
//
|
|
}
|
|
|
|
return {};
|
|
};
|
|
|
|
/**
|
|
* 提取json内容
|
|
* @param {*} s
|
|
* @returns
|
|
*/
|
|
export const extractJson = (raw) => {
|
|
const jsonRegex = /({.*}|\[.*\])/s;
|
|
const match = raw.match(jsonRegex);
|
|
return match ? match[0] : null;
|
|
};
|
|
|
|
/**
|
|
* 空闲执行
|
|
* @param {*} cb
|
|
* @param {*} timeout
|
|
* @returns
|
|
*/
|
|
export const scheduleIdle = (cb, timeout = 200) => {
|
|
if (window.requestIdleCallback) {
|
|
return requestIdleCallback(cb, { timeout });
|
|
}
|
|
return setTimeout(cb, timeout);
|
|
};
|
|
|
|
/**
|
|
* 截取url部分
|
|
* @param {*} href
|
|
* @returns
|
|
*/
|
|
export const parseUrlPattern = (href) => {
|
|
if (href.startsWith("file")) {
|
|
const filename = href.substring(href.lastIndexOf("/") + 1);
|
|
return filename;
|
|
} else if (href.startsWith("http")) {
|
|
const url = new URL(href);
|
|
return url.host;
|
|
}
|
|
return href;
|
|
};
|
|
|
|
/**
|
|
* 带超时的任务
|
|
* @param {Promise|Function} task - 任务
|
|
* @param {number} timeout - 超时时间 (毫秒)
|
|
* @param {string} [timeoutMsg] - 超时错误提示
|
|
* @returns {Promise}
|
|
*/
|
|
export const withTimeout = (task, timeout, timeoutMsg = "Task timed out") => {
|
|
const promise = typeof task === "function" ? task() : task;
|
|
return Promise.race([
|
|
promise,
|
|
new Promise((_, reject) =>
|
|
setTimeout(() => reject(new Error(timeoutMsg)), timeout)
|
|
),
|
|
]);
|
|
};
|
|
|
|
/**
|
|
* 截短字符串
|
|
* @param {*} str
|
|
* @param {*} maxLength
|
|
* @returns
|
|
*/
|
|
export const truncateWords = (str, maxLength) => {
|
|
if (str.length <= maxLength) return str;
|
|
const truncated = str.slice(0, maxLength);
|
|
return truncated.slice(0, truncated.lastIndexOf(" ")) + " …";
|
|
};
|
|
|
|
/**
|
|
* 生成随机数
|
|
* @param {*} min
|
|
* @param {*} max
|
|
* @param {*} integer
|
|
* @returns
|
|
*/
|
|
export const randomBetween = (min, max, integer = true) => {
|
|
const value = Math.random() * (max - min) + min;
|
|
return integer ? Math.floor(value) : value;
|
|
};
|