fix:完善相关页面
This commit is contained in:
@@ -1,34 +1,223 @@
|
||||
<template>
|
||||
<div class="mj-layout">
|
||||
<el-container>
|
||||
<el-aside :width> 左侧菜单模块 </el-aside>
|
||||
<el-aside :width="width">
|
||||
<div class="mj-aside-content">
|
||||
<!-- 顶部company公司标记 -->
|
||||
<div class="mj-aside-company"></div>
|
||||
<div class="mj-aside-menu">
|
||||
<div class="mj-aside-title" v-show="!isCollapse">{{ topTitle }}</div>
|
||||
<mjMenus class="mj-aside_menu" :isCollapse="isCollapse" :menuList="sideMenuList" :active-menu="selectedActiveMenu"
|
||||
@menu-select="handleSideMenuSelect" />
|
||||
</div>
|
||||
<!-- 展开收缩左侧菜单按钮 -->
|
||||
<div class="mj-collapse" @click="showCollapse"></div>
|
||||
</div>
|
||||
</el-aside>
|
||||
<el-container>
|
||||
<el-header>头部模块</el-header>
|
||||
<el-header class="mj-header-content">
|
||||
<mjMenus :menuList="topLevelMenuList" mode="horizontal" :active-menu="selectedTopMenu"
|
||||
@menu-select="handleTopMenuSelect" />
|
||||
</el-header>
|
||||
<el-main>
|
||||
内容区域模块
|
||||
<!-- <card-item :list="[1,2,3,4,5,6]"/> -->
|
||||
<router-view />
|
||||
</el-main>
|
||||
</el-container>
|
||||
</el-container>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import mjMenus from '@/components/standardMenu/index.vue';
|
||||
import { useUserStore } from '@/store'
|
||||
defineOptions({
|
||||
name: "Layout",
|
||||
});
|
||||
const isCollapse = ref(false);
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
// 响应式断点(小屏阈值,小于此值视为小屏)
|
||||
const BREAKPOINT = 1024;
|
||||
|
||||
// 屏幕宽度
|
||||
const screenWidth = ref(window.innerWidth);
|
||||
|
||||
// 菜单收缩状态:完全根据屏幕大小自动判断
|
||||
const isCollapse = computed(() => {
|
||||
return screenWidth.value < BREAKPOINT;
|
||||
});
|
||||
|
||||
const width = computed(() => {
|
||||
return isCollapse.value ? "60px" : "240px";
|
||||
return isCollapse.value ? "80px" : "224px";
|
||||
});
|
||||
|
||||
// 监听窗口大小变化
|
||||
const handleResize = () => {
|
||||
screenWidth.value = window.innerWidth;
|
||||
// isCollapse 是计算属性,会自动响应 screenWidth 的变化
|
||||
};
|
||||
|
||||
// 展开收缩菜单(临时切换,窗口大小变化时会自动恢复)
|
||||
const showCollapse = () => {
|
||||
if (isCollapse.value) {
|
||||
screenWidth.value = BREAKPOINT + 1;
|
||||
} else {
|
||||
screenWidth.value = BREAKPOINT - 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 返回菜单数据
|
||||
const menuList = computed(() => {
|
||||
return userStore.routes || []
|
||||
});
|
||||
|
||||
// 获取一级菜单数据(不包含 children)
|
||||
const topLevelMenuList = computed(() => {
|
||||
return menuList.value.map(item => {
|
||||
const { children, ...rest } = item
|
||||
return rest
|
||||
})
|
||||
})
|
||||
|
||||
const topTitle = computed(() => {
|
||||
return topLevelMenuList.value.find(path => path.path === selectedTopMenu.value)?.meta?.title || '-'
|
||||
})
|
||||
|
||||
// 当前选中的顶部菜单
|
||||
const selectedTopMenu = ref<string>('')
|
||||
const selectedActiveMenu = ref<string>('');
|
||||
|
||||
// 根据选中的顶部菜单,获取左侧菜单列表
|
||||
const sideMenuList = computed(() => {
|
||||
if (!selectedTopMenu.value) {
|
||||
// 默认选中第一个有 children 的菜单
|
||||
const firstMenuWithChildren = menuList.value.find(item => item.children && item.children.length > 0)
|
||||
if (firstMenuWithChildren) {
|
||||
return (firstMenuWithChildren.children || []).map(child=>{
|
||||
const fullPath = child.path.startsWith('/')
|
||||
? child.path
|
||||
: `${firstMenuWithChildren.path}/${child.path}`
|
||||
|
||||
return {
|
||||
...child,
|
||||
path: fullPath
|
||||
}
|
||||
})
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 根据选中的顶部菜单路径,找到对应的菜单项
|
||||
const selectedMenu = menuList.value.find(item => item.path === selectedTopMenu.value)
|
||||
if (selectedMenu && selectedMenu.children) {
|
||||
return selectedMenu.children.map(child=>{
|
||||
const fullPath = child.path.startsWith('/')
|
||||
? child.path
|
||||
: `${selectedMenu.path}/${child.path}`
|
||||
|
||||
return {
|
||||
...child,
|
||||
path: fullPath
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
return []
|
||||
})
|
||||
|
||||
// 处理顶部菜单选中事件
|
||||
const handleTopMenuSelect = (menuPath: string) => {
|
||||
selectedTopMenu.value = menuPath
|
||||
}
|
||||
|
||||
// 左侧菜单选中事件
|
||||
const handleSideMenuSelect = (menuPath: string) => {
|
||||
selectedActiveMenu.value = menuPath;
|
||||
}
|
||||
|
||||
// 初始化:默认选中第一个菜单
|
||||
onMounted(() => {
|
||||
if (topLevelMenuList.value.length > 0) {
|
||||
const firstMenu = topLevelMenuList.value[0]
|
||||
if (firstMenu && firstMenu.path) {
|
||||
selectedTopMenu.value = firstMenu.path
|
||||
}
|
||||
}
|
||||
|
||||
// 监听窗口大小变化
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
// 初始化时根据屏幕大小设置菜单状态
|
||||
handleResize();
|
||||
});
|
||||
|
||||
// 组件卸载时移除监听
|
||||
onUnmounted(() => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
});
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mj-layout {
|
||||
height: inherit;
|
||||
|
||||
:deep(.el-container) {
|
||||
height: inherit;
|
||||
}
|
||||
|
||||
:deep(.el-aside) {
|
||||
transition: width 0.3s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:deep(.el-main) {
|
||||
--el-main-padding:16px;
|
||||
background-color: #f8fafc;
|
||||
}
|
||||
|
||||
.mj-aside-content {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-right: 1px solid var(--mj-border-color);
|
||||
|
||||
.mj-aside-company {
|
||||
height: var(--mj-menu-header-height);
|
||||
border-bottom: 1px solid var(--mj-border-color);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.mj-aside-menu {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
.mj-aside-title {
|
||||
font-size: 10px;
|
||||
color: #888;
|
||||
padding: 10px var(--el-menu-base-level-padding);
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
.mj-collapse {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: calc(var(--mj-menu-header-height)/2 - 10px);
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 1px 6px #0000001f;
|
||||
}
|
||||
}
|
||||
|
||||
.mj-header-content {
|
||||
--el-header-padding: 0;
|
||||
border-bottom: 1px solid var(--mj-border-color);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user