""" 配置管理 """ import os from pathlib import Path from typing import Optional from dataclasses import dataclass from pydantic import BaseModel @dataclass class DatabaseConfig: """数据库配置""" url: str = "sqlite:///./data/alert_platform.db" @dataclass class COSConfig: """腾讯云 COS 存储配置(通过 CVM 角色认证,无需密钥)""" region: str = "ap-beijing" bucket: str = "" # 格式: bucketname-appid upload_prefix: str = "alerts" # 对象 Key 前缀 presign_expire: int = 1800 # 预签名URL有效期(秒),默认30分钟 enabled: bool = False # 是否启用 COS @dataclass class AppConfig: """应用配置""" host: str = "0.0.0.0" port: int = 8000 debug: bool = True dev_mode: bool = True # 开发模式:跳过认证验证,返回超级管理员权限 @dataclass class AIModelConfig: """AI 模型配置""" endpoint: str = "" api_key: str = "" @dataclass class VLMConfig: """VLM 视觉语言模型配置""" api_key: str = "" base_url: str = "https://dashscope.aliyuncs.com/compatible-mode/v1" model: str = "qwen3-vl-flash-2026-01-22" timeout: int = 10 enabled: bool = False enable_thinking: bool = False @dataclass class WeChatConfig: """企微通知配置""" corp_id: str = "" agent_id: str = "" secret: str = "" token: str = "" encoding_aes_key: str = "" enabled: bool = False test_uids: str = "" # 演示模式:逗号分隔的企微userid,如 "zhangsan,lisi" service_base_url: str = "" # H5页面公网地址,如 https://vsp.viewshanghai.com @dataclass class AgentConfig: """交互Agent配置""" llm_api_key: str = "" llm_base_url: str = "https://dashscope.aliyuncs.com/compatible-mode/v1" llm_model: str = "qwen-plus" llm_timeout: int = 15 enabled: bool = False @dataclass class RedisConfig: """Redis 配置""" host: str = "localhost" port: int = 6379 password: str = "" db: int = 0 max_connections: int = 50 decode_responses: bool = True enabled: bool = True @dataclass class CameraNameConfig: """摄像头名称格式化配置""" # WVP API基础URL wvp_api_base: str = "http://localhost:18080" # 显示格式模板(支持变量:{camera_code}, {name}, {stream}) # 可选格式: # - "{name}" - 仅名称(推荐,告警列表使用) # - "{camera_code} {name}/{stream}" - cam_xxx 名称/流id(完整格式) # - "{name}/{stream}" - 名称/流id # - "{camera_code}" - 仅code display_format: str = "{name}" # 名称字段优先级(从高到低) # 从StreamProxy对象中提取名称时的字段优先级 # 注意:gb_name 可能包含 "/" 后缀,会自动去除 name_field_priority: list = None # 查询超时(秒) query_timeout: int = 15 def __post_init__(self): if self.name_field_priority is None: # 默认优先级:gb_name > app > stream self.name_field_priority = ["gbName", "app", "stream"] class Settings(BaseModel): """全局配置""" database: DatabaseConfig = DatabaseConfig() cos: COSConfig = COSConfig() app: AppConfig = AppConfig() ai_model: AIModelConfig = AIModelConfig() vlm: VLMConfig = VLMConfig() wechat: WeChatConfig = WeChatConfig() agent: AgentConfig = AgentConfig() redis: RedisConfig = RedisConfig() camera_name: CameraNameConfig = CameraNameConfig() def load_settings() -> Settings: """从环境变量加载配置""" from dotenv import load_dotenv load_dotenv() return Settings( database=DatabaseConfig( url=os.getenv("DATABASE_URL", "sqlite:///./data/alert_platform.db"), ), cos=COSConfig( region=os.getenv("COS_REGION", "ap-beijing"), bucket=os.getenv("COS_BUCKET", ""), upload_prefix=os.getenv("COS_UPLOAD_PREFIX", "alerts"), presign_expire=int(os.getenv("COS_PRESIGN_EXPIRE", "1800")), enabled=os.getenv("COS_ENABLED", "false").lower() == "true", ), app=AppConfig( host=os.getenv("APP_HOST", "0.0.0.0"), port=int(os.getenv("APP_PORT", "8000")), debug=os.getenv("DEBUG", "true").lower() == "true", dev_mode=os.getenv("DEV_MODE", "true").lower() == "true", ), ai_model=AIModelConfig( endpoint=os.getenv("AI_MODEL_ENDPOINT", ""), api_key=os.getenv("AI_MODEL_API_KEY", ""), ), vlm=VLMConfig( api_key=os.getenv("DASHSCOPE_API_KEY", ""), base_url=os.getenv("VLM_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"), model=os.getenv("VLM_MODEL", "qwen3-vl-flash-2026-01-22"), timeout=int(os.getenv("VLM_TIMEOUT", "10")), enabled=os.getenv("VLM_ENABLED", "false").lower() == "true", enable_thinking=os.getenv("VLM_ENABLE_THINKING", "false").lower() == "true", ), wechat=WeChatConfig( corp_id=os.getenv("WECHAT_CORP_ID", ""), agent_id=os.getenv("WECHAT_AGENT_ID", ""), secret=os.getenv("WECHAT_SECRET", ""), token=os.getenv("WECHAT_TOKEN", ""), encoding_aes_key=os.getenv("WECHAT_ENCODING_AES_KEY", ""), enabled=os.getenv("WECHAT_ENABLED", "false").lower() == "true", test_uids=os.getenv("WECHAT_TEST_UIDS", ""), service_base_url=os.getenv("SERVICE_BASE_URL", ""), ), agent=AgentConfig( llm_api_key=os.getenv("DASHSCOPE_API_KEY", ""), llm_base_url=os.getenv("AGENT_LLM_BASE_URL", "https://dashscope.aliyuncs.com/compatible-mode/v1"), llm_model=os.getenv("AGENT_LLM_MODEL", "qwen-plus"), llm_timeout=int(os.getenv("AGENT_LLM_TIMEOUT", "15")), enabled=os.getenv("AGENT_ENABLED", "false").lower() == "true", ), redis=RedisConfig( host=os.getenv("REDIS_HOST", "localhost"), port=int(os.getenv("REDIS_PORT", "6379")), password=os.getenv("REDIS_PASSWORD", ""), db=int(os.getenv("REDIS_DB", "0")), max_connections=int(os.getenv("REDIS_MAX_CONNECTIONS", "50")), enabled=os.getenv("REDIS_ENABLED", "true").lower() == "true", ), camera_name=CameraNameConfig( wvp_api_base=os.getenv("WVP_API_BASE", "http://localhost:18080"), display_format=os.getenv("CAMERA_NAME_FORMAT", "{name}"), query_timeout=int(os.getenv("CAMERA_QUERY_TIMEOUT", "15")), ), ) settings = load_settings()