From 1bda9524add969e315d870f284046ecf1097f956 Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期日, 24 八月 2025 18:01:25 +0800
Subject: [PATCH] 修改

---
 src/dell55AAData/Dell55AA12HighPerf.java        |   36 
 src/dell55AAData/Dell55AA01Parser.java          |  163 +-
 src/dell_targets/TagManagementPanel.java        |  142 ++
 src/dell_targets/Dell_tag.java                  |  305 +++++
 src/window/WelcomeFrame.java                    |    2 
 src/databases/DBConnector.java                  |   57 +
 systemfile/logfile/openlog.txt                  |  294 +++++
 src/dell_system/SettingsPanelContent.java       |   20 
 src/dell_system/CompanyManagementPanel.java     |   64 
 src/udptcp/UDPPortAReceiver.java                |    3 
 src/dell55AAData/DellGngga.java                 |   77 +
 src/dell_targets/TagTypeManagementPanel.java    |   57 
 src/udptcp/UDPPortBReceiver.java                |  198 +-
 src/dell_targets/SatelliteDevicePanel.java      |  483 ++++++++
 src/dell55AAData/XTB.java                       |   60 +
 src/publicsWay/TableUtils.java                  |  123 +
 src/dell_anchor/BaseStationManagementPanel.java |  186 +-
 src/publicsWay/TrackData.java                   |  177 +++
 src/dell_system/SerialPacketParser.java         |    4 
 src/targets/LocationTag.java                    |   46 
 src/chushihua/Chushihua.java                    |    8 
 src/publicsWay/PacketProcessingSystemB.java     |  252 ++++
 src/window/NavigationTreeFactory.java           |    3 
 src/dell_system/MessageViewPanel.java           |   31 
 src/dell_targets/Dell_SystemConfiguration.java  |   16 
 src/dell55AAData/Dell55AA02Parser.java          |   85 
 src/publicsWay/PacketProcessingSystem.java      |    4 
 systemfile/Messages_en.properties               |   42 
 systemfile/Messages_zh.properties               |   43 
 src/scheduled_task/TrackTableManager.java       |  119 +-
 src/window/ContentPanelFactory.java             |    3 
 src/publicsWay/ButtonUtils.java                 |   40 
 src/publicsWay/TrackDataBatchInserter.java      |  122 ++
 33 files changed, 2,771 insertions(+), 494 deletions(-)

diff --git a/src/chushihua/Chushihua.java b/src/chushihua/Chushihua.java
index eb33bb9..978d302 100644
--- a/src/chushihua/Chushihua.java
+++ b/src/chushihua/Chushihua.java
@@ -8,7 +8,9 @@
 import dell_targets.Dell_BaseStation;
 import dell_targets.Dell_SystemConfiguration;
 import dell_targets.Dell_tag;
-import publicsWay.UDPPortAReceiver;
+import scheduled_task.TrackTableManager;
+import udptcp.UDPPortAReceiver;
+import udptcp.UDPPortBReceiver;
 
 public class Chushihua {
 	public static void getchushihua()  {
@@ -17,12 +19,14 @@
 			Dell_tag.getlocationTags();
 			Dell_BaseStation.getBaseStations();
 			UDPPortAReceiver.startReceiver();
+			UDPPortBReceiver.startReceiver();
 			Dell_Map.getAllMaps();
 			Dell_Fence.getAllFences();
 			Dell_company.getAllCompanies();
 			Dell_LayerManagement.getAllLayers();
 			Dell_GroupManagement.getAllGroups();			
-			if(Dell_SystemConfiguration.gnsstoxyOpen) {Dell_Map.get_foor_xycs();}			
+			if(Dell_SystemConfiguration.gnsstoxyOpen) {Dell_Map.get_foor_xycs();}	
+			TrackTableManager.Start();//生成归轨迹表
 		} catch (SQLException e) {
 			// TODO 自动生成的 catch 块
 			e.printStackTrace();
diff --git a/src/databases/DBConnector.java b/src/databases/DBConnector.java
index 1d89561..edf9e0e 100644
--- a/src/databases/DBConnector.java
+++ b/src/databases/DBConnector.java
@@ -95,6 +95,8 @@
                     case "FIELD_VALIDATION_FAIL": return "字段验证失败";
                     case "DEVICE_ID_EXISTS": return "设备编号已存在";
                     case "INVALID_NUMBER_FORMAT": return "无效的数字格式"; 
+                    case "DB_DDL_ERROR": return "执行DDL语句失败";
+                    case "DB_BATCH_INSERT_ERROR": return "批量插入失败";
                     // 添加缺失的键
                     case "DB_QUERY_ERROR": return "数据库查询失败";
                     default: 
@@ -117,6 +119,8 @@
                             "FIELD_VALIDATION_FAIL",
                             "DEVICE_ID_EXISTS",
                             "INVALID_NUMBER_FORMAT",
+                            "DB_DDL_ERROR",
+                            "DB_BATCH_INSERT_ERROR",
                             "DB_QUERY_ERROR"  // 添加缺失的键
                     )
                 );
@@ -497,4 +501,57 @@
         return pstmt.executeQuery();
     }
     
+ // 在DBConnector类中添加以下方法
+
+    /**
+     * 检查表是否存在
+     */
+    public static boolean tableExists(String tableName) {
+        try (Connection conn = connectToDatabase()) {
+            if (conn == null) return false;
+            try (ResultSet rs = conn.getMetaData().getTables(null, null, tableName, null)) {
+                return rs.next();
+            }
+        } catch (SQLException e) {
+            logError("DB_QUERY_ERROR", "检查表是否存在失败: " + e.getMessage());
+            return false;
+        }
+    }
+    
+    /**
+     * 执行DDL语句(创建表等)
+     */
+    public static boolean executeDDL(String ddlSQL) {
+        try (Connection conn = connectToDatabase();
+             Statement stmt = conn.createStatement()) {
+            stmt.execute(ddlSQL);
+            return true;
+        } catch (SQLException e) {
+            logError("DB_DDL_ERROR", "执行DDL语句失败: " + e.getMessage() + "\nDDL: " + ddlSQL);
+            return false;
+        }
+    }
+    
+    /**
+     * 执行批量更新操作
+     */
+    public static int executeBatchUpdate(String sql, List<Object[]> paramsList) {
+        try (Connection conn = connectToDatabase();
+             PreparedStatement pstmt = conn.prepareStatement(sql)) {
+            
+            for (Object[] params : paramsList) {
+                for (int i = 0; i < params.length; i++) {
+                    pstmt.setObject(i + 1, params[i]);
+                }
+                pstmt.addBatch();
+            }
+            
+            int[] results = pstmt.executeBatch();
+            return results.length;
+        } catch (SQLException e) {
+            logError("DB_BATCH_INSERT_ERROR", "批量插入失败: " + e.getMessage() + "\nSQL: " + sql);
+            return 0;
+        }
+    }
+    
 }
\ No newline at end of file
diff --git a/src/dell55AAData/Dell55AA01Parser.java b/src/dell55AAData/Dell55AA01Parser.java
index 7e6cdff..da46771 100644
--- a/src/dell55AAData/Dell55AA01Parser.java
+++ b/src/dell55AAData/Dell55AA01Parser.java
@@ -22,7 +22,7 @@
 		public int distance;      // 距离(毫米)
 		public int power;         // 电量(0-100)
 		public int buttonPressed; // 按钮状态
-
+		public boolean buttonPressed2;
 		public void reset() {
 			sequenceNum = 0;
 			tagId = "";
@@ -30,6 +30,7 @@
 			distance = 0;
 			power = 0;
 			buttonPressed = 0;
+			buttonPressed2=false;
 		}
 	}
 
@@ -39,98 +40,110 @@
 	 * @return 解析结果(错误时返回null)
 	 */
 	public static ParseResult parse(String message, String ip, int port) {
-	    if (message == null || message.isEmpty()) {
-	        return null;
-	    }
+		if (message == null || message.isEmpty()) {
+			return null;
+		}
 
-	    // 清洗数据:移除所有非十六进制字符
-	    char[] cleanedMessage = cleanMessage(message);
+		// 清洗数据:移除所有非十六进制字符
+		char[] cleanedMessage = cleanMessage(message);
 
-	    // 数据校验
-	    if (cleanedMessage == null || cleanedMessage.length < MIN_LENGTH) {
-	        return null;
-	    }
+		// 数据校验
+		if (cleanedMessage == null || cleanedMessage.length < MIN_LENGTH) {
+			return null;
+		}
 
-	    // 协议头校验 (55AA01)
-	    if (!new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) {
-	        return null;
-	    }
+		// 协议头校验 (55AA01)
+		if (!new String(cleanedMessage, 0, 6).equals(EXPECTED_HEADER)) {
+			return null;
+		}
 
-	    ParseResult result = RESULT_CACHE.get();
-	    result.reset();
+		ParseResult result = RESULT_CACHE.get();
+		result.reset();
 
-	    try {
-	        if (cleanedMessage.length < 30) { // 确保有足够长度访问charAt(28)
-	            return null;
-	        }
+		try {
+			if (cleanedMessage.length < 30) { // 确保有足够长度访问charAt(28)
+				return null;
+			}
 
-	        // 解析序列号 (位置8-9)
-	        result.sequenceNum = HexUtils.fastHexToByte(cleanedMessage[8], cleanedMessage[9]);
+			// 解析序列号 (位置8-9)
+			result.sequenceNum = HexUtils.fastHexToByte(cleanedMessage[8], cleanedMessage[9]);
 
-	        // 解析标签ID (位置10-13, 小端序)
-	        result.tagId = new String(new char[]{
-	                cleanedMessage[12], cleanedMessage[13], // 高位
-	                cleanedMessage[10], cleanedMessage[11]  // 低位
-	        });
+			// 解析标签ID (位置10-13, 小端序)
+			result.tagId = new String(new char[]{
+					cleanedMessage[12], cleanedMessage[13], // 高位
+					cleanedMessage[10], cleanedMessage[11]  // 低位
+			});
 
-	        // 解析锚点ID (位置14-17, 小端序)
-	        result.anchorId = new String(new char[]{
-	                cleanedMessage[16], cleanedMessage[17], // 高位
-	                cleanedMessage[14], cleanedMessage[15]  // 低位
-	        });
+			// 解析锚点ID (位置14-17, 小端序)
+			result.anchorId = new String(new char[]{
+					cleanedMessage[16], cleanedMessage[17], // 高位
+					cleanedMessage[14], cleanedMessage[15]  // 低位
+			});
 
-	        // 解析距离 (位置18-25, 4字节小端整数)
-	        int b0 = HexUtils.fastHexToByte(cleanedMessage[18], cleanedMessage[19]); // 最低位
-	        int b1 = HexUtils.fastHexToByte(cleanedMessage[20], cleanedMessage[21]);
-	        int b2 = HexUtils.fastHexToByte(cleanedMessage[22], cleanedMessage[23]);
-	        int b3 = HexUtils.fastHexToByte(cleanedMessage[24], cleanedMessage[25]); // 最高位
-	        int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
-	        result.distance = raw; // 保持原始整数值
+			// 解析距离 (位置18-25, 4字节小端整数)
+			int b0 = HexUtils.fastHexToByte(cleanedMessage[18], cleanedMessage[19]); // 最低位
+			int b1 = HexUtils.fastHexToByte(cleanedMessage[20], cleanedMessage[21]);
+			int b2 = HexUtils.fastHexToByte(cleanedMessage[22], cleanedMessage[23]);
+			int b3 = HexUtils.fastHexToByte(cleanedMessage[24], cleanedMessage[25]); // 最高位
+			int raw = (b3 << 24) | (b2 << 16) | (b1 << 8) | b0;
+			result.distance = raw; // 保持原始整数值
 
-	        // 解析电量 (位置26-27)
-	        result.power = HexUtils.fastHexToByte(cleanedMessage[26], cleanedMessage[27]);
+			// 解析电量 (位置26-27)
+			result.power = HexUtils.fastHexToByte(cleanedMessage[26], cleanedMessage[27]);
 
-	        // 解析按钮状态 (位置28-29)
-	        result.buttonPressed = HexUtils.fastHexToByte(cleanedMessage[28], cleanedMessage[29]);
+			// 解析按钮状态 (位置28-29)
+			result.buttonPressed = HexUtils.fastHexToByte(cleanedMessage[28], cleanedMessage[29]);
+			result.buttonPressed2 =result.buttonPressed==1;
+			// 日志和更新操作可以考虑优化或减少调用频率
+			if (MessageViewPanel.isWindowVisible) {
+			    StringBuilder sb = new StringBuilder();
+			    sb.append("55AA01 Seq:")
+			      .append(result.sequenceNum)
+			      .append(",Tagid:")
+			      .append(result.tagId)
+			      .append(",Anchorid:")
+			      .append(result.anchorId)
+			      .append(",Distance:")
+			      .append(result.distance)
+			      .append(",Power:")
+			      .append(result.power)
+			      .append(",Button:")
+			      .append(result.buttonPressed);
+			    MessageViewPanel.showData(sb.toString(), ip, port, 0, "UDPA", "55AA01", "ALL");
+			}
 
-	        // 日志和更新操作可以考虑优化或减少调用频率
-	        String hexData = "55AA01 包序:" + result.sequenceNum + ",标签编号:" + result.tagId + ",基站编号:" + result.anchorId +
-	                ",距离:" + result.distance + ",电量:" + result.power +
-	                ",按钮状态:" + result.buttonPressed;
-	        MessageViewPanel.showData(hexData, ip, port, 0, "UDPA", "55AA01", "ALL");
+			String time = EfficientTimeFormatter.getCurrentTimeFormatted();
+			Dell_BaseStation.updateBaseStationProperty(result.anchorId, "ipAddress", ip);
+			Dell_BaseStation.updateBaseStationProperty(result.anchorId, "port", port + "");
+			Dell_BaseStation.updateBaseStationProperty(result.anchorId, "status", "1");
+			Dell_BaseStation.updateBaseStationProperty(result.anchorId, "onlineTime", time);
 
-	        String time = EfficientTimeFormatter.getCurrentTimeFormatted();
-	        Dell_BaseStation.updateBaseStationProperty(result.anchorId, "ipAddress", ip);
-	        Dell_BaseStation.updateBaseStationProperty(result.anchorId, "port", port + "");
-	        Dell_BaseStation.updateBaseStationProperty(result.anchorId, "status", "1");
-	        Dell_BaseStation.updateBaseStationProperty(result.anchorId, "onlineTime", time);
+			Dell_tag.updateLocationTagProperty(result.tagId, "sosStatus", result.buttonPressed + "");
+			Dell_tag.updateLocationTagProperty(result.tagId, "onlineStatus", "1");
+			Dell_tag.updateLocationTagProperty(result.tagId, "lastUwbSignalTime", time);
+			Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingSeq", result.sequenceNum + "");
+			Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingBaseId", result.anchorId);
+			Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingDistance", result.distance + "");
+			Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingBaseCount", "1");
 
-	        Dell_tag.updateLocationTagProperty(result.tagId, "sosStatus", result.buttonPressed + "");
-	        Dell_tag.updateLocationTagProperty(result.tagId, "onlineStatus", "1");
-	        Dell_tag.updateLocationTagProperty(result.tagId, "lastUwbSignalTime", time);
-	        Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingSeq", result.sequenceNum + "");
-	        Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingBaseId", result.anchorId);
-	        Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingDistance", result.distance + "");
-	        Dell_tag.updateLocationTagProperty(result.tagId, "latestRangingBaseCount", "1");
+		} catch (IndexOutOfBoundsException | NumberFormatException e) {
+			System.err.println("Parsing error in packet from " + ip + ":" + port);
+			return null;
+		}
 
-	    } catch (IndexOutOfBoundsException | NumberFormatException e) {
-	        System.err.println("Parsing error in packet from " + ip + ":" + port);
-	        return null;
-	    }
-
-	    return result;
+		return result;
 	}
 
 	private static char[] cleanMessage(String message) {
-	    char[] cleaned = new char[message.length()];
-	    int j = 0;
-	    for (char c : message.toCharArray()) {
-	        if (Character.isDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
-	            cleaned[j++] = Character.toUpperCase(c);
-	        }
-	    }
-	    if (j == 0) return null;
-	    return Arrays.copyOf(cleaned, j);
+		char[] cleaned = new char[message.length()];
+		int j = 0;
+		for (char c : message.toCharArray()) {
+			if (Character.isDigit(c) || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) {
+				cleaned[j++] = Character.toUpperCase(c);
+			}
+		}
+		if (j == 0) return null;
+		return Arrays.copyOf(cleaned, j);
 	}
 
 	public static void updateBase(String baseStationId, String propertyName, String value) {
diff --git a/src/dell55AAData/Dell55AA02Parser.java b/src/dell55AAData/Dell55AA02Parser.java
index 741ae5e..6ad5b14 100644
--- a/src/dell55AAData/Dell55AA02Parser.java
+++ b/src/dell55AAData/Dell55AA02Parser.java
@@ -1,44 +1,42 @@
 package dell55AAData;
 
+import dell_system.MessageViewPanel;
 import dell_targets.Dell_BaseStation;
+import publicsWay.EfficientTimeFormatter;
 
 public class Dell55AA02Parser {
-	private static final String EXPECTED_HEADER = "55AA02";
-	private static final int MIN_LENGTH = 36; // 18字节 * 2字符/字节
-	private static final int BASE_ID_START = 8;   // 基站ID起始位置(第4字节)
-	private static final int SYNC_STATUS_START = 12; // 同步状态起始位置(第5字节)
-	private static final int PRESSURE_START = 14; // 气压值起始位置(第6字节)
+	private static final int SYNC_STATUS_START = 12;  // 同步状态起始位置(第5字节)
+	private static final int PRESSURE_START = 14;     // 气压值起始位置(第6字节)
+	private static final int MIN_MESSAGE_LENGTH = 22; // 最小有效数据长度
+
+	// 重用StringBuilder减少内存分配
+	private static final ThreadLocal<StringBuilder> hexDataBuilder = 
+			ThreadLocal.withInitial(() -> new StringBuilder(64));
 
 	/**
-	 * 解析55AA02格式的基站数据
+	 * 高效解析55AA02格式的基站数据
 	 * @param message 接收到的数据(十六进制字符串)
 	 */
-	public static void parseAndUpdate(String message) {
+	public static void parse(String message, String ip, int port) {
 		// 1. 基础校验
-		if (message == null || message.length() < MIN_LENGTH) {
+		if (message == null || message.length() < MIN_MESSAGE_LENGTH) {
 			return;
 		}
 
-		// 2. 头部校验(固定开头字符串)
-		for (int i = 0; i < EXPECTED_HEADER.length(); i++) {
-			if (message.charAt(i) != EXPECTED_HEADER.charAt(i)) {
-				return;
-			}
-		}
+		// 2. 解析标签ID (位置8-11, 小端序)
+		char c8 = message.charAt(8);
+		char c9 = message.charAt(9);
+		char c10 = message.charAt(10);
+		char c11 = message.charAt(11);
 
-		// 3. 解析基站ID(原始数据字符串)
-		String baseId = new String(new char[]{
-				message.charAt(BASE_ID_START),
-				message.charAt(BASE_ID_START + 1),
-				message.charAt(BASE_ID_START + 2),
-				message.charAt(BASE_ID_START + 3)
-		});
+		// 直接构建baseId字符串
+		String baseId = new String(new char[]{c10, c11, c8, c9});
 
-		// 4. 解析同步状态(1字节)
-		char syncChar = message.charAt(SYNC_STATUS_START + 1); // 取状态字符
-		String syncStatus = (syncChar == '0') ? "0" : "1";
+		// 3. 解析同步状态(1字节)
+		char syncStatusChar = message.charAt(SYNC_STATUS_START + 1);
+		String syncStatus = (syncStatusChar == '0') ? "0" : "1";
 
-		// 5. 解析气压值(4字节小端序)
+		// 4. 高效解析气压值(4字节小端序)
 		int pressure = 0;
 		for (int i = 0; i < 8; i += 2) {
 			int idx = PRESSURE_START + i;
@@ -46,21 +44,34 @@
 			int byteValue = HexUtils.fastHexToByte(message.charAt(idx), message.charAt(idx + 1));
 			pressure |= (byteValue << (i * 4)); // 小端合并
 		}
-		String pressureStr = String.valueOf(pressure);
 
-		// 6. 更新基站数据		
-		updateBaseStationData(baseId, syncStatus ,pressureStr);
-	}
 
-	/**
-	 * 更新基站数据
-	 * @param baseId 基站ID
-	 * @param syncStatus 同步状态
-	 * @param pressure 气压值字符串
-	 */
-	private static void updateBaseStationData(String baseId, String syncStatus, String pressure) {
+		// 5. 更新基站数据
+		if (MessageViewPanel.isWindowVisible) {
+			StringBuilder sb = hexDataBuilder.get();
+			sb.setLength(0);
+			sb.append("55AA02 AnchorHeart,Anchorid:")
+			.append(baseId)
+			.append(",SyncStatus:")
+			.append(syncStatus)
+			.append(",Pressure:")
+			.append(pressure);
+			MessageViewPanel.showData(sb.toString(), ip, port, 0, "UDPA", "55AA02", baseId);
+		}
+
+		// 延迟创建时间字符串直到必要时刻
+		String time = EfficientTimeFormatter.getCurrentTimeFormatted();
+
+		// 使用预分配字符串常量减少内存分配
+		Dell_BaseStation.updateBaseStationProperty(baseId, "ipAddress", ip);
+		Dell_BaseStation.updateBaseStationProperty(baseId, "port", Integer.toString(port));
+		Dell_BaseStation.updateBaseStationProperty(baseId, "status", "1");
+		Dell_BaseStation.updateBaseStationProperty(baseId, "onlineTime", time);
 		Dell_BaseStation.updateBaseStationProperty(baseId, "syncStatus", syncStatus);
-		Dell_BaseStation.updateBaseStationProperty(baseId, "barometerReading", pressure);
+		Dell_BaseStation.updateBaseStationProperty(baseId, "barometerReading", Integer.toString(pressure));
 	}
 
+
+
+
 }
\ No newline at end of file
diff --git a/src/dell55AAData/Dell55AA12HighPerf.java b/src/dell55AAData/Dell55AA12HighPerf.java
index 46f169a..d27ad7f 100644
--- a/src/dell55AAData/Dell55AA12HighPerf.java
+++ b/src/dell55AAData/Dell55AA12HighPerf.java
@@ -1,5 +1,7 @@
 package dell55AAData;
 
+import dell_system.MessageViewPanel;
+
 public class Dell55AA12HighPerf {
     
     // 协议常量
@@ -8,6 +10,9 @@
     private static final int MIN_LENGTH = 34; // 最小数据长度
     private static final ThreadLocal<ParseResult> RESULT_CACHE = // 解析结果缓存
         ThreadLocal.withInitial(ParseResult::new);
+ // 重用StringBuilder减少内存分配
+ 	private static final ThreadLocal<StringBuilder> hexDataBuilder = 
+ 			ThreadLocal.withInitial(() -> new StringBuilder(64));
 
     // 解析结果类
     public static class ParseResult { 
@@ -84,6 +89,37 @@
         // 解析锚点信息
         parseAnchorInfo(chars, result);
         
+        if (MessageViewPanel.isWindowVisible) {
+        	// 组装基站信息
+            StringBuilder ids = new StringBuilder();
+            StringBuilder dists = new StringBuilder();
+            StringBuilder powers = new StringBuilder();
+            for (int i = 0; i < result.anchorCount; i++) {
+                if (i > 0) {
+                    ids.append(',');
+                    dists.append(',');
+                    powers.append(',');
+                }
+                ids.append(result.anchorIds[i]);
+                dists.append(result.distances[i]);
+                powers.append(result.anchorPowers[i]);
+            }
+			StringBuilder sb = hexDataBuilder.get();
+			  sb.append("55AA12 ,Seq:").append(result.sequenceNum)
+              .append(",Tagid:").append(result.tagId)
+              .append(",Power: ").append(result.power).append("%")
+              .append(",button:").append(result.sosButtonPressed)
+              .append(",Static:").append(result.isStatic )
+              .append(",Sleep:").append(result.isSleeping )
+              .append(",State:").append(result.vibrationState )
+              .append(",TagRemoved:").append(result.tagRemoved)
+              .append(",TagHeight:").append(result.tagHeight)
+              .append(",AncNum:").append(result.anchorCount)
+              .append(",AncIds:[").append(ids)
+              .append("],Dis:[").append(dists)
+              .append("],AncPowers:[").append(powers).append("]").append('\n');              
+			MessageViewPanel.showData(sb.toString(), ip, port, 0, "UDPA", "55AA12",result.tagId);
+		}
         return result;
     }
 
diff --git a/src/dell55AAData/DellGngga.java b/src/dell55AAData/DellGngga.java
new file mode 100644
index 0000000..d3c4074
--- /dev/null
+++ b/src/dell55AAData/DellGngga.java
@@ -0,0 +1,77 @@
+package dell55AAData;
+
+public class DellGngga {
+    // 解析结果存储
+    private String utcTime; // UTC时间
+    private String latitude; // 纬度
+    private String latHemisphere; // 纬度半球(N/S)
+    private String longitude; // 经度
+    private String lonHemisphere; // 经度半球(E/W)
+    private String quality; // 定位质量指示器
+    private String satellites; // 使用的卫星数量
+    private String hdop; // 水平精度因子
+    private String altitude; // 海拔高度
+    private String altitudeUnit; // 海拔高度单位
+    private String geoidHeight; // 大地水准面高度
+    private String geoidHeightUnit; // 大地水准面高度单位
+    private String differentialTime; // 差分时间(秒)
+    private String checksum = ""; // 校验和
+    private String deviceId; // 设备ID
+    private String battery; // 电池电量
+    private String signalStrength; // 信号强度
+    private String reserve1; // 保留字段1
+    private String reserve2; // 保留字段2
+    private String reserve3; // 保留字段3
+
+    public void parse(String data) {
+        // 直接按逗号分割字段
+        String[] fields = data.split(",");
+        
+        // 验证字段数量
+        if (fields.length < 21) return;
+
+        // 直接赋值各个字段
+        utcTime = fields[1];
+        latitude = fields[2];
+        latHemisphere = fields[3];
+        longitude = fields[4];
+        lonHemisphere = fields[5];
+        quality = fields[6];
+        satellites = fields[7];
+        hdop = fields[8];
+        altitude = fields[9];
+        altitudeUnit = fields[10];
+        geoidHeight = fields[11];
+        geoidHeightUnit = fields[12];
+        differentialTime = fields[13];
+        checksum = fields[14];
+        deviceId = fields[15];
+        battery = fields[16];
+        signalStrength = fields[17];
+        reserve1 = fields[18];
+        reserve2 = fields[19];
+        reserve3 = fields[20];
+    }
+
+    // ===== 结果获取方法 =====
+    public String getUtcTime() { return utcTime; }
+    public String getLatitude() { return latitude; }
+    public String getLatHemisphere() { return latHemisphere; }
+    public String getLongitude() { return longitude; }
+    public String getLonHemisphere() { return lonHemisphere; }
+    public String getQuality() { return quality; }
+    public String getSatellites() { return satellites; }
+    public String getHdop() { return hdop; }
+    public String getAltitude() { return altitude; }
+    public String getAltitudeUnit() { return altitudeUnit; }
+    public String getGeoidHeight() { return geoidHeight; }
+    public String getGeoidHeightUnit() { return geoidHeightUnit; }
+    public String getDifferentialTime() { return differentialTime; }
+    public String getChecksum() { return checksum; }
+    public String getDeviceId() { return deviceId; }
+    public String getBattery() { return battery; }
+    public String getSignalStrength() { return signalStrength; }
+    public String getReserve1() { return reserve1; }
+    public String getReserve2() { return reserve2; }
+    public String getReserve3() { return reserve3; }
+}
\ No newline at end of file
diff --git a/src/dell55AAData/XTB.java b/src/dell55AAData/XTB.java
new file mode 100644
index 0000000..f7fcd73
--- /dev/null
+++ b/src/dell55AAData/XTB.java
@@ -0,0 +1,60 @@
+package dell55AAData;
+public class XTB {
+    // 解析结果存储
+    private String header;         // 包头
+    private String deviceId;       // 设备编号
+    private String battery;        // 电量
+    private String version;        // 版本号
+    private String ccid;           // CCID
+    private String button;         // 按键
+    private String rtcmSource;     // RTCM源
+    
+    // 用于高效解析的临时变量
+    private int startIndex;
+    private int endIndex;
+    private String data;
+    
+    public void parse(String data) {
+        this.data = data;
+        int fieldCount = 0;
+        startIndex = 0;
+        endIndex = 0;
+        
+        // 快速遍历字符串解析字段
+        for (int i = 0; i < data.length(); i++) {
+            if (data.charAt(i) == ',' || i == data.length() - 1) {
+                endIndex = (i == data.length() - 1) ? i + 1 : i;
+                assignField(fieldCount, startIndex, endIndex);
+                fieldCount++;
+                startIndex = i + 1;
+                
+                // 如果已经解析了所有7个字段,提前退出
+                if (fieldCount >= 7) break;
+            }
+        }
+    }
+    
+    private void assignField(int fieldIndex, int start, int end) {
+        switch (fieldIndex) {
+            case 0: header = data.substring(start, end); break;
+            case 1: deviceId = data.substring(start, end); break;
+            case 2: battery = data.substring(start, end); break;
+            case 3: version = data.substring(start, end); break;
+            case 4: ccid = data.substring(start, end); break;
+            case 5: button = data.substring(start, end); break;
+            case 6: 
+                // 对于最后一个字段,需要确保获取到字符串末尾
+                rtcmSource = data.substring(start);
+                break;
+        }
+    }
+    
+    // ===== 结果获取方法 =====
+    public String getHeader() { return header; }
+    public String getDeviceId() { return deviceId; }
+    public String getBattery() { return battery; }
+    public String getVersion() { return version; }
+    public String getCcid() { return ccid; }
+    public String getButton() { return button; }
+    public String getRtcmSource() { return rtcmSource; }
+}
diff --git a/src/dell_anchor/BaseStationManagementPanel.java b/src/dell_anchor/BaseStationManagementPanel.java
index b5c7650..9f6cbd6 100644
--- a/src/dell_anchor/BaseStationManagementPanel.java
+++ b/src/dell_anchor/BaseStationManagementPanel.java
@@ -2,12 +2,12 @@
 
 import databases.DBConnector;
 import dell_targets.Dell_BaseStation;
-
+import publicsWay.ButtonUtils;
+import publicsWay.TableUtils;
 import javax.swing.*;
 import javax.swing.border.EmptyBorder;
 import javax.swing.table.*;
 import java.awt.*;
-import java.awt.event.*;
 import java.sql.SQLException;
 import java.util.*;
 import java.util.List;
@@ -28,49 +28,56 @@
         setLayout(new BorderLayout());
         setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
         
-        // 创建搜索面板
-        JPanel searchPanel = new JPanel(new BorderLayout(5, 5));
-        searchPanel.setBorder(BorderFactory.createTitledBorder(getMessage("SEARCH")));
+        // 顶部操作面板
+        JPanel topPanel = new JPanel(new BorderLayout(5, 5));
+        topPanel.setBorder(BorderFactory.createTitledBorder(messages.getString("QUICK_OPERATION")));
         
-        // 创建搜索组件
+        // 搜索面板
+        JPanel searchInputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
+        JLabel searchLabel = new JLabel(messages.getString("BASE_STATION_ID") + ":");
         searchField = new JTextField(15);
-        JButton searchButton = new JButton(getMessage("SEARCH"));
-        JButton refreshButton = new JButton(getMessage("REFRESH"));
-        JButton addButton = new JButton(getMessage("ADD"));
-        JButton editButton = new JButton(getMessage("EDIT"));
-        JButton deleteButton = new JButton(getMessage("DELETE"));
-        refreshButton.addActionListener(e -> loadBaseStationData());
-
-        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
-        buttonPanel.add(searchButton);
-        buttonPanel.add(refreshButton);
-        buttonPanel.add(addButton);
-        buttonPanel.add(editButton);
-        buttonPanel.add(deleteButton);
-
-        searchPanel.add(searchField, BorderLayout.CENTER);
-        searchPanel.add(buttonPanel, BorderLayout.EAST);
         
-        // 添加按钮事件监听器
-        addButton.addActionListener(e -> addNewBaseStation());
-        editButton.addActionListener(e -> editSelectedBaseStation());
-        deleteButton.addActionListener(e -> deleteSelectedBaseStations());
-        searchButton.addActionListener(new SearchAction());
-       
+        // 使用ButtonUtils创建蓝色按钮
+        JButton searchButton = ButtonUtils.createBlueButton(messages.getString("SEARCH"));
+        JButton resetButton = ButtonUtils.createBlueButton(messages.getString("RESET"));
+        JButton refreshButton = ButtonUtils.createBlueButton(messages.getString("REFRESH"));
+        JButton addButton = ButtonUtils.createBlueButton(messages.getString("ADD"));
+        JButton editButton = ButtonUtils.createBlueButton(messages.getString("EDIT"));
+        JButton deleteButton = ButtonUtils.createBlueButton(messages.getString("DELETE"));
+
+        searchInputPanel.add(searchLabel);
+        searchInputPanel.add(searchField);
+        searchInputPanel.add(searchButton);
+        searchInputPanel.add(resetButton);
+        searchInputPanel.add(refreshButton);
+        
+        // 操作按钮面板
+        JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
+        actionPanel.add(addButton);
+        actionPanel.add(editButton);
+        actionPanel.add(deleteButton);
+
+        // 将搜索面板和操作按钮面板放在一行
+        JPanel rowPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
+        rowPanel.add(searchInputPanel);
+        rowPanel.add(actionPanel);
+
+        topPanel.add(rowPanel, BorderLayout.CENTER);
+        
         // 创建表格列名
         String[] columnNames = {
-            getMessage("INDEX"),
-            getMessage("BASE_STATION_ID"), 
-            getMessage("BASE_STATION_STATUS"), 
-            getMessage("X_COORD"), 
-            getMessage("Y_COORD"), 
-            getMessage("Z_COORD"), 
-            getMessage("LAYER"), 
-            getMessage("GROUP"), 
-            getMessage("PORT"), 
-            getMessage("FIRMWARE_VERSION"), 
-            getMessage("ONLINE_TIME"), 
-            getMessage("COMPANY")
+            messages.getString("INDEX"),
+            messages.getString("BASE_STATION_ID"), 
+            messages.getString("BASE_STATION_STATUS"), 
+            messages.getString("X_COORD"), 
+            messages.getString("Y_COORD"), 
+            messages.getString("Z_COORD"), 
+            messages.getString("LAYER"), 
+            messages.getString("GROUP"), 
+            messages.getString("PORT"), 
+            messages.getString("FIRMWARE_VERSION"), 
+            messages.getString("ONLINE_TIME"), 
+            messages.getString("COMPANY")
         };
         
         // 创建表格模型
@@ -81,14 +88,16 @@
             }
         };
         
-        // 创建表格
+        // 创建表格 - 使用TableUtils中的方法
         baseStationTable = new JTable(tableModel);
+        TableUtils.setupTableStyle(baseStationTable);
+        TableUtils.setupTableHeaderStyle(baseStationTable);
         baseStationTable.setAutoCreateRowSorter(true);
         baseStationTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
         
         // 设置列宽
         TableColumnModel columnModel = baseStationTable.getColumnModel();
-        columnModel.getColumn(0).setPreferredWidth(30);  // 序号
+        columnModel.getColumn(0).setPreferredWidth(30);  // 索引
         columnModel.getColumn(1).setPreferredWidth(100); // 基站编号
         columnModel.getColumn(2).setPreferredWidth(70);  // 状态
         columnModel.getColumn(3).setPreferredWidth(70);  // X坐标
@@ -101,31 +110,30 @@
         columnModel.getColumn(10).setPreferredWidth(120); // 上线时间
         columnModel.getColumn(11).setPreferredWidth(100); // 所属公司
         
-        // 设置表头样式
-        JTableHeader header = baseStationTable.getTableHeader();
-        // 设置表头左对齐
-        header.setDefaultRenderer(new DefaultTableCellRenderer() {
-            @Override
-            public Component getTableCellRendererComponent(JTable table, Object value,
-                    boolean isSelected, boolean hasFocus, int row, int column) {
-                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
-                setHorizontalAlignment(SwingConstants.LEFT);
-                setBackground(Color.GRAY);
-                setForeground(Color.WHITE);
-                setFont(getFont().deriveFont(Font.BOLD));
-                return this;
-            }
-        });
+        // 应用单元格渲染器到所有列 - 使用TableUtils中的方法
+        DefaultTableCellRenderer cellRenderer = TableUtils.createCenteredCellRenderer();
+        for (int i = 0; i < baseStationTable.getColumnCount(); i++) {
+            baseStationTable.getColumnModel().getColumn(i).setCellRenderer(cellRenderer);
+        }
         
         JScrollPane scrollPane = new JScrollPane(baseStationTable);
         scrollPane.setPreferredSize(new Dimension(1200, 500));
+        scrollPane.setBorder(BorderFactory.createEmptyBorder()); // 移除滚动面板边框
         
         // 添加组件
-        add(searchPanel, BorderLayout.NORTH);
+        add(topPanel, BorderLayout.NORTH);
         add(scrollPane, BorderLayout.CENTER);
         
         // 加载数据
         loadBaseStationData();
+        
+        // 添加事件监听器
+        searchButton.addActionListener(e -> searchBaseStations());
+        resetButton.addActionListener(e -> resetSearch());
+        refreshButton.addActionListener(e -> loadBaseStationData());
+        addButton.addActionListener(e -> addNewBaseStation());
+        editButton.addActionListener(e -> editSelectedBaseStation());
+        deleteButton.addActionListener(e -> deleteSelectedBaseStations());
     }
     
     private void loadBaseStationData() {
@@ -163,6 +171,36 @@
                 bs.getCompany()
             });
         }
+    }
+    
+    // 搜索基站
+    private void searchBaseStations() {
+        String keyword = searchField.getText().trim();
+        if (keyword.isEmpty()) {
+            updateTable(allBaseStations);
+            return;
+        }
+
+        List<LocationBaseStation> filtered = new ArrayList<>();
+        for (LocationBaseStation bs : allBaseStations) {
+            if ((bs.getCode() != null && bs.getCode().toLowerCase().contains(keyword.toLowerCase())) ||
+                (bs.getCompany() != null && bs.getCompany().toLowerCase().contains(keyword.toLowerCase()))) {
+                filtered.add(bs);
+            }
+        }
+
+        if (filtered.isEmpty()) {
+            JOptionPane.showMessageDialog(this, getMessage("SEARCH_NO_RESULTS"),
+                    getMessage("INFO"), JOptionPane.INFORMATION_MESSAGE);
+        }
+
+        updateTable(filtered);
+    }
+    
+    // 重置搜索
+    private void resetSearch() {
+        searchField.setText("");
+        updateTable(allBaseStations);
     }
     
     // 添加新基站
@@ -272,7 +310,7 @@
             return false;
         }
         
-        // HEX格式验证(0-9, A-F)
+        // HEX格式验证(0-9, A-F)
         if (!Pattern.matches("[0-9A-Fa-f]+", bs.getCode())) {
             JOptionPane.showMessageDialog(this, getMessage("INVALID_HEX_FORMAT"),
                                         getMessage("ERROR"), JOptionPane.ERROR_MESSAGE);
@@ -446,32 +484,6 @@
         return result > 0;
     }
     
-    // 搜索功能
-    private class SearchAction implements ActionListener {
-        @Override
-        public void actionPerformed(ActionEvent e) {
-            String keyword = searchField.getText().trim();
-            if (keyword.isEmpty()) {
-                updateTable(allBaseStations);
-                return;
-            }
-            
-            List<LocationBaseStation> filteredList = new ArrayList<>();
-            for (LocationBaseStation bs : allBaseStations) {
-                if (matchesKeyword(bs, keyword)) {
-                    filteredList.add(bs);
-                }
-            }
-            
-            updateTable(filteredList);
-        }
-        
-        private boolean matchesKeyword(LocationBaseStation bs, String keyword) {
-            return (bs.getCode() != null && bs.getCode().contains(keyword)) ||
-                   (bs.getCompany() != null && bs.getCompany().contains(keyword));
-        }
-    }
-    
     private String getMessage(String key) {
         try {
             return messages.getString(key);
@@ -580,8 +592,8 @@
 
         // 按钮面板
         JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
-        JButton okButton = new JButton(messages.getString("OK"));
-        JButton cancelButton = new JButton(messages.getString("CANCEL"));
+        JButton okButton = ButtonUtils.createBlueButton(messages.getString("OK"));
+        JButton cancelButton = ButtonUtils.createBlueButton(messages.getString("CANCEL"));
 
         okButton.addActionListener(e -> {
             confirmed = true;
diff --git a/src/dell_system/CompanyManagementPanel.java b/src/dell_system/CompanyManagementPanel.java
index 7fc187f..84c795a 100644
--- a/src/dell_system/CompanyManagementPanel.java
+++ b/src/dell_system/CompanyManagementPanel.java
@@ -9,6 +9,9 @@
 import java.util.*;
 import java.util.List;
 import java.util.ResourceBundle;
+import publicsWay.ButtonUtils; // 添加ButtonUtils导入
+import publicsWay.TableUtils; // 添加TableUtils导入
+
 public class CompanyManagementPanel extends JPanel {
     private static final long serialVersionUID = 1L;
     private JTable companyTable;
@@ -18,33 +21,36 @@
     private JTextField searchField;
 
     @SuppressWarnings("serial")
-	public CompanyManagementPanel(ResourceBundle messages) {
+    public CompanyManagementPanel(ResourceBundle messages) {
         this.messages = messages;
         setLayout(new BorderLayout());
         setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
-                
-     // 顶部面板
+        
+        // 顶部操作面板
         JPanel topPanel = new JPanel(new BorderLayout(5, 5));
-        topPanel.setBorder(BorderFactory.createTitledBorder(getMessage("QKOP")));
+        topPanel.setBorder(BorderFactory.createTitledBorder(getMessage("QUICK_OPERATION")));
 
         // 左侧搜索输入组件
         JPanel searchInputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
         JLabel searchLabel = new JLabel(getMessage("COMPANY_NAME") + ":");
-        searchField = new JTextField(20);
-        JButton searchButton = new JButton(getMessage("SEARCH"));
-        JButton resetButton = new JButton(getMessage("RESET"));
+        searchField = new JTextField(15);
+        
+        // 使用ButtonUtils创建蓝色按钮
+        JButton searchButton = ButtonUtils.createBlueButton(getMessage("SEARCH"));
+        JButton resetButton = ButtonUtils.createBlueButton(getMessage("RESET"));
+        JButton refreshButton = ButtonUtils.createBlueButton(getMessage("REFRESH"));
 
         searchInputPanel.add(searchLabel);
         searchInputPanel.add(searchField);
         searchInputPanel.add(searchButton);
         searchInputPanel.add(resetButton);
+        searchInputPanel.add(refreshButton);
 
         // 右侧操作按钮
         JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
-        JButton addButton = new JButton(getMessage("ADD"));
-        JButton editButton = new JButton(getMessage("EDIT"));
-        JButton deleteButton = new JButton(getMessage("DELETE"));
-        JButton refreshButton = new JButton(getMessage("REFRESH"));
+        JButton addButton = ButtonUtils.createBlueButton(getMessage("ADD"));
+        JButton editButton = ButtonUtils.createBlueButton(getMessage("EDIT"));
+        JButton deleteButton = ButtonUtils.createBlueButton(getMessage("DELETE"));
 
         actionPanel.add(addButton);
         actionPanel.add(editButton);
@@ -52,9 +58,11 @@
         actionPanel.add(refreshButton);
 
         // 将左侧搜索和右侧操作添加到搜索面板
-        topPanel.add(searchInputPanel, BorderLayout.CENTER);
-        topPanel.add(actionPanel, BorderLayout.EAST);
+        JPanel rowPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
+        rowPanel.add(searchInputPanel);
+        rowPanel.add(actionPanel);
 
+        topPanel.add(rowPanel, BorderLayout.CENTER);
         
         // 创建表格列名
         String[] columnNames = {
@@ -72,8 +80,10 @@
             }
         };
         
-        // 创建表格
+        // 创建表格 - 使用TableUtils中的方法
         companyTable = new JTable(tableModel);
+        TableUtils.setupTableStyle(companyTable);
+        TableUtils.setupTableHeaderStyle(companyTable);
         companyTable.setAutoCreateRowSorter(true);
         companyTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
         
@@ -83,29 +93,15 @@
         companyTable.getColumnModel().getColumn(2).setPreferredWidth(100);
         companyTable.getColumnModel().getColumn(3).setPreferredWidth(200);
         
-        // 设置表头样式
-        JTableHeader header = companyTable.getTableHeader();
-        header.setBackground(Color.GRAY);
-        header.setForeground(Color.WHITE);
-        header.setFont(header.getFont().deriveFont(Font.BOLD));
-        
-        // 创建表头渲染器
-        DefaultTableCellRenderer headerRenderer = new DefaultTableCellRenderer() {
-            {
-                setHorizontalAlignment(SwingConstants.LEFT);
-                setBackground(Color.GRAY);
-                setForeground(Color.WHITE);
-                setFont(getFont().deriveFont(Font.BOLD));
-            }
-        };
-        
-        // 应用表头渲染器
+        // 应用单元格渲染器到所有列 - 使用TableUtils中的方法
+        DefaultTableCellRenderer cellRenderer = TableUtils.createCenteredCellRenderer();
         for (int i = 0; i < companyTable.getColumnCount(); i++) {
-            companyTable.getColumnModel().getColumn(i).setHeaderRenderer(headerRenderer);
+            companyTable.getColumnModel().getColumn(i).setCellRenderer(cellRenderer);
         }
         
         JScrollPane scrollPane = new JScrollPane(companyTable);
         scrollPane.setPreferredSize(new Dimension(800, 400));
+        scrollPane.setBorder(BorderFactory.createEmptyBorder()); // 移除滚动面板边框
         
         // 添加组件
         add(topPanel, BorderLayout.NORTH);
@@ -414,8 +410,8 @@
 
             // 按钮面板
             JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
-            JButton okButton = new JButton(getMessage("OK"));
-            JButton cancelButton = new JButton(getMessage("CANCEL"));
+            JButton okButton = ButtonUtils.createBlueButton(getMessage("OK"));
+            JButton cancelButton = ButtonUtils.createBlueButton(getMessage("CANCEL"));
 
             okButton.addActionListener(e -> {
                 confirmed = true;
diff --git a/src/dell_system/MessageViewPanel.java b/src/dell_system/MessageViewPanel.java
index aaab8a1..c99f8b2 100644
--- a/src/dell_system/MessageViewPanel.java
+++ b/src/dell_system/MessageViewPanel.java
@@ -12,7 +12,7 @@
 import java.util.ResourceBundle;
 import dell_targets.Dell_tag;
 import publicsWay.Languages;
-import publicsWay.UDPPortAReceiver;
+import udptcp.UDPPortAReceiver;
 import udptcp.UDPPortBReceiver;
 
 public class MessageViewPanel extends JPanel {
@@ -32,6 +32,9 @@
     private JRadioButton rdoSendHex;
     private JRadioButton rdoSendAscii;
     private JCheckBox chkAppendNewline;
+ // 添加常量定义最大行数
+    private static final int MAX_LINES = 10000;
+    private static final int TRIM_LINES = 5000; // 当超过最大行数时保留的行数
     
     private static final ThreadLocal<StringBuilder> SB =
             ThreadLocal.withInitial(() -> new StringBuilder(256));
@@ -100,7 +103,7 @@
                 "ALL", 
                 "55AA01", "55AA02", "55AA03", "55AA05", "55AA07", 
                 "55AA0A", "55AA0C", "55AA12", "55AA14", "55AA20",
-                "GNGGA", "XTB"
+                "GNGGA", "XTB", "GBGGA", "SSGGA"
         });
         protocolPanel.add(cbProtocol, BorderLayout.CENTER);
         add(protocolPanel, gbc);
@@ -400,6 +403,18 @@
 
         SwingUtilities.invokeLater(() -> {
             txtDataView.append(displayData.toString() + "\n");
+            
+            // 检查并限制行数
+            int lineCount = txtDataView.getLineCount();
+            if (lineCount > MAX_LINES) {
+                try {
+                    int end = txtDataView.getLineEndOffset(TRIM_LINES - 1);
+                    txtDataView.replaceRange("", 0, end);
+                } catch (Exception ex) {
+                    ex.printStackTrace();
+                }
+            }
+            
             txtDataView.setCaretPosition(txtDataView.getDocument().getLength());
         });
     }
@@ -459,6 +474,18 @@
             SwingUtilities.invokeLater(() -> {
                 txtDataView.append(finalText);
                 txtDataView.append("\n");
+                
+                // 检查并限制行数
+                int lineCount = txtDataView.getLineCount();
+                if (lineCount > MAX_LINES) {
+                    try {
+                        int end = txtDataView.getLineEndOffset(TRIM_LINES - 1);
+                        txtDataView.replaceRange("", 0, end);
+                    } catch (Exception ex) {
+                        ex.printStackTrace();
+                    }
+                }
+                
                 txtDataView.setCaretPosition(txtDataView.getDocument().getLength());
             });
 
diff --git a/src/dell_system/SerialPacketParser.java b/src/dell_system/SerialPacketParser.java
index c523447..43b5a31 100644
--- a/src/dell_system/SerialPacketParser.java
+++ b/src/dell_system/SerialPacketParser.java
@@ -38,7 +38,7 @@
                 return sb.toString();
             }
 
-            String button = r.buttonPressed ? bundle.getString("yes") : bundle.getString("no");
+            String button = r.buttonPressed2 ? bundle.getString("yes") : bundle.getString("no");
             sb.append(bundle.getString("label.sequence")).append(": ").append(r.sequenceNum).append(',')
               .append(bundle.getString("label.id")).append(": ").append(r.tagId).append(',')
               .append(bundle.getString("label.anchor_ids")).append(": ").append(r.anchorId).append(',')
@@ -47,7 +47,7 @@
               .append(bundle.getString("status.button")).append(": ").append(button);
 
         } else if (hex.startsWith("55AA12")) {
-            ParseResult r = Dell55AA12HighPerf.parse(hex);
+            ParseResult r = Dell55AA12HighPerf.parse(hex,"127.0.0.1",0);
             if (r == null) {
                 sb.append(bundle.getString("parser.invalid")).append(" 55AA12");
                 return sb.toString();
diff --git a/src/dell_system/SettingsPanelContent.java b/src/dell_system/SettingsPanelContent.java
index 08b7aab..ded27cb 100644
--- a/src/dell_system/SettingsPanelContent.java
+++ b/src/dell_system/SettingsPanelContent.java
@@ -29,10 +29,11 @@
 import javax.swing.JRadioButton;
 import javax.swing.JTextField;
 import targets.SystemConfiguration;
+import publicsWay.ButtonUtils; // 新增导入
 
 @SuppressWarnings("serial")
 public class SettingsPanelContent extends JPanel {
-    private ResourceBundle messages; // 多语言资源包
+    private ResourceBundle messages; // 语言资源包
     private Map<String, JComponent> settingComponents; // 设置组件映射
     private SystemConfiguration currentConfig; // 当前系统配置
     private int settingIndex = 1; // 设置项索引
@@ -148,7 +149,7 @@
         
         // 添加组合框设置
         addComboBoxSetting("REALTIME_TRAJECTORY_COLOR", "realTimeTrajectoryColor",
-                new String[]{"红色", "绿色", "黑色", "紫色", "黄色"},
+                new String[]{"红色", "绿色", "黑色", "蓝色", "黄色"},
                 new Integer[]{1, 2, 3, 4, 5});
         addComboBoxSetting("SYSTEM_LANGUAGE", "systemLanguage",
                 new String[]{"中文", "英文", "法文", "阿拉伯文"},
@@ -246,7 +247,8 @@
         gbcButton.anchor = GridBagConstraints.WEST; // 左对齐
         gbcButton.insets = new Insets(5, 0, 5, 5); // 边距
 
-        JButton confirmButton = new JButton(messages.getString("SAVE")); // "保存"按钮
+        // 使用ButtonUtils创建蓝色按钮
+        JButton confirmButton = ButtonUtils.createBlueButton(messages.getString("SAVE")); // "保存"按钮
         confirmButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体
         confirmButton.setPreferredSize(new Dimension(80, 30)); // 设置大小
         // 添加保存操作监听器
@@ -310,7 +312,8 @@
         gbcButton.anchor = GridBagConstraints.WEST; // 左对齐
         gbcButton.insets = new Insets(5, 0, 5, 5); // 边距
 
-        JButton confirmButton = new JButton(messages.getString("SAVE")); // "保存"按钮
+        // 使用ButtonUtils创建蓝色按钮
+        JButton confirmButton = ButtonUtils.createBlueButton(messages.getString("SAVE")); // "保存"按钮
         confirmButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体
         confirmButton.setPreferredSize(new Dimension(80, 30)); // 设置大小
         // 添加保存操作监听器
@@ -399,7 +402,8 @@
         gbcButton.anchor = GridBagConstraints.WEST; // 左对齐
         gbcButton.insets = new Insets(5, 0, 5, 5); // 边距
 
-        JButton confirmButton = new JButton(messages.getString("SAVE")); // "保存"按钮
+        // 使用ButtonUtils创建蓝色按钮
+        JButton confirmButton = ButtonUtils.createBlueButton(messages.getString("SAVE")); // "保存"按钮
         confirmButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体
         confirmButton.setPreferredSize(new Dimension(80, 30)); // 设置大小
         // 添加保存操作监听器
@@ -487,7 +491,8 @@
         gbcButton.anchor = GridBagConstraints.WEST; // 左对齐
         gbcButton.insets = new Insets(5, 0, 5, 5); // 边距
 
-        JButton confirmButton = new JButton(messages.getString("SAVE")); // "保存"按钮
+        // 使用ButtonUtils创建蓝色按钮
+        JButton confirmButton = ButtonUtils.createBlueButton(messages.getString("SAVE")); // "保存"按钮
         confirmButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体
         confirmButton.setPreferredSize(new Dimension(80, 30)); // 设置大小
         // 添加保存操作监听器
@@ -576,7 +581,8 @@
         gbcButton.anchor = GridBagConstraints.WEST; // 左对齐
         gbcButton.insets = new Insets(5, 0, 5, 5); // 边距
 
-        JButton confirmButton = new JButton(messages.getString("SAVE")); // "保存"按钮
+        // 使用ButtonUtils创建蓝色按钮
+        JButton confirmButton = ButtonUtils.createBlueButton(messages.getString("SAVE")); // "保存"按钮
         confirmButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体
         confirmButton.setPreferredSize(new Dimension(80, 30)); // 设置大小
         // 添加保存操作监听器
diff --git a/src/dell_targets/Dell_SystemConfiguration.java b/src/dell_targets/Dell_SystemConfiguration.java
index 73647cb..294899a 100644
--- a/src/dell_targets/Dell_SystemConfiguration.java
+++ b/src/dell_targets/Dell_SystemConfiguration.java
@@ -17,6 +17,7 @@
 	public static String language="0";
 	public static int hexport=8234;
 	public static int ascallport=7000;
+	public static int TrajectoryRetentionDays=30;//轨迹保存天数
     // 获取系统配置列表
     public static List<SystemConfiguration> getSystemConfigurations()  {
         // 创建配置对象列表
@@ -61,7 +62,20 @@
 			    // 位置转发间隔
 			    config.setLocationForwardingInterval(rs.getString("location_forwarding_interval"));
 			    // 轨迹保存天数
-			    config.setTrajectorySaveDays(rs.getString("trajectory_save_days"));
+			    String savedays=rs.getString("trajectory_save_days");
+			    if (savedays != null && !savedays.trim().isEmpty()) {
+			        try {
+			        	TrajectoryRetentionDays= Integer.parseInt(savedays);
+			            if (TrajectoryRetentionDays <= 0) {
+			                // 如果转换后的值不是正整数,可以抛出异常或设置为默认值
+			                throw new IllegalArgumentException("The value must be a positive integer.");
+			            }
+			        } catch (NumberFormatException e) {
+			            // 如果字符串不是有效的整数格式,可以抛出异常或设置为默认值
+			            System.err.println("Invalid number format: " + savedays);
+			        }
+			    }			    
+			    config.setTrajectorySaveDays(savedays);
 			    // 标签离线判断时长
 			    config.setTagOfflineJudgmentDuration(rs.getString("tag_offline_judgment_duration"));
 			    // 基站离线判断时长
diff --git a/src/dell_targets/Dell_tag.java b/src/dell_targets/Dell_tag.java
index 2a1f489..bad10aa 100644
--- a/src/dell_targets/Dell_tag.java
+++ b/src/dell_targets/Dell_tag.java
@@ -21,7 +21,7 @@
 		    }
 		while (rs.next()) {
 			LocationTag locationTag = new LocationTag();
-			locationTag.setId((int) rs.getLong("id"));			
+			locationTag.setId((int) rs.getLong("id"));
 			locationTag.setDeviceNumber(rs.getString("device_id"));
 			locationTag.setDeviceName(rs.getString("device_name"));
 			locationTag.setDeviceVersion(rs.getString("device_version"));
@@ -90,7 +90,11 @@
 			locationTag.setMotionlessEndTime(rs.getString("stationary_end_time"));
 			locationTag.setMotionlessDuration(rs.getString("stationary_duration"));
 			locationTag.setValidSatelliteSignal(rs.getString("tag_valid_satellite_signal"));
-			locationTag.setCompany(rs.getString("company"));
+			String company=rs.getString("company");
+			if (company == null || company.trim().isEmpty() || company.equals("-1") ) {
+			    company = "Unknown";
+			}
+			locationTag.setCompany(company);
 			locationTag.setSleepTime(rs.getString("sleep_time"));
 			locationTag.setVibrationTime(rs.getString("vibration_time"));
 			locationTag.setFrequency(rs.getString("frequency"));
@@ -106,6 +110,257 @@
 			locationTag.setInteractionType(rs.getString("Interaction_Type"));
 			locationTag.setIpAddress(rs.getString("ipAddress"));
 			locationTag.setIpPort(rs.getString("Interaction_Type"));
+
+			locationTag.setId((int) rs.getLong("id"));
+
+			String deviceNumber = rs.getString("device_id");
+			if (deviceNumber == null || deviceNumber.trim().isEmpty() || deviceNumber.equals("-1")) {
+			    deviceNumber = "Unknown";
+			}
+			locationTag.setDeviceNumber(deviceNumber);
+
+			String deviceName = rs.getString("device_name");
+			if (deviceName == null || deviceName.trim().isEmpty() || deviceName.equals("-1")) {
+			    deviceName = "Unknown";
+			}
+			locationTag.setDeviceName(deviceName);
+
+			String deviceVersion = rs.getString("device_version");
+			if (deviceVersion == null || deviceVersion.trim().isEmpty() || deviceVersion.equals("-1")) {
+			    deviceVersion = "Unknown";
+			}
+			locationTag.setDeviceVersion(deviceVersion);
+
+			String deviceCardNumber = rs.getString("device_card_number");
+			if (deviceCardNumber == null || deviceCardNumber.trim().isEmpty() || deviceCardNumber.equals("-1")) {
+			    deviceCardNumber = "Unknown";
+			}
+			locationTag.setDeviceCardNumber(deviceCardNumber);
+
+			String deviceType = rs.getString("device_type");
+			if (deviceType == null || deviceType.trim().isEmpty() || deviceType.equals("-1")) {
+			    deviceType = "Unknown";
+			}
+			locationTag.setDeviceType(deviceType);
+
+			String team = rs.getString("affiliated_class");
+			if (team == null || team.trim().isEmpty() || team.equals("-1")) {
+			    team = "Unknown";
+			}
+			locationTag.setTeam(team);
+
+			String group = rs.getString("affiliated_group");
+			if (group == null || group.trim().isEmpty() || group.equals("-1")) {
+			    group = "Unknown";
+			}
+			locationTag.setGroup(group);
+
+			String department = rs.getString("department");
+			if (department == null || department.trim().isEmpty() || department.equals("-1")) {
+			    department = "Unknown";
+			}
+			locationTag.setDepartment(department);
+
+			String iconAddress = rs.getString("icon_url");
+			if (iconAddress == null || iconAddress.trim().isEmpty() || iconAddress.equals("-1")) {
+			    iconAddress = "Unknown";
+			}
+			locationTag.setIconAddress(iconAddress);
+
+			String gender = rs.getString("gender");
+			if (gender == null || gender.trim().isEmpty() || gender.equals("-1")) {
+			    gender = "Unknown";
+			}
+			locationTag.setGender(gender);
+
+			String ethnicity = rs.getString("ethnic_group");
+			if (ethnicity == null || ethnicity.trim().isEmpty() || ethnicity.equals("-1")) {
+			    ethnicity = "Unknown";
+			}
+			locationTag.setEthnicity(ethnicity);
+
+			String communicationAddress = rs.getString("communication_address");
+			if (communicationAddress == null || communicationAddress.trim().isEmpty() || communicationAddress.equals("-1")) {
+			    communicationAddress = "Unknown";
+			}
+			locationTag.setCommunicationAddress(communicationAddress);
+
+			String boundPhone = rs.getString("bound_phone");
+			if (boundPhone == null || boundPhone.trim().isEmpty() || boundPhone.equals("-1")) {
+			    boundPhone = "Unknown";
+			}
+			locationTag.setBoundPhone(boundPhone);
+
+			String idNumber = rs.getString("id_card_number");
+			if (idNumber == null || idNumber.trim().isEmpty() || idNumber.equals("-1")) {
+			    idNumber = "Unknown";
+			}
+			locationTag.setIdNumber(idNumber);
+
+			String position = rs.getString("personnel_position");
+			if (position == null || position.trim().isEmpty() || position.equals("-1")) {
+			    position = "Unknown";
+			}
+			locationTag.setPosition(position);
+
+			String boundPlateNumber = rs.getString("bound_license_plate");
+			if (boundPlateNumber == null || boundPlateNumber.trim().isEmpty() || boundPlateNumber.equals("-1")) {
+			    boundPlateNumber = "Unknown";
+			}
+			locationTag.setBoundPlateNumber(boundPlateNumber);
+
+			String faceAddress = rs.getString("face_image_url");
+			if (faceAddress == null || faceAddress.trim().isEmpty() || faceAddress.equals("-1")) {
+			    faceAddress = "Unknown";
+			}
+			locationTag.setFaceAddress(faceAddress);
+
+			String heartRate = rs.getString("heart_rate");
+			if (heartRate == null || heartRate.trim().isEmpty() || heartRate.equals("-1")) {
+			    heartRate = "Unknown";
+			}
+			locationTag.setHeartRate(heartRate);
+
+			String bloodPressure = rs.getString("blood_pressure");
+			if (bloodPressure == null || bloodPressure.trim().isEmpty() || bloodPressure.equals("-1")) {
+			    bloodPressure = "Unknown";
+			}
+			locationTag.setBloodPressure(bloodPressure);
+
+			String bloodOxygen = rs.getString("blood_oxygen");
+			if (bloodOxygen == null || bloodOxygen.trim().isEmpty() || bloodOxygen.equals("-1")) {
+			    bloodOxygen = "Unknown";
+			}
+			locationTag.setBloodOxygen(bloodOxygen);
+
+			String temperature = rs.getString("body_temperature");
+			if (temperature == null || temperature.trim().isEmpty() || temperature.equals("-1")) {
+			    temperature = "Unknown";
+			}
+			locationTag.setTemperature(temperature);
+
+			String sosStatus = rs.getString("sos_status");
+			if (sosStatus == null || sosStatus.trim().isEmpty() || sosStatus.equals("-1")) {
+			    sosStatus = "Unknown";
+			}
+			locationTag.setSosStatus(sosStatus);
+
+			String motionStatus = rs.getString("motion_status");
+			if (motionStatus == null || motionStatus.trim().isEmpty() || motionStatus.equals("-1")) {
+			    motionStatus = "Unknown";
+			}
+			locationTag.setMotionStatus(motionStatus);
+
+			String onlineStatus = rs.getString("online_status");
+			if (onlineStatus == null || onlineStatus.trim().isEmpty() || onlineStatus.equals("-1")) {
+			    onlineStatus = "Unknown";
+			}
+			locationTag.setOnlineStatus(onlineStatus);
+
+			String searchStatus = rs.getString("search_status");
+			if (searchStatus == null || searchStatus.trim().isEmpty() || searchStatus.equals("-1")) {
+			    searchStatus = "Unknown";
+			}
+			locationTag.setSearchStatus(searchStatus);
+
+			String batteryStatus = rs.getString("battery_status");
+			if (batteryStatus == null || batteryStatus.trim().isEmpty() || batteryStatus.equals("-1")) {
+			    batteryStatus = "Unknown";
+			}
+			locationTag.setBatteryStatus(batteryStatus);
+
+			String deviceBattery = rs.getString("device_battery");
+			if (deviceBattery == null || deviceBattery.trim().isEmpty() || deviceBattery.equals("-1")) {
+			    deviceBattery = "Unknown";
+			}
+			locationTag.setDeviceBattery(deviceBattery);
+
+			String removalStatus = rs.getString("removal_status");
+			if (removalStatus == null || removalStatus.trim().isEmpty() || removalStatus.equals("-1")) {
+			    removalStatus = "Unknown";
+			}
+			locationTag.setRemovalStatus(removalStatus);
+
+			String collisionStatus = rs.getString("collision_status");
+			if (collisionStatus == null || collisionStatus.trim().isEmpty() || collisionStatus.equals("-1")) {
+			    collisionStatus = "Unknown";
+			}
+			locationTag.setCollisionStatus(collisionStatus);
+
+			String elevationStatus = rs.getString("climbing_status");
+			if (elevationStatus == null || elevationStatus.trim().isEmpty() || elevationStatus.equals("-1")) {
+			    elevationStatus = "Unknown";
+			}
+			locationTag.setElevationStatus(elevationStatus);
+
+			String gatheringCount = rs.getString("gathering_count");
+			if (gatheringCount == null || gatheringCount.trim().isEmpty() || gatheringCount.equals("-1")) {
+			    gatheringCount = "Unknown";
+			}
+			locationTag.setGatheringCount(gatheringCount);
+
+			String proximityAlarm = rs.getString("proximity_alarm");
+			if (proximityAlarm == null || proximityAlarm.trim().isEmpty() || proximityAlarm.equals("-1")) {
+			    proximityAlarm = "Unknown";
+			}
+			locationTag.setProximityAlarm(proximityAlarm);
+
+			String area = rs.getString("current_area");
+			if (area == null || area.trim().isEmpty() || area.equals("-1")) {
+			    area = "Unknown";
+			}
+			locationTag.setArea(area);
+
+			String xCoordinate = rs.getString("x_coordinate");
+			if (xCoordinate == null || xCoordinate.trim().isEmpty() || xCoordinate.equals("-1")) {
+			    xCoordinate = "Unknown";
+			}
+			locationTag.setXCoordinate(xCoordinate);
+
+			String yCoordinate = rs.getString("y_coordinate");
+			if (yCoordinate == null || yCoordinate.trim().isEmpty() || yCoordinate.equals("-1")) {
+			    yCoordinate = "Unknown";
+			}
+			locationTag.setYCoordinate(yCoordinate);
+
+			String zCoordinate = rs.getString("z_coordinate");
+			if (zCoordinate == null || zCoordinate.trim().isEmpty() || zCoordinate.equals("-1")) {
+			    zCoordinate = "Unknown";
+			}
+			locationTag.setZCoordinate(zCoordinate);
+
+			String floor = rs.getString("current_floor");
+			if (floor == null || floor.trim().isEmpty() || floor.equals("-1")) {
+			    floor = "Unknown";
+			}
+			locationTag.setFloor(floor);
+
+			String speed = rs.getString("movement_speed");
+			if (speed == null || speed.trim().isEmpty() || speed.equals("-1")) {
+			    speed = "Unknown";
+			}
+			locationTag.setSpeed(speed);
+
+			String locationSource = rs.getString("position_source");
+			if (locationSource == null || locationSource.trim().isEmpty() || locationSource.equals("-1")) {
+			    locationSource = "Unknown";
+			}
+			locationTag.setLocationSource(locationSource);
+
+			String lastUwbSignalTime = rs.getString("last_uwb_signal_time");
+			if (lastUwbSignalTime == null || lastUwbSignalTime.trim().isEmpty() || lastUwbSignalTime.equals("-1")) {
+			    lastUwbSignalTime = "Unknown";
+			}
+			locationTag.setLastUwbSignalTime(lastUwbSignalTime);
+
+			String lastSatelliteSignalTime = rs.getString("last_satellite_signal_time");
+			if (lastSatelliteSignalTime == null || lastSatelliteSignalTime.trim().isEmpty() || lastSatelliteSignalTime.equals("-1")) {
+			    lastSatelliteSignalTime = "Unknown";
+			}
+			
+			locationTag.setAutoUpgraded("Unknown");
+			locationTag.setIsSatelliteDevice("-1");
+			locationTag.setRTKsource("Unknown");
 			locationTags.add(locationTag);
 			tagMap.put(locationTag.getDeviceNumber(), locationTag); // 添加到映射
 		}
@@ -226,6 +481,9 @@
             case "interactionType": tag.setInteractionType(value); break;
             case "ipAddress": tag.setIpAddress(value); break;
             case "ipPort": tag.setIpPort(value); break;
+            case "gnGgaDataTime": tag.setGnGgaDataTime(value); break;
+            case "isSatelliteDevice": tag.setIsSatelliteDevice(value);break;
+            case "RTKsource": tag.setRTKsource(value);break;
             default: 
                 throw new IllegalArgumentException("无效属性: " + propertyName);
         }
@@ -293,4 +551,47 @@
         }
         return tagMap.size();
     }
+    
+    /**
+     * 根据单个属性查询LocationTag对象
+     * @param propertyName 属性名(deviceNumber/deviceVersion/company)
+     * @param propertyValue 属性值
+     * @return 满足条件的LocationTag对象列表
+     */
+    public static List<LocationTag> getLocationTagsByProperty(String propertyName, String propertyValue) {
+        if (tagMap == null || tagMap.isEmpty()) {
+            try {
+                getlocationTags(); // 初始化数据
+            } catch (SQLException e) {
+                e.printStackTrace();
+                return Collections.emptyList();
+            }
+        }
+        
+        List<LocationTag> result = new ArrayList<>();
+        
+        for (LocationTag tag : tagMap.values()) {
+            switch (propertyName) {
+                case "deviceNumber":
+                    if (propertyValue.equals(tag.getDeviceNumber())) {
+                        result.add(tag);
+                    }
+                    break;
+                case "deviceVersion":
+                    if (propertyValue.equals(tag.getDeviceVersion())) {
+                        result.add(tag);
+                    }
+                    break;
+                case "company":
+                    if (propertyValue.equals(tag.getCompany())) {
+                        result.add(tag);
+                    }
+                    break;
+                default:
+                    throw new IllegalArgumentException("不支持的属性: " + propertyName);
+            }
+        }
+        
+        return result;
+    }
 } 
\ No newline at end of file
diff --git a/src/dell_targets/SatelliteDevicePanel.java b/src/dell_targets/SatelliteDevicePanel.java
new file mode 100644
index 0000000..406252f
--- /dev/null
+++ b/src/dell_targets/SatelliteDevicePanel.java
@@ -0,0 +1,483 @@
+package dell_targets;
+import targets.LocationTag;
+import dell_targets.Dell_tag;
+import javax.swing.*;
+import javax.swing.table.*;
+import java.awt.*;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.*;
+import java.util.List;
+import java.util.ResourceBundle;
+import publicsWay.ButtonUtils; // 导入ButtonUtils
+import publicsWay.TableUtils; // 导入TableUtils
+
+public class SatelliteDevicePanel extends JPanel {
+	private static final long serialVersionUID = 1L;
+	private JTable deviceTable;
+	private DefaultTableModel tableModel;
+	private List<LocationTag> allDevices;
+	private ResourceBundle messages;
+	private JTextField searchField;
+	private JComboBox<String> upgradeConditionCombo;
+	private JTextField upgradeValueField;
+	private JButton startUpgradeButton;
+	private JTextField firmwareUrlField; // 固件升级文本域
+
+	public static String FirmwareURL="";//固件升级地址
+	public static boolean isOpenUpgrade=false;//是否开启了升级功能
+	public static List<LocationTag> needUpgradeList=null;//需要升级的设备集合
+
+	@SuppressWarnings("serial")
+	public SatelliteDevicePanel(ResourceBundle messages) {
+		this.messages = messages;
+		setLayout(new BorderLayout());
+		setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
+		
+		// 添加窗口关闭监听器
+        addWindowCloseListener();
+		
+		// 顶部操作面板
+		JPanel topPanel = new JPanel(new BorderLayout(5, 5));
+		topPanel.setBorder(BorderFactory.createTitledBorder(messages.getString("QUICK_OPERATION")));
+
+		// 搜索面板
+		JPanel searchInputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
+		JLabel searchLabel = new JLabel(messages.getString("DEVICE_NUMBER") + ":");
+		searchField = new JTextField(15);
+
+		// 使用ButtonUtils创建蓝色按钮
+		JButton searchButton = ButtonUtils.createBlueButton(messages.getString("SEARCH"));
+		JButton resetButton = ButtonUtils.createBlueButton(messages.getString("RESET"));
+		JButton refreshButton = ButtonUtils.createBlueButton(messages.getString("REFRESH"));
+
+		searchInputPanel.add(searchLabel);
+		searchInputPanel.add(searchField);
+		searchInputPanel.add(searchButton);
+		searchInputPanel.add(resetButton);
+		searchInputPanel.add(refreshButton);
+		
+		// 升级条件面板
+		JPanel upgradePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));        
+		upgradeConditionCombo = new JComboBox<>(new String[]{
+				messages.getString("SET_UPGRADE_CONDITIONS"),
+				messages.getString("BY_VERSION"),
+				messages.getString("BY_NUMBER"), 
+				messages.getString("BY_SELECTED_DEVICE"),
+				messages.getString("BY_COMPANY_NAME")
+		});
+		upgradeValueField = new JTextField(15);
+		startUpgradeButton = ButtonUtils.createBlueButton(messages.getString("START_UPGRADE"));
+
+		// 新增固件地址文本框
+		JLabel firmwareUrlLabel = new JLabel(messages.getString("FIRMWARE_URL") + ":");
+		firmwareUrlField = new JTextField(20);
+		firmwareUrlField.setToolTipText(messages.getString("ENTER_FIRMWARE_DOWNLOAD_URL"));
+
+		upgradePanel.add(upgradeConditionCombo);
+		upgradePanel.add(upgradeValueField);
+		upgradePanel.add(firmwareUrlLabel);
+		upgradePanel.add(firmwareUrlField);
+		upgradePanel.add(startUpgradeButton);
+
+		// 操作按钮面板
+		JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
+
+		// 将搜索面板、升级面板和操作面板放在一行
+		JPanel rowPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
+		rowPanel.add(searchInputPanel);
+		rowPanel.add(upgradePanel);
+		rowPanel.add(actionPanel);
+
+		topPanel.add(rowPanel, BorderLayout.CENTER);
+
+		// 创建表格列名 - 增加所属公司和指令发送列
+		String[] columnNames = {
+				messages.getString("SELECT"),
+				messages.getString("INDEX"),
+				messages.getString("COMPANY"), // 新增所属公司列
+				messages.getString("DEVICE_NUMBER"),
+				messages.getString("LONGITUDE"),
+				messages.getString("LATITUDE"),
+				messages.getString("ALTITUDE"),
+				messages.getString("STATUS"),
+				messages.getString("SATELLITE_COUNT"),
+				messages.getString("DIFFERENTIAL_TIME"),
+				messages.getString("RtkSource"),
+				messages.getString("VERSION"),
+				messages.getString("CARD_NUMBER"),
+				messages.getString("ADDRESS"),
+				messages.getString("PORT"),
+				messages.getString("COMMAND_SEND"), // 新增指令发送列
+				messages.getString("UPDATE_TIME")
+		};
+
+		// 创建表格模型
+		tableModel = new DefaultTableModel(columnNames, 0) {
+			@Override
+			public boolean isCellEditable(int row, int column) {
+				// 只有选择列和指令发送列可编辑
+				return column == 0 || column == 14;
+			}
+
+			@Override
+			public Class<?> getColumnClass(int columnIndex) {
+				// 选择列使用Boolean类型
+				if (columnIndex == 0) {
+					return Boolean.class;
+				}
+				return Object.class;
+			}
+		};
+
+		// 创建表格 - 使用TableUtils中的方法
+		deviceTable = new JTable(tableModel);
+		TableUtils.setupTableStyle(deviceTable);
+		TableUtils.setupTableHeaderStyle(deviceTable);
+		deviceTable.setAutoCreateRowSorter(true);
+		deviceTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+
+		// 更新列宽设置,增加差分源列的宽度
+		deviceTable.getColumnModel().getColumn(0).setPreferredWidth(50);
+		deviceTable.getColumnModel().getColumn(1).setPreferredWidth(50);
+		deviceTable.getColumnModel().getColumn(2).setPreferredWidth(100);
+		deviceTable.getColumnModel().getColumn(3).setPreferredWidth(100);
+		deviceTable.getColumnModel().getColumn(4).setPreferredWidth(80);
+		deviceTable.getColumnModel().getColumn(5).setPreferredWidth(80);
+		deviceTable.getColumnModel().getColumn(6).setPreferredWidth(80);
+		deviceTable.getColumnModel().getColumn(7).setPreferredWidth(60);
+		deviceTable.getColumnModel().getColumn(8).setPreferredWidth(80);
+		deviceTable.getColumnModel().getColumn(9).setPreferredWidth(100);
+		deviceTable.getColumnModel().getColumn(10).setPreferredWidth(100); // 差分源列宽度
+		deviceTable.getColumnModel().getColumn(11).setPreferredWidth(80);
+		deviceTable.getColumnModel().getColumn(12).setPreferredWidth(100);
+		deviceTable.getColumnModel().getColumn(13).setPreferredWidth(120);
+		deviceTable.getColumnModel().getColumn(14).setPreferredWidth(80);
+		deviceTable.getColumnModel().getColumn(15).setPreferredWidth(100);
+		deviceTable.getColumnModel().getColumn(16).setPreferredWidth(150);
+
+		// 应用单元格渲染器到所有列 - 使用TableUtils中的方法
+		DefaultTableCellRenderer cellRenderer = TableUtils.createCenteredCellRenderer();
+		for (int i = 0; i < deviceTable.getColumnCount(); i++) {
+			deviceTable.getColumnModel().getColumn(i).setCellRenderer(cellRenderer);
+		}
+
+		// 特殊处理选择列(复选框)
+		TableColumn selectColumn = deviceTable.getColumnModel().getColumn(0);
+		selectColumn.setCellRenderer(new DefaultTableCellRenderer() {
+			private JCheckBox checkBox = new JCheckBox();
+
+			@Override
+			public Component getTableCellRendererComponent(JTable table, Object value,
+					boolean isSelected, boolean hasFocus,
+					int row, int column) {
+				if (value instanceof Boolean) {
+					checkBox.setSelected((Boolean) value);
+				}
+				checkBox.setHorizontalAlignment(SwingConstants.CENTER);
+
+				// 设置交替行颜色
+				if (!isSelected) {
+					if (row % 2 == 0) {
+						checkBox.setBackground(new Color(240, 240, 200)); // 淡黄色
+					} else {
+						checkBox.setBackground(Color.WHITE); // 白色
+					}
+				} else {
+					checkBox.setBackground(new Color(200, 220, 240)); // 选中行的蓝色
+				}
+
+				checkBox.setOpaque(true);
+				return checkBox;
+			}
+		});
+
+		JScrollPane scrollPane = new JScrollPane(deviceTable);
+		scrollPane.setPreferredSize(new Dimension(1200, 400));
+		scrollPane.setBorder(BorderFactory.createEmptyBorder()); // 移除滚动面板边框
+
+		// 添加组件
+		add(topPanel, BorderLayout.NORTH);
+		add(scrollPane, BorderLayout.CENTER);
+
+		// 加载数据
+		loadDeviceData();
+
+		// 添加事件监听器
+		searchButton.addActionListener(e -> searchDevices());
+		resetButton.addActionListener(e -> resetSearch());
+		refreshButton.addActionListener(e -> loadDeviceData());
+		startUpgradeButton.addActionListener(e -> startUpgrade());
+
+		// 添加表格模型监听器,用于自动更新选中设备到文本框
+		tableModel.addTableModelListener(e -> {
+			if (e.getColumn() == 0 && messages.getString("BY_SELECTED_DEVICE").equals(upgradeConditionCombo.getSelectedItem())) {
+				updateSelectedDevicesToTextField();
+			}
+		});
+
+		// 添加升级条件组合框监听器
+		upgradeConditionCombo.addActionListener(e -> {
+			if (messages.getString("BY_SELECTED_DEVICE").equals(upgradeConditionCombo.getSelectedItem())) {
+				updateSelectedDevicesToTextField();
+			}
+		});
+	}
+
+	// 更新选中设备到文本框
+	private void updateSelectedDevicesToTextField() {
+		List<String> selectedDevices = new ArrayList<>();
+		for (int i = 0; i < tableModel.getRowCount(); i++) {
+			Boolean isSelected = (Boolean) tableModel.getValueAt(i, 0);
+			if (isSelected != null && isSelected) {
+				String deviceNumber = (String) tableModel.getValueAt(i, 3); // 设备编号在第3列
+				selectedDevices.add(deviceNumber);
+			}
+		}
+		upgradeValueField.setText(String.join(",", selectedDevices));
+	}
+
+	// 按钮渲染器
+	class ButtonRenderer extends JButton implements TableCellRenderer {
+		private static final long serialVersionUID = 1L;
+
+		public ButtonRenderer() {
+			setOpaque(true);
+		}
+
+		@Override
+		public Component getTableCellRendererComponent(JTable table, Object value,
+				boolean isSelected, boolean hasFocus,
+				int row, int column) {
+			setText((value == null) ? "" : value.toString());
+			return this;
+		}
+	}
+
+	// 按钮编辑器
+	class ButtonEditor extends DefaultCellEditor {
+		private static final long serialVersionUID = 1L;
+		private String label;
+		private JButton button;
+
+		public ButtonEditor(JCheckBox checkBox) {
+			super(checkBox);
+			button = new JButton();
+			button.setOpaque(true);
+			button.addActionListener(e -> fireEditingStopped());
+		}
+
+		@Override
+		public Component getTableCellEditorComponent(JTable table, Object value,
+				boolean isSelected, int row, int column) {
+			label = (value == null) ? "" : value.toString();
+			button.setText(label);
+			return button;
+		}
+
+		@Override
+		public Object getCellEditorValue() {
+			return label;
+		}
+	}
+
+	private void loadDeviceData() {
+		try {
+			allDevices = Dell_tag.getOnlineLocationTags();
+			updateTable(allDevices);
+		} catch (Exception ex) {
+			JOptionPane.showMessageDialog(this, messages.getString("DATA_LOAD_ERROR") + ": " + ex.getMessage(), 
+					messages.getString("ERROR"), JOptionPane.ERROR_MESSAGE);
+		}
+	}
+
+	// 搜索设备
+	private void searchDevices() {
+		String keyword = searchField.getText().trim();
+		if (keyword.isEmpty()) {
+			updateTable(allDevices);
+			return;
+		}
+
+		List<LocationTag> filtered = new ArrayList<>();
+		for (LocationTag device : allDevices) {
+			if (device.getDeviceNumber() != null && 
+					device.getDeviceNumber().toLowerCase().contains(keyword.toLowerCase())) {
+				filtered.add(device);
+			}
+		}
+
+		if (filtered.isEmpty()) {
+			JOptionPane.showMessageDialog(this, messages.getString("SEARCH_NO_RESULTS"),
+					messages.getString("INFO"), JOptionPane.INFORMATION_MESSAGE);
+		}
+
+		updateTable(filtered);
+	}
+
+	// 重置搜索
+	private void resetSearch() {
+		searchField.setText("");
+		updateTable(allDevices);
+	}
+
+	private void updateTable(List<LocationTag> devices) {
+		tableModel.setRowCount(0);
+
+		int index = 1;
+		for (LocationTag device : devices) {
+			tableModel.addRow(new Object[]{
+					false, // 选择列
+					index++,
+					device.getCompany(), // 新增公司列
+					device.getDeviceNumber(),                
+					device.getLongitude(),
+					device.getLatitude(),
+					device.getAltitude(),
+					device.getSatelliteQuality(),
+					device.getSatelliteCount(),
+					device.getDifferentialTime(),
+					device.getRTKsource(), // 新增差分源数据
+					device.getDeviceVersion(),
+					device.getDeviceCardNumber(),
+					device.getIpAddress(),
+					device.getIpPort(),                
+					device.getAutoUpgraded(),// 指令发送按钮
+					device.getGnGgaDataTime()
+			});
+		}
+	}
+
+	// 启动升级
+	private void startUpgrade() {		
+		int dex = upgradeConditionCombo.getSelectedIndex();
+		
+		String value = upgradeValueField.getText().trim();
+		String firmwareUrl = firmwareUrlField.getText().trim();
+
+		if (firmwareUrl.isEmpty()) {
+			JOptionPane.showMessageDialog(this, messages.getString("FIRMWARE_URL_REQUIRED"),
+					messages.getString("WARNING"), JOptionPane.WARNING_MESSAGE);
+			return;
+		}
+
+		if (value.isEmpty()) {
+			JOptionPane.showMessageDialog(this, messages.getString("UPGRADE_VALUE_REQUIRED"),
+					messages.getString("WARNING"), JOptionPane.WARNING_MESSAGE);
+			return;
+		}
+
+		List<LocationTag> devicesToUpgrade = new ArrayList<>();
+
+		// 根据条件执行升级逻辑
+		if (dex == 3) {
+			// 获取选中的设备
+			for (int i = 0; i < tableModel.getRowCount(); i++) {
+				Boolean isSelected = (Boolean) tableModel.getValueAt(i, 0);
+				if (isSelected != null && isSelected) {
+					String deviceNumber = (String) tableModel.getValueAt(i, 3);
+					LocationTag device = Dell_tag.getTagByDeviceId(deviceNumber);
+					if (device != null) {
+						devicesToUpgrade.add(device);
+					}
+				}
+			}
+
+			if (devicesToUpgrade.isEmpty()) {
+				JOptionPane.showMessageDialog(this, messages.getString("SELECT_DEVICE_TO_UPGRADE"),
+						messages.getString("WARNING"), JOptionPane.WARNING_MESSAGE);
+				return;
+			}
+		} else if (dex == 1) {
+			// 执行按版本升级
+			devicesToUpgrade = Dell_tag.getLocationTagsByProperty("deviceVersion", value);
+		} else if (dex == 2) {
+			// 执行按设备编号升级 - 修复逻辑错误
+			String[] tagIds = value.split("[\\s,;]+"); // 使用正则表达式分割多种分隔符
+			for (String tagId : tagIds) {
+				List<LocationTag> devicesForId = Dell_tag.getLocationTagsByProperty("deviceNumber", tagId.trim());
+				if (devicesForId != null) {
+					devicesToUpgrade.addAll(devicesForId);
+				}
+			}			
+		} else if (dex == 4) {
+			// 执行按公司名称升级
+			devicesToUpgrade = Dell_tag.getLocationTagsByProperty("company", value);
+		}
+
+		// 验证是否有设备需要升级
+		if (devicesToUpgrade.isEmpty()) {
+			JOptionPane.showMessageDialog(this, messages.getString("NO_DEVICES_TO_UPGRADE"),
+					messages.getString("WARNING"), JOptionPane.WARNING_MESSAGE);
+			return;
+		}
+
+		FirmwareURL = firmwareUrl; // 固件升级地址
+		isOpenUpgrade = true; // 是否开启了升级功能
+		needUpgradeList = devicesToUpgrade; // 需要升级的设备集合
+		
+		// 执行升级
+		performUpgrade(devicesToUpgrade, firmwareUrl);
+	}
+
+	private void performUpgrade(List<LocationTag> devices, String firmwareUrl) {
+	    // 构建设备编号列表字符串
+	    StringBuilder deviceListBuilder = new StringBuilder();
+	    int maxDisplay = 20;
+	    int displayCount = Math.min(devices.size(), maxDisplay);
+	    
+	    for (int i = 0; i < displayCount; i++) {
+	        if (i > 0) {
+	            deviceListBuilder.append(", ");
+	        }
+	        deviceListBuilder.append(devices.get(i).getDeviceNumber());
+	    }
+	    
+	    if (devices.size() > maxDisplay) {
+	        deviceListBuilder.append(messages.getString("UPGRADE_DEVICE_ELLIPSIS"))
+	                         .append(devices.size())
+	                         .append(messages.getString("UPGRADE_DEVICE_UNIT"));
+	    }
+	    
+	    // 创建包含设备列表和固件地址的完整消息
+	    String message = messages.getString("UPGRADE_CONFIRMATION_HEADER") + 
+	                     deviceListBuilder.toString() + 
+	                     "\n\n" + messages.getString("FIRMWARE_URL_LABEL") + ": " + firmwareUrl +
+	                     "\n\n" + String.format(messages.getString("TOTAL_DEVICES_COUNT"), devices.size());
+	    
+	    JOptionPane.showMessageDialog(this, 
+	            message,
+	            messages.getString("INFO"), JOptionPane.INFORMATION_MESSAGE);
+	}
+	
+	// 添加窗口关闭监听器
+    private void addWindowCloseListener() {
+        // 获取顶层窗口
+        Window window = SwingUtilities.getWindowAncestor(this);
+        if (window != null) {
+            window.addWindowListener(new WindowAdapter() {
+                @Override
+                public void windowClosing(WindowEvent e) {
+                    isOpenUpgrade = false;
+                }
+                
+                @Override
+                public void windowClosed(WindowEvent e) {
+                    isOpenUpgrade = false;
+                }
+            });
+        }
+    }
+
+	public static String getFirmwareURL() {
+		return FirmwareURL;
+	}
+
+	public static boolean isOpenUpgrade() {
+		return isOpenUpgrade;
+	}
+
+	public static List<LocationTag> getNeedUpgradeList() {
+		return needUpgradeList;
+	}
+}
\ No newline at end of file
diff --git a/src/dell_targets/TagManagementPanel.java b/src/dell_targets/TagManagementPanel.java
index 06daa66..35b29d5 100644
--- a/src/dell_targets/TagManagementPanel.java
+++ b/src/dell_targets/TagManagementPanel.java
@@ -2,13 +2,16 @@
 
 import targets.LocationTag;
 import javax.swing.*;
+import javax.swing.table.DefaultTableCellRenderer;
 import javax.swing.table.DefaultTableModel;
+import javax.swing.table.JTableHeader;
 import java.awt.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.sql.SQLException;
 import java.util.List;
 import java.util.ResourceBundle;
+import publicsWay.ButtonUtils;  // Added import
 
 public class TagManagementPanel extends JPanel {
     private static final long serialVersionUID = 1L;
@@ -21,31 +24,39 @@
     public TagManagementPanel(ResourceBundle messages) {
         this.messages = messages;
         setLayout(new BorderLayout());
-        setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
+        setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
         
-        // 创建搜索面板
-        JPanel searchPanel = new JPanel(new BorderLayout(5, 5));
-        searchPanel.setBorder(BorderFactory.createTitledBorder(messages.getString("SEARCH")));
+        // 创建顶部面板
+        JPanel topPanel = new JPanel(new BorderLayout(5, 5));
+        topPanel.setBorder(BorderFactory.createTitledBorder(messages.getString("SEARCH")));
         
-        // 创建搜索文本框和按钮
-        searchField = new JTextField(10); // 缩短搜索文本框长度
-        JButton searchButton = new JButton(messages.getString("SEARCH"));
-        JButton refreshButton = new JButton(messages.getString("REFRESH")); // 添加刷新按钮
-        refreshButton.addActionListener(e -> loadTagData()); // 绑定刷新动作
+        // 左侧搜索组件面板
+        JPanel searchInputPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
+        JLabel searchLabel = new JLabel(messages.getString("DEVICE_NUMBER") + ":");
+        searchField = new JTextField(20);
+        
+        // 使用ButtonUtils创建按钮
+        JButton searchButton = ButtonUtils.createBlueButton(messages.getString("SEARCH"));
+        JButton resetButton = ButtonUtils.createBlueButton(messages.getString("RESET"));
 
-        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
-        buttonPanel.add(searchButton);
-        buttonPanel.add(refreshButton);
+        searchInputPanel.add(searchLabel);
+        searchInputPanel.add(searchField);
+        searchInputPanel.add(searchButton);
+        searchInputPanel.add(resetButton);
 
-        searchPanel.add(searchField, BorderLayout.CENTER);
-        searchPanel.add(buttonPanel, BorderLayout.EAST);
-        
-        // 创建操作按钮面板
-        JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
-        JButton addButton = new JButton(messages.getString("ADD"));
-        JButton deleteButton = new JButton(messages.getString("DELETE"));
+        // 右侧操作按钮面板
+        JPanel actionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 0));
+        JButton addButton = ButtonUtils.createBlueButton(messages.getString("ADD"));
+        JButton deleteButton = ButtonUtils.createBlueButton(messages.getString("DELETE"));
+        JButton refreshButton = ButtonUtils.createBlueButton(messages.getString("REFRESH"));
+
         actionPanel.add(addButton);
         actionPanel.add(deleteButton);
+        actionPanel.add(refreshButton);
+
+        // 将左侧搜索和右侧操作添加到顶部面板
+        topPanel.add(searchInputPanel, BorderLayout.CENTER);
+        topPanel.add(actionPanel, BorderLayout.EAST);
         
         // 创建表格 - 按照表5要求修改列名
         String[] columnNames = {
@@ -75,6 +86,13 @@
         tagTable.setAutoCreateRowSorter(true);
         tagTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
         
+        // 设置表格样式 - 去掉竖线,只显示横线,栅栏效果
+        tagTable.setShowVerticalLines(false); // 不显示竖线
+        tagTable.setShowHorizontalLines(true); // 显示横线
+        tagTable.setGridColor(new Color(220, 220, 220)); // 设置网格线颜色为浅灰色
+        tagTable.setIntercellSpacing(new Dimension(0, 1)); // 设置单元格间距,增加行间距
+        tagTable.setRowHeight(25); // 设置行高
+        
         // 设置列宽
         tagTable.getColumnModel().getColumn(0).setPreferredWidth(30);
         tagTable.getColumnModel().getColumn(1).setPreferredWidth(100);
@@ -88,19 +106,95 @@
         tagTable.getColumnModel().getColumn(9).setPreferredWidth(120); // 上线时间
         tagTable.getColumnModel().getColumn(10).setPreferredWidth(100);
         
+        // 设置表头样式
+        JTableHeader header = tagTable.getTableHeader();
+        header.setBackground(new Color(70, 130, 180)); // 钢蓝色表头
+        header.setForeground(Color.WHITE);
+        header.setFont(header.getFont().deriveFont(Font.BOLD));
+        header.setPreferredSize(new Dimension(header.getWidth(), 30)); // 增加表头高度
+        
+        // 创建表头渲染器
+        DefaultTableCellRenderer headerRenderer = new DefaultTableCellRenderer() {
+            /**
+			 * 
+			 */
+			private static final long serialVersionUID = 1L;
+
+			{
+                setHorizontalAlignment(SwingConstants.CENTER);
+                setBackground(new Color(70, 130, 180)); // 钢蓝色表头
+                setForeground(Color.WHITE);
+                setFont(getFont().deriveFont(Font.BOLD));
+                setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); // 增加表头内边距
+            }
+        };
+        
+        // 应用表头渲染器
+        for (int i = 0; i < tagTable.getColumnCount(); i++) {
+            tagTable.getColumnModel().getColumn(i).setHeaderRenderer(headerRenderer);
+        }
+        
+        // 创建单元格渲染器,实现栅栏效果
+        DefaultTableCellRenderer cellRenderer = new DefaultTableCellRenderer() {
+            /**
+			 * 
+			 */
+			private static final long serialVersionUID = 1L;
+
+			@Override
+            public Component getTableCellRendererComponent(JTable table, Object value,
+                                                         boolean isSelected, boolean hasFocus,
+                                                         int row, int column) {
+                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+                
+                // 设置交替行颜色
+                if (!isSelected) {
+                    if (row % 2 == 0) {
+                        c.setBackground(new Color(240, 240, 200)); // 浅灰色
+                    } else {
+                        c.setBackground(Color.WHITE); // 白色
+                    }
+                } else {
+                    c.setBackground(new Color(200, 220, 240)); // 选中行的蓝色
+                }
+                
+                // 设置单元格对齐方式
+                if (column == 0) { // 索引列居中
+                    setHorizontalAlignment(SwingConstants.CENTER);
+                } else if (column == 5) { // 电池电量列居中
+                    setHorizontalAlignment(SwingConstants.CENTER);
+                } else {
+                    setHorizontalAlignment(SwingConstants.CENTER);
+                }
+                
+                // 设置单元格边框
+                setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5)); // 左右内边距
+                
+                return c;
+            }
+        };
+        
+        // 应用单元格渲染器到所有列
+        for (int i = 0; i < tagTable.getColumnCount(); i++) {
+            tagTable.getColumnModel().getColumn(i).setCellRenderer(cellRenderer);
+        }
+        
         JScrollPane scrollPane = new JScrollPane(tagTable);
         scrollPane.setPreferredSize(new Dimension(1200, 400));
+        scrollPane.setBorder(BorderFactory.createEmptyBorder()); // 移除滚动面板边框
         
         // 添加组件
-        add(searchPanel, BorderLayout.NORTH);
+        add(topPanel, BorderLayout.NORTH);
         add(scrollPane, BorderLayout.CENTER);
-        add(actionPanel, BorderLayout.SOUTH);
         
         // 加载数据
         loadTagData();
         
         // 添加事件监听器
         searchButton.addActionListener(new SearchAction());
+        resetButton.addActionListener(e -> resetSearch());
+        refreshButton.addActionListener(e -> loadTagData());
+        
         addButton.addActionListener(e -> {
             AddTagDialog dialog = new AddTagDialog((Frame) SwingUtilities.getWindowAncestor(TagManagementPanel.this), messages);
             dialog.setVisible(true);
@@ -194,6 +288,12 @@
         }
     }
     
+    // 重置搜索
+    private void resetSearch() {
+        searchField.setText("");
+        updateTable(allTags);
+    }
+    
     private class SearchAction implements ActionListener {
         @Override
         public void actionPerformed(ActionEvent e) {
diff --git a/src/dell_targets/TagTypeManagementPanel.java b/src/dell_targets/TagTypeManagementPanel.java
index 24f23b1..8b434ca 100644
--- a/src/dell_targets/TagTypeManagementPanel.java
+++ b/src/dell_targets/TagTypeManagementPanel.java
@@ -11,6 +11,8 @@
 import java.util.List;
 import java.util.ResourceBundle;
 import java.nio.charset.StandardCharsets;
+import publicsWay.ButtonUtils; // 导入ButtonUtils
+import publicsWay.TableUtils; // 导入TableUtils
 
 public class TagTypeManagementPanel extends JPanel {
     private static final long serialVersionUID = 1L;
@@ -20,7 +22,7 @@
     private ResourceBundle messages;
 
     @SuppressWarnings("serial")
-	public TagTypeManagementPanel(ResourceBundle messages) {
+    public TagTypeManagementPanel(ResourceBundle messages) {
         this.messages = messages;
         setLayout(new BorderLayout());
         setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
@@ -31,10 +33,12 @@
         
         // 创建按钮面板
         JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
-        JButton addButton = new JButton(getMessage("ADD"));
-        JButton editButton = new JButton(getMessage("EDIT"));
-        JButton deleteButton = new JButton(getMessage("DELETE"));
-        JButton refreshButton = new JButton(getMessage("REFRESH"));
+        
+        // 使用ButtonUtils创建蓝色按钮
+        JButton addButton = ButtonUtils.createBlueButton(getMessage("ADD"));
+        JButton editButton = ButtonUtils.createBlueButton(getMessage("EDIT"));
+        JButton deleteButton = ButtonUtils.createBlueButton(getMessage("DELETE"));
+        JButton refreshButton = ButtonUtils.createBlueButton(getMessage("REFRESH"));
         
         buttonPanel.add(addButton);
         buttonPanel.add(editButton);
@@ -57,10 +61,17 @@
             public boolean isCellEditable(int row, int column) {
                 return false;
             }
+            
+            @Override
+            public Class<?> getColumnClass(int columnIndex) {
+                return Object.class;
+            }
         };
         
-        // 创建表格
+        // 创建表格 - 使用TableUtils中的方法
         typeTable = new JTable(tableModel);
+        TableUtils.setupTableStyle(typeTable);
+        TableUtils.setupTableHeaderStyle(typeTable);
         typeTable.setAutoCreateRowSorter(true);
         typeTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
         
@@ -70,29 +81,15 @@
         typeTable.getColumnModel().getColumn(2).setPreferredWidth(150);
         typeTable.getColumnModel().getColumn(3).setPreferredWidth(200);
         
-        // 设置表头样式(左对齐)
-        JTableHeader header = typeTable.getTableHeader();
-        header.setBackground(Color.GRAY);
-        header.setForeground(Color.WHITE);
-        header.setFont(header.getFont().deriveFont(Font.BOLD));
-        
-        // 创建表头渲染器(左对齐)
-        DefaultTableCellRenderer headerRenderer = new DefaultTableCellRenderer() {
-            {
-                setHorizontalAlignment(SwingConstants.LEFT);
-                setBackground(Color.GRAY);
-                setForeground(Color.WHITE);
-                setFont(getFont().deriveFont(Font.BOLD));
-            }
-        };
-        
-        // 应用表头渲染器
+        // 应用单元格渲染器到所有列 - 使用TableUtils中的方法
+        DefaultTableCellRenderer cellRenderer = TableUtils.createCenteredCellRenderer();
         for (int i = 0; i < typeTable.getColumnCount(); i++) {
-            typeTable.getColumnModel().getColumn(i).setHeaderRenderer(headerRenderer);
+            typeTable.getColumnModel().getColumn(i).setCellRenderer(cellRenderer);
         }
         
         JScrollPane scrollPane = new JScrollPane(typeTable);
         scrollPane.setPreferredSize(new Dimension(800, 400));
+        scrollPane.setBorder(BorderFactory.createEmptyBorder()); // 移除滚动面板边框
         
         // 添加组件
         add(topPanel, BorderLayout.NORTH);
@@ -148,7 +145,7 @@
     
     private String getInteractionCodeFromIndex(int index) {
         switch (index) {
-            case 0: return "1"; // 震动
+            case 0: return "1"; // 振动
             case 1: return "2"; // 蜂鸣
             case 2: return "3"; // TTS
             case 3: return "4"; // 无
@@ -330,7 +327,7 @@
         fieldValues.put("interaction_type", type.getInteractionType());
         fieldValues.put("save_time", type.getSaveTime()); // 更新时间
         
-        // 直接使用传入的 type 对象的 ID
+        // 直接使用传入的type对象的ID
         if (type.getId() == null || type.getId().trim().isEmpty()) {
             JOptionPane.showMessageDialog(this, getMessage("TAG_TYPE_NOT_FOUND"),
                                         getMessage("ERROR"), JOptionPane.ERROR_MESSAGE);
@@ -404,7 +401,7 @@
             // 交互类型
             JLabel interactionLabel = new JLabel(getMessage("INTERACTION_TYPE") + ": *");
             String[] options = {
-                getMessage("VIBRATION"), // 震动
+                getMessage("VIBRATION"), // 振动
                 getMessage("BEEP"),      // 蜂鸣
                 getMessage("TTS"),       // 语音
                 getMessage("NONE")       // 无
@@ -436,8 +433,10 @@
 
             // 按钮面板
             JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
-            JButton okButton = new JButton(getMessage("OK"));
-            JButton cancelButton = new JButton(getMessage("CANCEL"));
+            
+            // 使用ButtonUtils创建蓝色按钮
+            JButton okButton = ButtonUtils.createBlueButton(getMessage("OK"));
+            JButton cancelButton = ButtonUtils.createBlueButton(getMessage("CANCEL"));
 
             okButton.addActionListener(e -> {
                 confirmed = true;
diff --git a/src/publicsWay/ButtonUtils.java b/src/publicsWay/ButtonUtils.java
new file mode 100644
index 0000000..dcd3926
--- /dev/null
+++ b/src/publicsWay/ButtonUtils.java
@@ -0,0 +1,40 @@
+package publicsWay;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+public class ButtonUtils {
+    
+    /**
+     * 创建蓝色样式按钮的通用方法
+     * @param text 按钮文本
+     * @return 配置好样式的JButton
+     */
+    public static JButton createBlueButton(String text) {
+        JButton button = new JButton(text);
+        button.setBackground(new Color(0, 120, 215)); // 蓝色背景
+        button.setForeground(Color.WHITE); // 白色文字
+        button.setFocusPainted(false);
+        button.setOpaque(true);
+        button.setBorderPainted(false);
+        button.setFont(button.getFont().deriveFont(Font.BOLD)); // 加粗字体
+        
+        // 添加鼠标悬停效果
+        button.addMouseListener(new MouseAdapter() {
+            @Override
+            public void mouseEntered(MouseEvent e) {
+                button.setBackground(Color.GRAY); // 鼠标悬停时变为灰色
+                button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); // 鼠标变为手型
+            }
+            
+            @Override
+            public void mouseExited(MouseEvent e) {
+                button.setBackground(new Color(0, 120, 215)); // 鼠标离开时恢复蓝色
+                button.setCursor(Cursor.getDefaultCursor()); // 鼠标恢复默认形状
+            }
+        });
+        
+        return button;
+    }
+}
\ No newline at end of file
diff --git a/src/publicsWay/PacketProcessingSystem.java b/src/publicsWay/PacketProcessingSystem.java
index 24dcf5c..8d9bdad 100644
--- a/src/publicsWay/PacketProcessingSystem.java
+++ b/src/publicsWay/PacketProcessingSystem.java
@@ -3,6 +3,7 @@
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.atomic.AtomicBoolean;
 import dell55AAData.Dell55AA01Parser;
+import dell55AAData.Dell55AA02Parser;
 import dell55AAData.Dell55AA12HighPerf;
 
 import java.util.concurrent.ExecutorService;
@@ -84,6 +85,7 @@
                     // 处理解析后的数据包
                     for (PacketParser.DataPacket p : parsedPackets) {
                         // 根据包头类型路由到不同解析器
+//                    	System.out.println(p.getPacketType());
                         switch (p.getPacketType()) {
                             case 0x01:
                                 processType01(p,ip,port);break;
@@ -122,7 +124,7 @@
 
     private static void processType02(PacketParser.DataPacket packet,String ip,int port) {
     	String hexData = PacketParser.bytesToHexString(packet.getPacket());
-        System.out.println("处理55AA02包: " + packet);
+    	Dell55AA02Parser.parse(hexData,ip,port);
         // 实际业务逻辑
     }
     
diff --git a/src/publicsWay/PacketProcessingSystemB.java b/src/publicsWay/PacketProcessingSystemB.java
new file mode 100644
index 0000000..6b3ed9f
--- /dev/null
+++ b/src/publicsWay/PacketProcessingSystemB.java
@@ -0,0 +1,252 @@
+package publicsWay;
+
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Pattern;
+import dell55AAData.DellGngga;
+import dell55AAData.XTB;
+
+import java.util.regex.Matcher;
+import dell_system.MessageViewPanel;
+import dell_targets.Dell_tag;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class PacketProcessingSystemB {
+	// 线程安全的报文存储队列(集合A)
+	private static final ConcurrentLinkedQueue<HexPacket> packetQueue = new ConcurrentLinkedQueue<>();
+	private static final AtomicBoolean isRunning = new AtomicBoolean(false);
+	private static final ExecutorService parserExecutor = Executors.newSingleThreadExecutor();
+	private static Thread parserThread;
+	private static boolean a1 = true;
+
+	// 可重用的DellGngga实例(线程安全)
+	private static final ThreadLocal<DellGngga> dellGnggaParser = ThreadLocal.withInitial(DellGngga::new);
+	private static final ThreadLocal<XTB> dellXTB = ThreadLocal.withInitial(XTB::new);
+	// 报文存储结构
+	public static class HexPacket {
+		public final String ip;
+		public final int port;
+		public final String hexData;
+		public final long timestamp;
+
+		public HexPacket(String ip, int port, String hexData, long timestamp) {
+			this.ip = ip;
+			this.port = port;
+			this.hexData = hexData;
+			this.timestamp = timestamp;
+		}
+
+		public String getIp() {
+			return ip;
+		}
+
+		public int getPort() {
+			return port;
+		}
+
+		public String getHexData() {
+			return hexData;
+		}
+
+		public long getTimestamp() {
+			return timestamp;
+		}
+	}
+
+	// 接收端存储报文(UDPPortAReceiver中调用)
+	public static void storePacket(String ip, int port, String hexData) {
+		if (a1) {
+			startProcessing();
+			a1 = false;
+		}
+		if (packetQueue.size() < 100000) { // 限制队列大小防止OOM
+			packetQueue.offer(new HexPacket(ip, port, hexData, System.currentTimeMillis()));
+		}
+	}
+
+	// 启动解析系统
+	public static void startProcessing() {
+		if (isRunning.get()) return;
+
+		isRunning.set(true);
+		parserThread = new Thread(() -> {
+			while (isRunning.get()) {
+				HexPacket packet = packetQueue.poll();
+				if (packet == null) {
+					Thread.yield(); // 队列为空时让出CPU
+					continue;
+				}
+
+				try {                    
+					String receivedata = packet.hexData; 
+					String ip = packet.getIp();
+					int port = packet.getPort();
+					processData(receivedata, ip, port);                   
+
+				} catch (Exception e) {
+					System.err.println("解析错误: " + e.getMessage());
+				}
+			}
+		});
+
+		parserThread.setDaemon(true);
+		parserThread.start();
+	}
+
+	// 停止解析系统
+	public static void stopProcessing() {
+		isRunning.set(false);
+		parserExecutor.shutdownNow();
+		if (parserThread != null) {
+			parserThread.interrupt();
+		}
+	}
+
+	public static void processData(String receivedata, String ip, int port) {
+		// 去掉回车换行符
+		receivedata = receivedata.replaceAll("[\\r\\n]+", "");
+		// 转大写
+		receivedata = receivedata.toUpperCase();
+
+		// 定义正则表达式,匹配以 $GNGGA、$XTB、$SSGGA、$GBGGA 或 55AA 开头的数据
+		String regex = "(\\$GNGGA[^$]*|\\$XTB[^$]*|\\$SSGGA[^$]*|\\$GBGGA[^$]*|55AA[^$]*)";
+
+		// 使用正则表达式分割字符串
+		Pattern pattern = Pattern.compile(regex);
+		Matcher matcher = pattern.matcher(receivedata);
+
+		// 遍历匹配到的数据
+		while (matcher.find()) {
+			String data = matcher.group(1);
+
+			if (data.startsWith("$GNGGA")) {
+				handleGNGGA(data, ip, port);
+			} else if (data.startsWith("$XTB")) {
+				handleXTB(data, ip, port);
+			} else if (data.startsWith("$SSGGA")) {
+				handleSSGGA(data, ip, port);
+			} else if (data.startsWith("$GBGGA")) {
+				handleGBGGA(data, ip, port);
+			} else if (data.startsWith("55AA")) {
+				handle55AA(data, ip, port);
+			}
+		}
+	}
+
+	private static void handleGNGGA(String data, String ip, int port) {// 处理$GNGGA数据
+		MessageViewPanel.showData(data, ip, port, 0, "UDPB", "GNGGA", "ALL");        
+		// 使用可重用的解析器实例解析数据
+		dellGGA(data, ip,port);
+
+	}
+
+	private static void handleXTB(String data, String ip, int port) {
+		// 处理$XTB数据
+		MessageViewPanel.showData(data, ip, port, 0, "UDPB", "XTB", "ALL");
+		// 具体解析逻辑
+		dellXTB(data,ip,port) ;  
+	}
+
+	private static void handleSSGGA(String data, String ip, int port) {
+		// 处理$SSGGA数据
+		MessageViewPanel.showData(data, ip, port, 0, "UDPB", "SSGGA", "ALL");
+		dellGGA(data, ip,port);
+		// 具体解析逻辑
+	}
+
+	private static void handleGBGGA(String data, String ip, int port) {
+		// 处理$GBGGA数据
+		MessageViewPanel.showData(data, ip, port, 0, "UDPB", "GBGGA", "ALL");
+		// 具体解析逻辑
+		dellGGA(data, ip,port);
+	}
+
+	private static void handle55AA(String data, String ip, int port) {
+		// 处理55AA数据
+		System.out.println("Handling 55AA: " + data);
+		// 具体解析逻辑
+	}
+
+	private static void dellGGA(String data, String ip, int port) {
+		DellGngga parser = dellGnggaParser.get();
+		parser.parse(data); 
+		String utcTime= parser.getUtcTime();
+		String latitude = parser.getLatitude(); // 获取纬度值
+		String latHemisphere = parser.getLatHemisphere(); // 获取纬度半球(N或S)
+		String longitude = parser.getLongitude(); // 获取经度值
+		String lonHemisphere = parser.getLonHemisphere(); // 获取经度半球(E或W)
+		String quality = parser.getQuality(); // 获取GPS定位质量
+		String satellites = parser.getSatellites(); // 获取使用的卫星数量
+		String hdop = parser.getHdop(); // 获取水平精度因子
+		String altitude = parser.getAltitude(); // 获取海拔高度
+		String altitudeUnit = parser.getAltitudeUnit(); // 获取海拔单位
+		String geoidHeight = parser.getGeoidHeight(); // 获取大地水准面高度
+		String geoidHeightUnit = parser.getGeoidHeightUnit(); // 获取大地水准面高度单位
+		String differentialTime = parser.getDifferentialTime(); // 获取差分时间
+		String checksum = parser.getChecksum(); // 获取校验和
+		String deviceId = parser.getDeviceId(); // 获取设备ID        
+		String battery = parser.getBattery(); // 获取电池电量
+		String signalStrength = parser.getSignalStrength(); // 获取信号强度
+		String reserve1 = parser.getReserve1(); // 获取保留字段1
+		String reserve2 = parser.getReserve2(); // 获取保留字段2
+		String reserve3 = parser.getReserve3(); // 获取保留字段3
+
+		String portStr = String.valueOf(port); // 将端口号转换为字符串
+		String time = EfficientTimeFormatter.getCurrentTimeFormatted(); 
+		Dell_tag.updateLocationTagProperty(deviceId, "utcTime",utcTime);
+		Dell_tag.updateLocationTagProperty(deviceId, "deviceBattery",time);
+		Dell_tag.updateLocationTagProperty(deviceId, "lastSatelliteSignalTime",time);
+		Dell_tag.updateLocationTagProperty(deviceId, "gnGgaDataTime",time);
+		Dell_tag.updateLocationTagProperty(deviceId, "latitude",latitude);
+		Dell_tag.updateLocationTagProperty(deviceId, "longitude",longitude);
+		Dell_tag.updateLocationTagProperty(deviceId, "satelliteQuality",quality);
+		Dell_tag.updateLocationTagProperty(deviceId, "satelliteCount",satellites);
+		Dell_tag.updateLocationTagProperty(deviceId, "altitude",altitude);
+		Dell_tag.updateLocationTagProperty(deviceId, "ipAddress",ip);
+		Dell_tag.updateLocationTagProperty(deviceId, "ipPort",portStr);
+		Dell_tag.updateLocationTagProperty(deviceId, "onlineStatus","1");   
+		Dell_tag.updateLocationTagProperty(deviceId, "isSatelliteDevice","1");  
+		Dell_tag.updateLocationTagProperty(deviceId, "differentialTime",differentialTime);
+		
+		// 创建TrackData对象并添加到批量插入器
+		TrackData trackData = new TrackData(
+	        parser.getDeviceId(),
+	        parser.getUtcTime(),
+	        parser.getLatitude(),
+	        parser.getLongitude(),
+	        parser.getQuality(),
+	        parser.getSatellites(),
+	        parser.getHdop(),
+	        parser.getAltitude(),
+	        parser.getGeoidHeight(),
+	        parser.getDifferentialTime(),
+	        parser.getBattery()
+	    );
+	    
+	    TrackDataBatchInserter.addTrackData(trackData);
+
+	}
+	private static void dellXTB(String data, String ip, int port) {
+		String portStr = String.valueOf(port); // 将端口号转换为字符串
+		XTB parser = dellXTB.get();
+		parser.parse(data);        
+		String deviceId=parser.getDeviceId();// 设备编号
+		String battery=parser.getBattery();// 电量
+		String version=parser.getVersion();// 版本号
+		String ccid=parser.getCcid();   // CCID
+		String button=parser.getButton(); // 按键
+		String rtcmSource=parser.getRtcmSource();  
+		Dell_tag.updateLocationTagProperty(deviceId, "ipAddress",ip);
+		Dell_tag.updateLocationTagProperty(deviceId, "ipPort",portStr);
+		Dell_tag.updateLocationTagProperty(deviceId, "RTKsource",rtcmSource);
+		Dell_tag.updateLocationTagProperty(deviceId, "sosStatus",button);
+		Dell_tag.updateLocationTagProperty(deviceId, "deviceCardNumber",ccid);
+		Dell_tag.updateLocationTagProperty(deviceId, "deviceVersion",version);
+
+	}
+	
+	
+
+}
\ No newline at end of file
diff --git a/src/publicsWay/TableUtils.java b/src/publicsWay/TableUtils.java
index 248c617..6545e35 100644
--- a/src/publicsWay/TableUtils.java
+++ b/src/publicsWay/TableUtils.java
@@ -1,47 +1,110 @@
-package publicsWay; // 包声明
-import javax.swing.*; // 导入Swing组件
-import javax.swing.table.DefaultTableCellRenderer; // 导入表格单元格渲染器
-import javax.swing.table.DefaultTableModel; // 导入默认表格模型
-import java.awt.*; // 导入AWT图形组件
+package publicsWay;
 
-public class TableUtils { // 表格工具类
+import javax.swing.*;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.DefaultTableModel;
+import javax.swing.table.JTableHeader;
+import java.awt.*;
+
+public class TableUtils {
     
-    // 创建通用表格的方法
+    // Create a styled table with specified column names
     @SuppressWarnings("serial")
-	public static JTable createCommonTable(String[] columnNames) { // 静态方法可直接调用
-        // 创建表格模型 - 匿名内部类扩展DefaultTableModel
-        DefaultTableModel model = new DefaultTableModel(columnNames, 0) { // 初始化表格模型
+    public static JTable createCommonTable(String[] columnNames) {
+        // Create table model
+        DefaultTableModel model = new DefaultTableModel(columnNames, 0) {
             @Override
-            public boolean isCellEditable(int row, int column) { // 重写单元格可编辑性
-                return false; // 所有单元格不可编辑
+            public boolean isCellEditable(int row, int column) {
+                return false;
             }
         };
         
-        // 创建表格实例
-        JTable table = new JTable(model); // 使用自定义模型创建表格
-        table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); // 设置单选模式
+        // Create table instance
+        JTable table = new JTable(model);
+        table.setAutoCreateRowSorter(true);
+        table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
         
-        // 创建表头渲染器
-        DefaultTableCellRenderer headerRenderer = createHeaderRenderer(); // 调用渲染器创建方法
+        // Apply table styling
+        setupTableStyle(table);
         
-        // 应用表头渲染器到所有列
-        for (int i = 0; i < table.getColumnCount(); i++) { // 遍历所有列
-            table.getColumnModel().getColumn(i).setHeaderRenderer(headerRenderer); // 设置列头渲染器
-        }
+        // Apply header styling
+        setupTableHeaderStyle(table);
         
-        return table; // 返回配置好的表格实例
+        return table;
     }
     
-    // 创建表头渲染器
+    // Setup basic table styling
+    public static void setupTableStyle(JTable table) {
+        table.setShowVerticalLines(false);
+        table.setShowHorizontalLines(true);
+        table.setGridColor(new Color(220, 220, 220));
+        table.setIntercellSpacing(new Dimension(0, 1));
+        table.setRowHeight(25);
+    }
+    
+    // Setup table header styling
+    public static void setupTableHeaderStyle(JTable table) {
+        JTableHeader header = table.getTableHeader();
+        header.setBackground(new Color(70, 130, 180));
+        header.setForeground(Color.WHITE);
+        header.setFont(header.getFont().deriveFont(Font.BOLD));
+        header.setPreferredSize(new Dimension(header.getWidth(), 30));
+        
+        // Create and apply header renderer
+        DefaultTableCellRenderer headerRenderer = createHeaderRenderer();
+        for (int i = 0; i < table.getColumnCount(); i++) {
+            table.getColumnModel().getColumn(i).setHeaderRenderer(headerRenderer);
+        }
+    }
+    
+    // Create header renderer
     @SuppressWarnings("serial")
-	private static DefaultTableCellRenderer createHeaderRenderer() { // 私有工具方法
-        return new DefaultTableCellRenderer() { // 返回匿名内部类实例
-            { // 实例初始化块
-                setHorizontalAlignment(SwingConstants.LEFT); // 设置表头文本左对齐
-                setBackground(Color.GRAY); // 设置表头背景为灰色
-                setForeground(Color.WHITE); // 设置表头文字为白色
-                setFont(getFont().deriveFont(Font.BOLD)); // 设置表头字体加粗
+    private static DefaultTableCellRenderer createHeaderRenderer() {
+        return new DefaultTableCellRenderer() {
+            {
+                setHorizontalAlignment(SwingConstants.CENTER);
+                setBackground(new Color(70, 130, 180));
+                setForeground(Color.WHITE);
+                setFont(getFont().deriveFont(Font.BOLD));
+                setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
             }
         };
     }
+    
+    // Create cell renderer with zebra striping
+    @SuppressWarnings("serial")
+    public static DefaultTableCellRenderer createCellRenderer(int alignment) {
+        return new DefaultTableCellRenderer() {
+            @Override
+            public Component getTableCellRendererComponent(JTable table, Object value,
+                    boolean isSelected, boolean hasFocus,
+                    int row, int column) {
+                Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
+
+                // Set alternating row colors
+                if (!isSelected) {
+                    if (row % 2 == 0) {
+                        c.setBackground(new Color(240, 240, 200));
+                    } else {
+                        c.setBackground(Color.WHITE);
+                    }
+                } else {
+                    c.setBackground(new Color(200, 220, 240));
+                }
+
+                // Set cell alignment
+                setHorizontalAlignment(alignment);
+
+                // Set cell padding
+                setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
+
+                return c;
+            }
+        };
+    }
+    
+    // Create centered cell renderer with zebra striping (most common case)
+    public static DefaultTableCellRenderer createCenteredCellRenderer() {
+        return createCellRenderer(SwingConstants.CENTER);
+    }
 }
\ No newline at end of file
diff --git a/src/publicsWay/TrackData.java b/src/publicsWay/TrackData.java
new file mode 100644
index 0000000..39dd18e
--- /dev/null
+++ b/src/publicsWay/TrackData.java
@@ -0,0 +1,177 @@
+package publicsWay;
+
+public class TrackData {
+	public String deviceNumber; // 设备编号
+	public String deviceName; // 设备名称
+	public String xCoordinate; // X坐标
+	public String yCoordinate; // Y坐标
+	public String zCoordinate; // Z坐标
+	public String layer; // 层级
+	public String battery; // 电池电量
+	public String utcTimes; // UTC时间
+	public String latitude; // 纬度
+	public String longitude; // 经度
+	public String positioningQuality; // 定位质量
+	public String satelliteCount; // 卫星数量
+	public String hdop; // 水平精度因子
+	public String altitude; // 海拔高度
+	public String geoidHeight; // 地球高程
+	public String differentialTime; // 差分时间
+	public String source; // 数据来源
+	public String company; // 公司名称
+	public String saveTime; // 保存时间
+	public TrackData(
+	        String deviceNumber, // 设备编号
+	        String deviceName, // 设备名称
+	        String xCoordinate, // X坐标
+	        String yCoordinate, // Y坐标
+	        String zCoordinate, // Z坐标
+	        String layer, // 层级
+	        String battery, // 电池电量
+	        String utcTimes, // UTC时间
+	        String latitude, // 纬度
+	        String longitude, // 经度
+	        String positioningQuality, // 定位质量
+	        String satelliteCount, // 卫星数量
+	        String hdop, // 水平精度因子
+	        String altitude, // 海拔高度
+	        String geoidHeight, // 地球高程
+	        String differentialTime, // 差分时间
+	        String source, // 数据来源
+	        String company, // 公司名称
+	        String saveTime) {
+	    this.deviceNumber = deviceNumber;
+	    this.deviceName = deviceName; // 补充初始化
+	    this.xCoordinate = xCoordinate; // 补充初始化
+	    this.yCoordinate = yCoordinate; // 补充初始化
+	    this.zCoordinate = zCoordinate; // 补充初始化
+	    this.layer = layer; // 补充初始化
+	    this.battery = battery;
+	    this.utcTimes = utcTimes;
+	    this.latitude = latitude;
+	    this.longitude = longitude;
+	    this.positioningQuality = positioningQuality;
+	    this.satelliteCount = satelliteCount;
+	    this.hdop = hdop;
+	    this.altitude = altitude;
+	    this.geoidHeight = geoidHeight;
+	    this.differentialTime = differentialTime;
+	    this.source = source; // 使用传入的 source 参数
+	    this.company = company; // 补充初始化
+	    this.saveTime = saveTime; // 使用传入的 saveTime 参数
+	}
+	public String getDeviceNumber() {
+		return deviceNumber;
+	}
+	public String getDeviceName() {
+		return deviceName;
+	}
+	public String getxCoordinate() {
+		return xCoordinate;
+	}
+	public String getyCoordinate() {
+		return yCoordinate;
+	}
+	public String getzCoordinate() {
+		return zCoordinate;
+	}
+	public String getLayer() {
+		return layer;
+	}
+	public String getBattery() {
+		return battery;
+	}
+	public String getUtcTimes() {
+		return utcTimes;
+	}
+	public String getLatitude() {
+		return latitude;
+	}
+	public String getLongitude() {
+		return longitude;
+	}
+	public String getPositioningQuality() {
+		return positioningQuality;
+	}
+	public String getSatelliteCount() {
+		return satelliteCount;
+	}
+	public String getHdop() {
+		return hdop;
+	}
+	public String getAltitude() {
+		return altitude;
+	}
+	public String getGeoidHeight() {
+		return geoidHeight;
+	}
+	public String getDifferentialTime() {
+		return differentialTime;
+	}
+	public String getSource() {
+		return source;
+	}
+	public String getCompany() {
+		return company;
+	}
+	public String getSaveTime() {
+		return saveTime;
+	}
+	public void setDeviceNumber(String deviceNumber) {
+		this.deviceNumber = deviceNumber;
+	}
+	public void setDeviceName(String deviceName) {
+		this.deviceName = deviceName;
+	}
+	public void setxCoordinate(String xCoordinate) {
+		this.xCoordinate = xCoordinate;
+	}
+	public void setyCoordinate(String yCoordinate) {
+		this.yCoordinate = yCoordinate;
+	}
+	public void setzCoordinate(String zCoordinate) {
+		this.zCoordinate = zCoordinate;
+	}
+	public void setLayer(String layer) {
+		this.layer = layer;
+	}
+	public void setBattery(String battery) {
+		this.battery = battery;
+	}
+	public void setUtcTimes(String utcTimes) {
+		this.utcTimes = utcTimes;
+	}
+	public void setLatitude(String latitude) {
+		this.latitude = latitude;
+	}
+	public void setLongitude(String longitude) {
+		this.longitude = longitude;
+	}
+	public void setPositioningQuality(String positioningQuality) {
+		this.positioningQuality = positioningQuality;
+	}
+	public void setSatelliteCount(String satelliteCount) {
+		this.satelliteCount = satelliteCount;
+	}
+	public void setHdop(String hdop) {
+		this.hdop = hdop;
+	}
+	public void setAltitude(String altitude) {
+		this.altitude = altitude;
+	}
+	public void setGeoidHeight(String geoidHeight) {
+		this.geoidHeight = geoidHeight;
+	}
+	public void setDifferentialTime(String differentialTime) {
+		this.differentialTime = differentialTime;
+	}
+	public void setSource(String source) {
+		this.source = source;
+	}
+	public void setCompany(String company) {
+		this.company = company;
+	}
+	public void setSaveTime(String saveTime) {
+		this.saveTime = saveTime;
+	}
+}
diff --git a/src/publicsWay/TrackDataBatchInserter.java b/src/publicsWay/TrackDataBatchInserter.java
new file mode 100644
index 0000000..fd38d48
--- /dev/null
+++ b/src/publicsWay/TrackDataBatchInserter.java
@@ -0,0 +1,122 @@
+package publicsWay;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import databases.DBConnector;
+import scheduled_task.TrackTableManager;
+
+public class TrackDataBatchInserter {
+    private static final int BATCH_SIZE = 1000;
+    private static final long BATCH_INTERVAL_MS = 1000;
+    private static final int MAX_QUEUE_SIZE = 100000;
+    
+    private static final ConcurrentLinkedQueue<TrackData> trackDataQueue = new ConcurrentLinkedQueue<>();
+    private static final ScheduledExecutorService batchInsertExecutor = Executors.newSingleThreadScheduledExecutor();
+    
+    static {
+        batchInsertExecutor.scheduleAtFixedRate(() -> {
+            try {
+                batchInsertTrackData();
+            } catch (Exception e) {
+                System.err.println("批量插入数据异常: " + e.getMessage());
+            }
+        }, BATCH_INTERVAL_MS, BATCH_INTERVAL_MS, TimeUnit.MILLISECONDS);
+    }
+    
+ 
+    // 添加数据到队列
+    public static void addTrackData(TrackData data) {
+        if (trackDataQueue.size() < MAX_QUEUE_SIZE) {
+            trackDataQueue.offer(data);
+        }
+    }
+    
+    private static void batchInsertTrackData() {
+        if (trackDataQueue.isEmpty()) {
+            return;
+        }
+        
+        String tableName = "tb_track_" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
+        
+        List<TrackData> batchList = new ArrayList<>(BATCH_SIZE);
+        int count = 0;
+        
+        while (count < BATCH_SIZE && !trackDataQueue.isEmpty()) {
+            TrackData data = trackDataQueue.poll();
+            if (data != null) {
+                batchList.add(data);
+                count++;
+            }
+        }
+        
+        if (batchList.isEmpty()) {
+            return;
+        }
+        
+        try {
+            // 使用DBConnector检查表是否存在,不存在则创建
+            if (!DBConnector.tableExists(tableName)) {
+                DBConnector.executeDDL(TrackTableManager.getcreateSQL(tableName));
+            }
+            
+            // 准备批量插入数据
+            List<Object[]> paramsList = new ArrayList<>();
+            for (TrackData data : batchList) {
+                Object[] params = new Object[]{
+                    data.getDeviceNumber(), 
+                    data.getDeviceName(), 
+                    data.getxCoordinate(), 
+                    data.getxCoordinate(),
+                    data.getxCoordinate(), 
+                    data.getLayer(), 
+                    data.getBattery(), 
+                    data.getUtcTimes(), 
+                    data.getLatitude(),
+                    data.getLongitude(), 
+                    data.getPositioningQuality(), 
+                    data.getSatelliteCount(), 
+                    data.getHdop(),
+                    data.getAltitude(), 
+                    data.getGeoidHeight(), 
+                    data.getDifferentialTime(), 
+                    data.getSource(),
+                    data.getCompany(), 
+                    data.getSaveTime()
+                };
+                paramsList.add(params);
+            }
+            
+            // 使用DBConnector进行批量插入
+            String sql = "INSERT INTO " + tableName + " (device_number, device_name, x_coordinate, " +
+                       "y_coordinate, z_coordinate, layer, battery, utc_times, latitude, longitude, " +
+                       "positioning_quality, satellite_count, hdop, altitude, geoid_height, " +
+                       "differential_time, source, company, save_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+            
+            DBConnector.executeBatchUpdate(sql, paramsList);
+            
+        } catch (Exception e) {
+            System.err.println("批量插入数据表异常: " + e.getMessage());
+            // 将错误的数据重新放回队列
+            trackDataQueue.addAll(batchList);
+        }
+    }
+    
+    // 关闭批量插入服务
+    public static void shutdown() {
+        batchInsertExecutor.shutdown();
+        try {
+            if (!batchInsertExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
+                batchInsertExecutor.shutdownNow();
+            }
+        } catch (InterruptedException e) {
+            batchInsertExecutor.shutdownNow();
+            Thread.currentThread().interrupt();
+        }
+    }
+}
diff --git a/src/scheduled_task/TrackTableManager.java b/src/scheduled_task/TrackTableManager.java
index 9107b6e..887e2d1 100644
--- a/src/scheduled_task/TrackTableManager.java
+++ b/src/scheduled_task/TrackTableManager.java
@@ -7,21 +7,18 @@
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
+import dell_targets.Dell_SystemConfiguration;
+import databases.DBConnector;  // 添加导入
 
 public class TrackTableManager {
-
-    // 配置参数
-    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/your_database?useSSL=false";
-    private static final String USERNAME = "your_username";
-    private static final String PASSWORD = "your_password";
-    private static final int SAVE_DAYS = 30; // 轨迹数据保存天数
+    // 移除硬编码的数据库连接参数
+    private static final int SAVE_DAYS = Dell_SystemConfiguration.TrajectoryRetentionDays;
     private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
     private static final String TABLE_PREFIX = "tb_track_";
-
-    public static void main(String[] args) {
+    
+    public static void Start() {
         // 初始化时立即执行一次
-        manageTables();
-        
+        manageTables();        
         // 创建定时任务(每天凌晨1点执行)
         ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
         scheduler.scheduleAtFixedRate(
@@ -34,85 +31,85 @@
 
     // 主管理逻辑
     private static void manageTables() {
-        try (Connection conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD)) {
-            // 1. 创建明天的表
-            createTomorrowTable(conn);
+        try {
+            // 1. 创建未来3天的表
+            createFutureTables();
             
             // 2. 删除过期表
-            deleteExpiredTables(conn);
+            deleteExpiredTables();
             
         } catch (SQLException e) {
             System.err.println("数据库操作失败: " + e.getMessage());
         }
     }
 
-    // 创建明天的表
-    private static void createTomorrowTable(Connection conn) throws SQLException {
-        String tomorrow = LocalDate.now().plusDays(1).format(DATE_FORMATTER);
-        String tableName = TABLE_PREFIX + tomorrow;
-        
-        if (!tableExists(conn, tableName)) {
-            String createSQL = "CREATE TABLE " + tableName + " (" +
-                "id INT(30) PRIMARY KEY AUTO_INCREMENT COMMENT '序号'," +
-                "device_number VARCHAR(30) NOT NULL COMMENT '设备编号'," +
-                "device_name VARCHAR(30) COMMENT '设备名称'," +
-                "x_coordinate VARCHAR(30) COMMENT 'X坐标'," +
-                "y_coordinate VARCHAR(30) COMMENT 'Y坐标'," +
-                "z_coordinate VARCHAR(30) COMMENT 'Z坐标'," +
-                "layer VARCHAR(30) COMMENT '所在层'," +
-                "battery VARCHAR(30) COMMENT '电量'," +
-                "utc_times VARCHAR(30) COMMENT 'UTC时间'," +
-                "latitude VARCHAR(30) COMMENT '纬度'," +
-                "longitude VARCHAR(30) COMMENT '经度'," +
-                "positioning_quality VARCHAR(30) COMMENT '定位质量'," +
-                "satellite_count VARCHAR(30) COMMENT '卫星数量'," +
-                "hdop VARCHAR(30) COMMENT '水平精度因子'," +
-                "altitude VARCHAR(30) COMMENT '海拔高度'," +
-                "geoid_height VARCHAR(30) COMMENT '大地水准面高度'," +
-                "differential_time VARCHAR(30) COMMENT '差分时间'," +
-                "source VARCHAR(30) COMMENT '定位结果来源(0=UWB,1=卫星,3=蓝牙)'," +
-                "company VARCHAR(30) COMMENT '所属公司'," +
-                "save_time VARCHAR(30) COMMENT '保存时间'" +
-                ") ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='轨迹记录表'";
-            
-            try (Statement stmt = conn.createStatement()) {
-                stmt.executeUpdate(createSQL);
-                System.out.println("表创建成功: " + tableName);
-            }
-        } else {
-            System.out.println("表已存在: " + tableName);
+    // 创建未来3天的表(包括明天、后天和大后天)
+    private static void createFutureTables() throws SQLException {
+        for (int i = 1; i <= 3; i++) {
+            String futureDate = LocalDate.now().plusDays(i).format(DATE_FORMATTER);
+            String tableName = TABLE_PREFIX + futureDate;            
+            if (!tableExists(tableName)) {                
+                DBConnector.executeUpdate(getcreateSQL(tableName));
+            } 
         }
     }
 
     // 删除过期表
-    private static void deleteExpiredTables(Connection conn) throws SQLException {
+    private static void deleteExpiredTables() throws SQLException {
         LocalDate thresholdDate = LocalDate.now().minusDays(SAVE_DAYS);
         String threshold = thresholdDate.format(DATE_FORMATTER);
         
-        for (String table : getAllTrackTables(conn)) {
+        for (String table : getAllTrackTables()) {
             String datePart = table.substring(TABLE_PREFIX.length());
             if (datePart.compareTo(threshold) < 0) {
-                try (Statement stmt = conn.createStatement()) {
-                    stmt.executeUpdate("DROP TABLE " + table);
-                    System.out.println("已删除过期表: " + table);
-                }
+                DBConnector.executeUpdate("DROP TABLE " + table);
             }
         }
     }
+    
+    public static String getcreateSQL(String tableName) {
+    	 String createSQL = "CREATE TABLE " + tableName + " (" +
+                 "id INT(30) PRIMARY KEY AUTO_INCREMENT COMMENT '序号'," +
+                 "device_number VARCHAR(30) NOT NULL COMMENT '设备编号'," +
+                 "device_name VARCHAR(30) COMMENT '设备名称'," +
+                 "x_coordinate VARCHAR(30) COMMENT 'X坐标'," +
+                 "y_coordinate VARCHAR(30) COMMENT 'Y坐标'," +
+                 "z_coordinate VARCHAR(30) COMMENT 'Z坐标'," +
+                 "layer VARCHAR(30) COMMENT '所在层'," +
+                 "battery VARCHAR(30) COMMENT '电量'," +
+                 "utc_times VARCHAR(30) COMMENT 'UTC时间'," +
+                 "latitude VARCHAR(30) COMMENT '纬度'," +
+                 "longitude VARCHAR(30) COMMENT '经度'," +
+                 "positioning_quality VARCHAR(30) COMMENT '定位质量'," +
+                 "satellite_count VARCHAR(30) COMMENT '卫星数量'," +
+                 "hdop VARCHAR(30) COMMENT '水平精度因子'," +
+                 "altitude VARCHAR(30) COMMENT '海拔高度'," +
+                 "geoid_height VARCHAR(30) COMMENT '大地水准面高度'," +
+                 "differential_time VARCHAR(30) COMMENT '差分时间'," +
+                 "source VARCHAR(30) COMMENT '定位结果来源(0=UWB,1=卫星,3=蓝牙)'," +
+                 "company VARCHAR(30) COMMENT '所属公司'," +
+                 "save_time VARCHAR(30) COMMENT '保存时间'" +
+                 ") ENGINE=INNODB DEFAULT CHARSET=utf8mb4 COMMENT='轨迹记录表'";
+		return createSQL;
+    }
 
     // 检查表是否存在
-    private static boolean tableExists(Connection conn, String tableName) throws SQLException {
-        try (ResultSet rs = conn.getMetaData().getTables(null, null, tableName, null)) {
-            return rs.next();
+    private static boolean tableExists(String tableName) throws SQLException {
+        try (ResultSet rs = DBConnector.executeQuery(
+            "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?", 
+            tableName)) {
+            return rs.next() && rs.getInt(1) > 0;
         }
     }
 
     // 获取所有轨迹表
-    private static List<String> getAllTrackTables(Connection conn) throws SQLException {
+    private static List<String> getAllTrackTables() throws SQLException {
         List<String> tables = new ArrayList<>();
-        try (ResultSet rs = conn.getMetaData().getTables(null, null, TABLE_PREFIX + "%", null)) {
+        try (ResultSet rs = DBConnector.executeQuery(
+            "SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name LIKE ?", 
+            TABLE_PREFIX + "%")) {
             while (rs.next()) {
-                tables.add(rs.getString("TABLE_NAME"));
+                tables.add(rs.getString("table_name"));
             }
         }
         return tables;
diff --git a/src/targets/LocationTag.java b/src/targets/LocationTag.java
index 8759f85..21b56fe 100644
--- a/src/targets/LocationTag.java
+++ b/src/targets/LocationTag.java
@@ -90,7 +90,11 @@
     public String InteractionType;
     public String ipAddress;
     public String ipPort;
-
+    public String gnGgaDataTime;//接收到gngga数据时间
+    public String satelliteChipType;//卫星芯片类型
+    public String AutoUpgraded;//完成了自动升级
+    public String isSatelliteDevice;//是否是卫星定位设备,-1不知道1是0不是
+    public String RTKsource;//差分源
         // Getter和Setter方法
     public int getId() {
         return id;
@@ -801,4 +805,44 @@
 	public void setIpPort(String ipPort) {
 		this.ipPort = ipPort;
 	}
+
+	public String getGnGgaDataTime() {
+		return gnGgaDataTime;
+	}
+
+	public String getSatelliteChipType() {
+		return satelliteChipType;
+	}
+
+	public void setGnGgaDataTime(String gnGgaDataTime) {
+		this.gnGgaDataTime = gnGgaDataTime;
+	}
+
+	public void setSatelliteChipType(String satelliteChipType) {
+		this.satelliteChipType = satelliteChipType;
+	}
+
+	public String  getAutoUpgraded() {
+		return AutoUpgraded;
+	}
+
+	public void setAutoUpgraded(String autoUpgraded) {
+		AutoUpgraded = autoUpgraded;
+	}
+
+	public String getIsSatelliteDevice() {
+		return isSatelliteDevice;
+	}
+
+	public void setIsSatelliteDevice(String isSatelliteDevice) {
+		this.isSatelliteDevice = isSatelliteDevice;
+	}
+
+	public String getRTKsource() {
+		return RTKsource;
+	}
+
+	public void setRTKsource(String rTKsource) {
+		RTKsource = rTKsource;
+	}
 }
\ No newline at end of file
diff --git a/src/publicsWay/UDPPortAReceiver.java b/src/udptcp/UDPPortAReceiver.java
similarity index 98%
rename from src/publicsWay/UDPPortAReceiver.java
rename to src/udptcp/UDPPortAReceiver.java
index 2c68130..6739b3f 100644
--- a/src/publicsWay/UDPPortAReceiver.java
+++ b/src/udptcp/UDPPortAReceiver.java
@@ -1,4 +1,4 @@
-package publicsWay;
+package udptcp;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
@@ -8,6 +8,7 @@
 
 import dell_system.MessageViewPanel;
 import dell_targets.Dell_SystemConfiguration;
+import publicsWay.PacketProcessingSystem;
 
 public class UDPPortAReceiver {
 	public static final int PORT =Dell_SystemConfiguration.hexport;
diff --git a/src/udptcp/UDPPortBReceiver.java b/src/udptcp/UDPPortBReceiver.java
index 9ba1dd9..63185c3 100644
--- a/src/udptcp/UDPPortBReceiver.java
+++ b/src/udptcp/UDPPortBReceiver.java
@@ -2,112 +2,112 @@
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicLong;
 
-import publicsWay.PacketProcessingSystem;
+import dell_system.MessageViewPanel;
+import dell_targets.Dell_SystemConfiguration;
+import publicsWay.PacketProcessingSystemB;
 
 public class UDPPortBReceiver {
-    public static final int PORT = 7000;
-    @SuppressWarnings("unused")
+	public static final int PORT =Dell_SystemConfiguration.ascallport;
+	@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);
-                            
-                        } 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;
 
-    public static long getPacketCount() {
-        return packetCount.get();
-    }
+		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());
+							String asciiData = new String(packet.getData(), 0, packet.getLength(), StandardCharsets.US_ASCII);
+							// 去掉回车和换行
+					        asciiData = asciiData.replaceAll("\r", "").replaceAll("\n", "");
+							// 调用时添加本地端口参数							
+							PacketProcessingSystemB.storePacket(ip, port, asciiData);
+							// 报文查看窗口显示数据
+							MessageViewPanel.showData(asciiData, ip, port, PORT,"UDPB","ALL","ALL");
+							packetCount.incrementAndGet();  // 关键修复:增加计数器  
+
+						} catch (Exception e) {
+							System.err.println("Error processing UDP-B packet: " + e.getMessage());
+						}
+					});
+				}
+			} catch (Exception e) {
+				System.err.println("UDP-B 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 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/ContentPanelFactory.java b/src/window/ContentPanelFactory.java
index 6e9b00d..26044ea 100644
--- a/src/window/ContentPanelFactory.java
+++ b/src/window/ContentPanelFactory.java
@@ -15,6 +15,7 @@
 import dell_system.VersionInfoPanel;
 import dell_targets.BatteryRecordPanel;
 import dell_targets.DifferentialBaseStationManagementPanel;
+import dell_targets.SatelliteDevicePanel;
 import dell_targets.TagManagementPanel;
 import dell_targets.TagTypeManagementPanel;
 import javax.swing.*;
@@ -120,6 +121,8 @@
                 panel.add(new QuickCalculationPanel(messages), BorderLayout.CENTER);
             } else if (nodeName.equals(messages.getString("Serial_Port_Tool"))) {// 涓插彛宸ュ叿              
                 panel.add(new SerialCommPanel(messages), BorderLayout.CENTER);
+            }else if (nodeName.equals(messages.getString("SatelliteEquipment"))) {//鍗槦璁惧              
+                panel.add(new SatelliteDevicePanel(messages), BorderLayout.CENTER);
             } else {
                 // 瀵逛簬鏈疄鐜板姛鑳斤紝鏄剧ず寮�鍙戜腑鎻愮ず
                 JLabel label = new JLabel(messages.getString("DEVELOPING") + ": " + nodeName, SwingConstants.CENTER);
diff --git a/src/window/NavigationTreeFactory.java b/src/window/NavigationTreeFactory.java
index 3e767c6..f2fc369 100644
--- a/src/window/NavigationTreeFactory.java
+++ b/src/window/NavigationTreeFactory.java
@@ -30,7 +30,8 @@
         deviceNode.add(new DefaultMutableTreeNode(messages.getString("BASE_MANAGEMENT")));      // 基站管理
         deviceNode.add(new DefaultMutableTreeNode(messages.getString("GATEWAY_MANAGEMENT")));   // 网关管理
         deviceNode.add(new DefaultMutableTreeNode(messages.getString("DIFF_BASE")));            // 差分基站
-        deviceNode.add(new DefaultMutableTreeNode(messages.getString("TAG_TYPE")));             // 标签类型
+        deviceNode.add(new DefaultMutableTreeNode(messages.getString("TAG_TYPE")));  
+        deviceNode.add(new DefaultMutableTreeNode(messages.getString("SatelliteEquipment")));  // 卫星设备
         root.add(deviceNode);
         
         // 算法节点 (一级)
diff --git a/src/window/WelcomeFrame.java b/src/window/WelcomeFrame.java
index 7867f43..8d081b6 100644
--- a/src/window/WelcomeFrame.java
+++ b/src/window/WelcomeFrame.java
@@ -9,10 +9,10 @@
 
 import java.util.ResourceBundle;
 
+import udptcp.UDPPortAReceiver;
 import udptcp.UDPPortBReceiver;
 import dell_targets.Dell_BaseStation;
 import dell_targets.Dell_tag;
-import publicsWay.UDPPortAReceiver;
 import dell_targets.Dell_SystemConfiguration;
 
 public class WelcomeFrame extends JInternalFrame {
diff --git a/systemfile/Messages_en.properties b/systemfile/Messages_en.properties
index 0ae7fd4..db77d58 100644
--- a/systemfile/Messages_en.properties
+++ b/systemfile/Messages_en.properties
@@ -1,3 +1,45 @@
+RtkSource=RtkSource
+UPGRADE_DEVICE_ELLIPSIS=...
+UPGRADE_DEVICE_UNIT=device(s)
+UPGRADE_CONFIRMATION_HEADER=Preparing to upgrade the following devices:
+FIRMWARE_URL_LABEL=Firmware URL
+TOTAL_DEVICES_COUNT=Total devices: %d
+UPGRADE_DEVICES_WITH_URL=Preparing to upgrade %d devices, device IDs: %s, firmware address: %s
+SET_UPGRADE_CONDITIONS=SetUpgradeConditions
+BY_COMPANY_NAME=ByCompanyName
+COMPANY = Company
+COMMAND_SEND = Command Send
+FIRMWARE_URL = Firmware URL
+ENTER_FIRMWARE_DOWNLOAD_URL = Enter the firmware download URL
+FIRMWARE_URL_REQUIRED = Firmware download URL is required
+UPGRADE_DEVICES_WITH_URL = Upgrading %d devices with firmware URL: %s
+SEND_COMMAND = Send Command
+SatelliteEquipment=SatelliteEquipment
+QUICK_OPERATION=Quick Operation  
+SELECT=Select  
+INDEX=Index  
+DEVICE_NUMBER=Device Number  
+LONGITUDE=Longitude  
+LATITUDE=Latitude  
+ALTITUDE=Altitude  
+STATUS=Status  
+SATELLITE_COUNT=Satellite Count  
+DIFFERENTIAL_TIME=Differential Time  
+VERSION=Version  
+CARD_NUMBER=Card Number  
+ADDRESS=Address  
+PORT=Port  
+UPDATE_TIME=Update Time  
+UPGRADE_CONDITION=Upgrade Condition  
+BY_VERSION=By Version  
+BY_NUMBER=By Number  
+BY_SELECTED_DEVICE=By Selected Device  
+START_UPGRADE=Start Upgrade  
+UPGRADE_VALUE_REQUIRED=Upgrade value is required  
+SELECT_DEVICE_TO_UPGRADE=Select device to upgrade  
+UPGRADE_SELECTED_DEVICES=Start upgrading the selected %d devices  
+UPGRADE_BY_VERSION=Start upgrading devices with version %s  
+UPGRADE_BY_NUMBER=Start upgrading device with number %s
 TAG_STATS = Tag Statistics  
 BASE_STATION_STATS = Base Station Statistics  
 SOFTWARE_VERSION = Software Version  
diff --git a/systemfile/Messages_zh.properties b/systemfile/Messages_zh.properties
index 2f3aebe..540df4c 100644
--- a/systemfile/Messages_zh.properties
+++ b/systemfile/Messages_zh.properties
@@ -1,3 +1,46 @@
+# 鍗槦璁惧绠$悊鐩稿叧璧勬簮
+RtkSource=宸垎婧�
+UPGRADE_DEVICE_ELLIPSIS=... (鍏�
+UPGRADE_DEVICE_UNIT=涓澶�)
+UPGRADE_CONFIRMATION_HEADER=鍑嗗鍗囩骇浠ヤ笅璁惧:\n
+FIRMWARE_URL_LABEL=鍥轰欢鍦板潃
+TOTAL_DEVICES_COUNT=鎬诲叡 %d 涓澶�
+UPGRADE_DEVICES_WITH_URL=鍑嗗鍗囩骇 %d 涓澶囷紝璁惧缂栧彿锛�%s锛屽浐浠跺湴鍧�锛�%s
+SET_UPGRADE_CONDITIONS=璁剧疆鍗囩骇鏉′欢
+BY_COMPANY_NAME=鏍规嵁鍏徃鍚嶇О
+COMPANY=鎵�灞炲叕鍙�
+COMMAND_SEND=鎸囦护鍙戦��
+FIRMWARE_URL=鍥轰欢鍦板潃
+ENTER_FIRMWARE_DOWNLOAD_URL=褰曞叆闇�瑕佸崌绾у浐浠朵笅杞藉湴鍧�
+FIRMWARE_URL_REQUIRED=璇疯緭鍏ュ浐浠朵笅杞藉湴鍧�
+UPGRADE_DEVICES_WITH_URL=灏嗕负%d涓澶囨墽琛屽崌绾э紝鍥轰欢鍦板潃锛�%s
+SEND_COMMAND=鍙戦�佹寚浠�
+SatelliteEquipment=鍗槦璁惧
+QUICK_OPERATION=蹇嵎鎿嶄綔
+SELECT=閫夋嫨
+INDEX=搴忓彿
+DEVICE_NUMBER=缂栧彿
+LONGITUDE=缁忓害
+LATITUDE=绾害
+ALTITUDE=楂樼▼
+STATUS=鐘舵��
+SATELLITE_COUNT=鍗槦鏁�
+DIFFERENTIAL_TIME=宸垎鏃堕棿
+VERSION=鐗堟湰
+CARD_NUMBER=鍗″彿
+ADDRESS=鍦板潃
+PORT=绔彛
+UPDATE_TIME=鏇存柊鏃堕棿
+UPGRADE_CONDITION=鍗囩骇鏉′欢
+BY_VERSION=鏍规嵁鐗堟湰
+BY_NUMBER=鏍规嵁缂栧彿
+BY_SELECTED_DEVICE=鏍规嵁閫変腑鐨勮澶�
+START_UPGRADE=鍚姩鍗囩骇
+UPGRADE_VALUE_REQUIRED=璇疯緭鍏ュ崌绾ф潯浠跺��
+SELECT_DEVICE_TO_UPGRADE=璇烽�夋嫨瑕佸崌绾х殑璁惧
+UPGRADE_SELECTED_DEVICES=寮�濮嬪崌绾ч�変腑鐨� %d 涓澶�
+UPGRADE_BY_VERSION=寮�濮嬪崌绾х増鏈负 %s 鐨勮澶�
+UPGRADE_BY_NUMBER=寮�濮嬪崌绾ц澶囩紪鍙蜂负 %s 鐨勮澶�
 TAG_STATS=鏍囩缁熻
 BASE_STATION_STATS=鍩虹珯缁熻
 SOFTWARE_VERSION=杞欢鐗堟湰
diff --git a/systemfile/logfile/openlog.txt b/systemfile/logfile/openlog.txt
index 0f4e122..a9ea94c 100644
--- a/systemfile/logfile/openlog.txt
+++ b/systemfile/logfile/openlog.txt
@@ -960,3 +960,297 @@
 工作时长: 0小时 0分钟 25秒
 -----------------------------------
 程序启动: 2025-08-11 23:04:55
+程序关闭: 2025-08-11 23:15:52
+工作时长: 0小时 10分钟 57秒
+-----------------------------------
+程序启动: 2025-08-12 21:50:17
+程序关闭: 2025-08-12 21:52:16
+工作时长: 0小时 1分钟 58秒
+-----------------------------------
+程序启动: 2025-08-12 21:52:33
+程序关闭: 2025-08-12 21:52:57
+工作时长: 0小时 0分钟 24秒
+-----------------------------------
+程序启动: 2025-08-12 21:52:59
+程序关闭: 2025-08-12 21:57:54
+工作时长: 0小时 4分钟 54秒
+-----------------------------------
+程序启动: 2025-08-12 21:57:56
+程序关闭: 2025-08-12 21:58:34
+工作时长: 0小时 0分钟 38秒
+-----------------------------------
+程序启动: 2025-08-12 21:58:40
+程序启动: 2025-08-12 22:01:53
+程序启动: 2025-08-12 22:03:37
+程序启动: 2025-08-12 22:06:02
+程序启动: 2025-08-12 22:12:48
+程序关闭: 2025-08-12 22:15:41
+工作时长: 0小时 2分钟 52秒
+-----------------------------------
+程序启动: 2025-08-12 22:19:13
+程序启动: 2025-08-12 23:13:17
+程序关闭: 2025-08-12 23:13:21
+工作时长: 0小时 54分钟 8秒
+-----------------------------------
+程序启动: 2025-08-12 23:13:23
+程序关闭: 2025-08-12 23:16:01
+工作时长: 0小时 2分钟 37秒
+-----------------------------------
+程序启动: 2025-08-12 23:16:02
+程序关闭: 2025-08-12 23:16:28
+工作时长: 0小时 0分钟 25秒
+-----------------------------------
+程序启动: 2025-08-15 23:09:00
+程序关闭: 2025-08-15 23:17:24
+工作时长: 0小时 8分钟 24秒
+-----------------------------------
+程序启动: 2025-08-21 21:25:25
+程序关闭: 2025-08-21 21:28:51
+工作时长: 0小时 3分钟 25秒
+-----------------------------------
+程序启动: 2025-08-23 15:41:33
+程序关闭: 2025-08-23 15:43:01
+工作时长: 0小时 1分钟 28秒
+-----------------------------------
+程序启动: 2025-08-23 15:45:38
+程序关闭: 2025-08-23 15:46:00
+工作时长: 0小时 0分钟 21秒
+-----------------------------------
+程序启动: 2025-08-23 15:47:59
+程序关闭: 2025-08-23 15:48:09
+工作时长: 0小时 0分钟 9秒
+-----------------------------------
+程序启动: 2025-08-23 16:18:45
+程序关闭: 2025-08-23 16:19:17
+工作时长: 0小时 0分钟 32秒
+-----------------------------------
+程序启动: 2025-08-23 16:22:53
+程序启动: 2025-08-23 16:25:27
+程序关闭: 2025-08-23 16:31:00
+工作时长: 0小时 5分钟 32秒
+-----------------------------------
+程序启动: 2025-08-23 16:31:02
+程序关闭: 2025-08-23 16:31:31
+工作时长: 0小时 0分钟 28秒
+-----------------------------------
+程序启动: 2025-08-23 16:32:43
+程序关闭: 2025-08-23 16:34:04
+工作时长: 0小时 1分钟 21秒
+-----------------------------------
+程序启动: 2025-08-23 16:35:29
+程序启动: 2025-08-23 16:37:39
+程序启动: 2025-08-23 16:43:57
+程序关闭: 2025-08-23 16:45:05
+工作时长: 0小时 1分钟 8秒
+-----------------------------------
+程序启动: 2025-08-23 17:01:49
+程序关闭: 2025-08-23 21:13:53
+工作时长: 4小时 12分钟 4秒
+-----------------------------------
+程序启动: 2025-08-23 21:13:57
+程序关闭: 2025-08-23 21:14:07
+工作时长: 0小时 0分钟 9秒
+-----------------------------------
+程序启动: 2025-08-23 21:15:06
+程序关闭: 2025-08-23 21:55:14
+工作时长: 0小时 40分钟 7秒
+-----------------------------------
+程序启动: 2025-08-23 21:55:16
+程序关闭: 2025-08-23 21:59:33
+工作时长: 0小时 4分钟 17秒
+-----------------------------------
+程序启动: 2025-08-23 21:59:35
+程序关闭: 2025-08-23 22:01:21
+工作时长: 0小时 1分钟 46秒
+-----------------------------------
+程序启动: 2025-08-23 22:01:23
+程序关闭: 2025-08-23 22:04:10
+工作时长: 0小时 2分钟 46秒
+-----------------------------------
+程序启动: 2025-08-23 22:04:12
+程序关闭: 2025-08-23 22:05:25
+工作时长: 0小时 1分钟 13秒
+-----------------------------------
+程序启动: 2025-08-23 22:05:27
+程序关闭: 2025-08-23 22:05:48
+工作时长: 0小时 0分钟 21秒
+-----------------------------------
+程序启动: 2025-08-23 22:06:20
+程序关闭: 2025-08-23 22:06:34
+工作时长: 0小时 0分钟 14秒
+-----------------------------------
+程序启动: 2025-08-23 22:07:49
+程序关闭: 2025-08-23 22:08:14
+工作时长: 0小时 0分钟 24秒
+-----------------------------------
+程序启动: 2025-08-23 22:08:34
+程序关闭: 2025-08-23 22:10:39
+工作时长: 0小时 2分钟 5秒
+-----------------------------------
+程序启动: 2025-08-23 22:11:06
+程序关闭: 2025-08-23 22:38:24
+工作时长: 0小时 27分钟 17秒
+-----------------------------------
+程序启动: 2025-08-23 22:38:27
+程序关闭: 2025-08-23 22:38:52
+工作时长: 0小时 0分钟 25秒
+-----------------------------------
+程序启动: 2025-08-23 22:38:57
+程序启动: 2025-08-23 22:42:02
+程序关闭: 2025-08-23 22:46:21
+工作时长: 0小时 4分钟 19秒
+-----------------------------------
+程序启动: 2025-08-23 22:46:24
+程序关闭: 2025-08-23 22:47:27
+工作时长: 0小时 1分钟 3秒
+-----------------------------------
+程序启动: 2025-08-23 22:47:30
+程序启动: 2025-08-23 22:59:41
+程序关闭: 2025-08-23 23:00:29
+工作时长: 0小时 0分钟 47秒
+-----------------------------------
+程序启动: 2025-08-23 23:05:46
+程序关闭: 2025-08-23 23:09:25
+工作时长: 0小时 3分钟 39秒
+-----------------------------------
+程序启动: 2025-08-24 09:46:48
+程序关闭: 2025-08-24 10:31:07
+工作时长: 0小时 44分钟 19秒
+-----------------------------------
+程序启动: 2025-08-24 10:31:09
+程序关闭: 2025-08-24 10:31:14
+工作时长: 0小时 0分钟 5秒
+-----------------------------------
+程序启动: 2025-08-24 10:34:14
+程序启动: 2025-08-24 10:43:12
+程序关闭: 2025-08-24 10:44:57
+工作时长: 0小时 1分钟 45秒
+-----------------------------------
+程序启动: 2025-08-24 10:52:51
+程序关闭: 2025-08-24 10:53:14
+工作时长: 0小时 0分钟 22秒
+-----------------------------------
+程序启动: 2025-08-24 10:54:37
+程序关闭: 2025-08-24 10:59:41
+工作时长: 0小时 5分钟 3秒
+-----------------------------------
+程序启动: 2025-08-24 10:59:43
+程序关闭: 2025-08-24 11:04:30
+工作时长: 0小时 4分钟 47秒
+-----------------------------------
+程序启动: 2025-08-24 11:04:56
+程序关闭: 2025-08-24 11:05:08
+工作时长: 0小时 0分钟 12秒
+-----------------------------------
+程序启动: 2025-08-24 11:06:34
+程序关闭: 2025-08-24 11:10:47
+工作时长: 0小时 4分钟 12秒
+-----------------------------------
+程序启动: 2025-08-24 11:10:50
+程序关闭: 2025-08-24 11:13:07
+工作时长: 0小时 2分钟 16秒
+-----------------------------------
+程序启动: 2025-08-24 11:13:09
+程序关闭: 2025-08-24 11:23:21
+工作时长: 0小时 10分钟 12秒
+-----------------------------------
+程序启动: 2025-08-24 11:23:23
+程序关闭: 2025-08-24 12:35:19
+工作时长: 1小时 11分钟 55秒
+-----------------------------------
+程序启动: 2025-08-24 12:35:22
+程序关闭: 2025-08-24 12:41:38
+工作时长: 0小时 6分钟 15秒
+-----------------------------------
+程序启动: 2025-08-24 12:41:41
+程序关闭: 2025-08-24 12:55:40
+工作时长: 0小时 13分钟 59秒
+-----------------------------------
+程序启动: 2025-08-24 12:55:42
+程序关闭: 2025-08-24 12:56:25
+工作时长: 0小时 0分钟 42秒
+-----------------------------------
+程序启动: 2025-08-24 12:57:15
+程序关闭: 2025-08-24 12:57:47
+工作时长: 0小时 0分钟 31秒
+-----------------------------------
+程序启动: 2025-08-24 13:03:07
+程序关闭: 2025-08-24 13:07:28
+工作时长: 0小时 4分钟 20秒
+-----------------------------------
+程序启动: 2025-08-24 13:07:30
+程序关闭: 2025-08-24 13:07:48
+工作时长: 0小时 0分钟 17秒
+-----------------------------------
+程序启动: 2025-08-24 13:09:13
+程序关闭: 2025-08-24 13:09:55
+工作时长: 0小时 0分钟 41秒
+-----------------------------------
+程序启动: 2025-08-24 13:12:54
+程序启动: 2025-08-24 13:18:23
+程序关闭: 2025-08-24 13:18:27
+工作时长: 0小时 5分钟 32秒
+-----------------------------------
+程序启动: 2025-08-24 13:18:29
+程序关闭: 2025-08-24 13:19:01
+工作时长: 0小时 0分钟 31秒
+-----------------------------------
+程序启动: 2025-08-24 13:20:34
+程序关闭: 2025-08-24 13:25:22
+工作时长: 0小时 4分钟 47秒
+-----------------------------------
+程序启动: 2025-08-24 13:25:23
+程序关闭: 2025-08-24 13:26:33
+工作时长: 0小时 1分钟 10秒
+-----------------------------------
+程序启动: 2025-08-24 13:26:36
+程序关闭: 2025-08-24 13:27:25
+工作时长: 0小时 0分钟 49秒
+-----------------------------------
+程序启动: 2025-08-24 13:40:36
+程序关闭: 2025-08-24 13:41:12
+工作时长: 0小时 0分钟 35秒
+-----------------------------------
+程序启动: 2025-08-24 13:41:35
+程序关闭: 2025-08-24 13:42:05
+工作时长: 0小时 0分钟 29秒
+-----------------------------------
+程序启动: 2025-08-24 13:43:24
+程序启动: 2025-08-24 13:48:00
+程序关闭: 2025-08-24 13:48:04
+工作时长: 0小时 4分钟 40秒
+-----------------------------------
+程序启动: 2025-08-24 13:48:06
+程序关闭: 2025-08-24 13:48:30
+工作时长: 0小时 0分钟 24秒
+-----------------------------------
+程序启动: 2025-08-24 13:48:46
+程序关闭: 2025-08-24 13:53:20
+工作时长: 0小时 4分钟 33秒
+-----------------------------------
+程序启动: 2025-08-24 14:28:32
+程序关闭: 2025-08-24 14:31:07
+工作时长: 0小时 2分钟 34秒
+-----------------------------------
+程序启动: 2025-08-24 14:31:40
+程序关闭: 2025-08-24 14:40:24
+工作时长: 0小时 8分钟 44秒
+-----------------------------------
+程序启动: 2025-08-24 14:40:26
+程序启动: 2025-08-24 14:51:47
+程序关闭: 2025-08-24 14:51:51
+工作时长: 0小时 11分钟 25秒
+-----------------------------------
+程序启动: 2025-08-24 14:51:53
+程序关闭: 2025-08-24 16:44:14
+工作时长: 1小时 52分钟 20秒
+-----------------------------------
+程序启动: 2025-08-24 16:44:16
+程序关闭: 2025-08-24 16:56:04
+工作时长: 0小时 11分钟 48秒
+-----------------------------------
+程序启动: 2025-08-24 16:56:06
+程序关闭: 2025-08-24 17:01:59
+工作时长: 0小时 5分钟 52秒
+-----------------------------------
+程序启动: 2025-08-24 17:02:01

--
Gitblit v1.9.3