diff --git a/app/api/endpoints/user.py b/app/api/endpoints/user.py index 45a769c..abdf8a3 100644 --- a/app/api/endpoints/user.py +++ b/app/api/endpoints/user.py @@ -19,6 +19,7 @@ from typing import Optional from datetime import datetime, timedelta from sqlalchemy import text from app.models.community import CommunityDB +from app.models.user_auth import UserAuthDB, UserAuthCreate, UserAuthInfo router = APIRouter() @@ -494,3 +495,62 @@ async def change_password( except Exception as e: db.rollback() return error_response(code=500, message=f"修改密码失败: {str(e)}") + +@router.post("/auth", response_model=ResponseModel) +async def create_user_auth( + auth: UserAuthCreate, + db: Session = Depends(get_db), + current_user: UserDB = Depends(get_current_user) +): + """用户实名认证""" + # 检查是否已认证 + if current_user.is_auth: + return error_response(code=400, message="用户已完成实名认证") + + # 检查是否存在认证记录 + exists = db.query(UserAuthDB).filter( + UserAuthDB.user_id == current_user.userid + ).first() + + if exists: + return error_response(code=400, message="该用户已有认证记录") + + try: + # 创建认证记录 + auth_record = UserAuthDB( + user_id=current_user.userid, + name=auth.name, + id_number=auth.id_number, + ) + db.add(auth_record) + + # 更新用户认证状态 + current_user.is_auth = True + + db.commit() + + return success_response(data=UserAuthInfo.model_validate(auth_record)) + except Exception as e: + db.rollback() + return error_response(code=500, message=f"认证失败: {str(e)}") + +@router.get("/auth", response_model=ResponseModel) +async def get_user_auth( + db: Session = Depends(get_db), + current_user: UserDB = Depends(get_current_user) +): + """获取用户认证信息""" + auth_record = db.query(UserAuthDB).filter( + UserAuthDB.user_id == current_user.userid + ).first() + + if not auth_record: + return error_response(code=404, message="未找到认证记录") + + # 身份证号脱敏:保留前4位和后4位,中间用*代替 + masked_id_number = f"{auth_record.id_number[:4]}{'*' * 10}{auth_record.id_number[-4:]}" + + auth_info = UserAuthInfo.model_validate(auth_record) + auth_info.id_number = masked_id_number + + return success_response(data=auth_info) diff --git a/app/models/user.py b/app/models/user.py index e533bc1..40e3dd6 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -38,6 +38,7 @@ class UserDB(Base): create_time = Column(DateTime(timezone=True), server_default=func.now()) update_time = Column(DateTime(timezone=True), onupdate=func.now()) community_id = Column(Integer, ForeignKey("communities.id"), nullable=True) # 归属小区 + is_auth = Column(Boolean, nullable=False, default=False) # Pydantic 模型 class UserLogin(BaseModel): @@ -60,6 +61,7 @@ class UserInfo(BaseModel): coupon_count: Optional[int] = 0 community_id: Optional[int] = None community_name: Optional[str] = None + is_auth: bool = False class Config: from_attributes = True diff --git a/app/models/user_auth.py b/app/models/user_auth.py new file mode 100644 index 0000000..e8616fb --- /dev/null +++ b/app/models/user_auth.py @@ -0,0 +1,28 @@ +from sqlalchemy import Column, String, Integer, DateTime, Boolean, ForeignKey, UniqueConstraint +from sqlalchemy.sql import func +from pydantic import BaseModel, Field +from typing import Optional +from datetime import datetime +from .database import Base + +class UserAuthDB(Base): + __tablename__ = "user_auth_records" + + id = Column(Integer, primary_key=True, autoincrement=True) + user_id = Column(Integer, ForeignKey("users.userid"), unique=True, nullable=False) + name = Column(String(50), nullable=False) + id_number = Column(String(18), nullable=False) + create_time = Column(DateTime(timezone=True), server_default=func.now()) + update_time = Column(DateTime(timezone=True), onupdate=func.now()) + +class UserAuthCreate(BaseModel): + name: str = Field(..., min_length=2, max_length=50) + id_number: str = Field(..., min_length=18, max_length=18, pattern="^[0-9Xx]{18}$") + +class UserAuthInfo(BaseModel): + name: str + id_number: str + create_time: datetime + + class Config: + from_attributes = True \ No newline at end of file