From a8a90fd2d5040e66cc66b3da122a7f82561ff6f6 Mon Sep 17 00:00:00 2001 From: 826220679@qq.com <826220679@qq.com> Date: 星期六, 09 八月 2025 23:32:29 +0800 Subject: [PATCH] 优化了欢迎页面 --- src/dell_targets/Dell_BaseStation.java | 47 +++ systemfile/Messages_en.properties | 9 src/udptcp/UDPPortAReceiver.java | 198 ++++++------ systemfile/Messages_zh.properties | 11 src/dell_targets/Dell_tag.java | 163 ++++++++++ src/window/WelcomeFrame.java | 368 +++++++++++++----------- src/dell_targets/Dell_SystemConfiguration.java | 11 systemfile/logfile/openlog.txt | 80 +++++ 8 files changed, 610 insertions(+), 277 deletions(-) diff --git a/src/dell_targets/Dell_BaseStation.java b/src/dell_targets/Dell_BaseStation.java index 67002d3..c58dd3b 100644 --- a/src/dell_targets/Dell_BaseStation.java +++ b/src/dell_targets/Dell_BaseStation.java @@ -4,18 +4,23 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.ConcurrentHashMap; public class Dell_BaseStation { - static List<LocationBaseStation> baseStations; + public static List<LocationBaseStation> baseStations; private static ConcurrentHashMap<String, LocationBaseStation> baseStationMap; // 以基站ID为键的映射 public static List<LocationBaseStation> getBaseStations() throws SQLException { baseStations = new ArrayList<>(); baseStationMap = new ConcurrentHashMap<>(); // 修复:初始化映射 ResultSet rs = DBConnector.queryTableData("location_base_station"); - + if (rs == null) { + // 说明底层拿不到数据,直接抛异常或打印日志 + throw new SQLException("DBConnector.queryTableData returned null, " + + "please check database connection & SQL."); + } while (rs.next()) { LocationBaseStation baseStation = new LocationBaseStation(); baseStation.setId((int) rs.getLong("id")); @@ -133,5 +138,43 @@ public static LocationBaseStation getBaseStationById(String baseStationId) { return baseStationMap.get(baseStationId); // O(1)复杂度直接获取 } + + /** + * 获取所有在线状态(onlineStatus=1)的设备(高效内存操作) + * @return 不可修改的baseStationMap集合(避免外部修改缓存) + */ + public static List<LocationBaseStation> getOnlineBaseStations() { + if (baseStationMap == null || baseStationMap.isEmpty()) { + return Collections.emptyList(); // 缓存为空时返回空集合 + } + + List<LocationBaseStation> BaseStation = new ArrayList<>(); + for (LocationBaseStation base : baseStationMap.values()) { + if ("1".equals(base.getStatus())) { // 字符串比较避免NPE + BaseStation.add(base); + } + } + return Collections.unmodifiableList(BaseStation); // 返回不可变集合 + } + + /** + * 快速获取LocationTag对象的总数(使用内存缓存提高性能) + * @return LocationTag对象的总数 + */ + public static int getLocationBaseCount() { + if (baseStationMap == null) { + synchronized (LocationBaseStation.class) { + if (baseStationMap == null) { + try { + getBaseStations(); // 初始化缓存 + } catch (SQLException e) { + e.printStackTrace(); + return 0; // 初始化失败返回0 + } + } + } + } + return baseStationMap.size(); + } } \ No newline at end of file diff --git a/src/dell_targets/Dell_SystemConfiguration.java b/src/dell_targets/Dell_SystemConfiguration.java index 7d0a9f9..73647cb 100644 --- a/src/dell_targets/Dell_SystemConfiguration.java +++ b/src/dell_targets/Dell_SystemConfiguration.java @@ -15,6 +15,8 @@ public static boolean xytognssOpen=false; public static boolean gnsstoxyOpen=false; public static String language="0"; + public static int hexport=8234; + public static int ascallport=7000; // 获取系统配置列表 public static List<SystemConfiguration> getSystemConfigurations() { // 创建配置对象列表 @@ -40,9 +42,14 @@ // 数据库密码 config.setDatabasePassword(rs.getString("database_password")); // HEX数据UDP接收端口 - config.setHexDataUdpReceivePort(rs.getString("hex_data_udp_receive_port")); + String hexp=rs.getString("hex_data_udp_receive_port"); + hexport=Integer.parseInt(hexp); + config.setHexDataUdpReceivePort(hexp); + String ascll=rs.getString("ascii_data_udp_receive_port"); + ascallport=Integer.parseInt(ascll);; // ASCII数据UDP接收端口 - config.setAsciiDataUdpReceivePort(rs.getString("ascii_data_udp_receive_port")); + config.setAsciiDataUdpReceivePort(ascll); + // TCP数据接收端口1 config.setTcpDataReceivePort1(rs.getString("tcp_data_receive_port1")); // TCP数据接收端口2 diff --git a/src/dell_targets/Dell_tag.java b/src/dell_targets/Dell_tag.java index 1d74352..2a1f489 100644 --- a/src/dell_targets/Dell_tag.java +++ b/src/dell_targets/Dell_tag.java @@ -4,12 +4,21 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.concurrent.ConcurrentHashMap; public class Dell_tag { - static List<LocationTag> locationTags; + public static List<LocationTag> locationTags; + private static ConcurrentHashMap<String, LocationTag> tagMap; // 设备ID->标签对象的映射 public static List<LocationTag> getlocationTags() throws SQLException{ - List<LocationTag> locationTags = new ArrayList<>(); + List<LocationTag> locationTags = new ArrayList<>(); + tagMap = new ConcurrentHashMap<>(); // 初始化映射 ResultSet rs =DBConnector.queryTableData("location_tag"); + if (rs == null) { + // 说明底层拿不到数据,直接抛异常或打印日志 + throw new SQLException("DBConnector.queryTableData returned null, " + + "please check database connection & SQL."); + } while (rs.next()) { LocationTag locationTag = new LocationTag(); locationTag.setId((int) rs.getLong("id")); @@ -98,6 +107,7 @@ locationTag.setIpAddress(rs.getString("ipAddress")); locationTag.setIpPort(rs.getString("Interaction_Type")); locationTags.add(locationTag); + tagMap.put(locationTag.getDeviceNumber(), locationTag); // 添加到映射 } return locationTags; } @@ -119,6 +129,117 @@ DBConnector.executeUpdate(sql, deviceId); } + /** + * 根据设备ID高效修改属性值 + * @param deviceId 设备ID(device_id) + * @param propertyName 属性名(需与setter方法匹配) + * @param value 新属性值 + */ + public static void updateLocationTagProperty(String deviceId, String propertyName, String value) { + LocationTag tag = tagMap.get(deviceId); + if (tag == null) return; // 标签不存在则忽略 + + // 根据属性名调用对应setter + switch (propertyName) { + case "id": tag.setId(Integer.parseInt(value)); break; + case "deviceNumber": tag.setDeviceNumber(value); break; + case "deviceName": tag.setDeviceName(value); break; + case "deviceVersion": tag.setDeviceVersion(value); break; + case "deviceCardNumber": tag.setDeviceCardNumber(value); break; + case "deviceType": tag.setDeviceType(value); break; + case "team": tag.setTeam(value); break; + case "group": tag.setGroup(value); break; + case "department": tag.setDepartment(value); break; + case "iconAddress": tag.setIconAddress(value); break; + case "gender": tag.setGender(value); break; + case "ethnicity": tag.setEthnicity(value); break; + case "communicationAddress": tag.setCommunicationAddress(value); break; + case "boundPhone": tag.setBoundPhone(value); break; + case "idNumber": tag.setIdNumber(value); break; + case "position": tag.setPosition(value); break; + case "boundPlateNumber": tag.setBoundPlateNumber(value); break; + case "faceAddress": tag.setFaceAddress(value); break; + case "heartRate": tag.setHeartRate(value); break; + case "bloodPressure": tag.setBloodPressure(value); break; + case "bloodOxygen": tag.setBloodOxygen(value); break; + case "temperature": tag.setTemperature(value); break; + case "sosStatus": tag.setSosStatus(value); break; + case "motionStatus": tag.setMotionStatus(value); break; + case "onlineStatus": tag.setOnlineStatus(value); break; + case "searchStatus": tag.setSearchStatus(value); break; + case "batteryStatus": tag.setBatteryStatus(value); break; + case "deviceBattery": tag.setDeviceBattery(value); break; + case "removalStatus": tag.setRemovalStatus(value); break; + case "collisionStatus": tag.setCollisionStatus(value); break; + case "elevationStatus": tag.setElevationStatus(value); break; + case "gatheringCount": tag.setGatheringCount(value); break; + case "proximityAlarm": tag.setProximityAlarm(value); break; + case "area": tag.setArea(value); break; + case "xCoordinate": tag.setXCoordinate(value); break; + case "yCoordinate": tag.setYCoordinate(value); break; + case "zCoordinate": tag.setZCoordinate(value); break; + case "floor": tag.setFloor(value); break; + case "speed": tag.setSpeed(value); break; + case "locationSource": tag.setLocationSource(value); break; + case "lastUwbSignalTime": tag.setLastUwbSignalTime(value); break; + case "lastSatelliteSignalTime": tag.setLastSatelliteSignalTime(value); break; + case "uwbTimeSlot": tag.setUwbTimeSlot(value); break; + case "latestRangingSeq": tag.setLatestRangingSeq(value); break; + case "latestRangingBaseId": tag.setLatestRangingBaseId(value); break; + case "latestRangingDistance": tag.setLatestRangingDistance(value); break; + case "latestRangingBaseCount": tag.setLatestRangingBaseCount(value); break; + case "latestRangingSignalStrength": tag.setLatestRangingSignalStrength(value); break; + case "utcTime": tag.setUtcTime(value); break; + case "latitude": tag.setLatitude(value); break; + case "longitude": tag.setLongitude(value); break; + case "satelliteQuality": tag.setSatelliteQuality(value); break; + case "hdop": tag.setHdop(value); break; + case "satelliteCount": tag.setSatelliteCount(value); break; + case "altitude": tag.setAltitude(value); break; + case "differentialTime": tag.setDifferentialTime(value); break; + case "geoidHeight": tag.setGeoidHeight(value); break; + case "satelliteSpeed": tag.setSatelliteSpeed(value); break; + case "lastBarometricValue": tag.setLastBarometricValue(value); break; + case "recentCoordinates": tag.setRecentCoordinates(value); break; + case "recentBarometricValues": tag.setRecentBarometricValues(value); break; + case "offlineTime": tag.setOfflineTime(value); break; + case "onlineTime": tag.setOnlineTime(value); break; + case "offlineDuration": tag.setOfflineDuration(value); break; + case "onlineDuration": tag.setOnlineDuration(value); break; + case "motionlessStartTime": tag.setMotionlessStartTime(value); break; + case "motionlessEndTime": tag.setMotionlessEndTime(value); break; + case "motionlessDuration": tag.setMotionlessDuration(value); break; + case "validSatelliteSignal": tag.setValidSatelliteSignal(value); break; + case "company": tag.setCompany(value); break; + case "sleepTime": tag.setSleepTime(value); break; + case "vibrationTime": tag.setVibrationTime(value); break; + case "frequency": tag.setFrequency(value); break; + case "motionlessTime": tag.setMotionlessTime(value); break; + case "accelerationValue": tag.setAccelerationValue(value); break; + case "imuTime": tag.setImuTime(value); break; + case "reserved1": tag.setReserved1(value); break; + case "reserved2": tag.setReserved2(value); break; + case "reserved3": tag.setReserved3(value); break; + case "reserved4": tag.setReserved4(value); break; + case "reserved5": tag.setReserved5(value); break; + case "ipAndPort": tag.setIpAndPort(value); break; + case "interactionType": tag.setInteractionType(value); break; + case "ipAddress": tag.setIpAddress(value); break; + case "ipPort": tag.setIpPort(value); break; + default: + throw new IllegalArgumentException("无效属性: " + propertyName); + } + } + + /** + * 根据设备ID获取标签对象(高效访问) + * @param deviceId 设备ID + * @return 标签对象(不存在返回null) + */ + public static LocationTag getTagByDeviceId(String deviceId) { + return tagMap.get(deviceId); + } + //获取所有的tagid public static List<String> getAlldeviceIds() { List<String> types = new ArrayList<>(); @@ -134,4 +255,42 @@ } return types; } + + /** + * 获取所有在线状态(onlineStatus=1)的设备(高效内存操作) + * @return 不可修改的LocationTag集合(避免外部修改缓存) + */ + public static List<LocationTag> getOnlineLocationTags() { + if (tagMap == null || tagMap.isEmpty()) { + return Collections.emptyList(); // 缓存为空时返回空集合 + } + + List<LocationTag> onlineTags = new ArrayList<>(); + for (LocationTag tag : tagMap.values()) { + if ("1".equals(tag.getOnlineStatus())) { // 字符串比较避免NPE + onlineTags.add(tag); + } + } + return Collections.unmodifiableList(onlineTags); // 返回不可变集合 + } + + /** + * 快速获取LocationTag对象的总数(使用内存缓存提高性能) + * @return LocationTag对象的总数 + */ + public static int getLocationTagCount() { + if (tagMap == null) { + synchronized (Dell_tag.class) { + if (tagMap == null) { + try { + getlocationTags(); // 初始化缓存 + } catch (SQLException e) { + e.printStackTrace(); + return 0; // 初始化失败返回0 + } + } + } + } + return tagMap.size(); + } } \ No newline at end of file diff --git a/src/udptcp/UDPPortAReceiver.java b/src/udptcp/UDPPortAReceiver.java index a72e207..fea5a80 100644 --- a/src/udptcp/UDPPortAReceiver.java +++ b/src/udptcp/UDPPortAReceiver.java @@ -7,106 +7,110 @@ import java.util.concurrent.atomic.AtomicLong; import dell_system.MessageViewPanel; +import dell_targets.Dell_SystemConfiguration; public class UDPPortAReceiver { - public static final int PORT = 8234; - @SuppressWarnings("unused") + public static final int PORT =Dell_SystemConfiguration.hexport; + @SuppressWarnings("unused") private static final int MAX_DEVICES = 50000; - private static final AtomicLong packetCount = new AtomicLong(0); - private static final ExecutorService executor = Executors.newFixedThreadPool(10); - private static DatagramSocket socket; - private static volatile boolean isRunning = false; - private static Thread receiverThread; - @SuppressWarnings("unused") + private static final AtomicLong packetCount = new AtomicLong(0); + private static final ExecutorService executor = Executors.newFixedThreadPool(10); + private static DatagramSocket socket; + private static volatile boolean isRunning = false; + private static Thread receiverThread; + @SuppressWarnings("unused") private static final int LOCAL_PORT = PORT; // 定义本地端口 - // 启动接收器的静态方法 - public static void startReceiver() { - if (isRunning) return; - isRunning = true; - receiverThread = new Thread(() -> { - try { - socket = new DatagramSocket(PORT); - byte[] buffer = new byte[2048]; - while (isRunning) { - DatagramPacket packet = new DatagramPacket(buffer, buffer.length); - socket.receive(packet); - executor.execute(() -> { - try { - String ip = packet.getAddress().getHostAddress(); - int port = packet.getPort(); - String hexData = bytesToHex(packet.getData(), packet.getLength()); - // 调用时添加本地端口参数 - PacketProcessingSystem.storePacket(ip, port, hexData); - // 报文查看窗口显示数据 - MessageViewPanel.showData(hexData, ip, port, PORT,"1"); - - } catch (Exception e) { - System.err.println("Error processing UDP-A packet: " + e.getMessage()); - } - }); - } - } catch (Exception e) { - System.err.println("UDP-A Server crashed: " + e.getMessage()); - } finally { - if (socket != null && !socket.isClosed()) { - socket.close(); - } - } - }); - receiverThread.setDaemon(true); - receiverThread.start(); - } - - // 停止接收器 - public static void stopReceiver() { - isRunning = false; - if (socket != null && !socket.isClosed()) { - socket.close(); - } - executor.shutdown(); - } - - // 发送数据到指定设备 - public static void sendData(String ip, int port, String data, boolean isHex) { - try { - byte[] sendBytes; - if (isHex) { - // HEX格式发送:将十六进制字符串转换为字节数组 - sendBytes = hexStringToByteArray(data); - } else { - // ASCII格式发送:直接获取字节数组 - sendBytes = data.getBytes(); - } - - InetAddress address = InetAddress.getByName(ip); - DatagramPacket packet = new DatagramPacket(sendBytes, sendBytes.length, address, port); - socket.send(packet); - } catch (Exception e) { - System.err.println("Error sending UDP data: " + e.getMessage()); - } - } - - private static String bytesToHex(byte[] bytes, int length) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < length; i++) { - sb.append(String.format("%02X", bytes[i])); - } - return sb.toString(); - } - - private static byte[] hexStringToByteArray(String hex) { - hex = hex.replaceAll("\\s", ""); // 移除所有空格 - int len = hex.length(); - byte[] data = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - // 处理每两个字符作为一个字节 - data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) - + Character.digit(hex.charAt(i+1), 16)); - } - return data; - } + // 启动接收器的静态方法 + public static void startReceiver() { + if (isRunning) return; + isRunning = true; + receiverThread = new Thread(() -> { + try { + socket = new DatagramSocket(PORT); + byte[] buffer = new byte[2048]; + while (isRunning) { + DatagramPacket packet = new DatagramPacket(buffer, buffer.length); + socket.receive(packet); + executor.execute(() -> { + try { + String ip = packet.getAddress().getHostAddress(); + int port = packet.getPort(); + String hexData = bytesToHex(packet.getData(), packet.getLength()); + // 调用时添加本地端口参数 + PacketProcessingSystem.storePacket(ip, port, hexData); + // 报文查看窗口显示数据 + MessageViewPanel.showData(hexData, ip, port, PORT,"1"); + // +++ 增加包计数 +++ + packetCount.incrementAndGet(); // 关键修复:增加计数器 + } catch (Exception e) { + System.err.println("Error processing UDP-A packet: " + e.getMessage()); + } + }); + } + } catch (Exception e) { + System.err.println("UDP-A Server crashed: " + e.getMessage()); + } finally { + if (socket != null && !socket.isClosed()) { + socket.close(); + } + } + }); + receiverThread.setDaemon(true); + receiverThread.start(); + } - public static long getPacketCount() { - return packetCount.get(); - } + // 停止接收器 + public static void stopReceiver() { + isRunning = false; + if (socket != null && !socket.isClosed()) { + socket.close(); + } + executor.shutdown(); + } + + // 发送数据到指定设备 + public static void sendData(String ip, int port, String data, boolean isHex) { + try { + byte[] sendBytes; + if (isHex) { + // HEX格式发送:将十六进制字符串转换为字节数组 + sendBytes = hexStringToByteArray(data); + } else { + // ASCII格式发送:直接获取字节数组 + sendBytes = data.getBytes(); + } + + InetAddress address = InetAddress.getByName(ip); + DatagramPacket packet = new DatagramPacket(sendBytes, sendBytes.length, address, port); + socket.send(packet); + } catch (Exception e) { + System.err.println("Error sending UDP data: " + e.getMessage()); + } + } + + private static String bytesToHex(byte[] bytes, int length) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < length; i++) { + sb.append(String.format("%02X", bytes[i])); + } + return sb.toString(); + } + + private static byte[] hexStringToByteArray(String hex) { + hex = hex.replaceAll("\\s", ""); // 移除所有空格 + int len = hex.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + // 处理每两个字符作为一个字节 + data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4) + + Character.digit(hex.charAt(i+1), 16)); + } + return data; + } + + // 获取接收到的数据包总数 + public static long getPacketCount() { + return packetCount.get(); + } + } \ No newline at end of file diff --git a/src/window/WelcomeFrame.java b/src/window/WelcomeFrame.java index 158957e..1fa4cb4 100644 --- a/src/window/WelcomeFrame.java +++ b/src/window/WelcomeFrame.java @@ -1,213 +1,237 @@ -package window; // 包声明 -import java.awt.*; // 导入AWT包 -import java.sql.Connection; // 导入数据库连接类 -import java.sql.ResultSet; // 导入结果集类 -import java.sql.Statement; // 导入SQL语句类 -import javax.swing.*; // 导入Swing包 -import javax.swing.border.EmptyBorder; // 导入空边框类 -import java.util.ResourceBundle; // 导入资源束类 -import udptcp.UDPPortAReceiver; // 导入UDP端口A接收器 -import udptcp.UDPPortBReceiver; // 导入UDP端口B接收器 -import javax.swing.plaf.basic.BasicInternalFrameUI; // 导入基础内部框架UI +package window; -public class WelcomeFrame extends JInternalFrame { // 欢迎框架类 - private static final long serialVersionUID = 1L; // 序列化版本ID - private ResourceBundle messages; // 消息资源束 - private Connection conn; // 数据库连接 - private Timer statsTimer; // 统计定时器 - private JLabel udpAPacketCountLabel; // UDP端口A包计数标签 - private JLabel udpBPacketCountLabel; // UDP端口B包计数标签 - private JLabel memoryUsageLabel; // 内存使用标签 - private JLabel threadCountLabel; // 线程计数标签 +import java.awt.*; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.Statement; +import javax.swing.*; +import javax.swing.border.EmptyBorder; +import java.util.ResourceBundle; +import udptcp.UDPPortAReceiver; +import udptcp.UDPPortBReceiver; +import dell_targets.Dell_BaseStation; +import dell_targets.Dell_tag; +import dell_targets.Dell_SystemConfiguration; - public WelcomeFrame(ResourceBundle messages, Connection conn) { // 构造函数 - super("", true, true, true, true); // 调用父类构造函数,设置标题为空 - this.messages = messages; // 初始化消息资源束 - this.conn = conn; // 初始化数据库连接 +public class WelcomeFrame extends JInternalFrame { + private static final long serialVersionUID = 1L; + private final ResourceBundle messages; + private final Connection conn; + private Timer statsTimer; + private JLabel memoryUsageLabel; + private JLabel threadCountLabel; + private JLabel tagStatsLabel; + private JLabel baseStationStatsLabel; + private JLabel dbVersionLabel; + private JLabel udpAInfoLabel; + private JLabel udpBInfoLabel; + + public WelcomeFrame(ResourceBundle messages, Connection conn) { + super("", true, true, true, true); + this.messages = messages; + this.conn = conn; - initializeFrame(); // 初始化框架 - setContentPane(createWelcomePanel()); // 设置内容面板 - startStatsTimer(); // 启动统计定时器 + initializeFrame(); + setContentPane(createWelcomePanel()); + startStatsTimer(); } - private void initializeFrame() { // 初始化框架方法 - setSize(900, 700); // 设置框架大小 - setLocation(100, 100); // 设置框架位置 - setMaximizable(true); // 设置可最大化 - setIconifiable(true); // 设置可图标化 - setClosable(true); // 设置可关闭 - setBorder(null); // 移除边框 - setVisible(true); // 设置可见 + private void initializeFrame() { + setSize(900, 700); + setLocation(100, 100); + setMaximizable(true); + setIconifiable(true); + setClosable(true); + setBorder(null); // 移除标题栏 - BasicInternalFrameUI ui = (BasicInternalFrameUI) this.getUI(); // 获取UI组件 - ui.setNorthPane(null); // 移除标题栏 + ((javax.swing.plaf.basic.BasicInternalFrameUI)this.getUI()).setNorthPane(null); try { - setMaximum(true); // 尝试最大化窗口 + setMaximum(true); } catch (java.beans.PropertyVetoException e) { - e.printStackTrace(); // 打印异常堆栈 + e.printStackTrace(); } + + setVisible(true); // 确保框架可见 } - private JPanel createWelcomePanel() { // 创建欢迎面板方法 - JPanel panel = new BackgroundPanel(); // 创建背景面板 - panel.setLayout(new BorderLayout()); // 设置边界布局 - panel.setBorder(new EmptyBorder(30, 30, 30, 30)); // 设置空边框 + private JPanel createWelcomePanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.setBorder(new EmptyBorder(30, 30, 30, 30)); + panel.setBackground(new Color(245, 248, 255)); - // 创建标题面板 - JPanel titlePanel = new JPanel(new BorderLayout()); // 创建边界布局面板 - titlePanel.setOpaque(false); // 设置透明 + // 标题面板 + JPanel titlePanel = new JPanel(new BorderLayout()); + titlePanel.setOpaque(false); + titlePanel.setBorder(new EmptyBorder(0, 0, 30, 0)); - JLabel titleLabel = new JLabel(messages.getString("APP_NAME"), SwingConstants.CENTER); // 创建应用名称标签 - titleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 42)); // 设置字体 - titleLabel.setForeground(new Color(25, 25, 112)); // 设置前景色 - titleLabel.setBorder(new EmptyBorder(20, 0, 20, 0)); // 设置空边框 - titleLabel.setOpaque(false); // 设置透明 + JLabel titleLabel = new JLabel(messages.getString("APP_NAME"), SwingConstants.CENTER); + titleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 42)); + titleLabel.setForeground(new Color(25, 25, 112)); - JLabel subtitleLabel = new JLabel(messages.getString("WELCOME_MSG"), SwingConstants.CENTER); // 创建欢迎消息标签 - subtitleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.ITALIC, 22)); // 设置字体 - subtitleLabel.setForeground(new Color(70, 130, 180)); // 设置前景色 - subtitleLabel.setOpaque(false); // 设置透明 + JLabel subtitleLabel = new JLabel(messages.getString("WELCOME_MSG"), SwingConstants.CENTER); + subtitleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.ITALIC, 22)); + subtitleLabel.setForeground(new Color(70, 130, 180)); + subtitleLabel.setBorder(new EmptyBorder(10, 0, 20, 0)); - titlePanel.add(titleLabel, BorderLayout.NORTH); // 添加标题到北部 - titlePanel.add(subtitleLabel, BorderLayout.CENTER); // 添加副标题到中部 + titlePanel.add(titleLabel, BorderLayout.NORTH); + titlePanel.add(subtitleLabel, BorderLayout.CENTER); - // 创建信息面板 - JPanel infoPanel = new JPanel(new GridLayout(0, 2, 20, 20)); // 创建网格布局面板 - infoPanel.setBorder(new EmptyBorder(30, 50, 30, 50)); // 设置空边框 - infoPanel.setBackground(new Color(255, 255, 255, 180)); // 设置半透明白色背景 - infoPanel.setOpaque(true); // 设置不透明 + // 主信息面板 + JPanel infoPanel = new JPanel(new GridBagLayout()); + infoPanel.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createLineBorder(new Color(200, 220, 240), 2), + new EmptyBorder(30, 40, 30, 40) + )); + infoPanel.setBackground(new Color(255, 255, 255, 255)); + infoPanel.setOpaque(true); - // 添加系统状态信息 - infoPanel.add(createInfoLabel(messages.getString("SYSTEM_STATUS"), - messages.getString("RUNNING_NORMAL"), - new Color(0, 100, 0))); // 深绿色 + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(15, 15, 15, 15); + gbc.anchor = GridBagConstraints.WEST; + gbc.fill = GridBagConstraints.HORIZONTAL; - // 添加数据库连接信息 - infoPanel.add(createInfoLabel(messages.getString("DB_CONNECTION"), - conn != null ? messages.getString("CONNECTED") : messages.getString("DISCONNECTED"), - conn != null ? new Color(0, 100, 0) : Color.RED)); // 连接成功绿色/失败红色 + // 第一列 + gbc.gridx = 0; + gbc.gridy = 0; - try { - if (conn != null) { // 检查数据库连接 - try (Statement stmt = conn.createStatement(); // 创建语句 - ResultSet rs = stmt.executeQuery("SELECT VERSION()")) { // 执行版本查询 - if (rs.next()) { // 如果有结果 - infoPanel.add(createInfoLabel(messages.getString("DB_VERSION"), - rs.getString(1), - new Color(25, 25, 112))); // 添加数据库版本 - } - } - } - } catch (Exception e) { - e.printStackTrace(); // 打印异常 + // 修复1: 初始化标签并设置初始文本 + tagStatsLabel = new JLabel("0 / 0"); + tagStatsLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + infoPanel.add(createInfoRow(messages.getString("TAG_STATS"), tagStatsLabel, new Color(0, 100, 0)), gbc); + + gbc.gridy++; + baseStationStatsLabel = new JLabel("0 / 0"); + baseStationStatsLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + infoPanel.add(createInfoRow(messages.getString("BASE_STATION_STATS"), baseStationStatsLabel, new Color(0, 100, 0)), gbc); + + gbc.gridy++; + udpAInfoLabel = new JLabel(Dell_SystemConfiguration.hexport + " - " + messages.getString("RECEIVED_PACKETS") + ": 0"); + udpAInfoLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + infoPanel.add(createInfoRow(messages.getString("UDP_PORT_A"), udpAInfoLabel, new Color(178, 34, 34)), gbc); + + gbc.gridy++; + udpBInfoLabel = new JLabel(Dell_SystemConfiguration.ascallport + " - " + messages.getString("RECEIVED_PACKETS") + ": 0"); + udpBInfoLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + infoPanel.add(createInfoRow(messages.getString("UDP_PORT_B"), udpBInfoLabel, new Color(178, 34, 34)), gbc); + + gbc.gridy++; + memoryUsageLabel = new JLabel("0 MB / 0 MB"); + memoryUsageLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + infoPanel.add(createInfoRow(messages.getString("MEMORY_USAGE"), memoryUsageLabel, new Color(148, 0, 211)), gbc); + + // 第二列 + gbc.gridx = 1; + gbc.gridy = 0; + threadCountLabel = new JLabel("0"); + threadCountLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + infoPanel.add(createInfoRow(messages.getString("THREAD_COUNT"), threadCountLabel, new Color(148, 0, 211)), gbc); + + gbc.gridy++; + dbVersionLabel = new JLabel(""); // 初始为空,稍后设置 + dbVersionLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + infoPanel.add(createInfoRow(messages.getString("DB_VERSION"), dbVersionLabel, new Color(25, 25, 112)), gbc); + + gbc.gridy++; + JLabel dbStatusLabel = new JLabel(conn != null ? messages.getString("CONNECTED") : messages.getString("DISCONNECTED")); + dbStatusLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + dbStatusLabel.setForeground(conn != null ? new Color(0, 100, 0) : Color.RED); + infoPanel.add(createInfoRow(messages.getString("DB_STATUS"), dbStatusLabel, new Color(25, 25, 112)), gbc); + + gbc.gridy++; + JLabel softwareVersionLabel = new JLabel(messages.getString("APP_VERSION")); + softwareVersionLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + infoPanel.add(createInfoRow(messages.getString("SOFTWARE_VERSION"), softwareVersionLabel, new Color(25, 25, 112)), gbc); + + // 初始化数据库版本 + if (conn != null && dbVersionLabel.getText().isEmpty()) { + updateDbVersion(); } - - // 添加当前用户信息 - infoPanel.add(createInfoLabel(messages.getString("CURRENT_USER"), - messages.getString("ADMIN"), - new Color(25, 25, 112))); // 深蓝色 - - // 添加系统时间信息 - infoPanel.add(createInfoLabel(messages.getString("SYSTEM_TIME"), - new java.util.Date().toString(), - new Color(25, 25, 112))); // 深蓝色 - - // 添加UDP端口A统计 - infoPanel.add(createInfoLabel(messages.getString("UDP_PORT_A"), "0", new Color(178, 34, 34))); // 砖红色 - udpAPacketCountLabel = createInfoLabel("", "", new Color(178, 34, 34)); // 创建计数标签 - infoPanel.add(udpAPacketCountLabel); // 添加计数标签 - - // 添加UDP端口B统计 - infoPanel.add(createInfoLabel(messages.getString("UDP_PORT_B"), "0", new Color(178, 34, 34))); // 砖红色 - udpBPacketCountLabel = createInfoLabel("", "", new Color(178, 34, 34)); // 创建计数标签 - infoPanel.add(udpBPacketCountLabel); // 添加计数标签 - - // 添加内存使用统计 - infoPanel.add(createInfoLabel(messages.getString("MEMORY_USAGE"), "", new Color(148, 0, 211))); // 紫罗兰色 - memoryUsageLabel = createInfoLabel("", "", new Color(148, 0, 211)); // 创建内存标签 - infoPanel.add(memoryUsageLabel); // 添加内存标签 - - // 添加线程计数统计 - infoPanel.add(createInfoLabel(messages.getString("THREAD_COUNT"), "", new Color(148, 0, 211))); // 紫罗兰色 - threadCountLabel = createInfoLabel("", "", new Color(148, 0, 211)); // 创建线程标签 - infoPanel.add(threadCountLabel); // 添加线程标签 - - // 创建状态面板 - JPanel statsPanel = new JPanel(new GridLayout(1, 4, 15, 15)); // 创建网格布局面板 - statsPanel.setBorder(new EmptyBorder(20, 50, 10, 50)); // 设置空边框 - statsPanel.setOpaque(false); // 设置透明 - - // 添加统计盒子 - statsPanel.add(createStatBox(messages.getString("UDP_PORT_A_STAT"), udpAPacketCountLabel)); // UDP端口A统计 - statsPanel.add(createStatBox(messages.getString("UDP_PORT_B_STAT"), udpBPacketCountLabel)); // UDP端口B统计 - statsPanel.add(createStatBox(messages.getString("MEMORY_USAGE_STAT"), memoryUsageLabel)); // 内存使用统计 - statsPanel.add(createStatBox(messages.getString("THREAD_COUNT_STAT"), threadCountLabel)); // 线程计数统计 // 组装主面板 - panel.add(titlePanel, BorderLayout.NORTH); // 添加标题面板到北部 - panel.add(infoPanel, BorderLayout.CENTER); // 添加信息面板到中部 - panel.add(statsPanel, BorderLayout.SOUTH); // 添加状态面板到南部 + panel.add(titlePanel, BorderLayout.NORTH); + panel.add(infoPanel, BorderLayout.CENTER); - return panel; // 返回面板 + return panel; } - private JLabel createInfoLabel(String title, String value, Color color) { // 创建信息标签方法 - JLabel label = new JLabel("<html><div style='text-align:center;'><b>" + title + "</b><br>" + value + "</div></html>"); // 创建带HTML格式的标签 - label.setFont(new Font(messages.getString("FONT_NAME"), Font.PLAIN, 16)); // 设置字体 - label.setForeground(color); // 设置前景色 - label.setHorizontalAlignment(SwingConstants.CENTER); // 设置水平居中 - label.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直居中 - label.setOpaque(false); // 设置透明 - return label; // 返回标签 + private JPanel createInfoRow(String title, JLabel valueLabel, Color color) { + JPanel rowPanel = new JPanel(new BorderLayout(10, 0)); + rowPanel.setOpaque(false); + + JLabel titleLabel = new JLabel(title + ":"); + titleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); + titleLabel.setForeground(color.darker()); + + valueLabel.setForeground(color); + + rowPanel.add(titleLabel, BorderLayout.WEST); + rowPanel.add(valueLabel, BorderLayout.CENTER); + + // 添加装饰器 + JPanel decorator = new JPanel(); + decorator.setPreferredSize(new Dimension(5, 5)); + decorator.setBackground(color); + decorator.setOpaque(true); + rowPanel.add(decorator, BorderLayout.EAST); + + return rowPanel; } - private JPanel createStatBox(String title, JLabel valueLabel) { // 创建统计盒子方法 - JPanel boxPanel = new JPanel(new BorderLayout()); // 创建边界布局面板 - boxPanel.setBorder(BorderFactory.createCompoundBorder( // 设置复合边框 - BorderFactory.createLineBorder(new Color(70, 130, 180), 2), // 蓝色边框 - new EmptyBorder(15, 10, 15, 10) // 内边距 - )); - boxPanel.setBackground(new Color(240, 248, 255, 220)); // 设置半透明背景 - boxPanel.setOpaque(true); // 设置不透明 - - JLabel titleLabel = new JLabel(title, SwingConstants.CENTER); // 创建标题标签 - titleLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 18)); // 设置粗体 - titleLabel.setForeground(new Color(25, 25, 112)); // 设置深蓝色 - - valueLabel.setFont(new Font(messages.getString("FONT_NAME"), Font.BOLD, 24)); // 设置粗体大字号 - valueLabel.setHorizontalAlignment(SwingConstants.CENTER); // 设置居中 - - boxPanel.add(titleLabel, BorderLayout.NORTH); // 添加标题到北部 - boxPanel.add(valueLabel, BorderLayout.CENTER); // 添加值标签到中部 - - return boxPanel; // 返回面板 + private void updateDbVersion() { + if (conn != null) { + try (Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT VERSION()")) { + if (rs.next()) { + dbVersionLabel.setText(rs.getString(1)); + } + } catch (Exception ex) { + dbVersionLabel.setText("N/A"); + } + } } - private void startStatsTimer() { // 启动统计定时器方法 - statsTimer = new Timer(1000, e -> { // 创建1秒间隔的定时器 - // 更新UDP数据包计数 - udpAPacketCountLabel.setText(String.valueOf(UDPPortAReceiver.getPacketCount())); // 更新端口A计数 - udpBPacketCountLabel.setText(String.valueOf(UDPPortBReceiver.getPacketCount())); // 更新端口B计数 + private void startStatsTimer() { + statsTimer = new Timer(1000, e -> { + // 更新UDP端口A信息 + int packetCountA = (int) UDPPortAReceiver.getPacketCount(); + udpAInfoLabel.setText(Dell_SystemConfiguration.hexport + " - " + + messages.getString("RECEIVED_PACKETS") + ": " + packetCountA); + + // 更新UDP端口B信息 + int packetCountB = (int) UDPPortBReceiver.getPacketCount(); + udpBInfoLabel.setText(Dell_SystemConfiguration.ascallport + " - " + + messages.getString("RECEIVED_PACKETS") + ": " + packetCountB); // 更新内存使用情况 - Runtime runtime = Runtime.getRuntime(); // 获取运行时实例 - long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024); // 计算已用内存(MB) - long maxMemory = runtime.maxMemory() / (1024 * 1024); // 计算最大内存(MB) - memoryUsageLabel.setText(usedMemory + " " + messages.getString("MB") + " / " + maxMemory + " " + messages.getString("MB")); // 设置内存文本 + Runtime runtime = Runtime.getRuntime(); + long usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / (1024 * 1024); + long maxMemory = runtime.maxMemory() / (1024 * 1024); + memoryUsageLabel.setText(usedMemory + " " + messages.getString("MB") + " / " + + maxMemory + " " + messages.getString("MB")); - // 更新线程数量 - threadCountLabel.setText(String.valueOf(Thread.activeCount())); // 设置活动线程数 + // 更新线程数 + threadCountLabel.setText(String.valueOf(Thread.activeCount())); + + // 更新标签状态 + int onlineTags = Dell_tag.getOnlineLocationTags().size(); + int totalTags = Dell_tag.getLocationTagCount(); + tagStatsLabel.setText(onlineTags + " / " + totalTags); + + // 更新基站状态 + int onlineStations = Dell_BaseStation.getOnlineBaseStations().size(); + int totalStations = Dell_BaseStation.getLocationBaseCount(); + baseStationStatsLabel.setText(onlineStations + " / " + totalStations); }); - statsTimer.start(); // 启动定时器 + statsTimer.start(); } @Override - public void dispose() { // 销毁方法 - super.dispose(); // 调用父类销毁 - if (statsTimer != null) { // 检查定时器 - statsTimer.stop(); // 停止定时器 + public void dispose() { + super.dispose(); + if (statsTimer != null) { + statsTimer.stop(); } } } \ No newline at end of file diff --git a/systemfile/Messages_en.properties b/systemfile/Messages_en.properties index ea593dd..d565c51 100644 --- a/systemfile/Messages_en.properties +++ b/systemfile/Messages_en.properties @@ -1,3 +1,12 @@ +TAG_STATS = Tag Statistics +BASE_STATION_STATS = Base Station Statistics +SOFTWARE_VERSION = Software Version +APP_VERSION = 1.0.0 +UDP_PORT_A = UDP Receive Port A +UDP_PORT_B = UDP Receive Port B +DB_VERSION = Database Version +DB_STATUS = Database Status +RECEIVED_PACKETS=Received # New message viewing related resources MESSAGE_VIEW_ALL_TYPES=All Types MESSAGE_VIEW_UDP_PORT_A=UDP Port A diff --git a/systemfile/Messages_zh.properties b/systemfile/Messages_zh.properties index f809f94..891f3c5 100644 --- a/systemfile/Messages_zh.properties +++ b/systemfile/Messages_zh.properties @@ -1,3 +1,12 @@ +TAG_STATS=鏍囩缁熻 +BASE_STATION_STATS=鍩虹珯缁熻 +SOFTWARE_VERSION=杞欢鐗堟湰 +APP_VERSION=1.0.0 +UDP_PORT_A=鏁版嵁鎺ユ敹绔彛 +UDP_PORT_B=鏁版嵁鎺ユ敹绔彛 +DB_VERSION=鏁版嵁搴撶増鏈� +DB_STATUS=鏁版嵁搴撶姸鎬� +RECEIVED_PACKETS=鎺ユ敹 # 鏂板鐨勬姤鏂囨煡鐪嬬浉鍏宠祫婧� MESSAGE_VIEW_ALL_TYPES=鎵�鏈夌被鍨� MESSAGE_VIEW_UDP_PORT_A=UDP绔彛A @@ -483,8 +492,6 @@ MESSAGE_VIEW_EMPTY_DATA=鍙戦�佸唴瀹逛笉鑳戒负绌� ERROR=閿欒 # 娆㈣繋鐣岄潰鐩戞帶 -UDP_PORT_A=UDP绔彛A (8234) -UDP_PORT_B=UDP绔彛B (7000) MEMORY_USAGE=鍐呭瓨浣跨敤 THREAD_COUNT=绾跨▼鏁伴噺 MB=MB diff --git a/systemfile/logfile/openlog.txt b/systemfile/logfile/openlog.txt index f8a393f..f73e05b 100644 --- a/systemfile/logfile/openlog.txt +++ b/systemfile/logfile/openlog.txt @@ -701,3 +701,83 @@ 工作时长: 0小时 4分钟 12秒 ----------------------------------- 程序启动: 2025-08-09 16:32:39 +程序关闭: 2025-08-09 20:05:40 +工作时长: 3小时 33分钟 1秒 +----------------------------------- +程序启动: 2025-08-09 20:07:08 +程序关闭: 2025-08-09 20:11:43 +工作时长: 0小时 4分钟 35秒 +----------------------------------- +程序启动: 2025-08-09 20:11:46 +程序关闭: 2025-08-09 21:57:03 +工作时长: 1小时 45分钟 17秒 +----------------------------------- +程序启动: 2025-08-09 21:57:05 +程序关闭: 2025-08-09 22:02:50 +工作时长: 0小时 5分钟 44秒 +----------------------------------- +程序启动: 2025-08-09 22:12:39 +程序关闭: 2025-08-09 22:21:24 +工作时长: 0小时 8分钟 45秒 +----------------------------------- +程序启动: 2025-08-09 22:21:26 +程序关闭: 2025-08-09 22:31:29 +工作时长: 0小时 10分钟 2秒 +----------------------------------- +程序启动: 2025-08-09 22:31:30 +程序关闭: 2025-08-09 22:31:44 +工作时长: 0小时 0分钟 13秒 +----------------------------------- +程序启动: 2025-08-09 22:31:59 +程序关闭: 2025-08-09 22:44:51 +工作时长: 0小时 12分钟 52秒 +----------------------------------- +程序启动: 2025-08-09 22:44:53 +程序关闭: 2025-08-09 22:44:55 +工作时长: 0小时 0分钟 1秒 +----------------------------------- +程序启动: 2025-08-09 22:45:33 +程序关闭: 2025-08-09 22:45:35 +工作时长: 0小时 0分钟 1秒 +----------------------------------- +程序启动: 2025-08-09 22:46:58 +程序关闭: 2025-08-09 22:49:10 +工作时长: 0小时 2分钟 12秒 +----------------------------------- +程序启动: 2025-08-09 22:49:12 +程序关闭: 2025-08-09 22:58:17 +工作时长: 0小时 9分钟 4秒 +----------------------------------- +程序启动: 2025-08-09 22:58:19 +程序关闭: 2025-08-09 23:09:45 +工作时长: 0小时 11分钟 25秒 +----------------------------------- +程序启动: 2025-08-09 23:09:47 +程序关闭: 2025-08-09 23:19:34 +工作时长: 0小时 9分钟 46秒 +----------------------------------- +程序启动: 2025-08-09 23:19:36 +程序关闭: 2025-08-09 23:19:51 +工作时长: 0小时 0分钟 14秒 +----------------------------------- +程序启动: 2025-08-09 23:20:10 +程序关闭: 2025-08-09 23:20:15 +工作时长: 0小时 0分钟 5秒 +----------------------------------- +程序启动: 2025-08-09 23:21:01 +程序关闭: 2025-08-09 23:21:05 +工作时长: 0小时 0分钟 4秒 +----------------------------------- +程序启动: 2025-08-09 23:24:49 +程序关闭: 2025-08-09 23:29:56 +工作时长: 0小时 5分钟 6秒 +----------------------------------- +程序启动: 2025-08-09 23:29:58 +程序关闭: 2025-08-09 23:30:36 +工作时长: 0小时 0分钟 38秒 +----------------------------------- +程序启动: 2025-08-09 23:30:38 +程序关闭: 2025-08-09 23:30:52 +工作时长: 0小时 0分钟 14秒 +----------------------------------- +程序启动: 2025-08-09 23:30:58 -- Gitblit v1.9.3