eaabebbceb
- MAC地址格式统一为小写 xxxx-xxxx-xxxx,支持三种格式输入 - 更换设备MAC时自动清理OLT新发现列表中的冲突ONU记录 - 设备编辑新增场所类型字段(手动输入),区域改为下拉快速填充 - 编辑/更换设备时自动移除new_devices中同MAC的待入库记录 - 新增登录过期自动跳转(401拦截 + 过期提示) - 新增关于页面(/about),支持Markdown渲染,管理员可在设置中编辑内容 - 新增device_status_history每日自动清理任务(保留30天) - 更新README.md和about.md
101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
"""系统设置 API(仅管理员)"""
|
||
import time
|
||
import redis as redis_lib
|
||
from fastapi import APIRouter, Depends, HTTPException
|
||
from sqlalchemy.orm import Session
|
||
from app.core.database import get_db
|
||
from app.core.config import settings
|
||
from app.middleware.permission_middleware import require_permission
|
||
from app.models.setting import SystemSetting
|
||
|
||
router = APIRouter(prefix="/api/settings", tags=["系统设置"])
|
||
|
||
MIN_CHECK_INTERVAL = 300 # 5 分钟
|
||
MAX_CHECK_INTERVAL = 86400 # 24 小时
|
||
|
||
_INTERVAL_REDIS_KEY = "system:check_interval_seconds"
|
||
|
||
|
||
def _get_redis():
|
||
return redis_lib.from_url(settings.REDIS_URL, decode_responses=True)
|
||
|
||
|
||
@router.get("")
|
||
def get_settings(
|
||
db: Session = Depends(get_db),
|
||
_: dict = Depends(require_permission('*')),
|
||
):
|
||
"""获取所有系统设置,附带下次扫描时间"""
|
||
rows = db.query(SystemSetting).all()
|
||
result = {row.key: {"value": row.value, "description": row.description} for row in rows}
|
||
|
||
# 计算下次扫描时间
|
||
try:
|
||
r = _get_redis()
|
||
interval_str = r.get(_INTERVAL_REDIS_KEY)
|
||
last_run_str = r.get("check_all_devices:last_run")
|
||
is_running = bool(r.get("check_all_devices:running"))
|
||
interval = int(interval_str) if interval_str else 1800
|
||
next_run_ts = (float(last_run_str) + interval) if last_run_str else None
|
||
result["next_check_at"] = {
|
||
"value": str(int(next_run_ts)) if next_run_ts else None,
|
||
"running": is_running,
|
||
"description": "下次扫描时间戳(Unix)"
|
||
}
|
||
except Exception:
|
||
result["next_check_at"] = {"value": None, "running": False, "description": "下次扫描时间戳(Unix)"}
|
||
|
||
return result
|
||
|
||
|
||
@router.put("/check_interval")
|
||
def update_check_interval(
|
||
seconds: int,
|
||
db: Session = Depends(get_db),
|
||
_: dict = Depends(require_permission('*')),
|
||
):
|
||
"""更新定时检查间隔(秒),范围 300~86400"""
|
||
if seconds < MIN_CHECK_INTERVAL:
|
||
raise HTTPException(status_code=400, detail=f"间隔不能小于 {MIN_CHECK_INTERVAL} 秒(5分钟)")
|
||
if seconds > MAX_CHECK_INTERVAL:
|
||
raise HTTPException(status_code=400, detail=f"间隔不能大于 {MAX_CHECK_INTERVAL} 秒(24小时)")
|
||
|
||
setting = db.query(SystemSetting).filter_by(key='check_interval_seconds').first()
|
||
if setting:
|
||
setting.value = str(seconds)
|
||
else:
|
||
db.add(SystemSetting(key='check_interval_seconds', value=str(seconds), description='定时检查间隔(秒)'))
|
||
db.commit()
|
||
|
||
# 同步到 Redis,让 Celery 任务立即生效
|
||
_get_redis().set(_INTERVAL_REDIS_KEY, str(seconds))
|
||
|
||
# 重置上次运行时间,让下次触发时立即按新间隔计算
|
||
_get_redis().delete("check_all_devices:last_run")
|
||
|
||
return {"key": "check_interval_seconds", "value": seconds}
|
||
|
||
|
||
@router.get("/about")
|
||
def get_about(db: Session = Depends(get_db)):
|
||
"""获取关于页面内容(公开接口,无需登录)"""
|
||
setting = db.query(SystemSetting).filter_by(key='about_content').first()
|
||
return {"content": setting.value if setting else ""}
|
||
|
||
|
||
@router.put("/about")
|
||
def update_about(
|
||
body: dict,
|
||
db: Session = Depends(get_db),
|
||
_: dict = Depends(require_permission('*')),
|
||
):
|
||
"""更新关于页面内容(仅管理员)"""
|
||
content = body.get("content", "")
|
||
setting = db.query(SystemSetting).filter_by(key='about_content').first()
|
||
if setting:
|
||
setting.value = content
|
||
else:
|
||
db.add(SystemSetting(key='about_content', value=content, description='关于页面内容(Markdown)'))
|
||
db.commit()
|
||
return {"key": "about_content", "value": content}
|