commit
a196139e9a
@ -0,0 +1,29 @@
|
||||
### IntelliJ IDEA ###
|
||||
out/
|
||||
!**/src/main/**/out/
|
||||
!**/src/test/**/out/
|
||||
|
||||
### Eclipse ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
bin/
|
||||
!**/src/main/**/bin/
|
||||
!**/src/test/**/bin/
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
||||
|
||||
### Mac OS ###
|
||||
.DS_Store
|
||||
@ -0,0 +1,8 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
@ -0,0 +1,5 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GoogleJavaFormatSettings">
|
||||
<option name="enabled" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="sun.mail.javax" type="repository">
|
||||
<properties maven-id="com.sun.mail:javax.mail:1.6.2" />
|
||||
<CLASSES>
|
||||
<root url="jar://$MAVEN_REPOSITORY$/com/sun/mail/javax.mail/1.6.2/javax.mail-1.6.2.jar!/" />
|
||||
<root url="jar://$MAVEN_REPOSITORY$/javax/activation/activation/1.1/activation-1.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" project-jdk-name="23" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/MathLearningSoftware.iml" filepath="$PROJECT_DIR$/MathLearningSoftware.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Palette2">
|
||||
<group name="Swing">
|
||||
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
|
||||
</item>
|
||||
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
|
||||
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
|
||||
<initial-values>
|
||||
<property name="text" value="Button" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="RadioButton" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="CheckBox" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
|
||||
<initial-values>
|
||||
<property name="text" value="Label" />
|
||||
</initial-values>
|
||||
</item>
|
||||
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
|
||||
<preferred-size width="150" height="-1" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
|
||||
<preferred-size width="150" height="50" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
|
||||
<preferred-size width="200" height="200" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
|
||||
</item>
|
||||
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
|
||||
<preferred-size width="-1" height="20" />
|
||||
</default-constraints>
|
||||
</item>
|
||||
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
|
||||
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
|
||||
</item>
|
||||
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
|
||||
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
|
||||
</item>
|
||||
</group>
|
||||
</component>
|
||||
</project>
|
||||
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="sun.mail.javax" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@ -0,0 +1,4 @@
|
||||
2023@qq.com|971458|Hsh2006|true
|
||||
202326010221@168.com|829554||false
|
||||
14498@qq.com|862004||false
|
||||
1449892469@qq.com|137032|Ly2004|true
|
||||
@ -0,0 +1,13 @@
|
||||
package com.mathlearning;
|
||||
|
||||
import com.mathlearning.view.LoginFrame;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
javax.swing.SwingUtilities.invokeLater(
|
||||
() -> {
|
||||
LoginFrame loginFrame = new LoginFrame();
|
||||
loginFrame.setVisible(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package com.mathlearning.controller;
|
||||
|
||||
public class NavigationController {
|
||||
private static NavigationController instance;
|
||||
|
||||
private NavigationController() {}
|
||||
|
||||
public static NavigationController getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new NavigationController();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void navigateToLogin() {
|
||||
System.out.println("导航到登录界面");
|
||||
}
|
||||
|
||||
public void navigateToLevelSelection() {
|
||||
System.out.println("导航到难度选择界面");
|
||||
}
|
||||
|
||||
public void navigateToQuiz() {
|
||||
System.out.println("导航到答题界面");
|
||||
}
|
||||
|
||||
public void navigateToScore() {
|
||||
System.out.println("导航到分数界面");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,77 @@
|
||||
package com.mathlearning.controller;
|
||||
|
||||
import com.mathlearning.model.Question;
|
||||
import com.mathlearning.model.QuestionGenerator;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class QuestionController {
|
||||
private QuestionGenerator questionGenerator;
|
||||
private List<Question> currentQuestions;
|
||||
private int currentQuestionIndex;
|
||||
private int score;
|
||||
private int[] userAnswers;
|
||||
|
||||
public QuestionController() {
|
||||
this.questionGenerator = new QuestionGenerator();
|
||||
}
|
||||
|
||||
public void startNewQuiz(String level, int questionCount) {
|
||||
this.currentQuestions = questionGenerator.generateQuestions(level, questionCount);
|
||||
this.currentQuestionIndex = 0;
|
||||
this.score = 0;
|
||||
this.userAnswers = new int[questionCount];
|
||||
// Initialize with -1 (no answer)
|
||||
for (int i = 0; i < userAnswers.length; i++) {
|
||||
userAnswers[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public Question getCurrentQuestion() {
|
||||
if (currentQuestions == null || currentQuestionIndex >= currentQuestions.size()) {
|
||||
return null;
|
||||
}
|
||||
return currentQuestions.get(currentQuestionIndex);
|
||||
}
|
||||
|
||||
public void submitAnswer(int answerIndex) {
|
||||
if (currentQuestionIndex < userAnswers.length) {
|
||||
userAnswers[currentQuestionIndex] = answerIndex;
|
||||
}
|
||||
|
||||
if (answerIndex != -1 && currentQuestions.get(currentQuestionIndex).isCorrect(answerIndex)) {
|
||||
score++;
|
||||
}
|
||||
|
||||
currentQuestionIndex++;
|
||||
}
|
||||
|
||||
public boolean hasNextQuestion() {
|
||||
return currentQuestions != null && currentQuestionIndex < currentQuestions.size();
|
||||
}
|
||||
|
||||
public int getCurrentQuestionNumber() {
|
||||
return currentQuestionIndex + 1;
|
||||
}
|
||||
*/
|
||||
public int getTotalQuestions() {
|
||||
return currentQuestions != null ? currentQuestions.size() : 0;
|
||||
}
|
||||
|
||||
public int getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public double getPercentage() {
|
||||
return getTotalQuestions() > 0 ? (double) score / getTotalQuestions() * 100 : 0;
|
||||
}
|
||||
|
||||
public int[] getUserAnswers() {
|
||||
return userAnswers;
|
||||
}
|
||||
|
||||
public List<Question> getCurrentQuestions() {
|
||||
return currentQuestions;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,36 @@
|
||||
package com.mathlearning.model;
|
||||
|
||||
public class Question {
|
||||
private String questionText;
|
||||
private String[] options;
|
||||
private int correctAnswerIndex;
|
||||
private String level;
|
||||
|
||||
public Question(String questionText, String[] options, int correctAnswerIndex, String level) {
|
||||
this.questionText = questionText;
|
||||
this.options = options;
|
||||
this.correctAnswerIndex = correctAnswerIndex;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public String getQuestionText() {
|
||||
return questionText;
|
||||
}
|
||||
|
||||
public String[] getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public int getCorrectAnswerIndex() {
|
||||
return correctAnswerIndex;
|
||||
}
|
||||
|
||||
public String getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public boolean isCorrect(int selectedIndex) {
|
||||
return selectedIndex == correctAnswerIndex;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
package com.mathlearning.model;
|
||||
|
||||
public class User {
|
||||
private String email;
|
||||
private String password;
|
||||
private String registrationCode;
|
||||
private boolean isRegistered;
|
||||
|
||||
public User(String email, String registrationCode) {
|
||||
this.email = email;
|
||||
this.registrationCode = registrationCode;
|
||||
this.isRegistered = false;
|
||||
this.password = null;
|
||||
}
|
||||
|
||||
// Getters and setters
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getRegistrationCode() {
|
||||
return registrationCode;
|
||||
}
|
||||
|
||||
public void setRegistrationCode(String registrationCode) {
|
||||
this.registrationCode = registrationCode;
|
||||
}
|
||||
|
||||
public boolean isRegistered() {
|
||||
return isRegistered;
|
||||
}
|
||||
|
||||
public void setRegistered(boolean registered) {
|
||||
isRegistered = registered;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
package com.mathlearning.service;
|
||||
|
||||
import com.mathlearning.model.User;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class UserService {
|
||||
private static final String USER_DATA_FILE = "data/users.txt";
|
||||
private List<User> users;
|
||||
|
||||
public UserService() {
|
||||
this.users = loadUsers();
|
||||
}
|
||||
|
||||
public boolean registerUser(String email, String registrationCode) {
|
||||
// Check if email already exists
|
||||
for (User user : users) {
|
||||
if (user.getEmail().equals(email)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
User newUser = new User(email, registrationCode);
|
||||
users.add(newUser);
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean completeRegistration(String email, String password) {
|
||||
for (User user : users) {
|
||||
if (user.getEmail().equals(email) && !user.isRegistered()) {
|
||||
user.setPassword(password);
|
||||
user.setRegistered(true);
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean login(String email, String password) {
|
||||
for (User user : users) {
|
||||
if (user.getEmail().equals(email)
|
||||
&& user.isRegistered()
|
||||
&& user.getPassword().equals(password)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean changePassword(String email, String oldPassword, String newPassword) {
|
||||
for (User user : users) {
|
||||
if (user.getEmail().equals(email) && user.getPassword().equals(oldPassword)) {
|
||||
user.setPassword(newPassword);
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public User getUserByEmail(String email) {
|
||||
for (User user : users) {
|
||||
if (user.getEmail().equals(email)) {
|
||||
return user;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean updateUser(User updatedUser) {
|
||||
for (int i = 0; i < users.size(); i++) {
|
||||
if (users.get(i).getEmail().equals(updatedUser.getEmail())) {
|
||||
users.set(i, updatedUser);
|
||||
saveUsers();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<User> loadUsers() {
|
||||
List<User> userList = new ArrayList<>();
|
||||
try {
|
||||
File file = new File(USER_DATA_FILE);
|
||||
if (!file.exists()) {
|
||||
return userList;
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(new FileReader(file));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] parts = line.split("\\|");
|
||||
if (parts.length >= 4) {
|
||||
User user = new User(parts[0], parts[1]);
|
||||
user.setPassword(parts[2]);
|
||||
user.setRegistered(Boolean.parseBoolean(parts[3]));
|
||||
userList.add(user);
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("加载用户数据失败: " + e.getMessage());
|
||||
}
|
||||
return userList;
|
||||
}
|
||||
|
||||
private void saveUsers() {
|
||||
try {
|
||||
File file = new File(USER_DATA_FILE);
|
||||
file.getParentFile().mkdirs();
|
||||
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter(file));
|
||||
for (User user : users) {
|
||||
String line =
|
||||
user.getEmail()
|
||||
+ "|"
|
||||
+ user.getRegistrationCode()
|
||||
+ "|"
|
||||
+ (user.getPassword() != null ? user.getPassword() : "")
|
||||
+ "|"
|
||||
+ user.isRegistered();
|
||||
writer.write(line);
|
||||
writer.newLine();
|
||||
}
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
System.out.println("保存用户数据失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,137 @@
|
||||
package com.mathlearning.view;
|
||||
|
||||
import com.mathlearning.controller.AuthController;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class LevelSelectionFrame extends JFrame {
|
||||
private AuthController authController;
|
||||
|
||||
public LevelSelectionFrame(AuthController authController) {
|
||||
this.authController = authController;
|
||||
initializeUI();
|
||||
}
|
||||
|
||||
private void initializeUI() {
|
||||
setTitle("数学学习软件 - 选择难度");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setSize(500, 450);
|
||||
setLocationRelativeTo(null);
|
||||
setResizable(false);
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
// 顶部按钮面板 - 包含返回登录和修改密码按钮
|
||||
JPanel topPanel = new JPanel(new BorderLayout());
|
||||
|
||||
// 左侧:返回登录按钮
|
||||
JPanel leftPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
JButton backButton = new JButton("← 返回登录");
|
||||
backButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||
backButton.setBackground(new Color(180, 180, 180));
|
||||
backButton.setForeground(Color.BLACK);
|
||||
backButton.setFocusPainted(false);
|
||||
backButton.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
|
||||
backButton.addActionListener(e -> backToLogin());
|
||||
leftPanel.add(backButton);
|
||||
|
||||
// 右侧:修改密码按钮
|
||||
JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||
JButton changePasswordButton = new JButton("修改密码");
|
||||
changePasswordButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||
changePasswordButton.setBackground(new Color(255, 165, 0));
|
||||
changePasswordButton.setForeground(Color.WHITE);
|
||||
changePasswordButton.setFocusPainted(false);
|
||||
changePasswordButton.setBorder(BorderFactory.createEmptyBorder(5, 15, 5, 15));
|
||||
changePasswordButton.addActionListener(e -> openChangePasswordDialog());
|
||||
rightPanel.add(changePasswordButton);
|
||||
|
||||
topPanel.add(leftPanel, BorderLayout.WEST);
|
||||
topPanel.add(rightPanel, BorderLayout.EAST);
|
||||
mainPanel.add(topPanel, BorderLayout.NORTH);
|
||||
|
||||
// 主内容区域
|
||||
JLabel titleLabel = new JLabel("选择学习难度", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 24));
|
||||
titleLabel.setBorder(BorderFactory.createEmptyBorder(20, 0, 30, 0));
|
||||
mainPanel.add(titleLabel, BorderLayout.CENTER);
|
||||
|
||||
JPanel buttonPanel = new JPanel(new GridLayout(3, 1, 20, 20));
|
||||
buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 50, 10, 50));
|
||||
|
||||
JButton primaryButton = createLevelButton("小学", new Color(76, 175, 120));
|
||||
JButton middleButton = createLevelButton("初中", new Color(255, 152, 100));
|
||||
JButton highButton = createLevelButton("高中", new Color(244, 67, 104));
|
||||
|
||||
buttonPanel.add(primaryButton);
|
||||
buttonPanel.add(middleButton);
|
||||
buttonPanel.add(highButton);
|
||||
|
||||
mainPanel.add(buttonPanel, BorderLayout.CENTER);
|
||||
|
||||
// 底部显示当前用户信息
|
||||
if (authController.getCurrentUser() != null) {
|
||||
JLabel userInfoLabel =
|
||||
new JLabel("当前用户: " + authController.getCurrentUser().getEmail(), JLabel.CENTER);
|
||||
userInfoLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||
userInfoLabel.setForeground(Color.GRAY);
|
||||
userInfoLabel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
|
||||
mainPanel.add(userInfoLabel, BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
primaryButton.addActionListener(e -> openQuestionCountFrame("小学"));
|
||||
middleButton.addActionListener(e -> openQuestionCountFrame("初中"));
|
||||
highButton.addActionListener(e -> openQuestionCountFrame("高中"));
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private JButton createLevelButton(String text, Color color) {
|
||||
JButton button = new JButton(text);
|
||||
button.setFont(new Font("Microsoft YaHei", Font.BOLD, 20));
|
||||
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 void backToLogin() {
|
||||
int result =
|
||||
JOptionPane.showConfirmDialog(this, "确定要退出登录吗?", "确认退出", JOptionPane.YES_NO_OPTION);
|
||||
|
||||
if (result == JOptionPane.YES_OPTION) {
|
||||
LoginFrame loginFrame = new LoginFrame();
|
||||
loginFrame.setVisible(true);
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void openQuestionCountFrame(String level) {
|
||||
QuestionCountFrame countFrame = new QuestionCountFrame(this, level);
|
||||
countFrame.setVisible(true);
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
// 修改密码对话框 - 不需要输入邮箱
|
||||
private void openChangePasswordDialog() {
|
||||
PasswordChangeFrame passwordChangeFrame = new PasswordChangeFrame(authController);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,157 @@
|
||||
package com.mathlearning.view;
|
||||
|
||||
import com.mathlearning.controller.AuthController;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
public class LoginFrame extends JFrame {
|
||||
private AuthController authController;
|
||||
private JTextField emailField;
|
||||
private JPasswordField passwordField;
|
||||
|
||||
public LoginFrame() {
|
||||
this.authController = new AuthController();
|
||||
initializeUI();
|
||||
}
|
||||
|
||||
private void initializeUI() {
|
||||
setTitle("数学学习软件 - 登录");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setSize(500, 400);
|
||||
setLocationRelativeTo(null);
|
||||
setResizable(false);
|
||||
|
||||
// 使用更灵活的布局
|
||||
JPanel mainPanel = new JPanel();
|
||||
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 40, 30, 40));
|
||||
|
||||
// 标题
|
||||
JLabel titleLabel = new JLabel("数学学习软件", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 28));
|
||||
titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
|
||||
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 30, 0));
|
||||
mainPanel.add(titleLabel);
|
||||
|
||||
// 添加一些间距
|
||||
mainPanel.add(Box.createRigidArea(new Dimension(0, 20)));
|
||||
|
||||
// 邮箱输入区域
|
||||
JPanel emailPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
emailPanel.setMaximumSize(new Dimension(400, 60));
|
||||
|
||||
JLabel emailLabel = new JLabel("邮箱:");
|
||||
emailLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
|
||||
emailLabel.setPreferredSize(new Dimension(80, 30));
|
||||
|
||||
emailField = new JTextField();
|
||||
emailField.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
||||
emailField.setPreferredSize(new Dimension(250, 35));
|
||||
|
||||
emailPanel.add(emailLabel);
|
||||
emailPanel.add(emailField);
|
||||
mainPanel.add(emailPanel);
|
||||
|
||||
// 添加间距
|
||||
mainPanel.add(Box.createRigidArea(new Dimension(0, 15)));
|
||||
|
||||
// 密码输入区域
|
||||
JPanel passwordPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
passwordPanel.setMaximumSize(new Dimension(400, 60));
|
||||
|
||||
JLabel passwordLabel = new JLabel("密码:");
|
||||
passwordLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 16));
|
||||
passwordLabel.setPreferredSize(new Dimension(80, 30));
|
||||
|
||||
passwordField = new JPasswordField();
|
||||
passwordField.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
||||
passwordField.setPreferredSize(new Dimension(250, 35));
|
||||
|
||||
passwordPanel.add(passwordLabel);
|
||||
passwordPanel.add(passwordField);
|
||||
mainPanel.add(passwordPanel);
|
||||
|
||||
// 添加间距
|
||||
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
|
||||
|
||||
// 按钮区域 - 只有登录和注册按钮
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
|
||||
buttonPanel.setMaximumSize(new Dimension(400, 50));
|
||||
|
||||
JButton loginButton = createStyledButton("登录", new Color(70, 130, 180));
|
||||
JButton registerButton = createStyledButton("注册", new Color(60, 179, 113));
|
||||
|
||||
buttonPanel.add(loginButton);
|
||||
buttonPanel.add(registerButton);
|
||||
|
||||
mainPanel.add(buttonPanel);
|
||||
|
||||
// 添加底部间距
|
||||
mainPanel.add(Box.createVerticalGlue());
|
||||
|
||||
// 添加操作监听器
|
||||
loginButton.addActionListener(new LoginAction());
|
||||
registerButton.addActionListener(e -> openRegisterFrame());
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private JButton createStyledButton(String text, Color color) {
|
||||
JButton button = new JButton(text);
|
||||
button.setFont(new Font("Microsoft YaHei", 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 class LoginAction implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String email = emailField.getText().trim();
|
||||
String password = new String(passwordField.getPassword());
|
||||
|
||||
if (email.isEmpty() || password.isEmpty()) {
|
||||
JOptionPane.showMessageDialog(LoginFrame.this, "请输入邮箱和密码", "错误", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (authController.login(email, password)) {
|
||||
JOptionPane.showMessageDialog(
|
||||
LoginFrame.this, "登录成功!", "成功", JOptionPane.INFORMATION_MESSAGE);
|
||||
openLevelSelectionFrame();
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(LoginFrame.this, "邮箱或密码错误", "错误", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void openRegisterFrame() {
|
||||
RegisterFrame registerFrame = new RegisterFrame();
|
||||
registerFrame.setVisible(true);
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
private void openLevelSelectionFrame() {
|
||||
LevelSelectionFrame levelFrame = new LevelSelectionFrame(authController);
|
||||
levelFrame.setVisible(true);
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package com.mathlearning.view;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
|
||||
public class QuestionCountFrame extends JFrame {
|
||||
private String level;
|
||||
private JTextField countField;
|
||||
private LevelSelectionFrame parentFrame;
|
||||
|
||||
public QuestionCountFrame(LevelSelectionFrame parent, String level) {
|
||||
this.level = level;
|
||||
this.parentFrame = parent;
|
||||
initializeUI();
|
||||
}
|
||||
|
||||
private void initializeUI() {
|
||||
setTitle("题目数量 - " + level);
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setSize(300, 200);
|
||||
setLocationRelativeTo(null);
|
||||
setResizable(false);
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
JLabel titleLabel = new JLabel(level + "数学题目", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
|
||||
mainPanel.add(titleLabel, BorderLayout.NORTH);
|
||||
|
||||
JPanel formPanel = new JPanel(new FlowLayout());
|
||||
|
||||
JLabel countLabel = new JLabel("题目数量:");
|
||||
countLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
||||
countField = new JTextField(10);
|
||||
countField.setText("10"); // Default value
|
||||
|
||||
formPanel.add(countLabel);
|
||||
formPanel.add(countField);
|
||||
|
||||
JButton startButton = new JButton("开始答题");
|
||||
startButton.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
||||
|
||||
mainPanel.add(formPanel, BorderLayout.CENTER);
|
||||
mainPanel.add(startButton, BorderLayout.SOUTH);
|
||||
|
||||
startButton.addActionListener(new StartAction());
|
||||
|
||||
this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
this.addWindowListener(
|
||||
new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
parentFrame.setVisible(true);
|
||||
}
|
||||
});
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private class StartAction implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
int count = Integer.parseInt(countField.getText().trim());
|
||||
if (count < 10 || count > 30) {
|
||||
JOptionPane.showMessageDialog(
|
||||
QuestionCountFrame.this, "题目数量应在10-30之间", "错误", JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
|
||||
openQuizFrame(count);
|
||||
} catch (NumberFormatException ex) {
|
||||
JOptionPane.showMessageDialog(
|
||||
QuestionCountFrame.this, "请输入有效的数字", "错误", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void openQuizFrame(int count) {
|
||||
QuizFrame quizFrame = new QuizFrame(level, count, parentFrame);
|
||||
quizFrame.setVisible(true);
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,279 @@
|
||||
package com.mathlearning.view;
|
||||
|
||||
import com.mathlearning.controller.AuthController;
|
||||
import com.mathlearning.service.EmailService;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.FocusListener;
|
||||
|
||||
public class RegisterFrame extends JFrame {
|
||||
private AuthController authController;
|
||||
private JTextField emailField;
|
||||
private JLabel resultLabel;
|
||||
private JButton registerButton;
|
||||
private Timer countdownTimer;
|
||||
private int remainingTime = 0;
|
||||
private JTextField codeField;
|
||||
private JButton submitButton;
|
||||
private String currentEmail; // 存储当前正在注册的邮箱
|
||||
|
||||
public RegisterFrame() {
|
||||
this.authController = new AuthController();
|
||||
initializeUI();
|
||||
}
|
||||
|
||||
private void initializeUI() {
|
||||
setTitle("数学学习软件 - 注册");
|
||||
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
setSize(500, 300); // 保持原有宽度以显示更长的提示信息
|
||||
setLocationRelativeTo(null);
|
||||
setResizable(false);
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
// 添加顶部返回按钮
|
||||
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
JButton backButton = new JButton("← 返回登录");
|
||||
backButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||
backButton.setBackground(new Color(200, 250, 190));
|
||||
backButton.addActionListener(e -> backToLogin());
|
||||
topPanel.add(backButton);
|
||||
mainPanel.add(topPanel, BorderLayout.NORTH);
|
||||
|
||||
JLabel titleLabel = new JLabel("用户注册", JLabel.CENTER);
|
||||
titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 18));
|
||||
mainPanel.add(titleLabel, BorderLayout.CENTER);
|
||||
|
||||
JPanel formPanel = new JPanel(new GridLayout(3, 2, 10, 10));
|
||||
formPanel.setLayout(null);
|
||||
JLabel emailLabel = new JLabel("邮箱地址:");
|
||||
emailLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
||||
emailLabel.setBounds(20, 20, 100, 20);
|
||||
emailField = new JTextField();
|
||||
emailField.setBounds(100, 20, 180, 30);
|
||||
// 添加邮箱输入框的焦点监听器,实现实时验证
|
||||
emailField.addFocusListener(
|
||||
new FocusListener() {
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
// 获得焦点时不清除内容
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
// 失去焦点时验证邮箱格式
|
||||
validateEmailInRealTime();
|
||||
}
|
||||
});
|
||||
|
||||
// 添加输入监听器,实现输入时实时验证
|
||||
emailField
|
||||
.getDocument()
|
||||
.addDocumentListener(
|
||||
new javax.swing.event.DocumentListener() {
|
||||
public void insertUpdate(javax.swing.event.DocumentEvent e) {
|
||||
validateEmailInRealTime();
|
||||
}
|
||||
|
||||
public void removeUpdate(javax.swing.event.DocumentEvent e) {
|
||||
validateEmailInRealTime();
|
||||
}
|
||||
|
||||
public void changedUpdate(javax.swing.event.DocumentEvent e) {
|
||||
validateEmailInRealTime();
|
||||
}
|
||||
});
|
||||
|
||||
registerButton = new JButton("获取注册码");
|
||||
registerButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
||||
registerButton.setBounds(285, 20, 140, 30);
|
||||
registerButton.setEnabled(false); // 初始时禁用
|
||||
JLabel codeLabel = new JLabel("注册码:");
|
||||
codeLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
||||
codeLabel.setBounds(20, 60, 100, 20);
|
||||
codeField = new JTextField();
|
||||
codeField.setBounds(100, 60, 180, 30);
|
||||
codeField.setEnabled(false); // 初始时禁用
|
||||
|
||||
submitButton = new JButton("注册");
|
||||
submitButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
||||
submitButton.setBounds(285, 60, 140, 30);
|
||||
submitButton.setEnabled(false); // 初始时禁用
|
||||
|
||||
formPanel.add(emailLabel);
|
||||
formPanel.add(emailField);
|
||||
formPanel.add(new JLabel());
|
||||
formPanel.add(registerButton);
|
||||
formPanel.add(codeLabel);
|
||||
formPanel.add(codeField);
|
||||
formPanel.add(submitButton);
|
||||
|
||||
resultLabel = new JLabel("请输入有效的邮箱地址", JLabel.CENTER);
|
||||
resultLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||
resultLabel.setForeground(Color.BLUE);
|
||||
|
||||
mainPanel.add(formPanel, BorderLayout.CENTER);
|
||||
mainPanel.add(resultLabel, BorderLayout.SOUTH);
|
||||
registerButton.addActionListener(new RegisterAction());
|
||||
submitButton.addActionListener(new SubmitAction());
|
||||
countdownTimer = new Timer(1000, new CountdownAction());
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
// 实时验证邮箱格式
|
||||
private void validateEmailInRealTime() {
|
||||
try {
|
||||
String email = emailField.getText().trim();
|
||||
|
||||
if (email.isEmpty()) {
|
||||
resultLabel.setText("请输入邮箱地址");
|
||||
resultLabel.setForeground(Color.BLUE);
|
||||
registerButton.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
|
||||
String validationMessage = authController.getEmailValidationMessage(email);
|
||||
|
||||
if (validationMessage.equals("邮箱格式正确")) {
|
||||
resultLabel.setText("✓ 邮箱格式正确");
|
||||
resultLabel.setForeground(new Color(0, 150, 0)); // 绿色
|
||||
registerButton.setEnabled(true);
|
||||
} else {
|
||||
resultLabel.setText("✗ " + validationMessage);
|
||||
resultLabel.setForeground(Color.RED);
|
||||
registerButton.setEnabled(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
resultLabel.setText("✗ 邮箱验证服务暂时不可用");
|
||||
resultLabel.setForeground(Color.RED);
|
||||
registerButton.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private class RegisterAction implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
if (EmailService.isNetworkAvailable()) {
|
||||
String email = emailField.getText().trim();
|
||||
if (email.isEmpty()) {
|
||||
resultLabel.setText("请输入邮箱地址");
|
||||
resultLabel.setForeground(Color.RED);
|
||||
return;
|
||||
}
|
||||
String validationMessage = authController.getEmailValidationMessage(email); // 再次验证邮箱格式
|
||||
if (!validationMessage.equals("邮箱格式正确")) {
|
||||
resultLabel.setText("✗ " + validationMessage);
|
||||
resultLabel.setForeground(Color.RED);
|
||||
return;
|
||||
}
|
||||
String result = authController.register(email);
|
||||
resultLabel.setText(result);
|
||||
if (result.contains("发送")) {
|
||||
resultLabel.setForeground(Color.BLUE);
|
||||
currentEmail = email; // 保存当前邮箱
|
||||
remainingTime = 120; // 开始倒计时
|
||||
registerButton.setEnabled(false);
|
||||
codeField.setEnabled(true); // 启用验证码输入框
|
||||
submitButton.setEnabled(true); // 启用注册按钮
|
||||
updateRegisterButtonText();
|
||||
countdownTimer.start();
|
||||
} else {
|
||||
resultLabel.setForeground(Color.RED);
|
||||
}
|
||||
} else {
|
||||
showDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class SubmitAction implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String code = codeField.getText().trim();
|
||||
|
||||
if (code.isEmpty()) {
|
||||
resultLabel.setText("请输入验证码");
|
||||
resultLabel.setForeground(Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentEmail == null) {
|
||||
resultLabel.setText("请先获取验证码");
|
||||
resultLabel.setForeground(Color.RED);
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用AuthController验证验证码
|
||||
if (authController.isCodeRegistered(currentEmail, code)) {
|
||||
countdownTimer.stop();
|
||||
resultLabel.setText("验证码正确,正在跳转...");
|
||||
resultLabel.setForeground(new Color(0, 150, 0));
|
||||
|
||||
// 延迟跳转到密码设置界面
|
||||
Timer openTimer =
|
||||
new Timer(
|
||||
1000,
|
||||
evt -> {
|
||||
openPasswordSetupFrame(currentEmail, code);
|
||||
});
|
||||
openTimer.setRepeats(false);
|
||||
openTimer.start();
|
||||
} else {
|
||||
resultLabel.setText("验证码错误或已过期,请重新输入");
|
||||
resultLabel.setForeground(Color.RED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class CountdownAction implements ActionListener {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
remainingTime--;
|
||||
updateRegisterButtonText();
|
||||
|
||||
if (remainingTime <= 0) {
|
||||
countdownTimer.stop();
|
||||
registerButton.setEnabled(true);
|
||||
registerButton.setText("获取注册码");
|
||||
codeField.setEnabled(false);
|
||||
submitButton.setEnabled(false);
|
||||
resultLabel.setText("验证码已过期,请重新获取");
|
||||
resultLabel.setForeground(Color.RED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRegisterButtonText() {
|
||||
registerButton.setText(String.format("重新发送(%ds)", remainingTime));
|
||||
}
|
||||
|
||||
private void backToLogin() {
|
||||
if (countdownTimer != null && countdownTimer.isRunning()) {
|
||||
countdownTimer.stop();
|
||||
}
|
||||
LoginFrame loginFrame = new LoginFrame();
|
||||
loginFrame.setVisible(true);
|
||||
this.dispose();
|
||||
}
|
||||
|
||||
private void openPasswordSetupFrame(String email, String code) {
|
||||
try {
|
||||
PasswordSetupFrame passwordFrame = new PasswordSetupFrame(email, code, authController);
|
||||
passwordFrame.setVisible(true);
|
||||
this.dispose();
|
||||
} catch (Exception e) {
|
||||
System.out.println("打开密码设置界面时发生异常: " + e.getMessage());
|
||||
JOptionPane.showMessageDialog(this, "打开密码设置界面失败,请重试", "错误", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private void showDialog() {
|
||||
JOptionPane.showMessageDialog(this, "网络连接失败,请稍后再试", "错误", JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
package com.mathlearning.view;
|
||||
|
||||
import com.mathlearning.controller.QuestionController;
|
||||
import com.mathlearning.model.Question;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
public class ScoreFrame extends JFrame {
|
||||
private QuestionController questionController;
|
||||
private int[] userSelections;
|
||||
private List<Question> allQuestions;
|
||||
private LevelSelectionFrame parentFrame;
|
||||
|
||||
public ScoreFrame(
|
||||
QuestionController questionController,
|
||||
int[] userSelections,
|
||||
List<Question> allQuestions,
|
||||
LevelSelectionFrame parent) {
|
||||
this.parentFrame = parent;
|
||||
this.questionController = questionController;
|
||||
this.userSelections = userSelections;
|
||||
this.allQuestions = allQuestions;
|
||||
initializeUI();
|
||||
}
|
||||
|
||||
private void initializeUI() {
|
||||
setTitle("答题结果");
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setSize(500, 400);
|
||||
setLocationRelativeTo(null);
|
||||
setResizable(false);
|
||||
|
||||
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
|
||||
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
||||
|
||||
// Score summary
|
||||
int score = questionController.getScore();
|
||||
int total = questionController.getTotalQuestions();
|
||||
double percentage = questionController.getPercentage();
|
||||
|
||||
JLabel scoreLabel =
|
||||
new JLabel(String.format("得分: %d/%d (%.1f%%)", score, total, percentage), JLabel.CENTER);
|
||||
scoreLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 24));
|
||||
|
||||
Color color;
|
||||
if (percentage >= 80) color = Color.GREEN;
|
||||
else if (percentage >= 60) color = Color.ORANGE;
|
||||
else color = Color.RED;
|
||||
|
||||
scoreLabel.setForeground(color);
|
||||
mainPanel.add(scoreLabel, BorderLayout.NORTH);
|
||||
|
||||
// Detailed results - 使用传递过来的题目和用户选择
|
||||
JTextArea detailsArea = new JTextArea();
|
||||
detailsArea.setEditable(false);
|
||||
detailsArea.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12));
|
||||
|
||||
StringBuilder details = new StringBuilder();
|
||||
details.append("答题详情:\n\n");
|
||||
|
||||
for (int i = 0; i < allQuestions.size(); i++) {
|
||||
Question q = allQuestions.get(i);
|
||||
int userAnswer = userSelections[i];
|
||||
boolean isCorrect = (userAnswer != -1) && q.isCorrect(userAnswer);
|
||||
|
||||
details.append(String.format("第%d题: %s\n", i + 1, q.getQuestionText()));
|
||||
details.append(
|
||||
String.format(
|
||||
"你的答案: %s\n",
|
||||
userAnswer == -1
|
||||
? "未作答"
|
||||
: (char) ('A' + userAnswer) + ". " + q.getOptions()[userAnswer]));
|
||||
details.append(
|
||||
String.format(
|
||||
"正确答案: %s\n",
|
||||
(char) ('A' + q.getCorrectAnswerIndex())
|
||||
+ ". "
|
||||
+ q.getOptions()[q.getCorrectAnswerIndex()]));
|
||||
details.append(isCorrect ? "✓ 正确\n" : "✗ 错误\n");
|
||||
details.append("--------------------\n");
|
||||
}
|
||||
|
||||
detailsArea.setText(details.toString());
|
||||
JScrollPane scrollPane = new JScrollPane(detailsArea);
|
||||
mainPanel.add(scrollPane, BorderLayout.CENTER);
|
||||
|
||||
// Buttons
|
||||
JPanel buttonPanel = new JPanel(new FlowLayout());
|
||||
JButton restartButton = new JButton("重新开始");
|
||||
JButton exitButton = new JButton("退出");
|
||||
|
||||
restartButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
||||
exitButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
|
||||
|
||||
buttonPanel.add(restartButton);
|
||||
buttonPanel.add(exitButton);
|
||||
|
||||
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
|
||||
|
||||
restartButton.addActionListener(e -> restartToLevelSelection());
|
||||
exitButton.addActionListener(e -> System.exit(0));
|
||||
|
||||
add(mainPanel);
|
||||
}
|
||||
|
||||
private void restartToLevelSelection() {
|
||||
parentFrame.setVisible(true);
|
||||
this.dispose();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue