Files
cunkebao_v3/Touchkebao/src/components/Upload/ChatFileUpload/example.tsx
超级老白兔 9b3181576f feat: 初始化项目基础架构与核心功能
添加项目基础文件结构、路由配置、API接口和核心组件
实现登录认证、权限控制、WebSocket通信等基础功能
引入antd-mobile UI组件库和Vite构建工具
配置TypeScript、ESLint、Prettier等开发环境
添加移动端适配方案和全局样式
完成首页、工作台、个人中心等基础页面框架
2025-09-11 15:00:57 +08:00

255 lines
7.7 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState } from "react";
import { Input, Button, Card, Space, Typography, Divider } from "antd";
import { SendOutlined } from "@ant-design/icons";
import ChatFileUpload from "./index";
const { TextArea } = Input;
const { Text } = Typography;
interface ChatMessage {
id: string;
type: "text" | "file";
content: string;
timestamp: Date;
fileInfo?: {
url: string;
name: string;
type: string;
size: number;
};
}
const ChatFileUploadExample: React.FC = () => {
const [messages, setMessages] = useState<ChatMessage[]>([]);
const [inputValue, setInputValue] = useState("");
// 处理文件上传
const handleFileUploaded = (fileInfo: {
url: string;
name: string;
type: string;
size: number;
}) => {
const newMessage: ChatMessage = {
id: Date.now().toString(),
type: "file",
content: `文件: ${fileInfo.name}`,
timestamp: new Date(),
fileInfo,
};
setMessages(prev => [...prev, newMessage]);
};
// 处理文本发送
const handleSendText = () => {
if (!inputValue.trim()) return;
const newMessage: ChatMessage = {
id: Date.now().toString(),
type: "text",
content: inputValue,
timestamp: new Date(),
};
setMessages(prev => [...prev, newMessage]);
setInputValue("");
};
// 格式化文件大小
const formatFileSize = (bytes: number) => {
if (bytes === 0) return "0 B";
const k = 1024;
const sizes = ["B", "KB", "MB", "GB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
};
// 获取文件类型图标
const getFileTypeIcon = (type: string, name: string) => {
const lowerType = type.toLowerCase();
const lowerName = name.toLowerCase();
if (lowerType.startsWith("image/")) {
return "🖼️";
} else if (lowerType.startsWith("video/")) {
return "🎥";
} else if (lowerType.startsWith("audio/")) {
return "🎵";
} else if (lowerType === "application/pdf") {
return "📄";
} else if (lowerName.endsWith(".doc") || lowerName.endsWith(".docx")) {
return "📝";
} else if (lowerName.endsWith(".xls") || lowerName.endsWith(".xlsx")) {
return "📊";
} else if (lowerName.endsWith(".ppt") || lowerName.endsWith(".pptx")) {
return "📈";
} else {
return "📎";
}
};
return (
<div style={{ maxWidth: 600, margin: "0 auto", padding: 20 }}>
<Card title="聊天文件上传示例" style={{ marginBottom: 20 }}>
<Space direction="vertical" style={{ width: "100%" }}>
<Text></Text>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</Space>
</Card>
{/* 聊天消息区域 */}
<Card
title="聊天记录"
style={{
height: 400,
marginBottom: 20,
overflowY: "auto",
}}
bodyStyle={{ height: 320, overflowY: "auto" }}
>
{messages.length === 0 ? (
<div style={{ textAlign: "center", color: "#999", marginTop: 100 }}>
</div>
) : (
<div>
{messages.map(message => (
<div key={message.id} style={{ marginBottom: 16 }}>
<div
style={{
background: "#f0f0f0",
padding: 12,
borderRadius: 8,
maxWidth: "80%",
wordBreak: "break-word",
}}
>
{message.type === "text" ? (
<div>{message.content}</div>
) : (
<div>
<div
style={{
display: "flex",
alignItems: "center",
gap: 8,
marginBottom: 4,
}}
>
<span>
{getFileTypeIcon(
message.fileInfo!.type,
message.fileInfo!.name,
)}
</span>
<Text strong>{message.fileInfo!.name}</Text>
</div>
<div style={{ fontSize: 12, color: "#666" }}>
: {formatFileSize(message.fileInfo!.size)}
</div>
<div style={{ fontSize: 12, color: "#666" }}>
: {message.fileInfo!.type}
</div>
<a
href={message.fileInfo!.url}
target="_blank"
rel="noopener noreferrer"
style={{ fontSize: 12, color: "#1890ff" }}
>
</a>
</div>
)}
<div
style={{
fontSize: 11,
color: "#999",
marginTop: 4,
textAlign: "right",
}}
>
{message.timestamp.toLocaleTimeString()}
</div>
</div>
</div>
))}
</div>
)}
</Card>
{/* 输入区域 */}
<Card title="发送消息">
<Space direction="vertical" style={{ width: "100%" }}>
<TextArea
value={inputValue}
onChange={e => setInputValue(e.target.value)}
placeholder="输入消息内容..."
autoSize={{ minRows: 2, maxRows: 4 }}
onPressEnter={e => {
if (!e.shiftKey) {
e.preventDefault();
handleSendText();
}
}}
/>
<div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
}}
>
<Space>
{/* 文件上传组件 */}
<ChatFileUpload
onFileUploaded={handleFileUploaded}
maxSize={50} // 最大50MB
accept="*/*" // 接受所有文件类型
buttonText="文件"
buttonIcon={<span>📎</span>}
/>
{/* 图片上传组件 */}
<ChatFileUpload
onFileUploaded={handleFileUploaded}
maxSize={10} // 最大10MB
accept="image/*" // 只接受图片
buttonText="图片"
buttonIcon={<span>🖼</span>}
/>
{/* 文档上传组件 */}
<ChatFileUpload
onFileUploaded={handleFileUploaded}
maxSize={20} // 最大20MB
accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx" // 只接受文档
buttonText="文档"
buttonIcon={<span>📄</span>}
/>
</Space>
<Button
type="primary"
icon={<SendOutlined />}
onClick={handleSendText}
disabled={!inputValue.trim()}
>
</Button>
</div>
</Space>
</Card>
</div>
);
};
export default ChatFileUploadExample;