V4.8.14 dev (#3234)
* feat: rewrite chat context (#3176) * feat: add app auto execute (#3115) * feat: add app auto execute * auto exec configtion * chatting animation * change icon * fix * fix * fix link * feat: add chat context to all chatbox * perf: loading ui --------- Co-authored-by: heheer <heheer@sealos.io> * app auto exec (#3179) * add chat records loaded state (#3184) * perf: chat store reset storage (#3186) * perf: chat store reset storage * perf: auto exec code * chore: workflow ui (#3175) * chore: workflow ui * fix * change icon color config * change popover to mymenu * 4.8.14 test (#3189) * update doc * fix: token check * perf: icon button * update doc * feat: share page support configuration Whether to allow the original view (#3194) * update doc * perf: fix index (#3206) * perf: i18n * perf: Add service entry (#3226) * 4.8.14 test (#3228) * fix: ai log * fix: text splitter * fix: reference unselect & user form description & simple to advance (#3229) * fix: reference unselect & user form description & simple to advance * change abort position * perf * perf: code (#3232) * perf: code * update doc * fix: create btn permission (#3233) * update doc * fix: refresh chatbox listener * perf: check invalid reference * perf: check invalid reference * update doc * fix: ui props --------- Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
@@ -14,6 +14,8 @@ import { useContextSelector } from 'use-context-selector';
|
||||
import { ChatContext } from '@/web/core/chat/context/chatContext';
|
||||
import MyBox from '@fastgpt/web/components/common/MyBox';
|
||||
import { formatTimeToChatTime } from '@fastgpt/global/common/string/time';
|
||||
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||
import { useChatStore } from '@/web/core/chat/context/useChatStore';
|
||||
|
||||
type HistoryItemType = {
|
||||
id: string;
|
||||
@@ -23,25 +25,7 @@ type HistoryItemType = {
|
||||
updateTime: Date;
|
||||
};
|
||||
|
||||
const ChatHistorySlider = ({
|
||||
appId,
|
||||
appName,
|
||||
appAvatar,
|
||||
confirmClearText,
|
||||
onDelHistory,
|
||||
onClearHistory,
|
||||
onSetHistoryTop,
|
||||
onSetCustomTitle
|
||||
}: {
|
||||
appId?: string;
|
||||
appName: string;
|
||||
appAvatar: string;
|
||||
confirmClearText: string;
|
||||
onDelHistory: (e: { chatId: string }) => void;
|
||||
onClearHistory: () => void;
|
||||
onSetHistoryTop?: (e: { chatId: string; top: boolean }) => void;
|
||||
onSetCustomTitle?: (e: { chatId: string; title: string }) => void;
|
||||
}) => {
|
||||
const ChatHistorySlider = ({ confirmClearText }: { confirmClearText: string }) => {
|
||||
const theme = useTheme();
|
||||
const router = useRouter();
|
||||
const isUserChatPage = router.pathname === '/chat';
|
||||
@@ -51,13 +35,17 @@ const ChatHistorySlider = ({
|
||||
const { isPc } = useSystem();
|
||||
const { userInfo } = useUserStore();
|
||||
|
||||
const {
|
||||
onChangeChatId,
|
||||
chatId: activeChatId,
|
||||
isLoading,
|
||||
ScrollData,
|
||||
histories
|
||||
} = useContextSelector(ChatContext, (v) => v);
|
||||
const { appId, chatId: activeChatId } = useChatStore();
|
||||
const onChangeChatId = useContextSelector(ChatContext, (v) => v.onChangeChatId);
|
||||
const isLoading = useContextSelector(ChatContext, (v) => v.isLoading);
|
||||
const ScrollData = useContextSelector(ChatContext, (v) => v.ScrollData);
|
||||
const histories = useContextSelector(ChatContext, (v) => v.histories);
|
||||
const onDelHistory = useContextSelector(ChatContext, (v) => v.onDelHistory);
|
||||
const onClearHistory = useContextSelector(ChatContext, (v) => v.onClearHistories);
|
||||
const onUpdateHistory = useContextSelector(ChatContext, (v) => v.onUpdateHistory);
|
||||
|
||||
const appName = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app.name);
|
||||
const appAvatar = useContextSelector(ChatItemContext, (v) => v.chatBoxData?.app.avatar);
|
||||
|
||||
const concatHistory = useMemo(() => {
|
||||
const formatHistories: HistoryItemType[] = histories.map((item) => {
|
||||
@@ -169,14 +157,13 @@ const ChatHistorySlider = ({
|
||||
size={'mdSquare'}
|
||||
aria-label={''}
|
||||
borderRadius={'50%'}
|
||||
icon={<MyIcon name={'common/clearLight'} w={'16px'} />}
|
||||
onClick={() =>
|
||||
openConfirm(() => {
|
||||
onClearHistory();
|
||||
})()
|
||||
}
|
||||
>
|
||||
<MyIcon name={'common/clearLight'} w={'16px'} />
|
||||
</IconButton>
|
||||
/>
|
||||
)}
|
||||
</Flex>
|
||||
|
||||
@@ -249,45 +236,38 @@ const ChatHistorySlider = ({
|
||||
menuList={[
|
||||
{
|
||||
children: [
|
||||
...(onSetHistoryTop
|
||||
? [
|
||||
{
|
||||
label: item.top
|
||||
? t('common:core.chat.Unpin')
|
||||
: t('common:core.chat.Pin'),
|
||||
icon: 'core/chat/setTopLight',
|
||||
onClick: () => {
|
||||
onSetHistoryTop({
|
||||
chatId: item.id,
|
||||
top: !item.top
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
...(onSetCustomTitle
|
||||
? [
|
||||
{
|
||||
label: t('common:common.Custom Title'),
|
||||
icon: 'common/customTitleLight',
|
||||
onClick: () => {
|
||||
onOpenModal({
|
||||
defaultVal: item.customTitle || item.title,
|
||||
onSuccess: (e) =>
|
||||
onSetCustomTitle({
|
||||
chatId: item.id,
|
||||
title: e
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
: []),
|
||||
{
|
||||
label: item.top
|
||||
? t('common:core.chat.Unpin')
|
||||
: t('common:core.chat.Pin'),
|
||||
icon: 'core/chat/setTopLight',
|
||||
onClick: () => {
|
||||
onUpdateHistory({
|
||||
chatId: item.id,
|
||||
top: !item.top
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
label: t('common:common.Custom Title'),
|
||||
icon: 'common/customTitleLight',
|
||||
onClick: () => {
|
||||
onOpenModal({
|
||||
defaultVal: item.customTitle || item.title,
|
||||
onSuccess: (e) =>
|
||||
onUpdateHistory({
|
||||
chatId: item.id,
|
||||
customTitle: e
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('common:common.Delete'),
|
||||
icon: 'delete',
|
||||
onClick: () => {
|
||||
onDelHistory({ chatId: item.id });
|
||||
onDelHistory(item.id);
|
||||
if (item.id === activeChatId) {
|
||||
onChangeChatId();
|
||||
}
|
||||
|
||||
@@ -6,12 +6,16 @@ import { Box, Grid, Stack } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { PluginRunBoxTabEnum } from '@/components/core/chat/ChatContainer/PluginRunBox/constants';
|
||||
import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
|
||||
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
|
||||
const CustomPluginRunBox = (props: PluginRunBoxProps) => {
|
||||
const { tab, setTab } = props;
|
||||
const { isPc } = useSystem();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const tab = useContextSelector(ChatItemContext, (v) => v.pluginRunTab);
|
||||
const setTab = useContextSelector(ChatItemContext, (v) => v.setPluginRunTab);
|
||||
|
||||
useEffect(() => {
|
||||
if (isPc && tab === PluginRunBoxTabEnum.input) {
|
||||
setTab(PluginRunBoxTabEnum.output);
|
||||
@@ -24,7 +28,7 @@ const CustomPluginRunBox = (props: PluginRunBoxProps) => {
|
||||
<Box color={'myGray.900'} mb={5}>
|
||||
{t('common:common.Input')}
|
||||
</Box>
|
||||
<PluginRunBox {...props} tab={PluginRunBoxTabEnum.input} />
|
||||
<PluginRunBox {...props} showTab={PluginRunBoxTabEnum.input} />
|
||||
</Box>
|
||||
<Stack px={3} py={4} h={'100%'} alignItems={'flex-start'} w={'100%'} overflow={'auto'}>
|
||||
<Box display={'inline-block'}>
|
||||
|
||||
@@ -41,7 +41,6 @@ const SliderApps = ({ apps, activeAppId }: { apps: AppListItemType[]; activeAppI
|
||||
router.replace({
|
||||
query: {
|
||||
...router.query,
|
||||
chatId: '',
|
||||
appId
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import NextHead from '@/components/common/NextHead';
|
||||
import { useRouter } from 'next/router';
|
||||
import { delChatRecordById, getInitChatInfo } from '@/web/core/chat/api';
|
||||
import { getInitChatInfo } from '@/web/core/chat/api';
|
||||
import { Box, Flex, Drawer, DrawerOverlay, DrawerContent, useTheme } from '@chakra-ui/react';
|
||||
import { streamFetch } from '@/web/common/api/fetch';
|
||||
import { useChatStore } from '@/web/core/chat/context/storeChat';
|
||||
import { useChatStore } from '@/web/core/chat/context/useChatStore';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
|
||||
@@ -21,103 +21,75 @@ import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
|
||||
import { getMyApps } from '@/web/core/app/api';
|
||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
|
||||
import { useCreation, useMount } from 'ahooks';
|
||||
import { useMount } from 'ahooks';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
|
||||
import { defaultChatData, GetChatTypeEnum } from '@/global/core/chat/constants';
|
||||
import ChatContextProvider, { ChatContext } from '@/web/core/chat/context/chatContext';
|
||||
import { AppListItemType } from '@fastgpt/global/core/app/type';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useChat } from '@/components/core/chat/ChatContainer/useChat';
|
||||
import ChatBox from '@/components/core/chat/ChatContainer/ChatBox';
|
||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||
import { InitChatResponse } from '@/global/core/chat/api';
|
||||
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
|
||||
import ChatItemContextProvider, { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||
import ChatRecordContextProvider, {
|
||||
ChatRecordContext
|
||||
} from '@/web/core/chat/context/chatRecordContext';
|
||||
import { InitChatResponse } from '@/global/core/chat/api';
|
||||
|
||||
const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox'));
|
||||
|
||||
type Props = { appId: string; chatId: string };
|
||||
|
||||
const Chat = ({
|
||||
appId,
|
||||
chatId,
|
||||
myApps
|
||||
}: Props & {
|
||||
myApps: AppListItemType[];
|
||||
}) => {
|
||||
const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
||||
const router = useRouter();
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation();
|
||||
const { userInfo } = useUserStore();
|
||||
const { isPc } = useSystem();
|
||||
const { setLastChatAppId } = useChatStore();
|
||||
const { userInfo } = useUserStore();
|
||||
const { setLastChatAppId, chatId, appId, outLinkAuthData } = useChatStore();
|
||||
|
||||
const {
|
||||
onUpdateHistory,
|
||||
onClearHistories,
|
||||
onDelHistory,
|
||||
isOpenSlider,
|
||||
onCloseSlider,
|
||||
forbidLoadChat,
|
||||
onChangeChatId,
|
||||
onUpdateHistoryTitle
|
||||
} = useContextSelector(ChatContext, (v) => v);
|
||||
const isOpenSlider = useContextSelector(ChatContext, (v) => v.isOpenSlider);
|
||||
const onCloseSlider = useContextSelector(ChatContext, (v) => v.onCloseSlider);
|
||||
const forbidLoadChat = useContextSelector(ChatContext, (v) => v.forbidLoadChat);
|
||||
const onChangeChatId = useContextSelector(ChatContext, (v) => v.onChangeChatId);
|
||||
const onUpdateHistoryTitle = useContextSelector(ChatContext, (v) => v.onUpdateHistoryTitle);
|
||||
|
||||
const params = useCreation(() => {
|
||||
return {
|
||||
chatId,
|
||||
appId,
|
||||
type: GetChatTypeEnum.normal
|
||||
};
|
||||
}, [appId, chatId]);
|
||||
const {
|
||||
ChatBoxRef,
|
||||
variablesForm,
|
||||
pluginRunTab,
|
||||
setPluginRunTab,
|
||||
resetVariables,
|
||||
chatRecords,
|
||||
ScrollData,
|
||||
setChatRecords,
|
||||
totalRecordsCount
|
||||
} = useChat(params);
|
||||
const resetVariables = useContextSelector(ChatItemContext, (v) => v.resetVariables);
|
||||
const isPlugin = useContextSelector(ChatItemContext, (v) => v.isPlugin);
|
||||
const setChatBoxData = useContextSelector(ChatItemContext, (v) => v.setChatBoxData);
|
||||
|
||||
// get chat app info
|
||||
const [chatData, setChatData] = useState<InitChatResponse>(defaultChatData);
|
||||
const isPlugin = chatData.app.type === AppTypeEnum.plugin;
|
||||
const chatRecords = useContextSelector(ChatRecordContext, (v) => v.chatRecords);
|
||||
const totalRecordsCount = useContextSelector(ChatRecordContext, (v) => v.totalRecordsCount);
|
||||
|
||||
// Load chat init data
|
||||
const [chatData, setChatData] = useState<InitChatResponse>(defaultChatData);
|
||||
const { loading: isLoading } = useRequest2(
|
||||
async () => {
|
||||
if (!appId || forbidLoadChat.current) return;
|
||||
|
||||
const res = await getInitChatInfo({ appId, chatId });
|
||||
res.userAvatar = userInfo?.avatar;
|
||||
|
||||
setChatData(res);
|
||||
setChatBoxData(res);
|
||||
// reset chat variables
|
||||
resetVariables({
|
||||
variables: res.variables
|
||||
});
|
||||
|
||||
setLastChatAppId(appId);
|
||||
},
|
||||
{
|
||||
manual: false,
|
||||
refreshDeps: [appId, chatId],
|
||||
onError(e: any) {
|
||||
setLastChatAppId('');
|
||||
|
||||
// reset all chat tore
|
||||
if (e?.code === 501) {
|
||||
setLastChatAppId('');
|
||||
router.replace('/app/list');
|
||||
} else {
|
||||
router.replace({
|
||||
query: {
|
||||
...router.query,
|
||||
appId: myApps[0]?._id,
|
||||
chatId: ''
|
||||
appId: myApps[0]?._id
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -136,7 +108,6 @@ const Chat = ({
|
||||
generatingMessage,
|
||||
variables
|
||||
}: StartChatFnProps) => {
|
||||
const completionChatId = chatId || getNanoid();
|
||||
// Just send a user prompt
|
||||
const histories = messages.slice(-1);
|
||||
const { responseText, responseData } = await streamFetch({
|
||||
@@ -145,7 +116,7 @@ const Chat = ({
|
||||
variables,
|
||||
responseChatItemId,
|
||||
appId,
|
||||
chatId: completionChatId
|
||||
chatId
|
||||
},
|
||||
onMessage: generatingMessage,
|
||||
abortCtrl: controller
|
||||
@@ -154,10 +125,7 @@ const Chat = ({
|
||||
const newTitle = getChatTitleFromChatMessage(GPTMessages2Chats(histories)[0]);
|
||||
|
||||
// new chat
|
||||
if (completionChatId !== chatId && controller.signal.reason !== 'leave') {
|
||||
onChangeChatId(completionChatId, true);
|
||||
}
|
||||
onUpdateHistoryTitle({ chatId: completionChatId, newTitle });
|
||||
onUpdateHistoryTitle({ chatId, newTitle });
|
||||
// update chat window
|
||||
setChatData((state) => ({
|
||||
...state,
|
||||
@@ -166,32 +134,13 @@ const Chat = ({
|
||||
|
||||
return { responseText, responseData, isNewChat: forbidLoadChat.current };
|
||||
},
|
||||
[chatId, appId, onUpdateHistoryTitle, forbidLoadChat, onChangeChatId]
|
||||
[chatId, appId, onUpdateHistoryTitle, forbidLoadChat]
|
||||
);
|
||||
const loading = isLoading;
|
||||
|
||||
const RenderHistorySlider = useMemo(() => {
|
||||
const Children = (
|
||||
<ChatHistorySlider
|
||||
confirmClearText={t('common:core.chat.Confirm to clear history')}
|
||||
appId={appId}
|
||||
appName={chatData.app.name}
|
||||
appAvatar={chatData.app.avatar}
|
||||
onDelHistory={(e) => onDelHistory({ ...e, appId })}
|
||||
onClearHistory={() => {
|
||||
onClearHistories({ appId });
|
||||
}}
|
||||
onSetHistoryTop={(e) => {
|
||||
onUpdateHistory({ ...e, appId });
|
||||
}}
|
||||
onSetCustomTitle={async (e) => {
|
||||
onUpdateHistory({
|
||||
appId,
|
||||
chatId: e.chatId,
|
||||
customTitle: e.title
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<ChatHistorySlider confirmClearText={t('common:core.chat.Confirm to clear history')} />
|
||||
);
|
||||
|
||||
return isPc || !appId ? (
|
||||
@@ -208,18 +157,7 @@ const Chat = ({
|
||||
<DrawerContent maxWidth={'75vw'}>{Children}</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}, [
|
||||
appId,
|
||||
chatData.app.avatar,
|
||||
chatData.app.name,
|
||||
isOpenSlider,
|
||||
isPc,
|
||||
onClearHistories,
|
||||
onCloseSlider,
|
||||
onDelHistory,
|
||||
onUpdateHistory,
|
||||
t
|
||||
]);
|
||||
}, [appId, isOpenSlider, isPc, onCloseSlider, t]);
|
||||
|
||||
return (
|
||||
<Flex h={'100%'}>
|
||||
@@ -257,33 +195,20 @@ const Chat = ({
|
||||
<Box flex={'1 0 0'} bg={'white'}>
|
||||
{isPlugin ? (
|
||||
<CustomPluginRunBox
|
||||
pluginInputs={chatData.app.pluginInputs}
|
||||
variablesForm={variablesForm}
|
||||
histories={chatRecords}
|
||||
setHistories={setChatRecords}
|
||||
appId={chatData.appId}
|
||||
chatConfig={chatData.app.chatConfig}
|
||||
tab={pluginRunTab}
|
||||
setTab={setPluginRunTab}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
outLinkAuthData={outLinkAuthData}
|
||||
onNewChat={() => onChangeChatId(getNanoid())}
|
||||
onStartChat={onStartChat}
|
||||
/>
|
||||
) : (
|
||||
<ChatBox
|
||||
ScrollData={ScrollData}
|
||||
ref={ChatBoxRef}
|
||||
chatHistories={chatRecords}
|
||||
setChatHistories={setChatRecords}
|
||||
variablesForm={variablesForm}
|
||||
showEmptyIntro
|
||||
appAvatar={chatData.app.avatar}
|
||||
userAvatar={userInfo?.avatar}
|
||||
chatConfig={chatData.app?.chatConfig}
|
||||
feedbackType={'user'}
|
||||
onStartChat={onStartChat}
|
||||
onDelMessage={({ contentId }) => delChatRecordById({ contentId, appId, chatId })}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
outLinkAuthData={outLinkAuthData}
|
||||
showEmptyIntro
|
||||
feedbackType={'user'}
|
||||
onStartChat={onStartChat}
|
||||
chatType={'chat'}
|
||||
showRawSource
|
||||
showNodeStatus
|
||||
@@ -297,13 +222,12 @@ const Chat = ({
|
||||
);
|
||||
};
|
||||
|
||||
const Render = (props: Props) => {
|
||||
const Render = (props: { appId: string }) => {
|
||||
const { appId } = props;
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
|
||||
const { lastChatAppId, lastChatId } = useChatStore();
|
||||
const { source, chatId, lastChatAppId, setSource, setAppId } = useChatStore();
|
||||
|
||||
const { data: myApps = [], runAsync: loadMyApps } = useRequest2(
|
||||
() => getMyApps({ getRecentlyChat: true }),
|
||||
@@ -316,16 +240,6 @@ const Render = (props: Props) => {
|
||||
useMount(async () => {
|
||||
// pc: redirect to latest model chat
|
||||
if (!appId) {
|
||||
if (lastChatAppId) {
|
||||
return router.replace({
|
||||
query: {
|
||||
...router.query,
|
||||
appId: lastChatAppId,
|
||||
chatId: lastChatId
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const apps = await loadMyApps();
|
||||
if (apps.length === 0) {
|
||||
toast({
|
||||
@@ -337,27 +251,45 @@ const Render = (props: Props) => {
|
||||
router.replace({
|
||||
query: {
|
||||
...router.query,
|
||||
appId: apps[0]._id,
|
||||
chatId: ''
|
||||
appId: lastChatAppId || apps[0]._id
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
setSource('online');
|
||||
});
|
||||
// Watch appId
|
||||
useEffect(() => {
|
||||
setAppId(appId);
|
||||
}, [appId, setAppId]);
|
||||
|
||||
const providerParams = useMemo(() => ({ appId, source: ChatSourceEnum.online }), [appId]);
|
||||
return (
|
||||
<ChatContextProvider params={providerParams}>
|
||||
<Chat {...props} myApps={myApps} />
|
||||
</ChatContextProvider>
|
||||
const chatHistoryProviderParams = useMemo(
|
||||
() => ({ appId, source: ChatSourceEnum.online }),
|
||||
[appId]
|
||||
);
|
||||
const chatRecordProviderParams = useMemo(() => {
|
||||
return {
|
||||
appId,
|
||||
type: GetChatTypeEnum.normal,
|
||||
chatId: chatId
|
||||
};
|
||||
}, [appId, chatId]);
|
||||
|
||||
return source === ChatSourceEnum.online ? (
|
||||
<ChatContextProvider params={chatHistoryProviderParams}>
|
||||
<ChatItemContextProvider>
|
||||
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
||||
<Chat myApps={myApps} />
|
||||
</ChatRecordContextProvider>
|
||||
</ChatItemContextProvider>
|
||||
</ChatContextProvider>
|
||||
) : null;
|
||||
};
|
||||
|
||||
export async function getServerSideProps(context: any) {
|
||||
return {
|
||||
props: {
|
||||
appId: context?.query?.appId || '',
|
||||
chatId: context?.query?.chatId || '',
|
||||
...(await serviceSideProps(context, ['file', 'app', 'chat', 'workflow']))
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Box, Flex, Drawer, DrawerOverlay, DrawerContent } from '@chakra-ui/react';
|
||||
import { streamFetch } from '@/web/common/api/fetch';
|
||||
@@ -13,7 +13,7 @@ import ChatHeader from './components/ChatHeader';
|
||||
import ChatHistorySlider from './components/ChatHistorySlider';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { delChatRecordById, getInitOutLinkChatInfo } from '@/web/core/chat/api';
|
||||
import { getInitOutLinkChatInfo } from '@/web/core/chat/api';
|
||||
import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils';
|
||||
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
|
||||
import { OutLinkWithAppType } from '@fastgpt/global/support/outLink/type';
|
||||
@@ -26,16 +26,21 @@ import { InitChatResponse } from '@/global/core/chat/api';
|
||||
import { defaultChatData, GetChatTypeEnum } from '@/global/core/chat/constants';
|
||||
import { useMount } from 'ahooks';
|
||||
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import { useChat } from '@/components/core/chat/ChatContainer/useChat';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||
import { useShareChatStore } from '@/web/core/chat/storeShareChat';
|
||||
import ChatItemContextProvider, { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||
import ChatRecordContextProvider, {
|
||||
ChatRecordContext
|
||||
} from '@/web/core/chat/context/chatRecordContext';
|
||||
import { useChatStore } from '@/web/core/chat/context/useChatStore';
|
||||
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
|
||||
const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox'));
|
||||
|
||||
type Props = {
|
||||
appId: string;
|
||||
appName: string;
|
||||
appIntro: string;
|
||||
appAvatar: string;
|
||||
@@ -46,17 +51,12 @@ type Props = {
|
||||
showNodeStatus: boolean;
|
||||
};
|
||||
|
||||
const OutLink = (
|
||||
props: Props & {
|
||||
outLinkUid: string;
|
||||
}
|
||||
) => {
|
||||
const OutLink = (props: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const { outLinkUid, showRawSource, showNodeStatus } = props;
|
||||
const { showRawSource, showNodeStatus } = props;
|
||||
const {
|
||||
shareId = '',
|
||||
chatId = '',
|
||||
showHistory = '1',
|
||||
showHead = '1',
|
||||
authToken,
|
||||
@@ -64,49 +64,69 @@ const OutLink = (
|
||||
...customVariables
|
||||
} = router.query as {
|
||||
shareId: string;
|
||||
chatId: string;
|
||||
showHistory: '0' | '1';
|
||||
showHead: '0' | '1';
|
||||
authToken: string;
|
||||
[key: string]: string;
|
||||
};
|
||||
const { isPc } = useSystem();
|
||||
const { outLinkAuthData, appId, chatId } = useChatStore();
|
||||
|
||||
const isOpenSlider = useContextSelector(ChatContext, (v) => v.isOpenSlider);
|
||||
const onCloseSlider = useContextSelector(ChatContext, (v) => v.onCloseSlider);
|
||||
const forbidLoadChat = useContextSelector(ChatContext, (v) => v.forbidLoadChat);
|
||||
const onChangeChatId = useContextSelector(ChatContext, (v) => v.onChangeChatId);
|
||||
const onUpdateHistoryTitle = useContextSelector(ChatContext, (v) => v.onUpdateHistoryTitle);
|
||||
|
||||
const resetVariables = useContextSelector(ChatItemContext, (v) => v.resetVariables);
|
||||
const isPlugin = useContextSelector(ChatItemContext, (v) => v.isPlugin);
|
||||
const setChatBoxData = useContextSelector(ChatItemContext, (v) => v.setChatBoxData);
|
||||
|
||||
const chatRecords = useContextSelector(ChatRecordContext, (v) => v.chatRecords);
|
||||
const totalRecordsCount = useContextSelector(ChatRecordContext, (v) => v.totalRecordsCount);
|
||||
|
||||
const initSign = useRef(false);
|
||||
const [isEmbed, setIdEmbed] = useState(true);
|
||||
|
||||
const [chatData, setChatData] = useState<InitChatResponse>(defaultChatData);
|
||||
const { loading: isLoading } = useRequest2(
|
||||
async () => {
|
||||
const shareId = outLinkAuthData.shareId;
|
||||
const outLinkUid = outLinkAuthData.outLinkUid;
|
||||
if (!outLinkUid || !shareId || forbidLoadChat.current) return;
|
||||
|
||||
const {
|
||||
onUpdateHistoryTitle,
|
||||
onUpdateHistory,
|
||||
onClearHistories,
|
||||
onDelHistory,
|
||||
isOpenSlider,
|
||||
onCloseSlider,
|
||||
forbidLoadChat,
|
||||
onChangeChatId
|
||||
} = useContextSelector(ChatContext, (v) => v);
|
||||
const res = await getInitOutLinkChatInfo({
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid
|
||||
});
|
||||
|
||||
const params = useMemo(() => {
|
||||
return {
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid,
|
||||
appId: chatData.appId,
|
||||
type: GetChatTypeEnum.outLink
|
||||
};
|
||||
}, [chatData.appId, chatId, outLinkUid, shareId]);
|
||||
const {
|
||||
ChatBoxRef,
|
||||
variablesForm,
|
||||
pluginRunTab,
|
||||
setPluginRunTab,
|
||||
resetVariables,
|
||||
chatRecords,
|
||||
ScrollData,
|
||||
setChatRecords,
|
||||
totalRecordsCount
|
||||
} = useChat(params);
|
||||
setChatData(res);
|
||||
setChatBoxData(res);
|
||||
resetVariables({
|
||||
variables: res.variables
|
||||
});
|
||||
},
|
||||
{
|
||||
manual: false,
|
||||
refreshDeps: [shareId, outLinkAuthData, chatId],
|
||||
onSuccess() {
|
||||
// send init message
|
||||
if (!initSign.current) {
|
||||
initSign.current = true;
|
||||
if (window !== top) {
|
||||
window.top?.postMessage({ type: 'shareChatReady' }, '*');
|
||||
}
|
||||
}
|
||||
},
|
||||
onError(e: any) {
|
||||
if (chatId) {
|
||||
onChangeChatId('');
|
||||
}
|
||||
},
|
||||
onFinally() {
|
||||
forbidLoadChat.current = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const startChat = useCallback(
|
||||
async ({
|
||||
@@ -138,10 +158,8 @@ const OutLink = (
|
||||
...customVariables
|
||||
},
|
||||
responseChatItemId,
|
||||
shareId,
|
||||
chatId: completionChatId,
|
||||
appType: chatData.app.type,
|
||||
outLinkUid
|
||||
...outLinkAuthData
|
||||
},
|
||||
onMessage: generatingMessage,
|
||||
abortCtrl: controller
|
||||
@@ -175,57 +193,11 @@ const OutLink = (
|
||||
|
||||
return { responseText, responseData, isNewChat: forbidLoadChat.current };
|
||||
},
|
||||
[
|
||||
chatId,
|
||||
customVariables,
|
||||
shareId,
|
||||
chatData.app.type,
|
||||
outLinkUid,
|
||||
onUpdateHistoryTitle,
|
||||
forbidLoadChat,
|
||||
onChangeChatId
|
||||
]
|
||||
);
|
||||
|
||||
const { loading: isLoading } = useRequest2(
|
||||
async () => {
|
||||
if (!shareId || !outLinkUid || forbidLoadChat.current) return;
|
||||
|
||||
const res = await getInitOutLinkChatInfo({
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid
|
||||
});
|
||||
setChatData(res);
|
||||
|
||||
resetVariables({
|
||||
variables: res.variables
|
||||
});
|
||||
},
|
||||
{
|
||||
manual: false,
|
||||
refreshDeps: [shareId, outLinkUid, chatId],
|
||||
onSuccess() {
|
||||
// send init message
|
||||
if (!initSign.current) {
|
||||
initSign.current = true;
|
||||
if (window !== top) {
|
||||
window.top?.postMessage({ type: 'shareChatReady' }, '*');
|
||||
}
|
||||
}
|
||||
},
|
||||
onError(e: any) {
|
||||
if (chatId) {
|
||||
onChangeChatId('');
|
||||
}
|
||||
},
|
||||
onFinally() {
|
||||
forbidLoadChat.current = false;
|
||||
}
|
||||
}
|
||||
[chatId, customVariables, outLinkAuthData, onUpdateHistoryTitle, forbidLoadChat, onChangeChatId]
|
||||
);
|
||||
|
||||
// window init
|
||||
const [isEmbed, setIdEmbed] = useState(true);
|
||||
useMount(() => {
|
||||
setIdEmbed(window !== top);
|
||||
});
|
||||
@@ -233,32 +205,7 @@ const OutLink = (
|
||||
const RenderHistoryList = useMemo(() => {
|
||||
const Children = (
|
||||
<ChatHistorySlider
|
||||
appName={chatData.app.name}
|
||||
appAvatar={chatData.app.avatar}
|
||||
confirmClearText={t('common:core.chat.Confirm to clear share chat history')}
|
||||
onDelHistory={({ chatId }) =>
|
||||
onDelHistory({ appId: chatData.appId, chatId, shareId, outLinkUid })
|
||||
}
|
||||
onClearHistory={() => {
|
||||
onClearHistories({ shareId, outLinkUid });
|
||||
}}
|
||||
onSetHistoryTop={(e) => {
|
||||
onUpdateHistory({
|
||||
...e,
|
||||
appId: chatData.appId,
|
||||
shareId,
|
||||
outLinkUid
|
||||
});
|
||||
}}
|
||||
onSetCustomTitle={(e) => {
|
||||
onUpdateHistory({
|
||||
appId: chatData.appId,
|
||||
chatId: e.chatId,
|
||||
customTitle: e.title,
|
||||
shareId,
|
||||
outLinkUid
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -280,21 +227,7 @@ const OutLink = (
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}, [
|
||||
chatData.app.avatar,
|
||||
chatData.app.name,
|
||||
chatData.appId,
|
||||
isOpenSlider,
|
||||
isPc,
|
||||
onClearHistories,
|
||||
onCloseSlider,
|
||||
onDelHistory,
|
||||
onUpdateHistory,
|
||||
outLinkUid,
|
||||
shareId,
|
||||
showHistory,
|
||||
t
|
||||
]);
|
||||
}, [isOpenSlider, isPc, onCloseSlider, showHistory, t]);
|
||||
|
||||
const loading = isLoading;
|
||||
|
||||
@@ -329,43 +262,21 @@ const OutLink = (
|
||||
) : null}
|
||||
{/* chat box */}
|
||||
<Box flex={1} bg={'white'}>
|
||||
{chatData.app.type === AppTypeEnum.plugin ? (
|
||||
{isPlugin ? (
|
||||
<CustomPluginRunBox
|
||||
pluginInputs={chatData.app.pluginInputs}
|
||||
variablesForm={variablesForm}
|
||||
histories={chatRecords}
|
||||
setHistories={setChatRecords}
|
||||
appId={chatData.appId}
|
||||
tab={pluginRunTab}
|
||||
setTab={setPluginRunTab}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
outLinkAuthData={outLinkAuthData}
|
||||
onNewChat={() => onChangeChatId(getNanoid())}
|
||||
onStartChat={startChat}
|
||||
/>
|
||||
) : (
|
||||
<ChatBox
|
||||
ScrollData={ScrollData}
|
||||
ref={ChatBoxRef}
|
||||
chatHistories={chatRecords}
|
||||
setChatHistories={setChatRecords}
|
||||
variablesForm={variablesForm}
|
||||
appAvatar={chatData.app.avatar}
|
||||
userAvatar={chatData.userAvatar}
|
||||
chatConfig={chatData.app?.chatConfig}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
outLinkAuthData={outLinkAuthData}
|
||||
feedbackType={'user'}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={({ contentId }) =>
|
||||
delChatRecordById({
|
||||
contentId,
|
||||
appId: chatData.appId,
|
||||
chatId,
|
||||
shareId,
|
||||
outLinkUid
|
||||
})
|
||||
}
|
||||
appId={chatData.appId}
|
||||
chatId={chatId}
|
||||
shareId={shareId}
|
||||
outLinkUid={outLinkUid}
|
||||
chatType="share"
|
||||
showRawSource={showRawSource}
|
||||
showNodeStatus={showNodeStatus}
|
||||
@@ -380,29 +291,57 @@ const OutLink = (
|
||||
};
|
||||
|
||||
const Render = (props: Props) => {
|
||||
const { shareId, authToken, customUid } = props;
|
||||
const { shareId, authToken, customUid, appId } = props;
|
||||
const { localUId, loaded } = useShareChatStore();
|
||||
const { source, chatId, setSource, setAppId, setOutLinkAuthData } = useChatStore();
|
||||
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
|
||||
const contextParams = useMemo(() => {
|
||||
const chatHistoryProviderParams = useMemo(() => {
|
||||
return { shareId, outLinkUid: authToken || customUid || localUId };
|
||||
}, [authToken, customUid, localUId, shareId]);
|
||||
const chatRecordProviderParams = useMemo(() => {
|
||||
return {
|
||||
appId,
|
||||
shareId,
|
||||
outLinkUid: chatHistoryProviderParams.outLinkUid,
|
||||
chatId,
|
||||
type: GetChatTypeEnum.outLink
|
||||
};
|
||||
}, [appId, chatHistoryProviderParams.outLinkUid, chatId, shareId]);
|
||||
|
||||
useMount(() => {
|
||||
setIsLoaded(true);
|
||||
});
|
||||
const systemLoaded = isLoaded && loaded && contextParams.outLinkUid;
|
||||
|
||||
return (
|
||||
<>
|
||||
{systemLoaded ? (
|
||||
<ChatContextProvider params={contextParams}>
|
||||
<OutLink {...props} outLinkUid={contextParams.outLinkUid} />;
|
||||
</ChatContextProvider>
|
||||
) : (
|
||||
<NextHead title="Loading..." />
|
||||
)}
|
||||
</>
|
||||
setSource('share');
|
||||
});
|
||||
const systemLoaded = isLoaded && loaded && chatHistoryProviderParams.outLinkUid;
|
||||
|
||||
// Set outLinkAuthData
|
||||
useEffect(() => {
|
||||
setOutLinkAuthData({
|
||||
shareId,
|
||||
outLinkUid: chatHistoryProviderParams.outLinkUid
|
||||
});
|
||||
return () => {
|
||||
setOutLinkAuthData({});
|
||||
};
|
||||
}, [chatHistoryProviderParams.outLinkUid, setOutLinkAuthData, shareId]);
|
||||
// Watch appId
|
||||
useEffect(() => {
|
||||
setAppId(appId);
|
||||
}, [appId, setAppId]);
|
||||
|
||||
return source === ChatSourceEnum.share ? (
|
||||
<ChatContextProvider params={chatHistoryProviderParams}>
|
||||
<ChatItemContextProvider>
|
||||
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
||||
<OutLink {...props} />
|
||||
</ChatRecordContextProvider>
|
||||
</ChatItemContextProvider>
|
||||
</ChatContextProvider>
|
||||
) : (
|
||||
<NextHead title={props.appName} desc={props.appIntro} icon={props.appAvatar} />
|
||||
);
|
||||
};
|
||||
|
||||
@@ -433,6 +372,7 @@ export async function getServerSideProps(context: any) {
|
||||
|
||||
return {
|
||||
props: {
|
||||
appId: String(app?.appId?._id) ?? '',
|
||||
appName: app?.appId?.name ?? 'AI',
|
||||
appAvatar: app?.appId?.avatar ?? '',
|
||||
appIntro: app?.appId?.intro ?? 'AI',
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import NextHead from '@/components/common/NextHead';
|
||||
import { delChatRecordById, getTeamChatInfo } from '@/web/core/chat/api';
|
||||
import { getTeamChatInfo } from '@/web/core/chat/api';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Box, Flex, Drawer, DrawerOverlay, DrawerContent, useTheme } from '@chakra-ui/react';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import SideBar from '@/components/SideBar';
|
||||
import PageContainer from '@/components/PageContainer';
|
||||
import { getMyTokensApps } from '@/web/core/chat/api';
|
||||
@@ -25,10 +24,16 @@ import { InitChatResponse } from '@/global/core/chat/api';
|
||||
import { defaultChatData, GetChatTypeEnum } from '@/global/core/chat/constants';
|
||||
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
import { useChat } from '@/components/core/chat/ChatContainer/useChat';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useSystem } from '@fastgpt/web/hooks/useSystem';
|
||||
import ChatItemContextProvider, { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
|
||||
import ChatRecordContextProvider, {
|
||||
ChatRecordContext
|
||||
} from '@/web/core/chat/context/chatRecordContext';
|
||||
import { useChatStore } from '@/web/core/chat/context/useChatStore';
|
||||
import { useMount } from 'ahooks';
|
||||
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
|
||||
const CustomPluginRunBox = dynamic(() => import('./components/CustomPluginRunBox'));
|
||||
|
||||
type Props = { appId: string; chatId: string; teamId: string; teamToken: string };
|
||||
@@ -38,51 +43,59 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
||||
const router = useRouter();
|
||||
const {
|
||||
teamId = '',
|
||||
appId = '',
|
||||
chatId = '',
|
||||
appId: appIdQuery = '',
|
||||
teamToken,
|
||||
...customVariables
|
||||
} = router.query as Props & {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
const { toast } = useToast();
|
||||
const theme = useTheme();
|
||||
const { isPc } = useSystem();
|
||||
|
||||
const { outLinkAuthData, appId, chatId } = useChatStore();
|
||||
|
||||
const isOpenSlider = useContextSelector(ChatContext, (v) => v.isOpenSlider);
|
||||
const onCloseSlider = useContextSelector(ChatContext, (v) => v.onCloseSlider);
|
||||
const forbidLoadChat = useContextSelector(ChatContext, (v) => v.forbidLoadChat);
|
||||
const onChangeChatId = useContextSelector(ChatContext, (v) => v.onChangeChatId);
|
||||
const onUpdateHistoryTitle = useContextSelector(ChatContext, (v) => v.onUpdateHistoryTitle);
|
||||
|
||||
const resetVariables = useContextSelector(ChatItemContext, (v) => v.resetVariables);
|
||||
const setChatBoxData = useContextSelector(ChatItemContext, (v) => v.setChatBoxData);
|
||||
|
||||
const chatRecords = useContextSelector(ChatRecordContext, (v) => v.chatRecords);
|
||||
const totalRecordsCount = useContextSelector(ChatRecordContext, (v) => v.totalRecordsCount);
|
||||
|
||||
// get chat app info
|
||||
const [chatData, setChatData] = useState<InitChatResponse>(defaultChatData);
|
||||
const { loading: isLoading } = useRequest2(
|
||||
async () => {
|
||||
if (!appId || forbidLoadChat.current) return;
|
||||
|
||||
const {
|
||||
onUpdateHistoryTitle,
|
||||
onUpdateHistory,
|
||||
onClearHistories,
|
||||
onDelHistory,
|
||||
isOpenSlider,
|
||||
onCloseSlider,
|
||||
forbidLoadChat,
|
||||
onChangeChatId
|
||||
} = useContextSelector(ChatContext, (v) => v);
|
||||
const res = await getTeamChatInfo({ teamId, appId, chatId, teamToken });
|
||||
|
||||
const params = useMemo(() => {
|
||||
return {
|
||||
appId,
|
||||
chatId,
|
||||
teamId,
|
||||
teamToken,
|
||||
type: GetChatTypeEnum.team
|
||||
};
|
||||
}, [appId, chatId, teamId, teamToken]);
|
||||
const {
|
||||
ChatBoxRef,
|
||||
variablesForm,
|
||||
pluginRunTab,
|
||||
setPluginRunTab,
|
||||
resetVariables,
|
||||
chatRecords,
|
||||
ScrollData,
|
||||
setChatRecords,
|
||||
totalRecordsCount
|
||||
} = useChat(params);
|
||||
setChatData(res);
|
||||
setChatBoxData(res);
|
||||
// reset chat records
|
||||
resetVariables({
|
||||
variables: res.variables
|
||||
});
|
||||
},
|
||||
{
|
||||
manual: false,
|
||||
refreshDeps: [teamId, teamToken, appId, chatId],
|
||||
onError(e: any) {
|
||||
console.log(e);
|
||||
if (chatId) {
|
||||
onChangeChatId();
|
||||
}
|
||||
},
|
||||
onFinally() {
|
||||
forbidLoadChat.current = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const startChat = useCallback(
|
||||
async ({
|
||||
@@ -143,58 +156,9 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
||||
]
|
||||
);
|
||||
|
||||
// get chat app info
|
||||
const { loading: isLoading } = useRequest2(
|
||||
async () => {
|
||||
if (!appId || forbidLoadChat.current) return;
|
||||
|
||||
const res = await getTeamChatInfo({ teamId, appId, chatId, teamToken });
|
||||
setChatData(res);
|
||||
|
||||
// reset chat records
|
||||
resetVariables({
|
||||
variables: res.variables
|
||||
});
|
||||
},
|
||||
{
|
||||
manual: false,
|
||||
refreshDeps: [teamId, teamToken, appId, chatId],
|
||||
onError(e: any) {
|
||||
console.log(e);
|
||||
if (chatId) {
|
||||
onChangeChatId('');
|
||||
}
|
||||
},
|
||||
onFinally() {
|
||||
forbidLoadChat.current = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const RenderHistoryList = useMemo(() => {
|
||||
const Children = (
|
||||
<ChatHistorySlider
|
||||
appId={appId}
|
||||
appName={chatData.app.name}
|
||||
appAvatar={chatData.app.avatar}
|
||||
confirmClearText={t('common:core.chat.Confirm to clear history')}
|
||||
onDelHistory={(e) => onDelHistory({ ...e, appId, teamId, teamToken })}
|
||||
onClearHistory={() => {
|
||||
onClearHistories({ appId, teamId, teamToken });
|
||||
}}
|
||||
onSetHistoryTop={(e) => {
|
||||
onUpdateHistory({ ...e, teamId, teamToken, appId });
|
||||
}}
|
||||
onSetCustomTitle={async (e) => {
|
||||
onUpdateHistory({
|
||||
appId,
|
||||
chatId: e.chatId,
|
||||
customTitle: e.title,
|
||||
teamId,
|
||||
teamToken
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<ChatHistorySlider confirmClearText={t('common:core.chat.Confirm to clear history')} />
|
||||
);
|
||||
|
||||
return isPc || !appId ? (
|
||||
@@ -211,20 +175,7 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
||||
<DrawerContent maxWidth={'75vw'}>{Children}</DrawerContent>
|
||||
</Drawer>
|
||||
);
|
||||
}, [
|
||||
appId,
|
||||
chatData.app.avatar,
|
||||
chatData.app.name,
|
||||
isOpenSlider,
|
||||
isPc,
|
||||
onClearHistories,
|
||||
onCloseSlider,
|
||||
onDelHistory,
|
||||
onUpdateHistory,
|
||||
t,
|
||||
teamId,
|
||||
teamToken
|
||||
]);
|
||||
}, [appId, isOpenSlider, isPc, onCloseSlider, t]);
|
||||
|
||||
const loading = isLoading;
|
||||
|
||||
@@ -261,41 +212,19 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
||||
<Box flex={1}>
|
||||
{chatData.app.type === AppTypeEnum.plugin ? (
|
||||
<CustomPluginRunBox
|
||||
pluginInputs={chatData.app.pluginInputs}
|
||||
variablesForm={variablesForm}
|
||||
histories={chatRecords}
|
||||
setHistories={setChatRecords}
|
||||
appId={chatData.appId}
|
||||
tab={pluginRunTab}
|
||||
setTab={setPluginRunTab}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
outLinkAuthData={outLinkAuthData}
|
||||
onNewChat={() => onChangeChatId(getNanoid())}
|
||||
onStartChat={startChat}
|
||||
/>
|
||||
) : (
|
||||
<ChatBox
|
||||
ref={ChatBoxRef}
|
||||
ScrollData={ScrollData}
|
||||
chatHistories={chatRecords}
|
||||
setChatHistories={setChatRecords}
|
||||
variablesForm={variablesForm}
|
||||
appAvatar={chatData.app.avatar}
|
||||
userAvatar={chatData.userAvatar}
|
||||
chatConfig={chatData.app?.chatConfig}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
outLinkAuthData={outLinkAuthData}
|
||||
feedbackType={'user'}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={({ contentId }) =>
|
||||
delChatRecordById({
|
||||
contentId,
|
||||
appId: chatData.appId,
|
||||
chatId,
|
||||
teamId,
|
||||
teamToken
|
||||
})
|
||||
}
|
||||
appId={chatData.appId}
|
||||
chatId={chatId}
|
||||
teamId={teamId}
|
||||
teamToken={teamToken}
|
||||
chatType="team"
|
||||
showRawSource
|
||||
showNodeStatus
|
||||
@@ -311,9 +240,8 @@ const Chat = ({ myApps }: { myApps: AppListItemType[] }) => {
|
||||
|
||||
const Render = (props: Props) => {
|
||||
const { teamId, appId, teamToken } = props;
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const router = useRouter();
|
||||
const { source, chatId, setSource, setAppId, setOutLinkAuthData } = useChatStore();
|
||||
|
||||
const { data: myApps = [], runAsync: loadMyApps } = useRequest2(
|
||||
async () => {
|
||||
@@ -323,34 +251,61 @@ const Render = (props: Props) => {
|
||||
return [];
|
||||
},
|
||||
{
|
||||
manual: false
|
||||
manual: true
|
||||
}
|
||||
);
|
||||
|
||||
// 初始化聊天框
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (appId || myApps.length === 0) return;
|
||||
useMount(async () => {
|
||||
setSource('team');
|
||||
|
||||
router.replace({
|
||||
query: {
|
||||
...router.query,
|
||||
appId: myApps[0]._id,
|
||||
chatId: ''
|
||||
}
|
||||
});
|
||||
})();
|
||||
}, [appId, loadMyApps, myApps, router, t, toast]);
|
||||
const apps = await loadMyApps();
|
||||
|
||||
if (appId || apps.length === 0) return;
|
||||
|
||||
router.replace({
|
||||
query: {
|
||||
...router.query,
|
||||
appId: apps[0]._id
|
||||
}
|
||||
});
|
||||
});
|
||||
// Watch appId
|
||||
useEffect(() => {
|
||||
setAppId(appId);
|
||||
}, [appId, setAppId]);
|
||||
useEffect(() => {
|
||||
setOutLinkAuthData({
|
||||
teamId,
|
||||
teamToken
|
||||
});
|
||||
return () => {
|
||||
setOutLinkAuthData({});
|
||||
};
|
||||
}, [teamId, teamToken, setOutLinkAuthData]);
|
||||
|
||||
const contextParams = useMemo(() => {
|
||||
return { teamId, appId, teamToken };
|
||||
}, [teamId, appId, teamToken]);
|
||||
const chatRecordProviderParams = useMemo(() => {
|
||||
return {
|
||||
appId,
|
||||
chatId,
|
||||
teamId,
|
||||
teamToken,
|
||||
type: GetChatTypeEnum.team
|
||||
};
|
||||
}, [appId, chatId, teamId, teamToken]);
|
||||
|
||||
return (
|
||||
return source === ChatSourceEnum.team ? (
|
||||
<ChatContextProvider params={contextParams}>
|
||||
<Chat {...props} myApps={myApps} />
|
||||
<ChatItemContextProvider>
|
||||
<ChatRecordContextProvider params={chatRecordProviderParams}>
|
||||
<Chat {...props} myApps={myApps} />
|
||||
</ChatRecordContextProvider>
|
||||
</ChatItemContextProvider>
|
||||
</ChatContextProvider>
|
||||
);
|
||||
) : null;
|
||||
};
|
||||
|
||||
export async function getServerSideProps(context: any) {
|
||||
|
||||
Reference in New Issue
Block a user