From 2fa1faebe0ddb51f5359018deeaa0cf5e7c1dd81 Mon Sep 17 00:00:00 2001 From: Lan Date: Wed, 3 Jun 2026 04:38:30 +0800 Subject: [PATCH] feat: add admin batch file policy update --- apps/admin/schemas.py | 8 ++++++ apps/admin/services.py | 34 +++++++++++++++++++++++++ apps/admin/views.py | 57 +++++++++++++++++++++++++++++++++++++++++- 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/apps/admin/schemas.py b/apps/admin/schemas.py index ef68ea7..50a5083 100644 --- a/apps/admin/schemas.py +++ b/apps/admin/schemas.py @@ -33,3 +33,11 @@ class UpdateFileData(BaseModel): suffix: Optional[str] = None expired_at: Optional[Union[datetime.datetime, str]] = None expired_count: Optional[int] = None + + +class BatchUpdateFileData(BaseModel): + ids: list[int] + expired_at: Optional[Union[datetime.datetime, str]] = None + expired_count: Optional[int] = None + clearExpiredAt: Optional[bool] = None + clear_expired_at: Optional[bool] = None diff --git a/apps/admin/services.py b/apps/admin/services.py index a744a2a..9e1ad7c 100644 --- a/apps/admin/services.py +++ b/apps/admin/services.py @@ -73,6 +73,40 @@ class FileService: "failed": failed, } + async def update_files(self, file_ids: list[int], update_data: dict[str, Any]): + unique_ids = list(dict.fromkeys(file_ids)) + updated = [] + 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 file_code.update_from_dict(update_data).save() + updated.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), + "updatedCount": len(updated), + "updated_count": len(updated), + "missingCount": len(missing), + "missing_count": len(missing), + "failedCount": len(failed), + "failed_count": len(failed), + "updated": updated, + "missing": missing, + "failed": failed, + } + async def list_files( self, page: int, diff --git a/apps/admin/views.py b/apps/admin/views.py index 93e1954..14d5d14 100644 --- a/apps/admin/views.py +++ b/apps/admin/views.py @@ -14,7 +14,15 @@ from apps.admin.dependencies import ( get_config_service, get_local_file_service, ) -from apps.admin.schemas import IDData, IDsData, ShareItem, DeleteItem, LoginData, UpdateFileData +from apps.admin.schemas import ( + IDData, + IDsData, + BatchUpdateFileData, + ShareItem, + DeleteItem, + LoginData, + UpdateFileData, +) from core.response import APIResponse from apps.base.models import FileCodes, KeyValue from apps.admin.dependencies import create_token @@ -163,6 +171,53 @@ async def file_batch_delete_post( return await batch_delete_files(data, file_service) +async def batch_update_files( + data: BatchUpdateFileData, + file_service: FileService, +): + if not data.ids: + raise HTTPException(status_code=400, detail="请选择要更新的文件") + + update_data = {} + fields_set = data.model_fields_set + should_clear_expired_at = bool(data.clearExpiredAt or data.clear_expired_at) + + if should_clear_expired_at: + update_data["expired_at"] = None + update_data["expired_count"] = -1 + elif "expired_at" in fields_set and data.expired_at != "": + update_data["expired_at"] = data.expired_at + + if ( + not should_clear_expired_at + and "expired_count" in fields_set + and data.expired_count is not None + ): + update_data["expired_count"] = data.expired_count + + if not update_data: + raise HTTPException(status_code=400, detail="请选择要更新的字段") + + result = await file_service.update_files(data.ids, update_data) + return APIResponse(detail=result) + + +@admin_api.patch("/file/batch-update") +async def file_batch_update( + data: BatchUpdateFileData, + file_service: FileService = Depends(get_file_service), +): + return await batch_update_files(data, file_service) + + +@admin_api.post("/file/batch-update") +async def file_batch_update_post( + data: BatchUpdateFileData, + file_service: FileService = Depends(get_file_service), +): + return await batch_update_files(data, file_service) + + @admin_api.get("/file/list") async def file_list( page: int = 1,