From 038a2df3dad92c20cb507b3d46059ffc04aa0594 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Tue, 7 Jan 2025 16:15:26 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=85=8D=E7=BD=AE=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/endpoints/community.py | 43 ++++++++++++++++++++++++--- app/api/endpoints/config.py | 54 ++++++++++++++++++++++++++++++++++ app/main.py | 3 +- app/models/community.py | 3 +- app/models/config.py | 21 +++++++++++++ 5 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 app/api/endpoints/config.py create mode 100644 app/models/config.py diff --git a/app/api/endpoints/community.py b/app/api/endpoints/community.py index 1a39d2c..def7d5f 100644 --- a/app/api/endpoints/community.py +++ b/app/api/endpoints/community.py @@ -24,13 +24,48 @@ async def create_community( @router.get("/", response_model=ResponseModel) async def get_communities( - skip: int = 0, - limit: int = 10, + latitude: float, + longitude: float, db: Session = Depends(get_db) ): """获取社区列表""" - communities = db.query(CommunityDB).offset(skip).limit(limit).all() - return success_response(data=[CommunityInfo.model_validate(c) for c in communities]) + communities = db.query(CommunityDB).all() + + # 计算距离并排序 + community_list = [] + for community in communities: + # 使用 Haversine 公式计算两点之间的距离 + distance = calculate_distance( + latitude, longitude, + community.latitude, community.longitude + ) + + community_info = CommunityInfo.model_validate(community) + community_info.distance = distance + community_list.append(community_info) + + # 按距离排序 + community_list.sort(key=lambda x: x.distance) + + return success_response(data=community_list) + +def calculate_distance(lat1: float, lon1: float, lat2: float, lon2: float) -> float: + """计算两点之间的距离(米)""" + from math import radians, sin, cos, sqrt, atan2 + + R = 6371000 # 地球半径(米) + + # 转换为弧度 + lat1, lon1, lat2, lon2 = map(radians, [lat1, lon1, lat2, lon2]) + + # Haversine 公式 + dlat = lat2 - lat1 + dlon = lon2 - lon1 + a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2 + c = 2 * atan2(sqrt(a), sqrt(1-a)) + distance = R * c + + return round(distance, 2) # 保留2位小数 @router.get("/{community_id}", response_model=ResponseModel) async def get_community( diff --git a/app/api/endpoints/config.py b/app/api/endpoints/config.py new file mode 100644 index 0000000..331ca6a --- /dev/null +++ b/app/api/endpoints/config.py @@ -0,0 +1,54 @@ +from fastapi import APIRouter, Depends +from sqlalchemy.orm import Session +from app.models.config import ConfigDB, ConfigInfo +from app.models.user import UserDB +from app.models.database import get_db +from app.api.deps import get_admin_user +from app.core.response import success_response, error_response, ResponseModel + +router = APIRouter() + +@router.get("", response_model=ResponseModel) +async def get_configs( + db: Session = Depends(get_db) +): + """获取所有配置""" + configs = db.query(ConfigDB).all() + + # 转换为数组格式 + config_list = [ + ConfigInfo.model_validate(config) + for config in configs + ] + + return success_response(data=config_list) + +@router.post("", response_model=ResponseModel) +async def create_config( + config: ConfigInfo, + db: Session = Depends(get_db), + admin: UserDB = Depends(get_admin_user) # 仅管理员可操作 +): + """创建配置""" + # 检查key是否已存在 + exists = db.query(ConfigDB).filter(ConfigDB.key == config.key).first() + if exists: + return error_response(code=400, message=f"配置项 {config.key} 已存在") + + # 创建新配置 + db_config = ConfigDB( + key=config.key, + value=config.value + ) + + try: + db.add(db_config) + db.commit() + db.refresh(db_config) + return success_response( + message="配置创建成功", + data=ConfigInfo.model_validate(db_config) + ) + except Exception as e: + db.rollback() + return error_response(code=500, message=f"创建失败: {str(e)}") \ No newline at end of file diff --git a/app/main.py b/app/main.py index 5948594..66b34c2 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,6 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from app.api.endpoints import user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_product_category, merchant_order, point +from app.api.endpoints import user, address, community, station, order, coupon, community_building, upload, merchant, merchant_product, merchant_product_category, merchant_order, point, config from app.models.database import Base, engine from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse @@ -39,6 +39,7 @@ app.include_router(merchant_product.router, prefix="/api/merchant/product", tags app.include_router(merchant_product_category.router, prefix="/api/merchant/category", tags=["商品分类"]) app.include_router(merchant_order.router, prefix="/api/merchant/order", tags=["商家订单"]) app.include_router(point.router, prefix="/api/point", tags=["用户积分"]) +app.include_router(config.router, prefix="/api/config", tags=["系统配置"]) @app.get("/") async def root(): diff --git a/app/models/community.py b/app/models/community.py index e286336..d33d97e 100644 --- a/app/models/community.py +++ b/app/models/community.py @@ -33,8 +33,9 @@ class CommunityInfo(BaseModel): id: int name: str address: str - longitude: float latitude: float + longitude: float + distance: Optional[float] = None # 距离,单位:米 class Config: from_attributes = True \ No newline at end of file diff --git a/app/models/config.py b/app/models/config.py new file mode 100644 index 0000000..ae9be47 --- /dev/null +++ b/app/models/config.py @@ -0,0 +1,21 @@ +from sqlalchemy import Column, Integer, String, Text, DateTime +from sqlalchemy.sql import func +from pydantic import BaseModel, Field +from datetime import datetime +from .database import Base + +class ConfigDB(Base): + __tablename__ = "configs" + + id = Column(Integer, primary_key=True, autoincrement=True) + key = Column(String(100), unique=True, nullable=False) + value = Column(Text, nullable=False) + create_time = Column(DateTime(timezone=True), server_default=func.now()) + update_time = Column(DateTime(timezone=True), onupdate=func.now()) + +class ConfigInfo(BaseModel): + key: str + value: str + + class Config: + from_attributes = True \ No newline at end of file