202 lines
6.3 KiB
Python
202 lines
6.3 KiB
Python
# -*- coding = utf-8 -*-
|
|
# @Time : 2025/2/13 下午4:53
|
|
# @File : routes.py
|
|
# @Software : PyCharm
|
|
# @Author : xingc
|
|
# @Desc :
|
|
from typing import List, Literal
|
|
|
|
from fastapi import APIRouter, Query, Depends, HTTPException, status
|
|
from sqlalchemy import select, func
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from core.base import schema as base_schema
|
|
from core.db.crud import CRUD
|
|
from core.db.engine import get_async_session
|
|
from core.db.models import User, UserFollows, UserCollection
|
|
from core.routers.auth.schema import LoginUser
|
|
from core.routers.auth.services import get_current_user_form_http
|
|
|
|
from . import schema
|
|
from .actions import update_user_follower_total
|
|
|
|
user_router = APIRouter(prefix='/user', tags=['用户模块'])
|
|
|
|
|
|
@user_router.get('/me/info', summary='用户信息(我的)', response_model=base_schema.BaseResponse[schema.User])
|
|
async def get_me_info(
|
|
login_user: LoginUser = Depends(get_current_user_form_http),
|
|
db_session: AsyncSession = Depends(get_async_session)
|
|
):
|
|
db_crud = CRUD(db_session, User)
|
|
user = await db_crud.get(filters={'user_id': login_user.user_id})
|
|
if user is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='用户不存在')
|
|
|
|
user.displayed_card_total = await db_crud.total(
|
|
model=UserCollection,
|
|
filters={
|
|
'user_id': login_user.user_id,
|
|
'displayed': True}
|
|
)
|
|
return {'data': user}
|
|
|
|
|
|
@user_router.get(
|
|
'/visit/{user_id}/info',
|
|
summary='用户信息(访问者)',
|
|
response_model=base_schema.BaseResponse[schema.VisitUser]
|
|
)
|
|
async def get_visit_user_info(
|
|
user_id: int,
|
|
login_user: LoginUser = Depends(get_current_user_form_http),
|
|
db_session: AsyncSession = Depends(get_async_session)
|
|
):
|
|
if user_id == login_user.user_id:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='无法操作')
|
|
|
|
db_crud = CRUD(db_session, User)
|
|
user = await db_crud.get(filters={'user_id': user_id})
|
|
if user is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='访问用户不存在')
|
|
|
|
user.is_follow = await db_crud.exists(
|
|
model=UserFollows,
|
|
filters={
|
|
'follower_id': login_user.user_id,
|
|
'followed_id': user_id
|
|
}
|
|
)
|
|
|
|
user.displayed_card_total = await db_crud.total(
|
|
model=UserCollection,
|
|
filters={
|
|
'user_id': user.user_id,
|
|
'displayed': True}
|
|
)
|
|
|
|
return {'data': user}
|
|
|
|
|
|
@user_router.get(
|
|
'/followers/all',
|
|
summary='获取所有关注列表',
|
|
response_model=base_schema.BaseResponse[
|
|
base_schema.Paginated[
|
|
List[schema.LiteUser]
|
|
]
|
|
]
|
|
)
|
|
async def get_all_followers(
|
|
login_user: LoginUser = Depends(get_current_user_form_http),
|
|
page: int = Query(default=1, gt=0),
|
|
page_size: int = Query(default=15, gt=0, le=200),
|
|
db_session: AsyncSession = Depends(get_async_session)
|
|
):
|
|
# 组装查询条件
|
|
conditions = [
|
|
UserFollows.follower_id == login_user.user_id
|
|
]
|
|
|
|
# 记录总数查询
|
|
total_stmt = (
|
|
select(func.count()).select_from(UserFollows).filter(*conditions)
|
|
)
|
|
total = await db_session.execute(total_stmt)
|
|
|
|
# 分页记录查询
|
|
stmt = (
|
|
select(User, UserFollows)
|
|
.join(User, UserFollows.followed_id == User.user_id)
|
|
.where(*conditions)
|
|
.order_by(UserFollows.created_at.desc()).limit(page_size).offset((page - 1) * page_size)
|
|
)
|
|
records = await db_session.execute(stmt)
|
|
|
|
return {
|
|
'data': {
|
|
'list': records.scalars().all(),
|
|
'total': total.scalar(),
|
|
'page': page,
|
|
'page_size': page_size,
|
|
},
|
|
}
|
|
|
|
|
|
@user_router.post('/me/update', summary='更新用户信息', response_model=base_schema.BaseResponse[schema.User])
|
|
async def update_me(
|
|
payload: schema.UpdateUserIn,
|
|
login_user: LoginUser = Depends(get_current_user_form_http),
|
|
db_session: AsyncSession = Depends(get_async_session)
|
|
):
|
|
db_crud = CRUD(db_session, User)
|
|
result = await db_crud.update(payload.model_dump(exclude_none=True), filters={'user_id': login_user.user_id})
|
|
if result is None:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='无法操作')
|
|
|
|
return {'data': result}
|
|
|
|
|
|
@user_router.post('/follow/{user_id}/', summary='新增/取消关注用户', response_model=base_schema.BaseResponse)
|
|
async def follow_user(
|
|
user_id: int,
|
|
action: Literal['follower', 'unfollower'],
|
|
login_user: LoginUser = Depends(get_current_user_form_http),
|
|
db_session: AsyncSession = Depends(get_async_session)
|
|
):
|
|
if user_id == login_user.user_id:
|
|
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='无法操作')
|
|
|
|
db_crud = CRUD(db_session, User)
|
|
follower_user: User | None = await db_crud.get(filters={'user_id': user_id})
|
|
if follower_user is None:
|
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='被关注者不存在')
|
|
|
|
db_crud = CRUD(db_session, UserFollows)
|
|
record = {
|
|
'follower_id': login_user.user_id,
|
|
'followed_id': follower_user.user_id,
|
|
}
|
|
if action == 'follower':
|
|
await db_crud.create(data=record, filters=record)
|
|
elif action == 'unfollower':
|
|
await db_crud.delete(filters=record)
|
|
|
|
await update_user_follower_total(
|
|
follower_id=login_user.user_id,
|
|
followed_id=follower_user.user_id,
|
|
db_session=db_session
|
|
)
|
|
|
|
return {'message': 'ok'}
|
|
|
|
|
|
@user_router.post(
|
|
'/search/',
|
|
summary='搜索用户',
|
|
response_model=base_schema.BaseResponse[
|
|
base_schema.Paginated[
|
|
List[schema.LiteUser]
|
|
]
|
|
]
|
|
)
|
|
async def search_user(
|
|
nickname: str = Query(...),
|
|
page_size: int = Query(default=30, gt=0, le=30),
|
|
login_user: LoginUser = Depends(get_current_user_form_http),
|
|
db_session: AsyncSession = Depends(get_async_session)
|
|
):
|
|
db_crud = CRUD(db_session, User)
|
|
users, total = await db_crud.get_paginated(
|
|
page_size=page_size,
|
|
filters={
|
|
'nickname__like': nickname,
|
|
'user_id__ne': login_user.user_id
|
|
}
|
|
)
|
|
return {'data': {
|
|
'list': users,
|
|
'total': total,
|
|
'page_size': page_size
|
|
}}
|