""" 系统配置服务 - 增强版 """ from sqlalchemy.orm import Session from sqlalchemy import and_, func from typing import Dict, Any, List, Optional from ..models.system import SystemConfig, ConfigType, ConfigCategory from ..schemas.system import ( SystemConfigCreate, SystemConfigUpdate, SystemConfigResponse, SystemConfigGroup, SystemConfigSummary ) class SystemService: """系统配置服务""" # 配置分类显示名称映射 CATEGORY_NAMES = { ConfigCategory.GAME_ECONOMY: "游戏经济配置", ConfigCategory.GAME_LOGIC: "游戏逻辑配置", ConfigCategory.SYSTEM_OPERATIONS: "系统运维配置", ConfigCategory.UI_DISPLAY: "界面显示配置", } # 配置分类描述映射 CATEGORY_DESCRIPTIONS = { ConfigCategory.GAME_ECONOMY: "游戏经济相关配置,如奖励、低保、抽水比例等", ConfigCategory.GAME_LOGIC: "游戏逻辑相关配置,如倒计时、活跃宝箱数等", ConfigCategory.SYSTEM_OPERATIONS: "系统运维相关配置,如分页、WebSocket等", ConfigCategory.UI_DISPLAY: "界面显示相关配置", } @staticmethod def get_config(db: Session, key: str) -> Optional[SystemConfig]: """ 根据键获取配置 """ return db.query(SystemConfig).filter(SystemConfig.config_key == key).first() @staticmethod def get_all_configs(db: Session) -> List[SystemConfig]: """ 获取所有配置 """ return db.query(SystemConfig).order_by( SystemConfig.category, SystemConfig.display_order, SystemConfig.config_key ).all() @staticmethod def get_configs_by_category(db: Session, category: ConfigCategory) -> List[SystemConfig]: """ 根据分类获取配置 """ return db.query(SystemConfig).filter( SystemConfig.category == category ).order_by( SystemConfig.display_order, SystemConfig.config_key ).all() @staticmethod def get_config_groups(db: Session) -> List[SystemConfigGroup]: """ 获取配置分组 """ configs = SystemService.get_all_configs(db) groups = {} for config in configs: category = config.category if category not in groups: groups[category] = [] groups[category].append(config) result = [] for category, configs in groups.items(): result.append( SystemConfigGroup( category=category, category_name=SystemService.CATEGORY_NAMES.get(category, str(category)), category_description=SystemService.CATEGORY_DESCRIPTIONS.get(category, ""), configs=[SystemConfigResponse.model_validate(c) for c in configs] ) ) return result @staticmethod def create_config(db: Session, config_data: SystemConfigCreate) -> SystemConfig: """ 创建配置 """ # 检查键是否已存在 existing_config = db.query(SystemConfig).filter( SystemConfig.config_key == config_data.config_key ).first() if existing_config: raise ValueError("配置键已存在") db_config = SystemConfig( config_key=config_data.config_key, config_value=config_data.config_value, config_type=config_data.config_type, category=config_data.category, description=config_data.description, is_editable=config_data.is_editable, is_public=config_data.is_public, display_order=config_data.display_order, ) db.add(db_config) db.commit() db.refresh(db_config) return db_config @staticmethod def update_config(db: Session, key: str, config_data: SystemConfigUpdate) -> Optional[SystemConfig]: """ 更新配置 """ db_config = SystemService.get_config(db, key) if not db_config: return None if not db_config.is_editable: raise ValueError("该配置项不可编辑") update_data = config_data.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(db_config, field, value) db.commit() db.refresh(db_config) return db_config @staticmethod def delete_config(db: Session, key: str) -> bool: """ 删除配置 """ db_config = SystemService.get_config(db, key) if not db_config: return False if not db_config.is_editable: raise ValueError("该配置项不可删除") db.delete(db_config) db.commit() return True @staticmethod def batch_update_configs(db: Session, configs: Dict[str, str]) -> List[SystemConfig]: """ 批量更新配置 """ updated_configs = [] for key, value in configs.items(): config = SystemService.update_config(db, key, SystemConfigUpdate(config_value=value)) if config: updated_configs.append(config) return updated_configs @staticmethod def get_config_summary(db: Session) -> SystemConfigSummary: """ 获取配置概览 """ total_configs = db.query(SystemConfig).count() editable_configs = db.query(SystemConfig).filter(SystemConfig.is_editable == True).count() public_configs = db.query(SystemConfig).filter(SystemConfig.is_public == True).count() # 统计各分类的配置数量 category_counts = {} for category in ConfigCategory: count = db.query(SystemConfig).filter(SystemConfig.category == category).count() category_counts[category.value] = count return SystemConfigSummary( total_configs=total_configs, editable_configs=editable_configs, public_configs=public_configs, category_counts=category_counts ) @staticmethod def get_public_configs(db: Session) -> Dict[str, str]: """ 获取公开配置(供前端使用) """ configs = db.query(SystemConfig).filter(SystemConfig.is_public == True).all() return {c.config_key: c.config_value for c in configs} @staticmethod def get_typed_value(config: SystemConfig) -> Any: """ 根据配置类型获取正确类型的值 """ if config.config_type == ConfigType.NUMBER: try: return float(config.config_value) if '.' in config.config_value else int(config.config_value) except ValueError: return config.config_value elif config.config_type == ConfigType.BOOLEAN: return config.config_value.lower() in ('true', '1', 'yes', 'on') elif config.config_type == ConfigType.JSON: import json try: return json.loads(config.config_value) except json.JSONDecodeError: return config.config_value else: return config.config_value @staticmethod def initialize_default_configs(db: Session): """ 初始化默认系统配置 """ from ..models.system import ConfigType, ConfigCategory # 检查是否已有配置 existing_count = db.query(SystemConfig).count() if existing_count > 0: print(f"系统已有 {existing_count} 个配置项,跳过初始化") return # 游戏经济配置 game_economy_configs = [ { "config_key": "GAME_NEW_USER_REWARD", "config_value": "100000", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_ECONOMY, "description": "新用户注册奖励(分)", "is_editable": True, "is_public": False, "display_order": 1, }, { "config_key": "GAME_DAILY_ALLOWANCE", "config_value": "5000", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_ECONOMY, "description": "每日低保(分)", "is_editable": True, "is_public": False, "display_order": 2, }, { "config_key": "GAME_ALLOWANCE_THRESHOLD", "config_value": "1000", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_ECONOMY, "description": "低保门槛(分)", "is_editable": True, "is_public": False, "display_order": 3, }, { "config_key": "GAME_HOUSE_EDGE", "config_value": "0.10", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_ECONOMY, "description": "总抽水比例", "is_editable": True, "is_public": False, "display_order": 4, }, { "config_key": "GAME_STREAMER_SHARE", "config_value": "0.05", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_ECONOMY, "description": "主播分润比例", "is_editable": True, "is_public": False, "display_order": 5, }, { "config_key": "GAME_PLATFORM_SHARE", "config_value": "0.05", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_ECONOMY, "description": "平台分润比例", "is_editable": True, "is_public": False, "display_order": 6, }, { "config_key": "GAME_DAILY_CHECKIN_REWARD", "config_value": "1000", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_ECONOMY, "description": "每日签到奖励(分)", "is_editable": True, "is_public": False, "display_order": 7, }, { "config_key": "BALANCE_ZERO_REWARD_AMOUNT", "config_value": "10000", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_ECONOMY, "description": "余额清零自动发放金额(分)", "is_editable": True, "is_public": False, "display_order": 8, }, { "config_key": "ALLOWANCE_RESET_TIME", "config_value": "00:00", "config_type": ConfigType.STRING, "category": ConfigCategory.GAME_ECONOMY, "description": "低保每日刷新时间(HH:MM格式)", "is_editable": True, "is_public": False, "display_order": 9, }, ] # 游戏逻辑配置 game_logic_configs = [ { "config_key": "GAME_DEFAULT_COUNTDOWN", "config_value": "300", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_LOGIC, "description": "默认倒计时(秒)", "is_editable": True, "is_public": False, "display_order": 1, }, { "config_key": "GAME_MIN_COUNTDOWN", "config_value": "10", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_LOGIC, "description": "最小倒计时(秒)", "is_editable": True, "is_public": False, "display_order": 2, }, { "config_key": "GAME_MAX_COUNTDOWN", "config_value": "3600", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_LOGIC, "description": "最大倒计时(秒)", "is_editable": True, "is_public": False, "display_order": 3, }, { "config_key": "GAME_DEFAULT_MAX_ACTIVE_CHESTS", "config_value": "10", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_LOGIC, "description": "默认最大活跃宝箱数", "is_editable": True, "is_public": False, "display_order": 4, }, { "config_key": "GAME_MIN_COMMISSION_RATE", "config_value": "0.0", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_LOGIC, "description": "最小主播抽成(%)", "is_editable": True, "is_public": False, "display_order": 5, }, { "config_key": "GAME_MAX_COMMISSION_RATE", "config_value": "100.0", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_LOGIC, "description": "最大主播抽成(%)", "is_editable": True, "is_public": False, "display_order": 6, }, { "config_key": "GAME_DEFAULT_COMMISSION_RATE", "config_value": "5.0", "config_type": ConfigType.NUMBER, "category": ConfigCategory.GAME_LOGIC, "description": "默认主播抽成(%)", "is_editable": True, "is_public": False, "display_order": 7, }, ] # 系统运维配置 system_operations_configs = [ { "config_key": "PAGINATION_DEFAULT_PAGE_SIZE", "config_value": "20", "config_type": ConfigType.NUMBER, "category": ConfigCategory.SYSTEM_OPERATIONS, "description": "默认分页大小", "is_editable": True, "is_public": False, "display_order": 1, }, { "config_key": "PAGINATION_ADMIN_PAGE_SIZE", "config_value": "20", "config_type": ConfigType.NUMBER, "category": ConfigCategory.SYSTEM_OPERATIONS, "description": "管理员页面分页大小", "is_editable": True, "is_public": False, "display_order": 2, }, { "config_key": "PAGINATION_ANNOUNCEMENT_PAGE_SIZE", "config_value": "10", "config_type": ConfigType.NUMBER, "category": ConfigCategory.SYSTEM_OPERATIONS, "description": "公告页面分页大小", "is_editable": True, "is_public": False, "display_order": 3, }, { "config_key": "WS_BROADCAST_INTERVAL", "config_value": "200", "config_type": ConfigType.NUMBER, "category": ConfigCategory.SYSTEM_OPERATIONS, "description": "WebSocket广播间隔(毫秒)", "is_editable": True, "is_public": False, "display_order": 4, }, { "config_key": "WS_HEARTBEAT_INTERVAL", "config_value": "30", "config_type": ConfigType.NUMBER, "category": ConfigCategory.SYSTEM_OPERATIONS, "description": "WebSocket心跳间隔(秒)", "is_editable": True, "is_public": False, "display_order": 5, }, { "config_key": "WS_CONNECTION_TIMEOUT", "config_value": "60", "config_type": ConfigType.NUMBER, "category": ConfigCategory.SYSTEM_OPERATIONS, "description": "WebSocket连接超时(秒)", "is_editable": True, "is_public": False, "display_order": 6, }, ] # 界面显示配置 ui_display_configs = [ { "config_key": "ANNOUNCEMENT_DEFAULT_PRIORITY", "config_value": "0", "config_type": ConfigType.NUMBER, "category": ConfigCategory.UI_DISPLAY, "description": "公告默认优先级", "is_editable": True, "is_public": False, "display_order": 1, }, { "config_key": "ANNOUNCEMENT_MAX_PRIORITY", "config_value": "100", "config_type": ConfigType.NUMBER, "category": ConfigCategory.UI_DISPLAY, "description": "公告最大优先级", "is_editable": True, "is_public": False, "display_order": 2, }, ] # 合并所有配置 all_configs = ( game_economy_configs + game_logic_configs + system_operations_configs + ui_display_configs ) # 创建配置项 created_count = 0 for config_data in all_configs: try: # 检查配置是否已存在 existing = db.query(SystemConfig).filter( SystemConfig.config_key == config_data["config_key"] ).first() if not existing: db_config = SystemConfig(**config_data) db.add(db_config) created_count += 1 except Exception as e: print(f"创建配置 {config_data['config_key']} 失败: {e}") db.commit() print(f"成功初始化 {created_count} 个默认配置项")