/** * 系统配置API服务 * @author MHXY Development Team * @version 1.0.0 */ import { SystemConfig, SaveConfigRequest } from '../types/systemConfig'; const API_BASE_URL = '/api/system-config'; class SystemConfigService { /** * 获取所有系统配置 */ async getAllConfigs(): Promise { // 模拟API调用 await new Promise(resolve => setTimeout(resolve, 300)); // 返回模拟数据 return [ // 基本配置 { id: 1, config_key: 'site_name', config_value: '梦幻西游一站式运营管理系统', config_type: 'string', config_group: 'basic', config_label: '网站名称', config_description: '系统显示名称', sort_order: 1 }, { id: 2, config_key: 'site_version', config_value: '1.0.0', config_type: 'string', config_group: 'basic', config_label: '系统版本', config_description: '当前系统版本号', sort_order: 2 }, { id: 3, config_key: 'site_description', config_value: '专业的游戏运营管理平台', config_type: 'string', config_group: 'basic', config_label: '系统描述', config_description: '系统描述信息', sort_order: 3 }, { id: 4, config_key: 'admin_email', config_value: 'admin@mhxy.com', config_type: 'string', config_group: 'basic', config_label: '管理员邮箱', config_description: '系统管理员联系邮箱', sort_order: 4 }, { id: 5, config_key: 'maintenance_mode', config_value: '0', config_type: 'boolean', config_group: 'basic', config_label: '维护模式', config_description: '开启后用户无法正常访问系统', sort_order: 5 }, { id: 6, config_key: 'default_language', config_value: 'zh-CN', config_type: 'string', config_group: 'basic', config_label: '默认语言', config_description: '系统默认语言设置', sort_order: 6 }, // 安全配置 { id: 7, config_key: 'jwt_secret', config_value: 'JWT_SECRET_32_BYTE_RANDOM_STRING_2025', config_type: 'string', config_group: 'security', config_label: 'JWT密钥', config_description: '用于JWT令牌签名的密钥,建议32位字符', sort_order: 1 }, { id: 8, config_key: 'jwt_expires_in', config_value: '24', config_type: 'number', config_group: 'security', config_label: 'JWT过期时间(小时)', config_description: 'JWT访问令牌的有效期,单位:小时', sort_order: 2 }, { id: 9, config_key: 'jwt_refresh_expires_in', config_value: '168', config_type: 'number', config_group: 'security', config_label: 'JWT刷新令牌过期时间(小时)', config_description: 'JWT刷新令牌的有效期,单位:小时', sort_order: 3 }, { id: 10, config_key: 'login_attempt_limit', config_value: '5', config_type: 'number', config_group: 'security', config_label: '登录尝试次数限制', config_description: '连续登录失败次数限制', sort_order: 4 }, { id: 11, config_key: 'session_timeout', config_value: '30', config_type: 'number', config_group: 'security', config_label: '会话超时时间(分钟)', config_description: '用户会话超时时间', sort_order: 5 }, { id: 12, config_key: 'password_min_length', config_value: '6', config_type: 'number', config_group: 'security', config_label: '密码最小长度', config_description: '用户密码最小长度要求', sort_order: 6 }, { id: 13, config_key: 'enable_2fa', config_value: '0', config_type: 'boolean', config_group: 'security', config_label: '启用双因子认证', config_description: '是否启用双因子认证功能', sort_order: 7 }, // 游戏通信配置 { id: 14, config_key: 'game_server_api', config_value: 'http://127.0.0.1:8080/tool/http', config_type: 'string', config_group: 'game', config_label: '游戏服务端API', config_description: '游戏服务端HTTP接口地址', sort_order: 1 }, { id: 15, config_key: 'game_server_psk', config_value: 'THIS_IS_A_32_BYTE_FIXED_PSK!!!!!', config_type: 'string', config_group: 'game', config_label: '游戏服务端PSK', config_description: '游戏服务端预共享密钥,用于API认证', sort_order: 2 }, { id: 16, config_key: 'game_server_timeout', config_value: '30', config_type: 'number', config_group: 'game', config_label: '请求超时时间(秒)', config_description: '与游戏服务端通信的超时时间', sort_order: 3 }, { id: 17, config_key: 'game_server_retry_count', config_value: '3', config_type: 'number', config_group: 'game', config_label: '重试次数', config_description: 'API请求失败时的重试次数', sort_order: 4 }, { id: 18, config_key: 'player_auto_register', config_value: '1', config_type: 'boolean', config_group: 'game', config_label: '玩家自动注册', config_description: '新玩家是否自动创建账号', sort_order: 5 }, { id: 19, config_key: 'game_log_level', config_value: 'info', config_type: 'string', config_group: 'game', config_label: '游戏日志级别', config_description: '游戏相关操作的日志记录级别', sort_order: 6 } ]; } /** * 按分组获取配置 */ async getConfigsByGroup(group: string): Promise { const allConfigs = await this.getAllConfigs(); return allConfigs.filter(config => config.config_group === group); } /** * 保存单个配置项 */ async saveConfig(request: SaveConfigRequest): Promise<{ success: boolean; message: string }> { // 模拟API调用 await new Promise(resolve => setTimeout(resolve, 500)); // 模拟验证逻辑 if (!request.config_key || !request.config_value) { throw new Error('配置键名和值不能为空'); } // 特殊验证 if (request.config_key === 'jwt_secret' && request.config_value.length < 32) { throw new Error('JWT密钥至少需要32位字符'); } if (request.config_key === 'game_server_api' && !/^https?:\/\/.+/.test(request.config_value)) { throw new Error('游戏服务端API必须是有效的HTTP/HTTPS地址'); } return { success: true, message: '配置保存成功' }; } /** * 批量保存配置 */ async saveConfigs(requests: SaveConfigRequest[]): Promise<{ success: boolean; message: string; errors?: string[] }> { const errors: string[] = []; for (const request of requests) { try { await this.saveConfig(request); } catch (error) { errors.push(`${request.config_key}: ${error instanceof Error ? error.message : '未知错误'}`); } } return { success: errors.length === 0, message: errors.length === 0 ? '所有配置保存成功' : '部分配置保存失败', errors: errors.length > 0 ? errors : undefined }; } /** * 获取配置历史记录 */ async getConfigHistory(configKey?: string, limit: number = 50): Promise { // 模拟API调用 await new Promise(resolve => setTimeout(resolve, 300)); const mockHistory: any[] = [ { id: 1, config_key: 'jwt_secret', old_value: 'OLD_JWT_SECRET_32_BYTE_STRING_2024', new_value: 'JWT_SECRET_32_BYTE_RANDOM_STRING_2025', changed_by: 1, changed_reason: '更新JWT密钥以提升安全性', created_at: '2025-12-12T10:30:00.000Z', admin_user: { username: 'admin', real_name: '系统管理员' } }, { id: 2, config_key: 'game_server_api', old_value: 'http://192.168.1.100:8080/tool/http', new_value: 'http://127.0.0.1:8080/tool/http', changed_by: 1, changed_reason: '更新为本地开发环境地址', created_at: '2025-12-12T09:15:00.000Z', admin_user: { username: 'admin', real_name: '系统管理员' } } ]; return configKey ? mockHistory.filter(item => item.config_key === configKey) : mockHistory; } /** * 同步配置到.env文件 */ async syncToEnvFile(configs: EnvConfig): Promise<{ success: boolean; message: string }> { // 模拟API调用 await new Promise(resolve => setTimeout(resolve, 1000)); // 模拟文件写入操作 console.log('同步配置到.env文件:', configs); return { success: true, message: '配置已成功同步到.env文件' }; } /** * 重置指定配置项为默认值 */ async resetConfig(configKey: string): Promise<{ success: boolean; message: string; defaultValue?: string }> { // 模拟API调用 await new Promise(resolve => setTimeout(resolve, 300)); const defaultValues: Record = { 'jwt_secret': 'JWT_SECRET_32_BYTE_RANDOM_STRING_2025', 'game_server_api': 'http://127.0.0.1:8080/tool/http', 'game_server_psk': 'THIS_IS_A_32_BYTE_FIXED_PSK!!!!!', 'jwt_expires_in': '24', 'login_attempt_limit': '5', 'session_timeout': '30' }; const defaultValue = defaultValues[configKey]; if (!defaultValue) { throw new Error('未找到该配置项的默认值'); } return { success: true, message: '配置已重置为默认值', defaultValue }; } /** * 验证配置值 */ validateConfigValue(configKey: string, value: any): { valid: boolean; error?: string } { switch (configKey) { case 'jwt_secret': if (typeof value !== 'string' || value.length < 32) { return { valid: false, error: 'JWT密钥至少需要32位字符' }; } break; case 'game_server_api': if (!/^https?:\/\/.+/.test(value)) { return { valid: false, error: '请输入有效的HTTP/HTTPS地址' }; } break; case 'game_server_psk': if (typeof value !== 'string' || value.length < 32) { return { valid: false, error: 'PSK密钥至少需要32位字符' }; } break; case 'jwt_expires_in': case 'login_attempt_limit': case 'session_timeout': const num = Number(value); if (isNaN(num) || num <= 0) { return { valid: false, error: '请输入有效的正整数' }; } break; } return { valid: true }; } } export const systemConfigService = new SystemConfigService(); export default systemConfigService;