| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- # web/server.py
- import os
- from pathlib import Path
- from fastapi import FastAPI, HTTPException
- from fastapi.staticfiles import StaticFiles
- from fastapi.responses import FileResponse
- from pydantic import BaseModel
- from core.app_manager import AppManager
- from vs_log_macros import VSC_INFO, VSC_ERROR
- app = FastAPI(title="Visa Plugin Manager")
- # === 1. 路径计算 (关键修改) ===
- # 获取 web/server.py 所在的绝对路径目录
- CURRENT_DIR = Path(__file__).resolve().parent
- # 拼接出 static 目录: .../web/static
- STATIC_DIR = CURRENT_DIR / "static"
- # 拼接出 index.html 路径
- INDEX_FILE = STATIC_DIR / "index.html"
- VSC_INFO("web", f"Static Directory configured at: {STATIC_DIR}")
- VSC_INFO("web", f"Index File expected at: {INDEX_FILE}")
- # 确保目录存在
- if not STATIC_DIR.exists():
- VSC_INFO("web", "Static directory missing, creating...")
- STATIC_DIR.mkdir(parents=True, exist_ok=True)
- # === 2. 挂载静态文件 ===
- # 挂载 /static 路径,用于访问 CSS/JS 等资源 (虽然本例是CDN,但保留以备用)
- app.mount("/static", StaticFiles(directory=str(STATIC_DIR)), name="static")
- # === 3. 根路径路由 ===
- @app.get("/")
- async def read_index():
- # 显式检查文件是否存在,方便调试
- if not INDEX_FILE.exists():
- return {
- "error": "Index file not found",
- "expected_path": str(INDEX_FILE),
- "tip": "Please ensure 'index.html' exists in the 'web/static' folder."
- }
- return FileResponse(str(INDEX_FILE))
- # === 数据模型 ===
- class GroupControl(BaseModel):
- group_id: str
- class OTARequest(BaseModel):
- plugin_name: str
- # === API 接口 ===
- @app.get("/status")
- def get_status():
- return {"data": AppManager.Instance().get_status()}
- @app.post("/reload_config")
- def reload_config():
- AppManager.Instance().load_configs()
- return {"message": "Configuration reloaded"}
- @app.post("/start")
- def start_group(payload: GroupControl):
- if AppManager.Instance().start_group(payload.group_id):
- return {"message": f"Group {payload.group_id} started"}
- raise HTTPException(status_code=400, detail="Failed to start group")
- @app.post("/stop")
- def stop_group(payload: GroupControl):
- if AppManager.Instance().stop_group(payload.group_id):
- return {"message": f"Group {payload.group_id} stopped"}
- raise HTTPException(status_code=400, detail="Group not running or failed to stop")
- @app.post("/restart")
- def restart_group(payload: GroupControl):
- if AppManager.Instance().restart_group(payload.group_id):
- return {"message": f"Group {payload.group_id} restarted"}
- raise HTTPException(status_code=400, detail="Failed to restart")
- @app.post("/ota")
- def ota_update(payload: OTARequest):
- try:
- restarted = AppManager.Instance().ota_update_plugin(payload.plugin_name)
- return {
- "message": f"Plugin {payload.plugin_name} reloaded",
- "restarted_groups": restarted
- }
- except Exception as e:
- raise HTTPException(status_code=500, detail=str(e))
- def run_web_server(host="0.0.0.0", port=8000):
- import uvicorn
- # log_level warning 减少控制台刷屏
- uvicorn.run(app, host=host, port=port, log_level="info")
|