稳定可用版本
This commit is contained in:
@@ -1,26 +1,43 @@
|
||||
package com.example.workutils;
|
||||
|
||||
import com.example.workutils.system.config.*;
|
||||
import com.example.workutils.system.plugin.Plugin;
|
||||
import com.example.workutils.system.plugin.PluginDescriptor;
|
||||
import com.example.workutils.system.plugin.PluginManager;
|
||||
import com.example.workutils.system.plugin.VisualPluginFactory;
|
||||
import com.example.workutils.system.support.JfxBootstrap;
|
||||
import com.example.workutils.system.support.WinConsole;
|
||||
import com.example.workutils.system.ui.MainWindow;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.Parent;
|
||||
import javafx.scene.control.Alert;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.Scanner;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
|
||||
@Slf4j
|
||||
public class WorkUtilsApplication implements CommandLineRunner {
|
||||
|
||||
private final PluginManager pluginManager;
|
||||
private final WorkUtilsProperties properties;
|
||||
private final SettingsService settingsService;
|
||||
|
||||
public WorkUtilsApplication(PluginManager pluginManager) {
|
||||
/** 主窗口引用,供内嵌插件面板使用 */
|
||||
private MainWindow mainWindow;
|
||||
/** 系统设置窗口缓存(内嵌模式复用) */
|
||||
private SettingsWindow settingsWindow;
|
||||
|
||||
public WorkUtilsApplication(PluginManager pluginManager, WorkUtilsProperties properties,
|
||||
SettingsService settingsService) {
|
||||
this.pluginManager = pluginManager;
|
||||
this.properties = properties;
|
||||
this.settingsService = settingsService;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -31,29 +48,188 @@ public class WorkUtilsApplication implements CommandLineRunner {
|
||||
@Override
|
||||
public void run(String... args) throws Exception {
|
||||
if (args.length == 0) {
|
||||
showMainWindow();
|
||||
} else if ("--console".equals(args[0])) {
|
||||
showInteractiveMenu();
|
||||
} else {
|
||||
processCommand(args);
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 主窗口入口 ====================
|
||||
|
||||
private void showMainWindow() throws InterruptedException {
|
||||
JfxBootstrap.await();
|
||||
if (JfxBootstrap.isFailed()) {
|
||||
System.err.println("JavaFX 初始化失败,回退到控制台模式");
|
||||
showInteractiveMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
List<MainWindow.NavItem> navItems = buildNavItems();
|
||||
|
||||
CountDownLatch windowClosed = new CountDownLatch(1);
|
||||
Platform.runLater(() -> {
|
||||
try {
|
||||
mainWindow = new MainWindow(navItems, properties);
|
||||
mainWindow.showAndWait();
|
||||
} catch (Exception e) {
|
||||
log.error("主窗口创建失败", e);
|
||||
System.err.println("主窗口创建失败: " + e.getMessage());
|
||||
} finally {
|
||||
windowClosed.countDown();
|
||||
}
|
||||
});
|
||||
|
||||
windowClosed.await();
|
||||
log.info("主窗口已关闭");
|
||||
}
|
||||
|
||||
// ==================== 导航项构建 ====================
|
||||
|
||||
private List<MainWindow.NavItem> buildNavItems() {
|
||||
List<MainWindow.NavItem> items = new ArrayList<>();
|
||||
|
||||
for (Plugin plugin : pluginManager.getEnabledPlugins()) {
|
||||
PluginDescriptor desc = plugin.getDescriptor();
|
||||
VisualPluginFactory factory = plugin.getVisualFactory();
|
||||
String pluginId = desc.getId();
|
||||
|
||||
items.add(new MainWindow.NavItem(
|
||||
desc.getIcon(),
|
||||
desc.getName(),
|
||||
desc.getDescription(),
|
||||
factory != null ? () -> openPluginEmbedded(pluginId, plugin, factory) : null,
|
||||
pluginId
|
||||
));
|
||||
}
|
||||
|
||||
// 系统设置 — 内嵌为 Tab
|
||||
items.add(new MainWindow.NavItem(
|
||||
"⚙️", "系统设置",
|
||||
"配置系统路径、数据库连接、项目路径、多数据源、字体大小等",
|
||||
this::openSettingsEmbedded,
|
||||
"__settings__"
|
||||
));
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
// ==================== 内嵌优先打开 ====================
|
||||
|
||||
/**
|
||||
* 优先尝试内嵌模式;若插件不支持嵌入,则退回到独立窗口。
|
||||
* <p>
|
||||
* 在 JFX 线程上调用(来自导航按钮事件)。
|
||||
*/
|
||||
private void openPluginEmbedded(String pluginId, Plugin plugin, VisualPluginFactory factory) {
|
||||
// 配置检查
|
||||
String configError = plugin.checkConfig();
|
||||
if (configError != null) {
|
||||
showConfigAlert(plugin.getName(), configError);
|
||||
return;
|
||||
}
|
||||
|
||||
// 尝试获取内嵌面板
|
||||
Parent embeddedPane = factory.getEmbeddedPane();
|
||||
if (embeddedPane != null && mainWindow != null) {
|
||||
PluginDescriptor desc = plugin.getDescriptor();
|
||||
mainWindow.embedPlugin(pluginId, desc.getIcon(), desc.getName(), embeddedPane);
|
||||
return;
|
||||
}
|
||||
|
||||
// 回退:独立窗口模式
|
||||
openPluginStandalone(plugin, factory);
|
||||
}
|
||||
|
||||
// ==================== 独立窗口模式(弹出或回退) ====================
|
||||
|
||||
/**
|
||||
* 以独立窗口形式打开插件。用于:
|
||||
* <ul>
|
||||
* <li>插件不支持内嵌时的回退</li>
|
||||
* <li>用户点击「弹出窗口」按钮</li>
|
||||
* </ul>
|
||||
*/
|
||||
private void openPluginStandalone(Plugin plugin, VisualPluginFactory factory) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
JfxBootstrap.await();
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
return;
|
||||
}
|
||||
|
||||
CountDownLatch windowClosed = new CountDownLatch(1);
|
||||
Platform.runLater(() -> {
|
||||
try {
|
||||
factory.open(windowClosed::countDown);
|
||||
} catch (Exception e) {
|
||||
log.error("独立窗口创建失败: {}", plugin.getName(), e);
|
||||
windowClosed.countDown();
|
||||
}
|
||||
});
|
||||
try {
|
||||
windowClosed.await();
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}, plugin.getId() + "-Window").start();
|
||||
}
|
||||
|
||||
// ==================== 配置提示 ====================
|
||||
|
||||
private void showConfigAlert(String pluginName, String message) {
|
||||
Alert alert = new Alert(Alert.AlertType.WARNING);
|
||||
alert.setTitle("配置检查");
|
||||
alert.setHeaderText(pluginName + " 配置不完整");
|
||||
alert.setContentText(message);
|
||||
alert.showAndWait();
|
||||
}
|
||||
|
||||
// ==================== 系统设置 ====================
|
||||
|
||||
private void openSettingsEmbedded() {
|
||||
if (settingsWindow == null) {
|
||||
settingsWindow = settingsService.createSettingsWindow(null);
|
||||
}
|
||||
if (mainWindow != null) {
|
||||
Parent pane = settingsWindow.getContentPane();
|
||||
mainWindow.embedPlugin("__settings__", "⚙️", "系统设置", pane);
|
||||
}
|
||||
}
|
||||
|
||||
private void openSettingsStandalone() {
|
||||
if (settingsWindow == null) {
|
||||
settingsWindow = settingsService.createSettingsWindow(null);
|
||||
}
|
||||
javafx.stage.Stage s = settingsWindow.getStage();
|
||||
if (s != null) {
|
||||
s.show();
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated 保留兼容旧路径 */
|
||||
private void openSettingsWindow() {
|
||||
new Thread(() -> settingsService.showSettings(null, null),
|
||||
"SettingsWindow-Thread").start();
|
||||
}
|
||||
|
||||
// ==================== 控制台模式(降级) ====================
|
||||
|
||||
private void showInteractiveMenu() {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
pluginManager.runMainMenu(scanner);
|
||||
}
|
||||
|
||||
/**
|
||||
* 命令行模式:通过 PluginManager 按命令名分发到对应 Tool
|
||||
* 启动类不依赖任何具体业务 Service
|
||||
*/
|
||||
private void processCommand(String... args) throws Exception {
|
||||
String command = args[0].toLowerCase();
|
||||
|
||||
Optional<Plugin> toolOpt = pluginManager.getPluginByCommand(command);
|
||||
if (toolOpt.isPresent()) {
|
||||
Plugin plugin = toolOpt.get();
|
||||
try {
|
||||
String[] toolArgs = args.length > 1 ? Arrays.copyOfRange(args, 1, args.length) : new String[0];
|
||||
String[] toolArgs = args.length > 1
|
||||
? Arrays.copyOfRange(args, 1, args.length) : new String[0];
|
||||
plugin.executeCommand(toolArgs);
|
||||
} catch (Exception e) {
|
||||
log.error("命令执行失败: {} [{}]", plugin.getName(), plugin.getId(), e);
|
||||
|
||||
Reference in New Issue
Block a user