Major changes: - New frontend (platform/web/): Vite + React 18 + TypeScript + Tailwind - 4-module navigation: 数据送标 / 模型管理 / 车队管理 / 系统管理 - Data catalog with charts (DMS/ADAS/Lane 3-tab view) - Quality review workflow (标注质检): Good/Fine/Bad scoring with auto-advance - Audit enhancements: batch operations, rejection categories, Feishu notifications - Operation audit log (操作日志) - World model simulation studio (仿真工坊) - Dataset version management with snapshots and diff - ADAS 7-class dataset integration (138K images organized + compressed) - User management with Feishu integration and pagination - CRUD/search/filter on all pages, card layout redesign - PIL-optimized image overlay rendering - Auto-snapshot on build, in_review workflow stage - Removed embedded algorithm code (now in workspace)
134 lines
4.1 KiB
Python
134 lines
4.1 KiB
Python
"""平台批次送标申请 API。"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Annotated, Any
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from pydantic import BaseModel, Field
|
|
|
|
from as_platform.auth.deps import get_current_user, require_any_permission
|
|
from as_platform.db.models import User
|
|
from as_platform.deliveries import service as delivery_svc
|
|
|
|
router = APIRouter(prefix="/api/v1/deliveries", tags=["deliveries"])
|
|
|
|
|
|
class DeliveryBody(BaseModel):
|
|
project: str = "dms"
|
|
task: str | None = None
|
|
mode: str | None = None
|
|
batch_name: str = ""
|
|
source_type: str | None = None
|
|
vehicle_scene: str | None = None
|
|
collection_start: str | None = None
|
|
collection_end: str | None = None
|
|
data_path: str = ""
|
|
estimated_count: int | None = None
|
|
remark: str | None = None
|
|
owner_user_id: int | None = None
|
|
owner_name: str | None = None
|
|
|
|
|
|
class DeliveryPatchBody(BaseModel):
|
|
project: str | None = None
|
|
task: str | None = None
|
|
mode: str | None = None
|
|
batch_name: str | None = None
|
|
source_type: str | None = None
|
|
vehicle_scene: str | None = None
|
|
collection_start: str | None = None
|
|
collection_end: str | None = None
|
|
data_path: str | None = None
|
|
estimated_count: int | None = None
|
|
remark: str | None = None
|
|
owner_user_id: int | None = None
|
|
owner_name: str | None = None
|
|
|
|
|
|
@router.get("")
|
|
def api_list_deliveries(
|
|
_user: Annotated[User, Depends(require_any_permission("read:deliveries", "read:pending", "*"))],
|
|
status: str | None = Query(None),
|
|
mine: bool = Query(False),
|
|
mine_editable: bool = Query(False, description="待我处理:仅草稿/驳回"),
|
|
offset: int = Query(0, ge=0),
|
|
limit: int = Query(20, ge=1, le=100),
|
|
) -> dict[str, Any]:
|
|
mine_id = _user.id if mine or mine_editable else None
|
|
return delivery_svc.list_deliveries(
|
|
status=status,
|
|
mine_user_id=mine_id,
|
|
mine_editable_only=mine_editable,
|
|
offset=offset,
|
|
limit=limit,
|
|
)
|
|
|
|
|
|
@router.get("/{delivery_id}")
|
|
def api_get_delivery(
|
|
delivery_id: str,
|
|
_user: Annotated[User, Depends(require_any_permission("read:deliveries", "read:pending", "*"))],
|
|
) -> dict[str, Any]:
|
|
row = delivery_svc.get_delivery(delivery_id)
|
|
if not row:
|
|
raise HTTPException(404, "送标申请不存在")
|
|
return row
|
|
|
|
|
|
@router.post("")
|
|
def api_create_delivery(
|
|
body: DeliveryBody,
|
|
user: Annotated[User, Depends(require_any_permission("write:delivery_submit", "*"))],
|
|
) -> dict[str, Any]:
|
|
try:
|
|
return delivery_svc.create_delivery(body.model_dump(), user)
|
|
except ValueError as e:
|
|
raise HTTPException(400, str(e)) from e
|
|
|
|
|
|
@router.patch("/{delivery_id}")
|
|
def api_patch_delivery(
|
|
delivery_id: str,
|
|
body: DeliveryPatchBody,
|
|
user: Annotated[User, Depends(require_any_permission("write:delivery_submit", "*"))],
|
|
) -> dict[str, Any]:
|
|
data = body.model_dump(exclude_unset=True)
|
|
try:
|
|
return delivery_svc.update_delivery(delivery_id, data, user)
|
|
except ValueError as e:
|
|
raise HTTPException(400, str(e)) from e
|
|
|
|
|
|
@router.post("/{delivery_id}/submit")
|
|
def api_submit_delivery(
|
|
delivery_id: str,
|
|
user: Annotated[User, Depends(require_any_permission("write:delivery_submit", "*"))],
|
|
) -> dict[str, Any]:
|
|
try:
|
|
return delivery_svc.submit_delivery_for_review(delivery_id, user)
|
|
except ValueError as e:
|
|
raise HTTPException(400, str(e)) from e
|
|
|
|
|
|
@router.post("/{delivery_id}/retry-ingest")
|
|
def api_retry_delivery_ingest(
|
|
delivery_id: str,
|
|
user: Annotated[User, Depends(require_any_permission("write:delivery_submit", "*"))],
|
|
) -> dict[str, Any]:
|
|
try:
|
|
return delivery_svc.retry_delivery_ingest(delivery_id, user)
|
|
except ValueError as e:
|
|
raise HTTPException(400, str(e)) from e
|
|
|
|
|
|
@router.delete("/{delivery_id}")
|
|
def api_delete_delivery(
|
|
delivery_id: str,
|
|
user: Annotated[User, Depends(require_any_permission("write:delivery_submit", "*"))],
|
|
) -> dict[str, Any]:
|
|
try:
|
|
delivery_svc.delete_delivery(delivery_id, user)
|
|
return {"ok": True}
|
|
except ValueError as e:
|
|
raise HTTPException(400, str(e)) from e
|