First upload.

Signed-off-by: Chen Xiao <abigwc@gmail.com>
This commit is contained in:
Chen Xiao
2026-05-09 14:40:49 +08:00
parent 0b64e2de94
commit 08a05b088a
95 changed files with 1198 additions and 67802 deletions
+61
View File
@@ -6,14 +6,26 @@ from fastapi import APIRouter, HTTPException, Depends
from fastapi.responses import FileResponse
from pydantic import BaseModel
from starlette.background import BackgroundTask
import docx
from docx.shared import Pt
from docx.oxml.ns import qn
import auth
import db
from formula_processor import preprocess_formulas
router = APIRouter()
class StyleOptions(BaseModel):
base_font_size: Optional[int] = 12
base_font_family: Optional[str] = "宋体"
h1_size: Optional[int] = 18
h2_size: Optional[int] = 16
h3_size: Optional[int] = 14
h4_size: Optional[int] = 12
class DocRequest(BaseModel):
markdown: str
styleOptions: Optional[StyleOptions] = None
def remove_file(path: str):
try:
@@ -53,6 +65,55 @@ async def convert_md_to_docx(req: DocRequest, current_user: Optional[dict] = Dep
)
os.remove(md_tmp_path)
# ====== 样式后处理 ======
if req.styleOptions:
doc = docx.Document(tmp_path)
def set_font(style_name, font_name, font_size):
try:
style = doc.styles[style_name]
if font_size:
style.font.size = Pt(font_size)
if font_name:
style.font.name = font_name
style._element.rPr.rFonts.set(qn('w:eastAsia'), font_name)
except KeyError:
pass
set_font('Normal', req.styleOptions.base_font_family, req.styleOptions.base_font_size)
set_font('Heading 1', req.styleOptions.base_font_family, req.styleOptions.h1_size)
set_font('Heading 2', req.styleOptions.base_font_family, req.styleOptions.h2_size)
set_font('Heading 3', req.styleOptions.base_font_family, req.styleOptions.h3_size)
set_font('Heading 4', req.styleOptions.base_font_family, req.styleOptions.h4_size)
set_font('Heading 5', req.styleOptions.base_font_family, req.styleOptions.h4_size)
set_font('Heading 6', req.styleOptions.base_font_family, req.styleOptions.h4_size)
# 强制遍历并覆盖所有段落的 run,确保样式生效
for p in doc.paragraphs:
# 判定当前段落是不是标题
current_font_size = req.styleOptions.base_font_size
current_font_family = req.styleOptions.base_font_family
if p.style.name.startswith('Heading'):
level_str = p.style.name.replace('Heading ', '')
try:
level = int(level_str)
if level == 1: current_font_size = req.styleOptions.h1_size
elif level == 2: current_font_size = req.styleOptions.h2_size
elif level == 3: current_font_size = req.styleOptions.h3_size
elif level >= 4: current_font_size = req.styleOptions.h4_size
except:
pass
# 为该段落中每一个具体的 run 设置字体
for run in p.runs:
run.font.name = current_font_family
run._element.rPr.rFonts.set(qn('w:eastAsia'), current_font_family)
if current_font_size:
run.font.size = Pt(current_font_size)
doc.save(tmp_path)
return FileResponse(
tmp_path,
media_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document',