- 首页/播放页: 去掉 antd Layout 改用 div 避免 flex 布局问题
- 播放页: 返回按钮改为 navigate('/') 替代 window.close()
- 后端登录/验证: 改用 POST JSON body 替代 query param
- 后端鉴权: require_auth 依赖注入保护所有管理接口
- nodes路由: 修复 /strategy 被 /{node_id} 拦截的顺序问题
- 前端 Settings: 策略更新改为 JSON body
68 lines
2.0 KiB
Python
68 lines
2.0 KiB
Python
from fastapi import APIRouter, HTTPException, Depends
|
|
from pydantic import BaseModel
|
|
from config import settings
|
|
from routes.auth import require_auth
|
|
from services.load_balancer import lb
|
|
from services.multicast_detector import multicast_detector
|
|
|
|
router = APIRouter(prefix="/api/nodes", tags=["nodes"])
|
|
|
|
|
|
class NodeUpdate(BaseModel):
|
|
weight: int
|
|
enabled: bool | None = None
|
|
|
|
|
|
class StrategyUpdate(BaseModel):
|
|
strategy: str
|
|
multicast_enabled: bool | None = None
|
|
|
|
|
|
@router.get("")
|
|
async def list_nodes(_: bool = Depends(require_auth)):
|
|
nodes = []
|
|
for n in settings.edge_nodes:
|
|
nodes.append({
|
|
"id": n["id"],
|
|
"name": n["name"],
|
|
"host": n["host"],
|
|
"hls_port": n["hls_port"],
|
|
"api_port": n["api_port"],
|
|
"weight": n["weight"],
|
|
"enabled": n.get("enabled", True),
|
|
})
|
|
return nodes
|
|
|
|
|
|
@router.get("/strategy")
|
|
async def get_strategy(_: bool = Depends(require_auth)):
|
|
return {
|
|
"strategy": settings.load_balance_strategy,
|
|
"multicast_enabled": settings.multicast_enabled,
|
|
"multicast_available": multicast_detector.is_available(),
|
|
}
|
|
|
|
|
|
@router.put("/strategy")
|
|
async def update_strategy(body: StrategyUpdate, _: bool = Depends(require_auth)):
|
|
if body.strategy in ("round-robin", "weighted", "least-conn"):
|
|
settings.load_balance_strategy = body.strategy
|
|
if body.multicast_enabled is not None:
|
|
settings.multicast_enabled = body.multicast_enabled
|
|
return {"ok": True}
|
|
|
|
|
|
@router.put("/{node_id}")
|
|
async def update_node(node_id: str, body: NodeUpdate, _: bool = Depends(require_auth)):
|
|
found = False
|
|
for n in settings.edge_nodes:
|
|
if n["id"] == node_id:
|
|
n["weight"] = body.weight
|
|
if body.enabled is not None:
|
|
n["enabled"] = body.enabled
|
|
found = True
|
|
break
|
|
if not found:
|
|
raise HTTPException(status_code=404, detail="Node not found")
|
|
return {"ok": True}
|