Files
TeyvatGuide/src/utils/toolFunc.ts
2024-06-26 22:41:25 +08:00

225 lines
6.4 KiB
TypeScript

/**
* @file utils/toolFunc.ts
* @description 一些工具函数
* @since Beta v0.4.1
*/
import { os, path } from "@tauri-apps/api";
import colorConvert from "color-convert";
import type { KEYWORD } from "color-convert/conversions.js";
import { v4 } from "uuid";
import { score } from "wcag-color";
/**
* @description 时间戳转换为时间字符串
* @returns {string} 时间字符串 d天 hh:mm:ss
* @param time
*/
export function stamp2LastTime(time: number): string {
const day = Math.floor(time / (24 * 3600 * 1000));
const hour = Math.floor((time % (24 * 3600 * 1000)) / (3600 * 1000));
const minute = Math.floor((time % (3600 * 1000)) / (60 * 1000));
const second = Math.floor((time % (60 * 1000)) / 1000);
return `${day === 0 ? "" : `${day}`} ${hour.toFixed(0).padStart(2, "0")}:${minute
.toFixed(0)
.padStart(2, "0")}:${second.toFixed(0).padStart(2, "0")}`;
}
/**
* @description 时间戳转换为日期
* @since Alpha v0.2.3
* @param {number} timestamp - 时间戳(毫秒)
* @returns {string} 日期 2021-01-01 00:00:00
*/
export function timestampToDate(timestamp: number): string {
return new Date(timestamp).toLocaleString("zh", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});
}
/**
* @description 获取当前时间, YY-MM-DD HH:MM:SS
* @since Beta v0.3.6
* @returns {string} 当前时间
*/
export function getNowStr(): string {
const now = new Date();
const year = now.getFullYear();
const month = (now.getMonth() + 1).toString().padStart(2, "0");
const date = now.getDate().toString().padStart(2, "0");
const hour = now.getHours().toString().padStart(2, "0");
const minute = now.getMinutes().toString().padStart(2, "0");
const second = now.getSeconds().toString().padStart(2, "0");
return `${year}-${month}-${date} ${hour}:${minute}:${second}`;
}
/**
* @description 获取设备信息(初始化时)
* @since Beta v0.4.1
* @returns {TGApp.App.Device.DeviceInfo} 设备信息
*/
export function getInitDeviceInfo(): TGApp.App.Device.DeviceInfo {
return {
device_id: v4(),
product: getRandomString(6, "upperNumber"),
device_name: getRandomString(12, "upperNumber"),
seed_id: v4(),
seed_time: Date.now().toString(),
device_fp: "0000000000000",
};
}
/**
* @description 获取设备信息(登录时)
* @since Beta v0.3.6
* @param {string} key - 设备信息 key
* @returns {string} 设备信息
*/
export function getDeviceInfo(key: "device_id" | "device_fp"): string {
const localDevice = localStorage.getItem("deviceInfo");
let deviceInfo: TGApp.App.Device.DeviceInfo;
if (localDevice === null) {
deviceInfo = getInitDeviceInfo();
localStorage.setItem("deviceInfo", JSON.stringify({ deviceInfo }));
} else {
deviceInfo = JSON.parse(localDevice).deviceInfo;
}
return deviceInfo[key];
}
/**
* @description byte 转成 KB MB GB
* @since Beta v0.3.4
* @param {number} bytes - 字节数
* @returns {string} KB MB GB
*/
export function bytesToSize(bytes: number): string {
if (bytes === 0) return "0 B";
const k = 1024;
const sizes = ["B", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}`;
}
/**
* @description 获取缓存目录
* @since Beta v0.3.4
* @returns {string|string[]} 缓存目录
*/
export async function getCacheDir(): Promise<string[] | false> {
const cacheDir = await path.appCacheDir();
const osType = await os.type();
if (osType === "Windows_NT") {
const cache = `${cacheDir}EBWebview${path.sep}Default${path.sep}Cache`;
const codeCache = `${cacheDir}EBWebview${path.sep}Default${path.sep}Code Cache`;
return [cache, codeCache];
} else if (osType === "Darwin") {
return [`${cacheDir}WebKit`];
}
return false;
}
/**
* @description 获取随机字符串
* @since Beta v0.4.1
* @param {number} length 字符串长度
* @param {string} type
* @returns {string} 随机字符串
*/
export function getRandomString(length: number, type: string = "all"): string {
const char = "abcdefghijklmnopqrstuvwxyz";
const num = "0123456789";
let str: string;
switch (type) {
case "all":
str = char + char.toUpperCase() + num;
break;
case "number":
str = num;
break;
case "lower":
str = char;
break;
case "upper":
str = char.toUpperCase();
break;
case "upperNumber":
str = char.toUpperCase() + num;
break;
case "letter":
str = char + char.toUpperCase();
break;
case "hex":
str = num + "abcdef";
break;
default:
str = char + char.toUpperCase() + num;
}
let res = "";
for (let i = 0; i < length; i++) {
res += str.charAt(Math.floor(Math.random() * str.length));
}
return res;
}
/**
* @description 将颜色转为 hex
* @since Beta v0.3.9
* @param {string} color - 颜色
* @returns {string} hex
*/
function color2Hex(color: string): string {
if (color.startsWith("#")) return color;
if (color.startsWith("rgb")) {
// 正则获取 rgb(0, 0, 0) 或 rgba(0, 0, 0, 0) 或 rgb(0 0 0/0)
const reg = /rgba?\((.*?)\)/;
const match = reg.exec(color);
if (match === null) return "#000000";
const rgb = match[1];
const rgbArr = rgb.split(/[ ,/]/);
if (rgbArr.length < 3) return "#000000";
const r = parseInt(rgbArr[0]);
const g = parseInt(rgbArr[1]);
const b = parseInt(rgbArr[2]);
return colorConvert.rgb.hex([r, g, b]);
}
return colorConvert.keyword.hex(<KEYWORD>color);
}
/**
* @description 判断颜色是否相似
* @since Beta v0.3.9
* @param {string} colorBg - 背景颜色
* @param {string} colorText - 文本颜色
* @returns {boolean} 是否相似
*/
export function isColorSimilar(colorBg: string, colorText: string): boolean {
const hexBg = color2Hex(colorBg);
const hexText = color2Hex(colorText);
return score(hexText, hexBg) === "Fail";
}
/**
* @description 解析带样式的文本
* @since Beta v0.3.8
* @param {string} desc - 带样式的文本
* @returns {string} 解析后的文本
*/
export function parseHtmlText(desc: string): string {
const reg = /<color=(.*?)>(.*?)<\/color>/g;
let match = reg.exec(desc);
while (match !== null) {
const color = match[1];
const text = match[2];
desc = desc.replace(match[0], `<span title="${text}" style="color: ${color}">${text}</span>`);
match = reg.exec(desc);
}
desc = desc.replace(/\\n/g, "<br />");
return desc;
}