diff --git a/App.xaml.cs b/App.xaml.cs index 7a0c16d..fd6c215 100644 --- a/App.xaml.cs +++ b/App.xaml.cs @@ -1,4 +1,6 @@ using System.Windows; +using System.Windows.Controls; +using iNKORE.UI.WPF.Modern.Common.IconKeys; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog; @@ -60,11 +62,29 @@ public partial class App : Application { base.OnStartup(e); InitDB(); + // InitMenu(); MainWindow = Services.GetRequiredService(); MainWindow.Show(); } + private void InitMenu() + { + using (var db = DbContext.GetInstance()) + { + List items = new List(); + items.Add(new DbMenu() { Id = 1, Name = "主页", Icon = SegoeFluentIcons.Home.Glyph, ParentId = 0}); + items.Add(new DbMenu() { Id = 1, Name = "设备", Icon = SegoeFluentIcons.Devices.Glyph, ParentId = 0}); + items.Add(new DbMenu() { Id = 1, Name = "数据转换", Icon = SegoeFluentIcons.Move.Glyph, ParentId = 0}); + items.Add(new DbMenu() { Id = 1, Name = "设置", Icon = SegoeFluentIcons.Settings.Glyph, ParentId = 0}); + items.Add(new DbMenu() { Id = 1, Name = "关于", Icon = SegoeFluentIcons.Info.Glyph, ParentId = 0}); + db.Insertable(items).ExecuteCommand(); + } + + + + } + private void InitDB() { var _db = DbContext.GetInstance(); @@ -77,5 +97,6 @@ public partial class App : Application _db.CodeFirst.InitTables(); _db.CodeFirst.InitTables(); _db.CodeFirst.InitTables(); + _db.CodeFirst.InitTables(); } } \ No newline at end of file diff --git a/Data/Entities/DbMenu.cs b/Data/Entities/DbMenu.cs new file mode 100644 index 0000000..4f6572b --- /dev/null +++ b/Data/Entities/DbMenu.cs @@ -0,0 +1,16 @@ +using SqlSugar; + +namespace PMSWPF.Data.Entities; + +[SugarTable("Menu")] +public class DbMenu +{ + [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] + public int Id { get; set; } + public string Icon { get; set; } + public string Name { get; set; } + public int ParentId { get; set; } + + [SugarColumn(IsIgnore = true)] + public List Items { get; set; } +} \ No newline at end of file diff --git a/Data/Repositories/DevicesRepositories.cs b/Data/Repositories/DevicesRepositories.cs index 05498e5..016118f 100644 --- a/Data/Repositories/DevicesRepositories.cs +++ b/Data/Repositories/DevicesRepositories.cs @@ -3,11 +3,17 @@ using PMSWPF.Excptions; using PMSWPF.Extensions; using PMSWPF.Helper; using PMSWPF.Models; +using SqlSugar; namespace PMSWPF.Data.Repositories; -public class DevicesRepositories : BaseRepositories +public class DevicesRepositories { + private SqlSugarClient _db; + public DevicesRepositories() + { + _db = DbContext.GetInstance(); + } public async Task Add(Device device) { var exist = await _db.Queryable().Where(d => d.Name == device.Name).FirstAsync(); @@ -30,8 +36,7 @@ public class DevicesRepositories : BaseRepositories var devices = new List(); foreach (var dbDevice in dlist) { - var device = dbDevice.NewTo(); - device.VariableTables = CovertHelper.ConvertList(dbDevice.VariableTables); + var device = dbDevice.CopyTo(); devices.Add(device); } diff --git a/Data/Repositories/MenuRepositories.cs b/Data/Repositories/MenuRepositories.cs new file mode 100644 index 0000000..4b7c8ba --- /dev/null +++ b/Data/Repositories/MenuRepositories.cs @@ -0,0 +1,25 @@ +using System.Windows.Controls; +using PMSWPF.Data.Entities; +using SqlSugar; + +namespace PMSWPF.Data.Repositories; + +public class MenuRepositories +{ + private readonly SqlSugarClient _db; + + public MenuRepositories() + { + _db=DbContext.GetInstance(); + } + + public async Task> GetMenu() + { + return await _db.Queryable().ToListAsync(); + } + + public async Task AddMenu(DbMenu dbMenu) + { + return await _db.Insertable(dbMenu).ExecuteCommandAsync(); + } +} \ No newline at end of file diff --git a/Extensions/ObjectExtensions.cs b/Extensions/ObjectExtensions.cs index deeaa79..b22def8 100644 --- a/Extensions/ObjectExtensions.cs +++ b/Extensions/ObjectExtensions.cs @@ -1,53 +1,161 @@ -namespace PMSWPF.Extensions; +using System.Collections; +using System.Reflection; + +namespace PMSWPF.Extensions; public static class ObjectExtensions { + /// - /// 对象转换,将source对象上的所有属性的值,都转换到target对象上 + /// 复制一个新的对象并返回 /// - /// - /// - /// - public static void CopyTo(this object source, T target) + /// 源对象 + /// 新的对象类型 + /// 新的对象 + public static T CopyTo(this Object source) where T : new() { - var sourceType = source.GetType(); - var targetType = target.GetType(); - var sourceProperties = sourceType.GetProperties(); - foreach (var sourceProperty in sourceProperties) + T t = new T(); + CopyTo(source, t); + return t; + } + + /// + /// 将可读写的公共属性值从源对象复制到目标对象。 + /// 属性名称和类型必须匹配,或者它们是具有匹配元素名称的泛型List类型。 + /// 对嵌套对象和列表执行深拷贝。 + /// + /// 源对象。 + /// 目标对象。 + public static void CopyTo(this object tsource, object ttarget) + { + // 1. 基本的空值检查,提高健壮性 + if (tsource == null) { - var targetProperty = targetType.GetProperty(sourceProperty.Name); - if (targetProperty != null && targetProperty.CanWrite && sourceProperty.CanRead && - targetProperty.PropertyType == sourceProperty.PropertyType) + // Console.WriteLine("源对象为空。无法复制。"); + throw new ArgumentNullException("源对象为空。无法复制。"); + return; + } + + if (ttarget == null) + { + // Console.WriteLine("目标对象为空。无法复制。"); + throw new ArgumentNullException("目标对象为空。无法复制。"); + return; + } + + Type sourceType = tsource.GetType(); + Type targetType = ttarget.GetType(); + + // 2. 缓存源类型的公共实例属性,避免在循环中重复获取 + PropertyInfo[] sourceProperties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance); + + foreach (PropertyInfo sourceProperty in sourceProperties) + { + // 确保源属性可读 + if (!sourceProperty.CanRead) { - var value = sourceProperty.GetValue(source, null); - targetProperty.SetValue(target, value, null); + continue; + } + + // 在目标类型中查找对应的属性 + PropertyInfo targetProperty = + targetType.GetProperty(sourceProperty.Name, BindingFlags.Public | BindingFlags.Instance); + + // 确保目标属性存在且可写 + if (targetProperty != null && targetProperty.CanWrite) + { + object sourceValue = sourceProperty.GetValue(tsource); + + // 场景 1: 属性类型完全相同 + if (targetProperty.PropertyType == sourceProperty.PropertyType) + { + targetProperty.SetValue(ttarget, sourceValue); + } + // 场景 2: 属性类型不同,但可能是泛型 List 类型 + else + { + bool isSourceList = sourceProperty.PropertyType.IsGenericType && + sourceProperty.PropertyType.GetGenericTypeDefinition() == typeof(List<>); + bool isTargetList = targetProperty.PropertyType.IsGenericType && + targetProperty.PropertyType.GetGenericTypeDefinition() == typeof(List<>); + + if (isSourceList && isTargetList) + { + // 获取源列表的元素类型 + Type sourceListItemType = sourceProperty.PropertyType.GetGenericArguments()[0]; + // 获取目标列表的元素类型 + Type targetListItemType = targetProperty.PropertyType.GetGenericArguments()[0]; + + // 检查列表元素类型名称是否匹配(用于潜在的深拷贝) + if (sourceProperty.Name == targetProperty.Name) + { + // 如果源列表为空,则将目标属性设置为 null + if (sourceValue == null) + { + targetProperty.SetValue(ttarget, null); + continue; + } + + // 将源值强制转换为 IEnumerable 以便遍历 + var sourceList = (IEnumerable)sourceValue; + + // 创建一个目标泛型列表的新实例 + // 假设 CreateGenericList 助手方法可用,或按注释创建 + // var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetListItemType)); + IList targetList = CreateGenericList(targetListItemType); + + foreach (var item in sourceList) + { + // 确保列表项不为空,然后尝试深拷贝 + if (item == null) + { + // 如果源列表项为 null,则直接添加到目标列表 + targetList.Add(null); + continue; + } + + // 创建目标列表元素类型的一个实例 + var targetDataItem = Activator.CreateInstance(targetListItemType); + + // 递归调用 CopyTo,对嵌套对象进行深拷贝 + CopyTo(item, targetDataItem); + + // 将复制后的项添加到目标列表 + targetList.Add(targetDataItem); + } + + // 将填充好的目标列表设置给目标对象的属性 + targetProperty.SetValue(ttarget, targetList); + } + else + { + // 列表类型匹配,但元素类型名称不匹配。此处跳过,或可实现更复杂的转换。 + Console.WriteLine( + $"由于列表元素类型不匹配,跳过属性 '{sourceProperty.Name}':源 '{sourceListItemType.Name}',目标 '{targetListItemType.Name}'"); + } + } + else + { + // 类型不同,且都不是泛型 List。此处跳过,或可实现类型转换。 + Console.WriteLine( + $"由于类型不匹配,跳过属性 '{sourceProperty.Name}':源 '{sourceProperty.PropertyType.Name}',目标 '{targetProperty.PropertyType.Name}'"); + } + } } } } /// - /// 创建一个泛型对象,将source对象上的所有属性的值,都转换到新创建对象上 + /// 辅助方法,用于动态创建泛型 List。 /// - /// - /// - /// - public static T NewTo(this object source) where T : new() + /// 列表应包含的元素类型。 + /// List 的 IList 实例。 + private static IList CreateGenericList(Type itemType) { - var target = new T(); - var sourceType = source.GetType(); - var targetType = target.GetType(); - var sourceProperties = sourceType.GetProperties(); - foreach (var sourceProperty in sourceProperties) - { - var targetProperty = targetType.GetProperty(sourceProperty.Name); - if (targetProperty != null && targetProperty.CanWrite && sourceProperty.CanRead && - targetProperty.PropertyType == sourceProperty.PropertyType) - { - var value = sourceProperty.GetValue(source, null); - targetProperty.SetValue(target, value, null); - } - } - - return target; + Type listType = typeof(List<>).MakeGenericType(itemType); + return (IList)Activator.CreateInstance(listType); } + + + } \ No newline at end of file diff --git a/PMSWPF.csproj b/PMSWPF.csproj index ebf9543..84c5d6c 100644 --- a/PMSWPF.csproj +++ b/PMSWPF.csproj @@ -25,5 +25,8 @@ Always + + + diff --git a/ViewModels/Dialogs/DeviceDialogViewModel.cs b/ViewModels/Dialogs/DeviceDialogViewModel.cs index 71cb80d..418fede 100644 --- a/ViewModels/Dialogs/DeviceDialogViewModel.cs +++ b/ViewModels/Dialogs/DeviceDialogViewModel.cs @@ -23,6 +23,6 @@ public partial class DeviceDialogViewModel : ObservableObject [RelayCommand] public void AddDevice() { - device.CopyTo(_saveDevice); + device.CopyTo(_saveDevice); } } \ No newline at end of file diff --git a/ViewModels/MainViewModel.cs b/ViewModels/MainViewModel.cs index 54878ad..15d8b30 100644 --- a/ViewModels/MainViewModel.cs +++ b/ViewModels/MainViewModel.cs @@ -1,4 +1,7 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using System.Collections.ObjectModel; +using CommunityToolkit.Mvvm.ComponentModel; +using PMSWPF.Data.Entities; +using PMSWPF.Data.Repositories; using PMSWPF.Services; namespace PMSWPF.ViewModels; @@ -8,16 +11,22 @@ public partial class MainViewModel : ViewModelBase private readonly NavgatorServices _navgatorServices; [ObservableProperty] private ViewModelBase currentViewModel; + [ObservableProperty] + private ObservableCollection _menus; public MainViewModel(NavgatorServices navgatorServices) { _navgatorServices = navgatorServices; _navgatorServices.OnViewModelChanged += () => { CurrentViewModel = _navgatorServices.CurrentViewModel; }; CurrentViewModel = new HomeViewModel(); + CurrentViewModel.OnLoaded(); } - public override void OnLoaded() + public override async void OnLoaded() { + MenuRepositories mr = new MenuRepositories(); + var menuList= await mr.GetMenu(); + Menus=new ObservableCollection(menuList); } } \ No newline at end of file diff --git a/Views/MainView.xaml b/Views/MainView.xaml index 9863dec..c86090f 100644 --- a/Views/MainView.xaml +++ b/Views/MainView.xaml @@ -11,7 +11,7 @@ Title="设备管理系统" Width="1080" Height="800" - + ui:WindowHelper.UseModernWindowStyle="True" ui:WindowHelper.SystemBackdropType="Mica" d:DataContext="{d:DesignInstance vm:MainViewModel}"