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; public class lishijilu extends JFrame { 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 tableScrollPane; private JTable historyTable; private DefaultTableModel tableModel; private JLabel displayCountLabel; // 历史记录数据 private List 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<>(); initializeUI(); setupEventListeners(); loadDemoData(); // 加载演示数据 updateDisplay(); } private void initializeUI() { // 设置窗口属性 - 7寸竖屏 (480x800) setTitle("历史记录 - UWB人员定位卡发卡机管理系统"); setSize(480, 800); setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setLocationRelativeTo(null); setResizable(false); // 设置不透明背景 getContentPane().setBackground(BACKGROUND_COLOR); // 主面板 mainPanel = new JPanel(); mainPanel.setLayout(new BorderLayout()); mainPanel.setBackground(BACKGROUND_COLOR); mainPanel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8)); // 创建顶部标题栏 JPanel headerPanel = createHeaderPanel(); // 创建控制面板 controlPanel = createControlPanel(); // 创建表格区域 JPanel tablePanel = createTablePanel(); mainPanel.add(headerPanel, BorderLayout.NORTH); mainPanel.add(controlPanel, BorderLayout.CENTER); mainPanel.add(tablePanel, BorderLayout.SOUTH); add(mainPanel); } private JPanel createHeaderPanel() { JPanel panel = new JPanel(new BorderLayout()); panel.setBackground(BACKGROUND_COLOR); panel.setPreferredSize(new Dimension(464, 40)); // 标题 titleLabel = new JLabel("历史记录"); titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 18)); 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.setFocusPainted(false); backButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); panel.add(titleLabel, BorderLayout.WEST); panel.add(backButton, BorderLayout.EAST); return panel; } 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; // 表格不可编辑 } }; 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); // 底部信息栏 JPanel footerPanel = new JPanel(new BorderLayout()); footerPanel.setBackground(CARD_COLOR); footerPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, new Color(255, 255, 255, 25))); footerPanel.setPreferredSize(new Dimension(440, 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条记录"); noteLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 11)); noteLabel.setForeground(TEXT_LIGHT_COLOR); footerPanel.add(countPanel, BorderLayout.WEST); footerPanel.add(noteLabel, BorderLayout.EAST); panel.add(tableScrollPane, 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(); }); // 清空按钮 clearButton.addActionListener(e -> { clearAllRecords(); }); } // 历史记录类 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 )); } // 按时间排序(最新的在前面) 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) { e.printStackTrace(); } SwingUtilities.invokeLater(() -> { lishijilu frame = new lishijilu(); frame.setVisible(true); }); } }