package View; import Service.User_service; import Service.Exam_service; import Base.Exam_result; import Base.Question; import javax.swing.*; import java.awt.*; import java.util.List; public class MainFrame extends JFrame { private final User_service userService; private Exam_service examService; private CardLayout cardLayout; private JPanel mainPanel; private String currentUserId; // UI组件字段 private JTextField loginIdField; private JPasswordField loginPasswordField; private JTextField regEmailField; private JTextField regCodeField; private JPasswordField regPasswordField; private JPasswordField regConfirmPasswordField; private JTextField regUserIdField; private JLabel questionLabel; private JRadioButton[] optionButtons; private ButtonGroup optionGroup; private JLabel questionNumberLabel; private JButton prevButton; private JButton nextButton; private JButton submitButton; private JLabel resultLabel; public MainFrame() { userService = new User_service(); initializeUI(); setTitle("数学学习系统"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(800, 600); setLocationRelativeTo(null); } private void initializeUI() { cardLayout = new CardLayout(); mainPanel = new JPanel(cardLayout); createLoginPanel(); createRegisterPanel(); createGradeSelectionPanel(); createExamPanel(); createResultPanel(); createWrongQuestionsPanel(); // 新增错题面板 createPasswordChangePanel(); add(mainPanel); showLoginPanel(); } private void createLoginPanel() { JPanel panel = new JPanel(new BorderLayout(10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100)); JLabel titleLabel = new JLabel("数学学习系统", JLabel.CENTER); titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24)); panel.add(titleLabel, BorderLayout.NORTH); JPanel formPanel = new JPanel(new GridLayout(3, 2, 15, 15)); formPanel.setBorder(BorderFactory.createEmptyBorder(30, 50, 30, 50)); formPanel.add(new JLabel("用户名:", JLabel.CENTER)); loginIdField = new JTextField(); formPanel.add(loginIdField); formPanel.add(new JLabel("密码:", JLabel.CENTER)); loginPasswordField = new JPasswordField(); formPanel.add(loginPasswordField); panel.add(formPanel, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); JButton loginButton = createStyledButton("登录"); loginButton.addActionListener(e -> login()); buttonPanel.add(loginButton); JButton registerButton = createStyledButton("注册账号"); registerButton.addActionListener(e -> showRegisterPanel()); buttonPanel.add(registerButton); JButton exitButton = createStyledButton("退出"); exitButton.addActionListener(e -> exitchoice()); buttonPanel.add(exitButton); panel.add(buttonPanel, BorderLayout.SOUTH); mainPanel.add(panel, "Login"); } private void createRegisterPanel() { JPanel panel = new JPanel(new BorderLayout(10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(30, 80, 30, 80)); JLabel titleLabel = new JLabel("用户注册", JLabel.CENTER); titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20)); panel.add(titleLabel, BorderLayout.NORTH); JPanel formPanel = new JPanel(new GridLayout(5, 2, 15, 15)); formPanel.setBorder(BorderFactory.createEmptyBorder(20, 50, 20, 50)); formPanel.add(new JLabel("邮箱:", JLabel.CENTER)); regEmailField = new JTextField(); formPanel.add(regEmailField); formPanel.add(new JLabel("验证码:", JLabel.CENTER)); JPanel codePanel = new JPanel(new BorderLayout(5, 0)); regCodeField = new JTextField(); codePanel.add(regCodeField, BorderLayout.CENTER); JButton sendCodeButton = new JButton("发送验证码"); sendCodeButton.setFont(new Font("微软雅黑", Font.PLAIN, 10)); sendCodeButton.addActionListener(e -> sendVerificationCode()); codePanel.add(sendCodeButton, BorderLayout.EAST); formPanel.add(codePanel); formPanel.add(new JLabel("密码:", JLabel.CENTER)); regPasswordField = new JPasswordField(); formPanel.add(regPasswordField); formPanel.add(new JLabel("确认密码:", JLabel.CENTER)); regConfirmPasswordField = new JPasswordField(); formPanel.add(regConfirmPasswordField); formPanel.add(new JLabel("用户名:", JLabel.CENTER)); regUserIdField = new JTextField(); formPanel.add(regUserIdField); panel.add(formPanel, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); JButton registerButton = createStyledButton("注册"); registerButton.addActionListener(e -> register()); buttonPanel.add(registerButton); JButton backButton = createStyledButton("返回登录"); backButton.addActionListener(e -> showLoginPanel()); buttonPanel.add(backButton); panel.add(buttonPanel, BorderLayout.SOUTH); mainPanel.add(panel, "Register"); } private void createGradeSelectionPanel() { JPanel panel = new JPanel(new BorderLayout(10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100)); JLabel titleLabel = new JLabel("选择学习阶段", JLabel.CENTER); titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24)); panel.add(titleLabel, BorderLayout.NORTH); JPanel gradePanel = new JPanel(new GridLayout(4, 1, 20, 20)); gradePanel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100)); JButton primaryButton = createGradeButton("小学"); primaryButton.addActionListener(e -> startExam("小学")); gradePanel.add(primaryButton); JButton juniorButton = createGradeButton("初中"); juniorButton.addActionListener(e -> startExam("初中")); gradePanel.add(juniorButton); JButton seniorButton = createGradeButton("高中"); seniorButton.addActionListener(e -> startExam("高中")); gradePanel.add(seniorButton); panel.add(gradePanel, BorderLayout.CENTER); JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); JButton changePasswordButton = createStyledButton("修改密码"); changePasswordButton.addActionListener(e -> showPasswordChangePanel()); bottomPanel.add(changePasswordButton); // 新增:删除账号按钮 JButton deleteAccountButton = createStyledButton("删除账号"); deleteAccountButton.setBackground(new Color(220, 20, 60)); // 红色背景提示危险操作 deleteAccountButton.addActionListener(e -> deleteAccount()); bottomPanel.add(deleteAccountButton); JButton logoutButton = createStyledButton("退出登录"); logoutButton.addActionListener(e -> logout()); bottomPanel.add(logoutButton); panel.add(bottomPanel, BorderLayout.SOUTH); mainPanel.add(panel, "GradeSelection"); } // 新增:删除当前账号功能 private void deleteAccount() { // 简单确认对话框 int result = JOptionPane.showConfirmDialog( this, "确定要删除当前账号吗?\n用户名:" + currentUserId + "\n此操作不可恢复!", "确认删除账号", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); if (result == JOptionPane.YES_OPTION) { // 直接使用当前用户名作为邮箱(根据您的系统设计,用户名可能就是邮箱) // 或者让用户输入邮箱确认 String userEmail = JOptionPane.showInputDialog( this, "请输入您的邮箱进行确认:", "确认删除", JOptionPane.QUESTION_MESSAGE ); if (userEmail != null && !userEmail.trim().isEmpty()) { // 调用User_service的Unregister函数删除账号 String deleteResult = userService.Unregister(userEmail.trim()); if (deleteResult.equals("删除成功")) { JOptionPane.showMessageDialog(this, "账号删除成功!"); // 清除当前用户信息并返回登录界面 currentUserId = null; examService = null; showLoginPanel(); } else { JOptionPane.showMessageDialog(this, "删除失败:" + deleteResult); } } } } private void createExamPanel() { JPanel panel = new JPanel(new BorderLayout(10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 40)); // 顶部信息栏 JPanel topPanel = new JPanel(new BorderLayout()); questionNumberLabel = new JLabel("", JLabel.LEFT); questionNumberLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); topPanel.add(questionNumberLabel, BorderLayout.WEST); panel.add(topPanel, BorderLayout.NORTH); // 题目区域 JPanel questionPanel = new JPanel(new BorderLayout(10, 20)); questionPanel.setBorder(BorderFactory.createEmptyBorder(30, 50, 30, 50)); questionLabel = new JLabel("", JLabel.CENTER); questionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18)); questionPanel.add(questionLabel, BorderLayout.NORTH); // 选项区域 JPanel optionsPanel = new JPanel(new GridLayout(4, 1, 10, 10)); optionsPanel.setBorder(BorderFactory.createEmptyBorder(20, 100, 20, 100)); optionButtons = new JRadioButton[4]; optionGroup = new ButtonGroup(); for (int i = 0; i < 4; i++) { optionButtons[i] = new JRadioButton(); optionButtons[i].setFont(new Font("微软雅黑", Font.PLAIN, 16)); optionGroup.add(optionButtons[i]); optionsPanel.add(optionButtons[i]); } questionPanel.add(optionsPanel, BorderLayout.CENTER); panel.add(questionPanel, BorderLayout.CENTER); // 导航按钮区域 JPanel navPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); prevButton = createStyledButton("上一题"); prevButton.addActionListener(e -> goToPreviousQuestion()); navPanel.add(prevButton); nextButton = createStyledButton("下一题"); nextButton.addActionListener(e -> goToNextQuestion()); navPanel.add(nextButton); submitButton = createStyledButton("提交试卷"); submitButton.addActionListener(e -> submitExam()); navPanel.add(submitButton); panel.add(navPanel, BorderLayout.SOUTH); mainPanel.add(panel, "Exam"); } private void createResultPanel() { JPanel panel = new JPanel(new BorderLayout(10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100)); resultLabel = new JLabel("", JLabel.CENTER); resultLabel.setFont(new Font("微软雅黑", Font.BOLD, 24)); panel.add(resultLabel, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 30, 20)); // 新增查看错题按钮 JButton reviewButton = createStyledButton("查看错题"); reviewButton.addActionListener(e -> showWrongQuestions()); buttonPanel.add(reviewButton); JButton continueButton = createStyledButton("继续做题"); continueButton.addActionListener(e -> showGradeSelectionPanel()); buttonPanel.add(continueButton); JButton exitButton = createStyledButton("退出程序"); exitButton.addActionListener(e -> System.exit(0)); buttonPanel.add(exitButton); panel.add(buttonPanel, BorderLayout.SOUTH); mainPanel.add(panel, "Result"); } private void createWrongQuestionsPanel() { JPanel panel = new JPanel(new BorderLayout(10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(20, 40, 20, 40)); // 标题 JLabel titleLabel = new JLabel("错题回顾", JLabel.CENTER); titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20)); panel.add(titleLabel, BorderLayout.NORTH); // 错题内容区域(使用滚动面板) JTextArea wrongQuestionsArea = new JTextArea(); wrongQuestionsArea.setFont(new Font("微软雅黑", Font.PLAIN, 14)); wrongQuestionsArea.setEditable(false); wrongQuestionsArea.setLineWrap(true); wrongQuestionsArea.setWrapStyleWord(true); JScrollPane scrollPane = new JScrollPane(wrongQuestionsArea); scrollPane.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); panel.add(scrollPane, BorderLayout.CENTER); // 存储错题文本区域引用 panel.putClientProperty("wrongQuestionsArea", wrongQuestionsArea); // 返回按钮 JPanel bottomPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); JButton backButton = createStyledButton("返回成绩"); backButton.addActionListener(e -> showResultPanel()); bottomPanel.add(backButton); panel.add(bottomPanel, BorderLayout.SOUTH); mainPanel.add(panel, "WrongQuestions"); } private void createPasswordChangePanel() { JPanel panel = new JPanel(new BorderLayout(10, 10)); panel.setBorder(BorderFactory.createEmptyBorder(50, 100, 50, 100)); JLabel titleLabel = new JLabel("修改密码", JLabel.CENTER); titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20)); panel.add(titleLabel, BorderLayout.NORTH); JPanel formPanel = new JPanel(new GridLayout(4, 2, 15, 15)); formPanel.setBorder(BorderFactory.createEmptyBorder(30, 80, 30, 80)); formPanel.add(new JLabel("邮箱:", JLabel.RIGHT)); JTextField emailField = new JTextField(); formPanel.add(emailField); formPanel.add(new JLabel("原密码:", JLabel.RIGHT)); JPasswordField oldPasswordField = new JPasswordField(); formPanel.add(oldPasswordField); formPanel.add(new JLabel("新密码:", JLabel.RIGHT)); JPasswordField newPasswordField = new JPasswordField(); formPanel.add(newPasswordField); formPanel.add(new JLabel("确认新密码:", JLabel.RIGHT)); JPasswordField confirmPasswordField = new JPasswordField(); formPanel.add(confirmPasswordField); panel.add(formPanel, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); JButton changeButton = createStyledButton("确认修改"); changeButton.addActionListener(e -> { String email = emailField.getText(); String oldPassword = new String(oldPasswordField.getPassword()); String newPassword = new String(newPasswordField.getPassword()); String confirmPassword = new String(confirmPasswordField.getPassword()); changePassword(email, oldPassword, newPassword, confirmPassword); }); buttonPanel.add(changeButton); JButton backButton = createStyledButton("返回"); backButton.addActionListener(e -> showGradeSelectionPanel()); buttonPanel.add(backButton); panel.add(buttonPanel, BorderLayout.SOUTH); mainPanel.add(panel, "PasswordChange"); } private JButton createStyledButton(String text) { JButton button = new JButton(text); button.setFont(new Font("微软雅黑", Font.BOLD, 14)); button.setFocusPainted(false); button.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20)); return button; } private JButton createGradeButton(String text) { JButton button = new JButton(text); button.setFont(new Font("微软雅黑", Font.BOLD, 18)); button.setFocusPainted(false); button.setBorder(BorderFactory.createEmptyBorder(20, 0, 20, 0)); return button; } // 界面显示方法 private void showLoginPanel() { loginIdField.setText(""); loginPasswordField.setText(""); cardLayout.show(mainPanel, "Login"); } private void showRegisterPanel() { regEmailField.setText(""); regCodeField.setText(""); regPasswordField.setText(""); regConfirmPasswordField.setText(""); regUserIdField.setText(""); cardLayout.show(mainPanel, "Register"); } private void showGradeSelectionPanel() { cardLayout.show(mainPanel, "GradeSelection"); } private void showPasswordChangePanel() { cardLayout.show(mainPanel, "PasswordChange"); } private void showExamPanel() { cardLayout.show(mainPanel, "Exam"); } private void showResultPanel() { cardLayout.show(mainPanel, "Result"); } private void showWrongQuestionsPanel() { cardLayout.show(mainPanel, "WrongQuestions"); } // 业务逻辑方法 private void login() { String id = loginIdField.getText().trim(); String password = new String(loginPasswordField.getPassword()); if (id.isEmpty() || password.isEmpty()) { JOptionPane.showMessageDialog(this, "请输入用户名和密码"); return; } String result = userService.login(id, password); if (result.equals("登陆成功")) { currentUserId = id; showGradeSelectionPanel(); } else { JOptionPane.showMessageDialog(this, result); } } private void sendVerificationCode() { String email = regEmailField.getText().trim(); if (email.isEmpty()) { JOptionPane.showMessageDialog(this, "请输入邮箱地址"); return; } String result = userService.register(email); JOptionPane.showMessageDialog(this, result); } private void register() { String email = regEmailField.getText().trim(); String code = regCodeField.getText().trim(); String password = new String(regPasswordField.getPassword()); String confirmPassword = new String(regConfirmPasswordField.getPassword()); String userId = regUserIdField.getText().trim(); if (email.isEmpty() || code.isEmpty() || password.isEmpty() || userId.isEmpty()) { JOptionPane.showMessageDialog(this, "请填写所有字段"); return; } if (!password.equals(confirmPassword)) { JOptionPane.showMessageDialog(this, "两次输入的密码不一致"); return; } String result = userService.check_register(email, code, password, userId); JOptionPane.showMessageDialog(this, result); if (result.equals("注册成功")) { showLoginPanel(); } } private void startExam(String gradeType) { String input = JOptionPane.showInputDialog(this, "请输入" + gradeType + "题目数量:", "题目数量", JOptionPane.QUESTION_MESSAGE); if (input == null) return; try { int numQuestions = Integer.parseInt(input.trim()); if (numQuestions < 10 || numQuestions > 30) { JOptionPane.showMessageDialog(this, "题目数量范围是10-30"); return; } examService = new Exam_service(numQuestions, gradeType, currentUserId); showCurrentQuestion(); showExamPanel(); } catch (NumberFormatException e) { JOptionPane.showMessageDialog(this, "请输入有效的数字"); } } private void showCurrentQuestion() { Question question = examService.get_now_question(); if (question != null) { int currentIndex = examService.get_now_index(); int totalQuestions = examService.get_paper().size(); questionNumberLabel.setText(String.format("第 %d 题 / 共 %d 题", currentIndex + 1, totalQuestions)); questionLabel.setText("
" + question.toString() + "
"); for (int i = 0; i < 4; i++) { String optionText = question.getOptions(i); optionButtons[i].setText((char)('A' + i) + ": " + optionText); } Integer userAnswer = examService.get_user_answer(currentIndex); optionGroup.clearSelection(); if (userAnswer != null && userAnswer >= 0 && userAnswer < 4) { optionButtons[userAnswer].setSelected(true); } updateNavigationButtons(); } } private void updateNavigationButtons() { int currentIndex = examService.get_now_index(); int totalQuestions = examService.get_paper().size(); prevButton.setEnabled(currentIndex > 0); nextButton.setEnabled(currentIndex < totalQuestions - 1); submitButton.setEnabled(currentIndex == totalQuestions - 1); } private void goToPreviousQuestion() { if (examService.pre_one()) { showCurrentQuestion(); } } private void goToNextQuestion() { int selectedOption = getSelectedOption(); if (selectedOption == -1) { JOptionPane.showMessageDialog(this, "请选择一个答案"); return; } boolean hasNext = examService.next_one(selectedOption); if (hasNext) { showCurrentQuestion(); } else { showExamResult(); } } private void submitExam() { int selectedOption = getSelectedOption(); if (selectedOption == -1) { JOptionPane.showMessageDialog(this, "请选择一个答案"); return; } examService.next_one(selectedOption); showExamResult(); } private int getSelectedOption() { for (int i = 0; i < 4; i++) { if (optionButtons[i].isSelected()) { return i; } } return -1; } private void showExamResult() { Exam_result result = examService.calculate_result(); String resultText = String.format( "
" + "

考试完成!

" + "

%s数学测试

" + "

总题数: %d

" + "

答对题数: %d

" + "

得分: %.1f

" + "

用时: %s

" + "

正确率: %s

" + "
", result.getExamType(), result.getTotalQuestions(), result.getCorrectAnswers(), result.getScore(), result.get_time(), result.getCorrectRate() ); resultLabel.setText(resultText); showResultPanel(); } // 新增:查看错题功能 // 修正:查看错题功能 - 简洁显示 private void showWrongQuestions() { // 获取考试结果 Exam_result result = examService.calculate_result(); java.util.List wrongQuestionIndices = result.getWrongQuestions(); if (wrongQuestionIndices.isEmpty()) { JOptionPane.showMessageDialog(this, "恭喜!本次考试没有错题!"); return; } // 获取错题面板和文本区域 JPanel wrongQuestionsPanel = (JPanel) mainPanel.getComponent(5); // 第6个面板是错题面板 JTextArea wrongQuestionsArea = (JTextArea) ((JScrollPane) wrongQuestionsPanel.getComponent(1)).getViewport().getView(); // 构建错题显示内容 StringBuilder sb = new StringBuilder(); sb.append("本次考试共有 ").append(wrongQuestionIndices.size()).append(" 道错题:\n\n"); java.util.ArrayList paper = examService.get_paper(); for (int i = 0; i < wrongQuestionIndices.size(); i++) { int questionIndex = wrongQuestionIndices.get(i); Question question = paper.get(questionIndex); // 只显示一个题号 sb.append("第 ").append(questionIndex + 1).append(" 题:"); sb.append(question.toString()).append("\n"); // 显示所有选项,在正确答案后打勾 sb.append("选项:\n"); for (int j = 0; j < 4; j++) { char optionChar = (char) ('A' + j); sb.append(" ").append(optionChar).append(". ").append(question.getOptions(j)); // 标记正确答案 if (question.getOptions(j).equals(question.getAnswer())) { sb.append(" √"); } // 标记用户选择的错误答案 Integer userAnswer = examService.get_user_answer(questionIndex); if (userAnswer != null && userAnswer == j && !question.getOptions(j).equals(question.getAnswer())) { sb.append(" X"); } sb.append("\n"); } sb.append("\n"); sb.append("-".repeat(50)).append("\n\n"); } wrongQuestionsArea.setText(sb.toString()); showWrongQuestionsPanel(); } private void changePassword(String email, String oldPassword, String newPassword, String confirmPassword) { if (email.isEmpty() || oldPassword.isEmpty() || newPassword.isEmpty()) { JOptionPane.showMessageDialog(this, "请填写所有字段"); return; } if (!newPassword.equals(confirmPassword)) { JOptionPane.showMessageDialog(this, "两次输入的新密码不一致"); return; } String result = userService.change_pwd(email, oldPassword, newPassword); JOptionPane.showMessageDialog(this, result); if (result.equals("修改成功")) { showGradeSelectionPanel(); } } private void logout() { currentUserId = null; examService = null; showLoginPanel(); } public void exitchoice(){ System.exit(0); } // 主函数 public static void main(String[] args) { SwingUtilities.invokeLater(() -> { new MainFrame().setVisible(true); }); } }