feat(gui): 添加用户登录功能- 新增 LoginWindow 类实现登录界面

- 在主程序启动时显示登录窗口
- 实现用户注册和密码重置功能
- 添加在线验证和用户标签相关类
This commit is contained in:
tzdwindows 7
2025-03-02 20:53:36 +08:00
parent b06c8fd4e7
commit 0310d046aa
8 changed files with 537 additions and 41 deletions

View File

@@ -342,6 +342,7 @@ public class AxisInnovatorsBox {
try {
//main.initLog4j2();
main.setTopic();
List<Map<String, String>> validFiles = ArgsParser.parseArgs(args);
for (Map<String, String> fileInfo : validFiles) {
String extension = fileInfo.get("extension");
@@ -355,6 +356,11 @@ public class AxisInnovatorsBox {
main.thread = new Thread(() -> {
try {
// 登录窗口
LoginWindow.createAndShow();
// 主任务1加载插件
logger.info("Loaded plugins Started");
main.progressBarManager.updateMainProgress(++main.completedTasks);

View File

@@ -3,6 +3,7 @@ package com.axis.innovators.box;
import com.axis.innovators.box.decompilation.gui.ModernJarViewer;
import com.axis.innovators.box.events.GlobalEventBus;
import com.axis.innovators.box.events.OpenFileEvents;
import com.axis.innovators.box.gui.LoginWindow;
import com.axis.innovators.box.tools.ArgsParser;
import com.axis.innovators.box.tools.FolderCleaner;
import com.axis.innovators.box.tools.FolderCreator;
@@ -42,6 +43,7 @@ public class Main {
return;
}
}
AxisInnovatorsBox.run(args);
}
}

View File

@@ -205,6 +205,8 @@ public class FridaWindow extends WindowsJDialog {
styleMenuItem(aboutItem);
aboutItem.addActionListener(e -> showAboutDialog());
helpMenu.add(aboutItem);
menuBar.add(fileMenu);
menuBar.add(helpMenu);
setJMenuBar(menuBar);

View File

@@ -0,0 +1,436 @@
package com.axis.innovators.box.gui;
import com.axis.innovators.box.verification.UserTags;
import com.axis.innovators.box.verification.VerificationService;
import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatIntelliJLaf;
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* 用于登录的主窗口
* @author tzdwindows 7
*/
public class LoginWindow {
private static final AtomicReference<UserTags> loginResult = new AtomicReference<>(UserTags.None);
private JDialog dialog;
private JTextField emailField;
private JPasswordField passwordField;
private JCheckBox showPasswordCheckBox;
private static final int FIELD_WIDTH = 300;
private static final int FIELD_HEIGHT = 35;
public static UserTags createAndShow() {
AtomicReference<UserTags> result = new AtomicReference<>(UserTags.None);
try {
SwingUtilities.invokeAndWait(() -> {
LoginWindow loginWindow = new LoginWindow();
loginWindow.dialog.setVisible(true);
result.set(loginResult.get());
if(result.get() == UserTags.None) {
System.exit(0);
}
});
} catch (Exception e) {
e.printStackTrace();
}
return result.get();
}
private LoginWindow() {
setupLookAndFeel();
createMainDialog();
buildLoginUI();
}
private void setupLookAndFeel() {
try {
UIManager.setLookAndFeel(new FlatDarculaLaf());
// 自定义输入框样式
UIManager.put("Component.arc", 12);
UIManager.put("TextComponent.arc", 12);
UIManager.put("Button.arc", 8);
UIManager.put("ProgressBar.arc", 8);
UIManager.put("TextComponent.background", new Color(0x383838));
UIManager.put("TextField.placeholderForeground", new Color(0x808080));
} catch (UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
}
private void createMainDialog() {
dialog = new JDialog((Frame) null, "AXIS 安全认证", true);
dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
dialog.setSize(380, 500);
dialog.setLocationRelativeTo(null);
dialog.setResizable(false);
dialog.setLayout(new BorderLayout());
}
private void buildLoginUI() {
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
JLabel titleLabel = new JLabel("欢迎登录");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(titleLabel);
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
JPanel inputContainer = new JPanel();
inputContainer.setLayout(new BoxLayout(inputContainer, BoxLayout.Y_AXIS));
inputContainer.setOpaque(false);
inputContainer.setAlignmentX(Component.CENTER_ALIGNMENT);
inputContainer.add(createInputField("账号", buildEmailField()));
inputContainer.add(Box.createRigidArea(new Dimension(0, 10)));
inputContainer.add(createInputField("密码", buildPasswordField()));
mainPanel.add(inputContainer);
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
JButton loginButton = createLoginButton();
loginButton.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(loginButton);
JPanel linksPanel = createUtilityLinks();
linksPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
mainPanel.add(linksPanel);
mainPanel.add(Box.createVerticalGlue());
dialog.add(mainPanel, BorderLayout.CENTER);
}
private JComponent buildEmailField() {
emailField = new JTextField();
customizeTextField(emailField, "请输入邮箱或手机号");
return emailField;
}
private JComponent buildPasswordField() {
JPanel passwordPanel = new JPanel(new BorderLayout());
passwordPanel.setOpaque(false);
passwordPanel.setBorder(new RoundBorder(8, new Color(0x454545)));
// 密码输入框
passwordField = new JPasswordField();
passwordField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
passwordField.putClientProperty("JTextField.placeholderText", "请输入密码");
passwordField.setMaximumSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT));
passwordField.setPreferredSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT));
passwordField.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 5));
passwordPanel.add(passwordField, BorderLayout.CENTER);
// 显示密码按钮
JPanel togglePanel = new JPanel(new BorderLayout());
togglePanel.setOpaque(false);
togglePanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
showPasswordCheckBox = new JCheckBox();
showPasswordCheckBox.setOpaque(false);
showPasswordCheckBox.setPreferredSize(new Dimension(32, 32));
showPasswordCheckBox.setBackground(new Color(0x46494B));
showPasswordCheckBox.setIcon(UIManager.getIcon("PasswordView.icon"));
showPasswordCheckBox.setSelectedIcon(UIManager.getIcon("PasswordHide.icon"));
showPasswordCheckBox.addActionListener(e -> togglePasswordVisibility());
togglePanel.add(showPasswordCheckBox, BorderLayout.CENTER);
passwordPanel.add(togglePanel, BorderLayout.EAST);
return passwordPanel;
}
private void customizeTextField(JComponent field, String placeholder) {
field.setPreferredSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT));
field.setMaximumSize(new Dimension(FIELD_WIDTH, FIELD_HEIGHT));
field.putClientProperty("JComponent.roundRect", true);
field.putClientProperty("JTextField.placeholderText", placeholder);
field.setFont(new Font("微软雅黑", Font.PLAIN, 14));
field.setBorder(BorderFactory.createCompoundBorder(
new RoundBorder(8, new Color(0x454545)),
BorderFactory.createEmptyBorder(10, 15, 10, 15)
));
}
private JPanel createInputField(String label, JComponent field) {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
panel.setOpaque(false);
panel.setMaximumSize(new Dimension(280, 62));
JLabel titleLabel = new JLabel(label);
titleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 13));
titleLabel.setForeground(new Color(0x9E9E9E));
titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
panel.add(titleLabel);
panel.add(Box.createVerticalStrut(8));
panel.add(field);
return panel;
}
private JButton createLoginButton() {
JButton button = new JButton("立即登录");
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setForeground(Color.WHITE);
button.setBackground(new Color(0x2B579A));
button.setPreferredSize(new Dimension(285, 40));
button.setMaximumSize(new Dimension(285, 40));
button.setAlignmentX(Component.CENTER_ALIGNMENT);
button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
button.addActionListener(e -> attemptLogin());
// 悬停效果
button.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
button.setBackground(new Color(0x3C6DB0));
}
public void mouseExited(java.awt.event.MouseEvent evt) {
button.setBackground(new Color(0x2B579A));
}
});
return button;
}
private static class RoundBorder extends LineBorder {
private final int radius;
public RoundBorder(int radius, Color color) {
super(color, 1);
this.radius = radius;
}
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.drawRoundRect(x, y, width-1, height-1, radius, radius);
g2.dispose();
}
}
private JPanel createUtilityLinks() {
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
panel.setOpaque(false);
JButton registerBtn = createTextButton("注册账号", this::showRegister);
JButton forgotBtn = createTextButton("忘记密码", this::showForgotPassword);
panel.add(Box.createHorizontalGlue());
panel.add(registerBtn);
panel.add(Box.createHorizontalStrut(15));
panel.add(forgotBtn);
panel.add(Box.createHorizontalGlue());
return panel;
}
private JButton createTextButton(String text, Runnable action) {
JButton button = new JButton(text);
button.setForeground(new Color(0x8AB4F8));
button.setFont(new Font("微软雅黑", Font.PLAIN, 12));
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setFocusPainted(false);
button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
button.addActionListener(e -> action.run());
return button;
}
private void togglePasswordVisibility() {
if (showPasswordCheckBox.isSelected()) {
passwordField.setEchoChar((char) 0);
} else {
passwordField.setEchoChar('•');
}
}
private void attemptLogin() {
String email = emailField.getText().trim();
String password = new String(passwordField.getPassword()).trim();
if (email.isEmpty() || password.isEmpty()) {
showError("请输入完整的登录信息");
return;
}
loginResult.set(VerificationService.determineUserType(null));
dialog.dispose();
}
private void showError(String message) {
JOptionPane.showMessageDialog(dialog, message, "验证错误",
JOptionPane.ERROR_MESSAGE);
}
private void showRegister() {
JDialog registerDialog = new JDialog(dialog, "注册新账号", true);
registerDialog.setSize(380, 500);
registerDialog.setLocationRelativeTo(dialog);
registerDialog.setResizable(false);
registerDialog.setLayout(new BorderLayout());
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
// 标题
JLabel titleLabel = new JLabel("新用户注册");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(titleLabel);
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
// 输入容器
JPanel inputContainer = new JPanel();
inputContainer.setLayout(new BoxLayout(inputContainer, BoxLayout.Y_AXIS));
inputContainer.setOpaque(false);
// 用户名
JTextField usernameField = new JTextField();
customizeTextField(usernameField, "请输入用户名");
inputContainer.add(createInputField("用户名", usernameField));
inputContainer.add(Box.createRigidArea(new Dimension(0, 10)));
// 邮箱
JTextField emailField = new JTextField();
customizeTextField(emailField, "请输入邮箱");
inputContainer.add(createInputField("邮箱", emailField));
inputContainer.add(Box.createRigidArea(new Dimension(0, 10)));
// 密码
JPasswordField passwordField = new JPasswordField();
customizeTextField(passwordField, "请输入密码");
inputContainer.add(createInputField("密码", passwordField));
inputContainer.add(Box.createRigidArea(new Dimension(0, 10)));
// 确认密码
JPasswordField confirmField = new JPasswordField();
customizeTextField(confirmField, "请再次输入密码");
inputContainer.add(createInputField("确认密码", confirmField));
mainPanel.add(inputContainer);
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
// 注册按钮
JButton regButton = new JButton("立即注册");
styleButton(regButton);
regButton.addActionListener(e -> {
String pwd = new String(passwordField.getPassword());
String confirm = new String(confirmField.getPassword());
if(!pwd.equals(confirm)) {
JOptionPane.showMessageDialog(registerDialog, "两次输入的密码不一致", "注册错误",
JOptionPane.ERROR_MESSAGE);
return;
}
// 调用验证服务
boolean success = VerificationService.registerUser(
usernameField.getText(),
emailField.getText(),
pwd
);
if(success) {
JOptionPane.showMessageDialog(registerDialog, "注册成功,请登录", "注册成功",
JOptionPane.INFORMATION_MESSAGE);
registerDialog.dispose();
} else {
JOptionPane.showMessageDialog(registerDialog, "注册失败,请检查信息", "注册错误",
JOptionPane.ERROR_MESSAGE);
}
});
mainPanel.add(regButton);
// 返回登录链接
JButton backBtn = createTextButton("返回登录", registerDialog::dispose);
backBtn.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(Box.createRigidArea(new Dimension(0, 15)));
mainPanel.add(backBtn);
registerDialog.add(mainPanel, BorderLayout.CENTER);
registerDialog.setVisible(true);
}
private void showForgotPassword() {
JDialog forgotDialog = new JDialog(dialog, "找回密码", true);
forgotDialog.setSize(380, 350);
forgotDialog.setLocationRelativeTo(dialog);
forgotDialog.setResizable(false);
forgotDialog.setLayout(new BorderLayout());
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
JLabel titleLabel = new JLabel("找回密码");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 24));
titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(titleLabel);
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
// 邮箱输入
JTextField emailField = new JTextField();
customizeTextField(emailField, "请输入注册邮箱");
mainPanel.add(createInputField("注册邮箱", emailField));
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
// 提交按钮
JButton submitBtn = new JButton("发送重置邮件");
styleButton(submitBtn);
submitBtn.addActionListener(e -> {
if(VerificationService.sendPasswordReset(emailField.getText())) {
JOptionPane.showMessageDialog(forgotDialog, "重置邮件已发送,请查收", "操作成功",
JOptionPane.INFORMATION_MESSAGE);
forgotDialog.dispose();
} else {
JOptionPane.showMessageDialog(forgotDialog, "邮箱未注册或发送失败", "操作失败",
JOptionPane.ERROR_MESSAGE);
}
});
mainPanel.add(submitBtn);
// 返回链接
JButton backBtn = createTextButton("返回登录", forgotDialog::dispose);
backBtn.setAlignmentX(Component.CENTER_ALIGNMENT);
mainPanel.add(Box.createRigidArea(new Dimension(0, 15)));
mainPanel.add(backBtn);
forgotDialog.add(mainPanel, BorderLayout.CENTER);
forgotDialog.setVisible(true);
}
// 通用按钮样式方法
private void styleButton(JButton button) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setForeground(Color.WHITE);
button.setBackground(new Color(0x2B579A));
button.setPreferredSize(new Dimension(285, 40));
button.setMaximumSize(new Dimension(285, 40));
button.setAlignmentX(Component.CENTER_ALIGNMENT);
button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
// 悬停效果
button.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseEntered(java.awt.event.MouseEvent evt) {
button.setBackground(new Color(0x3C6DB0));
}
public void mouseExited(java.awt.event.MouseEvent evt) {
button.setBackground(new Color(0x2B579A));
}
});
}
}

View File

@@ -65,43 +65,9 @@ public class MainWindow extends JFrame {
getContentPane().setBackground(new Color(0, 0, 0, 0));
JPanel mainPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Color color1 = new Color(235, 241, 250);
Color color2 = new Color(255, 255, 255);
GradientPaint gp = new GradientPaint(0, 0, color1, getWidth(), getHeight(), color2);
g2d.setPaint(gp);
g2d.fillRect(0, 0, getWidth(), getHeight());
if (isBackground) {
try {
ImageIcon backgroundImage = LoadIcon.loadIcon("start_page.png", 500);
if (isBlur) {
BufferedImage bufferedImage = toBufferedImage(backgroundImage.getImage());
BufferedImage blurredImage = applyGaussianBlur(bufferedImage, 5);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.1f));
int x = (getWidth() - blurredImage.getWidth()) / 2;
int y = (getHeight() - blurredImage.getHeight()) / 2;
g2d.drawImage(blurredImage, x, y, this);
} else {
int x = (getWidth() - backgroundImage.getIconWidth()) / 2;
int y = (getHeight() - backgroundImage.getIconHeight()) / 2;
g2d.drawImage(backgroundImage.getImage(), x, y, this);
}
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
} catch (Exception e) {
logger.error("Failed to load background image", e);
}
}
}
};
JPanel mainPanel = new JPanel();
mainPanel.setOpaque(true);
mainPanel.putClientProperty("FlatLaf.style", "background: null;");
mainPanel.setLayout(new BorderLayout(20, 20));
mainPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
@@ -211,7 +177,7 @@ public class MainWindow extends JFrame {
tabbedPane.setBackground(new Color(0, 0, 0, 0));
tabbedPane.setBorder(null);
tabbedPane.setUI(new CustomTabbedPaneUI());
//tabbedPane.setUI(new CustomTabbedPaneUI());
for (ToolCategory category : categories) {
JPanel toolsPanel = createToolsPanel(category);
@@ -223,7 +189,7 @@ public class MainWindow extends JFrame {
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
JScrollBar verticalScrollBar = scrollPane.getVerticalScrollBar();
verticalScrollBar.setUI(new CustomScrollBarUI());
//verticalScrollBar.setUI(new CustomScrollBarUI());
verticalScrollBar.setPreferredSize(new Dimension(10, 100));
if (category.getIcon() == null){
@@ -261,7 +227,7 @@ public class MainWindow extends JFrame {
// 创建标题
JLabel title = new JLabel(LanguageManager.getLoadedLanguages().getText("mainWindow.title.2"));
title.setFont(new Font("微软雅黑", Font.BOLD, 28));
title.setForeground(new Color(44, 62, 80));
title.setForeground(new Color(255, 255, 255));
JButton settings = new JButton(LoadIcon.loadIcon("settings.png", 32));
settings.putClientProperty(FlatClientProperties.BUTTON_TYPE, FlatClientProperties.BUTTON_TYPE_BORDERLESS);
@@ -349,7 +315,7 @@ public class MainWindow extends JFrame {
card.setPreferredSize(new Dimension(200, 150));
card.setMinimumSize(new Dimension(100, 75));
card.setLayout(new BorderLayout(15, 15));
card.setBackground(CARD_COLOR);
//card.setBackground(CARD_COLOR);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(new Color(225, 229, 234), 1),
BorderFactory.createEmptyBorder(20, 20, 20, 20)
@@ -371,12 +337,12 @@ public class MainWindow extends JFrame {
JLabel titleLabel = new JLabel(tool.getTitle());
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
titleLabel.setForeground(new Color(44, 62, 80));
titleLabel.setForeground(new Color(255, 255, 255));
titleLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
JTextArea descArea = new JTextArea(tool.getDescription());
descArea.setFont(new Font("微软雅黑", Font.PLAIN, 14));
descArea.setForeground(new Color(127, 140, 153));
descArea.setForeground(new Color(177, 177, 177));
descArea.setLineWrap(true);
descArea.setWrapStyleWord(true);
descArea.setEditable(false);

View File

@@ -0,0 +1,25 @@
package com.axis.innovators.box.verification;
import java.util.UUID;
/**
* 在线验证用户身份
* @author tzdwindows 7
*/
public class OnlineVerification {
public String onlineVerification;
public UserTags userTags;
public OnlineVerification(){
}
OnlineVerification(String onlineVerification, UserTags userTags){
this.onlineVerification = onlineVerification;
this.userTags = userTags;
}
public OnlineVerification validateLogin(String identifier, String password){
return new OnlineVerification(identifier, UserTags.RegularUsers);
}
}

View File

@@ -0,0 +1,32 @@
package com.axis.innovators.box.verification;
/**
* 用户标签组
* @author tzdwindows 7
*/
public enum UserTags {
/**
* 没有登录的标签
*/
None,
/**
* 普通用户标签
*/
RegularUsers,
/**
* 管理员标签
*/
AdminUsers,
/**
* VIP用户标签
*/
VipUsers,
/**
* SVip用户标签
*/
SVipUsers,
/**
* 企业用户标签
*/
EnterpriseUsers
}

View File

@@ -0,0 +1,27 @@
package com.axis.innovators.box.verification;
/**
* @author tzdwindows 7
*/
public class VerificationService {
public static OnlineVerification validateLogin(String identifier, String password) {
return null;
}
public static UserTags determineUserType(OnlineVerification identifier) {
return UserTags.RegularUsers;
}
/**
* 发送密码重置链接给用户
* @param text
* @return
*/
public static boolean sendPasswordReset(String text) {
return true;
}
public static boolean registerUser(String text, String text1, String pwd) {
return true;
}
}