import java.util.List; import java.util.Scanner; /** * View: 所有 I/O 集中在这里,颜色常量统一管理 * 选做暗色主题:只需改 THEME_PRIMARY / THEME_SECONDARY 两个常量即可 */ public class ConsoleView { // ── ANSI 基础色 ── private static final String ANSI_RESET = "\033[0m"; private static final String ANSI_GREEN = "\033[32m"; private static final String ANSI_RED = "\033[31m"; private static final String ANSI_YELLOW = "\033[33m"; private static final String ANSI_CYAN = "\033[36m"; private static final String ANSI_BOLD = "\033[1m"; // ── 选做:主题常量(暗色主题只改这两行)── private static final String THEME_PRIMARY = ANSI_CYAN; // 暗色主题可换 ANSI_GREEN private static final String THEME_SECONDARY = ANSI_YELLOW; // 暗色主题可换 ANSI_CYAN private final Scanner scanner = new Scanner(System.in); public void printSuccess(String msg) { System.out.println(ANSI_GREEN + msg + ANSI_RESET); } public void printError(String msg) { System.out.println(ANSI_RED + "[ERROR] " + msg + ANSI_RESET); } public void printInfo(String msg) { System.out.println(THEME_PRIMARY + msg + ANSI_RESET); } public void printWarning(String msg) { System.out.println(THEME_SECONDARY + "[WARN] " + msg + ANSI_RESET); } public void printBold(String msg) { System.out.println(ANSI_BOLD + msg + ANSI_RESET); } /** 展示文章列表 */ public void display(List
articles) { if (articles.isEmpty()) { printWarning("暂无文章,请先使用 crawl 抓取。"); return; } printBold("── 文章列表 (" + articles.size() + " 篇) ──"); for (int i = 0; i < articles.size(); i++) { Article a = articles.get(i); if (a == null) { printWarning((i + 1) + ". [null 条目,已跳过]"); continue; } System.out.printf(THEME_PRIMARY + "%2d. %s" + ANSI_RESET + "%n", i + 1, a); } } /** 读取一行用户输入,显示提示符 */ public String readLine() { System.out.print(ANSI_BOLD + "> " + ANSI_RESET); return scanner.nextLine().trim(); } }