48 lines
2.0 KiB
Vue
48 lines
2.0 KiB
Vue
<script setup>
|
|
/**
|
|
* 全站入口:公共购买页可在未登录时使用独立布局,其余页面沿用路由指定的布局。
|
|
* 路由放行与组件实际挂载同时受会话约束,防止重定向等待期间仍执行受保护页面请求。
|
|
*/
|
|
import { computed, onMounted, onBeforeUnmount } from "vue";
|
|
import { useRouter } from "#app";
|
|
import { NuxtLayout, NuxtPage, NuxtRouteAnnouncer } from "#components";
|
|
import BuildUpdateNotice from "~/components/BuildUpdateNotice.vue";
|
|
import OperationToasts from "~/components/OperationToasts.vue";
|
|
import { useAuth } from "~/lib/auth.js";
|
|
import { t as useTheme } from "~/lib/useTheme.js";
|
|
import { isPublicShop, isAuthPage, isPublicRoute } from "~/utils/access.js";
|
|
|
|
const auth = useAuth();
|
|
// 入口控制 NuxtPage 是否挂载,必须读取守卫已确认的路由;Nuxt useRoute 要等页面完成才同步,会形成循环等待。
|
|
const route = useRouter().currentRoute;
|
|
const theme = useTheme();
|
|
// 只为访客切换公开购买布局;登录后的同一路由继续使用会员中心布局。
|
|
const layout = computed(() =>
|
|
!auth.isLoggedIn && isPublicShop(route.value)
|
|
? "public-order"
|
|
: route.value.meta.layout,
|
|
);
|
|
// 中间件负责导航,入口负责禁止未授权组件树挂载,两者处理的是不同的生命周期阶段。
|
|
const canRenderRoute = computed(
|
|
() => auth.isLoggedIn || isPublicRoute(route.value),
|
|
);
|
|
// 账号切换时重新创建布局与页面,清除旧账号的局部状态;登录入口自身按路径区分。
|
|
const routeSessionKey = computed(() =>
|
|
isAuthPage(route.value.path) || route.value.path === "/home.htm"
|
|
? route.value.path
|
|
: auth.token || "anonymous",
|
|
);
|
|
// 主题监听由入口统一注册和释放,避免每次页面导航重复绑定系统主题事件。
|
|
onMounted(theme.init);
|
|
onBeforeUnmount(theme.dispose);
|
|
</script>
|
|
|
|
<template>
|
|
<NuxtRouteAnnouncer />
|
|
<BuildUpdateNotice />
|
|
<OperationToasts />
|
|
<NuxtLayout v-if="canRenderRoute" :key="routeSessionKey" :name="layout"
|
|
><NuxtPage
|
|
/></NuxtLayout>
|
|
</template>
|