feat(上传组件): 添加SimpleFileUpload组件并集成到聊天窗口
- 创建新的SimpleFileUpload组件实现文件上传功能 - 在聊天窗口替换原有上传按钮为新的组件 - 为上传API添加调试日志 - 移除聊天窗口重复的音频图标导入
This commit is contained in:
@@ -10,18 +10,22 @@ export async function uploadFile(
|
||||
uploadUrl: string = "/v1/attachment/upload",
|
||||
): Promise<string> {
|
||||
try {
|
||||
console.log("uploadFile 接收到的文件:", file);
|
||||
console.log("上传URL:", uploadUrl);
|
||||
|
||||
// 创建 FormData 对象用于文件上传
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
// 使用 request 方法上传文件,设置正确的 Content-Type
|
||||
const res = await request(uploadUrl, formData, "POST", {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
console.log("FormData 创建完成");
|
||||
console.log("FormData 内容:", formData.get("file"));
|
||||
|
||||
// 使用 request 方法上传文件,让浏览器自动设置 Content-Type
|
||||
const res = await request(uploadUrl, formData, "POST");
|
||||
console.log("上传响应:", res);
|
||||
return res.url;
|
||||
} catch (e: any) {
|
||||
console.error("uploadFile 错误:", e);
|
||||
throw new Error(e?.message || "文件上传失败");
|
||||
}
|
||||
}
|
||||
|
||||
97
Cunkebao/src/components/Upload/SimpleFileUpload/index.tsx
Normal file
97
Cunkebao/src/components/Upload/SimpleFileUpload/index.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
import React, { useRef, useState } from "react";
|
||||
import { Button, message } from "antd";
|
||||
import { FolderOutlined, LoadingOutlined } from "@ant-design/icons";
|
||||
import { uploadFile } from "@/api/common";
|
||||
|
||||
interface SimpleFileUploadProps {
|
||||
onFileUploaded?: (filePath: string) => void;
|
||||
disabled?: boolean;
|
||||
className?: string;
|
||||
maxSize?: number; // 最大文件大小(MB)
|
||||
accept?: string; // 接受的文件类型
|
||||
}
|
||||
|
||||
const SimpleFileUpload: React.FC<SimpleFileUploadProps> = ({
|
||||
onFileUploaded,
|
||||
disabled = false,
|
||||
className,
|
||||
maxSize = 50,
|
||||
accept = "*/*",
|
||||
}) => {
|
||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||
const [uploading, setUploading] = useState(false);
|
||||
|
||||
// 验证文件
|
||||
const validateFile = (file: File): boolean => {
|
||||
if (file.size > maxSize * 1024 * 1024) {
|
||||
message.error(`文件大小不能超过 ${maxSize}MB`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// 处理文件选择
|
||||
const handleFileSelect = async (
|
||||
event: React.ChangeEvent<HTMLInputElement>,
|
||||
) => {
|
||||
const files = event.target.files;
|
||||
if (!files || files.length === 0) return;
|
||||
|
||||
const file = files[0];
|
||||
console.log("选择的文件:", file);
|
||||
console.log("文件名:", file.name);
|
||||
console.log("文件大小:", file.size);
|
||||
console.log("文件类型:", file.type);
|
||||
|
||||
if (!validateFile(file)) {
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.value = "";
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
setUploading(true);
|
||||
|
||||
try {
|
||||
console.log("开始上传文件...");
|
||||
const fileUrl = await uploadFile(file);
|
||||
console.log("上传成功,文件URL:", fileUrl);
|
||||
onFileUploaded?.(fileUrl);
|
||||
message.success("文件上传成功");
|
||||
} catch (error: any) {
|
||||
console.error("文件上传失败:", error);
|
||||
message.error(error.message || "文件上传失败");
|
||||
} finally {
|
||||
setUploading(false);
|
||||
if (fileInputRef.current) {
|
||||
fileInputRef.current.value = "";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
if (disabled || uploading) return;
|
||||
fileInputRef.current?.click();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
accept={accept}
|
||||
onChange={handleFileSelect}
|
||||
style={{ display: "none" }}
|
||||
/>
|
||||
<Button
|
||||
type="text"
|
||||
icon={uploading ? <LoadingOutlined /> : <FolderOutlined />}
|
||||
onClick={handleClick}
|
||||
disabled={disabled || uploading}
|
||||
className={className}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SimpleFileUpload;
|
||||
@@ -3,10 +3,7 @@ import { Layout, Input, Button, Dropdown, Menu, Tooltip, Modal } from "antd";
|
||||
import {
|
||||
ShareAltOutlined,
|
||||
SendOutlined,
|
||||
SmileOutlined,
|
||||
FolderOutlined,
|
||||
AudioOutlined,
|
||||
AudioOutlined as AudioHoldOutlined,
|
||||
CodeSandboxOutlined,
|
||||
MessageOutlined,
|
||||
EnvironmentOutlined,
|
||||
@@ -16,6 +13,7 @@ import { ContractData, weChatGroup } from "@/pages/pc/ckbox/data";
|
||||
import { useWebSocketStore } from "@/store/module/websocket/websocket";
|
||||
import { EmojiPicker } from "@/components/EmojiSeclection";
|
||||
import { EmojiInfo } from "@/components/EmojiSeclection/wechatEmoji";
|
||||
import SimpleFileUpload from "@/components/Upload/SimpleFileUpload";
|
||||
import styles from "./MessageEnter.module.scss";
|
||||
|
||||
const { Footer } = Layout;
|
||||
@@ -96,11 +94,14 @@ const MessageEnter: React.FC<MessageEnterProps> = ({ contract }) => {
|
||||
|
||||
// 处理表情选择
|
||||
const handleEmojiSelect = (emoji: EmojiInfo) => {
|
||||
console.log("选择表情:", emoji.name);
|
||||
// 将表情插入到输入框文字的最后
|
||||
setInputValue(prevValue => prevValue + `[${emoji.name}]`);
|
||||
};
|
||||
|
||||
const handleFileUploaded = (filePath: string) => {
|
||||
console.log("文件上传成功,路径:", filePath);
|
||||
// 这里可以根据需要处理文件路径,比如发送文件消息
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* 聊天输入 */}
|
||||
@@ -109,13 +110,12 @@ const MessageEnter: React.FC<MessageEnterProps> = ({ contract }) => {
|
||||
<div className={styles.inputToolbar}>
|
||||
<div className={styles.leftTool}>
|
||||
<EmojiPicker onEmojiSelect={handleEmojiSelect} />
|
||||
<Tooltip title="上传附件">
|
||||
<Button
|
||||
type="text"
|
||||
icon={<FolderOutlined />}
|
||||
className={styles.toolbarButton}
|
||||
/>
|
||||
</Tooltip>
|
||||
<SimpleFileUpload
|
||||
onFileUploaded={handleFileUploaded}
|
||||
className={styles.toolbarButton}
|
||||
maxSize={50}
|
||||
accept="*/*"
|
||||
/>
|
||||
<Tooltip title="收藏">
|
||||
<Button
|
||||
type="text"
|
||||
@@ -140,7 +140,7 @@ const MessageEnter: React.FC<MessageEnterProps> = ({ contract }) => {
|
||||
<Tooltip title="按住说话">
|
||||
<Button
|
||||
type="text"
|
||||
icon={<AudioHoldOutlined />}
|
||||
icon={<AudioOutlined />}
|
||||
className={styles.toolbarButton}
|
||||
style={{ position: "relative" }}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user