添加 'controller/AppController.java'

liuxingpeng_branch
pus7f45rn 6 months ago
parent aa7dfe06bc
commit 023f7ae9d9

@ -0,0 +1,316 @@
package controller;
import model.*;
import service.*;
import view.*;
import javax.swing.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
public class AppController {
// 模型和服务
private final UserManager userManager;
private final ExamManager examManager;
private final EmailService emailService;
// 视图
private final MainFrame mainFrame;
private final LoginView loginView;
private final RegisterView registerView;
private final PasswordSetView passwordSetView;
private final MainMenuView mainMenuView;
private final ExamView examView;
private final ScoreView scoreView;
// 应用状态
private User currentUser;
private String emailForRegistration;
private String usernameForRegistration;
private final Map<String, String> registrationCodes = new HashMap<>();
private List<Question> currentExam;
private int currentQuestionIndex;
private int score;
private int[] userAnswers; // 新增:用于存储用户每一题的答案
public AppController() {
this.mainFrame = new MainFrame();
this.userManager = new UserManager();
this.examManager = new ExamManager();
this.emailService = new EmailService();
this.loginView = new LoginView();
this.registerView = new RegisterView();
this.passwordSetView = new PasswordSetView();
this.mainMenuView = new MainMenuView();
this.examView = new ExamView();
this.scoreView = new ScoreView();
mainFrame.addPanel(loginView, "LOGIN");
mainFrame.addPanel(registerView, "REGISTER");
mainFrame.addPanel(passwordSetView, "PASSWORD_SET");
mainFrame.addPanel(mainMenuView, "MAIN_MENU");
mainFrame.addPanel(examView, "EXAM");
mainFrame.addPanel(scoreView, "SCORE");
attachListeners();
mainFrame.showPanel("LOGIN");
}
/**
* UI
*/
private void attachListeners() {
// --- 登录逻辑 ---
loginView.getLoginButton().addActionListener(e -> handleLogin());
loginView.getRegisterButton().addActionListener(e -> mainFrame.showPanel("REGISTER"));
// --- 注册逻辑 ---
registerView.getGetCodeButton().addActionListener(e -> handleGetCode());
registerView.getRegisterButton().addActionListener(e -> handleVerifyCode());
registerView.getBackButton().addActionListener(e -> mainFrame.showPanel("LOGIN"));
// --- 密码设置逻辑 ---
passwordSetView.getSubmitButton().addActionListener(e -> handleSetPassword());
// --- 主菜单逻辑 ---
mainMenuView.getStartExamButton().addActionListener(e -> handleStartExam());
mainMenuView.getChangePasswordButton().addActionListener(e -> handleChangePassword());
mainMenuView.getLogoutButton().addActionListener(e -> handleLogout());
// --- 考试逻辑 (已重构) ---
examView.getPrevButton().addActionListener(e -> handlePreviousQuestion());
examView.getNextButton().addActionListener(e -> handleNextQuestion());
examView.getFinishButton().addActionListener(e -> handleFinishExam());
// --- 分数界面逻辑 ---
scoreView.getContinueButton().addActionListener(e -> {
String welcomeName = currentUser.getUsername() != null && !currentUser.getUsername().isEmpty() ? currentUser.getUsername() : currentUser.getEmail();
mainMenuView.setWelcomeMessage("欢迎, " + welcomeName);
mainFrame.showPanel("MAIN_MENU");
});
scoreView.getExitButton().addActionListener(e -> handleLogout());
}
// --- 核心处理方法 ---
private void handleLogin() {
User user = userManager.authenticate(loginView.getIdentifier(), loginView.getPassword());
if (user != null) {
currentUser = user;
String welcomeName = user.getUsername() != null && !user.getUsername().isEmpty() ? user.getUsername() : user.getEmail();
mainMenuView.setWelcomeMessage("欢迎, " + welcomeName);
mainFrame.showPanel("MAIN_MENU");
} else {
JOptionPane.showMessageDialog(mainFrame, "邮箱/用户名或密码错误", "登录失败", JOptionPane.ERROR_MESSAGE);
}
loginView.clearFields();
}
private void handleGetCode() {
String email = registerView.getEmail();
String username = registerView.getUsername();
if (!ValidationService.isValidEmail(email)) {
JOptionPane.showMessageDialog(mainFrame, "请输入有效的邮箱格式!", "格式错误", JOptionPane.ERROR_MESSAGE);
return;
}
if (username.trim().isEmpty() || username.contains("|") || username.contains(" ")) {
JOptionPane.showMessageDialog(mainFrame, "用户名不能为空,且不能包含'|'或空格!", "格式错误", JOptionPane.ERROR_MESSAGE);
return;
}
if (userManager.emailExists(email)) {
JOptionPane.showMessageDialog(mainFrame, "该邮箱已被注册!", "注册失败", JOptionPane.ERROR_MESSAGE);
return;
}
if (userManager.usernameExists(username)) {
JOptionPane.showMessageDialog(mainFrame, "该用户名已被使用!", "注册失败", JOptionPane.ERROR_MESSAGE);
return;
}
emailForRegistration = email;
usernameForRegistration = username;
String code = String.format("%06d", new Random().nextInt(1000000));
registrationCodes.put(emailForRegistration, code);
final JButton getCodeButton = registerView.getGetCodeButton();
getCodeButton.setEnabled(false);
getCodeButton.setText("发送中...");
SwingWorker<Void, Void> worker = new SwingWorker<>() {
private Exception mailException = null;
@Override
protected Void doInBackground() {
try {
emailService.sendVerificationCode(emailForRegistration, code);
} catch (Exception e) {
this.mailException = e;
}
return null;
}
@Override
protected void done() {
getCodeButton.setEnabled(true);
getCodeButton.setText("发送验证邮件");
if (mailException == null) {
JOptionPane.showMessageDialog(mainFrame, "一封包含验证码的【电子邮件】已发送至您的邮箱,请登录邮箱查收。", "发送成功", JOptionPane.INFORMATION_MESSAGE);
} else {
String errorMessage = "邮件发送失败,请检查:\n1. 网络连接是否正常。\n2. config.properties 中的邮箱和授权码是否正确。\n\n错误详情: " + mailException.getMessage();
JOptionPane.showMessageDialog(mainFrame, errorMessage, "发送失败", JOptionPane.ERROR_MESSAGE);
mailException.printStackTrace();
}
}
};
worker.execute();
}
private void handleVerifyCode() {
String code = registerView.getCode();
if (code.equals(registrationCodes.get(emailForRegistration))) {
mainFrame.showPanel("PASSWORD_SET");
} else {
JOptionPane.showMessageDialog(mainFrame, "注册码错误!", "验证失败", JOptionPane.ERROR_MESSAGE);
}
}
private void handleSetPassword() {
String pass1 = passwordSetView.getPassword();
String pass2 = passwordSetView.getConfirmPassword();
if (!pass1.equals(pass2)) {
JOptionPane.showMessageDialog(mainFrame, "两次输入的密码不一致!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
if (!ValidationService.isPasswordStrong(pass1)) {
JOptionPane.showMessageDialog(mainFrame, "密码必须为6-10位且包含大小写字母和数字。", "密码格式错误", JOptionPane.ERROR_MESSAGE);
return;
}
userManager.registerUser(emailForRegistration, usernameForRegistration, pass1, UserType.PRIMARY);
JOptionPane.showMessageDialog(mainFrame, "注册成功!请返回登录。", "成功", JOptionPane.INFORMATION_MESSAGE);
mainFrame.showPanel("LOGIN");
}
private void handleStartExam() {
UserType type = mainMenuView.getSelectedType();
int count = mainMenuView.getQuestionCount();
if(currentUser.getUserType() != type) {
currentUser.setUserType(type);
userManager.updateUser(currentUser);
}
currentExam = examManager.generateExam(currentUser, type, count);
if (currentExam.size() < count) {
JOptionPane.showMessageDialog(mainFrame, "抱歉,未能生成足够数量的不重复题目,实际生成 " + currentExam.size() + " 道。", "提示", JOptionPane.WARNING_MESSAGE);
}
if (currentExam.isEmpty()) return;
currentQuestionIndex = 0;
score = 0;
userAnswers = new int[currentExam.size()];
Arrays.fill(userAnswers, -1); // -1 代表未作答
examView.setupForExam(currentExam.size());
displayCurrentQuestion();
mainFrame.showPanel("EXAM");
}
private void displayCurrentQuestion() {
Question q = currentExam.get(currentQuestionIndex);
int savedAnswer = userAnswers[currentQuestionIndex];
examView.displayQuestion(q, currentQuestionIndex + 1, currentExam.size(), savedAnswer);
examView.updateNavigationButtons(currentQuestionIndex, currentExam.size());
}
private void handlePreviousQuestion() {
saveCurrentAnswer();
if (currentQuestionIndex > 0) {
currentQuestionIndex--;
displayCurrentQuestion();
}
}
private void handleNextQuestion() {
saveCurrentAnswer();
if (currentQuestionIndex < currentExam.size() - 1) {
currentQuestionIndex++;
displayCurrentQuestion();
}
}
private void saveCurrentAnswer() {
int selectedIndex = examView.getSelectedIndex();
userAnswers[currentQuestionIndex] = selectedIndex;
}
private void handleFinishExam() {
saveCurrentAnswer();
int choice = JOptionPane.showConfirmDialog(mainFrame,
"您确定要交卷吗?\n未完成的题目将按 0 分计算。",
"确认交卷",
JOptionPane.YES_NO_OPTION);
if (choice == JOptionPane.YES_OPTION) {
calculateScore();
int finalScore = (int) Math.round((double) score / currentExam.size() * 100);
scoreView.setScore(finalScore, score, currentExam.size());
mainFrame.showPanel("SCORE");
}
}
private void calculateScore() {
score = 0;
for (int i = 0; i < currentExam.size(); i++) {
if (userAnswers[i] != -1 && userAnswers[i] == currentExam.get(i).getCorrectOptionIndex()) {
score++;
}
}
}
private void handleChangePassword() {
ChangePasswordView dialog = new ChangePasswordView(mainFrame);
dialog.getConfirmButton().addActionListener(e -> {
String oldPass = dialog.getOldPassword();
String newPass = dialog.getNewPassword();
String confirmPass = dialog.getConfirmPassword();
if (userManager.authenticate(currentUser.getEmail(), oldPass) == null) {
JOptionPane.showMessageDialog(dialog, "原密码错误!", "验证失败", JOptionPane.ERROR_MESSAGE);
return;
}
if (!newPass.equals(confirmPass)) {
JOptionPane.showMessageDialog(dialog, "两次输入的新密码不一致!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
if (!ValidationService.isPasswordStrong(newPass)) {
JOptionPane.showMessageDialog(dialog, "新密码必须为6-10位且包含大小写字母和数字。", "密码格式错误", JOptionPane.ERROR_MESSAGE);
return;
}
currentUser.setHashedPassword(newPass);
userManager.updateUser(currentUser);
JOptionPane.showMessageDialog(dialog, "密码修改成功!", "成功", JOptionPane.INFORMATION_MESSAGE);
dialog.dispose();
});
dialog.getCancelButton().addActionListener(e -> dialog.dispose());
dialog.setVisible(true);
}
private void handleLogout() {
currentUser = null;
loginView.clearFields();
mainFrame.showPanel("LOGIN");
}
}
Loading…
Cancel
Save