From e27abe1f6b7f1a4b8495f00390351daf60da4a36 Mon Sep 17 00:00:00 2001
From: papapatrick <109422393+Patrickill@users.noreply.github.com>
Date: Mon, 29 Jul 2024 18:36:13 +0800
Subject: [PATCH] =?UTF-8?q?perf:=20=E8=BF=90=E8=A1=8C=E8=AF=A6=E6=83=85?=
=?UTF-8?q?=E5=BC=B9=E7=AA=97=E4=BC=98=E5=8C=96=20(#2192)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* perf: 运行详情弹窗优化
* style: 调整样式
* style: 弹窗样式优化&&应用切换圆角添加
* fix: 修复编译错误
---
.../app/public/imgs/modal/wholeRecord.svg | 12 +-
.../components/RenderResponseDetail.tsx | 2 +-
.../chat/components/WholeResponseModal.tsx | 440 ++++++++++++++----
.../Flow/nodes/render/NodeCard.tsx | 8 +-
.../src/pages/chat/components/ChatHeader.tsx | 4 +-
.../chat/components/CustomPluginRunBox.tsx | 4 +-
6 files changed, 376 insertions(+), 94 deletions(-)
diff --git a/projects/app/public/imgs/modal/wholeRecord.svg b/projects/app/public/imgs/modal/wholeRecord.svg
index eb91469b0..c0a4afbc3 100644
--- a/projects/app/public/imgs/modal/wholeRecord.svg
+++ b/projects/app/public/imgs/modal/wholeRecord.svg
@@ -1 +1,11 @@
-
\ No newline at end of file
+
diff --git a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderResponseDetail.tsx b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderResponseDetail.tsx
index 0e6f1757e..48d572a0c 100644
--- a/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderResponseDetail.tsx
+++ b/projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderResponseDetail.tsx
@@ -13,7 +13,7 @@ const RenderResponseDetail = () => {
<>{'进行中'}>
) : (
-
+
);
};
diff --git a/projects/app/src/components/core/chat/components/WholeResponseModal.tsx b/projects/app/src/components/core/chat/components/WholeResponseModal.tsx
index 431d1251f..46bca0a2e 100644
--- a/projects/app/src/components/core/chat/components/WholeResponseModal.tsx
+++ b/projects/app/src/components/core/chat/components/WholeResponseModal.tsx
@@ -1,10 +1,8 @@
import React, { useMemo, useState } from 'react';
-import { Box, useTheme, Flex, Image, BoxProps } from '@chakra-ui/react';
+import { Box, Flex, BoxProps, useDisclosure } from '@chakra-ui/react';
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
import { useTranslation } from 'next-i18next';
import { moduleTemplatesFlat } from '@fastgpt/global/core/workflow/template/constants';
-
-import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
import MyModal from '@fastgpt/web/components/common/MyModal';
import Markdown from '@/components/Markdown';
import { QuoteList } from '../ChatContainer/ChatBox/components/QuoteModal';
@@ -13,6 +11,17 @@ import { formatNumber } from '@fastgpt/global/common/math/tools';
import { useI18n } from '@/web/context/I18n';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import Avatar from '@fastgpt/web/components/common/Avatar';
+import { useSystem } from '@fastgpt/web/hooks/useSystem';
+import MyIcon from '@fastgpt/web/components/common/Icon';
+
+type sideTabItemType = {
+ moduleLogo?: string;
+ moduleName: string;
+ runningTime?: number;
+ moduleType: string;
+ nodeId: string;
+ children: sideTabItemType[];
+};
function RowRender({
children,
@@ -40,7 +49,6 @@ function Row({
value?: string | number | boolean | object;
rawDom?: React.ReactNode;
}) {
- const theme = useTheme();
const val = value || rawDom;
const isObject = typeof value === 'object';
@@ -66,9 +74,9 @@ function Row({
label={label}
mb={isObject ? 0 : 1}
{...(isObject
- ? { transform: 'translateY(-3px)' }
+ ? { py: 2, transform: 'translateY(-3px)' }
: value
- ? { px: 3, py: 2, border: theme.borders.base }
+ ? { px: 3, py: 2, border: 'base' }
: {})}
>
@@ -93,7 +101,8 @@ const WholeResponseModal = ({
isOpen={true}
onClose={onClose}
h={['90vh', '80vh']}
- minW={['90vw', '600px']}
+ maxH={['90vh', '700px']}
+ minW={['90vw', '880px']}
iconSrc="/imgs/modal/wholeRecord.svg"
title={
@@ -112,59 +121,138 @@ export default WholeResponseModal;
export const ResponseBox = React.memo(function ResponseBox({
response,
showDetail,
- hideTabs = false
+ hideTabs = false,
+ useMobile = false
}: {
response: ChatHistoryItemResType[];
showDetail: boolean;
hideTabs?: boolean;
+ useMobile?: boolean;
}) {
- const theme = useTheme();
+ const { t } = useTranslation();
+ const { isPc } = useSystem();
+ const flattedResponse = useMemo(() => flattenArray(response), [response]);
+ const [currentNodeId, setCurrentNodeId] = useState(
+ flattedResponse[0]?.nodeId ? flattedResponse[0].nodeId : ''
+ );
+ const activeModule = useMemo(
+ () => flattedResponse.find((item) => item.nodeId === currentNodeId) as ChatHistoryItemResType,
+ [currentNodeId, flattedResponse]
+ );
+ const sideResponse: sideTabItemType[] = useMemo(() => {
+ return pretreatmentResponse(response);
+ }, [response]);
+ const {
+ isOpen: isOpenMobileModal,
+ onOpen: onOpenMobileModal,
+ onClose: onCloseMobileModal
+ } = useDisclosure();
+
+ return (
+ <>
+ {isPc && !useMobile ? (
+
+
+
+
+
+
+
+
+
+
+ ) : (
+ <>
+
+ {!isOpenMobileModal && (
+
+ {
+ setCurrentNodeId(item);
+ onOpenMobileModal();
+ }}
+ isMobile={true}
+ />
+
+ )}
+ {isOpenMobileModal && (
+
+
+ {
+ e.stopPropagation();
+ onCloseMobileModal();
+ }}
+ position={'absolute'}
+ left={2}
+ top={'50%'}
+ transform={'translateY(-50%)'}
+ />
+
+ activeModule.moduleType === template.flowNodeType
+ )?.avatar
+ }
+ w={'1.25rem'}
+ h={'1.25rem'}
+ borderRadius={'sm'}
+ />
+
+
+ {t(activeModule.moduleName as any)}
+
+
+
+
+ )}
+
+ >
+ )}
+ >
+ );
+});
+
+const WholeResponseContent = ({
+ activeModule,
+ hideTabs,
+ showDetail
+}: {
+ activeModule: ChatHistoryItemResType;
+ hideTabs?: boolean;
+ showDetail: boolean;
+}) => {
const { t } = useTranslation();
const { workflowT } = useI18n();
- const list = useMemo(
- () =>
- response.map((item, i) => ({
- label: (
-
- item.moduleType === template.flowNodeType)
- ?.avatar
- }
- alt={''}
- w={'1.25rem'}
- borderRadius={'sm'}
- />
- {t(item.moduleName as any)}
-
- ),
- value: `${i}`
- })),
- [response, t]
- );
-
- const [currentTab, setCurrentTab] = useState(`0`);
-
- const activeModule = useMemo(() => response[Number(currentTab)], [currentTab, response]);
-
return (
-
- {!hideTabs && (
-
-
-
- )}
+ <>
{activeModule && (
+ {/* common info */}
<>
>
-
{/* ai chat */}
<>
+
{activeModule.historyPreview?.map((item, i) => (
>
-
{/* dataset search */}
<>
{activeModule?.searchMode && (
@@ -279,7 +366,6 @@ export const ResponseBox = React.memo(function ResponseBox({
/>
)}
>
-
{/* classify question */}
<>
>
-
{/* if-else */}
<>
>
-
{/* extract */}
<>
>
-
{/* http */}
<>
@@ -325,49 +408,236 @@ export const ResponseBox = React.memo(function ResponseBox({
value={activeModule?.httpResult}
/>
>
-
{/* plugin */}
<>
- {activeModule?.pluginDetail && activeModule?.pluginDetail.length > 0 && (
-
-
-
- }
- />
- )}
>
-
{/* text output */}
-
- {/* tool call */}
- {activeModule?.toolDetail && activeModule?.toolDetail.length > 0 && (
-
-
-
- }
- />
- )}
-
{/* code */}
)}
-
+ >
);
-});
+};
+
+const WholeResponseSideTab = ({
+ response,
+ value,
+ onChange,
+ isMobile = false
+}: {
+ response: sideTabItemType[];
+ value: string;
+ onChange: (index: string) => void;
+ isMobile?: boolean;
+}) => {
+ return (
+ <>
+ {response.map((item) => (
+
+
+
+ ))}
+ >
+ );
+};
+
+const AccordionSideTabItem = ({
+ sideBarItem,
+ onChange,
+ value,
+ index
+}: {
+ sideBarItem: sideTabItemType;
+ onChange: (nodeId: string) => void;
+ value: string;
+ index: number;
+}) => {
+ const { isOpen: isShowAccordion, onToggle: onToggleShowAccordion } = useDisclosure({
+ defaultIsOpen: false
+ });
+ return (
+ <>
+
+
+ {
+ e.stopPropagation();
+ onToggleShowAccordion();
+ }}
+ _hover={{ color: 'primary.600', cursor: 'pointer' }}
+ />
+
+
+ {isShowAccordion && (
+
+ {sideBarItem.children.map((item) => (
+
+ ))}
+
+ )}
+ >
+ );
+};
+
+const NormalSideTabItem = ({
+ sideBarItem,
+ onChange,
+ value,
+ index,
+ children
+}: {
+ sideBarItem: sideTabItemType;
+ onChange: (nodeId: string) => void;
+ value: string;
+ index: number;
+ children?: React.ReactNode;
+}) => {
+ const { t } = useTranslation();
+ const leftIndex = index > 3 ? 3 : index;
+ return (
+ {
+ onChange(sideBarItem.nodeId);
+ }}
+ background={value === sideBarItem.nodeId ? 'myGray.100' : ''}
+ _hover={{ background: 'myGray.100' }}
+ p={2}
+ width={'100%'}
+ cursor={'pointer'}
+ pl={leftIndex === 0 ? '0.5rem' : `${1.5 * leftIndex + 0.5}rem`}
+ borderRadius={'md'}
+ position={'relative'}
+ >
+ sideBarItem.moduleType === template.flowNodeType)
+ ?.avatar
+ }
+ alt={''}
+ w={'1.5rem'}
+ h={'1.5rem'}
+ borderRadius={'sm'}
+ />
+
+
+ {t(sideBarItem.moduleName as any)}
+
+
+ {t(sideBarItem.runningTime as any) + 's'}
+
+
+
+ {children}
+
+
+ );
+};
+
+const SideTabItem = ({
+ sideBarItem,
+ onChange,
+ value,
+ index
+}: {
+ sideBarItem: sideTabItemType;
+ onChange: (nodeId: string) => void;
+ value: string;
+ index: number;
+}) => {
+ if (!sideBarItem) return null;
+ return sideBarItem.children.length !== 0 ? (
+ <>
+
+
+
+ >
+ ) : (
+
+ );
+};
+
+function pretreatmentResponse(res: ChatHistoryItemResType[]): sideTabItemType[] {
+ return res.map((item) => {
+ let children: sideTabItemType[] = [];
+ if (!!(item?.toolDetail || item?.pluginDetail)) {
+ if (item?.toolDetail) children.push(...pretreatmentResponse(item?.toolDetail));
+ if (item?.pluginDetail) children.push(...pretreatmentResponse(item?.pluginDetail));
+ }
+
+ return {
+ moduleLogo: item.moduleLogo,
+ moduleName: item.moduleName,
+ runningTime: item.runningTime,
+ moduleType: item.moduleType,
+ nodeId: item.nodeId,
+ children
+ };
+ });
+}
+
+function flattenArray(arr: ChatHistoryItemResType[]) {
+ const result: ChatHistoryItemResType[] = [];
+
+ function helper(currentArray: ChatHistoryItemResType[]) {
+ currentArray.forEach((item) => {
+ if (item && typeof item === 'object') {
+ result.push(item);
+
+ if (Array.isArray(item.toolDetail)) {
+ helper(item.toolDetail);
+ }
+ if (Array.isArray(item.pluginDetail)) {
+ helper(item.pluginDetail);
+ }
+ }
+ });
+ }
+
+ helper(arr);
+ return result;
+}
diff --git a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx
index 77e74e397..36b5059d0 100644
--- a/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx
+++ b/projects/app/src/pages/app/detail/components/WorkflowComponents/Flow/nodes/render/NodeCard.tsx
@@ -573,8 +573,8 @@ const NodeDebugResponse = React.memo(function NodeDebugResponse({
top={0}
zIndex={10}
w={'420px'}
- maxH={'100%'}
minH={'300px'}
+ maxH={'100%'}
border={'base'}
>
{/* Status header */}
@@ -614,7 +614,7 @@ const NodeDebugResponse = React.memo(function NodeDebugResponse({
)}
{/* Show result */}
-
+
{!debugResult.message && !response && (
)}
@@ -623,7 +623,9 @@ const NodeDebugResponse = React.memo(function NodeDebugResponse({
{debugResult.message}
)}
- {response && }
+ {response && (
+
+ )}
)}
diff --git a/projects/app/src/pages/chat/components/ChatHeader.tsx b/projects/app/src/pages/chat/components/ChatHeader.tsx
index ed3bebf55..6e3f18fc0 100644
--- a/projects/app/src/pages/chat/components/ChatHeader.tsx
+++ b/projects/app/src/pages/chat/components/ChatHeader.tsx
@@ -174,7 +174,7 @@ const MobileDrawer = ({
onClick: () => onclickApp(item._id)
})}
>
-
+
{item.name}
@@ -223,7 +223,7 @@ const MobileHeader = ({
)}
-
+
{name}
diff --git a/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx b/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx
index 31d115a3d..b83b1d5e3 100644
--- a/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx
+++ b/projects/app/src/pages/chat/components/CustomPluginRunBox.tsx
@@ -27,7 +27,7 @@ const CustomPluginRunBox = (props: PluginRunBoxProps) => {
-
+
list={[
{ label: t('common:common.Output'), value: PluginRunBoxTabEnum.output },
@@ -61,7 +61,7 @@ const CustomPluginRunBox = (props: PluginRunBoxProps) => {
py={0}
fontSize={'sm'}
/>
-
+