From 87d45cc777c0888d27c19a0addf18fe61c103569 Mon Sep 17 00:00:00 2001 From: Lan Date: Wed, 3 Jun 2026 04:24:16 +0800 Subject: [PATCH] feat: add admin batch file deletion --- apps/admin/schemas.py | 4 ++++ apps/admin/services.py | 42 ++++++++++++++++++++++++++++++++++++++++-- apps/admin/views.py | 28 +++++++++++++++++++++++++++- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/apps/admin/schemas.py b/apps/admin/schemas.py index 2567f7c..ef68ea7 100644 --- a/apps/admin/schemas.py +++ b/apps/admin/schemas.py @@ -8,6 +8,10 @@ class IDData(BaseModel): id: int +class IDsData(BaseModel): + ids: list[int] + + class ShareItem(BaseModel): expire_value: int expire_style: str = "day" diff --git a/apps/admin/services.py b/apps/admin/services.py index be0986c..a744a2a 100644 --- a/apps/admin/services.py +++ b/apps/admin/services.py @@ -30,10 +30,48 @@ class FileService: def __init__(self): self.file_storage: FileStorageInterface = storages[settings.file_storage]() + async def _delete_file_code(self, file_code: FileCodes): + if file_code.text is None: + await self.file_storage.delete_file(file_code) + await file_code.delete() + async def delete_file(self, file_id: int): file_code = await FileCodes.get(id=file_id) - await self.file_storage.delete_file(file_code) - await file_code.delete() + await self._delete_file_code(file_code) + + async def delete_files(self, file_ids: list[int]): + unique_ids = list(dict.fromkeys(file_ids)) + deleted = [] + failed = [] + missing = [] + + for file_id in unique_ids: + file_code = await FileCodes.filter(id=file_id).first() + if not file_code: + missing.append(file_id) + continue + + try: + await self._delete_file_code(file_code) + deleted.append(file_id) + except Exception as exc: + failed.append({"id": file_id, "reason": str(exc)}) + + return { + "requestedCount": len(file_ids), + "requested_count": len(file_ids), + "uniqueCount": len(unique_ids), + "unique_count": len(unique_ids), + "deletedCount": len(deleted), + "deleted_count": len(deleted), + "missingCount": len(missing), + "missing_count": len(missing), + "failedCount": len(failed), + "failed_count": len(failed), + "deleted": deleted, + "missing": missing, + "failed": failed, + } async def list_files( self, diff --git a/apps/admin/views.py b/apps/admin/views.py index 5cdb01f..93e1954 100644 --- a/apps/admin/views.py +++ b/apps/admin/views.py @@ -14,7 +14,7 @@ from apps.admin.dependencies import ( get_config_service, get_local_file_service, ) -from apps.admin.schemas import IDData, ShareItem, DeleteItem, LoginData, UpdateFileData +from apps.admin.schemas import IDData, IDsData, ShareItem, DeleteItem, LoginData, UpdateFileData from core.response import APIResponse from apps.base.models import FileCodes, KeyValue from apps.admin.dependencies import create_token @@ -137,6 +137,32 @@ async def file_delete( return APIResponse() +async def batch_delete_files( + data: IDsData, + file_service: FileService, +): + if not data.ids: + raise HTTPException(status_code=400, detail="请选择要删除的文件") + result = await file_service.delete_files(data.ids) + return APIResponse(detail=result) + + +@admin_api.delete("/file/batch-delete") +async def file_batch_delete( + data: IDsData, + file_service: FileService = Depends(get_file_service), +): + return await batch_delete_files(data, file_service) + + +@admin_api.post("/file/batch-delete") +async def file_batch_delete_post( + data: IDsData, + file_service: FileService = Depends(get_file_service), +): + return await batch_delete_files(data, file_service) + + @admin_api.get("/file/list") async def file_list( page: int = 1,