feat: 初始化考培练系统项目

- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
111
2026-01-24 19:33:28 +08:00
commit 998211c483
1197 changed files with 228429 additions and 0 deletions

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

@@ -0,0 +1,140 @@
"""考培练系统后端主应用"""
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi.staticfiles import StaticFiles
import json
import os
from app.core.config import get_settings
from app.api.v1 import api_router
# 配置日志
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
logger = logging.getLogger(__name__)
settings = get_settings()
@asynccontextmanager
async def lifespan(app: FastAPI):
"""应用生命周期管理"""
# 启动时执行
logger.info(f"启动 {settings.APP_NAME} v{settings.APP_VERSION}")
# 初始化 Redis
try:
from app.core.redis import init_redis, close_redis
await init_redis()
logger.info("Redis 初始化成功")
except Exception as e:
logger.warning(f"Redis 初始化失败(非致命): {e}")
yield
# 关闭时执行
try:
from app.core.redis import close_redis
await close_redis()
logger.info("Redis 连接已关闭")
except Exception as e:
logger.warning(f"关闭 Redis 连接失败: {e}")
logger.info("应用关闭")
# 自定义 JSON 响应类,确保中文正确编码
class UTF8JSONResponse(JSONResponse):
def render(self, content) -> bytes:
return json.dumps(
content,
ensure_ascii=False,
allow_nan=False,
indent=None,
separators=(",", ":"),
).encode("utf-8")
# 创建FastAPI应用
app = FastAPI(
title=settings.APP_NAME,
version=settings.APP_VERSION,
description="考培练系统后端API",
lifespan=lifespan,
# 确保响应正确的 UTF-8 编码
default_response_class=UTF8JSONResponse,
)
# 配置CORS
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 健康检查端点
@app.get("/health")
async def health_check():
"""健康检查"""
return {
"status": "healthy",
"service": settings.APP_NAME,
"version": settings.APP_VERSION,
}
# 根路径
@app.get("/")
async def root():
"""根路径"""
return {
"message": f"欢迎使用{settings.APP_NAME}",
"version": settings.APP_VERSION,
"docs": "/docs",
}
# 注册路由
app.include_router(api_router, prefix="/api/v1")
# 挂载静态文件目录
# 创建上传目录(如果不存在)
upload_path = settings.UPLOAD_PATH
os.makedirs(upload_path, exist_ok=True)
# 挂载上传文件目录为静态文件服务
app.mount("/static/uploads", StaticFiles(directory=upload_path), name="uploads")
# 全局异常处理
@app.exception_handler(Exception)
async def global_exception_handler(request, exc):
"""全局异常处理"""
logger.error(f"未处理的异常: {exc}", exc_info=True)
return JSONResponse(
status_code=500,
content={
"code": 500,
"message": "内部服务器错误",
"detail": str(exc) if settings.DEBUG else None,
},
)
if __name__ == "__main__":
import uvicorn
uvicorn.run(
"app.main:app",
host=settings.HOST,
port=settings.PORT,
reload=settings.DEBUG,
log_level=settings.LOG_LEVEL.lower(),
)
# 测试热重载 - Fri Sep 26 03:37:07 CST 2025