ALIEZ 1 miesiąc temu
rodzic
commit
d29ee339ff
2 zmienionych plików z 42 dodań i 3 usunięć
  1. 7 3
      src/lib/api.ts
  2. 35 0
      src/lib/env.ts

+ 7 - 3
src/lib/api.ts

@@ -4,7 +4,8 @@ import axios, {
   type AxiosRequestConfig,
 } from "axios";
 
-import { getApiBaseUrl } from "@/lib/env";
+import { clearUser } from "@/lib/auth-types";
+import { getApiBaseUrl, resolveAuthLoginHref } from "@/lib/env";
 
 /**
  * 业务后端接口约定:
@@ -76,7 +77,7 @@ function notifySessionTimeoutAndRedirect() {
   if (authTimeoutDialogShown) return;
   authTimeoutDialogShown = true;
   window.alert("登录超时,请重新登录");
-  window.location.assign("/auth/login");
+  window.location.assign(resolveAuthLoginHref());
 }
 
 function isPlainObject(v: unknown): v is Record<string, unknown> {
@@ -101,7 +102,10 @@ api.interceptors.response.use(
     const body = res.data;
     if (!isPlainObject(body) || !("code" in body)) return res;
     if (body.code === 600 || body.code === "600") {
-      setApiAuthToken(null);
+      if (typeof window !== "undefined") {
+        setApiAuthToken(null);
+        clearUser();
+      }
       notifySessionTimeoutAndRedirect();
       return Promise.reject(new ApiError("登录状态失效,请重新登录", 600, body));
     }

+ 35 - 0
src/lib/env.ts

@@ -47,6 +47,41 @@ function resolveApiBaseUrlValue(raw: string | undefined): string {
   return s;
 }
 
+/**
+ * 登录页跳转地址(仅浏览器)。
+ * 相对路径 `/auth/login` 会保留当前 URL 的端口;若用户通过 `jinclab.com:4000` 访问而
+ * `NEXT_PUBLIC_SITE_URL` 为无端口的公网地址,则用后者 origin,避免地址栏出现 `:4000`。
+ * 本地开发未配置 SITE_URL 时仍用相对路径。
+ */
+export function resolveAuthLoginHref(): string {
+  const path = "/auth/login";
+  if (typeof window === "undefined") return path;
+
+  const site = process.env.NEXT_PUBLIC_SITE_URL?.trim().replace(/\/$/, "");
+  if (!site) return path;
+
+  let siteUrl: URL;
+  try {
+    siteUrl = new URL(site);
+  } catch {
+    return path;
+  }
+
+  const canonical = siteUrl.hostname;
+  const allowedHosts = new Set([canonical, `www.${canonical}`]);
+
+  try {
+    const current = new URL(window.location.href);
+    if (allowedHosts.has(current.hostname)) {
+      return `${siteUrl.origin}${path}`;
+    }
+  } catch {
+    return path;
+  }
+
+  return path;
+}
+
 export function resolveAppEnv(): AppEnv {
   const fromEnv = process.env.NEXT_PUBLIC_APP_ENV;
   if (fromEnv === "local" || fromEnv === "test" || fromEnv === "production") {