v2.0 #2

Merged
hnu202326010125 merged 1 commits from zhanghongwei_branch into develop 3 months ago

@ -0,0 +1 @@
MathLearningApp.java

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="ReplaceRangeToWithRangeUntil" enabled="true" level="WEAK WARNING" enabled_by_default="true" />
</profile>
</component>

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_23" default="true" project-jdk-name="21" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

@ -11,15 +11,18 @@ import java.util.Map;
// 用户类
class User {
private String username;
private String email;
private String password;
private String verificationCode;
public User(String email, String password) {
public User(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
public String getUsername() { return username; }
public String getEmail() { return email; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
@ -245,27 +248,36 @@ class EmailUtil {
// 用户管理类
class UserManager {
private Map<String, User> users;
private Map<String, User> usersByEmail;
private Map<String, User> usersByUsername;
public UserManager() {
users = new HashMap<>();
usersByEmail = new HashMap<>();
usersByUsername = new HashMap<>();
// 添加一些测试用户
users.put("test@test.com", new User("test@test.com", "Test123"));
users.put("user@example.com", new User("user@example.com", "User123"));
addUser("测试用户", "test@test.com", "Test123");
addUser("示例用户", "user@example.com", "User123");
}
public boolean registerUser(String email, String password) {
if (users.containsKey(email)) {
private void addUser(String username, String email, String password) {
User user = new User(username, email, password);
usersByEmail.put(email, user);
usersByUsername.put(username, user);
}
public boolean registerUser(String username, String email, String password) {
if (usersByEmail.containsKey(email) || usersByUsername.containsKey(username)) {
return false;
}
User user = new User(email, password);
users.put(email, user);
User user = new User(username, email, password);
usersByEmail.put(email, user);
usersByUsername.put(username, user);
return true;
}
public User login(String email, String password) {
User user = users.get(email);
User user = usersByEmail.get(email);
if (user != null && user.getPassword().equals(password)) {
return user;
}
@ -273,7 +285,7 @@ class UserManager {
}
public boolean updatePassword(String email, String oldPassword, String newPassword) {
User user = users.get(email);
User user = usersByEmail.get(email);
if (user != null && user.getPassword().equals(oldPassword)) {
user.setPassword(newPassword);
return true;
@ -282,7 +294,11 @@ class UserManager {
}
public boolean isEmailRegistered(String email) {
return users.containsKey(email);
return usersByEmail.containsKey(email);
}
public boolean isUsernameRegistered(String username) {
return usersByUsername.containsKey(username);
}
}
@ -304,6 +320,7 @@ public class MathLearningApp {
private ButtonGroup optionGroup;
private JRadioButton[] optionButtons;
private JLabel scoreLabel;
private JLabel welcomeLabel;
public MathLearningApp() {
userManager = new UserManager();
@ -313,7 +330,7 @@ public class MathLearningApp {
private void initializeUI() {
mainFrame = new JFrame("数学学习软件");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setSize(500, 400);
mainFrame.setSize(600, 500);
mainFrame.setLocationRelativeTo(null);
cardLayout = new CardLayout();
@ -335,46 +352,66 @@ public class MathLearningApp {
private void createLoginPanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.insets = new Insets(15, 15, 15, 15);
gbc.fill = GridBagConstraints.HORIZONTAL;
JLabel titleLabel = new JLabel("用户登录", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
JLabel titleLabel = new JLabel("数学学习软件", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
titleLabel.setForeground(new Color(0, 100, 200));
gbc.gridx = 0; gbc.gridy = 0; gbc.gridwidth = 2;
panel.add(titleLabel, gbc);
JLabel subtitleLabel = new JLabel("用户登录", JLabel.CENTER);
subtitleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
subtitleLabel.setForeground(Color.GRAY);
gbc.gridy = 1;
panel.add(subtitleLabel, gbc);
gbc.gridwidth = 1;
gbc.gridy = 1; gbc.gridx = 0;
panel.add(new JLabel("邮箱:"), gbc);
gbc.gridy = 2; gbc.gridx = 0;
JLabel emailLabel = new JLabel("邮箱:");
emailLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
panel.add(emailLabel, gbc);
gbc.gridx = 1;
emailField = new JTextField(20);
emailField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
panel.add(emailField, gbc);
gbc.gridy = 2; gbc.gridx = 0;
panel.add(new JLabel("密码:"), gbc);
gbc.gridy = 3; gbc.gridx = 0;
JLabel passwordLabel = new JLabel("密码:");
passwordLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
panel.add(passwordLabel, gbc);
gbc.gridx = 1;
passwordField = new JPasswordField(20);
passwordField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
panel.add(passwordField, gbc);
gbc.gridy = 3; gbc.gridx = 0; gbc.gridwidth = 2;
gbc.gridy = 4; gbc.gridx = 0; gbc.gridwidth = 2;
JPanel buttonPanel = new JPanel(new FlowLayout());
JButton loginButton = new JButton("登录");
JButton loginButton = createStyledButton("登录", new Color(70, 130, 180));
loginButton.addActionListener(e -> handleLogin());
buttonPanel.add(loginButton);
JButton registerButton = new JButton("注册");
JButton registerButton = createStyledButton("注册", new Color(60, 179, 113));
registerButton.addActionListener(e -> cardLayout.show(mainPanel, "Register"));
buttonPanel.add(registerButton);
JButton changePasswordButton = new JButton("修改密码");
JButton changePasswordButton = createStyledButton("修改密码", new Color(218, 165, 32));
changePasswordButton.addActionListener(e -> cardLayout.show(mainPanel, "ChangePassword"));
buttonPanel.add(changePasswordButton);
panel.add(buttonPanel, gbc);
// 添加测试账号提示
gbc.gridy = 5;
JLabel testAccountLabel = new JLabel("测试账号: test@test.com / Test123", JLabel.CENTER);
testAccountLabel.setFont(new Font("微软雅黑", Font.ITALIC, 12));
testAccountLabel.setForeground(Color.GRAY);
panel.add(testAccountLabel, gbc);
mainPanel.add(panel, "Login");
}
@ -391,38 +428,52 @@ public class MathLearningApp {
gbc.gridwidth = 1;
gbc.gridy = 1; gbc.gridx = 0;
panel.add(new JLabel("用户名:"), gbc);
gbc.gridx = 1;
JTextField usernameField = new JTextField(20);
panel.add(usernameField, gbc);
gbc.gridy = 2; gbc.gridx = 0;
panel.add(new JLabel("邮箱:"), gbc);
gbc.gridx = 1;
JTextField registerEmailField = new JTextField(20);
panel.add(registerEmailField, gbc);
gbc.gridy = 2; gbc.gridx = 0; gbc.gridwidth = 2;
JButton sendCodeButton = new JButton("发送验证码");
gbc.gridy = 3; gbc.gridx = 0; gbc.gridwidth = 2;
JButton sendCodeButton = createStyledButton("发送验证码", new Color(70, 130, 180));
panel.add(sendCodeButton, gbc);
gbc.gridwidth = 1;
gbc.gridy = 3; gbc.gridx = 0;
gbc.gridy = 4; gbc.gridx = 0;
panel.add(new JLabel("验证码:"), gbc);
gbc.gridx = 1;
JTextField registerCodeField = new JTextField(20);
panel.add(registerCodeField, gbc);
gbc.gridy = 4; gbc.gridx = 0; gbc.gridwidth = 2;
JButton registerButton = new JButton("注册");
gbc.gridy = 5; gbc.gridx = 0; gbc.gridwidth = 2;
JButton registerButton = createStyledButton("注册", new Color(60, 179, 113));
registerButton.addActionListener(e -> {
String username = usernameField.getText();
String email = registerEmailField.getText();
String code = registerCodeField.getText();
if (email.isEmpty() || code.isEmpty()) {
JOptionPane.showMessageDialog(panel, "请填写邮箱和验证码");
if (username.isEmpty() || email.isEmpty() || code.isEmpty()) {
JOptionPane.showMessageDialog(panel, "请填写所有信息");
return;
}
if (userManager.isUsernameRegistered(username)) {
JOptionPane.showMessageDialog(panel, "用户名已被使用");
return;
}
// 验证验证码简化处理只要6位就通过
if (code.length() == 6) {
// 保存邮箱信息用于后续设置密码
// 保存用户信息用于后续设置密码
mainPanel.putClientProperty("registerUsername", username);
mainPanel.putClientProperty("registerEmail", email);
cardLayout.show(mainPanel, "SetPassword");
} else {
@ -431,13 +482,25 @@ public class MathLearningApp {
});
panel.add(registerButton, gbc);
gbc.gridy = 5;
JButton backButton = new JButton("返回登录");
gbc.gridy = 6;
JButton backButton = createStyledButton("返回登录", new Color(169, 169, 169));
backButton.addActionListener(e -> cardLayout.show(mainPanel, "Login"));
panel.add(backButton, gbc);
sendCodeButton.addActionListener(e -> {
String username = usernameField.getText();
String email = registerEmailField.getText();
if (username.isEmpty() || email.isEmpty()) {
JOptionPane.showMessageDialog(panel, "请填写用户名和邮箱");
return;
}
if (userManager.isUsernameRegistered(username)) {
JOptionPane.showMessageDialog(panel, "用户名已被使用");
return;
}
if (isValidEmail(email)) {
if (userManager.isEmailRegistered(email)) {
JOptionPane.showMessageDialog(panel, "该邮箱已被注册");
@ -485,14 +548,15 @@ public class MathLearningApp {
panel.add(confirmSetPasswordField, gbc);
gbc.gridy = 3; gbc.gridx = 0; gbc.gridwidth = 2;
JButton setPasswordButton = new JButton("设置密码");
JButton setPasswordButton = createStyledButton("设置密码", new Color(60, 179, 113));
setPasswordButton.addActionListener(e -> {
String password = new String(setPasswordField.getPassword());
String confirmPassword = new String(confirmSetPasswordField.getPassword());
String username = (String) mainPanel.getClientProperty("registerUsername");
String email = (String) mainPanel.getClientProperty("registerEmail");
if (validatePassword(password, confirmPassword)) {
if (userManager.registerUser(email, password)) {
if (userManager.registerUser(username, email, password)) {
JOptionPane.showMessageDialog(panel, "注册成功!");
cardLayout.show(mainPanel, "Login");
} else {
@ -506,24 +570,37 @@ public class MathLearningApp {
}
private void createLevelSelectionPanel() {
JPanel panel = new JPanel(new GridLayout(4, 1, 10, 10));
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
panel.setBackground(new Color(240, 248, 255));
JLabel titleLabel = new JLabel("选择学习阶段", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
panel.add(titleLabel);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
titleLabel.setForeground(new Color(0, 100, 200));
panel.add(titleLabel, BorderLayout.NORTH);
welcomeLabel = new JLabel("", JLabel.CENTER);
welcomeLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
welcomeLabel.setForeground(Color.DARK_GRAY);
panel.add(welcomeLabel, BorderLayout.CENTER);
JButton primaryButton = new JButton("小学");
JPanel buttonPanel = new JPanel(new GridLayout(3, 1, 20, 20));
buttonPanel.setBorder(BorderFactory.createEmptyBorder(20, 50, 20, 50));
buttonPanel.setBackground(new Color(240, 248, 255));
JButton primaryButton = createLevelButton("小学", new Color(135, 206, 250));
primaryButton.addActionListener(e -> startExam("小学"));
panel.add(primaryButton);
buttonPanel.add(primaryButton);
JButton juniorButton = new JButton("初中");
JButton juniorButton = createLevelButton("初中", new Color(100, 149, 237));
juniorButton.addActionListener(e -> startExam("初中"));
panel.add(juniorButton);
buttonPanel.add(juniorButton);
JButton seniorButton = new JButton("高中");
JButton seniorButton = createLevelButton("高中", new Color(65, 105, 225));
seniorButton.addActionListener(e -> startExam("高中"));
panel.add(seniorButton);
buttonPanel.add(seniorButton);
panel.add(buttonPanel, BorderLayout.SOUTH);
mainPanel.add(panel, "LevelSelection");
}
@ -531,7 +608,7 @@ public class MathLearningApp {
private void createQuestionCountPanel() {
JPanel panel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
gbc.insets = new Insets(15, 15, 15, 15);
JLabel titleLabel = new JLabel("请输入题目数量", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
@ -539,10 +616,17 @@ public class MathLearningApp {
panel.add(titleLabel, gbc);
JTextField countField = new JTextField(10);
countField.setFont(new Font("微软雅黑", Font.PLAIN, 16));
gbc.gridy = 1;
panel.add(countField, gbc);
JButton startButton = new JButton("开始答题");
JLabel hintLabel = new JLabel("(建议5-20题)", JLabel.CENTER);
hintLabel.setFont(new Font("微软雅黑", Font.ITALIC, 12));
hintLabel.setForeground(Color.GRAY);
gbc.gridy = 2;
panel.add(hintLabel, gbc);
JButton startButton = createStyledButton("开始答题", new Color(60, 179, 113));
startButton.addActionListener(e -> {
try {
int count = Integer.parseInt(countField.getText());
@ -556,7 +640,7 @@ public class MathLearningApp {
JOptionPane.showMessageDialog(panel, "请输入有效的数字");
}
});
gbc.gridy = 2;
gbc.gridy = 3;
panel.add(startButton, gbc);
mainPanel.add(panel, "QuestionCount");
@ -565,24 +649,31 @@ public class MathLearningApp {
private void createExamPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
panel.setBackground(new Color(240, 248, 255));
questionLabel = new JLabel("", JLabel.CENTER);
questionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 16));
questionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18));
questionLabel.setBorder(BorderFactory.createEmptyBorder(10, 10, 20, 10));
panel.add(questionLabel, BorderLayout.NORTH);
JPanel optionsPanel = new JPanel(new GridLayout(4, 1, 10, 10));
JPanel optionsPanel = new JPanel(new GridLayout(4, 1, 15, 15));
optionsPanel.setBorder(BorderFactory.createEmptyBorder(20, 50, 20, 50));
optionsPanel.setBackground(new Color(240, 248, 255));
optionGroup = new ButtonGroup();
optionButtons = new JRadioButton[4];
for (int i = 0; i < 4; i++) {
optionButtons[i] = new JRadioButton();
optionButtons[i].setFont(new Font("微软雅黑", Font.PLAIN, 16));
optionButtons[i].setBackground(new Color(240, 248, 255));
optionGroup.add(optionButtons[i]);
optionsPanel.add(optionButtons[i]);
}
panel.add(optionsPanel, BorderLayout.CENTER);
JButton submitButton = new JButton("提交答案");
JButton submitButton = createStyledButton("提交答案", new Color(70, 130, 180));
submitButton.addActionListener(e -> handleAnswerSubmission());
panel.add(submitButton, BorderLayout.SOUTH);
@ -591,19 +682,26 @@ public class MathLearningApp {
private void createScorePanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
panel.setBorder(BorderFactory.createEmptyBorder(40, 40, 40, 40));
panel.setBackground(new Color(240, 248, 255));
JLabel titleLabel = new JLabel("答题完成", JLabel.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 28));
titleLabel.setForeground(new Color(0, 100, 200));
panel.add(titleLabel, BorderLayout.NORTH);
scoreLabel = new JLabel("", JLabel.CENTER);
scoreLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
scoreLabel.setFont(new Font("微软雅黑", Font.BOLD, 36));
scoreLabel.setForeground(new Color(220, 20, 60));
panel.add(scoreLabel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout());
JButton continueButton = new JButton("继续做题");
JButton continueButton = createStyledButton("继续做题", new Color(60, 179, 113));
continueButton.addActionListener(e -> cardLayout.show(mainPanel, "LevelSelection"));
buttonPanel.add(continueButton);
JButton exitButton = new JButton("退出");
JButton exitButton = createStyledButton("退出登录", new Color(205, 92, 92));
exitButton.addActionListener(e -> {
currentUser = null;
cardLayout.show(mainPanel, "Login");
@ -658,7 +756,7 @@ public class MathLearningApp {
gbc.gridy = 5; gbc.gridx = 0; gbc.gridwidth = 2;
JPanel buttonPanel = new JPanel(new FlowLayout());
JButton changeButton = new JButton("修改密码");
JButton changeButton = createStyledButton("修改密码", new Color(60, 179, 113));
changeButton.addActionListener(e -> {
String email = changePasswordEmailField.getText();
String oldPassword = new String(oldPasswordField.getPassword());
@ -676,7 +774,7 @@ public class MathLearningApp {
});
buttonPanel.add(changeButton);
JButton backButton = new JButton("返回");
JButton backButton = createStyledButton("返回", new Color(169, 169, 169));
backButton.addActionListener(e -> cardLayout.show(mainPanel, "Login"));
buttonPanel.add(backButton);
@ -697,6 +795,7 @@ public class MathLearningApp {
currentUser = userManager.login(email, password);
if (currentUser != null) {
welcomeLabel.setText("欢迎, " + currentUser.getUsername() + "!");
JOptionPane.showMessageDialog(mainPanel, "登录成功!");
cardLayout.show(mainPanel, "LevelSelection");
} else {
@ -746,7 +845,8 @@ public class MathLearningApp {
private void displayCurrentQuestion() {
if (currentQuestionIndex < currentExam.size()) {
Question question = currentExam.get(currentQuestionIndex);
questionLabel.setText("题目 " + (currentQuestionIndex + 1) + "/" + currentExam.size() + ": " + question.getContent());
questionLabel.setText("<html><div style='text-align: center;'>题目 " + (currentQuestionIndex + 1) + "/" +
currentExam.size() + "<br>" + question.getContent() + "</div></html>");
String[] options = question.getOptions();
for (int i = 0; i < 4; i++) {
@ -785,12 +885,82 @@ public class MathLearningApp {
}
private void showScore() {
double percentage = (double) score / currentExam.size() * 100;
scoreLabel.setText(String.format("得分: %d/%d (%.1f%%)", score, currentExam.size(), percentage));
// 计算百分制得分
int totalQuestions = currentExam.size();
int percentScore = (int) Math.round((double) score / totalQuestions * 100);
// 根据得分设置不同的颜色和评语
String comment;
Color color;
if (percentScore >= 90) {
comment = "优秀!";
color = new Color(0, 128, 0); // 绿色
} else if (percentScore >= 80) {
comment = "良好!";
color = new Color(0, 100, 0); // 深绿色
} else if (percentScore >= 60) {
comment = "及格!";
color = new Color(218, 165, 32); // 金色
} else {
comment = "加油!";
color = new Color(220, 20, 60); // 红色
}
scoreLabel.setText("<html><div style='text-align: center;'>" +
"得分: <font color='" + getHexColor(color) + "'><b>" + percentScore + "分</b></font><br>" +
"(" + score + "/" + totalQuestions + ")<br>" +
"<font size='5'>" + comment + "</font></div></html>");
cardLayout.show(mainPanel, "Score");
}
// 工具方法
private JButton createStyledButton(String text, Color color) {
JButton button = new JButton(text);
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setBackground(color);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 20));
button.setCursor(new Cursor(Cursor.HAND_CURSOR));
// 添加鼠标悬停效果
button.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
button.setBackground(color.darker());
}
public void mouseExited(java.awt.event.MouseEvent evt) {
button.setBackground(color);
}
});
return button;
}
private JButton createLevelButton(String text, Color color) {
JButton button = new JButton(text);
button.setFont(new Font("微软雅黑", Font.BOLD, 18));
button.setBackground(color);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createEmptyBorder(15, 0, 15, 0));
button.setCursor(new Cursor(Cursor.HAND_CURSOR));
button.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
button.setBackground(color.darker());
}
public void mouseExited(java.awt.event.MouseEvent evt) {
button.setBackground(color);
}
});
return button;
}
private String getHexColor(Color color) {
return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue());
}
private boolean isValidEmail(String email) {
String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
Pattern pattern = Pattern.compile(emailRegex);

Loading…
Cancel
Save