"""系统设置 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": "企业微信配置已保存"}