添加了 Mqtt 的界面和添加对话框

This commit is contained in:
2025-07-04 22:39:44 +08:00
parent 8325717b95
commit f86ce8194b
12 changed files with 452 additions and 14 deletions

View File

@@ -3,6 +3,8 @@ using System.Diagnostics;
using System.Threading.Tasks;
using NLog;
using PMSWPF.Data.Entities;
using PMSWPF.Models;
using PMSWPF.Extensions;
namespace PMSWPF.Data.Repositories;
@@ -18,7 +20,7 @@ public class MqttRepository
/// </summary>
/// <param name="id">主键ID</param>
/// <returns></returns>
public async Task<DbMqtt> GetByIdAsync(int id)
public async Task<Mqtt> GetById(int id)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
@@ -27,7 +29,7 @@ public class MqttRepository
var result = await _db.Queryable<DbMqtt>().In(id).SingleAsync();
stopwatch.Stop();
Logger.Info($"根据ID '{id}' 获取Mqtt配置耗时{stopwatch.ElapsedMilliseconds}ms");
return result;
return result.CopyTo<Mqtt>();
}
}
@@ -35,7 +37,7 @@ public class MqttRepository
/// 获取所有Mqtt配置
/// </summary>
/// <returns></returns>
public async Task<List<DbMqtt>> GetAllAsync()
public async Task<List<Mqtt>> GetAll()
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
@@ -44,7 +46,7 @@ public class MqttRepository
var result = await _db.Queryable<DbMqtt>().ToListAsync();
stopwatch.Stop();
Logger.Info($"获取所有Mqtt配置耗时{stopwatch.ElapsedMilliseconds}ms");
return result;
return result.CopyTo<List<Mqtt>>();
}
}
@@ -53,13 +55,13 @@ public class MqttRepository
/// </summary>
/// <param name="mqtt">Mqtt实体</param>
/// <returns></returns>
public async Task<int> AddAsync(DbMqtt mqtt)
public async Task<int> Add(Mqtt mqtt)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
using (var _db = DbContext.GetInstance())
{
var result = await _db.Insertable(mqtt).ExecuteReturnIdentityAsync();
var result = await _db.Insertable(mqtt.CopyTo<DbMqtt>()).ExecuteReturnIdentityAsync();
stopwatch.Stop();
Logger.Info($"新增Mqtt配置 '{mqtt.Name}' 耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
@@ -71,13 +73,13 @@ public class MqttRepository
/// </summary>
/// <param name="mqtt">Mqtt实体</param>
/// <returns></returns>
public async Task<int> UpdateAsync(DbMqtt mqtt)
public async Task<int> Edit(Mqtt mqtt)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
using (var _db = DbContext.GetInstance())
{
var result = await _db.Updateable(mqtt).ExecuteCommandAsync();
var result = await _db.Updateable(mqtt.CopyTo<DbMqtt>()).ExecuteCommandAsync();
stopwatch.Stop();
Logger.Info($"更新Mqtt配置 '{mqtt.Name}' 耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
@@ -87,17 +89,17 @@ public class MqttRepository
/// <summary>
/// 根据ID删除Mqtt配置
/// </summary>
/// <param name="id">主键ID</param>
/// <param name="mqtt">Mqtt实体</param>
/// <returns></returns>
public async Task<int> DeleteAsync(int id)
public async Task<int> Delete(Mqtt mqtt)
{
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
using (var _db = DbContext.GetInstance())
{
var result = await _db.Deleteable<DbMqtt>().In(id).ExecuteCommandAsync();
var result = await _db.Deleteable<DbMqtt>().In(mqtt.Id).ExecuteCommandAsync();
stopwatch.Stop();
Logger.Info($"删除Mqtt配置ID '{id}' 耗时:{stopwatch.ElapsedMilliseconds}ms");
Logger.Info($"删除Mqtt配置ID '{mqtt.Id}' 耗时:{stopwatch.ElapsedMilliseconds}ms");
return result;
}
}

View File

@@ -4,6 +4,6 @@ public enum LoadTypes
{
Devices,
Menu,
Mqtt,
Mqtts,
All
}

View File

@@ -34,6 +34,20 @@
<ItemGroup>
<Compile Remove="Data\Repositories\BaseRepositories.cs" />
</ItemGroup>
<ItemGroup>
<Page Update="Views\MqttsView.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Compile Update="Views\MqttsView.xaml.cs">
<DependentUpon>MqttsView.xaml</DependentUpon>
</Compile>
<Page Update="Views\Dialogs\MqttDialog.xaml">
<Generator>MSBuild:Compile</Generator>
</Page>
<Compile Update="Views\Dialogs\MqttDialog.xaml.cs">
<DependentUpon>MqttDialog.xaml</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Remove="Assets\AppIcon.png" />
<Resource Include="Assets\AppIcon.png" />

View File

@@ -18,12 +18,15 @@ public partial class DataServices : ObservableRecipient, IRecipient<LoadMessage>
[ObservableProperty] private List<Device> _devices;
[ObservableProperty] private List<VariableTable> _variableTables;
[ObservableProperty] private List<MenuBean> menuTrees;
[ObservableProperty] private List<Mqtt> _mqtts;
private readonly DeviceRepository _deviceRepository;
private readonly MenuRepository _menuRepository;
private readonly MqttRepository _mqttRepository;
public event Action<List<Device>> OnDeviceListChanged;
public event Action<List<MenuBean>> OnMenuTreeListChanged;
public event Action<List<Mqtt>> OnMqttListChanged;
partial void OnDevicesChanged(List<Device> devices)
@@ -36,6 +39,11 @@ public partial class DataServices : ObservableRecipient, IRecipient<LoadMessage>
OnMenuTreeListChanged?.Invoke(MenuTrees);
}
partial void OnMqttsChanged(List<Mqtt> mqtts)
{
OnMqttListChanged?.Invoke(mqtts);
}
public DataServices(ILogger<DataServices> logger)
{
@@ -43,6 +51,7 @@ public partial class DataServices : ObservableRecipient, IRecipient<LoadMessage>
IsActive = true;
_deviceRepository = new DeviceRepository();
_menuRepository = new MenuRepository();
_mqttRepository = new MqttRepository();
}
@@ -60,6 +69,7 @@ public partial class DataServices : ObservableRecipient, IRecipient<LoadMessage>
case LoadTypes.All:
await LoadDevices();
await LoadMenus();
await LoadMqtts();
break;
case LoadTypes.Devices:
await LoadDevices();
@@ -67,6 +77,9 @@ public partial class DataServices : ObservableRecipient, IRecipient<LoadMessage>
case LoadTypes.Menu:
await LoadMenus();
break;
case LoadTypes.Mqtts:
await LoadMqtts();
break;
}
}
catch (Exception e)
@@ -90,4 +103,9 @@ public partial class DataServices : ObservableRecipient, IRecipient<LoadMessage>
DataServicesHelper.SortMenus(menu);
}
}
private async Task LoadMqtts()
{
Mqtts = await _mqttRepository.GetAll();
}
}

View File

@@ -43,6 +43,34 @@ public class DialogService :IDialogService
}
public async Task<Mqtt> ShowAddMqttDialog()
{
var mqtt = new Mqtt();
MqttDialogViewModel vm = new MqttDialogViewModel(mqtt);
vm.Title = "添加MQTT";
vm.PrimaryButContent = "添加MQTT";
return await ShowConentDialog(vm, mqtt);
}
public async Task<Mqtt> ShowEditMqttDialog(Mqtt mqtt)
{
MqttDialogViewModel vm = new MqttDialogViewModel(mqtt);
vm.Title = "编辑MQTT";
vm.PrimaryButContent = "编辑MQTT";
return await ShowConentDialog(vm, mqtt);
}
private static async Task<Mqtt> ShowConentDialog(MqttDialogViewModel viewModel, Mqtt mqtt)
{
var dialog = new MqttDialog(viewModel);
var res = await dialog.ShowAsync();
if (res == ContentDialogResult.Primary)
{
return mqtt;
}
return null;
}
public async Task<bool> ShowConfrimeDialog(string title, string message,string buttonText="确认")
{
ConfrimDialogViewModel vm = new ConfrimDialogViewModel();

View File

@@ -7,7 +7,8 @@ public interface IDialogService
{
Task<Device> ShowAddDeviceDialog();
Task<Device> ShowEditDeviceDialog(Device device);
Task<Mqtt> ShowAddMqttDialog();
Task<Mqtt> ShowEditMqttDialog(Mqtt mqtt);
Task<bool> ShowConfrimeDialog(string title, string message,string buttonText="确认");
Task<VariableTable> ShowAddVarTableDialog();

View File

@@ -0,0 +1,26 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using PMSWPF.Models;
namespace PMSWPF.ViewModels.Dialogs;
public partial class MqttDialogViewModel : ObservableObject
{
[ObservableProperty]
private Mqtt _mqtt;
[ObservableProperty] private string title ;
[ObservableProperty] private string primaryButContent ;
public MqttDialogViewModel(Mqtt mqtt)
{
_mqtt = mqtt;
}
[RelayCommand]
public void AddMqtt()
{
}
}

View File

@@ -0,0 +1,113 @@
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Microsoft.Extensions.Logging;
using PMSWPF.Data;
using PMSWPF.Data.Repositories;
using PMSWPF.Enums;
using PMSWPF.Helper;
using PMSWPF.Models;
using PMSWPF.Services;
namespace PMSWPF.ViewModels;
public partial class MqttsViewModel : ViewModelBase
{
private readonly DataServices _dataServices;
private readonly IDialogService _dialogService;
private readonly MqttRepository _mqttRepository;
private readonly ILogger<MqttsViewModel> _logger;
[ObservableProperty]
private ObservableCollection<Mqtt> _mqtts;
[ObservableProperty]
private Mqtt _selectedMqtt;
public MqttsViewModel(
ILogger<MqttsViewModel> logger, IDialogService dialogService, DataServices dataServices
)
{
_mqttRepository = new MqttRepository();
_logger = logger;
_dialogService = dialogService;
_dataServices = dataServices;
MessageHelper.SendLoadMessage(LoadTypes.Mqtts);
_dataServices.OnMqttListChanged += (mqtts) => { Mqtts = new ObservableCollection<Mqtt>(mqtts); };
}
[RelayCommand]
public async void AddMqtt()
{
try
{
var mqtt = await _dialogService.ShowAddMqttDialog();
if (mqtt == null)
{
_logger.LogInformation("用户取消了添加MQTT操作。");
return;
}
await _mqttRepository.Add(mqtt);
}
catch (Exception e)
{
NotificationHelper.ShowMessage($"添加MQTT的过程中发生错误{e.Message}", NotificationType.Error);
_logger.LogError($"添加MQTT的过程中发生错误{e}");
}
}
[RelayCommand]
public async void DeleteMqtt()
{
try
{
if (SelectedMqtt == null)
{
NotificationHelper.ShowMessage("你没有选择任何MQTT请选择MQTT后再点击删除", NotificationType.Error);
return;
}
string msg = $"确认要删除MQTT名为:{SelectedMqtt.Name}";
var isDel = await _dialogService.ShowConfrimeDialog("删除MQTT", msg, "删除MQTT");
if (isDel)
{
await _mqttRepository.Delete(SelectedMqtt);
MessageHelper.SendLoadMessage(LoadTypes.Mqtts);
NotificationHelper.ShowMessage($"删除MQTT成功,MQTT名{SelectedMqtt.Name}", NotificationType.Success);
}
}
catch (Exception e)
{
NotificationHelper.ShowMessage($"删除MQTT的过程中发生错误{e.Message}", NotificationType.Error);
_logger.LogError($"删除MQTT的过程中发生错误{e}");
}
}
[RelayCommand]
public async void EditMqtt()
{
try
{
if (SelectedMqtt == null)
{
NotificationHelper.ShowMessage("你没有选择任何MQTT请选择MQTT后再点击编辑", NotificationType.Error);
return;
}
var editMqtt = await _dialogService.ShowEditMqttDialog(SelectedMqtt);
if (editMqtt != null)
{
var res = await _mqttRepository.Edit(editMqtt);
MessageHelper.SendLoadMessage(LoadTypes.Mqtts);
}
}
catch (Exception e)
{
NotificationHelper.ShowMessage($"编辑MQTT的过程中发生错误{e.Message}", NotificationType.Error);
_logger.LogError($"编辑MQTT的过程中发生错误{e}");
}
}
}

View File

@@ -0,0 +1,74 @@
<ui:ContentDialog x:Class="PMSWPF.Views.Dialogs.MqttDialog"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:vmd="clr-namespace:PMSWPF.ViewModels.Dialogs"
xmlns:vc="clr-namespace:PMSWPF.ValueConverts"
xmlns:ex="clr-namespace:PMSWPF.Extensions"
xmlns:en="clr-namespace:PMSWPF.Enums"
Title="{Binding Title}"
CloseButtonText="取消"
DefaultButton="Primary"
PrimaryButtonText="{Binding PrimaryButContent}"
Background="#fff"
d:DataContext="{d:DesignInstance vmd:MqttDialogViewModel}"
mc:Ignorable="d">
<ui:ContentDialog.Resources>
<ex:EnumBindingSource x:Key="mqttPlatform" EnumType="{x:Type en:MqttPlatform}" />
<vc:EnumDescriptionConverter x:Key="EnumDescriptionConverter" />
</ui:ContentDialog.Resources>
<Grid Width="480" Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<!-- 左边列 -->
<ikw:SimpleStackPanel Grid.Column="0" Margin="10 10 20 10 " Spacing="12">
<!-- MQTT名称 -->
<TextBlock Text="MQTT名称" HorizontalAlignment="Left" Style="{StaticResource TextBlockSubTitle}" />
<TextBox Text="{Binding Mqtt.Name, UpdateSourceTrigger=PropertyChanged}" />
<!-- MQTT IP地址 -->
<TextBlock Text="MQTT IP地址" HorizontalAlignment="Left" Style="{StaticResource TextBlockSubTitle}" />
<TextBox AcceptsReturn="True" Text="{Binding Mqtt.Host, UpdateSourceTrigger=PropertyChanged}" />
<!-- Mqtt平台 -->
<TextBlock Text="Mqtt平台" HorizontalAlignment="Left" Style="{StaticResource TextBlockSubTitle}" />
<ComboBox SelectedItem="{Binding Mqtt.Platform}" ItemsSource="{Binding Source={StaticResource mqttPlatform} }">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource EnumDescriptionConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<CheckBox FontSize="16" Content="是否设为默认" Margin="0 30 0 0" IsChecked="{Binding Mqtt.IsDefault}" />
</ikw:SimpleStackPanel>
<!-- 右边列 -->
<ikw:SimpleStackPanel Margin="10" Grid.Column="1" Spacing="12">
<!-- MQTT备注 -->
<TextBlock Text="MQTT备注" HorizontalAlignment="Left" Style="{StaticResource TextBlockSubTitle}" />
<TextBox Text="{Binding Mqtt.Remark, UpdateSourceTrigger=PropertyChanged}" />
<!-- MQTT端口 -->
<TextBlock Text="MQTT端口" HorizontalAlignment="Left" Style="{StaticResource TextBlockSubTitle}" />
<TextBox AcceptsReturn="True" Text="{Binding Mqtt.Port, UpdateSourceTrigger=PropertyChanged}" />
<!-- 用户名 -->
<TextBlock Text="用户名" HorizontalAlignment="Left" Style="{StaticResource TextBlockSubTitle}" />
<TextBox Text="{Binding Mqtt.UserName, UpdateSourceTrigger=PropertyChanged}" />
<!-- 密码 -->
<TextBlock Text="密码" HorizontalAlignment="Left" Style="{StaticResource TextBlockSubTitle}" />
<TextBox Text="{Binding Mqtt.PassWord, UpdateSourceTrigger=PropertyChanged}" />
<CheckBox FontSize="16" Content="是否启用" Margin="0 30 0 0" IsChecked="{Binding Mqtt.IsActive}" />
</ikw:SimpleStackPanel>
</Grid>
</ui:ContentDialog>

View File

@@ -0,0 +1,15 @@
using System.Windows.Controls;
using iNKORE.UI.WPF.Modern.Controls;
namespace PMSWPF.Views.Dialogs;
using PMSWPF.ViewModels.Dialogs;
public partial class MqttDialog : ContentDialog
{
public MqttDialog(MqttDialogViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
}
}

136
Views/MqttsView.xaml Normal file
View File

@@ -0,0 +1,136 @@
<UserControl x:Class="PMSWPF.Views.MqttsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:ui="http://schemas.inkore.net/lib/ui/wpf/modern"
xmlns:ikw="http://schemas.inkore.net/lib/ui/wpf"
xmlns:vm="clr-namespace:PMSWPF.ViewModels"
d:DataContext="{d:DesignInstance vm:MqttsViewModel}"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="300">
<UserControl.Resources>
<DataTemplate x:Key="MqttItemTemplate">
<Border Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
BorderBrush="{DynamicResource SystemControlHighlightBaseMediumLowBrush}"
BorderThickness="1"
CornerRadius="8"
Margin="5"
Padding="15">
<Border.Effect>
<DropShadowEffect ShadowDepth="1"
Color="Black"
Opacity="0.1"
BlurRadius="5" />
</Border.Effect>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Row 0: Header with Name and ToggleSwitch -->
<DockPanel Grid.Row="0"
Margin="0,0,0,10">
<ui:ToggleSwitch DockPanel.Dock="Right"
IsOn="{Binding IsActive}"
OffContent="停止"
OnContent="启动" />
<TextBlock Text="{Binding Name}"
FontSize="20"
FontWeight="SemiBold"
VerticalAlignment="Center" />
</DockPanel>
<!-- Row 1: Details with Icons -->
<StackPanel Grid.Row="1"
Margin="0,0,0,10">
<StackPanel Orientation="Horizontal"
Margin="0,2">
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Info}"
VerticalAlignment="Center"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="{Binding Remark}"
Foreground="{DynamicResource SystemControlForegroundBaseMediumBrush}"
TextTrimming="CharacterEllipsis" />
</StackPanel>
<StackPanel Orientation="Horizontal"
Margin="0,2">
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Connect}"
VerticalAlignment="Center"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock>
<Run Text="{Binding Host, FallbackValue='127.0.0.1'}" />
<Run Text=":" />
<Run Text="{Binding Port, FallbackValue='1883'}" />
</TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal"
Margin="0,2">
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.DeveloperTools}"
VerticalAlignment="Center"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock>
<Run Text="{Binding Platform, FallbackValue='EMQX'}" />
</TextBlock>
</StackPanel>
</StackPanel>
</Grid>
</Border>
</DataTemplate>
</UserControl.Resources>
<StackPanel>
<!-- 操作菜单栏 -->
<ui:CommandBar DefaultLabelPosition="Right"
IsOpen="False">
<!-- 添加MQTT -->
<ui:AppBarButton Command="{Binding AddMqttCommand}"
Label="添加MQTT">
<ui:AppBarButton.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Add}" />
</ui:AppBarButton.Icon>
</ui:AppBarButton>
<!-- 编辑MQTT -->
<ui:AppBarButton Command="{Binding EditMqttCommand}"
Label="编辑MQTT">
<ui:AppBarButton.Icon>
<ui:FontIcon Icon="{x:Static ui:SegoeFluentIcons.Edit}" />
</ui:AppBarButton.Icon>
</ui:AppBarButton>
<!-- 删除MQTT -->
<ui:AppBarButton Command="{Binding DeleteMqttCommand}"
Label="删除MQTT">
<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.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:CommandBar.SecondaryCommands>
</ui:CommandBar>
<ui:GridView x:Name="BasicGridView"
Margin="20"
IsItemClickEnabled="True"
SelectedItem="{Binding SelectedMqtt }"
ItemsSource="{Binding Mqtts}"
ItemTemplate="{StaticResource MqttItemTemplate}"
SelectionMode="Single" />
</StackPanel>
</UserControl>

11
Views/MqttsView.xaml.cs Normal file
View File

@@ -0,0 +1,11 @@
using System.Windows.Controls;
namespace PMSWPF.Views;
public partial class MqttsView : UserControl
{
public MqttsView()
{
InitializeComponent();
}
}