From b518f895dec5264fd25e22a68300c40ceba6f43d Mon Sep 17 00:00:00 2001
From: 826220679@qq.com <826220679@qq.com>
Date: 星期六, 20 十二月 2025 15:30:20 +0800
Subject: [PATCH] 新增了按钮功能

---
 dikuai.properties                        |   12 
 src/dikuai/addzhangaiwu.java             |    2 
 src/lujing/MowingPathGenerationPage.java |  119 ++-------
 src/zhuye/Lookbutton.java                |  107 ++++++++
 set.properties                           |    6 
 src/zhuye/Fuzhibutton.java               |  270 ++++++++++++++++++++++
 src/dikuai/Dikuai.java                   |   16 +
 src/zhuye/buttonset.java                 |    2 
 src/dikuai/Dikuaiguanli.java             |  169 +++++++++----
 9 files changed, 545 insertions(+), 158 deletions(-)

diff --git a/dikuai.properties b/dikuai.properties
index 57a6cac..15b98c9 100644
--- a/dikuai.properties
+++ b/dikuai.properties
@@ -1,5 +1,5 @@
 #Dikuai Properties
-#Sat Dec 20 12:24:28 GMT+08:00 2025
+#Sat Dec 20 14:47:09 GMT+08:00 2025
 LAND2.boundaryCoordinates=5.38,-6.41;-11.15,-8.94;-12.75,-4.68;-12.23,-3.28;-11.12,-3.17;-9.29,-3.53;-7.46,-3.89;-5.62,-4.25;-3.79,-4.61;-1.96,-4.97;-0.12,-5.33;1.71,-5.69;3.54,-6.05;5.38,-6.41
 LAND1.intelligentSceneAnalysis=-1
 LAND1.mowingSafetyDistance=-1
@@ -7,13 +7,19 @@
 LAND1.returnPointCoordinates=-1
 LAND1.landNumber=LAND1
 LAND2.landName=1452
+LAND2.userId=-1
+LAND2.intelligentSceneAnalysis=-1
 LAND2.mowingOverlapDistance=0.06
 LAND2.landArea=55.11
+LAND1.returnPathCoordinates=-1
 LAND1.mowingPattern=骞宠绾�
 LAND1.mowingOverlapDistance=0.06
-LAND2.updateTime=2025-12-20 12\:24\:28
+LAND2.updateTime=2025-12-20 14\:47\:09
 LAND2.createTime=2025-12-20 12\:24\:28
 LAND1.mowingWidth=34
+LAND2.returnPathCoordinates=-1
+LAND2.angleThreshold=-1
+LAND2.boundaryPointInterval=-1
 LAND2.mowingWidth=34
 LAND1.plannedPath=-5.830841,-2.644443;-12.323966,-4.153883;-12.276978,-4.492026;-6.161845,-3.070456;-6.492848,-3.496470;-12.229991,-4.830169;-12.183003,-5.168312;-6.823852,-3.922484;-7.154855,-4.348497;-12.136016,-5.506455;-12.089028,-5.844598;-7.487144,-4.774810;-7.821079,-5.201505;-12.042040,-6.182741;-11.995053,-6.520885;-8.155014,-5.628200;-8.700347,-6.104039;-11.948065,-6.859028;-11.901077,-7.197171;-10.070186,-6.771548;-11.440025,-7.439057;-11.854090,-7.535314
 LAND1.updateTime=2025-12-19 19\:44\:17
@@ -23,6 +29,8 @@
 LAND2.boundaryOriginalCoordinates=39.831468,116.279941,49.29;39.831465,116.279925,49.33;39.831463,116.279908,49.34;39.831462,116.279891,49.35;39.831461,116.279874,49.33;39.831458,116.279859,49.34;39.831456,116.279843,49.32;39.831454,116.279827,49.32;39.831452,116.279813,49.42;39.831450,116.279798,49.41;39.831448,116.279783,49.36;39.831447,116.279769,49.26;39.831445,116.279757,49.24;39.831445,116.279747,49.38;39.831448,116.279741,49.27;39.831455,116.279736,49.26;39.831463,116.279733,49.26;39.831473,116.279731,49.26;39.831483,116.279729,49.25;39.831491,116.279730,49.26;39.831496,116.279735,49.22;39.831497,116.279748,49.27
 LAND1.boundaryPointInterval=-1
 LAND1.createTime=2025-12-19 18\:31\:53
+LAND2.returnPointCoordinates=-1
+LAND2.mowingTrack=-1
 LAND1.userId=-1
 LAND1.angleThreshold=-1
 LAND2.mowingBladeWidth=0.40
diff --git a/set.properties b/set.properties
index 06130a8..a526d41 100644
--- a/set.properties
+++ b/set.properties
@@ -1,5 +1,5 @@
 #Current work land selection updated
-#Sat Dec 20 12:59:18 GMT+08:00 2025
+#Sat Dec 20 15:10:30 GMT+08:00 2025
 appVersion=-1
 simCardNumber=-1
 currentWorkLandNumber=LAND2
@@ -7,8 +7,8 @@
 boundaryLengthVisible=false
 idleTrailDurationSeconds=60
 handheldMarkerId=1872
-viewCenterX=0.99
-viewCenterY=6.06
+viewCenterX=5.62
+viewCenterY=6.22
 manualBoundaryDrawingMode=false
 mowerId=860
 serialPortName=COM15
diff --git a/src/dikuai/Dikuai.java b/src/dikuai/Dikuai.java
index d206242..a21456c 100644
--- a/src/dikuai/Dikuai.java
+++ b/src/dikuai/Dikuai.java
@@ -23,6 +23,8 @@
     private String plannedPath;
     // 杩斿洖鐐瑰潗鏍�
     private String returnPointCoordinates;
+    // 寰�杩旇矾寰勫潗鏍囷紙鍓茶崏鏈哄畬鎴愬壊鑽変綔涓氳繑鍥炵殑璺緞鍧愭爣锛屾牸寮忥細X1,Y1;X2,Y2;...;XN,YN锛�
+    private String returnPathCoordinates;
     // 杈圭晫鐐归棿闅�
     private String boundaryPointInterval;
     // 瑙掑害闃堝��
@@ -100,6 +102,7 @@
                 dikuai.boundaryCoordinates = landProps.getProperty("boundaryCoordinates", "-1");
                 dikuai.plannedPath = landProps.getProperty("plannedPath", "-1");
                 dikuai.returnPointCoordinates = landProps.getProperty("returnPointCoordinates", "-1");
+                dikuai.returnPathCoordinates = landProps.getProperty("returnPathCoordinates", "-1");
                 dikuai.boundaryPointInterval = landProps.getProperty("boundaryPointInterval", "-1");
                 dikuai.angleThreshold = landProps.getProperty("angleThreshold", "-1");
                 dikuai.intelligentSceneAnalysis = landProps.getProperty("intelligentSceneAnalysis", "-1");
@@ -204,6 +207,9 @@
             case "returnPointCoordinates":
                 this.returnPointCoordinates = value;
                 return true;
+            case "returnPathCoordinates":
+                this.returnPathCoordinates = value;
+                return true;
             case "boundaryPointInterval":
                 this.boundaryPointInterval = value;
                 return true;
@@ -267,6 +273,7 @@
             if (dikuai.boundaryCoordinates != null) properties.setProperty(landNumber + ".boundaryCoordinates", dikuai.boundaryCoordinates);
             if (dikuai.plannedPath != null) properties.setProperty(landNumber + ".plannedPath", dikuai.plannedPath);
             if (dikuai.returnPointCoordinates != null) properties.setProperty(landNumber + ".returnPointCoordinates", dikuai.returnPointCoordinates);
+            if (dikuai.returnPathCoordinates != null) properties.setProperty(landNumber + ".returnPathCoordinates", dikuai.returnPathCoordinates);
             if (dikuai.boundaryPointInterval != null) properties.setProperty(landNumber + ".boundaryPointInterval", dikuai.boundaryPointInterval);
             if (dikuai.angleThreshold != null) properties.setProperty(landNumber + ".angleThreshold", dikuai.angleThreshold);
             if (dikuai.intelligentSceneAnalysis != null) properties.setProperty(landNumber + ".intelligentSceneAnalysis", dikuai.intelligentSceneAnalysis);
@@ -351,6 +358,14 @@
         this.returnPointCoordinates = returnPointCoordinates;
     }
 
+    public String getReturnPathCoordinates() {
+        return returnPathCoordinates;
+    }
+
+    public void setReturnPathCoordinates(String returnPathCoordinates) {
+        this.returnPathCoordinates = returnPathCoordinates;
+    }
+
     public String getBoundaryPointInterval() {
         return boundaryPointInterval;
     }
@@ -465,6 +480,7 @@
                 ", boundaryCoordinates='" + boundaryCoordinates + '\'' +
                 ", plannedPath='" + plannedPath + '\'' +
                 ", returnPointCoordinates='" + returnPointCoordinates + '\'' +
+                ", returnPathCoordinates='" + returnPathCoordinates + '\'' +
                 ", boundaryPointInterval='" + boundaryPointInterval + '\'' +
                 ", angleThreshold='" + angleThreshold + '\'' +
                 ", intelligentSceneAnalysis='" + intelligentSceneAnalysis + '\'' +
diff --git a/src/dikuai/Dikuaiguanli.java b/src/dikuai/Dikuaiguanli.java
index 009cc73..740ccf8 100644
--- a/src/dikuai/Dikuaiguanli.java
+++ b/src/dikuai/Dikuaiguanli.java
@@ -11,8 +11,6 @@
 import java.io.IOException;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
-import ui.UIConfig;
-import ui.UIUtils;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Map;
@@ -30,6 +28,9 @@
 import zhuye.MapRenderer;
 import zhuye.Shouye;
 import zhuye.Coordinate;
+import zhuye.buttonset;
+import zhuye.Fuzhibutton;
+import zhuye.Lookbutton;
 import gecaoji.Device;
 
 /**
@@ -314,10 +315,14 @@
 		contentPanel.add(mowingSafetyDistancePanel);
 		contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
 
-		// 杩斿洖鐐瑰潗鏍囷紙甯︿慨鏀规寜閽級
-		contentPanel.add(createCardInfoItemWithButton("杩斿洖鐐瑰潗鏍�:",
-			getDisplayValue(dikuai.getReturnPointCoordinates(), "鏈缃�"),
-			"淇敼", e -> editReturnPoint(dikuai)));
+		// 寰�杩旂偣璺緞锛堝甫鏌ョ湅鍥炬爣鎸夐挳锛�
+		JPanel returnPathPanel = createCardInfoItemWithButton("寰�杩旂偣璺緞:",
+			getDisplayValue(dikuai.getReturnPathCoordinates(), "鏈缃�"),
+			createViewButton(e -> editReturnPath(dikuai)));
+		configureInteractiveLabel(getInfoItemTitleLabel(returnPathPanel),
+			() -> editReturnPath(dikuai),
+			"鐐瑰嚮鏌ョ湅/缂栬緫寰�杩旂偣璺緞");
+		contentPanel.add(returnPathPanel);
 	contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
 
 		ObstacleSummary obstacleSummary = getObstacleSummaryFromCache(dikuai.getLandNumber());
@@ -776,9 +781,80 @@
 		contentPanel.add(scrollPane, BorderLayout.CENTER);
 
 		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
-		JButton okButton = new JButton("纭畾");
-		JButton cancelButton = new JButton("鍙栨秷");
-		JButton copyButton = new JButton("澶嶅埗");
+		
+		// 鍒ゆ柇鏄惁鏄線杩旂偣璺緞瀵硅瘽妗�
+		boolean isReturnPathDialog = title != null && title.contains("寰�杩旂偣璺緞");
+		JButton okButton;
+		JButton cancelButton;
+		JButton copyButton;
+		
+		if (isReturnPathDialog) {
+			// 寰�杩旂偣璺緞瀵硅瘽妗嗭細浣跨敤 buttonset 椋庢牸鐨勭‘瀹氭寜閽紝鍥炬爣鎸夐挳
+			okButton = buttonset.createStyledButton("鍘荤粯鍒�", new Color(70, 130, 220));
+			
+			// 鍙栨秷鎸夐挳浣跨敤 closepage.png 鍥炬爣
+			cancelButton = new JButton();
+			ImageIcon closeIcon = loadIcon("image/closepage.png", 25, 25);
+			if (closeIcon != null) {
+				cancelButton.setIcon(closeIcon);
+			} else {
+				cancelButton.setText("鍏抽棴");
+			}
+			cancelButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 11));
+			cancelButton.setForeground(PRIMARY_COLOR);
+			cancelButton.setBorder(BorderFactory.createEmptyBorder());
+			cancelButton.setContentAreaFilled(false);
+			cancelButton.setFocusPainted(false);
+			cancelButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+			cancelButton.addMouseListener(new MouseAdapter() {
+				public void mouseEntered(MouseEvent e) { cancelButton.setOpaque(true); cancelButton.setBackground(new Color(255, 240, 240)); }
+				public void mouseExited(MouseEvent e) { cancelButton.setOpaque(false); }
+			});
+			
+			// 浣跨敤 Fuzhibutton 鍒涘缓澶嶅埗鎸夐挳
+			copyButton = Fuzhibutton.createCopyButton(
+				(java.util.function.Supplier<String>) () -> {
+					String text = textArea.getText();
+					if (text == null) {
+						text = "";
+					}
+					String trimmed = text.trim();
+					if (trimmed.isEmpty() || "-1".equals(trimmed)) {
+						return null; // 杩斿洖null浼氳Е鍙�"鏈缃澶嶅埗鐨勫唴瀹�"鎻愮ず
+					}
+					return text;
+				},
+				"澶嶅埗" + title,
+				new Color(230, 250, 240)
+			);
+			
+		} else {
+			// 鍏朵粬瀵硅瘽妗嗕繚鎸佸師鏈夋牱寮�
+			okButton = new JButton("纭畾");
+			cancelButton = new JButton("鍙栨秷");
+			copyButton = new JButton("澶嶅埗");
+			
+			// 鍏朵粬瀵硅瘽妗嗙殑澶嶅埗鎸夐挳閫昏緫
+			copyButton.addActionListener(e -> {
+				String text = textArea.getText();
+				if (text == null) {
+					text = "";
+				}
+				String trimmed = text.trim();
+				if (trimmed.isEmpty() || "-1".equals(trimmed)) {
+					JOptionPane.showMessageDialog(dialog, title + " 鏈缃�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+					return;
+				}
+				try {
+					StringSelection selection = new StringSelection(text);
+					Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+					clipboard.setContents(selection, selection);
+					JOptionPane.showMessageDialog(dialog, title + " 宸插鍒跺埌鍓创鏉�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
+				} catch (Exception ex) {
+					JOptionPane.showMessageDialog(dialog, "澶嶅埗澶辫触: " + ex.getMessage(), "閿欒", JOptionPane.ERROR_MESSAGE);
+				}
+			});
+		}
 
 		final boolean[] confirmed = new boolean[] {false};
 		final String[] resultHolder = new String[1];
@@ -791,26 +867,6 @@
 
 		cancelButton.addActionListener(e -> dialog.dispose());
 
-		copyButton.addActionListener(e -> {
-			String text = textArea.getText();
-			if (text == null) {
-				text = "";
-			}
-			String trimmed = text.trim();
-			if (trimmed.isEmpty() || "-1".equals(trimmed)) {
-				JOptionPane.showMessageDialog(dialog, title + " 鏈缃�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
-				return;
-			}
-			try {
-				StringSelection selection = new StringSelection(text);
-				Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
-				clipboard.setContents(selection, selection);
-				JOptionPane.showMessageDialog(dialog, title + " 宸插鍒跺埌鍓创鏉�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
-			} catch (Exception ex) {
-				JOptionPane.showMessageDialog(dialog, "澶嶅埗澶辫触: " + ex.getMessage(), "閿欒", JOptionPane.ERROR_MESSAGE);
-			}
-		});
-
 		buttonPanel.add(okButton);
 		buttonPanel.add(cancelButton);
 		buttonPanel.add(copyButton);
@@ -819,6 +875,18 @@
 		dialog.setContentPane(contentPanel);
 		dialog.getRootPane().setDefaultButton(okButton);
 		dialog.pack();
+		
+		// 濡傛灉鏄線杩旂偣璺緞瀵硅瘽妗嗭紝璁剧疆瀹藉害涓洪椤电殑90%锛岄珮搴︿繚鎸佷笉鍙�
+		if (isReturnPathDialog) {
+			Shouye shouye = Shouye.getInstance();
+			if (shouye != null && shouye.getWidth() > 0) {
+				int homeWidth = shouye.getWidth();
+				int dialogWidth = (int)(homeWidth * 0.9);
+				Dimension currentSize = dialog.getSize();
+				dialog.setSize(dialogWidth, currentSize.height);
+			}
+		}
+		
 		dialog.setLocationRelativeTo(this);
 		dialog.setVisible(true);
 
@@ -1620,27 +1688,8 @@
 	}
 
 	private JButton createViewButton(ActionListener listener) {
-		JButton btn = new JButton();
-		ImageIcon lookIcon = loadIcon("image/look.png", 25, 25);
-		if (lookIcon != null) {
-			btn.setIcon(lookIcon);
-		} else {
-			btn.setText("鏌ョ湅");
-		}
-		btn.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 11));
-		btn.setForeground(PRIMARY_COLOR);
-		btn.setBorder(BorderFactory.createEmptyBorder());
-		btn.setContentAreaFilled(false);
-		btn.setFocusPainted(false);
-		btn.setCursor(new Cursor(Cursor.HAND_CURSOR));
-		btn.addMouseListener(new MouseAdapter() {
-			public void mouseEntered(MouseEvent e) { btn.setOpaque(true); btn.setBackground(new Color(230, 250, 240)); }
-			public void mouseExited(MouseEvent e) { btn.setOpaque(false); }
-		});
-		if (listener != null) {
-			btn.addActionListener(listener);
-		}
-		return btn;
+		// 浣跨敤 Lookbutton 绫诲垱寤烘煡鐪嬫寜閽�
+		return Lookbutton.createViewButton(listener, new Color(230, 250, 240));
 	}
 
 	private JButton createPrimaryFooterButton(String text) {
@@ -1861,13 +1910,21 @@
 		});
 	}
 
-	private void editReturnPoint(Dikuai dikuai) {
-		FanhuiDialog fd = new FanhuiDialog(SwingUtilities.getWindowAncestor(this), dikuai);
-		fd.setVisible(true);
-		// 濡傛灉瀵硅瘽妗嗗凡鏇存柊鏁版嵁锛屽埛鏂版樉绀�
-		if (fd.isUpdated()) {
-			loadDikuaiData();
+	private void editReturnPath(Dikuai dikuai) {
+		if (dikuai == null) {
+			return;
 		}
+		String edited = promptCoordinateEditing("鏌ョ湅 / 缂栬緫寰�杩旂偣璺緞", dikuai.getReturnPathCoordinates());
+		if (edited == null) {
+			return;
+		}
+		String normalized = normalizeCoordinateInput(edited);
+		if (!saveFieldAndRefresh(dikuai, "returnPathCoordinates", normalized)) {
+			JOptionPane.showMessageDialog(this, "鏃犳硶鏇存柊寰�杩旂偣璺緞", "閿欒", JOptionPane.ERROR_MESSAGE);
+			return;
+		}
+		String message = "-1".equals(normalized) ? "寰�杩旂偣璺緞宸叉竻绌�" : "寰�杩旂偣璺緞宸叉洿鏂�";
+		JOptionPane.showMessageDialog(this, message, "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
 	}
 
 	/**
diff --git a/src/dikuai/addzhangaiwu.java b/src/dikuai/addzhangaiwu.java
index 6c69177..662c5c1 100644
--- a/src/dikuai/addzhangaiwu.java
+++ b/src/dikuai/addzhangaiwu.java
@@ -1359,7 +1359,7 @@
         }
         if (!configMap.isEmpty()) {
             List<ExistingObstacle> remaining = new ArrayList<>(configMap.values());
-            remaining.sort(Comparator.comparing(ExistingObstacle::getName, String.CASE_INSENSITIVE_ORDER));
+            remaining.sort((a, b) -> String.CASE_INSENSITIVE_ORDER.compare(a.getName(), b.getName()));
             result.addAll(remaining);
         }
         if (result.isEmpty()) {
diff --git a/src/lujing/MowingPathGenerationPage.java b/src/lujing/MowingPathGenerationPage.java
index 73a8fde..c55639b 100644
--- a/src/lujing/MowingPathGenerationPage.java
+++ b/src/lujing/MowingPathGenerationPage.java
@@ -3,8 +3,6 @@
 import javax.swing.*;
 import javax.swing.SwingUtilities;
 import java.awt.*;
-import java.awt.datatransfer.Clipboard;
-import java.awt.datatransfer.StringSelection;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.math.BigDecimal;
@@ -23,6 +21,7 @@
 import org.locationtech.jts.geom.Coordinate;
 import gecaoji.Device;
 import java.util.Locale;
+import zhuye.Fuzhibutton;
 
 /**
  * 鐢熸垚鍓茶崏璺緞椤甸潰
@@ -762,15 +761,18 @@
         titleLabel.setForeground(TEXT_COLOR);
         titlePanel.add(titleLabel, BorderLayout.WEST);
         
-        // 鍒涘缓澶嶅埗鎸夐挳
-        JButton copyButton = createCopyButton(title, () -> {
-            String text = textArea.getText();
-            if (text == null || text.trim().isEmpty()) {
-                JOptionPane.showMessageDialog(this, title + " 鏈缃�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
-                return;
-            }
-            copyToClipboard(text, title);
-        });
+        // 鍒涘缓澶嶅埗鎸夐挳锛堜娇鐢� Fuzhibutton锛�
+        JButton copyButton = Fuzhibutton.createCopyButton(
+            () -> {
+                String text = textArea.getText();
+                if (text == null || text.trim().isEmpty() || "-1".equals(text.trim())) {
+                    return null; // 杩斿洖null浼氳Е鍙�"鏈缃�"鎻愮ず
+                }
+                return text;
+            },
+            "澶嶅埗" + title,
+            new Color(230, 250, 240)
+        );
         titlePanel.add(copyButton, BorderLayout.EAST);
         
         section.add(titlePanel, BorderLayout.NORTH);
@@ -812,15 +814,18 @@
         titleLabel.setForeground(TEXT_COLOR);
         titlePanel.add(titleLabel, BorderLayout.WEST);
         
-        // 鍒涘缓澶嶅埗鎸夐挳
-        JButton copyButton = createCopyButton(title, () -> {
-            String text = textField.getText();
-            if (text == null || text.trim().isEmpty()) {
-                JOptionPane.showMessageDialog(this, title + " 鏈缃�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
-                return;
-            }
-            copyToClipboard(text, title);
-        });
+        // 鍒涘缓澶嶅埗鎸夐挳锛堜娇鐢� Fuzhibutton锛�
+        JButton copyButton = Fuzhibutton.createCopyButton(
+            () -> {
+                String text = textField.getText();
+                if (text == null || text.trim().isEmpty() || "-1".equals(text.trim())) {
+                    return null; // 杩斿洖null浼氳Е鍙�"鏈缃�"鎻愮ず
+                }
+                return text;
+            },
+            "澶嶅埗" + title,
+            new Color(230, 250, 240)
+        );
         titlePanel.add(copyButton, BorderLayout.EAST);
         
         section.add(titlePanel, BorderLayout.NORTH);
@@ -962,80 +967,6 @@
         return "parallel";
     }
     
-    /**
-     * 鍒涘缓澶嶅埗鎸夐挳
-     */
-    private JButton createCopyButton(String title, Runnable copyAction) {
-        JButton copyButton = new JButton();
-        Font titleFont = new Font("寰蒋闆呴粦", Font.BOLD, 14);
-        FontMetrics metrics = getFontMetrics(titleFont);
-        int iconSize = metrics.getHeight(); // 浣跨敤鏍囬瀛椾綋楂樺害浣滀负鍥炬爣澶у皬
-        
-        // 鍔犺浇澶嶅埗鍥炬爣
-        ImageIcon copyIcon = null;
-        ImageIcon successIcon = null;
-        try {
-            ImageIcon originalCopyIcon = new ImageIcon("image/fuzhi.png");
-            Image scaledCopyImage = originalCopyIcon.getImage().getScaledInstance(iconSize, iconSize, Image.SCALE_SMOOTH);
-            copyIcon = new ImageIcon(scaledCopyImage);
-            
-            // 鍔犺浇鎴愬姛鍥炬爣
-            ImageIcon originalSuccessIcon = new ImageIcon("image/fuzhisucc.png");
-            Image scaledSuccessImage = originalSuccessIcon.getImage().getScaledInstance(iconSize, iconSize, Image.SCALE_SMOOTH);
-            successIcon = new ImageIcon(scaledSuccessImage);
-        } catch (Exception e) {
-            // 濡傛灉鍥剧墖鍔犺浇澶辫触锛屼娇鐢ㄦ枃鏈�
-            copyButton.setText("澶嶅埗");
-            copyButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
-            System.err.println("鏃犳硶鍔犺浇澶嶅埗鍥炬爣: " + e.getMessage());
-        }
-        
-        final ImageIcon finalCopyIcon = copyIcon;
-        final ImageIcon finalSuccessIcon = successIcon;
-        
-        copyButton.setIcon(finalCopyIcon);
-        copyButton.setContentAreaFilled(false);
-        copyButton.setBorder(null);
-        copyButton.setFocusPainted(false);
-        copyButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
-        copyButton.setToolTipText("澶嶅埗" + title);
-        
-        // 娣诲姞鐐瑰嚮浜嬩欢
-        copyButton.addActionListener(e -> {
-            copyAction.run();
-            // 澶嶅埗鎴愬姛鍚庡垏鎹㈠浘鏍�
-            if (finalSuccessIcon != null) {
-                copyButton.setIcon(finalSuccessIcon);
-                // 1绉掑悗鎭㈠鍘熷浘鏍�
-                Timer timer = new Timer(1000, evt -> {
-                    copyButton.setIcon(finalCopyIcon);
-                });
-                timer.setRepeats(false);
-                timer.start();
-            }
-        });
-        
-        return copyButton;
-    }
-    
-    /**
-     * 澶嶅埗鏂囨湰鍒板壀璐存澘
-     */
-    private void copyToClipboard(String text, String title) {
-        if (text == null || text.trim().isEmpty()) {
-            JOptionPane.showMessageDialog(this, title + " 鏈缃�", "鎻愮ず", JOptionPane.INFORMATION_MESSAGE);
-            return;
-        }
-        
-        try {
-            StringSelection selection = new StringSelection(text);
-            Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
-            clipboard.setContents(selection, selection);
-            // 鍘绘帀鎴愬姛鎻愮ず寮圭獥
-        } catch (Exception ex) {
-            JOptionPane.showMessageDialog(this, "澶嶅埗澶辫触: " + ex.getMessage(), "閿欒", JOptionPane.ERROR_MESSAGE);
-        }
-    }
 }
 
 
diff --git a/src/zhuye/Fuzhibutton.java b/src/zhuye/Fuzhibutton.java
new file mode 100644
index 0000000..340977f
--- /dev/null
+++ b/src/zhuye/Fuzhibutton.java
@@ -0,0 +1,270 @@
+package zhuye;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+/**
+ * 澶嶅埗鎸夐挳宸ュ叿绫�
+ * 鎻愪緵缁熶竴鐨勫鍒舵寜閽垱寤烘柟娉曪紝榛樿鏄剧ず澶嶅埗鍥炬爣锛屽鍒舵垚鍔熷悗鏄剧ず鎴愬姛鍥炬爣
+ */
+public final class Fuzhibutton {
+    
+    // 榛樿鍥炬爣澶у皬
+    private static final int DEFAULT_ICON_SIZE = 18;
+    // 鎴愬姛鍥炬爣鏄剧ず鏃堕暱锛堟绉掞級
+    private static final int SUCCESS_ICON_DURATION = 1500;
+    
+    private Fuzhibutton() {
+        // 宸ュ叿绫讳笉闇�瑕佸疄渚嬪寲
+    }
+    
+    /**
+     * 鍒涘缓澶嶅埗鎸夐挳
+     * 榛樿鏄剧ず image/fuzhi.png 鍥炬爣锛屽鍒舵垚鍔熷悗鏄剧ず image/fuzhisucc.png 鍥炬爣
+     * 
+     * @param textToCopy 瑕佸鍒剁殑鏂囨湰鍐呭锛堝鏋滀负null锛屽垯闇�瑕佸湪鐐瑰嚮鏃堕�氳繃鍥炶皟鎻愪緵锛�
+     * @param tooltip 鎸夐挳鎻愮ず鏂囨湰
+     * @param hoverColor 榧犳爣鎮仠鏃剁殑鑳屾櫙棰滆壊锛堝鏋滀负null锛屼娇鐢ㄩ粯璁ら鑹诧級
+     * @return 閰嶇疆濂界殑澶嶅埗鎸夐挳
+     */
+    public static JButton createCopyButton(String textToCopy, String tooltip, Color hoverColor) {
+        JButton copyButton = new JButton();
+        
+        // 鍔犺浇鍥炬爣
+        ImageIcon copyIcon = loadIcon("image/fuzhi.png", DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
+        ImageIcon successIcon = loadIcon("image/fuzhisucc.png", DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
+        
+        final ImageIcon finalCopyIcon = copyIcon;
+        final ImageIcon finalSuccessIcon = successIcon;
+        
+        // 璁剧疆鎸夐挳鍥炬爣
+        if (copyIcon != null) {
+            copyButton.setIcon(copyIcon);
+        } else {
+            copyButton.setText("澶嶅埗");
+        }
+        
+        // 璁剧疆鎸夐挳鏍峰紡
+        copyButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 11));
+        copyButton.setForeground(new Color(46, 139, 87)); // PRIMARY_COLOR
+        copyButton.setBorder(BorderFactory.createEmptyBorder());
+        copyButton.setContentAreaFilled(false);
+        copyButton.setFocusPainted(false);
+        copyButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        
+        // 璁剧疆鎻愮ず鏂囨湰涓�"澶嶅埗淇℃伅"
+        copyButton.setToolTipText("澶嶅埗淇℃伅");
+        
+        // 璁剧疆鎮仠鏁堟灉
+        final Color finalHoverColor = hoverColor != null ? hoverColor : new Color(230, 250, 240);
+        copyButton.addMouseListener(new MouseAdapter() {
+            public void mouseEntered(MouseEvent e) {
+                copyButton.setOpaque(true);
+                copyButton.setBackground(finalHoverColor);
+            }
+            
+            public void mouseExited(MouseEvent e) {
+                copyButton.setOpaque(false);
+            }
+        });
+        
+        // 娣诲姞澶嶅埗鍔熻兘
+        copyButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                String text = textToCopy;
+                
+                // 濡傛灉 textToCopy 涓� null锛屽皾璇曚粠鐖剁粍浠惰幏鍙栨枃鏈紙濡� JTextArea锛�
+                if (text == null) {
+                    // 灏濊瘯浠庣埗缁勪欢涓煡鎵� JTextArea
+                    Container parent = copyButton.getParent();
+                    while (parent != null) {
+                        if (parent instanceof JDialog) {
+                            Component[] components = ((JDialog) parent).getContentPane().getComponents();
+                            text = findTextFromComponents(components);
+                            break;
+                        } else if (parent instanceof JFrame) {
+                            Component[] components = ((JFrame) parent).getContentPane().getComponents();
+                            text = findTextFromComponents(components);
+                            break;
+                        }
+                        parent = parent.getParent();
+                    }
+                }
+                
+                // 濡傛灉娌℃湁闇�瑕佸鍒剁殑鍐呭锛岀洿鎺ヨ繑鍥烇紝涓嶆樉绀哄脊绐楁彁绀�
+                if (text == null || text.trim().isEmpty() || "-1".equals(text.trim())) {
+                    return;
+                }
+                
+                try {
+                    StringSelection selection = new StringSelection(text);
+                    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+                    clipboard.setContents(selection, selection);
+                    
+                    // 澶嶅埗鎴愬姛鍚庡垏鎹负鎴愬姛鍥炬爣
+                    if (finalSuccessIcon != null) {
+                        copyButton.setIcon(finalSuccessIcon);
+                        // 1.5绉掑悗鎭㈠涓哄師濮嬪浘鏍�
+                        Timer timer = new Timer(SUCCESS_ICON_DURATION, evt -> {
+                            if (finalCopyIcon != null) {
+                                copyButton.setIcon(finalCopyIcon);
+                            }
+                        });
+                        timer.setRepeats(false);
+                        timer.start();
+                    }
+                } catch (Exception ex) {
+                    JOptionPane.showMessageDialog(
+                        SwingUtilities.getWindowAncestor(copyButton),
+                        "澶嶅埗澶辫触: " + ex.getMessage(),
+                        "閿欒",
+                        JOptionPane.ERROR_MESSAGE
+                    );
+                }
+            }
+        });
+        
+        return copyButton;
+    }
+    
+    /**
+     * 鍒涘缓澶嶅埗鎸夐挳锛堜娇鐢ㄥ洖璋冨嚱鏁版彁渚涜澶嶅埗鐨勬枃鏈級
+     * 
+     * @param copyAction 澶嶅埗鍔ㄤ綔鍥炶皟锛岃繑鍥炶澶嶅埗鐨勬枃鏈�
+     * @param tooltip 鎸夐挳鎻愮ず鏂囨湰
+     * @param hoverColor 榧犳爣鎮仠鏃剁殑鑳屾櫙棰滆壊锛堝鏋滀负null锛屼娇鐢ㄩ粯璁ら鑹诧級
+     * @return 閰嶇疆濂界殑澶嶅埗鎸夐挳
+     */
+    public static JButton createCopyButton(java.util.function.Supplier<String> copyAction, String tooltip, Color hoverColor) {
+        JButton copyButton = new JButton();
+        
+        // 鍔犺浇鍥炬爣
+        ImageIcon copyIcon = loadIcon("image/fuzhi.png", DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
+        ImageIcon successIcon = loadIcon("image/fuzhisucc.png", DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
+        
+        final ImageIcon finalCopyIcon = copyIcon;
+        final ImageIcon finalSuccessIcon = successIcon;
+        
+        // 璁剧疆鎸夐挳鍥炬爣
+        if (copyIcon != null) {
+            copyButton.setIcon(copyIcon);
+        } else {
+            copyButton.setText("澶嶅埗");
+        }
+        
+        // 璁剧疆鎸夐挳鏍峰紡
+        copyButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 11));
+        copyButton.setForeground(new Color(46, 139, 87)); // PRIMARY_COLOR
+        copyButton.setBorder(BorderFactory.createEmptyBorder());
+        copyButton.setContentAreaFilled(false);
+        copyButton.setFocusPainted(false);
+        copyButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        
+        // 璁剧疆鎻愮ず鏂囨湰涓�"澶嶅埗淇℃伅"
+        copyButton.setToolTipText("澶嶅埗淇℃伅");
+        
+        // 璁剧疆鎮仠鏁堟灉
+        final Color finalHoverColor = hoverColor != null ? hoverColor : new Color(230, 250, 240);
+        copyButton.addMouseListener(new MouseAdapter() {
+            public void mouseEntered(MouseEvent e) {
+                copyButton.setOpaque(true);
+                copyButton.setBackground(finalHoverColor);
+            }
+            
+            public void mouseExited(MouseEvent e) {
+                copyButton.setOpaque(false);
+            }
+        });
+        
+        // 娣诲姞澶嶅埗鍔熻兘
+        copyButton.addActionListener(new ActionListener() {
+            @Override
+            public void actionPerformed(ActionEvent e) {
+                String text = copyAction != null ? copyAction.get() : null;
+                
+                // 濡傛灉娌℃湁闇�瑕佸鍒剁殑鍐呭锛岀洿鎺ヨ繑鍥烇紝涓嶆樉绀哄脊绐楁彁绀�
+                if (text == null || text.trim().isEmpty() || "-1".equals(text.trim())) {
+                    return;
+                }
+                
+                try {
+                    StringSelection selection = new StringSelection(text);
+                    Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+                    clipboard.setContents(selection, selection);
+                    
+                    // 澶嶅埗鎴愬姛鍚庡垏鎹负鎴愬姛鍥炬爣
+                    if (finalSuccessIcon != null) {
+                        copyButton.setIcon(finalSuccessIcon);
+                        // 1.5绉掑悗鎭㈠涓哄師濮嬪浘鏍�
+                        Timer timer = new Timer(SUCCESS_ICON_DURATION, evt -> {
+                            if (finalCopyIcon != null) {
+                                copyButton.setIcon(finalCopyIcon);
+                            }
+                        });
+                        timer.setRepeats(false);
+                        timer.start();
+                    }
+                } catch (Exception ex) {
+                    JOptionPane.showMessageDialog(
+                        SwingUtilities.getWindowAncestor(copyButton),
+                        "澶嶅埗澶辫触: " + ex.getMessage(),
+                        "閿欒",
+                        JOptionPane.ERROR_MESSAGE
+                    );
+                }
+            }
+        });
+        
+        return copyButton;
+    }
+    
+    /**
+     * 鍔犺浇鍥炬爣骞惰皟鏁村ぇ灏�
+     * 
+     * @param path 鍥炬爣璺緞
+     * @param width 鐩爣瀹藉害
+     * @param height 鐩爣楂樺害
+     * @return 璋冩暣澶у皬鍚庣殑鍥炬爣锛屽鏋滃姞杞藉け璐ヨ繑鍥瀗ull
+     */
+    private static ImageIcon loadIcon(String path, int width, int height) {
+        try {
+            ImageIcon rawIcon = new ImageIcon(path);
+            if (rawIcon.getIconWidth() <= 0 || rawIcon.getIconHeight() <= 0) {
+                return null;
+            }
+            Image scaled = rawIcon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
+            return new ImageIcon(scaled);
+        } catch (Exception ex) {
+            System.err.println("鏃犳硶鍔犺浇鍥炬爣: " + path + " - " + ex.getMessage());
+            return null;
+        }
+    }
+    
+    /**
+     * 浠庣粍浠舵爲涓煡鎵� JTextArea 骞惰幏鍙栧叾鏂囨湰
+     * 
+     * @param components 缁勪欢鏁扮粍
+     * @return 鎵惧埌鐨勬枃鏈紝濡傛灉鏈壘鍒拌繑鍥瀗ull
+     */
+    private static String findTextFromComponents(Component[] components) {
+        for (Component comp : components) {
+            if (comp instanceof JTextArea) {
+                return ((JTextArea) comp).getText();
+            } else if (comp instanceof Container) {
+                String text = findTextFromComponents(((Container) comp).getComponents());
+                if (text != null) {
+                    return text;
+                }
+            }
+        }
+        return null;
+    }
+}
+
diff --git a/src/zhuye/Lookbutton.java b/src/zhuye/Lookbutton.java
new file mode 100644
index 0000000..aebfb9e
--- /dev/null
+++ b/src/zhuye/Lookbutton.java
@@ -0,0 +1,107 @@
+package zhuye;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+
+/**
+ * 鏌ョ湅鎸夐挳宸ュ叿绫�
+ * 鎻愪緵缁熶竴鐨勬煡鐪嬫寜閽垱寤烘柟娉曪紝榛樿鏄剧ず鏌ョ湅鍥炬爣锛岀偣鍑绘寜閽墽琛屽搴旂殑鎿嶄綔
+ */
+public final class Lookbutton {
+    
+    // 榛樿鍥炬爣澶у皬
+    private static final int DEFAULT_ICON_SIZE =25;
+    
+    private Lookbutton() {
+        // 宸ュ叿绫讳笉闇�瑕佸疄渚嬪寲
+    }
+    
+    /**
+     * 鍒涘缓鏌ョ湅鎸夐挳
+     * 榛樿鏄剧ず image/look.png 鍥炬爣锛岀偣鍑绘寜閽墽琛屼紶鍏ョ殑鎿嶄綔
+     * 
+     * @param listener 鎸夐挳鐐瑰嚮浜嬩欢鐩戝惉鍣紝褰撴寜閽鐐瑰嚮鏃舵墽琛�
+     * @param hoverColor 榧犳爣鎮仠鏃剁殑鑳屾櫙棰滆壊锛堝鏋滀负null锛屼娇鐢ㄩ粯璁ら鑹诧級
+     * @return 閰嶇疆濂界殑鏌ョ湅鎸夐挳
+     */
+    public static JButton createViewButton(ActionListener listener, Color hoverColor) {
+        JButton viewButton = new JButton();
+        
+        // 鍔犺浇鍥炬爣
+        ImageIcon lookIcon = loadIcon("image/look.png", DEFAULT_ICON_SIZE, DEFAULT_ICON_SIZE);
+        
+        // 璁剧疆鎸夐挳鍥炬爣
+        if (lookIcon != null) {
+            viewButton.setIcon(lookIcon);
+        } else {
+            viewButton.setText("鏌ョ湅");
+        }
+        
+        // 璁剧疆鎸夐挳鏍峰紡
+        viewButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 11));
+        viewButton.setForeground(new Color(46, 139, 87)); // PRIMARY_COLOR
+        viewButton.setBorder(BorderFactory.createEmptyBorder());
+        viewButton.setContentAreaFilled(false);
+        viewButton.setFocusPainted(false);
+        viewButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        
+        // 璁剧疆鎻愮ず鏂囨湰涓�"鐐瑰嚮鏌ョ湅"
+        viewButton.setToolTipText("鐐瑰嚮鏌ョ湅");
+        
+        // 璁剧疆鎮仠鏁堟灉
+        final Color finalHoverColor = hoverColor != null ? hoverColor : new Color(230, 250, 240);
+        viewButton.addMouseListener(new MouseAdapter() {
+            public void mouseEntered(MouseEvent e) {
+                viewButton.setOpaque(true);
+                viewButton.setBackground(finalHoverColor);
+            }
+            
+            public void mouseExited(MouseEvent e) {
+                viewButton.setOpaque(false);
+            }
+        });
+        
+        // 娣诲姞鐐瑰嚮浜嬩欢
+        if (listener != null) {
+            viewButton.addActionListener(listener);
+        }
+        
+        return viewButton;
+    }
+    
+    /**
+     * 鍒涘缓鏌ョ湅鎸夐挳锛堜娇鐢ㄩ粯璁ゆ偓鍋滈鑹诧級
+     * 
+     * @param listener 鎸夐挳鐐瑰嚮浜嬩欢鐩戝惉鍣紝褰撴寜閽鐐瑰嚮鏃舵墽琛�
+     * @return 閰嶇疆濂界殑鏌ョ湅鎸夐挳
+     */
+    public static JButton createViewButton(ActionListener listener) {
+        return createViewButton(listener, null);
+    }
+    
+    /**
+     * 鍔犺浇鍥炬爣骞惰皟鏁村ぇ灏�
+     * 
+     * @param path 鍥炬爣璺緞
+     * @param width 鐩爣瀹藉害
+     * @param height 鐩爣楂樺害
+     * @return 璋冩暣澶у皬鍚庣殑鍥炬爣锛屽鏋滃姞杞藉け璐ヨ繑鍥瀗ull
+     */
+    private static ImageIcon loadIcon(String path, int width, int height) {
+        try {
+            ImageIcon rawIcon = new ImageIcon(path);
+            if (rawIcon.getIconWidth() <= 0 || rawIcon.getIconHeight() <= 0) {
+                return null;
+            }
+            Image scaled = rawIcon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH);
+            return new ImageIcon(scaled);
+        } catch (Exception ex) {
+            System.err.println("鏃犳硶鍔犺浇鍥炬爣: " + path + " - " + ex.getMessage());
+            return null;
+        }
+    }
+}
+
diff --git a/src/zhuye/buttonset.java b/src/zhuye/buttonset.java
index 2d6df18..549a9f5 100644
--- a/src/zhuye/buttonset.java
+++ b/src/zhuye/buttonset.java
@@ -1,6 +1,4 @@
 package zhuye;
-
-import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Cursor;
 import java.awt.Dimension;

--
Gitblit v1.10.0