This commit is contained in:
Li1304553726 2025-05-08 16:31:48 +08:00
parent 89102d7f8c
commit 84a5066097
1 changed files with 79 additions and 42 deletions

View File

@ -10,6 +10,9 @@ import {
Input, Input,
Alert, Alert,
Pagination, Pagination,
Select,
Space,
Tag,
} from "antd"; } from "antd";
import { TusUploader } from "@web/src/components/common/uploader/TusUploader"; import { TusUploader } from "@web/src/components/common/uploader/TusUploader";
import { SendOutlined, DeleteOutlined, LoginOutlined } from "@ant-design/icons"; import { SendOutlined, DeleteOutlined, LoginOutlined } from "@ant-design/icons";
@ -27,6 +30,7 @@ export function VideoContent() {
const [fileIds, setFileIds] = useState<string[]>([]); const [fileIds, setFileIds] = useState<string[]>([]);
const [uploaderKey, setUploaderKey] = useState<number>(0); const [uploaderKey, setUploaderKey] = useState<number>(0);
const [searchTerm, setSearchTerm] = useState(""); const [searchTerm, setSearchTerm] = useState("");
const [fileType, setFileType] = useState<string>("all");
// 分页状态 // 分页状态
const [imagePage, setImagePage] = useState(1); const [imagePage, setImagePage] = useState(1);
@ -43,8 +47,11 @@ export function VideoContent() {
data: resources, data: resources,
refetch, refetch,
isLoading, isLoading,
}: { data: ResourceDto[]; refetch: () => void; isLoading: boolean } = }: {
api.resource.findMany.useQuery({ data: ResourceDto[];
refetch: () => void;
isLoading: boolean;
} = api.resource.findMany.useQuery({
where: { where: {
deletedAt: null, deletedAt: null,
postId: null, postId: null,
@ -54,7 +61,17 @@ export function VideoContent() {
}, },
}); });
// 处理资源数据 // 定义常见文件类型和它们的扩展名
const fileTypes = {
all: { label: "全部", extensions: [] },
document: { label: "文档", extensions: ["doc", "docx", "pdf", "txt"] },
spreadsheet: { label: "表格", extensions: ["xls", "xlsx", "csv"] },
presentation: { label: "ppt", extensions: ["ppt", "pptx"] },
video: { label: "音视频", extensions: ["mp4", "avi", "mov", "webm","mp3", "wav", "ogg"] },
archive: { label: "压缩包", extensions: ["zip", "rar", "7z"] },
};
// 修改资源处理逻辑,加入文件类型筛选
const { imageResources, fileResources, imagePagination, filePagination } = const { imageResources, fileResources, imagePagination, filePagination } =
useMemo(() => { useMemo(() => {
if (!resources) { if (!resources) {
@ -74,10 +91,11 @@ export function VideoContent() {
const original = `http://${env.SERVER_IP}:${env.UPLOAD_PORT}/uploads/${resource.url}`; const original = `http://${env.SERVER_IP}:${env.UPLOAD_PORT}/uploads/${resource.url}`;
const isImg = isImage(resource.url); const isImg = isImage(resource.url);
// 确保 title 存在,优先使用 resource.title然后是 resource.meta.filename // 提取文件扩展名
const extension = resource.url.split(".").pop()?.toLowerCase() || "";
const displayTitle = const displayTitle =
resource.title || resource.meta?.filename || "未命名文件"; resource.title || resource.meta?.filename || "未命名文件";
// 用于搜索的名称,确保从 meta.filename 获取(如果存在)
const searchableFilename = resource.meta?.filename || ""; const searchableFilename = resource.meta?.filename || "";
return { return {
@ -85,20 +103,27 @@ export function VideoContent() {
url: isImg ? getCompressedImageUrl(original) : original, url: isImg ? getCompressedImageUrl(original) : original,
originalUrl: original, originalUrl: original,
isImage: isImg, isImage: isImg,
title: displayTitle, // 用于显示 title: displayTitle,
searchableFilename: searchableFilename, // 用于搜索 searchableFilename: searchableFilename,
extension: extension,
}; };
}) })
.filter(Boolean); .filter(Boolean);
// 根据搜索词筛选文件资源 (基于 searchableFilename) // 根据搜索词和文件类型筛选
const filteredFileResources = processedResources.filter( const filteredFileResources = processedResources.filter((res) => {
(res) => // 首先检查是否符合搜索词
!res.isImage && const matchesSearch = res.searchableFilename
res.searchableFilename
.toLowerCase() .toLowerCase()
.includes(searchTerm.toLowerCase()) .includes(searchTerm.toLowerCase());
);
// 然后检查文件类型
const matchesType =
fileType === "all" ||
fileTypes[fileType]?.extensions.includes(res.extension);
return !res.isImage && matchesSearch && matchesType;
});
const allImageResources = processedResources.filter((res) => res.isImage); const allImageResources = processedResources.filter((res) => res.isImage);
@ -124,7 +149,7 @@ export function VideoContent() {
data: filteredFileResources, data: filteredFileResources,
}, },
}; };
}, [resources, imagePage, filePage, searchTerm]); // searchTerm 作为依赖项 }, [resources, imagePage, filePage, searchTerm, fileType]); // 添加fileType依赖
const createMutation = api.resource.create.useMutation({}); const createMutation = api.resource.create.useMutation({});
const handleSubmit = async () => { const handleSubmit = async () => {
@ -223,6 +248,7 @@ export function VideoContent() {
<p>excelppt等多种格式文件</p> <p>excelppt等多种格式文件</p>
</div> </div>
</header> </header>
<div className="flex flex-wrap items-center gap-4 mb-4">
<Input.Search <Input.Search
placeholder="搜索文件名" placeholder="搜索文件名"
allowClear allowClear
@ -230,6 +256,23 @@ export function VideoContent() {
onChange={(e) => setSearchTerm(e.target.value)} onChange={(e) => setSearchTerm(e.target.value)}
style={{ width: 300 }} style={{ width: 300 }}
/> />
<Select
value={fileType}
onChange={(value) => setFileType(value)}
style={{ width: 120 }}
options={Object.entries(fileTypes).map(([key, { label }]) => ({
value: key,
label: label,
}))}
/>
{/* {fileType !== "all" && (
<Tag color="blue" closable onClose={() => setFileType("all")}>
{fileTypes[fileType]?.label}
</Tag>
)} */}
</div>
{!isAuthenticated && ( {!isAuthenticated && (
<Alert <Alert
message="请先登录" message="请先登录"
@ -373,20 +416,20 @@ export function VideoContent() {
</div> </div>
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="font-medium truncate"> <div className="font-medium truncate">
{resource.title} {resource.meta?.filename}
</div> </div>
{resource.description && ( {/* {resource.meta?.filetype && (
<div className="text-xs text-gray-500 mt-1"> <div className="text-xs text-gray-500 mt-1">
: {resource.description} : {resource.meta?.filetype}
</div> </div>
)} )} */}
<div className="text-xs text-gray-500 flex items-center gap-2"> <div className="text-xs text-gray-500 flex items-center gap-2">
<span> <span>
{dayjs(resource.createdAt).format("YYYY-MM-DD")} {dayjs(resource.createdAt).format("YYYY-MM-DD")}
</span> </span>
<span> <span>
{resource.meta?.size && {resource.meta?.size &&
formatFileSize(resource.meta.size)} formatFileSize(resource.meta?.size)}
</span> </span>
</div> </div>
</div> </div>
@ -416,12 +459,6 @@ export function VideoContent() {
</div> </div>
)} )}
{fileResources.length === 0 && searchTerm && (
<div className="text-center py-4 text-gray-500">
"{searchTerm}"
</div>
)}
{/* 文件分页 */} {/* 文件分页 */}
{filePagination.total > pageSize && ( {filePagination.total > pageSize && (
<div className="flex justify-center mt-6"> <div className="flex justify-center mt-6">