From ea58e0335ece9195c1162a2472613f803829868b Mon Sep 17 00:00:00 2001 From: Tyrone CT Date: Mon, 30 Mar 2026 14:33:10 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=A1=AE=E8=AE=A4=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E5=AF=BC=E5=87=BA=E7=AD=96=E7=95=A5=EF=BC=9A1)=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=86=B2=E7=AA=81=E6=8C=89=20ConfigName=20+?= =?UTF-8?q?=20CANLINInfo=20=E5=88=A4=E9=87=8D=EF=BC=8CCAN/LIN/CANFD=20?= =?UTF-8?q?=E5=8F=AF=E5=90=8C=E5=90=8D=EF=BC=9B2)=20=E5=A2=9E=E9=87=8F?= =?UTF-8?q?=E5=AF=BC=E5=85=A5=E5=AF=B9=E5=90=8C=E5=90=8D=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E9=87=8D=E5=91=BD=E5=90=8D=EF=BC=88=5Fimport?= =?UTF-8?q?=5F=E6=97=B6=E9=97=B4=E6=88=B3=EF=BC=89=EF=BC=9B3)=20JSON=20?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E5=B0=BD=E9=87=8F=E4=B8=8E=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E5=BA=93=E6=A8=A1=E5=9E=8B=E4=B8=80=E8=87=B4=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E4=B8=8D=E5=8A=A0=E6=B3=A8=E9=87=8A=EF=BC=9B4)=20LogicRule=20?= =?UTF-8?q?=E4=B9=9F=E9=9C=80=E9=9A=8F=E9=85=8D=E7=BD=AE=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=EF=BC=8C=E8=A7=84=E5=88=99=E5=90=8C=E5=90=8D?= =?UTF-8?q?=E5=86=B2=E7=AA=81=E9=87=87=E7=94=A8=E8=A6=86=E7=9B=96=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=EF=BC=9B5)=20=E5=AF=BC=E5=85=A5=E5=90=8E=E9=9C=80?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E5=88=B7=E6=96=B0=20CAN/CANFD/LIN=20?= =?UTF-8?q?=E4=BB=A5=E5=8F=8A=20ZLG=20=E5=AF=B9=E5=BA=94=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=EF=BC=9B6)=20=E5=85=A5=E5=8F=A3=E6=8C=89=E7=8E=B0=E6=9C=89?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E8=8F=9C=E5=8D=95=E5=BC=B9=E7=AA=97=EF=BC=88?= =?UTF-8?q?ComDialogEvent=20+=20DialogService=EF=BC=89=E6=8E=A5=E5=85=A5?= =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CapMachine.Wpf/App.config | 1 + CapMachine.Wpf/App.xaml.cs | 2 + .../PrismEvent/CanLinConfigChangedEvent.cs | 11 + .../Services/CanLinConfigImExportService.cs | 1088 +++++++++++++++++ CapMachine.Wpf/Services/ComActionService.cs | 17 + .../Services/NavigationMenuService.cs | 8 +- .../ViewModels/CANConfigViewModel.cs | 11 + .../ViewModels/CANFDConfigViewModel.cs | 11 + .../DialogCanLinConfigImExportViewModel.cs | 319 +++++ .../ViewModels/LinConfigViewModel.cs | 12 + .../ViewModels/ZlgCanDriveConfigViewModel.cs | 12 + .../ViewModels/ZlgLinDriveConfigViewModel.cs | 11 + .../Views/DialogCanLinConfigImExportView.xaml | 83 ++ .../DialogCanLinConfigImExportView.xaml.cs | 28 + 14 files changed, 1610 insertions(+), 4 deletions(-) create mode 100644 CapMachine.Wpf/PrismEvent/CanLinConfigChangedEvent.cs create mode 100644 CapMachine.Wpf/Services/CanLinConfigImExportService.cs create mode 100644 CapMachine.Wpf/ViewModels/DialogCanLinConfigImExportViewModel.cs create mode 100644 CapMachine.Wpf/Views/DialogCanLinConfigImExportView.xaml create mode 100644 CapMachine.Wpf/Views/DialogCanLinConfigImExportView.xaml.cs diff --git a/CapMachine.Wpf/App.config b/CapMachine.Wpf/App.config index f00b9b7..9a5c2da 100644 --- a/CapMachine.Wpf/App.config +++ b/CapMachine.Wpf/App.config @@ -7,6 +7,7 @@ + diff --git a/CapMachine.Wpf/App.xaml.cs b/CapMachine.Wpf/App.xaml.cs index 8584f2f..77f3a48 100644 --- a/CapMachine.Wpf/App.xaml.cs +++ b/CapMachine.Wpf/App.xaml.cs @@ -140,6 +140,7 @@ namespace CapMachine.Wpf containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); + containerRegistry.RegisterSingleton(); containerRegistry.RegisterSingleton(); @@ -204,6 +205,7 @@ namespace CapMachine.Wpf containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); + containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); containerRegistry.RegisterDialog(); diff --git a/CapMachine.Wpf/PrismEvent/CanLinConfigChangedEvent.cs b/CapMachine.Wpf/PrismEvent/CanLinConfigChangedEvent.cs new file mode 100644 index 0000000..e5da74d --- /dev/null +++ b/CapMachine.Wpf/PrismEvent/CanLinConfigChangedEvent.cs @@ -0,0 +1,11 @@ +using Prism.Events; + +namespace CapMachine.Wpf.PrismEvent +{ + /// + /// CAN/CANFD/LIN 配置变更事件。 + /// + public class CanLinConfigChangedEvent : PubSubEvent + { + } +} diff --git a/CapMachine.Wpf/Services/CanLinConfigImExportService.cs b/CapMachine.Wpf/Services/CanLinConfigImExportService.cs new file mode 100644 index 0000000..ce8affc --- /dev/null +++ b/CapMachine.Wpf/Services/CanLinConfigImExportService.cs @@ -0,0 +1,1088 @@ +using CapMachine.Model; +using CapMachine.Model.CANLIN; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace CapMachine.Wpf.Services +{ + /// + /// CAN/LIN 配置导入模式。 + /// + public enum CanLinImportMode + { + /// + /// 覆盖导入:同名同类型配置先删除后导入。 + /// + Overwrite = 1, + + /// + /// 增量导入:同名同类型配置自动重命名后导入。 + /// + IncrementalRename = 2, + } + + /// + /// 导入导出执行结果。 + /// + public class CanLinConfigImExportResult + { + /// + /// 执行是否成功。 + /// + public bool IsSuccess { get; set; } + + /// + /// 结果消息。 + /// + public string Message { get; set; } = string.Empty; + + /// + /// 导出配置数量。 + /// + public int ExportedConfigCount { get; set; } + + /// + /// 导入配置数量。 + /// + public int ImportedConfigCount { get; set; } + + /// + /// 覆盖配置数量。 + /// + public int OverwrittenConfigCount { get; set; } + + /// + /// 重命名配置数量。 + /// + public int RenamedConfigCount { get; set; } + + /// + /// 新增规则数量。 + /// + public int InsertedRuleCount { get; set; } + + /// + /// 覆盖规则数量。 + /// + public int UpdatedRuleCount { get; set; } + + /// + /// 重命名后的配置明细。 + /// + public List RenamedConfigs { get; set; } = new List(); + } + + /// + /// CAN/CANFD/LIN 配置导入导出服务。 + /// + public class CanLinConfigImExportService + { + /// + /// 文件结构版本。 + /// + private const string SchemaVersion = "1.0"; + + /// + /// 初始化导入导出服务。 + /// + /// 数据库实例。 + /// 日志服务。 + public CanLinConfigImExportService(IFreeSql freeSql, ILogService logService) + { + FreeSql = freeSql; + LogService = logService; + } + + /// + /// 数据库访问对象。 + /// + public IFreeSql FreeSql { get; } + + /// + /// 日志服务。 + /// + public ILogService LogService { get; } + + /// + /// 导出当前 CAN/CANFD/LIN 配置到 JSON 文件。 + /// + /// 目标文件路径。 + /// 执行结果。 + public CanLinConfigImExportResult ExportToFile(string filePath) + { + var result = new CanLinConfigImExportResult(); + try + { + if (string.IsNullOrWhiteSpace(filePath)) + { + result.Message = "导出路径不能为空"; + return result; + } + + var package = BuildExportPackage(); + var json = JsonConvert.SerializeObject(package, Formatting.Indented); + + var dir = Path.GetDirectoryName(filePath); + if (!string.IsNullOrWhiteSpace(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + + File.WriteAllText(filePath, json, Encoding.UTF8); + + result.IsSuccess = true; + result.ExportedConfigCount = package.CanLinConfigPros.Count; + result.Message = $"导出成功,配置数量:{result.ExportedConfigCount}"; + return result; + } + catch (Exception ex) + { + LogService.Error($"导出 CAN/LIN 配置失败:{ex}"); + result.Message = $"导出失败:{ex.Message}"; + return result; + } + } + + /// + /// 从 JSON 文件导入 CAN/CANFD/LIN 配置到数据库。 + /// + /// 源文件路径。 + /// 导入模式。 + /// 执行结果。 + public CanLinConfigImExportResult ImportFromFile(string filePath, CanLinImportMode importMode) + { + var result = new CanLinConfigImExportResult(); + try + { + if (string.IsNullOrWhiteSpace(filePath)) + { + result.Message = "导入文件路径不能为空"; + return result; + } + + if (!File.Exists(filePath)) + { + result.Message = "导入文件不存在"; + return result; + } + + var json = File.ReadAllText(filePath, Encoding.UTF8); + var package = JsonConvert.DeserializeObject(json); + if (package == null) + { + result.Message = "导入文件解析失败"; + return result; + } + + if (package.CanLinConfigPros == null || package.CanLinConfigPros.Count == 0) + { + result.Message = "导入文件中没有 CAN/CANFD/LIN 配置数据"; + return result; + } + + FreeSql.Transaction(() => + { + var ruleMaps = UpsertLogicRules(package.LogicRules ?? new List(), result); + foreach (var configSnapshot in package.CanLinConfigPros) + { + ImportSingleConfig(configSnapshot, importMode, ruleMaps, result); + } + }); + + result.IsSuccess = true; + result.Message = + $"导入成功:新增配置 {result.ImportedConfigCount},覆盖配置 {result.OverwrittenConfigCount},重命名配置 {result.RenamedConfigCount},新增规则 {result.InsertedRuleCount},覆盖规则 {result.UpdatedRuleCount}"; + return result; + } + catch (Exception ex) + { + LogService.Error($"导入 CAN/LIN 配置失败:{ex}"); + result.Message = $"导入失败:{ex.Message}"; + return result; + } + } + + /// + /// 构建导出快照对象。 + /// + /// 导出快照。 + private CanLinConfigPackageSnapshot BuildExportPackage() + { + var logicRules = FreeSql.Select().OrderBy(a => a.Id).ToList(); + + var canConfigPros = FreeSql.Select() + .Where(a => a.CANLINInfo == CANLIN.CAN) + .Include(a => a.CANConfigExd) + .IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule)) + .IncludeMany(a => a.CanScheduleConfigs) + .ToList(); + + var canFdConfigPros = FreeSql.Select() + .Where(a => a.CANLINInfo == CANLIN.CANFD) + .Include(a => a.CANFdConfigExd) + .IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule)) + .IncludeMany(a => a.CanFdScheduleConfigs) + .ToList(); + + var linConfigPros = FreeSql.Select() + .Where(a => a.CANLINInfo == CANLIN.LIN) + .Include(a => a.LINConfigExd) + .IncludeMany(a => a.CanLinConfigContents, then => then.Include(b => b.LogicRule)) + .IncludeMany(a => a.LinScheduleConfigs) + .ToList(); + + var allConfigPros = new List(); + allConfigPros.AddRange(canConfigPros); + allConfigPros.AddRange(canFdConfigPros); + allConfigPros.AddRange(linConfigPros); + + return new CanLinConfigPackageSnapshot + { + SchemaVersion = SchemaVersion, + ExportTime = DateTime.Now, + LogicRules = logicRules.Select(MapLogicRuleSnapshot).ToList(), + CanLinConfigPros = allConfigPros.Select(MapConfigSnapshot).ToList(), + }; + } + + /// + /// 导入单个配置程序。 + /// + /// 配置快照。 + /// 导入模式。 + /// 规则映射。 + /// 结果对象。 + private void ImportSingleConfig( + CanLinConfigProSnapshot snapshot, + CanLinImportMode importMode, + ImportRuleMaps ruleMaps, + CanLinConfigImExportResult result) + { + if (snapshot == null) + { + return; + } + + var sourceName = (snapshot.ConfigName ?? string.Empty).Trim(); + if (string.IsNullOrWhiteSpace(sourceName)) + { + throw new InvalidOperationException("导入文件中存在空配置名称"); + } + + var canlinInfo = snapshot.CANLINInfo; + var finalConfigName = sourceName; + + var sameConfigExists = FreeSql.Select() + .Where(a => a.CANLINInfo == canlinInfo) + .Where(a => a.ConfigName == sourceName) + .Any(); + + if (sameConfigExists) + { + if (importMode == CanLinImportMode.Overwrite) + { + DeleteExistingConfig(sourceName, canlinInfo); + result.OverwrittenConfigCount++; + } + else + { + finalConfigName = BuildUniqueImportName(sourceName, canlinInfo); + result.RenamedConfigCount++; + result.RenamedConfigs.Add($"{sourceName} -> {finalConfigName} ({canlinInfo})"); + } + } + + var configExdIds = CreateConfigExd(snapshot, canlinInfo); + + var insertPro = FreeSql.Insert(new CanLinConfigPro + { + ConfigName = finalConfigName, + CANLINInfo = canlinInfo, + CANConfigExdId = configExdIds.CANConfigExdId, + CANFdConfigExdId = configExdIds.CANFdConfigExdId, + LINConfigExdId = configExdIds.LINConfigExdId, + }).ExecuteInserted().FirstOrDefault(); + + if (insertPro == null) + { + throw new InvalidOperationException($"配置程序导入失败:{finalConfigName}"); + } + + var rwConfigs = snapshot.CanLinConfigContents ?? new List(); + foreach (var rwConfig in rwConfigs) + { + var logicRuleId = ResolveLogicRuleId(rwConfig, ruleMaps); + var rwInsertResult = FreeSql.Insert(new CanLinRWConfig + { + RWInfo = rwConfig.RWInfo, + Name = string.IsNullOrWhiteSpace(rwConfig.Name) ? rwConfig.SignalName : rwConfig.Name, + MsgFrameName = rwConfig.MsgFrameName ?? string.Empty, + SignalName = rwConfig.SignalName ?? string.Empty, + DefautValue = rwConfig.DefautValue, + CanLinConfigProId = insertPro.Id, + LogicRuleId = logicRuleId, + }).ExecuteAffrows(); + + if (rwInsertResult <= 0) + { + throw new InvalidOperationException($"导入读写配置失败:{finalConfigName}/{rwConfig.SignalName}"); + } + } + + if (canlinInfo == CANLIN.CAN) + { + foreach (var sch in snapshot.CanScheduleConfigs ?? new List()) + { + FreeSql.Insert(new CANScheduleConfig + { + MsgName = sch.MsgName, + Cycle = sch.Cycle, + OrderSend = sch.OrderSend, + SchTabIndex = sch.SchTabIndex, + CanLinConfigProId = insertPro.Id, + }).ExecuteAffrows(); + } + } + else if (canlinInfo == CANLIN.CANFD) + { + foreach (var sch in snapshot.CanFdScheduleConfigs ?? new List()) + { + FreeSql.Insert(new CANFdScheduleConfig + { + MsgName = sch.MsgName, + Cycle = sch.Cycle, + OrderSend = sch.OrderSend, + SchTabIndex = sch.SchTabIndex, + CanLinConfigProId = insertPro.Id, + }).ExecuteAffrows(); + } + } + else if (canlinInfo == CANLIN.LIN) + { + foreach (var sch in snapshot.LinScheduleConfigs ?? new List()) + { + FreeSql.Insert(new LINScheduleConfig + { + IsActive = sch.IsActive, + IsMsgActived = sch.IsMsgActived, + MsgName = sch.MsgName, + MsgNameIndex = sch.MsgNameIndex, + Cycle = sch.Cycle, + SchTabIndex = sch.SchTabIndex, + SchTabName = sch.SchTabName, + CanLinConfigProId = insertPro.Id, + }).ExecuteAffrows(); + } + } + + result.ImportedConfigCount++; + } + + /// + /// 创建并保存配置扩展信息。 + /// + /// 配置快照。 + /// 配置类型。 + /// 扩展配置主键集合。 + private ConfigExdIds CreateConfigExd(CanLinConfigProSnapshot snapshot, CANLIN canlinInfo) + { + var ids = new ConfigExdIds(); + if (canlinInfo == CANLIN.CAN) + { + var canExd = snapshot.CANConfigExd ?? new CANConfigExdSnapshot(); + var insert = FreeSql.Insert(new CANConfigExd + { + BaudRate = canExd.BaudRate, + Cycle = canExd.Cycle, + DbcPath = canExd.DbcPath ?? string.Empty, + SchEnable = canExd.SchEnable, + }).ExecuteInserted().FirstOrDefault(); + + if (insert == null) + { + throw new InvalidOperationException("导入 CAN 扩展配置失败"); + } + + ids.CANConfigExdId = insert.Id; + } + else if (canlinInfo == CANLIN.CANFD) + { + var canFdExd = snapshot.CANFdConfigExd ?? new CANFdConfigExdSnapshot(); + var insert = FreeSql.Insert(new CANFdConfigExd + { + DataBaudRate = canFdExd.DataBaudRate, + ArbBaudRate = canFdExd.ArbBaudRate, + ISOEnable = canFdExd.ISOEnable, + ResEnable = canFdExd.ResEnable, + Cycle = canFdExd.Cycle, + DbcPath = canFdExd.DbcPath ?? string.Empty, + SchEnable = canFdExd.SchEnable, + }).ExecuteInserted().FirstOrDefault(); + + if (insert == null) + { + throw new InvalidOperationException("导入 CANFD 扩展配置失败"); + } + + ids.CANFdConfigExdId = insert.Id; + } + else + { + var linExd = snapshot.LINConfigExd ?? new LINConfigExdSnapshot(); + var insert = FreeSql.Insert(new LINConfigExd + { + BaudRate = linExd.BaudRate, + Cycle = linExd.Cycle, + LdfPath = linExd.LdfPath ?? string.Empty, + SchEnable = linExd.SchEnable, + }).ExecuteInserted().FirstOrDefault(); + + if (insert == null) + { + throw new InvalidOperationException("导入 LIN 扩展配置失败"); + } + + ids.LINConfigExdId = insert.Id; + } + + return ids; + } + + /// + /// 删除同名同类型的旧配置。 + /// + /// 配置名称。 + /// 配置类型。 + private void DeleteExistingConfig(string configName, CANLIN canlinInfo) + { + var oldConfigs = FreeSql.Select() + .Where(a => a.CANLINInfo == canlinInfo) + .Where(a => a.ConfigName == configName) + .ToList(); + + foreach (var oldConfig in oldConfigs) + { + FreeSql.Delete().Where(a => a.CanLinConfigProId == oldConfig.Id).ExecuteAffrows(); + FreeSql.Delete().Where(a => a.CanLinConfigProId == oldConfig.Id).ExecuteAffrows(); + FreeSql.Delete().Where(a => a.CanLinConfigProId == oldConfig.Id).ExecuteAffrows(); + FreeSql.Delete().Where(a => a.CanLinConfigProId == oldConfig.Id).ExecuteAffrows(); + FreeSql.Delete(oldConfig.Id).ExecuteAffrows(); + + if (canlinInfo == CANLIN.CAN && oldConfig.CANConfigExdId > 0) + { + FreeSql.Delete(oldConfig.CANConfigExdId).ExecuteAffrows(); + } + else if (canlinInfo == CANLIN.CANFD && oldConfig.CANFdConfigExdId > 0) + { + FreeSql.Delete(oldConfig.CANFdConfigExdId).ExecuteAffrows(); + } + else if (canlinInfo == CANLIN.LIN && oldConfig.LINConfigExdId > 0) + { + FreeSql.Delete(oldConfig.LINConfigExdId).ExecuteAffrows(); + } + } + } + + /// + /// 生成可用的增量重命名配置名。 + /// + /// 原始名称。 + /// 配置类型。 + /// 可用名称。 + private string BuildUniqueImportName(string originalName, CANLIN canlinInfo) + { + var baseName = $"{originalName}_import_{DateTime.Now:yyyyMMddHHmmss}"; + var candidate = baseName; + var suffix = 1; + + while (FreeSql.Select() + .Where(a => a.CANLINInfo == canlinInfo) + .Where(a => a.ConfigName == candidate) + .Any()) + { + candidate = $"{baseName}_{suffix}"; + suffix++; + } + + return candidate; + } + + /// + /// 导入并覆盖逻辑规则。 + /// + /// 规则快照集合。 + /// 执行结果。 + /// 规则映射。 + private ImportRuleMaps UpsertLogicRules(List logicRules, CanLinConfigImExportResult result) + { + var maps = new ImportRuleMaps(); + foreach (var snapshot in logicRules) + { + if (snapshot == null) + { + continue; + } + + var ruleName = (snapshot.Name ?? string.Empty).Trim(); + if (string.IsNullOrWhiteSpace(ruleName)) + { + continue; + } + + var oldRule = FreeSql.Select().Where(a => a.Name == ruleName).First(); + if (oldRule != null) + { + FreeSql.Update() + .Set(a => a.Description, snapshot.Description) + .Set(a => a.Expression, snapshot.Expression) + .Set(a => a.ParameterType, snapshot.ParameterType) + .Where(a => a.Id == oldRule.Id) + .ExecuteAffrows(); + + maps.NameToTargetId[ruleName] = oldRule.Id; + if (snapshot.Id > 0) + { + maps.SourceIdToTargetId[snapshot.Id] = oldRule.Id; + } + result.UpdatedRuleCount++; + } + else + { + var insertRule = FreeSql.Insert(new LogicRule + { + Name = ruleName, + Description = snapshot.Description, + Expression = snapshot.Expression, + ParameterType = snapshot.ParameterType, + }).ExecuteInserted().FirstOrDefault(); + + if (insertRule == null) + { + throw new InvalidOperationException($"导入逻辑规则失败:{ruleName}"); + } + + maps.NameToTargetId[ruleName] = insertRule.Id; + if (snapshot.Id > 0) + { + maps.SourceIdToTargetId[snapshot.Id] = insertRule.Id; + } + + result.InsertedRuleCount++; + } + } + + return maps; + } + + /// + /// 解析读写配置对应的目标规则 Id。 + /// + /// 读写配置快照。 + /// 规则映射。 + /// 规则 Id。 + private long ResolveLogicRuleId(CanLinRWConfigSnapshot rwSnapshot, ImportRuleMaps ruleMaps) + { + if (rwSnapshot == null) + { + return 0; + } + + if (rwSnapshot.LogicRule != null) + { + var ruleName = (rwSnapshot.LogicRule.Name ?? string.Empty).Trim(); + if (!string.IsNullOrWhiteSpace(ruleName) && ruleMaps.NameToTargetId.TryGetValue(ruleName, out var byNameId)) + { + return byNameId; + } + } + + if (rwSnapshot.LogicRuleId > 0 && ruleMaps.SourceIdToTargetId.TryGetValue(rwSnapshot.LogicRuleId, out var bySourceId)) + { + return bySourceId; + } + + return 0; + } + + /// + /// 将规则实体映射为快照。 + /// + /// 规则实体。 + /// 规则快照。 + private static LogicRuleSnapshot MapLogicRuleSnapshot(LogicRule rule) + { + return new LogicRuleSnapshot + { + Id = rule.Id, + Name = rule.Name, + Description = rule.Description, + Expression = rule.Expression, + ParameterType = rule.ParameterType, + }; + } + + /// + /// 将配置实体映射为快照。 + /// + /// 配置实体。 + /// 配置快照。 + private static CanLinConfigProSnapshot MapConfigSnapshot(CanLinConfigPro configPro) + { + return new CanLinConfigProSnapshot + { + ConfigName = configPro.ConfigName, + CANLINInfo = configPro.CANLINInfo, + CreateTime = configPro.CreateTime, + CANConfigExd = configPro.CANConfigExd == null + ? null + : new CANConfigExdSnapshot + { + BaudRate = configPro.CANConfigExd.BaudRate, + Cycle = configPro.CANConfigExd.Cycle, + DbcPath = configPro.CANConfigExd.DbcPath, + SchEnable = configPro.CANConfigExd.SchEnable, + }, + CANFdConfigExd = configPro.CANFdConfigExd == null + ? null + : new CANFdConfigExdSnapshot + { + DataBaudRate = configPro.CANFdConfigExd.DataBaudRate, + ArbBaudRate = configPro.CANFdConfigExd.ArbBaudRate, + ISOEnable = configPro.CANFdConfigExd.ISOEnable, + ResEnable = configPro.CANFdConfigExd.ResEnable, + Cycle = configPro.CANFdConfigExd.Cycle, + DbcPath = configPro.CANFdConfigExd.DbcPath, + SchEnable = configPro.CANFdConfigExd.SchEnable, + }, + LINConfigExd = configPro.LINConfigExd == null + ? null + : new LINConfigExdSnapshot + { + BaudRate = configPro.LINConfigExd.BaudRate, + Cycle = configPro.LINConfigExd.Cycle, + LdfPath = configPro.LINConfigExd.LdfPath, + SchEnable = configPro.LINConfigExd.SchEnable, + }, + CanLinConfigContents = (configPro.CanLinConfigContents ?? new List()) + .Select(a => new CanLinRWConfigSnapshot + { + RWInfo = a.RWInfo, + Name = a.Name, + MsgFrameName = a.MsgFrameName, + SignalName = a.SignalName, + DefautValue = a.DefautValue, + LogicRuleId = a.LogicRuleId, + LogicRule = a.LogicRule == null ? null : MapLogicRuleSnapshot(a.LogicRule), + }).ToList(), + CanScheduleConfigs = (configPro.CanScheduleConfigs ?? new List()) + .Select(a => new CANScheduleConfigSnapshot + { + MsgName = a.MsgName, + Cycle = a.Cycle, + OrderSend = a.OrderSend, + SchTabIndex = a.SchTabIndex, + }).ToList(), + CanFdScheduleConfigs = (configPro.CanFdScheduleConfigs ?? new List()) + .Select(a => new CANFdScheduleConfigSnapshot + { + MsgName = a.MsgName, + Cycle = a.Cycle, + OrderSend = a.OrderSend, + SchTabIndex = a.SchTabIndex, + }).ToList(), + LinScheduleConfigs = (configPro.LinScheduleConfigs ?? new List()) + .Select(a => new LINScheduleConfigSnapshot + { + IsActive = a.IsActive, + IsMsgActived = a.IsMsgActived, + MsgName = a.MsgName, + MsgNameIndex = a.MsgNameIndex, + Cycle = a.Cycle, + SchTabIndex = a.SchTabIndex, + SchTabName = a.SchTabName, + }).ToList(), + }; + } + + /// + /// 规则映射上下文。 + /// + private class ImportRuleMaps + { + /// + /// 规则名称到目标库规则 Id 的映射。 + /// + public Dictionary NameToTargetId { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); + + /// + /// 源文件规则 Id 到目标库规则 Id 的映射。 + /// + public Dictionary SourceIdToTargetId { get; set; } = new Dictionary(); + } + + /// + /// 扩展配置主键集合。 + /// + private class ConfigExdIds + { + /// + /// CAN 扩展主键。 + /// + public long CANConfigExdId { get; set; } + + /// + /// CANFD 扩展主键。 + /// + public long CANFdConfigExdId { get; set; } + + /// + /// LIN 扩展主键。 + /// + public long LINConfigExdId { get; set; } + } + } + + /// + /// CAN/LIN 配置导入导出文件根对象。 + /// + public class CanLinConfigPackageSnapshot + { + /// + /// 文件结构版本。 + /// + public string SchemaVersion { get; set; } = string.Empty; + + /// + /// 导出时间。 + /// + public DateTime ExportTime { get; set; } + + /// + /// 规则集合。 + /// + public List LogicRules { get; set; } = new List(); + + /// + /// 配置程序集合。 + /// + public List CanLinConfigPros { get; set; } = new List(); + } + + /// + /// 逻辑规则快照。 + /// + public class LogicRuleSnapshot + { + /// + /// 主键。 + /// + public long Id { get; set; } + + /// + /// 规则名称。 + /// + public string? Name { get; set; } + + /// + /// 规则描述。 + /// + public string? Description { get; set; } + + /// + /// 规则表达式。 + /// + public string? Expression { get; set; } + + /// + /// 参数类型。 + /// + public string? ParameterType { get; set; } + } + + /// + /// 配置程序快照。 + /// + public class CanLinConfigProSnapshot + { + /// + /// 配置名称。 + /// + public string? ConfigName { get; set; } + + /// + /// 配置分类。 + /// + public CANLIN CANLINInfo { get; set; } + + /// + /// 创建时间。 + /// + public DateTime CreateTime { get; set; } + + /// + /// CAN 扩展配置。 + /// + public CANConfigExdSnapshot? CANConfigExd { get; set; } + + /// + /// CANFD 扩展配置。 + /// + public CANFdConfigExdSnapshot? CANFdConfigExd { get; set; } + + /// + /// LIN 扩展配置。 + /// + public LINConfigExdSnapshot? LINConfigExd { get; set; } + + /// + /// 读写配置集合。 + /// + public List? CanLinConfigContents { get; set; } + + /// + /// CAN 调度配置。 + /// + public List? CanScheduleConfigs { get; set; } + + /// + /// CANFD 调度配置。 + /// + public List? CanFdScheduleConfigs { get; set; } + + /// + /// LIN 调度配置。 + /// + public List? LinScheduleConfigs { get; set; } + } + + /// + /// CAN 扩展快照。 + /// + public class CANConfigExdSnapshot + { + /// + /// 波特率。 + /// + public int BaudRate { get; set; } + + /// + /// 周期。 + /// + public int Cycle { get; set; } + + /// + /// DBC 路径。 + /// + public string? DbcPath { get; set; } + + /// + /// 调度启用。 + /// + public bool SchEnable { get; set; } + } + + /// + /// CANFD 扩展快照。 + /// + public class CANFdConfigExdSnapshot + { + /// + /// 数据波特率。 + /// + public int DataBaudRate { get; set; } + + /// + /// 仲裁波特率。 + /// + public int ArbBaudRate { get; set; } + + /// + /// ISO 开关。 + /// + public bool ISOEnable { get; set; } + + /// + /// 终端电阻开关。 + /// + public bool ResEnable { get; set; } + + /// + /// 周期。 + /// + public int Cycle { get; set; } + + /// + /// DBC 路径。 + /// + public string? DbcPath { get; set; } + + /// + /// 调度启用。 + /// + public bool SchEnable { get; set; } + } + + /// + /// LIN 扩展快照。 + /// + public class LINConfigExdSnapshot + { + /// + /// 波特率。 + /// + public int BaudRate { get; set; } + + /// + /// 周期。 + /// + public int Cycle { get; set; } + + /// + /// LDF 路径。 + /// + public string? LdfPath { get; set; } + + /// + /// 调度启用。 + /// + public bool SchEnable { get; set; } + } + + /// + /// 读写配置快照。 + /// + public class CanLinRWConfigSnapshot + { + /// + /// 读写类型。 + /// + public RW RWInfo { get; set; } + + /// + /// 配置名称。 + /// + public string? Name { get; set; } + + /// + /// 帧名。 + /// + public string? MsgFrameName { get; set; } + + /// + /// 信号名。 + /// + public string? SignalName { get; set; } + + /// + /// 默认值。 + /// + public string? DefautValue { get; set; } + + /// + /// 规则 Id。 + /// + public long LogicRuleId { get; set; } + + /// + /// 规则对象。 + /// + public LogicRuleSnapshot? LogicRule { get; set; } + } + + /// + /// CAN 调度快照。 + /// + public class CANScheduleConfigSnapshot + { + /// + /// 消息名。 + /// + public string? MsgName { get; set; } + + /// + /// 周期。 + /// + public int Cycle { get; set; } + + /// + /// 发送方式。 + /// + public int OrderSend { get; set; } + + /// + /// 调度表索引。 + /// + public int SchTabIndex { get; set; } + } + + /// + /// CANFD 调度快照。 + /// + public class CANFdScheduleConfigSnapshot + { + /// + /// 消息名。 + /// + public string? MsgName { get; set; } + + /// + /// 周期。 + /// + public int Cycle { get; set; } + + /// + /// 发送方式。 + /// + public int OrderSend { get; set; } + + /// + /// 调度表索引。 + /// + public int SchTabIndex { get; set; } + } + + /// + /// LIN 调度快照。 + /// + public class LINScheduleConfigSnapshot + { + /// + /// 是否启用。 + /// + public bool IsActive { get; set; } + + /// + /// 是否消息激活。 + /// + public bool IsMsgActived { get; set; } + + /// + /// 消息名。 + /// + public string? MsgName { get; set; } + + /// + /// 消息索引。 + /// + public int MsgNameIndex { get; set; } + + /// + /// 周期。 + /// + public int Cycle { get; set; } + + /// + /// 调度索引。 + /// + public int SchTabIndex { get; set; } + + /// + /// 调度名。 + /// + public string? SchTabName { get; set; } + } +} diff --git a/CapMachine.Wpf/Services/ComActionService.cs b/CapMachine.Wpf/Services/ComActionService.cs index b1f4438..374c146 100644 --- a/CapMachine.Wpf/Services/ComActionService.cs +++ b/CapMachine.Wpf/Services/ComActionService.cs @@ -70,6 +70,9 @@ namespace CapMachine.Wpf.Services } ShowLogicRule(msg.Par); break; + case "CAN/CANFD/LIN配置导入导出": + ShowCanLinConfigImExport(msg.Par); + break; default: break; } @@ -136,6 +139,20 @@ namespace CapMachine.Wpf.Services }); } + /// + /// CAN/CANFD/LIN 配置导入导出弹窗。 + /// + /// 透传参数。 + private void ShowCanLinConfigImExport(object par) + { + DialogService.ShowDialog("DialogCanLinConfigImExportView", new DialogParameters() { { "Name", par } }, (dialogResult) => + { + if (dialogResult.Result == ButtonResult.OK) + { + } + }); + } + diff --git a/CapMachine.Wpf/Services/NavigationMenuService.cs b/CapMachine.Wpf/Services/NavigationMenuService.cs index 716ea63..3e9aca6 100644 --- a/CapMachine.Wpf/Services/NavigationMenuService.cs +++ b/CapMachine.Wpf/Services/NavigationMenuService.cs @@ -44,10 +44,10 @@ namespace CapMachine.Wpf.Services { new NavigationItem("Rule","规则转换","DialogLogicRuleView"), }), - //new NavigationItem("", "PID设置","",new ObservableCollection() - //{ - // new NavigationItem("Circle","转速PID",""), - //}), + new NavigationItem("", "配置导出","",new ObservableCollection() + { + new NavigationItem("","CAN/CANFD/LIN配置导入导出","DialogCanLinConfigImExport"), + }), //new NavigationItem("", "通信配置","",new ObservableCollection() //{ // new NavigationItem("Circle","CAN配置","CANConfigView"), diff --git a/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs b/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs index 69ed3b8..cb0e6bc 100644 --- a/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs +++ b/CapMachine.Wpf/ViewModels/CANConfigViewModel.cs @@ -57,6 +57,7 @@ namespace CapMachine.Wpf.ViewModels DialogService = dialogService; EventAggregator.GetEvent().Subscribe(LogicRuleChangeEventCall); + EventAggregator.GetEvent().Subscribe(CanLinConfigChangedEventCall); //数据波特率 DataBaudRateCbxItems = new ObservableCollection() @@ -150,6 +151,16 @@ namespace CapMachine.Wpf.ViewModels //InitWriteRuleCbx(); } + /// + /// CAN/LIN 配置导入后刷新当前页面。 + /// + /// 事件消息。 + private void CanLinConfigChangedEventCall(string msg) + { + InitLoadCanConfigPro(); + InitWriteRuleCbx(); + } + /// /// 初始化写规则下拉框 /// diff --git a/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs b/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs index 78e00f8..ea27dc2 100644 --- a/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs +++ b/CapMachine.Wpf/ViewModels/CANFDConfigViewModel.cs @@ -55,6 +55,7 @@ namespace CapMachine.Wpf.ViewModels DialogService = dialogService; EventAggregator.GetEvent().Subscribe(LogicRuleChangeEventCall); + EventAggregator.GetEvent().Subscribe(CanLinConfigChangedEventCall); //仲裁波特率 ArbBaudRateCbxItems = new ObservableCollection() @@ -170,6 +171,16 @@ namespace CapMachine.Wpf.ViewModels //InitWriteRuleCbx(); } + /// + /// CAN/LIN 配置导入后刷新当前页面。 + /// + /// 事件消息。 + private void CanLinConfigChangedEventCall(string msg) + { + InitLoadCanConfigPro(); + InitWriteRuleCbx(); + } + /// /// 初始化写规则下拉框 /// diff --git a/CapMachine.Wpf/ViewModels/DialogCanLinConfigImExportViewModel.cs b/CapMachine.Wpf/ViewModels/DialogCanLinConfigImExportViewModel.cs new file mode 100644 index 0000000..6e22ef3 --- /dev/null +++ b/CapMachine.Wpf/ViewModels/DialogCanLinConfigImExportViewModel.cs @@ -0,0 +1,319 @@ +using CapMachine.Core; +using CapMachine.Wpf.PrismEvent; +using CapMachine.Wpf.Services; +using Microsoft.Win32; +using Prism.Commands; +using Prism.Events; +using Prism.Services.Dialogs; +using System; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Windows; + +namespace CapMachine.Wpf.ViewModels +{ + /// + /// CAN/CANFD/LIN 配置导入导出弹窗 ViewModel。 + /// + public class DialogCanLinConfigImExportViewModel : DialogViewModel + { + /// + /// 初始化导入导出弹窗。 + /// + /// 导入导出服务。 + /// 事件聚合器。 + public DialogCanLinConfigImExportViewModel( + CanLinConfigImExportService canLinConfigImExportService, + IEventAggregator eventAggregator) + { + CanLinConfigImExportService = canLinConfigImExportService; + EventAggregator = eventAggregator; + Title = "CAN/CANFD/LIN配置导入导出"; + + ImportModes = new ObservableCollection + { + new ImportModeOption { Text = "覆盖导入(同名同类型先删除后导入)", Mode = CanLinImportMode.Overwrite }, + new ImportModeOption { Text = "增量导入(同名同类型自动重命名)", Mode = CanLinImportMode.IncrementalRename }, + }; + + SelectedImportMode = ImportModes.FirstOrDefault(); + } + + /// + /// 导入导出服务。 + /// + public CanLinConfigImExportService CanLinConfigImExportService { get; } + + /// + /// 事件聚合器。 + /// + public IEventAggregator EventAggregator { get; } + + private string _importFilePath = string.Empty; + /// + /// 导入文件路径。 + /// + public string ImportFilePath + { + get { return _importFilePath; } + set { _importFilePath = value; RaisePropertyChanged(); } + } + + private ObservableCollection _importModes = new ObservableCollection(); + /// + /// 导入模式集合。 + /// + public ObservableCollection ImportModes + { + get { return _importModes; } + set { _importModes = value; RaisePropertyChanged(); } + } + + private ImportModeOption? _selectedImportMode; + /// + /// 当前选中的导入模式。 + /// + public ImportModeOption? SelectedImportMode + { + get { return _selectedImportMode; } + set { _selectedImportMode = value; RaisePropertyChanged(); } + } + + private string _resultMessage = string.Empty; + /// + /// 操作结果消息。 + /// + public string ResultMessage + { + get { return _resultMessage; } + set { _resultMessage = value; RaisePropertyChanged(); } + } + + private DelegateCommand? _browseImportFileCmd; + /// + /// 选择导入文件命令。 + /// + public DelegateCommand BrowseImportFileCmd + { + get + { + if (_browseImportFileCmd == null) + { + _browseImportFileCmd = new DelegateCommand(BrowseImportFile); + } + + return _browseImportFileCmd; + } + } + + private DelegateCommand? _importCmd; + /// + /// 导入命令。 + /// + public DelegateCommand ImportCmd + { + get + { + if (_importCmd == null) + { + _importCmd = new DelegateCommand(ImportConfig); + } + + return _importCmd; + } + } + + private DelegateCommand? _exportCmd; + /// + /// 导出命令。 + /// + public DelegateCommand ExportCmd + { + get + { + if (_exportCmd == null) + { + _exportCmd = new DelegateCommand(ExportConfig); + } + + return _exportCmd; + } + } + + private DelegateCommand? _closeCmd; + /// + /// 关闭命令。 + /// + public DelegateCommand CloseCmd + { + get + { + if (_closeCmd == null) + { + _closeCmd = new DelegateCommand(CloseDialog); + } + + return _closeCmd; + } + } + + /// + /// 打开文件选择框并选择导入文件。 + /// + private void BrowseImportFile() + { + try + { + var openFileDialog = new OpenFileDialog + { + Filter = "JSON文件 (*.json)|*.json|所有文件 (*.*)|*.*", + CheckFileExists = true, + CheckPathExists = true, + }; + + var ok = openFileDialog.ShowDialog(); + if (ok == true) + { + ImportFilePath = openFileDialog.FileName; + } + } + catch (Exception ex) + { + MessageBox.Show($"选择导入文件失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + + /// + /// 执行配置导入。 + /// + private void ImportConfig() + { + try + { + if (string.IsNullOrWhiteSpace(ImportFilePath)) + { + MessageBox.Show("请先选择导入文件", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + if (SelectedImportMode == null) + { + MessageBox.Show("请选择导入模式", "提示", MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + var result = CanLinConfigImExportService.ImportFromFile(ImportFilePath, SelectedImportMode.Mode); + ResultMessage = BuildResultText(result); + + if (!result.IsSuccess) + { + MessageBox.Show(ResultMessage, "导入失败", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + EventAggregator.GetEvent().Publish("import"); + EventAggregator.GetEvent().Publish("import"); + MessageBox.Show(ResultMessage, "导入成功", MessageBoxButton.OK, MessageBoxImage.Information); + } + catch (Exception ex) + { + ResultMessage = $"导入失败:{ex.Message}"; + MessageBox.Show(ResultMessage, "导入失败", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + + /// + /// 执行配置导出。 + /// + private void ExportConfig() + { + try + { + var saveFileDialog = new SaveFileDialog + { + Filter = "JSON文件 (*.json)|*.json|所有文件 (*.*)|*.*", + DefaultExt = "json", + FileName = $"CanLinConfigExport_{DateTime.Now:yyyyMMddHHmmss}.json", + }; + + var ok = saveFileDialog.ShowDialog(); + if (ok != true) + { + return; + } + + var result = CanLinConfigImExportService.ExportToFile(saveFileDialog.FileName); + ResultMessage = BuildResultText(result); + + if (!result.IsSuccess) + { + MessageBox.Show(ResultMessage, "导出失败", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + MessageBox.Show(ResultMessage, "导出成功", MessageBoxButton.OK, MessageBoxImage.Information); + } + catch (Exception ex) + { + ResultMessage = $"导出失败:{ex.Message}"; + MessageBox.Show(ResultMessage, "导出失败", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + + /// + /// 关闭弹窗。 + /// + private void CloseDialog() + { + RaiseRequestClose(new DialogResult(ButtonResult.Cancel)); + } + + /// + /// 构建结果文本。 + /// + /// 执行结果。 + /// 显示文本。 + private static string BuildResultText(CanLinConfigImExportResult result) + { + var builder = new StringBuilder(); + builder.AppendLine(result.Message); + + if (result.RenamedConfigs != null && result.RenamedConfigs.Count > 0) + { + builder.AppendLine("重命名明细:"); + foreach (var line in result.RenamedConfigs) + { + builder.AppendLine($"- {line}"); + } + } + + return builder.ToString(); + } + + /// + /// 弹窗打开回调。 + /// + /// 弹窗参数。 + public override void OnDialogOpened(IDialogParameters parameters) + { + ResultMessage = string.Empty; + } + + /// + /// 导入模式选项。 + /// + public class ImportModeOption + { + /// + /// 文本。 + /// + public string Text { get; set; } = string.Empty; + + /// + /// 模式值。 + /// + public CanLinImportMode Mode { get; set; } + } + } +} diff --git a/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs b/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs index 86bf656..336df1a 100644 --- a/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs +++ b/CapMachine.Wpf/ViewModels/LinConfigViewModel.cs @@ -4,6 +4,7 @@ using CapMachine.Model.CANLIN; using CapMachine.Wpf.CanDrive; using CapMachine.Wpf.Dtos; using CapMachine.Wpf.LinDrive; +using CapMachine.Wpf.PrismEvent; using CapMachine.Wpf.Services; using Prism.Commands; using Prism.Events; @@ -55,6 +56,7 @@ namespace CapMachine.Wpf.ViewModels //MachineDataService = machineDataService; DialogService = dialogService; + EventAggregator.GetEvent().Subscribe(CanLinConfigChangedEventCall); //数据波特率 DataBaudRateCbxItems = new ObservableCollection() @@ -144,6 +146,16 @@ namespace CapMachine.Wpf.ViewModels //InitWriteRuleCbx(); } + /// + /// CAN/LIN 配置导入后刷新当前页面。 + /// + /// 事件消息。 + private void CanLinConfigChangedEventCall(string msg) + { + InitLoadLinConfigPro(); + InitWriteRuleCbx(); + } + /// /// 初始化写规则下拉框 /// diff --git a/CapMachine.Wpf/ViewModels/ZlgCanDriveConfigViewModel.cs b/CapMachine.Wpf/ViewModels/ZlgCanDriveConfigViewModel.cs index 8ba3087..57efe98 100644 --- a/CapMachine.Wpf/ViewModels/ZlgCanDriveConfigViewModel.cs +++ b/CapMachine.Wpf/ViewModels/ZlgCanDriveConfigViewModel.cs @@ -3,6 +3,7 @@ using CapMachine.Core; using CapMachine.Model.CANLIN; using CapMachine.Wpf.CanDrive; using CapMachine.Wpf.Dtos; +using CapMachine.Wpf.PrismEvent; using CapMachine.Wpf.Services; using CapMachine.Wpf.Views; using ImTools; @@ -79,6 +80,7 @@ namespace CapMachine.Wpf.ViewModels ZlgCanDriveService = zlgCanDriveService; ZlgLinDriveService = zlgLinDriveService; Mapper = mapper; + EventAggregator.GetEvent().Subscribe(CanLinConfigChangedEventCall); SelectedMode = ZlgCanMode.Can; @@ -129,6 +131,16 @@ namespace CapMachine.Wpf.ViewModels InitLoadCanConfigPro(); } + /// + /// CAN/LIN 配置导入后刷新当前页面。 + /// + /// 事件消息。 + private void CanLinConfigChangedEventCall(string msg) + { + InitWriteRuleCbx(); + ReloadCurrentConfigPro(); + } + /// /// 初始化“写入规则”下拉框数据源。 /// diff --git a/CapMachine.Wpf/ViewModels/ZlgLinDriveConfigViewModel.cs b/CapMachine.Wpf/ViewModels/ZlgLinDriveConfigViewModel.cs index 7163f8f..e7e6882 100644 --- a/CapMachine.Wpf/ViewModels/ZlgLinDriveConfigViewModel.cs +++ b/CapMachine.Wpf/ViewModels/ZlgLinDriveConfigViewModel.cs @@ -3,6 +3,7 @@ using CapMachine.Core; using CapMachine.Model.CANLIN; using CapMachine.Wpf.Dtos; using CapMachine.Wpf.LinDrive; +using CapMachine.Wpf.PrismEvent; using CapMachine.Wpf.Services; using CapMachine.Wpf.Views; using ImTools; @@ -46,10 +47,20 @@ namespace CapMachine.Wpf.ViewModels ComActionService = comActionService; LogicRuleService = logicRuleService; Mapper = mapper; + EventAggregator.GetEvent().Subscribe(CanLinConfigChangedEventCall); InitLoadLinConfigPro(); } + /// + /// CAN/LIN 配置导入后刷新当前页面。 + /// + /// 事件消息。 + private void CanLinConfigChangedEventCall(string msg) + { + ReloadCurrentConfigPro(); + } + /// /// Prism 弹窗服务。 /// diff --git a/CapMachine.Wpf/Views/DialogCanLinConfigImExportView.xaml b/CapMachine.Wpf/Views/DialogCanLinConfigImExportView.xaml new file mode 100644 index 0000000..052680b --- /dev/null +++ b/CapMachine.Wpf/Views/DialogCanLinConfigImExportView.xaml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + +