108 lines
3.8 KiB
Python
108 lines
3.8 KiB
Python
from datetime import datetime
|
|
from typing import Optional
|
|
from fastapi import APIRouter, Depends, Query, HTTPException
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, func
|
|
from app.api.deps import get_db
|
|
from app.models.announcement import Announcement
|
|
from app.models.schemas import AnnouncementResponse, AnnouncementListResponse
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
@router.get("/announcements", response_model=AnnouncementListResponse)
|
|
async def list_announcements(
|
|
page: int = Query(1, ge=1),
|
|
page_size: int = Query(20, ge=1, le=100),
|
|
source_code: Optional[str] = None,
|
|
keyword: Optional[str] = None,
|
|
start_date: Optional[str] = None,
|
|
end_date: Optional[str] = None,
|
|
crawl_mode: Optional[str] = None,
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
conditions = []
|
|
if source_code:
|
|
conditions.append(Announcement.source_code == source_code)
|
|
if crawl_mode:
|
|
conditions.append(Announcement.crawl_mode == crawl_mode)
|
|
if start_date:
|
|
conditions.append(Announcement.publish_date >= start_date)
|
|
if end_date:
|
|
conditions.append(Announcement.publish_date <= end_date)
|
|
if keyword:
|
|
conditions.append(
|
|
Announcement.title.ilike(f"%{keyword}%")
|
|
)
|
|
|
|
base_query = select(Announcement)
|
|
if conditions:
|
|
base_query = base_query.where(*conditions)
|
|
|
|
count_query = select(func.count()).select_from(base_query.subquery())
|
|
total_result = await db.execute(count_query)
|
|
total = total_result.scalar() or 0
|
|
|
|
items_query = base_query.order_by(Announcement.publish_date.desc()) \
|
|
.offset((page - 1) * page_size).limit(page_size)
|
|
items_result = await db.execute(items_query)
|
|
items = items_result.scalars().all()
|
|
|
|
return AnnouncementListResponse(
|
|
total=total,
|
|
page=page,
|
|
page_size=page_size,
|
|
items=[AnnouncementResponse.model_validate(item) for item in items],
|
|
)
|
|
|
|
|
|
@router.get("/announcements/{announcement_id}", response_model=AnnouncementResponse)
|
|
async def get_announcement(announcement_id: int, db: AsyncSession = Depends(get_db)):
|
|
result = await db.execute(
|
|
select(Announcement).where(Announcement.id == announcement_id)
|
|
)
|
|
item = result.scalar_one_or_none()
|
|
if item is None:
|
|
raise HTTPException(status_code=404, detail="公告不存在")
|
|
return AnnouncementResponse.model_validate(item)
|
|
|
|
|
|
@router.get("/announcements/today", response_model=AnnouncementListResponse)
|
|
async def get_today_announcements(db: AsyncSession = Depends(get_db)):
|
|
today = datetime.now().date()
|
|
result = await db.execute(
|
|
select(Announcement).where(
|
|
func.date(Announcement.publish_date) == today
|
|
).order_by(Announcement.publish_date.desc())
|
|
)
|
|
items = result.scalars().all()
|
|
return AnnouncementListResponse(
|
|
total=len(items), page=1, page_size=len(items),
|
|
items=[AnnouncementResponse.model_validate(item) for item in items],
|
|
)
|
|
|
|
|
|
@router.get("/announcements/stats")
|
|
async def get_stats(db: AsyncSession = Depends(get_db)):
|
|
total = await db.execute(select(func.count()).select_from(Announcement))
|
|
today_count = await db.execute(
|
|
select(func.count()).where(
|
|
func.date(Announcement.publish_date) == func.current_date()
|
|
).select_from(Announcement)
|
|
)
|
|
new_count = await db.execute(
|
|
select(func.count()).where(Announcement.is_new == True)
|
|
.select_from(Announcement)
|
|
)
|
|
unsent = await db.execute(
|
|
select(func.count()).where(
|
|
Announcement.is_sent == False, Announcement.is_new == True
|
|
).select_from(Announcement)
|
|
)
|
|
return {
|
|
"total": total.scalar() or 0,
|
|
"today": today_count.scalar() or 0,
|
|
"new": new_count.scalar() or 0,
|
|
"unsent": unsent.scalar() or 0,
|
|
}
|