From d8c814bc031254e8010e78e4c30d2bdb08cfaa0c Mon Sep 17 00:00:00 2001 From: StarInk Date: Sun, 3 Aug 2025 22:05:49 +0800 Subject: [PATCH 01/55] =?UTF-8?q?=F0=9F=92=BE=20Feat:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=B5=81=E8=84=9A=E6=9C=AC=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E5=8F=8A=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Docs/Architecture/Detiled-Plan.md | 372 ++++++++++++++++++ .../Docs/Architecture/Separation-Plan.md | 83 ++++ KitX Dashboard/KitX.Dashboard.csproj | 1 + KitX Dashboard/Models/WorkflowCase.cs | 5 +- .../Services/WorkflowScriptService.cs | 125 ++++++ .../ViewModels/Pages/WorkflowPageViewModel.cs | 13 +- .../WorkflowScriptEditorWindowViewModel.cs | 101 +++++ KitX Dashboard/Views/Pages/WorkflowPage.axaml | 6 +- .../Views/WorkflowScriptEditorWindow.axaml | 54 +++ .../Views/WorkflowScriptEditorWindow.axaml.cs | 162 ++++++++ 10 files changed, 918 insertions(+), 4 deletions(-) create mode 100644 KitX Dashboard/Docs/Architecture/Detiled-Plan.md create mode 100644 KitX Dashboard/Docs/Architecture/Separation-Plan.md create mode 100644 KitX Dashboard/Services/WorkflowScriptService.cs create mode 100644 KitX Dashboard/ViewModels/WorkflowScriptEditorWindowViewModel.cs create mode 100644 KitX Dashboard/Views/WorkflowScriptEditorWindow.axaml create mode 100644 KitX Dashboard/Views/WorkflowScriptEditorWindow.axaml.cs diff --git a/KitX Dashboard/Docs/Architecture/Detiled-Plan.md b/KitX Dashboard/Docs/Architecture/Detiled-Plan.md new file mode 100644 index 0000000..905660e --- /dev/null +++ b/KitX Dashboard/Docs/Architecture/Detiled-Plan.md @@ -0,0 +1,372 @@ +# KitX Dashboard 前后端分离详细重构分析报告 + +## 1. 项目现状总结 + +基于对整个KitX Dashboard项目的深入分析,我发现这是一个典型的单体应用架构,所有业务逻辑、数据管理、网络通信和UI逻辑都耦合在一个项目中。 + +### 1.1 核心架构问题 +- **高度耦合**: UI逻辑与业务逻辑混杂在ViewModels中 +- **直接依赖**: ViewModels直接调用Manager类和静态实例 +- **配置混乱**: 前端UI配置与后端业务配置混合在同一配置文件中 +- **网络通信**: 所有网络服务都运行在前端应用进程中 + +## 2. 需要分离到后端(Core项目)的逻辑 + +### 2.1 管理器层 (`Managers/`) - 完全迁移 + +**核心业务管理器:** +- [`ManagerBase.cs`](KitX Dashboard/Managers/ManagerBase.cs:5) - 需重构为服务基类 +- [`PluginsManager.cs`](KitX Dashboard/Managers/PluginsManager.cs:16) - 插件生命周期管理 + - `ImportPlugin()` 方法 (第20行) - 插件导入逻辑 + - 插件安装和卸载功能 +- [`SecurityManager.cs`](KitX Dashboard/Managers/SecurityManager.cs:15) - 安全管理核心 + - RSA加密解密 (`EncryptString`, `DecryptString`) + - 设备密钥管理 (`AddDeviceKey`, `RemoveDeviceKey`) + - 设备授权验证 (`IsDeviceAuthorized`) +- [`ConfigManager.cs`](KitX Dashboard/Managers/ConfigManager.cs:12) - 配置管理系统 + - 配置文件热重载机制 + - 多配置文件管理 (`LoadConfigFile()`) +- [`ActivityManager.cs`](KitX Dashboard/Managers/ActivityManager.cs:12) - 活动日志管理 + - LiteDB数据库操作 + - 活动记录和查询功能 +- [`StatisticsManager.cs`](KitX Dashboard/Managers/StatisticsManager.cs:13) - 统计数据处理 + - 使用统计数据收集 + - 数据持久化存储 +- [`WebManager.cs`](KitX Dashboard/Managers/WebManager.cs:11) - 网络服务管理 + - 服务器启动/停止控制 + - 网络服务协调 +- [`TasksManager.cs`](KitX Dashboard/Managers/TasksManager.cs:7) - 任务调度 +- [`AnnouncementManager.cs`](KitX Dashboard/Managers/AnnouncementManager.cs:16) - 公告管理 + - HTTP API调用逻辑 (`CheckNewAnnouncements`) + +### 2.2 网络通信层 (`Network/`) - 完全迁移 + +**设备网络通信:** +- [`DevicesServer.cs`](KitX Dashboard/Network/DevicesNetwork/DevicesServer.cs:20) - ASP.NET Core Web API服务器 + - 设备连接管理 + - JWT令牌管理 + - API控制器集成 +- [`DevicesDiscoveryServer.cs`](KitX Dashboard/Network/DevicesNetwork/DevicesDiscoveryServer.cs:20) - UDP广播服务 + - 多播网络发现 (`MultiDevicesBroadCastSend`, `MultiDevicesBroadCastReceive`) + - 网络接口管理 (`FindSupportNetworkInterfaces`) +- [`DevicesOrganizer.cs`](KitX Dashboard/Network/DevicesNetwork/DevicesOrganizer.cs) - 设备组织管理 +- API控制器 (`DevicesServerControllers/V1/`) + +**插件网络通信:** +- [`PluginsServer.cs`](KitX Dashboard/Network/PluginsNetwork/PluginsServer.cs:13) - WebSocket服务器 + - Fleck WebSocket实现 + - 插件连接管理 +- [`PluginConnector.cs`](KitX Dashboard/Network/PluginsNetwork/PluginConnector.cs:16) - 插件连接器 + - 插件注册处理 + - 消息协议处理 + +**网络工具:** +- [`NetworkHelper.cs`](KitX Dashboard/Network/NetworkHelper.cs:17) - 网络工具类 + - IP地址获取 (`GetInterNetworkIPv4`, `GetInterNetworkIPv6`) + - 设备信息构建 (`GetDeviceInfo`) + - MAC地址获取 (`TryGetDeviceMacAddress`) + +### 2.3 数据模型层 (`Models/`) - 部分迁移 + +**业务实体模型:** +- [`PluginInstallation.cs`](KitX Dashboard/Models/PluginInstallation.cs:9) - 插件安装信息 +- [`WorkflowCase.cs`](KitX Dashboard/Models/WorkflowCase.cs:5) - 工作流定义 +- [`Component.cs`](KitX Dashboard/Models/Component.cs:3) - 组件信息 + +**注意**: [`DeviceCase.cs`](KitX Dashboard/Models/DeviceCase.cs:22) 需要重构,其中包含大量UI逻辑和业务逻辑的混合 + +### 2.4 配置管理层 (`Configuration/`) - 部分迁移 + +**核心配置基础设施:** +- [`ConfigBase.cs`](KitX Dashboard/Configuration/ConfigBase.cs:16) - 配置基类和序列化扩展 +- [`ConfigFetcher.cs`](KitX Dashboard/Configuration/ConfigFetcher.cs:5) - 配置获取器基类 + +**业务配置 (需迁移到Core):** +- [`SecurityConfig.cs`](KitX Dashboard/Configuration/SecurityConfig.cs) - 安全配置 +- [`PluginsConfig.cs`](KitX Dashboard/Configuration/PluginsConfig.cs) - 插件配置 +- [`MarketConfig.cs`](KitX Dashboard/Configuration/MarketConfig.cs) - 市场配置 +- [`AnnouncementConfig.cs`](KitX Dashboard/Configuration/AnnouncementConfig.cs) - 公告配置 + +**UI配置 (保留在前端):** +- [`AppConfig.cs`](KitX Dashboard/Configuration/AppConfig.cs:10) 中的UI相关部分: + - `Config_Windows` (第65行) - 窗口配置 + - `Config_Pages` (第106行) - 页面配置 + - 主题和语言设置 + +### 2.5 服务层 (`Services/`) - 部分迁移 + +**后端服务 (迁移到Core):** +- [`DebugService.cs`](KitX Dashboard/Services/DebugService.cs:13) 中的代码执行逻辑 +- [`EventService.cs`](KitX Dashboard/Services/EventService.cs:7) 中的业务事件部分 + +## 3. 保留在前端(Dashboard项目)的逻辑 + +### 3.1 视图层 (`Views/`) - 完全保留 +- 所有AXAML视图文件 +- 视图代码后置文件 +- UI控件和样式 + +### 3.2 视图模型层 (`ViewModels/`) - 重构保留 + +**需要重构的ViewModels:** +- [`ViewModelBase.cs`](KitX Dashboard/ViewModels/ViewModelBase.cs:10) - 移除直接的ConfigManager依赖 (第47行) +- [`AppViewModel.cs`](KitX Dashboard/ViewModels/AppViewModel.cs:13) - 移除对AnnouncementManager的直接调用 (第44行) +- [`MainWindowViewModel.cs`](KitX Dashboard/ViewModels/MainWindowViewModel.cs:8) - 基本结构可保留 +- [`DevicesPageViewModel.cs`](KitX Dashboard/ViewModels/Pages/DevicesPageViewModel.cs:10) - 移除对WebManager的直接依赖 (第23行) +- [`HomePageViewModel.cs`](KitX Dashboard/ViewModels/Pages/HomePageViewModel.cs:9) - 移除对ConfigManager的直接访问 (第38行) + +### 3.3 UI专用组件 +- 转换器 (`Converters/`) +- 样式和主题 (`Styles/`) +- 语言资源 (`Languages/`) +- UI相关的工具类 + +## 4. 详细重构实施计划 + +### 阶段1: Core项目基础架构重构 + +**1.1 项目类型转换** +```xml + + + + net8.0 + Library + + +``` + +**1.2 创建服务接口层** +``` +KitX Dashboard Core/ +├── Interfaces/ +│ ├── IPluginService.cs // 插件管理服务接口 +│ ├── ISecurityService.cs // 安全管理服务接口 +│ ├── IConfigurationService.cs // 配置管理服务接口 +│ ├── IActivityService.cs // 活动日志服务接口 +│ ├── IStatisticsService.cs // 统计服务接口 +│ ├── INetworkService.cs // 网络服务接口 +│ ├── IDeviceService.cs // 设备管理服务接口 +│ └── IAnnouncementService.cs // 公告服务接口 +``` + +**1.3 依赖注入容器配置** +```csharp +// ServiceCollectionExtensions.cs +public static class ServiceCollectionExtensions +{ + public static IServiceCollection AddKitXCore(this IServiceCollection services) + { + // 注册核心服务 + services.AddSingleton(); + services.AddSingleton(); + // ... 其他服务注册 + return services; + } +} +``` + +### 阶段2: 业务逻辑迁移重构 + +**2.1 Manager to Service 重构模式** + +以PluginsManager为例: +```csharp +// 原 PluginsManager.cs (第16行) +internal class PluginsManager +{ + internal static void ImportPlugin(string[] kxpfiles, bool inGraphic = false) + { + // 业务逻辑... + } +} + +// 重构后的 IPluginService.cs +public interface IPluginService +{ + Task ImportPluginAsync(string[] kxpFiles, bool inGraphic = false); + Task> GetInstalledPluginsAsync(); + Task UninstallPluginAsync(string pluginId); +} + +// 重构后的 PluginService.cs +public class PluginService : IPluginService +{ + private readonly IConfigurationService _configService; + private readonly ILogger _logger; + + public async Task ImportPluginAsync(string[] kxpFiles, bool inGraphic = false) + { + // 从原PluginsManager.ImportPlugin迁移的逻辑 + } +} +``` + +**2.2 配置管理重构** + +分离业务配置和UI配置: +```csharp +// Core项目中的业务配置 +public class CoreAppConfig +{ + public PluginConfig Plugins { get; set; } + public SecurityConfig Security { get; set; } + public NetworkConfig Network { get; set; } + public LoggingConfig Logging { get; set; } +} + +// Dashboard项目中的UI配置 +public class UIConfig +{ + public WindowConfig Windows { get; set; } + public ThemeConfig Theme { get; set; } + public LanguageConfig Language { get; set; } +} +``` + +**2.3 网络服务重构** + +```csharp +// INetworkService.cs +public interface INetworkService +{ + Task StartDevicesServerAsync(); + Task StopDevicesServerAsync(); + Task StartPluginsServerAsync(); + Task StopPluginsServerAsync(); + Task GetLocalDeviceInfoAsync(); +} +``` + +### 阶段3: 前端架构重构 + +**3.1 Service Proxy层创建** +``` +KitX Dashboard/ +├── ServiceProxies/ +│ ├── IServiceProxy.cs // 服务代理基接口 +│ ├── PluginServiceProxy.cs // 插件服务代理 +│ ├── SecurityServiceProxy.cs // 安全服务代理 +│ ├── DeviceServiceProxy.cs // 设备服务代理 +│ └── ConfigServiceProxy.cs // 配置服务代理 +``` + +**3.2 ViewModels重构模式** + +以DevicesPageViewModel为例: +```csharp +// 重构前 (第23行直接依赖WebManager) +if (Instances.WebManager is null) return; +await Instances.WebManager.RestartAsync(...) + +// 重构后 (通过服务代理) +public class DevicesPageViewModel : ViewModelBase +{ + private readonly IDeviceServiceProxy _deviceService; + + public DevicesPageViewModel(IDeviceServiceProxy deviceService) + { + _deviceService = deviceService; + } + + private async Task RestartDevicesServerAsync() + { + await _deviceService.RestartDevicesServerAsync(); + } +} +``` + +### 阶段4: 通信层设计 + +**4.1 API接口设计** +```csharp +// REST API 设计 +[ApiController] +[Route("api/v1/[controller]")] +public class PluginsController : ControllerBase +{ + [HttpGet] + public async Task GetInstalledPlugins() + + [HttpPost("import")] + public async Task ImportPlugin([FromBody] ImportPluginRequest request) + + [HttpDelete("{id}")] + public async Task UninstallPlugin(string id) +} +``` + +**4.2 实时通信 (SignalR)** +```csharp +// 用于实时状态更新 +public class DashboardHub : Hub +{ + public async Task JoinGroup(string groupName) + public async Task LeaveGroup(string groupName) +} + +// 事件推送 +public interface IDashboardEventNotifier +{ + Task NotifyPluginInstalled(PluginInfo plugin); + Task NotifyDeviceConnected(DeviceInfo device); + Task NotifyConfigurationChanged(string configType); +} +``` + +## 5. 关键重构要点 + +### 5.1 配置管理分离策略 +- **业务配置** → Core项目 (插件、安全、网络配置) +- **UI配置** → Dashboard项目 (窗口、主题、语言配置) +- **共享配置** → 通过API同步 + +### 5.2 事件系统重构 +- 将[`EventService.cs`](KitX Dashboard/Services/EventService.cs:7)分离为: + - **Core事件**: 业务逻辑事件 (插件安装、设备连接等) + - **UI事件**: 界面交互事件 (主题变更、语言切换等) + +### 5.3 数据持久化分离 +- **LiteDB数据库** → Core项目管理 +- **UI状态缓存** → Dashboard项目管理 + +### 5.4 安全架构重构 +- [`SecurityManager.cs`](KitX Dashboard/Managers/SecurityManager.cs:15) → Core项目 +- 设备密钥管理完全在后端处理 +- 前端只处理UI层的身份验证 + +## 6. 实施建议 + +### 6.1 分阶段实施 +1. **第一阶段**: 完成Core项目基础架构搭建 +2. **第二阶段**: 迁移核心业务逻辑 (插件管理、安全管理) +3. **第三阶段**: 迁移网络通信层 +4. **第四阶段**: 重构前端ViewModels +5. **第五阶段**: 完善API接口和测试 + +### 6.2 向下兼容策略 +- 保持现有配置文件格式兼容 +- 逐步迁移现有数据 +- 提供配置迁移工具 + +### 6.3 测试策略 +- **单元测试**: Core项目的业务逻辑 +- **集成测试**: API接口测试 +- **UI测试**: 前端功能测试 +- **端到端测试**: 完整流程测试 + +## 7. 预期收益 + +### 7.1 架构优势 +- **职责分离**: 前后端各司其职 +- **可扩展性**: 支持多种前端实现 +- **可维护性**: 业务逻辑集中管理 +- **可测试性**: 独立的业务逻辑测试 + +### 7.2 技术优势 +- **性能优化**: 后端可独立优化 +- **并发处理**: 更好的并发控制 +- **资源管理**: 独立的资源管理 +- **部署灵活**: 前后端独立部署 + +这个详细的重构分析为KitX Dashboard的前后端分离提供了清晰的路线图,确保重构过程的系统性和可执行性。建议按照分阶段实施的策略,逐步完成整个重构过程,以降低风险并保证系统的稳定性。 diff --git a/KitX Dashboard/Docs/Architecture/Separation-Plan.md b/KitX Dashboard/Docs/Architecture/Separation-Plan.md new file mode 100644 index 0000000..fca74f9 --- /dev/null +++ b/KitX Dashboard/Docs/Architecture/Separation-Plan.md @@ -0,0 +1,83 @@ +# KitX Dashboard 前后端分离架构设计文档 + +## 1. 概述 + +本方案将KitX Dashboard拆分为: +- **前端**:KitX Dashboard (UI层) +- **后端**:KitX Dashboard Core (业务逻辑层) + +## 2. 架构设计 + +```mermaid +graph TD + subgraph "KitX Dashboard (前端)" + A[Views] --> B[ViewModels] + B --> C[Service Interfaces] + C --> D[Core API] + end + + subgraph "KitX Dashboard Core (后端)" + D --> E[Business Services] + E --> F[Managers] + F --> G[Data Models] + end +``` + +## 3. 职责划分 + +### 后端(Core项目) +- 所有业务逻辑处理 +- 数据管理和持久化 +- 网络通信 +- 插件管理 +- 安全配置 +- 统计和日志 + +### 前端(Dashboard项目) +- 用户界面展示 +- 用户交互处理 +- 视图状态管理 +- 通过接口调用后端服务 + +## 4. 实施步骤 + +1. **重构Core项目** + - 改为类库项目 + - 设计服务接口层 + - 建立DI容器 + +2. **代码迁移** + - 迁移Models、Managers、Services等 + +3. **接口设计** + - 定义服务接口 + - 实现服务类 + - 创建服务工厂 + +4. **前端适配** + - 重构ViewModels + - 实现服务代理 + - 更新DI配置 + +## 5. 目录结构 + +``` +KitX Dashboard Core/ +├── Interfaces/ +├── Services/ +├── Models/ +├── Managers/ +└── Extensions/ + +KitX Dashboard/ +├── Views/ +├── ViewModels/ +├── ServiceProxies/ +└── Locators/ +``` + +## 6. 后续计划 + +- 按阶段实施迁移 +- 逐步测试验证 +- 完善文档 diff --git a/KitX Dashboard/KitX.Dashboard.csproj b/KitX Dashboard/KitX.Dashboard.csproj index 513fbd8..594b679 100644 --- a/KitX Dashboard/KitX.Dashboard.csproj +++ b/KitX Dashboard/KitX.Dashboard.csproj @@ -113,6 +113,7 @@ + diff --git a/KitX Dashboard/Models/WorkflowCase.cs b/KitX Dashboard/Models/WorkflowCase.cs index 6296f96..19c77a8 100644 --- a/KitX Dashboard/Models/WorkflowCase.cs +++ b/KitX Dashboard/Models/WorkflowCase.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace KitX.Dashboard.Models { @@ -8,5 +8,6 @@ public class WorkflowCase public required string Description { get; set; } // 简介信息 public required string IconPath { get; set; } // 图标路径 public bool IsRunning { get; set; } // 运行状态 + public string ScriptPath { get; set; } = string.Empty; // 脚本文件路径 } -} +} \ No newline at end of file diff --git a/KitX Dashboard/Services/WorkflowScriptService.cs b/KitX Dashboard/Services/WorkflowScriptService.cs new file mode 100644 index 0000000..c0edb6f --- /dev/null +++ b/KitX Dashboard/Services/WorkflowScriptService.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Linq; +using Csharpell.Core; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Scripting; +using Kscript.CSharp.Parser; +using KitX.Shared.CSharp.Plugin; + +namespace KitX.Dashboard.Services; + +public static class WorkflowScriptService +{ + private static CSharpScriptEngine Engine => new(); + + // 存储当前可用的插件列表,用于生成API + private static List AvailablePlugins { get; set; } = new(); + + /// + /// 更新可用插件列表 + /// + /// 插件列表 + public static void UpdateAvailablePlugins(List plugins) + { + AvailablePlugins = plugins ?? new List(); + } + + /// + /// 执行工作流脚本代码 + /// + /// 要执行的代码 + /// 是否包含时间戳 + /// 取消令牌 + /// 执行结果 + public static async Task ExecuteCodesAsync( + string code, + bool includeTimestamp = true, + CancellationToken cancellationToken = default + ) + { + var sw = new Stopwatch(); + var begin = DateTime.Now; + sw.Start(); + + try + { + // 生成包含插件API的程序集 + Assembly? pluginApiAssembly = null; + if (AvailablePlugins.Any()) + { + try + { + pluginApiAssembly = Parser.Generate(AvailablePlugins, "KitXWorkflowPlugins"); + } + catch (Exception ex) + { + // 如果插件API生成失败,记录错误但继续执行脚本 + var error = $"Failed to generate plugin API: {ex.Message}"; + Console.WriteLine(error); + } + } + + // 执行脚本 + var result = ( + await Engine.ExecuteAsync( + code, + options => + { + options = options + .WithReferences(Assembly.GetExecutingAssembly()) + .WithImports( + "KitX", + "KitX.Dashboard", + "KitX.Shared.CSharp.Plugin", + "System", + "System.Collections.Generic", + "System.Threading.Tasks" + ) + .WithLanguageVersion(LanguageVersion.Preview); + + // 如果有插件API程序集,添加为引用 + if (pluginApiAssembly != null) + { + options = options.WithReferences(pluginApiAssembly); + } + + return options; + }, + addDefaultImports: true, + runInReplMode: false, + cancellationToken: cancellationToken + ) + )?.ToString(); + + sw.Stop(); + + return includeTimestamp + ? new StringBuilder() + .AppendLine($"[{begin:yyyy-MM-dd HH:mm:ss}] [I] Workflow script posted.") + .AppendLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [I] Script ended, took {sw.ElapsedMilliseconds} ms.") + .AppendLine(result) + .ToString() + : result; + } + catch (Exception e) + { + sw.Stop(); + + return includeTimestamp + ? new StringBuilder() + .AppendLine($"[{begin:yyyy-MM-dd HH:mm:ss}] [I] Workflow script posted.") + .AppendLine( + $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] [E] Exception caught after {sw.ElapsedMilliseconds} ms, Message: {e.Message}" + ) + .AppendLine(e.StackTrace) + .ToString() + : e.StackTrace; + } + } +} diff --git a/KitX Dashboard/ViewModels/Pages/WorkflowPageViewModel.cs b/KitX Dashboard/ViewModels/Pages/WorkflowPageViewModel.cs index 78b682f..6cf226f 100644 --- a/KitX Dashboard/ViewModels/Pages/WorkflowPageViewModel.cs +++ b/KitX Dashboard/ViewModels/Pages/WorkflowPageViewModel.cs @@ -1,4 +1,4 @@ -using System.Collections.ObjectModel; +using System.Collections.ObjectModel; using System.Reactive; using System.Threading.Tasks; using Avalonia.Metadata; @@ -61,6 +61,14 @@ public sealed override void InitCommands() var messageBoxStandardWindow = MessageBoxManager.GetMessageBoxStandard("C", "XK", icon: Icon.Error).ShowWindowAsync(); return Task.CompletedTask; }); + + // 添加打开工作流脚本编辑器的命令 + OpenWorkflowEditorCommand = ReactiveCommand.Create(() => + { + var editorWindow = new WorkflowScriptEditorWindow(); + editorWindow.Show(); + return Task.CompletedTask; + }); } public sealed override void InitEvents() @@ -104,5 +112,8 @@ internal double NoWorkflow_TipHeight internal ReactiveCommand? RunWorkflowCommand { get; set; } internal ReactiveCommand? StopWorkflowCommand { get; set; } + + // 新增命令:打开工作流脚本编辑器 + internal ReactiveCommand? OpenWorkflowEditorCommand { get; set; } } } diff --git a/KitX Dashboard/ViewModels/WorkflowScriptEditorWindowViewModel.cs b/KitX Dashboard/ViewModels/WorkflowScriptEditorWindowViewModel.cs new file mode 100644 index 0000000..2a423ef --- /dev/null +++ b/KitX Dashboard/ViewModels/WorkflowScriptEditorWindowViewModel.cs @@ -0,0 +1,101 @@ +using System; +using System.Reactive; +using System.Threading; +using System.Threading.Tasks; +using Avalonia.Threading; +using AvaloniaEdit.Document; +using KitX.Dashboard.Services; +using ReactiveUI; +using System.Reflection; +using System.Collections.Generic; +using Kscript.CSharp.Parser; +using KitX.Shared.CSharp.Plugin; + +namespace KitX.Dashboard.ViewModels; + +internal class WorkflowScriptEditorWindowViewModel : ViewModelBase +{ + private CancellationTokenSource? _cancellationTokenSource; + + private readonly IDisposable _codeDocumentSubscription; + + public WorkflowScriptEditorWindowViewModel() + { + InitCommands(); + InitEvents(); + + // 订阅CodeDocument属性变化 + _codeDocumentSubscription = this.WhenAnyValue(x => x.CodeDocument) + .Subscribe(document => + { + // 在这里处理CodeDocument变化的逻辑 + if (document != null) + { + // 例如:可以在这里触发代码分析或保存操作 + // SubmitCodes(document); + } + }); + } + + public sealed override void InitCommands() + { + CancelExecutionCommand = ReactiveCommand.Create(() => _cancellationTokenSource?.Cancel()); + } + + public sealed override void InitEvents() { } + + internal void SubmitCodes(IDocument doc) + { + IsExecuting = true; + + var code = doc.Text; + + var tokenSource = new CancellationTokenSource(); + + _cancellationTokenSource = tokenSource; + + Task.Run( + async () => + { + var result = await WorkflowScriptService.ExecuteCodesAsync(code, cancellationToken: tokenSource.Token); + + tokenSource.Dispose(); + + _cancellationTokenSource = null; + + Dispatcher.UIThread.Invoke(() => + { + ExecutionResult = result ?? string.Empty; + + IsExecuting = false; + }); + }, + tokenSource.Token + ); + } + + internal void CancelExecution() + { + _cancellationTokenSource?.Cancel(); + } + + private string _executionResult = string.Empty; + + public string ExecutionResult + { + get => _executionResult; + set => this.RaiseAndSetIfChanged(ref _executionResult, value); + } + + private bool _isExecuting; + + public bool IsExecuting + { + get => _isExecuting; + set => this.RaiseAndSetIfChanged(ref _isExecuting, value); + } + + internal IDocument? CodeDocument { get; set; } + + internal ReactiveCommand? CancelExecutionCommand { get; set; } +} \ No newline at end of file diff --git a/KitX Dashboard/Views/Pages/WorkflowPage.axaml b/KitX Dashboard/Views/Pages/WorkflowPage.axaml index 58bda2f..70b101f 100644 --- a/KitX Dashboard/Views/Pages/WorkflowPage.axaml +++ b/KitX Dashboard/Views/Pages/WorkflowPage.axaml @@ -1,4 +1,4 @@ - + + +