| | |
| | | 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 JPanel mainPanel; |
| | | private JLabel titleLabel; |
| | | private JButton backButton; |
| | | |
| | | // 控制面板组件 |
| | | 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 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.setFont(new Font("Microsoft YaHei", Font.BOLD, 22)); |
| | | titleLabel.setForeground(TEXT_COLOR); |
| | | titleLabel.setIcon(createIcon("📜", 20)); |
| | | |
| | | // 返回按钮 |
| | | 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); |
| | | |
| | | return panel; |
| | | // 返回按钮悬停效果 |
| | | backButton.addMouseListener(new java.awt.event.MouseAdapter() { |
| | | public void mouseEntered(java.awt.event.MouseEvent evt) { |
| | | backButton.setBackground(brighterColor(PRIMARY_COLOR)); |
| | | } |
| | | |
| | | private JPanel createControlPanel() { |
| | | public void mouseExited(java.awt.event.MouseEvent evt) { |
| | | 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() { |
| | | JPanel panel = new JPanel(new BorderLayout()); |
| | | panel.setBackground(CARD_COLOR); |
| | | panel.setBackground(DARK_LIGHT_COLOR); |
| | | panel.setOpaque(true); |
| | | panel.setBorder(BorderFactory.createCompoundBorder( |
| | | BorderFactory.createLineBorder(new Color(52, 152, 219, 25), 1), |
| | | BorderFactory.createLineBorder(new Color(52, 152, 219, 26)), |
| | | 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) |
| | | // 内容标题 |
| | | 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) |
| | | )); |
| | | 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)); |
| | | JLabel contentTitle = new JLabel("日志内容"); |
| | | contentTitle.setFont(new Font("Microsoft YaHei", Font.BOLD, 14)); |
| | | contentTitle.setForeground(TEXT_COLOR); |
| | | |
| | | buttonPanel.add(refreshButton); |
| | | buttonPanel.add(clearButton); |
| | | contentHeader.add(contentTitle, BorderLayout.WEST); |
| | | |
| | | panel.add(statsPanel, BorderLayout.WEST); |
| | | panel.add(buttonPanel, BorderLayout.EAST); |
| | | // 创建文本域 |
| | | 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)); |
| | | |
| | | 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; // 表格不可编辑 |
| | | } |
| | | }; |
| | | |
| | | 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)); |
| | | |
| | | // 设置表头 |
| | | 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))); |
| | | |
| | | // 设置列宽 |
| | | historyTable.getColumnModel().getColumn(0).setPreferredWidth(150); // 时间 |
| | | historyTable.getColumnModel().getColumn(1).setPreferredWidth(80); // 卡槽编号 |
| | | historyTable.getColumnModel().getColumn(2).setPreferredWidth(60); // 操作 |
| | | historyTable.getColumnModel().getColumn(3).setPreferredWidth(80); // 操作对象 |
| | | |
| | | // 自定义渲染器 |
| | | historyTable.setDefaultRenderer(Object.class, new HistoryTableCellRenderer()); |
| | | |
| | | // 滚动面板 |
| | | tableScrollPane = new JScrollPane(historyTable); |
| | | tableScrollPane.setBorder(BorderFactory.createEmptyBorder()); |
| | | tableScrollPane.getViewport().setBackground(new Color(26, 43, 68, 200)); |
| | | |
| | | // 自定义滚动条 |
| | | JScrollBar verticalScrollBar = tableScrollPane.getVerticalScrollBar(); |
| | | verticalScrollBar.setBackground(CARD_COLOR); |
| | | verticalScrollBar.setUnitIncrement(16); |
| | | // 创建滚动面板 |
| | | 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() { |
| | |
| | | backButton.addActionListener(e -> { |
| | | dispose(); |
| | | }); |
| | | } |
| | | |
| | | // 刷新按钮 |
| | | refreshButton.addActionListener(e -> { |
| | | refreshData(); |
| | | // 加载日志内容 |
| | | private void loadLogContent() { |
| | | File logFile = new File("log.properties"); |
| | | |
| | | if (!logFile.exists()) { |
| | | contentTextArea.setText("日志文件不存在。"); |
| | | return; |
| | | } |
| | | |
| | | Properties logProps = new Properties(); |
| | | try (FileInputStream in = new FileInputStream(logFile)) { |
| | | logProps.load(in); |
| | | |
| | | // 检查记录数量,如果超过1000条则删除旧记录 |
| | | if (logProps.size() > 1000) { |
| | | trimLogProperties(logProps); |
| | | } |
| | | |
| | | // 构建显示内容 |
| | | StringBuilder content = new StringBuilder(); |
| | | content.append("日志文件内容 (").append(logProps.size()).append(" 条记录):\n\n"); |
| | | |
| | | // 按时间戳排序显示 |
| | | logProps.stringPropertyNames().stream() |
| | | .sorted((a, b) -> Long.compare(Long.parseLong(b), Long.parseLong(a))) |
| | | .forEach(key -> { |
| | | String value = logProps.getProperty(key); |
| | | content.append("时间戳: ").append(key).append("\n"); |
| | | content.append("内容: ").append(value).append("\n"); |
| | | content.append("----------------------------------------\n"); |
| | | }); |
| | | |
| | | // 清空按钮 |
| | | clearButton.addActionListener(e -> { |
| | | clearAllRecords(); |
| | | }); |
| | | } |
| | | contentTextArea.setText(content.toString()); |
| | | |
| | | // 历史记录类 |
| | | 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; |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | contentTextArea.setText("加载日志文件时出错: " + e.getMessage()); |
| | | } catch (NumberFormatException e) { |
| | | contentTextArea.setText("日志文件格式错误。"); |
| | | } |
| | | } |
| | | |
| | | // 加载演示数据 |
| | | private void loadDemoData() { |
| | | if (historyRecords.isEmpty()) { |
| | | generateDemoData(); |
| | | } |
| | | } |
| | | // 修剪日志属性,只保留最新的1000条记录 |
| | | private void trimLogProperties(Properties logProps) { |
| | | // 按时间戳排序,保留最新的1000条 |
| | | logProps.stringPropertyNames().stream() |
| | | .sorted((a, b) -> Long.compare(Long.parseLong(b), Long.parseLong(a))) |
| | | .skip(1000) |
| | | .forEach(logProps::remove); |
| | | |
| | | // 生成演示数据 |
| | | 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 |
| | | )); |
| | | } |
| | | |
| | | // 按时间排序(最新的在前面) |
| | | historyRecords.sort((a, b) -> Long.compare(b.id, a.id)); |
| | | |
| | | // 限制为最大记录数 |
| | | 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) |
| | | }); |
| | | } |
| | | |
| | | // 更新统计信息 |
| | | updateStats(); |
| | | } |
| | | |
| | | // 更新统计信息 |
| | | 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() { |
| | | int result = JOptionPane.showConfirmDialog( |
| | | this, |
| | | "确定要清空所有历史记录吗?此操作不可恢复。", |
| | | "确认清空", |
| | | JOptionPane.YES_NO_OPTION, |
| | | JOptionPane.WARNING_MESSAGE |
| | | ); |
| | | |
| | | if (result == JOptionPane.YES_OPTION) { |
| | | historyRecords.clear(); |
| | | updateDisplay(); |
| | | } |
| | | } |
| | | |
| | | // 添加测试记录(用于演示) |
| | | 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%概率为管理员操作 |
| | | |
| | | historyRecords.add(0, new HistoryRecord( |
| | | System.currentTimeMillis(), |
| | | new Date().toInstant().toString(), |
| | | randomSlot, |
| | | randomOperation, |
| | | randomOperator |
| | | )); |
| | | |
| | | // 限制为最大记录数 |
| | | if (historyRecords.size() > MAX_RECORDS) { |
| | | historyRecords.remove(historyRecords.size() - 1); |
| | | } |
| | | |
| | | 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); |
| | | } |
| | | |
| | | @Override |
| | | public int getIconWidth() { |
| | | return size; |
| | | } |
| | | |
| | | @Override |
| | | public int getIconHeight() { |
| | | return size; |
| | | } |
| | | }; |
| | | } |
| | | |
| | | // 主方法测试 |
| | | public static void main(String[] args) { |
| | | // 设置系统外观 |
| | | try { |
| | | UIManager.setLookAndFeel(UIManager.getSystemLookAndFeel()); |
| | | } catch (Exception e) { |
| | | // 保存修剪后的属性 |
| | | try (FileOutputStream out = new FileOutputStream("log.properties")) { |
| | | logProps.store(out, "UWB人员定位卡发卡机历史记录 - 自动修剪至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 frame = new lishijilu(); |
| | | frame.setVisible(true); |
| | | lishijilu dialog = new lishijilu(parent); |
| | | dialog.setVisible(true); |
| | | }); |
| | | } |
| | | |
| | | } |