Files
manage/src/components/ChatAi/index.jsx
2025-01-03 18:30:59 +08:00

147 lines
4.6 KiB
JavaScript

import { Button, Drawer, Input, Space, message } from 'antd';
import { useChat } from "ai/react";
import { CodeHighlight } from "@mantine/code-highlight";
import { DownloadOutlined } from '@ant-design/icons';
import { useRef, useEffect } from 'react';
import { useSessionStorage } from 'react-use';
export default function ChatAIDrawer({ open, onClose, onExport }) {
const STORAGE_KEY = 'chat_history';
const [storedMessages, setStoredMessages] = useSessionStorage(STORAGE_KEY, '[]');
const { messages, input, handleSubmit, handleInputChange, isLoading, setMessages } = useChat({
api: "https://test-ai-quirkyai.vercel.app/api/chat",
initialMessages: JSON.parse(storedMessages),
});
const messagesEndRef = useRef(null);
useEffect(() => {
setStoredMessages(JSON.stringify(messages));
}, [messages, setStoredMessages]);
// 新消息时自动滚动到底部
useEffect(() => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [messages]);
// 修改导出函数,接收单条消息内容
const handleExport = (content) => {
try {
const jsonContent = JSON.parse(content);
onExport?.(jsonContent);
} catch (error) {
console.log(error);
message.error('导出失败,请重试');
}
};
return (
<Drawer
title={
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span>AI 助手</span>
<Button
size="small"
onClick={() => {
setMessages([]);
setStoredMessages('[]');
message.success('历史记录已清空');
}}
>
清空历史
</Button>
</div>
}
placement="right"
width={600}
open={open}
onClose={onClose}
>
<div style={{ display: 'flex', flexDirection: 'column', height: 'calc(100vh - 108px)' }}>
<div style={{
flex: 1,
overflowY: 'auto',
marginBottom: 16,
padding: '0 16px'
}}>
{messages.map((message) => (
<div
key={message.id}
style={{
marginBottom: 16,
backgroundColor: message.role === 'assistant' ? '#f0f9ff' : '#f8f9fa',
padding: 16,
borderRadius: 12,
boxShadow: '0 2px 4px rgba(0,0,0,0.05)'
}}
>
<div style={{
fontWeight: 'bold',
marginBottom: 8,
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
color: message.role === 'assistant' ? '#1677ff' : '#52525b'
}}>
<span>{message.role === 'assistant' ? 'AI 助手' : '用户'}</span>
{message.role === 'assistant' && (
<Button
type="link"
size="small"
icon={<DownloadOutlined />}
onClick={() => handleExport(message.content)}
>
导出
</Button>
)}
</div>
<div>
{message.role === "assistant" ? (
<CodeHighlight
code={message.content}
language="json"
copyLabel="复制代码"
copiedLabel="已复制!"
withLineNumbers
/>
) : (
<div style={{
whiteSpace: 'pre-wrap',
wordBreak: 'break-word'
}}>
{message.content}
</div>
)}
</div>
</div>
))}
<div ref={messagesEndRef} />
</div>
<form onSubmit={handleSubmit} style={{
padding: '16px',
borderTop: '1px solid #f0f0f0',
backgroundColor: '#fff'
}}>
<Space.Compact style={{ width: '100%' }}>
<Input
value={input}
placeholder="请输入您的问题..."
onChange={handleInputChange}
disabled={isLoading}
style={{ borderRadius: '6px 0 0 6px' }}
/>
<Button
type="primary"
htmlType="submit"
loading={isLoading}
style={{ borderRadius: '0 6px 6px 0' }}
>
发送
</Button>
</Space.Compact>
</form>
</div>
</Drawer>
);
}