333 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
数据查询API路由
支持景区、产品、风格、受众等基础数据的查询
"""
import logging
from typing import List, Dict, Any, Optional
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel, Field
from api.services.database_service import DatabaseService
from api.dependencies import get_database_service
logger = logging.getLogger(__name__)
router = APIRouter(
prefix="/data",
tags=["data"],
responses={404: {"description": "Not found"}},
)
class ScenicSpotResponse(BaseModel):
"""景区响应模型"""
id: int = Field(..., description="景区ID")
name: str = Field(..., description="景区名称")
address: Optional[str] = Field(None, description="地址")
description: Optional[str] = Field(None, description="描述")
advantage: Optional[str] = Field(None, description="优势")
highlight: Optional[str] = Field(None, description="亮点")
isPublic: bool = Field(..., description="是否公开")
userId: int = Field(..., description="用户ID")
class ProductResponse(BaseModel):
"""产品响应模型"""
id: int = Field(..., description="产品ID")
name: str = Field(..., description="产品名称")
originPrice: Optional[float] = Field(None, description="原价")
realPrice: Optional[float] = Field(None, description="实际价格")
packageInfo: Optional[str] = Field(None, description="套票信息")
description: Optional[str] = Field(None, description="描述")
advantage: Optional[str] = Field(None, description="优势")
highlight: Optional[str] = Field(None, description="亮点")
isPublic: bool = Field(..., description="是否公开")
userId: int = Field(..., description="用户ID")
class StyleResponse(BaseModel):
"""风格响应模型"""
id: int = Field(..., description="风格ID")
styleName: str = Field(..., description="风格名称")
description: Optional[str] = Field(None, description="描述")
class AudienceResponse(BaseModel):
"""受众响应模型"""
id: int = Field(..., description="受众ID")
audienceName: str = Field(..., description="受众名称")
description: Optional[str] = Field(None, description="描述")
@router.get("/scenic-spots", response_model=List[ScenicSpotResponse], summary="获取景区列表")
async def get_scenic_spots(
user_id: Optional[int] = Query(None, description="用户ID如果提供则只返回该用户的景区"),
is_public: Optional[bool] = Query(None, description="是否公开,如果提供则过滤公开/私有景区"),
db_service: DatabaseService = Depends(get_database_service)
):
"""
获取景区列表
- **user_id**: 用户ID如果提供则只返回该用户的景区
- **is_public**: 是否公开,如果提供则过滤公开/私有景区
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
spots = db_service.list_all_scenic_spots(user_id=user_id, is_public=is_public)
return [ScenicSpotResponse(**spot) for spot in spots]
except Exception as e:
logger.error(f"获取景区列表失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"获取景区列表失败: {str(e)}")
@router.get("/scenic-spots/{spot_id}", response_model=ScenicSpotResponse, summary="根据ID获取景区信息")
async def get_scenic_spot_by_id(
spot_id: int,
db_service: DatabaseService = Depends(get_database_service)
):
"""
根据ID获取景区信息
- **spot_id**: 景区ID
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
spot = db_service.get_scenic_spot_by_id(spot_id)
if not spot:
raise HTTPException(status_code=404, detail=f"未找到ID为{spot_id}的景区")
return ScenicSpotResponse(**spot)
except HTTPException:
raise
except Exception as e:
logger.error(f"获取景区信息失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"获取景区信息失败: {str(e)}")
@router.get("/products", response_model=List[ProductResponse], summary="获取产品列表")
async def get_products(
user_id: Optional[int] = Query(None, description="用户ID如果提供则只返回该用户的产品"),
is_public: Optional[bool] = Query(None, description="是否公开,如果提供则过滤公开/私有产品"),
db_service: DatabaseService = Depends(get_database_service)
):
"""
获取产品列表
- **user_id**: 用户ID如果提供则只返回该用户的产品
- **is_public**: 是否公开,如果提供则过滤公开/私有产品
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
products = db_service.list_all_products(user_id=user_id, is_public=is_public)
return [ProductResponse(**product) for product in products]
except Exception as e:
logger.error(f"获取产品列表失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"获取产品列表失败: {str(e)}")
@router.get("/products/{product_id}", response_model=ProductResponse, summary="根据ID获取产品信息")
async def get_product_by_id(
product_id: int,
db_service: DatabaseService = Depends(get_database_service)
):
"""
根据ID获取产品信息
- **product_id**: 产品ID
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
product = db_service.get_product_by_id(product_id)
if not product:
raise HTTPException(status_code=404, detail=f"未找到ID为{product_id}的产品")
return ProductResponse(**product)
except HTTPException:
raise
except Exception as e:
logger.error(f"获取产品信息失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"获取产品信息失败: {str(e)}")
@router.get("/styles", response_model=List[StyleResponse], summary="获取风格列表")
async def get_styles(
db_service: DatabaseService = Depends(get_database_service)
):
"""
获取所有风格列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
styles = db_service.list_all_styles()
return [StyleResponse(**style) for style in styles]
except Exception as e:
logger.error(f"获取风格列表失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"获取风格列表失败: {str(e)}")
@router.get("/styles/{style_id}", response_model=StyleResponse, summary="根据ID获取风格信息")
async def get_style_by_id(
style_id: int,
db_service: DatabaseService = Depends(get_database_service)
):
"""
根据ID获取风格信息
- **style_id**: 风格ID
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
style = db_service.get_style_by_id(style_id)
if not style:
raise HTTPException(status_code=404, detail=f"未找到ID为{style_id}的风格")
return StyleResponse(**style)
except HTTPException:
raise
except Exception as e:
logger.error(f"获取风格信息失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"获取风格信息失败: {str(e)}")
@router.get("/audiences", response_model=List[AudienceResponse], summary="获取受众列表")
async def get_audiences(
db_service: DatabaseService = Depends(get_database_service)
):
"""
获取所有受众列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
audiences = db_service.list_all_audiences()
return [AudienceResponse(**audience) for audience in audiences]
except Exception as e:
logger.error(f"获取受众列表失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"获取受众列表失败: {str(e)}")
@router.get("/audiences/{audience_id}", response_model=AudienceResponse, summary="根据ID获取受众信息")
async def get_audience_by_id(
audience_id: int,
db_service: DatabaseService = Depends(get_database_service)
):
"""
根据ID获取受众信息
- **audience_id**: 受众ID
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
audience = db_service.get_audience_by_id(audience_id)
if not audience:
raise HTTPException(status_code=404, detail=f"未找到ID为{audience_id}的受众")
return AudienceResponse(**audience)
except HTTPException:
raise
except Exception as e:
logger.error(f"获取受众信息失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"获取受众信息失败: {str(e)}")
@router.post("/scenic-spots/batch", response_model=List[ScenicSpotResponse], summary="批量获取景区信息")
async def get_scenic_spots_batch(
spot_ids: List[int],
db_service: DatabaseService = Depends(get_database_service)
):
"""
批量获取景区信息
- **spot_ids**: 景区ID列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
spots = db_service.get_scenic_spots_by_ids(spot_ids)
return [ScenicSpotResponse(**spot) for spot in spots]
except Exception as e:
logger.error(f"批量获取景区信息失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"批量获取景区信息失败: {str(e)}")
@router.post("/products/batch", response_model=List[ProductResponse], summary="批量获取产品信息")
async def get_products_batch(
productIds: List[int],
db_service: DatabaseService = Depends(get_database_service)
):
"""
批量获取产品信息
- **productIds**: 产品ID列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
products = db_service.get_products_by_ids(productIds)
return [ProductResponse(**product) for product in products]
except Exception as e:
logger.error(f"批量获取产品信息失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"批量获取产品信息失败: {str(e)}")
@router.post("/styles/batch", response_model=List[StyleResponse], summary="批量获取风格信息")
async def get_styles_batch(
styleIds: List[int],
db_service: DatabaseService = Depends(get_database_service)
):
"""
批量获取风格信息
- **styleIds**: 风格ID列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
styles = db_service.get_styles_by_ids(styleIds)
return [StyleResponse(**style) for style in styles]
except Exception as e:
logger.error(f"批量获取风格信息失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"批量获取风格信息失败: {str(e)}")
@router.post("/audiences/batch", response_model=List[AudienceResponse], summary="批量获取受众信息")
async def get_audiences_batch(
audienceIds: List[int],
db_service: DatabaseService = Depends(get_database_service)
):
"""
批量获取受众信息
- **audienceIds**: 受众ID列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
audiences = db_service.get_audiences_by_ids(audienceIds)
return [AudienceResponse(**audience) for audience in audiences]
except Exception as e:
logger.error(f"批量获取受众信息失败: {e}", exc_info=True)
raise HTTPException(status_code=500, detail=f"批量获取受众信息失败: {str(e)}")