Compare commits

...

2 Commits

4 changed files with 46 additions and 56 deletions

View File

@ -130,7 +130,7 @@ function addDynamicRoutes(menus) {
path: "/", path: "/",
name: "Main", name: "Main",
component: () => import("@/views/Main.vue"), component: () => import("@/views/Main.vue"),
redirect: "/dashboard", redirect: "/home",
meta: { requiresAuth: true }, meta: { requiresAuth: true },
children: [...staticMainChildren, ...dynamicRoutes] // 合并静态和动态子路由 children: [...staticMainChildren, ...dynamicRoutes] // 合并静态和动态子路由
}); });
@ -190,8 +190,17 @@ router.beforeEach(async (to, from, next) => {
} }
if (!dynamicRoutesAdded) { if (!dynamicRoutesAdded) {
await loadAndAddDynamicRoutes(); try {
// 路由加载后重新导航,确保路由匹配正确 await loadAndAddDynamicRoutes();
} catch (error) {
console.error('动态路由加载失败:', error);
// token 无效时跳转登录
if (error?.message === 'token无效' || error?.response?.status === 401) {
next({ path: '/login' });
return;
}
}
// 路由加载后重新导航,确保路由匹配正确
next({ path: to.path, replace: true }); next({ path: to.path, replace: true });
return; return;
} }

View File

@ -2,6 +2,7 @@
* 通用的别名路径解析工具 * 通用的别名路径解析工具
* 用于在动态导入时解析 @ 别名路径 * 用于在动态导入时解析 @ 别名路径
*/ */
import { h } from 'vue';
// 使用 import.meta.glob 预加载所有组件 // 使用 import.meta.glob 预加载所有组件
const viewsModules = import.meta.glob('../views/**/*.vue'); const viewsModules = import.meta.glob('../views/**/*.vue');

View File

@ -119,31 +119,11 @@ const handleAsideMenuClick = async (menuItem) => {
return; return;
} }
// router.push(targetPath).catch(err => {
let routeExists = router.resolve(targetPath).matched.length > 0; if (err.name !== 'NavigationDuplicated') {
console.error('路由跳转失败:', err);
if (!routeExists) {
// 500ms
for (let i = 0; i < 5; i++) {
await new Promise(resolve => setTimeout(resolve, 100));
routeExists = router.resolve(targetPath).matched.length > 0;
if (routeExists) break;
} }
} });
//
if (routeExists) {
router.push(targetPath).catch(err => {
if (err.name !== 'NavigationDuplicated') {
console.error('路由跳转失败:', err);
}
});
} else {
//
console.warn('路由不存在,尝试刷新页面:', targetPath);
//
ElMessage.warning(`路由 ${targetPath} 不存在,请刷新缓存后重试`);
}
}; };
const tabsCloseTab = (targetKey) => { const tabsCloseTab = (targetKey) => {
tabsStore.removeTab(targetKey); tabsStore.removeTab(targetKey);
@ -166,39 +146,17 @@ const closeAll = () => {
watch( watch(
() => tabsStore.activeTab, () => tabsStore.activeTab,
(newVal, oldVal) => { (newVal, oldVal) => {
// oldVal undefined
// watchtabhandleAsideMenuClick
if (newVal && oldVal !== undefined && router.currentRoute.value.fullPath !== newVal) { if (newVal && oldVal !== undefined && router.currentRoute.value.fullPath !== newVal) {
// tab
if (newVal === defaultDashboardPath) { if (newVal === defaultDashboardPath) {
tabsStore.closeAll(); tabsStore.closeAll();
} }
nextTick(() => {
// router.push(newVal).catch(err => {
const routeExists = router.resolve(newVal).matched.length > 0; if (err.name !== 'NavigationDuplicated') {
console.error('路由跳转失败:', err);
if (routeExists) {
//
nextTick(() => {
router.push(newVal).catch(err => {
if (err.name !== 'NavigationDuplicated') {
console.error('路由跳转失败:', err);
}
});
});
} else {
//
setTimeout(() => {
const retryRouteExists = router.resolve(newVal).matched.length > 0;
if (retryRouteExists && router.currentRoute.value.fullPath !== newVal) {
router.push(newVal).catch(err => {
if (err.name !== 'NavigationDuplicated') {
console.error('路由跳转失败:', err);
}
});
} }
}, 100); });
} });
} }
}, },
{ flush: 'post' } { flush: 'post' }

View File

@ -58,6 +58,8 @@
</label> </label>
<div class="action-links"> <div class="action-links">
<a class="forget-link" @click.prevent="goForget">忘记密码?</a> <a class="forget-link" @click.prevent="goForget">忘记密码?</a>
<span>&nbsp;&nbsp;|&nbsp;&nbsp;</span>
<a class="forget-link" @click.prevent="clearCache">清除缓存</a>
</div> </div>
</div> </div>
<transition name="fade"> <transition name="fade">
@ -66,6 +68,9 @@
<button class="login-btn" @click="handleLogin" :disabled="loading"> <button class="login-btn" @click="handleLogin" :disabled="loading">
{{ loading ? "登录中..." : "登 录" }} {{ loading ? "登录中..." : "登 录" }}
</button> </button>
<div>
</div>
</div> </div>
</div> </div>
<!-- 背景光效 --> <!-- 背景光效 -->
@ -74,7 +79,7 @@
</div> </div>
</template> </template>
<script setup> <script setup lang="ts">
import { ref, onMounted, nextTick } from "vue"; import { ref, onMounted, nextTick } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useAuthStore } from "@/stores/auth"; import { useAuthStore } from "@/stores/auth";
@ -420,6 +425,23 @@ onMounted(() => {
const goRegister = () => router.push("/register"); const goRegister = () => router.push("/register");
const goForget = () => router.push("/forget"); const goForget = () => router.push("/forget");
const clearCache = async () => {
try {
await ElMessageBox.confirm("确定要清除本地缓存吗?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
});
localStorage.clear();
sessionStorage.clear();
ElMessage.success("缓存已清除");
//
window.location.reload();
} catch {
//
}
};
</script> </script>
<style scoped> <style scoped>