From eb5c8a061da3d36e3ec2b01442854b4b3f2f5dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E9=BB=98=E6=B6=B5?= <15530826+wgll926@user.noreply.gitee.com> Date: Sat, 11 Oct 2025 14:27:02 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E5=86=8C?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=B9=B6=E5=AE=8C=E5=96=84=E9=82=AE=E7=AE=B1?= =?UTF-8?q?=E9=AA=8C=E8=AF=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 70 ++- pom.xml | 8 + run_gui.bat | 11 + .../mathsystemtogether/EmailCodeService.java | 125 ----- .../mathsystemtogether/ExamController.java | 443 +++--------------- .../example/mathsystemtogether/exam-view.fxml | 72 +-- .../mathsystemtogether/mail.properties | 9 - 7 files changed, 140 insertions(+), 598 deletions(-) delete mode 100644 src/main/java/com/example/mathsystemtogether/EmailCodeService.java delete mode 100644 src/main/resources/com/example/mathsystemtogether/mail.properties diff --git a/README.md b/README.md index 98d86a0..0e20bb8 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ mvn exec:java -Dexec.mainClass="com.example.mathsystemtogether.HelloApplication" ## 👤 用户账号 +### 预设测试账号 + 系统预设了9个测试账号: | 用户名 | 密码 | 难度级别 | 题目类型 | @@ -45,12 +47,54 @@ mvn exec:java -Dexec.mainClass="com.example.mathsystemtogether.HelloApplication" | 王五2 | 123 | 高中 | 三角函数运算 | | 王五3 | 123 | 高中 | 三角函数运算 | +### 新用户注册 + +系统支持新用户注册功能: + +1. **点击注册按钮**:在登录界面点击"📝 注册"按钮 +2. **填写注册信息**: + - 用户名(至少3个字符) + - 密码(至少6个字符) + - 确认密码 + - 邮箱地址 + - 难度级别选择 +3. **邮箱验证**: + - 点击"📤 发送验证码"获取验证码 + - 输入收到的6位数字验证码 + - 验证码有效期为5分钟 +4. **完成注册**:点击"🚀 注册"完成账户创建 +5. **自动跳转**:注册成功后自动返回登录界面 + +**注意**: +- 用户名不能重复 +- 邮箱地址格式必须正确 +- 验证码通过真实邮件发送 +- 用户数据保存在本地 `user_data.txt` 文件中 + +### 邮件服务配置 + +系统支持真实的邮箱验证码功能,已配置QQ邮箱: + +- **邮箱地址**:1961004835@qq.com +- **SMTP服务器**:smtp.qq.com:587 +- **配置文件**:`src/main/resources/mail.properties` + +如需修改邮箱配置,请编辑 `mail.properties` 文件。 + ## 🎮 使用流程 -### 1. 用户登录 +### 1. 用户登录或注册 + +**登录现有账户:** - 输入用户名(如:张三1) - 输入密码(123) -- 点击"登录"按钮 +- 点击"🚀 登录"按钮 + +**注册新账户:** +- 点击"📝 注册"按钮 +- 填写注册信息(用户名、密码、邮箱、难度级别) +- 获取并输入邮箱验证码 +- 点击"🚀 注册"完成账户创建 ### 2. 设置考试 - 选择难度级别(小学/初中/高中) @@ -125,10 +169,16 @@ MathSystemTogether/ ├── src/main/java/com/example/mathsystemtogether/ │ ├── HelloApplication.java # 主应用程序入口 │ ├── ExamController.java # 考试系统控制器 +│ ├── RegisterController.java # 注册功能控制器 +│ ├── EmailService.java # 邮件服务类 │ ├── Question.java # 选择题数据模型 │ └── ChoiceQuestionGenerator.java # 选择题生成器 ├── src/main/resources/com/example/mathsystemtogether/ -│ └── exam-view.fxml # 考试界面布局文件 +│ ├── exam-view.fxml # 考试界面布局文件 +│ └── register-view.fxml # 注册界面布局文件 +├── src/main/resources/ +│ └── mail.properties # 邮件服务配置文件 +├── user_data.txt # 用户数据存储文件 ├── papers/ # 题目文件存储目录 │ ├── 张三1/ # 用户文件夹 │ ├── 李四1/ @@ -140,6 +190,12 @@ MathSystemTogether/ ## 🔧 核心功能 +### 用户管理功能 +- **用户注册**:支持新用户注册,包含邮箱验证 +- **用户登录**:支持预设账号和注册账号登录 +- **数据存储**:用户信息保存在本地文件中 +- **数据验证**:用户名唯一性、邮箱格式验证 + ### 题目生成算法 - **小学**:基础四则运算(+、-、×、÷) - **初中**:平方运算(²)、开方运算(√) @@ -156,6 +212,14 @@ MathSystemTogether/ - 进度实时更新 - 结果自动统计 +### 邮箱验证功能 +- **真实邮件发送**:通过SMTP服务器发送验证码邮件 +- **验证码生成**:6位数字随机验证码 +- **时效控制**:验证码5分钟有效期 +- **防重复发送**:60秒倒计时限制 +- **格式验证**:邮箱地址格式检查 +- **HTML邮件**:美观的HTML格式验证码邮件 + ## 📊 考试结果 系统会显示: diff --git a/pom.xml b/pom.xml index 579e6ad..7ba6d4d 100644 --- a/pom.xml +++ b/pom.xml @@ -61,6 +61,14 @@ 21 + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + com.example.mathsystemtogether.HelloApplication + + org.openjfx javafx-maven-plugin diff --git a/run_gui.bat b/run_gui.bat index c9ec487..c25cf96 100644 --- a/run_gui.bat +++ b/run_gui.bat @@ -7,11 +7,22 @@ echo 系统功能: echo - 支持小学、初中、高中三个难度级别 echo - 选择题形式答题 echo - 自动评分和结果统计 +echo - 用户注册功能(邮箱验证码) +echo - 本地用户数据存储 echo. echo 测试账号: echo - 小学:张三1/123, 张三2/123, 张三3/123 echo - 初中:李四1/123, 李四2/123, 李四3/123 echo - 高中:王五1/123, 王五2/123, 王五3/123 echo. +echo 新用户注册: +echo - 点击"注册"按钮创建新账户 +echo - 使用邮箱获取验证码 +echo - 选择适合的难度级别 +echo. +echo 邮件服务配置: +echo - 已配置QQ邮箱:1961004835@qq.com +echo - 配置文件:src/main/resources/mail.properties +echo. mvn exec:java -Dexec.mainClass="com.example.mathsystemtogether.HelloApplication" pause diff --git a/src/main/java/com/example/mathsystemtogether/EmailCodeService.java b/src/main/java/com/example/mathsystemtogether/EmailCodeService.java deleted file mode 100644 index 0bdf163..0000000 --- a/src/main/java/com/example/mathsystemtogether/EmailCodeService.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.example.mathsystemtogether; - -import java.time.Duration; -import java.time.Instant; -import java.util.Map; -import java.util.Properties; -import java.util.Random; -import java.util.concurrent.ConcurrentHashMap; -import jakarta.mail.Authenticator; -import jakarta.mail.Message; -import jakarta.mail.MessagingException; -import jakarta.mail.PasswordAuthentication; -import jakarta.mail.Session; -import jakarta.mail.Transport; -import jakarta.mail.internet.InternetAddress; -import jakarta.mail.internet.MimeMessage; - -/** - * 简单的内存版邮箱验证码服务(单进程适用)。 - * 如需真实发信,可将 sendEmail 方法接入 SMTP 或第三方服务。 - */ -public class EmailCodeService { - - private static class CodeRecord { - final String code; - final Instant expireAt; - - CodeRecord(String code, Instant expireAt) { - this.code = code; - this.expireAt = expireAt; - } - } - - private final Map emailToCode = new ConcurrentHashMap<>(); - private final Map emailToLastSend = new ConcurrentHashMap<>(); - private final Random random = new Random(); - - private final Duration codeTtl = Duration.ofMinutes(5); - private final Duration rateLimit = Duration.ofSeconds(60); - - public void sendCode(String email) { - Instant now = Instant.now(); - Instant last = emailToLastSend.get(email); - if (last != null && Duration.between(last, now).compareTo(rateLimit) < 0) { - long waitSeconds = rateLimit.minus(Duration.between(last, now)).getSeconds(); - throw new IllegalStateException("请求过于频繁,请于" + waitSeconds + "秒后重试"); - } - - String code = generateCode(); - emailToCode.put(email, new CodeRecord(code, now.plus(codeTtl))); - emailToLastSend.put(email, now); - - // 使用 SMTP 发送邮件(QQ邮箱) - sendEmail(email, code); - } - - public boolean verifyCode(String email, String code) { - CodeRecord record = emailToCode.get(email); - if (record == null) return false; - if (Instant.now().isAfter(record.expireAt)) { - emailToCode.remove(email); - return false; - } - boolean ok = record.code.equals(code); - if (ok) { - emailToCode.remove(email); // 一次性 - } - return ok; - } - - private String generateCode() { - return String.valueOf(100000 + random.nextInt(900000)); - } - - private void sendEmail(String email, String code) { - // 从资源文件读取发件配置 - Properties conf = new Properties(); - try { - conf.load(EmailCodeService.class.getResourceAsStream("/com/example/mathsystemtogether/mail.properties")); - } catch (Exception e) { - System.out.println("[EmailCodeService] 读取 mail.properties 失败,改为控制台输出验证码:" + code); - return; - } - - String from = conf.getProperty("mail.from", ""); - String authCode = conf.getProperty("mail.authCode", ""); - String host = conf.getProperty("mail.host", "smtp.qq.com"); - String port = conf.getProperty("mail.port", "465"); - boolean ssl = Boolean.parseBoolean(conf.getProperty("mail.ssl", "true")); - String subject = conf.getProperty("mail.subject", "您的验证码"); - String bodyPrefix = conf.getProperty("mail.bodyPrefix", "验证码:"); - String bodySuffix = conf.getProperty("mail.bodySuffix", ",5分钟内有效。"); - - if (from.isEmpty() || authCode.isEmpty()) { - System.out.println("[EmailCodeService] 未配置 mail.from 或 mail.authCode,改为控制台输出验证码:" + code); - return; - } - - Properties props = new Properties(); - props.put("mail.smtp.host", host); - props.put("mail.smtp.port", port); - props.put("mail.smtp.auth", "true"); - props.put("mail.smtp.ssl.enable", String.valueOf(ssl)); - - Session session = Session.getInstance(props, new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication(from, authCode); - } - }); - - try { - Message message = new MimeMessage(session); - message.setFrom(new InternetAddress(from)); - message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(email)); - message.setSubject(subject); - message.setText(bodyPrefix + code + bodySuffix); - Transport.send(message); - } catch (MessagingException e) { - throw new IllegalStateException("邮件发送失败:" + e.getMessage(), e); - } - } -} - - diff --git a/src/main/java/com/example/mathsystemtogether/ExamController.java b/src/main/java/com/example/mathsystemtogether/ExamController.java index c994773..cb60676 100644 --- a/src/main/java/com/example/mathsystemtogether/ExamController.java +++ b/src/main/java/com/example/mathsystemtogether/ExamController.java @@ -8,35 +8,22 @@ import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import java.time.Instant; import java.util.*; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; /** * 考试系统控制器 */ public class ExamController { - @FXML private VBox registerPanel; - @FXML private TextField registerUsernameField; - @FXML private PasswordField registerPasswordField; - @FXML private TextField registerEmailField; - @FXML private TextField registerCodeField; - @FXML private Button sendRegisterCodeButton; - @FXML private Button verifyRegisterCodeButton; - @FXML private Label registerStatusLabel; - // 登录界面控件 @FXML private TextField usernameField; @FXML private PasswordField passwordField; @FXML private Button loginButton; - @FXML private TextField emailField; - @FXML private TextField emailCodeField; - @FXML private Button sendCodeButton; - @FXML private Button verifyCodeButton; - @FXML private Label emailStatusLabel; - @FXML private Label loginStatusLabel; @FXML private Button registerButton; - + @FXML private Label loginStatusLabel; // 考试设置界面控件 @FXML private VBox examSetupPanel; @@ -47,36 +34,12 @@ public class ExamController { @FXML private Button logoutButton; @FXML private Label statusLabel; - // 添加设置密码面板相关控件引用(需要在FXML中添加对应控件) - @FXML private VBox setPasswordPanel; - @FXML private PasswordField setPasswordField; - @FXML private PasswordField confirmPasswordField; - @FXML private Button confirmSetPasswordButton; - @FXML private Label setPasswordStatusLabel; - - // 添加修改密码面板相关控件引用 - @FXML private VBox changePasswordPanel; - @FXML private PasswordField oldPasswordField; - @FXML private PasswordField newPasswordField; - @FXML private PasswordField confirmNewPasswordField; - @FXML private Button confirmChangePasswordButton; - @FXML private Button cancelChangePasswordButton; - @FXML private Label changePasswordStatusLabel; - - // 添加修改密码按钮引用 - @FXML private Button changePasswordButton; // 数据成员 private Account currentAccount; private List examQuestions; - private int currentQuestionIndex = 0; - private Map userAnswers = new HashMap<>(); private ChoiceQuestionGenerator questionGenerator; private final Map userMap = new HashMap<>(); - private final EmailCodeService emailCodeService = new EmailCodeService(); - private boolean emailVerified = false; - private final Map pendingRegistrations = new HashMap<>(); - - + private static final String USER_DATA_FILE = "user_data.txt"; // 常量定义 private static final int MIN_QUESTIONS = 5; @@ -85,344 +48,12 @@ public class ExamController { @FXML public void initialize() { initAccounts(); + loadUserDataFromFile(); setupLevelComboBox(); examSetupPanel.setVisible(false); questionCountField.setText("10"); - - if (registerPanel != null) { - registerPanel.setVisible(false); - } - if (setPasswordPanel != null) { - setPasswordPanel.setVisible(false); - } - if (changePasswordPanel != null) { - changePasswordPanel.setVisible(false); - } - } - // 添加内部类用于存储注册信息 - static class RegisterInfo { - final String username; - String password; - final String email; - final String registerCode; - final Instant expireTime; - boolean codeVerified; - - RegisterInfo(String username, String password, String email, String registerCode) { - this.username = username; - this.password = password; - this.email = email; - this.registerCode = registerCode; - this.expireTime = Instant.now().plusSeconds(300); // 5分钟有效期 - this.codeVerified = false; - } - - public boolean isExpired() { - return Instant.now().isAfter(expireTime); - } - } - - -@FXML -private void handleVerifyRegisterCode() { - String email = registerEmailField.getText().trim(); - String code = registerCodeField.getText().trim(); - - if (email.isEmpty() || code.isEmpty()) { - registerStatusLabel.setText("请填写邮箱和验证码"); - registerStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - // 使用邮箱验证码服务验证 - boolean isValid = emailCodeService.verifyCode(email, code); - - if (isValid) { - // 检查是否有待处理的注册信息 - RegisterInfo registerInfo = pendingRegistrations.get(email); - if (registerInfo != null) { - registerInfo.codeVerified = true; - registerStatusLabel.setText("验证码验证成功,请设置密码"); - registerStatusLabel.setStyle("-fx-text-fill: green;"); - - // 显示设置密码面板 - if (setPasswordPanel != null) { - setPasswordPanel.setVisible(true); - } - } else { - registerStatusLabel.setText("注册信息丢失,请重新注册"); - registerStatusLabel.setStyle("-fx-text-fill: red;"); - } - } else { - registerStatusLabel.setText("验证码错误或已过期"); - registerStatusLabel.setStyle("-fx-text-fill: red;"); - } -} - - - - @FXML - private void showRegisterPanel() { - if (registerPanel != null) { - registerPanel.setVisible(true); - } - } - - @FXML - private void hideRegisterPanel() { - // 隐藏注册面板 - if (registerPanel != null) { - registerPanel.setVisible(false); - } - - // 显示登录面板相关组件 - if (usernameField != null) usernameField.setVisible(true); - if (passwordField != null) passwordField.setVisible(true); - if (emailField != null) emailField.setVisible(true); - if (emailCodeField != null) emailCodeField.setVisible(true); - if (sendCodeButton != null) sendCodeButton.setVisible(true); - if (verifyCodeButton != null) verifyCodeButton.setVisible(true); - if (loginButton != null) loginButton.setVisible(true); - if (emailStatusLabel != null) emailStatusLabel.setVisible(true); - if (loginStatusLabel != null) loginStatusLabel.setVisible(true); - - // 清空注册相关字段 - if (registerUsernameField != null) registerUsernameField.clear(); - if (registerEmailField != null) registerEmailField.clear(); - if (registerCodeField != null) registerCodeField.clear(); - if (registerStatusLabel != null) registerStatusLabel.setText(""); - } - @FXML - private void showSetPasswordPanel() { - if (setPasswordPanel != null) { - setPasswordPanel.setVisible(true); - } - } - - /** - * 隐藏设置密码面板 - */ - @FXML - private void hideSetPasswordPanel() { - if (setPasswordPanel != null) { - setPasswordPanel.setVisible(false); - } - } - - /** - * 确认设置密码 - */ - @FXML -private void handleSetPassword() { - String password = setPasswordField.getText(); - String confirmPassword = confirmPasswordField.getText(); - - if (password.isEmpty() || confirmPassword.isEmpty()) { - setPasswordStatusLabel.setText("请输入密码"); - setPasswordStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - if (!password.equals(confirmPassword)) { - setPasswordStatusLabel.setText("两次输入的密码不一致"); - setPasswordStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - if (!isValidPassword(password)) { - setPasswordStatusLabel.setText("密码必须为6-10位,包含大小写字母和数字"); - setPasswordStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - // 获取邮箱(从注册邮箱字段) - String email = registerEmailField.getText().trim(); - RegisterInfo registerInfo = pendingRegistrations.get(email); - - if (registerInfo != null) { - // 更新注册信息中的密码 - registerInfo.password = password; - - // 完成注册 - userMap.put(registerInfo.username, new Account(registerInfo.username, password, Level.小学)); - pendingRegistrations.remove(email); - - setPasswordStatusLabel.setText("注册成功!可以使用新账号登录"); - setPasswordStatusLabel.setStyle("-fx-text-fill: green;"); - - // 清空所有注册相关输入框 - registerUsernameField.clear(); - registerEmailField.clear(); - registerCodeField.clear(); - setPasswordField.clear(); - confirmPasswordField.clear(); - - // 隐藏面板 - if (setPasswordPanel != null) { - setPasswordPanel.setVisible(false); - } - if (registerPanel != null) { - registerPanel.setVisible(false); - } - - // 显示登录面板 - hideRegisterPanel(); - } else { - setPasswordStatusLabel.setText("注册信息丢失,请重新注册"); - setPasswordStatusLabel.setStyle("-fx-text-fill: red;"); } -} -// 添加注册按钮事件处理方法 -@FXML -private void handleRegisterUser() { - String username = registerUsernameField.getText().trim(); - String email = registerEmailField.getText().trim(); - - if (username.isEmpty() || email.isEmpty()) { - registerStatusLabel.setText("请填写用户名和邮箱"); - registerStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - if (userMap.containsKey(username)) { - registerStatusLabel.setText("用户名已存在"); - registerStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - try { - // 发送注册验证码 - emailCodeService.sendCode(email); - - // 生成验证码并创建注册信息(密码将在后续设置) - String tempPassword = ""; // 临时空密码 - RegisterInfo registerInfo = new RegisterInfo(username, tempPassword, email, ""); - pendingRegistrations.put(email, registerInfo); - - registerStatusLabel.setText("注册验证码已发送到邮箱,请查收"); - registerStatusLabel.setStyle("-fx-text-fill: green;"); - } catch (Exception e) { - registerStatusLabel.setText("发送验证码失败:" + e.getMessage()); - registerStatusLabel.setStyle("-fx-text-fill: red;"); - } -} - - - /** - * 显示修改密码面板 - */ - @FXML - private void showChangePasswordPanel() { - if (changePasswordPanel != null && currentAccount != null) { - changePasswordPanel.setVisible(true); - changePasswordPanel.toFront(); - } - } - - /** - * 隐藏修改密码面板 - */ - @FXML - private void hideChangePasswordPanel() { - if (changePasswordPanel != null) { - changePasswordPanel.setVisible(false); - // 清空输入框 - oldPasswordField.clear(); - newPasswordField.clear(); - confirmNewPasswordField.clear(); - changePasswordStatusLabel.setText(""); - } - } - - /** - * 确认修改密码 - */ - @FXML - private void handleChangePassword() { - if (currentAccount == null) { - changePasswordStatusLabel.setText("请先登录"); - changePasswordStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - String oldPassword = oldPasswordField.getText(); - String newPassword = newPasswordField.getText(); - String confirmNewPassword = confirmNewPasswordField.getText(); - - if (oldPassword.isEmpty() || newPassword.isEmpty() || confirmNewPassword.isEmpty()) { - changePasswordStatusLabel.setText("请填写所有字段"); - changePasswordStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - // 验证原密码 - if (!currentAccount.password.equals(oldPassword)) { - changePasswordStatusLabel.setText("原密码错误"); - changePasswordStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - // 验证新密码一致性 - if (!newPassword.equals(confirmNewPassword)) { - changePasswordStatusLabel.setText("新密码两次输入不一致"); - changePasswordStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - // 验证新密码强度 - if (!isValidPassword(newPassword)) { - changePasswordStatusLabel.setText("新密码必须为6-10位,包含大小写字母和数字"); - changePasswordStatusLabel.setStyle("-fx-text-fill: red;"); - return; - } - - // 更新密码 - Account account = userMap.get(currentAccount.username); - if (account != null) { - account.password = newPassword; // 注意:需要修改Account类使password可修改 - currentAccount.password = newPassword; - changePasswordStatusLabel.setText("密码修改成功"); - changePasswordStatusLabel.setStyle("-fx-text-fill: green;"); - - // 清空输入框 - oldPasswordField.clear(); - newPasswordField.clear(); - confirmNewPasswordField.clear(); - - // 隐藏面板 - hideChangePasswordPanel(); - } - } - - /** - * 验证密码强度 - * @param password 密码 - * @return 是否符合要求 - */ - private boolean isValidPassword(String password) { - // 长度检查 - if (password.length() < 6 || password.length() > 10) { - return false; - } - - // 检查是否包含大小写字母和数字 - boolean hasUpper = false; - boolean hasLower = false; - boolean hasDigit = false; - - for (char c : password.toCharArray()) { - if (Character.isUpperCase(c)) { - hasUpper = true; - } else if (Character.isLowerCase(c)) { - hasLower = true; - } else if (Character.isDigit(c)) { - hasDigit = true; - } - } - - return hasUpper && hasLower && hasDigit; - } private void initAccounts() { // 小学三个账号 userMap.put("张三1", new Account("张三1", "123", Level.小学)); @@ -444,6 +75,34 @@ private void handleRegisterUser() { 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() { @@ -464,28 +123,39 @@ private void handleRegisterUser() { 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); + registerStage.show(); + + } catch (Exception e) { + loginStatusLabel.setText("打开注册界面失败:" + e.getMessage()); + loginStatusLabel.setStyle("-fx-text-fill: red;"); + } + } + @FXML private void handleLogout() { currentAccount = null; examQuestions = null; - currentQuestionIndex = 0; - userAnswers.clear(); examSetupPanel.setVisible(false); usernameField.clear(); passwordField.clear(); loginStatusLabel.setText(""); statusLabel.setText(""); - emailVerified = false; - if (emailField != null) emailField.clear(); - if (emailCodeField != null) emailCodeField.clear(); - if (emailStatusLabel != null) emailStatusLabel.setText(""); } @FXML @@ -508,8 +178,6 @@ private void handleRegisterUser() { String selectedLevel = levelComboBox.getValue(); ChoiceQuestionGenerator.Level level = ChoiceQuestionGenerator.Level.valueOf(selectedLevel); - - // 生成考试题目 questionGenerator = new ChoiceQuestionGenerator(); examQuestions = questionGenerator.generateQuestions(level, count); @@ -529,10 +197,6 @@ private void handleRegisterUser() { } } - - - - private void startExam() { try { // 打开专门的考试界面 @@ -560,7 +224,6 @@ private void handleRegisterUser() { } } - // 内部类 static class Account { final String username; @@ -577,4 +240,4 @@ private void handleRegisterUser() { enum Level { 小学, 初中, 高中 } -} +} \ No newline at end of file diff --git a/src/main/resources/com/example/mathsystemtogether/exam-view.fxml b/src/main/resources/com/example/mathsystemtogether/exam-view.fxml index 265d79f..7f86954 100644 --- a/src/main/resources/com/example/mathsystemtogether/exam-view.fxml +++ b/src/main/resources/com/example/mathsystemtogether/exam-view.fxml @@ -57,7 +57,7 @@