first commit
This commit is contained in:
9
MeetSpot/app/models/__init__.py
Normal file
9
MeetSpot/app/models/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
"""数据模型包。"""
|
||||
|
||||
from app.db.database import Base # noqa: F401
|
||||
|
||||
# 导入所有模型以确保它们注册到Base.metadata
|
||||
from app.models.user import User # noqa: F401
|
||||
from app.models.room import GatheringRoom, RoomParticipant # noqa: F401
|
||||
from app.models.message import ChatMessage, VenueVote # noqa: F401
|
||||
|
||||
53
MeetSpot/app/models/message.py
Normal file
53
MeetSpot/app/models/message.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""聊天消息与投票记录模型。"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy import Column, DateTime, ForeignKey, String, Text, UniqueConstraint, func
|
||||
|
||||
from app.db.database import Base
|
||||
|
||||
|
||||
def _generate_uuid() -> str:
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
class VenueVote(Base):
|
||||
__tablename__ = "venue_votes"
|
||||
__table_args__ = (UniqueConstraint("room_id", "venue_id", "user_id", name="uq_vote"),)
|
||||
|
||||
id = Column(String(36), primary_key=True, default=_generate_uuid)
|
||||
room_id = Column(String(36), ForeignKey("gathering_rooms.id"), nullable=False)
|
||||
venue_id = Column(String(100), nullable=False)
|
||||
user_id = Column(String(36), ForeignKey("users.id"), nullable=False)
|
||||
vote_type = Column(String(20), nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
|
||||
class ChatMessage(Base):
|
||||
__tablename__ = "chat_messages"
|
||||
|
||||
id = Column(String(36), primary_key=True, default=_generate_uuid)
|
||||
room_id = Column(String(36), ForeignKey("gathering_rooms.id"), nullable=False)
|
||||
user_id = Column(String(36), ForeignKey("users.id"), nullable=False)
|
||||
content = Column(Text, nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
|
||||
|
||||
class ChatMessageCreate(BaseModel):
|
||||
content: str = Field(..., min_length=1, description="聊天内容")
|
||||
|
||||
|
||||
class VoteCreate(BaseModel):
|
||||
venue_id: str
|
||||
vote_type: str = Field(..., pattern="^(like|dislike)$")
|
||||
|
||||
|
||||
class VoteRead(BaseModel):
|
||||
venue_id: str
|
||||
vote_type: str
|
||||
user_id: str
|
||||
created_at: Optional[datetime] = None
|
||||
|
||||
60
MeetSpot/app/models/room.py
Normal file
60
MeetSpot/app/models/room.py
Normal file
@@ -0,0 +1,60 @@
|
||||
"""聚会房间相关的ORM与Pydantic模型。"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional, Tuple
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy import Column, DateTime, Float, ForeignKey, String, Text, UniqueConstraint, func
|
||||
|
||||
from app.db.database import Base
|
||||
|
||||
|
||||
def _generate_uuid() -> str:
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
class GatheringRoom(Base):
|
||||
__tablename__ = "gathering_rooms"
|
||||
|
||||
id = Column(String(36), primary_key=True, default=_generate_uuid)
|
||||
name = Column(String(100), nullable=False)
|
||||
description = Column(Text, default="")
|
||||
host_user_id = Column(String(36), ForeignKey("users.id"), nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
gathering_time = Column(DateTime(timezone=True))
|
||||
status = Column(String(20), default="pending")
|
||||
venue_keywords = Column(String(100), default="咖啡馆")
|
||||
final_venue_json = Column(Text, nullable=True)
|
||||
|
||||
|
||||
class RoomParticipant(Base):
|
||||
__tablename__ = "room_participants"
|
||||
__table_args__ = (UniqueConstraint("room_id", "user_id", name="uq_room_user"),)
|
||||
|
||||
id = Column(String(36), primary_key=True, default=_generate_uuid)
|
||||
room_id = Column(String(36), ForeignKey("gathering_rooms.id"), nullable=False)
|
||||
user_id = Column(String(36), ForeignKey("users.id"), nullable=False)
|
||||
location_name = Column(String(200))
|
||||
location_lat = Column(Float)
|
||||
location_lng = Column(Float)
|
||||
joined_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
role = Column(String(20), default="member")
|
||||
|
||||
|
||||
class GatheringRoomCreate(BaseModel):
|
||||
name: str = Field(..., description="聚会名称")
|
||||
description: str = Field("", description="聚会描述")
|
||||
gathering_time: Optional[datetime] = Field(
|
||||
None, description="聚会时间,ISO 字符串"
|
||||
)
|
||||
venue_keywords: str = Field("咖啡馆", description="场所类型关键词")
|
||||
|
||||
|
||||
class RoomParticipantRead(BaseModel):
|
||||
user_id: str
|
||||
nickname: str
|
||||
location_name: Optional[str] = None
|
||||
location_coords: Optional[Tuple[float, float]] = None
|
||||
role: str
|
||||
|
||||
44
MeetSpot/app/models/user.py
Normal file
44
MeetSpot/app/models/user.py
Normal file
@@ -0,0 +1,44 @@
|
||||
"""用户相关SQLAlchemy模型与Pydantic模式。"""
|
||||
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
from sqlalchemy import Column, DateTime, String, func
|
||||
|
||||
from app.db.database import Base
|
||||
|
||||
|
||||
def _generate_uuid() -> str:
|
||||
return str(uuid.uuid4())
|
||||
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = "users"
|
||||
|
||||
id = Column(String(36), primary_key=True, default=_generate_uuid)
|
||||
phone = Column(String(20), unique=True, nullable=False)
|
||||
nickname = Column(String(50), nullable=False)
|
||||
avatar_url = Column(String(255), default="")
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
last_login = Column(DateTime(timezone=True))
|
||||
|
||||
|
||||
class UserCreate(BaseModel):
|
||||
phone: str = Field(..., description="手机号")
|
||||
nickname: Optional[str] = Field(None, description="昵称,可选")
|
||||
avatar_url: Optional[str] = Field("", description="头像URL,可选")
|
||||
|
||||
|
||||
class UserRead(BaseModel):
|
||||
id: str
|
||||
phone: str
|
||||
nickname: str
|
||||
avatar_url: str = ""
|
||||
created_at: datetime
|
||||
last_login: Optional[datetime] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
Reference in New Issue
Block a user