Files
fquiz/api/app/api/v1/tower_models.py
T
chengkai3 6a653a4960 fix:[FL-220][菜单禁用访问控制]
Co-authored-by: multica-agent <github@multica.ai>
2026-06-20 18:40:29 +08:00

177 lines
6.4 KiB
Python

from __future__ import annotations
from fastapi import APIRouter, Depends, File, HTTPException, Query, UploadFile, status
from fastapi.responses import StreamingResponse
from sqlalchemy.orm import Session
from ...core.database import get_db
from ...core.dependencies import CurrentUser, require_any_permission, require_enabled_menu_route, require_permission
from ...schemas.tower_model import (
TowerModelCreateRequest,
TowerModelImageUploadResponse,
TowerModelListResponse,
TowerModelSeedResponse,
TowerModelSummary,
TowerModelUpdateRequest,
)
from ...services.file_service import download_file_from_path
from ...services.tower_model_service import (
create_tower_model,
delete_tower_model,
get_tower_model_by_id,
list_tower_models,
list_tower_models_for_selector,
seed_tower_models_from_legacy,
seed_tower_models_from_upload,
serialize_tower_model,
update_tower_model,
upload_tower_model_image,
)
router = APIRouter(prefix="/tower-models", tags=["tower-models"], dependencies=[Depends(require_enabled_menu_route)])
@router.get("", response_model=TowerModelListResponse)
def get_tower_model_list(
limit: int = Query(default=50, ge=1, le=200),
offset: int = Query(default=0, ge=0),
keyword: str | None = Query(default=None),
enabled: bool | None = Query(default=None),
_: CurrentUser = Depends(require_any_permission("tower_model.read", "tower_model.manage", "tower.read", "tower.manage")),
db: Session = Depends(get_db),
) -> TowerModelListResponse:
return list_tower_models(
db,
limit=limit,
offset=offset,
keyword=keyword,
enabled=enabled,
)
@router.get("/selector", response_model=list[TowerModelSummary])
def get_tower_model_selector(
_: CurrentUser = Depends(require_any_permission("tower_model.read", "tower_model.manage", "tower.read", "tower.manage")),
db: Session = Depends(get_db),
) -> list[TowerModelSummary]:
return list_tower_models_for_selector(db)
@router.post("", response_model=TowerModelSummary)
def create_tower_model_endpoint(
payload: TowerModelCreateRequest,
current_user: CurrentUser = Depends(require_permission("tower_model.manage")),
db: Session = Depends(get_db),
) -> TowerModelSummary:
created = create_tower_model(db, payload, actor=current_user.user)
if not created:
raise HTTPException(status_code=status.HTTP_409_CONFLICT, detail="杆塔模型编码已存在")
return created
@router.patch("/{model_id}", response_model=TowerModelSummary)
def update_tower_model_endpoint(
model_id: str,
payload: TowerModelUpdateRequest,
current_user: CurrentUser = Depends(require_permission("tower_model.manage")),
db: Session = Depends(get_db),
) -> TowerModelSummary:
updated = update_tower_model(db, model_id, payload, actor=current_user.user)
if not updated:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="杆塔模型不存在")
return updated
@router.delete("/{model_id}")
def delete_tower_model_endpoint(
model_id: str,
_: CurrentUser = Depends(require_permission("tower_model.manage")),
db: Session = Depends(get_db),
) -> dict[str, bool]:
deleted = delete_tower_model(db, model_id)
if not deleted:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="杆塔模型不存在")
return {"success": True}
@router.post("/{model_id}/image", response_model=TowerModelImageUploadResponse)
def upload_tower_model_image_endpoint(
model_id: str,
mount_code: str = Query(..., min_length=2, max_length=64),
file: UploadFile = File(...),
current_user: CurrentUser = Depends(require_permission("tower_model.manage")),
db: Session = Depends(get_db),
) -> TowerModelImageUploadResponse:
return upload_tower_model_image(
db,
model_id=model_id,
mount_code=mount_code,
file=file,
actor=current_user.user,
)
@router.get("/{model_id}/image")
def get_tower_model_image(
model_id: str,
_: CurrentUser = Depends(require_any_permission("tower_model.read", "tower_model.manage", "tower.read", "tower.manage")),
db: Session = Depends(get_db),
) -> StreamingResponse:
item = get_tower_model_by_id(db, model_id)
if not item:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="杆塔模型不存在")
if not item.image_mount_code or not item.image_path:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="杆塔模型未配置图片")
filename, content, content_type = download_file_from_path(
db,
mount_code=item.image_mount_code,
path=item.image_path,
)
headers = {"Content-Disposition": f'inline; filename="{filename}"'}
return StreamingResponse(iter([content]), media_type=content_type or "application/octet-stream", headers=headers)
@router.post("/seed/legacy", response_model=TowerModelSeedResponse)
def seed_legacy_tower_models_endpoint(
overwrite_existing: bool = Query(default=False),
current_user: CurrentUser = Depends(require_permission("tower_model.manage")),
db: Session = Depends(get_db),
) -> TowerModelSeedResponse:
return seed_tower_models_from_legacy(
db,
actor=current_user.user,
overwrite_existing=overwrite_existing,
)
@router.post("/seed/upload", response_model=TowerModelSeedResponse)
def seed_uploaded_tower_models_endpoint(
overwrite_existing: bool = Query(default=False),
setting_file: UploadFile = File(...),
ganta_file: UploadFile = File(...),
images_zip: UploadFile | None = File(default=None),
current_user: CurrentUser = Depends(require_permission("tower_model.manage")),
db: Session = Depends(get_db),
) -> TowerModelSeedResponse:
return seed_tower_models_from_upload(
db,
actor=current_user.user,
overwrite_existing=overwrite_existing,
setting_file=setting_file,
ganta_file=ganta_file,
images_zip=images_zip,
)
@router.get("/{model_id}", response_model=TowerModelSummary)
def get_tower_model_detail(
model_id: str,
_: CurrentUser = Depends(require_any_permission("tower_model.read", "tower_model.manage", "tower.read", "tower.manage")),
db: Session = Depends(get_db),
) -> TowerModelSummary:
item = get_tower_model_by_id(db, model_id)
if not item:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="杆塔模型不存在")
return serialize_tower_model(item)