Feat: Switch the root route to the new page #3221 (#9560)

### What problem does this PR solve?

Feat: Switch the root route to the new page #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-08-19 17:41:03 +08:00
committed by GitHub
parent d5729e598f
commit b8bfbac2e5
12 changed files with 265 additions and 164 deletions

View File

@ -24,13 +24,17 @@ export const useNavigatePage = () => {
); );
const navigateToHome = useCallback(() => { const navigateToHome = useCallback(() => {
navigate(Routes.Home); navigate(Routes.Root);
}, [navigate]); }, [navigate]);
const navigateToProfile = useCallback(() => { const navigateToProfile = useCallback(() => {
navigate(Routes.ProfileSetting); navigate(Routes.ProfileSetting);
}, [navigate]); }, [navigate]);
const navigateToOldProfile = useCallback(() => {
navigate(Routes.UserSetting);
}, [navigate]);
const navigateToChatList = useCallback(() => { const navigateToChatList = useCallback(() => {
navigate(Routes.Chats); navigate(Routes.Chats);
}, [navigate]); }, [navigate]);
@ -139,5 +143,6 @@ export const useNavigatePage = () => {
navigateToSearch, navigateToSearch,
navigateToFiles, navigateToFiles,
navigateToAgentList, navigateToAgentList,
navigateToOldProfile,
}; };
}; };

View File

@ -40,7 +40,7 @@ export function Header() {
const { t } = useTranslation(); const { t } = useTranslation();
const { pathname } = useLocation(); const { pathname } = useLocation();
const navigate = useNavigateWithFromState(); const navigate = useNavigateWithFromState();
const { navigateToProfile } = useNavigatePage(); const { navigateToOldProfile } = useNavigatePage();
const changeLanguage = useChangeLanguage(); const changeLanguage = useChangeLanguage();
const { setTheme, theme } = useTheme(); const { setTheme, theme } = useTheme();
@ -74,7 +74,7 @@ export function Header() {
const tagsData = useMemo( const tagsData = useMemo(
() => [ () => [
{ path: Routes.Home, name: t('header.home'), icon: House }, { path: Routes.Root, name: t('header.Root'), icon: House },
{ path: Routes.Datasets, name: t('header.dataset'), icon: Library }, { path: Routes.Datasets, name: t('header.dataset'), icon: Library },
{ path: Routes.Chats, name: t('header.chat'), icon: MessageSquareText }, { path: Routes.Chats, name: t('header.chat'), icon: MessageSquareText },
{ path: Routes.Searches, name: t('header.search'), icon: Search }, { path: Routes.Searches, name: t('header.search'), icon: Search },
@ -90,7 +90,7 @@ export function Header() {
return { return {
label: label:
tag.path === Routes.Home ? ( tag.path === Routes.Root ? (
<HeaderIcon className="size-6"></HeaderIcon> <HeaderIcon className="size-6"></HeaderIcon>
) : ( ) : (
<span>{tag.name}</span> <span>{tag.name}</span>
@ -100,18 +100,18 @@ export function Header() {
}); });
}, [tagsData]); }, [tagsData]);
const currentPath = useMemo(() => { // const currentPath = useMemo(() => {
return ( // return (
tagsData.find((x) => pathname.startsWith(x.path))?.path || Routes.Home // tagsData.find((x) => pathname.startsWith(x.path))?.path || Routes.Root
); // );
}, [pathname, tagsData]); // }, [pathname, tagsData]);
const handleChange = (path: SegmentedValue) => { const handleChange = (path: SegmentedValue) => {
navigate(path as Routes); navigate(path as Routes);
}; };
const handleLogoClick = useCallback(() => { const handleLogoClick = useCallback(() => {
navigate(Routes.Home); navigate(Routes.Root);
}, [navigate]); }, [navigate]);
return ( return (
@ -123,14 +123,19 @@ export function Header() {
className="size-10 mr-[12]" className="size-10 mr-[12]"
onClick={handleLogoClick} onClick={handleLogoClick}
/> />
<div className="flex items-center gap-1.5 text-text-secondary"> <a
<Github className="size-3.5" /> className="flex items-center gap-1.5 text-text-secondary"
<span className=" text-base">21.5k stars</span> target="_blank"
</div> href="https://github.com/infiniflow/ragflow"
rel="noreferrer"
>
<Github className="size-4" />
{/* <span className=" text-base">21.5k stars</span> */}
</a>
</div> </div>
<Segmented <Segmented
options={options} options={options}
value={currentPath} value={pathname}
onChange={handleChange} onChange={handleChange}
></Segmented> ></Segmented>
<div className="flex items-center gap-5 text-text-badge"> <div className="flex items-center gap-5 text-text-badge">
@ -160,7 +165,7 @@ export function Header() {
name={nickname} name={nickname}
avatar={avatar} avatar={avatar}
className="size-8 cursor-pointer" className="size-8 cursor-pointer"
onClick={navigateToProfile} onClick={navigateToOldProfile}
></RAGFlowAvatar> ></RAGFlowAvatar>
{/* Temporarily hidden */} {/* Temporarily hidden */}
{/* <Badge className="h-5 w-8 absolute font-normal p-0 justify-center -right-8 -top-2 text-bg-base bg-gradient-to-l from-[#42D7E7] to-[#478AF5]"> {/* <Badge className="h-5 w-8 absolute font-normal p-0 justify-center -right-8 -top-2 text-bg-base bg-gradient-to-l from-[#42D7E7] to-[#478AF5]">

View File

@ -63,7 +63,7 @@ function AgentDropdownMenuItem({
export default function Agent() { export default function Agent() {
const { id } = useParams(); const { id } = useParams();
const { navigateToAgentList } = useNavigatePage(); const { navigateToAgents } = useNavigatePage();
const { const {
visible: chatDrawerVisible, visible: chatDrawerVisible,
hideModal: hideChatDrawer, hideModal: hideChatDrawer,
@ -113,7 +113,7 @@ export default function Agent() {
<Breadcrumb> <Breadcrumb>
<BreadcrumbList> <BreadcrumbList>
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink onClick={navigateToAgentList}> <BreadcrumbLink onClick={navigateToAgents}>
Agent Agent
</BreadcrumbLink> </BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>

View File

@ -44,7 +44,7 @@ const getEndOfToday = (): Date => {
return today; return today;
}; };
const AgentLogPage: React.FC = () => { const AgentLogPage: React.FC = () => {
const { navigateToAgentList, navigateToAgent } = useNavigatePage(); const { navigateToAgents, navigateToAgent } = useNavigatePage();
const { flowDetail: agentDetail } = useFetchDataOnMount(); const { flowDetail: agentDetail } = useFetchDataOnMount();
const { id: canvasId } = useParams(); const { id: canvasId } = useParams();
const queryClient = useQueryClient(); const queryClient = useQueryClient();
@ -210,9 +210,7 @@ const AgentLogPage: React.FC = () => {
<Breadcrumb> <Breadcrumb>
<BreadcrumbList> <BreadcrumbList>
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink onClick={navigateToAgentList}> <BreadcrumbLink onClick={navigateToAgents}>Agent</BreadcrumbLink>
Agent
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>

View File

@ -18,7 +18,7 @@ import { TemplateCard } from './template-card';
import { MenuItemKey, SideBar } from './template-sidebar'; import { MenuItemKey, SideBar } from './template-sidebar';
export default function AgentTemplates() { export default function AgentTemplates() {
const { navigateToAgentList } = useNavigatePage(); const { navigateToAgents } = useNavigatePage();
const { t } = useTranslation(); const { t } = useTranslation();
const list = useFetchAgentTemplates(); const list = useFetchAgentTemplates();
const { loading, setAgent } = useSetAgent(); const { loading, setAgent } = useSetAgent();
@ -89,9 +89,7 @@ export default function AgentTemplates() {
<Breadcrumb> <Breadcrumb>
<BreadcrumbList> <BreadcrumbList>
<BreadcrumbItem> <BreadcrumbItem>
<BreadcrumbLink onClick={navigateToAgentList}> <BreadcrumbLink onClick={navigateToAgents}>Agent</BreadcrumbLink>
Agent
</BreadcrumbLink>
</BreadcrumbItem> </BreadcrumbItem>
<BreadcrumbSeparator /> <BreadcrumbSeparator />
<BreadcrumbItem> <BreadcrumbItem>

View File

@ -1,10 +1,18 @@
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import { useFetchAgentListByPage } from '@/hooks/use-agent-request'; import { useFetchAgentListByPage } from '@/hooks/use-agent-request';
import { ApplicationCard } from './application-card'; import { ApplicationCard } from './application-card';
export function Agents() { export function Agents() {
const { data } = useFetchAgentListByPage(); const { data } = useFetchAgentListByPage();
const { navigateToAgent } = useNavigatePage();
return data return data
.slice(0, 10) .slice(0, 10)
.map((x) => <ApplicationCard key={x.id} app={x}></ApplicationCard>); .map((x) => (
<ApplicationCard
key={x.id}
app={x}
onClick={navigateToAgent(x.id)}
></ApplicationCard>
));
} }

View File

@ -10,11 +10,12 @@ type ApplicationCardProps = {
title: string; title: string;
update_time: number; update_time: number;
}; };
onClick?(): void;
}; };
export function ApplicationCard({ app }: ApplicationCardProps) { export function ApplicationCard({ app, onClick }: ApplicationCardProps) {
return ( return (
<Card className="w-[264px]"> <Card className="w-[264px]" onClick={onClick}>
<CardContent className="p-2.5 group flex justify-between"> <CardContent className="p-2.5 group flex justify-between">
<div className="flex items-center gap-2.5"> <div className="flex items-center gap-2.5">
<RAGFlowAvatar <RAGFlowAvatar

View File

@ -1,15 +1,20 @@
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import { useFetchDialogList } from '@/hooks/use-chat-request'; import { useFetchDialogList } from '@/hooks/use-chat-request';
import { ApplicationCard } from './application-card'; import { ApplicationCard } from './application-card';
export function ChatList() { export function ChatList() {
const { data } = useFetchDialogList(); const { data } = useFetchDialogList();
const { navigateToChat } = useNavigatePage();
return data.dialogs return data.dialogs.slice(0, 10).map((x) => (
.slice(0, 10) <ApplicationCard
.map((x) => ( key={x.id}
<ApplicationCard app={{
key={x.id} avatar: x.icon,
app={{ avatar: x.icon, title: x.name, update_time: x.update_time }} title: x.name,
></ApplicationCard> update_time: x.update_time,
)); }}
onClick={navigateToChat(x.id)}
></ApplicationCard>
));
} }

View File

@ -1,15 +1,20 @@
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import { useFetchSearchList } from '../next-searches/hooks'; import { useFetchSearchList } from '../next-searches/hooks';
import { ApplicationCard } from './application-card'; import { ApplicationCard } from './application-card';
export function SearchList() { export function SearchList() {
const { data } = useFetchSearchList(); const { data } = useFetchSearchList();
const { navigateToSearch } = useNavigatePage();
return data?.data.search_apps return data?.data.search_apps.slice(0, 10).map((x) => (
.slice(0, 10) <ApplicationCard
.map((x) => ( key={x.id}
<ApplicationCard app={{
key={x.id} avatar: x.avatar,
app={{ avatar: x.avatar, title: x.name, update_time: x.update_time }} title: x.name,
></ApplicationCard> update_time: x.update_time,
)); }}
onClick={() => navigateToSearch(x.id)}
></ApplicationCard>
));
} }

View File

@ -36,7 +36,7 @@ const Login = () => {
const { isLogin } = useAuth(); const { isLogin } = useAuth();
useEffect(() => { useEffect(() => {
if (isLogin) { if (isLogin) {
navigate('/knowledge'); navigate('/');
} }
}, [isLogin, navigate]); }, [isLogin, navigate]);
@ -68,7 +68,7 @@ const Login = () => {
password: rsaPassWord, password: rsaPassWord,
}); });
if (code === 0) { if (code === 0) {
navigate('/knowledge'); navigate('/');
} }
} else { } else {
const code = await register({ const code = await register({

View File

@ -2,16 +2,49 @@ import { Flex } from 'antd';
import { Outlet } from 'umi'; import { Outlet } from 'umi';
import SideBar from './sidebar'; import SideBar from './sidebar';
import { PageHeader } from '@/components/page-header';
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from '@/components/ui/breadcrumb';
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import { cn } from '@/lib/utils';
import { House } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import styles from './index.less'; import styles from './index.less';
const UserSetting = () => { const UserSetting = () => {
const { t } = useTranslation();
const { navigateToHome } = useNavigatePage();
return ( return (
<Flex className={styles.settingWrapper}> <section>
<SideBar></SideBar> <PageHeader>
<Flex flex={1} className={styles.outletWrapper}> <Breadcrumb>
<Outlet></Outlet> <BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink onClick={navigateToHome}>
<House className="size-4" />
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>{t('setting.profile')}</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
</PageHeader>
<Flex className={cn(styles.settingWrapper, '-translate-y-6')}>
<SideBar></SideBar>
<Flex flex={1} className={styles.outletWrapper}>
<Outlet></Outlet>
</Flex>
</Flex> </Flex>
</Flex> </section>
); );
}; };

View File

@ -1,4 +1,5 @@
export enum Routes { export enum Routes {
Root = '/',
Login = '/login', Login = '/login',
Logout = '/logout', Logout = '/logout',
Home = '/home', Home = '/home',
@ -40,6 +41,7 @@ export enum Routes {
AgentLogPage = '/agent-log-page', AgentLogPage = '/agent-log-page',
AgentShare = '/agent/share', AgentShare = '/agent/share',
ChatShare = `${Chats}/share`, ChatShare = `${Chats}/share`,
UserSetting = '/user-setting',
} }
const routes = [ const routes = [
@ -68,116 +70,116 @@ const routes = [
component: `@/pages${Routes.AgentShare}`, component: `@/pages${Routes.AgentShare}`,
layout: false, layout: false,
}, },
{ // {
path: '/', // path: '/',
component: '@/layouts', // component: '@/layouts',
layout: false, // layout: false,
wrappers: ['@/wrappers/auth'], // wrappers: ['@/wrappers/auth'],
routes: [ // routes: [
{ path: '/', redirect: '/knowledge' }, // { path: '/', redirect: '/knowledge' },
{ // {
path: '/knowledge', // path: '/knowledge',
component: '@/pages/knowledge', // component: '@/pages/knowledge',
// component: '@/pages/knowledge/datasets', // // component: '@/pages/knowledge/datasets',
}, // },
{ // {
path: '/knowledge', // path: '/knowledge',
component: '@/pages/add-knowledge', // component: '@/pages/add-knowledge',
routes: [ // routes: [
{ // {
path: '/knowledge/dataset', // path: '/knowledge/dataset',
component: '@/pages/add-knowledge/components/knowledge-dataset', // component: '@/pages/add-knowledge/components/knowledge-dataset',
routes: [ // routes: [
{ // {
path: '/knowledge/dataset', // path: '/knowledge/dataset',
component: '@/pages/add-knowledge/components/knowledge-file', // component: '@/pages/add-knowledge/components/knowledge-file',
}, // },
{ // {
path: '/knowledge/dataset/chunk', // path: '/knowledge/dataset/chunk',
component: '@/pages/add-knowledge/components/knowledge-chunk', // component: '@/pages/add-knowledge/components/knowledge-chunk',
}, // },
], // ],
}, // },
{ // {
path: '/knowledge/configuration', // path: '/knowledge/configuration',
component: '@/pages/add-knowledge/components/knowledge-setting', // component: '@/pages/add-knowledge/components/knowledge-setting',
}, // },
{ // {
path: '/knowledge/testing', // path: '/knowledge/testing',
component: '@/pages/add-knowledge/components/knowledge-testing', // component: '@/pages/add-knowledge/components/knowledge-testing',
}, // },
{ // {
path: '/knowledge/knowledgeGraph', // path: '/knowledge/knowledgeGraph',
component: '@/pages/add-knowledge/components/knowledge-graph', // component: '@/pages/add-knowledge/components/knowledge-graph',
}, // },
], // ],
}, // },
{ // {
path: '/chat', // path: '/chat',
component: '@/pages/chat', // component: '@/pages/chat',
}, // },
{ // {
path: '/user-setting', // path: '/user-setting',
component: '@/pages/user-setting', // component: '@/pages/user-setting',
routes: [ // routes: [
{ path: '/user-setting', redirect: '/user-setting/profile' }, // { path: '/user-setting', redirect: '/user-setting/profile' },
{ // {
path: '/user-setting/profile', // path: '/user-setting/profile',
// component: '@/pages/user-setting/setting-profile', // // component: '@/pages/user-setting/setting-profile',
component: '@/pages/user-setting/setting-profile', // component: '@/pages/user-setting/setting-profile',
}, // },
{ // {
path: '/user-setting/locale', // path: '/user-setting/locale',
component: '@/pages/user-setting/setting-locale', // component: '@/pages/user-setting/setting-locale',
}, // },
{ // {
path: '/user-setting/password', // path: '/user-setting/password',
component: '@/pages/user-setting/setting-password', // component: '@/pages/user-setting/setting-password',
}, // },
{ // {
path: '/user-setting/model', // path: '/user-setting/model',
component: '@/pages/user-setting/setting-model', // component: '@/pages/user-setting/setting-model',
}, // },
{ // {
path: '/user-setting/team', // path: '/user-setting/team',
component: '@/pages/user-setting/setting-team', // component: '@/pages/user-setting/setting-team',
}, // },
{ // {
path: '/user-setting/system', // path: '/user-setting/system',
component: '@/pages/user-setting/setting-system', // component: '@/pages/user-setting/setting-system',
}, // },
{ // {
path: '/user-setting/api', // path: '/user-setting/api',
component: '@/pages/user-setting/setting-api', // component: '@/pages/user-setting/setting-api',
}, // },
{ // {
path: `/user-setting${Routes.Mcp}`, // path: `/user-setting${Routes.Mcp}`,
component: `@/pages${Routes.ProfileMcp}`, // component: `@/pages${Routes.ProfileMcp}`,
}, // },
], // ],
}, // },
{ // {
path: '/file', // path: '/file',
component: '@/pages/file-manager', // component: '@/pages/file-manager',
}, // },
{ // {
path: '/flow', // path: '/flow',
component: '@/pages/flow/list', // component: '@/pages/flow/list',
}, // },
{ // {
path: Routes.AgentList, // path: Routes.AgentList,
component: `@/pages/${Routes.Agents}`, // component: `@/pages/${Routes.Agents}`,
}, // },
{ // {
path: '/flow/:id', // path: '/flow/:id',
component: '@/pages/flow', // component: '@/pages/flow',
}, // },
{ // {
path: '/search', // path: '/search',
component: '@/pages/search', // component: '@/pages/search',
}, // },
], // ],
}, // },
{ {
path: '/document/:id', path: '/document/:id',
component: '@/pages/document-viewer', component: '@/pages/document-viewer',
@ -189,12 +191,12 @@ const routes = [
layout: false, layout: false,
}, },
{ {
path: Routes.Home, path: Routes.Root,
layout: false, layout: false,
component: '@/layouts/next', component: '@/layouts/next',
routes: [ routes: [
{ {
path: Routes.Home, path: Routes.Root,
component: `@/pages${Routes.Home}`, component: `@/pages${Routes.Home}`,
}, },
], ],
@ -382,6 +384,47 @@ const routes = [
}, },
], ],
}, },
{
path: '/user-setting',
component: '@/pages/user-setting',
layout: false,
routes: [
{ path: '/user-setting', redirect: '/user-setting/profile' },
{
path: '/user-setting/profile',
// component: '@/pages/user-setting/setting-profile',
component: '@/pages/user-setting/setting-profile',
},
{
path: '/user-setting/locale',
component: '@/pages/user-setting/setting-locale',
},
{
path: '/user-setting/password',
component: '@/pages/user-setting/setting-password',
},
{
path: '/user-setting/model',
component: '@/pages/user-setting/setting-model',
},
{
path: '/user-setting/team',
component: '@/pages/user-setting/setting-team',
},
{
path: '/user-setting/system',
component: '@/pages/user-setting/setting-system',
},
{
path: '/user-setting/api',
component: '@/pages/user-setting/setting-api',
},
{
path: `/user-setting${Routes.Mcp}`,
component: `@/pages${Routes.ProfileMcp}`,
},
],
},
]; ];
export default routes; export default routes;