|
|
|
@ -1,7 +1,8 @@
|
|
|
|
|
<script lang="ts"> |
|
|
|
|
<script lang="ts" setup> |
|
|
|
|
import type { CSSProperties } from 'vue' |
|
|
|
|
import { computed, defineComponent, onMounted, ref, unref, watch } from 'vue' |
|
|
|
|
import { computed, onMounted, ref, unref, watch } from 'vue' |
|
|
|
|
import type { RouteLocationNormalized } from 'vue-router' |
|
|
|
|
import { onClickOutside } from '@vueuse/core' |
|
|
|
|
import LayoutTrigger from '../trigger/index.vue' |
|
|
|
|
import { useDragLine } from './useLayoutSider' |
|
|
|
|
import type { Menu } from '@/router/types' |
|
|
|
@ -16,36 +17,22 @@ import { useDesign } from '@/hooks/web/useDesign'
|
|
|
|
|
import { useI18n } from '@/hooks/web/useI18n' |
|
|
|
|
import { useGo } from '@/hooks/web/usePage' |
|
|
|
|
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '@/enums/appEnum' |
|
|
|
|
import clickOutside from '@/directives/clickOutside' |
|
|
|
|
import { getChildrenMenus, getCurrentParentPath, getShallowMenus } from '@/router/menus' |
|
|
|
|
import { listenerRouteChange } from '@/logics/mitt/routeChange' |
|
|
|
|
|
|
|
|
|
export default defineComponent({ |
|
|
|
|
name: 'LayoutMixSider', |
|
|
|
|
components: { |
|
|
|
|
ScrollContainer, |
|
|
|
|
AppLogo, |
|
|
|
|
SimpleMenu, |
|
|
|
|
Icon, |
|
|
|
|
LayoutTrigger, |
|
|
|
|
SimpleMenuTag, |
|
|
|
|
}, |
|
|
|
|
directives: { |
|
|
|
|
clickOutside, |
|
|
|
|
}, |
|
|
|
|
setup() { |
|
|
|
|
const menuModules = ref<Menu[]>([]) |
|
|
|
|
const activePath = ref('') |
|
|
|
|
const childrenMenus = ref<Menu[]>([]) |
|
|
|
|
const openMenu = ref(false) |
|
|
|
|
const dragBarRef = ref<ElRef>(null) |
|
|
|
|
const sideRef = ref<ElRef>(null) |
|
|
|
|
const currentRoute = ref<Nullable<RouteLocationNormalized>>(null) |
|
|
|
|
|
|
|
|
|
const { prefixCls } = useDesign('layout-mix-sider') |
|
|
|
|
const go = useGo() |
|
|
|
|
const { t } = useI18n() |
|
|
|
|
const { |
|
|
|
|
const wrap = ref(null) |
|
|
|
|
const menuModules = ref<Menu[]>([]) |
|
|
|
|
const activePath = ref('') |
|
|
|
|
const childrenMenus = ref<Menu[]>([]) |
|
|
|
|
const openMenu = ref(false) |
|
|
|
|
const dragBarRef = ref<ElRef>(null) |
|
|
|
|
const sideRef = ref<ElRef>(null) |
|
|
|
|
const currentRoute = ref<Nullable<RouteLocationNormalized>>(null) |
|
|
|
|
|
|
|
|
|
const { prefixCls } = useDesign('layout-mix-sider') |
|
|
|
|
const go = useGo() |
|
|
|
|
const { t } = useI18n() |
|
|
|
|
const { |
|
|
|
|
getMenuWidth, |
|
|
|
|
getCanDrag, |
|
|
|
|
getCloseMixSidebarOnChange, |
|
|
|
@ -57,22 +44,22 @@ export default defineComponent({
|
|
|
|
|
setMenuSetting, |
|
|
|
|
getIsMixSidebar, |
|
|
|
|
getCollapsed, |
|
|
|
|
} = useMenuSetting() |
|
|
|
|
} = useMenuSetting() |
|
|
|
|
|
|
|
|
|
const { title } = useGlobSetting() |
|
|
|
|
const permissionStore = usePermissionStore() |
|
|
|
|
const { title } = useGlobSetting() |
|
|
|
|
const permissionStore = usePermissionStore() |
|
|
|
|
|
|
|
|
|
useDragLine(sideRef, dragBarRef, true) |
|
|
|
|
useDragLine(sideRef, dragBarRef, true) |
|
|
|
|
|
|
|
|
|
const getMenuStyle = computed((): CSSProperties => { |
|
|
|
|
const getMenuStyle = computed((): CSSProperties => { |
|
|
|
|
return { |
|
|
|
|
width: unref(openMenu) ? `${unref(getMenuWidth)}px` : 0, |
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define |
|
|
|
|
left: `${unref(getMixSideWidth)}px`, |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
const getIsFixed = computed(() => { |
|
|
|
|
const getIsFixed = computed(() => { |
|
|
|
|
// eslint-disable-next-line vue/no-side-effects-in-computed-properties |
|
|
|
|
mixSideHasChildren.value = unref(childrenMenus).length > 0 |
|
|
|
|
const isFixed = unref(getMixSideFixed) && unref(mixSideHasChildren) |
|
|
|
@ -81,24 +68,24 @@ export default defineComponent({
|
|
|
|
|
openMenu.value = true |
|
|
|
|
|
|
|
|
|
return isFixed |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
const getMixSideWidth = computed(() => { |
|
|
|
|
const getMixSideWidth = computed(() => { |
|
|
|
|
return unref(getCollapsed) ? SIDE_BAR_MINI_WIDTH : SIDE_BAR_SHOW_TIT_MINI_WIDTH |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
const getDomStyle = computed((): CSSProperties => { |
|
|
|
|
const getDomStyle = computed((): CSSProperties => { |
|
|
|
|
const fixedWidth = unref(getIsFixed) ? unref(getRealWidth) : 0 |
|
|
|
|
const width = `${unref(getMixSideWidth) + fixedWidth}px` |
|
|
|
|
return getWrapCommonStyle(width) |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
const getWrapStyle = computed((): CSSProperties => { |
|
|
|
|
const getWrapStyle = computed((): CSSProperties => { |
|
|
|
|
const width = `${unref(getMixSideWidth)}px` |
|
|
|
|
return getWrapCommonStyle(width) |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
const getMenuEvents = computed(() => { |
|
|
|
|
const getMenuEvents = computed(() => { |
|
|
|
|
return !unref(getMixSideFixed) |
|
|
|
|
? { |
|
|
|
|
onMouseleave: () => { |
|
|
|
@ -107,16 +94,16 @@ export default defineComponent({
|
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
: {} |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
const getShowDragBar = computed(() => unref(getCanDrag)) |
|
|
|
|
const getShowDragBar = computed(() => unref(getCanDrag)) |
|
|
|
|
|
|
|
|
|
onMounted(async () => { |
|
|
|
|
onMounted(async () => { |
|
|
|
|
menuModules.value = await getShallowMenus() |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// Menu changes |
|
|
|
|
watch( |
|
|
|
|
// Menu changes |
|
|
|
|
watch( |
|
|
|
|
[() => permissionStore.getLastBuildMenuTime, () => permissionStore.getBackMenuList], |
|
|
|
|
async () => { |
|
|
|
|
menuModules.value = await getShallowMenus() |
|
|
|
@ -124,26 +111,26 @@ export default defineComponent({
|
|
|
|
|
{ |
|
|
|
|
immediate: true, |
|
|
|
|
}, |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
listenerRouteChange((route) => { |
|
|
|
|
listenerRouteChange((route) => { |
|
|
|
|
currentRoute.value = route |
|
|
|
|
setActive(true) |
|
|
|
|
if (unref(getCloseMixSidebarOnChange)) |
|
|
|
|
closeMenu() |
|
|
|
|
}) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
function getWrapCommonStyle(width: string): CSSProperties { |
|
|
|
|
function getWrapCommonStyle(width: string): CSSProperties { |
|
|
|
|
return { |
|
|
|
|
width, |
|
|
|
|
maxWidth: width, |
|
|
|
|
minWidth: width, |
|
|
|
|
flex: `0 0 ${width}`, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Process module menu click |
|
|
|
|
async function handleModuleClick(path: string, hover = false) { |
|
|
|
|
// Process module menu click |
|
|
|
|
async function handleModuleClick(path: string, hover = false) { |
|
|
|
|
const children = await getChildrenMenus(path) |
|
|
|
|
if (unref(activePath) === path) { |
|
|
|
|
if (!hover) { |
|
|
|
@ -172,10 +159,10 @@ export default defineComponent({
|
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
childrenMenus.value = children |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set the currently active menu and submenu |
|
|
|
|
async function setActive(setChildren = false) { |
|
|
|
|
// Set the currently active menu and submenu |
|
|
|
|
async function setActive(setChildren = false) { |
|
|
|
|
const path = currentRoute.value?.path |
|
|
|
|
if (!path) |
|
|
|
|
return |
|
|
|
@ -196,18 +183,18 @@ export default defineComponent({
|
|
|
|
|
childrenMenus.value = [] |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleMenuClick(path: string) { |
|
|
|
|
function handleMenuClick(path: string) { |
|
|
|
|
go(path) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleClickOutside() { |
|
|
|
|
function handleClickOutside() { |
|
|
|
|
setActive(true) |
|
|
|
|
closeMenu() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function getItemEvents(item: Menu) { |
|
|
|
|
function getItemEvents(item: Menu) { |
|
|
|
|
if (unref(getMixSideTrigger) === 'hover') { |
|
|
|
|
return { |
|
|
|
|
onMouseenter: () => handleModuleClick(item.path, true), |
|
|
|
@ -221,52 +208,29 @@ export default defineComponent({
|
|
|
|
|
return { |
|
|
|
|
onClick: () => handleModuleClick(item.path), |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleFixedMenu() { |
|
|
|
|
function handleFixedMenu() { |
|
|
|
|
setMenuSetting({ |
|
|
|
|
mixSideFixed: !unref(getIsFixed), |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Close menu |
|
|
|
|
function closeMenu() { |
|
|
|
|
// Close menu |
|
|
|
|
function closeMenu() { |
|
|
|
|
if (!unref(getIsFixed)) |
|
|
|
|
openMenu.value = false |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
t, |
|
|
|
|
prefixCls, |
|
|
|
|
menuModules, |
|
|
|
|
handleModuleClick, |
|
|
|
|
activePath, |
|
|
|
|
childrenMenus, |
|
|
|
|
getShowDragBar, |
|
|
|
|
handleMenuClick, |
|
|
|
|
getMenuStyle, |
|
|
|
|
handleClickOutside, |
|
|
|
|
sideRef, |
|
|
|
|
dragBarRef, |
|
|
|
|
title, |
|
|
|
|
openMenu, |
|
|
|
|
getMenuTheme, |
|
|
|
|
getItemEvents, |
|
|
|
|
getMenuEvents, |
|
|
|
|
getDomStyle, |
|
|
|
|
handleFixedMenu, |
|
|
|
|
getMixSideFixed, |
|
|
|
|
getWrapStyle, |
|
|
|
|
getCollapsed, |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
onClickOutside(wrap, () => { |
|
|
|
|
handleClickOutside() |
|
|
|
|
}) |
|
|
|
|
</script> |
|
|
|
|
|
|
|
|
|
<template> |
|
|
|
|
<div :class="`${prefixCls}-dom`" :style="getDomStyle" /> |
|
|
|
|
<div |
|
|
|
|
v-click-outside="handleClickOutside" |
|
|
|
|
ref="wrap" |
|
|
|
|
:style="getWrapStyle" |
|
|
|
|
:class="[ |
|
|
|
|
prefixCls, |
|
|
|
|