Files
daily-paper/app/routes/user.py
T

104 lines
3.4 KiB
Python

"""用户数据 JSON API — 收藏、阅读状态、笔记。"""
from __future__ import annotations
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse
from pydantic import BaseModel
from sqlalchemy.orm import Session
from app.database import get_db
from app.services.user_data import (
get_note,
save_note,
set_reading_status,
toggle_bookmark,
)
router = APIRouter(prefix="/api", tags=["user-data"])
# ── 请求模型 ──────────────────────────────────────────────────────────
class ReadingStatusRequest(BaseModel):
status: str
class NoteRequest(BaseModel):
content: str
# ── 收藏 ──────────────────────────────────────────────────────────────
@router.post("/bookmark/{arxiv_id}")
def bookmark_toggle(arxiv_id: str, request: Request, db: Session = Depends(get_db)):
"""切换收藏状态。支持 HTMX 局部刷新和 JSON 响应。"""
result = toggle_bookmark(db, arxiv_id)
if "error" in result:
raise HTTPException(status_code=404, detail=result["error"])
# HTMX 请求 → 返回 HTML 片段
if request.headers.get("HX-Request"):
star = "" if result["bookmarked"] else ""
active_class = " active" if result["bookmarked"] else ""
html = (
f'<button class="btn-bookmark{active_class}" '
f'hx-post="/api/bookmark/{arxiv_id}" '
f'hx-target="#user-data-{arxiv_id}" '
f'hx-swap="outerHTML">'
f"{star}</button>"
)
return HTMLResponse(content=html)
return result
# ── 阅读状态 ──────────────────────────────────────────────────────────
@router.post("/reading-status/{arxiv_id}")
def reading_status_update(
arxiv_id: str,
body: ReadingStatusRequest,
db: Session = Depends(get_db),
):
"""更新阅读状态。"""
result = set_reading_status(db, arxiv_id, body.status)
if "error" in result:
if result["error"] == "not_found":
raise HTTPException(status_code=404, detail="Paper not found")
elif result["error"] == "invalid_status":
raise HTTPException(
status_code=422,
detail=f"Invalid status. Valid: {result['valid']}",
)
return result
# ── 笔记 ──────────────────────────────────────────────────────────────
@router.get("/note/{arxiv_id}")
def note_get(arxiv_id: str, db: Session = Depends(get_db)):
"""获取笔记。"""
result = get_note(db, arxiv_id)
if result is None:
raise HTTPException(status_code=404, detail="Paper not found")
return result
@router.post("/note/{arxiv_id}")
def note_save(arxiv_id: str, body: NoteRequest, db: Session = Depends(get_db)):
"""保存笔记。"""
result = save_note(db, arxiv_id, body.content)
if "error" in result:
raise HTTPException(status_code=404, detail=result["error"])
return result