新增PDF生成并发设置
This commit is contained in:
@@ -10,6 +10,7 @@ from app.api.routes import (
|
||||
admin_logs,
|
||||
admin_pdf_cleanup,
|
||||
admin_projects,
|
||||
admin_settings,
|
||||
auth,
|
||||
health,
|
||||
public,
|
||||
@@ -27,4 +28,5 @@ api_router.include_router(admin_exports.router, prefix="/admin/exports", tags=["
|
||||
api_router.include_router(admin_logs.router, prefix="/admin/logs", tags=["admin-logs"])
|
||||
api_router.include_router(admin_pdf_cleanup.router, prefix="/admin/pdf-cleanup", tags=["admin-pdf-cleanup"])
|
||||
api_router.include_router(admin_backups.router, prefix="/admin/backups", tags=["admin-backups"])
|
||||
api_router.include_router(admin_settings.router, prefix="/admin/settings", tags=["admin-settings"])
|
||||
api_router.include_router(public.router, prefix="/public", tags=["public"])
|
||||
|
||||
@@ -10,7 +10,8 @@ from app.models import AdminUser, Certificate, CertificateAccessToken, Learner,
|
||||
from app.schemas.certificate import CertificateCreate, CertificateOut
|
||||
from app.services.certificate_number import build_certificate_no
|
||||
from app.services.logs import log_action
|
||||
from app.services.pdf import render_certificate_pdf
|
||||
from app.services.pdf import PdfGenerationBusy, render_certificate_pdf
|
||||
from app.services.system_settings import get_pdf_generation_concurrency_limit
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -143,7 +144,16 @@ def download_certificate(
|
||||
project = db.query(ProjectCourse).filter(ProjectCourse.code == certificate.project_code).first()
|
||||
if not learner or not token:
|
||||
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Certificate data is incomplete")
|
||||
pdf_path = render_certificate_pdf(certificate, learner, project, token)
|
||||
try:
|
||||
pdf_path = render_certificate_pdf(
|
||||
certificate,
|
||||
learner,
|
||||
project,
|
||||
token,
|
||||
concurrency_limit=get_pdf_generation_concurrency_limit(db),
|
||||
)
|
||||
except PdfGenerationBusy as exc:
|
||||
raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail=str(exc)) from exc
|
||||
db.commit()
|
||||
return FileResponse(pdf_path, media_type="application/pdf", filename=f"{certificate.certificate_no}.pdf")
|
||||
|
||||
|
||||
44
backend/app/api/routes/admin_settings.py
Normal file
44
backend/app/api/routes/admin_settings.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.api.deps import require_roles
|
||||
from app.db.session import get_db
|
||||
from app.models import AdminUser
|
||||
from app.schemas.setting import PdfSettingsOut, PdfSettingsUpdate
|
||||
from app.services.logs import log_action
|
||||
from app.services.system_settings import get_pdf_settings, update_pdf_generation_concurrency_limit
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/pdf", response_model=PdfSettingsOut)
|
||||
def get_pdf_generation_settings(
|
||||
db: Session = Depends(get_db),
|
||||
_: AdminUser = Depends(require_roles("system_admin")),
|
||||
) -> dict[str, object]:
|
||||
settings = get_pdf_settings(db)
|
||||
db.commit()
|
||||
return settings
|
||||
|
||||
|
||||
@router.put("/pdf", response_model=PdfSettingsOut)
|
||||
def update_pdf_generation_settings(
|
||||
payload: PdfSettingsUpdate,
|
||||
db: Session = Depends(get_db),
|
||||
admin: AdminUser = Depends(require_roles("system_admin")),
|
||||
) -> dict[str, object]:
|
||||
before = get_pdf_settings(db)
|
||||
after = update_pdf_generation_concurrency_limit(db, payload.pdf_generation_concurrency_limit)
|
||||
log_action(
|
||||
db,
|
||||
admin,
|
||||
"update_pdf_settings",
|
||||
"system_setting",
|
||||
"pdf_generation_concurrency_limit",
|
||||
detail={
|
||||
"before": before["pdf_generation_concurrency_limit"],
|
||||
"after": after["pdf_generation_concurrency_limit"],
|
||||
},
|
||||
)
|
||||
db.commit()
|
||||
return after
|
||||
@@ -8,9 +8,10 @@ from app.db.session import get_db
|
||||
from app.models import Certificate, CertificateAccessToken, Learner, ProjectCourse
|
||||
from app.services.captcha import make_captcha, verify_captcha
|
||||
from app.services.logs import log_action, mask_phone
|
||||
from app.services.pdf import render_certificate_pdf
|
||||
from app.services.pdf import PdfGenerationBusy, render_certificate_pdf
|
||||
from app.services.rate_limit import hit_too_often
|
||||
from app.services.sms import generate_sms_code, verify_sms_code
|
||||
from app.services.system_settings import get_pdf_generation_concurrency_limit
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
@@ -150,7 +151,16 @@ def download_certificate_pdf(token: str, db: Session = Depends(get_db)) -> FileR
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="证书已作废,不支持下载正常 PDF")
|
||||
|
||||
project = db.query(ProjectCourse).filter(ProjectCourse.code == certificate.project_code).first()
|
||||
pdf_path = render_certificate_pdf(certificate, learner, project, access_token)
|
||||
try:
|
||||
pdf_path = render_certificate_pdf(
|
||||
certificate,
|
||||
learner,
|
||||
project,
|
||||
access_token,
|
||||
concurrency_limit=get_pdf_generation_concurrency_limit(db),
|
||||
)
|
||||
except PdfGenerationBusy as exc:
|
||||
raise HTTPException(status_code=status.HTTP_429_TOO_MANY_REQUESTS, detail=str(exc)) from exc
|
||||
log_action(db, None, "public_download_certificate", "certificate", certificate.id, {"certificate_no": certificate.certificate_no, "learner_name": learner.current_name, "project_code": certificate.project_code})
|
||||
db.commit()
|
||||
return FileResponse(pdf_path, media_type="application/pdf", filename=f"{certificate.certificate_no}.pdf")
|
||||
|
||||
Reference in New Issue
Block a user