diff --git a/docSite/content/zh-cn/docs/development/upgrading/4811.md b/docSite/content/zh-cn/docs/development/upgrading/4811.md index 427ab90c1..f43a4caa8 100644 --- a/docSite/content/zh-cn/docs/development/upgrading/4811.md +++ b/docSite/content/zh-cn/docs/development/upgrading/4811.md @@ -21,5 +21,6 @@ weight: 813 4. 优化 - 工作流嵌套层级限制 20 层,避免因编排不合理导致的无限死循环。 5. 优化 - 工作流 handler 性能优化。 6. 优化 - 工作流快捷键,避免调试测试时也会触发。 -7. 修复 - 知识库选择权限问题。 -8. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。 +7. 优化 - 流输出,切换 tab 时仍可以继续输出。 +8. 修复 - 知识库选择权限问题。 +9. 修复 - 空 chatId 发起对话,首轮携带用户选择时会异常。 diff --git a/packages/service/core/workflow/dispatch/index.ts b/packages/service/core/workflow/dispatch/index.ts index 7ab7a9414..f586456a3 100644 --- a/packages/service/core/workflow/dispatch/index.ts +++ b/packages/service/core/workflow/dispatch/index.ts @@ -374,6 +374,18 @@ export async function dispatchWorkFlow(data: Props): Promise 0) { + skippedNodeIdList.add(node.nodeId); + } + // In the current version, only one interactive node is allowed at the same time const interactiveResponse = nodeRunResult.result?.[DispatchNodeResponseKeyEnum.interactive]; if (interactiveResponse) { @@ -559,7 +571,6 @@ export async function dispatchWorkFlow(data: Props): Promise item.isEntry); - // reset entry runtimeNodes.forEach((item) => { // Interactive node is not the entry node, return interactive result diff --git a/packages/web/hooks/useScrollPagination.tsx b/packages/web/hooks/useScrollPagination.tsx index d27e382e4..da989c64c 100644 --- a/packages/web/hooks/useScrollPagination.tsx +++ b/packages/web/hooks/useScrollPagination.tsx @@ -141,7 +141,6 @@ export function useScrollPagination< // Reload data useRequest( async () => { - console.log('reload', 11111); loadData(1); }, { diff --git a/projects/app/src/components/Layout/index.tsx b/projects/app/src/components/Layout/index.tsx index 1cd1ed0dc..ea76ff28f 100644 --- a/projects/app/src/components/Layout/index.tsx +++ b/projects/app/src/components/Layout/index.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { Box, Flex } from '@chakra-ui/react'; import { useRouter } from 'next/router'; import { useLoading } from '@fastgpt/web/hooks/useLoading'; @@ -12,6 +12,7 @@ import { useI18nLng } from '@fastgpt/web/hooks/useI18n'; import Auth from './auth'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useMount } from 'ahooks'; +import { watchWindowHidden } from '@/web/common/system/utils'; const Navbar = dynamic(() => import('./navbar')); const NavbarPhone = dynamic(() => import('./navbarPhone')); const UpdateInviteModal = dynamic(() => import('@/components/support/user/team/UpdateInviteModal')); @@ -68,6 +69,14 @@ const Layout = ({ children }: { children: JSX.Element }) => { setUserDefaultLng(); }); + // Add global listener + useEffect(() => { + document.addEventListener('visibilitychange', watchWindowHidden); + return () => { + document.removeEventListener('visibilitychange', watchWindowHidden); + }; + }); + return ( <> diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx index d0df23eec..1966d19e5 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/ImportSettings.tsx @@ -4,17 +4,16 @@ import MyModal from '@fastgpt/web/components/common/MyModal'; import { useToast } from '@fastgpt/web/hooks/useToast'; import { useContextSelector } from 'use-context-selector'; import { WorkflowContext } from '../context'; -import { useI18n } from '@/web/context/I18n'; import { useTranslation } from 'next-i18next'; import MyIcon from '@fastgpt/web/components/common/Icon'; import { useSelectFile } from '@/web/common/file/hooks/useSelectFile'; import { useSystem } from '@fastgpt/web/hooks/useSystem'; + type Props = { onClose: () => void; }; const ImportSettings = ({ onClose }: Props) => { - const { appT } = useI18n(); const { toast } = useToast(); const { File, onOpen } = useSelectFile({ fileType: 'json', @@ -25,21 +24,6 @@ const ImportSettings = ({ onClose }: Props) => { const [isDragging, setIsDragging] = useState(false); const [value, setValue] = useState(''); const { t } = useTranslation(); - const handleDragEnter = useCallback((e: DragEvent) => { - e.preventDefault(); - setIsDragging(true); - }, []); - - const handleDragLeave = useCallback((e: DragEvent) => { - e.preventDefault(); - setIsDragging(false); - }, []); - const handleDrop = useCallback(async (e: DragEvent) => { - e.preventDefault(); - const file = e.dataTransfer.files[0]; - readJSONFile(file); - setIsDragging(false); - }, []); const readJSONFile = useCallback( (file: File) => { @@ -62,6 +46,25 @@ const ImportSettings = ({ onClose }: Props) => { [t, toast] ); + const handleDragEnter = useCallback((e: DragEvent) => { + e.preventDefault(); + setIsDragging(true); + }, []); + + const handleDragLeave = useCallback((e: DragEvent) => { + e.preventDefault(); + setIsDragging(false); + }, []); + const handleDrop = useCallback( + async (e: DragEvent) => { + e.preventDefault(); + const file = e.dataTransfer.files[0]; + readJSONFile(file); + setIsDragging(false); + }, + [readJSONFile] + ); + const onSelectFile = useCallback( async (e: File[]) => { const file = e[0]; @@ -70,16 +73,14 @@ const ImportSettings = ({ onClose }: Props) => { }, [readJSONFile] ); + return ( - - {appT('import_configs')} - - } + iconSrc="common/importLight" + iconColor="primary.600" + title={t('app:import_configs')} size={isPc ? 'lg' : 'md'} > @@ -129,14 +130,12 @@ const ImportSettings = ({ onClose }: Props) => { border={'1px solid'} borderRadius={'md'} borderColor={'myGray.200'} - h={'15.125rem'} value={value} placeholder={ isPc ? t('app:paste_config') + '\n' + t('app:or_drag_JSON') : t('app:paste_config') } - defaultValue={value} rows={16} onChange={(e) => setValue(e.target.value)} /> diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx index 4cf829be4..3685d99a7 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/components/FlowController.tsx @@ -34,12 +34,10 @@ const FlowController = React.memo(function FlowController() { // Controller shortcut key useKeyPress(['ctrl.z', 'meta.z'], (e) => { - e.preventDefault(); if (!mouseInCanvas) return; undo(); }); useKeyPress(['ctrl.shift.z', 'meta.shift.z', 'ctrl.y', 'meta.y'], (e) => { - e.preventDefault(); if (!mouseInCanvas) return; redo(); }); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useKeyboard.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useKeyboard.tsx index cfe61d1c2..63d48bc02 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useKeyboard.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/hooks/useKeyboard.tsx @@ -86,12 +86,10 @@ export const useKeyboard = () => { }, [computedNewNodeName, hasInputtingElement, setNodes]); useKeyPressEffect(['ctrl.c', 'meta.c'], (e) => { - e.preventDefault(); if (!mouseInCanvas) return; onCopy(); }); useKeyPressEffect(['ctrl.v', 'meta.v'], (e) => { - e.preventDefault(); if (!mouseInCanvas) return; onParse(); }); diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx index 4156c6b0f..e60d01020 100644 --- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx +++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/Handle/ToolHandle.tsx @@ -44,7 +44,7 @@ export const ToolTargetHandle = ({ show, nodeId }: ToolHandleProps) => { type="target" id={handleId} position={Position.Top} - isConnectableStart={false} + isConnectableEnd={showHandle} > void; }; + windowHidden: boolean; } } diff --git a/projects/app/src/web/common/api/fetch.ts b/projects/app/src/web/common/api/fetch.ts index 42cf54939..d729a7f92 100644 --- a/projects/app/src/web/common/api/fetch.ts +++ b/projects/app/src/web/common/api/fetch.ts @@ -84,7 +84,7 @@ export const streamFetch = ({ } if (responseQueue.length > 0) { - const fetchCount = Math.max(1, Math.round(responseQueue.length / 30)); + const fetchCount = Math.max(1, Math.round(responseQueue.length / 20)); for (let i = 0; i < fetchCount; i++) { const item = responseQueue[i]; onMessage(item); @@ -100,7 +100,9 @@ export const streamFetch = ({ return finish(); } - requestAnimationFrame(animateResponseText); + window.windowHidden + ? setTimeout(animateResponseText, 16) + : requestAnimationFrame(animateResponseText); } // start animation animateResponseText(); diff --git a/projects/app/src/web/common/system/utils.ts b/projects/app/src/web/common/system/utils.ts index 3d5ea1ef8..d3fb7f7e4 100644 --- a/projects/app/src/web/common/system/utils.ts +++ b/projects/app/src/web/common/system/utils.ts @@ -13,3 +13,12 @@ export const getWebLLMModel = (model?: string) => { const list = useSystemStore.getState().llmModelList; return list.find((item) => item.model === model || item.name === model) ?? list[0]; }; + +export const watchWindowHidden = () => { + // @ts-ignore + if (document.hidden) { + window.windowHidden = true; + } else { + window.windowHidden = false; + } +};