120 lines
4.4 KiB
Python
120 lines
4.4 KiB
Python
# app/main.py
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.staticfiles import StaticFiles
|
|
import os
|
|
import time
|
|
|
|
from app.config import get_settings
|
|
from app.database import engine, Base
|
|
from app.routers import auth, home_modules, nav_menus, settings as settings_router, upload, images, crawl, wechat_crawl, batch_wechat_crawl, contact_qrcodes, app_downloads, home_experts, home_partners, columns, articles, seo, prerender
|
|
|
|
settings = get_settings()
|
|
|
|
# Create database tables
|
|
Base.metadata.create_all(bind=engine)
|
|
|
|
app = FastAPI(
|
|
title=settings.APP_NAME,
|
|
description="飞点健康官网 CMS 系统 API",
|
|
version="1.0.0"
|
|
)
|
|
|
|
# CORS
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=settings.CORS_ORIGINS,
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Static files for uploads
|
|
# Use the actual uploads directory where crawl.py saves images
|
|
# Resolve relative to backend root to match config.UPLOAD_DIR
|
|
backend_root = os.path.dirname(os.path.dirname(__file__))
|
|
upload_dir = os.path.join(backend_root, settings.UPLOAD_DIR)
|
|
os.makedirs(upload_dir, exist_ok=True)
|
|
app.mount("/uploads", StaticFiles(directory=upload_dir), name="uploads")
|
|
|
|
# New unified storage structure
|
|
storage_admin_dir = os.path.join(backend_root, "..", "storage", "admin")
|
|
storage_public_dir = os.path.join(backend_root, "..", "storage", "public")
|
|
storage_tmp_dir = os.path.join(backend_root, "..", "storage", "tmp")
|
|
os.makedirs(storage_admin_dir, exist_ok=True)
|
|
os.makedirs(storage_public_dir, exist_ok=True)
|
|
os.makedirs(storage_tmp_dir, exist_ok=True)
|
|
app.mount("/storage/admin", StaticFiles(directory=storage_admin_dir), name="storage_admin")
|
|
app.mount("/storage/public", StaticFiles(directory=storage_public_dir), name="storage_public")
|
|
app.mount("/storage/tmp", StaticFiles(directory=storage_tmp_dir), name="storage_tmp")
|
|
|
|
|
|
def cleanup_old_temp_files():
|
|
"""启动时清理超过24小时的采集临时文件"""
|
|
try:
|
|
if os.name == 'nt': # Windows
|
|
temp_dir = os.path.join(backend_root, "..", "storage", "tmp", "crawl")
|
|
else:
|
|
temp_dir = "/tmp/news_crawl"
|
|
|
|
if not os.path.exists(temp_dir):
|
|
return
|
|
|
|
now = time.time()
|
|
max_age = 24 * 3600 # 24小时
|
|
count = 0
|
|
|
|
for root, dirs, files in os.walk(temp_dir):
|
|
for f in files:
|
|
filepath = os.path.join(root, f)
|
|
try:
|
|
if now - os.path.getmtime(filepath) > max_age:
|
|
os.remove(filepath)
|
|
count += 1
|
|
except OSError:
|
|
pass
|
|
|
|
if count > 0:
|
|
print(f"[cleanup] 已清理 {count} 个过期临时文件")
|
|
except Exception as e:
|
|
print(f"[cleanup] 清理临时文件失败: {e}")
|
|
|
|
|
|
# 启动时执行清理
|
|
cleanup_old_temp_files()
|
|
|
|
# Routers
|
|
# SEO 路由(无 /api 前缀,直接暴露于根域名)
|
|
app.include_router(seo.router)
|
|
app.include_router(prerender.router)
|
|
|
|
app.include_router(auth.router, prefix="/api/auth", tags=["认证"])
|
|
app.include_router(home_modules.router, prefix="/api", tags=["首页模块"])
|
|
app.include_router(nav_menus.router, prefix="/api", tags=["导航菜单"])
|
|
app.include_router(settings_router.router, prefix="/api", tags=["系统设置"])
|
|
app.include_router(upload.router, prefix="/api", tags=["文件上传"])
|
|
app.include_router(images.router, prefix="/api", tags=["图片管理"])
|
|
app.include_router(crawl.router, prefix="/api", tags=["文章采集"])
|
|
app.include_router(wechat_crawl.router, prefix="/api", tags=["公众号采集"])
|
|
app.include_router(batch_wechat_crawl.router, prefix="/api", tags=["批量公众号采集"])
|
|
app.include_router(contact_qrcodes.router, prefix="/api", tags=["咨询二维码"])
|
|
app.include_router(app_downloads.router, prefix="/api", tags=["下载应用"])
|
|
app.include_router(home_experts.router, prefix="/api", tags=["专家团队"])
|
|
app.include_router(home_partners.router, prefix="/api", tags=["合作伙伴"])
|
|
app.include_router(columns.router, prefix="/api", tags=["栏目管理"])
|
|
app.include_router(articles.router, prefix="/api", tags=["内容管理"])
|
|
|
|
|
|
@app.get("/")
|
|
def root():
|
|
return {
|
|
"message": f"Welcome to {settings.APP_NAME}",
|
|
"docs": "/docs",
|
|
"version": "1.0.0"
|
|
}
|
|
|
|
|
|
@app.get("/health")
|
|
def health_check():
|
|
return {"status": "ok"}
|