Skip to content

Commit 203ebd1

Browse files
committed
支持自定义首页
1 parent 7f23267 commit 203ebd1

9 files changed

Lines changed: 240 additions & 44 deletions

File tree

backend/api-gateway/src/main/java/com/datamate/gateway/ApiGatewayApplication.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
5555
.route("data-cleaning", r -> r.path("/api/cleaning/**")
5656
.uri("http://datamate-backend-python:18000"))
5757

58+
.route("data-setting", r -> r.path("/api/sys-param/**")
59+
.uri("http://datamate-backend-python:18000"))
60+
5861
.route("deer-flow-frontend", r -> r.path("/chat/**")
5962
.uri("http://deer-flow-frontend:3000"))
6063

deployment/helm/datamate/values.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public:
4242
DB_PASSWORD: "password"
4343
CERT_PASS: ""
4444
DOMAIN: ""
45+
HOME_PAGE_URL: ""
4546

4647
datasetVolume: &datasetVolume
4748
name: dataset-volume
@@ -90,6 +91,11 @@ database:
9091
secretKeyRef:
9192
name: datamate-conf
9293
key: DB_PASSWORD
94+
- name: HOME_PAGE_URL
95+
valueFrom:
96+
secretKeyRef:
97+
name: datamate-conf
98+
key: HOME_PAGE_URL
9399
volumes:
94100
- *dataVolume
95101
- *logVolume

frontend/src/main.tsx

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,39 +11,96 @@ import theme from "./theme";
1111
import {errorConfigStore} from "@/utils/errorConfigStore.ts";
1212
import "@/i18n";
1313

14+
async function checkHomePageRedirect(): Promise<string | null> {
15+
try {
16+
const response = await fetch('/api/sys-param/sys.home.page.url', {
17+
cache: 'no-store'
18+
});
19+
20+
if (response.ok) {
21+
const result = await response.json();
22+
return result.data?.paramValue?.trim() || null;
23+
}
24+
} catch (error) {
25+
console.error('Failed to fetch home page URL:', error);
26+
}
27+
28+
return null;
29+
}
30+
31+
function showLoadingUI() {
32+
const container = document.getElementById("root");
33+
if (!container) return;
34+
35+
container.innerHTML = `
36+
<div style="
37+
min-height: 100vh;
38+
background: linear-gradient(to bottom right, #eff6ff, #e0e7ff);
39+
display: flex;
40+
align-items: center;
41+
justify-content: center;
42+
">
43+
<div style="text-align: center;">
44+
<div style="
45+
width: 40px;
46+
height: 40px;
47+
border: 3px solid #e5e7eb;
48+
border-top-color: #3b82f6;
49+
border-radius: 50%;
50+
animation: spin 1s linear infinite;
51+
"></div>
52+
<style>
53+
@keyframes spin {
54+
to { transform: rotate(360deg); }
55+
}
56+
</style>
57+
</div>
58+
</div>
59+
`;
60+
}
61+
1462
async function bootstrap() {
1563
const container = document.getElementById("root");
1664
if (!container) return;
1765

18-
const root = createRoot(container);
66+
showLoadingUI();
1967

2068
try {
21-
// 2. 【关键步骤】在渲染前,等待配置文件加载完成
22-
// 这一步会发起 fetch 请求去拿 /config/error-code.json
23-
await errorConfigStore.loadConfig();
69+
const [, homePageUrl] = await Promise.all([
70+
errorConfigStore.loadConfig(),
71+
checkHomePageRedirect()
72+
]);
73+
74+
if (homePageUrl) {
75+
const currentPath = window.location.pathname;
76+
const targetPath = new URL(homePageUrl, window.location.origin).pathname;
77+
78+
if (currentPath === '/' && currentPath !== targetPath) {
79+
window.location.href = homePageUrl;
80+
return;
81+
}
82+
}
2483

2584
} catch (e) {
26-
// 容错处理:即使配置文件加载失败(比如404),也不应该导致整个 App 白屏崩溃
27-
// 此时 App 会使用代码里的默认兜底文案
28-
console.error('Error config load failed, using default messages.', e);
29-
} finally {
30-
// 3. 无论配置加载成功与否,最后都执行渲染
31-
root.render(
32-
<StrictMode>
33-
<Provider store={store}>
34-
<ConfigProvider theme={ theme }>
35-
<AntdApp>
36-
<Suspense fallback={<Spin />}>
37-
<TopLoadingBar />
38-
<RouterProvider router={router} />
39-
</Suspense>
40-
</AntdApp>
41-
</ConfigProvider>
42-
</Provider>
43-
</StrictMode>
44-
);
85+
console.error('Config load failed:', e);
4586
}
87+
88+
const root = createRoot(container);
89+
90+
root.render(
91+
<StrictMode>
92+
<Provider store={store}>
93+
<ConfigProvider theme={ theme }>
94+
<AntdApp>
95+
<Suspense fallback={<Spin />}>
96+
<TopLoadingBar />
97+
<RouterProvider router={router} />
98+
</Suspense>
99+
</AntdApp>
100+
</ConfigProvider>
101+
</Provider>
102+
</StrictMode>
103+
);
46104
}
47105

48-
// 4. 执行启动
49106
bootstrap();

frontend/src/pages/Home/Home.tsx

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,67 @@ import {
22
FolderOpen,
33
Settings,
44
ArrowRight,
5-
Sparkles,
65
Target,
76
Zap,
87
Database,
98
MessageSquare,
109
GitBranch,
10+
Sparkles,
1111
} from "lucide-react";
1212
import { features, menuItems } from "../Layout/Menu.tsx";
13-
import { useState } from 'react';
13+
import { useState, useEffect } from 'react';
1414
import { useNavigate } from "react-router";
15-
import { Card, Dropdown, Button } from "antd";
15+
import { Card, Dropdown, Button, Spin } from "antd";
1616
import type { MenuProps } from 'antd';
1717
import { Globe } from "lucide-react";
1818
import { useTranslation } from "react-i18next";
1919
import i18n from "@/i18n";
20+
import { getHomePageUrl } from '@/utils/systemParam';
2021

2122
export default function WelcomePage() {
2223
const navigate = useNavigate();
2324
const [isChecking, setIsChecking] = useState(false);
25+
const [isCheckingRedirect, setIsCheckingRedirect] = useState(true);
2426
const { t } = useTranslation();
2527

28+
useEffect(() => {
29+
let isMounted = true;
30+
31+
const checkAndRedirect = async () => {
32+
try {
33+
const homePageUrl = await getHomePageUrl();
34+
35+
if (!isMounted) return;
36+
37+
if (homePageUrl) {
38+
window.location.href = homePageUrl;
39+
return;
40+
}
41+
42+
setIsCheckingRedirect(false);
43+
} catch (error) {
44+
console.error('Failed to check home page URL:', error);
45+
if (isMounted) {
46+
setIsCheckingRedirect(false);
47+
}
48+
}
49+
};
50+
51+
checkAndRedirect();
52+
53+
return () => {
54+
isMounted = false;
55+
};
56+
}, []);
57+
58+
if (isCheckingRedirect) {
59+
return (
60+
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center">
61+
<Spin size="large" />
62+
</div>
63+
);
64+
}
65+
2666
const languageMenuItems: MenuProps['items'] = [
2767
{
2868
key: 'zh',
@@ -42,7 +82,6 @@ export default function WelcomePage() {
4282
}
4383
];
4484

45-
// 检查接口连通性的函数
4685
const checkDeerFlowDeploy = async (): Promise<boolean> => {
4786
try {
4887
const controller = new AbortController();
@@ -59,7 +98,6 @@ export default function WelcomePage() {
5998

6099
clearTimeout(timeoutId);
61100

62-
// 检查 HTTP 状态码在 200-299 范围内
63101
if (response.ok) {
64102
return true;
65103
}
@@ -70,22 +108,19 @@ export default function WelcomePage() {
70108
};
71109

72110
const handleChatClick = async () => {
73-
if (isChecking) return; // 防止重复点击
111+
if (isChecking) return;
74112

75113
setIsChecking(true);
76114

77115
try {
78116
const isDeerFlowDeploy = await checkDeerFlowDeploy();
79117

80118
if (isDeerFlowDeploy) {
81-
// 接口正常,执行原有逻辑
82119
window.location.href = "/chat";
83120
} else {
84-
// 接口异常,使用 navigate 跳转
85121
navigate("/chat");
86122
}
87123
} catch (error) {
88-
// 发生错误时也使用 navigate 跳转
89124
console.error('检查过程中发生错误:', error);
90125
navigate("/chat");
91126
} finally {

frontend/src/utils/systemParam.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* System Parameter API
3+
* 系统参数 API 接口
4+
*/
5+
import { get } from '@/utils/request';
6+
7+
export interface SysParam {
8+
id: string;
9+
paramValue: string;
10+
paramType: string;
11+
optionList?: string;
12+
description?: string;
13+
isBuiltIn: boolean;
14+
canModify: boolean;
15+
isEnabled: boolean;
16+
createdAt?: string;
17+
updatedAt?: string;
18+
createdBy?: string;
19+
updatedBy?: string;
20+
}
21+
22+
/**
23+
* 获取所有系统参数
24+
*/
25+
export async function getSystemParams(): Promise<SysParam[]> {
26+
const response = await get<{ code: string; message: string; data: SysParam[] }>('/api/sys-param/list');
27+
return response.data || [];
28+
}
29+
30+
/**
31+
* 根据ID获取系统参数
32+
*/
33+
export async function getSystemParamById(paramId: string): Promise<SysParam | null> {
34+
try {
35+
const response = await get<{ code: string; message: string; data: SysParam }>(`/api/sys-param/${paramId}`);
36+
return response.data;
37+
} catch (error) {
38+
return null;
39+
}
40+
}
41+
42+
/**
43+
* 获取首页URL配置
44+
*/
45+
export async function getHomePageUrl(): Promise<string | null> {
46+
try {
47+
const param = await getSystemParamById('sys.home.page.url');
48+
return param?.paramValue?.trim() || null;
49+
} catch (error) {
50+
console.error('Failed to get home page URL:', error);
51+
return null;
52+
}
53+
}

0 commit comments

Comments
 (0)