package com.ytlk.ocr; import com.ytlk.huidan.table.ButtonRenderer; import com.ytlk.huidan.table.LabelRenderer; import com.ytlk.ocr.table.*; import com.ytlk.ocr.util.FileUtils; import com.ytlk.ocr.vo.UserErrorVo; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.TableColumn; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.List; import java.util.Map; public class OCRSwingArea extends JFrame { private static OCRSwingArea instance = null; public static JTable table; public static JTable table2; public static final int MAX_FILE_NUM = 5; private OCRSwingArea() { setOpacity(0.0f); this.setTitle("工资发放OCR识别与核对工具"); this.setResizable(false); // this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); this.setBounds(0, 0, 1000, 565); setLocationRelativeTo(null); getContentPane().setLayout(null); getContentPane().setBackground(new Color(236, 236, 248)); /**********************工资册源版文件导入:(Excel表格)*******************/ JLabel label1 = new JLabel("工资册源版文件导入:"); label1.setHorizontalAlignment(JLabel.LEFT); label1.setFont(new Font("微软雅黑", Font.BOLD, 14)); label1.setBounds(15, 10, 160, 30); label1.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直对齐方式 getContentPane().add(label1); JLabel label2 = new JLabel("(Excel表格)"); label2.setHorizontalAlignment(JLabel.LEFT); label2.setFont(new Font("微软雅黑", Font.BOLD, 14)); label2.setBounds(45, 30, 100, 30); label2.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直对齐方式 getContentPane().add(label2); // 添加文件按钮 JButton selectFile = new JButton("添加"); selectFile.setFont(new Font("微软雅黑", Font.PLAIN, 15)); selectFile.setBounds(200, 20, 80, 30); getContentPane().add(selectFile); // 重置文件按钮 JButton resetFile = new JButton("重置"); resetFile.setFont(new Font("微软雅黑", Font.PLAIN, 15)); resetFile.setBounds(300, 20, 80, 30); getContentPane().add(resetFile); // 文件表格 FileTableModel fileTableModel = new FileTableModel(); table = new JTable(fileTableModel); table.setRowSelectionAllowed(false); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); TableColumn labelColumn = table.getColumn("文件"); labelColumn.setCellRenderer(new LabelRenderer()); labelColumn.setPreferredWidth(390); TableColumn buttonColumn = table.getColumn("操作"); buttonColumn.setPreferredWidth(80); buttonColumn.setCellRenderer(new ButtonRenderer()); buttonColumn.setCellEditor(new OCRTableCellEditorButton()); JScrollPane statusScrollPane1 = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); statusScrollPane1.setBounds(15, 60, 480, 350); getContentPane().add(statusScrollPane1); /**********************工资册源版文件导入:添加按钮监听事件*******************/ selectFile.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); fc.setMultiSelectionEnabled(true); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); fc.setFileFilter(new FileNameExtensionFilter("Excel Files (*.xls, *.xlsx)", "xls", "xlsx")); fc.setAcceptAllFileFilterUsed(false); int val = fc.showOpenDialog(null); // 文件打开对话框 if (val == fc.APPROVE_OPTION) { // 正常选择文件 File[] fs = fc.getSelectedFiles(); boolean flag = FileUtils.getTableFileName(fileTableModel, fs); if (flag) { JOptionPane.showMessageDialog(null, "请勿选择相同工资册源版文件"); return; } int isExceedFileNum = FileUtils.isExceedFileNum(fileTableModel, fs); if (isExceedFileNum > MAX_FILE_NUM) { JOptionPane.showMessageDialog(null, "工资册源版文件超出" + MAX_FILE_NUM + "个文件限制"); return; } for (File f : fs) { fileTableModel.addRow(new Object[]{f, ""}); OCRSwingArea.table.setValueAt(0, table.getRowCount() - 1, 1); } } } }); /**********************工资册源版文件导入:重置按钮监听事件*******************/ resetFile.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int rows = fileTableModel.getRowCount(); if (rows > 0) { for (int i = rows - 1; i >= 0; i--) { fileTableModel.removeRow(i); } } } }); /**********************工资册签字版导入:(PDF)*******************/ JLabel label3 = new JLabel("工资册签字版导入:"); label3.setHorizontalAlignment(JLabel.LEFT); label3.setFont(new Font("微软雅黑", Font.BOLD, 14)); label3.setBounds(500, 10, 160, 30); label3.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直对齐方式 getContentPane().add(label3); JLabel label4 = new JLabel("(PDF)"); label4.setHorizontalAlignment(JLabel.LEFT); label4.setFont(new Font("微软雅黑", Font.BOLD, 14)); label4.setBounds(530, 30, 100, 30); label4.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直对齐方式 getContentPane().add(label4); // 添加文件按钮2 JButton selectFile2 = new JButton("添加"); selectFile2.setFont(new Font("微软雅黑", Font.PLAIN, 15)); selectFile2.setBounds(650, 20, 80, 30); getContentPane().add(selectFile2); // 重置文件按钮2 JButton resetFile2 = new JButton("重置"); resetFile2.setFont(new Font("微软雅黑", Font.PLAIN, 15)); resetFile2.setBounds(750, 20, 80, 30); getContentPane().add(resetFile2); // 文件表格2 FileTableModel fileTableModel2 = new FileTableModel(); table2 = new JTable(fileTableModel2); table2.setRowSelectionAllowed(false); table2.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); TableColumn buttonColumn2 = table2.getColumn("操作"); buttonColumn2.setPreferredWidth(80); buttonColumn2.setCellRenderer(new ButtonRenderer()); buttonColumn2.setCellEditor(new OCRTableCellEditorButton2()); TableColumn labelColumn2 = table2.getColumn("文件"); labelColumn2.setCellRenderer(new LabelRenderer()); labelColumn2.setPreferredWidth(390); JScrollPane statusScrollPane2 = new JScrollPane(table2, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); statusScrollPane2.setBounds(500, 60, 480, 350); getContentPane().add(statusScrollPane2); /**********************工资册签字版导入:添加按钮监听事件*******************/ selectFile2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser fc = new JFileChooser(); fc.setMultiSelectionEnabled(true); fc.setFileSelectionMode(JFileChooser.FILES_ONLY); fc.setFileFilter(new FileNameExtensionFilter("PDF Documents", "pdf")); // fc.setFileFilter(new FileNameExtensionFilter("Excel Files (*.xls, *.xlsx)", "xls", "xlsx")); fc.setAcceptAllFileFilterUsed(false); int val = fc.showOpenDialog(null); // 文件打开对话框 if (val == fc.APPROVE_OPTION) { // 正常选择文件 File[] fs = fc.getSelectedFiles(); boolean flag = FileUtils.getTableFileName(fileTableModel2, fs); if (flag) { JOptionPane.showMessageDialog(null, "请勿选择相同工资册签字版文件"); return; } int isExceedFileNum = FileUtils.isExceedFileNum(fileTableModel2, fs); if (isExceedFileNum > MAX_FILE_NUM) { JOptionPane.showMessageDialog(null, "工资册签字版文件超出" + MAX_FILE_NUM + "个文件限制"); return; } for (File f : fs) { fileTableModel2.addRow(new Object[]{f, ""}); OCRSwingArea.table2.setValueAt(0, table2.getRowCount() - 1, 1); } } } }); /**********************工资册签字版导入:重置按钮监听事件*******************/ resetFile2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int rows = fileTableModel2.getRowCount(); if (rows > 0) { for (int i = rows - 1; i >= 0; i--) { fileTableModel2.removeRow(i); } } } }); /**********************提示*******************/ JLabel label5 = new JLabel("注:1.支持批量导入进行核定"); label5.setHorizontalAlignment(JLabel.LEFT); label5.setFont(new Font("微软雅黑", Font.PLAIN, 14)); label5.setBounds(15, 430, 350, 30); label5.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直对齐方式 label5.setForeground(Color.RED); getContentPane().add(label5); JLabel label6 = new JLabel("2.请保证需核对的Excel与PDF文件名称一致"); label6.setHorizontalAlignment(JLabel.LEFT); label6.setFont(new Font("微软雅黑", Font.PLAIN, 14)); label6.setBounds(43, 450, 350, 30); label6.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直对齐方式 label6.setForeground(Color.RED); getContentPane().add(label6); JLabel label7 = new JLabel("3.请保证文件中包含有【姓名】【实发工资】字段"); label7.setHorizontalAlignment(JLabel.LEFT); label7.setFont(new Font("微软雅黑", Font.PLAIN, 14)); label7.setBounds(43, 470, 350, 30); label7.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直对齐方式 label7.setForeground(Color.RED); getContentPane().add(label7); JLabel label8 = new JLabel("4.Excel文件、PDF文件最多只能各上传五个文件"); label8.setHorizontalAlignment(JLabel.LEFT); label8.setFont(new Font("微软雅黑", Font.PLAIN, 14)); label8.setBounds(43, 490, 350, 30); label8.setVerticalAlignment(SwingConstants.CENTER); // 设置垂直对齐方式 label8.setForeground(Color.RED); getContentPane().add(label8); /**********************开始核对*******************/ JButton startCheckBtn = new JButton("开 始 核 对"); startCheckBtn.setFont(new Font("微软雅黑", Font.BOLD, 18)); startCheckBtn.setBounds(500, 450, 400, 40); getContentPane().add(startCheckBtn); startCheckBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int rowCount = fileTableModel.getRowCount(); int rowCount2 = fileTableModel2.getRowCount(); setButtonDisable(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); if (rowCount == 0) { JOptionPane.showMessageDialog(null, "请先上传工资册源版文件"); setButtonEnable(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); return; } if (rowCount2 == 0) { JOptionPane.showMessageDialog(null, "请先上传工资册签字版文件"); setButtonEnable(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); return; } boolean flag = FileUtils.fileIsEquality(fileTableModel, fileTableModel2); if (flag) { JOptionPane.showMessageDialog(null, "请确保工资册源版文件与工资册签字版文件数量相等"); setButtonEnable(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); return; } boolean flag2 = FileUtils.fileNameIsEquality(fileTableModel, fileTableModel2); if (flag2) { JOptionPane.showMessageDialog(null, "请确保工资册源版文件与工资册签字版文件文件名称一致"); setButtonEnable(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); return; } showLoadingDialog(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); } }); // 添加 WindowAdapter 关闭的监听事件 addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.out.println("窗口正在关闭"); // 在这里执行关闭前的操作 int rows = fileTableModel.getRowCount(); if (rows > 0) { for (int i = rows - 1; i >= 0; i--) { fileTableModel.removeRow(i); } } int rows2 = fileTableModel2.getRowCount(); if (rows2 > 0) { for (int i = rows2 - 1; i >= 0; i--) { fileTableModel2.removeRow(i); } } } }); } public void setButtonEnable(JButton selectFile, JButton selectFile2, JButton resetFile, JButton resetFile2, JButton startCheckBtn) { selectFile.setEnabled(true); selectFile2.setEnabled(true); resetFile.setEnabled(true); resetFile2.setEnabled(true); startCheckBtn.setEnabled(true); } public void setButtonDisable(JButton selectFile, JButton selectFile2, JButton resetFile, JButton resetFile2, JButton startCheckBtn) { selectFile.setEnabled(false); selectFile2.setEnabled(false); resetFile.setEnabled(false); resetFile2.setEnabled(false); startCheckBtn.setEnabled(false); } /** * 执行比较结果 * * @param selectFile * @param selectFile2 * @param resetFile * @param resetFile2 * @param startCheckBtn * @return void * @author cwchen * @date 2025/3/11 17:19 */ public void showLoadingDialog(JButton selectFile, JButton selectFile2, JButton resetFile, JButton resetFile2, JButton startCheckBtn) { JFrame parent = this; // 创建加载框 JDialog loadingDialog = new JDialog(parent, "核对中", true); loadingDialog.setSize(400, 150); loadingDialog.setLocationRelativeTo(parent); // 禁用关闭按钮 loadingDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); // 添加加载提示 JLabel label = new JLabel("正在处理中,请稍后...", SwingConstants.CENTER); label.setFont(new Font("微软雅黑", Font.PLAIN, 16)); label.setBounds(15, 10, 400, 30); JLabel label2 = new JLabel("等待时间可能较长,正在OCR识别、表格提取、数据比对中...", SwingConstants.CENTER); label2.setFont(new Font("微软雅黑", Font.PLAIN, 12)); label2.setBounds(15, 30, 400, 30); loadingDialog.add(label); loadingDialog.add(label2); new Thread(() -> { try { Object obj = HandleDataUtil.handleData(); if (obj instanceof String) { String checkExcelData = (String) obj; if (StringUtils.isNotBlank(checkExcelData)) { // 任务完成后关闭加载框 loadingDialog.dispose(); setButtonEnable(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); JOptionPane.showMessageDialog(null, checkExcelData); } } else if (obj instanceof List) { loadingDialog.dispose(); setButtonEnable(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); List> errorDataList = (List>) obj; showModalDialog(errorDataList); } } catch (Exception e) { e.printStackTrace(); // 任务完成后关闭加载框 loadingDialog.dispose(); setButtonEnable(selectFile, selectFile2, resetFile, resetFile2, startCheckBtn); } }).start(); // 显示加载框 loadingDialog.setVisible(true); } public void showModalDialog(List> errorDataList) { JFrame parent = this; // 创建模态对话框 JDialog dialog = new JDialog(parent, "比对结果", true); // true表示模态 dialog.setSize(690, 450); dialog.setLocationRelativeTo(parent); // 相对于父窗口居中显示 dialog.setLayout(new FlowLayout()); JPanel parentContentPanel = new JPanel(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; // 列索引 gbc.fill = GridBagConstraints.HORIZONTAL; // 水平填充 gbc.weightx = 1; // 水平权重 parentContentPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); // 设置内边距 String[] columnNames = {"姓名", "Excel表格实发工资", "PDF实发工资","异常项"}; for (int i = 0; i < errorDataList.size(); i++) { Map map = errorDataList.get(i); JPanel childContentPanel = new JPanel(); childContentPanel.setLayout(new BoxLayout(childContentPanel, BoxLayout.Y_AXIS)); // 垂直布局 String fileName = (String) map.get("fileName"); List errorList = (List) map.get("errorList"); JLabel label = new JLabel(fileName); JLabel label2 = new JLabel(" 异常数据" + errorList.size() + "条"); JButton toggleButton = new JButton("收起/展开"); toggleButton.setPreferredSize(new Dimension(80, 30)); label2.setForeground(Color.RED); JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT)); // 左对齐 panel.add(label); panel.add(label2); panel.add(toggleButton); childContentPanel.add(panel); if (CollectionUtils.isNotEmpty(errorList)) { ErrorTableModel errorTableModel = new ErrorTableModel(errorList, columnNames); JTable errorTable = new JTable(errorTableModel); errorTable.setRowSelectionAllowed(false); errorTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); errorTable.setRowHeight(25); // 设置行高 TableColumn cellColumn = errorTable.getColumn("姓名"); cellColumn.setPreferredWidth(100); TableColumn cellColumn2 = errorTable.getColumn("Excel表格实发工资"); cellColumn2.setPreferredWidth(150); TableColumn cellColumn3 = errorTable.getColumn("PDF实发工资"); cellColumn3.setPreferredWidth(150); TableColumn cellColumn4 = errorTable.getColumn("异常项"); cellColumn4.setPreferredWidth(200); JScrollPane jScrollPane = new JScrollPane(errorTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); JPanel panel2 = new JPanel(); panel2.setLayout(new BoxLayout(panel2, BoxLayout.Y_AXIS)); // 垂直排列 panel2.add(jScrollPane); // 计算表格总高度 int rowHeight = errorTable.getRowHeight(); int rowCount = errorTable.getRowCount(); int tableHeight = rowHeight * rowCount + 50; panel2.setPreferredSize(new Dimension(600, tableHeight)); toggleButton.addActionListener(new ToggleListener(panel2)); // 为每个按钮添加监听器 childContentPanel.add(panel2); } gbc.gridy = i; // 行索引 parentContentPanel.add(childContentPanel,gbc); } gbc.gridy = errorDataList.size() + 1; gbc.weighty = 1; // 垂直权重,使组件占满剩余空间 gbc.fill = GridBagConstraints.BOTH; // 组件水平和垂直填充 parentContentPanel.add(new JLabel(""), gbc); // 添加一个空标签占位 // 创建JScrollPane并设置其滚动条策略(可选) JScrollPane scrollPane = new JScrollPane(parentContentPanel); scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); // 水平滚动条按需显示 scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); // 垂直滚动条按需显示 scrollPane.setPreferredSize(new Dimension(660, 400)); // 设置滚动面板的尺寸,以适应内容或手动设置大小 dialog.add(scrollPane); dialog.setVisible(true); } public String getTime(String time) { if (time.startsWith("0")) { return time.substring(1); } else { return time; } } public File getCurrenPath() { try { String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getFile(); path = java.net.URLDecoder.decode(path, "UTF-8"); File file = new File(path); if (file.isFile()) { return new File(file.getParent()); } else { return file; } } catch (UnsupportedEncodingException e) { e.printStackTrace(); throw new RuntimeException(e); } } public void deleteTemp() { File path = getCurrenPath(); File dir = path.getParentFile(); for (File f : dir.listFiles()) { if (!f.getAbsoluteFile().equals(path.getAbsolutePath())) { File zb = new File(f.getAbsoluteFile() + File.separator + "hdpdf.jar"); if (zb.exists()) { for (File t : f.listFiles()) { t.delete(); } f.delete(); } } } } public File getCurrentJarDir() { try { File f = new File("."); if (f.exists()) { return f; } return getCurrenPath(); } catch (Exception e) { throw new RuntimeException(e); } } private JPanel createLabel(String v, List kws, JPanel sp) { // Icon icon = new ImageIcon(getClass().getResource("/close.jpg")); JPanel p = new JPanel(); p.setLayout(new BorderLayout()); JLabel lbl = new JLabel(v); lbl.setFont(new Font("微软雅黑", Font.PLAIN, 16)); // p.setBorder(BorderFactory.createLineBorder(Color.gray)); p.add(lbl, BorderLayout.CENTER); JButton bt = new JButton("X"); // bt.setIcon(icon); bt.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { remove(v, kws, sp); } }); p.add(bt, BorderLayout.EAST); return p; } private void remove(String v, List keywords, JPanel sp) { for (int i = keywords.size() - 1; i >= 0; i--) { if (keywords.get(i).equals(v)) { keywords.remove(i); break; } } sp.removeAll(); for (String k : keywords) { JPanel p = createLabel(k, keywords, sp); sp.add(p); } sp.revalidate(); sp.repaint(); } public static OCRSwingArea getInstance() { if (null == instance) { synchronized (OCRSwingArea.class) { if (null == instance) { instance = new OCRSwingArea(); } } } return instance; } public void initUI() { this.setVisible(true); deleteTemp(); } }