UPDATE: 1、优化动态加载路由;2、修改模式切换,菜单没刷新等问题

This commit is contained in:
贾同学
2025-10-27 16:27:12 +08:00
parent 9376d702f3
commit 425b54bc44
17 changed files with 507 additions and 466 deletions

View File

@@ -28,8 +28,14 @@
import { computed } from 'vue'
import { useAuthStore } from '@/stores/modules/auth'
import { useModeStore } from '@/stores/modules/mode' // 引入模式 store
import { useTabsStore } from '@/stores/modules/tabs'
import { useRouter } from 'vue-router'
import { initDynamicRouter } from '@/routers/modules/dynamicRouter'
const router = useRouter()
const authStore = useAuthStore()
const modeStore = useModeStore()
const tabsStore = useTabsStore()
const title = computed(() => {
return modeStore.currentMode === '' ? '选择模块' : modeStore.currentMode + '模块'
@@ -64,7 +70,9 @@ const handelOpen = async (item: string, key: string) => {
await authStore.setShowMenu()
modeStore.setCurrentMode(item) // 将模式code存入 store
// 强制刷新页面
window.location.reload()
await tabsStore.closeMultipleTab()
await initDynamicRouter()
await router.push({ path: '/home/index' })
}
</script>
<style scoped lang="scss">

View File

@@ -1,12 +1,4 @@
<template>
<!-- <div class="userInfo">-->
<!-- <div class="icon">-->
<!-- <Avatar/>-->
<!-- </div>-->
<!-- <div class="username">-->
<!-- {{ username }}-->
<!-- </div>-->
<!-- </div>-->
<el-dropdown trigger="click">
<div class="userInfo">
<div class="icon">
@@ -80,7 +72,6 @@
import { computed, ref } from 'vue'
import { LOGIN_URL } from '@/config'
import { useRouter } from 'vue-router'
import { logoutApi } from '@/api/user/login'
import { useUserStore } from '@/stores/modules/user'
import { ElMessage, ElMessageBox } from 'element-plus'
import InfoDialog from './InfoDialog.vue'
@@ -90,10 +81,9 @@ import VersionDialog from '@/views/system/versionRegister/index.vue'
import { Avatar, Sunny, Switch, Tools } from '@element-plus/icons-vue'
import { useAuthStore } from '@/stores/modules/auth'
import { useDictStore } from '@/stores/modules/dict'
import { useAppSceneStore, useModeStore } from '@/stores/modules/mode'
import { useTheme } from '@/hooks/useTheme'
import { useAppSceneStore } from '@/stores/modules/mode'
import { useI18n } from 'vue-i18n'
import { updateScene } from '@/api/system/base/index'
import { updateScene } from '@/api/system/base'
const userStore = useUserStore()
const dictStore = useDictStore()
@@ -101,10 +91,6 @@ const username = computed(() => userStore.userInfo.name)
const router = useRouter()
const authStore = useAuthStore()
const modeStore = useModeStore()
const AppSceneStore = useAppSceneStore()
const { changePrimary } = useTheme()
// 初始化 i18n
const { t } = useI18n() // 使用 t 方法替代 $t
@@ -116,21 +102,8 @@ const logout = () => {
cancelButtonText: '取消',
type: 'warning'
}).then(async () => {
// 1.执行退出登录接口
await logoutApi()
// 2.清除 Token
userStore.setAccessToken('')
userStore.setRefreshToken('')
userStore.setExp(0)
userStore.setUserInfo({ id: '', name: '' })
userStore.setIsRefreshToken(false)
dictStore.setDictData([])
modeStore.setCurrentMode('')
AppSceneStore.setCurrentMode('')
// 3.重定向到登陆页
ElMessage.success('退出登录成功!')
//重置菜单/导航栏权限
await authStore.resetAuthStore()
await userStore.logout()
await router.push(LOGIN_URL)
})
}
@@ -157,8 +130,9 @@ const changeScene = async (value: string) => {
}
//模式切换
const changeMode = () => {
const changeMode = async () => {
authStore.changeModel()
await router.push('/home/index')
}
</script>

View File

@@ -52,19 +52,10 @@ import { ElMessage, type FormItemRule } from 'element-plus'
import { updatePassWord } from '@/api/user/user'
import { type User } from '@/api/user/interface/user'
import { useUserStore } from '@/stores/modules/user'
import { useAuthStore } from '@/stores/modules/auth'
import { useDictStore } from '@/stores/modules/dict'
import { logoutApi } from '@/api/user/login'
import { LOGIN_URL } from '@/config'
import { useAppSceneStore, useModeStore } from '@/stores/modules/mode'
import { UserState } from '@/stores/interface'
import { useRouter } from 'vue-router'
const userStore = useUserStore()
const dictStore = useDictStore()
const authStore = useAuthStore()
const modeStore = useModeStore()
const AppSceneStore = useAppSceneStore()
const router = useRouter()
// 定义弹出组件元信息
const dialogFormRef = ref()
@@ -134,19 +125,7 @@ const save = () => {
await updatePassWord(formContent.value)
ElMessage.success('修改密码成功,请重新登录!')
setTimeout(async () => {
// 1.执行退出登录接口
await logoutApi()
// 2.清除 Token
userStore.setAccessToken('')
userStore.setRefreshToken('')
userStore.setExp(0)
userStore.setUserInfo({ id: '', name: '' } as UserState['userInfo'])
userStore.setIsRefreshToken(false)
dictStore.setDictData([])
modeStore.setCurrentMode('')
AppSceneStore.setCurrentMode('')
//重置菜单/导航栏权限
await authStore.resetAuthStore()
await userStore.logout()
await router.push(LOGIN_URL)
}, 2000)
}

View File

@@ -1,98 +1,97 @@
<template>
<template v-for="subItem in menuList" :key="subItem.path">
<el-sub-menu v-if="subItem.children?.length" :index="subItem.path">
<template #title>
<el-icon>
<component :is="subItem.meta.icon"></component>
</el-icon>
<span class="sle">{{ subItem.meta.title }}</span>
</template>
<SubMenu :menu-list="subItem.children" />
</el-sub-menu>
<el-menu-item v-else :index="subItem.path" @click="handleClickMenu(subItem)">
<el-icon>
<component :is="subItem.meta.icon"></component>
</el-icon>
<template #title>
<span class="sle">{{ subItem.meta.title }}</span>
</template>
</el-menu-item>
</template>
<template v-for="subItem in menuList" :key="subItem.path">
<el-sub-menu v-if="subItem.children?.length" :index="subItem.path">
<template #title>
<el-icon>
<component :is="subItem.meta.icon"></component>
</el-icon>
<span class="sle">{{ subItem.meta.title }}</span>
</template>
<SubMenu :menu-list="subItem.children" />
</el-sub-menu>
<el-menu-item v-else :index="subItem.path" @click="handleClickMenu(subItem)">
<el-icon>
<component :is="subItem.meta.icon"></component>
</el-icon>
<template #title>
<span class="sle">{{ subItem.meta.title }}</span>
</template>
</el-menu-item>
</template>
</template>
<script setup lang="ts">
import { onBeforeMount } from "vue";
import { useRouter } from "vue-router";
defineProps<{ menuList: Menu.MenuOptions[] }>();
const router = useRouter();
const handleClickMenu = (subItem: Menu.MenuOptions) => {
//console.log('1456----------------',subItem);
if (subItem.meta.isLink) return window.open(subItem.meta.isLink, "_blank");
router.push(subItem.path);
};
import { useRouter } from 'vue-router'
defineProps<{ menuList: Menu.MenuOptions[] }>()
const router = useRouter()
const handleClickMenu = async (subItem: Menu.MenuOptions) => {
if (subItem.meta?.isLink) {
window.open(subItem.meta.isLink, '_blank')
return
}
await router.push(subItem.path)
}
</script>
<style lang="scss">
.el-sub-menu .el-sub-menu__title:hover {
// color: var(--el-menu-hover-text-color) !important;
// background-color: transparent !important;
color: #fff !important;//一级导航文字选中颜色
//background-color: #5274a5 !important; //一级导航选中背景色
background-color: var(--el-color-primary-light-3) !important;
// color: var(--el-menu-hover-text-color) !important;
// background-color: transparent !important;
color: #fff !important; //一级导航文字选中颜色
//background-color: #5274a5 !important; //一级导航选中背景色
background-color: var(--el-color-primary-light-3) !important;
}
.el-menu--collapse {
.is-active {
.el-sub-menu__title {
color: #ffffff !important;
// background-color: var(--el-color-primary) !important;
//background-color: #5274a5 !important;
background-color: var(--el-color-primary-light-3) !important;
.is-active {
.el-sub-menu__title {
color: #ffffff !important;
// background-color: var(--el-color-primary) !important;
//background-color: #5274a5 !important;
background-color: var(--el-color-primary-light-3) !important;
border-bottom: 0 !important;
border-bottom: 0 !important;
}
}
}
}
.el-menu-item {
&:hover {
color: var(--el-menu-hover-text-color);
}
&.is-active {
// color: var(--el-menu-active-color) !important;
// background-color: var(--el-menu-active-bg-color) !important;
color: #fff !important;//一级导航文字选中颜色
//background-color: #5274a5 !important; //一级导航选中背景色
background-color: var(--el-color-primary-light-3) !important;
&::before {
position: absolute;
top: 0;
bottom: 0;
width: 4px;
content: "";
background-color: var(--el-color-primary);
&:hover {
color: var(--el-menu-hover-text-color);
}
&.is-active {
// color: var(--el-menu-active-color) !important;
// background-color: var(--el-menu-active-bg-color) !important;
color: #fff !important; //一级导航文字选中颜色
//background-color: #5274a5 !important; //一级导航选中背景色
background-color: var(--el-color-primary-light-3) !important;
&::before {
position: absolute;
top: 0;
bottom: 0;
width: 4px;
content: '';
background-color: var(--el-color-primary);
}
}
}
}
.vertical,
.classic,
.transverse {
.el-menu-item {
&.is-active {
&::before {
left: 0;
}
.el-menu-item {
&.is-active {
&::before {
left: 0;
}
}
}
}
}
.columns {
.el-menu-item {
&.is-active {
&::before {
right: 0;
}
.el-menu-item {
&.is-active {
&::before {
right: 0;
}
}
}
}
}
</style>