123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- <template>
- <div
- class="vab-fall-bar"
- :class="{
- 'is-collapse': collapse,
- }"
- >
- <vab-logo style="z-index: 999" />
- <fall-menu :data="handleRoutes">
- <template #level1="{ slotScope }">
- <a :title="translate(slotScope.meta.title)" @click="handleLink(slotScope)">
- <vab-icon :icon="slotScope.meta && slotScope.meta.icon" />
- <span>{{ translate(slotScope.meta.title) }}</span>
- <vab-icon v-if="slotScope.children" class="fall-icon-right" icon="arrow-right-s-line" />
- </a>
- </template>
- <template #level2="{ slotScope }">
- <span style="cursor: pointer" @click="handleLink(slotScope)">
- <vab-icon :icon="slotScope.meta && slotScope.meta.icon" />
- <span>{{ translate(slotScope.meta.title) }}</span>
- </span>
- </template>
- <template #level3="{ slotScope }">
- <a v-for="(level3, index) in slotScope" :key="index" :href="level3.url" @click="handleLink(level3)">
- - {{ translate(level3.meta.title) }}
- <el-tag v-if="level3.meta && level3.meta.badge" effect="dark" size="small" type="danger">
- {{ level3.meta.badge }}
- </el-tag>
- <span v-if="level3.meta && level3.meta.dot" class="vab-dot vab-dot-error">
- <span></span>
- </span>
- </a>
- </template>
- </fall-menu>
- </div>
- </template>
- <script lang="ts" setup>
- /**
- * @author:zxwk-sundan
- * @description:瀑布菜单最多支持到三级菜单,不支持左侧点击选中,且非element-plus官方组件,生产环境请谨慎使用
- */
- import { FallMenu } from '@opentiny/vue'
- import { isHashRouterMode } from '/@/config'
- import { translate } from '/@/i18n'
- import { useRoutesStore } from '/@/store/modules/routes'
- import { useSettingsStore } from '/@/store/modules/settings'
- import { isExternal } from '/@/utils/validate'
- defineOptions({
- name: 'VabFallBar',
- })
- const settingsStore = useSettingsStore()
- const routesStore = useRoutesStore()
- const { getRoutes: routes } = storeToRefs(routesStore)
- const route = useRoute()
- const router = useRouter()
- const { device, collapse } = storeToRefs(settingsStore)
- const { foldSideBar } = settingsStore
- const { enter, exit } = useFullscreen()
- const mousePosition = ref({ x: 0, y: 0 })
- const handleRoutes = computed(() =>
- routes.value.flatMap((route: any) => (route.meta.levelHidden && route.children ? [...route.children] : route))
- )
- const handleLink = (slotScope: any) => {
- nextTick(() => {
- const routePath = slotScope.path
- const target = slotScope.meta.target
- const fullscreen = slotScope.meta.fullscreen
- if (target === '_blank') {
- if (isExternal(routePath)) {
- window.open(routePath)
- router.push('/redirect')
- } else if (route.path !== routePath) isHashRouterMode ? window.open(`#${routePath}`) : window.open(routePath)
- router.push('/redirect')
- } else {
- if (isExternal(routePath)) window.location.href = routePath
- else if (route.path === routePath) {
- $pub('reload-router-view')
- } else {
- if (device.value === 'mobile') foldSideBar()
- if (slotScope.children) router.push(slotScope.redirect)
- else router.push(slotScope.path)
- }
- }
- setTimeout(() => {
- if (fullscreen) enter()
- else exit()
- }, 1000)
- })
- }
- useEventListener('mousemove', (e: MouseEvent) => {
- mousePosition.value = {
- x: e.clientX,
- y: e.clientY,
- }
- if ((mousePosition.value.x < 265 && !collapse.value) || (mousePosition.value.x < 65 && collapse.value)) {
- const element: any = document.querySelector('.vab-fall-bar .tiny-fall-menu__box')
- const base = 60
- const intervalSize = 48
- for (let i = 0; i < 10; i++) {
- const lowerBound = base + i * intervalSize
- const upperBound = lowerBound + intervalSize
- if (mousePosition.value.y > lowerBound && mousePosition.value.y < upperBound) {
- mousePosition.value.y = lowerBound - 60
- break
- }
- }
- element.style.top = `${mousePosition.value.y}px`
- }
- })
- </script>
- <style lang="scss" scoped>
- .vab-fall-bar {
- position: fixed;
- top: 0;
- bottom: 0;
- left: 0;
- z-index: var(--el-z-index);
- width: calc(var(--el-left-menu-width) - 1px);
- background: var(--el-menu-background-color);
- border-right: 1px solid var(--el-border-color);
- .fall-icon-right {
- float: right;
- }
- :deep() {
- .tiny-fall-menu {
- --ti-fall-menu-bg-color-normal: var(--el-menu-background-color);
- --ti-fall-menu-bg-color-hover: var(--el-color-primary);
- --ti-fall-menu-slot-bg-color: var(--el-menu-background-color);
- --ti-fall-menu-box-text-color: var(--el-color-white);
- --ti-fall-menu-slot-text-color: var(--el-color-white);
- --ti-common-font-size-base: var(--el-font-size-base);
- --ti-fall-menu-title-font-size: var(--el-font-size-base);
- --ti-fall-menu-box-width: 560px;
- &__nav {
- height: calc(var(--vh, 1vh) * 100);
- }
- &__wrap {
- padding: 0;
- background: var(--ti-fall-menu-bg-color-normal);
- }
- &__subnav {
- .icon-slot-left,
- .icon-slot-right {
- opacity: 0;
- }
- }
- &__list {
- right: 0 !important;
- left: 0 !important;
- min-width: 100%;
- li {
- display: block;
- float: none;
- width: 100%;
- a {
- display: block;
- width: calc(100% - 20px);
- margin: 0 10px 0px 10px !important;
- text-align: left;
- border-radius: var(--el-border-radius-base);
- [class*='ri-'] {
- margin-left: 1.5px;
- }
- [class*='ri-'] + span {
- padding-left: 3px;
- }
- }
- }
- .fall-hide {
- opacity: 1;
- }
- }
- &__box {
- top: 5px;
- left: var(--el-left-menu-width);
- min-width: var(--ti-fall-menu-box-width);
- padding: var(--el-padding);
- overflow-y: auto;
- border: 0;
- border-radius: var(--el-border-radius-base);
- box-shadow: none;
- transition:
- all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1),
- top 0.1s !important;
- .cont {
- padding: 0;
- }
- .sublist {
- li {
- h3.mcate-item-hd {
- color: var(--ti-fall-menu-box-title-text-color);
- [class*='ri-'] + span {
- padding-left: 3px;
- }
- &:hover {
- color: var(--el-color-primary) !important;
- }
- }
- p.mcate-item-bd {
- a {
- font-size: 13px;
- color: var(--ti-fall-menu-box-text-color);
- &:hover {
- color: var(--el-color-primary) !important;
- }
- .el-tag {
- height: 16px;
- padding: 0 5px 0 5px;
- }
- }
- }
- }
- }
- }
- }
- }
- &.is-collapse {
- width: 65px;
- :deep() {
- .tiny-fall-menu {
- &__list {
- li {
- a {
- [class*='ri-'] + span {
- display: none;
- }
- }
- }
- .fall-hide {
- opacity: 1;
- }
- }
- &__box {
- left: calc(var(--el-left-menu-width-min) + 2px);
- padding-right: 0;
- }
- }
- }
- }
- }
- </style>
- <style lang="scss">
- .vab-theme-technology {
- .tiny-fall-menu {
- --ti-fall-menu-bg-color-normal: var(--el-menu-background-color);
- --ti-fall-menu-bg-color-hover: var(--el-color-primary);
- --ti-fall-menu-slot-bg-color: var(--el-menu-background-color);
- --ti-fall-menu-box-text-color: #fff !important;
- --ti-fall-menu-slot-text-color: var(--el-color-white);
- &__list {
- a {
- color: #fff;
- }
- }
- &__box {
- border: 1px solid var(--el-border-color) !important;
- .sublist {
- li {
- h3.mcate-item-hd {
- color: var(--ti-fall-menu-box-title-text-color);
- }
- p.mcate-item-bd {
- a {
- color: var(--ti-fall-menu-box-text-color);
- }
- }
- }
- }
- }
- }
- }
- .vab-theme-plain {
- .tiny-fall-menu {
- --ti-fall-menu-bg-color-normal: var(--el-menu-background-color);
- --ti-fall-menu-bg-color-hover: var(--el-color-primary);
- --ti-fall-menu-slot-bg-color: var(--el-menu-background-color);
- --ti-fall-menu-box-text-color: var(--el-color-grey) !important;
- --ti-fall-menu-slot-text-color: var(--el-color-grey) !important;
- &__box {
- border: 1px solid var(--el-border-color) !important;
- .sublist {
- li {
- h3.mcate-item-hd {
- color: #515a6e !important;
- }
- p.mcate-item-bd {
- a {
- color: var(--ti-fall-menu-box-text-color);
- }
- }
- }
- }
- }
- &__list {
- a:hover {
- color: #fff !important;
- }
- }
- }
- }
- .dark {
- .tiny-fall-menu {
- --ti-fall-menu-bg-color-normal: var(--el-menu-background-color);
- --ti-fall-menu-bg-color-hover: var(--el-color-primary);
- --ti-fall-menu-slot-bg-color: var(--el-menu-background-color);
- --ti-fall-menu-box-text-color: var(--el-color-grey) !important;
- --ti-fall-menu-slot-text-color: var(--el-color-grey) !important;
- &__box {
- border: 1px solid var(--el-border-color) !important;
- .sublist {
- li {
- h3.mcate-item-hd {
- color: #fff !important;
- }
- p.mcate-item-bd {
- a {
- color: var(--ti-fall-menu-box-text-color);
- }
- }
- }
- }
- }
- &__list {
- a:hover {
- color: #fff !important;
- }
- }
- }
- }
- </style>
|