admin-vben/src/utils/index.ts

116 lines
3.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'
import type { App, Component } from 'vue'
import { unref } from 'vue'
import { isArray, isObject } from '@/utils/is'
import { cloneDeep, isEqual, mergeWith, unionWith } from 'lodash-es'
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
}
/**
* 递归合并两个对象。
* Recursively merge two objects.
* @param target 目标对象合并后结果存放于此。The target object to merge into.
* @param source 要合并的源对象。The source object to merge from.
* @returns 合并后的对象。The merged object.
*/
export function deepMerge<T extends object | null | undefined, U extends object | null | undefined>(target: T, source: U): T & U {
return mergeWith(cloneDeep(target), source, (objValue, srcValue) => {
if (isObject(objValue) && isObject(srcValue)) {
return mergeWith(cloneDeep(objValue), srcValue, (prevValue, nextValue) => {
// 如果是数组,合并数组(去重) If it is an array, merge the array (remove duplicates)
return isArray(prevValue) ? unionWith(prevValue, nextValue, isEqual) : undefined
})
}
})
}
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<T extends Record<string, unknown>, U>(props: T): Partial<U> {
const ret: Recordable = {}
Object.keys(props).map((key) => {
ret[key] = unref((props as Recordable)[key])
})
return ret as Partial<U>
}
export function getRawRoute(route: RouteLocationNormalized): RouteLocationNormalized {
if (!route) return route
const { matched, ...opt } = route
return {
...opt,
matched: (matched
? matched.map((item) => ({
meta: item.meta,
name: item.name,
path: item.path
}))
: undefined) as RouteRecordNormalized[]
}
}
// https://github.com/vant-ui/vant/issues/8302
type EventShim = {
new (...args: any[]): {
$props: {
onClick?: (...args: any[]) => void
}
}
}
export type WithInstall<T> = T & {
install(app: App): void
} & EventShim
export type CustomComponent = Component & { displayName?: string }
export const withInstall = <T extends CustomComponent>(component: T, alias?: string) => {
;(component as Record<string, unknown>).install = (app: App) => {
const compName = component.name || component.displayName
if (!compName) return
app.component(compName, component)
if (alias) {
app.config.globalProperties[alias] = component
}
}
return component as WithInstall<T>
}