feat: add admin dashboard, pipeline service, lightbox, and update dependencies

This commit is contained in:
2026-06-09 09:32:10 +08:00
parent 0d293422ac
commit 32978b3fc5
50 changed files with 4054 additions and 1618 deletions
+4 -25
View File
@@ -4,7 +4,7 @@ from __future__ import annotations
import os
import time
from datetime import date, datetime, timezone
from datetime import date
import pytest
from sqlalchemy import select
@@ -18,6 +18,8 @@ from app.models import (
UserNote,
UserReadingStatus,
)
from app.services.cleaner import cleanup_tmp, delete_papers_by_date_range
from app.utils import utc_now
# ── Fixtures ────────────────────────────────────────────────────────────
@@ -27,7 +29,7 @@ from app.models import (
def sample_paper_with_user_data(db_session, sample_papers_range):
"""给第一篇论文添加用户数据(收藏、阅读状态、笔记)。"""
paper = sample_papers_range[0]
now = datetime.now(timezone.utc)
now = utc_now()
db_session.add(UserBookmark(paper_id=paper.id, created_at=now))
db_session.add(
UserReadingStatus(paper_id=paper.id, status="read_summary", updated_at=now)
@@ -67,8 +69,6 @@ class TestCleanupTmp:
os.utime(old_dir, (old_mtime, old_mtime))
monkeypatch.setattr("app.services.cleaner.TMP_DIR", tmp_dir)
from app.services.cleaner import cleanup_tmp
result = cleanup_tmp()
assert result["scanned"] == 1
@@ -85,8 +85,6 @@ class TestCleanupTmp:
(recent_dir / "paper.pdf").write_text("fake pdf")
monkeypatch.setattr("app.services.cleaner.TMP_DIR", tmp_dir)
from app.services.cleaner import cleanup_tmp
result = cleanup_tmp()
assert result["scanned"] == 1
@@ -96,8 +94,6 @@ class TestCleanupTmp:
def test_cleanup_empty_dir(self, tmp_path, monkeypatch):
"""data/tmp/ 不存在时安全返回。"""
monkeypatch.setattr("app.services.cleaner.TMP_DIR", tmp_path / "nonexistent")
from app.services.cleaner import cleanup_tmp
result = cleanup_tmp()
assert result["scanned"] == 0
assert result["removed"] == 0
@@ -116,8 +112,6 @@ class TestCleanupTmp:
recent_dir.mkdir()
monkeypatch.setattr("app.services.cleaner.TMP_DIR", tmp_dir)
from app.services.cleaner import cleanup_tmp
result = cleanup_tmp()
assert result["scanned"] == 2
@@ -137,8 +131,6 @@ class TestDeletePapersByDateRange:
@pytest.mark.asyncio
async def test_delete_by_date_range(self, db_session, sample_papers_range):
"""删除指定日期范围的论文。"""
from app.services.cleaner import delete_papers_by_date_range
# 删除 1月11日 ~ 1月13日(3篇)
result = await delete_papers_by_date_range(
db_session,
@@ -159,8 +151,6 @@ class TestDeletePapersByDateRange:
@pytest.mark.asyncio
async def test_delete_creates_job_record(self, db_session, sample_papers_range):
"""删除操作应创建 data_delete_jobs 记录。"""
from app.services.cleaner import delete_papers_by_date_range
await delete_papers_by_date_range(
db_session,
date(2024, 1, 10),
@@ -178,8 +168,6 @@ class TestDeletePapersByDateRange:
@pytest.mark.asyncio
async def test_delete_creates_crawl_log(self, db_session, sample_papers_range):
"""删除操作应写入 crawl_logs。"""
from app.services.cleaner import delete_papers_by_date_range
await delete_papers_by_date_range(
db_session,
date(2024, 1, 10),
@@ -199,8 +187,6 @@ class TestDeletePapersByDateRange:
self, db_session, sample_paper_with_user_data
):
"""删除论文时应 cascade 删除关联的用户数据。"""
from app.services.cleaner import delete_papers_by_date_range
paper = sample_paper_with_user_data
# 删除
@@ -235,7 +221,6 @@ class TestDeletePapersByDateRange:
async def test_delete_removes_fts(self, db_session, sample_papers_range):
"""删除论文时应同步删除 FTS5 索引。"""
import sqlalchemy
from app.services.cleaner import delete_papers_by_date_range
await delete_papers_by_date_range(
db_session,
@@ -254,8 +239,6 @@ class TestDeletePapersByDateRange:
self, db_session, sample_papers_range, tmp_path, monkeypatch
):
"""删除论文时应删除本地文件目录。"""
from app.services.cleaner import delete_papers_by_date_range
papers_dir = tmp_path / "papers"
papers_dir.mkdir()
(papers_dir / "2401.10001").mkdir()
@@ -274,8 +257,6 @@ class TestDeletePapersByDateRange:
@pytest.mark.asyncio
async def test_delete_empty_range(self, db_session, sample_papers_range):
"""日期范围内无论文时返回 0。"""
from app.services.cleaner import delete_papers_by_date_range
result = await delete_papers_by_date_range(
db_session,
date(2025, 1, 1),
@@ -295,8 +276,6 @@ class TestDeletePapersByDateRange:
emb._chroma.reset()
from app.services.cleaner import delete_papers_by_date_range
result = await delete_papers_by_date_range(
db_session,
date(2024, 1, 10),