张世豪
昨天 00f4e4fc6e53a26cf3dc67d57d8b00536634d707
src/denglu/RegistrationFrame.java
@@ -1,11 +1,16 @@
package denglu;
import ui.UIConfig;
import login.EmailCodeSender;
import login.UserRegister;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.HashMap;
import java.util.Map;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.util.Arrays;
public class RegistrationFrame extends JFrame {
    private JTextField userField;
@@ -17,6 +22,7 @@
    private JButton cancelButton;
    private JButton sendCodeButton;
    private JLabel userLabel, emailLabel, verificationCodeLabel, passLabel, confirmPassLabel;
    private JLabel passwordHintLabel, matchStatusLabel, emailHintLabel;
    
    // 主题颜色
    private final Color THEME_COLOR = new Color(46, 139, 87);
@@ -30,7 +36,6 @@
    // 验证码相关
    private Timer countdownTimer;
    private int countdownSeconds = 60;
    private String generatedVerificationCode;
    public RegistrationFrame(Denglu parent, String languageCode) {
        this.parentFrame = parent;
@@ -225,13 +230,23 @@
        emailLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        emailField = new JTextField();
        emailField.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35));
        emailField.setFont(new Font("PingFang SC", Font.PLAIN, 14));
        emailField.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(200, 200, 200)),
            BorderFactory.createEmptyBorder(5, 8, 5, 8)
        ));
        emailField.setAlignmentX(Component.LEFT_ALIGNMENT);
        JPanel emailContainer = new JPanel(new BorderLayout());
        emailContainer.setBackground(Color.WHITE);
        emailContainer.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35));
        emailContainer.setAlignmentX(Component.LEFT_ALIGNMENT);
        emailContainer.add(emailField, BorderLayout.CENTER);
        emailHintLabel = new JLabel("");
        emailHintLabel.setFont(new Font("PingFang SC", Font.PLAIN, 12));
        emailHintLabel.setForeground(Color.RED);
        emailHintLabel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
        emailContainer.add(emailHintLabel, BorderLayout.EAST);
        
        // 验证码 - 标签左对齐
        verificationCodeLabel = new JLabel("验证码");
@@ -281,13 +296,8 @@
        passLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        passField = new JPasswordField();
        passField.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35));
        passField.setFont(new Font("PingFang SC", Font.PLAIN, 14));
        passField.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(200, 200, 200)),
            BorderFactory.createEmptyBorder(5, 8, 5, 8)
        ));
        passField.setAlignmentX(Component.LEFT_ALIGNMENT);
        JPanel passPanel = createPasswordPanel(passField);
        
        // 确认密码 - 标签左对齐
        confirmPassLabel = new JLabel("确认密码");
@@ -296,13 +306,20 @@
        confirmPassLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        confirmPassField = new JPasswordField();
        confirmPassField.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35));
        confirmPassField.setFont(new Font("PingFang SC", Font.PLAIN, 14));
        confirmPassField.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(200, 200, 200)),
            BorderFactory.createEmptyBorder(5, 8, 5, 8)
        ));
        confirmPassField.setAlignmentX(Component.LEFT_ALIGNMENT);
        JPanel confirmPassPanel = createPasswordPanel(confirmPassField);
        // 密码不一致提示
        matchStatusLabel = new JLabel(" ");
        matchStatusLabel.setFont(new Font("PingFang SC", Font.PLAIN, 12));
        matchStatusLabel.setForeground(Color.RED);
        matchStatusLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
        // 密码长度提示
        passwordHintLabel = new JLabel(" ");
        passwordHintLabel.setFont(new Font("PingFang SC", Font.PLAIN, 12));
        passwordHintLabel.setForeground(Color.RED);
        passwordHintLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
        
        // 注册按钮 - 单独一行,长度与文本框相同
        registerButton = new JButton("注册");
@@ -343,7 +360,7 @@
        formPanel.add(Box.createRigidArea(new Dimension(0, 10)));
        formPanel.add(emailLabel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 3)));
        formPanel.add(emailField);
        formPanel.add(emailContainer);
        formPanel.add(Box.createRigidArea(new Dimension(0, 10)));
        formPanel.add(verificationCodeLabel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 3)));
@@ -353,12 +370,16 @@
        formPanel.add(Box.createRigidArea(new Dimension(0, 10)));
        formPanel.add(passLabel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 3)));
        formPanel.add(passField);
        formPanel.add(passPanel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 10)));
        formPanel.add(confirmPassLabel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 3)));
        formPanel.add(confirmPassField);
        formPanel.add(Box.createRigidArea(new Dimension(0, 20)));
        formPanel.add(confirmPassPanel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 5)));
        formPanel.add(matchStatusLabel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 5)));
        formPanel.add(passwordHintLabel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 5)));
        formPanel.add(registerButton);
        formPanel.add(Box.createRigidArea(new Dimension(0, 8)));
        formPanel.add(cancelButton);
@@ -383,6 +404,61 @@
        
        // 回车键注册
        confirmPassField.addActionListener(e -> performRegistration());
        // 密码一致性检查
        DocumentListener matchListener = new DocumentListener() {
            private void checkMatch() {
                char[] p1 = passField.getPassword();
                char[] p2 = confirmPassField.getPassword();
                if (p2.length > 0 && p2.length == p1.length) {
                    if (!Arrays.equals(p1, p2)) {
                        matchStatusLabel.setText(getTranslationValue(currentLanguageCode, "password_mismatch_error", "两次输入的密码不一致"));
                    } else {
                        matchStatusLabel.setText(" ");
                    }
                } else {
                    matchStatusLabel.setText(" ");
                }
            }
            @Override
            public void insertUpdate(DocumentEvent e) { checkMatch(); }
            @Override
            public void removeUpdate(DocumentEvent e) { checkMatch(); }
            @Override
            public void changedUpdate(DocumentEvent e) { checkMatch(); }
        };
        confirmPassField.getDocument().addDocumentListener(matchListener);
        passField.getDocument().addDocumentListener(matchListener);
        // 密码长度检查
        passField.getDocument().addDocumentListener(new DocumentListener() {
            private void checkLength() {
                char[] password = passField.getPassword();
                if (password.length > 0 && password.length < 6) {
                     passwordHintLabel.setText(getTranslationValue(currentLanguageCode, "password_length_error", "密码长度不能少于6位"));
                } else {
                     passwordHintLabel.setText(" ");
                }
            }
            public void insertUpdate(DocumentEvent e) { checkLength(); }
            public void removeUpdate(DocumentEvent e) { checkLength(); }
            public void changedUpdate(DocumentEvent e) { checkLength(); }
        });
        // 邮箱格式检查
        emailField.getDocument().addDocumentListener(new DocumentListener() {
            private void validate() {
                String email = emailField.getText().trim();
                if (!email.isEmpty() && !isValidEmail(email)) {
                    emailHintLabel.setText(getTranslationValue(currentLanguageCode, "invalid_email_error", "邮箱格式错误"));
                } else {
                    emailHintLabel.setText("");
                }
            }
            public void insertUpdate(DocumentEvent e) { validate(); }
            public void removeUpdate(DocumentEvent e) { validate(); }
            public void changedUpdate(DocumentEvent e) { validate(); }
        });
    }
    private void updateLanguage(String languageCode) {
@@ -399,6 +475,9 @@
            registerButton.setText(getTranslationValue(languageCode, "register_button", registerButton.getText()));
            cancelButton.setText(getTranslationValue(languageCode, "cancel_button", cancelButton.getText()));
            sendCodeButton.setText(getTranslationValue(languageCode, "send_code_button", sendCodeButton.getText()));
            if (passwordHintLabel != null) {
                passwordHintLabel.setText(getTranslationValue(languageCode, "password_length_error", passwordHintLabel.getText()));
            }
        }
    }
@@ -437,35 +516,51 @@
            return;
        }
        
        // 生成随机验证码(实际应用中应该通过邮件发送)
        generatedVerificationCode = generateRandomCode();
        // 禁用按钮,防止重复点击
        sendCodeButton.setEnabled(false);
        
        // 在实际应用中,这里应该调用邮件发送服务
        // 这里仅模拟发送过程
        System.out.println("验证码 " + generatedVerificationCode + " 已发送到 " + email);
        // 在新线程中调用API,避免阻塞UI
        new Thread(() -> {
            try {
                // 调用邮件验证码发送API
                EmailCodeSender.EmailCodeResponse response = EmailCodeSender.sendEmailCode(email);
        
        // 获取当前语言的翻译
                // 在EDT线程中更新UI
                SwingUtilities.invokeLater(() -> {
                    if (response.isSuccess()) {
                        // 发送成功,显示提示并开始倒计时
        Map<String, String> translationMap = translations.get(currentLanguageCode);
        if (translationMap != null) {
                        String successMessage = translationMap != null ?
                            translationMap.get("verification_code_sent") : "验证码已发送到您的邮箱";
            JOptionPane.showMessageDialog(this, 
                translationMap.get("verification_code_sent"),
                            successMessage,
                "提示", 
                JOptionPane.INFORMATION_MESSAGE);
        } else {
            JOptionPane.showMessageDialog(this,
                "验证码已发送到您的邮箱",
                "提示",
                JOptionPane.INFORMATION_MESSAGE);
        }
        
        // 开始倒计时
                        // 开始60秒倒计时
        startCountdown();
                    } else {
                        // 发送失败,显示错误信息并恢复按钮
                        sendCodeButton.setEnabled(true);
                        String errorMessage = response.getMessage() != null ?
                            response.getMessage() : "验证码发送失败";
                        JOptionPane.showMessageDialog(this,
                            errorMessage,
                            "错误",
                            JOptionPane.ERROR_MESSAGE);
    }
    // 生成随机验证码
    private String generateRandomCode() {
        // 生成6位随机数字
        return String.valueOf((int)((Math.random() * 9 + 1) * 100000));
                });
            } catch (Exception e) {
                // 异常处理,恢复按钮并显示错误
                SwingUtilities.invokeLater(() -> {
                    sendCodeButton.setEnabled(true);
                    JOptionPane.showMessageDialog(this,
                        "发送验证码时发生错误: " + e.getMessage(),
                        "错误",
                        JOptionPane.ERROR_MESSAGE);
                });
            }
        }).start();
    }
    
    // 开始倒计时
@@ -506,17 +601,19 @@
    }
    private void performRegistration() {
        String username = userField.getText().trim();
        String nickname = userField.getText().trim();
        String email = emailField.getText().trim();
        String verificationCode = verificationCodeField.getText().trim();
        String password = new String(passField.getPassword());
        String confirmPassword = new String(confirmPassField.getPassword());
        String code = verificationCodeField.getText().trim();
        // 获取密码字段的值(与登录页面保持一致的处理方式)
        String password = new String(passField.getPassword()).trim();
        String confirmPassword = new String(confirmPassField.getPassword()).trim();
        
        // 获取当前语言的翻译
        Map<String, String> translationMap = translations.get(currentLanguageCode);
        
        // 输入验证
        if (username.isEmpty() || email.isEmpty() || verificationCode.isEmpty() ||
        if (nickname.isEmpty() || email.isEmpty() || code.isEmpty() ||
            password.isEmpty() || confirmPassword.isEmpty()) {
            String errorMessage = translationMap != null ? 
                translationMap.get("empty_fields_error") : "请填写所有字段";
@@ -553,19 +650,7 @@
            return;
        }
        
        // 验证验证码
        if (!verificationCode.equals(generatedVerificationCode)) {
            String errorMessage = translationMap != null ?
                translationMap.get("invalid_verification_code") : "验证码错误";
            JOptionPane.showMessageDialog(this,
                errorMessage,
                "输入错误",
                JOptionPane.WARNING_MESSAGE);
            verificationCodeField.setText("");
            verificationCodeField.requestFocus();
            return;
        }
        // 验证两次输入的密码是否一致
        if (!password.equals(confirmPassword)) {
            String errorMessage = translationMap != null ? 
                translationMap.get("password_mismatch_error") : "两次输入的密码不一致";
@@ -579,11 +664,21 @@
            return;
        }
        
        // 保存用户信息
        UserChuShiHua.updateProperty("userName", username);
        UserChuShiHua.updateProperty("email", email);
        UserChuShiHua.updateProperty("password", password);
        // 禁用注册按钮,防止重复提交
        registerButton.setEnabled(false);
        
        // 在新线程中调用API,避免阻塞UI
        new Thread(() -> {
            try {
                // 调用用户注册API
                UserRegister.RegisterResponse response = UserRegister.register(email, password, code, nickname,confirmPassword);
                // 在EDT线程中更新UI
                SwingUtilities.invokeLater(() -> {
                    registerButton.setEnabled(true);
                    if (response.isSuccess()) {
                        // 注册成功,显示成功提示
        String successMessage = translationMap != null ? 
            translationMap.get("success_message") : "注册成功!";
        JOptionPane.showMessageDialog(this, 
@@ -591,13 +686,29 @@
            "成功", 
            JOptionPane.INFORMATION_MESSAGE);
        
                        // 关闭注册窗口
        dispose();
        // 自动填充登录表单
        if (parentFrame != null) {
            // 这里需要访问父窗口的usernameField,但由于封装性,我们可能需要添加公共方法
            // 暂时留空,可以根据需要实现
                    } else {
                        // 注册失败,显示错误信息
                        String errorMessage = response.getMessage() != null ?
                            response.getMessage() : "注册失败";
                        JOptionPane.showMessageDialog(this,
                            errorMessage,
                            "注册失败",
                            JOptionPane.ERROR_MESSAGE);
        }
                });
            } catch (Exception e) {
                // 异常处理,恢复按钮并显示错误
                SwingUtilities.invokeLater(() -> {
                    registerButton.setEnabled(true);
                    JOptionPane.showMessageDialog(this,
                        "注册时发生错误: " + e.getMessage(),
                        "错误",
                        JOptionPane.ERROR_MESSAGE);
                });
            }
        }).start();
    }
    
    @Override
@@ -608,4 +719,47 @@
        }
        super.dispose();
    }
    private JPanel createPasswordPanel(JPasswordField passField) {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(Color.WHITE);
        panel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(200, 200, 200)),
            BorderFactory.createEmptyBorder(1, 1, 1, 1)
        ));
        panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 35));
        panel.setAlignmentX(Component.LEFT_ALIGNMENT);
        passField.setBorder(BorderFactory.createEmptyBorder(4, 8, 4, 8));
        panel.add(passField, BorderLayout.CENTER);
        JButton toggleBtn = new JButton();
        try {
            ImageIcon icon = new ImageIcon("image/look.png");
            if (icon.getIconWidth() > 0) {
                Image img = icon.getImage().getScaledInstance(20, 20, Image.SCALE_SMOOTH);
                toggleBtn.setIcon(new ImageIcon(img));
            } else {
                toggleBtn.setText("👁");
            }
        } catch (Exception e) {
            toggleBtn.setText("👁");
        }
        toggleBtn.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
        toggleBtn.setContentAreaFilled(false);
        toggleBtn.setFocusPainted(false);
        toggleBtn.setCursor(new Cursor(Cursor.HAND_CURSOR));
        toggleBtn.addActionListener(e -> {
            if (passField.getEchoChar() != 0) {
                passField.setEchoChar((char) 0);
            } else {
                passField.setEchoChar('•');
            }
        });
        panel.add(toggleBtn, BorderLayout.EAST);
        return panel;
    }
}