from pathlib import Path from fastapi import APIRouter, Depends, File, HTTPException, UploadFile from fastapi.responses import FileResponse from sqlalchemy.orm import Session from app.auth import require_admin from app.database import get_db from app.models import User from app.schemas import SystemSettingsOut, SystemSettingsUpdate from app.system_settings import ( clear_logo_files, ensure_upload_dir, find_logo_file, get_or_create_settings, logo_path, public_logo_url, ) router = APIRouter(prefix="/api", tags=["settings"]) ALLOWED_LOGO_EXT = {".png", ".jpg", ".jpeg", ".webp", ".svg", ".gif"} MAX_LOGO_BYTES = 2 * 1024 * 1024 def _settings_out(db: Session) -> SystemSettingsOut: row = get_or_create_settings(db) return SystemSettingsOut(system_name=row.system_name, logo_url=public_logo_url(row.logo_ext or None)) @router.get("/settings", response_model=SystemSettingsOut) def get_settings(db: Session = Depends(get_db)): return _settings_out(db) @router.get("/settings/logo") def get_logo(db: Session = Depends(get_db)): row = get_or_create_settings(db) path = find_logo_file(row.logo_ext or None) if not path: raise HTTPException(404, detail="未设置 Logo") media = { ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp", ".svg": "image/svg+xml", ".gif": "image/gif", }.get(path.suffix.lower(), "application/octet-stream") return FileResponse(path, media_type=media) @router.put("/admin/settings", response_model=SystemSettingsOut) def update_settings( body: SystemSettingsUpdate, db: Session = Depends(get_db), _: User = Depends(require_admin), ): row = get_or_create_settings(db) row.system_name = body.system_name.strip() db.commit() db.refresh(row) return _settings_out(db) @router.post("/admin/settings/logo", response_model=SystemSettingsOut) async def upload_logo( file: UploadFile = File(...), db: Session = Depends(get_db), _: User = Depends(require_admin), ): if not file.filename: raise HTTPException(400, detail="请选择文件") ext = Path(file.filename).suffix.lower() if ext not in ALLOWED_LOGO_EXT: raise HTTPException(400, detail="仅支持 png、jpg、webp、svg、gif") content = await file.read() if len(content) > MAX_LOGO_BYTES: raise HTTPException(400, detail="Logo 不能超过 2MB") ensure_upload_dir() clear_logo_files() ext_clean = ext.lstrip(".") dest = logo_path(ext_clean) dest.write_bytes(content) row = get_or_create_settings(db) row.logo_ext = ext_clean db.commit() db.refresh(row) return _settings_out(db) @router.delete("/admin/settings/logo", response_model=SystemSettingsOut) def delete_logo( db: Session = Depends(get_db), _: User = Depends(require_admin), ): clear_logo_files() row = get_or_create_settings(db) row.logo_ext = "" db.commit() db.refresh(row) return _settings_out(db)