b2c20ec43d
- 新增微信告警服务(wechat_service)和告警任务(alert_tasks) - 新增 WebSocket 实时推送端点 - 新增监控管理模块(monitor) - 增强统计仪表板:趋势图、区域分布、光功率历史 - 设备管理:添加坐标信息、标签系统、复合索引优化 - 前端:重构Dashboard/Charts页面,新增业务组件 - 新增5个数据库迁移(坐标、复合索引、标签、光功率历史、显示名) - 更新部署配置和脚本 - 新增测试框架基础结构
127 lines
4.4 KiB
Python
127 lines
4.4 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}
|
||
|
||
|
||
@router.put("/webhook")
|
||
def update_webhook(
|
||
body: dict,
|
||
db: Session = Depends(get_db),
|
||
_: dict = Depends(require_permission('*')),
|
||
):
|
||
"""更新企业微信告警配置(仅管理员)"""
|
||
configs = [
|
||
("wechat_corpid", body.get("corpid", ""), "企业微信 CorpID"),
|
||
("wechat_corpsecret", body.get("corpsecret", ""), "企业微信 CorpSecret"),
|
||
("wechat_agentid", body.get("agentid", ""), "企业微信 AgentID"),
|
||
]
|
||
for key, value, desc in configs:
|
||
setting = db.query(SystemSetting).filter_by(key=key).first()
|
||
if setting:
|
||
setting.value = value
|
||
else:
|
||
db.add(SystemSetting(key=key, value=value, description=desc))
|
||
|
||
db.commit()
|
||
return {"message": "企业微信配置已保存"}
|
||
|
||
|
||
|