230 lines
10 KiB
TypeScript
230 lines
10 KiB
TypeScript
/**
|
||
* 系统配置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<SystemConfig[]> {
|
||
// 模拟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<SystemConfig[]> {
|
||
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<any[]> {
|
||
// 模拟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<string, string> = {
|
||
'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; |