diff --git a/packages/web/components/common/MySelect/index.tsx b/packages/web/components/common/MySelect/index.tsx index 6534a4d41..d4b75a2d3 100644 --- a/packages/web/components/common/MySelect/index.tsx +++ b/packages/web/components/common/MySelect/index.tsx @@ -50,6 +50,7 @@ export type SelectProps = Omit & { showBorder?: boolean; }[]; isLoading?: boolean; + showAvatar?: boolean; onChange?: (val: T) => any | Promise; ScrollData?: ReturnType['ScrollData']; customOnOpen?: () => void; @@ -79,6 +80,7 @@ const MySelect = ( list = [], onChange, isLoading = false, + showAvatar = true, ScrollData, customOnOpen, customOnClose, @@ -255,7 +257,7 @@ const MySelect = ( /> ) : ( <> - {selectItem?.icon && ( + {selectItem?.icon && showAvatar && ( { ); }; -const MultipleRowSelector = ({ list, onChange, disableTip, placeholder, ...props }: Props) => { +const MultipleRowSelector = ({ + list, + onChange, + disableTip, + placeholder, + showAvatar = true, + ...props +}: Props) => { const { t } = useTranslation(); const { llmModelList, embeddingModelList, ttsModelList, sttModelList, reRankModelList } = useSystemStore(); @@ -193,17 +200,20 @@ const MultipleRowSelector = ({ list, onChange, disableTip, placeholder, ...props return ( - + {showAvatar && ( + + )} + {modelData?.name} ); - }, [modelList, props.value, t, avatarSize]); + }, [modelList, props.value, t, showAvatar, avatarSize]); return ( import('@/pageComponents/app/detail/Gate/components/GateToolSelect'), @@ -46,8 +47,8 @@ type Props = { resetInputVal: (val: ChatBoxInputType) => void; chatForm: UseFormReturn; placeholder?: string; - selectedToolIds?: string[]; - onSelectedToolIdsChange?: (toolIds: string[]) => void; + selectedTools?: FlowNodeTemplateType[]; + onSelectTools?: (toolIds: FlowNodeTemplateType[]) => void; }; const GateChatInput = ({ @@ -57,8 +58,8 @@ const GateChatInput = ({ resetInputVal, chatForm, placeholder, - selectedToolIds: externalSelectedToolIds, - onSelectedToolIdsChange + selectedTools: externalSelectedToolIds, + onSelectTools }: Props) => { const { t } = useTranslation(); const { isPc } = useSystem(); @@ -78,10 +79,9 @@ const GateChatInput = ({ const isChatting = useContextSelector(ChatBoxContext, (v) => v.isChatting); const fileSelectConfig = useContextSelector(ChatBoxContext, (v) => v.fileSelectConfig); - // 如果有外部传入的工具选择,使用外部的;否则使用内部状态 - const [internalSelectedToolIds, setInternalSelectedToolIds] = useState([]); - const selectedToolIds = externalSelectedToolIds ?? internalSelectedToolIds; - const setSelectedToolIds = onSelectedToolIdsChange ?? setInternalSelectedToolIds; + // eslint-disable-next-line react-hooks/exhaustive-deps + const selectedTools = externalSelectedToolIds ?? []; + const setSelectedToolIds = onSelectTools!; const { appDetail } = useContextSelector(AppContext, (v) => v); const { llmModelList } = useSystemStore(); @@ -93,10 +93,7 @@ const GateChatInput = ({ const [selectedModel, setSelectedModel] = useState(defaultModel); const showModelSelector = useMemo(() => { - return ( - router.pathname.startsWith('/chat/gate') && - !router.pathname.includes('/chat/gate/application') - ); + return router.pathname === '/chat/gate'; }, [router.pathname]); // 是否显示工具选择器 @@ -188,7 +185,7 @@ const GateChatInput = ({ text: textareaValue.trim(), files: fileList, gateModel: showModelSelector ? selectedModel : undefined, - selectedTool: selectedToolIds.length > 0 ? selectedToolIds.join(',') : null // 将工具ID数组转换为逗号分隔的字符串 + selectedTool: selectedTools.length > 0 ? selectedTools.join(',') : null // 将工具ID数组转换为逗号分隔的字符串 }); replaceFiles([]); }, @@ -200,7 +197,7 @@ const GateChatInput = ({ replaceFiles, showModelSelector, selectedModel, - selectedToolIds + selectedTools ] ); @@ -214,8 +211,9 @@ const GateChatInput = ({ boxShadow="0px 5px 16px -4px rgba(19, 51, 107, 0.08)" borderRadius="20px" position="relative" - p={4} - pb="56px" + px={4} + pb={'62px'} + pt={fileList.length > 0 ? 0 : 4} overflow="hidden" transition="all 0.2s ease" _hover={{ @@ -335,24 +333,18 @@ const GateChatInput = ({ > {showModelSelector && ( - )} {showTools && ( diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx index 9d641bb93..4710d1f9d 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx @@ -14,7 +14,7 @@ import type { } from '@fastgpt/global/core/chat/type.d'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { getErrText } from '@fastgpt/global/common/error/utils'; -import { Box, Checkbox, Flex, Text } from '@chakra-ui/react'; +import { Box, Checkbox, Flex, HStack, Text } from '@chakra-ui/react'; import { EventNameEnum, eventBus } from '@/web/common/utils/eventbus'; import { chats2GPTMessages } from '@fastgpt/global/core/chat/adapt'; import { useForm } from 'react-hook-form'; @@ -74,6 +74,9 @@ import { useRouter } from 'next/router'; import { getTeamGateConfig, getTeamGateConfigCopyRight } from '@/web/support/user/team/gate/api'; import type { getGateConfigCopyRightResponse } from '@fastgpt/global/support/user/team/gate/api'; import type { GateSchemaType } from '@fastgpt/global/support/user/team/gate/type'; +import type { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node'; +import type { AppListItemType } from '@fastgpt/global/core/app/type'; +import Avatar from '@fastgpt/web/components/common/Avatar'; const FeedbackModal = dynamic(() => import('./components/FeedbackModal')); const ReadFeedbackModal = dynamic(() => import('./components/ReadFeedbackModal')); @@ -96,8 +99,9 @@ type Props = OutLinkChatAuthProps & showVoiceIcon?: boolean; showEmptyIntro?: boolean; active?: boolean; // can use - selectedToolIds?: string[]; - onSelectedToolIdsChange?: (toolIds: string[]) => void; + selectedTools?: FlowNodeTemplateType[]; + onSelectTools?: (toolIds: FlowNodeTemplateType[]) => void; + recommendApps?: AppListItemType[]; onStartChat?: (e: StartChatFnProps) => Promise< StreamResponseType & { @@ -115,8 +119,9 @@ const ChatBox = ({ active = true, onStartChat, chatType, - selectedToolIds, - onSelectedToolIdsChange + selectedTools, + onSelectTools, + recommendApps = [] }: Props) => { const ScrollContainerRef = useRef(null); const { t } = useTranslation(); @@ -421,7 +426,7 @@ const ChatBox = ({ const router = useRouter(); const inGateRoute = useMemo(() => { - return router.pathname.startsWith('/chat/gate'); + return router.pathname === '/chat/gate'; }, [router.pathname]); /** * user confirm send prompt @@ -1124,11 +1129,7 @@ const ChatBox = ({ const { userInfo } = useUserStore(); const showWelcome = useMemo(() => { - return ( - router.pathname.startsWith('/chat/gate') && - !router.pathname.includes('/chat/gate/application') && - chatRecords.length === 0 - ); + return router.pathname === '/chat/gate' && chatRecords.length === 0; }, [router.pathname, chatRecords.length]); return ( @@ -1169,6 +1170,29 @@ const ChatBox = ({ {/* message input */} {onStartChat && chatStarted && active && !isInteractive && ( + + {recommendApps.map((item) => ( + { + router.push(`/chat/gate/application?appId=${item._id}`); + }} + > + + {item.name} + + ))} + chatController.current?.abort('stop')} @@ -1176,8 +1200,8 @@ const ChatBox = ({ resetInputVal={resetInputVal} chatForm={chatForm} placeholder={gateConfig?.placeholderText || '你可以问我任何问题'} - selectedToolIds={selectedToolIds} - onSelectedToolIdsChange={onSelectedToolIdsChange} + selectedTools={selectedTools} + onSelectTools={onSelectTools} /> )} @@ -1205,7 +1229,7 @@ const ChatBox = ({ {RenderRecords} {/* 移动端下的输入框和版权信息容器 */} - + {/* message input */} {onStartChat && chatStarted && active && !isInteractive && ( )} {!inGateRoute && ( diff --git a/projects/app/src/pageComponents/account/gateway/ConfigButtons.tsx b/projects/app/src/pageComponents/account/gateway/ConfigButtons.tsx index 29be46b1a..bf84c0ba5 100644 --- a/projects/app/src/pageComponents/account/gateway/ConfigButtons.tsx +++ b/projects/app/src/pageComponents/account/gateway/ConfigButtons.tsx @@ -7,7 +7,6 @@ import { useToast } from '@fastgpt/web/hooks/useToast'; import ShareGateModal from './ShareModol'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { getMyAppsGate, postCreateApp, putAppById } from '@/web/core/app/api'; -import { useUserStore } from '@/web/support/user/useUserStore'; import { emptyTemplates } from '@/web/core/app/templates'; import { saveGateConfig } from './HomeTable'; import type { GateSchemaType } from '@fastgpt/global/support/user/team/gate/type'; @@ -32,7 +31,10 @@ const ConfigButtons = ({ tab, appForm, gateConfig, copyRightConfig }: Props) => const { runAsync: saveHomeConfig, loading: savingHome } = useRequest2( async () => { if (!!gateConfig) { - await saveGateConfig(gateConfig); + await saveGateConfig({ + ...gateConfig, + status: true + }); toast({ title: t('common:save_success'), status: 'success' @@ -89,7 +91,6 @@ const ConfigButtons = ({ tab, appForm, gateConfig, copyRightConfig }: Props) => const gateApp = apps.find((app) => app.type === AppTypeEnum.gate); const currentTeamAvatar = copyRightConfig?.logo; const currentSlogan = gateConfig?.slogan; - console.log('gateApp', gateApp, currentTeamAvatar, currentSlogan, nodes, edges); if (gateApp) { if ( gateApp.avatar !== currentTeamAvatar || @@ -104,25 +105,17 @@ const ConfigButtons = ({ tab, appForm, gateConfig, copyRightConfig }: Props) => nodes, edges }); - toast({ - title: t('common:update_success'), - status: 'success' - }); } } else { await postCreateApp({ avatar: gateConfig?.logo, - name: gateConfig?.name, + name: 'App', intro: gateConfig?.slogan, type: AppTypeEnum.gate, modules: emptyTemplates[AppTypeEnum.gate].nodes, edges: emptyTemplates[AppTypeEnum.gate].edges, chatConfig: emptyTemplates[AppTypeEnum.gate].chatConfig }); - toast({ - title: t('common:create_success'), - status: 'success' - }); } } catch (error) { toast({ diff --git a/projects/app/src/pageComponents/account/gateway/HomeTable.tsx b/projects/app/src/pageComponents/account/gateway/HomeTable.tsx index 2d6b93a16..5455ce081 100644 --- a/projects/app/src/pageComponents/account/gateway/HomeTable.tsx +++ b/projects/app/src/pageComponents/account/gateway/HomeTable.tsx @@ -22,7 +22,6 @@ import { v1Workflow2V2 } from '@/web/core/workflow/adapt'; import { useMount } from 'ahooks'; import type { AppDetailType, AppSimpleEditFormType } from '@fastgpt/global/core/app/type'; import { useSimpleAppSnapshots } from '@/pageComponents/app/detail/Gate/useSnapshots'; -import { Dropdown } from 'react-day-picker'; import MyIcon from '@fastgpt/web/components/common/Icon'; import AddQuickAppModal from './AddQuickAppModal'; import { listQuickApps } from '@/web/support/user/team/gate/quickApp'; @@ -43,7 +42,6 @@ type Props = { tools: string[]; slogan: string; placeholderText: string; - onStatusChange?: (status: boolean) => void; onSloganChange?: (slogan: string) => void; onPlaceholderChange?: (text: string) => void; onToolsChange?: (tools: string[]) => void; @@ -54,7 +52,6 @@ const HomeTable = ({ appDetail, slogan, placeholderText, - onStatusChange, onSloganChange, onPlaceholderChange, onAppFormChange @@ -165,12 +162,6 @@ const HomeTable = ({ letterSpacing: '0.25px' }; - // 响应式工具布局 - - const handleStatusChange = (val: string) => { - onStatusChange?.(val === 'enabled'); - }; - const handleSloganChange = (val: string) => { onSloganChange?.(val); }; @@ -287,75 +278,6 @@ const HomeTable = ({ pb={6} pt={{ base: 4, md: 6 }} > - {/* 状态选择 */} - - - {t('account_gate:status')} - - - - - - - {t('account_gate:enabled')} - - - - - - - {t('account_gate:disabled')} - - - - - - {/* 快捷应用 */} {/* 标题行 */} - + {/* 标题区域 */} - + {t('common:core.app.Tool call')} - + {/* 已有工具时显示新增按钮 */} diff --git a/projects/app/src/pageComponents/app/detail/Gate/ChatGate.tsx b/projects/app/src/pageComponents/app/detail/Gate/ChatGate.tsx index 4f42525b8..56192f6dd 100644 --- a/projects/app/src/pageComponents/app/detail/Gate/ChatGate.tsx +++ b/projects/app/src/pageComponents/app/detail/Gate/ChatGate.tsx @@ -1,7 +1,6 @@ -import { Box, Flex } from '@chakra-ui/react'; +import { Box, Flex, HStack } from '@chakra-ui/react'; import React, { useEffect, useMemo, useState } from 'react'; -import { useSafeState } from 'ahooks'; import type { AppDetailType, AppSimpleEditFormType } from '@fastgpt/global/core/app/type'; import { useContextSelector } from 'use-context-selector'; import { useChatGate } from '../useChatGate'; @@ -11,6 +10,9 @@ import { useChatStore } from '@/web/core/chat/context/useChatStore'; import MyBox from '@fastgpt/web/components/common/MyBox'; import { cardStyles } from '../constants'; import ChatQuoteList from '@/pageComponents/chat/ChatQuoteList'; +import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; +import { getQuickApps, listQuickApps } from '@/web/support/user/team/gate/quickApp'; +import Avatar from '@fastgpt/web/components/common/Avatar'; type Props = { appForm: AppSimpleEditFormType; @@ -18,31 +20,17 @@ type Props = { appDetail: AppDetailType; // 添加 appDetail prop }; const ChatGate = ({ appForm, setRenderEdit, appDetail }: Props) => { - console.log('appDetai', appDetail); - console.log('appform', appForm); - const datasetCiteData = useContextSelector(ChatItemContext, (v) => v.datasetCiteData); const setCiteModalData = useContextSelector(ChatItemContext, (v) => v.setCiteModalData); - // 添加 selectedToolIds 状态管理 - const [selectedToolIds, setSelectedToolIds] = useState([]); - - const [workflowData] = useSafeState({ - nodes: appDetail.modules || [], - edges: appDetail.edges || [] - }); - useEffect(() => { setRenderEdit(!datasetCiteData); }, [datasetCiteData, setRenderEdit]); - const { ChatContainer, restartChat, loading } = useChatGate({ - ...workflowData, - chatConfig: appForm.chatConfig, + const { ChatContainer } = useChatGate({ + appForm, isReady: true, - appDetail, - selectedToolIds, // 传递 selectedToolIds - onSelectedToolIdsChange: setSelectedToolIds // 传递更新函数 + appDetail }); return ( diff --git a/projects/app/src/pageComponents/app/detail/Gate/components/GateToolSelect.tsx b/projects/app/src/pageComponents/app/detail/Gate/components/GateToolSelect.tsx index d33c5dd4d..baa98dfe5 100644 --- a/projects/app/src/pageComponents/app/detail/Gate/components/GateToolSelect.tsx +++ b/projects/app/src/pageComponents/app/detail/Gate/components/GateToolSelect.tsx @@ -12,25 +12,31 @@ import { ModalHeader, ModalBody, ModalCloseButton, - useDisclosure + useDisclosure, + HStack } from '@chakra-ui/react'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; import Avatar from '@fastgpt/web/components/common/Avatar'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { getTeamGateConfig } from '@/web/support/user/team/gate/api'; -import { getSystemPlugTemplates, getTeamPlugTemplates } from '@/web/core/app/api/plugin'; -import type { NodeTemplateListItemType } from '@fastgpt/global/core/workflow/type/node.d'; +import { + getPreviewPluginNode, + getSystemPlugTemplates, + getTeamPlugTemplates +} from '@/web/core/app/api/plugin'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; +import type { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node'; +import MyBox from '@fastgpt/web/components/common/MyBox'; type GateToolSelectProps = { - selectedToolIds: string[]; - onToolsChange: (toolIds: string[]) => void; + selectedTools: FlowNodeTemplateType[]; + onToolsChange: (tools: FlowNodeTemplateType[]) => void; buttonSize?: string; }; const GateToolSelect = ({ - selectedToolIds, + selectedTools, onToolsChange, buttonSize = 'md' }: GateToolSelectProps) => { @@ -77,60 +83,83 @@ const GateToolSelect = ({ }, [gateConfig?.tools, allAvailableTools]); // 处理单个工具的选择/取消选择 - const handleToolSelect = useCallback( - (toolId: string, checked: boolean) => { - const newSelectedIds = checked - ? [...selectedToolIds, toolId] - : selectedToolIds.filter((id) => id !== toolId); - onToolsChange(newSelectedIds); + const { runAsync: handleToolSelect, loading: loadingToolSelect } = useRequest2( + async (toolId: string, checked: boolean) => { + const tool = allAvailableTools.find((item) => item.id === toolId); + if (!tool) return; + + if (checked) { + const res = await getPreviewPluginNode({ appId: tool.id }); + onToolsChange([...selectedTools, res]); + } else { + onToolsChange(selectedTools.filter((item) => item.pluginId !== toolId)); + } }, - [selectedToolIds, onToolsChange] + { + refreshDeps: [allAvailableTools, selectedTools, onToolsChange] + } ); - const selectedCount = selectedToolIds.length; + const selectedCount = selectedTools.length; const loading = loadingGateConfig || loadingSystemPlugins || loadingTeamPlugins; - // 调试信息 - console.log('GateToolSelect Debug:', { - isOpen, - loading, - availableTools: availableTools.length, - gateConfigTools: gateConfig?.tools?.length || 0, - systemPlugins: systemPlugins.length, - teamPlugins: teamPlugins.length, - allAvailableTools: allAvailableTools.length - }); - - return ( + return availableTools.length > 0 ? ( <> - + {availableTools.length > 1 ? ( + + ) : ( + 0 && { + borderColor: 'primary.400 !important', + bg: 'primary.50' + })} + onClick={() => { + handleToolSelect(availableTools[0].id, selectedTools.length === 0); + }} + > + + + {availableTools[0].name} + + + )} @@ -152,76 +181,83 @@ const GateToolSelect = ({ - {loading ? ( - - - {t('common:Loading')} - - - ) : availableTools.length === 0 ? ( - - - - 请先在门户管理中配置工具,或检查是否有可用的插件 - - - ) : ( - - {availableTools.map((tool) => ( - handleToolSelect(tool.id, !selectedToolIds.includes(tool.id))} - > - - { - e.stopPropagation(); - handleToolSelect(tool.id, e.target.checked); - }} - mr={4} - colorScheme="blue" - /> - - - - {tool.name} - - {tool.intro && ( - - {tool.intro} + + {loading ? ( + + + {t('common:Loading')} + + + ) : availableTools.length === 0 ? ( + + + + 请先在门户管理中配置工具,或检查是否有可用的插件 + + + ) : ( + + {availableTools.map((tool) => ( + + handleToolSelect( + tool.id, + !selectedTools.some((item) => item.pluginId === tool.id) + ) + } + > + + item.pluginId === tool.id)} + onChange={(e) => { + e.stopPropagation(); + handleToolSelect(tool.id, e.target.checked); + }} + mr={4} + colorScheme="blue" + /> + + + + {tool.name} - )} - - - - ))} - - )} + {tool.intro && ( + + {tool.intro} + + )} + + + + ))} + + )} - {selectedToolIds.length > 0 && ( - - - 已选择 {selectedToolIds.length} 个工具 - - - )} + {selectedTools.length > 0 && ( + + + 已选择 {selectedTools.length} 个工具 + + + )} + - ); + ) : null; }; export default React.memo(GateToolSelect); diff --git a/projects/app/src/pageComponents/app/detail/useChatGate.tsx b/projects/app/src/pageComponents/app/detail/useChatGate.tsx index 5a1044428..f5dda2b47 100644 --- a/projects/app/src/pageComponents/app/detail/useChatGate.tsx +++ b/projects/app/src/pageComponents/app/detail/useChatGate.tsx @@ -1,16 +1,10 @@ import { useUserStore } from '@/web/support/user/useUserStore'; -import React, { useCallback, useEffect, useMemo } from 'react'; +import React, { useCallback, useEffect, useState } from 'react'; import type { StartChatFnProps } from '@/components/core/chat/ChatContainer/type'; import { streamFetch } from '@/web/common/api/fetch'; -import { useMemoizedFn } from 'ahooks'; +import { useMemoizedFn, useSafeState } from 'ahooks'; import { useContextSelector } from 'use-context-selector'; -import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node'; -import type { StoreEdgeItemType } from '@fastgpt/global/core/workflow/type/edge'; -import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; -import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; -import dynamic from 'next/dynamic'; -import { Box } from '@chakra-ui/react'; -import type { AppChatConfigType, AppDetailType } from '@fastgpt/global/core/app/type'; +import type { AppDetailType, AppSimpleEditFormType } from '@fastgpt/global/core/app/type'; import ChatBox from '@/components/core/chat/ChatContainer/ChatBox'; import { useChatStore } from '@/web/core/chat/context/useChatStore'; import { ChatItemContext } from '@/web/core/chat/context/chatItemContext'; @@ -20,29 +14,39 @@ import { useTranslation } from 'next-i18next'; import { ChatContext } from '@/web/core/chat/context/chatContext'; import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils'; import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt'; - -const PluginRunBox = dynamic(() => import('@/components/core/chat/ChatContainer/PluginRunBox')); +import { form2AppWorkflow } from '@/web/core/app/utils'; +import type { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node'; +import { listQuickApps } from '@/web/support/user/team/gate/quickApp'; export const useChatGate = ({ - selectedToolIds, - onSelectedToolIdsChange, - nodes, - edges, - chatConfig, + appForm, isReady, appDetail }: { - selectedToolIds?: string[]; - onSelectedToolIdsChange?: (toolIds: string[]) => void; - nodes: StoreNodeItemType[]; - edges: StoreEdgeItemType[]; - chatConfig: AppChatConfigType; + appForm: AppSimpleEditFormType; isReady: boolean; appDetail: AppDetailType; }) => { const { t } = useTranslation(); const { userInfo } = useUserStore(); const { setChatId, chatId, appId } = useChatStore(); + const [selectedTools, setSelectedTools] = useState([]); + + const [workflowData, setWorkflowData] = useSafeState({ + nodes: appDetail.modules || [], + edges: appDetail.edges || [] + }); + useEffect(() => { + const { nodes, edges } = form2AppWorkflow( + { + ...appForm, + selectedTools + }, + t + ); + setWorkflowData({ nodes, edges }); + }, [appForm, selectedTools, setWorkflowData, t]); + const onUpdateHistoryTitle = useContextSelector(ChatContext, (v) => v.onUpdateHistoryTitle); const startChat = useMemoizedFn( @@ -61,19 +65,18 @@ export const useChatGate = ({ data: { // Send histories and user messages messages: histories, - nodes, - edges, + nodes: workflowData.nodes, + edges: workflowData.edges, variables, responseChatItemId, appId, appName: t('chat:chat_gate_app', { name: appDetail.name }), chatId, - chatConfig, + chatConfig: appForm.chatConfig, metadata: { source: 'web', userAgent: navigator.userAgent - }, - selectedToolIds: selectedToolIds || [] + } }, onMessage: generatingMessage, abortCtrl: controller @@ -99,22 +102,18 @@ export const useChatGate = ({ const resetVariables = useContextSelector(ChatItemContext, (v) => v.resetVariables); const clearChatRecords = useContextSelector(ChatItemContext, (v) => v.clearChatRecords); - const pluginInputs = useMemo(() => { - return nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)?.inputs || []; - }, [nodes]); - // Set chat box data useEffect(() => { setChatBoxData({ userAvatar: userInfo?.avatar, appId: appId, app: { - chatConfig, + chatConfig: appForm.chatConfig, name: appDetail.name, avatar: appDetail.avatar, intro: appDetail.intro, type: appDetail.type, - pluginInputs + pluginInputs: [] } }); }, [ @@ -122,9 +121,8 @@ export const useChatGate = ({ appDetail.intro, appDetail.name, appDetail.type, + appForm.chatConfig, appId, - chatConfig, - pluginInputs, setChatBoxData, userInfo?.avatar ]); @@ -151,29 +149,24 @@ export const useChatGate = ({ setChatId(); }, [clearChatRecords, setChatId]); - const CustomChatContainer = useMemoizedFn(() => - appDetail.type === AppTypeEnum.plugin ? ( - - - - ) : ( - - ) - ); + // 精选应用 + const { data: recommendApps = [] } = useRequest2(listQuickApps, { + manual: false + }); + + const CustomChatContainer = useMemoizedFn(() => ( + + )); return { ChatContainer: CustomChatContainer, diff --git a/projects/app/src/pages/account/gateway/index.tsx b/projects/app/src/pages/account/gateway/index.tsx index 933c63573..88e9d3e06 100644 --- a/projects/app/src/pages/account/gateway/index.tsx +++ b/projects/app/src/pages/account/gateway/index.tsx @@ -29,9 +29,9 @@ type TabType = 'home' | 'copyright' | 'app' | 'logs'; const GatewayConfig = () => { const { t } = useTranslation(); - const [gateConfig, setGateConfig] = useState(undefined); + const [gateConfig, setGateConfig] = useState(); // 添加 appForm 状态 - const [appForm, setAppForm] = useState(undefined); + const [appForm, setAppForm] = useState(); //从 appForm 中获取 selectedTools的 id 组成 string 数组 //gateConfig?.tools 改成 diff --git a/projects/app/src/pages/api/core/chat/chatGate.ts b/projects/app/src/pages/api/core/chat/chatGate.ts index 44c7b3b37..0fedd4d9c 100644 --- a/projects/app/src/pages/api/core/chat/chatGate.ts +++ b/projects/app/src/pages/api/core/chat/chatGate.ts @@ -64,7 +64,6 @@ export type Props = { chatId: string; chatConfig: AppChatConfigType; metadata?: Record; - selectedToolIds?: string[]; }; async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -81,8 +80,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { appId, chatConfig, chatId, - metadata = {}, - selectedToolIds = [] + metadata = {} } = req.body as Props; try { if (!Array.isArray(nodes)) { @@ -91,47 +89,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { if (!Array.isArray(edges)) { throw new Error('Edges is not array'); } - - //对边进行过滤,只保留selectedToolIds中的边 - console.log('selectedToolIds', selectedToolIds); - - // 创建从 pluginId 到 nodeId 的映射 - const pluginIdToNodeIdMap = new Map(); - nodes.forEach((node) => { - if (node.pluginId) { - pluginIdToNodeIdMap.set(node.pluginId, node.nodeId); - } - }); - console.log('pluginIdToNodeIdMap', Object.fromEntries(pluginIdToNodeIdMap)); - - // 获取选中工具对应的 nodeId 集合 - const selectedNodeIds = new Set(); - selectedToolIds.forEach((pluginId) => { - const nodeId = pluginIdToNodeIdMap.get(pluginId); - if (nodeId) { - selectedNodeIds.add(nodeId); - } - }); - console.log('selectedNodeIds', Array.from(selectedNodeIds)); - - // 过滤边:保留第一个边和目标节点在选中工具中的边 - const filteredEdges = edges.filter((edge, index) => { - // 保留第一个边 - if (index === 0) { - return true; - } - - // 保留目标节点在选中工具中的边 - return selectedNodeIds.has(edge.target); - }); - - console.log('Original edges count:', edges.length); - console.log('Filtered edges count:', filteredEdges.length); - console.log('Filtered edges:', filteredEdges); - - // 使用过滤后的边 - edges = filteredEdges; - const chatMessages = GPTMessages2Chats(messages); // console.log(JSON.stringify(chatMessages, null, 2), '====', chatMessages.length); diff --git a/projects/app/src/pages/chat/gate/application.tsx b/projects/app/src/pages/chat/gate/application.tsx index c24845cae..f97d519d3 100644 --- a/projects/app/src/pages/chat/gate/application.tsx +++ b/projects/app/src/pages/chat/gate/application.tsx @@ -10,9 +10,6 @@ import { useTranslation } from 'next-i18next'; import FoldButton from '@/pageComponents/chat/gatechat/FoldButton'; import type { StartChatFnProps } from '@/components/core/chat/ChatContainer/type'; import PageContainer from '@/components/PageContainer'; -import SideBar from '@/components/SideBar'; -import ChatHistorySlider from '@/pageComponents/chat/ChatHistorySlider'; -import SliderApps from '@/pageComponents/chat/SliderApps'; import ChatHeader from '@/pageComponents/chat/ChatHeader'; import { useUserStore } from '@/web/support/user/useUserStore'; import { serviceSideProps } from '@/web/common/i18n/utils';