添加启动页

This commit is contained in:
2025-07-26 11:20:03 +08:00
parent e292ea9da8
commit db419edde3
10 changed files with 249 additions and 2 deletions

View File

@@ -0,0 +1,19 @@
namespace DMS.Application.Services;
public interface IInitializeService
{
/// <summary>
/// 初始化数据库表。
/// </summary>
void InitializeTables();
/// <summary>
/// 初始化数据库表索引。
/// </summary>
void InitializeTableIndex();
/// <summary>
/// 初始化默认菜单。
/// </summary>
void InitializeMenus();
}

View File

@@ -5,7 +5,7 @@ namespace DMS.Application.Services;
/// <summary>
/// 初始化服务,负责应用程序启动时的数据库和菜单初始化。
/// </summary>
public class InitializeService
public class InitializeService : IInitializeService
{
private readonly IInitializeRepository _repository;

View File

@@ -1,5 +1,8 @@
using System.Windows;
using DMS.Application.Interfaces;
using DMS.Application.Services;
using DMS.Core.Enums;
using DMS.Core.Interfaces.Repositories;
using DMS.Helper;
using DMS.Services;
using DMS.Services.Processors;
@@ -10,10 +13,14 @@ using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog;
using DMS.Extensions;
using DMS.Infrastructure.Configurations;
using DMS.Infrastructure.Data;
using DMS.Infrastructure.Repositories;
using Microsoft.Extensions.Hosting;
using DMS.WPF.Helper;
using DMS.WPF.Services;
using DMS.WPF.Services.Processors;
using IDataProcessingService = DMS.Services.IDataProcessingService;
using LogLevel = Microsoft.Extensions.Logging.LogLevel;
namespace DMS;
@@ -73,7 +80,7 @@ public partial class App : System.Windows.Application
NotificationHelper.ShowError("加载数据时发生错误,如果是连接字符串不正确,可以在设置界面更改:{exception.Message}", exception);
}
MainWindow = Host.Services.GetRequiredService<MainView>();
MainWindow = Host.Services.GetRequiredService<SplashWindow>();
MainWindow.Show();
// 根据配置启动服务
@@ -123,8 +130,18 @@ public partial class App : System.Windows.Application
services.AddSingleton<HistoryProcessor>();
services.AddSingleton<MqttPublishProcessor>();
// 注册Core中的仓库
services.AddSingleton<AppSettings>();
services.AddSingleton<SqlSugarDbContext>();
services.AddSingleton<IInitializeRepository, InitializeRepository>();
// 注册App服务
services.AddSingleton<IInitializeService,InitializeService>();
services.AddSingleton<IDeviceAppService,DeviceAppService>();
services.AddSingleton<INavigationService, NavigationService>();
// 注册视图模型
services.AddSingleton<SplashViewModel>();
services.AddSingleton<MainViewModel>();
services.AddSingleton<HomeViewModel>();
services.AddSingleton<DevicesViewModel>();
@@ -136,6 +153,7 @@ public partial class App : System.Windows.Application
services.AddSingleton<DeviceDetailViewModel>();
services.AddScoped<MqttsViewModel>();
//注册View视图
services.AddSingleton<SplashWindow>();
services.AddSingleton<SettingView>();
services.AddSingleton<MainView>();
services.AddSingleton<HomeView>();

View File

@@ -152,6 +152,7 @@
<ItemGroup>
<ProjectReference Include="..\DMS.Application\DMS.Application.csproj" />
<ProjectReference Include="..\DMS.Infrastructure\DMS.Infrastructure.csproj" />
</ItemGroup>

View File

@@ -0,0 +1,14 @@
// 文件: DMS.WPF/Services/INavigatable.cs
namespace DMS.WPF.Services;
/// <summary>
/// 定义了一个契约表示ViewModel可以安全地接收导航传入的参数。
/// </summary>
public interface INavigatable
{
/// <summary>
/// 当导航到此ViewModel时由导航服务调用此方法以传递参数。
/// </summary>
/// <param name="parameter">从导航源传递过来的参数对象。</param>
Task OnNavigatedToAsync(object parameter);
}

View File

@@ -0,0 +1,22 @@
// 文件: DMS.WPF/Services/INavigationService.cs
using System.Threading.Tasks;
namespace DMS.WPF.Services;
/// <summary>
/// 定义了应用程序的导航服务接口。
/// </summary>
public interface INavigationService
{
/// <summary>
/// 导航到由唯一键标识的视图,并传递一个参数。
/// </summary>
/// <param name="viewKey">在DI容器中注册的目标视图的唯一键通常是ViewModel的名称。</param>
/// <param name="parameter">要传递给目标ViewModel的参数。</param>
Task NavigateToAsync(string viewKey, object parameter = null);
/// <summary>
/// 显示主窗口。
/// </summary>
Task ShowMainWindowAsync();
}

View File

@@ -0,0 +1,72 @@
// 文件: DMS.WPF/Services/NavigationService.cs
using DMS.WPF.ViewModels;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DMS.ViewModels;
namespace DMS.WPF.Services;
/// <summary>
/// INavigationService 的实现负责解析ViewModel并处理参数传递。
/// </summary>
public class NavigationService : INavigationService
{
private readonly IServiceProvider _serviceProvider;
/// <summary>
/// 构造函数。
/// </summary>
public NavigationService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
/// <summary>
/// 导航到指定键的视图,并传递参数。
/// </summary>
public async Task NavigateToAsync(string viewKey, object parameter = null)
{
if (string.IsNullOrEmpty(viewKey))
{
return;
}
var mainViewModel = _serviceProvider.GetRequiredService<MainViewModel>();
var viewModelType = GetViewModelTypeByKey(viewKey);
var viewModel = _serviceProvider.GetRequiredService(viewModelType) as ViewModelBase;
if (viewModel is INavigatable navigatableViewModel)
{
await navigatableViewModel.OnNavigatedToAsync(parameter);
}
mainViewModel.CurrentViewModel = viewModel;
}
/// <summary>
/// 显示主窗口。
/// </summary>
public Task ShowMainWindowAsync()
{
var mainWindow = _serviceProvider.GetRequiredService<MainWindow>();
mainWindow.Show();
return Task.CompletedTask;
}
private Type GetViewModelTypeByKey(string key)
{
return key switch
{
"HomeView" => typeof(HomeViewModel),
"DevicesView" => typeof(DevicesViewModel),
"DeviceDetailView" => typeof(DeviceDetailViewModel),
"VariableTableView" => typeof(VariableTableViewModel),
"MqttsView" => typeof(MqttsViewModel),
"MqttServerDetailView" => typeof(MqttServerDetailViewModel),
"SettingView" => typeof(SettingViewModel),
_ => throw new KeyNotFoundException($"未找到与键 '{key}' 关联的视图模型类型。请检查 NavigationService 的映射配置。")
};
}
}

View File

@@ -0,0 +1,61 @@
// 文件: DMS.WPF/ViewModels/SplashViewModel.cs
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DMS.Application.Interfaces;
using DMS.WPF.Services;
using System;
using System.Threading.Tasks;
using DMS.Application.Services;
namespace DMS.WPF.ViewModels;
/// <summary>
/// 启动加载窗口的ViewModel。
/// </summary>
public partial class SplashViewModel : ObservableObject
{
private readonly IServiceProvider _serviceProvider;
private readonly IInitializeService _initializeService;
[ObservableProperty]
private string _loadingMessage = "正在加载...";
public SplashViewModel(IServiceProvider serviceProvider, IInitializeService initializeService)
{
_serviceProvider = serviceProvider;
_initializeService = initializeService;
}
/// <summary>
/// 开始执行初始化任务。
/// </summary>
public async Task InitializeAsync()
{
try
{
LoadingMessage = "正在初始化数据库...";
_initializeService.InitializeTables();
LoadingMessage = "正在加载系统配置...";
// 可以在这里添加加载配置的逻辑
await Task.Delay(1500); // 模拟耗时
LoadingMessage = "正在连接后台服务...";
// 可以在这里添加连接服务的逻辑
await Task.Delay(1500); // 模拟耗时
LoadingMessage = "加载完成,正在启动主界面...";
await Task.Delay(1500);
// 初始化完成,显示主窗口
var navigationService = (INavigationService)_serviceProvider.GetService(typeof(INavigationService));
await navigationService.ShowMainWindowAsync();
}
catch (Exception ex)
{
// 处理初始化过程中的异常
LoadingMessage = $"初始化失败: {ex.Message}";
// 在此可以记录日志或显示错误对话框
}
}
}

View File

@@ -0,0 +1,18 @@
<Window x:Class="DMS.WPF.Views.SplashWindow"
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:local="clr-namespace:DMS.WPF.Views"
mc:Ignorable="d"
Title="SplashWindow" Height="400" Width="600"
WindowStyle="None" WindowStartupLocation="CenterScreen" AllowsTransparency="True" Background="Transparent">
<Grid>
<Border CornerRadius="10" Background="#FF333333">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Image Source="/Assets/AppIcon.png" Width="100" Height="100"/>
<TextBlock Text="{Binding LoadingMessage}" Foreground="White" FontSize="16" Margin="0,20,0,0"/>
</StackPanel>
</Border>
</Grid>
</Window>

View File

@@ -0,0 +1,22 @@
// 文件: DMS.WPF/Views/SplashWindow.xaml.cs
using DMS.WPF.ViewModels;
using System.Windows;
namespace DMS.WPF.Views;
/// <summary>
/// SplashWindow.xaml 的交互逻辑
/// </summary>
public partial class SplashWindow : Window
{
public SplashWindow(SplashViewModel viewModel)
{
InitializeComponent();
DataContext = viewModel;
Loaded += async (s, e) =>
{
await viewModel.InitializeAsync();
Close();
};
}
}