242 lines
6.6 KiB
TypeScript
242 lines
6.6 KiB
TypeScript
import type { FC } from "react";
|
|
import "antd/dist/reset.css"; // 引入 antd 的样式
|
|
import { useEffect, useState } from "react";
|
|
import { useAsyncEffect } from "ahooks";
|
|
import { useThemeContext } from "@/app/components/chat/embedded-chatbot/theme/theme-context";
|
|
import { ChatWithHistoryContext, useChatWithHistoryContext } from "./context";
|
|
import { useChatWithHistory } from "./hooks";
|
|
import Sidebar from "./sidebar";
|
|
import HeaderInMobile from "./header-in-mobile";
|
|
import ConfigPanel from "./config-panel";
|
|
import ChatWrapper from "./chat-wrapper";
|
|
import type { InstalledApp } from "@/models/explore";
|
|
import Loading from "@/app/components/base/loading";
|
|
import useBreakpoints, { MediaType } from "@/hooks/use-breakpoints";
|
|
import { useRouter } from "next/navigation";
|
|
import AppUnavailable from "@/app/components/base/app-unavailable";
|
|
|
|
type ChatWithHistoryProps = {
|
|
className?: string;
|
|
userStr?: string;
|
|
};
|
|
|
|
const ChatWithHistory: FC<ChatWithHistoryProps> = ({ className, userStr }) => {
|
|
const {
|
|
appInfoError,
|
|
appData,
|
|
appInfoLoading,
|
|
appPrevChatTree,
|
|
showConfigPanelBeforeChat,
|
|
appChatListDataLoading,
|
|
chatShouldReloadKey,
|
|
isMobile,
|
|
themeBuilder,
|
|
} = useChatWithHistoryContext();
|
|
|
|
const chatReady = !showConfigPanelBeforeChat || !!appPrevChatTree.length;
|
|
const customConfig = appData?.custom_config;
|
|
const site = appData?.site;
|
|
|
|
useEffect(() => {
|
|
themeBuilder?.buildTheme(
|
|
site?.chat_color_theme,
|
|
site?.chat_color_theme_inverted
|
|
);
|
|
if (site) {
|
|
if (customConfig) document.title = `${site.title}`;
|
|
else document.title = `${site.title} - Powered by Dify`;
|
|
}
|
|
}, [site, customConfig, themeBuilder]);
|
|
|
|
if (appInfoLoading) {
|
|
return <Loading type="app" />;
|
|
}
|
|
|
|
if (appInfoError) {
|
|
return <AppUnavailable />;
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className={`h-full flex bg-white ${className} ${isMobile && "flex-col"}`}
|
|
>
|
|
{!isMobile && <Sidebar userStr={userStr} />}
|
|
{isMobile && <HeaderInMobile />}
|
|
<div
|
|
className={`grow overflow-hidden ${
|
|
showConfigPanelBeforeChat &&
|
|
!appPrevChatTree.length &&
|
|
"flex items-center justify-center"
|
|
}`}
|
|
>
|
|
{showConfigPanelBeforeChat &&
|
|
!appChatListDataLoading &&
|
|
!appPrevChatTree.length && (
|
|
<div
|
|
className={`flex w-full items-center justify-center h-full ${
|
|
isMobile && "px-4"
|
|
}`}
|
|
>
|
|
<ConfigPanel />
|
|
</div>
|
|
)}
|
|
{appChatListDataLoading && chatReady && <Loading type="app" />}
|
|
{chatReady && !appChatListDataLoading && (
|
|
<ChatWrapper key={chatShouldReloadKey} />
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export type ChatWithHistoryWrapProps = {
|
|
installedAppInfo?: InstalledApp;
|
|
className?: string;
|
|
userStr?: string;
|
|
};
|
|
|
|
const ChatWithHistoryWrap: FC<ChatWithHistoryWrapProps> = ({
|
|
installedAppInfo,
|
|
className,
|
|
userStr,
|
|
}) => {
|
|
const media = useBreakpoints();
|
|
const isMobile = media === MediaType.mobile;
|
|
const themeBuilder = useThemeContext();
|
|
|
|
const {
|
|
appInfoError,
|
|
appInfoLoading,
|
|
appData,
|
|
appParams,
|
|
appMeta,
|
|
appChatListDataLoading,
|
|
currentConversationId,
|
|
currentConversationItem,
|
|
appPrevChatTree,
|
|
pinnedConversationList,
|
|
conversationList,
|
|
showConfigPanelBeforeChat,
|
|
newConversationInputs,
|
|
newConversationInputsRef,
|
|
handleNewConversationInputsChange,
|
|
inputsForms,
|
|
handleNewConversation,
|
|
handleStartChat,
|
|
handleChangeConversation,
|
|
handlePinConversation,
|
|
handleUnpinConversation,
|
|
handleDeleteConversation,
|
|
conversationRenaming,
|
|
handleRenameConversation,
|
|
handleNewConversationCompleted,
|
|
chatShouldReloadKey,
|
|
isInstalledApp,
|
|
appId,
|
|
handleFeedback,
|
|
currentChatInstanceRef,
|
|
feedbackModal,
|
|
} = useChatWithHistory(installedAppInfo);
|
|
|
|
return (
|
|
<ChatWithHistoryContext.Provider
|
|
value={{
|
|
appInfoError,
|
|
appInfoLoading,
|
|
appData,
|
|
appParams,
|
|
appMeta,
|
|
appChatListDataLoading,
|
|
currentConversationId,
|
|
currentConversationItem,
|
|
appPrevChatTree,
|
|
pinnedConversationList,
|
|
conversationList,
|
|
showConfigPanelBeforeChat,
|
|
newConversationInputs,
|
|
newConversationInputsRef,
|
|
handleNewConversationInputsChange,
|
|
inputsForms,
|
|
handleNewConversation,
|
|
handleStartChat,
|
|
handleChangeConversation,
|
|
handlePinConversation,
|
|
handleUnpinConversation,
|
|
handleDeleteConversation,
|
|
conversationRenaming,
|
|
handleRenameConversation,
|
|
handleNewConversationCompleted,
|
|
chatShouldReloadKey,
|
|
isMobile,
|
|
isInstalledApp,
|
|
appId,
|
|
handleFeedback,
|
|
currentChatInstanceRef,
|
|
themeBuilder,
|
|
}}
|
|
>
|
|
<ChatWithHistory className={className} userStr={userStr} />
|
|
{feedbackModal} {/* 确保 feedbackModal 正确渲染 */}
|
|
</ChatWithHistoryContext.Provider>
|
|
);
|
|
};
|
|
|
|
const ChatWithHistoryWrapWithCheckToken: FC<ChatWithHistoryWrapProps> = ({
|
|
installedAppInfo,
|
|
className,
|
|
}) => {
|
|
const [initialized, setInitialized] = useState(false);
|
|
const [appUnavailable, setAppUnavailable] = useState<boolean>(false);
|
|
const [resCode, setResCode] = useState<number>(200);
|
|
const router = useRouter();
|
|
const [userName, setUserName] = useState("");
|
|
const [nickName, setNickName] = useState("");
|
|
|
|
useAsyncEffect(async () => {
|
|
if (!initialized) {
|
|
if (!installedAppInfo) {
|
|
const accessToken = localStorage.getItem("token");
|
|
if (!accessToken) {
|
|
router.replace("/login");
|
|
} else {
|
|
fetch(`/dev-api/getInfo`, {
|
|
method: "GET",
|
|
headers: {
|
|
Authorization: `Bearer ${accessToken}`,
|
|
},
|
|
})
|
|
.then((res) => res.json())
|
|
.then((data) => {
|
|
if (data.code !== 200) {
|
|
localStorage.removeItem("token");
|
|
router.replace("/login");
|
|
} else {
|
|
setUserName(data.user.userName);
|
|
setNickName(data.user.nickName);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
setResCode(500);
|
|
setAppUnavailable(true);
|
|
});
|
|
}
|
|
}
|
|
setInitialized(true);
|
|
}
|
|
}, []);
|
|
|
|
if (!initialized) return null;
|
|
|
|
if (appUnavailable) return <AppUnavailable code={resCode} />;
|
|
|
|
return (
|
|
<ChatWithHistoryWrap
|
|
installedAppInfo={installedAppInfo}
|
|
className={className}
|
|
userStr={`${nickName}[${userName}]`}
|
|
/>
|
|
);
|
|
};
|
|
|
|
export default ChatWithHistoryWrapWithCheckToken;
|