Template
Improve music processing robustness and workflow UX
Unify safe file-move behavior and richer progress semantics across backend tasks, while upgrading traditional-to-simplified conversion and refining the frontend multi-step panels for clearer execution feedback.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.music.service;
|
||||
|
||||
import com.music.common.FileTransferUtils;
|
||||
import com.music.dto.ProgressMessage;
|
||||
import org.jaudiotagger.audio.AudioFile;
|
||||
import org.jaudiotagger.audio.AudioFileIO;
|
||||
@@ -109,6 +110,7 @@ public class DedupService {
|
||||
AtomicInteger duplicateGroups = new AtomicInteger(0);
|
||||
AtomicInteger moved = new AtomicInteger(0);
|
||||
AtomicInteger failed = new AtomicInteger(0);
|
||||
Set<Path> processedDuplicates = new HashSet<>();
|
||||
|
||||
sendProgress(taskId, total, 0, 0, 0,
|
||||
"开始扫描音乐库...", false);
|
||||
@@ -147,7 +149,7 @@ public class DedupService {
|
||||
// 第二阶段:处理 MD5 去重结果(完全二进制重复)
|
||||
if (useMd5) {
|
||||
for (Map.Entry<String, List<Path>> entry : md5Groups.entrySet()) {
|
||||
List<Path> group = entry.getValue();
|
||||
List<Path> group = filterProcessableCandidates(entry.getValue(), processedDuplicates);
|
||||
if (group.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
@@ -158,15 +160,15 @@ public class DedupService {
|
||||
List<Path> duplicates = new ArrayList<>(group);
|
||||
duplicates.remove(keep);
|
||||
|
||||
moved.addAndGet(handleDuplicates(duplicates, keep, trashPath, mode, taskId, total,
|
||||
scanned, duplicateGroups, failed));
|
||||
handleDuplicates(duplicates, keep, trashPath, mode, taskId, total,
|
||||
scanned, duplicateGroups, moved, failed, processedDuplicates);
|
||||
}
|
||||
}
|
||||
|
||||
if (useMetadata) {
|
||||
// 第三阶段:处理元数据匹配去重结果
|
||||
for (Map.Entry<MetadataKey, List<Path>> entry : metadataGroups.entrySet()) {
|
||||
List<Path> group = entry.getValue();
|
||||
List<Path> group = filterProcessableCandidates(entry.getValue(), processedDuplicates);
|
||||
if (group.size() <= 1) {
|
||||
continue;
|
||||
}
|
||||
@@ -177,8 +179,8 @@ public class DedupService {
|
||||
List<Path> duplicates = new ArrayList<>(group);
|
||||
duplicates.remove(keep);
|
||||
|
||||
moved.addAndGet(handleDuplicates(duplicates, keep, trashPath, mode, taskId, total,
|
||||
scanned, duplicateGroups, failed));
|
||||
handleDuplicates(duplicates, keep, trashPath, mode, taskId, total,
|
||||
scanned, duplicateGroups, moved, failed, processedDuplicates);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,30 +364,30 @@ public class DedupService {
|
||||
|
||||
/**
|
||||
* 将重复文件移动/复制到回收站,并更新统计与进度
|
||||
*
|
||||
* @return 实际成功移动/复制的文件数量
|
||||
*/
|
||||
private int handleDuplicates(List<Path> duplicates,
|
||||
Path keep,
|
||||
Path trashPath,
|
||||
String mode,
|
||||
String taskId,
|
||||
int total,
|
||||
AtomicInteger scanned,
|
||||
AtomicInteger duplicateGroups,
|
||||
AtomicInteger failed) {
|
||||
int movedCount = 0;
|
||||
private void handleDuplicates(List<Path> duplicates,
|
||||
Path keep,
|
||||
Path trashPath,
|
||||
String mode,
|
||||
String taskId,
|
||||
int total,
|
||||
AtomicInteger scanned,
|
||||
AtomicInteger duplicateGroups,
|
||||
AtomicInteger moved,
|
||||
AtomicInteger failed,
|
||||
Set<Path> processedDuplicates) {
|
||||
for (Path dup : duplicates) {
|
||||
try {
|
||||
Path target = resolveTargetFile(trashPath, dup.getFileName().toString());
|
||||
if ("move".equalsIgnoreCase(mode)) {
|
||||
Files.move(dup, target, StandardCopyOption.REPLACE_EXISTING);
|
||||
FileTransferUtils.moveWithFallback(dup, target);
|
||||
} else {
|
||||
Files.copy(dup, target, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
movedCount++;
|
||||
moved.incrementAndGet();
|
||||
processedDuplicates.add(toNormalizedAbsolutePath(dup));
|
||||
sendProgress(taskId, total, scanned.get(),
|
||||
duplicateGroups.get(), movedCount,
|
||||
duplicateGroups.get(), moved.get(),
|
||||
String.format("重复文件: %s (保留: %s)",
|
||||
dup.getFileName(), keep.getFileName()),
|
||||
false);
|
||||
@@ -394,7 +396,24 @@ public class DedupService {
|
||||
log.warn("处理重复文件失败: {}", dup, e);
|
||||
}
|
||||
}
|
||||
return movedCount;
|
||||
}
|
||||
|
||||
private List<Path> filterProcessableCandidates(List<Path> group, Set<Path> processedDuplicates) {
|
||||
List<Path> candidates = new ArrayList<>(group.size());
|
||||
for (Path file : group) {
|
||||
Path normalized = toNormalizedAbsolutePath(file);
|
||||
if (processedDuplicates.contains(normalized)) {
|
||||
continue;
|
||||
}
|
||||
if (Files.exists(file)) {
|
||||
candidates.add(file);
|
||||
}
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
private Path toNormalizedAbsolutePath(Path path) {
|
||||
return path.toAbsolutePath().normalize();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -424,8 +443,8 @@ public class DedupService {
|
||||
* 字段语义(供前端展示用):
|
||||
* - total:扫描到的音频文件总数
|
||||
* - processed:已扫描文件数
|
||||
* - success:重复组数量
|
||||
* - failed:移动/复制的重复文件数量
|
||||
* - duplicateGroups / success:重复组数量
|
||||
* - movedFiles / failed:移动/复制的重复文件数量
|
||||
*
|
||||
* 由于进度字段在不同任务中的含义略有差异,前端可根据 type === "dedup" 做专门映射。
|
||||
*/
|
||||
@@ -443,6 +462,8 @@ public class DedupService {
|
||||
pm.setProcessed(processed);
|
||||
pm.setSuccess(success);
|
||||
pm.setFailed(failed);
|
||||
pm.setDuplicateGroups(success);
|
||||
pm.setMovedFiles(failed);
|
||||
pm.setCurrentFile(null);
|
||||
pm.setMessage(message);
|
||||
pm.setCompleted(completed);
|
||||
@@ -451,4 +472,3 @@ public class DedupService {
|
||||
messagingTemplate.convertAndSend("/topic/progress/" + taskId, pm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user