VmDisplayPlugin.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using System.Windows;
  5. using Plugins.Vm.Models;
  6. using Plugins.Vm.Views;
  7. using TeamAAS.FlowEditor.Execution;
  8. using TeamAAS.FlowEditor.Models;
  9. using TeamAAS.FlowEditor.Plugins;
  10. namespace Plugins.Vm
  11. {
  12. /// <summary>
  13. /// VM 图像显示节点:把上游输出的图层/图像显示到指定画面框(视觉窗体);每个显示项可独立
  14. /// 链接 OK/NG 结果(可不链接)驱动该画面框状态圆点。镜像 VppDisplayPlugin。
  15. /// </summary>
  16. [Serializable]
  17. [Plugin("VM图像显示", PluginCategory.Vm模块, typeof(VmDisplayModel),
  18. "Monitor",
  19. Description = "把图层/图像显示到主页画面框;每项可独立链接 OK/NG 结果驱动状态圆点(可不链接)")]
  20. public class VmDisplayPlugin : BasePlugin<VmDisplayModel>
  21. {
  22. public override List<OutputField> DeclareOutputs()
  23. {
  24. var list = new List<OutputField>
  25. {
  26. new OutputField("显示画面数", typeof(int)),
  27. new OutputField("结果", typeof(bool)),
  28. };
  29. foreach (var kv in BuildItemKeys(Model))
  30. list.Add(new OutputField(kv.Key, typeof(object)));
  31. return list;
  32. }
  33. /// <summary>
  34. /// 依据显示项列表生成稳定的“输出键 → 显示项”映射:键优先取目标画面名,重名/空名时追加序号去重。
  35. /// DeclareOutputs 与 PluginRun 共用,保证键一致。
  36. /// </summary>
  37. private static List<KeyValuePair<string, VmDisplayItem>> BuildItemKeys(VmDisplayModel model)
  38. {
  39. var map = new List<KeyValuePair<string, VmDisplayItem>>();
  40. if (model?.DisplayItems == null) return map;
  41. var used = new HashSet<string>();
  42. for (int i = 0; i < model.DisplayItems.Count; i++)
  43. {
  44. var item = model.DisplayItems[i];
  45. if (item == null) continue;
  46. string key = string.IsNullOrWhiteSpace(item.FrameName) ? $"画面{item.FrameNo}" : item.FrameName;
  47. string unique = key;
  48. int dup = 2;
  49. while (!used.Add(unique)) unique = $"{key}({dup++})";
  50. map.Add(new KeyValuePair<string, VmDisplayItem>(unique, item));
  51. }
  52. return map;
  53. }
  54. public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary<string, object> results)
  55. {
  56. results = new Dictionary<string, object>();
  57. try
  58. {
  59. var windows = UCDispVm.Instance.vmWindow;
  60. int displayed = 0;
  61. Log(3, $"开始显示,显示项 {Model.DisplayItems?.Count ?? 0} 个,可用画面框 {windows?.Count ?? 0} 个");
  62. foreach (var kv in BuildItemKeys(Model))
  63. {
  64. var item = kv.Value;
  65. results[kv.Key] = null;
  66. if (item.FrameNo < 1 || windows == null || windows.Count < item.FrameNo)
  67. {
  68. Log(2, $"显示项[{kv.Key}] 目标画面序号 {item.FrameNo} 无效或画面框不足,已跳过", TeamAAS.LogLevel.Warning);
  69. continue;
  70. }
  71. var win = windows[item.FrameNo - 1];
  72. if (win == null)
  73. {
  74. Log(2, $"显示项[{kv.Key}] 画面框为空,已跳过", TeamAAS.LogLevel.Warning);
  75. continue;
  76. }
  77. object value = GetResolve(item.Source);
  78. results[kv.Key] = value;
  79. var toShow = value;
  80. Application.Current?.Dispatcher.Invoke(() => win.RefreshImage(toShow));
  81. displayed++;
  82. Log(4, $"显示项[{kv.Key}] → 画面{item.FrameNo},类型 {(value?.GetType().Name ?? "null")}");
  83. if (!string.IsNullOrWhiteSpace(item.OkNgBinding?.Formula))
  84. {
  85. bool ok = GetValue<bool>(item.OkNgBinding);
  86. win.SetLable(ok ? VmResultType.OK : VmResultType.NG);
  87. Log(4, $"显示项[{kv.Key}] OK/NG = {(ok ? "OK" : "NG")}");
  88. }
  89. }
  90. results["显示画面数"] = displayed;
  91. results["结果"] = true;
  92. Log(2, $"显示完成,共刷新 {displayed} 个画面");
  93. return NodeRunStatus.Success;
  94. }
  95. catch (Exception ex)
  96. {
  97. results["Error"] = ex.Message;
  98. results["结果"] = false;
  99. Log(1, $"VM图像显示异常: {ex.Message}", TeamAAS.LogLevel.Error);
  100. return NodeRunStatus.Failed;
  101. }
  102. }
  103. }
  104. }