"""Force-situation task detail API(力量态势任务详情,新类型任务). 与既有 task-analysis 数据交付接口完全独立:一个任务一份**自由 JSON 详情文档** (整体存储、整体替换,数据库不定死字段)。文档内容由消费方与产出方约定, 当前包含时间轴(重要时间节点)、任务衔接、页面单块内容等区块。 Routes (credential-free internal integration endpoints): GET /api/force-situation/tasks/{task_id}/detail PUT /api/force-situation/tasks/{task_id}/detail """ from __future__ import annotations from typing import Any from fastapi import APIRouter, Body, HTTPException, Query, Request from pydantic import BaseModel, Field router = APIRouter(prefix="/api/force-situation", tags=["force-situation"]) class ForceSituationDetailUpdate(BaseModel): """PUT body: 整体替换任务详情文档。""" detail: dict[str, Any] = Field(default_factory=dict) def _store(request: Request): store = getattr(request.app.state, "force_situation_store", None) if store is None: raise HTTPException(status_code=503, detail="力量态势详情存储未初始化") return store def _payload(record: dict[str, Any]) -> dict[str, Any]: return { "task_id": record.get("task_id"), "detail": record.get("detail") or {}, "updated_by": record.get("updated_by"), "updated_at": record.get("updated_at"), } @router.get("/tasks/{task_id}/detail") async def get_force_situation_detail( task_id: str, request: Request, version: int | None = Query(default=None, description="历史版本号;缺省返回当前最新"), ) -> dict[str, Any]: """读取任务详情文档;任务无数据时 404(前端回退本地演示数据)。 ``?version=N`` 返回该历史版本(时间轴刻度回看)。 """ if version is None: record = await _store(request).get_detail(task_id) if record is None: raise HTTPException(status_code=404, detail="任务详情不存在") return _payload(record) version_record = await _store(request).get_version(task_id, version) if version_record is None: raise HTTPException(status_code=404, detail=f"版本 {version} 不存在") return { "task_id": task_id, "version": version_record.get("version"), "detail": version_record.get("detail") or {}, "created_at": version_record.get("created_at"), "updated_by": version_record.get("updated_by"), } @router.get("/tasks/{task_id}/versions") async def list_force_situation_versions( task_id: str, request: Request, limit: int = Query(default=100, ge=1, le=500), ) -> dict[str, Any]: """版本列表(时间轴刻度,按版本号升序):``{version, created_at, updated_by}``。""" versions = await _store(request).list_versions(task_id, limit=limit) return {"task_id": task_id, "total": len(versions), "versions": versions} @router.put("/tasks/{task_id}/detail") async def put_force_situation_detail( task_id: str, request: Request, body: ForceSituationDetailUpdate = Body(...), ) -> dict[str, Any]: """整体替换任务详情文档(JSON 对象;结构自由,字段由消费方约定)。""" record = await _store(request).upsert_detail( task_id, body.detail, updated_by=None ) return _payload(record)