7 解构出的Api
ProxyOptions
import type { ProxyOptions } from 'vite';
import { InjectionKey, Ref } from 'vue'; import { createContext, useContext } from '/@/hooks/core/useContext'; export interface AppProviderContextProps { prefixCls: Ref<string>; isMobile: Ref<boolean>; } const key: InjectionKey<AppProviderContextProps> = Symbol(); export function createAppProviderContext(context: AppProviderContextProps) { return createContext<AppProviderContextProps>(context, key); } export function useAppProviderContext() { return useContext<AppProviderContextProps>(key); }
import type { CSSProperties, PropType } from 'vue';
import type { FunctionalComponent, CSSProperties } from 'vue';
const menuManager: { domList: Element[]; resolve: Fn; } = { domList: [], resolve: () => {}, };
const propsData: Partial<ContextMenuProps> = {};
const propsData: Partial<ContextMenuProps> = {};
let timerId: ReturnType<typeof setInterval> | null;
import type { CSSProperties } from 'vue';
import { useAttrs } from '/@/hooks/core/useAttrs';
import type { Directive, App } from 'vue'; const loadingDirective: Directive = { mounted(el, binding) { const tip = el.getAttribute('loading-tip'); const background = el.getAttribute('loading-background'); const size = el.getAttribute('loading-size'); const fullscreen = !!binding.modifiers.fullscreen; const instance = createLoading( { tip, background, size: size || 'large', loading: !!binding.value, absolute: !fullscreen, }, fullscreen ? document.body : el ); el.instance = instance; }, updated(el, binding) { const instance = el.instance; if (!instance) return; instance.setTip(el.getAttribute('loading-tip')); if (binding.oldValue !== binding.value) { if (binding.oldValue !== binding.value) { instance.setLoading?.(binding.value && !instance.loading); } } }, unmounted(el) { el?.instance?.close(); }, };
const mounted = (el: Element, binding: DirectiveBinding<any>) => { isAuth(el, binding); };
import type { InjectionKey, ComputedRef, Ref } from 'vue'; import { createContext, useContext } from '/@/hooks/core/useContext'; export interface PageContextProps { contentHeight: ComputedRef<number>; pageHeight: Ref<number>; setPageHeight: (height: number) => Promise<void>; } const key: InjectionKey<PageContextProps> = Symbol(); export function createPageContext(context: PageContextProps) { return createContext<PageContextProps>(context, key, { native: true }); } export function usePageContext() { return useContext<PageContextProps>(key); }
export function entries<T>(obj: Recordable<T>): [string, T][] { return Object.keys(obj).map((key: string) => [key, obj[key]]); }
8 公共函数
isDevFn
export function isDevFn(mode: string): boolean { return mode === 'development'; }
wrapperEnv
/** * @description 转换从 .env 文件中获取的对象 * @author wfd * @date 2021/10/8 09:30 * @param envConf */ export function wrapperEnv(envConf: Recordable): ViteEnv { // 创建一个对象来存储转换的键值 const ret: any = {}; /** * @description wrapperEnv * @author wfd * @date 2021/10/8 14:19 * @example * Object.keys(envConf) = [ 'VITE_USE_MOCK', 'VITE_PUBLIC_PATH', 'VITE_PROXY', 'VITE_DROP_CONSOLE', 'VITE_GLOB_API_URL', 'VITE_GLOB_UPLOAD_URL', 'VITE_GLOB_API_URL_PREFIX', 'VITE_PORT', 'VITE_GLOB_APP_TITLE', 'VITE_GLOB_APP_SHORT_NAME' ] */ for (const envName of Object.keys(envConf)) { /** * @description realName 是每一个配置对应的 value 中间的正则替换就是将\\n替换成\n。 console.log('asda\\\n\\n\n'.replace(/\n/g, '\n')) =>asda\ [回车\n] \n [回车\n] console.log('asda\\\n\\n\n'.replace(/\\n/g, '\n'))=>asda\ [回车\n] [回车\n] [回车\n] console.log('asda\\\n\\n\n'.replace(/\\\n/g, '\n'))=>asda [回车\n] \n [回车\n] */ let realName = envConf[envName].replace(/\\n/g, '\n'); // 将 'true' 或者 'false' 的字符串转换为 boolean 对应的 true 或者 false realName = realName === 'true' ? true : realName === 'false' ? false : realName; // 端口转换成 number 类型 if (envName === 'VITE_PORT') { realName = Number(realName); } // 将代理配置转换成数组 if (envName === 'VITE_PROXY' && realName) { try { realName = JSON.parse(realName.replace(/'/g, '"')); } catch (error) { realName = ''; } } // 将转换后的属性值 realName 赋值给 ret 对应的每一个键 ret[envName] = realName; // 将原始的值也就是未转换的值赋值给 process.env if (typeof realName === 'string') { process.env[envName] = realName; } else if (typeof realName === 'object') { process.env[envName] = JSON.stringify(realName); } } return ret; }
getConfFiles
/** * 获取当前环境下生效的配置文件名 */ function getConfFiles() { const script = process.env.npm_lifecycle_script; const reg = new RegExp('--mode ([a-z]+)'); const result = reg.exec(script as string) as any; if (result) { const mode = result[1] as string; return ['.env', `.env.${mode}`]; } return ['.env', '.env.production']; }
getEnvConfig
export function getEnvConfig(match = 'VITE_GLOB_', confFiles = getConfFiles()) { let envConfig = {}; confFiles.forEach((item) => { try { const env = dotenv.parse(fs.readFileSync(path.resolve(process.cwd(), item))); envConfig = { ...envConfig, ...env }; } catch (e) { console.error(`Error in parsing ${item}`, e); } }); const reg = new RegExp(`^(${match})`); Object.keys(envConfig).forEach((key) => { if (!reg.test(key)) { Reflect.deleteProperty(envConfig, key); } }); return envConfig; }
resultSuccess
export function resultSuccess<T = Recordable>(result: T, { message = 'ok' } = {}) { return { code: 0, result, message, type: 'success', }; }
resultPageSuccess
export function resultPageSuccess<T = any>( page: number, pageSize: number, list: T[], { message = 'ok' } = {} ) { const pageData = pagination(page, pageSize, list); \ return { ...resultSuccess({ items: pageData, total: list.length, }), message, }; }
resultError
export function resultError(message = 'Request failed', { code = -1, result = null } = {}) { return { code, result, message, type: 'error', }; }
pagination
export function pagination<T = any>(pageNo: number, pageSize: number, array: T[]): T[] { const offset = (pageNo - 1) * Number(pageSize); const ret = offset + Number(pageSize) >= array.length ? array.slice(offset, array.length) : array.slice(offset, offset + Number(pageSize)); return ret; }
requestParams
export interface requestParams { method: string; body: any; headers?: { authorization?: string }; query: any; }
getRequestToken
/** * @description 本函数用于从request数据中获取token,请根据项目的实际情况修改 * */ export function getRequestToken({ headers }: requestParams): string | undefined { return headers?.authorization; }
getRootPath
export function getRootPath(...dir: string[]) { return path.resolve(process.cwd(), ...dir); }
withInstall
export const withInstall = <T>(component: T, alias?: string) => { const comp = component as any; comp.install = (app: App) => { app.component(comp.name || comp.displayName, component); if (alias) { app.config.globalProperties[alias] = component; } }; return component as T & Plugin; };
isHexColor
/** * 判断是否 十六进制颜色值. * 输入形式可为 #fff000 #f00 * * @param String color 十六进制颜色值 * @return Boolean */ export function isHexColor(color: string) { const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/; return reg.test(color); }
rgbToHex
/** * RGB 颜色值转换为 十六进制颜色值. * r, g, 和 b 需要在 [0, 255] 范围内 * * @return String 类似#ff00ff * @param r * @param g * @param b */ export function rgbToHex(r: number, g: number, b: number) { // tslint:disable-next-line:no-bitwise const hex = ((r << 16) | (g << 8) | b).toString(16); return '#' + new Array(Math.abs(hex.length - 7)).join('0') + hex; }
hexToRGB
/** * Transform a HEX color to its RGB representation * @param {string} hex The color to transform * @returns The RGB representation of the passed color */ export function hexToRGB(hex: string) { let sHex = hex.toLowerCase(); if (isHexColor(hex)) { if (sHex.length === 4) { let sColorNew = '#'; for (let i = 1; i < 4; i += 1) { sColorNew += sHex.slice(i, i + 1).concat(sHex.slice(i, i + 1)); } sHex = sColorNew; } const sColorChange: number[] = []; for (let i = 1; i < 7; i += 2) { sColorChange.push(parseInt('0x' + sHex.slice(i, i + 2))); } return 'RGB(' + sColorChange.join(',') + ')'; } return sHex; }
colorIsDark
export function colorIsDark(color: string) { if (!isHexColor(color)) return; const [r, g, b] = hexToRGB(color) .replace(/(?:\(|\)|rgb|RGB)*/g, '') .split(',') .map((item) => Number(item)); return r * 0.299 + g * 0.578 + b * 0.114 < 192; }
darken
/** * Darkens a HEX color given the passed percentage * @param {string} color The color to process * @param {number} amount The amount to change the color by * @returns {string} The HEX representation of the processed color */ export function darken(color: string, amount: number) { color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color; amount = Math.trunc((255 * amount) / 100); return `#${subtractLight(color.substring(0, 2), amount)}${subtractLight( color.substring(2, 4), amount )}${subtractLight(color.substring(4, 6), amount)}`; }
lighten
/** * Lightens a 6 char HEX color according to the passed percentage * @param {string} color The color to change * @param {number} amount The amount to change the color by * @returns {string} The processed color represented as HEX */ export function lighten(color: string, amount: number) { color = color.indexOf('#') >= 0 ? color.substring(1, color.length) : color; amount = Math.trunc((255 * amount) / 100); return `#${addLight(color.substring(0, 2), amount)}${addLight( color.substring(2, 4), amount )}${addLight(color.substring(4, 6), amount)}`; }
addLight
/* Suma el porcentaje indicado a un color (RR, GG o BB) hexadecimal para aclararlo */ /** * Sums the passed percentage to the R, G or B of a HEX color * @param {string} color The color to change * @param {number} amount The amount to change the color by * @returns {string} The processed part of the color */ function addLight(color: string, amount: number) { const cc = parseInt(color, 16) + amount; const c = cc > 255 ? 255 : cc; return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`; }
luminanace
/** * Calculates luminance of an rgb color * @param {number} r red * @param {number} g green * @param {number} b blue */ function luminanace(r: number, g: number, b: number) { const a = [r, g, b].map((v) => { v /= 255; return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4); }); return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; }
contrast
/** * Calculates contrast between two rgb colors * @param {string} rgb1 rgb color 1 * @param {string} rgb2 rgb color 2 */ function contrast(rgb1: string[], rgb2: number[]) { return ( (luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) / (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05) ); }
calculateBestTextColor
/** * Determines what the best text color is (black or white) based con the contrast with the background * @param hexColor - Last selected color by the user */ export function calculateBestTextColor(hexColor: string) { const rgbColor = hexToRGB(hexColor.substring(1)); const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0]); \ return contrastWithBlack >= 12 ? '#000000' : '#FFFFFF'; }
subtractLight
/** * Subtracts the indicated percentage to the R, G or B of a HEX color * @param {string} color The color to change * @param {number} amount The amount to change the color by * @returns {string} The processed part of the color */ function subtractLight(color: string, amount: number) { const cc = parseInt(color, 16) - amount; const c = cc < 0 ? 0 : cc; return c.toString(16).length > 1 ? c.toString(16) : `0${c.toString(16)}`; }