This commit is contained in:
王鹏
2026-04-09 14:55:54 +08:00
commit a2f5875d1b
60 changed files with 5210 additions and 0 deletions

179
config_loader.py Normal file
View File

@@ -0,0 +1,179 @@
from __future__ import annotations
import os
from pathlib import Path
from typing import Any
import yaml
class Config:
"""配置管理类"""
_instance = None
_config_data = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
def __init__(self):
if self._config_data is None:
self._load_config()
def _load_config(self) -> None:
"""加载配置文件"""
config_path = Path(__file__).parent / "config.yaml"
# 默认配置
default_config = {
"wechat": {
"appid": "",
"appsecret": ""
},
"chrome": {
"path": r"C:\Program Files\Google\Chrome\Application\chrome.exe"
},
"step1": {
"url": "https://feast.yidaima.cn/login",
"username": "wangpeng",
"password": "Feastcoding@123",
"project_name": "【A167】基于Springboot + vue3实现的宿舍报修系统",
"feast_button": "FeastCoding"
},
"step2": {
"url": "http://yidaima.cn:6005/"
},
"database": {
"host": "localhost",
"port": 3306,
"database": "test",
"user": "root",
"password": "123456"
}
}
if config_path.exists():
try:
with open(config_path, 'r', encoding='utf-8') as f:
loaded_config = yaml.safe_load(f) or {}
# 合并配置
self._config_data = self._merge_config(default_config, loaded_config)
except Exception as e:
print(f"[Config] 加载配置文件失败: {e},使用默认配置")
self._config_data = default_config
else:
print("[Config] 配置文件不存在,使用默认配置")
self._config_data = default_config
# 环境变量覆盖
self._apply_env_overrides()
def _merge_config(self, default: dict, loaded: dict) -> dict:
"""递归合并配置"""
result = default.copy()
for key, value in loaded.items():
if key in result and isinstance(result[key], dict) and isinstance(value, dict):
result[key] = self._merge_config(result[key], value)
else:
result[key] = value
return result
def _apply_env_overrides(self) -> None:
"""应用环境变量覆盖"""
# 微信配置
if os.environ.get("WECHAT_APPID"):
self._config_data["wechat"]["appid"] = os.environ.get("WECHAT_APPID")
if os.environ.get("WECHAT_APPSECRET"):
self._config_data["wechat"]["appsecret"] = os.environ.get("WECHAT_APPSECRET")
# Chrome 路径
if os.environ.get("CHROME_PATH"):
self._config_data["chrome"]["path"] = os.environ.get("CHROME_PATH")
# Step1 配置
if os.environ.get("FEAST_USERNAME"):
self._config_data["step1"]["username"] = os.environ.get("FEAST_USERNAME")
if os.environ.get("FEAST_PASSWORD"):
self._config_data["step1"]["password"] = os.environ.get("FEAST_PASSWORD")
# 数据库配置
if os.environ.get("DB_HOST"):
self._config_data["database"]["host"] = os.environ.get("DB_HOST")
if os.environ.get("DB_PORT"):
self._config_data["database"]["port"] = int(os.environ.get("DB_PORT"))
if os.environ.get("DB_NAME"):
self._config_data["database"]["database"] = os.environ.get("DB_NAME")
if os.environ.get("DB_USER"):
self._config_data["database"]["user"] = os.environ.get("DB_USER")
if os.environ.get("DB_PASSWORD"):
self._config_data["database"]["password"] = os.environ.get("DB_PASSWORD")
def get(self, key: str, default: Any = None) -> Any:
"""
获取配置值,支持点号分隔的路径
例如: get("wechat.appid") 或 get("step1.url")
"""
keys = key.split('.')
value = self._config_data
for k in keys:
if isinstance(value, dict) and k in value:
value = value[k]
else:
return default
return value
@property
def wechat_appid(self) -> str:
return self.get("wechat.appid", "")
@property
def wechat_appsecret(self) -> str:
return self.get("wechat.appsecret", "")
@property
def chrome_path(self) -> str:
return self.get("chrome.path", r"C:\Program Files\Google\Chrome\Application\chrome.exe")
@property
def step1_config(self) -> dict:
return self.get("step1", {})
@property
def step2_config(self) -> dict:
return self.get("step2", {})
@property
def database_config(self) -> dict:
return self.get("database", {})
# 全局配置实例
_config_instance = None
def get_config() -> Config:
"""获取配置实例(单例模式)"""
global _config_instance
if _config_instance is None:
_config_instance = Config()
return _config_instance
def reset_config():
"""重置配置实例(用于重新加载)"""
global _config_instance
_config_instance = None
if __name__ == "__main__":
# 测试配置加载
config = get_config()
print(f"WeChat AppID: {config.wechat_appid}")
print(f"WeChat AppSecret: {'*' * len(config.wechat_appsecret) if config.wechat_appsecret else '(empty)'}")
print(f"Chrome Path: {config.chrome_path}")
print(f"Step1 URL: {config.get('step1.url')}")
print(f"Step2 URL: {config.get('step2.url')}")
print(f"Database Host: {config.get('database.host')}")
print(f"Database Port: {config.get('database.port')}")