feat: 🎸 新增固定一级菜单配置
This commit is contained in:
@@ -1,96 +0,0 @@
|
||||
<template>
|
||||
<div ref="breadcrumbRef" class="breadcrumb">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue'
|
||||
import { defineComponent, provide, ref } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Breadcrumb',
|
||||
props: {
|
||||
separator: {
|
||||
type: String as PropType<string>,
|
||||
default: '/'
|
||||
},
|
||||
separatorClass: {
|
||||
type: String as PropType<string>,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const breadcrumbRef = ref<HTMLElement | null>(null)
|
||||
|
||||
provide('breadcrumb', props)
|
||||
|
||||
return {
|
||||
breadcrumbRef
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<style lang="less">
|
||||
.breadcrumb {
|
||||
padding-right: 20px;
|
||||
font-size: 12px;
|
||||
|
||||
&::after,
|
||||
&::before {
|
||||
display: table;
|
||||
content: '';
|
||||
}
|
||||
|
||||
&::after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
&__separator {
|
||||
margin: 0 9px;
|
||||
font-weight: 700;
|
||||
color: #6e90a7;
|
||||
|
||||
&[class*='icon'] {
|
||||
margin: 0 6px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
&__item {
|
||||
float: left;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&__inner {
|
||||
display: inline-block;
|
||||
color: #6e90a7;
|
||||
|
||||
a {
|
||||
font-weight: 700;
|
||||
color: #2c3a61;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
}
|
||||
|
||||
a:hover,
|
||||
&.is-link:hover {
|
||||
color: #1890ff;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
&__item:last-child .breadcrumb__inner,
|
||||
&__item:last-child &__inner a,
|
||||
&__item:last-child &__inner a:hover,
|
||||
&__item:last-child &__inner:hover {
|
||||
font-weight: 400;
|
||||
color: #6e90a7;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
&__item:last-child &__separator {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,51 +0,0 @@
|
||||
<template>
|
||||
<span class="breadcrumb__item">
|
||||
<span ref="linkRef" :class="['breadcrumb__inner']">
|
||||
<slot />
|
||||
</span>
|
||||
<i v-if="separatorClass" class="breadcrumb__separator" :class="separatorClass" />
|
||||
<span v-else class="breadcrumb__separator">{{ separator }}</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, inject, ref, onMounted, unref } from 'vue'
|
||||
import type { PropType } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'BreadcrumbItem',
|
||||
props: {
|
||||
to: {
|
||||
type: [String, Object] as PropType<string | object>,
|
||||
default: ''
|
||||
},
|
||||
replace: {
|
||||
type: Boolean as PropType<boolean>,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const linkRef = ref<HTMLElement | null>(null)
|
||||
const parent = inject('breadcrumb') as {
|
||||
separator: string
|
||||
separatorClass: string
|
||||
}
|
||||
const { push, replace } = useRouter()
|
||||
|
||||
onMounted(() => {
|
||||
const link = unref(linkRef)
|
||||
if (!link) return
|
||||
const { to } = props
|
||||
if (!props.to) return
|
||||
props.replace ? replace(to) : push(to)
|
||||
})
|
||||
|
||||
return {
|
||||
linkRef,
|
||||
separator: parent.separator && parent.separator,
|
||||
separatorClass: parent.separatorClass && parent.separatorClass
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
@@ -1,107 +0,0 @@
|
||||
<template>
|
||||
<Breadcrumb class="app-breadcrumb">
|
||||
<transition-group name="breadcrumb">
|
||||
<BreadcrumbItem
|
||||
v-for="(item,index) in levelList"
|
||||
:key="item.path"
|
||||
>
|
||||
<svg-icon v-if="item.meta.icon" :icon-class="item.meta.icon" class="icon-breadcrumb" />
|
||||
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">
|
||||
{{ item.meta.title }}
|
||||
</span>
|
||||
<a v-else @click.prevent="handleLink(item)">
|
||||
{{ item.meta.title }}
|
||||
</a>
|
||||
</BreadcrumbItem>
|
||||
</transition-group>
|
||||
</Breadcrumb>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { ref, defineComponent, watch } from 'vue'
|
||||
import type { RouteRecordRaw, RouteLocationMatched, RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { compile } from 'path-to-regexp'
|
||||
import Breadcrumb from './Breadcrumb.vue'
|
||||
import BreadcrumbItem from './BreadcrumbItem.vue'
|
||||
export default defineComponent({
|
||||
name: 'BreadcrumbWrap',
|
||||
components: {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem
|
||||
},
|
||||
setup() {
|
||||
const { currentRoute, push } = useRouter()
|
||||
|
||||
const levelList = ref<RouteRecordRaw[]>([])
|
||||
|
||||
function getBreadcrumb() {
|
||||
let matched: any[] = currentRoute.value.matched.filter((item: RouteLocationMatched) => item.meta && item.meta.title)
|
||||
const first = matched[0]
|
||||
|
||||
if (!isDashboard(first)) {
|
||||
matched = [{ path: '/dashboard', meta: { title: '首页', icon: 'dashboard' }}].concat(matched)
|
||||
}
|
||||
|
||||
levelList.value = matched.filter((item: RouteLocationMatched) => item.meta && item.meta.title && item.meta.breadcrumb !== false)
|
||||
}
|
||||
|
||||
function isDashboard(route: RouteLocationMatched) {
|
||||
const name = route && route.name
|
||||
if (!name) {
|
||||
return false
|
||||
}
|
||||
return (name as any).trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
|
||||
}
|
||||
|
||||
function pathCompile(path: string): string {
|
||||
const { params } = currentRoute.value
|
||||
const toPath = compile(path)
|
||||
return toPath(params)
|
||||
}
|
||||
|
||||
function handleLink(item: RouteRecordRaw): void {
|
||||
const { redirect, path } = item
|
||||
if (redirect) {
|
||||
push(redirect as string)
|
||||
return
|
||||
}
|
||||
push(pathCompile(path))
|
||||
}
|
||||
|
||||
watch(
|
||||
() => currentRoute.value,
|
||||
(route: RouteLocationNormalizedLoaded) => {
|
||||
if (route.path.startsWith('/redirect/')) {
|
||||
return
|
||||
}
|
||||
getBreadcrumb()
|
||||
},
|
||||
{
|
||||
immediate: true
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
levelList,
|
||||
handleLink
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.app-breadcrumb {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
margin-left: 10px;
|
||||
.no-redirect {
|
||||
color: #97a8be;
|
||||
cursor: text;
|
||||
}
|
||||
.icon-breadcrumb {
|
||||
color: #97a8be;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user