{fileList.map((file) => {
- const isSelected = selectedKeys.includes(file.id)
+ const isSelected = selectedSet.has(file.id)
const isDragging = dragState.draggedItems.some(
(f) => f.id === file.id
)
const isDropTarget = file.isDir && dragState.dropTargetId === file.id
const isMultiSelected = selectedKeys.length > 1 && isSelected
- const selectedFiles = fileList.filter((f) =>
- selectedKeys.includes(f.id)
- )
- const hasUnfavorited = selectedFiles.some((f) => !f.isFavorite)
- const downloadableFiles = selectedFiles.filter((f) => !f.isDir)
return (
diff --git a/src/pages/files/components/MySharesView.tsx b/src/pages/files/components/MySharesView.tsx
index 1dc78a03d42f613b8a18c2a2d45c66c81be70e06..42d715c04f285f2c8a46acec7ebf8e8a36ae13fc 100644
--- a/src/pages/files/components/MySharesView.tsx
+++ b/src/pages/files/components/MySharesView.tsx
@@ -1019,23 +1019,25 @@ export function MySharesView() {
open={deleteDialogVisible}
onOpenChange={setDeleteDialogVisible}
>
-
-
- 确认取消分享
-
- 确定要取消分享 "{deletingShare?.shareName}" 吗?取消后将无法恢复!
-
-
-
- 取消
-
- 确认
-
-
-
+ {deleteDialogVisible && (
+
+
+ 确认取消分享
+
+ 确定要取消分享 "{deletingShare?.shareName}" 吗?取消后将无法恢复!
+
+
+
+ 取消
+
+ 确认
+
+
+
+ )}
{/* 清空所有分享确认 */}
@@ -1043,23 +1045,25 @@ export function MySharesView() {
open={clearAllDialogVisible}
onOpenChange={setClearAllDialogVisible}
>
-
-
- 确认清空所有分享
-
- 确定要清空所有分享吗?所有分享链接将失效且无法恢复!
-
-
-
- 取消
-
- 清空
-
-
-
+ {clearAllDialogVisible && (
+
+
+ 确认清空所有分享
+
+ 确定要清空所有分享吗?所有分享链接将失效且无法恢复!
+
+
+
+ 取消
+
+ 清空
+
+
+
+ )}
{/* 批量删除确认弹窗 */}
@@ -1067,24 +1071,26 @@ export function MySharesView() {
open={batchDeleteDialogVisible}
onOpenChange={setBatchDeleteDialogVisible}
>
-
-
- 确认批量取消
-
- 确定要取消选中的 {selectedKeys.length}{' '}
- 个分享吗?取消后将无法恢复!
-
-
-
- 取消
-
- 确认
-
-
-
+ {batchDeleteDialogVisible && (
+
+
+ 确认批量取消
+
+ 确定要取消选中的 {selectedKeys.length}{' '}
+ 个分享吗?取消后将无法恢复!
+
+
+
+ 取消
+
+ 确认
+
+
+
+ )}
)
diff --git a/src/pages/files/components/RecycleBinView.tsx b/src/pages/files/components/RecycleBinView.tsx
index aefb93ff70c131431841d92d798372170873d231..b420c0b44b7ba52350bd2cb7e5c32e2e4b2369bd 100644
--- a/src/pages/files/components/RecycleBinView.tsx
+++ b/src/pages/files/components/RecycleBinView.tsx
@@ -166,16 +166,20 @@ export default function RecycleBinView() {
}
const confirmClearRecycle = async () => {
- setLoading(true)
try {
await clearRecycle()
- toast.success('回收站已清空')
+ // 乐观更新:先清空本地数据,避免 loading 状态导致的闪烁
+ setFileList([])
+ setTotal(0)
setClearDialogOpen(false)
setSelectedIds([])
commitSearch('')
setPagination((p) => ({ ...p, pageIndex: 0 }))
- } finally {
- setLoading(false)
+ toast.success('回收站已清空')
+ void fetchRecyclePage()
+ } catch {
+ // 失败时重新拉取,恢复真实数据
+ void fetchRecyclePage()
}
}
@@ -570,62 +574,68 @@ export default function RecycleBinView() {
)}
-
-
- 确认还原
-
- {operatingItem
- ? `确定要还原文件 "${operatingItem.name}" 吗?`
- : `确定要还原选中的 ${selectedIds.length} 个文件吗?`}
-
-
-
- 取消
- 还原
-
-
+ {restoreDialogOpen && (
+
+
+ 确认还原
+
+ {operatingItem
+ ? `确定要还原文件 "${operatingItem.name}" 吗?`
+ : `确定要还原选中的 ${selectedIds.length} 个文件吗?`}
+
+
+
+ 取消
+ 还原
+
+
+ )}
-
-
- 确认彻底删除
-
- {operatingItem
- ? `确定要彻底删除文件 "${operatingItem.name}" 吗?删除后将无法恢复!`
- : `确定要彻底删除选中的 ${selectedIds.length} 个文件吗?删除后将无法恢复!`}
-
-
-
- 取消
-
- 删除
-
-
-
+ {deleteDialogOpen && (
+
+
+ 确认彻底删除
+
+ {operatingItem
+ ? `确定要彻底删除文件 "${operatingItem.name}" 吗?删除后将无法恢复!`
+ : `确定要彻底删除选中的 ${selectedIds.length} 个文件吗?删除后将无法恢复!`}
+
+
+
+ 取消
+
+ 删除
+
+
+
+ )}
-
-
- 确认清空回收站
-
- 确定要清空回收站吗?所有文件将被彻底删除且无法恢复!
-
-
-
- 取消
-
- 清空
-
-
-
+ {clearDialogOpen && (
+
+
+ 确认清空回收站
+
+ 确定要清空回收站吗?所有文件将被彻底删除且无法恢复!
+
+
+
+ 取消
+
+ 清空
+
+
+
+ )}
)
diff --git a/src/pages/files/hooks/useFileList.ts b/src/pages/files/hooks/useFileList.ts
index a37358f11c77cbe62f9a7a0affc9d97dc7e54135..a158b696a061c4962604a071512349605d080836 100644
--- a/src/pages/files/hooks/useFileList.ts
+++ b/src/pages/files/hooks/useFileList.ts
@@ -209,6 +209,16 @@ export function useFileList() {
fetchInitial()
}, [fetchInitial])
+ /** 本地更新部分文件字段,避免不必要的列表刷新 */
+ const updateFileItems = useCallback(
+ (ids: string[], patch: Partial