package com.example.mathsystemtogether; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import java.util.*; import java.io.*; import java.nio.file.Files; import java.nio.file.Paths; /** * 考试系统控制器 */ public class ExamController { // 登录界面控件 @FXML private TextField usernameField; @FXML private PasswordField passwordField; @FXML private Button loginButton; @FXML private Button registerButton; @FXML private Label loginStatusLabel; // 考试设置界面控件 @FXML private VBox examSetupPanel; @FXML private Label welcomeLabel; @FXML private ComboBox levelComboBox; @FXML private TextField questionCountField; @FXML private Button startExamButton; @FXML private Button logoutButton; @FXML private Label statusLabel; @FXML private Button changePasswordButton; // 数据成员 private Account currentAccount; private List examQuestions; private ChoiceQuestionGenerator questionGenerator; private final Map userMap = new HashMap<>(); private static final String USER_DATA_FILE = "user_data.txt"; // 常量定义 private static final int MIN_QUESTIONS = 5; private static final int MAX_QUESTIONS = 20; @FXML public void initialize() { initAccounts(); loadUserDataFromFile(); setupLevelComboBox(); examSetupPanel.setVisible(false); questionCountField.setText("10"); } private void initAccounts() { // 小学三个账号 userMap.put("张三1", new Account("张三1", "123", Level.小学)); userMap.put("张三2", new Account("张三2", "123", Level.小学)); userMap.put("张三3", new Account("张三3", "123", Level.小学)); // 初中三个账号 userMap.put("李四1", new Account("李四1", "123", Level.初中)); userMap.put("李四2", new Account("李四2", "123", Level.初中)); userMap.put("李四3", new Account("李四3", "123", Level.初中)); // 高中三个账号 userMap.put("王五1", new Account("王五1", "123", Level.高中)); userMap.put("王五2", new Account("王五2", "123", Level.高中)); userMap.put("王五3", new Account("王五3", "123", Level.高中)); } private void setupLevelComboBox() { ObservableList levels = FXCollections.observableArrayList("小学", "初中", "高中"); levelComboBox.setItems(levels); levelComboBox.setValue("小学"); } private void loadUserDataFromFile() { try { if (!Files.exists(Paths.get(USER_DATA_FILE))) { return; } List lines = Files.readAllLines(Paths.get(USER_DATA_FILE)); for (String line : lines) { String[] parts = line.split("\\|"); if (parts.length >= 4) { String username = parts[0]; String password = parts[1]; String levelStr = parts[3]; Level level; try { level = Level.valueOf(levelStr); } catch (IllegalArgumentException e) { level = Level.小学; // 默认级别 } userMap.put(username, new Account(username, password, level)); } } } catch (IOException e) { // 加载用户数据失败,静默处理 } } @FXML private void handleLogin() { String username = usernameField.getText().trim(); String password = passwordField.getText(); if (username.isEmpty() || password.isEmpty()) { loginStatusLabel.setText("请输入用户名和密码"); loginStatusLabel.setStyle("-fx-text-fill: red;"); return; } Account account = userMap.get(username); if (account != null && account.password.equals(password)) { currentAccount = account; welcomeLabel.setText("欢迎," + username + "!当前级别:" + account.level); levelComboBox.setValue(account.level.toString()); examSetupPanel.setVisible(true); loginStatusLabel.setText("登录成功!"); loginStatusLabel.setStyle("-fx-text-fill: green;"); } else { loginStatusLabel.setText("用户名或密码错误"); loginStatusLabel.setStyle("-fx-text-fill: red;"); } } @FXML private void handleRegister() { try { // 打开注册界面 FXMLLoader loader = new FXMLLoader(getClass().getResource("register-view.fxml")); Scene scene = new Scene(loader.load(), 800, 800); Stage registerStage = new Stage(); registerStage.setTitle("数学考试系统 - 用户注册"); registerStage.setScene(scene); registerStage.setResizable(false); // 获取注册控制器并设置原始登录界面引用 RegisterController registerController = loader.getController(); Stage currentStage = (Stage) loginStatusLabel.getScene().getWindow(); registerController.setOriginalLoginStage(currentStage); registerStage.show(); } catch (Exception e) { loginStatusLabel.setText("打开注册界面失败:" + e.getMessage()); loginStatusLabel.setStyle("-fx-text-fill: red;"); } } @FXML private void handleLogout() { currentAccount = null; examQuestions = null; examSetupPanel.setVisible(false); usernameField.clear(); passwordField.clear(); loginStatusLabel.setText(""); statusLabel.setText(""); } @FXML private void handleStartExam() { if (currentAccount == null) { statusLabel.setText("请先登录"); statusLabel.setStyle("-fx-text-fill: red;"); return; } try { int count = Integer.parseInt(questionCountField.getText()); if (count < MIN_QUESTIONS || count > MAX_QUESTIONS) { statusLabel.setText("题目数量应在" + MIN_QUESTIONS + "-" + MAX_QUESTIONS + "之间"); statusLabel.setStyle("-fx-text-fill: red;"); return; } // 获取选择的级别 String selectedLevel = levelComboBox.getValue(); ChoiceQuestionGenerator.Level level = ChoiceQuestionGenerator.Level.valueOf(selectedLevel); // 生成考试题目 questionGenerator = new ChoiceQuestionGenerator(); examQuestions = questionGenerator.generateQuestions(level, count); if (examQuestions.isEmpty()) { statusLabel.setText("无法生成题目,请重试"); statusLabel.setStyle("-fx-text-fill: red;"); return; } // 开始考试 startExam(); } catch (NumberFormatException e) { statusLabel.setText("请输入有效的数字"); statusLabel.setStyle("-fx-text-fill: red;"); } } @FXML private void handleChangePassword() { if (currentAccount == null) { statusLabel.setText("请先登录"); statusLabel.setStyle("-fx-text-fill: red;"); return; } try { FXMLLoader loader = new FXMLLoader(getClass().getResource("change-password-view.fxml")); Scene scene = new Scene(loader.load(), 600, 500); Stage changePasswordStage = new Stage(); changePasswordStage.setTitle("修改密码"); changePasswordStage.setScene(scene); changePasswordStage.setResizable(false); // 传递当前用户信息给密码修改控制器 ChangePasswordController controller = loader.getController(); controller.setCurrentUser(currentAccount.username); controller.setExamController(this); changePasswordStage.show(); } catch (Exception e) { statusLabel.setText("打开修改密码界面失败:" + e.getMessage()); statusLabel.setStyle("-fx-text-fill: red;"); } } // 供 ChangePasswordController 调用的方法 public boolean checkUserPassword(String username, String password) { Account account = userMap.get(username); return account != null && account.password.equals(password); } // 更新用户密码 public void updateUserPassword(String username, String newPassword) { Account account = userMap.get(username); if (account != null) { account.password = newPassword; } } // 为继续做题设置用户信息 public void setUserForContinueExam(String username, String level) { // 设置当前用户 Account account = userMap.get(username); if (account != null) { currentAccount = account; welcomeLabel.setText("欢迎," + username + "!当前级别:" + account.level); levelComboBox.setValue(account.level.toString()); examSetupPanel.setVisible(true); loginStatusLabel.setText("继续做题模式"); loginStatusLabel.setStyle("-fx-text-fill: green;"); } } private void startExam() { try { // 打开专门的考试界面 FXMLLoader loader = new FXMLLoader(getClass().getResource("exam-taking-view.fxml")); Scene scene = new Scene(loader.load(), 1000, 950); Stage examStage = new Stage(); examStage.setTitle("数学考试 - " + currentAccount.username); examStage.setScene(scene); examStage.setResizable(false); // 设置考试数据 ExamTakingController examController = loader.getController(); examController.setExamData(examQuestions, currentAccount.username, levelComboBox.getValue()); // 显示考试窗口 examStage.show(); // 隐藏主窗口 Stage mainStage = (Stage) startExamButton.getScene().getWindow(); mainStage.hide(); } catch (Exception e) { statusLabel.setText("启动考试失败:" + e.getMessage()); statusLabel.setStyle("-fx-text-fill: red;"); } } // 内部类 static class Account { final String username; String password; final Level level; Account(String username, String password, Level level) { this.username = username; this.password = password; this.level = level; } } enum Level { 小学, 初中, 高中 } }