import type { App, DefineComponent, Plugin, Ref } from 'vue'; import { unref } from 'vue'; import { isObject } from './is'; export const noop = () => {}; /** * @description: Set ui mount node */ export function getPopupContainer(node?: HTMLElement): HTMLElement { return (node?.parentNode as HTMLElement) ?? document.body; } /** * Add the object as a parameter to the URL * @param baseUrl url * @param obj * @returns {string} * eg: * let obj = {a: '3', b: '4'} * setObjToUrlParams('www.baidu.com', obj) * ==>www.baidu.com?a=3&b=4 */ export function setObjToUrlParams(baseUrl: string, obj: any): string { let parameters = ''; for (const key in obj) { parameters += key + '=' + encodeURIComponent(obj[key]) + '&'; } parameters = parameters.replace(/&$/, ''); return /\?$/.test(baseUrl) ? baseUrl + parameters : baseUrl.replace(/\/?$/, '?') + parameters; } export function deepMerge(src: T, target: object = {}): T { let key: string; for (key in target) { src[key] = isObject(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key]); } return src; } export function openWindow( url: string, opt?: { target?: TargetContext | string; noopener?: boolean; noreferrer?: boolean; }, ) { const { target = '__blank', noopener = true, noreferrer = true } = opt || {}; const feature: string[] = []; noopener && feature.push('noopener=yes'); noreferrer && feature.push('noreferrer=yes'); window.open(url, target, feature.join(','))!; } // dynamic use hook props export function getDynamicProps(props: T): Partial { const ret: Recordable = {}; Object.keys(props).map((key) => { ret[key] = unref((props as Recordable)[key]); }); return ret as Partial; } export const withInstall = >( component: T, alias?: string, ) => { Reflect.defineProperty(component, 'install', (app: App) => { app.component(component.name || component.displayName, component); if (alias) { app.config.globalProperties[alias] = component; } }); return component as T & Plugin; }; /** * @description:生成唯一字段 */ export function getUniqueField(usedStr: Ref): string { // 可用字段 const fieldStr = 'abcdefghijklmnopqrstuvwxyz'; const len = usedStr.value.length; let field = ''; if (len === 0) { field = 'a'; } else { // 最后一个已用字段 const last = usedStr.value[len - 1]; const fieldLen = last.length; // 最后一个已用字段的最后一个字符在fieldStr中的序号 const index = fieldStr.indexOf(last[fieldLen - 1]); if (index > -1 && index < 25) { field = last.slice(0, fieldLen - 1) + fieldStr.charAt(index + 1); } else { field = new Array(fieldLen + 1).fill('a').join(''); } } usedStr.value.push(field); return field; } /** * * @param asyncFunc 传入一个异步任务 * @param timeout 一个毫秒数 * @description 至少执行时长为timeout */ export function atLeast(asyncFunc: () => Promise, timeout = 1000) { function timer() { return new Promise((r) => { setTimeout(() => { r(null); }, timeout); }); } return new Promise((resolve, reject) => { // 计时器是否结束 let timeup = false; timer().then(() => { timeup = true; if (resolved) { resolve(result); } }); // 异步任务的结果 let result: T; // 异步任务是否结束 let resolved = false; asyncFunc() .then((res) => { result = res; resolved = true; if (timeup) { resolve(res); } }) .catch((err) => { reject(err); }); }); } export * as AuthUtil from './auth'; export * as CipherUtil from './cipher'; export * as ColorUtil from './color'; export * as DateUtil from './dateUtil'; export * as DomUtil from './domUtils'; export * as IsUtil from './is'; export * as LogUtil from './log'; export * as MittUtil from './mitt'; export * as UuidUtil from './uuid'; export * as FileUtil from './file'; export * as StorageCacheUtil from './storageCache'; export * as HelperUtil from './helper';