mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-06-05 20:54:14 +00:00
fix(frontend): restore per-route document titles in the SPA
When the multi-entry MPA collapsed into a single index.html, every route inherited the static <title>3X-UI</title> from the shared shell, so every panel page showed "hostname - 3X-UI" instead of the original "hostname - Overview / Clients / Inbounds / ...". usePageTitle reads the current pathname and rewrites document.title on every navigation, matching the titles the deleted *.html files used to carry. Mounted in PanelLayout so it covers all panel routes without each page having to opt in. The startup applyDocumentTitle() call in main.tsx is gone — the hook sets the full "hostname - PageTitle" string itself.
This commit is contained in:
parent
6a6f44c884
commit
77099f91e8
3 changed files with 24 additions and 2 deletions
22
frontend/src/hooks/usePageTitle.ts
Normal file
22
frontend/src/hooks/usePageTitle.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
|
const TITLES: Record<string, string> = {
|
||||||
|
'/': 'Overview',
|
||||||
|
'/inbounds': 'Inbounds',
|
||||||
|
'/clients': 'Clients',
|
||||||
|
'/nodes': 'Nodes',
|
||||||
|
'/settings': 'Settings',
|
||||||
|
'/xray': 'Xray Config',
|
||||||
|
'/api-docs': 'API Docs',
|
||||||
|
};
|
||||||
|
|
||||||
|
export function usePageTitle() {
|
||||||
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const title = TITLES[pathname] || '3X-UI';
|
||||||
|
const host = window.location.hostname;
|
||||||
|
document.title = host ? `${host} - ${title}` : title;
|
||||||
|
}, [pathname]);
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
import { useWebSocketBridge } from '@/api/websocketBridge';
|
import { useWebSocketBridge } from '@/api/websocketBridge';
|
||||||
|
import { usePageTitle } from '@/hooks/usePageTitle';
|
||||||
|
|
||||||
export default function PanelLayout() {
|
export default function PanelLayout() {
|
||||||
useWebSocketBridge();
|
useWebSocketBridge();
|
||||||
|
usePageTitle();
|
||||||
return <Outlet />;
|
return <Outlet />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,12 @@ import { message } from 'antd';
|
||||||
import 'antd/dist/reset.css';
|
import 'antd/dist/reset.css';
|
||||||
|
|
||||||
import { setupAxios } from '@/api/axios-init.js';
|
import { setupAxios } from '@/api/axios-init.js';
|
||||||
import { applyDocumentTitle } from '@/utils';
|
|
||||||
import { readyI18n } from '@/i18n/react';
|
import { readyI18n } from '@/i18n/react';
|
||||||
import { ThemeProvider } from '@/hooks/useTheme';
|
import { ThemeProvider } from '@/hooks/useTheme';
|
||||||
import { QueryProvider } from '@/api/QueryProvider';
|
import { QueryProvider } from '@/api/QueryProvider';
|
||||||
import { router } from '@/routes';
|
import { router } from '@/routes';
|
||||||
|
|
||||||
setupAxios();
|
setupAxios();
|
||||||
applyDocumentTitle();
|
|
||||||
|
|
||||||
const messageContainer = document.getElementById('message');
|
const messageContainer = document.getElementById('message');
|
||||||
if (messageContainer) {
|
if (messageContainer) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue