feat: 增强MQTT服务管理功能并优化设备视图
This commit is contained in:
@@ -28,10 +28,18 @@ public interface IMqttAppService
|
||||
/// </summary>
|
||||
Task UpdateMqttServerAsync(MqttServerDto mqttServerDto);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 异步批量更新MQTT服务器。
|
||||
/// </summary>
|
||||
Task<int> UpdateMqttServersAsync(List<MqttServerDto> mqttServerDtos);
|
||||
|
||||
/// <summary>
|
||||
/// 异步根据ID删除一个MQTT服务器。
|
||||
/// </summary>
|
||||
Task<int> DeleteMqttServerAsync(int id);
|
||||
|
||||
/// <summary>
|
||||
/// 异步批量删除MQTT服务器。
|
||||
/// </summary>
|
||||
Task<bool> DeleteMqttServersAsync(List<int> ids);
|
||||
}
|
||||
@@ -17,15 +17,25 @@ public interface IMqttManagementService
|
||||
/// <summary>
|
||||
/// 异步创建一个新的MQTT服务器。
|
||||
/// </summary>
|
||||
Task<int> CreateMqttServerAsync(MqttServerDto mqttServerDto);
|
||||
Task<MqttServerDto> CreateMqttServerAsync(MqttServerDto mqttServerDto);
|
||||
|
||||
/// <summary>
|
||||
/// 异步更新一个已存在的MQTT服务器。
|
||||
/// </summary>
|
||||
Task UpdateMqttServerAsync(MqttServerDto mqttServerDto);
|
||||
Task<int> UpdateMqttServerAsync(MqttServerDto mqttServerDto);
|
||||
|
||||
/// <summary>
|
||||
/// 异步批量更新MQTT服务器。
|
||||
/// </summary>
|
||||
Task<int> UpdateMqttServersAsync(List<MqttServerDto> mqttServerDtos);
|
||||
|
||||
/// <summary>
|
||||
/// 异步删除一个MQTT服务器。
|
||||
/// </summary>
|
||||
Task DeleteMqttServerAsync(int id);
|
||||
Task<bool> DeleteMqttServerAsync(int id);
|
||||
|
||||
/// <summary>
|
||||
/// 异步批量删除MQTT服务器。
|
||||
/// </summary>
|
||||
Task<bool> DeleteMqttServersAsync(List<int> ids);
|
||||
}
|
||||
@@ -117,4 +117,60 @@ public class MqttAppService : IMqttAppService
|
||||
throw new ApplicationException($"删除MQTT服务器时发生错误,操作已回滚,错误信息:{ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步批量更新MQTT服务器(事务性操作)。
|
||||
/// </summary>
|
||||
/// <param name="mqttServerDtos">要更新的MQTT服务器数据传输对象列表。</param>
|
||||
/// <returns>成功更新的MQTT服务器数量。</returns>
|
||||
/// <exception cref="ApplicationException">如果批量更新MQTT服务器时发生错误。</exception>
|
||||
public async Task<int> UpdateMqttServersAsync(List<MqttServerDto> mqttServerDtos)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _repoManager.BeginTranAsync();
|
||||
var count = 0;
|
||||
foreach (var mqttServerDto in mqttServerDtos)
|
||||
{
|
||||
var mqttServer = await _repoManager.MqttServers.GetByIdAsync(mqttServerDto.Id);
|
||||
if (mqttServer != null)
|
||||
{
|
||||
_mapper.Map(mqttServerDto, mqttServer);
|
||||
await _repoManager.MqttServers.UpdateAsync(mqttServer);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
await _repoManager.CommitAsync();
|
||||
return count;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await _repoManager.RollbackAsync();
|
||||
throw new ApplicationException("批量更新MQTT服务器时发生错误,操作已回滚。", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步批量删除MQTT服务器(事务性操作)。
|
||||
/// </summary>
|
||||
/// <param name="ids">要删除的MQTT服务器ID列表。</param>
|
||||
/// <returns>如果删除成功则为 true,否则为 false。</returns>
|
||||
/// <exception cref="ApplicationException">如果批量删除MQTT服务器时发生错误。</exception>
|
||||
public async Task<bool> DeleteMqttServersAsync(List<int> ids)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (ids == null || !ids.Any()) return true;
|
||||
|
||||
await _repoManager.BeginTranAsync();
|
||||
var result = await _repoManager.MqttServers.DeleteByIdsAsync(ids);
|
||||
await _repoManager.CommitAsync();
|
||||
return result > 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
await _repoManager.RollbackAsync();
|
||||
throw new ApplicationException($"批量删除MQTT服务器时发生错误,操作已回滚,错误信息:{ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Collections.Concurrent;
|
||||
using AutoMapper;
|
||||
using DMS.Application.DTOs;
|
||||
using DMS.Application.Events;
|
||||
using DMS.Application.Interfaces;
|
||||
@@ -15,12 +17,20 @@ public class MqttManagementService : IMqttManagementService
|
||||
private readonly IMqttAppService _mqttAppService;
|
||||
private readonly IAppDataStorageService _appDataStorageService;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IDataProcessingService _dataProcessingService;
|
||||
|
||||
public MqttManagementService(IMqttAppService mqttAppService, IAppDataStorageService appDataStorageService, IEventService eventService)
|
||||
public MqttManagementService(IMqttAppService mqttAppService,
|
||||
IAppDataStorageService appDataStorageService,
|
||||
IEventService eventService,
|
||||
IMapper mapper,
|
||||
IDataProcessingService dataProcessingService)
|
||||
{
|
||||
_mqttAppService = mqttAppService;
|
||||
_appDataStorageService = appDataStorageService;
|
||||
_eventService = eventService;
|
||||
_mapper = mapper;
|
||||
_dataProcessingService = dataProcessingService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -42,7 +52,7 @@ public class MqttManagementService : IMqttManagementService
|
||||
/// <summary>
|
||||
/// 异步创建一个新的MQTT服务器。
|
||||
/// </summary>
|
||||
public async Task<int> CreateMqttServerAsync(MqttServerDto mqttServerDto)
|
||||
public async Task<MqttServerDto> CreateMqttServerAsync(MqttServerDto mqttServerDto)
|
||||
{
|
||||
var result = await _mqttAppService.CreateMqttServerAsync(mqttServerDto);
|
||||
|
||||
@@ -52,42 +62,165 @@ public class MqttManagementService : IMqttManagementService
|
||||
mqttServerDto.Id = result; // 假设返回的ID是新创建的
|
||||
if (_appDataStorageService.MqttServers.TryAdd(mqttServerDto.Id, mqttServerDto))
|
||||
{
|
||||
_eventService.RaiseMqttServerChanged(this, new MqttServerChangedEventArgs(ActionChangeType.Added, mqttServerDto));
|
||||
_eventService.RaiseMqttServerChanged(
|
||||
this, new MqttServerChangedEventArgs(ActionChangeType.Added, mqttServerDto));
|
||||
}
|
||||
}
|
||||
|
||||
return mqttServerDto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步更新一个已存在的MQTT服务器。
|
||||
/// </summary>
|
||||
public async Task<int> UpdateMqttServerAsync(MqttServerDto mqttServerDto)
|
||||
{
|
||||
return await UpdateMqttServersAsync(new List<MqttServerDto>() { mqttServerDto });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步批量更新MQTT服务器。
|
||||
/// </summary>
|
||||
public async Task<int> UpdateMqttServersAsync(List<MqttServerDto> mqttServerDtos)
|
||||
{
|
||||
var result = await _mqttAppService.UpdateMqttServersAsync(mqttServerDtos);
|
||||
|
||||
// 批量更新成功后,更新内存中的MQTT服务器
|
||||
if (result > 0 && mqttServerDtos != null)
|
||||
{
|
||||
foreach (var mqttServerDto in mqttServerDtos)
|
||||
{
|
||||
if (_appDataStorageService.MqttServers.TryGetValue(mqttServerDto.Id, out var mMqttServerDto))
|
||||
{
|
||||
// 比较旧值和新值,确定哪个属性发生了变化
|
||||
var changedProperties = GetChangedProperties(mMqttServerDto, mqttServerDto);
|
||||
|
||||
// 更新内存中的MQTT服务器
|
||||
_mapper.Map(mqttServerDto, mMqttServerDto);
|
||||
|
||||
// 为每个发生变化的属性触发事件
|
||||
foreach (var property in changedProperties)
|
||||
{
|
||||
_eventService.RaiseMqttServerChanged(
|
||||
this, new MqttServerChangedEventArgs(ActionChangeType.Updated, mMqttServerDto, property));
|
||||
}
|
||||
|
||||
// 如果没有任何属性发生变化,至少触发一次更新事件
|
||||
if (changedProperties.Count == 0)
|
||||
{
|
||||
_eventService.RaiseMqttServerChanged(
|
||||
this, new MqttServerChangedEventArgs(ActionChangeType.Updated, mMqttServerDto, MqttServerPropertyType.All));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果内存中不存在该MQTT服务器,则直接添加
|
||||
_appDataStorageService.MqttServers.TryAdd(mqttServerDto.Id, mqttServerDto);
|
||||
_eventService.RaiseMqttServerChanged(
|
||||
this, new MqttServerChangedEventArgs(ActionChangeType.Added, mqttServerDto, MqttServerPropertyType.All));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步更新一个已存在的MQTT服务器。
|
||||
/// </summary>
|
||||
public async Task UpdateMqttServerAsync(MqttServerDto mqttServerDto)
|
||||
{
|
||||
await _mqttAppService.UpdateMqttServerAsync(mqttServerDto);
|
||||
|
||||
// 更新成功后,更新内存中的MQTT服务器
|
||||
_appDataStorageService.MqttServers.AddOrUpdate(mqttServerDto.Id, mqttServerDto, (key, oldValue) => mqttServerDto);
|
||||
_eventService.RaiseMqttServerChanged(this, new MqttServerChangedEventArgs(ActionChangeType.Updated, mqttServerDto));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步删除一个MQTT服务器。
|
||||
/// </summary>
|
||||
public async Task DeleteMqttServerAsync(int id)
|
||||
public async Task<bool> DeleteMqttServerAsync(int id)
|
||||
{
|
||||
var mqttServer = await _mqttAppService.GetMqttServerByIdAsync(id); // 获取MQTT服务器信息用于内存删除
|
||||
var result = await _mqttAppService.DeleteMqttServerAsync(id);
|
||||
var result = await _mqttAppService.DeleteMqttServerAsync(id) > 0;
|
||||
|
||||
// 删除成功后,从内存中移除MQTT服务器
|
||||
if (result>0)
|
||||
if (result && mqttServer != null)
|
||||
{
|
||||
if (_appDataStorageService.MqttServers.TryRemove(id, out var mqttServerDto))
|
||||
{
|
||||
_eventService.RaiseMqttServerChanged(this, new MqttServerChangedEventArgs(ActionChangeType.Deleted, mqttServerDto));
|
||||
_eventService.RaiseMqttServerChanged(
|
||||
this, new MqttServerChangedEventArgs(ActionChangeType.Deleted, mqttServerDto));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步批量删除MQTT服务器。
|
||||
/// </summary>
|
||||
public async Task<bool> DeleteMqttServersAsync(List<int> ids)
|
||||
{
|
||||
var result = await _mqttAppService.DeleteMqttServersAsync(ids);
|
||||
|
||||
// 批量删除成功后,从内存中移除MQTT服务器
|
||||
if (result && ids != null)
|
||||
{
|
||||
foreach (var id in ids)
|
||||
{
|
||||
if (_appDataStorageService.MqttServers.TryRemove(id, out var mqttServerDto))
|
||||
{
|
||||
_eventService.RaiseMqttServerChanged(
|
||||
this, new MqttServerChangedEventArgs(ActionChangeType.Deleted, mqttServerDto));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取发生变化的属性列表
|
||||
/// </summary>
|
||||
/// <param name="oldMqttServer">旧MQTT服务器值</param>
|
||||
/// <param name="newMqttServer">新MQTT服务器值</param>
|
||||
/// <returns>发生变化的属性列表</returns>
|
||||
private List<MqttServerPropertyType> GetChangedProperties(MqttServerDto oldMqttServer, MqttServerDto newMqttServer)
|
||||
{
|
||||
var changedProperties = new List<MqttServerPropertyType>();
|
||||
|
||||
if (oldMqttServer.ServerName != newMqttServer.ServerName)
|
||||
changedProperties.Add(MqttServerPropertyType.ServerName);
|
||||
|
||||
if (oldMqttServer.ServerUrl != newMqttServer.ServerUrl)
|
||||
changedProperties.Add(MqttServerPropertyType.ServerUrl);
|
||||
|
||||
if (oldMqttServer.Port != newMqttServer.Port)
|
||||
changedProperties.Add(MqttServerPropertyType.Port);
|
||||
|
||||
if (oldMqttServer.IsConnect != newMqttServer.IsConnect)
|
||||
changedProperties.Add(MqttServerPropertyType.IsConnect);
|
||||
|
||||
if (oldMqttServer.Username != newMqttServer.Username)
|
||||
changedProperties.Add(MqttServerPropertyType.Username);
|
||||
|
||||
if (oldMqttServer.Password != newMqttServer.Password)
|
||||
changedProperties.Add(MqttServerPropertyType.Password);
|
||||
|
||||
if (oldMqttServer.IsActive != newMqttServer.IsActive)
|
||||
changedProperties.Add(MqttServerPropertyType.IsActive);
|
||||
|
||||
if (oldMqttServer.SubscribeTopic != newMqttServer.SubscribeTopic)
|
||||
changedProperties.Add(MqttServerPropertyType.SubscribeTopic);
|
||||
|
||||
if (oldMqttServer.PublishTopic != newMqttServer.PublishTopic)
|
||||
changedProperties.Add(MqttServerPropertyType.PublishTopic);
|
||||
|
||||
if (oldMqttServer.ClientId != newMqttServer.ClientId)
|
||||
changedProperties.Add(MqttServerPropertyType.ClientId);
|
||||
|
||||
if (oldMqttServer.MessageFormat != newMqttServer.MessageFormat)
|
||||
changedProperties.Add(MqttServerPropertyType.MessageFormat);
|
||||
|
||||
if (oldMqttServer.MessageHeader != newMqttServer.MessageHeader)
|
||||
changedProperties.Add(MqttServerPropertyType.MessageHeader);
|
||||
|
||||
if (oldMqttServer.MessageContent != newMqttServer.MessageContent)
|
||||
changedProperties.Add(MqttServerPropertyType.MessageContent);
|
||||
|
||||
if (oldMqttServer.MessageFooter != newMqttServer.MessageFooter)
|
||||
changedProperties.Add(MqttServerPropertyType.MessageFooter);
|
||||
|
||||
return changedProperties;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public class DataEventService : IDataEventService
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IDataStorageService _dataStorageService;
|
||||
private readonly IEventService _eventService;
|
||||
private readonly INotificationService _notificationService;
|
||||
private readonly IAppDataCenterService _appDataCenterService;
|
||||
private readonly IWPFDataService _wpfDataService;
|
||||
private readonly ILogger<DataEventService> _logger;
|
||||
@@ -33,6 +34,7 @@ public class DataEventService : IDataEventService
|
||||
public DataEventService(IMapper mapper,
|
||||
IDataStorageService dataStorageService,
|
||||
IEventService eventService,
|
||||
INotificationService notificationService,
|
||||
IAppDataCenterService appDataCenterService,
|
||||
IWPFDataService wpfDataService,
|
||||
ILogger<DataEventService> logger)
|
||||
@@ -40,6 +42,7 @@ public class DataEventService : IDataEventService
|
||||
_mapper = mapper;
|
||||
_dataStorageService = dataStorageService;
|
||||
_eventService = eventService;
|
||||
_notificationService = notificationService;
|
||||
_appDataCenterService = appDataCenterService;
|
||||
_wpfDataService = wpfDataService;
|
||||
_logger = logger;
|
||||
@@ -79,6 +82,7 @@ public class DataEventService : IDataEventService
|
||||
break;
|
||||
case MqttServerPropertyType.IsConnect:
|
||||
mqttServerItem.IsConnect=e.MqttServer.IsConnect;
|
||||
_notificationService.ShowSuccess($"MQTT服务器:{mqttServerItem.ServerName},连接发生了变化,状态:{e.MqttServer.IsConnect}");
|
||||
break;
|
||||
case MqttServerPropertyType.Username:
|
||||
break;
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
<UserControl x:Class="DMS.WPF.Views.DevicesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
xmlns:localConverters="clr-namespace:DMS.WPF.Converters"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:vm="clr-namespace:DMS.WPF.ViewModels"
|
||||
d:DataContext="{d:DesignInstance vm:DevicesViewModel}"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="300"
|
||||
mc:Ignorable="d">
|
||||
<UserControl
|
||||
x:Class="DMS.WPF.Views.DevicesView"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:hc="https://handyorg.github.io/handycontrol"
|
||||
xmlns:localConverters="clr-namespace:DMS.WPF.Converters"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
|
||||
xmlns:vm="clr-namespace:DMS.WPF.ViewModels"
|
||||
d:DataContext="{d:DesignInstance vm:DevicesViewModel}"
|
||||
d:DesignHeight="300"
|
||||
d:DesignWidth="300"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<localConverters:BooleanToBrushConverter x:Key="BooleanToBrushConverter" />
|
||||
|
||||
@@ -22,17 +23,19 @@
|
||||
|
||||
<!-- 设备项模板 -->
|
||||
<DataTemplate x:Key="DeviceItemTemplate">
|
||||
<Border Margin="5"
|
||||
Padding="15"
|
||||
Background="White"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8">
|
||||
<Border
|
||||
Margin="5"
|
||||
Padding="15"
|
||||
Background="White"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8">
|
||||
<Border.Effect>
|
||||
<DropShadowEffect BlurRadius="5"
|
||||
Opacity="0.1"
|
||||
ShadowDepth="2"
|
||||
Color="#888888" />
|
||||
<DropShadowEffect
|
||||
BlurRadius="5"
|
||||
Opacity="0.1"
|
||||
ShadowDepth="2"
|
||||
Color="#888888" />
|
||||
</Border.Effect>
|
||||
|
||||
<Grid>
|
||||
@@ -43,8 +46,7 @@
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 设备基本信息区域 -->
|
||||
<StackPanel Grid.Row="0"
|
||||
Margin="0,0,0,15">
|
||||
<StackPanel Grid.Row="0" Margin="0,0,0,15">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
@@ -53,71 +55,80 @@
|
||||
|
||||
<!-- 设备名称和描述 -->
|
||||
<StackPanel Grid.Column="0">
|
||||
<StackPanel Margin="0,0,0,5"
|
||||
Orientation="Horizontal">
|
||||
<ui:FontIcon Margin="0,0,8,0"
|
||||
FontSize="20"
|
||||
Foreground="{DynamicResource SystemAccentColorBrush}"
|
||||
Glyph="" />
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
<StackPanel Margin="0,0,0,5" Orientation="Horizontal">
|
||||
<ui:FontIcon
|
||||
Margin="0,0,8,0"
|
||||
FontSize="20"
|
||||
Foreground="{DynamicResource SystemAccentColorBrush}"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="16"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock Margin="0,0,0,8"
|
||||
FontSize="13"
|
||||
Foreground="#666666"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Margin="0,0,0,8"
|
||||
FontSize="13"
|
||||
Foreground="#666666"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ui:FontIcon Margin="0,0,5,0"
|
||||
FontSize="14"
|
||||
Foreground="#888888"
|
||||
Glyph="" />
|
||||
<TextBlock FontSize="12"
|
||||
Foreground="#888888"
|
||||
Text="{Binding DeviceType}" />
|
||||
<ui:FontIcon
|
||||
Margin="0,0,5,0"
|
||||
FontSize="14"
|
||||
Foreground="#888888"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="#888888"
|
||||
Text="{Binding DeviceType}" />
|
||||
|
||||
<Rectangle Width="1"
|
||||
Height="12"
|
||||
Margin="10,0"
|
||||
Fill="#CCCCCC" />
|
||||
<Rectangle
|
||||
Width="1"
|
||||
Height="12"
|
||||
Margin="10,0"
|
||||
Fill="#CCCCCC" />
|
||||
|
||||
<ui:FontIcon Margin="10,0,5,0"
|
||||
FontSize="14"
|
||||
Foreground="#888888"
|
||||
Glyph="" />
|
||||
<TextBlock FontSize="12"
|
||||
Foreground="#888888"
|
||||
Text="{Binding IsRunning, Converter={StaticResource BoolToStringConverter}, ConverterParameter='已连接;未连接'}" />
|
||||
<ui:FontIcon
|
||||
Margin="10,0,5,0"
|
||||
FontSize="14"
|
||||
Foreground="#888888"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
FontSize="12"
|
||||
Foreground="#888888"
|
||||
Text="{Binding IsRunning, Converter={StaticResource BoolToStringConverter}, ConverterParameter='已连接;未连接'}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 状态指示器 -->
|
||||
<StackPanel Grid.Column="1"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Horizontal">
|
||||
<Border
|
||||
Margin="0,0,10,0"
|
||||
Background="{Binding IsRunning, Converter={StaticResource BoolToColorConverter}, ConverterParameter='Green;Red'}"
|
||||
CornerRadius="8">
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Horizontal">
|
||||
<Border
|
||||
Margin="0,0,10,0"
|
||||
Background="{Binding IsRunning, Converter={StaticResource BoolToColorConverter}, ConverterParameter='Green;Red'}"
|
||||
CornerRadius="8">
|
||||
<TextBlock
|
||||
Margin="10 5"
|
||||
Margin="10,5"
|
||||
FontSize="14"
|
||||
Foreground="White"
|
||||
FontWeight="Bold"
|
||||
Foreground="White"
|
||||
Text="{Binding IsRunning, Converter={StaticResource BoolToStringConverter}, ConverterParameter='已连接;未连接'}" />
|
||||
</Border>
|
||||
|
||||
<ToggleButton x:Name="ExpandToggleButton"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Foreground="#666666"
|
||||
IsChecked="True"
|
||||
Style="{StaticResource DefaultToggleButtonStyle}"
|
||||
ToolTip="展开/收起变量表">
|
||||
<ToggleButton
|
||||
x:Name="ExpandToggleButton"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"
|
||||
Foreground="#666666"
|
||||
IsChecked="True"
|
||||
Style="{StaticResource DefaultToggleButtonStyle}"
|
||||
ToolTip="展开/收起变量表">
|
||||
<ToggleButton.Content>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.ChevronUp}" />
|
||||
@@ -129,55 +140,58 @@
|
||||
</StackPanel>
|
||||
|
||||
<!-- 变量表列表区域 -->
|
||||
<StackPanel Grid.Row="1"
|
||||
Margin="0,0,0,15">
|
||||
<Border Background="#F8F8F8"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="6"
|
||||
Visibility="{Binding ElementName=ExpandToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<StackPanel Grid.Row="1" Margin="0,0,0,15">
|
||||
<Border
|
||||
Background="#F8F8F8"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="1"
|
||||
CornerRadius="6"
|
||||
Visibility="{Binding ElementName=ExpandToggleButton, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<StackPanel>
|
||||
<!-- 变量表标题 -->
|
||||
<Border Padding="12,8"
|
||||
Background="#F0F0F0"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="0,0,0,1"
|
||||
CornerRadius="6,6,0,0">
|
||||
<Border
|
||||
Padding="12,8"
|
||||
Background="#F0F0F0"
|
||||
BorderBrush="#E0E0E0"
|
||||
BorderThickness="0,0,0,1"
|
||||
CornerRadius="6,6,0,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBlock Grid.Column="0"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#333333"
|
||||
Text="变量表列表" />
|
||||
<TextBlock
|
||||
Grid.Column="0"
|
||||
FontSize="14"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="#333333"
|
||||
Text="变量表列表" />
|
||||
|
||||
<Button Grid.Column="1"
|
||||
Width="28"
|
||||
Height="28"
|
||||
Padding="0"
|
||||
Content=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="14"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
Command="{Binding DataContext.AddVariableTableCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
ToolTip="添加变量表" />
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Width="28"
|
||||
Height="28"
|
||||
Padding="0"
|
||||
Command="{Binding DataContext.AddVariableTableCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="14"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
ToolTip="添加变量表" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- 变量表列表 -->
|
||||
<ItemsControl Margin="0"
|
||||
ItemsSource="{Binding VariableTables}">
|
||||
<ItemsControl Margin="0" ItemsSource="{Binding VariableTables}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="12,10"
|
||||
Background="White"
|
||||
BorderBrush="#EEEEEE"
|
||||
BorderThickness="0,0,0,1">
|
||||
<Border
|
||||
Padding="12,10"
|
||||
Background="White"
|
||||
BorderBrush="#EEEEEE"
|
||||
BorderThickness="0,0,0,1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
@@ -185,63 +199,67 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0">
|
||||
<StackPanel Margin="0,0,0,3"
|
||||
Orientation="Horizontal">
|
||||
<ui:FontIcon Margin="0,0,6,0"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource SystemAccentColorBrush}"
|
||||
Glyph="" />
|
||||
<TextBlock FontSize="13"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
<StackPanel Margin="0,0,0,3" Orientation="Horizontal">
|
||||
<ui:FontIcon
|
||||
Margin="0,0,6,0"
|
||||
FontSize="14"
|
||||
Foreground="{DynamicResource SystemAccentColorBrush}"
|
||||
Glyph="" />
|
||||
<TextBlock
|
||||
FontSize="13"
|
||||
FontWeight="SemiBold"
|
||||
Text="{Binding Name}" />
|
||||
</StackPanel>
|
||||
|
||||
<TextBlock MaxWidth="300"
|
||||
FontSize="11"
|
||||
Foreground="#888888"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
MaxWidth="300"
|
||||
FontSize="11"
|
||||
Foreground="#888888"
|
||||
Text="{Binding Description}"
|
||||
TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Grid.Column="1"
|
||||
Orientation="Horizontal">
|
||||
<TextBlock Margin="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="#666666"
|
||||
Text="{Binding Variables.Count}" />
|
||||
<TextBlock VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="#888888"
|
||||
Text="变量" />
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
||||
<TextBlock
|
||||
Margin="0,0,5,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="#666666"
|
||||
Text="{Binding Variables.Count}" />
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="12"
|
||||
Foreground="#888888"
|
||||
Text="变量" />
|
||||
|
||||
<Button Width="26"
|
||||
Height="26"
|
||||
Margin="8,0,0,0"
|
||||
Padding="0"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
Command="{Binding DataContext.EditVariableTableCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
ToolTip="编辑变量表">
|
||||
<Button
|
||||
Width="26"
|
||||
Height="26"
|
||||
Margin="8,0,0,0"
|
||||
Padding="0"
|
||||
Command="{Binding DataContext.EditVariableTableCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
ToolTip="编辑变量表">
|
||||
<Button.Content>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ui:FontIcon
|
||||
Icon="{x:Static ui:SegoeFluentIcons.Edit}" />
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Edit}" />
|
||||
</StackPanel>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
|
||||
<Button Width="26"
|
||||
Height="26"
|
||||
Margin="4,0,0,0"
|
||||
Padding="0"
|
||||
Content=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="14"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
Command="{Binding DataContext.DeleteVariableTableCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
ToolTip="删除变量表" />
|
||||
<Button
|
||||
Width="26"
|
||||
Height="26"
|
||||
Margin="4,0,0,0"
|
||||
Padding="0"
|
||||
Command="{Binding DataContext.DeleteVariableTableCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
Content=""
|
||||
FontFamily="Segoe MDL2 Assets"
|
||||
FontSize="14"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
ToolTip="删除变量表" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
@@ -250,31 +268,34 @@
|
||||
</ItemsControl>
|
||||
|
||||
<!-- 空状态提示 -->
|
||||
<TextBlock Padding="20,15"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="13"
|
||||
Foreground="#AAAAAA"
|
||||
Text="暂无变量表"
|
||||
Visibility="{Binding VariableTables, Converter={StaticResource CountToVisibilityConverter}}" />
|
||||
<TextBlock
|
||||
Padding="20,15"
|
||||
HorizontalAlignment="Center"
|
||||
FontSize="13"
|
||||
Foreground="#AAAAAA"
|
||||
Text="暂无变量表"
|
||||
Visibility="{Binding VariableTables, Converter={StaticResource CountToVisibilityConverter}}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
<!-- 操作按钮区域 -->
|
||||
<StackPanel Grid.Row="2"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button Width="36"
|
||||
Height="36"
|
||||
Margin="0,0,8,0"
|
||||
Padding="0"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
ToolTip="连接设备">
|
||||
<StackPanel
|
||||
Grid.Row="2"
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal">
|
||||
<Button
|
||||
Width="36"
|
||||
Height="36"
|
||||
Margin="0,0,8,0"
|
||||
Padding="0"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
ToolTip="连接设备">
|
||||
<!-- <Button.Effect> -->
|
||||
<!-- <DropShadowEffect BlurRadius="3" -->
|
||||
<!-- Opacity="0.2" -->
|
||||
<!-- ShadowDepth="1" -->
|
||||
<!-- Color="{DynamicResource SystemAccentColor}" /> -->
|
||||
<!-- <DropShadowEffect BlurRadius="3" -->
|
||||
<!-- Opacity="0.2" -->
|
||||
<!-- ShadowDepth="1" -->
|
||||
<!-- Color="{DynamicResource SystemAccentColor}" /> -->
|
||||
<!-- </Button.Effect> -->
|
||||
<Button.Content>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
@@ -283,13 +304,14 @@
|
||||
</Button.Content>
|
||||
</Button>
|
||||
|
||||
<Button Width="36"
|
||||
Height="36"
|
||||
Margin="0,0,8,0"
|
||||
Padding="0"
|
||||
Command="{Binding DataContext.EditDeviceCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
ToolTip="编辑设备">
|
||||
<Button
|
||||
Width="36"
|
||||
Height="36"
|
||||
Margin="0,0,8,0"
|
||||
Padding="0"
|
||||
Command="{Binding DataContext.EditDeviceCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
ToolTip="编辑设备">
|
||||
<Button.Content>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Edit}" />
|
||||
@@ -297,12 +319,13 @@
|
||||
</Button.Content>
|
||||
</Button>
|
||||
|
||||
<Button Width="36"
|
||||
Height="36"
|
||||
Margin="0,0,8,0"
|
||||
Padding="0"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
ToolTip="监控设备">
|
||||
<Button
|
||||
Width="36"
|
||||
Height="36"
|
||||
Margin="0,0,8,0"
|
||||
Padding="0"
|
||||
Style="{StaticResource DefaultButtonStyle}"
|
||||
ToolTip="监控设备">
|
||||
<Button.Content>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.TVMonitor}" />
|
||||
@@ -310,13 +333,14 @@
|
||||
</Button.Content>
|
||||
</Button>
|
||||
|
||||
<Button Width="36"
|
||||
Height="36"
|
||||
Padding="0"
|
||||
Command="{Binding DataContext.DeleteDeviceCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
Style="{StaticResource ButtonDanger.Small}"
|
||||
ToolTip="删除设备">
|
||||
<Button
|
||||
Width="36"
|
||||
Height="36"
|
||||
Padding="0"
|
||||
Command="{Binding DataContext.DeleteDeviceCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
Style="{StaticResource ButtonDanger.Small}"
|
||||
ToolTip="删除设备">
|
||||
<Button.Content>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Delete}" />
|
||||
@@ -331,50 +355,47 @@
|
||||
|
||||
<StackPanel>
|
||||
<!-- 操作菜单栏 -->
|
||||
<ui:CommandBar DefaultLabelPosition="Right"
|
||||
IsOpen="False">
|
||||
<ui:CommandBar DefaultLabelPosition="Right" IsOpen="False">
|
||||
<!-- 添加设备 -->
|
||||
<ui:AppBarButton Command="{Binding AddDeviceCommand}"
|
||||
Label="添加设备">
|
||||
<ui:AppBarButton Command="{Binding AddDeviceCommand}" Label="添加设备">
|
||||
<ui:AppBarButton.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Add}" />
|
||||
</ui:AppBarButton.Icon>
|
||||
</ui:AppBarButton>
|
||||
<!-- 编辑设备 -->
|
||||
<ui:AppBarButton Command="{Binding EditDeviceCommand}"
|
||||
Label="编辑设备">
|
||||
<ui:AppBarButton Command="{Binding EditDeviceCommand}" Label="编辑设备">
|
||||
<ui:AppBarButton.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Edit}" />
|
||||
</ui:AppBarButton.Icon>
|
||||
</ui:AppBarButton>
|
||||
<!-- 编辑设备 -->
|
||||
<ui:AppBarButton Command="{Binding DeleteDeviceCommand}"
|
||||
Label="删除设备">
|
||||
<ui:AppBarButton Command="{Binding DeleteDeviceCommand}" Label="删除设备">
|
||||
<ui:AppBarButton.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Delete}" />
|
||||
</ui:AppBarButton.Icon>
|
||||
</ui:AppBarButton>
|
||||
<ui:AppBarButton x:Name="ShareButton"
|
||||
Label="Share">
|
||||
<ui:AppBarButton x:Name="ShareButton" Label="Share">
|
||||
<ui:AppBarButton.Icon>
|
||||
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Share}" />
|
||||
</ui:AppBarButton.Icon>
|
||||
</ui:AppBarButton>
|
||||
<ui:CommandBar.SecondaryCommands>
|
||||
<ui:AppBarButton x:Name="SettingsButton"
|
||||
Icon="Setting"
|
||||
Label="Settings" />
|
||||
<ui:AppBarButton
|
||||
x:Name="SettingsButton"
|
||||
Icon="Setting"
|
||||
Label="Settings" />
|
||||
</ui:CommandBar.SecondaryCommands>
|
||||
</ui:CommandBar>
|
||||
|
||||
|
||||
<ui:GridView x:Name="BasicGridView"
|
||||
Margin="20"
|
||||
IsItemClickEnabled="True"
|
||||
ItemTemplate="{StaticResource DeviceItemTemplate}"
|
||||
ItemsSource="{Binding Devices}"
|
||||
SelectedItem="{Binding SelectedDevice}"
|
||||
SelectionMode="Single">
|
||||
<ui:GridView
|
||||
x:Name="BasicGridView"
|
||||
Margin="20"
|
||||
IsItemClickEnabled="True"
|
||||
ItemTemplate="{StaticResource DeviceItemTemplate}"
|
||||
ItemsSource="{Binding Devices}"
|
||||
SelectedItem="{Binding SelectedDevice}"
|
||||
SelectionMode="Single">
|
||||
<hc:Interaction.Triggers>
|
||||
<hc:EventTrigger EventName="MouseDoubleClick">
|
||||
<hc:InvokeCommandAction Command="{Binding NavigateToDetailCommand}" />
|
||||
|
||||
Reference in New Issue
Block a user