From ef336b906d03f2125096a00bc79904a51d91a291 Mon Sep 17 00:00:00 2001 From: "youhong.ai" Date: Tue, 4 Jul 2023 12:30:53 +0800 Subject: [PATCH] =?UTF-8?q?=E8=87=AA=E5=8A=A8=E6=89=93=E5=8C=85=E5=B7=A5?= =?UTF-8?q?=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FileSelectionApp.java | 171 ++++++++++++++++ checked.png | Bin 0 -> 14821 bytes icons/file.png | Bin 0 -> 14116 bytes icons/folder.png | Bin 0 -> 13998 bytes package.py | 103 ++++++++++ pom.xml | 7 +- .../impl/CompressDocPictureImpl.java | 10 +- src/test/java/FileCompressor.java | 63 ++++++ src/test/java/FileInfo.java | 61 ++++++ src/test/java/FileTreeBuilder.java | 110 +++++++++++ src/test/java/TreeViewExample.java | 182 ++++++++++++++++++ src/test/java/basetest/BaseTest.java | 4 +- src/test/resources/icons/file.png | Bin 0 -> 14116 bytes src/test/resources/icons/folder.png | Bin 0 -> 13998 bytes src/test/resources/style.css | 28 +++ unchecked.png | Bin 0 -> 14454 bytes 16 files changed, 734 insertions(+), 5 deletions(-) create mode 100644 FileSelectionApp.java create mode 100644 checked.png create mode 100644 icons/file.png create mode 100644 icons/folder.png create mode 100644 package.py create mode 100644 src/test/java/FileCompressor.java create mode 100644 src/test/java/FileInfo.java create mode 100644 src/test/java/FileTreeBuilder.java create mode 100644 src/test/java/TreeViewExample.java create mode 100644 src/test/resources/icons/file.png create mode 100644 src/test/resources/icons/folder.png create mode 100644 src/test/resources/style.css create mode 100644 unchecked.png diff --git a/FileSelectionApp.java b/FileSelectionApp.java new file mode 100644 index 0000000..38d3f4d --- /dev/null +++ b/FileSelectionApp.java @@ -0,0 +1,171 @@ +import java.awt.BorderLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTree; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreePath; + +public class FileSelectionApp extends JFrame { + private JTree fileTree; + private JCheckBox[] checkBoxes; + private JLabel statusLabel; + + public FileSelectionApp() { + setTitle("文件选择"); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setSize(600, 400); + setLocationRelativeTo(null); + + // 创建选择按钮 + JButton selectButton = new JButton("打包选中的文件或文件夹"); + selectButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + selectItems(); + } + }); + + // 创建文件树 + fileTree = new JTree(getFileTreeModel()); + fileTree.setRootVisible(false); + fileTree.setShowsRootHandles(true); + fileTree.addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + updateStatusLabel(); + } + }); + JScrollPane treeScrollPane = new JScrollPane(fileTree); + + // 创建结果标签 + statusLabel = new JLabel(); + updateStatusLabel(); + + // 创建面板并添加组件 + JPanel panel = new JPanel(new BorderLayout()); + panel.add(selectButton, BorderLayout.NORTH); + panel.add(treeScrollPane, BorderLayout.CENTER); + panel.add(statusLabel, BorderLayout.SOUTH); + + // 将面板添加到窗口 + add(panel); + } + + private DefaultMutableTreeNode getFileTreeModel() { + File targetDir = new File("target/classes/"); + DefaultMutableTreeNode root = new DefaultMutableTreeNode(targetDir.getName()); + buildFileTree(root, targetDir); + return root; + } + + private void buildFileTree(DefaultMutableTreeNode parent, File directory) { + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode(file.getName()); + parent.add(node); + if (file.isDirectory()) { + buildFileTree(node, file); + } + } + } + } + + private void selectItems() { + List selectedFiles = new ArrayList<>(); + DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) fileTree.getModel().getRoot(); + Enumeration enumeration = rootNode.breadthFirstEnumeration(); + while (enumeration.hasMoreElements()) { + DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement(); + if (node.isLeaf() && checkBoxes[node.getLevel()].isSelected()) { + TreePath path = new TreePath(node.getPath()); + selectedFiles.add(new File(path.toString().substring(1).replace(", ", "/"))); + } + } + if (!selectedFiles.isEmpty()) { + createZipFile(selectedFiles); + } else { + statusLabel.setText("请勾选要打包的文件或文件夹"); + } + } + + private void createZipFile(List files) { + JFileChooser fileChooser = new JFileChooser(); + int result = fileChooser.showSaveDialog(this); + if (result == JFileChooser.APPROVE_OPTION) { + File zipFile = fileChooser.getSelectedFile(); + try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile))) { + for (File file : files) { + addFileToZip(file, file.getName(), zipOutputStream); + } + statusLabel.setText("已将文件打包为:" + zipFile.getAbsolutePath()); + } catch (IOException e) { + statusLabel.setText("打包文件时出现错误:" + e.getMessage()); + } + } + } + + private void addFileToZip(File file, String entryName, ZipOutputStream zipOutputStream) throws IOException { + if (file.isDirectory()) { + File[] files = file.listFiles(); + if (files != null) { + for (File child : files) { + addFileToZip(child, entryName + "/" + child.getName(), zipOutputStream); + } + } + } else { + byte[] buffer = new byte[1024]; + FileInputStream fis = new FileInputStream(file); + zipOutputStream.putNextEntry(new ZipEntry(entryName)); + int length; + while ((length = fis.read(buffer)) > 0) { + zipOutputStream.write(buffer, 0, length); + } + zipOutputStream.closeEntry(); + fis.close(); + } + } + + private void updateStatusLabel() { + TreePath[] paths = fileTree.getSelectionPaths(); + if (paths != null) { + int selectedCount = paths.length; + statusLabel.setText("已选中 " + selectedCount + " 个文件/文件夹"); + } else { + statusLabel.setText(""); + } + } + + public static void main(String[] args) { + // 设置外观和风格 + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + e.printStackTrace(); + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + new FileSelectionApp().setVisible(true); + } + }); + } +} diff --git a/checked.png b/checked.png new file mode 100644 index 0000000000000000000000000000000000000000..39ff02bad74a123af54869d2c559b060908bcca8 GIT binary patch literal 14821 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', toggle_checkbox) + +# 启动主循环 +root.mainloop() diff --git a/pom.xml b/pom.xml index ead8c4a..5221995 100644 --- a/pom.xml +++ b/pom.xml @@ -130,7 +130,12 @@ easypoi-annotation 4.0.0 - + + + org.controlsfx + controlsfx + 8.40.14 + diff --git a/src/main/java/com/customization/youhong/taibao/compresspicture/impl/CompressDocPictureImpl.java b/src/main/java/com/customization/youhong/taibao/compresspicture/impl/CompressDocPictureImpl.java index 99a4f40..bfe25dd 100644 --- a/src/main/java/com/customization/youhong/taibao/compresspicture/impl/CompressDocPictureImpl.java +++ b/src/main/java/com/customization/youhong/taibao/compresspicture/impl/CompressDocPictureImpl.java @@ -29,9 +29,9 @@ import java.util.Objects; @WeaIocReplaceComponent("CompressDocPictureService") public class CompressDocPictureImpl { - private final CompressDocPictureMapper mapper = Util.getMapper(CompressDocPictureMapper.class); + private CompressDocPictureMapper mapper = null; - private final Logger log = Util.getLogger(); + private Logger log = null; /** * 这个是接口后置方法,大概的用法跟前置方法差不多,稍有差别 @@ -42,6 +42,12 @@ public class CompressDocPictureImpl { */ @WeaReplaceAfter(value = "/api/doc/save/save", order = 1) public String after(WeaAfterReplaceParam weaAfterReplaceParam) { + if (Objects.isNull(mapper)) { + mapper = Util.getMapper(CompressDocPictureMapper.class); + } + if (Objects.isNull(log)) { + log = Util.getLogger(); + } String data = weaAfterReplaceParam.getData(); try { Map paramMap = weaAfterReplaceParam.getParamMap(); diff --git a/src/test/java/FileCompressor.java b/src/test/java/FileCompressor.java new file mode 100644 index 0000000..e748dba --- /dev/null +++ b/src/test/java/FileCompressor.java @@ -0,0 +1,63 @@ +import aiyh.utils.tool.cn.hutool.core.util.StrUtil; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.List; +import java.util.function.Function; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +public class FileCompressor { + + public static void compressFiles(List filePaths, String outputZipPath, Function replacePath) throws IOException { + try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(outputZipPath))) { + for (String filePath : filePaths) { + File file = new File(filePath); + if (file.exists()) { + if (file.isDirectory()) { + addDirectoryToZip(file, file.getPath(), zipOutputStream, replacePath); + } else { + addFileToZip(file, file.getParent(), zipOutputStream, replacePath); + } + } else { + throw new IOException("File not found: " + filePath); + } + } + } + } + + private static void addDirectoryToZip(File directory, String parentPath, ZipOutputStream zipOutputStream, Function replacePath) throws IOException { + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + addDirectoryToZip(file, parentPath + File.separator + file.getName(), zipOutputStream, replacePath); + } else { + addFileToZip(file, parentPath, zipOutputStream, replacePath); + } + } + } + } + + private static void addFileToZip(File file, String parentPath, ZipOutputStream zipOutputStream, Function replacePath) throws IOException { + try (FileInputStream fileInputStream = new FileInputStream(file)) { + String entryPath = parentPath + File.separator + file.getName(); + String finalPath = replacePath.apply(entryPath); + if (StrUtil.isBlank(finalPath)) { + finalPath = "/"; + } + ZipEntry zipEntry = new ZipEntry(finalPath); + zipOutputStream.putNextEntry(zipEntry); + + byte[] buffer = new byte[1024]; + int length; + while ((length = fileInputStream.read(buffer)) >= 0) { + zipOutputStream.write(buffer, 0, length); + } + + zipOutputStream.closeEntry(); + } + } +} diff --git a/src/test/java/FileInfo.java b/src/test/java/FileInfo.java new file mode 100644 index 0000000..865a719 --- /dev/null +++ b/src/test/java/FileInfo.java @@ -0,0 +1,61 @@ +import javafx.scene.control.CheckBox; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Getter +@Setter +@ToString +public class FileInfo { + private String filePath; + private String fileName; + private String fileType; + private boolean isSelected; + private List children; + private CheckBox checkBox; + + // Constructors + + public FileInfo(String filePath, String fileName, String fileType, boolean isSelected) { + this.filePath = filePath; + this.fileName = fileName; + this.fileType = fileType; + this.isSelected = isSelected; + } + + public FileInfo() { + } + + // Methods + + public void addChild(FileInfo child) { + if (Objects.isNull(children)) { + this.children = new ArrayList<>(); + } + boolean added = children.add(child); + if (added) { + child.setCheckBox(new CheckBox()); + child.getCheckBox().setSelected(this.isSelected()); + } else { + // 处理添加失败的情况 + System.out.println("Failed to add child"); + } + } + + public boolean hasChildren() { + return children != null && !children.isEmpty(); + } + + @Override + public String toString() { + return fileName; + } + + public boolean isDirectory() { + return this.fileType.equals(FileTreeBuilder.DIRECTORY_TYPE); + } +} diff --git a/src/test/java/FileTreeBuilder.java b/src/test/java/FileTreeBuilder.java new file mode 100644 index 0000000..fe73b96 --- /dev/null +++ b/src/test/java/FileTreeBuilder.java @@ -0,0 +1,110 @@ +import java.io.File; +import java.util.Arrays; +import java.util.List; + +public class FileTreeBuilder { + + public static final String DIRECTORY_TYPE = "文件夹"; + public static final String FILE_TYPE = "文件"; + + public static FileInfo buildFileTree(String directoryPath) { + File root = new File(directoryPath); + if (!root.exists() || !root.isDirectory()) { + System.out.println("Invalid directory path: " + directoryPath); + return null; + } + + List blacklistPrefixes = Arrays.asList( + "target" + File.separator + "generated-sources", + "target" + File.separator + "generated-test-sources", + "target" + File.separator + "test-classes", + "target" + File.separator + "classes" + File.separator + "aiyh", + "target" + File.separator + "classes" + File.separator + "ebu7common", + "target" + File.separator + "classes" + File.separator + "ln", + "target" + File.separator + "classes" + File.separator + "cus_getlog" + ); + return buildFileTreeRecursively(root, blacklistPrefixes); + } + + public static FileInfo buildFileTree(String directoryPath, List blacklistPrefixes) { + File root = new File(directoryPath); + if (!root.exists() || !root.isDirectory()) { + System.out.println("Invalid directory path: " + directoryPath); + return null; + } + + return buildFileTreeRecursively(root, blacklistPrefixes); + } + + private static FileInfo buildFileTreeRecursively(File directory, List blacklistPrefixes) { + String filePath = directory.getAbsolutePath(); + String fileName = directory.getName(); + String fileType = DIRECTORY_TYPE; + boolean isSelected = false; + FileInfo fileInfo = new FileInfo(); + fileInfo.setFilePath(filePath); + fileInfo.setFileName(fileName); + fileInfo.setFileType(fileType); + fileInfo.setSelected(isSelected); + File[] files = directory.listFiles(); + if (files != null) { + for (File file : files) { + if (file.isDirectory()) { + if (!isBlacklisted(file.getAbsolutePath(), blacklistPrefixes)) { + FileInfo child = buildFileTreeRecursively(file, blacklistPrefixes); + fileInfo.addChild(child); + } + } else { + if (isBlacklisted(file.getPath(), blacklistPrefixes)) { + continue; + } + String childFilePath = file.getAbsolutePath(); + String childFileName = file.getName(); + String childFileType = FILE_TYPE; + boolean childIsSelected = false; + FileInfo childFileInfo = new FileInfo(); + childFileInfo.setFilePath(childFilePath); + childFileInfo.setFileName(childFileName); + childFileInfo.setFileType(childFileType); + childFileInfo.setSelected(childIsSelected); + fileInfo.addChild(childFileInfo); + } + } + } + + return fileInfo; + } + + private static boolean isBlacklisted(String filePath, List blacklistPrefixes) { + if (filePath.endsWith(".DS_Store") || filePath.endsWith(".DSStore")) { + return true; + } + for (String prefix : blacklistPrefixes) { + String path = FileTreeBuilder.class.getResource("").getPath(); + String prefixPath = path.substring(0, path.indexOf(File.separator + "target" + File.separator)) + File.separator; + if (filePath.startsWith(prefixPath + prefix)) { + return true; + } + } + return false; + } + + public static void printFileTree(FileInfo fileInfo, int level) { + if (fileInfo != null) { + for (int i = 0; i < level; i++) { + System.out.print(" "); + } + System.out.println(fileInfo.getFileName()); + List children = fileInfo.getChildren(); + for (FileInfo child : children) { + printFileTree(child, level + 1); + } + } + } + + public static void main(String[] args) { + String directoryPath = "target/"; + FileInfo fileTree = buildFileTree(directoryPath); + printFileTree(fileTree, 0); + } +} diff --git a/src/test/java/TreeViewExample.java b/src/test/java/TreeViewExample.java new file mode 100644 index 0000000..86fa3c2 --- /dev/null +++ b/src/test/java/TreeViewExample.java @@ -0,0 +1,182 @@ +import aiyh.utils.Util; +import javafx.application.Application; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Scene; +import javafx.scene.control.*; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.stage.FileChooser; +import javafx.stage.Stage; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class TreeViewExample extends Application { + + private boolean isEcology = false; + + private final List filePaths = new ArrayList<>(); + + private TreeView treeView; + private TreeItem rootItem; + + @Override + public void start(Stage primaryStage) { + primaryStage.setTitle("EBU7部开发一部自动打包工具"); + + FileInfo fileInfo = FileTreeBuilder.buildFileTree("target/"); + rootItem = createTreeItem(fileInfo); + + treeView = new TreeView<>(rootItem); + treeView.setShowRoot(false); + treeView.setCellFactory(treeViewParam -> new CheckBoxTreeCell()); + + BorderPane root = new BorderPane(); + root.setCenter(treeView); + + HBox buttonBox = new HBox(); + buttonBox.setSpacing(10); + buttonBox.setPadding(new Insets(10)); + buttonBox.setAlignment(Pos.CENTER_RIGHT); + + Button button = new Button("生成升级包"); + button.setOnAction(event -> { + FileChooser fileChooser = new FileChooser(); + fileChooser.setInitialFileName("sh_ebu_dev_1_ecology.zip"); + File outputFile = fileChooser.showSaveDialog(primaryStage); + if (outputFile != null) { + try { + FileCompressor.compressFiles(filePaths, outputFile.getAbsolutePath(), path -> { + String rootPath = Util.class.getResource("/").getPath(); + rootPath = rootPath.split(File.separator + "target" + File.separator)[0] + File.separator + "target" + File.separator + "classes" + File.separator; + String replace = "/ecology/" + (isEcology ? "WEB-INF/classes/" : "classbean/"); + if (path.endsWith(".jar")) { + replace = "/ecology/WEB-INF/lib/"; + path = rootPath + path.substring(path.lastIndexOf(File.separator) + 1); + } else if (path.contains("WEB-INF")) { + replace = "/ecology/"; + } + replace = path.replace(rootPath, replace); + return replace; + }); + clearSelections(); + updateTreeView(); + showSuccessAlert("升级包制作成功!"); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + + VBox checkBoxBox = new VBox(); + checkBoxBox.setPadding(new Insets(10)); + checkBoxBox.setAlignment(Pos.CENTER_RIGHT); + + CheckBox checkBox = new CheckBox("是否是信创环境"); + checkBox.selectedProperty().addListener((observable, oldValue, newValue) -> { + this.isEcology = newValue; + }); + + checkBoxBox.getChildren().add(checkBox); + + buttonBox.getChildren().addAll(button, checkBoxBox); + root.setBottom(buttonBox); + + Scene scene = new Scene(root, 600, 400); + scene.getStylesheets().add("style.css"); // 加载自定义的 CSS 文件 + primaryStage.setScene(scene); + primaryStage.show(); + } + + private TreeItem createTreeItem(FileInfo fileInfo) { + TreeItem treeItem = new TreeItem<>(fileInfo); + List children = fileInfo.getChildren(); + if (children != null) { + for (FileInfo child : children) { + TreeItem childItem = createTreeItem(child); + treeItem.getChildren().add(childItem); + } + } + return treeItem; + } + + private void clearSelections() { + for (String filePath : filePaths) { + TreeItem item = findTreeItem(filePath, rootItem); + if (item != null) { + FileInfo fileInfo = item.getValue(); + fileInfo.setSelected(false); + } + } + filePaths.clear(); + } + + private void updateTreeView() { + treeView.setRoot(null); // 清除原有根节点 + treeView.setRoot(rootItem); // 重新设置根节点 + } + + private TreeItem findTreeItem(String filePath, TreeItem root) { + if (root.getValue().getFilePath().equals(filePath)) { + return root; + } else { + for (TreeItem child : root.getChildren()) { + TreeItem foundItem = findTreeItem(filePath, child); + if (foundItem != null) { + return foundItem; + } + } + return null; + } + } + + private class CheckBoxTreeCell extends TreeCell { + private final CheckBox checkBox; + + public CheckBoxTreeCell() { + checkBox = new CheckBox(); + checkBox.selectedProperty().addListener((observable, oldValue, newValue) -> { + FileInfo fileInfo = getItem(); + fileInfo.setSelected(newValue); + String filePath = fileInfo.getFilePath(); + if (newValue) { + if (!filePaths.contains(filePath)) { + filePaths.add(filePath); + } + } else { + filePaths.remove(filePath); + } + System.out.println(fileInfo.getFilePath()); + }); + } + + @Override + protected void updateItem(FileInfo item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setText(null); + setGraphic(null); + } else { + checkBox.setSelected(item.isSelected()); + checkBox.setText(item.getFileName()); + setGraphic(checkBox); + } + } + } + + private void showSuccessAlert(String message) { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("提示"); + alert.setHeaderText(null); + alert.setContentText(message); + alert.showAndWait(); + } + + public static void main(String[] args) { + launch(args); + } +} diff --git a/src/test/java/basetest/BaseTest.java b/src/test/java/basetest/BaseTest.java index b394cb4..dbc040d 100644 --- a/src/test/java/basetest/BaseTest.java +++ b/src/test/java/basetest/BaseTest.java @@ -30,7 +30,7 @@ public class BaseTest { protected final Logger log = Util.getLogger(); - private static Properties propertiesStatic; + public static Properties propertiesStatic; @BeforeClass public static void beforeStatic() { @@ -130,7 +130,7 @@ public class BaseTest { @Test public void with() { - + Logger logger = Util.getLogger(); logger.info("aafasdf"); String sql = "select COMPANYNAME,LICENSE,EXPIREDATE,CVERSION from license "; diff --git a/src/test/resources/icons/file.png b/src/test/resources/icons/file.png new file mode 100644 index 0000000000000000000000000000000000000000..09b4c8e87db87ad6794e585a579fdfb0a2b683ef GIT binary patch literal 14116 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