|
@@ -43,6 +43,7 @@ import type { ConversationsProps } from "@ant-design/x";
|
|
|
import type { AgentItem } from "./data";
|
|
|
import MarkdownViewer from "@/components/ai/MarkdownViewer";
|
|
|
import { ChangeSessionName, DeleteSession } from "@/api/ai";
|
|
|
+import InfiniteScroll from "react-infinite-scroll-component";
|
|
|
|
|
|
type AssistantProps = {
|
|
|
agent?: AgentItem;
|
|
@@ -65,7 +66,7 @@ const roles: GetProp<typeof Bubble.List, "roles"> = {
|
|
|
),
|
|
|
messageRender: (content) => {
|
|
|
return typeof content === "string" ? (
|
|
|
- <Typography className={content?.includes('```') ? 'w-full' : ''}>
|
|
|
+ <Typography className={content?.includes("```") ? "w-full" : ""}>
|
|
|
<MarkdownViewer content={content} />
|
|
|
</Typography>
|
|
|
) : (
|
|
@@ -78,7 +79,7 @@ const roles: GetProp<typeof Bubble.List, "roles"> = {
|
|
|
placement: "end",
|
|
|
avatar: { icon: <UserOutlined />, style: { background: "#87d068" } },
|
|
|
messageRender: (content) => {
|
|
|
- return <div style={{ whiteSpace: 'pre-wrap' }}>{content}</div>
|
|
|
+ return <div style={{ whiteSpace: "pre-wrap" }}>{content}</div>;
|
|
|
},
|
|
|
},
|
|
|
};
|
|
@@ -97,6 +98,8 @@ export default (props: AssistantProps) => {
|
|
|
loadingSession,
|
|
|
addConversation,
|
|
|
setConversationList,
|
|
|
+ loadMoreConversation,
|
|
|
+ hasMoreConversation,
|
|
|
} = useChat({
|
|
|
app_name: props.agent?.key || "",
|
|
|
onSuccess: (msg) => {
|
|
@@ -361,7 +364,9 @@ export default (props: AssistantProps) => {
|
|
|
arr[messages.length - 1].loading = false;
|
|
|
arr[messages.length - 1].footer = (
|
|
|
<div>
|
|
|
- <div className="text-12px text-text-secondary pl-12px">(已停止思考)</div>
|
|
|
+ <div className="text-12px text-text-secondary pl-12px">
|
|
|
+ (已停止思考)
|
|
|
+ </div>
|
|
|
<BubbleFooter
|
|
|
content={arr[messages.length - 1].content as string}
|
|
|
query={arr[messages.length - 2].content as string}
|
|
@@ -393,29 +398,50 @@ export default (props: AssistantProps) => {
|
|
|
>
|
|
|
<XProvider direction="ltr">
|
|
|
<Flex style={{ height: "100%" }} gap={12}>
|
|
|
- <Spin spinning={loadingSession}>
|
|
|
- <div className="w-200px">
|
|
|
- <div className="w-full px-12px">
|
|
|
- <Button
|
|
|
- type="primary"
|
|
|
- className="w-full"
|
|
|
- icon={<PlusOutlined />}
|
|
|
- onClick={addConversation}
|
|
|
- >
|
|
|
- 新对话
|
|
|
- </Button>
|
|
|
- </div>
|
|
|
- <Conversations
|
|
|
- style={{ width: 200 }}
|
|
|
- activeKey={activeConversation}
|
|
|
- onActiveChange={changeConversation}
|
|
|
- menu={menuConfig}
|
|
|
- items={conversationList}
|
|
|
- />
|
|
|
+ <div className="w-200px flex flex-col">
|
|
|
+ <div className="w-full px-12px mb-12px">
|
|
|
+ <Button
|
|
|
+ type="primary"
|
|
|
+ className="w-full"
|
|
|
+ icon={<PlusOutlined />}
|
|
|
+ onClick={addConversation}
|
|
|
+ >
|
|
|
+ 新对话
|
|
|
+ </Button>
|
|
|
</div>
|
|
|
- </Spin>
|
|
|
+ <div id="scrollableDiv" className="flex-1 overflow-auto">
|
|
|
+ <InfiniteScroll
|
|
|
+ dataLength={conversationList?.length || 0}
|
|
|
+ next={loadMoreConversation}
|
|
|
+ hasMore={hasMoreConversation}
|
|
|
+ loader={
|
|
|
+ <div style={{ textAlign: "center" }}>
|
|
|
+ <Spin indicator={<RedoOutlined spin />} size="small" />
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ endMessage={<Divider plain><span className="text-12px text-text-secondary">无更多会话~</span></Divider>}
|
|
|
+ scrollableTarget="scrollableDiv"
|
|
|
+ style={{ overflow: "hidden" }}
|
|
|
+ >
|
|
|
+ <Spin spinning={loadingSession} className="flex-col">
|
|
|
+ <Conversations
|
|
|
+ style={{ width: 200 }}
|
|
|
+ activeKey={activeConversation}
|
|
|
+ onActiveChange={changeConversation}
|
|
|
+ menu={menuConfig}
|
|
|
+ items={conversationList}
|
|
|
+ />
|
|
|
+ </Spin>
|
|
|
+ </InfiniteScroll>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
<Divider type="vertical" style={{ height: "100%" }} />
|
|
|
- <Flex vertical style={{ flex: 1, overflow: 'hidden', height: '100%' }} gap={8}>
|
|
|
+ <Flex
|
|
|
+ vertical
|
|
|
+ style={{ flex: 1, overflow: "hidden", height: "100%" }}
|
|
|
+ gap={8}
|
|
|
+ >
|
|
|
<div
|
|
|
className="flex-1 overflow-hidden"
|
|
|
ref={contentRef}
|