Browse Source

新增光源控制器配置功能及界面支持

本次提交实现了系统设置中光源控制器的可视化配置与管理,包括:
- 在 IConfigService/ConfigService 中增加光源控制器及通道的增删查改接口与实现,支持持久化存储;
- SettingViewModel 增加光源控制器列表、选中项及相关命令,支持界面操作;
- SettingView.xaml 新增“光源控制器”Tab页,支持树形列表、参数编辑、串口/TCP配置等;
- 多语言资源增加相关本地化字符串;
- 统一和优化Tab页头部样式,相关代码细节完善。

该功能提升了系统对光源硬件的管理能力和易用性。
孝锋 徐 8 months ago
parent
commit
c392a38ace

+ 64 - 0
TeamAAS-VM/Interfaces/IConfigService.cs

@@ -5,6 +5,7 @@ using System.Threading.Tasks;
 using TeamAAS_VP.Models;
 using TeamAAS_VP.Models.Calibration;
 using TeamAAS_VP.Models.Feeder;
+using TeamAAS_VP.Models.Lights;
 
 namespace TeamAAS_VP.Interfaces
 {
@@ -312,6 +313,69 @@ namespace TeamAAS_VP.Interfaces
         /// <returns></returns>
         FeederClearWork GetClearanceTaskByNumber(int taskNumber);
 
+        // Light controllers and channels
+
+        /// <summary>
+        /// 获取所有已注册的灯光控制器信息的只读集合。
+        /// </summary>
+        /// <returns>灯光控制器信息的只读集合快照。</returns>
+        IReadOnlyCollection<LightControllerConfig> GetAllLightControllers();
+
+        /// <summary>
+        /// 根据标识获取单个灯光控制器信息。
+        /// </summary>
+        /// <param name="id">灯光控制器的唯一标识符。</param>
+        /// <returns>对应的 <see cref="LightControllerConfig"/> 实例;若未找到则返回 null。</returns>
+        LightControllerConfig GetLightController(int id);
+
+        /// <summary>
+        /// 新增或更新指定的灯光控制器信息。
+        /// </summary>
+        /// <param name="controller">要新增或更新的灯光控制器信息,不能为 null。</param>
+        /// <exception cref="ArgumentNullException">当 <paramref name="controller"/> 为 null 时抛出。</exception>
+        LightControllerConfig AddOrUpdateLightController(LightControllerConfig controller);
+
+        /// <summary>
+        /// 移除指定标识的灯光控制器信息。
+        /// </summary>
+        /// <param name="id">要移除的灯光控制器的唯一标识符。</param>
+        /// <returns>如果找到并移除成功则返回 true;否则返回 false。</returns>
+        bool RemoveLightController(int id);
+
+        /// <summary>
+        /// 判断是否包含指定标识的灯光控制器配置。
+        /// </summary>
+        /// <param name="id">灯光控制器唯一标识符。</param>
+        /// <returns>存在则返回 true,否则返回 false。</returns>
+        bool ContainsLightController(int id);
+
+        /// <summary>
+        /// 获取所有已注册的灯光通道信息的只读集合。
+        /// </summary>
+        /// <returns>灯光通道信息的只读集合快照。</returns>
+        IReadOnlyCollection<ChannelConfig> GetAllLightChannels();
+
+        /// <summary>
+        /// 根据全局索引获取单个灯光通道信息。
+        /// </summary>
+        /// <param name="globalIndex">灯光通道的全局索引。</param>
+        /// <returns>对应的 <see cref="ChannelConfig"/> 实例;若未找到则返回 null。</returns>
+        ChannelConfig GetLightChannelByGlobalIndex(int globalIndex);
+
+        /// <summary>
+        /// 判断是否包含指定全局索引的灯光通道配置。
+        /// </summary>
+        /// <param name="globalIndex">灯光通道的全局索引。</param>
+        /// <returns>存在则返回 true,否则返回 false。</returns>
+        bool ContainsLightChannelByGlobalIndex(int globalIndex);
+
+        /// <summary>
+        /// 更新指定灯光通道的默认亮度值并保存到持久化存储。
+        /// </summary>
+        /// <param name="globalIndex">灯光通道的全局索引。</param>
+        /// <param name="brightness">新的默认亮度值,范围应在合适的区间内。</param>
+        /// <returns>如果找到并更新成功则返回 true;否则返回 false。</returns>
+        bool UpdateChannelDefaultBrightness(int globalIndex, int brightness);
 
     }
 }

+ 45 - 0
TeamAAS-VM/Resources/Languages/Lang.Designer.cs

@@ -1329,6 +1329,24 @@ namespace TeamAAS_VP.Resources.Languages {
             }
         }
         
+        /// <summary>
+        ///   查找类似 光源控制器 的本地化字符串。
+        /// </summary>
+        public static string 光源控制器 {
+            get {
+                return ResourceManager.GetString("光源控制器", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   查找类似 光源控制器列表 的本地化字符串。
+        /// </summary>
+        public static string 光源控制器列表 {
+            get {
+                return ResourceManager.GetString("光源控制器列表", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   查找类似 全局参数个数 的本地化字符串。
         /// </summary>
@@ -1995,6 +2013,15 @@ namespace TeamAAS_VP.Resources.Languages {
             }
         }
         
+        /// <summary>
+        ///   查找类似 增加光源控制器 的本地化字符串。
+        /// </summary>
+        public static string 增加光源控制器 {
+            get {
+                return ResourceManager.GetString("增加光源控制器", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   查找类似 增加机器人 的本地化字符串。
         /// </summary>
@@ -4326,6 +4353,15 @@ namespace TeamAAS_VP.Resources.Languages {
             }
         }
         
+        /// <summary>
+        ///   查找类似 移除光源控制器 的本地化字符串。
+        /// </summary>
+        public static string 移除光源控制器 {
+            get {
+                return ResourceManager.GetString("移除光源控制器", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   查找类似 移除完成! 的本地化字符串。
         /// </summary>
@@ -5478,6 +5514,15 @@ namespace TeamAAS_VP.Resources.Languages {
             }
         }
         
+        /// <summary>
+        ///   查找类似 通道数 的本地化字符串。
+        /// </summary>
+        public static string 通道数 {
+            get {
+                return ResourceManager.GetString("通道数", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   查找类似 速度 的本地化字符串。
         /// </summary>

+ 15 - 0
TeamAAS-VM/Resources/Languages/Lang.resx

@@ -2063,4 +2063,19 @@
   <data name="节点头" xml:space="preserve">
     <value>节点头</value>
   </data>
+  <data name="增加光源控制器" xml:space="preserve">
+    <value>增加光源控制器</value>
+  </data>
+  <data name="移除光源控制器" xml:space="preserve">
+    <value>移除光源控制器</value>
+  </data>
+  <data name="光源控制器列表" xml:space="preserve">
+    <value>光源控制器列表</value>
+  </data>
+  <data name="通道数" xml:space="preserve">
+    <value>通道数</value>
+  </data>
+  <data name="光源控制器" xml:space="preserve">
+    <value>光源控制器</value>
+  </data>
 </root>

+ 194 - 1
TeamAAS-VM/Services/ConfigService.cs

@@ -11,6 +11,7 @@ using TeamAAS_VP.Interfaces;
 using TeamAAS_VP.Models;
 using TeamAAS_VP.Models.Calibration;
 using TeamAAS_VP.Models.Feeder;
+using TeamAAS_VP.Models.Lights;
 
 namespace TeamAAS_VP.Services
 {
@@ -31,6 +32,8 @@ namespace TeamAAS_VP.Services
             public static readonly string SystemConfigurationPath = "..//Config//SystemConfiguration.cfg";
             // Feeder清料任务配置路径
             public static readonly string FeederClearanceTasksConfigurationPath = "..//Config//FeederClearanceTasksConfiguration.cfg";
+            // 光源控制器配置路径
+            public static readonly string LightControllersConfigurationPath = "..//Config//LightControllersConfiguration.cfg";
         }
 
         private readonly object _sync = new object();
@@ -41,6 +44,8 @@ namespace TeamAAS_VP.Services
         private BgTcpIP BgCommunicate { get; set; }
         private BgModbusTcp BgModbusCommunicate { get; set; }
         private ObservableCollection<FeederClearWork> FeederClearanceTasks { get; set; }
+        // 光源控制器配置
+        private ObservableCollection<LightControllerConfig> LightControllers { get; set; }
 
         public ConfigService()
         {
@@ -105,6 +110,17 @@ namespace TeamAAS_VP.Services
                     // 读取 Feeder清料任务 配置
                     FeederClearanceTasks = FileHelper.ReadJsonFile<ObservableCollection<FeederClearWork>>(ConfigPaths.FeederClearanceTasksConfigurationPath);
                 }
+
+                // 读取光源控制器配置
+                if (!File.Exists(ConfigPaths.LightControllersConfigurationPath))
+                {
+                    LightControllers = new ObservableCollection<LightControllerConfig>();
+                    FileHelper.WriteJsonFile(LightControllers, ConfigPaths.LightControllersConfigurationPath);
+                }
+                else
+                {
+                    LightControllers = FileHelper.ReadJsonFile<ObservableCollection<LightControllerConfig>>(ConfigPaths.LightControllersConfigurationPath);
+                }
             }
         }
 
@@ -123,6 +139,7 @@ namespace TeamAAS_VP.Services
                 FileHelper.WriteJsonFile(Plcs, ConfigPaths.PlcConfigurationPath);
                 FileHelper.WriteJsonFile(BgCommunicate, ConfigPaths.BgTcpIpConfigurationPath);
                 FileHelper.WriteJsonFile(BgModbusCommunicate, ConfigPaths.BgModbusTcpConfigurationPath);
+                FileHelper.WriteJsonFile(LightControllers, ConfigPaths.LightControllersConfigurationPath);
             }
         }
 
@@ -273,7 +290,7 @@ namespace TeamAAS_VP.Services
         {
             lock (_sync)
             {
-                var robot = Robots.FirstOrDefault(r=> r.Id == id);
+                var robot = Robots.FirstOrDefault(r => r.Id == id);
                 if (robot != null)
                 {
                     return robot.StepDistance;
@@ -543,6 +560,182 @@ namespace TeamAAS_VP.Services
         }
         #endregion
 
+        #region Light controllers and channels
+
+        /// <summary>
+        /// 获取所有光源控制器配置的只读集合。
+        /// 线程安全:在内部使用 <see cref="_sync"/> 进行锁定以保证并发访问安全。
+        /// </summary>
+        /// <returns>按当前内存中存储顺序返回的只读 <see cref="LightControllerConfig"/> 集合。</returns>
+        public IReadOnlyCollection<LightControllerConfig> GetAllLightControllers()
+        {
+            lock (_sync) { return LightControllers.ToList().AsReadOnly(); }
+        }
+
+        /// <summary>
+        /// 根据控制器标识获取单个光源控制器配置。
+        /// 线程安全:该方法对内存集合进行只读访问并在内部加锁。
+        /// </summary>
+        /// <param name="id">控制器的整数标识(Id)。</param>
+        /// <returns>匹配的 <see cref="LightControllerConfig"/> 实例,找不到则返回 <c>null</c>。</returns>
+        public LightControllerConfig GetLightController(int id)
+        {
+            lock (_sync) { return LightControllers.FirstOrDefault(c => c.Id == id); }
+        }
+
+        /// <summary>
+        /// 新增或更新光源控制器配置。
+        /// - 若 <paramref name="controller"/> 为 <c>null</c> 返回 <c>null</c>。
+        /// - 更新时以 Id 匹配现有项并替换。
+        /// - 新增时分配连续的控制器 Id,并为控制器内的每个通道分配全局通道编号(GlobalIndex)。
+        /// 线程安全:在内部使用 <see cref="_sync"/> 锁定集合。
+        /// </summary>
+        /// <param name="controller">要添加或更新的 <see cref="LightControllerConfig"/> 实例。</param>
+        /// <returns>已添加或更新的 <see cref="LightControllerConfig"/> 实例;输入为 <c>null</c> 时返回 <c>null</c>。</returns>
+        /// <exception cref="ArgumentException">当要添加/更新的控制器名称与现有其他控制器重复时抛出。</exception>
+        public LightControllerConfig AddOrUpdateLightController(LightControllerConfig controller)
+        {
+            if (controller == null) return null;
+            lock (_sync)
+            {
+                // 名称不得与其他控制器重复(同名但不同 Id 不允许)
+                if (LightControllers.Any(c => c.Name == controller.Name && c.Id != controller.Id))
+                    throw new ArgumentException("Controller name must be unique");
+
+                var exist = LightControllers.FirstOrDefault(c => c.Id == controller.Id);
+                if (exist != null)
+                {
+                    // 更新现有控制器(按索引替换)
+                    var idx = LightControllers.IndexOf(exist);
+                    LightControllers[idx] = controller;
+                }
+                else
+                {
+                    // 新增控制器
+                    // 分配控制器编号为当前最大 Id + 1(若集合为空则为 1)
+                    controller.Id = LightControllers.Count > 0 ? LightControllers.Max(c => c.Id) + 1 : 1;
+
+                    // 计算下一个全局通道索引:在所有已存在控制器的通道 GlobalIndex 上取最大值并加1
+                    int nextGlobal = 0;
+                    if (LightControllers.SelectMany(c => c.ChannelConfigs).Any())
+                    {
+                        nextGlobal = LightControllers.SelectMany(c => c.ChannelConfigs).Max(ch => ch.GlobalIndex) + 1;
+                    }
+
+                    // 遍历新增控制器的通道,若通道的 GlobalIndex 无效(<0)或与现有通道冲突,则重新分配
+                    for (int i = 0; i < controller.ChannelConfigs.Count; i++)
+                    {
+                        var ch = controller.ChannelConfigs[i];
+                        if (ch.GlobalIndex < 0 || LightControllers.SelectMany(c => c.ChannelConfigs).Any(existingCh => existingCh.GlobalIndex == ch.GlobalIndex))
+                        {
+                            ch.GlobalIndex = nextGlobal;
+                            nextGlobal++;
+                        }
+                    }
+
+                    LightControllers.Add(controller);
+                }
+            }
+            // 持久化更新后的光源控制器配置
+            FileHelper.WriteJsonFile(LightControllers, ConfigPaths.LightControllersConfigurationPath);
+            return controller;
+        }
+
+        /// <summary>
+        /// 根据 Id 移除光源控制器配置。
+        /// - 移除后会对剩余控制器重新编号(从1开始连续编号)。
+        /// 线程安全:在方法体内对集合进行锁定。
+        /// </summary>
+        /// <param name="id">要移除的控制器 Id。</param>
+        /// <returns>如果成功移除返回 <c>true</c>,否则返回 <c>false</c>(比如未找到该 Id)。</returns>
+        public bool RemoveLightController(int id)
+        {
+            bool result = false;
+            lock (_sync)
+            {
+                var e = LightControllers.FirstOrDefault(c => c.Id == id);
+                if (e != null)
+                    result = LightControllers.Remove(e);
+
+                // 重新按 Id 排序并从 1 开始重新编号,以保持连续性
+                int no = 1;
+                var sorted = LightControllers.OrderBy(c => c.Id).ToList();
+                foreach (var c in sorted)
+                {
+                    c.Id = no;
+                    no++;
+                }
+                LightControllers.Clear();
+                foreach (var c in sorted)
+                {
+                    LightControllers.Add(c);
+                }
+            }
+            FileHelper.WriteJsonFile(LightControllers, ConfigPaths.LightControllersConfigurationPath);
+            return result;
+        }
+
+        /// <summary>
+        /// 判断是否包含指定 Id 的光源控制器。
+        /// 线程安全:在内部使用锁定进行检查。
+        /// </summary>
+        /// <param name="id">控制器 Id。</param>
+        /// <returns>存在返回 <c>true</c>,否则返回 <c>false</c>。</returns>
+        public bool ContainsLightController(int id) { lock (_sync) { return LightControllers.Any(c => c.Id == id); } }
+
+        /// <summary>
+        /// 获取所有光源通道的只读集合,按 GlobalIndex 升序返回。
+        /// 线程安全:方法内部加锁以保证集合读取的一致性。
+        /// </summary>
+        /// <returns>按 GlobalIndex 排序的 <see cref="ChannelConfig"/> 只读集合。</returns>
+        public IReadOnlyCollection<ChannelConfig> GetAllLightChannels()
+        {
+            lock (_sync) { return LightControllers.SelectMany(c => c.ChannelConfigs).OrderBy(ch => ch.GlobalIndex).ToList().AsReadOnly(); }
+        }
+
+        /// <summary>
+        /// 根据全局通道索引获取单个通道配置。
+        /// 线程安全:在内部加锁。
+        /// </summary>
+        /// <param name="globalIndex">通道的全局索引(GlobalIndex)。</param>
+        /// <returns>匹配的 <see cref="ChannelConfig"/> 实例,找不到则返回 <c>null</c>。</returns>
+        public ChannelConfig GetLightChannelByGlobalIndex(int globalIndex)
+        {
+            lock (_sync) { return LightControllers.SelectMany(c => c.ChannelConfigs).FirstOrDefault(ch => ch.GlobalIndex == globalIndex); }
+        }
+
+        /// <summary>
+        /// 判断是否存在指定全局通道索引的通道配置。
+        /// 线程安全:在内部使用锁定。
+        /// </summary>
+        /// <param name="globalIndex">全局通道索引。</param>
+        /// <returns>存在返回 <c>true</c>,否则返回 <c>false</c>。</returns>
+        public bool ContainsLightChannelByGlobalIndex(int globalIndex)
+        {
+            lock (_sync) { return LightControllers.SelectMany(c => c.ChannelConfigs).Any(ch => ch.GlobalIndex == globalIndex); }
+        }
+
+        /// <summary>
+        /// 更新指定全局通道的默认亮度(DefaultBrightness)。
+        /// 线程安全:在内部锁定集合并在更新后持久化配置。
+        /// </summary>
+        /// <param name="globalIndex">目标通道的全局索引(GlobalIndex)。</param>
+        /// <param name="brightness">要设置的亮度值(单位由 <see cref="ChannelConfig"/> 定义)。</param>
+        /// <returns>更新成功返回 <c>true</c>;找不到对应通道返回 <c>false</c>。</returns>
+        public bool UpdateChannelDefaultBrightness(int globalIndex, int brightness)
+        {
+            lock (_sync)
+            {
+                var ch = LightControllers.SelectMany(c => c.ChannelConfigs).FirstOrDefault(x => x.GlobalIndex == globalIndex);
+                if (ch == null) return false;
+                ch.DefaultBrightness = brightness;
+                FileHelper.WriteJsonFile(LightControllers, ConfigPaths.LightControllersConfigurationPath);
+                return true;
+            }
+        }
+
+        #endregion
+
         public void Dispose()
         {
             SaveAll();

+ 77 - 0
TeamAAS-VM/ViewModels/SettingViewModel.cs

@@ -20,10 +20,12 @@ using Team.FFFeederService.Interfaces;
 using TeamAAS_VP.Controls;
 using TeamAAS_VP.Core;
 using TeamAAS_VP.Core.Cameras;
+using TeamAAS_VP.Core.Lights;
 using TeamAAS_VP.Enums;
 using TeamAAS_VP.Events;
 using TeamAAS_VP.Interfaces;
 using TeamAAS_VP.Models;
+using TeamAAS_VP.Models.Lights;
 using TeamAAS_VP.Resources.Languages;
 using TeamAAS_VP.Services;
 using TeamAAS_VP.ViewModels.User;
@@ -41,6 +43,7 @@ namespace TeamAAS_VP.ViewModels
         IConfigService _configService;
         IRobotService _robotService;
         ICameraService _cameraService;
+        IFeederService _feeder_service;
         IFeederService _feederService;
         IPlcService _plcService;
         IProductService _productService;
@@ -290,6 +293,20 @@ namespace TeamAAS_VP.ViewModels
             set { SetProperty(ref _BgTcp, value); }
         }
 
+        private ObservableCollection<LightControllerConfig> _LightControllerList;
+        public ObservableCollection<LightControllerConfig> LightControllerList
+        {
+            get { return _LightControllerList; }
+            set { SetProperty(ref _LightControllerList, value); }
+        }
+
+        private LightControllerConfig _SelectLightController;
+        public LightControllerConfig SelectLightController
+        {
+            get { return _SelectLightController; }
+            set { SetProperty(ref _SelectLightController, value); }
+        }
+
         #endregion
 
         #region 命令
@@ -354,7 +371,14 @@ namespace TeamAAS_VP.ViewModels
         public DelegateCommand SavePlcsCommand =>
             _SavePlcsCommand ?? (_SavePlcsCommand = new DelegateCommand(ExecuteSavePlcsCommand));
 
+        private DelegateCommand _AddLightControllerCommand;
+        public DelegateCommand AddLightControllerCommand => _AddLightControllerCommand ?? (_AddLightControllerCommand = new DelegateCommand(ExecuteAddLightControllerCommand));
 
+        private DelegateCommand _RemoveLightControllerCommand;
+        public DelegateCommand RemoveLightControllerCommand => _RemoveLightControllerCommand ?? (_RemoveLightControllerCommand = new DelegateCommand(ExecuteRemoveLightControllerCommand));
+
+        private DelegateCommand _SaveLightControllersCommand;
+        public DelegateCommand SaveLightControllersCommand => _SaveLightControllersCommand ?? (_SaveLightControllersCommand = new DelegateCommand(ExecuteSaveLightControllersCommand));
         #endregion
 
         #region 事件
@@ -845,6 +869,48 @@ namespace TeamAAS_VP.ViewModels
         }
         #endregion
 
+        #region Light handlers
+        void ExecuteAddLightControllerCommand()
+        {
+            // create default controller
+            var ctrl = new LightControllerConfig()
+            {
+                Name = $"Controller {(LightControllerList?.Count ?? 0) + 1}",
+                LightModel = LightModel.KCS_KDC_12V60W_4T
+            };
+            LightControllerList.Add(ctrl);
+            _configService.AddOrUpdateLightController(ctrl);
+            SelectLightController = ctrl;
+            _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "添加完成", Duration = 1 });
+        }
+
+        void ExecuteRemoveLightControllerCommand()
+        {
+            if (SelectLightController == null) return;
+            if (MessageBox.Show("是否移除光源控制器?", "AAS", MessageBoxButton.YesNo, MessageBoxImage.Question) == MessageBoxResult.Yes)
+            {
+                _configService.RemoveLightController(SelectLightController.Id);
+                LightControllerList.Remove(SelectLightController);
+                SelectLightController = null;
+                _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "移除完成", Duration = 1 });
+            }
+        }
+
+        async void ExecuteSaveLightControllersCommand()
+        {
+            var view = new ShowMessage($"AAS", "是否保存光源控制器配置?");
+            var result = await DialogHost.Show(view, "RootDialog", null, null, null);
+            if (result != null && result is bool && (bool)result)
+            {
+                foreach (var item in LightControllerList)
+                {
+                    _configService.AddOrUpdateLightController(item);
+                }
+                _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = "完成", Duration = 1 });
+            }
+        }
+        #endregion
+
         #region 通讯
         async void ExecuteSaveCommunicateCommand(string parm)
         {
@@ -1066,6 +1132,17 @@ namespace TeamAAS_VP.ViewModels
                 }
             }
 
+            // load light controllers
+            if (LightControllerList == null)
+            {
+                LightControllerList = new ObservableCollection<LightControllerConfig>();
+                var controllers = _configService.GetAllLightControllers();
+                foreach (var ctrl in controllers)
+                {
+                    LightControllerList.Add(ctrl);
+                }
+            }
+
             if (BgTcp == null)
             {
                 BgTcp = _configService.GetBgTcp();

+ 392 - 56
TeamAAS-VM/Views/SettingView.xaml

@@ -14,6 +14,8 @@
              xmlns:ext="clr-namespace:TeamAAS_VP.Extension"
              xmlns:c="clr-namespace:TeamAAS_VP.ValueConverter"
              xmlns:lex="http://wpflocalizeextension.codeplex.com"
+             xmlns:coreLights="clr-namespace:TeamAAS_VP.Core.Lights"
+             xmlns:io="clr-namespace:System.IO.Ports;assembly=System"
              lex:ResxLocalizationProvider.DefaultAssembly="TeamAAS-VP"
              lex:ResxLocalizationProvider.DefaultDictionary="Lang"
              lex:LocalizeDictionary.DesignCulture="zh-CN"
@@ -25,6 +27,7 @@
              x:Class="TeamAAS_VP.Views.SettingView"
              prism:ViewModelLocator.AutoWireViewModel="True"
              FontFamily="{DynamicResource DefaultFont}">
+
     <b:Interaction.Triggers>
         <b:EventTrigger EventName="Loaded">
             <b:InvokeCommandAction Command="{Binding LoadedCommand}" />
@@ -36,6 +39,19 @@
         <c:RobotBrandToVisibiltyConverter x:Key="RobotBrandToVisibiltyConverterInverse"
                                           Inverse="True" />
         <c:PlcIdToNameConverter x:Key="PlcIdToNameConverter" />
+
+        <!-- Header text style: no wrap and trim with ellipsis, allows header to size to content -->
+        <Style x:Key="TabHeaderTextBlockStyle"
+               TargetType="TextBlock">
+            <Setter Property="TextWrapping"
+                    Value="NoWrap" />
+            <Setter Property="TextTrimming"
+                    Value="CharacterEllipsis" />
+            <Setter Property="HorizontalAlignment"
+                    Value="Center" />
+            <Setter Property="VerticalAlignment"
+                    Value="Center" />
+        </Style>
     </UserControl.Resources>
 
     <Grid>
@@ -52,16 +68,15 @@
             <!--相机配置-->
             <TabItem Margin="5,0">
                 <TabItem.Header>
-                    <StackPanel Width="auto"
-                                Height="auto">
+                    <StackPanel HorizontalAlignment="Stretch">
                         <materialDesign:PackIcon Width="24"
                                                  Height="24"
                                                  HorizontalAlignment="Center"
                                                  Kind="CameraPlusOutline" />
-                        <TextBlock HorizontalAlignment="Center"
-                                   TextWrapping="Wrap"
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
                                    FontSize="{DynamicResource Font.Size.Body2}"
-                                   Text="{lex:Loc SettingView_Camera_Text}" />
+                                   Text="{lex:Loc SettingView_Camera_Text}"
+                                   HorizontalAlignment="Stretch" />
                     </StackPanel>
                 </TabItem.Header>
 
@@ -185,15 +200,15 @@
             <!--机器人-->
             <TabItem>
                 <TabItem.Header>
-                    <StackPanel>
+                    <StackPanel HorizontalAlignment="Stretch">
                         <materialDesign:PackIcon Width="24"
                                                  Height="24"
                                                  HorizontalAlignment="Center"
                                                  Kind="RobotIndustrialOutline" />
-                        <TextBlock HorizontalAlignment="Center"
-                                   TextWrapping="Wrap"
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
                                    FontSize="{DynamicResource Font.Size.Body2}"
-                                   Text="{lex:Loc 机器人}" />
+                                   Text="{lex:Loc 机器人}"
+                                   HorizontalAlignment="Stretch" />
                     </StackPanel>
                 </TabItem.Header>
 
@@ -489,9 +504,9 @@
                                       VerticalAlignment="Center"
                                       Visibility="{Binding SelectRobot.RobotBrand,Converter={StaticResource RobotBrandToVisibiltyConverter}}" />
                             <!--编码格式-->
-                            <TextBlock Text="{lex:Loc 编码解码,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
-                                       Grid.Row="7"
+                            <TextBlock Grid.Row="7"
                                        Grid.Column="0"
+                                       Text="{lex:Loc 编码解码,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
                                        Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
                                        FontSize="{DynamicResource Font.Size.Body3}"
                                        HorizontalAlignment="Right"
@@ -535,7 +550,7 @@
                                     </DataTemplate>
                                 </ComboBox.ItemTemplate>
                             </ComboBox>
-                            <ScrollViewer Grid.RowSpan="8"
+                            <!--<ScrollViewer Grid.RowSpan="8"
                                           Grid.Column="2"
                                           HorizontalScrollBarVisibility="Auto"
                                           VerticalScrollBarVisibility="Auto"
@@ -733,7 +748,7 @@
                                              Grid.Column="1"
                                              Text="{Binding SelectRobot.PlcRobotParameter.CommandParameter.JogCmd}" />
                                 </Grid>
-                            </ScrollViewer>
+                            </ScrollViewer>-->
                         </Grid>
                     </ScrollViewer>
                 </Grid>
@@ -743,16 +758,15 @@
             <!--Feeder-->
             <TabItem>
                 <TabItem.Header>
-                    <StackPanel Width="auto"
-                                Height="auto">
+                    <StackPanel HorizontalAlignment="Stretch">
                         <materialDesign:PackIcon Width="24"
                                                  Height="24"
                                                  HorizontalAlignment="Center"
                                                  Kind="Vibrate" />
-                        <TextBlock HorizontalAlignment="Center"
-                                   TextWrapping="Wrap"
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
                                    FontSize="{DynamicResource Font.Size.Body2}"
-                                   Text="Feeder" />
+                                   Text="Feeder"
+                                   HorizontalAlignment="Stretch" />
                     </StackPanel>
                 </TabItem.Header>
 
@@ -1003,16 +1017,15 @@
             <!--PLC-->
             <TabItem>
                 <TabItem.Header>
-                    <StackPanel Width="auto"
-                                Height="auto">
+                    <StackPanel HorizontalAlignment="Stretch">
                         <materialDesign:PackIcon Width="24"
                                                  Height="24"
                                                  HorizontalAlignment="Center"
                                                  Kind="CellphoneLink" />
-                        <TextBlock HorizontalAlignment="Center"
-                                   TextWrapping="Wrap"
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
                                    FontSize="{DynamicResource Font.Size.Body2}"
-                                   Text="PLC" />
+                                   Text="PLC"
+                                   HorizontalAlignment="Stretch" />
                     </StackPanel>
                 </TabItem.Header>
 
@@ -1193,15 +1206,347 @@
                                        HorizontalAlignment="Right"
                                        VerticalAlignment="Center" />
                             <TextBox Grid.Row="4"
+                                     Grid.Column="1"
+                                     FontSize="{DynamicResource Font.Size.Body3}"
+                                     Margin="10,0"
+                                     MinWidth="80"
+                                     TextAlignment="Center"
+                                     HorizontalAlignment="Left"
+                                     VerticalAlignment="Center"
+                                     Width="{Binding ElementName=txt_plc_Id,Path=ActualWidth}"
+                                     Text="{Binding SelectPlc.NodeHeader,Mode=TwoWay}" />
+
+                        </Grid>
+                    </ScrollViewer>
+                </Grid>
+            </TabItem>
+
+            <!--光源控制器-->
+            <TabItem>
+                <TabItem.Header>
+                    <StackPanel HorizontalAlignment="Stretch">
+                        <materialDesign:PackIcon Width="24"
+                                                 Height="24"
+                                                 HorizontalAlignment="Center"
+                                                 Kind="TelevisionAmbientLight" />
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
+                                   FontSize="{DynamicResource Font.Size.Body2}"
+                                   Text="{lex:Loc 光源控制器}"
+                                   HorizontalAlignment="Stretch" />
+                    </StackPanel>
+                </TabItem.Header>
+
+                <Grid Margin="16">
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="50" />
+                        <RowDefinition Height="*" />
+                    </Grid.RowDefinitions>
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="auto" />
+                        <ColumnDefinition Width="*" />
+                    </Grid.ColumnDefinitions>
+                    <!--增删改查-->
+                    <StackPanel Grid.ColumnSpan="2"
+                                IsEnabled="{Binding IsAllowEdit}"
+                                Orientation="Horizontal">
+                        <Button Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
+                                ToolTip="{lex:Loc 增加光源控制器}"
+                                Command="{Binding AddLightControllerCommand}">
+                            <materialDesign:PackIcon Kind="Plus" />
+                        </Button>
+
+                        <Button Style="{StaticResource MaterialDesignFloatingActionMiniDarkButton}"
+                                ToolTip="{lex:Loc 移除光源控制器}"
+                                Margin="20,0"
+                                Command="{Binding RemoveLightControllerCommand}">
+                            <materialDesign:PackIcon Kind="DeleteForeverOutline" />
+                        </Button>
+                        <Button Style="{StaticResource MaterialDesignFloatingActionMiniSecondaryDarkButton}"
+                                ToolTip="{lex:Loc 保存}"
+                                Command="{Binding SaveLightControllersCommand}">
+                            <materialDesign:PackIcon Kind="ContentSaveCheck" />
+                        </Button>
+
+                    </StackPanel>
+                    <!--控制器列表-->
+                    <TreeView Grid.Row="1"
+                              Grid.Column="0"
+                              SelectedItemChanged="TreeView_SelectedItemChanged">
+                        <TreeViewItem Header="{lex:Loc 光源控制器列表}"
+                                      FontSize="{DynamicResource Font.Size.Title4}"
+                                      FontWeight="Bold"
+                                      IsExpanded="True"
+                                      ItemsSource="{Binding LightControllerList}">
+                            <TreeViewItem.ItemTemplate>
+                                <HierarchicalDataTemplate>
+                                    <StackPanel Orientation="Vertical">
+                                        <TextBlock FontSize="{DynamicResource Font.Size.Title4}">
+                                            <TextBlock.Text>
+                                                <MultiBinding StringFormat="{}{0}. {1}">
+                                                    <Binding Path="Id" />
+                                                    <Binding Path="Name" />
+                                                </MultiBinding>
+                                            </TextBlock.Text>
+                                        </TextBlock>
+
+                                        <StackPanel Orientation="Horizontal">
+                                            <TextBlock Text="{lex:Loc 型号, Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}"
+                                                       Margin="10,0,0,0" />
+                                            <TextBlock Text="{Binding LightModel,Mode=TwoWay}"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}" />
+                                        </StackPanel>
+                                        <StackPanel Orientation="Horizontal">
+                                            <TextBlock Text="{lex:Loc 通道数, Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}"
+                                                       Margin="10,0,0,0" />
+                                            <TextBlock Text="{Binding ChannelCount,Mode=TwoWay}"
+                                                       Style="{StaticResource MaterialDesignCaptionTextBlock}"
+                                                       FontSize="{DynamicResource Font.Size.Captions3}" />
+                                        </StackPanel>
+                                        <Border Height="2"
+                                                Margin="0"
+                                                BorderThickness="2"
+                                                BorderBrush="Green" />
+                                    </StackPanel>
+                                </HierarchicalDataTemplate>
+                            </TreeViewItem.ItemTemplate>
+                        </TreeViewItem>
+                    </TreeView>
+                    <!--参数详情-->
+                    <ScrollViewer Grid.Row="1"
+                                  IsEnabled="{Binding IsAllowEdit}"
+                                  Grid.Column="1"
+                                  Margin="20"
+                                  HorizontalAlignment="Left"
+                                  VerticalAlignment="Top"
+                                  Visibility="{Binding SelectLightController,Converter={StaticResource ObjectToVisibilityConverter}}">
+                        <Grid>
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="Auto" />
+                                <RowDefinition Height="*" />
+                            </Grid.RowDefinitions>
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="auto" />
+                                <ColumnDefinition Width="*" />
+                            </Grid.ColumnDefinitions>
+
+                            <!-- Id -->
+                            <TextBlock Text="Id: "
+                                       Grid.Row="0"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <TextBlock Text="{Binding SelectLightController.Id}"
+                                       Grid.Row="0"
                                        Grid.Column="1"
-                                       FontSize="{DynamicResource Font.Size.Body3}"
                                        Margin="10,0"
-                                       MinWidth="80"
-                                       TextAlignment="Center"
-                                       HorizontalAlignment="Left"
-                                       VerticalAlignment="Center"
-                                       Width="{Binding ElementName=txt_plc_Id,Path=ActualWidth}"
-                                       Text="{Binding SelectPlc.NodeHeader,Mode=TwoWay}" />
+                                       VerticalAlignment="Center" />
+
+                            <!-- Name -->
+                            <TextBlock Text="{lex:Loc 名称, Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
+                                       Grid.Row="1"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <TextBox Grid.Row="1"
+                                     Grid.Column="1"
+                                     Margin="10,0"
+                                     Text="{Binding SelectLightController.Name,Mode=TwoWay}" />
+
+                            <!-- Model -->
+                            <TextBlock Text="{lex:Loc 型号, Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
+                                       Grid.Row="2"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <ComboBox Grid.Row="2"
+                                      Grid.Column="1"
+                                      Margin="10,0"
+                                      SelectedItem="{Binding SelectLightController.LightModel,Mode=TwoWay}"
+                                      ItemsSource="{ext:EnumBindingSource EnumType=coreLights:LightModel}" />
+
+                            <!-- Channel count -->
+                            <TextBlock Text="{lex:Loc 通道数, Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0}: '}"
+                                       Grid.Row="3"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Center" />
+                            <TextBox Grid.Row="3"
+                                     Grid.Column="1"
+                                     Margin="10,0"
+                                     Text="{Binding SelectLightController.ChannelCount,Mode=TwoWay}"
+                                     IsReadOnly="True" />
+
+                            <!-- Channel configs list -->
+                            <TextBlock Text="{lex:Loc 通道配置}"
+                                       Grid.Row="4"
+                                       Grid.Column="0"
+                                       Style="{StaticResource MaterialDesignSubtitle1TextBlock}"
+                                       HorizontalAlignment="Right"
+                                       VerticalAlignment="Top" />
+                            <ItemsControl Grid.Row="4"
+                                          Grid.Column="1"
+                                          Margin="10,0"
+                                          ItemsSource="{Binding SelectLightController.ChannelConfigs}">
+                                <ItemsControl.ItemTemplate>
+                                    <DataTemplate>
+                                        <StackPanel Orientation="Horizontal"
+                                                    Margin="0,4">
+                                            <TextBlock Text="{Binding LocalIndex}"
+                                                       Width="30"
+                                                       VerticalAlignment="Center" />
+                                            <TextBox Text="{Binding Name,Mode=TwoWay}"
+                                                     Width="180"
+                                                     Margin="6,0" />
+                                            <TextBlock Text="亮度:"
+                                                       VerticalAlignment="Center"
+                                                       Margin="6,0" />
+                                            <TextBox Text="{Binding DefaultBrightness,Mode=TwoWay}"
+                                                     Width="80" />
+                                        </StackPanel>
+                                    </DataTemplate>
+                                </ItemsControl.ItemTemplate>
+                            </ItemsControl>
+
+                            <!-- Serial port config (visible for serial model) -->
+                            <GroupBox Grid.Row="5"
+                                      Grid.ColumnSpan="2"
+                                      Header="串口配置"
+                                      Margin="0,12,0,0">
+                                <GroupBox.Style>
+                                    <Style TargetType="GroupBox">
+                                        <Setter Property="Visibility"
+                                                Value="Collapsed" />
+                                        <Style.Triggers>
+                                            <DataTrigger Binding="{Binding SelectLightController.LightModel}"
+                                                         Value="{x:Static coreLights:LightModel.KCS_KDC_12V60W_4T}">
+                                                <Setter Property="Visibility"
+                                                        Value="Visible" />
+                                            </DataTrigger>
+                                        </Style.Triggers>
+                                    </Style>
+                                </GroupBox.Style>
+                                <Grid Margin="10">
+                                    <Grid.ColumnDefinitions>
+                                        <ColumnDefinition Width="auto" />
+                                        <ColumnDefinition Width="*" />
+                                    </Grid.ColumnDefinitions>
+                                    <Grid.RowDefinitions>
+                                        <RowDefinition Height="Auto" />
+                                        <RowDefinition Height="Auto" />
+                                        <RowDefinition Height="Auto" />
+                                        <RowDefinition Height="Auto" />
+                                        <RowDefinition Height="Auto" />
+                                    </Grid.RowDefinitions>
+                                    <TextBlock Text="PortName:"
+                                               Grid.Row="0"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
+                                    <TextBox Text="{Binding SelectLightController.SerialPortConfig.PortName,Mode=TwoWay}"
+                                             Grid.Row="0"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
+                                    <TextBlock Text="BaudRate:"
+                                               Grid.Row="1"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
+                                    <TextBox Text="{Binding SelectLightController.SerialPortConfig.BaudRate,Mode=TwoWay}"
+                                             Grid.Row="1"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
+                                    <TextBlock Text="Parity:"
+                                               Grid.Row="2"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
+                                    <ComboBox Grid.Row="2"
+                                              Grid.Column="1"
+                                              SelectedItem="{Binding SelectLightController.SerialPortConfig.Parity,Mode=TwoWay}">
+                                        <ComboBoxItem Content="{x:Static io:Parity.None}" />
+                                        <ComboBoxItem Content="{x:Static io:Parity.Odd}" />
+                                        <ComboBoxItem Content="{x:Static io:Parity.Even}" />
+                                        <ComboBoxItem Content="{x:Static io:Parity.Mark}" />
+                                        <ComboBoxItem Content="{x:Static io:Parity.Space}" />
+                                    </ComboBox>
+                                    <TextBlock Text="StopBits:"
+                                               Grid.Row="3"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
+                                    <ComboBox Grid.Row="3"
+                                              Grid.Column="1"
+                                              SelectedItem="{Binding SelectLightController.SerialPortConfig.StopBits,Mode=TwoWay}">
+                                        <ComboBoxItem Content="{x:Static io:StopBits.None}" />
+                                        <ComboBoxItem Content="{x:Static io:StopBits.One}" />
+                                        <ComboBoxItem Content="{x:Static io:StopBits.OnePointFive}" />
+                                        <ComboBoxItem Content="{x:Static io:StopBits.Two}" />
+                                    </ComboBox>
+                                    <TextBlock Text="DataBits:"
+                                               Grid.Row="4"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
+                                    <TextBox Text="{Binding SelectLightController.SerialPortConfig.DataBits,Mode=TwoWay}"
+                                             Grid.Row="4"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
+                                </Grid>
+                            </GroupBox>
+
+                            <!-- TCP config (visible for non-serial models) -->
+                            <GroupBox Grid.Row="5"
+                                      Grid.ColumnSpan="2"
+                                      Header="TCP 配置"
+                                      Margin="0,12,0,0">
+                                <GroupBox.Style>
+                                    <Style TargetType="GroupBox">
+                                        <Setter Property="Visibility"
+                                                Value="Visible" />
+                                        <Style.Triggers>
+                                            <DataTrigger Binding="{Binding SelectLightController.LightModel}"
+                                                         Value="{x:Static coreLights:LightModel.KCS_KDC_12V60W_4T}">
+                                                <Setter Property="Visibility"
+                                                        Value="Collapsed" />
+                                            </DataTrigger>
+                                        </Style.Triggers>
+                                    </Style>
+                                </GroupBox.Style>
+                                <Grid Margin="10">
+                                    <Grid.ColumnDefinitions>
+                                        <ColumnDefinition Width="auto" />
+                                        <ColumnDefinition Width="*" />
+                                    </Grid.ColumnDefinitions>
+                                    <Grid.RowDefinitions>
+                                        <RowDefinition Height="Auto" />
+                                        <RowDefinition Height="Auto" />
+                                    </Grid.RowDefinitions>
+                                    <TextBlock Text="IP:"
+                                               Grid.Row="0"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
+                                    <TextBox Text="{Binding SelectLightController.TcpConfig.IP,Mode=TwoWay}"
+                                             Grid.Row="0"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
+                                    <TextBlock Text="Port:"
+                                               Grid.Row="1"
+                                               Grid.Column="0"
+                                               HorizontalAlignment="Right" />
+                                    <TextBox Text="{Binding SelectLightController.TcpConfig.Port,Mode=TwoWay}"
+                                             Grid.Row="1"
+                                             Grid.Column="1"
+                                             Margin="6,0" />
+                                </Grid>
+                            </GroupBox>
 
                         </Grid>
                     </ScrollViewer>
@@ -1211,16 +1556,15 @@
             <!--通讯-->
             <TabItem>
                 <TabItem.Header>
-                    <StackPanel Width="auto"
-                                Height="auto">
+                    <StackPanel HorizontalAlignment="Stretch">
                         <materialDesign:PackIcon Width="24"
                                                  Height="24"
                                                  HorizontalAlignment="Center"
                                                  Kind="Lan" />
-                        <TextBlock HorizontalAlignment="Center"
-                                   TextWrapping="Wrap"
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
                                    FontSize="{DynamicResource Font.Size.Body2}"
-                                   Text="{lex:Loc 通讯}" />
+                                   Text="{lex:Loc 通讯}"
+                                   HorizontalAlignment="Stretch" />
                     </StackPanel>
                 </TabItem.Header>
                 <Grid Margin="20"
@@ -1450,16 +1794,15 @@
             <!--生产排班-->
             <TabItem>
                 <TabItem.Header>
-                    <StackPanel Width="auto"
-                                Height="auto">
+                    <StackPanel HorizontalAlignment="Stretch">
                         <materialDesign:PackIcon Width="24"
                                                  Height="24"
                                                  HorizontalAlignment="Center"
                                                  Kind="LanConnect" />
-                        <TextBlock HorizontalAlignment="Center"
-                                   TextWrapping="Wrap"
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
                                    FontSize="{DynamicResource Font.Size.Body2}"
-                                   Text="{lex:Loc 生产排班}" />
+                                   Text="{lex:Loc 生产排班}"
+                                   HorizontalAlignment="Stretch" />
                     </StackPanel>
                 </TabItem.Header>
 
@@ -1474,15 +1817,15 @@
             <!--字体-->
             <TabItem>
                 <TabItem.Header>
-                    <StackPanel>
+                    <StackPanel HorizontalAlignment="Stretch">
                         <materialDesign:PackIcon Width="24"
                                                  Height="24"
                                                  HorizontalAlignment="Center"
                                                  Kind="FontSize" />
-                        <TextBlock HorizontalAlignment="Center"
-                                   TextWrapping="Wrap"
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
                                    FontSize="{DynamicResource Font.Size.Body2}"
-                                   Text="{lex:Loc 字体}" />
+                                   Text="{lex:Loc 字体}"
+                                   HorizontalAlignment="Stretch" />
                     </StackPanel>
                 </TabItem.Header>
 
@@ -1639,16 +1982,15 @@
             <!--语言-->
             <TabItem>
                 <TabItem.Header>
-                    <StackPanel Width="auto"
-                                Height="auto">
+                    <StackPanel HorizontalAlignment="Stretch">
                         <materialDesign:PackIcon Width="24"
                                                  Height="24"
                                                  HorizontalAlignment="Center"
                                                  Kind="TranslateVariant" />
-                        <TextBlock HorizontalAlignment="Center"
-                                   TextWrapping="Wrap"
+                        <TextBlock Style="{StaticResource TabHeaderTextBlockStyle}"
                                    FontSize="{DynamicResource Font.Size.Body2}"
-                                   Text="{lex:Loc SettingView_Language_Text}" />
+                                   Text="{lex:Loc SettingView_Language_Text}"
+                                   HorizontalAlignment="Stretch" />
                     </StackPanel>
                 </TabItem.Header>
 
@@ -1709,13 +2051,6 @@
                                         <Setter Property="BorderBrush"
                                                 Value="Green" />
                                     </DataTrigger>
-                                    <!--<DataTrigger Binding="{Binding management.CurrentLanguage}"
-                                                 Value="{x:Static enums:Language.Chinese}">
-                                        <Setter Property="Background"
-                                                Value="#e4ff54" />
-                                        <Setter Property="BorderBrush"
-                                                Value="#e4ff54" />
-                                    </DataTrigger>-->
                                 </Style.Triggers>
                             </Style>
                         </Button.Style>
@@ -1774,6 +2109,7 @@
                     </Button>
                 </StackPanel>
             </TabItem>
+            
         </TabControl>
 
     </Grid>