515 lines
18 KiB
Python
515 lines
18 KiB
Python
"""
|
||
系统配置服务 - 增强版
|
||
"""
|
||
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} 个默认配置项")
|