Files
life-echo/api/routers/books.py
iammm0 32fdc066dd refactor: 优化后端认证和路由功能
- 优化auth.py认证路由
- 优化books.py书籍路由
- 优化sms_service.py短信服务
2026-01-29 10:57:05 +08:00

129 lines
4.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
回忆录相关 API 路由
"""
from fastapi import APIRouter, Depends, HTTPException, Query, Body
from pydantic import BaseModel
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database import get_async_db
from database.models import Book as BookModel
from database.models import User as UserModel
from services.pdf_service import pdf_service
from middleware.auth import get_current_user
router = APIRouter(prefix="/api/books", tags=["books"])
@router.get("/current")
async def get_current_book(
current_user: UserModel = Depends(get_current_user),
db: AsyncSession = Depends(get_async_db)
):
"""获取当前回忆录(需要认证)"""
stmt = select(BookModel).where(BookModel.user_id == current_user.id).order_by(BookModel.updated_at.desc()).limit(1)
result = await db.execute(stmt)
book = result.scalar_one_or_none()
if not book:
return {"message": "No book found"}
return {
"id": book.id,
"title": book.title,
"total_pages": book.total_pages,
"total_words": book.total_words,
"cover_image_url": book.cover_image_url,
"has_update": book.has_update,
"last_update_chapter_id": book.last_update_chapter_id,
}
@router.post("/clear-update")
async def clear_book_update(
current_user: UserModel = Depends(get_current_user),
db: AsyncSession = Depends(get_async_db),
):
"""清除回忆录更新标记"""
stmt = select(BookModel).where(BookModel.user_id == current_user.id).order_by(BookModel.updated_at.desc()).limit(1)
result = await db.execute(stmt)
book = result.scalar_one_or_none()
if not book:
return {"status": "ok", "message": "No book found"}
book.has_update = False
await db.commit()
return {"status": "ok"}
class UpdateBookRequest(BaseModel):
title: str
subtitle: str | None = None # 目前数据库不支持subtitle但保留字段以便将来扩展
@router.put("/{book_id}")
async def update_book(
book_id: str,
request: UpdateBookRequest = Body(...),
current_user: UserModel = Depends(get_current_user),
db: AsyncSession = Depends(get_async_db)
):
"""更新书籍标题(需要认证,只能更新自己的回忆录)"""
book = await db.get(BookModel, book_id)
if not book:
raise HTTPException(status_code=404, detail="Book not found")
# 验证用户权限
if book.user_id != current_user.id:
raise HTTPException(status_code=403, detail="无权更新此回忆录")
# 更新标题
book.title = request.title
# subtitle字段目前数据库不支持暂时忽略
await db.commit()
await db.refresh(book)
return {
"id": book.id,
"title": book.title,
"total_pages": book.total_pages,
"total_words": book.total_words,
"cover_image_url": book.cover_image_url,
"has_update": book.has_update,
"last_update_chapter_id": book.last_update_chapter_id,
}
class ExportPdfRequest(BaseModel):
book_id: str
@router.post("/export-pdf")
async def export_pdf(
request: ExportPdfRequest = Body(...),
current_user: UserModel = Depends(get_current_user),
db: AsyncSession = Depends(get_async_db)
):
"""导出 PDF需要认证只能导出自己的回忆录"""
book = await db.get(BookModel, request.book_id)
if not book:
raise HTTPException(status_code=404, detail="Book not found")
# 验证用户权限
if book.user_id != current_user.id:
raise HTTPException(status_code=403, detail="无权导出此回忆录")
# 获取所有章节
from database.models import Chapter
stmt = select(Chapter).where(Chapter.user_id == current_user.id).order_by(Chapter.order_index)
result = await db.execute(stmt)
chapters = result.scalars().all()
# 生成 PDF
pdf_bytes = await pdf_service.generate_pdf(book, chapters)
return {
"pdf_base64": pdf_bytes.decode('latin1'), # 简化处理,实际应该用 base64
"filename": f"{book.title}.pdf"
}