package view; import java.io.PrintWriter; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.util.HashMap; import java.util.Map; public class CrawlerView { private final PrintWriter out; private final BufferedReader in; private static final String RESET = "\033[0m"; private static final String RED = "\033[31m"; private static final String GREEN = "\033[32m"; private static final String YELLOW = "\033[33m"; private static final String BLUE = "\033[34m"; private static final String CYAN = "\033[36m"; public CrawlerView() { this.out = new PrintWriter(System.out, true); this.in = new BufferedReader(new InputStreamReader(System.in)); } public void showHeader(String message) { out.println(); out.println(CYAN + "═══════════════════════════════════════════════════" + RESET); out.println(CYAN + " " + message + RESET); out.println(CYAN + "═══════════════════════════════════════════════════" + RESET); out.flush(); } public void showMessage(String message) { out.println(BLUE + "[INFO]" + RESET + " " + message); out.flush(); } public void showSuccess(String message) { out.println(GREEN + "[成功]" + RESET + " " + message); out.flush(); } public void showError(String message) { out.println(RED + "[错误]" + RESET + " " + message); out.flush(); } public void showWarning(String message) { out.println(YELLOW + "[警告]" + RESET + " " + message); out.flush(); } public void showLine() { out.println("───────────────────────────────────────────────────"); out.flush(); } public void showMenu(Map options) { out.println(); out.println(BLUE + "┌─────────────── 功能菜单 ───────────────┐" + RESET); for (Map.Entry entry : options.entrySet()) { out.println(BLUE + "│ " + RESET + String.format("%-6s - %s", entry.getKey(), entry.getValue()) + " ".repeat(Math.max(0, 28 - entry.getValue().length())) + BLUE + "│" + RESET); } out.println(BLUE + "└──────────────────────────────────────────┘" + RESET); out.println(); out.print("请输入选项: "); out.flush(); } public String readInput() { try { return in.readLine(); } catch (IOException e) { showError("读取输入失败: " + e.getMessage()); return ""; } } public String readInput(String prompt) { out.print(prompt + ": "); out.flush(); return readInput(); } public int readIntInput(String prompt, int defaultValue) { try { String input = readInput(prompt); if (input == null || input.trim().isEmpty()) { return defaultValue; } return Integer.parseInt(input.trim()); } catch (NumberFormatException e) { showError("无效的数字,使用默认值: " + defaultValue); return defaultValue; } } public boolean confirm(String message) { out.print(message + " (y/n): "); out.flush(); try { String input = in.readLine(); return "y".equalsIgnoreCase(input.trim()); } catch (IOException e) { return false; } } public void showException(Throwable e) { out.println(); out.println(RED + "╔═══════════════════ 异常信息 ═══════════════════╗" + RESET); out.println(RED + "║" + RESET + " 类型: " + e.getClass().getSimpleName()); out.println(RED + "║" + RESET + " 消息: " + e.getMessage()); if (e.getCause() != null) { out.println(RED + "║" + RESET + " 原因: " + e.getCause().getMessage()); } out.println(RED + "╚═════════════════════════════════════════════════╝" + RESET); out.flush(); } public void showUsage() { out.println(); out.println(BLUE + "┌─────────────────── 使用说明 ──────────────────┐" + RESET); out.println(BLUE + "│" + RESET + " 1. 选择要执行的爬虫任务"); out.println(BLUE + "│" + RESET + " 2. 系统将自动爬取数据"); out.println(BLUE + "│" + RESET + " 3. 断网时将抛出 IOException"); out.println(BLUE + "│" + RESET + " 4. 数据将保存到当前目录"); out.println(BLUE + "└─────────────────────────────────────────────┘" + RESET); } public void showWelcome() { out.println(); out.println(CYAN + "╔══════════════════════════════════════════════════╗" + RESET); out.println(CYAN + "║ ║" + RESET); out.println(CYAN + "║ 多网站爬虫系统 v2.0 ║" + RESET); out.println(CYAN + "║ MVC + Command + Strategy ║" + RESET); out.println(CYAN + "║ 架构模式完整实现 ║" + RESET); out.println(CYAN + "║ ║" + RESET); out.println(CYAN + "╚══════════════════════════════════════════════════╝" + RESET); out.flush(); } public void showGoodbye() { out.println(); out.println(GREEN + "感谢使用爬虫系统,再见!" + RESET); out.flush(); } public void showProgress(int current, int total, String task) { int percentage = (int) ((current / (double) total) * 100); StringBuilder bar = new StringBuilder("["); int barLength = 30; int filled = (int) (barLength * current / (double) total); for (int i = 0; i < barLength; i++) { if (i < filled) { bar.append("█"); } else { bar.append("░"); } } bar.append("]"); out.print("\r" + BLUE + "[进度]" + RESET + " " + task + ": " + bar + " " + percentage + "% (" + current + "/" + total + ")"); out.flush(); if (current == total) { out.println(); } } public static Map getDefaultMenu() { Map menu = new HashMap<>(); menu.put("1", "当当网图书爬虫"); menu.put("2", "中国天气网爬虫"); menu.put("3", "豆瓣电影Top250爬虫"); menu.put("4", "运行所有爬虫"); menu.put("5", "查看使用说明"); menu.put("0", "退出系统"); return menu; } }