功能已稳定
This commit is contained in:
@@ -24,7 +24,7 @@
|
||||
<!-- Maven 编译/测试启动时的 JVM 参数,确保 IDEA 内运行不乱码 -->
|
||||
<argLine>-Dfile.encoding=UTF-8</argLine>
|
||||
<!-- OpenJFX 版本 -->
|
||||
<javafx.version>17.0.14</javafx.version>
|
||||
<javafx.version>17.0.15</javafx.version>
|
||||
<!-- AtlantaFX 版本 -->
|
||||
<atlantafx.version>2.0.1</atlantafx.version>
|
||||
<!-- 指定 JDK 17 路径(系统默认 JDK 8 时启用) -->
|
||||
|
||||
@@ -110,6 +110,16 @@ if %errorlevel% neq 0 (
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
::: 4.5 补充 JavaFX 原生 DLL(jlink 不会自动从 SDK bin/ 复制)
|
||||
echo Copy JavaFX native DLLs...
|
||||
if exist "%JFX_SDK_HOME%\bin\glass.dll" (
|
||||
xcopy /y /q "%JFX_SDK_HOME%\bin\*.dll" "%TARGET%\jre\bin\" >nul
|
||||
echo [OK] JavaFX DLLs copied
|
||||
) else (
|
||||
echo [WARN] No JavaFX DLLs found in %JFX_SDK_HOME%\bin
|
||||
)
|
||||
|
||||
echo [OK] JRE generated : %TARGET%\jre
|
||||
|
||||
::: ============================================================
|
||||
|
||||
@@ -70,6 +70,8 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
private List<DamagedRepo> lastDamagedRepos;
|
||||
/** 缓存上一次使用的目标分支 */
|
||||
private String lastBranch;
|
||||
/** 同步取消标记(供 GUI 终止按钮使用) */
|
||||
private volatile boolean syncCancelled = false;
|
||||
|
||||
// ==================== 启动时从日志恢复缓存 ====================
|
||||
|
||||
@@ -257,11 +259,7 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
Map<String, String> baseUrlMap = new LinkedHashMap<>();
|
||||
for (FileOperationHelper.ProjectPathInfo proj : projects) {
|
||||
if (proj.getRemoteBaseUrl() != null && !proj.getRemoteBaseUrl().isEmpty()) {
|
||||
String url = proj.getRemoteBaseUrl();
|
||||
if (!url.endsWith("/")) {
|
||||
url = url + "/";
|
||||
}
|
||||
baseUrlMap.put(normalizePath(proj.getPath()), url);
|
||||
baseUrlMap.put(normalizePath(proj.getPath()), proj.getRemoteBaseUrl());
|
||||
}
|
||||
}
|
||||
log.info("从项目路径文件加载了 {} 条远程URL映射", baseUrlMap.size());
|
||||
@@ -290,7 +288,7 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
int done = completed.incrementAndGet();
|
||||
String tag;
|
||||
switch (result) {
|
||||
case OK: tag = "成功"; break;
|
||||
case OK: tag = result.cloned ? "拉取" : "成功"; break;
|
||||
case DAMAGED: tag = "损坏"; break;
|
||||
default: tag = "失败"; break;
|
||||
}
|
||||
@@ -485,11 +483,7 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
List<FileOperationHelper.ProjectPathInfo> projects = fileOperationHelper.getProjectPathsWithStatus();
|
||||
for (FileOperationHelper.ProjectPathInfo proj : projects) {
|
||||
if (proj.getRemoteBaseUrl() != null && !proj.getRemoteBaseUrl().isEmpty()) {
|
||||
String url = proj.getRemoteBaseUrl();
|
||||
if (!url.endsWith("/")) {
|
||||
url = url + "/";
|
||||
}
|
||||
map.put(normalizePath(proj.getPath()), url);
|
||||
map.put(normalizePath(proj.getPath()), proj.getRemoteBaseUrl());
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -498,15 +492,14 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
return map;
|
||||
}
|
||||
|
||||
/** 解析 clone URL:优先从项目路径文件的 BASE_URL 拼接,其次用缓存的 remoteUrl */
|
||||
/** 解析 clone URL:BASE_URL 本身就是完整的 clone 地址,直接返回 */
|
||||
private String resolveCloneUrl(DamagedRepo dr, Map<String, String> baseUrlMap) {
|
||||
// 1. 从项目路径文件的 BASE_URL 拼接(项目路径文件为准)
|
||||
// 1. 从项目路径文件的 BASE_URL(已是完整 clone URL,如 https://user@host/path/repo.git)
|
||||
if (baseUrlMap != null) {
|
||||
String normalizedPath = normalizePath(dr.path);
|
||||
String baseUrl = baseUrlMap.get(normalizedPath);
|
||||
if (baseUrl != null) {
|
||||
String repoName = extractName(dr.path);
|
||||
return baseUrl + repoName;
|
||||
return baseUrl;
|
||||
}
|
||||
}
|
||||
// 2. 兜底:缓存的 remoteUrl
|
||||
@@ -520,9 +513,31 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
|
||||
private SyncResult syncOneRepo(String repoPath, String branch, Map<String, String> baseUrlMap) {
|
||||
File repoDir = new File(repoPath);
|
||||
if (!repoDir.exists() || !new File(repoDir, ".git").exists()) {
|
||||
|
||||
// 目录不存在 或 空目录 → 自动 clone
|
||||
if (!repoDir.exists() || (repoDir.isDirectory() && isEmptyDir(repoDir))) {
|
||||
String reason = !repoDir.exists() ? "目录不存在" : "目录为空";
|
||||
log.info("{},自动 clone: {}", reason, repoPath);
|
||||
String cloneUrl = resolveSimpleCloneUrl(repoPath, baseUrlMap);
|
||||
if (cloneUrl != null) {
|
||||
if (doClone(repoPath, branch, cloneUrl)) {
|
||||
SyncResult r = SyncResult.OK;
|
||||
r.output = "auto-cloned";
|
||||
r.cloned = true;
|
||||
return r;
|
||||
}
|
||||
log.warn("自动 clone 失败: {} -> {}", repoPath, "exit code != 0");
|
||||
}
|
||||
SyncResult r = SyncResult.DAMAGED;
|
||||
r.error = "目录不存在或无 .git";
|
||||
r.error = reason + ",自动 clone 失败(远程URL: " + (cloneUrl != null ? cloneUrl : "未知") + ")";
|
||||
r.remoteUrl = cloneUrl;
|
||||
return r;
|
||||
}
|
||||
|
||||
// 目录存在但无 .git → 仓库损坏
|
||||
if (!new File(repoDir, ".git").exists()) {
|
||||
SyncResult r = SyncResult.DAMAGED;
|
||||
r.error = "目录存在但无 .git(仓库损坏)";
|
||||
r.remoteUrl = getRemoteUrl(repoPath, baseUrlMap);
|
||||
return r;
|
||||
}
|
||||
@@ -583,40 +598,49 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
return result;
|
||||
}
|
||||
|
||||
// ==================== 重拉(clone)逻辑 ====================
|
||||
// ==================== clone 逻辑 ====================
|
||||
|
||||
private boolean doReclone(DamagedRepo dr, String cloneUrl) {
|
||||
String repoPath = dr.path;
|
||||
String branch = dr.branch;
|
||||
|
||||
// 删除旧目录
|
||||
/** 执行 git clone(删除旧目录后克隆),供 auto-clone 和手动重拉共用 */
|
||||
private boolean doClone(String repoPath, String branch, String cloneUrl) {
|
||||
File dir = new File(repoPath);
|
||||
// 确保父目录存在
|
||||
if (dir.getParentFile() != null && !dir.getParentFile().exists()) {
|
||||
dir.getParentFile().mkdirs();
|
||||
}
|
||||
// 删除旧目录(如果存在)
|
||||
if (dir.exists()) {
|
||||
try {
|
||||
deleteRecursive(dir.toPath());
|
||||
log.info("已删除仓库: {}", repoPath);
|
||||
System.out.println(" 已删除旧目录");
|
||||
} catch (IOException e) {
|
||||
System.err.println(" 删除失败: " + e.getMessage());
|
||||
log.error("删除失败: {}", repoPath, e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// clone
|
||||
String parentDir = dir.getParent();
|
||||
System.out.println(" clone URL: " + cloneUrl);
|
||||
String parentDir = dir.getParent() != null ? dir.getParent() : ".";
|
||||
CmdResult cr = runGit(parentDir,
|
||||
"git clone -b " + branch + " " + cloneUrl + " \"" + repoPath + "\"");
|
||||
|
||||
if (cr.ok) {
|
||||
System.out.println(" clone 成功");
|
||||
return true;
|
||||
} else {
|
||||
System.err.println(" clone 失败: " + cr.error);
|
||||
log.error("clone 失败: {} -> {}", cloneUrl, cr.error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** 手动重拉(供 DamagedRepo 场景使用) */
|
||||
private boolean doReclone(DamagedRepo dr, String cloneUrl) {
|
||||
System.out.println(" clone URL: " + cloneUrl);
|
||||
boolean ok = doClone(dr.path, dr.branch, cloneUrl);
|
||||
if (ok) {
|
||||
System.out.println(" clone 成功");
|
||||
} else {
|
||||
System.err.println(" clone 失败");
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
// ==================== Git 命令执行 ====================
|
||||
|
||||
/**
|
||||
@@ -721,16 +745,13 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
// 3. 兜底: 从项目路径文件中的 BASE_URL 拼接完整 clone URL
|
||||
// 格式: 项目路径文件 key=仓库路径, value=BASE_URL; clone URL = BASE_URL + cf/ + 仓库名
|
||||
// 3. 兜底: 项目路径文件中的 BASE_URL 即完整的 clone URL
|
||||
if (baseUrlMap != null) {
|
||||
String normalizedPath = normalizePath(repoPath);
|
||||
String baseUrl = baseUrlMap.get(normalizedPath);
|
||||
if (baseUrl != null) {
|
||||
String repoName = extractName(repoPath);
|
||||
String fullUrl = baseUrl + repoName;
|
||||
log.info("从项目路径文件拼接远程URL: {} -> {}", repoPath, fullUrl);
|
||||
return fullUrl;
|
||||
log.info("从项目路径文件获取远程URL: {} -> {}", repoPath, baseUrl);
|
||||
return baseUrl;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -766,6 +787,19 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
return idx >= 0 ? path.substring(idx + 1) : path;
|
||||
}
|
||||
|
||||
/** 判断目录是否为空 */
|
||||
private boolean isEmptyDir(File dir) {
|
||||
if (!dir.isDirectory()) return false;
|
||||
String[] files = dir.list();
|
||||
return files != null && files.length == 0;
|
||||
}
|
||||
|
||||
/** 从 baseUrlMap 获取 clone URL(不拼仓库名,BASE_URL 即完整 clone URL) */
|
||||
private String resolveSimpleCloneUrl(String repoPath, Map<String, String> baseUrlMap) {
|
||||
if (baseUrlMap == null) return null;
|
||||
return baseUrlMap.get(normalizePath(repoPath));
|
||||
}
|
||||
|
||||
/** 路径规范化:统一用 / 分隔、小写,用于映射表匹配 */
|
||||
private String normalizePath(String path) {
|
||||
if (path == null || path.isEmpty()) return "";
|
||||
@@ -801,6 +835,7 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
* 以回调方式同步所有项目(供可视窗口调用)
|
||||
*/
|
||||
public void syncWithCallback(String branch, SyncCallback cb) {
|
||||
syncCancelled = false;
|
||||
List<FileOperationHelper.ProjectPathInfo> projects;
|
||||
try {
|
||||
projects = fileOperationHelper.getProjectPathsWithStatus();
|
||||
@@ -814,12 +849,12 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
return;
|
||||
}
|
||||
|
||||
if (syncCancelled) { cb.onLog("[INFO] 同步已取消"); return; }
|
||||
|
||||
Map<String, String> baseUrlMap = new LinkedHashMap<>();
|
||||
for (FileOperationHelper.ProjectPathInfo proj : projects) {
|
||||
if (proj.getRemoteBaseUrl() != null && !proj.getRemoteBaseUrl().isEmpty()) {
|
||||
String url = proj.getRemoteBaseUrl();
|
||||
if (!url.endsWith("/")) url = url + "/";
|
||||
baseUrlMap.put(normalizePath(proj.getPath()), url);
|
||||
baseUrlMap.put(normalizePath(proj.getPath()), proj.getRemoteBaseUrl());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -835,7 +870,13 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
cb.onLog("并行线程: " + PARALLEL);
|
||||
cb.onLog("开始同步...\n");
|
||||
|
||||
if (syncCancelled) { cb.onLog("[INFO] 同步已取消"); pool.shutdownNow(); return; }
|
||||
|
||||
for (int i = 0; i < total; i++) {
|
||||
if (syncCancelled) {
|
||||
// 不再提交新任务,但已提交的会在 latch 中计完
|
||||
break;
|
||||
}
|
||||
final FileOperationHelper.ProjectPathInfo proj = projects.get(i);
|
||||
final String repoPath = proj.getPath();
|
||||
final String repoName = extractName(repoPath);
|
||||
@@ -850,7 +891,7 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
int done = completed.incrementAndGet();
|
||||
String tag;
|
||||
switch (result) {
|
||||
case OK: tag = "成功"; break;
|
||||
case OK: tag = result.cloned ? "拉取" : "成功"; break;
|
||||
case DAMAGED: tag = "损坏"; break;
|
||||
default: tag = "失败"; break;
|
||||
}
|
||||
@@ -869,10 +910,20 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
|
||||
pool.shutdown();
|
||||
try {
|
||||
boolean allDone = latch.await(SYNC_TOTAL_TIMEOUT_MINUTES, TimeUnit.MINUTES);
|
||||
if (!allDone) {
|
||||
pool.shutdownNow();
|
||||
cb.onLog("\n[ERROR] 同步超时(超过 " + SYNC_TOTAL_TIMEOUT_MINUTES + " 分钟),强制终止");
|
||||
// 缩短每次 await 时间,以便及时响应取消
|
||||
long checkIntervalMs = 500;
|
||||
long deadline = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(SYNC_TOTAL_TIMEOUT_MINUTES);
|
||||
while (!latch.await(checkIntervalMs, TimeUnit.MILLISECONDS)) {
|
||||
if (syncCancelled) {
|
||||
cb.onLog("\n[WARN] 用户取消了同步,正在终止...");
|
||||
pool.shutdownNow();
|
||||
break;
|
||||
}
|
||||
if (System.currentTimeMillis() > deadline) {
|
||||
pool.shutdownNow();
|
||||
cb.onLog("\n[ERROR] 同步超时(超过 " + SYNC_TOTAL_TIMEOUT_MINUTES + " 分钟),强制终止");
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
@@ -881,6 +932,7 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
return;
|
||||
}
|
||||
|
||||
// 汇总结果
|
||||
int success = 0, failed = 0;
|
||||
List<DamagedRepo> damagedRepos = new ArrayList<>();
|
||||
for (FileOperationHelper.ProjectPathInfo proj : projects) {
|
||||
@@ -914,6 +966,11 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
/** 取消当前正在执行的同步(供 GUI 终止按钮调用) */
|
||||
public void cancelSync() {
|
||||
this.syncCancelled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取损坏仓库的 clone URL(供窗口使用)
|
||||
*/
|
||||
@@ -969,6 +1026,7 @@ public class GitSyncPlugin implements Plugin, InitializingBean {
|
||||
String output;
|
||||
String error;
|
||||
String remoteUrl;
|
||||
boolean cloned; // 标记是否是通过 auto-clone 完成的,区别于正常 fetch+checkout+pull
|
||||
}
|
||||
|
||||
/** 损坏仓库信息 */
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Git 仓库同步可视化窗口
|
||||
@@ -46,7 +45,6 @@ public class GitSyncWindow {
|
||||
private ProgressBar progressBar;
|
||||
private Label progressLabel;
|
||||
private TextArea logArea;
|
||||
private final AtomicBoolean stopRequested = new AtomicBoolean(false);
|
||||
|
||||
// Tab 3: 损坏仓库处理
|
||||
private TableView<DamagedRow> damagedTable;
|
||||
@@ -204,7 +202,11 @@ public class GitSyncWindow {
|
||||
|
||||
stopBtn = StyledButton.danger("终止", Theme.base(14));
|
||||
stopBtn.setDisable(true);
|
||||
stopBtn.setOnAction(e -> stopRequested.set(true));
|
||||
stopBtn.setOnAction(e -> {
|
||||
stopBtn.setDisable(true);
|
||||
progressLabel.setText("正在终止...");
|
||||
plugin.cancelSync();
|
||||
});
|
||||
|
||||
branchRow.getChildren().addAll(branchLabel, branchField, syncBtn, stopBtn);
|
||||
|
||||
@@ -240,7 +242,6 @@ public class GitSyncWindow {
|
||||
|
||||
syncBtn.setDisable(true);
|
||||
stopBtn.setDisable(false);
|
||||
stopRequested.set(false);
|
||||
logArea.clear();
|
||||
progressBar.setProgress(0);
|
||||
progressLabel.setText("正在同步...");
|
||||
|
||||
@@ -44,9 +44,16 @@ public class MyBatisExportWindow {
|
||||
|
||||
// 操作
|
||||
private Button exportBtn;
|
||||
private Button stopBtn;
|
||||
private ProgressBar progressBar;
|
||||
private Label progressLabel;
|
||||
|
||||
// 日志
|
||||
private TextArea logArea;
|
||||
|
||||
// 取消标记
|
||||
private volatile boolean exportCancelled = false;
|
||||
|
||||
// 历史记录
|
||||
private TableView<HistoryRow> historyTable;
|
||||
private final ObservableList<HistoryRow> historyRows = FXCollections.observableArrayList();
|
||||
@@ -131,20 +138,40 @@ public class MyBatisExportWindow {
|
||||
exportBtn = StyledButton.primary("导出", Theme.bold(fsBtn()));
|
||||
exportBtn.setOnAction(e -> startExport());
|
||||
|
||||
filterRow.getChildren().addAll(modeLabel, filterModeCmb, filterValueField, filterHint, exportBtn);
|
||||
stopBtn = StyledButton.danger("终止", Theme.base(fsBtn()));
|
||||
stopBtn.setDisable(true);
|
||||
stopBtn.setOnAction(e -> {
|
||||
stopBtn.setDisable(true);
|
||||
progressLabel.setText("正在终止...");
|
||||
exportCancelled = true;
|
||||
});
|
||||
|
||||
filterRow.getChildren().addAll(modeLabel, filterModeCmb, filterValueField, filterHint, exportBtn, stopBtn);
|
||||
|
||||
// === 进度 ===
|
||||
HBox progressRow = new HBox(Theme.S2);
|
||||
progressRow.setAlignment(Pos.CENTER_LEFT);
|
||||
progressBar = new ProgressBar(0);
|
||||
progressBar.setPrefWidth(300);
|
||||
progressBar.setPrefHeight(16);
|
||||
progressBar.setPrefWidth(400);
|
||||
progressBar.setPrefHeight(20);
|
||||
progressBar.setVisible(false);
|
||||
progressLabel = new Label("");
|
||||
progressLabel.setFont(Theme.base(fsBody() - 2));
|
||||
progressLabel.setTextFill(Theme.TEXT_SECONDARY);
|
||||
progressRow.getChildren().addAll(progressBar, progressLabel);
|
||||
|
||||
// === 日志区域 ===
|
||||
Label logTitle = new Label("执行日志");
|
||||
logTitle.setFont(Theme.heading(fsBody()));
|
||||
logTitle.setTextFill(Theme.TEXT_PRIMARY);
|
||||
logArea = new TextArea();
|
||||
logArea.setEditable(false);
|
||||
logArea.setFont(Theme.mono(12));
|
||||
logArea.getStyleClass().add(Theme.CSS_LOG_AREA);
|
||||
logArea.setPrefHeight(150);
|
||||
logArea.setStyle("-fx-background-color: " + Theme.toWeb(Theme.BG_BODY) + ";");
|
||||
VBox.setVgrow(logArea, Priority.NEVER);
|
||||
|
||||
// === 标题 ===
|
||||
Label tableTitle = new Label("导出历史记录");
|
||||
tableTitle.setFont(Theme.heading(fsSection()));
|
||||
@@ -184,7 +211,7 @@ public class MyBatisExportWindow {
|
||||
historyTable.getColumns().addAll(colAction, colIndex, colQuery, colFile, colCount, colTime);
|
||||
|
||||
VBox.setVgrow(historyTable, Priority.ALWAYS);
|
||||
root.getChildren().addAll(filterRow, progressRow, tableTitle, historyTable);
|
||||
root.getChildren().addAll(filterRow, progressRow, logTitle, logArea, tableTitle, historyTable);
|
||||
stage.setScene(new Scene(root));
|
||||
}
|
||||
|
||||
|
||||
+44
-8
@@ -106,18 +106,28 @@ public class MyBatisExportService {
|
||||
}
|
||||
}
|
||||
|
||||
/** 导出进度回调 */
|
||||
public interface ExportCallback {
|
||||
void onProjectStart(int current, int total, String projectName);
|
||||
void onProjectDone(int current, int total, String projectName, int recordCount);
|
||||
/** 是否已请求取消 */
|
||||
boolean isCancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* 按过滤条件导出并返回结果(含文件路径,供窗口展示 + 保存 CSV)
|
||||
*/
|
||||
public ExportResult exportWithResult(String fileNamePrefix, String filterMode, String filterValue) throws Exception {
|
||||
SqlFilter filter = null;
|
||||
if ("table".equals(filterMode) && filterValue != null && !filterValue.isEmpty()) {
|
||||
filter = new TableFilter(filterValue);
|
||||
} else if ("keyword".equals(filterMode) && filterValue != null && !filterValue.isEmpty()) {
|
||||
filter = new KeywordFilter(filterValue);
|
||||
} else if ("tagid".equals(filterMode) && filterValue != null && !filterValue.isEmpty()) {
|
||||
filter = new TagIdFilter(filterValue);
|
||||
}
|
||||
return exportWithCallback(fileNamePrefix, filterMode, filterValue, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 带进度回调的导出(供可视化窗口使用)
|
||||
* @param cb 进度回调,传 null 则降级为无回调模式
|
||||
*/
|
||||
public ExportResult exportWithCallback(String fileNamePrefix, String filterMode, String filterValue,
|
||||
ExportCallback cb) throws Exception {
|
||||
SqlFilter filter = buildFilter(filterMode, filterValue);
|
||||
|
||||
List<String> projectPaths = fileOperationHelper.getProjectPaths();
|
||||
if (projectPaths.isEmpty()) {
|
||||
@@ -125,16 +135,30 @@ public class MyBatisExportService {
|
||||
return new ExportResult(new ArrayList<>(), "");
|
||||
}
|
||||
|
||||
int total = projectPaths.size();
|
||||
List<SqlExportRow> resultList = new ArrayList<>();
|
||||
int current = 0;
|
||||
|
||||
for (String projectPath : projectPaths) {
|
||||
current++;
|
||||
String projectName = fileOperationHelper.extractProjectName(projectPath);
|
||||
if (cb != null) {
|
||||
if (cb.isCancelled()) { break; }
|
||||
cb.onProjectStart(current, total, projectName);
|
||||
}
|
||||
try {
|
||||
List<String[]> projectRecords = processProject(projectPath, filter, null);
|
||||
for (String[] r : projectRecords) {
|
||||
resultList.add(new SqlExportRow(r[0], r[1], r[2], r[3], r[4]));
|
||||
}
|
||||
if (cb != null) {
|
||||
cb.onProjectDone(current, total, projectName, projectRecords.size());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("处理项目时出错: " + projectPath, e);
|
||||
if (cb != null) {
|
||||
cb.onProjectDone(current, total, projectName + " (出错)", 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +174,18 @@ public class MyBatisExportService {
|
||||
return new ExportResult(resultList, fileName);
|
||||
}
|
||||
|
||||
/** 根据过滤模式和值构建过滤器 */
|
||||
private SqlFilter buildFilter(String filterMode, String filterValue) {
|
||||
if ("table".equals(filterMode) && filterValue != null && !filterValue.isEmpty()) {
|
||||
return new TableFilter(filterValue);
|
||||
} else if ("keyword".equals(filterMode) && filterValue != null && !filterValue.isEmpty()) {
|
||||
return new KeywordFilter(filterValue);
|
||||
} else if ("tagid".equals(filterMode) && filterValue != null && !filterValue.isEmpty()) {
|
||||
return new TagIdFilter(filterValue);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void exportWithFilter(String fileNamePrefix, SqlFilter filter,
|
||||
ProcessStrategy processStrategy) throws Exception {
|
||||
List<String> projectPaths = fileOperationHelper.getProjectPaths();
|
||||
|
||||
@@ -231,7 +231,7 @@ public class WorkUtilsProperties {
|
||||
* 文件不存在时自动创建空文件。
|
||||
*/
|
||||
public Path getProjectPathsFilePath() {
|
||||
Path p = Paths.get(projectPathsFile != null ? projectPathsFile : "project_paths.txt");
|
||||
Path p = Paths.get(projectPathsFile != null ? projectPathsFile : "data/project_paths.txt");
|
||||
if (p.isAbsolute()) {
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,6 @@ public class MainWindow {
|
||||
stage.setScene(scene);
|
||||
|
||||
showWelcomePage();
|
||||
if (!navItems.isEmpty()) selectNavItem(navItems.get(0));
|
||||
}
|
||||
|
||||
// ==================== 统一顶部栏 ====================
|
||||
|
||||
Reference in New Issue
Block a user