338 lines
13 KiB
Python
Raw Normal View History

#!/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")
2025-07-18 19:32:55 +08:00
productName: str = Field(..., description="产品名称")
originPrice: Optional[float] = Field(None, description="原价")
realPrice: Optional[float] = Field(None, description="实际价格")
packageInfo: Optional[str] = Field(None, description="套票信息")
2025-07-18 19:32:55 +08:00
detailedDescription: Optional[str] = Field(None, description="产品描述")
keyAdvantages: Optional[str] = Field(None, description="产品优势")
highlights: Optional[str] = Field(None, description="产品亮点")
usageRules: Optional[str] = Field(None, description="使用规则详细说明")
surcharge: Optional[str] = Field(None, description="加价说明")
reservation: Optional[str] = Field(None, description="预约规则")
refund: Optional[str] = Field(None, description="退改政策")
discounts: 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(
2025-07-15 10:59:36 +08:00
productIds: List[int],
db_service: DatabaseService = Depends(get_database_service)
):
"""
批量获取产品信息
2025-07-15 10:59:36 +08:00
- **productIds**: 产品ID列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
2025-07-15 10:59:36 +08:00
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(
2025-07-15 10:59:36 +08:00
styleIds: List[int],
db_service: DatabaseService = Depends(get_database_service)
):
"""
批量获取风格信息
2025-07-15 10:59:36 +08:00
- **styleIds**: 风格ID列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
2025-07-15 10:59:36 +08:00
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(
2025-07-15 10:59:36 +08:00
audienceIds: List[int],
db_service: DatabaseService = Depends(get_database_service)
):
"""
批量获取受众信息
2025-07-15 10:59:36 +08:00
- **audienceIds**: 受众ID列表
"""
try:
if not db_service.is_available():
raise HTTPException(status_code=503, detail="数据库服务不可用")
2025-07-15 10:59:36 +08:00
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)}")