feat: 新增系统配置页面

This commit is contained in:
Stev_Wang
2025-12-12 20:01:39 +08:00
parent 5a3d3918ba
commit fb51d51215
15 changed files with 4633 additions and 93 deletions

View File

@@ -0,0 +1,230 @@
/**
* 系统配置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;