From b7030ede3c00aa29126d1d1a64bf7c3bc21171f9 Mon Sep 17 00:00:00 2001 From: 3944Realms Date: Sun, 28 Sep 2025 20:59:05 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A1.=E8=B0=83=E6=95=B4=E4=BA=86?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E7=95=8C=E9=9D=A2=E7=9A=84UI=202.=E5=8E=BB?= =?UTF-8?q?=E6=8E=89=E4=BA=86=E5=8F=8D=E9=A6=88=E5=8C=BA=E5=9F=9F=E7=9A=84?= =?UTF-8?q?=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 2 +- .../JavaFxApplication.java | 2 +- .../core/DuplicateFinder.java | 5 +- .../DuplicateDocumentPaneController.java | 78 ++++++- .../ui/module/PathCheckPaneController.java | 73 +++++- .../module/StorageCarrierPaneController.java | 88 +++++++- .../task/DuplicateDocumentDetectionTask.java | 17 +- src/main/resources/css/project-info-pane.css | 93 ++++++++ src/main/resources/css/step-1-pane.css | 159 ++++++++++++++ src/main/resources/css/step-2-pane.css | 207 ++++++++++++++++++ src/main/resources/css/step-3456-pane.css | 32 +++ src/main/resources/css/step-7-pane.css | 197 +++++++++++++++++ .../fxml/module/project-info-pane.fxml | 4 +- .../resources/fxml/module/step-1-pane.fxml | 18 +- .../resources/fxml/module/step-2-pane.fxml | 16 +- .../resources/fxml/module/step-3-pane.fxml | 2 +- .../resources/fxml/module/step-4-pane.fxml | 2 +- .../resources/fxml/module/step-5-pane.fxml | 2 +- .../resources/fxml/module/step-6-pane.fxml | 2 +- .../resources/fxml/module/step-7-pane.fxml | 37 ++-- 20 files changed, 956 insertions(+), 80 deletions(-) create mode 100644 src/main/resources/css/project-info-pane.css create mode 100644 src/main/resources/css/step-1-pane.css create mode 100644 src/main/resources/css/step-2-pane.css create mode 100644 src/main/resources/css/step-3456-pane.css create mode 100644 src/main/resources/css/step-7-pane.css diff --git a/gradle.properties b/gradle.properties index de312de..2eb2e5d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ project_group =top.r3944realms.docchecktoolrefacored project_name = doc-check-tool -project_version = 1.0 \ No newline at end of file +project_version = 1.0.0.3 \ No newline at end of file diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/JavaFxApplication.java b/src/main/java/top/r3944realms/docchecktoolrefactored/JavaFxApplication.java index 5e0fc9e..f6d66ea 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/JavaFxApplication.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/JavaFxApplication.java @@ -12,7 +12,7 @@ public class JavaFxApplication extends Application { @Override public void init() throws Exception { super.init(); - System.setVersion("1.0.0-beta"); + System.setVersion("1.0.0.3-beta"); } @Override diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/core/DuplicateFinder.java b/src/main/java/top/r3944realms/docchecktoolrefactored/core/DuplicateFinder.java index 88e8da5..fc58442 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/core/DuplicateFinder.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/core/DuplicateFinder.java @@ -201,9 +201,10 @@ public class DuplicateFinder { hashCalculator.calculateHash(file.getPath()); file.setHash(hash); - synchronized (hashGroups) { + //hashGroups已经定义为ConcurrentHashMap,可以利用它本身的线程安全方法来减少同步块 + //synchronized (hashGroups) { hashGroups.computeIfAbsent(hash, k -> new ArrayList<>()).add(file); - } + //} int current = processedFiles.incrementAndGet(); if (enableProgress && (current % PROGRESS_REPORT_INTERVAL == 0 || current == totalFilesToProcess)) { diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/DuplicateDocumentPaneController.java b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/DuplicateDocumentPaneController.java index 7a4f13c..6ca86ad 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/DuplicateDocumentPaneController.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/DuplicateDocumentPaneController.java @@ -1,5 +1,6 @@ package top.r3944realms.docchecktoolrefactored.ui.module; +import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.event.ActionEvent; import javafx.fxml.FXML; @@ -17,7 +18,6 @@ import top.r3944realms.docchecktoolrefactored.ui.utils.ProgressBar; import top.r3944realms.docchecktoolrefactored.util.LoggerMarker; import java.io.File; - /** * The type Duplicate document pane controller. */ @@ -31,6 +31,7 @@ public class DuplicateDocumentPaneController { @FXML private Button cancel1B; private final ProgressBar progressBar = new ProgressBar(); private DuplicateDocumentDetectionTask currentTask; // 保存任务引用 + /** * On select folder. * @@ -54,6 +55,7 @@ public class DuplicateDocumentPaneController { @FXML void onStart(ActionEvent actionEvent) { // 禁用开始按钮避免重复点击 start1B.setDisable(true); + removeResultStyle(); log.info(LoggerMarker.DEBUG_MARKER, "用户点击了开始查重按钮"); String folderPath = loadFolder1TF.getText(); if (folderPath == null || folderPath.trim().isEmpty()) { @@ -63,6 +65,10 @@ public class DuplicateDocumentPaneController { start1B.setDisable(false); return; } + // 调用提取的样式方法:移除结果文本域错误态 + removeResultStyle(); + // 调用提取的样式方法:添加开始按钮加载态 + addStartButtonLoadingStyle(); cancel1B.setDisable(false); // 显示进度条窗口 progressBar.showProgress(SceneManager.getPrimaryStage(), "重复文件检测", "正在初始化扫描..."); @@ -82,10 +88,10 @@ public class DuplicateDocumentPaneController { task.progressProperty().addListener(progressChangeListener); // 绑定任务的消息到结果文本区域 - ChangeListener messageChangeListener = (observable, oldValue, newValue) -> { - result1TA.setText(newValue); - }; - task.messageProperty().addListener(messageChangeListener); +// ChangeListener messageChangeListener = (observable, oldValue, newValue) -> { +// result1TA.setText(newValue); +// }; +// task.messageProperty().addListener(messageChangeListener); // 绑定取消按钮 -> task.cancel() progressBar.setOnCancel(() -> { @@ -101,6 +107,9 @@ public class DuplicateDocumentPaneController { result1TA.setText(task.getValue()); start1B.setDisable(false); cancel1B.setDisable(true); + // 调用提取的样式方法:移除开始按钮加载态 + removeStartButtonLoadingStyle(); + addResultSuccessfulStyle(); log.info(LoggerMarker.RELEASE_MARKER, "查重任务完成,结果如下:{}", task.getValue()); }); @@ -109,10 +118,14 @@ public class DuplicateDocumentPaneController { progressBar.closeProgress(); Throwable exception = task.getException(); currentTask.progressProperty().removeListener(progressChangeListener); - currentTask.messageProperty().removeListener(messageChangeListener); +// currentTask.messageProperty().removeListener(messageChangeListener); result1TA.setText("检测过程中发生错误: " + exception.getMessage()); + // 调用提取的样式方法:添加结果文本域错误态 + addResultErrorStyle(); DialogUtil.showDetailedErrorDialog("错误", "检测过程中发生错误", exception.getMessage()); start1B.setDisable(false); + // 调用提取的样式方法:移除开始按钮加载态 + removeStartButtonLoadingStyle(); cancel1B.setDisable(true); log.error(LoggerMarker.RELEASE_MARKER, "查重任务失败", exception); }); @@ -121,9 +134,11 @@ public class DuplicateDocumentPaneController { task.setOnCancelled(e -> { progressBar.closeProgress(); currentTask.progressProperty().removeListener(progressChangeListener); - currentTask.messageProperty().removeListener(messageChangeListener); +// currentTask.messageProperty().removeListener(messageChangeListener); result1TA.appendText("\n检测已取消"); start1B.setDisable(false); + // 调用提取的样式方法:移除开始按钮加载态 + removeStartButtonLoadingStyle(); cancel1B.setDisable(true); log.info(LoggerMarker.RELEASE_MARKER, "查重任务已被取消"); }); @@ -140,4 +155,51 @@ public class DuplicateDocumentPaneController { log.warn(LoggerMarker.DEBUG_MARKER, "没有正在运行的任务可取消"); } } -} + + // ======================== 提取的样式变更方法 ======================== + /** + * 为结果文本域添加错误态样式 + */ + private void addResultErrorStyle() { + Platform.runLater(() -> { + result1TA.getStyleClass().add("result-error"); + }); + } + /** + * 为结果文本域添加成功态样式 + */ + private void addResultSuccessfulStyle() { + Platform.runLater(() -> { + result1TA.getStyleClass().add("result-error"); + }); + } + + /** + * 为结果文本域移除样式 + */ + private void removeResultStyle() { + Platform.runLater(() -> { + result1TA.getStyleClass().remove("result-error"); + result1TA.getStyleClass().remove("result-success"); + }); + } + + /** + * 为开始按钮添加加载态样式 + */ + private void addStartButtonLoadingStyle() { + Platform.runLater(() -> { + start1B.getStyleClass().add("loading"); + }); + } + + /** + * 为开始按钮移除加载态样式 + */ + private void removeStartButtonLoadingStyle() { + Platform.runLater(() -> { + start1B.getStyleClass().remove("loading"); + }); + } + // ==================================================================== +} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/PathCheckPaneController.java b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/PathCheckPaneController.java index 20d533e..7f397be 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/PathCheckPaneController.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/PathCheckPaneController.java @@ -1,5 +1,6 @@ package top.r3944realms.docchecktoolrefactored.ui.module; +import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.concurrent.Task; import javafx.event.ActionEvent; @@ -119,6 +120,7 @@ public class PathCheckPaneController implements Initializable { */ @FXML void onGenerateLA(ActionEvent actionEvent) { generateLogicalAddress2B.setDisable(true); + removeResultStyle(); log.info(LoggerMarker.DEBUG_MARKER, "用户点击了生成逻辑地址文件按钮"); String filePath = loadCatalog2TF.getText(); if (filePath.isEmpty()) { @@ -179,6 +181,7 @@ public class PathCheckPaneController implements Initializable { progressBar.closeProgress(); result2TA.setText(task.getValue()); generateLogicalAddress2B.setDisable(false); + addResultSuccessfulStyle(); log.info(LoggerMarker.RELEASE_MARKER, "生成逻辑路径 csv 文件任务完成,输出csv文件路径:{}", task.getValue()); }); @@ -189,6 +192,7 @@ public class PathCheckPaneController implements Initializable { currentTask.progressProperty().removeListener(progressChangeListener); currentTask.messageProperty().removeListener(messageChangeListener); result2TA.setText("检测过程中发生错误: " + exception.getMessage()); + addResultErrorStyle(); DialogUtil.showDetailedErrorDialog("错误", "检测过程中发生错误: ", exception.getMessage()); generateLogicalAddress2B.setDisable(false); log.error(LoggerMarker.RELEASE_MARKER, "生成逻辑路径 csv 文件任务失败", exception); @@ -200,6 +204,7 @@ public class PathCheckPaneController implements Initializable { currentTask.progressProperty().removeListener(progressChangeListener); currentTask.messageProperty().removeListener(messageChangeListener); result2TA.appendText("\n检测已取消"); + removeResultStyle(); generateLogicalAddress2B.setDisable(false); log.info(LoggerMarker.RELEASE_MARKER, "生成逻辑路径 csv 文件任务已被取消"); }); @@ -215,6 +220,7 @@ public class PathCheckPaneController implements Initializable { */ @FXML void onGeneratePA(ActionEvent actionEvent) { generatePhysicalAddress2B.setDisable(true); + removeResultStyle(); String folderPath = loadJPGFolder2TF.getText(); if (folderPath.isEmpty()) { result2TA.setText("请先选择文件夹。"); @@ -283,6 +289,7 @@ public class PathCheckPaneController implements Initializable { result2TA.setText(task.getValue()); generatePhysicalAddress2B.setDisable(false); log.info(LoggerMarker.RELEASE_MARKER, "生成物理路径 csv 文件任务完成,输出csv文件路径:{}", task.getValue()); + addResultSuccessfulStyle(); }); // 处理任务失败情况 @@ -292,6 +299,7 @@ public class PathCheckPaneController implements Initializable { currentTask.progressProperty().removeListener(progressChangeListener); currentTask.messageProperty().removeListener(messageChangeListener); result2TA.setText("检测过程中发生错误: " + exception.getMessage()); + addResultErrorStyle(); DialogUtil.showDetailedErrorDialog("错误", "检测过程中发生错误: ", exception.getMessage()); generatePhysicalAddress2B.setDisable(false); log.error(LoggerMarker.RELEASE_MARKER, "生成物理路径 csv 文件任务失败", exception); @@ -303,6 +311,7 @@ public class PathCheckPaneController implements Initializable { currentTask.progressProperty().removeListener(progressChangeListener); currentTask.messageProperty().removeListener(messageChangeListener); result2TA.appendText("\n检测已取消"); + removeResultStyle(); generatePhysicalAddress2B.setDisable(false); log.info(LoggerMarker.RELEASE_MARKER, "生成物理路径 csv 文件任务已被取消"); }); @@ -328,7 +337,8 @@ public class PathCheckPaneController implements Initializable { return; } start2B.setDisable(true); - + removeStartButtonLoadingStyle(); + start2B.setText("比对中..."); // 显示进度条窗口 cancelableProgressBar.showProgress(SceneManager.getPrimaryStage(), "文件查漏检查", "正在初始化..."); // 创建后台任务 @@ -346,10 +356,10 @@ public class PathCheckPaneController implements Initializable { task.progressProperty().addListener(progressChangeListener); // 绑定任务的消息到结果文本区域 - ChangeListener messageChangeListener = (observable, oldValue, newValue) -> { - result2TA.setText(newValue); - }; - task.messageProperty().addListener(messageChangeListener); +// ChangeListener messageChangeListener = (observable, oldValue, newValue) -> { +// result2TA.setText(newValue); +// }; +// task.messageProperty().addListener(messageChangeListener); // 绑定取消按钮 -> task.cancel() cancelableProgressBar.setOnCancel(() -> { @@ -361,6 +371,8 @@ public class PathCheckPaneController implements Initializable { task.setOnSucceeded(event -> { cancelableProgressBar.closeProgress(); start2B.setDisable(false); + addStartButtonLoadingStyle(); + start2B.setText("开始对比"); result2TA.setText(AddressFileComparator.ComparisonResult.generateComparisonResults(task.getValue(), loadFolderType2CB.getValue().compareMode)); result2TA.setText(AddressFileComparator.ComparisonResult.generateComparisonResults(task.getValue(), loadFolderType2CB.getValue().compareMode)); //内部比较器已有,此处忽略日志打印 @@ -371,6 +383,8 @@ public class PathCheckPaneController implements Initializable { Throwable exception = task.getException(); result2TA.setText("文件比对失败: " + exception.getMessage()); start2B.setDisable(false); + removeStartButtonLoadingStyle(); + start2B.setText("开始对比"); DialogUtil.showDetailedErrorDialog("错误", "文件比对失败:", exception.getMessage()); log.error(LoggerMarker.RELEASE_MARKER, "查漏任务失败", exception); }); @@ -379,8 +393,10 @@ public class PathCheckPaneController implements Initializable { cancelableProgressBar.closeProgress(); result2TA.appendText("\n检测已取消"); start2B.setDisable(false); + removeStartButtonLoadingStyle(); + start2B.setText("开始对比"); currentTask.progressProperty().removeListener(progressChangeListener); - currentTask.messageProperty().removeListener(messageChangeListener); +// currentTask.messageProperty().removeListener(messageChangeListener); log.info(LoggerMarker.RELEASE_MARKER, "查漏任务取消"); }); @@ -447,6 +463,51 @@ public class PathCheckPaneController implements Initializable { this.compareMode = compareMode; } } + // ======================== 提取的样式变更方法 ======================== + /** + * 为结果文本域添加错误态样式 + */ + private void addResultErrorStyle() { + Platform.runLater(() -> { + result2TA.getStyleClass().add("result-error"); + }); + } + /** + * 为结果文本域添加成功态样式 + */ + private void addResultSuccessfulStyle() { + Platform.runLater(() -> { + result2TA.getStyleClass().add("result-error"); + }); + } + + /** + * 为结果文本域移除样式 + */ + private void removeResultStyle() { + Platform.runLater(() -> { + result2TA.getStyleClass().remove("result-error"); + result2TA.getStyleClass().remove("result-success"); + }); + } + /** + * 为开始按钮添加加载态样式 + */ + private void addStartButtonLoadingStyle() { + Platform.runLater(() -> { + start2B.getStyleClass().add("loading"); + }); + } + + /** + * 为开始按钮移除加载态样式 + */ + private void removeStartButtonLoadingStyle() { + Platform.runLater(() -> { + start2B.getStyleClass().remove("loading"); + }); + } + // ==================================================================== } diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/StorageCarrierPaneController.java b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/StorageCarrierPaneController.java index 29e4c75..f1eb659 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/StorageCarrierPaneController.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/module/StorageCarrierPaneController.java @@ -1,5 +1,6 @@ package top.r3944realms.docchecktoolrefactored.ui.module; +import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.concurrent.Task; import javafx.event.ActionEvent; @@ -50,6 +51,10 @@ public class StorageCarrierPaneController { @FXML private Button clearSelectedFoldersButton; + // 保存按钮原始文本,用于状态恢复 + private final String calculateHashOriginalText = "计算哈希值"; + private final String generateHashOriginalText = "生成哈希值表文件"; + private final top.r3944realms.docchecktoolrefactored.ui.utils.ProgressBar progressBar = new top.r3944realms.docchecktoolrefactored.ui.utils.ProgressBar(false); @FXML void onSelectLD(ActionEvent event) { @@ -81,7 +86,11 @@ public class StorageCarrierPaneController { loadDigitalOutcomes.setText(currentText + File.pathSeparator + folderPath); } } + log.info(LoggerMarker.DEBUG_MARKER, "用户选择了文件夹: {}", selectedFolder.getAbsolutePath()); + + // 添加成功样式 + applySuccessStyle(loadDigitalOutcomes); } else { log.info(LoggerMarker.DEBUG_MARKER, "用户取消了文件夹选择"); } @@ -93,6 +102,9 @@ public class StorageCarrierPaneController { loadDigitalOutcomes.setText(""); result7TA.setText("已清除所有已选择的文件夹"); log.info(LoggerMarker.DEBUG_MARKER, "已清除所有已选择的文件夹"); + + // 移除样式 + resetStyle(loadDigitalOutcomes); } @@ -109,6 +121,9 @@ public class StorageCarrierPaneController { System.setLastModifiedFile(selectedFile); loadCompressedFile.setText(selectedFile.getAbsolutePath()); log.info(LoggerMarker.DEBUG_MARKER, "用户选择了RAR文件: {}", selectedFile.getAbsolutePath()); + + // 添加成功样式 + applySuccessStyle(loadCompressedFile); } else { log.info(LoggerMarker.DEBUG_MARKER, "用户取消了RAR文件选择"); } @@ -124,6 +139,7 @@ public class StorageCarrierPaneController { result7TA.setText("请先选择一个 .rar 文件"); DialogUtil.showWarningDialog("警告", "操作有误", "请先选择一个 .rar 文件"); generateHashFile7B.setDisable(false); + // 重置样式 return; } @@ -136,16 +152,21 @@ public class StorageCarrierPaneController { return; } try { + // 添加加载样式 + applyLoadingStyle(generateHashFile7B, "处理中..."); log.info(LoggerMarker.DEBUG_MARKER, "开始计算RAR文件MD5哈希值: {}", filePath); MD5HashCalculator hashCalculator = new MD5HashCalculator(); String hashResult = hashCalculator.calculateHash(file.toPath()); result7TA.setText("计算结果:\n" + hashResult); + applySuccessStyle(result7TA); generateHashFile7B.setDisable(false); log.info(LoggerMarker.DEBUG_MARKER, "文件哈希值计算完成: {}", hashResult); } catch (IOException e) { log.error(LoggerMarker.DEBUG_MARKER, "计算文件哈希值时出错: {}", filePath, e); DialogUtil.showDetailedErrorDialog("错误", "生成哈希文件时出错:", e.getMessage()); generateHashFile7B.setDisable(false); + // 重置样式 + resetButtonStyle(generateHashFile7B, generateHashOriginalText); result7TA.setText("计算哈希值时出错: " + e.getMessage()); } } @@ -179,7 +200,7 @@ public class StorageCarrierPaneController { return; } } - + applyLoadingStyle(caculateHash7B, "处理中..."); FileChooser fileChooser = System.getFileChooser(); fileChooser.setTitle("选择保存哈希列表文件的位置"); fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("CSV Files", "*.csv")); @@ -219,16 +240,18 @@ public class StorageCarrierPaneController { }; task.progressProperty().addListener(progressChangeListener); // 绑定任务的消息到结果文本区域,实时显示进度 - ChangeListener messageChangeListener = (observable, oldValue, newValue) -> { - result7TA.setText(newValue); - }; - task.messageProperty().addListener(messageChangeListener); +// ChangeListener messageChangeListener = (observable, oldValue, newValue) -> { +// result7TA.setText(newValue); +// }; +// task.messageProperty().addListener(messageChangeListener); // 任务成功完成 task.setOnSucceeded(e -> { progressBar.closeProgress(); log.info(LoggerMarker.DEBUG_MARKER, "哈希文件生成任务成功完成"); caculateHash7B.setDisable(false); + applySuccessStyle(result7TA); + resetButtonStyle(caculateHash7B, calculateHashOriginalText); result7TA.setText(task.getValue()); }); @@ -237,10 +260,12 @@ public class StorageCarrierPaneController { progressBar.closeProgress(); Throwable exception = task.getException(); task.progressProperty().removeListener(progressChangeListener); - task.messageProperty().removeListener(messageChangeListener); +// task.messageProperty().removeListener(messageChangeListener); caculateHash7B.setDisable(false); String errorMsg = "生成哈希文件时出错: " + (exception != null ? exception.getMessage() : "未知错误"); + applyErrorStyle(result7TA); DialogUtil.showDetailedErrorDialog("错误", "生成哈希文件时出错", errorMsg); + resetButtonStyle(caculateHash7B, calculateHashOriginalText); log.error(LoggerMarker.RELEASE_MARKER, "哈希文件生成任务失败", exception); result7TA.setText(errorMsg); }); @@ -249,8 +274,10 @@ public class StorageCarrierPaneController { task.setOnCancelled(e -> { progressBar.closeProgress(); task.progressProperty().removeListener(progressChangeListener); - task.messageProperty().removeListener(messageChangeListener); +// task.messageProperty().removeListener(messageChangeListener); caculateHash7B.setDisable(false); + resetStyle(result7TA); + resetButtonStyle(caculateHash7B, calculateHashOriginalText); log.info(LoggerMarker.DEBUG_MARKER, "哈希文件生成任务被用户取消"); result7TA.setText("哈希文件生成操作已取消"); }); @@ -260,7 +287,54 @@ public class StorageCarrierPaneController { thread.setDaemon(true); thread.start(); } + // ======================== 提取的样式变更方法 ======================== + // 样式控制工具方法 + private void applyLoadingStyle(Button button, String text) { + Platform.runLater(() -> { + button.setText(text); + button.getStyleClass().add("loading"); + }); + } + + private void resetButtonStyle(Button button, String originalText) { + Platform.runLater(() -> { + button.setText(originalText); + button.getStyleClass().remove("loading"); + }); + } + + private void applySuccessStyle(TextField textField) { + Platform.runLater(() -> { + textField.getStyleClass().remove("error"); + textField.getStyleClass().add("success"); + }); + } + + private void applySuccessStyle(TextArea textArea) { + Platform.runLater(() -> { + textArea.getStyleClass().removeAll("error"); + textArea.getStyleClass().add("success"); + }); + } + + private void applyErrorStyle(TextArea textArea) { + Platform.runLater(() -> { + textArea.getStyleClass().removeAll("success"); + textArea.getStyleClass().add("error"); + }); + } + private void resetStyle(TextField textField) { + Platform.runLater(() -> { + textField.getStyleClass().removeAll("success", "error"); + }); + } + private void resetStyle(TextArea textArea) { + Platform.runLater(() -> { + textArea.getStyleClass().removeAll("success", "error"); + }); + } + // ==================================================================== } diff --git a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/task/DuplicateDocumentDetectionTask.java b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/task/DuplicateDocumentDetectionTask.java index 1e6b057..2e10dbf 100644 --- a/src/main/java/top/r3944realms/docchecktoolrefactored/ui/task/DuplicateDocumentDetectionTask.java +++ b/src/main/java/top/r3944realms/docchecktoolrefactored/ui/task/DuplicateDocumentDetectionTask.java @@ -66,16 +66,13 @@ public class DuplicateDocumentDetectionTask extends Task{ @Override public void onPhaseProgress(DuplicateFinder.Phase phase, int current, int total) { if (total > 0) { - updateProgress(current, total); - switch (phase) { - case GROUP_BY_SIZE: - totalFiles.set(total); - updateMessage(String.format("正在按文件大小分组: %d/%d", current, total)); - break; - case CALCULATE_HASH: - updateMessage(String.format("正在计算哈希值: %d/%d", current, total)); - break; - } + // 控制更新频率 + String msg = switch (phase) { + case GROUP_BY_SIZE -> String.format("正在按文件大小分组: %d/%d", current, total); + case CALCULATE_HASH -> String.format("正在计算哈希值: %d/%d", current, total); + }; + updateMessage(msg); + updateProgress(current, total); } } diff --git a/src/main/resources/css/project-info-pane.css b/src/main/resources/css/project-info-pane.css new file mode 100644 index 0000000..4f40014 --- /dev/null +++ b/src/main/resources/css/project-info-pane.css @@ -0,0 +1,93 @@ +/* 全局样式 */ +.root { + -fx-background-color: #F9FAFB; + -fx-font-family: "Microsoft YaHei", "SimHei", sans-serif; +} + +/* 标签样式 */ +Label { + -fx-text-fill: #111827; + -fx-font-size: 14px; + -fx-font-weight: 500; +} + +/* 文本输入框样式 */ +TextField { + -fx-background-color: #FFFFFF; + -fx-border-color: #E5E7EB; + -fx-border-width: 1px; + -fx-border-radius: 4px; + -fx-text-fill: #111827; + -fx-font-size: 14px; + -fx-padding: 6px 8px; + -fx-pref-height: 36px; +} + +TextField:focused { + -fx-border-color: #1A56DB; + -fx-border-width: 2px; + -fx-background-insets: 0; + -fx-effect: dropshadow(gaussian, rgba(26, 86, 219, 0.2), 4, 0, 0, 1); +} + +TextField:hover { + -fx-border-color: #9CA3AF; +} + +TextField:disabled { + -fx-background-color: #F3F4F6; + -fx-text-fill: #9CA3AF; + -fx-border-color: #E5E7EB; +} + +/* 按钮样式 */ +Button { + -fx-background-color: #1A56DB; + -fx-text-fill: #FFFFFF; + -fx-font-size: 14px; + -fx-font-weight: 500; + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-cursor: hand; +} + +Button:hover { + -fx-background-color: #1E40AF; +} + +Button:pressed { + -fx-background-color: #1E3A8A; +} + +Button:armed { + -fx-effect: none; +} + +/* 重置按钮特殊样式 */ +#infoResetB { + -fx-background-color: #FFFFFF; + -fx-text-fill: #1A56DB; + -fx-border-color: #1A56DB; + -fx-border-width: 1px; +} + +#infoResetB:hover { + -fx-background-color: #EFF6FF; +} + +/* 网格面板样式 */ +GridPane { + -fx-hgap: 16px; + -fx-vgap: 12px; +} + +/* 错误状态样式 */ +.error { + -fx-border-color: #DC2626 !important; +} + +/* 只读状态样式 */ +.read-only { + -fx-background-color: #F3F4F6; + -fx-cursor: default; +} \ No newline at end of file diff --git a/src/main/resources/css/step-1-pane.css b/src/main/resources/css/step-1-pane.css new file mode 100644 index 0000000..e829bcc --- /dev/null +++ b/src/main/resources/css/step-1-pane.css @@ -0,0 +1,159 @@ +/* 1. 全局基础样式:统一视觉基调 */ +.root { + -fx-background-color: #F9FAFB; /* 符合政企规范的浅灰背景,降低视觉疲劳 */ + -fx-font-family: "Microsoft YaHei", "SimHei", sans-serif; /* 适配中文显示 */ + -fx-font-size: 14px; /* 基础字号,保证可读性 */ +} + +/* 2. 网格布局样式:优化间距与对齐 */ +GridPane { + -fx-hgap: 16px; /* 列间距统一,避免元素拥挤 */ + -fx-vgap: 12px; /* 行间距统一,区分功能区域 */ + -fx-alignment: TOP_LEFT; /* 整体左对齐,符合政企软件操作习惯 */ +} + +/* 3. 标签样式:明确信息层级 */ +Label { + -fx-text-fill: #111827; /* 主文本色,保证清晰度 */ + -fx-font-weight: 500; /* 标签文字稍粗,突出引导性 */ + -fx-padding: 4px 0; /* 上下内边距,避免与输入框垂直错位 */ +} +/* 特殊标签:功能标题(如“工作内容”)强化区分 */ +Label[text="工作内容:"], +Label[text="结果反馈:"], +Label[text="载入文件夹:"] { + -fx-text-fill: #1A56DB; /* 主色调强调,突出核心功能区标题 */ + -fx-font-weight: 600; +} + +/* 4. 文本输入框样式:适配文件路径输入场景 */ +TextField { + -fx-background-color: #FFFFFF; /* 白色背景,保证输入内容清晰 */ + -fx-border-color: #E5E7EB; /* 淡灰边框,区分输入区域 */ + -fx-border-width: 1px; + -fx-border-radius: 4px; /* 圆角设计,避免尖锐感 */ + -fx-text-fill: #111827; + -fx-padding: 8px 12px; /* 内边距充足,输入文字不贴边 */ + -fx-pref-height: 36px; /* 统一高度,与按钮视觉对齐 */ + -fx-cursor: text; /* 文本光标,明确可输入状态 */ +} +/* 输入框交互状态:提升操作反馈 */ +TextField:focused { + -fx-border-color: #1A56DB; /* 聚焦时主色边框,明确当前操作项 */ + -fx-border-width: 2px; + -fx-background-insets: 0; /* 消除聚焦时默认内边距偏移 */ + -fx-effect: dropshadow(gaussian, rgba(26, 86, 219, 0.2), 4, 0, 0, 1); /* 轻微阴影,增强层次感 */ +} +TextField:hover { + -fx-border-color: #9CA3AF; /* 悬停时边框加深,提示可交互 */ +} +TextField:disabled { + -fx-background-color: #F3F4F6; /* 禁用时浅灰背景,区分不可操作状态 */ + -fx-text-fill: #9CA3AF; /* 禁用文本色减淡 */ + -fx-border-color: #E5E7EB; +} + +/* 5. 文本域样式:适配结果展示与操作指引 */ +TextArea { + -fx-background-color: #FFFFFF; + -fx-border-color: #E5E7EB; + -fx-border-width: 1px; + -fx-border-radius: 4px; + -fx-text-fill: #111827; + -fx-padding: 12px; /* 内边距充足,避免文字贴边 */ + -fx-font-size: 14px; + -fx-wrap-text: true; /* 自动换行,适配长文本(如文件路径、检查结果) */ + -fx-line-spacing: 6px; /* 行间距优化,提升多行文本质感 */ +} +/* 结果展示文本域(result1TA):强化可读性 */ +#result1TA { + -fx-pref-height: 580px; /* 适配FXML中结果区域高度,避免滚动条过多 */ + -fx-background-color: #FCFCFD; /* 比普通文本域稍浅,突出结果内容 */ +} +/* 操作指引文本域:区分功能属性 */ +TextArea[text*="点击“选择文件夹”按钮"] { + -fx-text-fill: #4B5563; /* 次要文本色,避免与核心结果冲突 */ + -fx-background-color: #F9FAFB; /* 背景与面板一致,突出“指引”属性 */ + -fx-border-color: #E5E7EB; +} +/* 文本域交互状态:与输入框保持一致 */ +TextArea:focused { + -fx-border-color: #1A56DB; + -fx-border-width: 2px; + -fx-effect: dropshadow(gaussian, rgba(26, 86, 219, 0.2), 4, 0, 0, 1); +} + +/* 6. 按钮样式:区分功能优先级 */ +Button { + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-font-size: 14px; + -fx-font-weight: 500; + -fx-padding: 8px 16px; + -fx-cursor: hand; /* 手型光标,提示可点击 */ + -fx-alignment: CENTER; /* 文字居中,保证视觉整齐 */ +} + +/* 6.1 核心操作按钮:开始检查(高优先级) */ +#start1B { + -fx-background-color: #1A56DB; /* 主色调,突出核心功能 */ + -fx-text-fill: #FFFFFF; + -fx-pref-height: 44px; /* 稍高高度,强化视觉权重 */ +} +#start1B:hover { + -fx-background-color: #1E40AF; /* hover时加深,提升反馈 */ +} +#start1B:pressed { + -fx-background-color: #1E3A8A; /* 点击时进一步加深,模拟按压感 */ +} +#start1B:disabled { + -fx-background-color: #94A3B8; /* 禁用时灰色,明确不可操作 */ + -fx-cursor: default; +} + +/* 6.2 辅助操作按钮:选择文件夹(中优先级) */ +#selectLoadFolder1B { + -fx-background-color: #FFFFFF; /* 白色背景,次要功能属性 */ + -fx-text-fill: #1A56DB; /* 主色文字,保持视觉关联 */ + -fx-border-color: #1A56DB; + -fx-border-width: 1px; + -fx-pref-height: 36px; /* 与输入框高度一致,视觉对齐 */ +} +#selectLoadFolder1B:hover { + -fx-background-color: #EFF6FF; /* hover时淡蓝背景,提示交互 */ +} +#selectLoadFolder1B:pressed { + -fx-background-color: #DBEAFE; +} + +/* 6.3 取消操作按钮:取消检查(低优先级,危险属性) */ +#cancel1B { + -fx-background-color: #FFFFFF; + -fx-text-fill: #DC2626; /* 警示色文字,提示“取消”的中断属性 */ + -fx-border-color: #DC2626; + -fx-border-width: 1px; + -fx-pref-height: 36px; +} +#cancel1B:hover { + -fx-background-color: #FEF2F2; /* hover时淡红背景,强化警示 */ +} +#cancel1B:pressed { + -fx-background-color: #FEE2E2; +} + +/* 7. 特殊状态样式:适配业务场景 */ +/* 7.1 加载中状态(可配合控制器动态添加) */ +.loading { + -fx-background-color: #F3F4F6; + -fx-cursor: wait; /* 等待光标,提示正在处理 */ +} +/* 7.2 结果异常状态(如重复文件提示) */ +.result-error { + -fx-background-color: #DC2626; /* 错误色,突出异常结果 */ + -fx-font-weight: 600; +} +/* 7.3 结果正常状态(如检查完成提示) */ +.result-success { + -fx-background-color: #059669; /* 成功色,传递正常反馈 */ + -fx-font-weight: 600; +} \ No newline at end of file diff --git a/src/main/resources/css/step-2-pane.css b/src/main/resources/css/step-2-pane.css new file mode 100644 index 0000000..8803227 --- /dev/null +++ b/src/main/resources/css/step-2-pane.css @@ -0,0 +1,207 @@ +/* 1. 全局基础样式:统一视觉基调 */ +.root { + -fx-background-color: #F9FAFB; /* 浅灰背景,符合政企软件简洁专业风格 */ + -fx-font-family: "Microsoft YaHei", "SimHei", sans-serif; /* 适配中文显示,避免字体错乱 */ + -fx-font-size: 14px; /* 基础字号,保证不同设备可读性 */ +} + +/* 2. 网格布局样式:优化功能区域间距与对齐 */ +GridPane { + -fx-hgap: 16px; /* 列间距统一,避免元素拥挤(适配多输入框/按钮布局) */ + -fx-vgap: 12px; /* 行间距统一,清晰区分“选择区”“操作区”“结果区” */ + -fx-alignment: TOP_LEFT; /* 整体左对齐,符合政企用户操作习惯 */ +} + +/* 3. 标签样式:明确信息层级,突出引导性 */ +Label { + -fx-text-fill: #111827; /* 主文本色,保证清晰度 */ + -fx-font-weight: 500; /* 标签文字稍粗,突出输入引导 */ + -fx-padding: 6px 0; /* 上下内边距,避免与输入组件垂直错位 */ + -fx-pref-width: 100px; /* 统一标签宽度,使输入框对齐(适配“载入目录”“载入文件夹”等标签) */ +} +/* 特殊标签:功能标题强化(如“工作内容”“结果反馈”) */ +Label[text="工作内容:"], +Label[text="结果反馈:"] { + -fx-text-fill: #1A56DB; /* 主色调强调,明确核心功能区边界 */ + -fx-font-weight: 600; + -fx-pref-width: 80px; /* 适配右侧指引区域宽度 */ +} + +/* 4. 下拉选择框(ChoiceBox)样式:适配“页面级/文件级”选择场景 */ +ChoiceBox { + -fx-background-color: #FFFFFF; /* 白色背景,保证选项清晰 */ + -fx-border-color: #E5E7EB; /* 淡灰边框,区分选择区域 */ + -fx-border-width: 1px; + -fx-border-radius: 4px; /* 圆角设计,避免尖锐感 */ + -fx-text-fill: #111827; + -fx-padding: 8px 12px; /* 内边距充足,选项文字不贴边 */ + -fx-pref-height: 36px; /* 与输入框/按钮高度一致,视觉对齐 */ + -fx-cursor: hand; /* 手型光标,提示可展开选择 */ +} +/* 下拉框交互状态:提升操作反馈 */ +ChoiceBox:hover { + -fx-border-color: #9CA3AF; /* 悬停时边框加深,提示可交互 */ +} +ChoiceBox:focused { + -fx-border-color: #1A56DB; /* 聚焦时主色边框,明确当前操作项 */ + -fx-border-width: 2px; + -fx-effect: dropshadow(gaussian, rgba(26, 86, 219, 0.2), 4, 0, 0, 1); /* 轻微阴影,增强层次感 */ +} +/* 下拉选项面板样式:与选择框视觉统一 */ +ChoiceBox .context-menu { + -fx-background-color: #FFFFFF; + -fx-border-color: #E5E7EB; + -fx-border-radius: 4px; + -fx-padding: 4px 0; +} +ChoiceBox .menu-item { + -fx-padding: 8px 16px; + -fx-font-size: 14px; +} +ChoiceBox .menu-item:hover { + -fx-background-color: #EFF6FF; /* 选项悬停淡蓝背景,与主色调呼应 */ + -fx-text-fill: #1A56DB; +} + +/* 5. 文本输入框样式:适配路径显示场景 */ +TextField { + -fx-background-color: #FFFFFF; + -fx-border-color: #E5E7EB; + -fx-border-width: 1px; + -fx-border-radius: 4px; + -fx-text-fill: #111827; + -fx-padding: 8px 12px; /* 内边距充足,长路径文字不贴边 */ + -fx-pref-height: 36px; /* 统一高度,与按钮/下拉框对齐 */ + -fx-cursor: text; +} +/* 输入框交互状态:与其他组件保持一致 */ +TextField:focused { + -fx-border-color: #1A56DB; + -fx-border-width: 2px; + -fx-background-insets: 0; + -fx-effect: dropshadow(gaussian, rgba(26, 86, 219, 0.2), 4, 0, 0, 1); +} +TextField:hover { + -fx-border-color: #9CA3AF; +} +TextField:disabled { + -fx-background-color: #F3F4F6; /* 禁用时浅灰背景,区分不可操作状态 */ + -fx-text-fill: #9CA3AF; + -fx-border-color: #E5E7EB; +} + +/* 6. 文本域样式:区分“结果展示”与“操作指引” */ +TextArea { + -fx-background-color: #FFFFFF; + -fx-border-color: #E5E7EB; + -fx-border-width: 1px; + -fx-border-radius: 4px; + -fx-text-fill: #111827; + -fx-padding: 12px; /* 内边距充足,避免文字贴边 */ + -fx-font-size: 14px; + -fx-wrap-text: true; /* 自动换行,适配长路径比对结果 */ + -fx-line-spacing: 6px; /* 行间距优化,提升多行文本质感 */ + -fx-pref-height: 550px; /* 适配FXML中结果区域高度,减少滚动条干扰 */ +} +/* 核心结果文本域(result2TA):强化可读性 */ +#result2TA { + -fx-background-color: #FCFCFD; /* 比普通文本域稍浅,突出结果内容 */ + -fx-pref-width: 800px; /* 适配左侧结果区域宽度,避免文字过宽 */ +} +/* 操作指引文本域:区分功能属性 */ +TextArea[text*="选择“页面级”"] { + -fx-text-fill: #4B5563; /* 次要文本色,避免与核心结果冲突 */ + -fx-background-color: #F9FAFB; /* 背景与面板一致,突出“指引”属性 */ + -fx-border-color: #E5E7EB; + -fx-pref-width: 400px; /* 适配右侧指引区域宽度 */ +} +/* 文本域交互状态:与输入框保持一致 */ +TextArea:focused { + -fx-border-color: #1A56DB; + -fx-border-width: 2px; + -fx-effect: dropshadow(gaussian, rgba(26, 86, 219, 0.2), 4, 0, 0, 1); +} + +/* 7. 按钮样式:按功能优先级区分,引导操作流程 */ +Button { + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-font-size: 14px; + -fx-font-weight: 500; + -fx-padding: 8px 16px; + -fx-cursor: hand; /* 手型光标,提示可点击 */ + -fx-alignment: CENTER; /* 文字居中,保证视觉整齐 */ + -fx-pref-height: 36px; /* 统一高度,与输入框/下拉框对齐 */ +} + +/* 7.1 核心操作按钮:开始比对(最高优先级) */ +#start2B { + -fx-background-color: #1A56DB; /* 主色调,突出“比对”核心功能 */ + -fx-text-fill: #FFFFFF; + -fx-pref-height: 44px; /* 稍高高度,强化视觉权重(适配多按钮布局中的焦点引导) */ + -fx-pref-width: 800px; /* 适配FXML中按钮宽度,保证操作区域完整 */ +} +#start2B:hover { + -fx-background-color: #1E40AF; /* hover时加深,提升反馈 */ +} +#start2B:pressed { + -fx-background-color: #1E3A8A; /* 点击时进一步加深,模拟按压感 */ +} +#start2B:disabled { + -fx-background-color: #94A3B8; /* 禁用时灰色,明确不可操作 */ + -fx-cursor: default; +} + +/* 7.2 辅助选择按钮:选择文件/文件夹(中优先级) */ +#selectLoadCatalog2B, +#selectJPGFolder2B { + -fx-background-color: #FFFFFF; /* 白色背景,次要功能属性 */ + -fx-text-fill: #1A56DB; /* 主色文字,保持视觉关联 */ + -fx-border-color: #1A56DB; + -fx-border-width: 1px; +} +#selectLoadCatalog2B:hover, +#selectJPGFolder2B:hover { + -fx-background-color: #EFF6FF; /* hover时淡蓝背景,提示交互 */ +} +#selectLoadCatalog2B:pressed, +#selectJPGFolder2B:pressed { + -fx-background-color: #DBEAFE; +} + +/* 7.3 生成操作按钮:生成地址文件(中优先级,功能关联) */ +#generateLogicalAddress2B, +#generatePhysicalAddress2B { + -fx-background-color: #059669; /* 成功色,传递“生成文件”的正向功能属性 */ + -fx-text-fill: #FFFFFF; +} +#generateLogicalAddress2B:hover, +#generatePhysicalAddress2B:hover { + -fx-background-color: #047857; /* hover时加深,提升反馈 */ +} +#generateLogicalAddress2B:pressed, +#generatePhysicalAddress2B:pressed { + -fx-background-color: #065F46; +} +#generateLogicalAddress2B:disabled, +#generatePhysicalAddress2B:disabled { + -fx-background-color: #6B7280; /* 禁用时灰色,明确不可操作 */ + -fx-cursor: default; +} + +/* 8. 特殊状态样式:适配业务场景需求 */ +/* 8.1 加载中状态(配合控制器动态添加,如比对过程中) */ +.loading { + -fx-background-color: #F3F4F6; + -fx-cursor: wait; /* 等待光标,提示正在处理 */ +} +/* 7.2 结果异常状态(如对比发现有问题,或者无法生成逻辑文件) */ +.result-error { + -fx-background-color: #DC2626; /* 警示色,突出路径差异结果 */ + -fx-font-weight: 600; +} +/* 8.3 比对正常状态(结果区域高亮成功) */ +.result-success { + -fx-background-color: #059669; /* 成功色,传递“无差异”反馈 */ + -fx-font-weight: 600; +} \ No newline at end of file diff --git a/src/main/resources/css/step-3456-pane.css b/src/main/resources/css/step-3456-pane.css new file mode 100644 index 0000000..7c90d49 --- /dev/null +++ b/src/main/resources/css/step-3456-pane.css @@ -0,0 +1,32 @@ +/* 1. 全局基础样式:奠定专业简洁基调 */ +.root { + -fx-background-color: #F9FAFB; /* 浅灰背景,符合政企软件低视觉疲劳需求 */ + -fx-font-family: "Microsoft YaHei", "SimHei", sans-serif; /* 适配中文显示,避免字体模糊 */ +} + +/* 2. 锚点布局样式:确保内容全屏适配 */ +AnchorPane { + -fx-padding: 24px; /* 充足内边距,避免文本贴边(适配800×1000px面板尺寸) */ +} + +/* 3. 核心文本域样式:优化验收标准可读性 */ +TextArea { + /* 基础视觉属性 */ + -fx-background-color: #FFFFFF; /* 白色背景,突出文本内容 */ + -fx-border-color: #E5E7EB; /* 淡灰边框,明确内容区域边界 */ + -fx-border-width: 1px; + -fx-border-radius: 4px; /* 圆角设计,避免尖锐感,提升专业度 */ + -fx-pref-width: 100%; /* 宽度全屏适配,符合FXML中1000px预设 */ + -fx-pref-height: 100%; /* 高度全屏适配,符合FXML中800px预设 */ + -fx-wrap-text: true; /* 强制自动换行,避免横向滚动条(适配长句说明) */ + + /* 文本样式优化:突出层级与重点 */ + -fx-font-size: 18px; /* 匹配FXML预设字号,保证远距离阅读清晰度 */ + -fx-text-fill: #111827; /* 主文本色,确保长时间阅读不费力 */ + -fx-line-spacing: 12px; /* 增大行间距,区分不同验收步骤(比默认多50%,提升可读性) */ + -fx-letter-spacing: 0.5px; /* 轻微字间距,优化中文“著录”“倾斜度”等专业术语识别 */ + + /* 交互体验:弱化编辑属性(因editable="false") */ + -fx-cursor: default; /* 默认光标,明确不可编辑状态 */ + -fx-focus-traversable: false; /* 取消焦点边框,避免用户误解“可操作” */ +} \ No newline at end of file diff --git a/src/main/resources/css/step-7-pane.css b/src/main/resources/css/step-7-pane.css new file mode 100644 index 0000000..7584545 --- /dev/null +++ b/src/main/resources/css/step-7-pane.css @@ -0,0 +1,197 @@ +/* 1. 全局基础样式:奠定专业简洁基调 */ +.root { + -fx-background-color: #F9FAFB; /* 浅灰背景,符合政企软件低视觉疲劳需求 */ + -fx-font-family: "Microsoft YaHei", "SimHei", sans-serif; /* 适配中文显示,避免字体模糊 */ + -fx-font-size: 14px; /* 基础字号,保证各组件文本一致性 */ +} + +/* 2. 网格布局样式:优化多组件排版一致性 */ +GridPane { + -fx-hgap: 12px; /* 列间距适配多按钮/输入框布局,避免拥挤 */ + -fx-vgap: 16px; /* 行间距区分“加载区”“操作区”“结果区”,提升层次感 */ + -fx-alignment: TOP_LEFT; /* 整体左对齐,符合政企用户操作习惯 */ + -fx-padding: 10px; /* 与FXML中padding呼应,确保整体边距统一 */ +} + +/* 3. 标签样式:明确功能引导,突出核心提示 */ +Label { + -fx-text-fill: #111827; /* 主文本色,保证清晰度 */ + -fx-font-weight: 500; /* 标签文字稍粗,突出输入引导 */ + -fx-pref-width: 120px; /* 统一标签宽度,使“载入数字化成果”“载入压缩包”等输入框对齐 */ +} +/* 修复压缩包提示标签显示不全:专项样式 */ +/* 匹配文本内容的标签(避免影响其他标签) */ +Label[text*="将档案目录、哈希值列表文件"] { + /* 1. 宽度适配:强制占满父容器(GridPane),避免列宽限制截断 */ + -fx-max-width: 100%; /* 最大宽度=父容器宽度(1065px-20px内边距=1045px) */ + -fx-pref-width: 100%; /* 优先使用100%宽度,覆盖原prefWidth="740.0" */ + + /* 2. 文本换行:允许长文本折行,避免横向溢出 */ + -fx-wrap-text: true; /* 核心属性:开启自动换行(默认false) */ + -fx-text-alignment: CENTER; /* 保持居中对齐,符合提示属性 */ + + /* 3. 内边距与间距:避免文本贴边,提升可读性 */ + + /* 4. 视觉强化:保持原提示属性,突出核心要求 */ + -fx-text-fill: #1A56DB; /* 主色调强调 */ + -fx-font-weight: 600; + -fx-font-size: 140px; +} +/* 特殊标签2:功能标题(如“工作内容”“结果反馈”) */ +Label[text="工作内容:"], +Label[text="结果反馈:"] { + -fx-text-fill: #1A56DB; /* 主色调强调,明确功能区边界 */ + -fx-font-weight: 600; + -fx-pref-width: 80px; /* 适配右侧指引区域宽度 */ +} + +/* 4. 文本输入框样式:适配文件路径与成果信息展示 */ +TextField { + -fx-background-color: #FFFFFF; /* 白色背景,保证输入内容清晰 */ + -fx-border-color: #E5E7EB; /* 淡灰边框,区分输入区域 */ + -fx-border-width: 1px; + -fx-border-radius: 4px; /* 圆角设计,避免尖锐感 */ + -fx-text-fill: #111827; + -fx-padding: 8px 12px; /* 内边距充足,长文件路径不贴边 */ + -fx-pref-height: 36px; /* 统一高度,与按钮视觉对齐 */ + -fx-cursor: text; /* 文本光标,明确可输入/选择状态 */ + -fx-hgrow: ALWAYS; /* 自适应列宽,符合FXML中hgrow="ALWAYS"设置 */ +} +/* 输入框交互状态:提升操作反馈 */ +TextField:focused { + -fx-border-color: #1A56DB; /* 聚焦时主色边框,明确当前操作项 */ + -fx-border-width: 2px; + -fx-background-insets: 0; + -fx-effect: dropshadow(gaussian, rgba(26, 86, 219, 0.2), 4, 0, 0, 1); /* 轻微阴影,增强层次感 */ +} +TextField:hover { + -fx-border-color: #9CA3AF; /* 悬停时边框加深,提示可交互 */ +} +TextField:disabled { + -fx-background-color: #F3F4F6; /* 禁用时浅灰背景,区分不可操作状态 */ + -fx-text-fill: #9CA3AF; + -fx-border-color: #E5E7EB; +} + +/* 5. 文本域样式:区分“结果展示”与“操作指引” */ +TextArea { + -fx-background-color: #FFFFFF; + -fx-border-color: #E5E7EB; + -fx-border-width: 1px; + -fx-border-radius: 4px; + -fx-text-fill: #111827; + -fx-padding: 12px; /* 内边距充足,避免文字贴边 */ + -fx-font-size: 14px; + -fx-wrap-text: true; /* 自动换行,适配长步骤说明与哈希结果 */ + -fx-line-spacing: 8px; /* 行间距优化,提升多行文本质感 */ + -fx-pref-height: 580px; /* 适配FXML中结果区域高度,减少滚动条干扰 */ +} +/* 核心结果文本域(result7TA):强化哈希结果可读性 */ +#result7TA { + -fx-background-color: #FCFCFD; /* 比普通文本域稍浅,突出结果内容 */ + -fx-pref-width: 600px; /* 适配左侧结果区域宽度,避免文字过宽 */ +} +/* 操作指引文本域:区分功能属性 */ +TextArea[text*="对照《存储载体检查登记表》"] { + -fx-text-fill: #4B5563; /* 次要文本色,避免与核心结果冲突 */ + -fx-background-color: #F9FAFB; /* 背景与面板一致,突出“指引”属性 */ + -fx-border-color: #E5E7EB; + -fx-pref-width: 400px; /* 适配右侧指引区域宽度 */ +} +/* 文本域交互状态:弱化编辑属性(因editable="false") */ +TextArea { + -fx-cursor: default; /* 默认光标,明确不可编辑状态 */ +} +TextArea:focused { + -fx-border-color: #1A56DB; /* 聚焦时仍保留边框反馈,避免用户误解“无响应” */ + -fx-border-width: 2px; +} + +/* 6. 按钮样式:按功能优先级区分,引导“加载-计算-打包-验证”流程 */ +Button { + -fx-border-radius: 4px; + -fx-background-radius: 4px; + -fx-font-size: 14px; + -fx-font-weight: 500; + -fx-padding: 8px 16px; + -fx-cursor: hand; /* 手型光标,提示可点击 */ + -fx-alignment: CENTER; /* 文字居中,保证视觉整齐 */ + -fx-pref-height: 36px; /* 统一高度,与输入框对齐 */ +} + +/* 6.1 核心操作按钮:生成哈希值/计算哈希值(高优先级) */ +#generateHashFile7B, +#caculateHash7B { + -fx-background-color: #1A56DB; /* 主色调,突出“哈希计算”核心功能(数据完整性验证关键步骤) */ + -fx-text-fill: #FFFFFF; + -fx-pref-width: 160px; /* 适配按钮文本长度,避免文字换行 */ +} +#generateHashFile7B:hover, +#caculateHash7B:hover { + -fx-background-color: #1E40AF; /* hover时加深,提升反馈 */ +} +#generateHashFile7B:pressed, +#caculateHash7B:pressed { + -fx-background-color: #1E3A8A; /* 点击时进一步加深,模拟按压感 */ +} +#generateHashFile7B:disabled, +#caculateHash7B:disabled { + -fx-background-color: #94A3B8; /* 禁用时灰色,明确不可操作(如未选择文件时) */ + -fx-cursor: default; +} + +/* 6.2 辅助选择按钮:选择文件(中优先级) */ +#selectLoadDigitalOutcomes7B, +#selectLoadCompressedFile7B { + -fx-background-color: #FFFFFF; /* 白色背景,次要功能属性 */ + -fx-text-fill: #1A56DB; /* 主色文字,保持视觉关联 */ + -fx-border-color: #1A56DB; + -fx-border-width: 1px; + -fx-pref-width: 100px; /* 适配“选择文件”文本长度 */ +} +#selectLoadDigitalOutcomes7B:hover, +#selectLoadCompressedFile7B:hover { + -fx-background-color: #EFF6FF; /* hover时淡蓝背景,提示交互 */ +} +#selectLoadDigitalOutcomes7B:pressed, +#selectLoadCompressedFile7B:pressed { + -fx-background-color: #DBEAFE; +} + +/* 6.3 清除操作按钮:清除选择(低优先级,辅助功能) */ +#clearSelectedFoldersButton { + -fx-background-color: #FFFFFF; + -fx-text-fill: #6B7280; /* 浅灰文字,弱化次要功能视觉权重 */ + -fx-border-color: #E5E7EB; /* 淡灰边框,区分按钮区域 */ + -fx-border-width: 1px; + -fx-pref-width: 80px; /* 适配“清除”文本长度 */ +} +#clearSelectedFoldersButton:hover { + -fx-background-color: #F3F4F6; /* hover时浅灰背景,提示交互 */ + -fx-text-fill: #111827; /* hover时文字加深,提升可读性 */ +} +#clearSelectedFoldersButton:pressed { + -fx-background-color: #E5E7EB; +} + +/* 7. 特殊状态样式:适配哈希计算与压缩包验证场景 */ +/* 7.1 加载中状态(如哈希计算过程中) */ +.loading { + -fx-background-color: #F3F4F6; + -fx-cursor: wait; /* 等待光标,提示正在处理 */ +} +/* 7.2 成功状态(结果区域高亮) */ +.success { + -fx-background-color: #059669; /* 成功色,传递“哈希值一致”反馈 */ + -fx-font-weight: 600; +} +/* 7.3 失败状态(结果区域高亮) */ +.error { + -fx-background-color: #DC2626; /* 警示色,突出“哈希值不一致”风险 */ + -fx-font-weight: 600; +} +/* 7.4 压缩包提示高亮(文本域内关键信息) */ +.package-highlight { + -fx-background-color: #1A56DB; /* 主色调,突出“数字化验收检测包.rar”核心文件名 */ + -fx-font-weight: 600; +} \ No newline at end of file diff --git a/src/main/resources/fxml/module/project-info-pane.fxml b/src/main/resources/fxml/module/project-info-pane.fxml index 8357881..024f517 100644 --- a/src/main/resources/fxml/module/project-info-pane.fxml +++ b/src/main/resources/fxml/module/project-info-pane.fxml @@ -9,7 +9,7 @@ - + @@ -134,7 +134,7 @@ - - - - - - - - - -