From fd0445a4d4d59bb099f18ff3d849917988012259 Mon Sep 17 00:00:00 2001
From: anerx <512464164@qq.com>
Date: Mon, 7 Apr 2025 23:25:45 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E7=89=88=E6=9C=AC?=
=?UTF-8?q?=E7=9A=84UI?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../Entities/VarietyEntity.cs | 20 +-
Seyounth.Hyosung.Data/Models/Pallet.cs | 20 +-
Seyounth.Hyosung.Data/Models/PalletType.cs | 2 +-
Seyounth.Hyosung.Data/ServiceExtensions.cs | 42 +-
.../Services/VarietyService.cs | 32 +-
Seyounth.Hyosung.UI/App.xaml | 17 +
Seyounth.Hyosung.UI/App.xaml.cs | 105 ++++
Seyounth.Hyosung.UI/AssemblyInfo.cs | 10 +
.../Assets/wpfui-icon-1024.png | Bin 0 -> 10779 bytes
Seyounth.Hyosung.UI/Assets/wpfui-icon-256.png | Bin 0 -> 4391 bytes
.../Helpers/EnumBindingSourceExtension.cs | 21 +
.../Helpers/EnumDescriptionConverter.cs | 23 +
.../Helpers/EnumToBooleanConverter.cs | 36 ++
Seyounth.Hyosung.UI/Models/AppConfig.cs | 9 +
Seyounth.Hyosung.UI/Models/DataColor.cs | 9 +
Seyounth.Hyosung.UI/Resources/Translations.cs | 6 +
.../Services/ApplicationHostService.cs | 59 ++
Seyounth.Hyosung.UI/Services/PageService.cs | 42 ++
.../Seyounth.Hyosung.UI.csproj | 38 ++
Seyounth.Hyosung.UI/Usings.cs | 4 +
.../ViewModels/Pages/DashboardViewModel.cs | 100 ++++
.../ViewModels/Pages/DataViewModel.cs | 100 ++++
.../Pages/PalletManagementViewModel.cs | 72 +++
.../ViewModels/Pages/SettingsViewModel.cs | 63 +++
.../ViewModels/Windows/MainWindowViewModel.cs | 69 +++
.../Views/Pages/DashboardPage.xaml | 99 ++++
.../Views/Pages/DashboardPage.xaml.cs | 19 +
Seyounth.Hyosung.UI/Views/Pages/DataPage.xaml | 261 +++++++++
.../Views/Pages/DataPage.xaml.cs | 80 +++
.../Views/Pages/PalletManagementPage.xaml | 87 +++
.../Views/Pages/PalletManagementPage.xaml.cs | 83 +++
.../Views/Pages/SettingsPage.xaml | 51 ++
.../Views/Pages/SettingsPage.xaml.cs | 18 +
.../Windows/AddOrUpdatePalletWindow.xaml | 13 +
.../Windows/AddOrUpdatePalletWindow.xaml.cs | 9 +
.../Views/Windows/MainWindow.xaml | 65 +++
.../Views/Windows/MainWindow.xaml.cs | 65 +++
Seyounth.Hyosung.UI/app.manifest | 75 +++
Seyounth.Hyosung.UI/appsettings.json | 5 +
Seyounth.Hyosung.UI/wpfui-icon.ico | Bin 0 -> 19438 bytes
Seyounth.Hyosung.sln | 26 +-
Seyounth.Hyosung/App.xaml | 133 ++++-
Seyounth.Hyosung/Seyounth.Hyosung.csproj | 2 +-
Seyounth.Hyosung/Views/MainWindow.xaml | 524 +++++++++++++-----
44 files changed, 2325 insertions(+), 189 deletions(-)
create mode 100644 Seyounth.Hyosung.UI/App.xaml
create mode 100644 Seyounth.Hyosung.UI/App.xaml.cs
create mode 100644 Seyounth.Hyosung.UI/AssemblyInfo.cs
create mode 100644 Seyounth.Hyosung.UI/Assets/wpfui-icon-1024.png
create mode 100644 Seyounth.Hyosung.UI/Assets/wpfui-icon-256.png
create mode 100644 Seyounth.Hyosung.UI/Helpers/EnumBindingSourceExtension.cs
create mode 100644 Seyounth.Hyosung.UI/Helpers/EnumDescriptionConverter.cs
create mode 100644 Seyounth.Hyosung.UI/Helpers/EnumToBooleanConverter.cs
create mode 100644 Seyounth.Hyosung.UI/Models/AppConfig.cs
create mode 100644 Seyounth.Hyosung.UI/Models/DataColor.cs
create mode 100644 Seyounth.Hyosung.UI/Resources/Translations.cs
create mode 100644 Seyounth.Hyosung.UI/Services/ApplicationHostService.cs
create mode 100644 Seyounth.Hyosung.UI/Services/PageService.cs
create mode 100644 Seyounth.Hyosung.UI/Seyounth.Hyosung.UI.csproj
create mode 100644 Seyounth.Hyosung.UI/Usings.cs
create mode 100644 Seyounth.Hyosung.UI/ViewModels/Pages/DashboardViewModel.cs
create mode 100644 Seyounth.Hyosung.UI/ViewModels/Pages/DataViewModel.cs
create mode 100644 Seyounth.Hyosung.UI/ViewModels/Pages/PalletManagementViewModel.cs
create mode 100644 Seyounth.Hyosung.UI/ViewModels/Pages/SettingsViewModel.cs
create mode 100644 Seyounth.Hyosung.UI/ViewModels/Windows/MainWindowViewModel.cs
create mode 100644 Seyounth.Hyosung.UI/Views/Pages/DashboardPage.xaml
create mode 100644 Seyounth.Hyosung.UI/Views/Pages/DashboardPage.xaml.cs
create mode 100644 Seyounth.Hyosung.UI/Views/Pages/DataPage.xaml
create mode 100644 Seyounth.Hyosung.UI/Views/Pages/DataPage.xaml.cs
create mode 100644 Seyounth.Hyosung.UI/Views/Pages/PalletManagementPage.xaml
create mode 100644 Seyounth.Hyosung.UI/Views/Pages/PalletManagementPage.xaml.cs
create mode 100644 Seyounth.Hyosung.UI/Views/Pages/SettingsPage.xaml
create mode 100644 Seyounth.Hyosung.UI/Views/Pages/SettingsPage.xaml.cs
create mode 100644 Seyounth.Hyosung.UI/Views/Windows/AddOrUpdatePalletWindow.xaml
create mode 100644 Seyounth.Hyosung.UI/Views/Windows/AddOrUpdatePalletWindow.xaml.cs
create mode 100644 Seyounth.Hyosung.UI/Views/Windows/MainWindow.xaml
create mode 100644 Seyounth.Hyosung.UI/Views/Windows/MainWindow.xaml.cs
create mode 100644 Seyounth.Hyosung.UI/app.manifest
create mode 100644 Seyounth.Hyosung.UI/appsettings.json
create mode 100644 Seyounth.Hyosung.UI/wpfui-icon.ico
diff --git a/Seyounth.Hyosung.Data/Entities/VarietyEntity.cs b/Seyounth.Hyosung.Data/Entities/VarietyEntity.cs
index eb09ce4..d968df5 100644
--- a/Seyounth.Hyosung.Data/Entities/VarietyEntity.cs
+++ b/Seyounth.Hyosung.Data/Entities/VarietyEntity.cs
@@ -6,7 +6,7 @@ namespace Seyounth.Hyosung.Data.Entities;
[SugarTable("system_variety", TableDescription = "品种表")]
public class VarietyEntity
{
- [SugarColumn(IsPrimaryKey = true, IsIdentity = true, ColumnDescription = "主键")]
+ [SugarColumn(IsPrimaryKey = true, ColumnDescription = "主键")]
public int Id { get; set; }
[SugarColumn(ColumnDescription = "品种代码")]
@@ -51,13 +51,13 @@ public class VarietyEntity
[SugarColumn(ColumnDescription = "托盘ID")]
public int TrayId { get; set; }
- [SugarColumn(ColumnDescription = "垛头尺寸")]
+ [SugarColumn(ColumnDescription = "垛头尺寸", IsNullable = true)]
public string? StackHeadSpec { get; set; }
[SugarColumn(ColumnDescription = "垛头数量")]
public int? StackHeadCount { get; set; }
- [SugarColumn(ColumnDescription = "纸托Id",IsNullable =true)]
+ [SugarColumn(ColumnDescription = "纸托Id", IsNullable = true)]
public int? PaperTrayId { get; set; }
[SugarColumn(ColumnDescription = "是否需要纸箱")]
@@ -84,13 +84,9 @@ public class VarietyEntity
[SugarColumn(ColumnDescription = "副标签数量")]
public int SubLabelCount { get; set; }
- [SugarColumn(IsNullable =true)]
- public int? LastNo { get; set; }
-
- [SugarColumn(IsNullable =true)]
- public double? NetWeight { get; set; }
-
- [SugarColumn(IsNullable =true)]
- public double? GrossWeight { get; set; }
-
+ [SugarColumn(IsNullable = true)] public int? LastNo { get; set; }
+
+ [SugarColumn(IsNullable = true)] public double? NetWeight { get; set; }
+
+ [SugarColumn(IsNullable = true)] public double? GrossWeight { get; set; }
}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Models/Pallet.cs b/Seyounth.Hyosung.Data/Models/Pallet.cs
index e061fdc..44400c6 100644
--- a/Seyounth.Hyosung.Data/Models/Pallet.cs
+++ b/Seyounth.Hyosung.Data/Models/Pallet.cs
@@ -5,8 +5,24 @@ namespace Seyounth.Hyosung.Data.Models;
public class Pallet : PalletEntity
{
- public string Name =>
- $"{Type.GetDescription()}({Width}*{Height}*{Length})({HoleCount}|{(IsBigHole != null && IsBigHole.Value ? "大" : "小")})";
+ public string Name
+ {
+ get
+ {
+ if (Type == PalletType.Honey)
+ {
+ return
+ $"{Type.GetDescription()}({Width}*{Length}*{Height})({HoleCount}|{(IsBigHole != null && IsBigHole.Value ? "大" : "小")})";
+ }
+ else if (Length != 0)
+ {
+ return $"{Type.GetDescription()}({Width}*{Length}*{Height})";
+ }
+ else return "无";
+ }
+
+ }
+
public static Pallet FromEntity(PalletEntity p)
{
diff --git a/Seyounth.Hyosung.Data/Models/PalletType.cs b/Seyounth.Hyosung.Data/Models/PalletType.cs
index e257c11..b4a4db7 100644
--- a/Seyounth.Hyosung.Data/Models/PalletType.cs
+++ b/Seyounth.Hyosung.Data/Models/PalletType.cs
@@ -12,7 +12,7 @@ public enum PalletType
///
/// 胶合板托盘
///
- [Description("胶合板")] Plywood = 1,
+ [Description("胶托")] Plywood = 1,
///
/// 木板托盘
diff --git a/Seyounth.Hyosung.Data/ServiceExtensions.cs b/Seyounth.Hyosung.Data/ServiceExtensions.cs
index 439ce32..6f10bb9 100644
--- a/Seyounth.Hyosung.Data/ServiceExtensions.cs
+++ b/Seyounth.Hyosung.Data/ServiceExtensions.cs
@@ -18,21 +18,21 @@ public static class ServiceExtensions
{
//#if RELEASE
SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
- {
- DbType = DbType.SqlServer,
- ConnectionString = connectionString,
- IsAutoCloseConnection = true,
- }
+ {
+ DbType = DbType.SqlServer,
+ ConnectionString = connectionString,
+ IsAutoCloseConnection = true,
+ }
);
//#elif DEBUG
- //SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
- // {
- // DbType = DbType.Sqlite,
- // ConnectionString = "Data Source=hyosung.db",
- // IsAutoCloseConnection = true,
- // InitKeyType = InitKeyType.Attribute
- // }
- //);
+ // SqlSugarScope sqlSugar = new SqlSugarScope(new ConnectionConfig()
+ // {
+ // DbType = DbType.Sqlite,
+ // ConnectionString = "Data Source=hyosung.db",
+ // IsAutoCloseConnection = true,
+ // InitKeyType = InitKeyType.Attribute
+ // }
+ // );
//#endif
return sqlSugar;
});
@@ -50,13 +50,13 @@ public static class ServiceExtensions
public static void UseHyosungData(this IServiceProvider provider)
{
- //var db = provider.GetRequiredService();
- //db.DbMaintenance.CreateDatabase();
- //db.CodeFirst.InitTables(typeof(VarietyEntity),
- // typeof(PalletEntity),
- // typeof(ScannedYarnEntity),
- // typeof(TrayEntity),
- // typeof(AgvBinEntity),
- // typeof(DictEntity));
+ var db = provider.GetRequiredService();
+ db.DbMaintenance.CreateDatabase();
+ db.CodeFirst.InitTables(typeof(VarietyEntity),
+ typeof(PalletEntity),
+ typeof(ScannedYarnEntity),
+ typeof(TrayEntity),
+ typeof(AgvBinEntity),
+ typeof(DictEntity));
}
}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.Data/Services/VarietyService.cs b/Seyounth.Hyosung.Data/Services/VarietyService.cs
index 78a42a6..902a27f 100644
--- a/Seyounth.Hyosung.Data/Services/VarietyService.cs
+++ b/Seyounth.Hyosung.Data/Services/VarietyService.cs
@@ -19,10 +19,10 @@ public class VarietyService : IVarietyService
{
_varietyRepository =
provider.CreateScope().ServiceProvider.GetRequiredService>();
- _palletRepository = provider.CreateScope().ServiceProvider.GetRequiredService>();
+ _palletRepository = provider.CreateScope().ServiceProvider.GetRequiredService>();
//_varietyRepository = provider.GetService>();
- // _palletRepository = provider.GetService>();
- _varietiesCache = new List(_varietyRepository.GetList());
+ // _palletRepository = provider.GetService>();
+ _varietiesCache = new List(_varietyRepository.GetList());
_palletsCache = new List(_palletRepository.GetList());
}
catch (Exception e)
@@ -49,14 +49,23 @@ public class VarietyService : IVarietyService
{
try
{
- var entity = await _varietyRepository.InsertReturnEntityAsync(variety.ToEntity());
- _varietiesCache.Add(entity);
+ var entity = _varietiesCache.FirstOrDefault(p => p.Id == variety.Id);
+ if (entity == null)
+ {
+ entity = await _varietyRepository.InsertReturnEntityAsync(variety.ToEntity());
+ _varietiesCache.Add(entity);
+ }
+ else
+ {
+ entity = variety.ToEntity();
+ await _varietyRepository.UpdateAsync(entity);
+ _varietiesCache[_varietiesCache.IndexOf(entity)] = entity;
+ }
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
-
}
public async Task UpdateVarietyAsync(Variety variety)
@@ -89,15 +98,20 @@ public class VarietyService : IVarietyService
public async Task GetLastNo(int varietyId)
{
- var variety = await (_varietyRepository.CopyNew().GetFirstAsync(x=>x.Id==varietyId));
+ var variety = await (_varietyRepository.CopyNew().GetFirstAsync(x => x.Id == varietyId));
return variety.LastNo;
}
- public async Task SetLastNo(int varietyId,int lastNo)
+ public async Task SetLastNo(int varietyId, int lastNo)
{
await _varietyRepository.CopyNew().AsUpdateable()
.Where(x => x.Id == varietyId)
- .SetColumns(x => x.LastNo , lastNo)
+ .SetColumns(x => x.LastNo, lastNo)
.ExecuteCommandAsync();
+ var variety = _varietiesCache.FirstOrDefault(x => x.Id == varietyId);
+ if (variety != null)
+ {
+ variety.LastNo = lastNo;
+ }
}
}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.UI/App.xaml b/Seyounth.Hyosung.UI/App.xaml
new file mode 100644
index 0000000..12af9cf
--- /dev/null
+++ b/Seyounth.Hyosung.UI/App.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Seyounth.Hyosung.UI/App.xaml.cs b/Seyounth.Hyosung.UI/App.xaml.cs
new file mode 100644
index 0000000..3459174
--- /dev/null
+++ b/Seyounth.Hyosung.UI/App.xaml.cs
@@ -0,0 +1,105 @@
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Seyounth.Hyosung.UI.Services;
+using Seyounth.Hyosung.UI.ViewModels.Pages;
+using Seyounth.Hyosung.UI.ViewModels.Windows;
+using Seyounth.Hyosung.UI.Views.Pages;
+using Seyounth.Hyosung.UI.Views.Windows;
+using System.IO;
+using System.Reflection;
+using System.Windows.Threading;
+using Microsoft.Extensions.Logging;
+using NLog.Extensions.Logging;
+using Seyounth.Hyosung.Core.Printer;
+using Seyounth.Hyosung.Runtime;
+using Wpf.Ui;
+
+namespace Seyounth.Hyosung.UI
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App
+ {
+ private static IHost _host;
+
+ public App()
+ {
+ var builder = Host
+ .CreateApplicationBuilder();
+ builder.Logging.ClearProviders();
+ builder.Logging.SetMinimumLevel(LogLevel.Trace);
+ builder.Logging.AddNLog("nlog.config");
+ builder.Configuration.AddJsonFile("PrintTemp.json", true, true);
+ builder.Configuration.AddJsonFile("appsettings.json", true, true);
+ builder.Services.Configure(builder.Configuration.GetSection("Print"));
+ builder.Services.AddHostedService();
+
+ // Page resolver service
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ // Theme manipulation
+ builder.Services.AddSingleton();
+
+ // TaskBar manipulation
+ builder.Services.AddSingleton();
+
+ // Service containing navigation, same as INavigationWindow... but without window
+ builder.Services.AddSingleton();
+
+ // Main window with navigation
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddSingleton();
+ builder.Services.AddHyosung(builder.Configuration);
+ _host = builder.Build();
+ }
+
+ ///
+ /// Gets registered service.
+ ///
+ /// Type of the service to get.
+ /// Instance of the service or .
+ public static T GetService()
+ where T : class
+ {
+ return _host.Services.GetService(typeof(T)) as T;
+ }
+
+ ///
+ /// Occurs when the application is loading.
+ ///
+ private void OnStartup(object sender, StartupEventArgs e)
+ {
+ _host.Services.UseHyosung();
+ _host.Start();
+ }
+
+ ///
+ /// Occurs when the application is closing.
+ ///
+ private async void OnExit(object sender, ExitEventArgs e)
+ {
+ await _host.StopAsync();
+
+ _host.Dispose();
+ }
+
+ ///
+ /// Occurs when an exception is thrown by an application but not handled.
+ ///
+ private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
+ {
+ // For more info see https://docs.microsoft.com/en-us/dotnet/api/system.windows.application.dispatcherunhandledexception?view=windowsdesktop-6.0
+ }
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.UI/AssemblyInfo.cs b/Seyounth.Hyosung.UI/AssemblyInfo.cs
new file mode 100644
index 0000000..7ad982e
--- /dev/null
+++ b/Seyounth.Hyosung.UI/AssemblyInfo.cs
@@ -0,0 +1,10 @@
+using System.Windows;
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+//(used if a resource is not found in the page,
+// app, or any theme specific resource dictionaries)
+)]
diff --git a/Seyounth.Hyosung.UI/Assets/wpfui-icon-1024.png b/Seyounth.Hyosung.UI/Assets/wpfui-icon-1024.png
new file mode 100644
index 0000000000000000000000000000000000000000..b70c4ed5957e11550ef2c58265430f28a01e2bd4
GIT binary patch
literal 10779
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
U_2T2`0T0>Rth3Ho?YZ;60kX|o`~Uy|
literal 0
HcmV?d00001
diff --git a/Seyounth.Hyosung.UI/Assets/wpfui-icon-256.png b/Seyounth.Hyosung.UI/Assets/wpfui-icon-256.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b5cf5d5aea2c545e8c5ca44f61ff7cb4669a2dd
GIT binary patch
literal 4391
zcmd5=3s4hh9$zS}6|^{~H$JG4i>cbfO?Eer%?2WP0+Px@5taHVZ1w>W$i^fPWK_^j
z%d`%1h=@uNYmtf$iemK?74>|a7EO7nD35Yd9YF@c0tyKCg-1#|TJY-JTxK%+eVgC+
zfByde|2O$!QNV)n_S5Vk2pX^Q^$LO@8?dy2-hBr=R_PD0;4xO``>_Fn941=6Hqh>`
zra+MWPEBx#F~r|bL2=PSlIGNmFfLjL&=BPA5vL=mNXE!hGvOMolHXEP%;#xnC4afp
zAMw}CXCgGd@p@)Sd_XW2A4w53-(xP%Jx&1xL^DQ`7Z)9+H7Meg{C>F#u(rGw@p=6a
zW2BNl&!UhQ;=hPDpVKouT!_LHf*?Gc5ULSYu4afiJPg555sHZrIgAnt6jfjtZ}7th
z>hv_L2=ek7R0eiReuUAeQ;0++lSyb23pstb2qg$YgkT~Jg8>3ItkW9FI9O|#F(ko@
zF;IGq&ZyzEJc~q9&BYj%d|>K;579cSSgm0&P9S2UI8rABQh9~1|w1hB2!4@t_Y?;kO8PaM{C%1Rw!nHqIfVu
zD8v$l6#o?z5RN8|RP@
zkd&oRlzhsPWQOJszSg`X9;4Dcc-|Dj0HME=`~mF-jy0M{Ju@#H#BM}#iC$?ur;TOw
z!_3!_dJ;4!MsHB^Sv?ocvl4-4H2?7%|=u|S6p=3CQNO4p)6yo6_0$5ovid$NuST;oZ|0YC(;in=
zf&!yg0mjD&1BH-Lw2WrKbj4ASc~l~UNg0j8ayfyrBq0~e7%*f9tl|FXK(VyM{xA%?
zT@AegS2oMidRYV;>vfaSf+nN~m&t(M*)2yn{
zw3?_B!Q~Ia{4RuK{*~W8X8V*0XRh)$@41v2=DMe6vipIz0~=NIE={rvh}7dQ*$nl61%6#!BV0yzHLV;=T&impP3kxe>CU&hAI6n{&^~vpc@N*{VOd
z;aKS!<=x%cZp+}3{k}oByAvSq)a}U)ZN;|=PaI2Un`$G}g*AR$env*Z(>0$*p3SK_
zgV(lJ8duaTJk?URaO#fA4yQ2voLNLh!(~B&?=gMRtW`bjrn(JKZ{Ow*vFgXn@hWpk
z{r>VX&hbw&^DjS7OU}a>@l@>x-{d!c0-0{K3&OX#XEmf3>EC%$e8}TbT}YsT?V7PA
zWqNn%xaoVzTlhYmR5Ux2N~~!@x5#
zld-j;AmisEm9hX2b5y1`{3LL!&Vnjpx+0x+b^nlhq_*$b0<$DH^QT)M1v#EH+b1eb
z{A+cwPMg|d7xeC%Q{Hlz>FS-IGQIcW3=h|18!AL|*5BcFY&-M!oV5#V7j5_US@}Ye
zd-q27+^7HIw)m8V2HJ-@U)pZUP6U9I75U~x{E}YK0Xtyr@F%&%JK^f6?9$(?WeC{;UequwKYHNy9V$!{&2Z6Wo
z7F)ZS*E6o#dm2u^h^yT7;?e0YwD6IS%T8YxXIH4)WmRL&?4T6C
zKh6B%-yt>;eoOD2?CfS7{q{Wwu{p3{$6UXH(hwV{w$AR2ao_d9#`zohn?+QUtH7?^zkl%-(HX8KPUD!Cf|<#{*ZZ+DkyWN-_FpjPKicy@$>un
zm5Zm9=Z>9dDF7E&$h&Y?ZF=PLqKCqs0)pCy%scm8TC#R(;+0_6rQtHyBiVg7yDrzZ
zH+lwj&xX2dj>NV-?>hk!6?1)AdOgcM>Bu&3JnB5N(hsC`N=F`^wx0RcsjkbZ_jG`A
z+Wy88_I_KNLtk%A)safo!L4GOJ4uHH&yCyav&NoxoBY<7!G-0gTFnj~#XUVuq0_YE
zeDXhws^bal3S7SOZ)+8B%@0&=4xX!Ld8gjG5D@?U?LDV{e(dU4Cr@avx>C_mmFV();
+ return attr?.Description ?? value.ToString();
+ }
+
+ public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.UI/Helpers/EnumToBooleanConverter.cs b/Seyounth.Hyosung.UI/Helpers/EnumToBooleanConverter.cs
new file mode 100644
index 0000000..698b3c1
--- /dev/null
+++ b/Seyounth.Hyosung.UI/Helpers/EnumToBooleanConverter.cs
@@ -0,0 +1,36 @@
+using System.Globalization;
+using System.Windows.Data;
+using Wpf.Ui.Appearance;
+
+namespace Seyounth.Hyosung.UI.Helpers
+{
+ internal class EnumToBooleanConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (parameter is not String enumString)
+ {
+ throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName");
+ }
+
+ if (!Enum.IsDefined(typeof(ApplicationTheme), value))
+ {
+ throw new ArgumentException("ExceptionEnumToBooleanConverterValueMustBeAnEnum");
+ }
+
+ var enumValue = Enum.Parse(typeof(ApplicationTheme), enumString);
+
+ return enumValue.Equals(value);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (parameter is not String enumString)
+ {
+ throw new ArgumentException("ExceptionEnumToBooleanConverterParameterMustBeAnEnumName");
+ }
+
+ return Enum.Parse(typeof(ApplicationTheme), enumString);
+ }
+ }
+}
diff --git a/Seyounth.Hyosung.UI/Models/AppConfig.cs b/Seyounth.Hyosung.UI/Models/AppConfig.cs
new file mode 100644
index 0000000..741ba78
--- /dev/null
+++ b/Seyounth.Hyosung.UI/Models/AppConfig.cs
@@ -0,0 +1,9 @@
+namespace Seyounth.Hyosung.UI.Models
+{
+ public class AppConfig
+ {
+ public string ConfigurationsFolder { get; set; }
+
+ public string AppPropertiesFileName { get; set; }
+ }
+}
diff --git a/Seyounth.Hyosung.UI/Models/DataColor.cs b/Seyounth.Hyosung.UI/Models/DataColor.cs
new file mode 100644
index 0000000..f1c3f68
--- /dev/null
+++ b/Seyounth.Hyosung.UI/Models/DataColor.cs
@@ -0,0 +1,9 @@
+using System.Windows.Media;
+
+namespace Seyounth.Hyosung.UI.Models
+{
+ public struct DataColor
+ {
+ public Brush Color { get; set; }
+ }
+}
diff --git a/Seyounth.Hyosung.UI/Resources/Translations.cs b/Seyounth.Hyosung.UI/Resources/Translations.cs
new file mode 100644
index 0000000..d1e09b5
--- /dev/null
+++ b/Seyounth.Hyosung.UI/Resources/Translations.cs
@@ -0,0 +1,6 @@
+namespace Seyounth.Hyosung.UI.Resources
+{
+ public partial class Translations
+ {
+ }
+}
diff --git a/Seyounth.Hyosung.UI/Services/ApplicationHostService.cs b/Seyounth.Hyosung.UI/Services/ApplicationHostService.cs
new file mode 100644
index 0000000..a7d467e
--- /dev/null
+++ b/Seyounth.Hyosung.UI/Services/ApplicationHostService.cs
@@ -0,0 +1,59 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Seyounth.Hyosung.UI.Views.Pages;
+using Seyounth.Hyosung.UI.Views.Windows;
+using Wpf.Ui;
+
+namespace Seyounth.Hyosung.UI.Services
+{
+ ///
+ /// Managed host of the application.
+ ///
+ public class ApplicationHostService : IHostedService
+ {
+ private readonly IServiceProvider _serviceProvider;
+
+ private INavigationWindow _navigationWindow;
+
+ public ApplicationHostService(IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ }
+
+ ///
+ /// Triggered when the application host is ready to start the service.
+ ///
+ /// Indicates that the start process has been aborted.
+ public async Task StartAsync(CancellationToken cancellationToken)
+ {
+ await HandleActivationAsync();
+ }
+
+ ///
+ /// Triggered when the application host is performing a graceful shutdown.
+ ///
+ /// Indicates that the shutdown process should no longer be graceful.
+ public async Task StopAsync(CancellationToken cancellationToken)
+ {
+ await Task.CompletedTask;
+ }
+
+ ///
+ /// Creates main window during activation.
+ ///
+ private async Task HandleActivationAsync()
+ {
+ if (!Application.Current.Windows.OfType().Any())
+ {
+ _navigationWindow = (
+ _serviceProvider.GetService(typeof(INavigationWindow)) as INavigationWindow
+ )!;
+ _navigationWindow!.ShowWindow();
+
+ _navigationWindow.Navigate(typeof(Views.Pages.DashboardPage));
+ }
+
+ await Task.CompletedTask;
+ }
+ }
+}
diff --git a/Seyounth.Hyosung.UI/Services/PageService.cs b/Seyounth.Hyosung.UI/Services/PageService.cs
new file mode 100644
index 0000000..9d69896
--- /dev/null
+++ b/Seyounth.Hyosung.UI/Services/PageService.cs
@@ -0,0 +1,42 @@
+using Wpf.Ui;
+
+namespace Seyounth.Hyosung.UI.Services
+{
+ ///
+ /// Service that provides pages for navigation.
+ ///
+ public class PageService : IPageService
+ {
+ ///
+ /// Service which provides the instances of pages.
+ ///
+ private readonly IServiceProvider _serviceProvider;
+
+ ///
+ /// Creates new instance and attaches the .
+ ///
+ public PageService(IServiceProvider serviceProvider)
+ {
+ _serviceProvider = serviceProvider;
+ }
+
+ ///
+ public T? GetPage()
+ where T : class
+ {
+ if (!typeof(FrameworkElement).IsAssignableFrom(typeof(T)))
+ throw new InvalidOperationException("The page should be a WPF control.");
+
+ return (T?)_serviceProvider.GetService(typeof(T));
+ }
+
+ ///
+ public FrameworkElement? GetPage(Type pageType)
+ {
+ if (!typeof(FrameworkElement).IsAssignableFrom(pageType))
+ throw new InvalidOperationException("The page should be a WPF control.");
+
+ return _serviceProvider.GetService(pageType) as FrameworkElement;
+ }
+ }
+}
diff --git a/Seyounth.Hyosung.UI/Seyounth.Hyosung.UI.csproj b/Seyounth.Hyosung.UI/Seyounth.Hyosung.UI.csproj
new file mode 100644
index 0000000..1ad74d9
--- /dev/null
+++ b/Seyounth.Hyosung.UI/Seyounth.Hyosung.UI.csproj
@@ -0,0 +1,38 @@
+
+
+
+ WinExe
+ net8.0-windows
+ app.manifest
+ wpfui-icon.ico
+ true
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Seyounth.Hyosung.UI/Usings.cs b/Seyounth.Hyosung.UI/Usings.cs
new file mode 100644
index 0000000..5efad98
--- /dev/null
+++ b/Seyounth.Hyosung.UI/Usings.cs
@@ -0,0 +1,4 @@
+global using CommunityToolkit.Mvvm.ComponentModel;
+global using CommunityToolkit.Mvvm.Input;
+global using System;
+global using System.Windows;
diff --git a/Seyounth.Hyosung.UI/ViewModels/Pages/DashboardViewModel.cs b/Seyounth.Hyosung.UI/ViewModels/Pages/DashboardViewModel.cs
new file mode 100644
index 0000000..2981d40
--- /dev/null
+++ b/Seyounth.Hyosung.UI/ViewModels/Pages/DashboardViewModel.cs
@@ -0,0 +1,100 @@
+using System.Collections.ObjectModel;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Services;
+using Seyounth.Hyosung.Runtime;
+using Wpf.Ui;
+using Wpf.Ui.Controls;
+
+namespace Seyounth.Hyosung.UI.ViewModels.Pages
+{
+ public partial class DashboardViewModel : ObservableObject, INavigationAware
+ {
+ [ObservableProperty] private ObservableCollection _varieties;
+
+ [ObservableProperty] private Variety _selectedVariety;
+
+ [ObservableProperty] private List _yarnCarTypes;
+
+ [ObservableProperty] private List _yarnCarSideType;
+
+ [ObservableProperty] private int _selectedYarnCarTypeIndex;
+
+ [ObservableProperty] private int _selectedYarnCarSideTypeIndex;
+
+ private readonly IVarietyService _varietyService;
+
+ private readonly IPalletService _palletService;
+
+ private readonly ISnackbarService _snackbarService;
+
+ private readonly IHyosungRuntime _runtime;
+
+ public DashboardViewModel(IVarietyService varietyService, ISnackbarService snackbarService,
+ IHyosungRuntime runtime)
+ {
+ _runtime = runtime;
+ SelectedYarnCarTypeIndex = 0;
+ SelectedYarnCarSideTypeIndex = 0;
+ _varietyService = varietyService;
+ _snackbarService = snackbarService;
+ Varieties = new ObservableCollection(varietyService.GetAll());
+
+ YarnCarTypes =
+ [
+ "A",
+ "B",
+ "C",
+ "D"
+ ];
+
+ YarnCarSideType =
+ [
+ "正面",
+ "反面"
+ ];
+ }
+
+ public void OnNavigatedTo()
+ {
+ Varieties = new ObservableCollection(_varietyService.GetAll());
+ }
+
+ public void OnNavigatedFrom()
+ {
+ }
+
+ [RelayCommand]
+ private void OnChangeVariety()
+ {
+ try
+ {
+ SelectedVariety.YarnCarType = SelectedYarnCarTypeIndex + 1;
+ SelectedVariety.YarnCarSide = SelectedYarnCarSideTypeIndex + 1;
+ _runtime.SendVarietyToPlcAsync(SelectedVariety);
+ _snackbarService.Show("切换成功", $"当前产品为: {SelectedVariety.Name}", ControlAppearance.Success,
+ new SymbolIcon(SymbolRegular.ArrowCircleUp24), TimeSpan.FromSeconds(5));
+ }
+ catch (Exception e)
+ {
+ _snackbarService.Show("切换异常", e.Message, ControlAppearance.Danger,
+ new SymbolIcon(SymbolRegular.ArrowCircleUp24), TimeSpan.FromSeconds(5));
+ }
+ }
+
+ [RelayCommand]
+ private void OnChangeVarietyLastNo()
+ {
+ if (SelectedVariety.LastNo != null)
+ {
+ _varietyService.SetLastNo(SelectedVariety.Id, SelectedVariety.LastNo.Value);
+ _snackbarService.Show("保存成功", "当前控制号保存成功", ControlAppearance.Success,
+ new SymbolIcon(SymbolRegular.Save24), TimeSpan.FromSeconds(5));
+ }
+ else
+ {
+ _snackbarService.Show("保存失败", "当前控制号为空", ControlAppearance.Danger,
+ new SymbolIcon(SymbolRegular.Save24), TimeSpan.FromSeconds(5));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.UI/ViewModels/Pages/DataViewModel.cs b/Seyounth.Hyosung.UI/ViewModels/Pages/DataViewModel.cs
new file mode 100644
index 0000000..3a2b4a8
--- /dev/null
+++ b/Seyounth.Hyosung.UI/ViewModels/Pages/DataViewModel.cs
@@ -0,0 +1,100 @@
+using System.Collections.ObjectModel;
+using Seyounth.Hyosung.UI.Models;
+using System.Windows.Media;
+using CommunityToolkit.Mvvm.Messaging;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Services;
+using Wpf.Ui.Controls;
+
+namespace Seyounth.Hyosung.UI.ViewModels.Pages
+{
+ public partial class DataViewModel : ObservableObject, INavigationAware
+ {
+ public class SavePalletCompletedMessage;
+
+ [ObservableProperty] private ObservableCollection _varieties;
+
+ [ObservableProperty] private ObservableCollection _pallets;
+
+ [ObservableProperty] private ObservableCollection _honeyPallets = new();
+
+ [ObservableProperty] private ObservableCollection _paperPallets = new();
+
+ [ObservableProperty] private ObservableCollection _trays = new();
+
+ private readonly IVarietyService _varietyService;
+ private readonly IPalletService _palletService;
+
+ public DataViewModel(IVarietyService varietyService, IPalletService palletService)
+ {
+ _varietyService = varietyService;
+ _palletService = palletService;
+ }
+
+ public void OnNavigatedTo()
+ {
+ Pallets = new ObservableCollection(_palletService.GetPallets());
+ HoneyPallets = new ObservableCollection(Pallets.Where(p => p.Type == PalletType.Honey));
+ var papers = Pallets.Where(p => p.Type == PalletType.Paper).ToList();
+ papers.Add(new Pallet());
+ papers = papers.OrderBy(p => p.Length).ToList();
+ PaperPallets = new ObservableCollection(papers);
+ Trays = new ObservableCollection(Pallets.Where(p =>
+ p.Type is PalletType.Plywood or PalletType.Wood));
+ var varieties = _varietyService.GetAll().Select(v =>
+ {
+ // 匹配相同ID的托盘对象
+ v.TopAndBottomPallet = HoneyPallets.FirstOrDefault(p => p.Id == v.TopAndBottomPallet.Id);
+ v.MiddlePallet = HoneyPallets.FirstOrDefault(p => p.Id == v.MiddlePallet.Id);
+ v.Tray = Trays.FirstOrDefault(p => p.Id == v.Tray.Id);
+ v.PaperTray = v.PaperTray is null
+ ? PaperPallets.First()
+ : PaperPallets.FirstOrDefault(p =>
+ p.Id == v.PaperTray.Id);
+ return v;
+ });
+
+ Varieties = new ObservableCollection(varieties);
+ }
+
+ public void OnNavigatedFrom()
+ {
+ }
+
+ [RelayCommand]
+ private void AddVariety()
+ {
+ var variety = new Variety
+ {
+ /* 初始化默认值 */
+ };
+ Varieties.Add(variety);
+ }
+
+ [RelayCommand]
+ private void OnDeleteVariety(object obj)
+ {
+ if (obj is Variety variety)
+ {
+ Varieties.Remove(variety);
+ _varietyService.DeleteVarietyAsync(variety);
+ }
+ else
+ {
+ Console.Write("Object is not a variety");
+ }
+ }
+
+ [RelayCommand]
+ private async Task OnSaveVariety(object obj)
+ {
+ if (obj is Variety variety)
+ {
+ await _varietyService.AddVarietyAsync(variety);
+ //Pallets = new ObservableCollection(_palletService.GetPallets());
+ }
+
+ WeakReferenceMessenger.Default.Send(new SavePalletCompletedMessage());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.UI/ViewModels/Pages/PalletManagementViewModel.cs b/Seyounth.Hyosung.UI/ViewModels/Pages/PalletManagementViewModel.cs
new file mode 100644
index 0000000..55a4012
--- /dev/null
+++ b/Seyounth.Hyosung.UI/ViewModels/Pages/PalletManagementViewModel.cs
@@ -0,0 +1,72 @@
+using System.Collections.ObjectModel;
+using CommunityToolkit.Mvvm.Messaging;
+using Seyounth.Hyosung.Data.Models;
+using Seyounth.Hyosung.Data.Services;
+using Wpf.Ui.Controls;
+
+namespace Seyounth.Hyosung.UI.ViewModels.Pages;
+
+public partial class PalletManagementViewModel : ObservableObject, INavigationAware
+{
+ public class SavePalletCompletedMessage;
+
+ [ObservableProperty] private ObservableCollection _pallets = [];
+ private readonly IPalletService _palletService;
+
+ ///
+ public PalletManagementViewModel(IPalletService palletService)
+ {
+ _palletService = palletService;
+ Pallets = new ObservableCollection(_palletService.GetPallets());
+ }
+
+ public void OnNavigatedTo()
+ {
+ Pallets = new ObservableCollection(_palletService.GetPallets());
+ }
+
+ public void OnNavigatedFrom()
+ {
+ }
+
+ [RelayCommand]
+ private void AddPallet()
+ {
+ var newPallet = new Pallet
+ {
+ /* 初始化默认值 */
+ };
+ Pallets.Add(newPallet);
+ }
+
+ [RelayCommand]
+ private void OnDeletePallet(object obj)
+ {
+ if (obj is Pallet pallet)
+ {
+ Pallets.Remove(pallet);
+ _palletService.DeletePalletAsync(pallet);
+ }
+ else
+ {
+ Console.Write("Object is not a Pallet");
+ }
+ }
+
+ [RelayCommand]
+ private void OnSavePallet(object obj)
+ {
+ if (obj is Pallet pallet)
+ {
+ if (pallet.Id == 0)
+ {
+ var id = _palletService.AddPalletAsync(pallet).Result;
+ //Pallets = new ObservableCollection(_palletService.GetPallets());
+ }
+ else
+ _palletService.UpdatePalletAsync(pallet);
+ }
+
+ WeakReferenceMessenger.Default.Send(new SavePalletCompletedMessage());
+ }
+}
\ No newline at end of file
diff --git a/Seyounth.Hyosung.UI/ViewModels/Pages/SettingsViewModel.cs b/Seyounth.Hyosung.UI/ViewModels/Pages/SettingsViewModel.cs
new file mode 100644
index 0000000..5d03bb4
--- /dev/null
+++ b/Seyounth.Hyosung.UI/ViewModels/Pages/SettingsViewModel.cs
@@ -0,0 +1,63 @@
+using Wpf.Ui.Appearance;
+using Wpf.Ui.Controls;
+
+namespace Seyounth.Hyosung.UI.ViewModels.Pages
+{
+ public partial class SettingsViewModel : ObservableObject, INavigationAware
+ {
+ private bool _isInitialized = false;
+
+ [ObservableProperty]
+ private string _appVersion = String.Empty;
+
+ [ObservableProperty]
+ private ApplicationTheme _currentTheme = ApplicationTheme.Unknown;
+
+ public void OnNavigatedTo()
+ {
+ if (!_isInitialized)
+ InitializeViewModel();
+ }
+
+ public void OnNavigatedFrom() { }
+
+ private void InitializeViewModel()
+ {
+ CurrentTheme = ApplicationThemeManager.GetAppTheme();
+ AppVersion = $"UiDesktopApp1 - {GetAssemblyVersion()}";
+
+ _isInitialized = true;
+ }
+
+ private string GetAssemblyVersion()
+ {
+ return System.Reflection.Assembly.GetExecutingAssembly().GetName().Version?.ToString()
+ ?? String.Empty;
+ }
+
+ [RelayCommand]
+ private void OnChangeTheme(string parameter)
+ {
+ switch (parameter)
+ {
+ case "theme_light":
+ if (CurrentTheme == ApplicationTheme.Light)
+ break;
+
+ ApplicationThemeManager.Apply(ApplicationTheme.Light);
+ CurrentTheme = ApplicationTheme.Light;
+
+ break;
+
+ default:
+ if (CurrentTheme == ApplicationTheme.Dark)
+ break;
+
+ ApplicationThemeManager.Apply(ApplicationTheme.Dark);
+ CurrentTheme = ApplicationTheme.Dark;
+
+ break;
+ }
+ }
+ }
+}
diff --git a/Seyounth.Hyosung.UI/ViewModels/Windows/MainWindowViewModel.cs b/Seyounth.Hyosung.UI/ViewModels/Windows/MainWindowViewModel.cs
new file mode 100644
index 0000000..d153bc1
--- /dev/null
+++ b/Seyounth.Hyosung.UI/ViewModels/Windows/MainWindowViewModel.cs
@@ -0,0 +1,69 @@
+using System.Collections.ObjectModel;
+using Wpf.Ui.Controls;
+
+namespace Seyounth.Hyosung.UI.ViewModels.Windows
+{
+ public partial class MainWindowViewModel : ObservableObject
+ {
+ [ObservableProperty]
+ private string _applicationTitle = "WPF UI - Seyounth.Hyosung.UI";
+
+ [ObservableProperty]
+ private ObservableCollection