123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- import { getUrlType } from './meta';
- // 加载第三方库
- export const loadLib = (() => {
- const cache: Record<string, Promise<void>> = {};
- const load = (
- lib: string,
- success: () => void,
- err: () => void,
- maxReq = 0
- ) => {
- const el = document.createElement("script");
- el.src = lib;
- document.body.appendChild(el);
- el.onload = success;
- el.onerror = () => {
- if (maxReq > 0) {
- load(lib, success, err, --maxReq);
- } else {
- err();
- }
- };
- };
- return (lib: string) => {
- if (!cache[lib]) {
- cache[lib] = new Promise((resolve, reject) => {
- load(lib, resolve, reject, 3);
- });
- }
- return cache[lib];
- };
- })();
- export const getSizeStr = (size: number) => {
- let mb = size;
- if (mb < 1024) {
- return `${mb.toFixed(2)}BYTE`;
- }
- mb /= 1024;
- if (mb < 1024) {
- return `${mb.toFixed(2)}KB`;
- }
- mb /= 1024;
- if (mb < 1024) {
- return `${mb.toFixed(2)}MB`;
- }
- mb /= 1024;
- if (mb < 1024) {
- return `${mb.toFixed(2)}GB`;
- }
- mb /= 1024;
- return `${mb.toFixed(2)}TB`;
- };
- // 日期格式化
- export const formatDate = (date: Date, fmt: string = 'yyyy-MM-dd hh:mm') => {
- const map = {
- 'M+': date.getMonth() + 1, //月份
- 'd+': date.getDate(), //日
- 'h+': date.getHours(), //小时
- 'm+': date.getMinutes(), //分
- 's+': date.getSeconds(), //秒
- 'q+': Math.floor((date.getMonth() + 3) / 3), //季度
- S: date.getMilliseconds() //毫秒
- }
- if (/(y+)/.test(fmt)) {
- fmt = fmt.replace(
- RegExp.$1,
- date
- .getFullYear()
- .toString()
- .substr(4 - RegExp.$1.length)
- )
- }
- ;(Object.keys(map) as Array<keyof typeof map>).forEach(k => {
- if (new RegExp('(' + k + ')').test(fmt)) {
- const val = map[k].toString()
- fmt = fmt.replace(
- RegExp.$1,
- RegExp.$1.length === 1 ? val : ('00' + val).substr(val.length)
- )
- }
- })
- return fmt
- }
- export const togetherCallback = (cbs: (() => void)[]) => () => together(cbs)
- export const together = (cbs: (() => void)[]) => {
- cbs.forEach(cb => cb())
- }
- export const getFileUrl = (file: LocalFile | string) =>
- typeof file === 'string'
- ? file
- : file.url
- export const getFileName = (file: any): string => {
- return typeof file === 'string'
- ? file.substring(file.lastIndexOf('/') + 1)
- : file.blob instanceof File ? file.blob.name : getUrlType(file.url)
- }
- export const asyncTimeout = (mis: number = 0) => new Promise(resolve => setTimeout(resolve, mis))
- export const jsonToForm = (data: { [key in string]: any }) => {
- const formData = new FormData()
- for (const [key, val] of Object.entries(data)) {
- if (Array.isArray(val)) {
- for (let i = 0; i < val.length; i++) {
- formData.append(`${key}`, val[i])
- }
- } else {
- formData.append(key, val)
- }
- }
- return formData
- }
- // 防抖
- export const debounce = <T extends (...args: any) => any>(
- fn: T,
- delay: number = 160
- ) => {
- let timeout: any;
- return function (...args: Parameters<T>) {
- clearTimeout(timeout);
- timeout = setTimeout(() => {
- fn.apply(null, args);
- }, delay);
- };
- };
- // 防抖
- export const debounceStack = <T extends (...args: any) => any>(
- fn: T,
- success: (data: ReturnType<T> extends Promise<infer P> ? P : ReturnType<T>) => void,
- delay: number = 160
- ) => {
- let dsToken = 0
- return debounce(async (...args: Parameters<T>) => {
- ++dsToken
- const currentToken = dsToken
- const result = await fn.apply(null, args);
- if (currentToken === dsToken) {
- success(result)
- }
- }, delay)
- };
- // 四舍五入保留指定位数
- export const round = (num: number, index: number = 2) => {
- const s = Math.pow(10, index)
- return Math.round(num * s) / s
- }
- export * from './store-help'
- export * from "./stack";
- export * from "./loading";
- export * from "./route";
- export * from "./asyncBus";
- export * from './mount'
- export * from './watch'
- export * from './diff'
- export * from './params'
- export * from './file-serve'
- export * from './video-cover'
- export * from './meta'
- function randomWord(randomFlag: boolean, min: number, max?: number) {
- let str = "";
- let range = min;
- const arr = [
- "0",
- "1",
- "2",
- "3",
- "4",
- "5",
- "6",
- "7",
- "8",
- "9",
- "a",
- "b",
- "c",
- "d",
- "e",
- "f",
- "g",
- "h",
- "i",
- "j",
- "k",
- "l",
- "m",
- "n",
- "o",
- "p",
- "q",
- "r",
- "s",
- "t",
- "u",
- "v",
- "w",
- "x",
- "y",
- "z",
- "A",
- "B",
- "C",
- "D",
- "E",
- "F",
- "G",
- "H",
- "I",
- "J",
- "K",
- "L",
- "M",
- "N",
- "O",
- "P",
- "Q",
- "R",
- "S",
- "T",
- "U",
- "V",
- "W",
- "X",
- "Y",
- "Z",
- ];
- // 随机产生
- if (randomFlag && max) {
- range = Math.round(Math.random() * (max - min)) + min;
- }
- for (let i = 0; i < range; i++) {
- const pos = Math.round(Math.random() * (arr.length - 1));
- str += arr[pos];
- }
- return str;
- }
- import { Base64 } from "js-base64";
- /**
- * 密码加密
- * @param {String} pwd
- */
- export function encodePwd(str: string, strv: string): string[];
- export function encodePwd(str: string): string;
- export function encodePwd(str: string, strv = "") {
- str = Base64.encode(str);
- const NUM = 2;
- const front = randomWord(false, 8);
- const middle = randomWord(false, 8);
- const end = randomWord(false, 8);
- const str1 = str.substring(0, NUM);
- const str2 = str.substring(NUM);
- if (strv) {
- const strv1 = strv.substring(0, NUM);
- const strv2 = strv.substring(NUM);
- return [
- front + str2 + middle + str1 + end,
- front + strv2 + middle + strv1 + end,
- ];
- }
- return front + str2 + middle + str1 + end;
- }
- /**
- * 判断是否为 Firefox 且版本小于 targetVersion(如 "115.9")
- * @param {string} targetVersion - 目标版本字符串,例如 "115.9"
- * @returns {boolean}
- */
- export function isFirefoxBelow(targetVersion = "115.9") {
- // 尝试使用 navigator.userAgentData (更现代) 如果可用且包含 brands
- // 注意:userAgentData.brand/version 可能随浏览器策略返回受限信息
- const navigator = window.navigator as any
- if (navigator.userAgentData && Array.isArray(navigator.userAgentData.brands)) {
- // brands 形如 [{brand: "Chromium", version: "116"}, ...] 或可能被 UA 凭空
- for (const b of navigator.userAgentData.brands) {
- if (typeof b.brand === "string" && /firefox/i.test(b.brand)) {
- const ver = b.version || "";
- return compareVersionStrings(ver, targetVersion) < 0;
- }
- }
- }
- // 回退到 userAgent 字符串
- const ua = navigator.userAgent || "";
- // Firefox 的 UA 通常包含 "Firefox/<version>"
- const m = ua.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/i);
- if (m && m[1]) {
- const ver = m[1];
- return compareVersionStrings(ver, targetVersion) < 0;
- }
- // 不是 Firefox 或版本未知
- return false;
- }
- /**
- * 比较两个版本字符串(如 "115.9.1" 与 "115.9")
- * 返回:
- * -1 如果 v1 < v2
- * 0 如果 v1 == v2
- * 1 如果 v1 > v2
- */
- function compareVersionStrings(v1: string, v2: string) {
- const seg1 = String(v1).split('.').map(s => parseInt(s, 10) || 0);
- const seg2 = String(v2).split('.').map(s => parseInt(s, 10) || 0);
- const len = Math.max(seg1.length, seg2.length);
- for (let i = 0; i < len; i++) {
- const a = seg1[i] || 0;
- const b = seg2[i] || 0;
- if (a < b) return -1;
- if (a > b) return 1;
- }
- return 0;
- }
|