Files
console-dev/app/plugins/03-session.client.js
T

41 lines
1.6 KiB
JavaScript

/** 同源多标签页会话同步:监听 jwt/clear 变更,退出时将当前受保护页面替换为登录页。 */
import { defineNuxtPlugin } from "#app";
import { useAuth, isValidJwt } from "~/lib/auth.js";
import { r as safeRedirect } from "~/lib/auth-redirect.js";
import { isPublicRoute } from "~/utils/access.js";
export default defineNuxtPlugin({
name: "console-session-sync",
dependsOn: ["console-ui"],
setup(app) {
const auth = useAuth();
const router = app.$router;
// 只处理 localStorage 会话事件;读取最新值而非 event.newValue,避免积压事件倒退状态。
function reconcileSession(event) {
if (
event.storageArea !== localStorage ||
(event.key !== null && event.key !== "jwt")
)
return;
// Read the latest value: several storage events may already be queued.
const persisted = localStorage.getItem("jwt");
if (persisted === auth.token) return;
if (isValidJwt(persisted)) auth.prepareLogin().commit(persisted);
else auth.clear();
const route = router.currentRoute.value;
if (!auth.isLoggedIn && !isPublicRoute(route)) {
const redirect = safeRedirect(route.fullPath);
void router.replace({
path: "/login",
query: redirect === "/" ? {} : { redirect },
});
}
}
window.addEventListener("storage", reconcileSession);
// 应用销毁时解绑,避免热重载或重新挂载后叠加处理同一 storage 事件。
app.vueApp.onUnmount(() =>
window.removeEventListener("storage", reconcileSession),
);
},
});