826220679@qq.com
17 小时以前 d655e19ad18eea30f3627fc1c499ae9fe4200d92
src/denglu/Denglu.java
@@ -1,6 +1,15 @@
package denglu;
import homein.WenJianSuo;
import ui.UIConfig;
import zhuye.Shouye;
import gecaoji.Device;
import chuankou.SerialPortNativeLoader;
import set.Setsys;
import udpdell.UDPServer;
import user.Usrdell;
import Mqttmessage.Client;
import login.LoginVerifier;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
@@ -35,7 +44,7 @@
    private void initializeTranslations() {
        translations = new HashMap<>();
        // 中文翻译
        Map<String, String> zh = new HashMap<>();
        zh.put("username_label", "用户名或邮箱");
@@ -45,7 +54,9 @@
        zh.put("login_button", "登录");
        zh.put("no_account", "还没有账户?");
        zh.put("sign_up", "立即注册");
        zh.put("app_info", "AutoMow © 2023 - 智能割草解决方案");
        zh.put("app_title", "智能割草系统");
        zh.put("window_title", "智能割草系统 - 登录");
        zh.put("app_info", "智能割草系统 © 2023 - 智能割草解决方案");
        zh.put("register_button", "注册新账户");
        translations.put("zh", zh);
@@ -58,7 +69,9 @@
        en.put("login_button", "Sign In");
        en.put("no_account", "Don't have an account?");
        en.put("sign_up", "Sign Up");
        en.put("app_info", "AutoMow © 2023 - Smart Mowing Solutions");
        en.put("app_title", "Smart Mowing System");
        en.put("window_title", "Smart Mowing System - Login");
        en.put("app_info", "Smart Mowing System © 2023 - Intelligent Lawn Care");
        en.put("register_button", "Create New Account");
        translations.put("en", en);
@@ -71,7 +84,9 @@
        es.put("login_button", "Iniciar Sesión");
        es.put("no_account", "¿No tienes una cuenta?");
        es.put("sign_up", "Regístrate");
        es.put("app_info", "AutoMow © 2023 - Soluciones de Corte Inteligente");
        es.put("app_title", "Sistema de Corte Inteligente");
        es.put("window_title", "Sistema de Corte Inteligente - Iniciar Sesión");
        es.put("app_info", "Sistema de Corte Inteligente © 2023 - Soluciones Inteligentes");
        es.put("register_button", "Crear Nueva Cuenta");
        translations.put("es", es);
@@ -84,8 +99,10 @@
        fr.put("login_button", "Se connecter");
        fr.put("no_account", "Vous n'avez pas de compte?");
        fr.put("sign_up", "S'inscrire");
        fr.put("app_info", "AutoMow © 2023 - Solutions de Tonte Intelligente");
        es.put("register_button", "Créer un Nouveau Compte");
        fr.put("app_title", "Système de Tonte Intelligent");
        fr.put("window_title", "Système de Tonte Intelligent - Connexion");
        fr.put("app_info", "Système de Tonte Intelligent © 2023 - Solutions de Tonte");
        fr.put("register_button", "Créer un Nouveau Compte");
        translations.put("fr", fr);
        // 德语翻译
@@ -97,18 +114,20 @@
        de.put("login_button", "Anmelden");
        de.put("no_account", "Sie haben noch kein Konto?");
        de.put("sign_up", "Registrieren");
        de.put("app_info", "AutoMow © 2023 - Intelligente Mäh-Lösungen");
        de.put("app_title", "Intelligentes Mähsystem");
        de.put("window_title", "Intelligentes Mähsystem - Anmeldung");
        de.put("app_info", "Intelligentes Mähsystem © 2023 - Mählösungen");
        de.put("register_button", "Neues Konto Erstellen");
        translations.put("de", de);
    }
    private void initializeUI() {
        setTitle("AutoMow - 登录");
        setTitle(getTranslationValue(currentLanguageCode, "window_title", "系统登录"));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // 设置紧凑布局尺寸
        setSize(320, 520);
        setMinimumSize(new Dimension(300, 500));
        setSize(UIConfig.DIALOG_WIDTH, UIConfig.DIALOG_HEIGHT);
        setMinimumSize(new Dimension(UIConfig.DIALOG_WIDTH, UIConfig.DIALOG_HEIGHT));
        setResizable(false);
        
        setupCompactLayout();
@@ -159,11 +178,6 @@
        ));
        
        // 登录标题
        JLabel loginTitle = new JLabel("AutoMow", SwingConstants.CENTER);
        loginTitle.setFont(new Font("PingFang SC", Font.BOLD, 24));
        loginTitle.setForeground(THEME_COLOR);
        loginTitle.setAlignmentX(Component.CENTER_ALIGNMENT);
        // 用户名输入
        usernameLabel = new JLabel("用户名或邮箱", SwingConstants.CENTER);
        usernameLabel.setFont(new Font("PingFang SC", Font.BOLD, 13));
@@ -212,7 +226,7 @@
        rememberForgotPanel.add(rememberMe, BorderLayout.WEST);
        rememberForgotPanel.add(forgotPassword, BorderLayout.EAST);
        
        // 登录按钮 - 水平居中,长度与文本框相同
        // 登录按钮 - 水平居中,长度与文本框宽度保持相近
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        buttonPanel.setBackground(Color.WHITE);
        buttonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 50));
@@ -221,8 +235,8 @@
        loginButton.setBackground(THEME_COLOR);
        loginButton.setForeground(Color.WHITE);
        loginButton.setFont(new Font("PingFang SC", Font.BOLD, 15));
        // 设置登录按钮长度与文本框相同
        loginButton.setPreferredSize(new Dimension(260, 42));
        // 设置登录按钮长度接近文本框宽度
        loginButton.setPreferredSize(new Dimension(300, 48));
        loginButton.setBorderPainted(false);
        loginButton.setFocusPainted(false);
        loginButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
@@ -248,7 +262,7 @@
        registerButton.setBackground(Color.WHITE);
        registerButton.setForeground(THEME_COLOR);
        registerButton.setFont(new Font("PingFang SC", Font.BOLD, 14));
        registerButton.setPreferredSize(new Dimension(140, 38));
        registerButton.setPreferredSize(new Dimension(180, 42));
        registerButton.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(THEME_COLOR),
            BorderFactory.createEmptyBorder(5, 15, 5, 15)
@@ -282,12 +296,11 @@
        signupPanel.add(signupLink);
        
        // 组装表单
        formPanel.add(loginTitle);
        formPanel.add(Box.createRigidArea(new Dimension(0, 25)));
    formPanel.add(Box.createRigidArea(new Dimension(0, 15)));
        formPanel.add(usernameLabel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 5)));
        formPanel.add(usernameField);
        formPanel.add(Box.createRigidArea(new Dimension(0, 15)));
    formPanel.add(Box.createRigidArea(new Dimension(0, 30)));
        formPanel.add(passwordLabel);
        formPanel.add(Box.createRigidArea(new Dimension(0, 5)));
        formPanel.add(passwordField);
@@ -307,7 +320,9 @@
        JPanel appInfoPanel = new JPanel();
        appInfoPanel.setBackground(Color.WHITE);
        appInfoPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 5, 0));
        appInfoLabel = new JLabel("AutoMow © 2023 - 智能割草解决方案");
        appInfoLabel = new JLabel(
            getTranslationValue(currentLanguageCode, "app_info", "智能割草系统 © 2023")
        );
        appInfoLabel.setFont(new Font("PingFang SC", Font.PLAIN, 10));
        appInfoLabel.setForeground(new Color(150, 150, 150));
        appInfoPanel.add(appInfoLabel);
@@ -331,10 +346,7 @@
        // 忘记密码点击事件
        forgotPassword.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                JOptionPane.showMessageDialog(Denglu.this,
                    "请联系管理员重置密码",
                    "忘记密码",
                    JOptionPane.INFORMATION_MESSAGE);
                new user.ZhaohuiMima(Denglu.this).setVisible(true);
            }
        });
        
@@ -356,20 +368,20 @@
        
        if (translation != null) {
            // 更新所有界面文本
            usernameLabel.setText(translation.get("username_label"));
            passwordLabel.setText(translation.get("password_label"));
            rememberMe.setText(translation.get("remember_me"));
            forgotPassword.setText(translation.get("forgot_password"));
            loginButton.setText(translation.get("login_button"));
            noAccountLabel.setText(translation.get("no_account"));
            signupLink.setText(translation.get("sign_up"));
            appInfoLabel.setText(translation.get("app_info"));
            usernameLabel.setText(getTranslationValue(langCode, "username_label", usernameLabel.getText()));
            passwordLabel.setText(getTranslationValue(langCode, "password_label", passwordLabel.getText()));
            rememberMe.setText(getTranslationValue(langCode, "remember_me", rememberMe.getText()));
            forgotPassword.setText(getTranslationValue(langCode, "forgot_password", forgotPassword.getText()));
            loginButton.setText(getTranslationValue(langCode, "login_button", loginButton.getText()));
            noAccountLabel.setText(getTranslationValue(langCode, "no_account", noAccountLabel.getText()));
            signupLink.setText(getTranslationValue(langCode, "sign_up", signupLink.getText()));
            appInfoLabel.setText(getTranslationValue(langCode, "app_info", appInfoLabel.getText()));
            // 更新注册按钮文本
            registerButton.setText(translation.get("register_button"));
            registerButton.setText(getTranslationValue(langCode, "register_button", registerButton.getText()));
            // 更新窗口标题
            setTitle("AutoMow - " + (langCode.equals("zh") ? "登录" : "Login"));
            setTitle(getTranslationValue(langCode, "window_title", getTitle()));
            
            // 更新语言设置到文件
            updateLanguagePreference(langCode);
@@ -387,6 +399,17 @@
        }
    }
    private String getTranslationValue(String languageCode, String key, String defaultValue) {
        Map<String, String> translation = translations.get(languageCode);
        if (translation != null) {
            String value = translation.get(key);
            if (value != null && !value.trim().isEmpty()) {
                return value;
            }
        }
        return defaultValue;
    }
    private void updateLanguagePreference(String languageCode) {
        String currentLanguage = UserChuShiHua.getProperty("language");
        if (!languageCode.equals(currentLanguage)) {
@@ -411,10 +434,23 @@
            usernameField.setText("");
        }
        
        // 如果密码为-1,清空密码框
        String savedPassword = UserChuShiHua.getProperty("password");
        if (savedPassword != null && savedPassword.equals("-1")) {
            passwordField.setText("");
        // 加载记住我状态
        String rememberPwd = UserChuShiHua.getProperty("rememberPassword");
        boolean isRemember = "1".equals(rememberPwd);
        rememberMe.setSelected(isRemember);
        // 如果记住我被选中,填充密码并自动登录(延迟执行,确保窗口已显示)
        if (isRemember) {
             String savedPassword = UserChuShiHua.getProperty("password");
             String savedEmail = UserChuShiHua.getProperty("email");
             if (savedPassword != null && !savedPassword.equals("-1") &&
                 savedEmail != null && !savedEmail.equals("-1")) {
                 passwordField.setText(savedPassword);
                 // 延迟执行自动登录,确保窗口已经显示
                 SwingUtilities.invokeLater(() -> {
                     performAutoLogin(savedEmail, savedPassword);
                 });
             }
        }
    }
@@ -430,11 +466,11 @@
    }
    private void performLogin() {
        String username = usernameField.getText().trim();
        String usernameOrEmail = usernameField.getText().trim();
        String password = new String(passwordField.getPassword()).trim();
        
        // 输入验证
        if (username.isEmpty()) {
        if (usernameOrEmail.isEmpty()) {
            JOptionPane.showMessageDialog(this, 
                "请输入用户名或邮箱", 
                "输入错误", 
@@ -452,58 +488,149 @@
            return;
        }
        
        // 验证用户名和密码
        if (validateLogin(username, password)) {
            JOptionPane.showMessageDialog(this,
                "登录成功!",
                "成功",
                JOptionPane.INFORMATION_MESSAGE);
            // 更新最后登录时间
            UserChuShiHua.updateProperty("lastLoginTime", String.valueOf(System.currentTimeMillis()));
            // 如果记住我被选中,保存用户名
            if (rememberMe.isSelected()) {
                UserChuShiHua.updateProperty("userName", username);
        // 获取邮箱地址(如果输入的是用户名,从配置文件中获取对应的邮箱)
        String email = getEmailFromInput(usernameOrEmail);
        // 禁用登录按钮,防止重复点击
        loginButton.setEnabled(false);
        // 在新线程中调用API,避免阻塞UI
        new Thread(() -> {
            try {
                // 调用登录验证API
                LoginVerifier.LoginVerifyResponse response = LoginVerifier.verifyLogin(email, password);
                // 在EDT线程中更新UI
                SwingUtilities.invokeLater(() -> {
                    loginButton.setEnabled(true);
                    if (response.isSuccess()) {
                        // 登录成功
                        // 更新最后登录时间
                        UserChuShiHua.updateProperty("lastLoginTime", String.valueOf(System.currentTimeMillis()));
                        // 保存记住我状态
                        if (rememberMe.isSelected()) {
                            UserChuShiHua.updateProperty("rememberPassword", "1");
                            UserChuShiHua.updateProperty("userName", usernameOrEmail);
                            UserChuShiHua.updateProperty("email", email);
                            UserChuShiHua.updateProperty("password", password);
                        } else {
                            UserChuShiHua.updateProperty("rememberPassword", "0");
                        }
                        // 关闭登录窗口并打开首页
                        openMainApplication();
                    } else {
                        // 登录失败,显示错误信息
                        String errorMessage = response.getMessage() != null ?
                            response.getMessage() : "用户名或密码错误!";
                        JOptionPane.showMessageDialog(this,
                            errorMessage,
                            "登录失败",
                            JOptionPane.ERROR_MESSAGE);
                        passwordField.setText("");
                        passwordField.requestFocus();
                    }
                });
            } catch (Exception e) {
                // 异常处理,恢复按钮并显示错误
                SwingUtilities.invokeLater(() -> {
                    loginButton.setEnabled(true);
                    JOptionPane.showMessageDialog(this,
                        "登录时发生错误: " + e.getMessage(),
                        "错误",
                        JOptionPane.ERROR_MESSAGE);
                    passwordField.setText("");
                    passwordField.requestFocus();
                });
            }
            // 这里可以添加跳转到主界面的代码
            openMainApplication();
        } else {
            JOptionPane.showMessageDialog(this,
                "用户名或密码错误!",
                "登录失败",
                JOptionPane.ERROR_MESSAGE);
            passwordField.setText("");
            passwordField.requestFocus();
        }
        }).start();
    }
    private boolean validateLogin(String username, String password) {
        // 从UserChuShiHua获取存储的用户数据进行比较
        String storedUsername = UserChuShiHua.getProperty("userName");
        String storedPassword = UserChuShiHua.getProperty("password");
        String storedEmail = UserChuShiHua.getProperty("email");
        // 检查用户名/邮箱和密码是否匹配
        boolean usernameMatch = username.equals(storedUsername) || username.equals(storedEmail);
        boolean passwordMatch = password.equals(storedPassword);
        return usernameMatch && passwordMatch;
    // 邮箱验证方法
    private boolean isValidEmail(String email) {
        // 简单的邮箱格式验证
        String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
        return email != null && email.matches(emailRegex);
    }
    // 获取邮箱地址(如果输入的是用户名,则从配置文件中获取邮箱)
    private String getEmailFromInput(String usernameOrEmail) {
        // 如果输入的是邮箱格式,直接返回
        if (isValidEmail(usernameOrEmail)) {
            return usernameOrEmail;
        }
        // 否则,从配置文件中获取保存的邮箱
        String savedEmail = UserChuShiHua.getProperty("email");
        if (savedEmail != null && !savedEmail.equals("-1")) {
            // 检查输入的用户名是否匹配保存的用户名
            String savedUsername = UserChuShiHua.getProperty("userName");
            if (usernameOrEmail.equals(savedUsername)) {
                return savedEmail;
            }
        }
        // 如果找不到邮箱,返回输入的字符串(可能是邮箱格式但验证失败,或者用户名不存在)
        return usernameOrEmail;
    }
    // 自动登录(从配置文件读取邮箱和密码)
    private void performAutoLogin(String email, String password) {
        // 在新线程中调用API,避免阻塞UI
        new Thread(() -> {
            try {
                LoginVerifier.LoginVerifyResponse response = LoginVerifier.verifyLogin(email, password);
                SwingUtilities.invokeLater(() -> {
                    if (response.isSuccess()) {
                        // 登录成功,跳转到主页
                        openMainApplication();
                    } else {
                        // 登录失败,清空密码字段,让用户重新输入
                        passwordField.setText("");
                        usernameField.requestFocus();
                    }
                });
            } catch (Exception e) {
                // 异常处理,清空密码字段
                SwingUtilities.invokeLater(() -> {
                    passwordField.setText("");
                    usernameField.requestFocus();
                });
            }
        }).start();
    }
    private void openMainApplication() {
        // 这里可以打开主应用程序窗口
        System.out.println("登录成功,准备打开主应用程序...");
        // 演示:3秒后关闭登录窗口
        Timer timer = new Timer(1000, e -> {
            dispose();
            System.out.println("登录窗口已关闭,主应用程序已启动");
        launchMainApp();
        dispose();
    }
    public static void launchMainApp() {
        System.out.println("准备打开主应用程序...");
        SwingUtilities.invokeLater(() -> {
            JFrame mainFrame = new JFrame("智能割草系统");
            mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
            Shouye homePanel = new Shouye();
            mainFrame.setContentPane(homePanel);
            // 设置与登录页面相同的尺寸
            mainFrame.setSize(UIConfig.DIALOG_WIDTH, UIConfig.DIALOG_HEIGHT);
            mainFrame.setMinimumSize(new Dimension(UIConfig.DIALOG_WIDTH, UIConfig.DIALOG_HEIGHT));
            mainFrame.setResizable(true);
            mainFrame.setLocationRelativeTo(null);
            mainFrame.setVisible(true);
            System.out.println("主应用程序已启动");
            // 启动后连接MQTT
            new Thread(() -> {
                System.out.println("正在连接MQTT服务器...");
                Client.lianjiemqqt();
            }).start();
        });
        timer.setRepeats(false);
        timer.start();
    }
    
    // 注册窗口方法
@@ -512,10 +639,63 @@
        RegistrationFrame registerFrame = new RegistrationFrame(this, currentLanguageCode);
        registerFrame.setVisible(true);
    }
    /**
     * 程序入口点
     * 集成Homein类的初始化逻辑
     */
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            new Denglu().setVisible(true);
        });
        // 检查程序是否已经运行
        if (WenJianSuo.isAlreadyRunning()) {
            JOptionPane.showMessageDialog(null,
                "程序已经在运行中!\n不能同时打开多个实例。",
                "警告",
                JOptionPane.WARNING_MESSAGE);
            System.exit(0);
            return;
        }
        // 添加关闭钩子,确保程序退出时释放锁
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            WenJianSuo.releaseLock();
        }));
        try {
            SerialPortNativeLoader.ensureLibraryPresent();
            // 初始化数据
            UserChuShiHua.initialize();
            Usrdell.initialize(); // 初始化用户属性
            Setsys setsys = new Setsys();
            setsys.initializeFromProperties();
            Device.initializeActiveDevice(setsys.getMowerId());
            UDPServer.startAsync();//启动数据接收线程
            // 显示初始数据
            System.out.println("初始用户名: " + UserChuShiHua.getProperty("userName"));
            System.out.println("初始密码: " + UserChuShiHua.getProperty("password"));
            // 启动登录界面(自动登录逻辑在 loadUserPreferences 中处理)
            EventQueue.invokeLater(() -> {
                try {
                    new Denglu().setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                    JOptionPane.showMessageDialog(null,
                        "登录界面启动失败: " + e.getMessage(),
                        "错误",
                        JOptionPane.ERROR_MESSAGE);
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null,
                "程序启动失败: " + e.getMessage(),
                "错误",
                JOptionPane.ERROR_MESSAGE);
        }
    }
}