From c498385fb7e372d13e2ee76d7b54ae2381728082 Mon Sep 17 00:00:00 2001
From: 张世豪 <979909237@qq.com>
Date: 星期三, 17 十二月 2025 19:35:57 +0800
Subject: [PATCH] 新增了测量模式

---
 src/set/Sets.java |  847 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 800 insertions(+), 47 deletions(-)

diff --git a/src/set/Sets.java b/src/set/Sets.java
index d33829b..9a4d8c2 100644
--- a/src/set/Sets.java
+++ b/src/set/Sets.java
@@ -1,40 +1,63 @@
 package set;
+
+import baseStation.BaseStation;
+
+import zhuye.MapRenderer;
+import zhuye.Shouye;
+import zhuye.buttonset;
+import zhuye.celiangmoshi;
 import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
 
 import java.awt.*;
 import java.awt.event.*;
 import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * 璁剧疆瀵硅瘽妗� - 鍙傝�僑houye.java鏍峰紡
  */
 public class Sets extends JDialog {
     private static final long serialVersionUID = 1L;
-    private static final int ROW_HEIGHT = 40;
-    private static final int ROW_SPACING = 25;
+    private static final int ROW_HEIGHT = 50;  // 澧炲姞琛岄珮浠ラ�傚簲鍒嗗壊绾�
+    private static final int ITEM_PADDING = 16;  // 鍒楄〃椤瑰唴杈硅窛
     
     // 涓婚棰滆壊
     private final Color THEME_COLOR;
-    private final Color BACKGROUND_COLOR = new Color(250, 250, 250);
-    private final Color PANEL_BACKGROUND = new Color(255, 255, 255);
-    private final Color BORDER_COLOR = new Color(220, 220, 220);
+    private final Color BACKGROUND_COLOR = new Color(245, 247, 250);  // 鏇存煍鍜岀殑娴呯伆鑹茶儗鏅�
+    private final Color PANEL_BACKGROUND = new Color(255, 255, 255);  // 鐧借壊闈㈡澘
+    private final Color BORDER_COLOR = new Color(233, 236, 239);  // 娴呰竟妗嗚壊
+    private final Color DIVIDER_COLOR = new Color(233, 236, 239);  // 鍒嗗壊绾块鑹�
     
     // 璁剧疆椤圭粍浠�
     private JLabel mowerIdLabel;
+    private JLabel baseStationIdLabel;
+    private JLabel handheldMarkerLabel;
     private JLabel simCardNumberLabel;
+    private JLabel baseStationSimLabel;
     private JLabel firmwareVersionLabel;
     private JLabel appVersionLabel;
+    private JLabel idleTrailDurationLabel;
+    private JLabel boundaryLengthVisibleLabel;
+    private JLabel measurementModeEnabledLabel;
     
     private JButton mowerIdEditBtn;
+    private JButton baseStationIdEditBtn;
+    private JButton handheldEditBtn;
     private JButton checkUpdateBtn;
+    private JButton feedbackButton;
+    private JButton idleTrailEditBtn;
     
     // 鏁版嵁妯″瀷
     private Setsys setData;
+    private final BaseStation baseStation;
     
     public Sets(JFrame parent, Color themeColor) {
         super(parent, "绯荤粺璁剧疆", true);
         this.THEME_COLOR = themeColor;
         this.setData = new Setsys();
+        this.baseStation = new BaseStation();
         initializeUI();
         loadData();
     }
@@ -43,6 +66,7 @@
         super(parent, "绯荤粺璁剧疆", true);
         this.THEME_COLOR = themeColor;
         this.setData = new Setsys();
+        this.baseStation = new BaseStation();
         initializeUI();
         loadData();
     }
@@ -56,70 +80,140 @@
         setLocationRelativeTo(getParent());
         setResizable(false);
         
-        // 鍒涘缓涓诲唴瀹归潰鏉�
+        // 鍒涘缓涓诲唴瀹归潰鏉匡紙浣跨敤鏇存煍鍜岀殑娴呯伆鑹茶儗鏅級
         JPanel mainPanel = new JPanel();
-        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
+        mainPanel.setLayout(new BorderLayout());
         mainPanel.setBackground(BACKGROUND_COLOR);
         mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
         
-        // 鍒涘缓璁剧疆椤归潰鏉�
+        // 鍒涘缓璁剧疆椤归潰鏉匡紙鍦嗚鐧借壊闈㈡澘锛�
         JPanel settingsPanel = createSettingsPanel();
         
         // 娣诲姞缁勪欢鍒颁富闈㈡澘
-        mainPanel.add(settingsPanel);
-        mainPanel.add(Box.createVerticalGlue());
+        mainPanel.add(settingsPanel, BorderLayout.CENTER);
         
         add(mainPanel, BorderLayout.CENTER);
     }
     
     private JPanel createSettingsPanel() {
+        // 鍒涘缓鍦嗚鐧借壊闈㈡澘瀹瑰櫒
+        JPanel container = new JPanel() {
+            @Override
+            protected void paintComponent(Graphics g) {
+                Graphics2D g2d = (Graphics2D) g.create();
+                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+                g2d.setColor(PANEL_BACKGROUND);
+                // 缁樺埗鍦嗚鐭╁舰鑳屾櫙
+                g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 16, 16);
+                g2d.dispose();
+            }
+        };
+        container.setLayout(new BorderLayout());
+        container.setOpaque(false);
+        
+        // 鍐呭闈㈡澘
         JPanel panel = new JPanel();
         panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
-        panel.setBackground(PANEL_BACKGROUND);
-        panel.setBorder(BorderFactory.createCompoundBorder(
-            BorderFactory.createLineBorder(BORDER_COLOR),
-            BorderFactory.createEmptyBorder(20, 20, 20, 20)
-        ));
+        panel.setOpaque(false);
+        panel.setBorder(BorderFactory.createEmptyBorder(8, 0, 8, 0));
         
         // 鍓茶崏鏈虹紪鍙�
         JPanel mowerIdPanel = createSettingItemPanel("鍓茶崏鏈虹紪鍙�", 
             setData.getMowerId() != null ? setData.getMowerId() : "鏈缃�", true);
         mowerIdLabel = (JLabel) mowerIdPanel.getClientProperty("valueLabel");
         mowerIdEditBtn = (JButton) mowerIdPanel.getClientProperty("editButton");
+
+        JPanel baseStationIdPanel = createSettingItemPanel("宸垎鍩哄噯绔欑紪鍙�",
+            resolveBaseStationId(), true);
+        baseStationIdLabel = (JLabel) baseStationIdPanel.getClientProperty("valueLabel");
+        baseStationIdEditBtn = (JButton) baseStationIdPanel.getClientProperty("editButton");
         
+        JPanel handheldPanel = createSettingItemPanel("渚挎惡鎵撶偣鍣ㄧ紪鍙�",
+            setData.getHandheldMarkerId() != null ? setData.getHandheldMarkerId() : "鏈缃�", true);
+        handheldMarkerLabel = (JLabel) handheldPanel.getClientProperty("valueLabel");
+        handheldEditBtn = (JButton) handheldPanel.getClientProperty("editButton");
+
         // 鐗╄仈鍗″彿
-        JPanel simCardPanel = createSettingItemPanel("鐗╄仈鍗″彿", 
+        JPanel simCardPanel = createSettingItemPanel("鍓茶崏鏈虹墿鑱旂綉鍗″彿", 
             setData.getSimCardNumber() != null ? setData.getSimCardNumber() : "鏈缃�", false);
         simCardNumberLabel = (JLabel) simCardPanel.getClientProperty("valueLabel");
+
+        JPanel baseStationSimPanel = createSettingItemPanel("鍩哄噯绔欑墿鑱旂綉鍗″彿",
+            resolveBaseStationSimCard(), false);
+        baseStationSimLabel = (JLabel) baseStationSimPanel.getClientProperty("valueLabel");
         
         // 鍥轰欢鐗堟湰
         JPanel firmwarePanel = createSettingItemPanel("鍥轰欢鐗堟湰", 
             setData.getFirmwareVersion() != null ? setData.getFirmwareVersion() : "鏈缃�", false);
         firmwareVersionLabel = (JLabel) firmwarePanel.getClientProperty("valueLabel");
+
+        JPanel idleTrailPanel = createSettingItemPanel("杞ㄨ抗鎷栧熬鏃堕暱",
+            formatIdleTrailDurationValue(), true);
+        idleTrailDurationLabel = (JLabel) idleTrailPanel.getClientProperty("valueLabel");
+        idleTrailEditBtn = (JButton) idleTrailPanel.getClientProperty("editButton");
+        
+        // 鏄剧ず杈圭晫璺濈璁剧疆椤�
+        JPanel boundaryLengthPanel = createBoundaryLengthPanel();
+        boundaryLengthVisibleLabel = (JLabel) boundaryLengthPanel.getClientProperty("valueLabel");
+        
+        // 寮�鍚祴閲忔ā寮忚缃」
+        JPanel measurementModePanel = createMeasurementModePanel();
+        measurementModeEnabledLabel = (JLabel) measurementModePanel.getClientProperty("valueLabel");
+
+        JPanel feedbackPanel = createFeedbackPanel();
         
         // APP鐗堟湰
         JPanel appVersionPanel = createAppVersionPanel();
         
-        addRowWithSpacing(panel, mowerIdPanel);
-        addRowWithSpacing(panel, simCardPanel);
-        addRowWithSpacing(panel, firmwarePanel);
-        panel.add(appVersionPanel);
+        // 娣诲姞璁剧疆椤癸紝浣跨敤鍒嗗壊绾垮垎闅�
+        addSettingItem(panel, mowerIdPanel, true);
+        addSettingItem(panel, baseStationIdPanel, true);
+        addSettingItem(panel, handheldPanel, true);
+        addSettingItem(panel, simCardPanel, true);
+        addSettingItem(panel, baseStationSimPanel, true);
+        addSettingItem(panel, firmwarePanel, true);
+        addSettingItem(panel, idleTrailPanel, true);
+        addSettingItem(panel, boundaryLengthPanel, true);
+        addSettingItem(panel, measurementModePanel, true);
+        addSettingItem(panel, feedbackPanel, true);
+        addSettingItem(panel, appVersionPanel, false);  // 鏈�鍚庝竴椤逛笉鍔犲垎鍓茬嚎
         
-        return panel;
+        container.add(panel, BorderLayout.CENTER);
+        return container;
+    }
+    
+    /**
+     * 娣诲姞璁剧疆椤癸紙甯﹀垎鍓茬嚎锛�
+     */
+    private void addSettingItem(JPanel container, JPanel itemPanel, boolean showDivider) {
+        container.add(itemPanel);
+        if (showDivider) {
+            // 娣诲姞鍒嗗壊绾�
+            JSeparator divider = new JSeparator();
+            divider.setForeground(DIVIDER_COLOR);
+            divider.setMaximumSize(new Dimension(Integer.MAX_VALUE, 1));
+            divider.setAlignmentX(Component.LEFT_ALIGNMENT);
+            container.add(divider);
+        }
     }
 
-    private void addRowWithSpacing(JPanel container, JPanel row) {
-        container.add(row);
-        container.add(Box.createRigidArea(new Dimension(0, ROW_SPACING)));
+    private String formatIdleTrailDurationValue() {
+        int seconds = setData != null ? setData.getIdleTrailDurationSeconds() : Setsys.DEFAULT_IDLE_TRAIL_DURATION_SECONDS;
+        if (seconds <= 0) {
+            seconds = Setsys.DEFAULT_IDLE_TRAIL_DURATION_SECONDS;
+        }
+        return seconds + "绉�";
     }
+
     
     private JPanel createSettingItemPanel(String title, String value, boolean editable) {
         JPanel panel = new JPanel(new GridBagLayout());
-        panel.setBackground(PANEL_BACKGROUND);
+        panel.setOpaque(false);  // 閫忔槑鑳屾櫙锛岀敱瀹瑰櫒缁樺埗
         panel.setAlignmentX(Component.LEFT_ALIGNMENT);
         panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
         panel.setPreferredSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
         panel.setMinimumSize(new Dimension(0, ROW_HEIGHT));
+        panel.setBorder(BorderFactory.createEmptyBorder(ITEM_PADDING, ITEM_PADDING, ITEM_PADDING, ITEM_PADDING));
 
         GridBagConstraints gbc = new GridBagConstraints();
 
@@ -165,11 +259,12 @@
     
     private JPanel createAppVersionPanel() {
         JPanel panel = new JPanel(new GridBagLayout());
-        panel.setBackground(PANEL_BACKGROUND);
+        panel.setOpaque(false);  // 閫忔槑鑳屾櫙
         panel.setAlignmentX(Component.LEFT_ALIGNMENT);
         panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
         panel.setPreferredSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
         panel.setMinimumSize(new Dimension(0, ROW_HEIGHT));
+        panel.setBorder(BorderFactory.createEmptyBorder(ITEM_PADDING, ITEM_PADDING, ITEM_PADDING, ITEM_PADDING));
 
         GridBagConstraints gbc = new GridBagConstraints();
 
@@ -194,28 +289,8 @@
         gbc.anchor = GridBagConstraints.EAST;
         panel.add(appVersionLabel, gbc);
 
-        checkUpdateBtn = new JButton("妫�鏌ユ洿鏂�");
+        checkUpdateBtn = buttonset.createStyledButton("妫�鏌ユ洿鏂�", THEME_COLOR);
         checkUpdateBtn.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
-        checkUpdateBtn.setBackground(THEME_COLOR);
-        checkUpdateBtn.setForeground(Color.WHITE);
-        checkUpdateBtn.setBorder(BorderFactory.createEmptyBorder(0, 12, 0, 12));
-        checkUpdateBtn.setPreferredSize(new Dimension(90, 25));
-        checkUpdateBtn.setMinimumSize(new Dimension(90, 25));
-        checkUpdateBtn.setMaximumSize(new Dimension(90, 25));
-        checkUpdateBtn.setFocusPainted(false);
-
-        checkUpdateBtn.addMouseListener(new MouseAdapter() {
-            public void mouseEntered(MouseEvent e) {
-                checkUpdateBtn.setBackground(new Color(
-                    Math.max(THEME_COLOR.getRed() - 20, 0),
-                    Math.max(THEME_COLOR.getGreen() - 20, 0),
-                    Math.max(THEME_COLOR.getBlue() - 20, 0)
-                ));
-            }
-            public void mouseExited(MouseEvent e) {
-                checkUpdateBtn.setBackground(THEME_COLOR);
-            }
-        });
 
         gbc = new GridBagConstraints();
         gbc.gridx = 2;
@@ -226,6 +301,288 @@
 
         return panel;
     }
+
+    private JPanel createFeedbackPanel() {
+        JPanel panel = new JPanel(new GridBagLayout());
+        panel.setOpaque(false);  // 閫忔槑鑳屾櫙
+        panel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setPreferredSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setMinimumSize(new Dimension(0, ROW_HEIGHT));
+        panel.setBorder(BorderFactory.createEmptyBorder(ITEM_PADDING, ITEM_PADDING, ITEM_PADDING, ITEM_PADDING));
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+        JLabel titleLabel = new JLabel("闂鍙嶉鍜ㄨ");
+        titleLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
+        titleLabel.setForeground(Color.BLACK);
+        titleLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        gbc.insets = new Insets(0, 0, 0, 12);
+        panel.add(titleLabel, gbc);
+
+        feedbackButton = buttonset.createStyledButton("鍙嶉", THEME_COLOR);
+        feedbackButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+
+        gbc = new GridBagConstraints();
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        gbc.weightx = 1.0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(feedbackButton, gbc);
+
+        return panel;
+    }
+    
+    /**
+     * 鍒涘缓鏄剧ず杈圭晫璺濈璁剧疆闈㈡澘
+     */
+    private JPanel createBoundaryLengthPanel() {
+        JPanel panel = new JPanel(new GridBagLayout());
+        panel.setOpaque(false);  // 閫忔槑鑳屾櫙
+        panel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setPreferredSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setMinimumSize(new Dimension(0, ROW_HEIGHT));
+        panel.setBorder(BorderFactory.createEmptyBorder(ITEM_PADDING, ITEM_PADDING, ITEM_PADDING, ITEM_PADDING));
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+        JLabel titleLabel = new JLabel("鏄剧ず杈圭晫璺濈");
+        titleLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
+        titleLabel.setForeground(Color.BLACK);
+        titleLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        gbc.insets = new Insets(0, 0, 0, 12);
+        panel.add(titleLabel, gbc);
+
+        boundaryLengthVisibleLabel = new JLabel(setData.isBoundaryLengthVisible() ? "宸插紑鍚�" : "宸插叧闂�");
+        boundaryLengthVisibleLabel.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 14));
+        boundaryLengthVisibleLabel.setForeground(Color.DARK_GRAY);
+        gbc = new GridBagConstraints();
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        gbc.weightx = 1.0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(boundaryLengthVisibleLabel, gbc);
+
+        panel.putClientProperty("valueLabel", boundaryLengthVisibleLabel);
+
+        // 鍒涘缓鍒囨崲鎸夐挳锛堜娇鐢ㄥ浘鏍囷級
+        JButton toggleBtn = createBoundaryLengthToggleButton();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(toggleBtn, gbc);
+        panel.putClientProperty("toggleButton", toggleBtn);
+
+        return panel;
+    }
+    
+    /**
+     * 鍒涘缓寮�鍚祴閲忔ā寮忚缃潰鏉�
+     */
+    private JPanel createMeasurementModePanel() {
+        JPanel panel = new JPanel(new GridBagLayout());
+        panel.setOpaque(false);  // 閫忔槑鑳屾櫙
+        panel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setPreferredSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT));
+        panel.setMinimumSize(new Dimension(0, ROW_HEIGHT));
+        panel.setBorder(BorderFactory.createEmptyBorder(ITEM_PADDING, ITEM_PADDING, ITEM_PADDING, ITEM_PADDING));
+
+        GridBagConstraints gbc = new GridBagConstraints();
+
+        JLabel titleLabel = new JLabel("寮�鍚祴閲忔ā寮�");
+        titleLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 14));
+        titleLabel.setForeground(Color.BLACK);
+        titleLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+        gbc.gridx = 0;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        gbc.insets = new Insets(0, 0, 0, 12);
+        panel.add(titleLabel, gbc);
+
+        measurementModeEnabledLabel = new JLabel(setData.isMeasurementModeEnabled() ? "宸插紑鍚�" : "宸插叧闂�");
+        measurementModeEnabledLabel.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 14));
+        measurementModeEnabledLabel.setForeground(Color.DARK_GRAY);
+        gbc = new GridBagConstraints();
+        gbc.gridx = 1;
+        gbc.gridy = 0;
+        gbc.weightx = 1.0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(measurementModeEnabledLabel, gbc);
+
+        panel.putClientProperty("valueLabel", measurementModeEnabledLabel);
+
+        // 鍒涘缓鍒囨崲鎸夐挳锛堜娇鐢ㄥ浘鏍囷級
+        JButton toggleBtn = createMeasurementModeToggleButton();
+        gbc = new GridBagConstraints();
+        gbc.gridx = 2;
+        gbc.gridy = 0;
+        gbc.weightx = 0;
+        gbc.anchor = GridBagConstraints.EAST;
+        panel.add(toggleBtn, gbc);
+        panel.putClientProperty("toggleButton", toggleBtn);
+
+        return panel;
+    }
+    
+    /**
+     * 鍒涘缓娴嬮噺妯″紡鍒囨崲鎸夐挳
+     */
+    private JButton createMeasurementModeToggleButton() {
+        JButton button = new JButton();
+        button.setContentAreaFilled(false);
+        button.setBorder(null);
+        button.setFocusPainted(false);
+        button.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        button.setPreferredSize(new Dimension(32, 32));
+        button.setMinimumSize(new Dimension(32, 32));
+        button.setMaximumSize(new Dimension(32, 32));
+        
+        updateMeasurementModeToggleButton(button);
+        
+        button.addActionListener(e -> toggleMeasurementMode(button));
+        
+        return button;
+    }
+    
+    /**
+     * 鏇存柊娴嬮噺妯″紡鍒囨崲鎸夐挳鍥炬爣
+     */
+    private void updateMeasurementModeToggleButton(JButton button) {
+        boolean isEnabled = setData.isMeasurementModeEnabled();
+        try {
+            String iconPath = isEnabled ? "image/open.png" : "image/close.png";
+            ImageIcon icon = new ImageIcon(iconPath);
+            if (icon.getIconWidth() > 0) {
+                Image scaledImage = icon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH);
+                button.setIcon(new ImageIcon(scaledImage));
+                button.setText(null);
+            } else {
+                button.setIcon(null);
+                button.setText(isEnabled ? "寮�" : "鍏�");
+            }
+        } catch (Exception e) {
+            button.setIcon(null);
+            button.setText(isEnabled ? "寮�" : "鍏�");
+            System.err.println("鏃犳硶鍔犺浇娴嬮噺妯″紡鍥炬爣: " + e.getMessage());
+        }
+    }
+    
+    /**
+     * 鍒囨崲娴嬮噺妯″紡鐘舵��
+     */
+    private void toggleMeasurementMode(JButton button) {
+        boolean newValue = !setData.isMeasurementModeEnabled();
+        setData.setMeasurementModeEnabled(newValue);
+        
+        // 淇濆瓨鍒伴厤缃枃浠�
+        setData.updateProperty("measurementModeEnabled", String.valueOf(newValue));
+        
+        // 鏇存柊UI
+        if (measurementModeEnabledLabel != null) {
+            measurementModeEnabledLabel.setText(newValue ? "宸插紑鍚�" : "宸插叧闂�");
+        }
+        updateMeasurementModeToggleButton(button);
+        
+        // 閫氱煡MapRenderer鏇存柊
+        Shouye shouye = Shouye.getInstance();
+        if (shouye != null) {
+            MapRenderer renderer = shouye.getMapRenderer();
+            if (renderer != null) {
+                renderer.setMeasurementMode(newValue);
+            }
+            if (newValue) {
+                celiangmoshi.start();
+            } else {
+                celiangmoshi.stop();
+            }
+            // 鍒锋柊鍦板浘鏄剧ず锛堥�氳繃MapRenderer瑙﹀彂閲嶇粯锛�
+            if (renderer != null) {
+                renderer.repaint();
+            }
+        }
+    }
+    
+    /**
+     * 鍒涘缓杈圭晫璺濈鏄剧ず鍒囨崲鎸夐挳
+     */
+    private JButton createBoundaryLengthToggleButton() {
+        JButton button = new JButton();
+        button.setContentAreaFilled(false);
+        button.setBorder(null);
+        button.setFocusPainted(false);
+        button.setCursor(new Cursor(Cursor.HAND_CURSOR));
+        button.setPreferredSize(new Dimension(32, 32));
+        button.setMinimumSize(new Dimension(32, 32));
+        button.setMaximumSize(new Dimension(32, 32));
+        
+        updateBoundaryLengthToggleButton(button);
+        
+        button.addActionListener(e -> toggleBoundaryLengthVisible(button));
+        
+        return button;
+    }
+    
+    /**
+     * 鏇存柊杈圭晫璺濈鍒囨崲鎸夐挳鍥炬爣
+     */
+    private void updateBoundaryLengthToggleButton(JButton button) {
+        boolean isVisible = setData.isBoundaryLengthVisible();
+        try {
+            String iconPath = isVisible ? "image/open.png" : "image/close.png";
+            ImageIcon icon = new ImageIcon(iconPath);
+            if (icon.getIconWidth() > 0) {
+                Image scaledImage = icon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH);
+                button.setIcon(new ImageIcon(scaledImage));
+                button.setText(null);
+            } else {
+                button.setIcon(null);
+                button.setText(isVisible ? "寮�" : "鍏�");
+            }
+        } catch (Exception e) {
+            button.setIcon(null);
+            button.setText(isVisible ? "寮�" : "鍏�");
+            System.err.println("鏃犳硶鍔犺浇杈圭晫璺濈鍥炬爣: " + e.getMessage());
+        }
+    }
+    
+    /**
+     * 鍒囨崲杈圭晫璺濈鏄剧ず鐘舵��
+     */
+    private void toggleBoundaryLengthVisible(JButton button) {
+        boolean newValue = !setData.isBoundaryLengthVisible();
+        setData.setBoundaryLengthVisible(newValue);
+        
+        // 淇濆瓨鍒伴厤缃枃浠�
+        setData.updateProperty("boundaryLengthVisible", String.valueOf(newValue));
+        
+        // 鏇存柊UI
+        if (boundaryLengthVisibleLabel != null) {
+            boundaryLengthVisibleLabel.setText(newValue ? "宸插紑鍚�" : "宸插叧闂�");
+        }
+        updateBoundaryLengthToggleButton(button);
+        
+        // 閫氱煡MapRenderer鏇存柊
+        Shouye shouye = Shouye.getInstance();
+        if (shouye != null) {
+            MapRenderer renderer = shouye.getMapRenderer();
+            if (renderer != null) {
+                renderer.setBoundaryLengthVisible(newValue);
+            }
+        }
+    }
     
     private JButton createEditButton() {
         JButton button = new JButton();
@@ -262,7 +619,50 @@
     private void loadData() {
         // 浠嶴etsys绫诲姞杞芥暟鎹�
         setData.initializeFromProperties();
+        baseStation.load();
         updateDisplay();
+        // 鍔犺浇骞跺簲鐢ㄤ笂娆′繚瀛樼殑瑙嗗浘涓績鍧愭爣
+        loadViewCenterFromProperties();
+    }
+    
+    /**
+     * 浠庨厤缃枃浠跺姞杞借鍥句腑蹇冨潗鏍囧苟搴旂敤鍒癕apRenderer
+     */
+    private void loadViewCenterFromProperties() {
+        Shouye shouye = Shouye.getInstance();
+        if (shouye == null) {
+            return;
+        }
+        MapRenderer renderer = shouye.getMapRenderer();
+        if (renderer == null) {
+            return;
+        }
+        
+        // 浠庨厤缃枃浠惰鍙栬鍥句腑蹇冨潗鏍�
+        String viewCenterXValue = Setsys.getPropertyValue("viewCenterX");
+        String viewCenterYValue = Setsys.getPropertyValue("viewCenterY");
+        
+        double savedTranslateX = 0.0;
+        double savedTranslateY = 0.0;
+        
+        if (viewCenterXValue != null && !viewCenterXValue.trim().isEmpty()) {
+            try {
+                savedTranslateX = Double.parseDouble(viewCenterXValue.trim());
+            } catch (NumberFormatException e) {
+                savedTranslateX = 0.0;
+            }
+        }
+        if (viewCenterYValue != null && !viewCenterYValue.trim().isEmpty()) {
+            try {
+                savedTranslateY = Double.parseDouble(viewCenterYValue.trim());
+            } catch (NumberFormatException e) {
+                savedTranslateY = 0.0;
+            }
+        }
+        
+        // 搴旂敤瑙嗗浘涓績鍧愭爣锛堜繚鎸佸綋鍓嶇缉鏀炬瘮渚嬶級
+        double currentScale = renderer.getScale();
+        renderer.setViewTransform(currentScale, savedTranslateX, savedTranslateY);
     }
     
     private void updateDisplay() {
@@ -270,18 +670,60 @@
         if (mowerIdLabel != null) {
             mowerIdLabel.setText(setData.getMowerId() != null ? setData.getMowerId() : "鏈缃�");
         }
+
+        if (baseStationIdLabel != null) {
+            baseStationIdLabel.setText(resolveBaseStationId());
+        }
+
+        if (handheldMarkerLabel != null) {
+            handheldMarkerLabel.setText(setData.getHandheldMarkerId() != null ? setData.getHandheldMarkerId() : "鏈缃�");
+        }
         
         // 鏇存柊鐗╄仈鍗″彿鏄剧ず
         if (simCardNumberLabel != null) {
             simCardNumberLabel.setText(setData.getSimCardNumber() != null ? 
                 setData.getSimCardNumber() : "鏈缃�");
         }
+
+        if (baseStationSimLabel != null) {
+            baseStationSimLabel.setText(resolveBaseStationSimCard());
+        }
         
         // 鏇存柊鍥轰欢鐗堟湰鏄剧ず
         if (firmwareVersionLabel != null) {
             firmwareVersionLabel.setText(setData.getFirmwareVersion() != null ? 
                 setData.getFirmwareVersion() : "鏈缃�");
         }
+
+        if (idleTrailDurationLabel != null) {
+            idleTrailDurationLabel.setText(formatIdleTrailDurationValue());
+        }
+        
+        // 鏇存柊鏄剧ず杈圭晫璺濈鐘舵��
+        if (boundaryLengthVisibleLabel != null) {
+            boundaryLengthVisibleLabel.setText(setData.isBoundaryLengthVisible() ? "宸插紑鍚�" : "宸插叧闂�");
+        }
+        // 鏇存柊鍒囨崲鎸夐挳鍥炬爣
+        JPanel boundaryLengthPanel = (JPanel) boundaryLengthVisibleLabel.getParent();
+        if (boundaryLengthPanel != null) {
+            JButton toggleBtn = (JButton) boundaryLengthPanel.getClientProperty("toggleButton");
+            if (toggleBtn != null) {
+                updateBoundaryLengthToggleButton(toggleBtn);
+            }
+        }
+        
+        // 鏇存柊娴嬮噺妯″紡鐘舵��
+        if (measurementModeEnabledLabel != null) {
+            measurementModeEnabledLabel.setText(setData.isMeasurementModeEnabled() ? "宸插紑鍚�" : "宸插叧闂�");
+        }
+        // 鏇存柊娴嬮噺妯″紡鍒囨崲鎸夐挳鍥炬爣
+        JPanel measurementModePanel = (JPanel) measurementModeEnabledLabel.getParent();
+        if (measurementModePanel != null) {
+            JButton toggleBtn = (JButton) measurementModePanel.getClientProperty("toggleButton");
+            if (toggleBtn != null) {
+                updateMeasurementModeToggleButton(toggleBtn);
+            }
+        }
         
         // 鏇存柊APP鐗堟湰鏄剧ず
         if (appVersionLabel != null) {
@@ -289,17 +731,63 @@
                 setData.getAppVersion() : "鏈缃�");
         }
     }
+
+    private String resolveBaseStationSimCard() {
+        if (baseStation == null) {
+            return "鏈缃�";
+        }
+        String value = baseStation.getIotSimCardNumber();
+        if (value == null) {
+            return "鏈缃�";
+        }
+        String trimmed = value.trim();
+        if (trimmed.isEmpty() || "-1".equals(trimmed)) {
+            return "鏈缃�";
+        }
+        return trimmed;
+    }
+
+    private String resolveBaseStationId() {
+        if (baseStation == null) {
+            return "鏈缃�";
+        }
+        String value = baseStation.getDeviceId();
+        if (value == null) {
+            return "鏈缃�";
+        }
+        String trimmed = value.trim();
+        if (trimmed.isEmpty() || "-1".equals(trimmed)) {
+            return "鏈缃�";
+        }
+        return trimmed;
+    }
     
     private void setupEventHandlers() {
         // 鍓茶崏鏈虹紪鍙风紪杈戞寜閽簨浠�
         if (mowerIdEditBtn != null) {
             mowerIdEditBtn.addActionListener(e -> editMowerId());
         }
+
+        if (baseStationIdEditBtn != null) {
+            baseStationIdEditBtn.addActionListener(e -> editBaseStationId());
+        }
         
         // 妫�鏌ユ洿鏂版寜閽簨浠�
         if (checkUpdateBtn != null) {
             checkUpdateBtn.addActionListener(e -> checkForUpdates());
         }
+
+        if (handheldEditBtn != null) {
+            handheldEditBtn.addActionListener(e -> editHandheldMarkerId());
+        }
+
+        if (feedbackButton != null) {
+            feedbackButton.addActionListener(e -> showFeedbackDialog());
+        }
+
+        if (idleTrailEditBtn != null) {
+            idleTrailEditBtn.addActionListener(e -> editIdleTrailDuration());
+        }
         
     }
     
@@ -327,6 +815,271 @@
             }
         }
     }
+
+    private void editHandheldMarkerId() {
+        String currentValue = setData.getHandheldMarkerId() != null ? setData.getHandheldMarkerId() : "";
+        String newValue = (String) JOptionPane.showInputDialog(this,
+                "璇疯緭鍏ヤ究鎼烘墦鐐瑰櫒缂栧彿:",
+                "淇敼渚挎惡鎵撶偣鍣ㄧ紪鍙�",
+                JOptionPane.QUESTION_MESSAGE,
+                null,
+                null,
+                currentValue);
+
+        if (newValue == null) {
+            return;
+        }
+
+        newValue = newValue.trim();
+        if (!newValue.isEmpty()) {
+            if (setData.updateProperty("handheldMarkerId", newValue)) {
+                if (handheldMarkerLabel != null) {
+                    handheldMarkerLabel.setText(newValue);
+                }
+                JOptionPane.showMessageDialog(this, "渚挎惡鎵撶偣鍣ㄧ紪鍙锋洿鏂版垚鍔�", "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
+            } else {
+                JOptionPane.showMessageDialog(this, "渚挎惡鎵撶偣鍣ㄧ紪鍙锋洿鏂板け璐�", "閿欒", JOptionPane.ERROR_MESSAGE);
+            }
+        }
+    }
+
+    private void editBaseStationId() {
+        String currentValue = "鏈缃�".equals(resolveBaseStationId()) ? "" : resolveBaseStationId();
+        String newValue = (String) JOptionPane.showInputDialog(this,
+                "璇疯緭鍏ュ樊鍒嗗熀鍑嗙珯缂栧彿:",
+                "淇敼宸垎鍩哄噯绔欑紪鍙�",
+                JOptionPane.QUESTION_MESSAGE,
+                null,
+                null,
+                currentValue);
+
+        if (newValue == null) {
+            return;
+        }
+
+        newValue = newValue.trim();
+        if (newValue.isEmpty()) {
+            JOptionPane.showMessageDialog(this, "宸垎鍩哄噯绔欑紪鍙蜂笉鑳戒负绌�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        try {
+            baseStation.updateByDeviceId(newValue,
+                    baseStation.getInstallationCoordinates(),
+                    baseStation.getIotSimCardNumber(),
+                    baseStation.getDeviceActivationTime(),
+                    baseStation.getDataUpdateTime());
+            baseStation.load();
+            if (baseStationIdLabel != null) {
+                baseStationIdLabel.setText(resolveBaseStationId());
+            }
+            JOptionPane.showMessageDialog(this, "宸垎鍩哄噯绔欑紪鍙锋洿鏂版垚鍔�", "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
+        } catch (IllegalArgumentException ex) {
+            JOptionPane.showMessageDialog(this, ex.getMessage(), "杈撳叆閿欒", JOptionPane.WARNING_MESSAGE);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            JOptionPane.showMessageDialog(this, "宸垎鍩哄噯绔欑紪鍙锋洿鏂板け璐�", "閿欒", JOptionPane.ERROR_MESSAGE);
+        }
+    }
+
+    private void editIdleTrailDuration() {
+        int currentSeconds = setData != null ? setData.getIdleTrailDurationSeconds() : Setsys.DEFAULT_IDLE_TRAIL_DURATION_SECONDS;
+        if (currentSeconds <= 0) {
+            currentSeconds = Setsys.DEFAULT_IDLE_TRAIL_DURATION_SECONDS;
+        }
+
+        String input = JOptionPane.showInputDialog(this,
+            "璇疯緭鍏ヨ建杩规嫋灏炬椂闀匡紙鍗曚綅锛氱锛�",
+            currentSeconds);
+
+        if (input == null) {
+            return;
+        }
+
+        String trimmed = input.trim();
+        if (trimmed.isEmpty()) {
+            JOptionPane.showMessageDialog(this, "杞ㄨ抗鎷栧熬鏃堕暱涓嶈兘涓虹┖", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        int parsedSeconds;
+        try {
+            parsedSeconds = Integer.parseInt(trimmed);
+        } catch (NumberFormatException ex) {
+            JOptionPane.showMessageDialog(this, "璇疯緭鍏ユ湁鏁堢殑鏁存暟绉掓暟", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        if (parsedSeconds < 5 || parsedSeconds > 600) {
+            JOptionPane.showMessageDialog(this, "璇疯緭鍏�5鍒�600涔嬮棿鐨勭鏁�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+            return;
+        }
+
+        if (setData.updateProperty("idleTrailDurationSeconds", String.valueOf(parsedSeconds))) {
+            int appliedSeconds = setData.getIdleTrailDurationSeconds();
+            if (idleTrailDurationLabel != null) {
+                idleTrailDurationLabel.setText(appliedSeconds + "绉�");
+            }
+            MapRenderer renderer = null;
+            Shouye shouye = Shouye.getInstance();
+            if (shouye != null) {
+                renderer = shouye.getMapRenderer();
+            }
+            if (renderer != null) {
+                renderer.setIdleTrailDurationSeconds(appliedSeconds);
+            }
+            JOptionPane.showMessageDialog(this, "杞ㄨ抗鎷栧熬鏃堕暱宸叉洿鏂颁负 " + appliedSeconds + " 绉�", "鎴愬姛", JOptionPane.INFORMATION_MESSAGE);
+        } else {
+            JOptionPane.showMessageDialog(this, "杞ㄨ抗鎷栧熬鏃堕暱鏇存柊澶辫触", "閿欒", JOptionPane.ERROR_MESSAGE);
+        }
+    }
+
+    private void showFeedbackDialog() {
+    JDialog dialog = new JDialog(this, "闂鍙嶉鍜ㄨ", true);
+    dialog.setLayout(new BorderLayout(0, 12));
+    dialog.setResizable(false);
+    dialog.setPreferredSize(new Dimension(400, 800));
+    dialog.setSize(new Dimension(400, 800));
+    dialog.setMinimumSize(new Dimension(400, 800));
+
+    JPanel content = new JPanel();
+    content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS));
+    content.setBorder(BorderFactory.createEmptyBorder(20, 24, 20, 24));
+    dialog.add(content, BorderLayout.CENTER);
+
+        JLabel descriptionLabel = new JLabel("闂鎻忚堪锛�");
+        descriptionLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 13));
+        descriptionLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
+        content.add(descriptionLabel);
+
+        content.add(Box.createRigidArea(new Dimension(0, 8)));
+
+        JTextArea descriptionArea = new JTextArea(5, 30);
+        descriptionArea.setLineWrap(true);
+        descriptionArea.setWrapStyleWord(true);
+        descriptionArea.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 13));
+        JScrollPane scrollPane = new JScrollPane(descriptionArea);
+        scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
+        content.add(scrollPane);
+
+        content.add(Box.createRigidArea(new Dimension(0, 16)));
+
+        JPanel photoControls = new JPanel(new FlowLayout(FlowLayout.LEFT, 12, 0));
+        photoControls.setAlignmentX(Component.LEFT_ALIGNMENT);
+        JLabel photoLabel = new JLabel("閫夋嫨鐓х墖锛堟渶澶�6寮狅級锛�");
+        photoLabel.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 13));
+    JButton selectPhotosButton = buttonset.createStyledButton("閫夋嫨鐓х墖", THEME_COLOR);
+    selectPhotosButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+        photoControls.add(photoLabel);
+        photoControls.add(selectPhotosButton);
+    content.add(photoControls);
+
+    content.add(Box.createRigidArea(new Dimension(0, 20)));
+
+        JPanel photoGrid = new JPanel(new GridLayout(2, 3, 12, 12));
+        photoGrid.setAlignmentX(Component.LEFT_ALIGNMENT);
+        photoGrid.setMaximumSize(new Dimension(Integer.MAX_VALUE, 220));
+        List<JLabel> photoSlots = new ArrayList<>();
+        for (int i = 0; i < 6; i++) {
+            JLabel slot = buildPhotoSlot();
+            photoGrid.add(slot);
+            photoSlots.add(slot);
+        }
+        content.add(photoGrid);
+
+        content.add(Box.createRigidArea(new Dimension(0, 20)));
+
+    JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+    JButton cancelButton = buttonset.createStyledButton("鏀惧純", new Color(128, 128, 128));
+    cancelButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+    JButton submitButton = buttonset.createStyledButton("鎻愪氦", THEME_COLOR);
+    submitButton.setFont(new Font("寰蒋闆呴粦", Font.PLAIN, 12));
+
+        buttonPanel.add(cancelButton);
+        buttonPanel.add(submitButton);
+        dialog.add(buttonPanel, BorderLayout.SOUTH);
+
+        List<File> selectedPhotos = new ArrayList<>();
+
+        selectPhotosButton.addActionListener(e -> {
+            JFileChooser chooser = new JFileChooser();
+            chooser.setMultiSelectionEnabled(true);
+            chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
+            chooser.setFileFilter(new FileNameExtensionFilter("鍥剧墖鏂囦欢", "jpg", "jpeg", "png", "bmp", "gif", "webp"));
+
+            if (chooser.showOpenDialog(dialog) == JFileChooser.APPROVE_OPTION) {
+                File[] files = chooser.getSelectedFiles();
+                if (files != null) {
+                    if (selectedPhotos.size() >= 6) {
+                        JOptionPane.showMessageDialog(dialog, "宸茶揪鍒�6寮犵収鐗囦笂闄�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                        return;
+                    }
+                    for (File file : files) {
+                        if (selectedPhotos.size() >= 6) {
+                            break;
+                        }
+                        if (file != null && file.exists() && file.isFile()) {
+                            selectedPhotos.add(file);
+                        }
+                    }
+                    updatePhotoPreview(photoSlots, selectedPhotos);
+                }
+            }
+        });
+
+        cancelButton.addActionListener(e -> dialog.dispose());
+
+        submitButton.addActionListener(e -> {
+            String description = descriptionArea.getText() != null ? descriptionArea.getText().trim() : "";
+            if (description.isEmpty()) {
+                JOptionPane.showMessageDialog(dialog, "璇峰~鍐欓棶棰樻弿杩�", "鎻愮ず", JOptionPane.WARNING_MESSAGE);
+                descriptionArea.requestFocusInWindow();
+                return;
+            }
+
+            // 鎻愪氦閫昏緫鍗犱綅
+            JOptionPane.showMessageDialog(dialog,
+                    "鍙嶉宸叉彁浜わ紝鎰熻阿鎮ㄧ殑鏀寔锛乗n鎻忚堪瀛楁暟锛�" + description.length() + "锛岀収鐗囨暟閲忥細" + selectedPhotos.size(),
+                    "鎻愪氦鎴愬姛",
+                    JOptionPane.INFORMATION_MESSAGE);
+            dialog.dispose();
+        });
+
+        dialog.pack();
+        dialog.setLocationRelativeTo(this);
+        dialog.setVisible(true);
+    }
+
+    private JLabel buildPhotoSlot() {
+        JLabel slot = new JLabel();
+        slot.setPreferredSize(new Dimension(100, 100));
+        slot.setMinimumSize(new Dimension(100, 100));
+        slot.setOpaque(true);
+        slot.setBackground(new Color(245, 245, 245));
+        slot.setHorizontalAlignment(SwingConstants.CENTER);
+        slot.setVerticalAlignment(SwingConstants.CENTER);
+        slot.setBorder(BorderFactory.createLineBorder(new Color(220, 220, 220), 1));
+        slot.setText("+");
+        slot.setFont(new Font("寰蒋闆呴粦", Font.BOLD, 18));
+        slot.setForeground(new Color(180, 180, 180));
+        return slot;
+    }
+
+    private void updatePhotoPreview(List<JLabel> slots, List<File> photos) {
+        for (int i = 0; i < slots.size(); i++) {
+            JLabel slot = slots.get(i);
+            if (i < photos.size()) {
+                File photo = photos.get(i);
+                ImageIcon icon = new ImageIcon(photo.getAbsolutePath());
+                Image scaled = icon.getImage().getScaledInstance(100, 100, Image.SCALE_SMOOTH);
+                slot.setIcon(new ImageIcon(scaled));
+                slot.setText(null);
+            } else {
+                slot.setIcon(null);
+                slot.setText("+");
+            }
+        }
+    }
     
     private void checkForUpdates() {
         // 妯℃嫙妫�鏌ユ洿鏂拌繃绋�

--
Gitblit v1.10.0