baoxiang/backend/app/services/system_service.py

495 lines
17 KiB
Python
Raw Normal View History

2025-12-16 18:06:50 +08:00
"""
系统配置服务 - 增强版
"""
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,
},
]
# 游戏逻辑配置
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} 个默认配置项")