Explorar o código

手动调光页支持多通道动态管理与操作

重构 LightManualViewModel,新增 Channels 集合及 ChannelItem 内部类,实现全局光源通道的动态加载、亮度调节、开关与保存操作。同步重构 LightManual.xaml,使用 ItemsControl+ScrollViewer 实现多通道卡片式展示和交互,提升页面灵活性与用户体验。
孝锋 徐 hai 8 meses
pai
achega
81e60499f7

+ 155 - 24
TeamAAS-VM/ViewModels/DebugMod/LightManualViewModel.cs

@@ -5,25 +5,34 @@ using Prism.Mvvm;
 using Prism.Regions;
 using System;
 using System.Collections.Generic;
+using System.Collections.ObjectModel;
 using System.Linq;
+using System.Threading.Tasks;
 using TeamAAS_VP.Core;
 using TeamAAS_VP.Data;
 using TeamAAS_VP.Events;
 using TeamAAS_VP.Interfaces;
+using TeamAAS_VP.Models.Lights;
 using TeamAAS_VP.Resources.Languages;
+using TeamAAS_VP.Core.Lights;
 
 namespace TeamAAS_VP.ViewModels.DebugMod
 {
-    public class LightManualViewModel : BindableBase
+    public class LightManualViewModel : BindableBase, INavigationAware
     {
         IContainerProvider _container;
         IEventAggregator _eventAggregator;
+        ILightManagerService _light_manager_service; // fallback
         ILightManagerService _lightManagerService;
         IConfigService _configService;
         ISystemDatabaseService _systemDatabaseService;
 
         #region 属性
-
+        private ObservableCollection<ChannelItem> _Channels = new ObservableCollection<ChannelItem>();
+        public ObservableCollection<ChannelItem> Channels
+        {
+            get => _Channels; set => SetProperty(ref _Channels, value);
+        }
         #endregion
 
         #region 命令
@@ -31,7 +40,6 @@ namespace TeamAAS_VP.ViewModels.DebugMod
         public DelegateCommand LoadedCommand =>
             _LoadedCommand ?? (_LoadedCommand = new DelegateCommand(ExecuteLoadedCommand));
 
-        
         #endregion
 
         #region 事件
@@ -42,6 +50,7 @@ namespace TeamAAS_VP.ViewModels.DebugMod
         {
             _container = container;
             _eventAggregator = ea;
+            _light_manager_service = lightManagerService;
             _lightManagerService = lightManagerService;
             _configService = configService;
             _systemDatabaseService = systemDatabaseService;
@@ -64,43 +73,39 @@ namespace TeamAAS_VP.ViewModels.DebugMod
         #endregion
 
         #region 继承
-        /// <summary>
-        /// 确认导航请求时调用。此方法允许您在导航之前执行一些操作。
-        /// </summary>
-        /// <param name="navigationContext"></param>
-        /// <param name="continuationCallback"></param>
         public void ConfirmNavigationRequest(NavigationContext navigationContext, Action<bool> continuationCallback)
         {
             continuationCallback(true);
         }
 
-        /// <summary>
-        /// 接收导航请求时调用。传入导航参数,包含有关导航目标的信息。
-        /// </summary>
-        /// <param name="navigationContext"></param>
-        /// <exception cref="NotImplementedException"></exception>
         public async void OnNavigatedTo(NavigationContext navigationContext)
         {
-            
+            // load channels from light manager service
+            Channels.Clear();
+            try
+            {
+                var globals = _lightManagerService.GlobalChannels.ToList();
+                foreach (var kv in globals)
+                {
+                    var item = new ChannelItem(kv.Key, (ILightChannel)kv.Value, _lightManagerService, _configService, _eventAggregator);
+                    Channels.Add(item);
+                    await item.InitializeAsync();
+                }
+            }
+            catch (Exception ex)
+            {
+                // ignore or notify
+            }
         }
 
-        /// <summary>
-        /// 是否允许导航到此视图模型。
-        /// </summary>
-        /// <param name="navigationContext"></param>
-        /// <returns></returns>
         public bool IsNavigationTarget(NavigationContext navigationContext)
         {
             return true;
         }
 
-        /// <summary>
-        /// 导航离开此视图模型时调用。您可以在此处执行清理操作或保存状态。
-        /// </summary>
-        /// <param name="navigationContext"></param>
         public void OnNavigatedFrom(NavigationContext navigationContext)
         {
-            
+            // nothing
         }
         #endregion
 
@@ -123,5 +128,131 @@ namespace TeamAAS_VP.ViewModels.DebugMod
                 IsAllowEdit = true;
             }
         }
+
+        // Nested ChannelItem class used as item VM
+        public class ChannelItem : BindableBase
+        {
+            private readonly int _globalId;
+            private readonly ILightChannel _channel;
+            private readonly ILightManagerService _lightManagerService;
+            private readonly IConfigService _configService;
+            private readonly IEventAggregator _eventAggregator;
+
+            public int GlobalId => _globalId;
+
+            private string _Name;
+            public string Name { get => _Name; set => SetProperty(ref _Name, value); }
+
+            private int _PendingBrightness;
+            public int PendingBrightness { get => _PendingBrightness; set => SetProperty(ref _PendingBrightness, value); }
+
+            private int _CurrentBrightness;
+            public int CurrentBrightness { get => _CurrentBrightness; set => SetProperty(ref _CurrentBrightness, value); }
+
+            private bool _IsOn;
+            public bool IsOn { get => _IsOn; set => SetProperty(ref _IsOn, value); }
+
+            public DelegateCommand SaveCommand { get; }
+            public DelegateCommand TurnOnCommand { get; }
+            public DelegateCommand TurnOffCommand { get; }
+
+            public ChannelItem(int globalId, ILightChannel channel, ILightManagerService lightManagerService, IConfigService configService, IEventAggregator eventAggregator)
+            {
+                _globalId = globalId;
+                _channel = channel;
+                _lightManagerService = lightManagerService;
+                _configService = configService;
+                _eventAggregator = eventAggregator;
+                Name = channel?.ChannelName ?? $"Channel {_globalId}";
+                PendingBrightness = 0;
+                CurrentBrightness = 0;
+                IsOn = false;
+
+                SaveCommand = new DelegateCommand(async () => await SaveAsync());
+                TurnOnCommand = new DelegateCommand(async () => await TurnOnAsync());
+                TurnOffCommand = new DelegateCommand(async () => await TurnOffAsync());
+            }
+
+            public async Task InitializeAsync()
+            {
+                try
+                {
+                    if (_channel != null)
+                    {
+                        var b = await _channel.GetBrightnessAsync();
+                        CurrentBrightness = b;
+                        PendingBrightness = b;
+                        IsOn = await _channel.GetStatusAsync();
+                    }
+                }
+                catch
+                {
+                }
+            }
+
+            private async Task SaveAsync()
+            {
+                try
+                {
+                    var success = await _lightManagerService.SetGlobalChannelBrightnessAsync(_globalId, PendingBrightness);
+                    if (success)
+                    {
+                        CurrentBrightness = PendingBrightness;
+                        IsOn = PendingBrightness > 0;
+                        // also save as default in config
+                        _configService.UpdateChannelDefaultBrightness(_globalId, PendingBrightness);
+                        _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"保存完成: {Name} -> {PendingBrightness}", Duration = 1 });
+                    }
+                    else
+                    {
+                        _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"保存失败: {Name}", Duration = 1 });
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"保存异常: {ex.Message}", Duration = 1 });
+                }
+            }
+
+            private async Task TurnOnAsync()
+            {
+                try
+                {
+                    var success = await _lightManagerService.TurnOnGlobalChannelAsync(_globalId);
+                    if (success)
+                    {
+                        IsOn = true;
+                        // refresh brightness
+                        var b = await _channel.GetBrightnessAsync();
+                        PendingBrightness = b;
+                        CurrentBrightness = b;
+                        _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"打开通道: {Name}", Duration = 1 });
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"打开异常: {ex.Message}", Duration = 1 });
+                }
+            }
+
+            private async Task TurnOffAsync()
+            {
+                try
+                {
+                    var success = await _lightManagerService.TurnOffGlobalChannelAsync(_globalId);
+                    if (success)
+                    {
+                        IsOn = false;
+                        PendingBrightness = 0;
+                        CurrentBrightness = 0;
+                        _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"关闭通道: {Name}", Duration = 1 });
+                    }
+                }
+                catch (Exception ex)
+                {
+                    _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = $"关闭异常: {ex.Message}", Duration = 1 });
+                }
+            }
+        }
     }
 }

+ 36 - 3
TeamAAS-VM/Views/DebugMod/LightManual.xaml

@@ -25,8 +25,41 @@
             <b:InvokeCommandAction Command="{Binding LoadedCommand}" />
         </b:EventTrigger>
     </b:Interaction.Triggers>
-    <Grid VerticalAlignment="Center"
-          IsEnabled="{Binding IsAllowEdit}">
-            
+    <Grid VerticalAlignment="Top" IsEnabled="{Binding IsAllowEdit}">
+        <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
+            <ItemsControl ItemsSource="{Binding Channels}">
+                <ItemsControl.ItemTemplate>
+                    <DataTemplate>
+                        <Border BorderBrush="Gray" BorderThickness="1" Margin="6" Padding="8" CornerRadius="6">
+                            <StackPanel Orientation="Vertical">
+                                <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
+                                    <TextBlock Text="通道:" FontWeight="Bold" Margin="0,0,6,0" />
+                                    <TextBlock Text="{Binding GlobalId}" Width="40" />
+                                    <TextBlock Text="名称:" FontWeight="Bold" Margin="10,0,6,0" />
+                                    <TextBlock Text="{Binding Name}" />
+                                </StackPanel>
+
+                                <StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="0,8,0,0">
+                                    <TextBlock Text="亮度:" VerticalAlignment="Center" Margin="0,0,6,0" />
+                                    <Slider Width="280" Minimum="0" Maximum="255" Value="{Binding PendingBrightness,Mode=TwoWay}" SmallChange="1" LargeChange="10" />
+                                    <TextBlock Text="{Binding PendingBrightness}" Width="40" Margin="6,0,0,0" VerticalAlignment="Center" />
+                                </StackPanel>
+
+                                <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,8,0,0">
+                                    <Button Content="打开" Command="{Binding TurnOnCommand}" Margin="0,0,8,0" />
+                                    <Button Content="关闭" Command="{Binding TurnOffCommand}" Margin="0,0,8,0" />
+                                    <Button Content="保存" Command="{Binding SaveCommand}" />
+                                </StackPanel>
+                            </StackPanel>
+                        </Border>
+                    </DataTemplate>
+                </ItemsControl.ItemTemplate>
+                <ItemsControl.ItemsPanel>
+                    <ItemsPanelTemplate>
+                        <StackPanel />
+                    </ItemsPanelTemplate>
+                </ItemsControl.ItemsPanel>
+            </ItemsControl>
+        </ScrollViewer>
     </Grid>
 </UserControl>