瀏覽代碼

refactor: ViewAView 迁移到 Profile 动态模式(P4)

- ViewAViewModel 新增 Profile / AnalogValues / DigitalValues 属性
- ApplyData 末尾新增 UpdateDynamicDictionaries 同步字典
- ViewAView.axaml 2D/3D 控件从 15 个硬编码属性绑定
  改为 Profile + AnalogValues + DigitalValues 字典驱动
- 右侧面板继续用原 ViewModel 属性,无功能变化
- 遗留的 StyledProperty(Tank1Level 等)保留但不再被 ViewAView 使用
DESKTOP-74CLTRG\Leol 1 月之前
父節點
當前提交
f91fcb52fb
共有 2 個文件被更改,包括 105 次插入 和 34 次删除
  1. 6 34
      src/YZWater.Avalonia/Views/ViewAView.axaml
  2. 99 0
      src/YZWater.Core/ViewModels/ViewAViewModel.cs

+ 6 - 34
src/YZWater.Avalonia/Views/ViewAView.axaml

@@ -66,23 +66,9 @@
                             <Grid>
                                 <controls:PumpStation2DControl
                                     IsVisible="{Binding Is2DView}"
-                                    Tank1Level="{Binding Tank1Level}"
-                                    Tank2Level="{Binding Tank2Level}"
-                                    Tank3Level="{Binding Tank3Level}"
-                                    Tank4Level="{Binding Tank4Level}"
-                                    InflowRate="{Binding InflowRate}"
-                                    OutflowRate="{Binding OutflowRate}"
-                                    Pump1Running="{Binding Pump1Running}"
-                                    Pump2Running="{Binding Pump2Running}"
-                                    Pump3Running="{Binding Pump3Running}"
-                                    Pump4Running="{Binding Pump4Running}"
-                                    Pump5Running="{Binding Pump5Running}"
-                                    Fan1Running="{Binding Fan1Running}"
-                                    Fan2Running="{Binding Fan2Running}"
-                                    Valve1Status="{Binding Valve1Status}"
-                                    Valve2Status="{Binding Valve2Status}"
-                                    Valve3Status="{Binding Valve3Status}"
-                                    Valve4Status="{Binding Valve4Status}"
+                                    Profile="{Binding Profile}"
+                                    AnalogValues="{Binding AnalogValues}"
+                                    DigitalValues="{Binding DigitalValues}"
                                     IsInflowRunning="{Binding IsInflowRunning}"
                                     IsOutflowRunning="{Binding IsOutflowRunning}"
                                     HasAlarm="{Binding HasAlarm}"
@@ -91,23 +77,9 @@
                                     Efficiency="{Binding Efficiency}"/>
                                 <controls:PumpStation3DControl
                                     IsVisible="{Binding Is3DView}"
-                                    Tank1Level="{Binding Tank1Level}"
-                                    Tank2Level="{Binding Tank2Level}"
-                                    Tank3Level="{Binding Tank3Level}"
-                                    Tank4Level="{Binding Tank4Level}"
-                                    InflowRate="{Binding InflowRate}"
-                                    OutflowRate="{Binding OutflowRate}"
-                                    Pump1Running="{Binding Pump1Running}"
-                                    Pump2Running="{Binding Pump2Running}"
-                                    Pump3Running="{Binding Pump3Running}"
-                                    Pump4Running="{Binding Pump4Running}"
-                                    Pump5Running="{Binding Pump5Running}"
-                                    Fan1Running="{Binding Fan1Running}"
-                                    Fan2Running="{Binding Fan2Running}"
-                                    Valve1Status="{Binding Valve1Status}"
-                                    Valve2Status="{Binding Valve2Status}"
-                                    Valve3Status="{Binding Valve3Status}"
-                                    Valve4Status="{Binding Valve4Status}"
+                                    Profile="{Binding Profile}"
+                                    AnalogValues="{Binding AnalogValues}"
+                                    DigitalValues="{Binding DigitalValues}"
                                     IsInflowRunning="{Binding IsInflowRunning}"
                                     IsOutflowRunning="{Binding IsOutflowRunning}"
                                     HasAlarm="{Binding HasAlarm}"

+ 99 - 0
src/YZWater.Core/ViewModels/ViewAViewModel.cs

@@ -16,6 +16,21 @@ public partial class ViewAViewModel : TranslatableViewModelBase
     private System.Timers.Timer? _clockTimer;
     private bool _disposed;
 
+    // ═══════════════════════════════════════════════
+    //  动态模式(Profile + 字典驱动 2D/3D 控件)
+    // ═══════════════════════════════════════════════
+
+    /// <summary>当前项目档案(供 2D/3D 控件动态渲染)</summary>
+    public ProjectProfile? Profile => ProjectService.Current;
+
+    /// <summary>模拟量字典 — 键为 "设备名.属性"</summary>
+    [ObservableProperty] private Dictionary<string, float> _analogValues = new();
+    private HashSet<string> _analogKeys = new();
+
+    /// <summary>数字量字典 — 键为 "设备名.属性"</summary>
+    [ObservableProperty] private Dictionary<string, bool> _digitalValues = new();
+    private HashSet<string> _digitalKeys = new();
+
     // ═══════════════════════════════════════════════
     //  水箱液位
     // ═══════════════════════════════════════════════
@@ -340,6 +355,90 @@ public partial class ViewAViewModel : TranslatableViewModelBase
 
         // 报警由 AlarmService 统一检测,通过 AlarmStateChanged 事件更新
         UpdateAlarmStateFromService();
+
+        // 同步动态字典(供 2D/3D 控件动态渲染)
+        UpdateDynamicDictionaries(data);
+    }
+
+    /// <summary>将 PlcDataModel 同步到 AnalogValues / DigitalValues 字典</summary>
+    private void UpdateDynamicDictionaries(PlcDataModel data)
+    {
+        var profile = ProjectService.Current;
+        if (profile == null) return;
+
+        var analogChanged = false;
+        var digitalChanged = false;
+
+        // 泵
+        foreach (var pump in profile.Pumps)
+        {
+            SetAnalog($"{pump.Name}.Current", data.GetAnalogRegister($"{pump.Name}.Current"), ref analogChanged);
+            SetDigital($"{pump.Name}.Run", data.GetDigitalRegister($"{pump.Name}.Run"), ref digitalChanged);
+            SetDigital($"{pump.Name}.Fault", data.GetDigitalRegister($"{pump.Name}.Fault"), ref digitalChanged);
+        }
+
+        // 水箱
+        foreach (var tank in profile.Tanks)
+        {
+            SetAnalog($"{tank.Name}.Level", data.GetAnalogRegister($"{tank.Name}.Level"), ref analogChanged);
+            for (int i = 1; i <= Math.Max(3, profile.Pumps.Count); i++)
+            {
+                var addr = tank.GetStartPumpLevelAddress(i);
+                if (!string.IsNullOrEmpty(addr))
+                    SetAnalog($"{tank.Name}.StartPump{i}Level", data.GetAnalogRegister($"{tank.Name}.StartPump{i}Level"), ref analogChanged);
+            }
+            SetAnalog($"{tank.Name}.StopLevel", data.GetAnalogRegister($"{tank.Name}.StopLevel"), ref analogChanged);
+            SetAnalog($"{tank.Name}.ProtectionLevel", data.GetAnalogRegister($"{tank.Name}.ProtectionLevel"), ref analogChanged);
+        }
+
+        // 仪表
+        foreach (var gauge in profile.Gauges)
+            SetAnalog($"{gauge.Name}.Value", data.GetAnalogRegister($"{gauge.Name}.Value"), ref analogChanged);
+
+        // 传感器
+        foreach (var sensor in profile.Sensors)
+            SetAnalog($"{sensor.Name}.Value", data.GetAnalogRegister($"{sensor.Name}.Value"), ref analogChanged);
+
+        // 数字量输入
+        foreach (var di in profile.DigitalInputs)
+            SetDigital($"DI.{di.Name}", data.GetDigitalRegister($"DI.{di.Name}"), ref digitalChanged);
+
+        // 数字量输出
+        foreach (var do_ in profile.DigitalOutputs)
+            SetDigital($"DO.{do_.Name}", data.GetDigitalRegister($"DO.{do_.Name}"), ref digitalChanged);
+
+        // 报警
+        SetDigital("Alarm.Active", AlarmService.Instance.HasActiveAlarm, ref digitalChanged);
+
+        // 重建字典(仅在键集合变化时)
+        if (analogChanged && _analogValues.Count != _analogKeys.Count)
+        {
+            _analogKeys = new HashSet<string>(_analogValues.Keys);
+            AnalogValues = new Dictionary<string, float>(_analogValues);
+        }
+        if (digitalChanged && _digitalValues.Count != _digitalKeys.Count)
+        {
+            _digitalKeys = new HashSet<string>(_digitalValues.Keys);
+            DigitalValues = new Dictionary<string, bool>(_digitalValues);
+        }
+    }
+
+    private void SetAnalog(string key, float value, ref bool changed)
+    {
+        if (!_analogValues.TryGetValue(key, out var old) || Math.Abs(old - value) > 0.001f)
+        {
+            _analogValues[key] = value;
+            changed = true;
+        }
+    }
+
+    private void SetDigital(string key, bool value, ref bool changed)
+    {
+        if (!_digitalValues.TryGetValue(key, out var old) || old != value)
+        {
+            _digitalValues[key] = value;
+            changed = true;
+        }
     }
 
     /// <summary>