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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CapMachine.Wpf/Views/DialogCanLinConfigImExportView.xaml.cs b/CapMachine.Wpf/Views/DialogCanLinConfigImExportView.xaml.cs
new file mode 100644
index 0000000..12dd502
--- /dev/null
+++ b/CapMachine.Wpf/Views/DialogCanLinConfigImExportView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace CapMachine.Wpf.Views
+{
+ ///
+ /// DialogCanLinConfigImExport.xaml 的交互逻辑
+ ///
+ public partial class DialogCanLinConfigImExportView : UserControl
+ {
+ public DialogCanLinConfigImExportView()
+ {
+ InitializeComponent();
+ }
+ }
+}