package com.ecep.contract.controller; import java.io.FileOutputStream; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; import java.util.List; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Properties; import java.util.concurrent.CompletableFuture; import java.util.logging.Level; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.util.StringUtils; import com.ecep.contract.Desktop; import com.ecep.contract.MessageHolder; import com.ecep.contract.SpringApp; import javafx.application.Platform; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleStringProperty; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.CheckBox; import javafx.scene.control.Label; import javafx.scene.control.ListView; import javafx.scene.control.PasswordField; import javafx.scene.control.TextField; import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; import javafx.stage.Stage; import lombok.Setter; public class LoginWidowController implements MessageHolder { private static final Logger logger = LoggerFactory.getLogger(LoginWidowController.class); @Setter MessageHolder holder; @Setter Stage primaryStage; @Setter Properties properties; @Override public void addMessage(Level level, String message) { holder.addMessage(level, message); } private void storeProperties() { try (FileOutputStream fos = new FileOutputStream("config.properties")) { // 保存到文件 properties.store(fos, "Updated config.properties"); info("配置文件已更新!"); } catch (java.io.IOException e) { error("保存配置文件失败:" + e.getMessage()); } } String getHost() { return properties.getProperty("server.host"); } public void tryLogin() { // CompletableFuture future = new CompletableFuture<>(); // 检查配置文件中是否保存用户名和密码 String userName = getUserName(); if (StringUtils.hasText(userName)) { try { EmployeeInfo employeeInfo = tryToConnect(userName, getPassword()); if (employeeInfo.errorCode < 0) { error("登录失败:错误代码=" + employeeInfo.errorCode); } else { logined(employeeInfo); } } catch (SQLException e) { throw new RuntimeException(e); } } else { showUserNameLoginDialog(null); } } private String getPassword() { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'getPassword'"); } private String getUserName() { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'getUserName'"); } CompletableFuture> getMacAndIP() { return CompletableFuture.supplyAsync(() -> { // mac ip List list = new ArrayList<>(); try { Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface anInterface = interfaces.nextElement(); if (anInterface.isLoopback()) { continue; } byte[] hardwareAddress = anInterface.getHardwareAddress(); if (hardwareAddress == null) { continue; } Enumeration inetAddresses = anInterface.getInetAddresses(); if (!inetAddresses.hasMoreElements()) { continue; } // -分割16进制表示法 StringBuilder sb = new StringBuilder(); for (int i = 0; i < hardwareAddress.length; i++) { sb.append( String.format("%02X%s", hardwareAddress[i], i < hardwareAddress.length - 1 ? "-" : "")); } while (inetAddresses.hasMoreElements()) { InetAddress inetAddress = inetAddresses.nextElement(); if (inetAddress instanceof Inet4Address) { list.add(new LoginWidowController.MacIP(sb.toString(), inetAddress.getHostAddress())); } } } } catch (SocketException e) { throw new RuntimeException(e); } return list; }); } private EmployeeInfo tryToConnect(String userName, String password) throws SQLException { String host = getHost(); String port = getPort(); String database = getDatabase(); if (logger.isDebugEnabled()) { logger.debug("try to connect db server host:{},port:{},database:{},user:{},pwd:{}", host, port, database, userName, "*"); } return null; } private String getDatabase() { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'getDatabase'"); } private String getPort() { // TODO Auto-generated method stub throw new UnsupportedOperationException("Unimplemented method 'getPort'"); } private void createSession(Connection connection, EmployeeInfo employeeInfo) { employeeInfo.sessionId = addHistory(connection, employeeInfo.employeeId, employeeInfo.binds.getFirst()); } private int addHistory(Connection connection, int employeeId, MacIP macIP) { try { String sql = "INSERT INTO EMPLOYEE_LOGIN_HISTORY (IP, MAC, DT, EMPLOYEE_ID) VALUES (?, ?, ?, ?)"; try (PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { ps.setString(1, macIP.ip); ps.setString(2, macIP.mac); ps.setObject(3, LocalDateTime.now()); // 根据数据库字段类型调整 ps.setInt(4, employeeId); ps.executeUpdate(); // 返回 新的主键值 ResultSet generatedKeys = ps.getGeneratedKeys(); if (generatedKeys.next()) { return generatedKeys.getInt(1); } } } catch (SQLException e) { holder.error("申请新会话编号失败"); logger.error("unable insert EMPLOYEE_LOGIN_HISTORY, ", e); } return -1; } static class MacIP { String ip; String mac; public MacIP(String mac, String ip) { this.mac = mac; this.ip = ip; } } static class EmployeeInfo { Integer employeeId; List binds = new ArrayList<>(); SimpleStringProperty name = new SimpleStringProperty(); SimpleBooleanProperty active = new SimpleBooleanProperty(); int sessionId; int errorCode = 0; public EmployeeInfo(Integer employeeId) { this.employeeId = employeeId; } public static EmployeeInfo error(int code) { EmployeeInfo employeeInfo = new EmployeeInfo(null); employeeInfo.errorCode = code; return employeeInfo; } public void addBind(MacIP macIP) { binds.add(macIP); } } private CompletableFuture tryLoginWithEmployeeBind(Connection connection, CompletableFuture> macAndIP) { CompletableFuture future = new CompletableFuture<>(); macAndIP.thenAccept(macIPS -> { if (macIPS.isEmpty()) { future.complete(EmployeeInfo.error(-1)); return; } HashMap employeeMap = new HashMap<>(); for (MacIP macIP : macIPS) { for (Integer employeeId : findAllBindEmployee(connection, macIP)) { employeeMap.computeIfAbsent(employeeId, k -> new EmployeeInfo(employeeId)).addBind(macIP); } } if (employeeMap.isEmpty()) { error("本机未绑定登录信息,请联系管理员更新."); // 当前计算机的信息,如用户名,计算机名等 String username = System.getProperty("user.name"); String computerName = System.getenv("COMPUTERNAME"); for (MacIP macIP : macIPS) { if (macIP.ip.equals("127.0.0.1")) { continue; } registerComputer(username, computerName, connection, macIP); } future.complete(EmployeeInfo.error(-2)); return; } if (employeeMap.size() == 1) { // 直接登录 EmployeeInfo employeeInfo = employeeMap.values().stream().findFirst().get(); // issue #1 登录成功后没有更新员工信息 fill(connection, employeeInfo); future.complete(employeeInfo); } else { List list = employeeMap.values().stream().toList(); // 选择登录 Platform.runLater(() -> { EmployeeInfo info = showEmployeeSelectDialog(list); future.complete(Objects.requireNonNullElseGet(info, () -> EmployeeInfo.error(-3))); }); for (EmployeeInfo info : list) { fill(connection, info); } } }); return future; } private EmployeeInfo showEmployeeSelectDialog(List list) { Stage stage = new Stage(); stage.initOwner(primaryStage); stage.setTitle("请选择账户登录系统"); stage.setWidth(360); stage.setHeight(280); Label label = new Label("您的主机关联了以下账户,请选择一个登录"); label.setPadding(new Insets(10, 0, 10, 10)); ListView