wty to develop #1
Merged
psoyzuart
merged 20 commits from wangtengyun_branch into develop 4 months ago
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 4.5 MiB |
@ -0,0 +1,170 @@
|
||||
/* 根容器样式 */
|
||||
.root {
|
||||
-fx-font-family: "Microsoft YaHei", "Segoe UI", sans-serif;
|
||||
-fx-background-image: url("1.jpg");
|
||||
-fx-background-repeat: no-repeat;
|
||||
-fx-background-size: cover;
|
||||
}
|
||||
|
||||
/* 通用按钮样式 */
|
||||
.button {
|
||||
-fx-background-color: #4CAF50;
|
||||
-fx-text-fill: white;
|
||||
-fx-font-size: 14px;
|
||||
-fx-font-weight: bold;
|
||||
-fx-padding: 10px 20px;
|
||||
-fx-background-radius: 25px;
|
||||
-fx-border-radius: 25px;
|
||||
-fx-cursor: hand;
|
||||
-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.3), 5, 0, 0, 2);
|
||||
-fx-transition: all 0.3s;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
-fx-background-color: #45a049;
|
||||
-fx-scale-x: 1.05;
|
||||
-fx-scale-y: 1.05;
|
||||
-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.5), 8, 0, 0, 3);
|
||||
}
|
||||
|
||||
.button:pressed {
|
||||
-fx-background-color: #3d8b40;
|
||||
-fx-scale-x: 0.95;
|
||||
-fx-scale-y: 0.95;
|
||||
}
|
||||
|
||||
/* 次要按钮样式 */
|
||||
.button-secondary {
|
||||
-fx-background-color: #2196F3;
|
||||
}
|
||||
|
||||
.button-secondary:hover {
|
||||
-fx-background-color: #1976D2;
|
||||
}
|
||||
|
||||
.button-secondary:pressed {
|
||||
-fx-background-color: #0D47A1;
|
||||
}
|
||||
|
||||
/* 警告按钮样式 */
|
||||
.button-warning {
|
||||
-fx-background-color: #ff9800;
|
||||
}
|
||||
|
||||
.button-warning:hover {
|
||||
-fx-background-color: #f57c00;
|
||||
}
|
||||
|
||||
/* 危险按钮样式 */
|
||||
.button-danger {
|
||||
-fx-background-color: #f44336;
|
||||
}
|
||||
|
||||
.button-danger:hover {
|
||||
-fx-background-color: #d32f2f;
|
||||
}
|
||||
|
||||
/* 标签样式 */
|
||||
.label {
|
||||
-fx-text-fill: #333333;
|
||||
-fx-font-size: 14px;
|
||||
}
|
||||
|
||||
.label-title {
|
||||
-fx-font-size: 24px;
|
||||
-fx-font-weight: bold;
|
||||
-fx-text-fill: #2c3e50;
|
||||
-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.1), 3, 0, 1, 1);
|
||||
}
|
||||
|
||||
.label-subtitle {
|
||||
-fx-font-size: 18px;
|
||||
-fx-font-weight: bold;
|
||||
-fx-text-fill: #34495e;
|
||||
}
|
||||
|
||||
.label-info {
|
||||
-fx-text-fill: #7f8c8d;
|
||||
-fx-font-size: 12px;
|
||||
}
|
||||
|
||||
/* 输入框样式 */
|
||||
.text-field, .password-field {
|
||||
-fx-background-color: white;
|
||||
-fx-border-color: #bdc3c7;
|
||||
-fx-border-radius: 15px;
|
||||
-fx-background-radius: 15px;
|
||||
-fx-padding: 10px 15px;
|
||||
-fx-font-size: 14px;
|
||||
-fx-effect: innershadow(three-pass-box, rgba(0,0,0,0.1), 5, 0, 0, 2);
|
||||
}
|
||||
|
||||
.text-field:focused, .password-field:focused {
|
||||
-fx-border-color: #3498db;
|
||||
-fx-effect: dropshadow(three-pass-box, rgba(52, 152, 219, 0.3), 10, 0, 0, 3);
|
||||
}
|
||||
|
||||
/* 下拉框样式 */
|
||||
.combo-box {
|
||||
-fx-background-color: white;
|
||||
-fx-border-color: #bdc3c7;
|
||||
-fx-border-radius: 15px;
|
||||
-fx-background-radius: 15px;
|
||||
-fx-padding: 5px 15px;
|
||||
}
|
||||
|
||||
.combo-box .arrow-button {
|
||||
-fx-background-color: transparent;
|
||||
}
|
||||
|
||||
.combo-box .list-cell {
|
||||
-fx-background-color: white;
|
||||
-fx-text-fill: #333333;
|
||||
}
|
||||
|
||||
.combo-box .list-view {
|
||||
-fx-background-color: white;
|
||||
-fx-border-color: #bdc3c7;
|
||||
-fx-border-radius: 10px;
|
||||
-fx-background-radius: 10px;
|
||||
}
|
||||
|
||||
/* 单选按钮样式 */
|
||||
.radio-button {
|
||||
-fx-text-fill: #333333;
|
||||
-fx-font-size: 14px;
|
||||
-fx-padding: 5px;
|
||||
}
|
||||
|
||||
.radio-button .radio {
|
||||
-fx-background-color: white;
|
||||
-fx-border-color: #bdc3c7;
|
||||
-fx-border-radius: 50%;
|
||||
-fx-background-radius: 50%;
|
||||
}
|
||||
|
||||
.radio-button:selected .radio {
|
||||
-fx-background-color: #3498db;
|
||||
-fx-border-color: #2980b9;
|
||||
}
|
||||
|
||||
.radio-button .dot {
|
||||
-fx-background-color: white;
|
||||
-fx-background-radius: 50%;
|
||||
}
|
||||
|
||||
/* 容器样式 */
|
||||
.vbox {
|
||||
-fx-background-color: rgba(255, 255, 255, 0.5);
|
||||
-fx-background-radius: 16px;
|
||||
}
|
||||
|
||||
|
||||
.container {
|
||||
-fx-background-color: white;
|
||||
-fx-background-radius: 20px;
|
||||
-fx-border-radius: 20px;
|
||||
-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.1), 15, 0, 0, 5);
|
||||
-fx-padding: 30px;
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.ExamController">
|
||||
<children>
|
||||
<VBox alignment="CENTER" maxHeight="360.0" maxWidth="270.0" minHeight="360.0" minWidth="270.0" prefHeight="360.0" prefWidth="270.0" spacing="20.0" styleClass="vbox" stylesheets="@css/main.css">
|
||||
<padding>
|
||||
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
|
||||
</padding>
|
||||
<Label fx:id="titleLabel" style="-fx-font-size: 25; -fx-font-weight: bold;" text="难度" />
|
||||
<HBox alignment="CENTER" prefHeight="65.0" prefWidth="241.0">
|
||||
<children>
|
||||
<ComboBox fx:id="difficultyCombo" prefHeight="37.0" prefWidth="99.0" promptText="难度" />
|
||||
<Region prefHeight="65.0" prefWidth="31.0" />
|
||||
<Button fx:id="switchDiffButton" onAction="#handleSwitchDifficulty" prefHeight="39.0" prefWidth="97.0" styleClass="button-warning" text="切换难度" />
|
||||
</children>
|
||||
</HBox>
|
||||
<TextField fx:id="countField" alignment="CENTER" maxWidth="220.0" promptText="输入生成题目数量 (10-30)" />
|
||||
<Button fx:id="startButton" onAction="#handleStartExam" styleClass="button-secondary" text="生成试卷" />
|
||||
<Button fx:id="logoutButton" onAction="#handleLogout" styleClass="button-danger" text="退出登录" />
|
||||
<VBox.margin>
|
||||
<Insets left="30.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="400.0" prefWidth="600.0" spacing="15" stylesheets="@css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.ExamController">
|
||||
<VBox alignment="CENTER_LEFT" maxHeight="300.0" maxWidth="270.0" prefHeight="300.0" styleClass="vbox">
|
||||
<children>
|
||||
<Label fx:id="problemText" style="-fx-font-size: 12;">
|
||||
<VBox.margin>
|
||||
<Insets left="8.0" />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
<Region prefHeight="17.0" prefWidth="300.0" />
|
||||
<VBox fx:id="optionsBox" alignment="CENTER_LEFT" maxHeight="150.0" maxWidth="300.0" spacing="5" />
|
||||
<HBox alignment="CENTER">
|
||||
<children>
|
||||
<Button fx:id="nextButton" onAction="#handleNextProblem" text="下一题" />
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets left="30.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
</VBox>
|
||||
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.PasswordField?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.LoginController">
|
||||
<children>
|
||||
<VBox alignment="CENTER" maxHeight="360.0" maxWidth="270.0" minHeight="360.0" minWidth="270.0" prefHeight="360.0" prefWidth="270.0" spacing="20.0" styleClass="vbox">
|
||||
<Label style="-fx-font-size: 25; -fx-font-weight: bold;" text="登 录" />
|
||||
<TextField fx:id="usernameField" maxWidth="220.0" promptText="用户名/邮箱" />
|
||||
<PasswordField fx:id="passwordField" maxWidth="220.0" promptText="密码" />
|
||||
<HBox alignment="CENTER" prefHeight="23.0" prefWidth="143.0">
|
||||
<children>
|
||||
<Button fx:id="loginButton" onAction="#handleLogin" styleClass="button-secondary" text="登录" />
|
||||
<Region prefHeight="23.0" prefWidth="30.0" />
|
||||
<Button fx:id="registerButton" onAction="#handleRegister" text="注册" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Button fx:id="modifyPasswordButton" onAction="#handleModifyPassword" styleClass="button-warning" text="修改密码" />
|
||||
<Label fx:id="messageLabel" style="-fx-text-fill: red;" textAlignment="CENTER">
|
||||
<VBox.margin>
|
||||
<Insets />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
<VBox.margin>
|
||||
<Insets left="30.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.PasswordField?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="400.0" prefWidth="600.0" spacing="10" stylesheets="@css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.ModifyPasswordController">
|
||||
<VBox alignment="CENTER" maxHeight="360.0" maxWidth="270.0" minHeight="360.0" minWidth="270.0" prefHeight="360.0" prefWidth="270.0" spacing="12.0" styleClass="vbox">
|
||||
<children>
|
||||
<Label style="-fx-font-size: 25; -fx-font-weight: bold;" text="修改密码">
|
||||
<VBox.margin>
|
||||
<Insets top="8.0" />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
<TextField fx:id="usernameField" alignment="CENTER" maxWidth="220.0" promptText="用户名" />
|
||||
<PasswordField fx:id="oldPasswordField" alignment="CENTER" maxWidth="220.0" promptText="旧密码" />
|
||||
<PasswordField fx:id="newPasswordField" alignment="CENTER" maxWidth="220.0" promptText="新密码" />
|
||||
<PasswordField fx:id="confirmPasswordField" alignment="CENTER" maxWidth="220.0" promptText="确认新密码" />
|
||||
<HBox alignment="CENTER" prefHeight="66.0" prefWidth="560.0">
|
||||
<children>
|
||||
<Button fx:id="backButton" onAction="#handleBack" styleClass="button-danger" text="返回登录" />
|
||||
<Region prefHeight="45.0" prefWidth="33.0" />
|
||||
<Button fx:id="modifyButton" onAction="#handleModifyPassword" styleClass="button-secondary" text="确认修改" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="messageLabel" style="-fx-text-fill: red;" />
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets left="30.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
</VBox>
|
||||
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.RegisterController">
|
||||
<VBox alignment="CENTER" maxHeight="360.0" maxWidth="270.0" prefHeight="360.0" prefWidth="270.0" spacing="30.0" styleClass="vbox">
|
||||
<children>
|
||||
<Label style="-fx-font-size: 24; -fx-font-weight: bold;" text="注册 (2/3) - 验证注册码">
|
||||
<VBox.margin>
|
||||
<Insets top="12.0" />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
<Label fx:id="emailLabel" text="已发送到: " />
|
||||
<TextField fx:id="codeField" alignment="CENTER" maxWidth="220.0" prefWidth="201.0" promptText="请输入收到的 6 位注册码" />
|
||||
<Button fx:id="resendButton" onAction="#handleResendCode" prefHeight="39.0" prefWidth="96.0" text="重新发送" />
|
||||
<HBox alignment="CENTER" prefHeight="58.0" prefWidth="560.0">
|
||||
<children>
|
||||
<Button fx:id="backButton" onAction="#handleBack" styleClass="button-danger" text="返回" />
|
||||
<Region prefHeight="58.0" prefWidth="49.0" />
|
||||
<Button fx:id="verifyButton" onAction="#handleVerifyCode" styleClass="button-secondary" text="验证" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="messageLabel" style="-fx-text-fill: red;" />
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets left="30.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
</VBox>
|
||||
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.RegisterController">
|
||||
<children>
|
||||
<VBox alignment="CENTER" maxHeight="360.0" maxWidth="270.0" prefHeight="360.0" prefWidth="270.0" spacing="30.0" styleClass="vbox" stylesheets="@css/main.css">
|
||||
<Label style="-fx-font-size: 25; -fx-font-weight: bold;" text="注册 (1/3) - 邮箱验证" />
|
||||
<TextField fx:id="emailField" alignment="CENTER" maxWidth="220.0" promptText="邮箱" />
|
||||
<Button fx:id="sendCodeButton" onAction="#handleSendCode" prefHeight="39.0" prefWidth="110.0" styleClass="button-secondary" text="发送注册码" />
|
||||
<Button fx:id="backButton" onAction="#handleBack" styleClass="button-danger" text="返回" />
|
||||
<Label fx:id="messageLabel" style="-fx-text-fill: red;" />
|
||||
<VBox.margin>
|
||||
<Insets left="30.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
</children>
|
||||
</VBox>
|
||||
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.PasswordField?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.RegisterController">
|
||||
<VBox alignment="CENTER" maxHeight="360.0" maxWidth="270.0" minHeight="360.0" minWidth="270.0" prefHeight="360.0" prefWidth="270.0" spacing="15.0" styleClass="vbox">
|
||||
<children>
|
||||
<Label fx:id="titleLabel" style="-fx-font-size: 25; -fx-font-weight: bold;" text="注册 (3/3) - 设置密码" />
|
||||
<TextField fx:id="usernameField" alignment="CENTER" maxWidth="220.0" promptText="设置用户名" />
|
||||
<PasswordField fx:id="passwordField" alignment="CENTER" maxWidth="220.0" promptText="设置密码" />
|
||||
<PasswordField fx:id="confirmPasswordField" alignment="CENTER" maxWidth="220.0" promptText="确认密码" />
|
||||
<Button fx:id="completeButton" onAction="#handleCompleteRegistration" prefWidth="96.0" styleClass="button-secondary" text="完成注册" />
|
||||
<Button fx:id="backButton" onAction="#handleBack" styleClass="button-danger" text="返回" />
|
||||
<Label fx:id="messageLabel" style="-fx-text-fill: red;" />
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets left="30.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
</VBox>
|
||||
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.image.Image?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="400.0" prefWidth="600.0" stylesheets="@css/main.css" xmlns="http://javafx.com/javafx/16" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ui.ExamController">
|
||||
<VBox alignment="CENTER" maxHeight="360.0" maxWidth="270.0" minHeight="360.0" minWidth="270.0" prefHeight="360.0" prefWidth="270.0" spacing="20.0" styleClass="vbox">
|
||||
<children>
|
||||
<Label fx:id="scoreLabel" style="-fx-font-size: 25; -fx-font-weight: bold;" text="恭喜您完成答题!" />
|
||||
<Label fx:id="finalScoreLabel" style="-fx-font-size: 15;" />
|
||||
<ImageView fitHeight="70.0" fitWidth="130.0" pickOnBounds="true" preserveRatio="true">
|
||||
<image>
|
||||
<Image url="@css/2.gif" />
|
||||
</image>
|
||||
</ImageView>
|
||||
<Button fx:id="continueButton" onAction="#handleContinue" prefHeight="39.0" prefWidth="218.0" styleClass="button-secondary" text="继续做题 (返回选择难度)" />
|
||||
<HBox alignment="CENTER" prefHeight="0.0" prefWidth="270.0">
|
||||
<children>
|
||||
<Button fx:id="logoutButton" onAction="#handleLogout" styleClass="button-warning" text="退出登录" />
|
||||
<Region prefHeight="39.0" prefWidth="28.0" />
|
||||
<Button fx:id="exitButton" onAction="#handleExit" styleClass="button-danger" text="退出程序" />
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets left="30.0" />
|
||||
</VBox.margin>
|
||||
</VBox>
|
||||
</VBox>
|
||||
@ -0,0 +1,35 @@
|
||||
package ui;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.scene.image.Image;
|
||||
|
||||
public class MainApplication extends Application {
|
||||
|
||||
@Override
|
||||
public void start(Stage primaryStage) throws Exception {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Login.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
// 获取控制器并设置primaryStage
|
||||
LoginController controller = loader.getController();
|
||||
controller.setPrimaryStage(primaryStage);
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
|
||||
// 设置窗口图标
|
||||
try {
|
||||
Image icon = new Image(getClass().getResourceAsStream("/fxml/css/3.png"));
|
||||
primaryStage.getIcons().add(icon);
|
||||
} catch (Exception e) {
|
||||
System.err.println("无法加载图标文件: " + e.getMessage());
|
||||
}
|
||||
|
||||
primaryStage.setTitle("小初高数学学习软件");
|
||||
primaryStage.setScene(scene);
|
||||
primaryStage.show();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
package ui;
|
||||
|
||||
import auth.AuthService;
|
||||
import auth.User;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ModifyPasswordController {
|
||||
|
||||
@FXML private TextField usernameField;
|
||||
@FXML private PasswordField oldPasswordField;
|
||||
@FXML private PasswordField newPasswordField;
|
||||
@FXML private PasswordField confirmPasswordField;
|
||||
@FXML private Label messageLabel;
|
||||
|
||||
private final AuthService authService = new AuthService();
|
||||
private Stage primaryStage;
|
||||
|
||||
public void setPrimaryStage(Stage primaryStage) {
|
||||
this.primaryStage = primaryStage;
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleModifyPassword() {
|
||||
String username = usernameField.getText().trim();
|
||||
String oldPassword = oldPasswordField.getText();
|
||||
String newPassword = newPasswordField.getText();
|
||||
String confirmPassword = confirmPasswordField.getText();
|
||||
|
||||
User user = authService.login(username, oldPassword);
|
||||
if (user == null) {
|
||||
messageLabel.setText("错误:用户名或旧密码不正确。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!newPassword.equals(confirmPassword)) {
|
||||
messageLabel.setText("错误:两次输入的新密码不一致。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AuthService.isPasswordValid(newPassword)) {
|
||||
messageLabel.setText("错误:新密码不符合要求 (6-10位, 需含大小写字母和数字)。");
|
||||
return;
|
||||
}
|
||||
|
||||
if (authService.updatePassword(username, newPassword)) {
|
||||
showAlert("成功", "密码修改成功,请重新登录。");
|
||||
showLoginScreen();
|
||||
} else {
|
||||
messageLabel.setText("错误:密码修改失败,请稍后重试。");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleBack() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Login.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
LoginController controller = loader.getController();
|
||||
|
||||
if (primaryStage != null) {
|
||||
controller.setPrimaryStage(primaryStage);
|
||||
Scene scene = new Scene(root);
|
||||
primaryStage.setScene(scene);
|
||||
} else {
|
||||
Stage currentStage = (Stage) usernameField.getScene().getWindow();
|
||||
controller.setPrimaryStage(currentStage);
|
||||
Scene scene = new Scene(root);
|
||||
currentStage.setScene(scene);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
showAlert("错误", "加载登录界面失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void showLoginScreen() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Login.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
LoginController controller = loader.getController();
|
||||
controller.setPrimaryStage(primaryStage);
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
primaryStage.setScene(scene);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
showAlert("错误", "加载登录界面失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void showAlert(String title, String message) {
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle(title);
|
||||
alert.setContentText(message);
|
||||
alert.showAndWait();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,206 @@
|
||||
package ui;
|
||||
|
||||
import auth.AuthService;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RegisterController {
|
||||
|
||||
@FXML private TextField emailField;
|
||||
@FXML private TextField codeField;
|
||||
@FXML private TextField usernameField;
|
||||
@FXML private PasswordField passwordField;
|
||||
@FXML private PasswordField confirmPasswordField;
|
||||
@FXML private Label messageLabel;
|
||||
@FXML private Label emailLabel;
|
||||
@FXML private Label titleLabel;
|
||||
|
||||
private final AuthService authService = new AuthService();
|
||||
private final Map<String, String> pendingRegistrations = new HashMap<>();
|
||||
private Stage primaryStage;
|
||||
private String currentEmail;
|
||||
|
||||
public void setPrimaryStage(Stage primaryStage) {
|
||||
this.primaryStage = primaryStage;
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleSendCode() {
|
||||
String email = emailField.getText().trim();
|
||||
if (!authService.validateEmail(email)) {
|
||||
messageLabel.setText("错误:邮箱格式不正确。");
|
||||
return;
|
||||
}
|
||||
if (authService.isUsernameOrEmailTaken(null, email)) {
|
||||
messageLabel.setText("错误:该邮箱已被注册。");
|
||||
return;
|
||||
}
|
||||
|
||||
String code = authService.sendVerificationCode(email);
|
||||
if (code != null) {
|
||||
pendingRegistrations.put(email, code);
|
||||
currentEmail = email;
|
||||
showAlert("成功", "验证码已发送到您的邮箱,请查收!");
|
||||
showRegisterCodeScreen();
|
||||
} else {
|
||||
messageLabel.setText("错误:验证码发送失败,请检查邮箱或服务器设置。");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleVerifyCode() {
|
||||
String inputCode = codeField.getText().trim();
|
||||
String storedCode = pendingRegistrations.get(currentEmail);
|
||||
|
||||
if (inputCode.equals(storedCode)) {
|
||||
messageLabel.setText("验证成功!");
|
||||
showRegisterPasswordScreen();
|
||||
} else {
|
||||
messageLabel.setText("错误:验证码不正确。");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleResendCode() {
|
||||
String newCode = authService.sendVerificationCode(currentEmail);
|
||||
if (newCode != null) {
|
||||
pendingRegistrations.put(currentEmail, newCode);
|
||||
messageLabel.setText("新的验证码已发送。");
|
||||
} else {
|
||||
messageLabel.setText("错误:重发失败。");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleCompleteRegistration() {
|
||||
String username = usernameField.getText().trim();
|
||||
String password = passwordField.getText();
|
||||
String confirmPassword = confirmPasswordField.getText();
|
||||
|
||||
if (!validatePasswordSetup(username, password, confirmPassword)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (authService.registerUser(username, password, currentEmail)) {
|
||||
pendingRegistrations.remove(currentEmail);
|
||||
showAlert("成功", "注册成功,请登录。");
|
||||
showLoginScreen();
|
||||
} else {
|
||||
messageLabel.setText("致命错误:注册失败,请联系管理员。");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void handleBack() {
|
||||
showLoginScreen();
|
||||
}
|
||||
|
||||
private boolean validatePasswordSetup(String username, String password, String confirmPassword) {
|
||||
if (authService.isUsernameOrEmailTaken(username, null)) {
|
||||
messageLabel.setText("错误:该用户名已被占用。");
|
||||
return false;
|
||||
}
|
||||
if (!password.equals(confirmPassword)) {
|
||||
messageLabel.setText("错误:两次密码输入不一致。");
|
||||
return false;
|
||||
}
|
||||
if (!AuthService.isPasswordValid(password)) {
|
||||
messageLabel.setText("错误:密码不符合要求 (6-10位, 需含大小写字母和数字)。");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void showRegisterCodeScreen() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/register-code.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
RegisterController controller = loader.getController();
|
||||
controller.setPrimaryStage(primaryStage);
|
||||
controller.setCurrentEmail(currentEmail);
|
||||
controller.setPendingRegistrations(pendingRegistrations);
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
primaryStage.setScene(scene);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
showAlert("错误", "加载验证码界面失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void showRegisterPasswordScreen() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/register-password.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
RegisterController controller = loader.getController();
|
||||
controller.setPrimaryStage(primaryStage);
|
||||
controller.setCurrentEmail(currentEmail);
|
||||
controller.setPendingRegistrations(pendingRegistrations);
|
||||
|
||||
Scene scene = new Scene(root);
|
||||
primaryStage.setScene(scene);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
showAlert("错误", "加载密码设置界面失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void showLoginScreen() {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Login.fxml"));
|
||||
Parent root = loader.load();
|
||||
|
||||
LoginController controller = loader.getController();
|
||||
|
||||
if (primaryStage != null) {
|
||||
controller.setPrimaryStage(primaryStage);
|
||||
Scene scene = new Scene(root);
|
||||
primaryStage.setScene(scene);
|
||||
} else {
|
||||
Stage currentStage = (Stage) emailField.getScene().getWindow();
|
||||
controller.setPrimaryStage(currentStage);
|
||||
Scene scene = new Scene(root);
|
||||
currentStage.setScene(scene);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
showAlert("错误", "加载登录界面失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Setters for sharing data between different registration screens
|
||||
public void setCurrentEmail(String email) {
|
||||
this.currentEmail = email;
|
||||
if (emailLabel != null) {
|
||||
emailLabel.setText("已发送到: " + email);
|
||||
}
|
||||
if (titleLabel != null) {
|
||||
titleLabel.setText("注册 (3/3) - 设置密码 (邮箱: " + email + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public void setPendingRegistrations(Map<String, String> pendingRegistrations) {
|
||||
this.pendingRegistrations.clear();
|
||||
this.pendingRegistrations.putAll(pendingRegistrations);
|
||||
}
|
||||
|
||||
private void showAlert(String title, String message) {
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle(title);
|
||||
alert.setContentText(message);
|
||||
alert.showAndWait();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue