You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
180 lines
7.5 KiB
180 lines
7.5 KiB
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<String, String> options) {
|
|
out.println();
|
|
out.println(BLUE + "┌─────────────── 功能菜单 ───────────────┐" + RESET);
|
|
for (Map.Entry<String, String> 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<String, String> getDefaultMenu() {
|
|
Map<String, String> menu = new HashMap<>();
|
|
menu.put("1", "当当网图书爬虫");
|
|
menu.put("2", "中国天气网爬虫");
|
|
menu.put("3", "豆瓣电影Top250爬虫");
|
|
menu.put("4", "运行所有爬虫");
|
|
menu.put("5", "查看使用说明");
|
|
menu.put("0", "退出系统");
|
|
return menu;
|
|
}
|
|
}
|