Initial commit: PastPaper Master full stack

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Zhao
2026-04-21 12:15:35 +07:00
commit 7a09167261
105 changed files with 24799 additions and 0 deletions

59
backend/app/main.py Normal file
View File

@@ -0,0 +1,59 @@
import asyncio
import threading
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.routers import analytics, papers, attempts, questions
def _resume_stale_papers():
"""启动时检查卡在 processing 的 paper自动续传 AI trio"""
try:
from app.services.supabase_client import get_supabase
from app.services.paper_processor import process_paper
sb = get_supabase()
stale = sb.table("papers").select("id").eq("status", "processing").execute().data
if not stale:
return
for p in stale:
paper_id = p["id"]
print(f"[STARTUP] Resuming processing for paper {paper_id[:8]}...")
def run(pid=paper_id):
asyncio.run(process_paper(pid, b"", None))
threading.Thread(target=run, daemon=True).start()
except Exception as e:
print(f"[STARTUP] Resume skipped: {e}")
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
_resume_stale_papers()
yield
# Shutdown (nothing to do)
app = FastAPI(title="PastPaper Master API", version="0.1.0", lifespan=lifespan)
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 开发阶段先放开,上线收紧
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(papers.router, prefix="/api/papers", tags=["papers"])
app.include_router(attempts.router, prefix="/api/attempts", tags=["attempts"])
app.include_router(questions.router, prefix="/api/questions", tags=["questions"])
app.include_router(analytics.router, prefix="/api/analytics", tags=["analytics"])
@app.get("/health")
def health():
return {"status": "ok"}