From 3467e973ac39bb9611329aceb36116cde5c1469a Mon Sep 17 00:00:00 2001 From: Lan Date: Wed, 3 Jun 2026 06:22:56 +0800 Subject: [PATCH] feat: add batch file policy actions --- apps/admin/schemas.py | 7 +++++ apps/admin/services.py | 63 ++++++++++++++++++++++++++++++++++++++++++ apps/admin/views.py | 36 ++++++++++++++++++++++++ 3 files changed, 106 insertions(+) diff --git a/apps/admin/schemas.py b/apps/admin/schemas.py index 42bfe6c..b157daf 100644 --- a/apps/admin/schemas.py +++ b/apps/admin/schemas.py @@ -48,3 +48,10 @@ class FilePolicyActionData(BaseModel): action: str downloadLimit: Optional[int] = None download_limit: Optional[int] = None + + +class BatchFilePolicyActionData(BaseModel): + ids: list[int] + action: str + downloadLimit: Optional[int] = None + download_limit: Optional[int] = None diff --git a/apps/admin/services.py b/apps/admin/services.py index b7348bb..4f42552 100644 --- a/apps/admin/services.py +++ b/apps/admin/services.py @@ -15,6 +15,13 @@ from core.utils import get_now, hash_password, is_password_hashed class FileService: + POLICY_ACTIONS = { + "extend_24h", + "extend_7d", + "make_permanent", + "reset_download_limit", + } + SORT_FIELDS = { "created_at", "createdat", @@ -129,6 +136,62 @@ class FileService: await file_code.update_from_dict(update_data).save() return await self.get_file_detail(file_id) + async def apply_files_policy_action( + self, + file_ids: list[int], + action: str, + download_limit: Optional[int] = None, + ) -> dict[str, Any]: + unique_ids = list(dict.fromkeys(file_ids)) + updated = [] + failed = [] + missing = [] + action = action.strip().lower() + + if action not in self.POLICY_ACTIONS: + raise HTTPException(status_code=400, detail="不支持的策略动作") + + if action == "reset_download_limit": + next_limit = download_limit if download_limit is not None else 5 + if next_limit < 1: + raise HTTPException(status_code=400, detail="取件次数必须大于 0") + + now = await get_now() + 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: + update_data = self._build_policy_action_update( + file_code=file_code, + action=action, + now=now, + download_limit=download_limit, + ) + 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), + "action": action, + "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 31c02f8..0106910 100644 --- a/apps/admin/views.py +++ b/apps/admin/views.py @@ -18,6 +18,7 @@ from apps.admin.schemas import ( IDData, IDsData, BatchUpdateFileData, + BatchFilePolicyActionData, FilePolicyActionData, ShareItem, DeleteItem, @@ -254,6 +255,41 @@ async def file_policy_action_post( return await apply_file_policy_action(data, file_service) +async def apply_batch_file_policy_action( + data: BatchFilePolicyActionData, + file_service: FileService, +): + if not data.ids: + raise HTTPException(status_code=400, detail="请选择要更新的文件") + + download_limit = data.downloadLimit + if download_limit is None: + download_limit = data.download_limit + + result = await file_service.apply_files_policy_action( + file_ids=data.ids, + action=data.action, + download_limit=download_limit, + ) + return APIResponse(detail=result) + + +@admin_api.patch("/file/batch-policy-action") +async def file_batch_policy_action( + data: BatchFilePolicyActionData, + file_service: FileService = Depends(get_file_service), +): + return await apply_batch_file_policy_action(data, file_service) + + +@admin_api.post("/file/batch-policy-action") +async def file_batch_policy_action_post( + data: BatchFilePolicyActionData, + file_service: FileService = Depends(get_file_service), +): + return await apply_batch_file_policy_action(data, file_service) + + @admin_api.get("/file/list") async def file_list( page: int = 1,