import { Request, Response } from 'express'; import { AppDataSource } from '../config/database'; import { Config } from '../models/Config'; import { EnvHelper } from '../utils/envHelper'; import nodemailer from 'nodemailer'; /** * 系统配置控制器 * 处理系统配置相关的操作,包括获取配置、更新配置、测试邮件等 */ export class ConfigController { /** * 获取所有配置 * 按配置类型分组返回 * @param req - Express请求对象 * @param res - Express响应对象 */ async getAllConfigs(req: Request, res: Response) { try { const configRepository = AppDataSource.getRepository(Config); const configs = await configRepository.find({ order: { configType: 'ASC', id: 'ASC' } }); const groupedConfigs: Record = { basic: [], security: [], game: [], payment: [], email: [] }; configs.forEach(config => { if (groupedConfigs[config.configType]) { groupedConfigs[config.configType].push({ id: config.id, configKey: config.configKey, configValue: config.configValue, description: config.description }); } }); return res.json({ success: true, data: groupedConfigs }); } catch (error) { console.error('获取配置失败:', error); return res.status(500).json({ success: false, message: '服务器内部错误' }); } } /** * 更新配置 * 批量更新配置,同时更新数据库和.env文件 * @param req - Express请求对象 * @param res - Express响应对象 */ async updateConfigs(req: Request, res: Response) { try { const { configs } = req.body; if (!configs || !Array.isArray(configs)) { return res.status(400).json({ success: false, message: '配置数据格式错误' }); } const configRepository = AppDataSource.getRepository(Config); const envUpdates: Record = {}; for (const config of configs) { if (!config.configKey || config.configValue === undefined) { continue; } const existingConfig = await configRepository.findOne({ where: { configKey: config.configKey } }); if (existingConfig) { existingConfig.configValue = String(config.configValue); await configRepository.save(existingConfig); } const envKey = this.mapConfigKeyToEnvKey(config.configKey); if (envKey) { envUpdates[envKey] = String(config.configValue); } } const envFilePath = EnvHelper.getEnvFilePath(process.env.NODE_ENV || 'development'); const updateSuccess = EnvHelper.updateEnvFile(envFilePath, envUpdates); if (!updateSuccess) { return res.status(500).json({ success: false, message: '更新.env文件失败' }); } return res.json({ success: true, message: '配置更新成功' }); } catch (error) { console.error('更新配置失败:', error); return res.status(500).json({ success: false, message: '服务器内部错误' }); } } /** * 测试邮件发送 * @param req - Express请求对象 * @param res - Express响应对象 */ async testEmail(req: Request, res: Response) { try { const { to } = req.body; if (!to || !this.isValidEmail(to)) { return res.status(400).json({ success: false, message: '请输入有效的邮箱地址' }); } const configRepository = AppDataSource.getRepository(Config); const mailConfigs = await configRepository.find({ where: [ { configKey: 'mail_from' }, { configKey: 'mail_smtp_host' }, { configKey: 'mail_smtp_port' }, { configKey: 'mail_smtp_user' }, { configKey: 'mail_smtp_password' } ] }); const configMap = new Map(mailConfigs.map(c => [c.configKey, c.configValue])); const mailFrom = configMap.get('mail_from'); const smtpHost = configMap.get('mail_smtp_host'); const smtpPort = configMap.get('mail_smtp_port'); const smtpUser = configMap.get('mail_smtp_user'); const smtpPassword = configMap.get('mail_smtp_password'); if (!mailFrom || !smtpHost || !smtpPort || !smtpUser || !smtpPassword) { return res.status(400).json({ success: false, message: '邮件配置不完整,请先配置邮件信息' }); } const transporter = nodemailer.createTransport({ host: smtpHost, port: Number(smtpPort), secure: Number(smtpPort) === 465, auth: { user: smtpUser, pass: smtpPassword } }); const mailOptions = { from: mailFrom, to: to, subject: '梦幻西游运营管理系统 - 邮件测试', text: '这是一封测试邮件,如果您收到此邮件,说明邮件配置正确。' }; await transporter.sendMail(mailOptions); return res.json({ success: true, message: '邮件发送成功' }); } catch (error) { console.error('测试邮件发送失败:', error); return res.status(500).json({ success: false, message: '邮件发送失败,请检查配置' }); } } /** * 将配置键映射到.env文件中的环境变量键 * @param configKey - 配置键 * @returns 环境变量键,如果不映射则返回null */ private mapConfigKeyToEnvKey(configKey: string): string | null { const mapping: Record = { 'backend_host': 'BACKEND_HOST', 'backend_port': 'PORT', 'log_level': 'LOG_LEVEL', 'cors_origin': 'CORS_ORIGIN', 'jwt_secret': 'JWT_SECRET', 'jwt_expires_in': 'JWT_EXPIRES_IN', 'game_server_proxy_url': 'GAME_SERVER_PROXY_URL', 'game_server_psk': 'GAME_PSK' }; return mapping[configKey] || null; } /** * 验证邮箱格式 * @param email - 邮箱地址 * @returns 是否有效 */ private isValidEmail(email: string): boolean { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(email); } /** * 检查玩家服务中心状态 * @param req - Express请求对象 * @param res - Express响应对象 */ async checkPlayerServiceStatus(req: Request, res: Response) { try { const configRepository = AppDataSource.getRepository(Config); const playerServiceEnabledConfig = await configRepository.findOne({ where: { configKey: 'player_service_enabled' } }); const playerServiceCloseMsgConfig = await configRepository.findOne({ where: { configKey: 'player_service_close_msg' } }); const enabled = playerServiceEnabledConfig?.configValue === 'true'; const closeMsg = playerServiceCloseMsgConfig?.configValue || '玩家服务中心系统维护中'; return res.json({ success: true, data: { enabled, closeMsg } }); } catch (error) { console.error('检查玩家服务中心状态失败:', error); return res.status(500).json({ success: false, message: '服务器内部错误' }); } } }