feat(Breadcrumbe): Add Breadcrumb component

style: change function to arrow function
This commit is contained in:
kailong321200875
2022-01-15 14:24:50 +08:00
parent 2fe9543b84
commit 4612e5544b
55 changed files with 586 additions and 270 deletions

View File

@@ -5,7 +5,7 @@
* @param String color 十六进制颜色值
* @return Boolean
*/
export function isHexColor(color: string) {
export const isHexColor = (color: string) => {
const reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-f]{6})$/
return reg.test(color)
}
@@ -19,7 +19,7 @@ export function isHexColor(color: string) {
* @param g
* @param b
*/
export function rgbToHex(r: number, g: number, b: number) {
export const 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
@@ -30,7 +30,7 @@ export function rgbToHex(r: number, g: number, b: number) {
* @param {string} hex The color to transform
* @returns The RGB representation of the passed color
*/
export function hexToRGB(hex: string) {
export const hexToRGB = (hex: string) => {
let sHex = hex.toLowerCase()
if (isHexColor(hex)) {
if (sHex.length === 4) {
@@ -49,7 +49,7 @@ export function hexToRGB(hex: string) {
return sHex
}
export function colorIsDark(color: string) {
export const colorIsDark = (color: string) => {
if (!isHexColor(color)) return
const [r, g, b] = hexToRGB(color)
.replace(/(?:\(|\)|rgb|RGB)*/g, '')
@@ -64,7 +64,7 @@ export function colorIsDark(color: string) {
* @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) {
export const 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(
@@ -79,7 +79,7 @@ export function darken(color: string, amount: number) {
* @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) {
export const 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(
@@ -95,7 +95,7 @@ export function lighten(color: string, amount: number) {
* @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 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)}`
@@ -107,7 +107,7 @@ function addLight(color: string, amount: number) {
* @param {number} g green
* @param {number} b blue
*/
function luminanace(r: number, g: number, b: number) {
const 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)
@@ -120,7 +120,7 @@ function luminanace(r: number, g: number, b: number) {
* @param {string} rgb1 rgb color 1
* @param {string} rgb2 rgb color 2
*/
function contrast(rgb1: string[], rgb2: number[]) {
const contrast = (rgb1: string[], rgb2: number[]) => {
return (
(luminanace(~~rgb1[0], ~~rgb1[1], ~~rgb1[2]) + 0.05) /
(luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05)
@@ -131,7 +131,7 @@ function contrast(rgb1: string[], rgb2: number[]) {
* 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) {
export const calculateBestTextColor = (hexColor: string) => {
const rgbColor = hexToRGB(hexColor.substring(1))
const contrastWithBlack = contrast(rgbColor.split(','), [0, 0, 0])
@@ -144,7 +144,7 @@ export function calculateBestTextColor(hexColor: string) {
* @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 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)}`

View File

@@ -21,7 +21,7 @@ export const withInstall = <T>(component: T, alias?: string) => {
* @param str 需要转下划线的驼峰字符串
* @returns 字符串下划线
*/
export function humpToUnderline(str: string): string {
export const humpToUnderline = (str: string): string => {
return str.replace(/([A-Z])/g, '-$1').toLowerCase()
}
@@ -29,12 +29,12 @@ export function humpToUnderline(str: string): string {
* @param str 需要转驼峰的下划线字符串
* @returns 字符串驼峰
*/
export function underlineToHump(str: string): string {
return str.replace(/\-(\w)/g, function (_, letter: string) {
export const underlineToHump = (str: string): string => {
return str.replace(/\-(\w)/g, (_, letter: string) => {
return letter.toUpperCase()
})
}
export function setCssVar(prop: string, val: any, dom = document.documentElement) {
export const setCssVar = (prop: string, val: any, dom = document.documentElement) => {
dom.style.setProperty(prop, val)
}

View File

@@ -2,23 +2,23 @@
const toString = Object.prototype.toString
export function is(val: unknown, type: string) {
export const is = (val: unknown, type: string) => {
return toString.call(val) === `[object ${type}]`
}
export function isDef<T = unknown>(val?: T): val is T {
export const isDef = <T = unknown>(val?: T): val is T => {
return typeof val !== 'undefined'
}
export function isUnDef<T = unknown>(val?: T): val is T {
export const isUnDef = <T = unknown>(val?: T): val is T => {
return !isDef(val)
}
export function isObject(val: any): val is Record<any, any> {
export const isObject = (val: any): val is Record<any, any> => {
return val !== null && is(val, 'Object')
}
export function isEmpty<T = unknown>(val: T): val is T {
export const isEmpty = <T = unknown>(val: T): val is T => {
if (isArray(val) || isString(val)) {
return val.length === 0
}
@@ -34,59 +34,59 @@ export function isEmpty<T = unknown>(val: T): val is T {
return false
}
export function isDate(val: unknown): val is Date {
export const isDate = (val: unknown): val is Date => {
return is(val, 'Date')
}
export function isNull(val: unknown): val is null {
export const isNull = (val: unknown): val is null => {
return val === null
}
export function isNullAndUnDef(val: unknown): val is null | undefined {
export const isNullAndUnDef = (val: unknown): val is null | undefined => {
return isUnDef(val) && isNull(val)
}
export function isNullOrUnDef(val: unknown): val is null | undefined {
export const isNullOrUnDef = (val: unknown): val is null | undefined => {
return isUnDef(val) || isNull(val)
}
export function isNumber(val: unknown): val is number {
export const isNumber = (val: unknown): val is number => {
return is(val, 'Number')
}
export function isPromise<T = any>(val: unknown): val is Promise<T> {
export const isPromise = <T = any>(val: unknown): val is Promise<T> => {
return is(val, 'Promise') && isObject(val) && isFunction(val.then) && isFunction(val.catch)
}
export function isString(val: unknown): val is string {
export const isString = (val: unknown): val is string => {
return is(val, 'String')
}
export function isFunction(val: unknown): val is Function {
export const isFunction = (val: unknown): val is Function => {
return typeof val === 'function'
}
export function isBoolean(val: unknown): val is boolean {
export const isBoolean = (val: unknown): val is boolean => {
return is(val, 'Boolean')
}
export function isRegExp(val: unknown): val is RegExp {
export const isRegExp = (val: unknown): val is RegExp => {
return is(val, 'RegExp')
}
export function isArray(val: any): val is Array<any> {
export const isArray = (val: any): val is Array<any> => {
return val && Array.isArray(val)
}
export function isWindow(val: any): val is Window {
export const isWindow = (val: any): val is Window => {
return typeof window !== 'undefined' && is(val, 'Window')
}
export function isElement(val: unknown): val is Element {
export const isElement = (val: unknown): val is Element => {
return isObject(val) && !!val.tagName
}
export function isMap(val: unknown): val is Map<any, any> {
export const isMap = (val: unknown): val is Map<any, any> => {
return is(val, 'Map')
}
@@ -94,12 +94,12 @@ export const isServer = typeof window === 'undefined'
export const isClient = !isServer
export function isUrl(path: string): boolean {
export const isUrl = (path: string): boolean => {
const reg =
/(((^https?:(?:\/\/)?)(?:[-:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&%@.\w_]*)#?(?:[\w]*))?)$/
return reg.test(path)
}
export function isDark(): boolean {
export const isDark = (): boolean => {
return window.matchMedia('(prefers-color-scheme: dark)').matches
}

View File

@@ -1,5 +1,5 @@
import { createRouter, createWebHashHistory } from 'vue-router'
import type { Router, RouteLocationNormalized, RouteRecordNormalized } from 'vue-router'
import type { Router, RouteLocationNormalized, RouteRecordNormalized, RouteMeta } from 'vue-router'
import { isUrl } from '@/utils/is'
import { useCache } from '@/hooks/web/useCache'
import { useAppStoreWithOut } from '@/store/modules/app'
@@ -23,7 +23,7 @@ export const getParentLayout = () => {
})
}
export function getRawRoute(route: RouteLocationNormalized): RouteLocationNormalized {
export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => {
if (!route) return route
const { matched, ...opt } = route
return {
@@ -39,15 +39,16 @@ export function getRawRoute(route: RouteLocationNormalized): RouteLocationNormal
}
// 前端控制路由生成
export function generateRoutesFn1(
export const generateRoutesFn1 = (
routes: AppRouteRecordRaw[],
basePath = '/'
): AppRouteRecordRaw[] {
): AppRouteRecordRaw[] => {
const res: AppRouteRecordRaw[] = []
for (const route of routes) {
const meta = route.meta as RouteMeta
// skip some route
if (route.meta && route.meta.hidden && !route.meta.showMainRoute) {
if (meta.hidden && !meta.showMainRoute) {
continue
}
@@ -55,7 +56,7 @@ export function generateRoutesFn1(
let onlyOneChild: Nullable<string> = null
if (route.children && route.children.length === 1 && !route.meta.alwaysShow) {
if (route.children && route.children.length === 1 && !meta.alwaysShow) {
onlyOneChild = (
isUrl(route.children[0].path)
? route.children[0].path
@@ -72,7 +73,7 @@ export function generateRoutesFn1(
data = Object.assign({}, route)
} else {
const routePath = pathResolve(basePath, onlyOneChild || route.path)
if (routePath === item.path || (route.meta && route.meta.followRoute === item.path)) {
if (routePath === item.path || meta.followRoute === item.path) {
data = Object.assign({}, route)
}
}
@@ -90,7 +91,7 @@ export function generateRoutesFn1(
}
// 后端控制路由生成
export function generateRoutesFn2(routes: AppRouteRecordRaw[]): AppRouteRecordRaw[] {
export const generateRoutesFn2 = (routes: AppRouteRecordRaw[]): AppRouteRecordRaw[] => {
const res: AppRouteRecordRaw[] = []
for (const route of routes) {
@@ -121,13 +122,13 @@ export function generateRoutesFn2(routes: AppRouteRecordRaw[]): AppRouteRecordRa
return res
}
export function pathResolve(parentPath: string, path: string) {
export const pathResolve = (parentPath: string, path: string) => {
const childPath = path.startsWith('/') || !path ? path : `/${path}`
return `${parentPath}${childPath}`
}
// 路由降级
export function flatMultiLevelRoutes(routes: AppRouteRecordRaw[]) {
export const flatMultiLevelRoutes = (routes: AppRouteRecordRaw[]) => {
const modules: AppRouteRecordRaw[] = cloneDeep(routes)
for (let index = 0; index < modules.length; index++) {
const route = modules[index]
@@ -140,7 +141,7 @@ export function flatMultiLevelRoutes(routes: AppRouteRecordRaw[]) {
}
// 层级是否大于2
function isMultipleRoute(route: AppRouteRecordRaw) {
const isMultipleRoute = (route: AppRouteRecordRaw) => {
if (!route || !Reflect.has(route, 'children') || !route.children?.length) {
return false
}
@@ -159,7 +160,7 @@ function isMultipleRoute(route: AppRouteRecordRaw) {
}
// 生成二级路由
function promoteRouteLevel(route: AppRouteRecordRaw) {
const promoteRouteLevel = (route: AppRouteRecordRaw) => {
let router: Router | null = createRouter({
routes: [route as unknown as RouteRecordNormalized],
history: createWebHashHistory()
@@ -173,11 +174,11 @@ function promoteRouteLevel(route: AppRouteRecordRaw) {
}
// 添加所有子菜单
function addToChildren(
const addToChildren = (
routes: RouteRecordNormalized[],
children: AppRouteRecordRaw[],
routeModule: AppRouteRecordRaw
) {
) => {
for (let index = 0; index < children.length; index++) {
const child = children[index]
const route = routes.find((item) => item.name === child.name)

207
src/utils/tree.ts Normal file
View File

@@ -0,0 +1,207 @@
interface TreeHelperConfig {
id: string
children: string
pid: string
}
const DEFAULT_CONFIG: TreeHelperConfig = {
id: 'id',
children: 'children',
pid: 'pid'
}
const getConfig = (config: Partial<TreeHelperConfig>) => Object.assign({}, DEFAULT_CONFIG, config)
// tree from list
export const listToTree = <T = any>(list: any[], config: Partial<TreeHelperConfig> = {}): T[] => {
const conf = getConfig(config) as TreeHelperConfig
const nodeMap = new Map()
const result: T[] = []
const { id, children, pid } = conf
for (const node of list) {
node[children] = node[children] || []
nodeMap.set(node[id], node)
}
for (const node of list) {
const parent = nodeMap.get(node[pid])
;(parent ? parent.children : result).push(node)
}
return result
}
export const treeToList = <T = any>(tree: any, config: Partial<TreeHelperConfig> = {}): T => {
config = getConfig(config)
const { children } = config
const result: any = [...tree]
for (let i = 0; i < result.length; i++) {
if (!result[i][children!]) continue
result.splice(i + 1, 0, ...result[i][children!])
}
return result
}
export const findNode = <T = any>(
tree: any,
func: Fn,
config: Partial<TreeHelperConfig> = {}
): T | null => {
config = getConfig(config)
const { children } = config
const list = [...tree]
for (const node of list) {
if (func(node)) return node
node[children!] && list.push(...node[children!])
}
return null
}
export const findNodeAll = <T = any>(
tree: any,
func: Fn,
config: Partial<TreeHelperConfig> = {}
): T[] => {
config = getConfig(config)
const { children } = config
const list = [...tree]
const result: T[] = []
for (const node of list) {
func(node) && result.push(node)
node[children!] && list.push(...node[children!])
}
return result
}
export const findPath = <T = any>(
tree: any,
func: Fn,
config: Partial<TreeHelperConfig> = {}
): T | T[] | null => {
config = getConfig(config)
const path: T[] = []
const list = [...tree]
const visitedSet = new Set()
const { children } = config
while (list.length) {
const node = list[0]
if (visitedSet.has(node)) {
path.pop()
list.shift()
} else {
visitedSet.add(node)
node[children!] && list.unshift(...node[children!])
path.push(node)
if (func(node)) {
return path
}
}
}
return null
}
export const findPathAll = (tree: any, func: Fn, config: Partial<TreeHelperConfig> = {}) => {
config = getConfig(config)
const path: any[] = []
const list = [...tree]
const result: any[] = []
const visitedSet = new Set(),
{ children } = config
while (list.length) {
const node = list[0]
if (visitedSet.has(node)) {
path.pop()
list.shift()
} else {
visitedSet.add(node)
node[children!] && list.unshift(...node[children!])
path.push(node)
func(node) && result.push([...path])
}
}
return result
}
export const filter = <T = any>(
tree: T[],
func: (n: T) => boolean,
config: Partial<TreeHelperConfig> = {}
): T[] => {
config = getConfig(config)
const children = config.children as string
function listFilter(list: T[]) {
return list
.map((node: any) => ({ ...node }))
.filter((node) => {
node[children] = node[children] && listFilter(node[children])
return func(node) || (node[children] && node[children].length)
})
}
return listFilter(tree)
}
export const forEach = <T = any>(
tree: T[],
func: (n: T) => any,
config: Partial<TreeHelperConfig> = {}
): void => {
config = getConfig(config)
const list: any[] = [...tree]
const { children } = config
for (let i = 0; i < list.length; i++) {
//func 返回true就终止遍历避免大量节点场景下无意义循环引起浏览器卡顿
if (func(list[i])) {
return
}
children && list[i][children] && list.splice(i + 1, 0, ...list[i][children])
}
}
/**
* @description: Extract tree specified structure
*/
export const treeMap = <T = any>(
treeData: T[],
opt: { children?: string; conversion: Fn }
): T[] => {
return treeData.map((item) => treeMapEach(item, opt))
}
/**
* @description: Extract tree specified structure
*/
export const treeMapEach = (
data: any,
{ children = 'children', conversion }: { children?: string; conversion: Fn }
) => {
const haveChildren = Array.isArray(data[children]) && data[children].length > 0
const conversionData = conversion(data) || {}
if (haveChildren) {
return {
...conversionData,
[children]: data[children].map((i: number) =>
treeMapEach(i, {
children,
conversion
})
)
}
} else {
return {
...conversionData
}
}
}
/**
* 递归遍历树结构
* @param treeDatas 树
* @param callBack 回调
* @param parentNode 父节点
*/
export const eachTree = (treeDatas: any[], callBack: Fn, parentNode = {}) => {
treeDatas.forEach((element) => {
const newNode = callBack(element, parentNode) || element
if (element.children) {
eachTree(element.children, callBack, newNode)
}
})
}

View File

@@ -1,7 +1,7 @@
import { Slots } from 'vue'
import { isFunction } from '@/utils/is'
export function getSlot(slots: Slots, slot = 'default', data?: Recordable) {
export const getSlot = (slots: Slots, slot = 'default', data?: Recordable) => {
// Reflect.has 判断一个对象是否存在某个属性
if (!slots || !Reflect.has(slots, slot)) {
return null