82 lines
3.1 KiB
Python
82 lines
3.1 KiB
Python
from sqlalchemy import Column, String, Integer, Float, DateTime, JSON, ForeignKey
|
||
from sqlalchemy.dialects.mysql import DECIMAL
|
||
from sqlalchemy.sql import func, select
|
||
from sqlalchemy.orm import relationship
|
||
from pydantic import BaseModel, Field
|
||
from typing import Optional, List
|
||
from datetime import datetime
|
||
from .database import Base
|
||
|
||
# 商家图片表
|
||
class MerchantImageDB(Base):
|
||
__tablename__ = "merchant_images"
|
||
|
||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
merchant_id = Column(Integer, ForeignKey("merchants.id", ondelete="CASCADE"), index=True)
|
||
image_url = Column(String(500), nullable=False)
|
||
sort = Column(Integer, nullable=False, default=0)
|
||
create_time = Column(DateTime(timezone=True), server_default=func.now())
|
||
|
||
class Config:
|
||
unique_together = [("merchant_id", "sort")]
|
||
|
||
# 数据库模型
|
||
class MerchantDB(Base):
|
||
__tablename__ = "merchants"
|
||
|
||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||
name = Column(String(100), nullable=False)
|
||
business_hours = Column(String(100), nullable=False) # 营业时间,如 "09:00-22:00"
|
||
address = Column(String(200), nullable=False)
|
||
longitude = Column(DECIMAL(9, 6), nullable=False) # 经度,精确到小数点后6位
|
||
latitude = Column(DECIMAL(9, 6), nullable=False) # 纬度,精确到小数点后6位
|
||
phone = Column(String(20), nullable=False)
|
||
create_time = Column(DateTime(timezone=True), server_default=func.now())
|
||
update_time = Column(DateTime(timezone=True), onupdate=func.now())
|
||
|
||
# 关联图片
|
||
images = relationship("MerchantImageDB",
|
||
order_by="MerchantImageDB.sort",
|
||
cascade="all, delete-orphan")
|
||
|
||
# Pydantic 模型
|
||
class MerchantImage(BaseModel):
|
||
image_url: str = Field(..., max_length=500)
|
||
sort: int = Field(..., ge=0) # 排序序号,从0开始
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
class MerchantCreate(BaseModel):
|
||
name: str = Field(..., max_length=100)
|
||
business_hours: str = Field(..., max_length=100)
|
||
address: str = Field(..., max_length=200)
|
||
longitude: float = Field(..., ge=-180, le=180, description="经度")
|
||
latitude: float = Field(..., ge=-180, le=180, description="纬度")
|
||
phone: str = Field(..., max_length=20, pattern=r'^\d+$')
|
||
images: List[MerchantImage] = []
|
||
|
||
class MerchantUpdate(BaseModel):
|
||
name: Optional[str] = Field(None, max_length=100)
|
||
business_hours: Optional[str] = Field(None, max_length=100)
|
||
address: Optional[str] = Field(None, max_length=200)
|
||
longitude: Optional[float] = Field(None, ge=-180, le=180, description="经度")
|
||
latitude: Optional[float] = Field(None, ge=-180, le=180, description="纬度")
|
||
phone: Optional[str] = Field(None, max_length=20, pattern=r'^\d+$')
|
||
images: Optional[List[MerchantImage]] = None
|
||
|
||
class MerchantInfo(BaseModel):
|
||
id: int
|
||
name: str
|
||
business_hours: str
|
||
address: str
|
||
longitude: float
|
||
latitude: float
|
||
phone: str
|
||
images: List[MerchantImage]
|
||
create_time: datetime
|
||
update_time: Optional[datetime]
|
||
distance: Optional[int] = None # 距离(米)
|
||
|
||
class Config:
|
||
from_attributes = True |