60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import { createRouter, createWebHistory, type Router } from "vue-router";
|
|
import { adminRoutes } from "./admin.ts";
|
|
import { memberRoutes } from "./member.ts";
|
|
import { setAuthRedirect } from "@/api/auth-redirect.ts";
|
|
import { useAdminSessionStore } from "@/stores/admin-session.ts";
|
|
import { useMemberTokenStore } from "@/stores/member-token.ts";
|
|
|
|
declare module "vue-router" {
|
|
interface RouteMeta {
|
|
public?: boolean;
|
|
requiresAdmin?: boolean;
|
|
requiresMember?: boolean;
|
|
world?: "admin" | "member";
|
|
}
|
|
}
|
|
|
|
export const router: Router = createRouter({
|
|
history: createWebHistory(),
|
|
routes: [
|
|
{ path: "/", redirect: "/admin/overview" },
|
|
...adminRoutes,
|
|
...memberRoutes,
|
|
{ path: "/:pathMatch(.*)*", redirect: "/admin/overview" },
|
|
],
|
|
});
|
|
|
|
router.beforeEach((to) => {
|
|
if (to.meta.public) return true;
|
|
|
|
const memberToken = useMemberTokenStore();
|
|
|
|
// 管理面:硬刷新后 Pinia 为空但会话 cookie 仍在——交给 GET /session 与 401 分流裁决
|
|
if (to.meta.requiresMember && !memberToken.hasToken) {
|
|
return { name: "member-login" };
|
|
}
|
|
|
|
return true;
|
|
});
|
|
|
|
/** 401 分流接入 router(由 main.ts 调用一次) */
|
|
export function bindAuthRedirectToRouter(): void {
|
|
setAuthRedirect((world, reason) => {
|
|
const adminSession = useAdminSessionStore();
|
|
const memberToken = useMemberTokenStore();
|
|
if (world === "admin") {
|
|
adminSession.signOut();
|
|
void router.push({
|
|
name: "admin-login",
|
|
query: reason === "expired" ? { reason: "expired" } : {},
|
|
});
|
|
} else {
|
|
memberToken.clearToken();
|
|
void router.push({
|
|
name: "member-login",
|
|
query: reason === "expired" ? { reason: "expired" } : {},
|
|
});
|
|
}
|
|
});
|
|
}
|