using System.Text; using MigrationTool; using MigrationTool.Models; // 设置控制台输出编码 Console.OutputEncoding = Encoding.UTF8; PrintBanner(); // 解析命令行参数 var options = ParseArguments(args); if (options == null) { PrintHelp(); return 1; } PrintOptions(options); // 确认执行 if (!options.DryRun) { Console.WriteLine(); Console.Write("确认开始迁移? (y/N): "); var confirm = Console.ReadLine()?.Trim().ToLowerInvariant(); if (confirm != "y" && confirm != "yes") { Console.WriteLine("已取消"); return 0; } } Console.WriteLine(); // 创建日志记录器 var logger = new ConsoleLogger(options.LogLevel); // 执行迁移 try { var service = new MigrationService(options, logger); var report = await service.MigrateAsync(); // 打印报告 report.PrintSummary(); return report.FailedCount > 0 ? 1 : 0; } catch (Exception ex) { logger.LogError($"迁移失败: {ex.Message}"); logger.LogDebug(ex.StackTrace ?? ""); return 2; } /// /// 解析命令行参数 /// static MigrationOptions? ParseArguments(string[] args) { var options = new MigrationOptions { ConnectionString = GetDefaultConnectionString() }; for (int i = 0; i < args.Length; i++) { var arg = args[i]; switch (arg.ToLowerInvariant()) { case "--help": case "-h": case "-?": return null; case "--connection-string": case "-c": if (i + 1 < args.Length) options.ConnectionString = args[++i]; break; case "--output-dir": case "-o": if (i + 1 < args.Length) options.OutputDir = args[++i]; break; case "--dry-run": case "-d": options.DryRun = true; break; case "--default-host": if (i + 1 < args.Length) options.DefaultHost = args[++i]; break; case "--service-port": if (i + 1 < args.Length && int.TryParse(args[++i], out var svcPort)) options.ServicePort = svcPort; break; case "--target-port": if (i + 1 < args.Length && int.TryParse(args[++i], out var tgtPort)) options.TargetPort = tgtPort; break; case "--no-validate": options.Validate = false; break; case "--tenant": case "-t": if (i + 1 < args.Length) options.TenantCode = args[++i]; break; case "--log-level": case "-l": if (i + 1 < args.Length && Enum.TryParse(args[++i], true, out var level)) options.LogLevel = level; break; case "--no-report": options.GenerateReport = false; break; case "--report-path": if (i + 1 < args.Length) options.ReportPath = args[++i]; break; default: Console.WriteLine($"未知参数: {arg}"); break; } } return options; } /// /// 获取默认连接字符串(从环境变量) /// static string GetDefaultConnectionString() { var envConnectionString = Environment.GetEnvironmentVariable("GATEWAY_CONNECTION_STRING"); if (!string.IsNullOrEmpty(envConnectionString)) { return envConnectionString; } return "Host=localhost;Database=fengling_gateway;Username=postgres;Password=postgres"; } /// /// 打印 Banner /// static void PrintBanner() { Console.WriteLine(); Console.WriteLine(@" __ __ _ _ _ _ _ _ "); Console.WriteLine(@" | \/ (_) | ___ _ __ | |_(_)_ __ __ _| |_ ___ | |_ "); Console.WriteLine(@" | |\/| | | |/ _ \ '_ \| __| | '_ \ / _` | __/ _ \ | __|"); Console.WriteLine(@" | | | | | | __/ | | | |_| | | | | (_| | || __/ | |_ "); Console.WriteLine(@" |_| |_|_|_|\___|_| |_|\__|_|_| |_|\__,_|\__\___| \__|"); Console.WriteLine(@" "); Console.WriteLine(@" Fengling Gateway Migration Tool v1.0.0"); Console.WriteLine(); } /// /// 打印帮助信息 /// static void PrintHelp() { Console.WriteLine("用法: MigrationTool [选项]"); Console.WriteLine(); Console.WriteLine("选项:"); Console.WriteLine(" -h, --help 显示帮助信息"); Console.WriteLine(" -c, --connection-string 数据库连接字符串 (默认: 从 GATEWAY_CONNECTION_STRING 环境变量读取)"); Console.WriteLine(" -o, --output-dir YAML 文件输出目录 (默认: ./output)"); Console.WriteLine(" -d, --dry-run 干运行模式,只输出不写入文件"); Console.WriteLine(" --default-host 默认路由 Host (默认: api.fengling.com)"); Console.WriteLine(" --service-port Service 端口 (默认: 80)"); Console.WriteLine(" --target-port 目标端口 (默认: 8080)"); Console.WriteLine(" --no-validate 跳过数据验证"); Console.WriteLine(" -t, --tenant 仅处理指定租户"); Console.WriteLine(" -l, --log-level 日志级别 (Trace/Debug/Information/Warning/Error)"); Console.WriteLine(" --no-report 不生成报告文件"); Console.WriteLine(" --report-path 指定报告文件路径"); Console.WriteLine(); Console.WriteLine("示例:"); Console.WriteLine(" MigrationTool --dry-run"); Console.WriteLine(" MigrationTool -c \"Host=db;Database=gateway;Username=postgres;Password=secret\" -o ./yaml"); Console.WriteLine(" MigrationTool --tenant tenant1 --dry-run"); Console.WriteLine(); } /// /// 打印选项 /// static void PrintOptions(MigrationOptions options) { Console.WriteLine("配置选项:"); Console.WriteLine($" 连接字符串: {MaskConnectionString(options.ConnectionString)}"); Console.WriteLine($" 输出目录: {Path.GetFullPath(options.OutputDir)}"); Console.WriteLine($" Dry-Run: {(options.DryRun ? "是" : "否")}"); Console.WriteLine($" 默认 Host: {options.DefaultHost}"); Console.WriteLine($" Service 端口: {options.ServicePort}"); Console.WriteLine($" Target 端口: {options.TargetPort}"); Console.WriteLine($" 验证数据: {(options.Validate ? "是" : "否")}"); Console.WriteLine($" 日志级别: {options.LogLevel}"); if (!string.IsNullOrEmpty(options.TenantCode)) { Console.WriteLine($" 指定租户: {options.TenantCode}"); } } /// /// 掩盖连接字符串中的敏感信息 /// static string MaskConnectionString(string connectionString) { if (string.IsNullOrEmpty(connectionString)) return "[empty]"; try { var builder = new Npgsql.NpgsqlConnectionStringBuilder(connectionString); if (!string.IsNullOrEmpty(builder.Password)) { builder.Password = "***"; } return builder.ToString(); } catch { return "[invalid]"; } } /// /// 简单的控制台日志记录器 /// public class ConsoleLogger : ILogger { private readonly LogLevel _minLevel; public ConsoleLogger(LogLevel minLevel) { _minLevel = minLevel; } public void LogTrace(string message) { if (_minLevel <= LogLevel.Trace) WriteLog("TRC", ConsoleColor.Gray, message); } public void LogDebug(string message) { if (_minLevel <= LogLevel.Debug) WriteLog("DBG", ConsoleColor.DarkGray, message); } public void LogInformation(string message) { if (_minLevel <= LogLevel.Information) WriteLog("INF", ConsoleColor.White, message); } public void LogWarning(string message) { if (_minLevel <= LogLevel.Warning) WriteLog("WRN", ConsoleColor.Yellow, message); } public void LogError(string message) { if (_minLevel <= LogLevel.Error) WriteLog("ERR", ConsoleColor.Red, message); } private static void WriteLog(string level, ConsoleColor color, string message) { var timestamp = DateTime.Now.ToString("HH:mm:ss"); var originalColor = Console.ForegroundColor; Console.ForegroundColor = color; Console.WriteLine($"[{timestamp}] [{level}] {message}"); Console.ForegroundColor = originalColor; } } /// /// 日志记录器接口 /// public interface ILogger { void LogTrace(string message); void LogDebug(string message); void LogInformation(string message); void LogWarning(string message); void LogError(string message); } /// /// 日志级别 /// public enum LogLevel { Trace, Debug, Information, Warning, Error }