优化菜单切换导致浏览器刷新问题
This commit is contained in:
@@ -1,128 +1,130 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<component :is="config.layout.layoutMode"></component>
|
<component :is="config.layout.layoutMode"></component>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue'
|
import { reactive } from 'vue'
|
||||||
import { useConfig } from '@/stores/config'
|
import { useConfig } from '@/stores/config'
|
||||||
import { useNavTabs } from '@/stores/navTabs'
|
import { useNavTabs } from '@/stores/navTabs'
|
||||||
import { useAdminInfo } from '@/stores/adminInfo'
|
import { useAdminInfo } from '@/stores/adminInfo'
|
||||||
import { useDictData } from '@/stores/dictData'
|
import { useDictData } from '@/stores/dictData'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import Default from '@/layouts/admin/container/default.vue'
|
import Default from '@/layouts/admin/container/default.vue'
|
||||||
import Classic from '@/layouts/admin/container/classic.vue'
|
import Classic from '@/layouts/admin/container/classic.vue'
|
||||||
import Streamline from '@/layouts/admin/container/streamline.vue'
|
import Streamline from '@/layouts/admin/container/streamline.vue'
|
||||||
import Double from '@/layouts/admin/container/double.vue'
|
import Double from '@/layouts/admin/container/double.vue'
|
||||||
import { onMounted, onBeforeMount } from 'vue'
|
import { onMounted, onBeforeMount } from 'vue'
|
||||||
import { handleAdminRoute, getFirstRoute, routePush } from '@/utils/router'
|
import { handleAdminRoute, getFirstRoute, routePush } from '@/utils/router'
|
||||||
import router from '@/router/index'
|
import router from '@/router/index'
|
||||||
import { useEventListener } from '@vueuse/core'
|
import { useEventListener } from '@vueuse/core'
|
||||||
import { isEmpty } from 'lodash-es'
|
import { isEmpty } from 'lodash-es'
|
||||||
import { setNavTabsWidth } from '@/utils/layout'
|
import { setNavTabsWidth } from '@/utils/layout'
|
||||||
import { adminBaseRoutePath } from '@/router/static'
|
import { adminBaseRoutePath } from '@/router/static'
|
||||||
import { getRouteMenu, dictDataCache } from '@/api/auth'
|
import { getRouteMenu, dictDataCache } from '@/api/auth'
|
||||||
import { getAreaList, areaSelect } from '@/api/common'
|
import { getAreaList, areaSelect } from '@/api/common'
|
||||||
import { BasicDictData } from '@/stores/interface'
|
import { BasicDictData } from '@/stores/interface'
|
||||||
import { getAllUserSimpleList, getUserById } from '@/api/user-boot/user'
|
import { getAllUserSimpleList, getUserById } from '@/api/user-boot/user'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
components: { Default, Classic, Streamline, Double }
|
components: { Default, Classic, Streamline, Double }
|
||||||
})
|
})
|
||||||
|
|
||||||
const navTabs = useNavTabs()
|
const navTabs = useNavTabs()
|
||||||
const config = useConfig()
|
const config = useConfig()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const adminInfo = useAdminInfo()
|
const adminInfo = useAdminInfo()
|
||||||
const dictData = useDictData()
|
const dictData = useDictData()
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
autoMenuCollapseLock: false
|
autoMenuCollapseLock: false
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// if (!adminInfo.token) return router.push({ name: 'login' })
|
// if (!adminInfo.token) return router.push({ name: 'login' })
|
||||||
|
|
||||||
init()
|
init()
|
||||||
setNavTabsWidth()
|
setNavTabsWidth()
|
||||||
useEventListener(window, 'resize', setNavTabsWidth)
|
useEventListener(window, 'resize', setNavTabsWidth)
|
||||||
})
|
})
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
onAdaptiveLayout()
|
onAdaptiveLayout()
|
||||||
useEventListener(window, 'resize', onAdaptiveLayout)
|
useEventListener(window, 'resize', onAdaptiveLayout)
|
||||||
})
|
})
|
||||||
|
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
await Promise.all([getAreaList(), dictDataCache(), getUserById(), areaSelect(), getAllUserSimpleList()]).then(res => {
|
await Promise.all([getAreaList(), dictDataCache(), getUserById(), areaSelect(), getAllUserSimpleList()]).then(res => {
|
||||||
dictData.state.area = res[0].data
|
dictData.state.area = res[0].data
|
||||||
dictData.state.basic = res[1].data
|
dictData.state.basic = res[1].data
|
||||||
dictData.state.userList = res[4].data
|
dictData.state.userList = res[4].data
|
||||||
adminInfo.dataFill(res[2].data)
|
adminInfo.dataFill(res[2].data)
|
||||||
dictData.state.areaTree = res[3].data
|
dictData.state.areaTree = res[3].data
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* 后台初始化请求,获取站点配置,动态路由等信息
|
* 后台初始化请求,获取站点配置,动态路由等信息
|
||||||
*/
|
*/
|
||||||
getRouteMenu().then((res: any) => {
|
getRouteMenu().then((res: any) => {
|
||||||
const handlerMenu = (data: any) => {
|
const handlerMenu = (data: any) => {
|
||||||
data.forEach((item: any) => {
|
data.forEach((item: any) => {
|
||||||
item.routePath =
|
item.routePath =
|
||||||
item.routePath[0] == '/' ? item.routePath.substring(1, item.routePath.length) : item.routePath
|
item.routePath[0] == '/' ? item.routePath.substring(1, item.routePath.length) : item.routePath
|
||||||
item.path = item.routePath
|
item.path = item.routePath
|
||||||
item.name = item.routePath
|
item.name = item.routePath
|
||||||
item.keepalive = item.routePath
|
item.keepalive = item.routePath
|
||||||
item.component = item.routeName
|
item.component = item.routeName
|
||||||
? item.routeName.indexOf('/src/views/') > -1
|
? item.routeName.indexOf('/src/views/') > -1
|
||||||
? item.routeName
|
? item.routeName
|
||||||
: `/src/views/${item.routeName}/index.vue`
|
: `/src/views/${item.routeName}/index.vue`
|
||||||
: ''
|
: ''
|
||||||
item.type = item.children && item.children.length > 0 ? 'menu_dir' : 'menu'
|
item.type = item.children && item.children.length > 0 ? 'menu_dir' : 'menu'
|
||||||
item.menu_type = item.children && item.children.length > 0 ? null : 'tab'
|
item.menu_type = item.children && item.children.length > 0 ? null : 'tab'
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
handlerMenu(item.children)
|
handlerMenu(item.children)
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
handlerMenu(res.data)
|
handlerMenu(res.data)
|
||||||
handleAdminRoute(res.data)
|
handleAdminRoute(res.data)
|
||||||
if (route.params.to) {
|
if (route.params.to) {
|
||||||
const lastRoute = JSON.parse(route.params.to as string)
|
const lastRoute = JSON.parse(route.params.to as string)
|
||||||
if (lastRoute.path != adminBaseRoutePath) {
|
if (lastRoute.path != adminBaseRoutePath) {
|
||||||
let query = !isEmpty(lastRoute.query) ? lastRoute.query : {}
|
let query = !isEmpty(lastRoute.query) ? lastRoute.query : {}
|
||||||
routePush({ path: lastRoute.path, query: query })
|
routePush({ path: lastRoute.path, query: query })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 跳转到第一个菜单
|
// 仅在 loading 页时跳转到第一个菜单,避免覆盖用户当前页面
|
||||||
let firstRoute = getFirstRoute(navTabs.state.tabsViewRoutes)
|
if (route.name === 'adminMainLoading') {
|
||||||
if (firstRoute) routePush(firstRoute.path)
|
const firstRoute = getFirstRoute(navTabs.state.tabsViewRoutes)
|
||||||
})
|
if (firstRoute) routePush(firstRoute.path)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
const onAdaptiveLayout = () => {
|
}
|
||||||
let defaultBeforeResizeLayout = {
|
|
||||||
layoutMode: config.layout.layoutMode,
|
const onAdaptiveLayout = () => {
|
||||||
menuCollapse: config.layout.menuCollapse
|
let defaultBeforeResizeLayout = {
|
||||||
}
|
layoutMode: config.layout.layoutMode,
|
||||||
|
menuCollapse: config.layout.menuCollapse
|
||||||
const clientWidth = document.body.clientWidth
|
}
|
||||||
if (clientWidth < 1024) {
|
|
||||||
/**
|
const clientWidth = document.body.clientWidth
|
||||||
* 锁定窗口改变自动调整 menuCollapse
|
if (clientWidth < 1024) {
|
||||||
* 避免已是小窗且打开了菜单栏时,意外的自动关闭菜单栏
|
/**
|
||||||
*/
|
* 锁定窗口改变自动调整 menuCollapse
|
||||||
if (!state.autoMenuCollapseLock) {
|
* 避免已是小窗且打开了菜单栏时,意外的自动关闭菜单栏
|
||||||
state.autoMenuCollapseLock = true
|
*/
|
||||||
config.setLayout('menuCollapse', true)
|
if (!state.autoMenuCollapseLock) {
|
||||||
}
|
state.autoMenuCollapseLock = true
|
||||||
config.setLayout('shrink', true)
|
config.setLayout('menuCollapse', true)
|
||||||
config.setLayoutMode('Classic')
|
}
|
||||||
} else {
|
config.setLayout('shrink', true)
|
||||||
state.autoMenuCollapseLock = false
|
config.setLayoutMode('Classic')
|
||||||
config.setLayout('menuCollapse', defaultBeforeResizeLayout.menuCollapse)
|
} else {
|
||||||
config.setLayout('shrink', false)
|
state.autoMenuCollapseLock = false
|
||||||
config.setLayoutMode(defaultBeforeResizeLayout.layoutMode)
|
config.setLayout('menuCollapse', defaultBeforeResizeLayout.menuCollapse)
|
||||||
}
|
config.setLayout('shrink', false)
|
||||||
}
|
config.setLayoutMode(defaultBeforeResizeLayout.layoutMode)
|
||||||
</script>
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-main class="layout-main" :style="mainHeight()">
|
<el-main class="layout-main" :style="mainHeight()">
|
||||||
<router-view v-slot="{ Component }">
|
<router-view v-slot="{ Component }">
|
||||||
<transition :name="config.layout.mainAnimation" mode="out-in">
|
<transition :name="config.layout.mainAnimation">
|
||||||
<keep-alive :include="state.keepAliveComponentNameList">
|
<keep-alive :include="state.keepAliveComponentNameList">
|
||||||
<component :is="Component" :key="state.componentKey" />
|
<component :is="Component" :key="state.componentKey || undefined" />
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</transition>
|
</transition>
|
||||||
</router-view>
|
</router-view>
|
||||||
@@ -32,7 +32,7 @@ const state: {
|
|||||||
componentKey: string
|
componentKey: string
|
||||||
keepAliveComponentNameList: string[]
|
keepAliveComponentNameList: string[]
|
||||||
} = reactive({
|
} = reactive({
|
||||||
componentKey: route.path,
|
componentKey: '',
|
||||||
keepAliveComponentNameList: []
|
keepAliveComponentNameList: []
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -79,7 +79,6 @@ onMounted(() => {
|
|||||||
watch(
|
watch(
|
||||||
() => route.path,
|
() => route.path,
|
||||||
() => {
|
() => {
|
||||||
state.componentKey = route.path
|
|
||||||
if (typeof navTabs.state.activeRoute?.meta.keepalive == 'string') {
|
if (typeof navTabs.state.activeRoute?.meta.keepalive == 'string') {
|
||||||
addKeepAliveComponentName(navTabs.state.activeRoute?.meta.keepalive)
|
addKeepAliveComponentName(navTabs.state.activeRoute?.meta.keepalive)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,98 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
v-loading="true"
|
v-loading="true"
|
||||||
element-loading-background="var(--ba-bg-color-overlay)"
|
element-loading-background="var(--ba-bg-color-overlay)"
|
||||||
element-loading-text="加载中"
|
element-loading-text="加载中"
|
||||||
class="default-main ba-main-loading"
|
class="default-main ba-main-loading"
|
||||||
:style="{ height:'calc(100vh - 170px)'}"
|
:style="{ height: 'calc(100vh - 170px)' }"
|
||||||
></div>
|
></div>
|
||||||
<div v-if="state.showReload" class="loading-footer mt10">
|
<div v-if="state.showReload" class="loading-footer mt10">
|
||||||
<el-button @click="refresh" type="warning">重新加载</el-button>
|
<el-button @click="refresh" type="warning">重新加载</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { onUnmounted, reactive } from 'vue'
|
import { onMounted, onUnmounted, reactive, watch } from 'vue'
|
||||||
import router from '@/router/index'
|
import { useRoute } from 'vue-router'
|
||||||
import { useNavTabs } from '@/stores/navTabs'
|
import router from '@/router/index'
|
||||||
import { isAdminApp } from '@/utils/common'
|
import { useNavTabs } from '@/stores/navTabs'
|
||||||
import { getFirstRoute, routePush } from '@/utils/router'
|
import { isAdminApp } from '@/utils/common'
|
||||||
let timer: number
|
import { getFirstRoute, routePush } from '@/utils/router'
|
||||||
|
import { isEmpty } from 'lodash-es'
|
||||||
const navTabs = useNavTabs()
|
import { adminBaseRoutePath } from '@/router/static'
|
||||||
const state = reactive({
|
|
||||||
maximumWait: 1000 * 6,
|
let timer: number
|
||||||
showReload: false,
|
|
||||||
})
|
const route = useRoute()
|
||||||
|
const navTabs = useNavTabs()
|
||||||
const refresh = () => {
|
const state = reactive({
|
||||||
router.go(0)
|
maximumWait: 1000 * 6,
|
||||||
}
|
showReload: false
|
||||||
// if (isAdminApp() && navTabs.state.tabsViewRoutes.length > 0) {
|
})
|
||||||
// let firstRoute = getFirstRoute(navTabs.state.tabsViewRoutes)
|
|
||||||
// if (firstRoute) routePush(firstRoute.path)
|
const tryRedirect = () => {
|
||||||
// }
|
if (route.params.to) {
|
||||||
|
try {
|
||||||
timer = window.setTimeout(() => {
|
const lastRoute = JSON.parse(route.params.to as string)
|
||||||
state.showReload = true
|
if (lastRoute.path && lastRoute.path !== adminBaseRoutePath) {
|
||||||
}, state.maximumWait)
|
const query = !isEmpty(lastRoute.query) ? lastRoute.query : {}
|
||||||
|
routePush({ path: lastRoute.path, query })
|
||||||
onUnmounted(() => {
|
return true
|
||||||
clearTimeout(timer)
|
}
|
||||||
})
|
} catch (error) {
|
||||||
</script>
|
console.error(error)
|
||||||
|
}
|
||||||
<style scoped lang="scss">
|
}
|
||||||
.ba-main-loading {
|
if (isAdminApp() && navTabs.state.tabsViewRoutes.length > 0) {
|
||||||
height: 300px;
|
const firstRoute = getFirstRoute(navTabs.state.tabsViewRoutes)
|
||||||
display: flex;
|
if (firstRoute) {
|
||||||
align-items: center;
|
routePush(firstRoute.path)
|
||||||
justify-content: center;
|
return true
|
||||||
}
|
}
|
||||||
.loading-footer {
|
}
|
||||||
display: flex;
|
return false
|
||||||
align-items: center;
|
}
|
||||||
justify-content: center;
|
|
||||||
}
|
const refresh = () => {
|
||||||
</style>
|
if (!tryRedirect()) {
|
||||||
|
router.replace(route.fullPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (tryRedirect()) return
|
||||||
|
|
||||||
|
const stop = watch(
|
||||||
|
() => navTabs.state.tabsViewRoutes.length,
|
||||||
|
len => {
|
||||||
|
if (len > 0 && tryRedirect()) {
|
||||||
|
stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
timer = window.setTimeout(() => {
|
||||||
|
state.showReload = true
|
||||||
|
}, state.maximumWait)
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
clearTimeout(timer)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.ba-main-loading {
|
||||||
|
height: 300px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.loading-footer {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ const staticRoutes: Array<RouteRecordRaw> = [
|
|||||||
|
|
||||||
{
|
{
|
||||||
// 后台找不到页面了-可能是路由未加载上
|
// 后台找不到页面了-可能是路由未加载上
|
||||||
path: adminBaseRoutePath + ':path(.*)*',
|
path: adminBaseRoutePath + '/:path(.*)*',
|
||||||
redirect: to => {
|
redirect: to => {
|
||||||
return {
|
return {
|
||||||
name: 'adminMainLoading',
|
name: 'adminMainLoading',
|
||||||
|
|||||||
@@ -179,7 +179,6 @@ function createAxios<Data = any, T = ApiPromise<Data>>(
|
|||||||
return Axios(response.config)
|
return Axios(response.config)
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
window.location.reload()
|
|
||||||
adminInfo.removeToken()
|
adminInfo.removeToken()
|
||||||
router.push({ name: 'login' })
|
router.push({ name: 'login' })
|
||||||
return Promise.reject(err)
|
return Promise.reject(err)
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ export const onClickMenu = (menu: RouteRecordRaw) => {
|
|||||||
switch (menu.meta?.menu_type) {
|
switch (menu.meta?.menu_type) {
|
||||||
case 'iframe':
|
case 'iframe':
|
||||||
case 'tab':
|
case 'tab':
|
||||||
|
if (router.currentRoute.value.path === menu.path) return
|
||||||
routePush({ path: menu.path })
|
routePush({ path: menu.path })
|
||||||
break
|
break
|
||||||
case 'link':
|
case 'link':
|
||||||
|
|||||||
Reference in New Issue
Block a user