diff --git a/src/Math_learning_app.java b/src/Math_learning_app.java new file mode 100644 index 0000000..7d785e4 --- /dev/null +++ b/src/Math_learning_app.java @@ -0,0 +1,38 @@ +import View.MainFrame; + +import javax.swing.*; + +public class Math_learning_app { + public static void main(String[] args) { + // 设置系统样式 - 使用正确的方法 + try { + // 使用跨平台外观 + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + + // 或者使用系统默认外观(推荐) + // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + + } catch (Exception e) { + // 如果设置失败,使用默认外观 + System.err.println("无法设置外观,使用默认外观"); + e.printStackTrace(); + } + + // 在事件分发线程中创建和显示GUI + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + try { + MainFrame mainFrame = new MainFrame(); + mainFrame.setVisible(true); + } catch (Exception e) { + JOptionPane.showMessageDialog(null, + "程序启动失败: " + e.getMessage(), + "错误", + JOptionPane.ERROR_MESSAGE); + e.printStackTrace(); + } + } + }); + } +} \ No newline at end of file diff --git a/src/View/MainFrame.java b/src/View/MainFrame.java new file mode 100644 index 0000000..51ed72a --- /dev/null +++ b/src/View/MainFrame.java @@ -0,0 +1,731 @@ +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("
考试完成!
" + + "%s数学测试
" + + "总题数: %d
" + + "答对题数: %d
" + + "得分: %.1f
" + + "用时: %s
" + + "正确率: %s
" + + "