fix:修复项目结构

This commit is contained in:
ZhangYonghao
2026-03-21 19:16:31 +08:00
parent 33a23bcc03
commit f2c371b87d
30 changed files with 0 additions and 0 deletions

0
backend/app/__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

22
backend/app/config.py Normal file
View File

@@ -0,0 +1,22 @@
import os
from pathlib import Path
from dotenv import load_dotenv
backend_dir = Path(__file__).resolve().parent.parent
load_dotenv(backend_dir / ".env")
class Settings:
app_name = "HTML Generator API"
api_prefix = "/api"
backend_dir = backend_dir
data_dir = backend_dir / "data"
database_path = data_dir / "html_generator.db"
database_url = f"sqlite:///{database_path.as_posix()}"
allowed_origins = ["*"]
frontend_base_url = os.environ.get("FRONTEND_BASE_URL", "http://localhost:3000")
static_dir = backend_dir / "../frontend/public/static"
settings = Settings()

23
backend/app/database.py Normal file
View File

@@ -0,0 +1,23 @@
from collections.abc import Generator
from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker
from app.config import settings
settings.data_dir.mkdir(parents=True, exist_ok=True)
engine = create_engine(
settings.database_url,
connect_args={"check_same_thread": False},
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db() -> Generator:
db = SessionLocal()
try:
yield db
finally:
db.close()

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

@@ -0,0 +1,43 @@
import logging
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config import settings
from app.database import Base, engine, SessionLocal
from app.models import HTMLFile
from app.routers import html
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
Base.metadata.create_all(bind=engine)
# 删除过期记录
db = SessionLocal()
try:
deleted_count = HTMLFile.delete_expired_records(db)
if deleted_count > 0:
logger.info(f"Deleted {deleted_count} expired HTML file records")
finally:
db.close()
app = FastAPI(title=settings.app_name)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.allowed_origins,
allow_credentials=False,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(html.router, prefix=settings.api_prefix)
@app.get("/")
def health_check() -> dict[str, str]:
return {"message": "HTML Generator API is running"}

30
backend/app/models.py Normal file
View File

@@ -0,0 +1,30 @@
from datetime import datetime, timedelta
from sqlalchemy import DateTime, Integer, String
from sqlalchemy.orm import Mapped, mapped_column, Session
from app.database import Base
class HTMLFile(Base):
__tablename__ = "html_files"
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
unique_id: Mapped[str] = mapped_column(
String(32), unique=True, index=True, nullable=False
)
filename: Mapped[str] = mapped_column(String(255), nullable=False)
created_at: Mapped[datetime] = mapped_column(
DateTime, default=datetime.utcnow, nullable=False
)
updated_at: Mapped[datetime] = mapped_column(
DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, nullable=False
)
@classmethod
def delete_expired_records(cls, db: Session, days: int = 5) -> int:
"""删除超过指定天数的记录"""
cutoff_date = datetime.utcnow() - timedelta(days=days)
deleted = db.query(cls).filter(cls.created_at < cutoff_date).delete()
db.commit()
return deleted

View File

View File

@@ -0,0 +1,86 @@
import os
import secrets
import logging
from fastapi import APIRouter, HTTPException, status, Depends
from sqlalchemy.orm import Session
from app.config import settings
from app.database import get_db
from app.models import HTMLFile
from app.schemas import HTMLGenerateRequest, HTMLGenerateResponse
router = APIRouter(prefix="/html", tags=["html"])
logger = logging.getLogger(__name__)
def generate_unique_id() -> str:
return secrets.token_urlsafe(16)
@router.post("/generate", response_model=HTMLGenerateResponse, status_code=status.HTTP_201_CREATED)
def generate_html(request: HTMLGenerateRequest, db: Session = Depends(get_db)):
try:
# 先删除过期记录
deleted_count = HTMLFile.delete_expired_records(db)
if deleted_count > 0:
logger.info(f"Deleted {deleted_count} expired HTML file records")
# 生成唯一 ID
unique_id = generate_unique_id()
# 确保静态文件目录存在
static_dir = settings.static_dir.resolve()
static_dir.mkdir(parents=True, exist_ok=True)
# 生成 HTML 文件路径
html_filename = f"{unique_id}.html"
html_path = static_dir / html_filename
# 写入 HTML 内容
with open(html_path, "w", encoding="utf-8") as f:
f.write(request.html_content)
# 保存到数据库
html_file = HTMLFile(
unique_id=unique_id,
filename=html_filename,
)
db.add(html_file)
db.commit()
db.refresh(html_file)
# 生成完整链接
html_url = f"{settings.frontend_base_url}/static/{html_filename}"
return HTMLGenerateResponse(
message="HTML 文件生成成功",
unique_id=unique_id,
url=html_url
)
except Exception as e:
logger.error(f"生成 HTML 文件失败: {str(e)}")
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"生成 HTML 文件失败: {str(e)}"
)
@router.get("/{unique_id}")
def get_html_file(unique_id: str, db: Session = Depends(get_db)):
html_file = db.query(HTMLFile).filter(HTMLFile.unique_id == unique_id).first()
if not html_file:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="HTML 文件不存在"
)
# 生成完整链接
html_url = f"{settings.frontend_base_url}/static/{html_file.filename}"
return {
"message": "HTML 文件查询成功",
"unique_id": html_file.unique_id,
"url": html_url
}

23
backend/app/schemas.py Normal file
View File

@@ -0,0 +1,23 @@
from datetime import datetime
from pydantic import BaseModel
class HTMLGenerateRequest(BaseModel):
html_content: str
class HTMLGenerateResponse(BaseModel):
message: str
unique_id: str
url: str
class HTMLFileResponse(BaseModel):
id: int
unique_id: str
filename: str
created_at: datetime
updated_at: datetime
class Config:
from_attributes = True