feat(页面): 聊天页面集成文件上传功能和动画样式

聊天页面更新:
- handleSend 方法扩展支持文件参数
- 将上传的文件转换为 sendMessage 所需格式
- 从数据库加载历史消息的上传图片和文档
- MessageBubble 组件传递 uploadedImages 和 uploadedDocuments

全局样式更新:
- 添加 fadeInFast 和 fadeOutFast 淡入淡出动画
- 添加 scaleInFast 缩放动画
- 用于模态框和灯箱的平滑过渡效果
This commit is contained in:
gaoziman 2025-12-20 12:15:03 +08:00
parent 4cb3f162e3
commit cb86380e7f
2 changed files with 51 additions and 2 deletions

View File

@ -11,6 +11,7 @@ import { useConversation, useConversations } from '@/hooks/useConversations';
import { useStreamChat, type ChatMessage } from '@/hooks/useStreamChat';
import { useModels, useTools, useSettings } from '@/hooks/useSettings';
import { useAuth } from '@/providers/AuthProvider';
import type { UploadFile } from '@/types/file-upload';
interface PageProps {
params: Promise<{ id: string }>;
@ -75,8 +76,12 @@ export default function ChatPage({ params }: PageProps) {
status: 'completed' as const,
inputTokens: msg.inputTokens || undefined,
outputTokens: msg.outputTokens || undefined,
// 从数据库加载图片数据
// 从数据库加载图片数据(代码执行产生的)
images: (msg.images as string[]) || undefined,
// 从数据库加载用户上传的图片
uploadedImages: (msg.uploadedImages as string[]) || undefined,
// 从数据库加载用户上传的文档
uploadedDocuments: (msg.uploadedDocuments as { name: string; size: number; type: string; content: string }[]) || undefined,
}));
setInitialMessages(historyMessages);
}
@ -214,7 +219,7 @@ export default function ChatPage({ params }: PageProps) {
};
// 发送消息
const handleSend = async (message: string) => {
const handleSend = async (message: string, files?: UploadFile[]) => {
let targetConversationId = chatId;
// 如果是新对话,先创建对话
@ -236,12 +241,20 @@ export default function ChatPage({ params }: PageProps) {
}
}
// 准备文件信息给 sendMessage
const uploadedFiles = files?.map(f => ({
file: f.file,
type: f.type,
previewUrl: f.previewUrl,
}));
await sendMessage({
conversationId: targetConversationId,
message,
model: selectedModelId,
tools: enabledTools,
enableThinking,
files: uploadedFiles,
});
};
@ -438,6 +451,8 @@ export default function ChatPage({ params }: PageProps) {
isStreaming={message.status === 'streaming'}
error={message.error}
images={message.images}
uploadedImages={message.uploadedImages}
uploadedDocuments={message.uploadedDocuments}
pyodideStatus={message.pyodideStatus}
/>
))

View File

@ -224,6 +224,40 @@ body {
animation: popUp 0.15s ease-out;
}
/* Modal 动画 */
@keyframes fadeInFast {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fadeOutFast {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes scaleInFast {
from {
opacity: 0;
transform: scale(0.95);
}
to {
opacity: 1;
transform: scale(1);
}
}
.animate-fade-in-fast {
animation: fadeInFast 0.15s ease-out;
}
.animate-fade-out-fast {
animation: fadeOutFast 0.15s ease-out;
}
.animate-scale-in-fast {
animation: scaleInFast 0.15s ease-out;
}
/* ========================================
响应式设计
======================================== */