feat: add admin dashboard, pipeline service, lightbox, and update dependencies
This commit is contained in:
+49
-60
@@ -2,18 +2,20 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
from datetime import date, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||
from fastapi.responses import RedirectResponse
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
|
||||
from app.config import settings
|
||||
from app.database import get_db
|
||||
from app.models import Paper
|
||||
from app.utils import templates, today_str
|
||||
from app.models import PAPER_FULL_LOAD, Paper
|
||||
from app.utils import PAPERS_DIR, safe_json_loads, templates, today_str, latest_paper_date
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -21,9 +23,9 @@ router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/")
|
||||
def index(request: Request):
|
||||
"""重定向到 /day/{today}。"""
|
||||
return RedirectResponse(url=f"/day/{today_str()}")
|
||||
def index(request: Request, db: Session = Depends(get_db)):
|
||||
"""重定向到最新有论文的日期页。"""
|
||||
return RedirectResponse(url=f"/day/{latest_paper_date(db)}")
|
||||
|
||||
|
||||
@router.get("/day/{date_str}")
|
||||
@@ -39,23 +41,24 @@ def day_page(date_str: str, request: Request, db: Session = Depends(get_db)):
|
||||
today = today_str()
|
||||
|
||||
papers = (
|
||||
db.query(Paper)
|
||||
.filter(Paper.paper_date == date_str)
|
||||
.options(
|
||||
joinedload(Paper.authors),
|
||||
joinedload(Paper.tags),
|
||||
joinedload(Paper.summary_status),
|
||||
joinedload(Paper.bookmark),
|
||||
db.execute(
|
||||
select(Paper)
|
||||
.where(Paper.paper_date == date_str)
|
||||
.options(*PAPER_FULL_LOAD)
|
||||
.order_by(Paper.upvotes.desc())
|
||||
)
|
||||
.order_by(Paper.upvotes.desc())
|
||||
.scalars()
|
||||
.unique()
|
||||
.all()
|
||||
)
|
||||
|
||||
dates_raw = (
|
||||
db.query(Paper.paper_date)
|
||||
.distinct()
|
||||
.order_by(Paper.paper_date.desc())
|
||||
.limit(30)
|
||||
db.execute(
|
||||
select(Paper.paper_date)
|
||||
.distinct()
|
||||
.order_by(Paper.paper_date.desc())
|
||||
.limit(30)
|
||||
)
|
||||
.all()
|
||||
)
|
||||
available_dates = [
|
||||
@@ -81,18 +84,17 @@ def day_page(date_str: str, request: Request, db: Session = Depends(get_db)):
|
||||
def paper_detail(arxiv_id: str, request: Request, db: Session = Depends(get_db)):
|
||||
"""论文详情页。"""
|
||||
paper = (
|
||||
db.query(Paper)
|
||||
.filter(Paper.arxiv_id == arxiv_id)
|
||||
.options(
|
||||
joinedload(Paper.authors),
|
||||
joinedload(Paper.tags),
|
||||
joinedload(Paper.summary),
|
||||
joinedload(Paper.summary_status),
|
||||
joinedload(Paper.bookmark),
|
||||
joinedload(Paper.reading_status),
|
||||
joinedload(Paper.note),
|
||||
db.execute(
|
||||
select(Paper)
|
||||
.where(Paper.arxiv_id == arxiv_id)
|
||||
.options(
|
||||
joinedload(Paper.summary),
|
||||
joinedload(Paper.note),
|
||||
*PAPER_FULL_LOAD,
|
||||
)
|
||||
)
|
||||
.first()
|
||||
.unique()
|
||||
.scalar_one_or_none()
|
||||
)
|
||||
if not paper:
|
||||
raise HTTPException(status_code=404, detail="Paper not found")
|
||||
@@ -108,28 +110,15 @@ def paper_detail(arxiv_id: str, request: Request, db: Session = Depends(get_db))
|
||||
images = _get_paper_images(arxiv_id)
|
||||
|
||||
# 预处理 JSON 字段供模板直接使用
|
||||
import json as _json
|
||||
|
||||
prereqs = {}
|
||||
if paper.summary and paper.summary.prerequisites_json:
|
||||
try:
|
||||
prereqs = _json.loads(paper.summary.prerequisites_json)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
benchmarks = []
|
||||
if paper.summary and paper.summary.results_benchmarks_json:
|
||||
try:
|
||||
benchmarks = _json.loads(paper.summary.results_benchmarks_json)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
|
||||
figures_raw = []
|
||||
if paper.summary and paper.summary.figures_json:
|
||||
try:
|
||||
figures_raw = _json.loads(paper.summary.figures_json)
|
||||
except (ValueError, TypeError):
|
||||
pass
|
||||
prereqs = safe_json_loads(
|
||||
paper.summary.prerequisites_json if paper.summary else None, default={}
|
||||
)
|
||||
benchmarks = safe_json_loads(
|
||||
paper.summary.results_benchmarks_json if paper.summary else None, default=[]
|
||||
)
|
||||
figures_raw = safe_json_loads(
|
||||
paper.summary.figures_json if paper.summary else None, default=[]
|
||||
)
|
||||
|
||||
linked_figures = _link_figures_with_images(figures_raw, images, arxiv_id)
|
||||
|
||||
@@ -228,9 +217,12 @@ def _get_similar_papers(db: Session, arxiv_id: str, top_k: int = 6) -> list[dict
|
||||
return []
|
||||
|
||||
papers = (
|
||||
db.query(Paper)
|
||||
.filter(Paper.arxiv_id.in_(list(papers_info.keys())))
|
||||
.options(joinedload(Paper.tags))
|
||||
db.execute(
|
||||
select(Paper)
|
||||
.where(Paper.arxiv_id.in_(list(papers_info.keys())))
|
||||
.options(joinedload(Paper.tags))
|
||||
)
|
||||
.scalars()
|
||||
.all()
|
||||
)
|
||||
|
||||
@@ -260,7 +252,7 @@ def _get_similar_papers(db: Session, arxiv_id: str, top_k: int = 6) -> list[dict
|
||||
|
||||
def _get_paper_images(arxiv_id: str) -> list[dict]:
|
||||
"""获取论文提取的图片列表。"""
|
||||
images_dir = Path("data/papers") / arxiv_id / "images"
|
||||
images_dir = PAPERS_DIR / arxiv_id / "images"
|
||||
if not images_dir.exists():
|
||||
return []
|
||||
|
||||
@@ -286,15 +278,12 @@ def _link_figures_with_images(
|
||||
if not figures or not images:
|
||||
return figures
|
||||
|
||||
import json as _json
|
||||
import re
|
||||
|
||||
manifest_path = Path("data/papers") / arxiv_id / "images" / "manifest.json"
|
||||
manifest_path = PAPERS_DIR / arxiv_id / "images" / "manifest.json"
|
||||
if not manifest_path.exists():
|
||||
return figures
|
||||
|
||||
try:
|
||||
manifest = _json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
except (ValueError, TypeError):
|
||||
return figures
|
||||
|
||||
|
||||
Reference in New Issue
Block a user