Compare commits

..

12 Commits

@ -0,0 +1,15 @@
<component name="ArtifactManager">
<artifact type="jar" name="TestSystem:jar">
<output-path>$PROJECT_DIR$/out/artifacts/TestSystem_jar</output-path>
<root id="archive" name="TestSystem.jar">
<element id="directory" name="META-INF">
<element id="file-copy" path="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
</element>
<element id="module-output" name="TestSystem" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/net/objecthunter/exp4j/0.4.8/exp4j-0.4.8.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/sun/mail/jakarta.mail/2.0.1/jakarta.mail-2.0.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/formdev/flatlaf/3.4.1/flatlaf-3.4.1.jar" path-in-jar="/" />
<element id="extracted-dir" path="$MAVEN_REPOSITORY$/com/sun/activation/jakarta.activation/2.0.1/jakarta.activation-2.0.1.jar" path-in-jar="/" />
</root>
</artifact>
</component>

@ -1,10 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ArtifactsWorkspaceSettings">
<artifacts-to-build>
<artifact name="TestSystem:jar" />
</artifacts-to-build>
</component>
<component name="AutoImportSettings">
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="1201acd7-f240-4a23-9c12-26bf9afcb8cb" name="更改" comment="初步框架" />
<list default="true" id="1201acd7-f240-4a23-9c12-26bf9afcb8cb" name="更改" comment="修复除零bug">
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/mathapp/problemGenerators/HighSchoolProblemGenerator.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/mathapp/problemGenerators/HighSchoolProblemGenerator.class" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
@ -33,38 +41,44 @@
</favorite-branches>
<option name="RECENT_BRANCH_BY_REPOSITORY">
<map>
<entry key="$PROJECT_DIR$" value="liwentao_branch" />
<entry key="$PROJECT_DIR$" value="main" />
</map>
</option>
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="ProjectColorInfo"><![CDATA[{
"customColor": "",
"associatedIndex": 1
}]]></component>
<component name="KubernetesApiPersistence">{}</component>
<component name="KubernetesApiProvider">{
&quot;isMigrated&quot;: true
}</component>
<component name="ProjectColorInfo">{
&quot;customColor&quot;: &quot;&quot;,
&quot;associatedIndex&quot;: 1
}</component>
<component name="ProjectId" id="33pYNF2i3YjFfOgekWFVlM8sKGc" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"RunOnceActivity.ShowReadmeOnStart": "true",
"kotlin-language-version-configured": "true",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
"node.js.selected.package.tslint": "(autodetect)",
"nodejs_package_manager_path": "npm",
"onboarding.tips.debug.path": "C:/Users/Teptao/Desktop/软件工程导论/结对项目/TestSystem/src/main/java/org/example/Main.java",
"project.structure.last.edited": "模块",
"project.structure.proportion": "0.15",
"project.structure.side.proportion": "0.2",
"vue.rearranger.settings.migration": "true",
"应用程序.MathApp.executor": "Run"
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;liwentao__branch&quot;,
&quot;kotlin-language-version-configured&quot;: &quot;true&quot;,
&quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
&quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
&quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
&quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
&quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
&quot;onboarding.tips.debug.path&quot;: &quot;C:/Users/Teptao/Desktop/软件工程导论/结对项目/TestSystem/src/main/java/org/example/Main.java&quot;,
&quot;project.structure.last.edited&quot;: &quot;工件&quot;,
&quot;project.structure.proportion&quot;: &quot;0.15&quot;,
&quot;project.structure.side.proportion&quot;: &quot;0.2&quot;,
&quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;,
&quot;应用程序.MathApp.executor&quot;: &quot;Run&quot;
}
}]]></component>
}</component>
<component name="RunManager">
<configuration name="MathApp" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="com.mathapp.MathApp" />
@ -82,6 +96,9 @@
<recent_temporary>
<list>
<item itemvalue="应用程序.MathApp" />
<item itemvalue="应用程序.MathApp" />
<item itemvalue="应用程序.MathApp" />
<item itemvalue="应用程序.MathApp" />
</list>
</recent_temporary>
</component>
@ -127,7 +144,39 @@
<option name="project" value="LOCAL" />
<updated>1760022602945</updated>
</task>
<option name="localTasksCounter" value="4" />
<task id="LOCAL-00004" summary="合并更改">
<option name="closed" value="true" />
<created>1760136750934</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1760136750934</updated>
</task>
<task id="LOCAL-00005" summary="合并更改">
<option name="closed" value="true" />
<created>1760136867337</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1760136867337</updated>
</task>
<task id="LOCAL-00006" summary="修复使用用户名登录时无法修改密码的问题">
<option name="closed" value="true" />
<created>1760182983400</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1760182983400</updated>
</task>
<task id="LOCAL-00007" summary="修复除零bug">
<option name="closed" value="true" />
<created>1760183246928</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1760183246928</updated>
</task>
<option name="localTasksCounter" value="8" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
@ -159,6 +208,9 @@
<component name="VcsManagerConfiguration">
<MESSAGE value="创建maven项目" />
<MESSAGE value="初步框架" />
<option name="LAST_COMMIT_MESSAGE" value="初步框架" />
<MESSAGE value="合并更改" />
<MESSAGE value="修复使用用户名登录时无法修改密码的问题" />
<MESSAGE value="修复除零bug" />
<option name="LAST_COMMIT_MESSAGE" value="修复除零bug" />
</component>
</project>

@ -1,2 +1,5 @@
# TestSystem
双击exe运行
密码加密后保存在txt中

@ -1,20 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.id="$MODULE_DIR$/pom.xml" external.system.module.type="SINGLE_MODULE" external.system.module.version="223-2" org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_22">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<component name="AdditionalModuleElements">
<content url="file://$MODULE_DIR$" dumb="true">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.formdev:flatlaf:3.4.1" level="project" />
<orderEntry type="library" name="Maven: com.sun.mail:jakarta.mail:2.0.1" level="project" />
<orderEntry type="library" name="Maven: com.sun.activation:jakarta.activation:2.0.1" level="project" />
<orderEntry type="library" name="Maven: net.objecthunter:exp4j:0.4.8" level="project" />
</component>
</module>

@ -0,0 +1,104 @@
用户: 11
时间: 20251009_235440
得分: 4 / 20
====================================
题目 1: 58 / 1^2 / 1 - 31 * 61
选项: -183.3 | -1828.2 | -1833 | 1833
你的答案: 1833
正确答案: -1833
--------------------
题目 2: 78 * sqrt(9) - 14 / 14 + 21
选项: -254 | 2540 | 254 | 25.4
你的答案: 25.4
正确答案: 254
--------------------
题目 3: 10 / 10^2
选项: 0.1 | -0.44 | 1.87 | -0.1
你的答案: 1.87
正确答案: 0.1
--------------------
题目 4: 51 * 74 / 1 + 2^2 * 38
选项: -3926 | 3927.72 | 39260 | 3926
你的答案: 39260
正确答案: 3926
--------------------
题目 5: 43 + 88 / sqrt(16) / 1
选项: 650 | -65 | 65 | 62.89
你的答案: 65
正确答案: 65
--------------------
题目 6: 2 * 48^2
选项: 4604.6 | 4608 | -4608 | 46080
你的答案: -4608
正确答案: 4608
--------------------
题目 7: sqrt(81) * 61 - 56 / 28 + 70
选项: 613.97 | 617 | 619.92 | 6170
你的答案: 6170
正确答案: 617
--------------------
题目 8: 73 / sqrt(64)
选项: 0.91 | 7.36 | 91.3 | 9.13
你的答案: 91.3
正确答案: 9.13
--------------------
题目 9: 29 * 44 + 44^2 / 22 - 45
选项: -1319 | 13190 | 131.9 | 1319
你的答案: 131.9
正确答案: 1319
--------------------
题目 10: 53 * sqrt(49) - 91
选项: 281.97 | -280 | 280 | 2800
你的答案: 280
正确答案: 280
--------------------
题目 11: 39 - 7 + 85^2
选项: -7257 | 7257 | 7259.54 | 725.7
你的答案: 7259.54
正确答案: 7257
--------------------
题目 12: sqrt(9) + 80
选项: 83 | 81.76 | 84.08 | -83
你的答案: 84.08
正确答案: 83
--------------------
题目 13: 71 - 48 / 16 / 8^2 * 23
选项: 69.92 | 74.21 | -69.92 | 66.37
你的答案: -69.92
正确答案: 69.92
--------------------
题目 14: 67 + sqrt(100) / 4 * 35
选项: -154.5 | 1545 | 157.75 | 154.5
你的答案: 157.75
正确答案: 154.5
--------------------
题目 15: sqrt(81) * 1 + 69
选项: -78 | 780 | 7.8 | 78
你的答案: 7.8
正确答案: 78
--------------------
题目 16: 14 / 7 * 82 - sqrt(9)
选项: 1610 | 160.16 | 161 | -161
你的答案: 161
正确答案: 161
--------------------
题目 17: 92 + 3 + 53^2
选项: 290.4 | 2904 | 29040 | 2899.46
你的答案: 29040
正确答案: 2904
--------------------
题目 18: 20 - 87 * 71^2
选项: -438547 | -438548.67 | 438547 | -4385470
你的答案: 438547
正确答案: -438547
--------------------
题目 19: 40^2 * 35
选项: 56000 | 55995.78 | 560000 | 56002.59
你的答案: 560000
正确答案: 56000
--------------------
题目 20: 59 * 93 + 51^2 / 17 * 12
选项: 73230 | 732.3 | 7323 | -7323
你的答案: 7323
正确答案: 7323
--------------------

@ -0,0 +1,54 @@
用户: 11
时间: 20251010_001044
得分: 3 / 10
====================================
题目 1: 7 + 35 * (75^2) + tan(pi/4)
选项: -196883 | 196887.67 | 196883 | 196878.95
你的答案: 196887.67
正确答案: 196883
--------------------
题目 2: sqrt(49) + 19 + 38 + 46 - 73 - tan(0)
选项: 37 | 35.09 | 3.7 | 34.85
你的答案: 34.85
正确答案: 37
--------------------
题目 3: sqrt(25) * 25 * 27 - 38 - sin(pi/6)
选项: -3336.5 | 3335.81 | 333.65 | 3336.5
你的答案: 333.65
正确答案: 3336.5
--------------------
题目 4: sqrt(100) / 83 / sin(pi/6)
选项: -0.24 | 0.02 | 3.98 | 0.24
你的答案: 3.98
正确答案: 0.24
--------------------
题目 5: 23 / 1 - 77 * sqrt(81) * 66 - tan(pi/6)
选项: -45712.35 | -4571.56 | -45715.58 | 45715.58
你的答案: -45715.58
正确答案: -45715.58
--------------------
题目 6: sqrt(36) - 67 + 2 / 2 / cos(0)
选项: -600 | -55.76 | -60 | 60
你的答案: -55.76
正确答案: -60
--------------------
题目 7: 13 - sqrt(81) * tan(pi/6)
选项: 78 | 7.8 | 11.8 | 3.35
你的答案: 11.8
正确答案: 7.8
--------------------
题目 8: 27 + 62 * 35 + (30^2) - 32 - cos(pi/3)
选项: -3064.5 | 3068.06 | 3066.31 | 3064.5
你的答案: 3064.5
正确答案: 3064.5
--------------------
题目 9: 72 + 18 / sqrt(49) / sin(pi/3)
选项: 7.5 | 73.65 | 74.97 | -74.97
你的答案: 74.97
正确答案: 74.97
--------------------
题目 10: (9^2) / 9 * 19 - sin(pi/3)
选项: 170.13 | 17.01 | -170.13 | 168.56
你的答案: -170.13
正确答案: 170.13
--------------------

@ -0,0 +1,54 @@
用户: 111
时间: 20251009_234734
得分: 2 / 10
====================================
题目 1: 95 + 48^2 * 7 + 96 * 36
选项: 196790 | -19679 | 19679 | 19683.08
你的答案: 19679
正确答案: 19679
--------------------
题目 2: 66 * 58 + 67 * sqrt(9)
选项: 40290 | 4029 | 4032.33 | 4031.06
你的答案: 4031.06
正确答案: 4029
--------------------
题目 3: 96 / 24 + 87 / 87^2
选项: -4.01 | 7.73 | 6.58 | 4.01
你的答案: 6.58
正确答案: 4.01
--------------------
题目 4: sqrt(9) - 96
选项: -930 | 93 | -9.3 | -93
你的答案: -9.3
正确答案: -93
--------------------
题目 5: 30 + 98 + 81^2 + 86 / 43
选项: 6687.47 | 669.1 | 6695.88 | 6691
你的答案: 6695.88
正确答案: 6691
--------------------
题目 6: sqrt(25) * 4
选项: 20 | 200 | 2 | -20
你的答案: 200
正确答案: 20
--------------------
题目 7: 17^2 * 7
选项: 2018.58 | 2022.15 | 2024.75 | 2023
你的答案: 2024.75
正确答案: 2023
--------------------
题目 8: 65 / 13 / 1 * 13^2 * 38
选项: 321100 | 3211 | 32114.95 | 32110
你的答案: 32114.95
正确答案: 32110
--------------------
题目 9: 56 / 1 + sqrt(64) - 5
选项: 58.53 | -59 | 59 | 5.9
你的答案: 58.53
正确答案: 59
--------------------
题目 10: 93 / sqrt(16) + 19
选项: 40.06 | 47.16 | 42.25 | -42.25
你的答案: 42.25
正确答案: 42.25
--------------------

@ -0,0 +1,54 @@
用户: 111
时间: 20251010_002008
得分: 3 / 10
====================================
题目 1: 9 * 28 - 36 + sqrt(25) * 85 + tan(pi/4)
选项: 646.48 | 641.16 | 642 | 64.2
你的答案: 64.2
正确答案: 642
--------------------
题目 2: (91^2) / 1 * cos(pi/4)
选项: 5857.24 | 5855.55 | 5852.13 | 585.56
你的答案: 585.56
正确答案: 5855.55
--------------------
题目 3: sqrt(25) * 15 - 19 + 56 - 35 / sin(pi/6)
选项: 42 | 43.2 | 420 | 40.73
你的答案: 420
正确答案: 42
--------------------
题目 4: 47 * 25 * sqrt(100) / 1 + cos(pi/6)
选项: 11746.83 | 11751.94 | 11750.87 | 1175.09
你的答案: 1175.09
正确答案: 11750.87
--------------------
题目 5: 16 + 33 / sqrt(64) * cos(pi/4)
选项: -18.92 | 1.89 | 189.2 | 18.92
你的答案: 189.2
正确答案: 18.92
--------------------
题目 6: 68 + 15 - sqrt(25) + 13 * 3 - sin(pi/6)
选项: 1165 | 116.5 | 11.65 | -116.5
你的答案: 11.65
正确答案: 116.5
--------------------
题目 7: 31 / 1 / 1 / sqrt(25) * 57 - sin(pi/6)
选项: 35.29 | 348.77 | 352.9 | -352.9
你的答案: 352.9
正确答案: 352.9
--------------------
题目 8: 77 + 90 - (45^2) - 60 * cos(pi/3)
选项: -1883.16 | -1892.42 | -1888 | -1889.63
你的答案: -1888
正确答案: -1888
--------------------
题目 9: 26 / sqrt(4) + cos(pi/6)
选项: 1.39 | 138.7 | 13.87 | 10.03
你的答案: 13.87
正确答案: 13.87
--------------------
题目 10: 70 - 66 * 53 + (18^2) - 33 * tan(pi/6)
选项: -312.31 | -3123.05 | -31230.5 | 3123.05
你的答案: -31230.5
正确答案: -3123.05
--------------------

@ -0,0 +1,54 @@
用户: teptao
时间: 20251010_092503
得分: 3 / 10
====================================
题目 1: sqrt(16) + 34 + 77 / tan(pi/3)
选项: 82.46 | 824.6 | 8.25 | -82.46
你的答案: 82.46
正确答案: 82.46
--------------------
题目 2: 35 * 30 / sqrt(4) + cos(pi/6)
选项: 529.63 | 525.87 | 520.88 | 524.58
你的答案: 525.87
正确答案: 525.87
--------------------
题目 3: 35 - 93 / 1 * (89^2) * 15 / tan(pi/4)
选项: -11049760 | 11049760 | -1104976 | -11049757.51
你的答案: -1104976
正确答案: -11049760
--------------------
题目 4: (16^2) * 75 / cos(0)
选项: -19200 | 192000 | 19204.12 | 19200
你的答案: 19204.12
正确答案: 19200
--------------------
题目 5: 19 * 90 - sqrt(36) * tan(pi/6)
选项: 1706.54 | 1701.81 | 17065.4 | -1706.54
你的答案: 17065.4
正确答案: 1706.54
--------------------
题目 6: 37 + 86 + sqrt(4) + sin(pi/6)
选项: 1255 | 125.5 | 124.64 | -125.5
你的答案: -125.5
正确答案: 125.5
--------------------
题目 7: 88 - sqrt(36) / 23 * 19 + 87 / cos(pi/6)
选项: -183.5 | 182.06 | 186.56 | 183.5
你的答案: 186.56
正确答案: 183.5
--------------------
题目 8: 57 - sqrt(49) - cos(pi/4)
选项: 4.93 | 46.5 | 44.99 | 49.29
你的答案: 44.99
正确答案: 49.29
--------------------
题目 9: 68 + 83 / 1 + 68 / sqrt(9) + tan(pi/6)
选项: 1742.4 | 17.42 | -174.24 | 174.24
你的答案: -174.24
正确答案: 174.24
--------------------
题目 10: 59 - sqrt(100) - 58 + tan(0)
选项: -0.9 | -90 | -9 | 9
你的答案: -9
正确答案: -9
--------------------

@ -1 +1,4 @@
test@example.com::jZae727K08KaOmKSgOaGzww/XVqLqBG7KAbpTTJzaI0=
test@example.com::jZae727K08KaOmKSgOaGzww/XVqLqBG7KAbpTTJzaI0=
Tester::Tester::7RcqFZEiXA1x7ggr5Sy2xvdMuJb6Xz/P8aMMmj+PZbI=
Tester2::1414246561@qq.com::7RcqFZEiXA1x7ggr5Sy2xvdMuJb6Xz/P8aMMmj+PZbI=

@ -25,6 +25,11 @@ public class MathApp extends JFrame {
public static final String RESULTS_PANEL = "ResultsPanel";
public static final String CHANGE_PASSWORD_PANEL = "ChangePasswordPanel";
private LoginPanel loginPanel;
private RegisterPanel registerPanel;
private MainMenuPanel mainMenuPanel;
private ChangePasswordPanel changePasswordPanel;
public MathApp() {
initUI();
}
@ -39,11 +44,16 @@ public class MathApp extends JFrame {
cardLayout = new CardLayout();
mainPanel = new JPanel(cardLayout);
loginPanel = new LoginPanel(this);
registerPanel = new RegisterPanel(this);
mainMenuPanel = new MainMenuPanel(this);
changePasswordPanel = new ChangePasswordPanel(this);
// 添加所有静态面板
mainPanel.add(new LoginPanel(this), LOGIN_PANEL);
mainPanel.add(new RegisterPanel(this), REGISTER_PANEL);
mainPanel.add(new MainMenuPanel(this), MAIN_MENU_PANEL);
mainPanel.add(new ChangePasswordPanel(this), CHANGE_PASSWORD_PANEL);
mainPanel.add(loginPanel, LOGIN_PANEL);
mainPanel.add(registerPanel, REGISTER_PANEL);
mainPanel.add(mainMenuPanel, MAIN_MENU_PANEL);
mainPanel.add(changePasswordPanel, CHANGE_PASSWORD_PANEL);
add(mainPanel);
}
@ -53,6 +63,23 @@ public class MathApp extends JFrame {
* @param panelName
*/
public void showPanel(String panelName) {
switch (panelName) {
case LOGIN_PANEL:
loginPanel.resetPanel();
break;
case REGISTER_PANEL:
registerPanel.resetPanel();
break;
case MAIN_MENU_PANEL :
mainMenuPanel.resetPanel();
break;
case CHANGE_PASSWORD_PANEL :
changePasswordPanel.resetPanel();
break;
default:
break;
}
cardLayout.show(mainPanel, panelName);
}

@ -6,21 +6,28 @@ import java.util.Base64;
import java.util.Random;
public class User {
private final String username;
private final String email;
private final String hashedPassword;
// 构造函数1用于新用户注册需要原始密码
public User(String email, String rawPassword) {
public User(String username, String email, String rawPassword) {
this.username = username;
this.email = email;
this.hashedPassword = hashPassword(rawPassword);
}
// 构造函数2用于从文件加载用户已是哈希密码
public User(String email, String hashedPassword, boolean isHashed) {
public User(String username, String email, String hashedPassword, boolean isHashed) {
this.username = username;
this.email = email;
this.hashedPassword = hashedPassword;
}
public String getUsername() {
return username;
}
public String getEmail() {
return email;
}

@ -82,6 +82,12 @@ public class ChangePasswordPanel extends JPanel {
backButton.addActionListener(e -> app.showPanel(MathApp.MAIN_MENU_PANEL));
}
public void resetPanel() {
oldPasswordField.setText("");
newPasswordField.setText("");
confirmNewPasswordField.setText("");
}
private void handleChangePassword() {
String email = app.getCurrentUserEmail();
if (email == null) {

@ -6,6 +6,8 @@ import com.mathapp.services.DataPersistence;
import javax.swing.*;
import java.awt.*;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
public class LoginPanel extends JPanel {
private final MathApp app;
@ -23,6 +25,52 @@ public class LoginPanel extends JPanel {
emailField = new JTextField(20);
passwordField = new JPasswordField(20);
emailField.setText("请输入账号(支持邮箱或用户名)");
emailField.setForeground(Color.GRAY);
passwordField.setText("........");
passwordField.setForeground(Color.GRAY);
emailField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
// 获得焦点时,若当前文本是提示文字,则清空并改为黑色
if (emailField.getText().equals("请输入账号(支持邮箱或用户名)")) {
emailField.setText("");
emailField.setForeground(Color.black);
}
}
public void focusLost(FocusEvent e) {
// 失去焦点时,若文本框为空,则恢复灰色提示文字
if (emailField.getText().isEmpty()) {
emailField.setForeground(Color.gray);
emailField.setText("请输入账号(支持邮箱或用户名)");
}
}
});
passwordField.addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
// 获得焦点时,若当前文本是提示文字,则清空并改为黑色
if (passwordField.getText().equals("........")) {
passwordField.setText("");
passwordField.setForeground(Color.black);
}
}
public void focusLost(FocusEvent e) {
// 失去焦点时,若文本框为空,则恢复灰色提示文字
if (passwordField.getText().isEmpty()) {
passwordField.setForeground(Color.gray);
passwordField.setText("........");
}
}
});
JButton loginButton = new JButton("登录");
loginButton.setFont(new Font("微软雅黑", Font.PLAIN, 16));
loginButton.setPreferredSize(new Dimension(120, 40));
@ -45,7 +93,7 @@ public class LoginPanel extends JPanel {
gbc.gridwidth = 1;
gbc.gridy = 1;
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("邮箱:"), gbc);
//add(new JLabel("账号(用户名或邮箱):"), gbc);
gbc.gridx = 1;
gbc.anchor = GridBagConstraints.WEST;
@ -54,7 +102,7 @@ public class LoginPanel extends JPanel {
gbc.gridx = 0;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("密码:"), gbc);
//add(new JLabel("密码:"), gbc);
gbc.gridx = 1;
gbc.anchor = GridBagConstraints.WEST;
@ -73,12 +121,17 @@ public class LoginPanel extends JPanel {
registerButton.addActionListener(e -> app.showPanel(MathApp.REGISTER_PANEL));
}
public void resetPanel() {
emailField.setText("");
passwordField.setText("");
}
private void handleLogin() {
String email = emailField.getText().trim();
String password = new String(passwordField.getPassword());
if (email.isEmpty() || password.isEmpty()) {
JOptionPane.showMessageDialog(this, "邮箱和密码不能为空!", "错误", JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(this, "账号和密码不能为空!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
@ -87,7 +140,7 @@ public class LoginPanel extends JPanel {
app.setCurrentUserEmail(email);
app.showPanel(MathApp.MAIN_MENU_PANEL);
} else {
JOptionPane.showMessageDialog(this, "邮箱或密码错误!", "登录失败", JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(this, "账号或密码错误!", "登录失败", JOptionPane.ERROR_MESSAGE);
}
}
}

@ -80,7 +80,21 @@ public class MainMenuPanel extends JPanel {
changePasswordButton.addActionListener(e -> app.showPanel(MathApp.CHANGE_PASSWORD_PANEL));
}
public void resetPanel() {
levelGroup.clearSelection();
questionCountField.setText("10");
}
private void handleStart() {
ButtonModel selectedModel = levelGroup.getSelection();
// 关键检查:判断是否有按钮被选中
if (selectedModel == null) {
JOptionPane.showMessageDialog(this, "请先选择一个难度级别!", "选择错误", JOptionPane.WARNING_MESSAGE);
return; // 发现未选择后,直接退出方法,不执行后续逻辑
}
String level = levelGroup.getSelection().getActionCommand();
int count;
try {

@ -15,9 +15,12 @@ public class RegisterPanel extends JPanel {
private final JTextField codeField;
private final JButton getCodeButton;
private String generatedCode;
private Timer cooldownTimer;
public RegisterPanel(MathApp app) {
this.app = app;
this.generatedCode = null;
this.cooldownTimer = null;
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
@ -74,6 +77,20 @@ public class RegisterPanel extends JPanel {
backButton.addActionListener(e -> app.showPanel(MathApp.LOGIN_PANEL));
}
public void resetPanel() {
emailField.setText("");
codeField.setText("");
getCodeButton.setText("获取验证码");
getCodeButton.setEnabled(true);
generatedCode = null;
if (cooldownTimer != null) {
cooldownTimer.stop();
cooldownTimer = null;
}
}
private void handleGetCode() {
String email = emailField.getText().trim();
if (!ValidationUtils.isValidEmail(email)) {
@ -131,24 +148,28 @@ public class RegisterPanel extends JPanel {
JOptionPane.showMessageDialog(this, "验证码错误!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
// 验证成功,跳转到设置密码页面
app.showSetPasswordPanel(emailField.getText().trim());
}
private void startCooldownTimer() {
Timer timer = new Timer(1000, null);
if (cooldownTimer != null) {
cooldownTimer.stop();
}
cooldownTimer = new Timer(1000, null);
final int[] countdown = {60};
timer.addActionListener(e -> {
cooldownTimer.addActionListener(e -> {
countdown[0]--;
if (countdown[0] >= 0) {
getCodeButton.setText(countdown[0] + "秒后重试");
} else {
timer.stop();
cooldownTimer.stop();
getCodeButton.setText("获取验证码");
getCodeButton.setEnabled(true);
}
});
timer.start();
cooldownTimer.start();
}
}

@ -11,6 +11,7 @@ import java.awt.*;
public class SetPasswordPanel extends JPanel {
private final MathApp app;
private final String email;
private final JTextField usernameField;
private final JPasswordField passwordField;
private final JPasswordField confirmPasswordField;
@ -26,6 +27,7 @@ public class SetPasswordPanel extends JPanel {
JLabel infoLabel = new JLabel("密码需6-10位且包含大小写字母和数字", SwingConstants.CENTER);
infoLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
usernameField = new JTextField(20);
passwordField = new JPasswordField(20);
confirmPasswordField = new JPasswordField(20);
JButton confirmButton = new JButton("完成注册");
@ -43,13 +45,22 @@ public class SetPasswordPanel extends JPanel {
gbc.gridwidth = 1;
gbc.gridy = 2;
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("用户名:"), gbc);
gbc.gridx = 1;
gbc.anchor = GridBagConstraints.WEST;
add(usernameField, gbc);
gbc.gridy = 3;
gbc.gridx = 0;
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("输入密码:"), gbc);
gbc.gridx = 1;
gbc.anchor = GridBagConstraints.WEST;
add(passwordField, gbc);
gbc.gridy = 3;
gbc.gridy = 4;
gbc.gridx = 0;
gbc.anchor = GridBagConstraints.EAST;
add(new JLabel("确认密码:"), gbc);
@ -58,7 +69,7 @@ public class SetPasswordPanel extends JPanel {
gbc.anchor = GridBagConstraints.WEST;
add(confirmPasswordField, gbc);
gbc.gridy = 4;
gbc.gridy = 5;
gbc.gridx = 0;
gbc.gridwidth = 2;
gbc.anchor = GridBagConstraints.CENTER;
@ -68,9 +79,20 @@ public class SetPasswordPanel extends JPanel {
}
private void handleSetPassword() {
String username = usernameField.getText().trim();
String password = new String(passwordField.getPassword());
String confirmPassword = new String(confirmPasswordField.getPassword());
if (username.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入用户名!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
if (DataPersistence.findUserByUsername(username) != null) {
JOptionPane.showMessageDialog(this, "该用户名已被使用!", "错误", JOptionPane.ERROR_MESSAGE);
return;
}
if (!password.equals(confirmPassword)) {
JOptionPane.showMessageDialog(this, "两次输入的密码不一致!", "错误", JOptionPane.ERROR_MESSAGE);
return;
@ -82,7 +104,7 @@ public class SetPasswordPanel extends JPanel {
}
// 创建用户并保存
User newUser = new User(email, password);
User newUser = new User(username, email, password);
DataPersistence.saveUser(newUser);
JOptionPane.showMessageDialog(this, "注册成功!现在您可以登录了。", "成功", JOptionPane.INFORMATION_MESSAGE);

@ -42,7 +42,8 @@ public class HighSchoolProblemGenerator extends MiddleSchoolProblemGenerator {
// 2c.【健壮性检查】检查这个新运算符是否会与三角函数的值构成除零错误
boolean isTrigValueZero = (function.equals("sin") && angleInDegrees == 0) ||
(function.equals("tan") && angleInDegrees == 0);
(function.equals("tan") && angleInDegrees == 0)||
(function.equals("cos") && angleInDegrees == 90);
// 如果新运算符是除法且三角函数的值是0则这是一个非法组合必须重试
if (connectingOperator == Operator.DIVIDE && isTrigValueZero) {

@ -32,7 +32,8 @@ public class DataPersistence {
}
public static void saveUser(User user) {
String userData = user.getEmail() + "::" + user.getHashedPassword() + System.lineSeparator();
// 更新数据格式为:用户名::邮箱::密码哈希
String userData = user.getUsername() + "::" + user.getEmail() + "::" + user.getHashedPassword() + System.lineSeparator();
try {
Files.writeString(USER_FILE_PATH, userData, StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.APPEND);
} catch (IOException e) {
@ -42,11 +43,31 @@ public class DataPersistence {
public static User findUserByEmail(String email) {
try (Stream<String> lines = Files.lines(USER_FILE_PATH, StandardCharsets.UTF_8)) {
return lines.filter(line -> line.startsWith(email + "::"))
return lines.filter(line -> {
String[] parts = line.split("::");
return parts.length >= 3 && (parts[1].equals(email)||parts[0].equals(email));
})
.map(line -> {
String[] parts = line.split("::");
// 构造函数会处理密码哈希
return new User(parts[0], parts[1], true);
return new User(parts[0], parts[1], parts[2], true);
})
.findFirst()
.orElse(null);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static User findUserByUsername(String username) {
try (Stream<String> lines = Files.lines(USER_FILE_PATH, StandardCharsets.UTF_8)) {
return lines.filter(line -> {
String[] parts = line.split("::");
return parts.length >= 3 && parts[0].equals(username);
})
.map(line -> {
String[] parts = line.split("::");
return new User(parts[0], parts[1], parts[2], true);
})
.findFirst()
.orElse(null);
@ -60,9 +81,10 @@ public class DataPersistence {
try {
List<String> lines = Files.readAllLines(USER_FILE_PATH, StandardCharsets.UTF_8);
for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).startsWith(email + "::")) {
User tempUser = new User(email, newPassword); // 用来生成新密码的哈希值
lines.set(i, email + "::" + tempUser.getHashedPassword());
String[] parts = lines.get(i).split("::");
if (parts.length >= 3 && parts[1].equals(email) || parts[0].equals(email)) {
User tempUser = new User(parts[0], email, newPassword);
lines.set(i, parts[0] + "::" + email + "::" + tempUser.getHashedPassword());
Files.write(USER_FILE_PATH, lines, StandardCharsets.UTF_8);
return true;
}

@ -10,10 +10,10 @@ public class EmailService {
// !!! 重要提示 !!!
// 请将以下信息替换为您自己的SMTP服务器信息和凭据
// 对于Gmail, 您需要生成一个 "应用专用密码"
private static final String SMTP_HOST = "smtp.your-email-provider.com"; // 例如smtp.gmail.com
private static final String SMTP_HOST = "smtp.qq.com"; // 例如smtp.gmail.com
private static final String SMTP_PORT = "587"; // 通常是 587 (TLS) 或 465 (SSL)
private static final String FROM_EMAIL = "your-email@example.com"; // 您的发件邮箱地址
private static final String PASSWORD = "your-app-password"; // 您的应用专用密码或邮箱密码
private static final String FROM_EMAIL = "971817787@qq.com"; // 您的发件邮箱地址
private static final String PASSWORD = "aqcwtvmqcghjbedf"; // 您的应用专用密码或邮箱密码
public static void sendVerificationCode(String toEmail, String code) throws MessagingException {
Properties props = new Properties();

Loading…
Cancel
Save