hulai-admin-api/app/routers/seasonal_products.py
刘涛 8c0a5f489d Initial commit: hulai admin API backend
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 22:01:23 +08:00

175 行
7.5 KiB
Python

"""
Seasonal products router: serves both autumn (游牧的森林) and winter (嗨冰雪).
Mounted twice at /api/autumn-products and /api/winter-products.
"""
from __future__ import annotations
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.database import get_db
from app.auth import get_current_user
from app.models.seasonal_product import (
SeasonalProductConfig, SeasonalProductVersion,
SeasonalProductHighlight, SeasonalProductTimeline,
)
from app.schemas.seasonal_product import (
SeasonalConfigSchema, SeasonalVersionSchema, SeasonalVersionResponse,
SeasonalHighlightSchema, SeasonalHighlightResponse,
SeasonalTimelineSchema, SeasonalTimelineResponse,
)
def create_seasonal_router(season: str, label: str) -> APIRouter:
router = APIRouter(prefix=f"/api/{season}-products", tags=[f"{label}产品"], dependencies=[Depends(get_current_user)])
def _get_config(db: Session) -> SeasonalProductConfig:
config = db.query(SeasonalProductConfig).filter_by(season=season).first()
if not config:
config = SeasonalProductConfig(season=season)
db.add(config)
db.flush()
return config
@router.get("/config", response_model=SeasonalConfigSchema)
def get_config(db: Session = Depends(get_db)):
c = _get_config(db)
return SeasonalConfigSchema(
narrative=c.narrative, style=c.style, brand_name=c.brand_name,
version_label=c.version_label, season_label=c.season_label,
)
@router.put("/config")
def update_config(req: SeasonalConfigSchema, db: Session = Depends(get_db)):
c = _get_config(db)
c.narrative = req.narrative
c.style = req.style
c.brand_name = req.brand_name
c.version_label = req.version_label
c.season_label = req.season_label
db.commit()
return {"message": "更新成功"}
# --- Versions ---
@router.get("/versions", response_model=list[SeasonalVersionResponse])
def list_versions(db: Session = Depends(get_db)):
rows = db.query(SeasonalProductVersion).filter_by(season=season).order_by(SeasonalProductVersion.sort_order).all()
return [
SeasonalVersionResponse(
id=v.id, version_id=v.version_id, name=v.name, days=v.days, nights=v.nights,
tag=v.tag, line=v.line, route=v.route, audience=v.audience,
description=v.description, highlights=v.highlights or [], itinerary=v.itinerary or [],
sort_order=v.sort_order,
)
for v in rows
]
@router.post("/versions", response_model=SeasonalVersionResponse, status_code=201)
def create_version(req: SeasonalVersionSchema, db: Session = Depends(get_db)):
v = SeasonalProductVersion(
season=season, version_id=req.version_id, name=req.name,
days=req.days, nights=req.nights, tag=req.tag, line=req.line,
route=req.route, audience=req.audience, description=req.description,
highlights=req.highlights, itinerary=req.itinerary,
)
db.add(v)
db.commit()
db.refresh(v)
return SeasonalVersionResponse(
id=v.id, version_id=v.version_id, name=v.name, days=v.days, nights=v.nights,
tag=v.tag, line=v.line, route=v.route, audience=v.audience,
description=v.description, highlights=v.highlights or [], itinerary=v.itinerary or [],
sort_order=v.sort_order,
)
@router.put("/versions/{v_id}")
def update_version(v_id: int, req: SeasonalVersionSchema, db: Session = Depends(get_db)):
v = db.query(SeasonalProductVersion).get(v_id)
if not v or v.season != season:
raise HTTPException(status_code=404, detail="版本不存在")
v.version_id = req.version_id
v.name = req.name
v.days = req.days
v.nights = req.nights
v.tag = req.tag
v.line = req.line
v.route = req.route
v.audience = req.audience
v.description = req.description
v.highlights = req.highlights
v.itinerary = req.itinerary
db.commit()
return {"message": "更新成功"}
@router.delete("/versions/{v_id}")
def delete_version(v_id: int, db: Session = Depends(get_db)):
v = db.query(SeasonalProductVersion).get(v_id)
if not v or v.season != season:
raise HTTPException(status_code=404, detail="版本不存在")
db.delete(v)
db.commit()
return {"message": "删除成功"}
# --- Highlights ---
@router.get("/highlights", response_model=list[SeasonalHighlightResponse])
def list_highlights(category: str = None, db: Session = Depends(get_db)):
q = db.query(SeasonalProductHighlight).filter_by(season=season)
if category:
q = q.filter_by(category=category)
return [
SeasonalHighlightResponse(id=h.id, category=h.category, title=h.title, description=h.description, sort_order=h.sort_order)
for h in q.order_by(SeasonalProductHighlight.sort_order).all()
]
@router.put("/highlights")
def update_highlights(items: list[SeasonalHighlightSchema], db: Session = Depends(get_db)):
db.query(SeasonalProductHighlight).filter_by(season=season).delete()
for i, h in enumerate(items):
db.add(SeasonalProductHighlight(season=season, category=h.category, title=h.title, description=h.description, sort_order=i))
db.commit()
return {"message": "亮点更新成功"}
# --- Timeline ---
@router.get("/timeline", response_model=list[SeasonalTimelineResponse])
def list_timeline(db: Session = Depends(get_db)):
rows = db.query(SeasonalProductTimeline).filter_by(season=season).order_by(SeasonalProductTimeline.sort_order).all()
return [
SeasonalTimelineResponse(id=t.id, version=t.version, date=t.date, title=t.title, changes=t.changes or [], reason=t.reason, sort_order=t.sort_order)
for t in rows
]
@router.post("/timeline", response_model=SeasonalTimelineResponse, status_code=201)
def create_timeline(req: SeasonalTimelineSchema, db: Session = Depends(get_db)):
t = SeasonalProductTimeline(season=season, version=req.version, date=req.date, title=req.title, changes=req.changes, reason=req.reason)
db.add(t)
db.commit()
db.refresh(t)
return SeasonalTimelineResponse(id=t.id, version=t.version, date=t.date, title=t.title, changes=t.changes or [], reason=t.reason, sort_order=t.sort_order)
@router.put("/timeline/{t_id}")
def update_timeline(t_id: int, req: SeasonalTimelineSchema, db: Session = Depends(get_db)):
t = db.query(SeasonalProductTimeline).get(t_id)
if not t or t.season != season:
raise HTTPException(status_code=404, detail="时间线不存在")
t.version = req.version
t.date = req.date
t.title = req.title
t.changes = req.changes
t.reason = req.reason
db.commit()
return {"message": "更新成功"}
@router.delete("/timeline/{t_id}")
def delete_timeline(t_id: int, db: Session = Depends(get_db)):
t = db.query(SeasonalProductTimeline).get(t_id)
if not t or t.season != season:
raise HTTPException(status_code=404, detail="时间线不存在")
db.delete(t)
db.commit()
return {"message": "删除成功"}
return router
autumn_router = create_seasonal_router("autumn", "秋季")
winter_router = create_seasonal_router("winter", "冬季")