+ {/* 操作栏:搜索、权限选择、上传按钮 */}
+
+
+
+ setKeyword(e.target.value)}
+ className="pl-9 h-9"
+ />
+
+
+
+ {/* 上传权限设置 */}
+
+
+
+
+
+
+
+
+
+
+ {/* 文件展示区 */}
+ {isPending ? (
+
+
+
+ ) : files.length === 0 ? (
+
+
+
+
+
+
+
还没有上传文件
+
+ {debouncedKeyword ? "未搜索到匹配的文件" : "上传您的第一个文件,支持图片、视频、文档和压缩包等格式。"}
+
+
+ {!debouncedKeyword && (
+
+ )}
+
+
+ ) : (
+
+ {files.map((file) => (
+
+ {/* 文件预览/图标区 */}
+
+ {file.mime_type.startsWith("image/") ? (
+ // eslint-disable-next-line @next/next/no-img-element
+

{
+ ;(e.currentTarget as HTMLImageElement).style.display = "none"
+ }}
+ />
+ ) : (
+ getFileIcon(file.mime_type)
+ )}
+
+ {/* 访问权限 Badge */}
+
+ {file.access_mode === 0 ? (
+
+
+ 私有
+
+ ) : (
+
+
+ 公开
+
+ )}
+
+
+
+ {/* 文件详情区 */}
+
+
+
+ {file.file_name}
+
+
+ {formatFileSize(file.file_size)}
+ {file.mime_type}
+
+
+
+
+
{formatDate(file.created_at)}
+
+
+
+
+
+
+
+
+ ))}
+
+ )}
+
+ {/* 分页 */}
+ {totalPages > 1 && (
+
+
+
+ {page} / {totalPages}
+
+
+
+ )}
+
+ {/* 删除确认 Dialog */}
+
!open && setDeleteTarget(null)}>
+
+
+ 确认删除文件
+
+ 确定要删除文件{" "}
+ 「{deleteTarget?.file_name}」{" "}
+ 吗?删除后此文件将无法恢复。
+
+
+
+ 取消
+ deleteTarget && deleteMutation.mutate(deleteTarget.id)}
+ disabled={deleteMutation.isPending}
+ className="bg-destructive hover:bg-destructive/90 text-destructive-foreground"
+ >
+ {deleteMutation.isPending && }
+ 确认删除
+
+
+
+
+
+ )
+}
diff --git a/frontend/components/common/user/files.tsx b/frontend/components/common/user/files.tsx
new file mode 100644
index 00000000..13bd52f0
--- /dev/null
+++ b/frontend/components/common/user/files.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import * as React from "react"
+import {motion} from "motion/react"
+
+import {UserFileManager} from "./file-manager"
+
+export function UserFilesMain() {
+ return (
+