262 lines
7.3 KiB
TypeScript
262 lines
7.3 KiB
TypeScript
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<string, any[]> = {
|
||
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<string, string> = {};
|
||
|
||
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<string, string> = {
|
||
'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: '服务器内部错误'
|
||
});
|
||
}
|
||
}
|
||
}
|