From 0327fd848efea5348162236b1ea454440fcd737a Mon Sep 17 00:00:00 2001 From: balibabu Date: Thu, 31 Jul 2025 12:14:00 +0800 Subject: [PATCH] Feat: Replace the link of the old version of the agent module #3221 (#9130) ### What problem does this PR solve? Feat: Automatically save agent canvas content Feat: Replace the link of the old version of the agent module #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/app.tsx | 6 +++- web/src/components/theme-provider.tsx | 29 +++++++++------ web/src/constants/common.ts | 6 ++++ web/src/hooks/use-agent-request.ts | 10 +++--- web/src/layouts/components/header/index.tsx | 2 +- .../components/right-toolbar/index.tsx | 6 ++-- web/src/layouts/next-header.tsx | 4 +-- web/src/pages/agent/hooks/use-save-graph.ts | 12 +++---- web/src/pages/agent/index.tsx | 36 ++++++++++++------- web/src/pages/next-chats/share/index.tsx | 3 ++ web/src/pages/profile-setting/mcp/index.tsx | 2 +- .../pages/profile-setting/sidebar/index.tsx | 3 +- web/tailwind.css | 2 +- 13 files changed, 77 insertions(+), 44 deletions(-) diff --git a/web/src/app.tsx b/web/src/app.tsx index 538b33147..4eb437948 100644 --- a/web/src/app.tsx +++ b/web/src/app.tsx @@ -21,6 +21,7 @@ import React, { ReactNode, useEffect, useState } from 'react'; import { ThemeProvider, useTheme } from './components/theme-provider'; import { SidebarProvider } from './components/ui/sidebar'; import { TooltipProvider } from './components/ui/tooltip'; +import { ThemeEnum } from './constants/common'; import storage from './utils/authorization-util'; dayjs.extend(customParseFormat); @@ -101,7 +102,10 @@ const RootProvider = ({ children }: React.PropsWithChildren) => { return ( - + {children} diff --git a/web/src/components/theme-provider.tsx b/web/src/components/theme-provider.tsx index a5b6e533b..4ae554ab0 100644 --- a/web/src/components/theme-provider.tsx +++ b/web/src/components/theme-provider.tsx @@ -1,20 +1,19 @@ +import { ThemeEnum } from '@/constants/common'; import React, { createContext, useContext, useEffect, useState } from 'react'; -type Theme = 'dark' | 'light' | 'system'; - type ThemeProviderProps = { children: React.ReactNode; - defaultTheme?: Theme; + defaultTheme?: ThemeEnum; storageKey?: string; }; type ThemeProviderState = { - theme: Theme; - setTheme: (theme: Theme) => void; + theme: ThemeEnum; + setTheme: (theme: ThemeEnum) => void; }; const initialState: ThemeProviderState = { - theme: 'light', + theme: ThemeEnum.Light, setTheme: () => null, }; @@ -22,17 +21,17 @@ const ThemeProviderContext = createContext(initialState); export function ThemeProvider({ children, - defaultTheme = 'light', + defaultTheme = ThemeEnum.Light, storageKey = 'vite-ui-theme', ...props }: ThemeProviderProps) { - const [theme, setTheme] = useState( - () => (localStorage.getItem(storageKey) as Theme) || defaultTheme, + const [theme, setTheme] = useState( + () => (localStorage.getItem(storageKey) as ThemeEnum) || defaultTheme, ); useEffect(() => { const root = window.document.documentElement; - root.classList.remove('light', 'dark'); + root.classList.remove(ThemeEnum.Light, ThemeEnum.Dark); localStorage.setItem(storageKey, theme); root.classList.add(theme); }, [storageKey, theme]); @@ -62,5 +61,13 @@ export const useTheme = () => { export const useIsDarkTheme = () => { const { theme } = useTheme(); - return theme === 'dark'; + return theme === ThemeEnum.Dark; }; + +export function useSwitchToDarkThemeOnMount() { + const { setTheme } = useTheme(); + + useEffect(() => { + setTheme(ThemeEnum.Dark); + }, [setTheme]); +} diff --git a/web/src/constants/common.ts b/web/src/constants/common.ts index 4acb8bb8c..bcbe7e646 100644 --- a/web/src/constants/common.ts +++ b/web/src/constants/common.ts @@ -150,3 +150,9 @@ export enum Platform { FastGPT = 'FastGPT', Coze = 'Coze', } + +export enum ThemeEnum { + Dark = 'dark', + Light = 'light', + System = 'system', +} diff --git a/web/src/hooks/use-agent-request.ts b/web/src/hooks/use-agent-request.ts index 0799d525e..3cd803450 100644 --- a/web/src/hooks/use-agent-request.ts +++ b/web/src/hooks/use-agent-request.ts @@ -266,7 +266,7 @@ export const useResetAgent = () => { return { data, loading, resetAgent: mutateAsync }; }; -export const useSetAgent = () => { +export const useSetAgent = (showMessage: boolean = true) => { const queryClient = useQueryClient(); const { data, @@ -282,9 +282,11 @@ export const useSetAgent = () => { }) => { const { data = {} } = await agentService.setCanvas(params); if (data.code === 0) { - message.success( - i18n.t(`message.${params?.id ? 'modified' : 'created'}`), - ); + if (showMessage) { + message.success( + i18n.t(`message.${params?.id ? 'modified' : 'created'}`), + ); + } queryClient.invalidateQueries({ queryKey: [AgentApiAction.FetchAgentList], }); diff --git a/web/src/layouts/components/header/index.tsx b/web/src/layouts/components/header/index.tsx index 87a6d3bdc..ffecfb770 100644 --- a/web/src/layouts/components/header/index.tsx +++ b/web/src/layouts/components/header/index.tsx @@ -29,7 +29,7 @@ const RagHeader = () => { { path: '/knowledge', name: t('knowledgeBase'), icon: KnowledgeBaseIcon }, { path: '/chat', name: t('chat'), icon: MessageOutlined }, { path: '/search', name: t('search'), icon: SearchOutlined }, - { path: '/flow', name: t('flow'), icon: GraphIcon }, + { path: '/agent-list', name: t('flow'), icon: GraphIcon }, { path: '/file', name: t('fileManager'), icon: FileIcon }, ], [t], diff --git a/web/src/layouts/components/right-toolbar/index.tsx b/web/src/layouts/components/right-toolbar/index.tsx index 2cda6a63b..9ef097a4d 100644 --- a/web/src/layouts/components/right-toolbar/index.tsx +++ b/web/src/layouts/components/right-toolbar/index.tsx @@ -6,7 +6,7 @@ import React, { useCallback, useMemo } from 'react'; import User from '../user'; import { useTheme } from '@/components/theme-provider'; -import { LanguageList, LanguageMap } from '@/constants/common'; +import { LanguageList, LanguageMap, ThemeEnum } from '@/constants/common'; import { useChangeLanguage } from '@/hooks/logic-hooks'; import { useFetchUserInfo, useListTenant } from '@/hooks/user-setting-hooks'; import { TenantRole } from '@/pages/user-setting/constants'; @@ -58,10 +58,10 @@ const RightToolBar = () => { }, []); const onMoonClick = React.useCallback(() => { - setTheme('light'); + setTheme(ThemeEnum.Light); }, [setTheme]); const onSunClick = React.useCallback(() => { - setTheme('dark'); + setTheme(ThemeEnum.Dark); }, [setTheme]); const handleBellClick = useCallback(() => { diff --git a/web/src/layouts/next-header.tsx b/web/src/layouts/next-header.tsx index 7a7ac9f1c..454cc3f3f 100644 --- a/web/src/layouts/next-header.tsx +++ b/web/src/layouts/next-header.tsx @@ -9,7 +9,7 @@ import { DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import { Segmented, SegmentedValue } from '@/components/ui/segmented'; -import { LanguageList, LanguageMap } from '@/constants/common'; +import { LanguageList, LanguageMap, ThemeEnum } from '@/constants/common'; import { useChangeLanguage } from '@/hooks/logic-hooks'; import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks'; import { useNavigateWithFromState } from '@/hooks/route-hook'; @@ -67,7 +67,7 @@ export function Header() { })); const onThemeClick = React.useCallback(() => { - setTheme(theme === 'dark' ? 'light' : 'dark'); + setTheme(theme === ThemeEnum.Dark ? ThemeEnum.Light : ThemeEnum.Dark); }, [setTheme, theme]); const handleBellClick = useCallback(() => { diff --git a/web/src/pages/agent/hooks/use-save-graph.ts b/web/src/pages/agent/hooks/use-save-graph.ts index 948c66f25..8ce4dc15e 100644 --- a/web/src/pages/agent/hooks/use-save-graph.ts +++ b/web/src/pages/agent/hooks/use-save-graph.ts @@ -4,16 +4,16 @@ import { useSetAgent, } from '@/hooks/use-agent-request'; import { RAGFlowNodeType } from '@/interfaces/database/flow'; +import { formatDate } from '@/utils/date'; import { useDebounceEffect } from 'ahooks'; -import dayjs from 'dayjs'; import { useCallback, useEffect, useState } from 'react'; import { useParams } from 'umi'; import useGraphStore from '../store'; import { useBuildDslData } from './use-build-dsl'; -export const useSaveGraph = () => { +export const useSaveGraph = (showMessage: boolean = true) => { const { data } = useFetchAgent(); - const { setAgent, loading } = useSetAgent(); + const { setAgent, loading } = useSetAgent(showMessage); const { id } = useParams(); const { buildDslData } = useBuildDslData(); @@ -57,11 +57,11 @@ export const useWatchAgentChange = (chatDrawerVisible: boolean) => { const [time, setTime] = useState(); const nodes = useGraphStore((state) => state.nodes); const edges = useGraphStore((state) => state.edges); - const { saveGraph } = useSaveGraph(); + const { saveGraph } = useSaveGraph(false); const { data: flowDetail } = useFetchAgent(); const setSaveTime = useCallback((updateTime: number) => { - setTime(dayjs(updateTime).format('YYYY-MM-DD HH:mm:ss')); + setTime(formatDate(updateTime)); }, []); useEffect(() => { @@ -77,7 +77,7 @@ export const useWatchAgentChange = (chatDrawerVisible: boolean) => { useDebounceEffect( () => { - // saveAgent(); + saveAgent(); }, [nodes, edges], { diff --git a/web/src/pages/agent/index.tsx b/web/src/pages/agent/index.tsx index 4abb178d1..ca4d2d688 100644 --- a/web/src/pages/agent/index.tsx +++ b/web/src/pages/agent/index.tsx @@ -1,4 +1,5 @@ import { PageHeader } from '@/components/page-header'; +import { useSwitchToDarkThemeOnMount } from '@/components/theme-provider'; import { Breadcrumb, BreadcrumbItem, @@ -40,6 +41,7 @@ import { useGetBeginNodeDataInputs } from './hooks/use-get-begin-query'; import { useSaveGraph, useSaveGraphBeforeOpeningDebugDrawer, + useWatchAgentChange, } from './hooks/use-save-graph'; import { useShowEmbedModal } from './hooks/use-show-dialog'; import { UploadAgentDialog } from './upload-agent-dialog'; @@ -94,23 +96,31 @@ export default function Agent() { const { showEmbedModal, hideEmbedModal, embedVisible, beta } = useShowEmbedModal(); const { navigateToAgentLogs } = useNavigatePage(); + const time = useWatchAgentChange(chatDrawerVisible); + + useSwitchToDarkThemeOnMount(); return (
- - - - - Agent - - - - - {agentDetail.title} - - - +
+ + + + + Agent + + + + + {agentDetail.title} + + + +
+ {t('flow.autosaved')} {time} +
+
{ } }, [data, showParameterDialog]); + useSwitchToDarkThemeOnMount(); + if (!conversationId) { return
empty
; } diff --git a/web/src/pages/profile-setting/mcp/index.tsx b/web/src/pages/profile-setting/mcp/index.tsx index b7f4c6d74..2f721105e 100644 --- a/web/src/pages/profile-setting/mcp/index.tsx +++ b/web/src/pages/profile-setting/mcp/index.tsx @@ -32,7 +32,7 @@ export default function McpServer() { ); return ( -
+
MCP Servers
diff --git a/web/src/pages/profile-setting/sidebar/index.tsx b/web/src/pages/profile-setting/sidebar/index.tsx index b3de5fbbe..75e63056d 100644 --- a/web/src/pages/profile-setting/sidebar/index.tsx +++ b/web/src/pages/profile-setting/sidebar/index.tsx @@ -2,6 +2,7 @@ import { useIsDarkTheme, useTheme } from '@/components/theme-provider'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; +import { ThemeEnum } from '@/constants/common'; import { useLogout } from '@/hooks/login-hooks'; import { useSecondPathName } from '@/hooks/route-hook'; import { cn } from '@/lib/utils'; @@ -60,7 +61,7 @@ export function SideBar() { const handleThemeChange = useCallback( (checked: boolean) => { - setTheme(checked ? 'dark' : 'light'); + setTheme(checked ? ThemeEnum.Dark : ThemeEnum.Light); }, [setTheme], ); diff --git a/web/tailwind.css b/web/tailwind.css index 881cb20a5..c5e765e05 100644 --- a/web/tailwind.css +++ b/web/tailwind.css @@ -81,7 +81,7 @@ --text-sub-title: rgba(151, 154, 171, 1); --text-sub-title-invert: rgba(91, 93, 106, 1); - --background-header-bar: rgba(11, 11, 12, 1); + --background-header-bar: rgba(0, 0, 0, 0.05); --text-title-invert: rgba(255, 255, 255, 1); --background-card: rgba(22, 22, 24, 0.05);