/** * .env配置同步功能组件 * @author MHXY Development Team * @version 1.0.0 */ import React, { useState } from 'react'; import { Modal, Form, Button, Space, Alert, Typography, Divider, Checkbox, Progress } from 'antd'; import { SyncOutlined, FileTextOutlined, CheckCircleOutlined, ExclamationCircleOutlined, DownloadOutlined } from '@ant-design/icons'; import { SystemConfig } from '../types/systemConfig'; import systemConfigService from '../services/systemConfigService'; const { Text, Paragraph } = Typography; const { confirm } = Modal; interface EnvSyncModalProps { visible: boolean; configs: SystemConfig[]; onClose: () => void; onSync?: () => void; } const EnvSyncModal: React.FC = ({ visible, configs, onClose, onSync }) => { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [progress, setProgress] = useState(0); const [syncResult, setSyncResult] = useState<{ success: boolean; message: string; details?: string[]; } | null>(null); // 准备.env文件内容 const generateEnvContent = (selectedConfigs: string[]): string => { const envVars: Record = {}; // 根据选择的配置生成环境变量 configs.forEach(config => { if (selectedConfigs.includes(config.config_key)) { switch (config.config_key) { case 'jwt_secret': envVars.JWT_SECRET = config.config_value; break; case 'jwt_expires_in': envVars.JWT_EXPIRES_IN = config.config_value; break; case 'game_server_api': envVars.GAME_SERVER_API = config.config_value; break; case 'game_server_psk': envVars.GAME_SERVER_PSK = config.config_value; break; case 'game_server_timeout': envVars.GAME_SERVER_TIMEOUT = config.config_value; break; case 'game_server_retry_count': envVars.GAME_SERVER_RETRY_COUNT = config.config_value; break; case 'site_name': envVars.SITE_NAME = config.config_value; break; case 'maintenance_mode': envVars.MAINTENANCE_MODE = config.config_value; break; } } }); // 生成.env文件内容 const envContent = [ '# .env文件 - 由系统配置自动生成', `# 生成时间: ${new Date().toLocaleString('zh-CN')}`, '# 警告: 请不要手动修改此文件,系统配置变更时此文件将被覆盖', '', '# === 系统基本信息 ===', `SITE_NAME="${envVars.SITE_NAME || '梦幻西游运营管理系统'}"`, `MAINTENANCE_MODE=${envVars.MAINTENANCE_MODE || '0'}`, '', '# === JWT安全配置 ===', `JWT_SECRET="${envVars.JWT_SECRET || ''}"`, `JWT_EXPIRES_IN=${envVars.JWT_EXPIRES_IN || '24'}`, '', '# === 游戏服务端配置 ===', `GAME_SERVER_API="${envVars.GAME_SERVER_API || ''}"`, `GAME_SERVER_PSK="${envVars.GAME_SERVER_PSK || ''}"`, `GAME_SERVER_TIMEOUT=${envVars.GAME_SERVER_TIMEOUT || '30'}`, `GAME_SERVER_RETRY_COUNT=${envVars.GAME_SERVER_RETRY_COUNT || '3'}`, '', '# === 其他配置 ===', '# 请在此处添加其他环境变量', '' ].join('\n'); return envContent; }; // 执行同步操作 const handleSync = async () => { try { const values = await form.validateFields(); const selectedConfigs = Object.keys(values).filter(key => values[key]); if (selectedConfigs.length === 0) { throw new Error('请至少选择一个配置项进行同步'); } setLoading(true); setProgress(0); setSyncResult(null); // 模拟同步进度 const progressSteps = [ { percent: 20, message: '准备配置数据...' }, { percent: 40, message: '生成.env文件内容...' }, { percent: 60, message: '验证配置格式...' }, { percent: 80, message: '执行同步操作...' }, { percent: 100, message: '同步完成' } ]; for (const step of progressSteps) { await new Promise(resolve => setTimeout(resolve, 500)); setProgress(step.percent); } // 准备环境配置数据 const envConfigs = selectedConfigs.reduce((acc, configKey) => { const config = configs.find(c => c.config_key === configKey); if (config) { switch (configKey) { case 'jwt_secret': acc.JWT_SECRET = config.config_value; break; case 'jwt_expires_in': acc.JWT_EXPIRES_IN = config.config_value; break; case 'game_server_api': acc.GAME_SERVER_API = config.config_value; break; case 'game_server_psk': acc.GAME_SERVER_PSK = config.config_value; break; } } return acc; }, {} as any); // 调用服务同步 const result = await systemConfigService.syncToEnvFile(envConfigs); setSyncResult({ success: result.success, message: result.message, details: selectedConfigs }); if (result.success) { onSync?.(); } } catch (error) { setSyncResult({ success: false, message: error instanceof Error ? error.message : '同步失败', details: [] }); } finally { setLoading(false); } }; // 下载.env文件 const handleDownload = () => { const selectedConfigs = ['jwt_secret', 'jwt_expires_in', 'game_server_api', 'game_server_psk']; const envContent = generateEnvContent(selectedConfigs); const blob = new Blob([envContent], { type: 'text/plain;charset=utf-8' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = '.env'; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); // 重置状态 setSyncResult(null); setProgress(0); }; // 关闭模态框 const handleClose = () => { setSyncResult(null); setProgress(0); form.resetFields(); onClose(); }; // 可同步的配置项 const configOptions = [ { key: 'jwt_secret', label: 'JWT密钥', description: 'JWT签名密钥,用于令牌验证', sensitive: true, envVar: 'JWT_SECRET' }, { key: 'jwt_expires_in', label: 'JWT过期时间', description: 'JWT访问令牌有效期(小时)', sensitive: false, envVar: 'JWT_EXPIRES_IN' }, { key: 'game_server_api', label: '游戏服务端API', description: '游戏服务端HTTP接口地址', sensitive: false, envVar: 'GAME_SERVER_API' }, { key: 'game_server_psk', label: '游戏服务端PSK', description: '游戏服务端预共享密钥', sensitive: true, envVar: 'GAME_SERVER_PSK' }, { key: 'game_server_timeout', label: '请求超时时间', description: '与游戏服务端通信超时时间(秒)', sensitive: false, envVar: 'GAME_SERVER_TIMEOUT' }, { key: 'game_server_retry_count', label: '重试次数', description: 'API请求失败时的重试次数', sensitive: false, envVar: 'GAME_SERVER_RETRY_COUNT' } ]; // 默认选中的配置 const defaultChecked = ['jwt_secret', 'jwt_expires_in', 'game_server_api', 'game_server_psk']; return ( 同步配置到.env文件 } open={visible} onCancel={handleClose} width={600} footer={[ , , ]} >
{/* 同步进度 */} {loading && (
正在执行同步操作...
)} {/* 同步结果 */} {syncResult && (
下载.env文件 ) } />
)} {/* 配置选择 */} {!syncResult?.success && (
{configOptions.map(option => (
{option.label} {option.sensitive && ( 敏感 )}
{option.description} {option.envVar}
))}
)} {/* 操作说明 */}
操作说明
  • 同步操作将把选中的配置写入项目的.env文件
  • 敏感配置(如密钥、密码)将被加密或掩码处理
  • 建议在同步前备份现有的.env文件
  • 同步完成后需要重启应用程序以使配置生效
); }; export default EnvSyncModal;