from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, func, update from app.core.database import get_db from app.core.deps import get_current_user from app.models.models import User, Notification from app.schemas.schemas import NotificationResponse, NotificationListResponse router = APIRouter(prefix="/notifications", tags=["通知管理"]) @router.get("", response_model=NotificationListResponse) async def list_notifications( page: int = Query(1, ge=1), size: int = Query(20, ge=1, le=100), unread_only: bool = False, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): q = select(Notification).where(Notification.user_id == user.id) if unread_only: q = q.where(Notification.is_read == 0) total_q = select(func.count(Notification.id)).where(Notification.user_id == user.id) total = (await db.execute(total_q)).scalar() q = q.order_by(Notification.created_at.desc()).offset((page - 1) * size).limit(size) items = (await db.execute(q)).scalars().all() unread = (await db.execute( select(func.count(Notification.id)).where( Notification.user_id == user.id, Notification.is_read == 0 ) )).scalar() return NotificationListResponse( items=[NotificationResponse.model_validate(n) for n in items], total=total, unread=unread, ) @router.put("/{notification_id}/read") async def mark_read( notification_id: int, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(Notification).where( Notification.id == notification_id, Notification.user_id == user.id ) ) n = result.scalar_one_or_none() if not n: raise HTTPException(status_code=404, detail="通知不存在") n.is_read = 1 await db.commit() return {"message": "已标记已读"} @router.put("/read-all") async def mark_all_read( user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): await db.execute( update(Notification).where( Notification.user_id == user.id, Notification.is_read == 0 ).values(is_read=1) ) await db.commit() return {"message": "全部已读"} @router.delete("/{notification_id}") async def delete_notification( notification_id: int, user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute( select(Notification).where( Notification.id == notification_id, Notification.user_id == user.id ) ) n = result.scalar_one_or_none() if not n: raise HTTPException(status_code=404, detail="通知不存在") await db.delete(n) await db.commit() return {"message": "已删除"}