# -*- coding: utf-8 -*- """运营端业务管理端点:任务 / 服务商 / 内容 / 系统配置 / 数据统计。 全部要求 operator 角色(内部子角色再按权限细分),并写审计日志。 """ from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException, Request from pydantic import BaseModel from ..dependencies import get_db from ...rbac import require_permission, require_roles, write_audit from ...infrastructure.repositories import Database router = APIRouter(prefix="/admin", tags=["admin-op"]) class TaskCreateRequest(BaseModel): title: str category: str = "" sub_category: str = "" description: str = "" mode: str = "grab" budget_min: int = 0 budget_max: int = 0 deadline: str = "" publisher_name: str = "" class TaskStatusRequest(BaseModel): status: str # review/published/completed/cancelled class ProviderCreateRequest(BaseModel): name: str category: str = "" level: str = "certified" status: str = "pending" contact: str = "" class ProviderUpdateRequest(BaseModel): level: str | None = None status: str | None = None contact: str | None = None class ContentCreateRequest(BaseModel): type: str = "news" title: str summary: str = "" body: str = "" status: str = "draft" class ContentStatusRequest(BaseModel): status: str # published/offline/draft class ConfigUpdateRequest(BaseModel): value: str description: str = "" # ── 任务管理 ────────────────────────────────────────────────────────────── @router.get("/tasks", summary="任务列表") async def list_tasks( status: str | None = None, db: Database = Depends(get_db), _u: dict = Depends(require_roles("operator")), ): return await db.tasks.list(status=status) @router.post("/tasks", summary="创建任务") async def create_task( req: TaskCreateRequest, request: Request, db: Database = Depends(get_db), actor: dict = Depends(require_permission("action:task.manage")), ): task = await db.tasks.create(req.model_dump(exclude_none=True)) await write_audit(db, action="task.create", resource="task", resource_id=task["id"], detail=task["title"], user=actor, request=request) return task @router.post("/tasks/{task_id}/status", summary="更新任务状态") async def set_task_status( task_id: str, req: TaskStatusRequest, request: Request, db: Database = Depends(get_db), actor: dict = Depends(require_permission("action:task.manage")), ): if await db.tasks.get(task_id) is None: raise HTTPException(status_code=404, detail="Task not found") task = await db.tasks.set_status(task_id, req.status) await write_audit(db, action="task.status", resource="task", resource_id=task_id, detail=req.status, user=actor, request=request) return task # ── 服务商管理 ──────────────────────────────────────────────────────────── @router.get("/providers", summary="服务商列表") async def list_providers( status: str | None = None, db: Database = Depends(get_db), _u: dict = Depends(require_roles("operator")), ): return await db.providers.list(status=status) @router.post("/providers", summary="创建服务商") async def create_provider( req: ProviderCreateRequest, request: Request, db: Database = Depends(get_db), actor: dict = Depends(require_permission("action:provider.manage")), ): prov = await db.providers.create(req.model_dump(exclude_none=True)) await write_audit(db, action="provider.create", resource="provider", resource_id=prov["id"], detail=prov["name"], user=actor, request=request) return prov @router.post("/providers/{provider_id}/update", summary="更新服务商(评级/状态)") async def update_provider( provider_id: str, req: ProviderUpdateRequest, request: Request, db: Database = Depends(get_db), actor: dict = Depends(require_permission("action:provider.manage")), ): updated = await db.providers.update(provider_id, req.model_dump(exclude_none=True)) if updated is None: raise HTTPException(status_code=404, detail="Provider not found") await write_audit(db, action="provider.update", resource="provider", resource_id=provider_id, detail=str(req.model_dump(exclude_none=True)), user=actor, request=request) return updated # ── 内容管理 ────────────────────────────────────────────────────────────── @router.get("/content", summary="内容列表") async def list_content( ctype: str | None = None, status: str | None = None, db: Database = Depends(get_db), _u: dict = Depends(require_roles("operator")), ): return await db.content.list(ctype=ctype, status=status) @router.post("/content", summary="创建内容") async def create_content( req: ContentCreateRequest, request: Request, db: Database = Depends(get_db), actor: dict = Depends(require_permission("action:content.manage")), ): item = await db.content.create(req.model_dump(exclude_none=True)) await write_audit(db, action="content.create", resource="content", resource_id=item["id"], detail=item["title"], user=actor, request=request) return item @router.post("/content/{content_id}/status", summary="发布/下架内容") async def set_content_status( content_id: str, req: ContentStatusRequest, request: Request, db: Database = Depends(get_db), actor: dict = Depends(require_permission("action:content.manage")), ): item = await db.content.set_status(content_id, req.status) if item is None: raise HTTPException(status_code=404, detail="Content not found") await write_audit(db, action="content.status", resource="content", resource_id=content_id, detail=req.status, user=actor, request=request) return item # ── 系统配置 ────────────────────────────────────────────────────────────── @router.get("/config", summary="系统配置列表") async def list_config( db: Database = Depends(get_db), _u: dict = Depends(require_roles("operator")), ): return await db.config.all() @router.put("/config/{key}", summary="更新系统配置") async def set_config( key: str, req: ConfigUpdateRequest, request: Request, db: Database = Depends(get_db), actor: dict = Depends(require_permission("action:config.manage")), ): cfg = await db.config.set(key, req.value, req.description) await write_audit(db, action="config.update", resource="config", resource_id=key, detail=req.value, user=actor, request=request) return cfg # ── 数据统计 ────────────────────────────────────────────────────────────── @router.get("/stats/overview", summary="运营数据总览") async def stats_overview( db: Database = Depends(get_db), _u: dict = Depends(require_roles("operator")), ): return await db.stats.overview()