nex_docus/backend/app/api/v1/notifications.py

145 lines
4.4 KiB
Python

"""
通知管理 API
"""
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, func, desc
from typing import List, Optional
from datetime import datetime
from app.core.database import get_db
from app.core.deps import get_current_user
from app.models.user import User
from app.models.notification import Notification
from app.schemas.notification import (
NotificationResponse,
NotificationUpdate,
UnreadCountResponse,
NotificationCreate
)
from app.schemas.response import success_response
from app.services.notification_service import notification_service
router = APIRouter()
@router.get("/", response_model=dict)
async def get_notifications(
page: int = 1,
page_size: int = 20,
unread_only: bool = False,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)
):
"""获取当前用户的通知列表"""
query = select(Notification).where(Notification.user_id == current_user.id)
if unread_only:
query = query.where(Notification.is_read == 0)
query = query.order_by(desc(Notification.created_at))
# 分页
offset = (page - 1) * page_size
query = query.offset(offset).limit(page_size)
result = await db.execute(query)
notifications = result.scalars().all()
# 获取总数
count_query = select(func.count()).select_from(Notification).where(Notification.user_id == current_user.id)
if unread_only:
count_query = count_query.where(Notification.is_read == 0)
total_result = await db.execute(count_query)
total = total_result.scalar()
data = [NotificationResponse.from_orm(n).dict() for n in notifications]
return {
"code": 200,
"message": "success",
"data": data,
"total": total,
"page": page,
"page_size": page_size
}
@router.get("/unread-count", response_model=dict)
async def get_unread_count(
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)
):
"""获取未读通知数量"""
result = await db.execute(
select(func.count()).select_from(Notification).where(
Notification.user_id == current_user.id,
Notification.is_read == 0
)
)
count = result.scalar()
return success_response(data={"unread_count": count})
@router.put("/{notification_id}/read", response_model=dict)
async def mark_as_read(
notification_id: int,
current_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 == current_user.id
)
)
notification = result.scalar_one_or_none()
if not notification:
raise HTTPException(status_code=404, detail="通知不存在")
if notification.is_read == 0:
notification.is_read = 1
notification.read_at = datetime.now()
await db.commit()
return success_response(message="已标记为已读")
@router.put("/read-all", response_model=dict)
async def mark_all_as_read(
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)
):
"""标记所有通知为已读"""
await db.execute(
update(Notification)
.where(Notification.user_id == current_user.id, Notification.is_read == 0)
.values(is_read=1, read_at=datetime.now())
)
await db.commit()
return success_response(message="全部标记为已读")
@router.post("/system", response_model=dict)
async def send_system_notification(
notification_in: NotificationCreate,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)
):
"""发送系统通知(仅限超级管理员)"""
if not current_user.is_superuser:
raise HTTPException(status_code=403, detail="只有管理员可以发送系统通知")
await notification_service.create_notification(
db=db,
user_id=notification_in.user_id,
title=notification_in.title,
content=notification_in.content,
type=notification_in.type,
category="system",
link=notification_in.link
)
await db.commit()
return success_response(message="系统通知发送成功")