张世豪
6 小时以前 a6077217e25f5804027194a5c2848e773eda1abd
src/xitongshezhi/lishijilu.java
@@ -17,20 +17,27 @@
    private static final Color DARK_LIGHT_COLOR = new Color(26, 43, 68);
    private static final Color TEXT_COLOR = new Color(224, 224, 224);
    private static final Color TEXT_LIGHT_COLOR = new Color(160, 200, 255);
    private static final Color DELETE_COLOR = new Color(231, 76, 60); // 删除按钮颜色
    private static final Color ACTIVE_BUTTON_COLOR = new Color(41, 128, 185); // 激活按钮颜色
    
    private JPanel mainPanel;
    private JLabel titleLabel;
    private JButton logButton; // 日志记录按钮
    private JButton errorLogButton; // 错误日志按钮
    private JButton backButton;
    private JButton deleteAllButton;
    
    // 文本域组件
    private JScrollPane textScrollPane;
    private JTextArea contentTextArea;
    
    // 当前显示的日志类型
    private String currentLogType = "log"; // "log" 或 "error"
    public lishijilu(JFrame parent) {
        super(parent, "", true);
        initializeUI();
        setupEventListeners();
        loadLogContent(); // 加载日志内容
        loadLogContent(); // 默认加载操作日志
    }
    private void initializeUI() {
@@ -71,12 +78,48 @@
        headerPanel.setOpaque(false);
        headerPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 12, 0));
        
        // 标题
        titleLabel = new JLabel("历史记录");
        titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 22));
        titleLabel.setForeground(TEXT_COLOR);
        // 创建日志类型选择按钮面板
        JPanel logTypePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
        logTypePanel.setOpaque(false);
        
        // 返回按钮 - 使用不透明设计
        // 日志记录按钮
        logButton = new JButton("日志记录");
        logButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        logButton.setBackground(ACTIVE_BUTTON_COLOR); // 默认激活状态
        logButton.setForeground(Color.WHITE);
        logButton.setOpaque(true);
        logButton.setFocusPainted(false);
        logButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16));
        logButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        // 错误日志按钮
        errorLogButton = new JButton("错误日志");
        errorLogButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        errorLogButton.setBackground(PRIMARY_COLOR); // 默认非激活状态
        errorLogButton.setForeground(Color.WHITE);
        errorLogButton.setOpaque(true);
        errorLogButton.setFocusPainted(false);
        errorLogButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16));
        errorLogButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        logTypePanel.add(logButton);
        logTypePanel.add(errorLogButton);
        // 操作按钮面板
        JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0));
        actionButtonPanel.setOpaque(false);
        // 删除全部记录按钮
        deleteAllButton = new JButton("删除全部");
        deleteAllButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        deleteAllButton.setBackground(DELETE_COLOR);
        deleteAllButton.setForeground(Color.WHITE);
        deleteAllButton.setOpaque(true);
        deleteAllButton.setFocusPainted(false);
        deleteAllButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16));
        deleteAllButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        // 返回按钮
        backButton = new JButton("关闭");
        backButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        backButton.setBackground(PRIMARY_COLOR);
@@ -85,6 +128,60 @@
        backButton.setFocusPainted(false);
        backButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16));
        backButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        actionButtonPanel.add(deleteAllButton);
        actionButtonPanel.add(backButton);
        // 按钮悬停效果
        setupButtonHoverEffects();
        headerPanel.add(logTypePanel, BorderLayout.WEST);
        headerPanel.add(actionButtonPanel, BorderLayout.EAST);
        return headerPanel;
    }
    private void setupButtonHoverEffects() {
        // 日志按钮悬停效果
        logButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                if (!currentLogType.equals("log")) {
                    logButton.setBackground(brighterColor(PRIMARY_COLOR));
                }
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                if (!currentLogType.equals("log")) {
                    logButton.setBackground(PRIMARY_COLOR);
                }
            }
        });
        // 错误日志按钮悬停效果
        errorLogButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                if (!currentLogType.equals("error")) {
                    errorLogButton.setBackground(brighterColor(PRIMARY_COLOR));
                }
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                if (!currentLogType.equals("error")) {
                    errorLogButton.setBackground(PRIMARY_COLOR);
                }
            }
        });
        // 删除按钮悬停效果
        deleteAllButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                deleteAllButton.setBackground(brighterColor(DELETE_COLOR));
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                deleteAllButton.setBackground(DELETE_COLOR);
            }
        });
        
        // 返回按钮悬停效果
        backButton.addMouseListener(new java.awt.event.MouseAdapter() {
@@ -96,19 +193,6 @@
                backButton.setBackground(PRIMARY_COLOR);
            }
        });
        JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        titlePanel.setOpaque(false);
        titlePanel.add(titleLabel);
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
        buttonPanel.setOpaque(false);
        buttonPanel.add(backButton);
        headerPanel.add(titlePanel, BorderLayout.WEST);
        headerPanel.add(buttonPanel, BorderLayout.EAST);
        return headerPanel;
    }
    
    private JPanel createContentPanel() {
@@ -177,37 +261,138 @@
        backButton.addActionListener(e -> {
            dispose();
        });
        // 删除全部记录按钮
        deleteAllButton.addActionListener(e -> {
            deleteAllRecords();
        });
        // 日志记录按钮
        logButton.addActionListener(e -> {
            switchToLogType("log");
        });
        // 错误日志按钮
        errorLogButton.addActionListener(e -> {
            switchToLogType("error");
        });
    }
    // 切换日志类型
    private void switchToLogType(String logType) {
        if (currentLogType.equals(logType)) {
            return; // 已经是当前类型,无需切换
        }
        currentLogType = logType;
        // 更新按钮状态
        if (logType.equals("log")) {
            logButton.setBackground(ACTIVE_BUTTON_COLOR);
            errorLogButton.setBackground(PRIMARY_COLOR);
        } else {
            logButton.setBackground(PRIMARY_COLOR);
            errorLogButton.setBackground(ACTIVE_BUTTON_COLOR);
        }
        // 加载对应类型的日志内容
        loadLogContent();
    }
    // 删除全部记录的方法
    private void deleteAllRecords() {
        // 确认对话框
        String logTypeName = currentLogType.equals("log") ? "操作" : "错误";
        int result = JOptionPane.showConfirmDialog(
            this,
            "确定要删除所有" + logTypeName + "记录吗?此操作不可恢复!",
            "确认删除",
            JOptionPane.YES_NO_OPTION,
            JOptionPane.WARNING_MESSAGE
        );
        if (result == JOptionPane.YES_OPTION) {
            try {
                String fileName = currentLogType.equals("log") ? "log.properties" : "err.properties";
                File logFile = new File(fileName);
                if (logFile.exists()) {
                    // 创建空的Properties对象并写入文件
                    Properties emptyProps = new Properties();
                    try (FileOutputStream out = new FileOutputStream(logFile);
                         OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8")) {
                        emptyProps.store(writer, "发卡机" + logTypeName + "记录 - 所有记录已清空");
                    }
                    // 更新文本域显示
                    contentTextArea.setText("所有" + logTypeName + "记录已成功删除。\n\n日志文件已清空。");
                    // 显示成功消息
                    JOptionPane.showMessageDialog(
                        this,
                        "所有" + logTypeName + "记录已成功删除。",
                        "删除成功",
                        JOptionPane.INFORMATION_MESSAGE
                    );
                } else {
                    contentTextArea.setText(logTypeName + "日志文件不存在,无需删除。");
                }
            } catch (IOException ex) {
                ex.printStackTrace();
                JOptionPane.showMessageDialog(
                    this,
                    "删除记录时出错: " + ex.getMessage(),
                    "错误",
                    JOptionPane.ERROR_MESSAGE
                );
            }
        }
    }
    
    // 加载日志内容
    private void loadLogContent() {
        File logFile = new File("log.properties");
        String fileName = currentLogType.equals("log") ? "log.properties" : "err.properties";
        String logTypeName = currentLogType.equals("log") ? "操作" : "错误";
        File logFile = new File(fileName);
        
        if (!logFile.exists()) {
            contentTextArea.setText("日志文件不存在。");
            contentTextArea.setText(logTypeName + "日志文件不存在。");
            return;
        }
        
        Properties logProps = new Properties();
        try (FileInputStream in = new FileInputStream(logFile)) {
            logProps.load(in);
        try (FileInputStream in = new FileInputStream(logFile);
             InputStreamReader reader = new InputStreamReader(in, "UTF-8")) {
            logProps.load(reader);
            
            // 检查记录数量,如果超过1000条则删除旧记录
            if (logProps.size() > 1000) {
                trimLogProperties(logProps);
                trimLogProperties(logProps, fileName);
            }
            
            // 构建显示内容
            StringBuilder content = new StringBuilder();
            content.append("日志文件内容 (").append(logProps.size()).append(" 条记录):\n\n");
            content.append(logTypeName).append("日志内容 (").append(logProps.size()).append(" 条记录):\n\n");
            
            // 按时间戳排序显示
            logProps.stringPropertyNames().stream()
                .sorted((a, b) -> Long.compare(Long.parseLong(b), Long.parseLong(a)))
                .sorted((a, b) -> {
                    try {
                        // 从键中提取时间戳部分进行比较
                        long timeA = extractTimestampFromKey(a);
                        long timeB = extractTimestampFromKey(b);
                        return Long.compare(timeB, timeA); // 降序排列,最新的在前
                    } catch (Exception e) {
                        return b.compareTo(a); // 如果提取失败,使用字符串比较
                    }
                })
                .forEach(key -> {
                    String value = logProps.getProperty(key);
                    content.append("时间戳: ").append(key).append("\n");
                    content.append("内容: ").append(value).append("\n");
                    content.append("时间: ").append(extractTimeFromValue(value)).append("\n");
                    content.append("内容: ").append(extractOperationFromValue(value)).append("\n");
                    content.append("----------------------------------------\n");
                });
            
@@ -215,23 +400,71 @@
            
        } catch (IOException e) {
            e.printStackTrace();
            contentTextArea.setText("加载日志文件时出错: " + e.getMessage());
        } catch (NumberFormatException e) {
            contentTextArea.setText("日志文件格式错误。");
            contentTextArea.setText("加载" + logTypeName + "日志文件时出错: " + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            contentTextArea.setText("处理" + logTypeName + "日志内容时出错: " + e.getMessage());
        }
    }
    
    // 从键中提取时间戳
    private long extractTimestampFromKey(String key) {
        try {
            // 键的格式: log_时间戳_UUID 或 error_时间戳_UUID
            String[] parts = key.split("_");
            if (parts.length >= 2) {
                return Long.parseLong(parts[1]);
            }
        } catch (Exception e) {
            // 如果解析失败,返回0
        }
        return 0L;
    }
    // 从值中提取时间部分
    private String extractTimeFromValue(String value) {
        if (value == null) return "未知时间";
        // 值的格式: [2025-11-21 14:44:39] 取卡操作:卡槽19被管理员取卡
        int start = value.indexOf('[');
        int end = value.indexOf(']');
        if (start >= 0 && end > start) {
            return value.substring(start + 1, end);
        }
        return value;
    }
    // 从值中提取操作部分
    private String extractOperationFromValue(String value) {
        if (value == null) return "未知内容";
        // 值的格式: [2025-11-21 14:44:39] 取卡操作:卡槽19被管理员取卡
        int end = value.indexOf(']');
        if (end >= 0 && end + 1 < value.length()) {
            return value.substring(end + 1).trim();
        }
        return value;
    }
    // 修剪日志属性,只保留最新的1000条记录
    private void trimLogProperties(Properties logProps) {
    private void trimLogProperties(Properties logProps, String fileName) {
        // 按时间戳排序,保留最新的1000条
        logProps.stringPropertyNames().stream()
            .sorted((a, b) -> Long.compare(Long.parseLong(b), Long.parseLong(a)))
            .sorted((a, b) -> {
                try {
                    long timeA = extractTimestampFromKey(a);
                    long timeB = extractTimestampFromKey(b);
                    return Long.compare(timeB, timeA);
                } catch (Exception e) {
                    return b.compareTo(a);
                }
            })
            .skip(1000)
            .forEach(logProps::remove);
        
        // 保存修剪后的属性
        try (FileOutputStream out = new FileOutputStream("log.properties")) {
            logProps.store(out, "UWB人员定位卡发卡机历史记录 - 自动修剪至1000条记录");
        try (FileOutputStream out = new FileOutputStream(fileName);
             OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8")) {
            String logTypeName = fileName.equals("log.properties") ? "操作" : "错误";
            logProps.store(writer, "发卡机" + logTypeName + "记录 - 自动修剪至1000条记录");
        } catch (IOException e) {
            e.printStackTrace();
        }
@@ -252,5 +485,4 @@
            dialog.setVisible(true);
        });
    }    
}