add - 添加 UI 界面
parent
23b8c8b3a2
commit
a97aca845e
@ -0,0 +1,13 @@
|
||||
<Application xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Sln.Wcs.UI"
|
||||
x:Class="Sln.Wcs.UI.App"
|
||||
RequestedThemeVariant="Dark">
|
||||
<Application.DataTemplates>
|
||||
<local:ViewLocator />
|
||||
</Application.DataTemplates>
|
||||
|
||||
<Application.Styles>
|
||||
<FluentTheme />
|
||||
</Application.Styles>
|
||||
</Application>
|
||||
@ -0,0 +1,110 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Com.Ctrip.Framework.Apollo;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NeoSmart.Caching.Sqlite;
|
||||
using Sln.Wcs.Repository;
|
||||
using Sln.Wcs.Serilog;
|
||||
using Sln.Wcs.UI.ViewModels;
|
||||
using Sln.Wcs.UI.Views;
|
||||
using ZiggyCreatures.Caching.Fusion;
|
||||
using ZiggyCreatures.Caching.Fusion.Serialization.NewtonsoftJson;
|
||||
|
||||
namespace Sln.Wcs.UI;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
// ---- 独立初始化 WCS 后端服务 ----
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// 1. Apollo 配置中心
|
||||
var basePath = AppContext.BaseDirectory;
|
||||
var localConfig = new ConfigurationBuilder()
|
||||
.SetBasePath(basePath)
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.Build();
|
||||
|
||||
services.AddSingleton<IConfiguration>(localConfig);
|
||||
|
||||
var apolloConfigSection = localConfig.GetSection("apollo");
|
||||
var apolloConfig = new ConfigurationBuilder()
|
||||
.SetBasePath(basePath)
|
||||
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
|
||||
.AddApollo(apolloConfigSection)
|
||||
.AddDefault()
|
||||
.Build();
|
||||
|
||||
// 替换为 Apollo 增强配置
|
||||
services.Remove(new ServiceDescriptor(typeof(IConfiguration), localConfig));
|
||||
services.AddSingleton<IConfiguration>(apolloConfig);
|
||||
|
||||
// 2. 加载程序集并扫描注册 DI
|
||||
var assemblies = new[]
|
||||
{
|
||||
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Common.dll")),
|
||||
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Cache.dll")),
|
||||
Assembly.LoadFrom(Path.Combine(basePath, "Sln.Wcs.Repository.dll")),
|
||||
};
|
||||
|
||||
services.Scan(scan => scan.FromAssemblies(assemblies)
|
||||
.AddClasses()
|
||||
.AsImplementedInterfaces()
|
||||
.AsSelf()
|
||||
.WithTransientLifetime());
|
||||
|
||||
// 3. 注册日志
|
||||
services.AddSingleton(typeof(SerilogHelper));
|
||||
|
||||
// 4. SqlSugar + FusionCache
|
||||
services.AddSqlSugarSetup();
|
||||
services.AddFusionCache()
|
||||
.WithSerializer(new FusionCacheNewtonsoftJsonSerializer())
|
||||
.WithDistributedCache(new SqliteCache(new SqliteCacheOptions
|
||||
{
|
||||
CachePath = apolloConfig["cachePath"]!
|
||||
}));
|
||||
|
||||
// 5. 注册 ViewModel
|
||||
services.AddSingleton<ViewModels.NavigationViewModel>();
|
||||
services.AddSingleton<ViewModels.HomePageViewModel>();
|
||||
services.AddTransient<ViewModels.Device.DeviceHostViewModel>();
|
||||
services.AddTransient<ViewModels.Device.DeviceInfoViewModel>();
|
||||
services.AddTransient<ViewModels.Device.DeviceParamViewModel>();
|
||||
services.AddTransient<ViewModels.Base.LocationInfoViewModel>();
|
||||
services.AddTransient<ViewModels.Base.MaterialInfoViewModel>();
|
||||
services.AddTransient<ViewModels.Base.StoreInfoViewModel>();
|
||||
services.AddTransient<ViewModels.Path.PathInfoViewModel>();
|
||||
services.AddTransient<ViewModels.Path.PathDetailsViewModel>();
|
||||
services.AddTransient<ViewModels.Task.TaskQueueViewModel>();
|
||||
services.AddTransient<ViewModels.Task.TaskDetailViewModel>();
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
|
||||
// ---- 启动后初始化 ----
|
||||
|
||||
// 启用 Serilog
|
||||
serviceProvider.UseSerilogExtensions();
|
||||
var config = serviceProvider.GetRequiredService<IConfiguration>();
|
||||
var log = serviceProvider.GetRequiredService<SerilogHelper>();
|
||||
log.Info($"系统启动成功,日志存放位置:{config["logPath"]}");
|
||||
|
||||
// 创建主窗口
|
||||
desktop.MainWindow = new MainWindow(serviceProvider.GetRequiredService<ViewModels.NavigationViewModel>());
|
||||
}
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
using Avalonia;
|
||||
using System;
|
||||
|
||||
namespace Sln.Wcs.UI;
|
||||
|
||||
sealed class Program
|
||||
{
|
||||
[STAThread]
|
||||
public static void Main(string[] args) => BuildAvaloniaApp()
|
||||
.StartWithClassicDesktopLifetime(args);
|
||||
|
||||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.WithInterFont()
|
||||
.LogToTrace();
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AvaloniaResource Include="Assets\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="11.1.5" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="11.1.5" />
|
||||
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.1.5" />
|
||||
<PackageReference Include="Avalonia.Fonts.Inter" Version="11.1.5" />
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="11.1.5" />
|
||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Com.Ctrip.Framework.Apollo" Version="2.11.0" />
|
||||
<PackageReference Include="Com.Ctrip.Framework.Apollo.Configuration" Version="2.11.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
|
||||
<PackageReference Include="Scrutor" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Sln.Wcs.Cache\Sln.Wcs.Cache.csproj" />
|
||||
<ProjectReference Include="..\Sln.Wcs.Common\Sln.Wcs.Common.csproj" />
|
||||
<ProjectReference Include="..\Sln.Wcs.Model\Sln.Wcs.Model.csproj" />
|
||||
<ProjectReference Include="..\Sln.Wcs.Repository\Sln.Wcs.Repository.csproj" />
|
||||
<ProjectReference Include="..\Sln.Wcs.Serilog\Sln.Wcs.Serilog.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@ -0,0 +1,30 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using System;
|
||||
|
||||
namespace Sln.Wcs.UI;
|
||||
|
||||
public class ViewLocator : IDataTemplate
|
||||
{
|
||||
public Control? Build(object? param)
|
||||
{
|
||||
if (param is null)
|
||||
return new TextBlock { Text = "DataContext is null" };
|
||||
|
||||
var viewName = param.GetType().FullName!
|
||||
.Replace("ViewModels", "Views")
|
||||
.Replace("ViewModel", "Window");
|
||||
|
||||
var type = Type.GetType(viewName);
|
||||
if (type is null)
|
||||
return new TextBlock { Text = $"View not found: {viewName}" };
|
||||
|
||||
return (Control)Activator.CreateInstance(type)!;
|
||||
}
|
||||
|
||||
public bool Match(object? data)
|
||||
{
|
||||
return data is ObservableObject;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Sln.Wcs.Repository.service.@base;
|
||||
using Sln.Wcs.UI.Views.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
public interface ICrudPageViewModel
|
||||
{
|
||||
void Load();
|
||||
Avalonia.Controls.Control CreateView();
|
||||
}
|
||||
|
||||
public abstract partial class CrudPageViewModel<T> : ObservableObject, ICrudPageViewModel where T : class, new()
|
||||
{
|
||||
protected readonly IBaseService<T> _service;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<T> _items = new();
|
||||
|
||||
[ObservableProperty]
|
||||
private T? _selectedItem;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _searchText = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _pageTitle = string.Empty;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _statusText = string.Empty;
|
||||
|
||||
public abstract List<FieldConfig> FieldConfigs { get; }
|
||||
public abstract Avalonia.Controls.Control CreateView();
|
||||
|
||||
/// <summary>
|
||||
/// Expression to search by name/code field. Override to customize.
|
||||
/// Returns null to skip filtering (load all).
|
||||
/// </summary>
|
||||
protected abstract Expression<Func<T, bool>>? BuildSearchExpression(string search);
|
||||
|
||||
protected CrudPageViewModel(IBaseService<T> service)
|
||||
{
|
||||
_service = service;
|
||||
AddCommand = new AsyncRelayCommand(Add);
|
||||
EditCommand = new AsyncRelayCommand(Edit);
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void Load()
|
||||
{
|
||||
Console.WriteLine($"[CRUD] Load 调用, T={typeof(T).Name}, SearchText='{SearchText}'");
|
||||
try
|
||||
{
|
||||
List<T> list;
|
||||
if (string.IsNullOrWhiteSpace(SearchText))
|
||||
{
|
||||
Console.WriteLine($"[CRUD] 调用 _service.Query() 无过滤");
|
||||
list = _service.Query();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[CRUD] 调用 _service.Query(expression)");
|
||||
var exp = BuildSearchExpression(SearchText);
|
||||
list = exp != null ? _service.Query(exp) : _service.Query();
|
||||
}
|
||||
Console.WriteLine($"[CRUD] _service.Query() 返回 {list.Count} 条记录");
|
||||
Items = new ObservableCollection<T>(list);
|
||||
StatusText = $"共 {list.Count} 条记录";
|
||||
Console.WriteLine($"[CRUD] Items 已设置, Count={Items.Count}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[CRUD] Load 异常: {ex}");
|
||||
StatusText = $"加载失败: {ex.Message}";
|
||||
}
|
||||
}
|
||||
|
||||
public AsyncRelayCommand AddCommand { get; }
|
||||
public AsyncRelayCommand EditCommand { get; }
|
||||
|
||||
private async System.Threading.Tasks.Task Add()
|
||||
{
|
||||
var entity = new T();
|
||||
var editor = new EntityEditWindow();
|
||||
var result = await editor.ShowDialog(entity, FieldConfigs, false, GetMainWindow());
|
||||
if (result)
|
||||
{
|
||||
_service.Insert(entity);
|
||||
Load();
|
||||
StatusText = "新增成功";
|
||||
}
|
||||
}
|
||||
|
||||
private async System.Threading.Tasks.Task Edit()
|
||||
{
|
||||
if (SelectedItem is null) return;
|
||||
var editor = new EntityEditWindow();
|
||||
var result = await editor.ShowDialog(SelectedItem, FieldConfigs, true, GetMainWindow());
|
||||
if (result)
|
||||
{
|
||||
_service.Update(SelectedItem);
|
||||
Load();
|
||||
StatusText = "编辑成功";
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Delete()
|
||||
{
|
||||
if (SelectedItem is null) return;
|
||||
var prop = typeof(T).GetProperty("objId") ?? typeof(T).GetProperty("ObjId");
|
||||
if (prop is null) return;
|
||||
var id = prop.GetValue(SelectedItem);
|
||||
_service.DeleteById(id!);
|
||||
Load();
|
||||
StatusText = "删除成功";
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void Search()
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
private Avalonia.Controls.Window GetMainWindow()
|
||||
{
|
||||
return (Avalonia.Controls.Window)Avalonia.Application.Current!
|
||||
.ApplicationLifetime!.GetType()
|
||||
.GetProperty("MainWindow")!
|
||||
.GetValue(Avalonia.Application.Current.ApplicationLifetime)!;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
namespace Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
public class FieldConfig
|
||||
{
|
||||
public string PropertyName { get; set; } = string.Empty;
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
public FieldType FieldType { get; set; } = FieldType.Text;
|
||||
public bool IsReadOnly { get; set; }
|
||||
public bool IsRequired { get; set; }
|
||||
}
|
||||
|
||||
public enum FieldType
|
||||
{
|
||||
Text,
|
||||
Number,
|
||||
Combo,
|
||||
CheckBox
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
public class LocationInfoViewModel : CrudPageViewModel<BaseLocationInfo>
|
||||
{
|
||||
public LocationInfoViewModel(IBaseLocationInfoService service) : base(service)
|
||||
{
|
||||
PageTitle = "库位信息管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "locationCode", DisplayName = "库位编号" },
|
||||
new() { PropertyName = "locationName", DisplayName = "库位名称" },
|
||||
new() { PropertyName = "locationArea", DisplayName = "库位区域" },
|
||||
new() { PropertyName = "storeCode", DisplayName = "所属仓库" },
|
||||
new() { PropertyName = "locationRows", DisplayName = "排", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "locationColumns", DisplayName = "列", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "locationLayers", DisplayName = "层", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "agvPosition", DisplayName = "AGV定位" },
|
||||
new() { PropertyName = "materialCode", DisplayName = "物料编号" },
|
||||
new() { PropertyName = "palletBarcode", DisplayName = "托盘条码" },
|
||||
new() { PropertyName = "stackCount", DisplayName = "库存数量" },
|
||||
new() { PropertyName = "locationStatus", DisplayName = "库位状态", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<BaseLocationInfo, bool>>? BuildSearchExpression(string search)
|
||||
=> x => (x.locationCode != null && x.locationCode.Contains(search))
|
||||
|| (x.locationName != null && x.locationName.Contains(search));
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Base.LocationInfoListView();
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
public class MaterialInfoViewModel : CrudPageViewModel<BaseMaterialInfo>
|
||||
{
|
||||
public MaterialInfoViewModel(IBaseMaterialInfoService service) : base(service)
|
||||
{
|
||||
PageTitle = "物料信息管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "materialCode", DisplayName = "物料编号", IsRequired = true },
|
||||
new() { PropertyName = "materialName", DisplayName = "物料名称" },
|
||||
new() { PropertyName = "materialType", DisplayName = "物料类型" },
|
||||
new() { PropertyName = "materialBarcode", DisplayName = "物料条码" },
|
||||
new() { PropertyName = "minStorageCycle", DisplayName = "最短存放周期", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "maxStorageCycle", DisplayName = "最长存放周期", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<BaseMaterialInfo, bool>>? BuildSearchExpression(string search)
|
||||
=> x => x.materialCode.Contains(search) || (x.materialName != null && x.materialName.Contains(search));
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Base.MaterialInfoListView();
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
public class StoreInfoViewModel : CrudPageViewModel<BaseStoreInfo>
|
||||
{
|
||||
public StoreInfoViewModel(IBaseStoreInfoService service) : base(service)
|
||||
{
|
||||
PageTitle = "仓库信息管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "storeCode", DisplayName = "仓库编号", IsRequired = true },
|
||||
new() { PropertyName = "storeName", DisplayName = "仓库名称" },
|
||||
new() { PropertyName = "storeType", DisplayName = "仓库类型", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<BaseStoreInfo, bool>>? BuildSearchExpression(string search)
|
||||
=> x => x.storeCode.Contains(search) || (x.storeName != null && x.storeName.Contains(search));
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Base.StoreInfoListView();
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Device;
|
||||
|
||||
public class DeviceHostViewModel : CrudPageViewModel<BaseDeviceHost>
|
||||
{
|
||||
public DeviceHostViewModel(IBaseDeviceHostService service) : base(service)
|
||||
{
|
||||
PageTitle = "设备主机管理";
|
||||
System.Console.WriteLine("[VM] DeviceHostViewModel 构造, service 类型: " + service.GetType().FullName);
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "hostCode", DisplayName = "主机编号", IsRequired = true },
|
||||
new() { PropertyName = "hostName", DisplayName = "主机名称" },
|
||||
new() { PropertyName = "hostType", DisplayName = "主机类型", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "hostIP", DisplayName = "主机IP" },
|
||||
new() { PropertyName = "hostPort", DisplayName = "主机端口", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "hostPath", DisplayName = "主机路径" },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<BaseDeviceHost, bool>>? BuildSearchExpression(string search)
|
||||
=> x => x.hostCode.Contains(search) || x.hostName.Contains(search);
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Device.DeviceHostListView();
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Device;
|
||||
|
||||
public class DeviceInfoViewModel : CrudPageViewModel<BaseDeviceInfo>
|
||||
{
|
||||
public DeviceInfoViewModel(IBaseDeviceInfoService service) : base(service)
|
||||
{
|
||||
PageTitle = "设备信息管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "deviceCode", DisplayName = "设备编号", IsRequired = true },
|
||||
new() { PropertyName = "deviceName", DisplayName = "设备名称" },
|
||||
new() { PropertyName = "deviceAlias", DisplayName = "设备别名" },
|
||||
new() { PropertyName = "deviceSerialNo", DisplayName = "设备序号", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "deviceType", DisplayName = "设备类型", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "deviceStatus", DisplayName = "设备状态", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "hostCode", DisplayName = "主机编号", IsRequired = true },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<BaseDeviceInfo, bool>>? BuildSearchExpression(string search)
|
||||
=> x => x.deviceCode.Contains(search) || (x.deviceName != null && x.deviceName.Contains(search));
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Device.DeviceInfoListView();
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Device;
|
||||
|
||||
public class DeviceParamViewModel : CrudPageViewModel<BaseDeviceParam>
|
||||
{
|
||||
public DeviceParamViewModel(IBaseDeviceParamService service) : base(service)
|
||||
{
|
||||
PageTitle = "设备参数管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "paramCode", DisplayName = "参数编号", IsRequired = true },
|
||||
new() { PropertyName = "deviceCode", DisplayName = "设备编号", IsRequired = true },
|
||||
new() { PropertyName = "paramName", DisplayName = "参数名称" },
|
||||
new() { PropertyName = "paramAddress", DisplayName = "参数地址" },
|
||||
new() { PropertyName = "paramType", DisplayName = "参数类型" },
|
||||
new() { PropertyName = "paramValue", DisplayName = "参数值", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "operationType", DisplayName = "操作类型" },
|
||||
new() { PropertyName = "operationFrequency", DisplayName = "操作频率(ms)" },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<BaseDeviceParam, bool>>? BuildSearchExpression(string search)
|
||||
=> x => x.paramCode.Contains(search) || x.paramName.Contains(search);
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Device.DeviceParamListView();
|
||||
}
|
||||
@ -0,0 +1,109 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.Serilog;
|
||||
using SqlSugar;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels;
|
||||
|
||||
public partial class MainViewModel : ObservableObject
|
||||
{
|
||||
private readonly SerilogHelper _log;
|
||||
private readonly IConfiguration _config;
|
||||
private readonly IBaseDeviceInfoService _deviceInfoService;
|
||||
private readonly ISqlSugarClient _db;
|
||||
|
||||
[ObservableProperty]
|
||||
private string _appTitle = "基于多场景应用的 WCS 通用平台";
|
||||
|
||||
[ObservableProperty]
|
||||
private string _appVersion = "V1.0.0";
|
||||
|
||||
[ObservableProperty]
|
||||
private string _statusMessage = "系统就绪,点击'加载设备'获取设备列表";
|
||||
|
||||
[ObservableProperty]
|
||||
private int _deviceCount;
|
||||
|
||||
[ObservableProperty]
|
||||
private ObservableCollection<DeviceSummary> _devices = new();
|
||||
|
||||
public MainViewModel(
|
||||
SerilogHelper log,
|
||||
IConfiguration config,
|
||||
IBaseDeviceInfoService deviceInfoService,
|
||||
ISqlSugarClient db)
|
||||
{
|
||||
_log = log;
|
||||
_config = config;
|
||||
_deviceInfoService = deviceInfoService;
|
||||
_db = db;
|
||||
LoadDevicesCommand = new AsyncRelayCommand(LoadDevicesAsync);
|
||||
}
|
||||
|
||||
public AsyncRelayCommand LoadDevicesCommand { get; }
|
||||
|
||||
private async System.Threading.Tasks.Task LoadDevicesAsync()
|
||||
{
|
||||
StatusMessage = "正在加载设备列表...";
|
||||
try
|
||||
{
|
||||
var devices = await System.Threading.Tasks.Task.Run(() =>
|
||||
_deviceInfoService.GetDeviceInfos(x => x.isFlag == 1).ToList());
|
||||
|
||||
Devices.Clear();
|
||||
foreach (var d in devices)
|
||||
{
|
||||
Devices.Add(new DeviceSummary
|
||||
{
|
||||
DeviceCode = d.deviceCode,
|
||||
DeviceName = d.deviceName ?? "",
|
||||
DeviceType = ParseDeviceType(d.deviceType),
|
||||
HostCode = d.hostCode,
|
||||
IsFlag = d.isFlag == 1
|
||||
});
|
||||
}
|
||||
|
||||
DeviceCount = Devices.Count;
|
||||
StatusMessage = $"已加载 {DeviceCount} 台设备";
|
||||
_log.Info($"UI: 设备列表加载完成,共{DeviceCount}台");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusMessage = $"加载设备失败: {ex.Message}";
|
||||
_log.Error($"UI: 设备列表加载失败 - {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
private void RefreshStatus()
|
||||
{
|
||||
var apolloEnv = _config["apollo:Env"] ?? "未知";
|
||||
var logPath = _config["logPath"] ?? "未配置";
|
||||
StatusMessage = $"Apollo环境: {apolloEnv} | 日志路径: {logPath} | 已连接设备: {DeviceCount}";
|
||||
}
|
||||
|
||||
private static string ParseDeviceType(int? deviceType) => deviceType switch
|
||||
{
|
||||
0 => "输送线",
|
||||
1 => "AGV",
|
||||
2 => "提升机",
|
||||
_ => "未知"
|
||||
};
|
||||
}
|
||||
|
||||
public class DeviceSummary
|
||||
{
|
||||
public string DeviceCode { get; set; } = string.Empty;
|
||||
public string DeviceName { get; set; } = string.Empty;
|
||||
public string DeviceType { get; set; } = string.Empty;
|
||||
public string HostCode { get; set; } = string.Empty;
|
||||
public bool IsFlag { get; set; }
|
||||
}
|
||||
@ -0,0 +1,117 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using Avalonia.Controls;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
using Sln.Wcs.UI.ViewModels.Device;
|
||||
using Sln.Wcs.UI.ViewModels.Path;
|
||||
using Sln.Wcs.UI.ViewModels.Task;
|
||||
using Sln.Wcs.UI.Views;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels;
|
||||
|
||||
public partial class NavigationViewModel : ObservableObject
|
||||
{
|
||||
private readonly IServiceProvider _sp;
|
||||
private readonly Dictionary<Type, ICrudPageViewModel> _vmCache = new();
|
||||
private readonly Dictionary<Type, Control> _viewCache = new();
|
||||
private Control? _homeView;
|
||||
|
||||
public ObservableCollection<TopMenuItem> TopMenuItems { get; } = new();
|
||||
|
||||
public event Action<Control?>? PageChanged;
|
||||
|
||||
public NavigationViewModel(IServiceProvider sp)
|
||||
{
|
||||
_sp = sp;
|
||||
BuildMenu();
|
||||
}
|
||||
|
||||
public void LoadDefaultPage() => ShowHome();
|
||||
|
||||
private void BuildMenu()
|
||||
{
|
||||
TopMenuItems.Clear();
|
||||
TopMenuItems.Add(new TopMenuItem("首页", ShowHome));
|
||||
TopMenuItems.Add(new TopMenuItem("基础数据", new List<SubMenuItem>
|
||||
{
|
||||
new("库位信息", () => NavigateTo<LocationInfoViewModel>()),
|
||||
new("物料信息", () => NavigateTo<MaterialInfoViewModel>()),
|
||||
new("仓库信息", () => NavigateTo<StoreInfoViewModel>()),
|
||||
}));
|
||||
TopMenuItems.Add(new TopMenuItem("设备管理", new List<SubMenuItem>
|
||||
{
|
||||
new("设备主机", () => NavigateTo<DeviceHostViewModel>()),
|
||||
new("设备信息", () => NavigateTo<DeviceInfoViewModel>()),
|
||||
new("设备参数", () => NavigateTo<DeviceParamViewModel>()),
|
||||
}));
|
||||
TopMenuItems.Add(new TopMenuItem("路径管理", new List<SubMenuItem>
|
||||
{
|
||||
new("路径信息", () => NavigateTo<PathInfoViewModel>()),
|
||||
new("路径明细", () => NavigateTo<PathDetailsViewModel>()),
|
||||
}));
|
||||
TopMenuItems.Add(new TopMenuItem("任务管理", new List<SubMenuItem>
|
||||
{
|
||||
new("任务队列", () => NavigateTo<TaskQueueViewModel>()),
|
||||
new("任务明细", () => NavigateTo<TaskDetailViewModel>()),
|
||||
}));
|
||||
}
|
||||
|
||||
private void ShowHome()
|
||||
{
|
||||
if (_homeView == null)
|
||||
{
|
||||
var vm = _sp.GetRequiredService<HomePageViewModel>();
|
||||
_homeView = new HomePageView { DataContext = vm };
|
||||
}
|
||||
PageChanged?.Invoke(_homeView);
|
||||
}
|
||||
|
||||
private void NavigateTo<T>() where T : ICrudPageViewModel
|
||||
{
|
||||
var type = typeof(T);
|
||||
if (!_vmCache.TryGetValue(type, out var vm))
|
||||
{
|
||||
vm = _sp.GetRequiredService<T>();
|
||||
_vmCache[type] = vm;
|
||||
}
|
||||
if (!_viewCache.TryGetValue(type, out var view))
|
||||
{
|
||||
view = vm.CreateView();
|
||||
view.DataContext = vm;
|
||||
_viewCache[type] = view;
|
||||
}
|
||||
PageChanged?.Invoke(view);
|
||||
vm.Load();
|
||||
}
|
||||
}
|
||||
|
||||
public class TopMenuItem
|
||||
{
|
||||
public string Label { get; set; }
|
||||
public List<SubMenuItem>? Children { get; set; }
|
||||
public Action? Action { get; set; }
|
||||
|
||||
public TopMenuItem(string label, Action action)
|
||||
{
|
||||
Label = label; Action = action;
|
||||
}
|
||||
|
||||
public TopMenuItem(string label, List<SubMenuItem> children)
|
||||
{
|
||||
Label = label; Children = children;
|
||||
}
|
||||
}
|
||||
|
||||
public class SubMenuItem
|
||||
{
|
||||
public string Label { get; set; }
|
||||
public Action Action { get; set; }
|
||||
|
||||
public SubMenuItem(string label, Action action)
|
||||
{
|
||||
Label = label; Action = action;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Path;
|
||||
|
||||
public class PathDetailsViewModel : CrudPageViewModel<BasePathDetails>
|
||||
{
|
||||
public PathDetailsViewModel(IBasePathDetailsService service) : base(service)
|
||||
{
|
||||
PageTitle = "路径明细管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "pathCode", DisplayName = "路径编号" },
|
||||
new() { PropertyName = "pathName", DisplayName = "路径名称" },
|
||||
new() { PropertyName = "startPoint", DisplayName = "起点" },
|
||||
new() { PropertyName = "endPoint", DisplayName = "终点" },
|
||||
new() { PropertyName = "deviceType", DisplayName = "设备类型", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<BasePathDetails, bool>>? BuildSearchExpression(string search)
|
||||
=> x => (x.pathCode != null && x.pathCode.Contains(search))
|
||||
|| (x.pathName != null && x.pathName.Contains(search));
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Path.PathDetailsListView();
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Path;
|
||||
|
||||
public class PathInfoViewModel : CrudPageViewModel<BasePathInfo>
|
||||
{
|
||||
public PathInfoViewModel(IBasePathInfoService service) : base(service)
|
||||
{
|
||||
PageTitle = "路径信息管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "pathCode", DisplayName = "路径编号" },
|
||||
new() { PropertyName = "pathName", DisplayName = "路径名称" },
|
||||
new() { PropertyName = "pathType", DisplayName = "路径类型", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "pathCategory", DisplayName = "路径类别", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "startPoint", DisplayName = "起点" },
|
||||
new() { PropertyName = "endPoint", DisplayName = "终点" },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<BasePathInfo, bool>>? BuildSearchExpression(string search)
|
||||
=> x => (x.pathCode != null && x.pathCode.Contains(search))
|
||||
|| (x.pathName != null && x.pathName.Contains(search));
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Path.PathInfoListView();
|
||||
}
|
||||
@ -0,0 +1,40 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Task;
|
||||
|
||||
public class TaskDetailViewModel : CrudPageViewModel<LiveTaskDetail>
|
||||
{
|
||||
public TaskDetailViewModel(ILiveTaskDetailService service) : base(service)
|
||||
{
|
||||
PageTitle = "任务明细管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "taskCode", DisplayName = "任务编号" },
|
||||
new() { PropertyName = "pathCode", DisplayName = "路径编号" },
|
||||
new() { PropertyName = "materialCode", DisplayName = "物料编号" },
|
||||
new() { PropertyName = "palletBarcode", DisplayName = "托盘条码" },
|
||||
new() { PropertyName = "materialBarcode", DisplayName = "物料条码" },
|
||||
new() { PropertyName = "materialCount", DisplayName = "物料数量", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "taskType", DisplayName = "任务类型", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "taskCategory", DisplayName = "任务类别", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "startPoint", DisplayName = "起始位置" },
|
||||
new() { PropertyName = "endPoint", DisplayName = "结束位置" },
|
||||
new() { PropertyName = "deviceType", DisplayName = "设备类型", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "isValidate", DisplayName = "校验物料", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "taskStatus", DisplayName = "任务状态", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<LiveTaskDetail, bool>>? BuildSearchExpression(string search)
|
||||
=> x => (x.taskCode != null && x.taskCode.Contains(search))
|
||||
|| (x.materialCode != null && x.materialCode.Contains(search));
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Task.TaskDetailListView();
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Sln.Wcs.Model.Domain;
|
||||
using Sln.Wcs.Repository.service;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.ViewModels.Task;
|
||||
|
||||
public class TaskQueueViewModel : CrudPageViewModel<LiveTaskQueue>
|
||||
{
|
||||
public TaskQueueViewModel(ILiveTaskQueueService service) : base(service)
|
||||
{
|
||||
PageTitle = "任务队列管理";
|
||||
}
|
||||
|
||||
public override List<FieldConfig> FieldConfigs => new()
|
||||
{
|
||||
new() { PropertyName = "taskCode", DisplayName = "任务编号" },
|
||||
new() { PropertyName = "materialCode", DisplayName = "物料编号" },
|
||||
new() { PropertyName = "palletBarcode", DisplayName = "托盘条码" },
|
||||
new() { PropertyName = "materialBarcode", DisplayName = "物料条码" },
|
||||
new() { PropertyName = "materialCount", DisplayName = "物料数量", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "taskType", DisplayName = "任务类型", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "taskCategory", DisplayName = "任务类别", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "startPoint", DisplayName = "起始位置" },
|
||||
new() { PropertyName = "endPoint", DisplayName = "结束位置" },
|
||||
new() { PropertyName = "pathCode", DisplayName = "路径编号" },
|
||||
new() { PropertyName = "taskStatus", DisplayName = "任务状态", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "taskSteps", DisplayName = "任务步骤", FieldType = FieldType.Number },
|
||||
new() { PropertyName = "isFlag", DisplayName = "启用", FieldType = FieldType.CheckBox },
|
||||
new() { PropertyName = "remark", DisplayName = "备注" },
|
||||
};
|
||||
|
||||
protected override Expression<Func<LiveTaskQueue, bool>>? BuildSearchExpression(string search)
|
||||
=> x => (x.taskCode != null && x.taskCode.Contains(search))
|
||||
|| (x.materialCode != null && x.materialCode.Contains(search));
|
||||
|
||||
public override Avalonia.Controls.Control CreateView() => new Sln.Wcs.UI.Views.Task.TaskQueueListView();
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Base.EntityEditWindow"
|
||||
x:CompileBindings="False"
|
||||
SizeToContent="WidthAndHeight"
|
||||
MaxWidth="750" MaxHeight="700"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Title="编辑"
|
||||
Background="#0F1620"
|
||||
Foreground="#BCC8D6"
|
||||
CanResize="False">
|
||||
|
||||
<Grid RowDefinitions="*,Auto" Margin="20,16,20,16">
|
||||
<ScrollViewer Grid.Row="0">
|
||||
<WrapPanel x:Name="FormPanel" />
|
||||
</ScrollViewer>
|
||||
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal"
|
||||
HorizontalAlignment="Right" Spacing="10" Margin="0,16,0,0">
|
||||
<Button x:Name="CancelBtn" Content="取消"
|
||||
Background="#0F1F38" Foreground="#8B9BB5"
|
||||
Padding="22,8" />
|
||||
<Button x:Name="SaveBtn" Content="保存"
|
||||
Background="#1565C0" Foreground="White"
|
||||
Padding="22,8" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Window>
|
||||
@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Base;
|
||||
|
||||
public partial class EntityEditWindow : Window
|
||||
{
|
||||
private object? _entity;
|
||||
private TaskCompletionSource<bool>? _tcs;
|
||||
|
||||
public EntityEditWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
CancelBtn.Click += (_, _) => CloseWith(false);
|
||||
SaveBtn.Click += (_, _) => CloseWith(true);
|
||||
}
|
||||
|
||||
public Task<bool> ShowDialog(object entity, List<FieldConfig> fields, bool isEdit, Window owner)
|
||||
{
|
||||
_entity = entity;
|
||||
Title = isEdit ? "编辑" : "新增";
|
||||
BuildForm(fields);
|
||||
_tcs = new TaskCompletionSource<bool>();
|
||||
ShowDialog(owner);
|
||||
return _tcs.Task;
|
||||
}
|
||||
|
||||
private void BuildForm(List<FieldConfig> fields)
|
||||
{
|
||||
FormPanel.Children.Clear();
|
||||
if (_entity is null) return;
|
||||
var type = _entity.GetType();
|
||||
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var prop = type.GetProperty(field.PropertyName);
|
||||
if (prop is null) continue;
|
||||
var value = prop.GetValue(_entity);
|
||||
|
||||
// 每行一个字段容器: 标题 + 输入框
|
||||
var cell = new Border
|
||||
{
|
||||
Width = 340,
|
||||
Padding = new Thickness(0, 4, 10, 4),
|
||||
};
|
||||
|
||||
var row = new Grid
|
||||
{
|
||||
ColumnDefinitions = new ColumnDefinitions("100,*"),
|
||||
};
|
||||
|
||||
var label = new TextBlock
|
||||
{
|
||||
Text = field.DisplayName + ":",
|
||||
FontSize = 12,
|
||||
Foreground = Brush.Parse("#8B9BB5"),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
row.Children.Add(label);
|
||||
|
||||
Control input;
|
||||
if (field.FieldType == FieldType.CheckBox)
|
||||
{
|
||||
var cb = new CheckBox
|
||||
{
|
||||
IsChecked = value is int iv ? iv == 1 : (value as bool? ?? false),
|
||||
IsEnabled = !field.IsReadOnly,
|
||||
Foreground = Brush.Parse("#DDE4F0"),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
cb.IsCheckedChanged += (_, _) =>
|
||||
prop.SetValue(_entity, cb.IsChecked == true ? 1 : 0);
|
||||
input = cb;
|
||||
}
|
||||
else
|
||||
{
|
||||
var tb = new TextBox
|
||||
{
|
||||
Text = value?.ToString() ?? "",
|
||||
IsReadOnly = field.IsReadOnly,
|
||||
Watermark = field.DisplayName,
|
||||
Background = Brush.Parse("#0C1622"),
|
||||
Foreground = Brush.Parse("#DDE4F0"),
|
||||
BorderBrush = Brush.Parse("#1A2F4A"),
|
||||
};
|
||||
if (field.FieldType == FieldType.Number)
|
||||
{
|
||||
tb.TextChanged += (_, _) =>
|
||||
{
|
||||
if (int.TryParse(tb.Text, out var num))
|
||||
prop.SetValue(_entity, num);
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
tb.TextChanged += (_, _) =>
|
||||
prop.SetValue(_entity, tb.Text);
|
||||
}
|
||||
input = tb;
|
||||
}
|
||||
Grid.SetColumn(input, 1);
|
||||
row.Children.Add(input);
|
||||
|
||||
cell.Child = row;
|
||||
FormPanel.Children.Add(cell);
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseWith(bool result)
|
||||
{
|
||||
_tcs?.TrySetResult(result);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Base.LocationInfoListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索库位编号/名称..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1*,0.8*,0.7*,0.7*,0.5*,0.5*,0.5*,0.8*,1*,0.7*,0.7*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="库位编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="库位名称" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="区域" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="仓库" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="排" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="列" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="层" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="7" Text="AGV定位" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="8" Text="物料编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="9" Text="状态" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="10" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="11" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1*,0.8*,0.7*,0.7*,0.5*,0.5*,0.5*,0.8*,1*,0.7*,0.7*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding locationCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding locationName}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding locationArea}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding storeCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding locationRows}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding locationColumns}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="6" Text="{Binding locationLayers}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="7" Text="{Binding agvPosition}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="8" Text="{Binding materialCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="9" Text="{Binding locationStatus}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="10" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="11" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Base;
|
||||
|
||||
public partial class LocationInfoListView : UserControl
|
||||
{
|
||||
public LocationInfoListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Base.MaterialInfoListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索物料编号/名称..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1.2*,1.3*,0.9*,1.2*,1*,1*,0.8*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="物料编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="物料名称" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="物料条码" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="最短存放" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="最长存放" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="7" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1.2*,1.3*,0.9*,1.2*,1*,1*,0.8*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding materialCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding materialName}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding materialType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding materialBarcode}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding minStorageCycle}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding maxStorageCycle}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="6" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="7" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Base;
|
||||
|
||||
public partial class MaterialInfoListView : UserControl
|
||||
{
|
||||
public MaterialInfoListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Base.StoreInfoListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索仓库编号/名称..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1.2*,1.5*,1*,1*,1*">
|
||||
<TextBlock Grid.Column="0" Text="仓库编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="仓库名称" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="仓库类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1.2*,1.5*,1*,1*,1*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding storeCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding storeName}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding storeType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="4" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Base;
|
||||
|
||||
public partial class StoreInfoListView : UserControl
|
||||
{
|
||||
public StoreInfoListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Device.DeviceHostListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索主机编号/名称..." Text="{Binding SearchText}" Width="260"
|
||||
Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1.5*,1.5*,0.8*,1.2*,0.8*,1.2*,1*,1.2*">
|
||||
<TextBlock Grid.Column="0" Text="主机编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="主机名称" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="主机IP" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="端口" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="路径" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="7" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
|
||||
Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1.5*,1.5*,0.8*,1.2*,0.8*,1.2*,1*,1.2*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding hostCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding hostName}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding hostType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding hostIP}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding hostPort}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding hostPath}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="6" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="7" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click"
|
||||
Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click"
|
||||
Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Device;
|
||||
|
||||
public partial class DeviceHostListView : UserControl
|
||||
{
|
||||
public DeviceHostListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Device.DeviceInfoListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索设备编号/名称..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1.2*,1.2*,0.8*,0.7*,0.7*,1*,0.8*,0.8*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="设备编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="设备名称" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="别名" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="状态" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="主机编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="序号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="7" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="8" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1.2*,1.2*,0.8*,0.7*,0.7*,1*,0.8*,0.8*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding deviceCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding deviceName}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding deviceAlias}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding deviceType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding deviceStatus}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding hostCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="6" Text="{Binding deviceSerialNo}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="7" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="8" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Device;
|
||||
|
||||
public partial class DeviceInfoListView : UserControl
|
||||
{
|
||||
public DeviceInfoListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Device.DeviceParamListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索参数编号/名称..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1*,1*,1.2*,1*,0.7*,0.6*,0.7*,0.7*,0.7*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="参数编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="设备编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="参数名称" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="参数地址" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="值" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="7" Text="频率" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="8" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="9" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1*,1*,1.2*,1*,0.7*,0.6*,0.7*,0.7*,0.7*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding paramCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding deviceCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding paramName}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding paramAddress}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding paramType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding paramValue}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="6" Text="{Binding operationType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="7" Text="{Binding operationFrequency}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="8" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="9" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Device;
|
||||
|
||||
public partial class DeviceParamListView : UserControl
|
||||
{
|
||||
public DeviceParamListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace Sln.Wcs.UI.Views;
|
||||
|
||||
public partial class HomePageView : UserControl
|
||||
{
|
||||
public HomePageView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
<Window xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:Sln.Wcs.UI.ViewModels"
|
||||
x:Class="Sln.Wcs.UI.Views.MainWindow"
|
||||
x:DataType="vm:NavigationViewModel"
|
||||
Title="基于多场景应用的 WCS 通用平台"
|
||||
Width="1280" Height="780"
|
||||
MinWidth="1000" MinHeight="600"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Background="#0A0E14"
|
||||
Foreground="#BCC8D6">
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,*">
|
||||
|
||||
<!-- Title Bar -->
|
||||
<Border Grid.Row="0" Padding="16,10" Background="#0A0E14">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12" VerticalAlignment="Center">
|
||||
<Canvas Width="24" Height="24">
|
||||
<Rectangle Canvas.Left="1" Canvas.Top="1" Width="22" Height="18" RadiusX="2" RadiusY="2" Fill="#0F1F38" Stroke="#4FC3F7" StrokeThickness="1.2" />
|
||||
<Rectangle Canvas.Left="4" Canvas.Top="4" Width="16" Height="5" RadiusX="1" RadiusY="1" Fill="#1B3A5C" />
|
||||
<Line StartPoint="5,11" EndPoint="19,11" Stroke="#1B3A5C" StrokeThickness="1" />
|
||||
<Ellipse Canvas.Left="5" Canvas.Top="5" Width="2" Height="2" Fill="#00E676" />
|
||||
<Ellipse Canvas.Left="9" Canvas.Top="5" Width="2" Height="2" Fill="#4FC3F7" />
|
||||
</Canvas>
|
||||
<TextBlock Text="基于多场景应用的 WCS 通用平台" FontSize="16" FontWeight="Bold" Foreground="#E1E8F0" />
|
||||
<Border Background="#1B3A5C" CornerRadius="3" Padding="6,2" VerticalAlignment="Center">
|
||||
<TextBlock Text="V1.0.0" FontSize="10" Foreground="#4FC3F7" />
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Menu Bar -->
|
||||
<Border Grid.Row="1" Padding="16,0" Background="#0C1622" BorderBrush="#1A2F4A" BorderThickness="0,1,0,1">
|
||||
<StackPanel x:Name="MenuContainer" Orientation="Horizontal" Spacing="0" />
|
||||
</Border>
|
||||
|
||||
<!-- Content Area -->
|
||||
<Border Grid.Row="2" x:Name="ContentArea" />
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
@ -0,0 +1,177 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Sln.Wcs.UI.ViewModels;
|
||||
|
||||
namespace Sln.Wcs.UI.Views;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private readonly NavigationViewModel _navVm;
|
||||
private readonly List<Popup> _openPopups = new();
|
||||
|
||||
public MainWindow(NavigationViewModel navigationVm)
|
||||
{
|
||||
InitializeComponent();
|
||||
_navVm = navigationVm;
|
||||
DataContext = _navVm;
|
||||
|
||||
_navVm.PageChanged += OnPageChanged;
|
||||
BuildMenu();
|
||||
_navVm.LoadDefaultPage();
|
||||
}
|
||||
|
||||
private void BuildMenu()
|
||||
{
|
||||
MenuContainer.Children.Clear();
|
||||
foreach (var item in _navVm.TopMenuItems)
|
||||
{
|
||||
var btn = new Button
|
||||
{
|
||||
Content = item.Label,
|
||||
Background = Brushes.Transparent,
|
||||
Foreground = Brush.Parse("#8B9BB5"),
|
||||
FontSize = 13,
|
||||
Padding = new Thickness(14, 12),
|
||||
Cursor = new Cursor(StandardCursorType.Hand),
|
||||
BorderThickness = new Thickness(0),
|
||||
};
|
||||
|
||||
if (item.Action != null)
|
||||
{
|
||||
btn.Click += (_, _) => item.Action();
|
||||
}
|
||||
|
||||
if (item.Children != null && item.Children.Count > 0)
|
||||
{
|
||||
var popup = new Popup
|
||||
{
|
||||
PlacementTarget = btn,
|
||||
Placement = PlacementMode.Bottom,
|
||||
IsLightDismissEnabled = false,
|
||||
};
|
||||
|
||||
var popupBorder = new Border
|
||||
{
|
||||
Background = Brush.Parse("#0F1620"),
|
||||
BorderBrush = Brush.Parse("#1A2F4A"),
|
||||
BorderThickness = new Thickness(1),
|
||||
CornerRadius = new CornerRadius(4),
|
||||
MinWidth = 160,
|
||||
};
|
||||
|
||||
var stack = new StackPanel { Margin = new Thickness(4) };
|
||||
foreach (var sub in item.Children)
|
||||
{
|
||||
var subBtn = new Button
|
||||
{
|
||||
Content = sub.Label,
|
||||
Background = Brushes.Transparent,
|
||||
Foreground = Brush.Parse("#8B9BB5"),
|
||||
FontSize = 12,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
HorizontalContentAlignment = HorizontalAlignment.Left,
|
||||
Padding = new Thickness(12, 8),
|
||||
BorderThickness = new Thickness(0),
|
||||
Cursor = new Cursor(StandardCursorType.Hand),
|
||||
};
|
||||
subBtn.Click += (_, _) =>
|
||||
{
|
||||
popup.Close();
|
||||
sub.Action();
|
||||
};
|
||||
subBtn.PointerEntered += (_, _) =>
|
||||
subBtn.Background = Brush.Parse("#1B3A5C");
|
||||
subBtn.PointerExited += (_, _) =>
|
||||
subBtn.Background = Brushes.Transparent;
|
||||
stack.Children.Add(subBtn);
|
||||
}
|
||||
popupBorder.Child = stack;
|
||||
popup.Child = popupBorder;
|
||||
|
||||
// Hover 展开,离开按钮或 popup 时关闭
|
||||
var closeTimer = new System.Timers.Timer(200) { AutoReset = false };
|
||||
bool mouseInPopup = false;
|
||||
bool mouseInButton = false;
|
||||
|
||||
popupBorder.PointerEntered += (_, _) => { mouseInPopup = true; closeTimer.Stop(); };
|
||||
popupBorder.PointerExited += (_, _) => { mouseInPopup = false; TryClose(); };
|
||||
|
||||
btn.PointerEntered += (_, _) =>
|
||||
{
|
||||
mouseInButton = true;
|
||||
closeTimer.Stop();
|
||||
btn.Background = Brush.Parse("#1B3A5C");
|
||||
btn.Foreground = Brush.Parse("#4FC3F7");
|
||||
CloseAllPopups();
|
||||
popup.Open();
|
||||
};
|
||||
btn.PointerExited += (_, _) =>
|
||||
{
|
||||
mouseInButton = false;
|
||||
TryClose();
|
||||
};
|
||||
|
||||
void TryClose()
|
||||
{
|
||||
closeTimer.Stop();
|
||||
closeTimer.Start();
|
||||
closeTimer.Elapsed += (_, _) =>
|
||||
{
|
||||
Avalonia.Threading.Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (!mouseInButton && !mouseInPopup)
|
||||
{
|
||||
popup.Close();
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
popup.Closed += (_, _) =>
|
||||
{
|
||||
btn.Background = Brushes.Transparent;
|
||||
btn.Foreground = Brush.Parse("#8B9BB5");
|
||||
};
|
||||
_openPopups.Add(popup);
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.PointerEntered += (_, _) =>
|
||||
{
|
||||
btn.Background = Brush.Parse("#1B3A5C");
|
||||
btn.Foreground = Brush.Parse("#4FC3F7");
|
||||
};
|
||||
btn.PointerExited += (_, _) =>
|
||||
{
|
||||
btn.Background = Brushes.Transparent;
|
||||
btn.Foreground = Brush.Parse("#8B9BB5");
|
||||
};
|
||||
}
|
||||
|
||||
MenuContainer.Children.Add(btn);
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseAllPopups()
|
||||
{
|
||||
foreach (var p in _openPopups)
|
||||
p.Close();
|
||||
}
|
||||
|
||||
private void OnPageChanged(Control? view)
|
||||
{
|
||||
if (view != null)
|
||||
{
|
||||
view.HorizontalAlignment = HorizontalAlignment.Stretch;
|
||||
view.VerticalAlignment = VerticalAlignment.Stretch;
|
||||
ContentArea.Child = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Path.PathDetailsListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索路径编号/名称..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1.2*,1.3*,1.2*,1.2*,0.8*,0.8*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="路径编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="路径名称" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="起点" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="终点" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="设备类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1.2*,1.3*,1.2*,1.2*,0.8*,0.8*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding pathCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding pathName}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding startPoint}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding endPoint}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding deviceType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="6" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Path;
|
||||
|
||||
public partial class PathDetailsListView : UserControl
|
||||
{
|
||||
public PathDetailsListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Path.PathInfoListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索路径编号/名称..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1.2*,1.3*,0.8*,0.8*,1.2*,1.2*,0.8*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="路径编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="路径名称" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="路径类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="路径类别" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="起点" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="终点" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="7" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1.2*,1.3*,0.8*,0.8*,1.2*,1.2*,0.8*,0.8*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding pathCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding pathName}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding pathType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding pathCategory}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding startPoint}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding endPoint}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="6" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="7" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Path;
|
||||
|
||||
public partial class PathInfoListView : UserControl
|
||||
{
|
||||
public PathInfoListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Task.TaskDetailListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索任务编号/物料编号..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1.2*,0.9*,1*,1.1*,0.6*,0.6*,0.6*,0.9*,0.9*,0.7*,0.7*,0.7*,0.7*">
|
||||
<TextBlock Grid.Column="0" Text="任务编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="路径编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="物料编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="托盘条码" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="数量" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="类别" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="7" Text="起始位置" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="8" Text="结束位置" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="9" Text="设备" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="10" Text="状态" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="11" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="12" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1.2*,0.9*,1*,1.1*,0.6*,0.6*,0.6*,0.9*,0.9*,0.7*,0.7*,0.7*,0.7*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding taskCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding pathCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding materialCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding palletBarcode}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding materialCount}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding taskType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="6" Text="{Binding taskCategory}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="7" Text="{Binding startPoint}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="8" Text="{Binding endPoint}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="9" Text="{Binding deviceType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="10" Text="{Binding taskStatus}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="11" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="12" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Task;
|
||||
|
||||
public partial class TaskDetailListView : UserControl
|
||||
{
|
||||
public TaskDetailListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
<UserControl x:CompileBindings="False" xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="Sln.Wcs.UI.Views.Task.TaskQueueListView">
|
||||
<Grid RowDefinitions="Auto,Auto,*" Margin="4" VerticalAlignment="Stretch">
|
||||
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto" Margin="0,0,0,8">
|
||||
<TextBox Grid.Column="0" Watermark="搜索任务编号/物料编号..." Text="{Binding SearchText}" Width="260" Background="#0C1622" Foreground="#DDE4F0" BorderBrush="#1A2F4A" />
|
||||
<Button Grid.Column="1" Content="搜索" Command="{Binding SearchCommand}" Background="#0F1F38" Foreground="#8B9BB5" Padding="14,6" Margin="8,0,0,0" />
|
||||
<Button Grid.Column="2" Content="新增" Command="{Binding AddCommand}" Background="#1565C0" Foreground="White" Padding="14,6" Margin="8,0,0,0" />
|
||||
</Grid>
|
||||
<Border Grid.Row="1" Background="#0C1622" Padding="8,6" BorderBrush="#1A2F4A" BorderThickness="1">
|
||||
<Grid ColumnDefinitions="1.2*,1*,1.2*,0.6*,0.6*,0.6*,1*,1*,0.7*,0.6*,0.8*,0.7*">
|
||||
<TextBlock Grid.Column="0" Text="任务编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="1" Text="物料编号" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="2" Text="托盘条码" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="3" Text="数量" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="4" Text="类型" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="5" Text="类别" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="6" Text="起始位置" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="7" Text="结束位置" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="8" Text="状态" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="9" Text="步骤" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="10" Text="备注" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
<TextBlock Grid.Column="11" Text="操作" FontSize="12" FontWeight="SemiBold" Foreground="#8B9BB5" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ListBox Grid.Row="2" ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Background="#0F1620" Foreground="#DDE4F0" BorderBrush="#1A2F4A" BorderThickness="1,0,1,1">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Border Padding="8,4" BorderBrush="#1A2F4A" BorderThickness="0,0,0,1">
|
||||
<Grid ColumnDefinitions="1.2*,1*,1.2*,0.6*,0.6*,0.6*,1*,1*,0.7*,0.6*,0.8*,0.7*">
|
||||
<TextBlock Grid.Column="0" Text="{Binding taskCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Text="{Binding materialCode}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="2" Text="{Binding palletBarcode}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Text="{Binding materialCount}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Text="{Binding taskType}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="5" Text="{Binding taskCategory}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="6" Text="{Binding startPoint}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="7" Text="{Binding endPoint}" Foreground="#64B5F6" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="8" Text="{Binding taskStatus}" Foreground="#8B9BB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="9" Text="{Binding taskSteps}" Foreground="#DDE4F0" FontSize="12" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="10" Text="{Binding remark}" Foreground="#6B8CB5" FontSize="12" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="11" Orientation="Horizontal" Spacing="6">
|
||||
<Button Content="编辑" Tag="{Binding}" Click="Edit_Click" Background="#0277BD" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
<Button Content="删除" Tag="{Binding}" Click="Delete_Click" Background="#B71C1C" Foreground="White" FontSize="11" Padding="8,3" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@ -0,0 +1,31 @@
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Sln.Wcs.UI.ViewModels.Base;
|
||||
|
||||
namespace Sln.Wcs.UI.Views.Task;
|
||||
|
||||
public partial class TaskQueueListView : UserControl
|
||||
{
|
||||
public TaskQueueListView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Edit_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("EditCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void Delete_Click(object? sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button btn && btn.Tag != null && DataContext is ICrudPageViewModel vm)
|
||||
{
|
||||
vm.GetType().GetProperty("SelectedItem")?.SetValue(vm, btn.Tag);
|
||||
(vm.GetType().GetProperty("DeleteCommand")?.GetValue(vm) as System.Windows.Input.ICommand)?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
@ -0,0 +1,18 @@
|
||||
{
|
||||
"exclude": [
|
||||
"**/bin",
|
||||
"**/bower_components",
|
||||
"**/jspm_packages",
|
||||
"**/node_modules",
|
||||
"**/obj",
|
||||
"**/platforms"
|
||||
],
|
||||
"apollo": {
|
||||
"AppId": "SlnWcs",
|
||||
"Env": "DEV",
|
||||
"MetaServer": "http://119.45.202.115:4320",
|
||||
"ConfigServer": [
|
||||
"http://119.45.202.115:4320"
|
||||
]
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue