|
|
""" |
|
|
新架构的主应用入口 |
|
|
整合所有路由和服务 |
|
|
""" |
|
|
from contextlib import asynccontextmanager |
|
|
from fastapi import FastAPI |
|
|
from fastapi.staticfiles import StaticFiles |
|
|
from fastapi.templating import Jinja2Templates |
|
|
|
|
|
from src.api.routes import tasks, logs, settings, prompts, results, login_state, websocket, accounts |
|
|
from src.api.dependencies import set_process_service |
|
|
from src.services.task_service import TaskService |
|
|
from src.services.process_service import ProcessService |
|
|
from src.services.scheduler_service import SchedulerService |
|
|
from src.infrastructure.persistence.json_task_repository import JsonTaskRepository |
|
|
|
|
|
|
|
|
|
|
|
process_service = ProcessService() |
|
|
scheduler_service = SchedulerService(process_service) |
|
|
|
|
|
|
|
|
set_process_service(process_service) |
|
|
|
|
|
|
|
|
@asynccontextmanager |
|
|
async def lifespan(app: FastAPI): |
|
|
"""应用生命周期管理""" |
|
|
|
|
|
print("正在启动应用...") |
|
|
|
|
|
|
|
|
task_repo = JsonTaskRepository() |
|
|
task_service = TaskService(task_repo) |
|
|
tasks_list = await task_service.get_all_tasks() |
|
|
|
|
|
for task in tasks_list: |
|
|
if task.is_running: |
|
|
await task_service.update_task_status(task.id, False) |
|
|
|
|
|
|
|
|
await scheduler_service.reload_jobs(tasks_list) |
|
|
scheduler_service.start() |
|
|
|
|
|
print("应用启动完成") |
|
|
|
|
|
yield |
|
|
|
|
|
|
|
|
print("正在关闭应用...") |
|
|
scheduler_service.stop() |
|
|
await process_service.stop_all() |
|
|
print("应用已关闭") |
|
|
|
|
|
|
|
|
|
|
|
app = FastAPI( |
|
|
title="闲鱼智能监控机器人", |
|
|
description="基于AI的闲鱼商品监控系统", |
|
|
version="2.0.0", |
|
|
lifespan=lifespan |
|
|
) |
|
|
|
|
|
|
|
|
app.include_router(tasks.router) |
|
|
app.include_router(logs.router) |
|
|
app.include_router(settings.router) |
|
|
app.include_router(prompts.router) |
|
|
app.include_router(results.router) |
|
|
app.include_router(login_state.router) |
|
|
app.include_router(websocket.router) |
|
|
app.include_router(accounts.router) |
|
|
|
|
|
|
|
|
|
|
|
app.mount("/static", StaticFiles(directory="static"), name="static") |
|
|
|
|
|
|
|
|
|
|
|
import os |
|
|
if os.path.exists("dist"): |
|
|
app.mount("/assets", StaticFiles(directory="dist/assets"), name="assets") |
|
|
|
|
|
|
|
|
|
|
|
@app.get("/health") |
|
|
async def health_check(): |
|
|
"""健康检查(无需认证)""" |
|
|
return {"status": "healthy", "message": "服务正常运行"} |
|
|
|
|
|
|
|
|
|
|
|
from fastapi import Request, HTTPException |
|
|
from fastapi.responses import FileResponse |
|
|
from pydantic import BaseModel |
|
|
from src.infrastructure.config.settings import settings |
|
|
|
|
|
class LoginRequest(BaseModel): |
|
|
username: str |
|
|
password: str |
|
|
|
|
|
|
|
|
@app.post("/auth/status") |
|
|
async def auth_status(payload: LoginRequest): |
|
|
"""检查认证状态""" |
|
|
if payload.username == settings.web_username and payload.password == settings.web_password: |
|
|
return {"authenticated": True, "username": payload.username} |
|
|
raise HTTPException(status_code=401, detail="认证失败") |
|
|
|
|
|
|
|
|
|
|
|
from fastapi.responses import JSONResponse |
|
|
|
|
|
@app.get("/") |
|
|
async def read_root(request: Request): |
|
|
"""提供 Vue 3 SPA 的主页面""" |
|
|
if os.path.exists("dist/index.html"): |
|
|
return FileResponse("dist/index.html") |
|
|
else: |
|
|
return JSONResponse( |
|
|
status_code=500, |
|
|
content={"error": "前端构建产物不存在,请先运行 cd web-ui && npm run build"} |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
@app.get("/{full_path:path}") |
|
|
async def serve_spa(request: Request, full_path: str): |
|
|
""" |
|
|
Catch-all 路由,将所有非 API 请求重定向到 index.html |
|
|
这样可以支持 Vue Router 的 HTML5 History 模式 |
|
|
""" |
|
|
|
|
|
if full_path.endswith(('.ico', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.css', '.js', '.json')): |
|
|
return JSONResponse(status_code=404, content={"error": "资源未找到"}) |
|
|
|
|
|
|
|
|
if os.path.exists("dist/index.html"): |
|
|
return FileResponse("dist/index.html") |
|
|
else: |
|
|
return JSONResponse( |
|
|
status_code=500, |
|
|
content={"error": "前端构建产物不存在,请先运行 cd web-ui && npm run build"} |
|
|
) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
import uvicorn |
|
|
from src.infrastructure.config.settings import settings |
|
|
|
|
|
print(f"启动新架构应用,端口: {settings.server_port}") |
|
|
uvicorn.run(app, host="0.0.0.0", port=settings.server_port) |
|
|
|