""" 系统配置数据访问对象 """ from typing import Dict, List, Optional, Any import json from datetime import datetime, date from .base_dao import BaseDAO class ConfigDAO(BaseDAO): """系统配置数据访问对象""" def get_config(self, key: str, default_value: Any = None) -> Any: """获取配置值""" query = "SELECT config_value, config_type FROM system_config WHERE config_key = %s" result = self._execute_single_query(query, (key,)) if not result: return default_value config_value = result['config_value'] config_type = result['config_type'] # 根据类型转换值 if config_type == 'integer': try: return int(config_value) if config_value else default_value except (ValueError, TypeError): return default_value elif config_type == 'float': try: return float(config_value) if config_value else default_value except (ValueError, TypeError): return default_value elif config_type == 'boolean': return config_value.lower() in ('true', '1', 'yes', 'on') if config_value else default_value elif config_type == 'json': try: return json.loads(config_value) if config_value else default_value except json.JSONDecodeError: return default_value else: # string return config_value if config_value else default_value def set_config(self, key: str, value: Any, config_type: str = 'string') -> bool: """设置配置值""" try: # 转换值为字符串存储 if config_type == 'json': str_value = json.dumps(value, ensure_ascii=False) elif config_type == 'boolean': str_value = str(value).lower() else: str_value = str(value) # 检查配置是否存在 existing = self._execute_single_query( "SELECT id FROM system_config WHERE config_key = %s", (key,) ) if existing: # 更新现有配置 query = """ UPDATE system_config SET config_value = %s, config_type = %s, updated_at = CURRENT_TIMESTAMP WHERE config_key = %s """ self._execute_update(query, (str_value, config_type, key)) else: # 插入新配置 query = """ INSERT INTO system_config (config_key, config_value, config_type) VALUES (%s, %s, %s) """ self._execute_insert(query, (key, str_value, config_type)) self.log_data_update('config', key, 'success', f'Config updated: {key}={value}') return True except Exception as e: self.logger.error(f"设置配置失败: {key}={value}, 错误: {e}") self.log_data_update('config', key, 'failed', str(e)) return False def get_all_configs(self) -> Dict[str, Dict]: """获取所有配置""" query = "SELECT * FROM system_config ORDER BY config_key" results = self._execute_query(query) configs = {} for result in results: key = result['config_key'] configs[key] = { 'value': self.get_config(key), 'type': result['config_type'], 'created_at': result['created_at'], 'updated_at': result['updated_at'] } return configs def delete_config(self, key: str) -> bool: """删除配置""" try: query = "DELETE FROM system_config WHERE config_key = %s" affected_rows = self._execute_update(query, (key,)) success = affected_rows > 0 if success: self.log_data_update('config', key, 'success', 'Config deleted') else: self.log_data_update('config', key, 'failed', 'Config not found') return success except Exception as e: self.logger.error(f"删除配置失败: {key}, 错误: {e}") self.log_data_update('config', key, 'failed', str(e)) return False def increment_counter(self, key: str, increment: int = 1) -> int: """递增计数器配置""" try: current_value = self.get_config(key, 0) new_value = current_value + increment self.set_config(key, new_value, 'integer') return new_value except Exception as e: self.logger.error(f"递增计数器失败: {key}, 错误: {e}") return 0 def reset_daily_counters(self) -> None: """重置每日计数器""" daily_counters = [ 'tushare_api_calls_today', ] for counter in daily_counters: self.set_config(counter, 0, 'integer') # 更新最后重置日期 self.set_config('last_counter_reset_date', self.get_today_date(), 'date') def get_last_data_update_date(self) -> Optional[str]: """获取最后数据更新日期""" return self.get_config('last_data_update_date') def set_last_data_update_date(self, date_str: str) -> bool: """设置最后数据更新日期""" return self.set_config('last_data_update_date', date_str, 'date') def get_cache_expiration_hours(self) -> int: """获取缓存过期时间(小时)""" return self.get_config('cache_expiration_hours', 24) def get_max_watchlist_size(self) -> int: """获取最大监控列表大小""" return self.get_config('max_watchlist_size', 50) def is_cache_expired(self, data_date: str) -> bool: """检查缓存是否过期""" try: cache_hours = self.get_cache_expiration_hours() current_date = date.today() data_date_obj = datetime.strptime(data_date, '%Y-%m-%d').date() days_diff = (current_date - data_date_obj).days return days_diff > 0 # 如果不是今天的数据,就算过期 except Exception: return True # 如果无法解析日期,认为过期