Skip to content

Commit 519728d

Browse files
committed
feat: 增加自定义首页
1 parent f083e89 commit 519728d

3 files changed

Lines changed: 85 additions & 16 deletions

File tree

frontend/src/main.tsx

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { store } from "./store";
1010
import { Provider } from "react-redux";
1111
import theme from "./theme";
1212
import {errorConfigStore} from "@/utils/errorConfigStore.ts";
13+
import { setCachedHomePageUrl, getCachedHomePageUrl } from "@/utils/systemParam";
1314
import "@/i18n";
1415

1516
function showLoadingUI() {
@@ -43,41 +44,81 @@ function showLoadingUI() {
4344
`;
4445
}
4546

47+
/**
48+
* 从 localStorage 读取 JWT token
49+
*/
50+
function getAuthToken(): string | null {
51+
const session = localStorage.getItem('session');
52+
if (session) {
53+
try {
54+
return JSON.parse(session).token || null;
55+
} catch {
56+
return null;
57+
}
58+
}
59+
return null;
60+
}
61+
4662
/**
4763
* 自定义首页URL重定向
4864
* 在任何渲染之前检查系统参数 sys.home.page.url,若已配置则立即跳转,确保无闪烁。
49-
* 使用原始 fetch 避免触发 antd message 等尚未初始化的 UI 组件
65+
* 使用原始 fetch 但携带 JWT token,避免已登录用户仍收到 401
5066
*/
51-
async function checkHomePageRedirect(): Promise<boolean> {
67+
async function checkHomePageRedirect(): Promise<{ redirected: boolean; authNeeded: boolean }> {
5268
if (window.location.pathname !== '/') {
53-
return false;
69+
return { redirected: false, authNeeded: false };
5470
}
71+
72+
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
73+
const token = getAuthToken();
74+
if (token) {
75+
headers['Authorization'] = `Bearer ${token}`;
76+
}
77+
5578
try {
5679
const response = await fetch('/api/sys-param/sys.home.page.url', {
5780
method: 'GET',
5881
credentials: 'include',
59-
headers: { 'Content-Type': 'application/json' },
82+
headers,
6083
});
6184
if (response.ok) {
6285
const result = await response.json();
6386
const url = result?.data?.paramValue?.trim();
6487
if (url) {
88+
setCachedHomePageUrl(url);
6589
window.location.replace(url);
66-
return true;
90+
return { redirected: true, authNeeded: false };
91+
}
92+
// 参数存在但值为空 → 管理员已清除,清掉缓存
93+
setCachedHomePageUrl(null);
94+
} else if (response.status === 401) {
95+
// 未登录,尝试从缓存读取
96+
const cachedUrl = getCachedHomePageUrl();
97+
if (cachedUrl) {
98+
window.location.replace(cachedUrl);
99+
return { redirected: true, authNeeded: false };
67100
}
101+
// 未登录且无缓存,需要弹出登录框
102+
return { redirected: false, authNeeded: true };
68103
}
69104
} catch {
70-
// 忽略错误,继续正常启动
105+
// 网络错误等,尝试从缓存读取
106+
const cachedUrl = getCachedHomePageUrl();
107+
if (cachedUrl) {
108+
window.location.replace(cachedUrl);
109+
return { redirected: true, authNeeded: false };
110+
}
71111
}
72-
return false;
112+
return { redirected: false, authNeeded: false };
73113
}
74114

75115
async function bootstrap() {
76116
const container = document.getElementById("root");
77117
if (!container) return;
78118

79119
// 在任何 UI 渲染之前检查自定义首页重定向
80-
if (await checkHomePageRedirect()) {
120+
const { redirected, authNeeded } = await checkHomePageRedirect();
121+
if (redirected) {
81122
return;
82123
}
83124

@@ -106,6 +147,13 @@ async function bootstrap() {
106147
</Provider>
107148
</StrictMode>
108149
);
150+
151+
// 未登录且无缓存时,等 React 挂载后弹出登录框
152+
if (authNeeded) {
153+
setTimeout(() => {
154+
window.dispatchEvent(new CustomEvent('show-login'));
155+
}, 500);
156+
}
109157
}
110158

111159
bootstrap();

frontend/src/pages/Layout/Header.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { User, Globe, LogIn, UserPlus, Sparkles, Shield } from "lucide-react"
2-
import { memo, useState, useEffect, useCallback, useRef } from "react";
2+
import { memo, useState, useEffect, useCallback } from "react";
33
import { NavLink } from "react-router";
44
import { Button, Dropdown, message } from "antd"
55
import type { MenuProps } from 'antd'
66
import { LoginDialog } from "./LoginDialog"
77
import { SignupDialog } from "./SignupDialog"
88
import { post, get } from "@/utils/request.ts";
9+
import { getCachedHomePageUrl, setCachedHomePageUrl } from "@/utils/systemParam";
910
import { getHomePageUrl } from "@/utils/systemParam";
1011
import { useTranslation } from "react-i18next";
1112
import i18n from "@/i18n";
@@ -42,7 +43,6 @@ export function Header() {
4243
const [currentUser, setCurrentUser] = useState<UserResponse | null>(null);
4344
const [authMode, setAuthMode] = useState<'SSO' | 'JWT' | 'NONE'>('NONE');
4445
const [userLoading, setUserLoading] = useState(true);
45-
const [homePageUrl, setHomePageUrl] = useState<string | null>(null);
4646

4747
const handleLogin = async (values: { username: string; password: string }) => {
4848
try {
@@ -124,15 +124,16 @@ export function Header() {
124124
};
125125

126126
const handleHomeClick = useCallback((e: React.MouseEvent) => {
127-
if (homePageUrl) {
127+
const homeUrl = getCachedHomePageUrl();
128+
if (homeUrl) {
128129
e.preventDefault();
129-
window.location.href = homePageUrl;
130+
window.location.href = homeUrl;
130131
}
131-
}, [homePageUrl]);
132+
}, []);
132133

133-
// 获取自定义首页URL
134+
// 已登录时后台刷新缓存,保持与后端同步
134135
useEffect(() => {
135-
getHomePageUrl().then(setHomePageUrl);
136+
getHomePageUrl().then(url => setCachedHomePageUrl(url)).catch(() => {});
136137
}, []);
137138

138139
// 检测是否在 ME 环境

frontend/src/utils/systemParam.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
11
/**
2-
* System Parameter API
32
* 系统参数 API 接口
43
*/
4+
5+
// localStorage 缓存 key
6+
const HOME_PAGE_URL_CACHE_KEY = 'datamate:homePageUrl';
7+
8+
/**
9+
* 将首页URL写入缓存
10+
*/
11+
export function setCachedHomePageUrl(url: string | null) {
12+
if (url) {
13+
localStorage.setItem(HOME_PAGE_URL_CACHE_KEY, url);
14+
} else {
15+
localStorage.removeItem(HOME_PAGE_URL_CACHE_KEY);
16+
}
17+
}
18+
19+
/**
20+
* 同步读取缓存的首页URL
21+
*/
22+
export function getCachedHomePageUrl(): string | null {
23+
return localStorage.getItem(HOME_PAGE_URL_CACHE_KEY);
24+
}
525
import { get } from '@/utils/request';
626

727
export interface SysParam {

0 commit comments

Comments
 (0)