张世豪
6 小时以前 a6077217e25f5804027194a5c2848e773eda1abd
src/xitongshezhi/lishijilu.java
@@ -1,379 +1,259 @@
package xitongshezhi;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.io.*;
import java.util.Properties;
public class lishijilu extends JFrame {
@SuppressWarnings("serial")
public class lishijilu extends JDialog {
    // 屏幕尺寸常量 - 适配7寸竖屏
    private static final int SCREEN_WIDTH = 480;
    private static final int SCREEN_HEIGHT = 800;
    // 颜色常量 - 统一使用kacaoguanli.java中的颜色定义
    private static final Color PRIMARY_COLOR = new Color(52, 152, 219);
    private static final Color DARK_COLOR = new Color(15, 28, 48);
    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 JPanel controlPanel;
    private JLabel totalRecordsLabel;
    private JLabel pickupCountLabel;
    private JLabel returnCountLabel;
    private JLabel adminCountLabel;
    private JButton refreshButton;
    private JButton clearButton;
    // 文本域组件
    private JScrollPane textScrollPane;
    private JTextArea contentTextArea;
    
    // 表格组件
    private JScrollPane tableScrollPane;
    private JTable historyTable;
    private DefaultTableModel tableModel;
    private JLabel displayCountLabel;
    // 当前显示的日志类型
    private String currentLogType = "log"; // "log" 或 "error"
    
    // 历史记录数据
    private List<HistoryRecord> historyRecords;
    private final int MAX_RECORDS = 100;
    // 颜色定义
    private final Color BACKGROUND_COLOR = new Color(15, 28, 48);
    private final Color CARD_COLOR = new Color(26, 43, 68);
    private final Color PRIMARY_COLOR = new Color(52, 152, 219);
    private final Color SECONDARY_COLOR = new Color(46, 204, 113);
    private final Color DANGER_COLOR = new Color(231, 76, 60);
    private final Color WARNING_COLOR = new Color(243, 156, 18);
    private final Color TEXT_COLOR = new Color(224, 224, 224);
    private final Color TEXT_LIGHT_COLOR = new Color(160, 200, 255);
    public lishijilu() {
        historyRecords = new ArrayList<>();
    public lishijilu(JFrame parent) {
        super(parent, "", true);
        initializeUI();
        setupEventListeners();
        loadDemoData(); // 加载演示数据
        updateDisplay();
        loadLogContent(); // 默认加载操作日志
    }
    private void initializeUI() {
        // 设置窗口属性 - 7寸竖屏 (480x800)
        setTitle("历史记录 - UWB人员定位卡发卡机管理系统");
        setSize(480, 800);
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setLocationRelativeTo(null);
        // 设置对话框属性
        setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        setLocationRelativeTo(getParent());
        setResizable(false);
        
        // 设置不透明背景
        getContentPane().setBackground(BACKGROUND_COLOR);
        // 设置系统外观
        try {
            UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        // 主面板
        mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.setBackground(BACKGROUND_COLOR);
        mainPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
        mainPanel.setBackground(DARK_COLOR);
        mainPanel.setOpaque(true);
        mainPanel.setBorder(BorderFactory.createEmptyBorder(12, 12, 12, 12));
        
        // 创建顶部标题栏
        JPanel headerPanel = createHeaderPanel();
        
        // 创建控制面板
        controlPanel = createControlPanel();
        // 创建表格区域
        JPanel tablePanel = createTablePanel();
        // 创建文本区域
        JPanel contentPanel = createContentPanel();
        
        mainPanel.add(headerPanel, BorderLayout.NORTH);
        mainPanel.add(controlPanel, BorderLayout.CENTER);
        mainPanel.add(tablePanel, BorderLayout.SOUTH);
        mainPanel.add(contentPanel, BorderLayout.CENTER);
        
        add(mainPanel);
        getContentPane().add(mainPanel);
    }
    
    private JPanel createHeaderPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(BACKGROUND_COLOR);
        panel.setPreferredSize(new Dimension(464, 40));
        JPanel headerPanel = new JPanel(new BorderLayout());
        headerPanel.setOpaque(false);
        headerPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 12, 0));
        
        // 标题
        titleLabel = new JLabel("历史记录");
        titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 18));
        titleLabel.setForeground(TEXT_COLOR);
        titleLabel.setIcon(createIcon("📜", 20));
        // 创建日志类型选择按钮面板
        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.BOLD, 12));
        backButton.setBackground(new Color(52, 152, 219, 50));
        backButton.setForeground(PRIMARY_COLOR);
        backButton.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(52, 152, 219, 75), 1),
            BorderFactory.createEmptyBorder(6, 12, 6, 12)
        ));
        backButton = new JButton("关闭");
        backButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14));
        backButton.setBackground(PRIMARY_COLOR);
        backButton.setForeground(Color.WHITE);
        backButton.setOpaque(true);
        backButton.setFocusPainted(false);
        backButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16));
        backButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        
        panel.add(titleLabel, BorderLayout.WEST);
        panel.add(backButton, BorderLayout.EAST);
        actionButtonPanel.add(deleteAllButton);
        actionButtonPanel.add(backButton);
        
        return panel;
        // 按钮悬停效果
        setupButtonHoverEffects();
        headerPanel.add(logTypePanel, BorderLayout.WEST);
        headerPanel.add(actionButtonPanel, BorderLayout.EAST);
        return headerPanel;
    }
    
    private JPanel createControlPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(CARD_COLOR);
        panel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(52, 152, 219, 25), 1),
            BorderFactory.createEmptyBorder(12, 12, 12, 12)
        ));
        panel.setPreferredSize(new Dimension(464, 80));
        // 统计信息面板
        JPanel statsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 15, 0));
        statsPanel.setBackground(CARD_COLOR);
        // 总记录
        JPanel totalPanel = createStatItem("总记录", "0");
        totalRecordsLabel = (JLabel) ((JPanel) totalPanel.getComponent(0)).getComponent(0);
        // 取卡数量
        JPanel pickupPanel = createStatItem("取卡", "0");
        pickupCountLabel = (JLabel) ((JPanel) pickupPanel.getComponent(0)).getComponent(0);
        // 还卡数量
        JPanel returnPanel = createStatItem("还卡", "0");
        returnCountLabel = (JLabel) ((JPanel) returnPanel.getComponent(0)).getComponent(0);
        // 管理员操作
        JPanel adminPanel = createStatItem("管理员操作", "0");
        adminCountLabel = (JLabel) ((JPanel) adminPanel.getComponent(0)).getComponent(0);
        statsPanel.add(totalPanel);
        statsPanel.add(pickupPanel);
        statsPanel.add(returnPanel);
        statsPanel.add(adminPanel);
        // 按钮面板
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0));
        buttonPanel.setBackground(CARD_COLOR);
        // 刷新按钮
        refreshButton = new JButton("刷新");
        refreshButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 12));
        refreshButton.setBackground(new Color(46, 204, 113, 50));
        refreshButton.setForeground(SECONDARY_COLOR);
        refreshButton.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(46, 204, 113, 75), 1),
            BorderFactory.createEmptyBorder(6, 12, 6, 12)
        ));
        refreshButton.setFocusPainted(false);
        refreshButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        // 清空按钮
        clearButton = new JButton("清空");
        clearButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 12));
        clearButton.setBackground(new Color(231, 76, 60, 50));
        clearButton.setForeground(DANGER_COLOR);
        clearButton.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(231, 76, 60, 75), 1),
            BorderFactory.createEmptyBorder(6, 12, 6, 12)
        ));
        clearButton.setFocusPainted(false);
        clearButton.setCursor(new Cursor(Cursor.HAND_CURSOR));
        buttonPanel.add(refreshButton);
        buttonPanel.add(clearButton);
        panel.add(statsPanel, BorderLayout.WEST);
        panel.add(buttonPanel, BorderLayout.EAST);
        return panel;
    }
    private JPanel createStatItem(String label, String value) {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setBackground(CARD_COLOR);
        panel.setAlignmentX(Component.CENTER_ALIGNMENT);
        JLabel valueLabel = new JLabel(value);
        valueLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16));
        valueLabel.setForeground(TEXT_COLOR);
        valueLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        JLabel nameLabel = new JLabel(label);
        nameLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 11));
        nameLabel.setForeground(TEXT_LIGHT_COLOR);
        nameLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
        panel.add(valueLabel);
        panel.add(nameLabel);
        return panel;
    }
    private JPanel createTablePanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(CARD_COLOR);
        panel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(52, 152, 219, 25), 1),
            BorderFactory.createEmptyBorder(12, 12, 12, 12)
        ));
        panel.setPreferredSize(new Dimension(464, 600));
        // 创建表格
        String[] columnNames = {"时间", "卡槽编号", "操作", "操作对象"};
        tableModel = new DefaultTableModel(columnNames, 0) {
            @Override
            public boolean isCellEditable(int row, int column) {
                return false; // 表格不可编辑
    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);
                }
            }
        });
        
        historyTable = new JTable(tableModel);
        historyTable.setFont(new Font("Microsoft YaHei", Font.PLAIN, 11));
        historyTable.setRowHeight(25);
        historyTable.setSelectionBackground(new Color(52, 152, 219, 100));
        historyTable.setGridColor(new Color(255, 255, 255, 50));
        historyTable.setShowGrid(true);
        historyTable.setIntercellSpacing(new Dimension(1, 1));
        // 错误日志按钮悬停效果
        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);
                }
            }
        });
        
        // 设置表头
        historyTable.getTableHeader().setFont(new Font("Microsoft YaHei", Font.BOLD, 11));
        historyTable.getTableHeader().setBackground(new Color(15, 28, 48, 200));
        historyTable.getTableHeader().setForeground(TEXT_LIGHT_COLOR);
        historyTable.getTableHeader().setBorder(BorderFactory.createMatteBorder(0, 0, 2, 0, new Color(52, 152, 219, 75)));
        // 删除按钮悬停效果
        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);
            }
        });
        
        // 设置列宽
        historyTable.getColumnModel().getColumn(0).setPreferredWidth(150); // 时间
        historyTable.getColumnModel().getColumn(1).setPreferredWidth(80);  // 卡槽编号
        historyTable.getColumnModel().getColumn(2).setPreferredWidth(60);  // 操作
        historyTable.getColumnModel().getColumn(3).setPreferredWidth(80);  // 操作对象
        // 返回按钮悬停效果
        backButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                backButton.setBackground(brighterColor(PRIMARY_COLOR));
            }
            public void mouseExited(java.awt.event.MouseEvent evt) {
                backButton.setBackground(PRIMARY_COLOR);
            }
        });
    }
    private JPanel createContentPanel() {
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBackground(DARK_LIGHT_COLOR);
        panel.setOpaque(true);
        panel.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createLineBorder(new Color(52, 152, 219, 26)),
            BorderFactory.createEmptyBorder(12, 12, 12, 12)
        ));
        
        // 自定义渲染器
        historyTable.setDefaultRenderer(Object.class, new HistoryTableCellRenderer());
        // 内容标题
        JPanel contentHeader = new JPanel(new BorderLayout());
        contentHeader.setOpaque(false);
        contentHeader.setBorder(BorderFactory.createCompoundBorder(
            BorderFactory.createMatteBorder(0, 0, 1, 0, new Color(255, 255, 255, 26)),
            BorderFactory.createEmptyBorder(0, 0, 8, 0)
        ));
        
        // 滚动面板
        tableScrollPane = new JScrollPane(historyTable);
        tableScrollPane.setBorder(BorderFactory.createEmptyBorder());
        tableScrollPane.getViewport().setBackground(new Color(26, 43, 68, 200));
        JLabel contentTitle = new JLabel("日志内容");
        contentTitle.setFont(new Font("Microsoft YaHei", Font.BOLD, 14));
        contentTitle.setForeground(TEXT_COLOR);
        
        // 自定义滚动条
        JScrollBar verticalScrollBar = tableScrollPane.getVerticalScrollBar();
        verticalScrollBar.setBackground(CARD_COLOR);
        verticalScrollBar.setUnitIncrement(16);
        contentHeader.add(contentTitle, BorderLayout.WEST);
        // 创建文本域
        contentTextArea = new JTextArea();
        contentTextArea.setEditable(false);
        contentTextArea.setBackground(DARK_LIGHT_COLOR);
        contentTextArea.setForeground(TEXT_COLOR);
        contentTextArea.setFont(new Font("宋体", Font.PLAIN, 12));
        contentTextArea.setLineWrap(true);
        contentTextArea.setWrapStyleWord(true);
        contentTextArea.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
        // 创建滚动面板
        textScrollPane = new JScrollPane(contentTextArea);
        textScrollPane.setBorder(BorderFactory.createEmptyBorder());
        textScrollPane.getVerticalScrollBar().setUnitIncrement(16);
        textScrollPane.setOpaque(false);
        textScrollPane.getViewport().setOpaque(false);
        
        // 底部信息栏
        JPanel footerPanel = new JPanel(new BorderLayout());
        footerPanel.setBackground(CARD_COLOR);
        footerPanel.setBackground(DARK_LIGHT_COLOR);
        footerPanel.setOpaque(true);
        footerPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, new Color(255, 255, 255, 25)));
        footerPanel.setPreferredSize(new Dimension(440, 30));
        footerPanel.setPreferredSize(new Dimension(432, 30));
        
        JLabel infoLabel = new JLabel("显示最近");
        infoLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 11));
        infoLabel.setForeground(TEXT_LIGHT_COLOR);
        displayCountLabel = new JLabel("0");
        displayCountLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 11));
        displayCountLabel.setForeground(TEXT_LIGHT_COLOR);
        JLabel recordsLabel = new JLabel("条记录");
        recordsLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 11));
        recordsLabel.setForeground(TEXT_LIGHT_COLOR);
        JPanel countPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
        countPanel.setBackground(CARD_COLOR);
        countPanel.add(infoLabel);
        countPanel.add(displayCountLabel);
        countPanel.add(recordsLabel);
        JLabel noteLabel = new JLabel("最多保留最近100条记录");
        JLabel noteLabel = new JLabel("最多保留最近1000条记录");
        noteLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 11));
        noteLabel.setForeground(TEXT_LIGHT_COLOR);
        noteLabel.setOpaque(false);
        
        footerPanel.add(countPanel, BorderLayout.WEST);
        footerPanel.add(noteLabel, BorderLayout.EAST);
        
        panel.add(tableScrollPane, BorderLayout.CENTER);
        panel.add(contentHeader, BorderLayout.NORTH);
        panel.add(textScrollPane, BorderLayout.CENTER);
        panel.add(footerPanel, BorderLayout.SOUTH);
        
        return panel;
    }
    // 自定义表格单元格渲染器
    private class HistoryTableCellRenderer extends DefaultTableCellRenderer {
        @Override
        public Component getTableCellRendererComponent(JTable table, Object value,
                                                     boolean isSelected, boolean hasFocus,
                                                     int row, int column) {
            Component comp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
            // 设置基本样式
            comp.setBackground(row % 2 == 0 ?
                new Color(26, 43, 68, 200) :
                new Color(255, 255, 255, 10));
            comp.setForeground(TEXT_COLOR);
            // 设置字体
            if (column == 0) { // 时间列使用等宽字体
                comp.setFont(new Font("Courier New", Font.PLAIN, 10));
            } else {
                comp.setFont(new Font("Microsoft YaHei", Font.PLAIN, 11));
            }
            // 操作列特殊处理
            if (column == 2 && value != null) {
                JLabel label = new JLabel(value.toString());
                label.setOpaque(true);
                label.setHorizontalAlignment(SwingConstants.CENTER);
                if (value.toString().equals("取卡")) {
                    label.setBackground(new Color(52, 152, 219, 50));
                    label.setForeground(PRIMARY_COLOR);
                    label.setBorder(BorderFactory.createCompoundBorder(
                        BorderFactory.createLineBorder(new Color(52, 152, 219, 75), 1),
                        BorderFactory.createEmptyBorder(2, 8, 2, 8)
                    ));
                } else if (value.toString().equals("还卡")) {
                    label.setBackground(new Color(46, 204, 113, 50));
                    label.setForeground(SECONDARY_COLOR);
                    label.setBorder(BorderFactory.createCompoundBorder(
                        BorderFactory.createLineBorder(new Color(46, 204, 113, 75), 1),
                        BorderFactory.createEmptyBorder(2, 8, 2, 8)
                    ));
                }
                if (isSelected) {
                    label.setBackground(new Color(52, 152, 219, 100));
                }
                return label;
            }
            // 操作对象列特殊处理
            if (column == 3 && value != null) {
                JLabel label = new JLabel(value.toString());
                label.setOpaque(true);
                label.setHorizontalAlignment(SwingConstants.CENTER);
                if (value.toString().equals("系统")) {
                    label.setBackground(new Color(149, 165, 166, 50));
                    label.setForeground(new Color(149, 165, 166));
                    label.setBorder(BorderFactory.createCompoundBorder(
                        BorderFactory.createLineBorder(new Color(149, 165, 166, 75), 1),
                        BorderFactory.createEmptyBorder(2, 8, 2, 8)
                    ));
                } else if (value.toString().equals("管理员")) {
                    label.setBackground(new Color(243, 156, 18, 50));
                    label.setForeground(WARNING_COLOR);
                    label.setBorder(BorderFactory.createCompoundBorder(
                        BorderFactory.createLineBorder(new Color(243, 156, 18, 75), 1),
                        BorderFactory.createEmptyBorder(2, 8, 2, 8)
                    ));
                }
                if (isSelected) {
                    label.setBackground(new Color(52, 152, 219, 100));
                }
                return label;
            }
            return comp;
        }
    }
    
    private void setupEventListeners() {
@@ -382,224 +262,227 @@
            dispose();
        });
        
        // 刷新按钮
        refreshButton.addActionListener(e -> {
            refreshData();
        // 删除全部记录按钮
        deleteAllButton.addActionListener(e -> {
            deleteAllRecords();
        });
        
        // 清空按钮
        clearButton.addActionListener(e -> {
            clearAllRecords();
        // 日志记录按钮
        logButton.addActionListener(e -> {
            switchToLogType("log");
        });
        // 错误日志按钮
        errorLogButton.addActionListener(e -> {
            switchToLogType("error");
        });
    }
    
    // 历史记录类
    private static class HistoryRecord {
        long id;
        String timestamp;
        int slotId;
        String operation; // "pickup" 或 "return"
        int operator; // 0=系统, 1=管理员
        HistoryRecord(long id, String timestamp, int slotId, String operation, int operator) {
            this.id = id;
            this.timestamp = timestamp;
            this.slotId = slotId;
            this.operation = operation;
            this.operator = operator;
        }
    }
    // 加载演示数据
    private void loadDemoData() {
        if (historyRecords.isEmpty()) {
            generateDemoData();
        }
    }
    // 生成演示数据
    private void generateDemoData() {
        String[] operations = {"pickup", "return"};
        int[] operators = {0, 1}; // 0=系统, 1=管理员
        long baseTime = System.currentTimeMillis() - (30L * 24 * 60 * 60 * 1000); // 30天前开始
        for (int i = 0; i < 50; i++) {
            int randomSlot = (int) (Math.random() * 60) + 1;
            String randomOperation = operations[(int) (Math.random() * operations.length)];
            int randomOperator = operators[(int) (Math.random() * operators.length)];
            long randomTime = baseTime + (long) (Math.random() * 30 * 24 * 60 * 60 * 1000);
            historyRecords.add(new HistoryRecord(
                randomTime,
                new Date(randomTime).toInstant().toString(),
                randomSlot,
                randomOperation,
                randomOperator
            ));
    // 切换日志类型
    private void switchToLogType(String logType) {
        if (currentLogType.equals(logType)) {
            return; // 已经是当前类型,无需切换
        }
        
        // 按时间排序(最新的在前面)
        historyRecords.sort((a, b) -> Long.compare(b.id, a.id));
        currentLogType = logType;
        
        // 限制为最大记录数
        if (historyRecords.size() > MAX_RECORDS) {
            historyRecords = historyRecords.subList(0, MAX_RECORDS);
        }
    }
    // 格式化时间显示
    private String formatTime(String isoString) {
        try {
            SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
            SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date date = inputFormat.parse(isoString);
            return outputFormat.format(date);
        } catch (Exception e) {
            return isoString;
        }
    }
    // 获取操作显示文本
    private String getOperationText(String operation) {
        return "pickup".equals(operation) ? "取卡" : "还卡";
    }
    // 获取操作对象显示文本
    private String getOperatorText(int operator) {
        return operator == 0 ? "系统" : "管理员";
    }
    // 更新显示
    private void updateDisplay() {
        // 更新表格
        tableModel.setRowCount(0);
        for (HistoryRecord record : historyRecords) {
            tableModel.addRow(new Object[]{
                formatTime(record.timestamp),
                record.slotId,
                getOperationText(record.operation),
                getOperatorText(record.operator)
            });
        // 更新按钮状态
        if (logType.equals("log")) {
            logButton.setBackground(ACTIVE_BUTTON_COLOR);
            errorLogButton.setBackground(PRIMARY_COLOR);
        } else {
            logButton.setBackground(PRIMARY_COLOR);
            errorLogButton.setBackground(ACTIVE_BUTTON_COLOR);
        }
        
        // 更新统计信息
        updateStats();
        // 加载对应类型的日志内容
        loadLogContent();
    }
    
    // 更新统计信息
    private void updateStats() {
        int total = historyRecords.size();
        int pickupCount = (int) historyRecords.stream()
            .filter(record -> "pickup".equals(record.operation))
            .count();
        int returnCount = (int) historyRecords.stream()
            .filter(record -> "return".equals(record.operation))
            .count();
        int adminCount = (int) historyRecords.stream()
            .filter(record -> record.operator == 1)
            .count();
        totalRecordsLabel.setText(String.valueOf(total));
        pickupCountLabel.setText(String.valueOf(pickupCount));
        returnCountLabel.setText(String.valueOf(returnCount));
        adminCountLabel.setText(String.valueOf(adminCount));
        displayCountLabel.setText(String.valueOf(total));
    }
    // 刷新数据
    private void refreshData() {
        String originalText = refreshButton.getText();
        // 显示刷新中状态
        refreshButton.setText("刷新中...");
        refreshButton.setEnabled(false);
        // 模拟数据刷新延迟
        Timer timer = new Timer(800, e -> {
            updateDisplay();
            // 恢复按钮状态
            refreshButton.setText(originalText);
            refreshButton.setEnabled(true);
        });
        timer.setRepeats(false);
        timer.start();
    }
    // 清空所有记录
    private void clearAllRecords() {
    // 删除全部记录的方法
    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) {
            historyRecords.clear();
            updateDisplay();
            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 addTestRecord() {
        int randomSlot = (int) (Math.random() * 60) + 1;
        String randomOperation = Math.random() > 0.5 ? "pickup" : "return";
        int randomOperator = Math.random() > 0.7 ? 1 : 0; // 30%概率为管理员操作
    // 加载日志内容
    private void loadLogContent() {
        String fileName = currentLogType.equals("log") ? "log.properties" : "err.properties";
        String logTypeName = currentLogType.equals("log") ? "操作" : "错误";
        
        historyRecords.add(0, new HistoryRecord(
            System.currentTimeMillis(),
            new Date().toInstant().toString(),
            randomSlot,
            randomOperation,
            randomOperator
        ));
        File logFile = new File(fileName);
        
        // 限制为最大记录数
        if (historyRecords.size() > MAX_RECORDS) {
            historyRecords.remove(historyRecords.size() - 1);
        if (!logFile.exists()) {
            contentTextArea.setText(logTypeName + "日志文件不存在。");
            return;
        }
        
        updateDisplay();
    }
    // 创建图标(使用文本表情符号)
    private Icon createIcon(String emoji, int size) {
        JLabel label = new JLabel(emoji);
        label.setFont(new Font("Segoe UI Emoji", Font.PLAIN, size));
        return new Icon() {
            @Override
            public void paintIcon(Component c, Graphics g, int x, int y) {
                label.setBounds(x, y, getIconWidth(), getIconHeight());
                label.paint(g);
        Properties logProps = new Properties();
        try (FileInputStream in = new FileInputStream(logFile);
             InputStreamReader reader = new InputStreamReader(in, "UTF-8")) {
            logProps.load(reader);
            // 检查记录数量,如果超过1000条则删除旧记录
            if (logProps.size() > 1000) {
                trimLogProperties(logProps, fileName);
            }
            
            @Override
            public int getIconWidth() {
                return size;
            }
            // 构建显示内容
            StringBuilder content = new StringBuilder();
            content.append(logTypeName).append("日志内容 (").append(logProps.size()).append(" 条记录):\n\n");
            
            @Override
            public int getIconHeight() {
                return size;
            }
        };
    }
    // 主方法测试
    public static void main(String[] args) {
        // 设置系统外观
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel());
            // 按时间戳排序显示
            logProps.stringPropertyNames().stream()
                .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(extractTimeFromValue(value)).append("\n");
                    content.append("内容: ").append(extractOperationFromValue(value)).append("\n");
                    content.append("----------------------------------------\n");
                });
            contentTextArea.setText(content.toString());
        } catch (IOException e) {
            e.printStackTrace();
            contentTextArea.setText("加载" + logTypeName + "日志文件时出错: " + e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            contentTextArea.setText("处理" + logTypeName + "日志内容时出错: " + e.getMessage());
        }
        SwingUtilities.invokeLater(() -> {
            lishijilu frame = new lishijilu();
            frame.setVisible(true);
        });
    }
    // 从键中提取时间戳
    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, String fileName) {
        // 按时间戳排序,保留最新的1000条
        logProps.stringPropertyNames().stream()
            .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(fileName);
             OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8")) {
            String logTypeName = fileName.equals("log.properties") ? "操作" : "错误";
            logProps.store(writer, "发卡机" + logTypeName + "记录 - 自动修剪至1000条记录");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    // 新增辅助方法:使颜色更亮
    private Color brighterColor(Color color) {
        int r = Math.min(255, color.getRed() + 30);
        int g = Math.min(255, color.getGreen() + 30);
        int b = Math.min(255, color.getBlue() + 30);
        return new Color(r, g, b);
    }
    // 静态方法:从其他页面调用
    public static void showHistoryDialog(JFrame parent) {
        SwingUtilities.invokeLater(() -> {
            lishijilu dialog = new lishijilu(parent);
            dialog.setVisible(true);
        });
    }
}