127 lines
4.5 KiB
Python
127 lines
4.5 KiB
Python
import uuid
|
|
from fastapi import APIRouter, Depends, HTTPException, UploadFile, File, Form, Query
|
|
from fastapi.responses import Response
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select
|
|
from app.core.database import get_db
|
|
from app.models.template import Template
|
|
from app.schemas.template import TemplateResponse, TemplateListItem, HTMLContentResponse, HTMLUpdateRequest
|
|
from app.services.file_storage import save_upload, get_file_content, delete_file, TEMPLATES_DIR
|
|
from app.services.document_processor import docx_to_html, html_to_docx_bytes, docx_to_pdf_bytes
|
|
|
|
router = APIRouter(prefix="/templates", tags=["模板管理"])
|
|
|
|
|
|
@router.post("", response_model=TemplateResponse)
|
|
async def upload_template(
|
|
file: UploadFile = File(...),
|
|
name: str | None = Form(None),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
if not file.filename or not file.filename.endswith(".docx"):
|
|
raise HTTPException(status_code=400, detail="仅支持 .docx 文件")
|
|
|
|
file_path = await save_upload(file, TEMPLATES_DIR)
|
|
file_content = await get_file_content(file_path)
|
|
html_content = await docx_to_html(file_content)
|
|
|
|
template = Template(
|
|
name=name or file.filename.replace(".docx", ""),
|
|
file_path=file_path,
|
|
html_content=html_content,
|
|
)
|
|
db.add(template)
|
|
await db.flush()
|
|
await db.refresh(template)
|
|
return template
|
|
|
|
|
|
@router.get("", response_model=list[TemplateListItem])
|
|
async def list_templates(
|
|
skip: int = Query(0, ge=0),
|
|
limit: int = Query(20, ge=1, le=100),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
query = select(Template).offset(skip).limit(limit).order_by(Template.created_at.desc())
|
|
result = await db.execute(query)
|
|
return result.scalars().all()
|
|
|
|
|
|
@router.get("/{template_id}", response_model=TemplateResponse)
|
|
async def get_template(template_id: str, db: AsyncSession = Depends(get_db)):
|
|
result = await db.execute(select(Template).where(Template.id == template_id))
|
|
template = result.scalar_one_or_none()
|
|
if not template:
|
|
raise HTTPException(status_code=404, detail="模板不存在")
|
|
return template
|
|
|
|
|
|
@router.get("/{template_id}/html", response_model=HTMLContentResponse)
|
|
async def get_template_html(template_id: str, db: AsyncSession = Depends(get_db)):
|
|
result = await db.execute(select(Template).where(Template.id == template_id))
|
|
template = result.scalar_one_or_none()
|
|
if not template:
|
|
raise HTTPException(status_code=404, detail="模板不存在")
|
|
return HTMLContentResponse(html_content=template.html_content or "")
|
|
|
|
|
|
@router.put("/{template_id}/html")
|
|
async def update_template_html(
|
|
template_id: str,
|
|
data: HTMLUpdateRequest,
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
result = await db.execute(select(Template).where(Template.id == template_id))
|
|
template = result.scalar_one_or_none()
|
|
if not template:
|
|
raise HTTPException(status_code=404, detail="模板不存在")
|
|
|
|
template.html_content = data.html_content
|
|
|
|
docx_bytes = html_to_docx_bytes(data.html_content)
|
|
with open(template.file_path, "wb") as f:
|
|
f.write(docx_bytes)
|
|
|
|
await db.flush()
|
|
return {"detail": "保存成功"}
|
|
|
|
|
|
@router.get("/{template_id}/download")
|
|
async def download_template(
|
|
template_id: str,
|
|
format: str = Query("docx", pattern="^(docx|pdf)$"),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
result = await db.execute(select(Template).where(Template.id == template_id))
|
|
template = result.scalar_one_or_none()
|
|
if not template:
|
|
raise HTTPException(status_code=404, detail="模板不存在")
|
|
|
|
file_content = await get_file_content(template.file_path)
|
|
|
|
if format == "pdf":
|
|
file_content = docx_to_pdf_bytes(file_content)
|
|
media_type = "application/pdf"
|
|
filename = f"{template.name}.pdf"
|
|
else:
|
|
media_type = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
filename = f"{template.name}.docx"
|
|
|
|
return Response(
|
|
content=file_content,
|
|
media_type=media_type,
|
|
headers={"Content-Disposition": f'attachment; filename="{filename}"'},
|
|
)
|
|
|
|
|
|
@router.delete("/{template_id}")
|
|
async def delete_template(template_id: str, db: AsyncSession = Depends(get_db)):
|
|
result = await db.execute(select(Template).where(Template.id == template_id))
|
|
template = result.scalar_one_or_none()
|
|
if not template:
|
|
raise HTTPException(status_code=404, detail="模板不存在")
|
|
|
|
delete_file(template.file_path)
|
|
await db.delete(template)
|
|
return {"detail": "删除成功"}
|