2026-04-19 21:34:14 +08:00
|
|
|
|
# auth - 认证路由
|
2026-04-19 22:22:45 +08:00
|
|
|
|
# Version: 0.0.1
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
|
|
|
|
|
|
|
|
|
|
|
from fastapi import APIRouter
|
|
|
|
|
|
# Version: 1.2.x
|
|
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException, status, Body
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from fastapi.security import OAuth2PasswordRequestForm
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from sqlalchemy.orm import Session
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from app.core.database import get_db
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from app.core.auth import verify_password, create_access_token, get_password_hash, get_current_user
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from app.models.models import User
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from app.schemas.schemas import Token, UserCreate, UserResponse
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
router = APIRouter(prefix="/api/auth", tags=["认证"])
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
def generate_user_code(db):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"""生成用户编码,从201开始,按自然数顺序递增,跳过已存在的"""
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 查找最大的user_code
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
max_code = db.query(User.user_code).filter(User.user_code != None).order_by(User.user_code.desc()).first()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if max_code and max_code[0]:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
try:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
num = int(max_code[0]) + 1
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:41:21 +08:00
|
|
|
|
if num < 201:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:41:21 +08:00
|
|
|
|
num = 201
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
# 检查是否已存在,如果存在则继续递增
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
while db.query(User).filter(User.user_code == str(num)).first():
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
num += 1
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:41:21 +08:00
|
|
|
|
return str(num)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
except:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
pass
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:41:21 +08:00
|
|
|
|
return "201"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
@router.post("/register", response_model=UserResponse)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
def register(user_data: UserCreate, db: Session = Depends(get_db)):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"""用户注册"""
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 检查用户名是否已存在
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
existing_user = db.query(User).filter(User.f01_01_name == user_data.f01_01_name).first()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if existing_user:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
raise HTTPException(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
detail="f01_01_name: 用户名已存在"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 检查邮箱是否已存在
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 22:52:37 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 22:52:37 +08:00
|
|
|
|
# 检查手机号是否已存在
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 22:52:37 +08:00
|
|
|
|
if user_data.phone:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 22:52:37 +08:00
|
|
|
|
existing_phone = db.query(User).filter(User.phone == user_data.phone).first()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 22:52:37 +08:00
|
|
|
|
if existing_phone:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 22:52:37 +08:00
|
|
|
|
raise HTTPException(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 22:52:37 +08:00
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-31 21:18:19 +08:00
|
|
|
|
detail="E00040:该手机号已被注册,请更换手机号"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 22:52:37 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if user_data.email:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
existing_email = db.query(User).filter(User.email == user_data.email).first()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if existing_email:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
raise HTTPException(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-31 21:18:19 +08:00
|
|
|
|
detail="E00041:该邮箱已被注册,请更换邮箱"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
# 处理邀请码
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
invited_by_user = None
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
if user_data.invite_code:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
# 查找邀请人
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
invited_by_user = db.query(User).filter(User.user_code == user_data.invite_code).first()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
if not invited_by_user:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
raise HTTPException(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
detail="E00042:邀请码无效"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 创建用户
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
import uuid
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
hashed_password = get_password_hash(user_data.password)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:22:27 +08:00
|
|
|
|
generated_code = generate_user_code(db)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
user = User(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
f99_90_id=str(uuid.uuid4()),
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
f99_91_user_id=str(uuid.uuid4()),
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:22:27 +08:00
|
|
|
|
user_code=generated_code,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
f01_01_name=user_data.f01_01_name,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
email=user_data.email,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
phone=user_data.phone,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
avatar=user_data.avatar,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
address=user_data.address,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
bio=user_data.bio,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
password=hashed_password,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
role="user"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
db.add(user)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
db.flush() # 确保获取user ID
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
# 更新邀请人、被邀请人的关联关系
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
if invited_by_user:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:22:27 +08:00
|
|
|
|
# 记录是被谁邀请的
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
user.f01_13_invite_code = invited_by_user.user_code
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
# 增加邀请人的邀请计数
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
invited_by_user.f99_101_invited_count = (invited_by_user.f99_101_invited_count or 0) + 1
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
# 生成自己的邀请码(用自己的user_code)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:22:27 +08:00
|
|
|
|
user.f01_13_invite_code = generated_code
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 08:14:01 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
db.commit()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
db.refresh(user)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
# 返回用户信息(避免Pydantic序列化问题)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
return {
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"id": user.f99_90_id,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"username": user.f01_01_name,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"user_code": user.user_code,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"email": user.email,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"phone": user.phone,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"avatar": user.avatar,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"role": user.role,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"level": user.f99_94_level,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"aiCount": user.f99_95_ai_count or 0,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"searchCount": user.f99_96_search_count or 0,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
"collectionCount": user.f99_97_collection_count or 0
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-11 01:47:55 +08:00
|
|
|
|
}
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
@router.post("/login", response_model=Token)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
def login(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
form_data: OAuth2PasswordRequestForm = Depends(),
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
db: Session = Depends(get_db)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:45:19 +08:00
|
|
|
|
"""用户登录 - 支持用户名或用户编码登录"""
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:45:19 +08:00
|
|
|
|
# 先尝试用户名登录
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
user = db.query(User).filter(User.f01_01_name == form_data.username).first()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:45:19 +08:00
|
|
|
|
# 如果用户名不存在,尝试用户编码登录
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:45:19 +08:00
|
|
|
|
if not user:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-04-09 00:45:19 +08:00
|
|
|
|
user = db.query(User).filter(User.user_code == form_data.username).first()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if not user:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
raise HTTPException(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
detail="E00011: 用户名或密码错误",
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
headers={"WWW-Authenticate": "Bearer"},
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 验证密码
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if not verify_password(form_data.password, user.password):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
raise HTTPException(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
detail="E00011: 用户名或密码错误",
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
headers={"WWW-Authenticate": "Bearer"},
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 23:20:12 +08:00
|
|
|
|
# 更新登录次数和最后登录时间
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 23:20:12 +08:00
|
|
|
|
from datetime import datetime
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 23:20:12 +08:00
|
|
|
|
user.f99_98_login_count = (user.f99_98_login_count or 0) + 1
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 23:20:12 +08:00
|
|
|
|
user.f99_99_last_login = datetime.now()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 23:20:12 +08:00
|
|
|
|
db.commit()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-24 23:20:12 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 生成 token
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
access_token = create_access_token(data={"sub": user.f99_90_id})
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
return {
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"access_token": access_token,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"token_type": "bearer"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
}
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
@router.get("/me", response_model=UserResponse)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
def get_current_user_info(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
current_user: User = Depends(lambda: None)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"""获取当前用户信息"""
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
raise HTTPException(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
status_code=status.HTTP_501_NOT_IMPLEMENTED,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
detail="请使用正确的依赖注入"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
@router.post("/change-password")
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
def change_password(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
old_password: str = Body(...),
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
new_password: str = Body(...),
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
current_user: User = Depends(get_current_user),
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
db: Session = Depends(get_db)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"""修改当前用户密码"""
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from app.core.auth import verify_password, get_password_hash
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 在当前session中重新查询用户
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
user = db.query(User).filter(User.f99_90_id == current_user.f99_90_id).first()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if not user:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
raise HTTPException(status_code=404, detail="用户不存在")
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 验证旧密码
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if not verify_password(old_password, user.password):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
raise HTTPException(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
status_code=status.HTTP_400_BAD_REQUEST,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
detail="当前密码错误"
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 更新密码
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
user.password = get_password_hash(new_password)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
db.commit()
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
return {"message": "密码修改成功"}
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# ============ 短信验证码接口 ============
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
@router.post("/send-verification-code")
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
def send_verification_code(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
phone: str = Body(..., min_length=11, max_length=11),
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
purpose: str = Body("register") # register | login | reset_password
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"""发送短信验证码"""
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from app.services.sms import send_verification_code as send_sms
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
# 验证手机号格式
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if not phone.startswith("1") or len(phone) != 11:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
return {"success": False, "message": "手机号格式不正确"}
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
result = send_sms(phone)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if result["success"]:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
return {
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"success": True,
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"message": f"验证码已发送到 {phone[:3]}****{phone[7:]}",
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"expire": result.get("expire", 300)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
}
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
else:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
return result
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
@router.post("/verify-code")
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
def verify_code(
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
phone: str = Body(...),
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
code: str = Body(..., min_length=6, max_length=6)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
):
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
"""验证短信验证码(仅验证,不执行后续操作)"""
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
from app.services.sms import verify_code as check_code
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
is_valid = check_code(phone, code)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
if is_valid:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
return {"success": True, "message": "验证成功"}
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
else:
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|
2026-03-23 11:08:52 +08:00
|
|
|
|
return {"success": False, "message": "验证码错误或已过期"}
|
2026-04-19 21:34:14 +08:00
|
|
|
|
# 更新:
|