diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts
index 997e489f9..3e6b6975e 100644
--- a/packages/web/components/common/Icon/constants.ts
+++ b/packages/web/components/common/Icon/constants.ts
@@ -97,6 +97,8 @@ export const iconPaths = {
'core/app/variable/textarea': () => import('./icons/core/app/variable/textarea.svg'),
'core/chat/QGFill': () => import('./icons/core/chat/QGFill.svg'),
'core/chat/cancelSpeak': () => import('./icons/core/chat/cancelSpeak.svg'),
+ 'core/chat/chevronSelector': () => import('./icons/core/chat/chevronSelector.svg'),
+ 'core/chat/sideLine': () => import('./icons/core/chat/sideLine.svg'),
'core/chat/chatFill': () => import('./icons/core/chat/chatFill.svg'),
'core/chat/chatLight': () => import('./icons/core/chat/chatLight.svg'),
'core/chat/chatModelTag': () => import('./icons/core/chat/chatModelTag.svg'),
diff --git a/packages/web/components/common/Icon/icons/core/chat/chevronSelector.svg b/packages/web/components/common/Icon/icons/core/chat/chevronSelector.svg
new file mode 100644
index 000000000..7262690df
--- /dev/null
+++ b/packages/web/components/common/Icon/icons/core/chat/chevronSelector.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/web/components/common/Icon/icons/core/chat/sideLine.svg b/packages/web/components/common/Icon/icons/core/chat/sideLine.svg
new file mode 100644
index 000000000..1d063172d
--- /dev/null
+++ b/packages/web/components/common/Icon/icons/core/chat/sideLine.svg
@@ -0,0 +1,3 @@
+
diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json
index cd3289aeb..52387c19b 100644
--- a/packages/web/i18n/en/common.json
+++ b/packages/web/i18n/en/common.json
@@ -1,6 +1,7 @@
{
"add_new": "Add new",
"App": "App",
+ "all_apps": "All Apps",
"click_to_resume": "Resume",
"code_editor": "Code edit",
"Export": "Export",
diff --git a/packages/web/i18n/zh/common.json b/packages/web/i18n/zh/common.json
index 70e8359d7..66ef3d30a 100644
--- a/packages/web/i18n/zh/common.json
+++ b/packages/web/i18n/zh/common.json
@@ -1,6 +1,7 @@
{
"add_new": "新增",
"App": "应用",
+ "all_apps": "全部应用",
"click_to_resume": "点击恢复",
"code_editor": "代码编辑",
"Export": "导出",
diff --git a/projects/app/src/pages/chat/components/ChatHeader.tsx b/projects/app/src/pages/chat/components/ChatHeader.tsx
index 8804d1e3c..703ca4030 100644
--- a/projects/app/src/pages/chat/components/ChatHeader.tsx
+++ b/projects/app/src/pages/chat/components/ChatHeader.tsx
@@ -1,11 +1,11 @@
-import React from 'react';
-import { Flex, useTheme, Box } from '@chakra-ui/react';
-import { useSystemStore } from '@/web/common/system/useSystemStore';
+import React, { useState, useCallback } from 'react';
+import { Flex, useTheme, Box, useDisclosure } from '@chakra-ui/react';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Avatar from '@fastgpt/web/components/common/Avatar';
import ToolMenu from './ToolMenu';
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
import { useTranslation } from 'next-i18next';
+
import MyTag from '@fastgpt/web/components/common/Tag/index';
import { useContextSelector } from 'use-context-selector';
import { ChatContext } from '@/web/core/chat/context/chatContext';
@@ -13,85 +13,287 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { InitChatResponse } from '@/global/core/chat/api';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
+import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
+import { useRouter } from 'next/router';
+import { AppListItemType } from '@fastgpt/global/core/app/type';
+import {
+ GetResourceFolderListProps,
+ GetResourceListItemResponse
+} from '@fastgpt/global/common/parentFolder/type';
+import { getMyApps } from '@/web/core/app/api';
+import SelectOneResource from '@/components/common/folder/SelectOneResource';
const ChatHeader = ({
chatData,
history,
showHistory,
- onRoute2AppDetail
+ onRoute2AppDetail,
+ apps
}: {
- chatData: InitChatResponse;
history: ChatItemType[];
showHistory?: boolean;
onRoute2AppDetail?: () => void;
+ apps?: AppListItemType[];
+ chatData: InitChatResponse;
}) => {
- const theme = useTheme();
- const { t } = useTranslation();
- const { isPc } = useSystem();
-
- const chatModels = chatData.app.chatModels;
const isPlugin = chatData.app.type === AppTypeEnum.plugin;
-
- const onOpenSlider = useContextSelector(ChatContext, (v) => v.onOpenSlider);
-
- return isPc && isPlugin ? null : (
-
- {isPc ? (
- <>
-
- {chatData.title}
-
-
-
-
- {history.length === 0
- ? t('common:core.chat.New Chat')
- : t('core.chat.History Amount', { amount: history.length })}
-
-
- {!!chatModels && chatModels.length > 0 && (
-
-
-
-
- {chatModels.join(',')}
-
-
-
- )}
-
- >
- ) : (
- <>
- {showHistory && (
-
+ {isPc && isPlugin ? null : (
+
+ {isPc ? (
+
+ ) : (
+
)}
-
-
-
- {chatData.app.name}
-
-
- >
+ {/* control */}
+ {!isPlugin && }
+
)}
+ >
+ );
+};
- {/* control */}
- {!isPlugin && }
-
+const MobileDrawer = ({
+ onCloseDrawer,
+ appId,
+ apps
+}: {
+ onCloseDrawer: () => void;
+ appId: string;
+ apps?: AppListItemType[];
+}) => {
+ enum TabEnum {
+ recently = 'recently',
+ app = 'app'
+ }
+ const { t } = useTranslation();
+ const { isPc } = useSystem();
+ const router = useRouter();
+ const isTeamChat = router.pathname === '/chat/team';
+ const [currentTab, setCurrentTab] = useState(TabEnum.recently);
+ const getAppList = useCallback(async ({ parentId }: GetResourceFolderListProps) => {
+ return getMyApps({ parentId }).then((res) =>
+ res.map((item) => ({
+ id: item._id,
+ name: item.name,
+ avatar: item.avatar,
+ isFolder: item.type === AppTypeEnum.folder
+ }))
+ );
+ }, []);
+ const { onChangeAppId } = useContextSelector(ChatContext, (v) => v);
+ return (
+ <>
+ {
+ onCloseDrawer();
+ }}
+ >
+ {/* menu */}
+ e.stopPropagation()}
+ background={'white'}
+ position={'relative'}
+ >
+ {!isPc && appId && (
+
+ flex={'1 0 0'}
+ width={isTeamChat ? '30%' : '60%'}
+ mr={10}
+ inlineStyles={{
+ px: 1
+ }}
+ list={[
+ ...(isTeamChat
+ ? [{ label: t('common:all_apps'), value: TabEnum.recently }]
+ : [
+ { label: t('common:core.chat.Recent use'), value: TabEnum.recently },
+ { label: t('common:all_apps'), value: TabEnum.app }
+ ])
+ ]}
+ value={currentTab}
+ onChange={setCurrentTab}
+ />
+ )}
+
+ e.stopPropagation()}
+ borderRadius={'0 0 10px 10px'}
+ position={'relative'}
+ padding={3}
+ pt={0}
+ pb={4}
+ >
+ {/* history */}
+ {currentTab === TabEnum.recently && (
+ <>
+ {Array.isArray(apps) &&
+ apps.map((item) => (
+
+ onChangeAppId(item._id)
+ })}
+ >
+
+
+ {item.name}
+
+
+
+ ))}
+ >
+ )}
+ {currentTab === TabEnum.app && !isPc && (
+ <>
+ {
+ if (!id) return;
+ onChangeAppId(id);
+ }}
+ server={getAppList}
+ />
+ >
+ )}
+
+
+ >
+ );
+};
+
+const MobileHeader = ({
+ showHistory,
+ go2AppDetail,
+ name,
+ avatar,
+ appId,
+ apps
+}: {
+ showHistory?: boolean;
+ go2AppDetail?: () => void;
+ avatar: string;
+ name: string;
+ apps?: AppListItemType[];
+ appId: string;
+}) => {
+ const { isPc } = useSystem();
+ const router = useRouter();
+ const onOpenSlider = useContextSelector(ChatContext, (v) => v.onOpenSlider);
+ const { isOpen: isOpenDrawer, onToggle: toggleDrawer, onClose: onCloseDrawer } = useDisclosure();
+ const isShareChat = router.pathname === '/chat/share';
+
+ return (
+ <>
+ {showHistory && (
+
+ )}
+
+
+
+ {name}
+
+ {isShareChat ? null : (
+
+ )}
+
+ {!isPc && isOpenDrawer && !isShareChat && (
+
+ )}
+ >
+ );
+};
+
+const PcHeader = ({
+ title,
+ chatModels,
+ history
+}: {
+ title: string;
+ chatModels?: string[];
+ history: ChatItemType[];
+}) => {
+ const { t } = useTranslation();
+ return (
+ <>
+
+ {title}
+
+
+
+
+ {history.length === 0
+ ? t('common:core.chat.New Chat')
+ : t('common:core.chat.History Amount', { amount: history.length })}
+
+
+ {!!chatModels && chatModels.length > 0 && (
+
+
+
+
+ {chatModels.join(',')}
+
+
+
+ )}
+
+ >
);
};
diff --git a/projects/app/src/pages/chat/components/ChatHistorySlider.tsx b/projects/app/src/pages/chat/components/ChatHistorySlider.tsx
index 6fd0f6cc9..bfc225823 100644
--- a/projects/app/src/pages/chat/components/ChatHistorySlider.tsx
+++ b/projects/app/src/pages/chat/components/ChatHistorySlider.tsx
@@ -1,6 +1,6 @@
-import React, { useCallback, useMemo, useState } from 'react';
+import React, { useMemo } from 'react';
import { Box, Button, Flex, useTheme, IconButton } from '@chakra-ui/react';
-import { useSystemStore } from '@/web/common/system/useSystemStore';
+import { useSystem } from '@fastgpt/web/hooks/useSystem';
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
import { useRouter } from 'next/router';
import Avatar from '@fastgpt/web/components/common/Avatar';
@@ -8,22 +8,13 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useTranslation } from 'next-i18next';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
-import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
import { useUserStore } from '@/web/support/user/useUserStore';
import { AppListItemType } from '@fastgpt/global/core/app/type';
import { useI18n } from '@/web/context/I18n';
import MyMenu from '@fastgpt/web/components/common/MyMenu';
-import SelectOneResource from '@/components/common/folder/SelectOneResource';
-import {
- GetResourceFolderListProps,
- GetResourceListItemResponse
-} from '@fastgpt/global/common/parentFolder/type';
-import { getMyApps } from '@/web/core/app/api';
-import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { useContextSelector } from 'use-context-selector';
import { ChatContext } from '@/web/core/chat/context/chatContext';
import MyBox from '@fastgpt/web/components/common/MyBox';
-import { useSystem } from '@fastgpt/web/hooks/useSystem';
type HistoryItemType = {
id: string;
@@ -32,12 +23,6 @@ type HistoryItemType = {
top?: boolean;
};
-enum TabEnum {
- recently = 'recently',
- 'app' = 'app',
- 'history' = 'history'
-}
-
const ChatHistorySlider = ({
appId,
appName,
@@ -69,12 +54,9 @@ const ChatHistorySlider = ({
const { isPc } = useSystem();
const { userInfo } = useUserStore();
- const [currentTab, setCurrentTab] = useState(TabEnum.history);
-
const {
histories,
onChangeChatId,
- onChangeAppId,
chatId: activeChatId,
isLoading
} = useContextSelector(ChatContext, (v) => v);
@@ -86,7 +68,10 @@ const ChatHistorySlider = ({
customTitle: item.customTitle,
top: item.top
}));
- const newChat: HistoryItemType = { id: activeChatId, title: t('common:core.chat.New Chat') };
+ const newChat: HistoryItemType = {
+ id: activeChatId,
+ title: t('common:core.chat.New Chat')
+ };
const activeChat = histories.find((item) => item.chatId === activeChatId);
return !activeChat ? [newChat].concat(formatHistories) : formatHistories;
@@ -106,17 +91,6 @@ const ChatHistorySlider = ({
[appId, userInfo?.team.permission.hasWritePer]
);
- const getAppList = useCallback(async ({ parentId }: GetResourceFolderListProps) => {
- return getMyApps({ parentId }).then((res) =>
- res.map((item) => ({
- id: item._id,
- name: item.name,
- avatar: item.avatar,
- isFolder: item.type === AppTypeEnum.folder
- }))
- );
- }, []);
-
return (
+
{!isPc && appId && (
-
- flex={'1 0 0'}
- mr={1}
- inlineStyles={{
- px: 1
- }}
- list={[
- ...(isTeamChat
- ? [{ label: t('common:App'), value: TabEnum.recently }]
- : [
- { label: t('common:core.chat.Recent use'), value: TabEnum.recently },
- { label: t('common:App'), value: TabEnum.app }
- ]),
- { label: t('common:core.chat.History'), value: TabEnum.history }
- ]}
- value={currentTab}
- onChange={setCurrentTab}
- />
+
+
+
+ {t('common:core.chat.History')}
+
+
)}
+ ))}
+ >
{/* exec */}
diff --git a/projects/app/src/pages/chat/index.tsx b/projects/app/src/pages/chat/index.tsx
index 893961113..90e2e5264 100644
--- a/projects/app/src/pages/chat/index.tsx
+++ b/projects/app/src/pages/chat/index.tsx
@@ -226,6 +226,7 @@ const Chat = ({
>
{/* header */}
router.push(`/app/detail?appId=${appId}`)}
diff --git a/projects/app/src/pages/chat/team.tsx b/projects/app/src/pages/chat/team.tsx
index 4d1026ffd..34f8e26b2 100644
--- a/projects/app/src/pages/chat/team.tsx
+++ b/projects/app/src/pages/chat/team.tsx
@@ -230,7 +230,7 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
flexDirection={'column'}
>
{/* header */}
-
+
{/* chat box */}
{chatData.app.type === AppTypeEnum.plugin ? (