Binary file not shown.
Binary file not shown.
@@ -0,0 +1,55 @@
|
||||
from fastapi import APIRouter, HTTPException, Depends
|
||||
from pydantic import BaseModel
|
||||
import db
|
||||
import auth
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class UserAuth(BaseModel):
|
||||
username: str
|
||||
password: str
|
||||
|
||||
@router.post("/api/register")
|
||||
def register(user: UserAuth):
|
||||
if not user.username or not user.password:
|
||||
raise HTTPException(status_code=400, detail="用户名和密码不能为空")
|
||||
if len(user.username) < 3 or len(user.username) > 20:
|
||||
raise HTTPException(status_code=400, detail="用户名长度需在3-20个字符之间")
|
||||
if len(user.password) < 6:
|
||||
raise HTTPException(status_code=400, detail="密码长度至少6个字符")
|
||||
|
||||
existing_user = db.get_user_by_username(user.username)
|
||||
if existing_user:
|
||||
raise HTTPException(status_code=400, detail="用户名已存在")
|
||||
|
||||
hashed_password = auth.get_password_hash(user.password)
|
||||
new_user = db.create_user({"username": user.username, "password": hashed_password})
|
||||
|
||||
return {"message": "注册成功", "userId": new_user["id"]}
|
||||
|
||||
@router.post("/api/login")
|
||||
def login(user: UserAuth):
|
||||
if not user.username or not user.password:
|
||||
raise HTTPException(status_code=400, detail="用户名和密码不能为空")
|
||||
|
||||
db_user = db.get_user_by_username(user.username)
|
||||
if not db_user:
|
||||
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
||||
|
||||
if not auth.verify_password(user.password, db_user["password"]):
|
||||
raise HTTPException(status_code=401, detail="用户名或密码错误")
|
||||
|
||||
token = auth.create_access_token({"id": db_user["id"], "username": db_user["username"]})
|
||||
return {
|
||||
"message": "登录成功",
|
||||
"token": token,
|
||||
"user": {"id": db_user["id"], "username": db_user["username"]}
|
||||
}
|
||||
|
||||
@router.get("/api/me")
|
||||
def get_me(current_user: dict = Depends(auth.get_current_user)):
|
||||
return {"user": {"id": current_user["id"], "username": current_user["username"]}}
|
||||
|
||||
@router.post("/api/logout")
|
||||
def logout():
|
||||
return {"message": "已退出登录"}
|
||||
@@ -0,0 +1,69 @@
|
||||
import os
|
||||
import tempfile
|
||||
import pypandoc
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, HTTPException, Depends
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel
|
||||
from starlette.background import BackgroundTask
|
||||
import auth
|
||||
import db
|
||||
from formula_processor import preprocess_formulas
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class DocRequest(BaseModel):
|
||||
markdown: str
|
||||
|
||||
def remove_file(path: str):
|
||||
try:
|
||||
os.remove(path)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@router.post("/api/convert")
|
||||
async def convert_md_to_docx(req: DocRequest, current_user: Optional[dict] = Depends(auth.get_optional_user)):
|
||||
try:
|
||||
# 如果带有合法登录 token,则记录历史
|
||||
if current_user:
|
||||
db.add_history_record(current_user["id"], req.markdown)
|
||||
|
||||
try:
|
||||
pypandoc.get_pandoc_version()
|
||||
except OSError:
|
||||
pypandoc.download_pandoc()
|
||||
|
||||
# ====== 公式预处理:统一各种定界符格式 ======
|
||||
# 将 GPT/AI 生成内容中 \(...\)、\[...\]、缺失反斜杠的 [...] 和 (...)
|
||||
# 全部转换为 Pandoc 可识别的标准 $...$ 和 $$...$$ 格式
|
||||
processed_markdown = preprocess_formulas(req.markdown)
|
||||
|
||||
fd, tmp_path = tempfile.mkstemp(suffix=".docx")
|
||||
os.close(fd)
|
||||
|
||||
md_fd, md_tmp_path = tempfile.mkstemp(suffix=".md")
|
||||
with os.fdopen(md_fd, 'w', encoding='utf-8') as f:
|
||||
f.write(processed_markdown)
|
||||
|
||||
pypandoc.convert_file(
|
||||
md_tmp_path,
|
||||
'docx',
|
||||
format='markdown+tex_math_dollars',
|
||||
outputfile=tmp_path
|
||||
)
|
||||
os.remove(md_tmp_path)
|
||||
|
||||
return FileResponse(
|
||||
tmp_path,
|
||||
media_type='application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
filename='document.docx',
|
||||
background=BackgroundTask(remove_file, tmp_path)
|
||||
)
|
||||
except Exception as e:
|
||||
print(f"Error during conversion: {e}")
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.get("/api/history")
|
||||
async def get_history(current_user: dict = Depends(auth.get_current_user)):
|
||||
history = db.get_history_records(current_user["id"])
|
||||
return {"history": history}
|
||||
Reference in New Issue
Block a user