diff --git a/FT472_20241126_051347.bak b/FT472_20241126_051347.bak
new file mode 100644
index 0000000..6ee1bce
Binary files /dev/null and b/FT472_20241126_051347.bak differ
diff --git a/TestProject1/TestProject1.csproj b/TestProject1/TestProject1.csproj
new file mode 100644
index 0000000..d87a666
--- /dev/null
+++ b/TestProject1/TestProject1.csproj
@@ -0,0 +1,19 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+ false
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestProject1/UnitTest1.cs b/TestProject1/UnitTest1.cs
new file mode 100644
index 0000000..58d2373
--- /dev/null
+++ b/TestProject1/UnitTest1.cs
@@ -0,0 +1,31 @@
+using HslCommunication.Profinet.Siemens;
+
+namespace TestProject1
+{
+ [TestClass]
+ public class UnitTest1
+ {
+ [TestMethod]
+ public void TestMethod1()
+ {
+ SiemensS7Net plc_Conv = new SiemensS7Net(SiemensPLCS.S1500, "127.0.0.1");
+ plc_Conv.ConnectTimeOut = 3;
+ OperateResult res = plc_Conv.ConnectServer();
+
+ if (res.IsSuccess)
+ {
+ Console.WriteLine(1);
+ }
+ else
+ {
+ Console.WriteLine(2);
+ }
+
+ Console.ReadKey();
+ }
+
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/TestProject1/Usings.cs b/TestProject1/Usings.cs
new file mode 100644
index 0000000..b60884e
--- /dev/null
+++ b/TestProject1/Usings.cs
@@ -0,0 +1,2 @@
+global using Microsoft.VisualStudio.TestTools.UnitTesting;
+global using HslCommunication;
\ No newline at end of file
diff --git a/WPFWCSDemo.sln b/WPFWCSDemo.sln
new file mode 100644
index 0000000..a5d6f78
--- /dev/null
+++ b/WPFWCSDemo.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.7.34003.232
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WPFWCSDemo", "WPFWCSDemo\WPFWCSDemo.csproj", "{604005A1-35A4-48E2-8011-20C38F2AC571}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject1", "TestProject1\TestProject1.csproj", "{BD8D724A-5381-4BBD-BB94-240AD27DD2A7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {604005A1-35A4-48E2-8011-20C38F2AC571}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {604005A1-35A4-48E2-8011-20C38F2AC571}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {604005A1-35A4-48E2-8011-20C38F2AC571}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {604005A1-35A4-48E2-8011-20C38F2AC571}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BD8D724A-5381-4BBD-BB94-240AD27DD2A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BD8D724A-5381-4BBD-BB94-240AD27DD2A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BD8D724A-5381-4BBD-BB94-240AD27DD2A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BD8D724A-5381-4BBD-BB94-240AD27DD2A7}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {395F0C62-C9BD-4A94-801B-049F19941808}
+ EndGlobalSection
+EndGlobal
diff --git a/WPFWCSDemo/API/Task/StockIn/StockIn_Receive.cs b/WPFWCSDemo/API/Task/StockIn/StockIn_Receive.cs
new file mode 100644
index 0000000..45151e7
--- /dev/null
+++ b/WPFWCSDemo/API/Task/StockIn/StockIn_Receive.cs
@@ -0,0 +1,54 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task.StockIn
+{
+ ///
+ /// 接收WMS推送的*入库*任务
+ ///
+ public class StockIn_Receive
+ {
+ ///
+ /// 流水号
+ ///
+ public string JobId { get; set; }
+ ///
+ /// 任务号
+ ///
+ public string TaskId { get; set; }
+ ///
+ /// 托盘编号
+ ///
+ public string PalletId { get; set; }
+ ///
+ /// 任务类型 1-入库 2-出库 3-移库
+ ///
+ public int TaskType { get; set; }
+ ///
+ /// 源站点
+ ///
+ public string SourceLocation { get; set; }
+ ///
+ /// 目标站点
+ ///
+ public string TargetLocation { get; set; }
+ ///
+ /// 优先级 1→3 高→低
+ ///
+ public int Priority { get; set; }
+ ///
+ /// 任务状态
+ ///
+ [JsonIgnore]
+ public string TaskCode { get; set; }
+ ///
+ /// 调度状态
+ ///
+ [JsonIgnore]
+ public string ScheduleCode { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/StockIn/StockIn_ReceiveResponse.cs b/WPFWCSDemo/API/Task/StockIn/StockIn_ReceiveResponse.cs
new file mode 100644
index 0000000..229accc
--- /dev/null
+++ b/WPFWCSDemo/API/Task/StockIn/StockIn_ReceiveResponse.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task.StockIn
+{
+ ///
+ /// 【接收*入库*推送后】向wms反馈消息
+ ///
+ public class StockIn_ReceiveResponse
+ {
+ ///
+ /// 作业号
+ ///
+ public string JobId { get; set; }
+ ///
+ /// 反馈信息
+ ///
+ public string Message { get; set; }
+ ///
+ /// 返回结果 0-正常 1-异常
+ ///
+ public int Result { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/StockIn/StockIn_Request.cs b/WPFWCSDemo/API/Task/StockIn/StockIn_Request.cs
new file mode 100644
index 0000000..a90311e
--- /dev/null
+++ b/WPFWCSDemo/API/Task/StockIn/StockIn_Request.cs
@@ -0,0 +1,42 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task.StockIn
+{
+ ///
+ /// wcs主动向wms请求*入库*任务
+ ///
+ public class StockIn_Request
+ {
+ ///
+ /// 接口名称
+ ///
+ [JsonIgnore]
+ public string Name { get; set; }
+ ///
+ /// 任务号
+ ///
+ public string TaskId { get; set; }
+ ///
+ /// 托盘号
+ ///
+ public string PalletId { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public string TaskType { get; set; }
+ ///
+ /// 源站点
+ ///
+ public string SourceLocation { get; set; }
+ ///
+ /// 发送结果
+ ///
+ [JsonIgnore]
+ public string Result { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/StockIn/StockIn_RequestResponse.cs b/WPFWCSDemo/API/Task/StockIn/StockIn_RequestResponse.cs
new file mode 100644
index 0000000..a005f54
--- /dev/null
+++ b/WPFWCSDemo/API/Task/StockIn/StockIn_RequestResponse.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task.StockIn
+{
+ ///
+ /// 【向wms请求*入库*后】wms的返回消息
+ ///
+ public class StockIn_RequestResponse
+ {
+ ///
+ /// 作业号
+ ///
+ public string JobId { get; set; }
+ ///
+ /// 反馈信息
+ ///
+ public string Message { get; set; }
+ ///
+ /// 返回结果 0-正常 1-异常
+ ///
+ public int Result { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/StockOut/StockOut_Receive.cs b/WPFWCSDemo/API/Task/StockOut/StockOut_Receive.cs
new file mode 100644
index 0000000..dec6ee6
--- /dev/null
+++ b/WPFWCSDemo/API/Task/StockOut/StockOut_Receive.cs
@@ -0,0 +1,54 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task.StockOut
+{
+ ///
+ /// 接收WMS推送的*出库*任务
+ ///
+ public class StockOut_Receive
+ {
+ ///
+ /// 流水号
+ ///
+ public string JobId { get; set; }
+ ///
+ /// 任务号
+ ///
+ public string TaskId { get; set; }
+ ///
+ /// 托盘编号
+ ///
+ public string PalletId { get; set; }
+ ///
+ /// 任务类型 1-入库 2-出库 3-移库
+ ///
+ public int TaskType { get; set; }
+ ///
+ /// 源站点
+ ///
+ public string SourceLocation { get; set; }
+ ///
+ /// 目标站点
+ ///
+ public string TargetLocation { get; set; }
+ ///
+ /// 优先级 1→3 高→低
+ ///
+ public int Priority { get; set; }
+ ///
+ /// 任务状态
+ ///
+ [JsonIgnore]
+ public string TaskCode { get; set; }
+ ///
+ /// 调度状态
+ ///
+ [JsonIgnore]
+ public string ScheduleCode { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/StockOut/StockOut_ReceiveReponse.cs b/WPFWCSDemo/API/Task/StockOut/StockOut_ReceiveReponse.cs
new file mode 100644
index 0000000..6e92caf
--- /dev/null
+++ b/WPFWCSDemo/API/Task/StockOut/StockOut_ReceiveReponse.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task.StockOut
+{
+ ///
+ /// 【接收*出库*推送后】向wms反馈消息
+ ///
+ public class StockOut_ReceiveReponse
+ {
+ ///
+ /// 作业号
+ ///
+ public string JobId { get; set; }
+ ///
+ /// 反馈信息,可空
+ ///
+ public string Message { get; set; }
+ ///
+ /// 返回结果 0-正常 1-异常
+ ///
+ public int Result { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/Task_Receive.cs b/WPFWCSDemo/API/Task/Task_Receive.cs
new file mode 100644
index 0000000..373ed30
--- /dev/null
+++ b/WPFWCSDemo/API/Task/Task_Receive.cs
@@ -0,0 +1,55 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task
+{
+ ///
+ /// 接收wms推送任务
+ ///
+ public class Task_Receive
+ {
+ ///
+ /// 流水号
+ ///
+ public string? JobId { get; set; }
+ ///
+ /// 任务号
+ ///
+ [JsonIgnore]
+ public string? TaskId { get; set; }
+ ///
+ /// 托盘编号
+ ///
+ public string? PalletId { get; set; }
+ ///
+ /// 任务类型 1-入库 2-出库 3-移库
+ ///
+ public ushort TaskType { get; set; }
+ ///
+ /// 源站点
+ ///
+ public string? SourceLocation { get; set; }
+ ///
+ /// 目标站点
+ ///
+ public string? TargetLocation { get; set; }
+ ///
+ /// 优先级 1→3 高→低
+ ///
+ public int Priority { get; set; }
+ ///
+ /// 任务状态
+ ///
+ [JsonIgnore]
+ public string TaskState { get; set; }
+ ///
+ /// 调度状态
+ ///
+ [JsonIgnore]
+ public string ScheduleState { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/Task_Response.cs b/WPFWCSDemo/API/Task/Task_Response.cs
new file mode 100644
index 0000000..a616ced
--- /dev/null
+++ b/WPFWCSDemo/API/Task/Task_Response.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task
+{
+ ///
+ /// 【接收wms推送任务后】向wms反馈消息
+ ///
+ public class Task_Response
+ {
+ ///
+ /// 作业号
+ ///
+ public string? JobId { get; set; }
+ ///
+ /// 反馈信息,可空
+ ///
+ public string? Message { get; set; }
+ ///
+ /// 返回结果 0-成功 1-失败
+ ///
+ public int Result { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/Task_StateRequest.cs b/WPFWCSDemo/API/Task/Task_StateRequest.cs
new file mode 100644
index 0000000..2b9962f
--- /dev/null
+++ b/WPFWCSDemo/API/Task/Task_StateRequest.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task
+{
+ ///
+ /// 根据任务状态请求wms-向wms反馈执行结果
+ ///
+ public class Task_StateRequest
+ {
+ ///
+ /// 作业号
+ ///
+ public string JobId { get; set; }
+ ///
+ /// 反馈信息
+ ///
+ public string Message { get; set; }
+
+ ///
+ /// 状态码 111-放货有货 121-取货无货 102-任务正常完成 103-任务人工完成 104-人工取消任务
+ ///
+ public string Code { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/Task_StateRequestResponse.cs b/WPFWCSDemo/API/Task/Task_StateRequestResponse.cs
new file mode 100644
index 0000000..d611b0c
--- /dev/null
+++ b/WPFWCSDemo/API/Task/Task_StateRequestResponse.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task
+{
+ ///
+ /// 向wms反馈任务状态(执行结果)后(完成、重分等)返回的消息
+ ///
+ public class Task_StateRequestResponse
+ {
+ ///
+ /// 作业号
+ ///
+ public string? JobId { get; set; }
+ ///
+ /// 【入库放货有货】重新分配的目标仓位
+ ///
+ public string? TargetLocation { get; set; }
+ ///
+ /// 反馈信息
+ ///
+ public string? Message { get; set; }
+ ///
+ /// 返回码 0-正常 1-异常
+ ///
+ public int Result { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/Task_StockInRequest.cs b/WPFWCSDemo/API/Task/Task_StockInRequest.cs
new file mode 100644
index 0000000..89fa77e
--- /dev/null
+++ b/WPFWCSDemo/API/Task/Task_StockInRequest.cs
@@ -0,0 +1,42 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task
+{
+ ///
+ /// wcs向wms请求入库
+ ///
+ public class Task_StockInRequest
+ {
+ ///
+ /// 接口名称
+ ///
+ [JsonIgnore]
+ public string Name { get; set; }
+ ///
+ /// 任务号
+ ///
+ public string TaskId { get; set; }
+ ///
+ /// 托盘号
+ ///
+ public string PalletId { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public int TaskType { get; set; }
+ ///
+ /// 源站点
+ ///
+ public string SourceLocation { get; set; }
+ ///
+ /// 发送结果 0-成功 1-失败
+ ///
+ [JsonIgnore]
+ public int Result { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/API/Task/Task_StockInRequestResponse.cs b/WPFWCSDemo/API/Task/Task_StockInRequestResponse.cs
new file mode 100644
index 0000000..7563ca5
--- /dev/null
+++ b/WPFWCSDemo/API/Task/Task_StockInRequestResponse.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.API.Task
+{
+ ///
+ /// 【wcs向wms请求入库后】wms的返回消息
+ ///
+ public class Task_StockInRequestResponse
+ {
+ ///
+ /// 流水号
+ ///
+ public string? JobId { get; set; }
+ ///
+ /// 目标站
+ ///
+ public string? TargetLocation { get; set; }
+ ///
+ /// 反馈信息
+ ///
+ public string? Message { get; set; }
+ ///
+ /// 反馈结果
+ ///
+ public int Result { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/App.config b/WPFWCSDemo/App.config
new file mode 100644
index 0000000..afaa34e
--- /dev/null
+++ b/WPFWCSDemo/App.config
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/WPFWCSDemo/App.xaml b/WPFWCSDemo/App.xaml
new file mode 100644
index 0000000..8446a6d
--- /dev/null
+++ b/WPFWCSDemo/App.xaml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/App.xaml.cs b/WPFWCSDemo/App.xaml.cs
new file mode 100644
index 0000000..710be3d
--- /dev/null
+++ b/WPFWCSDemo/App.xaml.cs
@@ -0,0 +1,193 @@
+using Quartz;
+using Quartz.Impl;
+using Quartz.Simpl;
+using Serilog;
+using Serilog.Events;
+using System;
+using System.Configuration;
+using System.Data;
+using System.Diagnostics;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using WPFWCSDemo.Schedules.CircleRGV;
+using WPFWCSDemo.Schedules.CommonTask;
+using WPFWCSDemo.Schedules.TaskFinish;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ private IScheduler _scheduler;
+ public App()
+ {
+ InitializeComponent();
+
+ //Serilog其他
+ //Serilog日志配置
+ //Debug-
+ //Info-调度信息
+ //Warning-设备读写/连接异常
+ //Error-执行异常,交互异常
+ Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Debug()
+ //.Filter.ByIncludingOnly(logEvent => logEvent.Level == LogEventLevel.Debug)
+ .WriteTo.File(path: $"D:/Logs/Debug/Debug.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}", restrictedToMinimumLevel: LogEventLevel.Debug, rollingInterval: RollingInterval.Day)
+ .WriteTo.File(path: $"D:/Logs/Info/Info.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}", restrictedToMinimumLevel: LogEventLevel.Information, rollingInterval: RollingInterval.Day)
+ .WriteTo.File(path: $"D:/Logs/Warning/Warning.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}", restrictedToMinimumLevel: LogEventLevel.Warning, rollingInterval: RollingInterval.Day)
+ .WriteTo.File(path: $"D:/Logs/Error/Error.txt", outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}", restrictedToMinimumLevel: LogEventLevel.Error, rollingInterval: RollingInterval.Day)
+ //.Filter.ByExcluding(logEvent => logEvent.Level == LogEventLevel.Warning)
+ .Enrich.FromLogContext()
+ .CreateLogger();
+
+ //获取app.config中sql连接字符串
+ SqlHelper.ConStr = ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString;
+
+
+ //检查进程是否已经启动,已经启动则显示报错信息退出程序。
+ string strProcessName = System.Diagnostics.Process.GetCurrentProcess().ProcessName;
+ if (System.Diagnostics.Process.GetProcessesByName(strProcessName).Length > 1)
+ {
+ MessageBox.Show("对不起,本地已经有系统正在运行", "退出", MessageBoxButton.OK, MessageBoxImage.Exclamation);
+ Current.Shutdown();
+ return;
+ }
+
+ }
+
+
+
+ protected async override void OnStartup(StartupEventArgs e)
+ {
+ try
+ {
+ Log.Information("**********************************Application Is Started**********************************");
+ Log.Information("**********************************Application Is Started**********************************");
+ Log.Information("**********************************Application Is Started**********************************");
+
+ Stopwatch stopwatch = new Stopwatch();
+ stopwatch.Start();
+
+ //==============================================================================================
+
+ Log.Information("【Application is Starting】环穿设备初始化中...");
+ CircleRGVsViewModel.InitializeRgv();
+ //CircleRGVsViewModel.RGVStationInitialize();
+ Log.Information("【Application is Starting】环穿设备初始化完成!");
+
+ //==============================================================================================
+
+ Log.Information("【Application is Starting】报警信息初始化中...");
+ AlarmViewModel.AlarmInitialize();
+ Log.Information("【Application is Starting】报警信息初始化完成!");
+
+ //==============================================================================================
+
+ Log.Information("【Application is Starting】调度程序初始化中...");
+
+ ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
+ _scheduler = schedulerFactory.GetScheduler().Result;
+ await _scheduler.Start();
+
+ Log.Information("【Application is Starting】调度程序启动中...");
+
+ #region 注册环穿调度任务
+
+ Log.Information("【Application is Starting】设备调度初始化中...");
+ GetScheduleJob(typeof(CircleRGVSchedule), "circleRGVJob", "circleRGVTrigger", "circleRGVSchedule", 2000);
+ #endregion
+
+ //-------------------------------------------------------------------------------
+
+ #region 调度任务处理
+
+ //任务处理---注册任务
+ Log.Information("【Application is Starting】任务处理调度初始化中...");
+ GetScheduleJob(typeof(TaskFinishSchedule), "taskHandlerJob", "taskHandlerTrigger", "taskHandlerSchedule", 1000);
+ #endregion
+
+ //-------------------------------------------------------------------------------
+
+ #region 全局任务
+
+ //全局任务---注册任务
+ Log.Information("【Application is Starting】全局任务初始化中...");
+ GetScheduleJob(typeof(CommonTask), "globalTaskJob", "globalTTrigger", "commonTask", 1000);
+ #endregion
+
+
+ Log.Information("【Application is Starting】调度程序初始化完成!");
+
+ //==============================================================================================
+
+ stopwatch.Stop();
+ Log.Information($"【Application is Starting】WCS工程已启动,用时{stopwatch.Elapsed.TotalSeconds}s");
+
+ SqlHelper.NewEventLog("WCS调度已启动", "SYS");
+ }
+ catch (Exception ex)
+ {
+ Log.Error($"【Application is Starting】{ex.Message}");
+ Log.Error($"【Application is Starting】{ex.InnerException}");
+ Current.Shutdown();
+ }
+
+
+ }
+
+
+
+ protected override void OnExit(ExitEventArgs e)
+ {
+ base.OnExit(e);
+ Log.Information("【Application is Exiting】程序正在退出!");
+ _scheduler.Shutdown(true).Wait();
+ //Current.Shutdown();
+ }
+
+
+ ///
+ /// Quartz调度任务注册
+ ///
+ /// 类名
+ /// 作业名称
+ /// 触发器名称
+ /// 任务组名称
+ private async void GetScheduleJob(Type className, string jobName, string triggerName, string group,int time)
+ {
+ var method = typeof(JobBuilder)
+ .GetMethods()
+ .First(m => m.Name == "Create" && m.IsGenericMethod);
+
+ var genericMethod = method.MakeGenericMethod(className);
+ var jobBuilder = genericMethod.Invoke(null, null);
+
+ //任务处理---注册任务
+ IJobDetail job = ((JobBuilder)jobBuilder)
+ //.Create()
+ .WithIdentity(jobName, group)
+ .DisallowConcurrentExecution()
+ .Build();
+
+ //任务处理---触发器
+ ITrigger trigger = TriggerBuilder
+ .Create()
+ .WithIdentity(triggerName, group)
+ .StartNow()
+ .WithSimpleSchedule(x => x
+ .WithInterval(TimeSpan.FromMilliseconds(time))
+ .RepeatForever())
+ .Build();
+
+ await _scheduler.ScheduleJob(job, trigger);
+ }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/AssemblyInfo.cs b/WPFWCSDemo/AssemblyInfo.cs
new file mode 100644
index 0000000..8b5504e
--- /dev/null
+++ b/WPFWCSDemo/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/WPFWCSDemo/Common/ConnectionUrl.cs b/WPFWCSDemo/Common/ConnectionUrl.cs
new file mode 100644
index 0000000..57ec7d4
--- /dev/null
+++ b/WPFWCSDemo/Common/ConnectionUrl.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Common
+{
+ public class ConnectionUrl
+ {
+ ///
+ /// wms连接url
+ ///
+ public static string wms = $"{ConfigurationManager.AppSettings["WmsIP"]}:{ConfigurationManager.AppSettings["WmsPort"]}";
+ ///
+ /// 输送机IP
+ ///
+ public static string Conv = $"{ConfigurationManager.AppSettings["Conv"]}";
+ ///
+ /// 1#提升机IP
+ ///
+ public static string lift1 = $"{ConfigurationManager.AppSettings["Lift1"]}";
+ ///
+ /// 2#提升机IP
+ ///
+ public static string lift2 = $"{ConfigurationManager.AppSettings["Lift2"]}";
+ ///
+ /// 1#穿梭车IP
+ ///
+ public static string rGV1 = $"{ConfigurationManager.AppSettings["RGV1"]}";
+ ///
+ /// 2#穿梭车IP
+ ///
+ public static string rGV2 = $"{ConfigurationManager.AppSettings["RGV2"]}";
+ ///
+ /// 1#堆垛机IP
+ ///
+ public static string stacker1 = $"{ConfigurationManager.AppSettings["Stacker1"]}";
+ ///
+ /// 2#堆垛机IP
+ ///
+ public static string stacker2 = $"{ConfigurationManager.AppSettings["Stacker2"]}";
+ ///
+ /// 3#堆垛机IP
+ ///
+ public static string stacker3 = $"{ConfigurationManager.AppSettings["Stacker3"]}";
+ }
+}
diff --git a/WPFWCSDemo/Common/Converters/ColorToBrushConverter.cs b/WPFWCSDemo/Common/Converters/ColorToBrushConverter.cs
new file mode 100644
index 0000000..5bb26fe
--- /dev/null
+++ b/WPFWCSDemo/Common/Converters/ColorToBrushConverter.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+using System.Windows.Media;
+
+namespace WPFWCSDemo.Common.Converters
+{
+ [ValueConversion(typeof(Color), typeof(Brush))]
+ public class ColorToBrushConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is Color color)
+ {
+ return new SolidColorBrush(color);
+ }
+ return Binding.DoNothing;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ if (value is SolidColorBrush brush)
+ {
+ return brush.Color;
+ }
+ return default(Color);
+ }
+ }
+}
diff --git a/WPFWCSDemo/Common/CustomAttributes/TimerTaskAttribute.cs b/WPFWCSDemo/Common/CustomAttributes/TimerTaskAttribute.cs
new file mode 100644
index 0000000..14d069d
--- /dev/null
+++ b/WPFWCSDemo/Common/CustomAttributes/TimerTaskAttribute.cs
@@ -0,0 +1,67 @@
+using Quartz;
+using Quartz.Impl;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Common.CustomAttributes
+{
+ [AttributeUsage(AttributeTargets.Method)]
+ public class TimerTaskAttribute:Attribute
+ {
+ public int Second { get; set; }
+ public int Minute { get; set; }
+ public int Hour { get; set; }
+
+ private IScheduler _scheduler;
+
+ ///
+ /// Quartz调度任务注册
+ ///
+ /// 类名
+ /// 作业名称
+ /// 触发器名称
+ /// 任务组名称
+ private async void GetScheduleJob(Type className, string jobName, string triggerName, string group, int time)
+ {
+ ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
+ _scheduler = schedulerFactory.GetScheduler().Result;
+ await _scheduler.Start();
+
+ var method = typeof(JobBuilder)
+ .GetMethods()
+ .First(m => m.Name == "Create" && m.IsGenericMethod);
+
+ var genericMethod = method.MakeGenericMethod(className);
+ var jobBuilder = genericMethod.Invoke(null, null);
+
+ //任务处理---注册任务
+ IJobDetail job = ((JobBuilder)jobBuilder)
+ //.Create()
+ .WithIdentity(jobName, group)
+ .DisallowConcurrentExecution()
+ .Build();
+
+ //任务处理---触发器
+ ITrigger trigger = TriggerBuilder
+ .Create()
+ .WithIdentity(triggerName, group)
+ .StartNow()
+ .WithSimpleSchedule(x => x
+ .WithInterval(TimeSpan.FromMilliseconds(time))
+ .RepeatForever())
+ .Build();
+
+ await _scheduler.ScheduleJob(job, trigger);
+ }
+
+
+
+
+
+ }
+
+
+}
diff --git a/WPFWCSDemo/Common/RGVStation.cs b/WPFWCSDemo/Common/RGVStation.cs
new file mode 100644
index 0000000..fc553ed
--- /dev/null
+++ b/WPFWCSDemo/Common/RGVStation.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Common
+{
+ ///
+ /// RGV取放货站点
+ ///
+ public class RGVStation
+ {
+ ///
+ /// 环穿运行设备数量
+ ///
+ public const int RGVCount = 13;
+
+ ///
+ /// H线供实垛 1001
+ ///
+ public const int LineH_Goods_In = 1001;
+ ///
+ /// M线供实垛 1003
+ ///
+ public const int LineM_Goods_In = 1003;
+ ///
+ /// L线供实垛 1005
+ ///
+ public const int LineL_Goods_In = 1005;
+ ///
+ /// G1线供实垛 1007
+ ///
+ public const int LineG1_Goods_In = 1007;
+ ///
+ /// G2线供实垛 1008
+ ///
+ public const int LineG2_Goods_In = 1008;
+
+
+ ///
+ /// 立库口送实垛1-1009
+ ///
+ public const int LineToWarehouse1_Out = 1009;
+ ///
+ /// 立库口送实垛2-1010
+ ///
+ public const int LineToWarehouse2_Out = 1010;
+ ///
+ /// G线送实垛-1011
+ ///
+ public const int LineG_Goods_Out = 1011;
+ ///
+ /// H线送实垛-1012
+ ///
+ public const int LineH_Goods_Out = 1012;
+
+ //==============================================================================================
+
+ ///
+ /// 供空托 1013
+ ///
+ public const int LineGH_Pallets_In = 1013;
+
+ ///
+ /// 放空托1 1002
+ ///
+ public const int LineH_Pallets_Out = 1002;
+ ///
+ /// 放空托2 1004
+ ///
+ public const int LineG_Pallets_Out = 1004;
+ ///
+ /// 放空托3 1006
+ ///
+ public const int LineLM_Pallets_Out = 1006;
+
+ }
+}
diff --git a/WPFWCSDemo/Data/AppDbContext.cs b/WPFWCSDemo/Data/AppDbContext.cs
new file mode 100644
index 0000000..8dd21a3
--- /dev/null
+++ b/WPFWCSDemo/Data/AppDbContext.cs
@@ -0,0 +1,141 @@
+using Microsoft.EntityFrameworkCore;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Xml;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.Utilities;
+
+namespace WPFWCSDemo.Data
+{
+ public class AppDbContext : DbContext
+ {
+ public DbSet Tasks { get; set; }
+ public DbSet TaskViews { get; set; }
+ public DbSet TaskHistoriesView { get; set; }
+ public DbSet TaskHistories { get; set; }
+ public DbSet Alarms { get; set; }
+ public DbSet AlarmHistories { get; set; }
+ public DbSet LoadedState { get; set; }
+ public DbSet Event_Log { get; set; }
+ public DbSet LineState { get; set; }
+ public DbSet ConvRequest { get; set; }
+
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString);
+ }
+
+
+ ///
+ /// 配置库与库表的映射关系
+ ///
+ ///
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ base.OnModelCreating(modelBuilder);
+
+ //TASK表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToTable("TASK");
+ e.HasKey(t => t.TaskId);
+ });
+
+ //TASK_VIEW表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToView("TASK_VIEW");
+ e.Property(t => t.JobId).HasColumnName("环穿编号");
+ e.Property(t => t.TaskId).HasColumnName("任务号");
+ e.Ignore(t => t.PalletId);
+ e.Property(t => t.TaskType).HasColumnName("任务类型");
+ e.Property(t => t.TaskState).HasColumnName("任务状态");
+ e.Property(t => t.ScheduleState).HasColumnName("调度状态");
+ e.Property(t => t.SourceLocation).HasColumnName("源站点");
+ e.Property(t => t.TargetLocation).HasColumnName("目标站点");
+ e.Ignore(t => t.ReportState);
+ e.Ignore(t => t.Priority);
+ e.Property(t => t.CreateTime).HasColumnName("生成时间");
+ e.Property(t => t.ScheduleTime).HasColumnName("调度时间");
+ e.HasNoKey();
+ });
+
+ //TASK_HISTORY表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToTable("TASK_HISTORY");
+ e.HasKey(t => t.Id);
+ });
+
+ //TASK_HISTORY_VIEW表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToView("TASK_HISTORY_VIEW");
+ e.Property(t => t.JobId).HasColumnName("环穿编号");
+ e.Property(t => t.TaskId).HasColumnName("任务号");
+ e.Ignore(t => t.PalletId);
+ e.Property(t => t.TaskType).HasColumnName("任务类型");
+ e.Property(t => t.TaskState).HasColumnName("任务状态");
+ e.Property(t => t.ScheduleState).HasColumnName("调度状态");
+ e.Property(t => t.SourceLocation).HasColumnName("源站点");
+ e.Property(t => t.TargetLocation).HasColumnName("目标站点");
+ e.Ignore(t => t.ReportState);
+ e.Ignore(t => t.Priority);
+ e.Property(t => t.CreateTime).HasColumnName("生成时间");
+ e.Property(t => t.ScheduleTime).HasColumnName("调度时间");
+ e.Property(t => t.FinishTime).HasColumnName("结束时间");
+ e.HasNoKey();
+ });
+
+ //ALARM表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToTable("ALARM");
+ e.HasKey(a => a.Point_Id);
+ });
+
+ //ALARM_LOG表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToTable("ALARM_LOG");
+ e.HasKey(a => a.Id);
+ });
+
+ //LOADEDSTATE表配置
+ modelBuilder.Entity(e =>
+ {
+ //e.ToTable("LoadedState");
+ e.HasKey(a => a.Station);
+ });
+
+ //EVENT_LOG表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToTable("EVENT_LOG");
+ e.HasKey(a => a.Id);
+ });
+
+ //LINESTATE表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToTable("LINESTATE");
+ e.HasKey(a => a.Name);
+ });
+
+ //CONVREQUEST表配置
+ modelBuilder.Entity(e =>
+ {
+ e.ToTable("CONVREQUEST");
+ e.HasKey(a => a.Id);
+ });
+
+ }
+ }
+}
diff --git a/WPFWCSDemo/MainWindow.xaml b/WPFWCSDemo/MainWindow.xaml
new file mode 100644
index 0000000..6bd669e
--- /dev/null
+++ b/WPFWCSDemo/MainWindow.xaml
@@ -0,0 +1,228 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/MainWindow.xaml.cs b/WPFWCSDemo/MainWindow.xaml.cs
new file mode 100644
index 0000000..eb59649
--- /dev/null
+++ b/WPFWCSDemo/MainWindow.xaml.cs
@@ -0,0 +1,79 @@
+using System.Windows;
+using System.Windows.Input;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.ViewModels;
+using WPFWCSDemo.Views;
+
+namespace WPFWCSDemo
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ DataContext = new MainViewModel(mainFrame);
+
+ DevicesNavigationView.GetMainFrame(mainFrame);
+
+ //初始页面
+ //mainFrame.Navigate(new MonitorView());
+ //this.NavigationService.Navigate(new Uri("MonitorView.xaml"));
+ mainFrame.NavigationService.Navigate(new DataInfoView());
+
+ #region 窗口拖动/大小化
+ //最小化
+ btnMin.Click += (s, e) => { this.WindowState = WindowState.Minimized; };
+ //最大化
+ btnMax.Click += (s, e) => { WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal; };
+ //双击最大化 / 最小化
+ colorZone.MouseDoubleClick += (s, e) =>
+ {
+ if (e.Source == s && !colorZone.IsMouseCaptureWithin)
+ {
+ WindowState = WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal;
+ }
+ };
+ //关闭
+ btnClose.Click += (s, e) =>
+ {
+ MessageDialog dialog = new MessageDialog();
+ dialog.Title = "弹窗提示";
+ // 显示弹窗窗口
+ dialog.ShowDialog();
+
+
+ //if (MessageBox.Show("关闭该系统可能导致执行中的任务中断,是否确认要退出程序?", "提示", )
+ //{
+ // //Environment.Exit(exitCode:1);
+ // Application.Current.Shutdown();
+ //}
+ //else
+ //{
+ // //关闭通道操作在这执行
+
+ //}
+
+ };
+ //设备控制器
+ //btnController.Click += (s, e) =>
+ //{
+ // ControllerView controllerView = new ControllerView();
+ // controllerView.Show();
+ //};
+
+ //拖动
+ colorZone.MouseMove += (s, e) =>
+ {
+ if (e.LeftButton == MouseButtonState.Pressed) DragMove();
+ };
+
+ //添加事件:选择后将左侧导航栏隐藏1
+ menuBar.SelectionChanged += (s, e) => { drawerHost.IsLeftDrawerOpen = false; };
+ #endregion
+
+ }
+ }
+}
diff --git a/WPFWCSDemo/Models/Cargo.cs b/WPFWCSDemo/Models/Cargo.cs
new file mode 100644
index 0000000..1c3a195
--- /dev/null
+++ b/WPFWCSDemo/Models/Cargo.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models
+{
+ ///
+ /// 货位状态表
+ ///
+ public class Cargo
+ {
+ ///
+ /// 货位编码
+ ///
+ public string Cargo_ID { get; set; }
+ ///
+ /// 货位名称
+ ///
+ public string Cargo_Name { get; set; }
+ ///
+ /// 货位区域
+ ///
+ public string Cargo_Area { get; set; }
+ ///
+ /// 货位状态
+ ///
+ public int Status { get; set; }
+ ///
+ /// 条码
+ ///
+ public string TrayCode { get; set; }
+ ///
+ /// 排
+ ///
+ public int Row { get; set; }
+ ///
+ /// 列
+ ///
+ public int Column { get; set; }
+ ///
+ /// 层
+ ///
+ public int Floor { get; set; }
+ ///
+ /// 巷道
+ ///
+ public int Road { get; set; }
+ ///
+ /// 是否可用
+ ///
+ public int Enable { get; set; }
+ ///
+ /// 更新时间
+ ///
+ public string UpdateTime { get; set; }
+
+ }
+}
diff --git a/WPFWCSDemo/Models/DataInfoTaskAsc.cs b/WPFWCSDemo/Models/DataInfoTaskAsc.cs
new file mode 100644
index 0000000..ba32ee5
--- /dev/null
+++ b/WPFWCSDemo/Models/DataInfoTaskAsc.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models
+{
+ ///
+ /// 看板页左侧部分任务展示
+ ///
+ public class DataInfoTaskAsc
+ {
+ ///
+ /// 作业号
+ ///
+ public string? JobId { get; set; }
+ ///
+ /// 任务号
+ ///
+ public string? TaskId { get; set; }
+ ///
+ /// 托盘条码
+ ///
+ public string? PalletId { get; set; }
+ ///
+ /// 调度状态
+ ///
+ public string? ScheduleState { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public int? TaskType { get; set; }
+ ///
+ /// 源站点
+ ///
+ public string? SourceLocation { get; set; }
+ ///
+ /// 目标站点
+ ///
+ public string? TargetLocation { get; set; }
+
+ }
+}
diff --git a/WPFWCSDemo/Models/DataInfoTaskbar.cs b/WPFWCSDemo/Models/DataInfoTaskbar.cs
new file mode 100644
index 0000000..8b4a292
--- /dev/null
+++ b/WPFWCSDemo/Models/DataInfoTaskbar.cs
@@ -0,0 +1,40 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models
+{
+ ///
+ /// 看板顶部任务
+ ///
+ public partial class DataInfoTaskbar : ObservableObject
+ {
+ ///
+ /// 图标
+ ///
+ public string? Icon { get; set; }
+ ///
+ /// 标题
+ ///
+ public string? Title { get; set; }
+ ///
+ /// 内容
+ ///
+ [ObservableProperty]
+ //public int? Content { get; set; }
+ public int? _content;
+ ///
+ /// 颜色
+ ///
+ [ObservableProperty]
+ //public string? Color { get; set; }
+ public string? _color;
+ ///
+ /// 触发目标(点击可能触发一些功能,增加命名空间)
+ ///
+ public string? Target { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/CircleRGV/CircleRGVCommand.cs b/WPFWCSDemo/Models/Devices/CircleRGV/CircleRGVCommand.cs
new file mode 100644
index 0000000..a4bac61
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/CircleRGV/CircleRGVCommand.cs
@@ -0,0 +1,46 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.CircleRGV
+{
+ public partial class CircleRGVCommand:ObservableObject
+ {
+ //*************************************************写入*************************************************
+ ///
+ /// 下发任务号
+ ///
+ public int Write_TaskNumber { get; set; }
+ ///
+ /// 下发穿梭车编号
+ ///
+ public int Write_DeviceNumber { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public int Write_TaskType { get; set; }
+ ///
+ /// 设备状态
+ ///
+ public int Write_DeviceState { get; set; }
+ ///
+ /// 下发取货站点
+ ///
+ public string? Write_SourceLocation { get; set; }
+ ///
+ /// 下发放货站点
+ ///
+ public string? Write_TargetLocation { get; set; }
+ ///
+ /// 下发完成
+ ///
+ public int Write_SendFinish { get; set; }
+ ///
+ /// 下发校验码
+ ///
+ public int Write_Checksum { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/CircleRGV/CircleRGVState.cs b/WPFWCSDemo/Models/Devices/CircleRGV/CircleRGVState.cs
new file mode 100644
index 0000000..d2362fe
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/CircleRGV/CircleRGVState.cs
@@ -0,0 +1,109 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.CircleRGV
+{
+ public class CircleRGVState : IDisposable
+ {
+ //*************************************************读取*************************************************
+ ///
+ /// 标题
+ ///
+ public string? Title { get; set; }
+ ///
+ /// 编号
+ ///
+ public int Number { get; set; }
+ ///
+ /// 操作模式 0-未知 1-工作 2-手动
+ ///
+ public short Read_Mode { get; set; }
+ ///
+ /// 设备状态 0-未知 1-工作 2-手动 3-自动待机 100-报警
+ ///
+ public short Read_DeviceState { get; set; }
+ ///
+ /// 执行阶段 1-取货途中,2-取货,3-送货途中,4-送货,5-完成
+ ///
+ public short Read_Phase { get; set; }
+ ///
+ /// 任务号
+ ///
+ public int Read_TaskNumber { get; set; }
+ ///
+ /// 允许下发 false-禁止 true-允许
+ ///
+ public bool Read_Permission { get; set; }
+ ///
+ /// 当前站点
+ ///
+ public string? Read_CurrentLocation { get; set; }
+ ///
+ /// 取货站点
+ ///
+ public string? Read_SourceLocation { get; set; }
+ ///
+ /// 放货站点
+ ///
+ public string? Read_TargetLocation { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public byte Read_TaskType { get; set; }
+ ///
+ /// BPS
+ ///
+ public int Read_BPSNumber { get; set; }
+ ///
+ /// 运行里程
+ ///
+ public double Read_Mileage { get; set; }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ private bool disposedValue;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // TODO: 释放托管状态(托管对象)
+ }
+
+ // TODO: 释放未托管的资源(未托管的对象)并重写终结器
+ // TODO: 将大型字段设置为 null
+ disposedValue = true;
+ }
+ }
+
+ // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
+ // ~CircleRGVState()
+ // {
+ // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
+ // Dispose(disposing: false);
+ // }
+
+ public void Dispose()
+ {
+ // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/CircleRGVStation/CircleRGVStationCommand.cs b/WPFWCSDemo/Models/Devices/CircleRGVStation/CircleRGVStationCommand.cs
new file mode 100644
index 0000000..466e5ad
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/CircleRGVStation/CircleRGVStationCommand.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.CircleRGVStation
+{
+ public class CircleRGVStationCommand
+ {
+ ///
+ /// 下发任务号
+ ///
+ public int Write_TaskNumber { get; set; }
+ ///
+ /// 下发穿梭车编号 常规任务-0 其他任务-环穿编号
+ ///
+ public int Write_DeviceNumber { get; set; }
+ ///
+ /// 任务类型 1-常规任务 2-小车回休息区 3-休息区小车上轨道
+ ///
+ public int Write_TaskType { get; set; }
+ ///
+ /// 下发取货站点
+ ///
+ public int Write_SourceLocation { get; set; }
+ ///
+ /// 下发放货站点
+ ///
+ public int Write_TargetLocation { get; set; }
+ ///
+ /// 下发完成
+ ///
+ public int Write_SendFinish { get; set; }
+ ///
+ /// 下发校验码-所有字节求和
+ ///
+ public short Write_Checksum { get; set; }
+
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/CircleRGVStation/CircleRGVStationState.cs b/WPFWCSDemo/Models/Devices/CircleRGVStation/CircleRGVStationState.cs
new file mode 100644
index 0000000..7e96aff
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/CircleRGVStation/CircleRGVStationState.cs
@@ -0,0 +1,197 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.CircleRGVStation
+{
+ public class CircleRGVStationState : IDisposable
+ {
+ ///
+ /// 允许下发 0-禁止下发 1-允许下发
+ ///
+ public int Read_Permission { get; set; }
+ ///
+ /// 下发状态 0-其他,1-正常接收,2-接收异常
+ ///
+ public int Read_SendState { get; set; }
+ ///
+ /// 任务号
+ ///
+ public int Read_TaskNumber { get; set; }
+
+
+
+
+
+ //---------------------------------供实垛侧站点---------------------------------
+ //---------------------------------供实垛侧站点---------------------------------
+ //---------------------------------供实垛侧站点---------------------------------
+
+ ///
+ /// 取货请求---供实垛-1001
+ ///
+ public bool Read_GetRequest_1001 { get; set; }
+ ///
+ /// 1001供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1001 { get; set; }
+
+ ///
+ /// 取货请求---供实垛-1003
+ ///
+ public bool Read_GetRequest_1003 { get; set; }
+ ///
+ /// 1003供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1003 { get; set; }
+
+ ///
+ /// 取货请求---供实垛-1005
+ ///
+ public bool Read_GetRequest_1005 { get; set; }
+ ///
+ /// 1005供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1005 { get; set; }
+
+ ///
+ /// 取货请求---D线供实垛-1007
+ ///
+ public bool Read_GetRequest_1007 { get; set; }
+ ///
+ /// 1007供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1007 { get; set; }
+
+ ///
+ /// 取货请求---D线供实垛-1008
+ ///
+ public bool Read_GetRequest_1008 { get; set; }
+ ///
+ /// 1008供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1008 { get; set; }
+
+ //-------------------------------------------------------------------------------
+
+ ///
+ /// 放货请求---立库入口1供实垛-1009
+ ///
+ public bool Read_PutRequest_1009 { get; set; }
+ ///
+ /// 1009供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1009 { get; set; }
+
+ ///
+ /// 放货请求---立库入口2供实垛-1010
+ ///
+ public bool Read_PutRequest_1010 { get; set; }
+ ///
+ /// 1010供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1010 { get; set; }
+
+ ///
+ /// 放货请求---供实垛-1011
+ ///
+ public bool Read_PutRequest_1011 { get; set; }
+ ///
+ /// 1011供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1011 { get; set; }
+
+ ///
+ /// 放货请求---供实垛-1012
+ ///
+ public bool Read_PutRequest_1012 { get; set; }
+ ///
+ /// 1012供实垛系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1012 { get; set; }
+
+ //==========================================================================
+
+ ///
+ /// 空托请求---供空托-1013
+ ///
+ public bool Read_GetRequest_1013 { get; set; }
+ ///
+ /// 1013供空托系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1013 { get; set; }
+
+ //-------------------------------------------------------------------
+
+ ///
+ /// 空托请求---放空托-1002
+ ///
+ public bool Read_PutRequest_1002 { get; set; }
+ ///
+ /// 1002供空托系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1002 { get; set; }
+
+ ///
+ /// 空托请求---放空托-1004
+ ///
+ public bool Read_PutRequest_1004 { get; set; }
+ ///
+ /// 1004供空托系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1004 { get; set; }
+
+ ///
+ /// 空托请求---放空托-1006
+ ///
+ public bool Read_PutRequest_1006 { get; set; }
+ ///
+ /// 1006供空托系统正常 true-正常 false-异常
+ ///
+ public bool Read_IsNotException_1006 { get; set; }
+
+
+
+
+
+
+
+
+
+
+ private bool disposedValue;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // TODO: 释放托管状态(托管对象)
+ }
+
+ // TODO: 释放未托管的资源(未托管的对象)并重写终结器
+ // TODO: 将大型字段设置为 null
+ disposedValue = true;
+ }
+ }
+
+ // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
+ // ~CircleRGVStationState()
+ // {
+ // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
+ // Dispose(disposing: false);
+ // }
+
+ public void Dispose()
+ {
+ // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/Conv/ConvCommand.cs b/WPFWCSDemo/Models/Devices/Conv/ConvCommand.cs
new file mode 100644
index 0000000..ecb6bde
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/Conv/ConvCommand.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.Conv
+{
+ public class ConvCommand
+ {
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/Conv/ConvGet/ConvGetCommand.cs b/WPFWCSDemo/Models/Devices/Conv/ConvGet/ConvGetCommand.cs
new file mode 100644
index 0000000..7e39bb4
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/Conv/ConvGet/ConvGetCommand.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.Conv.ConvGet
+{
+ public class ConvGetCommand
+ {
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/Conv/ConvGet/ConvGetState.cs b/WPFWCSDemo/Models/Devices/Conv/ConvGet/ConvGetState.cs
new file mode 100644
index 0000000..1046e59
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/Conv/ConvGet/ConvGetState.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.Conv.ConvGet
+{
+ public class ConvGetState
+ {
+ ///
+ /// A线取货请求
+ ///
+ public bool A_InRequest { get; set; }
+ ///
+ /// A线供实垛系统正常
+ ///
+ public bool A_Exception { get; set; }
+
+ ///
+ /// B线取货请求
+ ///
+ public bool B_InRequest { get; set; }
+ ///
+ /// B线回空托请求
+ ///
+ public bool B_BackRequest { get; set; }
+ ///
+ /// B线供实垛系统正常
+ ///
+ public bool B_Exception { get; set; }
+
+ ///
+ /// C线取货请求
+ ///
+ public bool C_InRequest { get; set; }
+ ///
+ /// C线回空托请求
+ ///
+ public bool C_BackRequest { get; set; }
+ ///
+ /// C线供实垛系统正常
+ ///
+ public bool C_Exception { get; set; }
+
+ ///
+ /// D线取货请求
+ ///
+ public bool D_InRequest { get; set; }
+ ///
+ /// D线供实垛系统正常
+ ///
+ public bool D_Exception { get; set; }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/Conv/ConvPut/ConvPutCommand.cs b/WPFWCSDemo/Models/Devices/Conv/ConvPut/ConvPutCommand.cs
new file mode 100644
index 0000000..76fb30d
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/Conv/ConvPut/ConvPutCommand.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.Conv.ConvPut
+{
+ public class ConvPutCommand
+ {
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/Conv/ConvPut/ConvPutState.cs b/WPFWCSDemo/Models/Devices/Conv/ConvPut/ConvPutState.cs
new file mode 100644
index 0000000..9b311f7
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/Conv/ConvPut/ConvPutState.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.Conv.ConvPut
+{
+
+ public class ConvPutState
+ {
+ ///
+ /// AB口请求出空托
+ ///
+ public bool AB_OutRequest { get; set; }
+ ///
+ /// AB输送机无故障
+ ///
+ public bool AB_Exception { get; set; }
+
+ ///
+ /// CD口请求出空托
+ ///
+ public bool CD_OutRequest { get; set; }
+ ///
+ /// CD输送机无故障
+ ///
+ public bool CD_Exception { get; set; }
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Devices/Conv/ConvState.cs b/WPFWCSDemo/Models/Devices/Conv/ConvState.cs
new file mode 100644
index 0000000..64f692c
--- /dev/null
+++ b/WPFWCSDemo/Models/Devices/Conv/ConvState.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Devices.Conv
+{
+ public class ConvState
+ {
+ ///
+ /// 任务号
+ ///
+ public int Read_TaskNumber { get; set; }
+ ///
+ /// 输送到位
+ ///
+ public int Read_InPosition { get; set; }
+ ///
+ /// 输送请求
+ ///
+ public int Read_TransRequest { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/Menu.cs b/WPFWCSDemo/Models/Menu.cs
new file mode 100644
index 0000000..7b4cd30
--- /dev/null
+++ b/WPFWCSDemo/Models/Menu.cs
@@ -0,0 +1,19 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models
+{
+ public class MenuBar
+ {
+
+ public string? Icon { get; set; }
+
+ public string? Title { get; set; }
+
+ public string? NameSpace { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/MessageDialog.cs b/WPFWCSDemo/Models/MessageDialog.cs
new file mode 100644
index 0000000..a27bde3
--- /dev/null
+++ b/WPFWCSDemo/Models/MessageDialog.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models
+{
+ public class MessageDialog
+ {
+ ///
+ /// 标题
+ ///
+ public string Title { get; set; }
+ ///
+ /// 内容
+ ///
+ public string Message { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/SettingMenu.cs b/WPFWCSDemo/Models/SettingMenu.cs
new file mode 100644
index 0000000..e7f372a
--- /dev/null
+++ b/WPFWCSDemo/Models/SettingMenu.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models
+{
+ ///
+ /// 系统导航菜单实体类
+ ///
+ public class SettingMenu
+ {
+ ///
+ /// 菜单图标
+ ///
+ public string Icon { get; set; }
+ ///
+ /// 菜单名称
+ ///
+ public string Title { get; set; }
+ ///
+ /// 菜单命名空间
+ ///
+ public string NameSpace { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/Alarm.cs b/WPFWCSDemo/Models/Tables/Alarm.cs
new file mode 100644
index 0000000..5473c71
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/Alarm.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ ///
+ /// 实时报警
+ ///
+ public class Alarm
+ {
+ ///
+ /// 报警名称
+ ///
+ [Key]
+ public string Point_Id { get; set; }
+ ///
+ /// 报警信息
+ ///
+ public string? Description { get; set; }
+ ///
+ /// 优先级
+ ///
+ public string? Priority { get; set; }
+ ///
+ /// 设备类别
+ ///
+ public string? Device_Id { get; set; }
+ ///
+ /// 开始时间
+ ///
+ public DateTime? Gen_Time { get; set; }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/AlarmHistory.cs b/WPFWCSDemo/Models/Tables/AlarmHistory.cs
new file mode 100644
index 0000000..d5d3330
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/AlarmHistory.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ ///
+ /// 历史报警
+ ///
+ public class AlarmHistory
+ {
+ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+ [AllowNull]
+ public Guid Id { get; set; } = Guid.NewGuid();
+ ///
+ /// 报警名称
+ ///
+ public string? Point_Id { get; set; }
+ ///
+ /// 报警信息
+ ///
+ public string? Description { get; set; }
+ ///
+ /// 优先级
+ ///
+ [AllowNull]
+ public string? Priority { get; set; }
+ ///
+ /// 设备类别
+ ///
+ public string? Device_Id { get; set; }
+ ///
+ /// 开始时间
+ ///
+ [AllowNull]
+ public DateTime? Gen_Time { get; set; }
+ ///
+ /// 复位时间
+ ///
+ //public DateTime? Reset_Time { get; set; }
+ ///
+ /// 删除时间
+ ///
+ //public DateTime? Delete_Time { get; set; }
+ ///
+ /// 结束时间
+ ///
+ public DateTime? End_Time { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/ConvRequest.cs b/WPFWCSDemo/Models/Tables/ConvRequest.cs
new file mode 100644
index 0000000..8625e34
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/ConvRequest.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ ///
+ /// 输送口请求
+ ///
+ public class ConvRequest
+ {
+ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+ [AllowNull]
+ [JsonIgnore]
+ public Guid Id { get; set; } = Guid.NewGuid();
+
+ ///
+ /// 1001
+ ///
+ public int Conv_Goods_In_1001 { get; set; }
+ ///
+ /// 1003
+ ///
+ public int Conv_Goods_In_1003 { get; set; }
+ ///
+ /// 1005
+ ///
+ public int Conv_Goods_In_1005 { get; set; }
+ ///
+ /// 1007
+ ///
+ public int Conv_Goods_In_1007 { get; set; }
+ ///
+ /// 1008
+ ///
+ public int Conv_Goods_In_1008 { get; set; }
+ /////
+ ///// 立库1-1009
+ /////
+ //public int Conv_Goods_Out_1009 { get; set; }
+ /////
+ ///// 立库1-1010
+ /////
+ //public int Conv_Goods_Out_1010 { get; set; }
+ /////
+ ///// 1011
+ /////
+ //public int Conv_Goods_Out_1011 { get; set; }
+ /////
+ ///// 1012
+ /////
+ //public int Conv_Goods_Out_1012 { get; set; }
+
+ ///
+ /// 时间
+ ///
+ [JsonIgnore]
+ public string? Time { get; set; }
+
+
+ ///
+ /// 1013
+ ///
+ public int Conv_Pallet_In_1013 { get; set; }
+ ///
+ /// 1002
+ ///
+ public int Conv_Pallet_Out_1002 { get; set; }
+ ///
+ /// 1004
+ ///
+ public int Conv_Pallet_Out_1004 { get; set; }
+ ///
+ /// 1006
+ ///
+ public int Conv_Pallet_Out_1006 { get; set; }
+
+
+
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/Event_Log.cs b/WPFWCSDemo/Models/Tables/Event_Log.cs
new file mode 100644
index 0000000..0d7b6a2
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/Event_Log.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ public class Event_Log
+ {
+ ///
+ /// 事件标识
+ ///
+ [JsonIgnore]
+ public Guid Id { get; set; } = Guid.NewGuid();
+ ///
+ /// 事件信息
+ ///
+ public string? Message { get; set; }
+ ///
+ /// 时间
+ ///
+ public string? TimeStamp { get; set; }
+ ///
+ /// 操作角色
+ ///
+ public string? UserId { get; set; }
+ ///
+ /// 事件类型(登录、操作、错误等)
+ ///
+ public string? Type { get; set; }
+ ///
+ /// 事件来源(名称、控件等)
+ ///
+ public string? Source { get; set; }
+ ///
+ /// 重要程度(信息、警告、错误等)
+ ///
+ public string? Level { get; set; }
+ ///
+ /// 事件状态(完成、失败等)
+ ///
+ public string? Status { get; set; }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/LineState.cs b/WPFWCSDemo/Models/Tables/LineState.cs
new file mode 100644
index 0000000..bd66754
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/LineState.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ public class LineState
+ {
+ ///
+ /// 输送线名称
+ ///
+ public string Name { get; set; }
+ ///
+ /// 源站
+ ///
+ public int Source { get; set; }
+ ///
+ /// 目标站
+ ///
+ public int Target { get; set; }
+ ///
+ /// 输送线是否允许生成任务(由上位控制) 1-正常 0-禁止
+ ///
+ public int IsEnable { get; set; }
+ ///
+ /// 输送线功能
+ ///
+ public string? Property { get; set; }
+ ///
+ /// 备注
+ ///
+ public string? Description { get; set; }
+
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/LoadedState.cs b/WPFWCSDemo/Models/Tables/LoadedState.cs
new file mode 100644
index 0000000..2f4ced6
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/LoadedState.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ public class LoadedState
+ {
+ ///
+ /// 站点
+ ///
+ public int Station { get; set; }
+ ///
+ /// 生成任务时间
+ ///
+ public DateTime? GenerationTime { get; set; }
+ ///
+ /// 开始取货时间
+ ///
+ public DateTime? LoadingTime { get; set; }
+ ///
+ /// 取货完成时间
+ ///
+ public DateTime? LoadedTime { get; set; }
+ ///
+ /// 开发放货时间
+ ///
+ public DateTime? PuttingTime { get; set; }
+
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/TaskHistory.cs b/WPFWCSDemo/Models/Tables/TaskHistory.cs
new file mode 100644
index 0000000..8c09fac
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/TaskHistory.cs
@@ -0,0 +1,67 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Linq;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ public class TaskHistory
+ {
+ [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
+ public Guid Id { get; set; } = Guid.NewGuid();
+ ///
+ /// 作业号
+ ///
+ public string? JobId { get; set; }
+ ///
+ /// 任务号
+ ///
+ public string? TaskId { get; set; }
+ ///
+ /// 条码
+ ///
+ public string? PalletId { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public string? TaskType { get; set; }
+ ///
+ /// 源站
+ ///
+ public string? SourceLocation { get; set; }
+ ///
+ /// 目标站
+ ///
+ public string? TargetLocation { get; set; }
+ ///
+ /// 优先级
+ ///
+ public int? Priority { get; set; }
+ ///
+ /// 任务状态
+ ///
+ public string? TaskState { get; set; }
+ ///
+ /// 调度状态
+ ///
+ public string? ScheduleState { get; set; }
+ ///
+ /// 生成时间
+ ///
+ public DateTime? CreateTime { get; set; }
+ ///
+ /// 调度时间
+ ///
+ public DateTime? ScheduleTime { get; set; }
+ ///
+ /// 完成时间
+ ///
+ public DateTime? FinishTime { get; set; }
+ ///
+ /// 反馈状态
+ ///
+ public string? ReportState { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/TaskHistoryView.cs b/WPFWCSDemo/Models/Tables/TaskHistoryView.cs
new file mode 100644
index 0000000..d11f108
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/TaskHistoryView.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ public class TaskHistoryView
+ {
+ ///
+ /// 作业号
+ ///
+ public string? JobId { get; set; }
+ ///
+ /// 任务号
+ ///
+ public string? TaskId { get; set; }
+ ///
+ /// 条码
+ ///
+ public string? PalletId { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public string? TaskType { get; set; }
+ ///
+ /// 源站
+ ///
+ public string? SourceLocation { get; set; }
+ ///
+ /// 目标站
+ ///
+ public string? TargetLocation { get; set; }
+ ///
+ /// 优先级
+ ///
+ public int? Priority { get; set; }
+ ///
+ /// 任务状态
+ ///
+ public string? TaskState { get; set; }
+ ///
+ /// 调度状态
+ ///
+ public string? ScheduleState { get; set; }
+ ///
+ /// 生成时间
+ ///
+ public DateTime? CreateTime { get; set; }
+ ///
+ /// 调度时间
+ ///
+ public DateTime? ScheduleTime { get; set; }
+ ///
+ /// 完成时间
+ ///
+ public DateTime? FinishTime { get; set; }
+ ///
+ /// 反馈状态
+ ///
+ public string? ReportState { get; set; }
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/TaskRT.cs b/WPFWCSDemo/Models/Tables/TaskRT.cs
new file mode 100644
index 0000000..26c8441
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/TaskRT.cs
@@ -0,0 +1,106 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ public class TaskRT : IDisposable
+ {
+ ///
+ /// 作业号
+ ///
+ public string? JobId { get; set; }
+ ///
+ /// 任务号
+ ///
+ public string TaskId { get; set; }
+ /////
+ ///// 任务号
+ /////
+ //public string TaskIdString { get; set; }
+ ///
+ /// 条码
+ ///
+ public string? PalletId { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public int TaskType { get; set; }
+ ///
+ /// 源站
+ ///
+ public string? SourceLocation { get; set; }
+ ///
+ /// 目标站
+ ///
+ public string? TargetLocation { get; set; }
+ ///
+ /// 优先级 1→3 高→低
+ ///
+ //public int Priority { get; set; }
+ ///
+ /// 任务状态
+ ///
+ public string? TaskState { get; set; }
+ ///
+ /// 调度状态
+ ///
+ public string? ScheduleState { get; set; }
+ ///
+ /// 生成时间
+ ///
+ [AllowNull]
+ public DateTime CreateTime { get; set; }
+ ///
+ /// 调度时间
+ ///
+ [AllowNull]
+ public DateTime ScheduleTime { get; set; }
+ ///
+ /// 报告状态
+ ///
+ //public int ReportState { get; set; }
+
+
+
+
+
+
+
+ private bool disposedValue;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // TODO: 释放托管状态(托管对象)
+ }
+
+ // TODO: 释放未托管的资源(未托管的对象)并重写终结器
+ // TODO: 将大型字段设置为 null
+ disposedValue = true;
+ }
+ }
+
+ // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
+ // ~TaskRT()
+ // {
+ // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
+ // Dispose(disposing: false);
+ // }
+
+ public void Dispose()
+ {
+ // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/WPFWCSDemo/Models/Tables/TaskView.cs b/WPFWCSDemo/Models/Tables/TaskView.cs
new file mode 100644
index 0000000..466451a
--- /dev/null
+++ b/WPFWCSDemo/Models/Tables/TaskView.cs
@@ -0,0 +1,108 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Models.Tables
+{
+ public partial class TaskView : ObservableObject, IDisposable
+ {
+
+ ///
+ /// 作业号
+ ///
+ [ObservableProperty]
+ //public string? JobId { get; set; }
+ public string? _jobId;
+
+ ///
+ /// 任务号
+ ///
+ public string? TaskId { get; set; }
+ ///
+ /// 条码
+ ///
+ public string? PalletId { get; set; }
+ ///
+ /// 任务类型
+ ///
+ public string? TaskType { get; set; }
+ ///
+ /// 源站
+ ///
+ public string? SourceLocation { get; set; }
+ ///
+ /// 目标站
+ ///
+ public string? TargetLocation { get; set; }
+ ///
+ /// 优先级 1→3 高→低
+ ///
+ public int Priority { get; set; }
+ ///
+ /// 任务状态
+ ///
+ [ObservableProperty]
+ //public string? TaskState { get; set; }
+ public string? _taskState;
+ ///
+ /// 调度状态
+ ///
+ [ObservableProperty]
+ //public string? ScheduleState { get; set; }
+ public string? _scheduleState;
+ ///
+ /// 生成时间
+ ///
+ public DateTime? CreateTime { get; set; }
+ ///
+ /// 调度时间
+ ///
+ public DateTime? ScheduleTime { get; set; }
+ ///
+ /// 报告状态
+ ///
+ public string? ReportState { get; set; }
+
+
+
+
+
+
+
+
+
+ private bool disposedValue;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // TODO: 释放托管状态(托管对象)
+ }
+
+ // TODO: 释放未托管的资源(未托管的对象)并重写终结器
+ // TODO: 将大型字段设置为 null
+ disposedValue = true;
+ }
+ }
+
+ // // TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
+ // ~TaskView()
+ // {
+ // // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
+ // Dispose(disposing: false);
+ // }
+
+ public void Dispose()
+ {
+ // 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/WPFWCSDemo/Models/WareHouseInfo.cs b/WPFWCSDemo/Models/WareHouseInfo.cs
new file mode 100644
index 0000000..c9feefc
--- /dev/null
+++ b/WPFWCSDemo/Models/WareHouseInfo.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Media;
+
+namespace WPFWCSDemo.Models
+{
+ ///
+ /// 仓位状态画面展示
+ ///
+ public class WareHouseInfo
+ {
+ ///
+ /// 填充颜色
+ ///
+ public System.Windows.Media.Brush FillColor { get; set; }
+ ///
+ /// 鼠标悬停提示
+ ///
+ public string Tooltip { get; set; }
+ ///
+ /// 悬停放大动画缩放中心点
+ ///
+ public System.Drawing.Point RenderCenter { get; set; }
+ ///
+ /// X坐标
+ ///
+ public double X { get; set; }
+ ///
+ /// Y坐标
+ ///
+ public double Y { get; set; }
+ }
+
+
+}
diff --git a/WPFWCSDemo/Resources/DevicesTemplate/StackerTemplate.xaml b/WPFWCSDemo/Resources/DevicesTemplate/StackerTemplate.xaml
new file mode 100644
index 0000000..18a45ce
--- /dev/null
+++ b/WPFWCSDemo/Resources/DevicesTemplate/StackerTemplate.xaml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Resources/DevicesTemplate/StackerTemplate.xaml.cs b/WPFWCSDemo/Resources/DevicesTemplate/StackerTemplate.xaml.cs
new file mode 100644
index 0000000..b78d8d9
--- /dev/null
+++ b/WPFWCSDemo/Resources/DevicesTemplate/StackerTemplate.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Resources.DevicesTemplate
+{
+ ///
+ /// StackerTemplate.xaml 的交互逻辑
+ ///
+ public partial class StackerTemplate : UserControl
+ {
+ public StackerTemplate()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Resources/RGV.png b/WPFWCSDemo/Resources/RGV.png
new file mode 100644
index 0000000..60e7c89
Binary files /dev/null and b/WPFWCSDemo/Resources/RGV.png differ
diff --git a/WPFWCSDemo/Resources/background.jpg b/WPFWCSDemo/Resources/background.jpg
new file mode 100644
index 0000000..7c9b711
Binary files /dev/null and b/WPFWCSDemo/Resources/background.jpg differ
diff --git a/WPFWCSDemo/Resources/yctd.jpg b/WPFWCSDemo/Resources/yctd.jpg
new file mode 100644
index 0000000..23fc0b8
Binary files /dev/null and b/WPFWCSDemo/Resources/yctd.jpg differ
diff --git a/WPFWCSDemo/Resources/升降.png b/WPFWCSDemo/Resources/升降.png
new file mode 100644
index 0000000..9381bea
Binary files /dev/null and b/WPFWCSDemo/Resources/升降.png differ
diff --git a/WPFWCSDemo/Resources/堆垛机.png b/WPFWCSDemo/Resources/堆垛机.png
new file mode 100644
index 0000000..cf2d4c4
Binary files /dev/null and b/WPFWCSDemo/Resources/堆垛机.png differ
diff --git a/WPFWCSDemo/Resources/无底堆垛机.png b/WPFWCSDemo/Resources/无底堆垛机.png
new file mode 100644
index 0000000..f1db432
Binary files /dev/null and b/WPFWCSDemo/Resources/无底堆垛机.png differ
diff --git a/WPFWCSDemo/Resources/清单.png b/WPFWCSDemo/Resources/清单.png
new file mode 100644
index 0000000..09c06a8
Binary files /dev/null and b/WPFWCSDemo/Resources/清单.png differ
diff --git a/WPFWCSDemo/Resources/输送机.png b/WPFWCSDemo/Resources/输送机.png
new file mode 100644
index 0000000..b834acc
Binary files /dev/null and b/WPFWCSDemo/Resources/输送机.png differ
diff --git a/WPFWCSDemo/Resources/齿轮.png b/WPFWCSDemo/Resources/齿轮.png
new file mode 100644
index 0000000..8a9473f
Binary files /dev/null and b/WPFWCSDemo/Resources/齿轮.png differ
diff --git a/WPFWCSDemo/S7.Net.dll b/WPFWCSDemo/S7.Net.dll
new file mode 100644
index 0000000..19ca602
Binary files /dev/null and b/WPFWCSDemo/S7.Net.dll differ
diff --git a/WPFWCSDemo/Schedules/CircleRGV/Check.cs b/WPFWCSDemo/Schedules/CircleRGV/Check.cs
new file mode 100644
index 0000000..9075f46
--- /dev/null
+++ b/WPFWCSDemo/Schedules/CircleRGV/Check.cs
@@ -0,0 +1,439 @@
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Schedules.CircleRGV
+{
+ ///
+ /// 任务校验
+ ///
+ public class Check
+ {
+ static int deviceCount = RGVStation.RGVCount;
+
+ ///
+ /// 生成【空托】任务条件校验
+ ///
+ /// 源站点(可表示某条输送线)
+ /// 目标站点(可表示某条输送线)
+ /// 输送口是否正常 true-系统正常 false-系统异常
+ /// 是否满足生成任务条件 true-可生成 false-禁止生成
+ public static bool CanTaskGenerated(int sourceLocation, int targetLocation, bool isNotException)
+ {
+ //校验---源站点请求
+ if (QueryForIsRequestReset(sourceLocation, 3)) return false;
+
+ //校验---目标站点请求
+ if (QueryForIsRequestReset(targetLocation, 3)) return false;
+
+ //校验---系统异常
+ if (!isNotException) return false;
+
+ //校验---同输送口相邻任务生成时间间隔过短
+ if (!CheckSendTaskTimeInterval(targetLocation, 999)) return false;
+
+ //校验---如果已经存在处于【取货阶段】的某个【空托】任务
+ //由于【空托任务】输送线的源站点唯一,因此必须等待该任务取货完成才能生成新的【空托】任务
+ if (!IsPalletConvHasGettingTask()) return false;
+
+ //校验---当前输送线存在【空托】任务
+ if (!GetRGVTaskForPalletsIsExist(targetLocation)) return false;
+
+ //校验5.当前同一【目标站点】是否已经生成任务
+ if (!CheckSendTaskIsRepeat(sourceLocation, TaskType.Pallet)) return false;
+
+ //校验---上位是否手动禁止生成
+ if (LineTaskForPermission(targetLocation) == 0) return false;
+
+ return true;
+
+ }
+
+
+
+ ///
+ /// 生成【实垛】任务校验条件
+ ///
+ /// 源站点(可表示某条输送线)
+ /// 输送口是否正常 true-系统正常 false-系统异常
+ /// 是否满足生成任务条件 true-可生成 false-禁止生成
+ public static bool CanTaskGenerated(int sourceLocation, bool isNotException)
+ {
+
+ //校验0 放货口无允许
+ //2025.9新增
+ //1003-1009输送口校验
+ if (sourceLocation == RGVStation.LineM_Goods_In)
+ {
+ if (QueryForIsRequestReset(RGVStation.LineToWarehouse1_Out, 3)) return false;
+ }
+ //2025.9新增
+ //1005-1010输送口校验
+ if (sourceLocation == RGVStation.LineL_Goods_In)
+ {
+ if (QueryForIsRequestReset(RGVStation.LineToWarehouse2_Out, 3)) return false;
+ }
+
+ //校验1.输送口无请求
+ if (QueryForIsRequestReset(sourceLocation, 3)) return false;
+
+ //校验2.输送口系统异常
+ if (!isNotException) return false;
+
+ //校验3.同输送口相邻任务生成时间间隔过短
+ if (!CheckSendTaskTimeInterval(sourceLocation)) return false;
+
+ //校验4.当前输送线存在取货阶段的任务
+ if (!GetRGVTaskForGoodsIsExist(sourceLocation)) return false;
+
+ //校验5.当前同一【源站点】是否已经生成【取货阶段】任务
+ if (!CheckSendTaskIsRepeat(sourceLocation, TaskType.Goods)) return false;
+
+ return true;
+
+ }
+
+
+
+
+
+ ///
+ /// 防错机制【用于避免请求延迟的重复下发】--- 检测上一条【实垛】任务放货时间与当前时间是否相差x秒以上
+ ///
+ /// 站点
+ /// true-相差大于x秒 false-相差小于x秒
+ public static bool CheckSendTaskTimeInterval(int location)
+ {
+ int diff = -15;
+
+ using var context = new AppDbContext();
+
+ var loadedState = context
+ .Set()
+ .Where(t => t.Station == location)
+ .FirstOrDefault();
+
+ if (DateTime.Now.AddSeconds(diff) >= loadedState!.LoadingTime)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// 防错机制【用于避免请求延迟的重复下发】--- 检测上一条【空托】任务放货时间(完成时间)与当前时间是否相差x秒以上
+ ///
+ /// 站点
+ /// true-相差大于x秒 false-相差小于x秒
+ public static bool CheckSendTaskTimeInterval(int location, int num)
+ {
+ int diff = -30;
+
+ using var context = new AppDbContext();
+
+ var loadedState = context
+ .Set()
+ .Where(t => t.Station == location)
+ .FirstOrDefault();
+
+ if (DateTime.Now.AddSeconds(diff) >= loadedState!.PuttingTime)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// 防错机制【重复下发】--- 检测已经生成但未下发的任务是否存在
+ ///
+ /// 源站点
+ /// true-同目标站点生成任务时间间隔合法 false-时间间隔过短
+ public static bool CheckSendTaskIsRepeat(int location, int type)
+ {
+ using var context = new AppDbContext();
+
+ //实垛
+ if (type == TaskType.Goods)
+ {
+ //生成的上一条【实垛】任务且同一个源站点 ---> 查找符合条件的记录
+ var count = context
+ .Set()
+ .Where(t => t.SourceLocation == location.ToString() && (t.ScheduleState==ScheduleStateCode.Trans_CircleRGV_Ready || t.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Picking))
+ .Count();
+
+ if (count < 1)
+ {
+ return true;
+ }
+ }
+
+ //空托
+ if (type == TaskType.Pallet)
+ {
+ //生成的上一条【空托】任务且同一个目标站点 ---> 查找符合条件的记录
+ var count1 = context
+ .Set()
+ .Where(t => t.TargetLocation == location.ToString())
+ .Count();
+
+ if (count1 < 1)
+ {
+ return true;
+ }
+ }
+
+ return false;
+
+ }
+
+
+
+
+ ///
+ /// 计算某个输送口请求的值的和---用于确定该输送口在一定时间内请求是否已经复位
+ /// 用于避免信号也许存在的不稳定(跳变)的情况
+ ///
+ /// 源站点/目标站点---表示对应列
+ /// 计算的时间间隔(单位:秒)
+ /// true-无请求---已复位 false-请求存在-未复位
+ public static bool QueryForIsRequestReset(int location, int count)
+ {
+ var context = new AppDbContext();
+
+ string s = DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss");
+
+ var timeIsExist = context.ConvRequest
+ .Where(a => a.Time == s)
+ .Count();
+
+ if (timeIsExist == 0) { return false; }
+
+ string line = "";
+
+ switch (location)
+ {
+ case RGVStation.LineH_Goods_In:
+ line = "Conv_Goods_In_1001";
+ break;
+ case RGVStation.LineM_Goods_In:
+ line = "Conv_Goods_In_1003";
+ break;
+ case RGVStation.LineL_Goods_In:
+ line = "Conv_Goods_In_1005";
+ break;
+ case RGVStation.LineG1_Goods_In:
+ line = "Conv_Goods_In_1007";
+ break;
+ case RGVStation.LineG2_Goods_In:
+ line = "Conv_Goods_In_1008";
+ break;
+
+
+ case RGVStation.LineGH_Pallets_In:
+ line = "Conv_Pallets_In_1013";
+ break;
+ case RGVStation.LineH_Pallets_Out:
+ line = "Conv_Pallets_Out_1002";
+ break;
+ case RGVStation.LineG_Pallets_Out:
+ line = "Conv_Pallets_Out_1004";
+ break;
+ case RGVStation.LineLM_Pallets_Out:
+ line = "Conv_Pallets_Out_1006";
+ break;
+
+ case RGVStation.LineToWarehouse1_Out:
+ line = "Conv_Goods_Out_1009";
+ break;
+ case RGVStation.LineToWarehouse2_Out:
+ line = "Conv_Goods_Out_1010";
+ break;
+ }
+
+ if (string.IsNullOrEmpty(line))
+ {
+ return false;
+ }
+
+ //获取当前时间节点前x行请求记录值
+ using DataTable? dt = SqlHelper.ExecuteTable($"SELECT TOP {count} * FROM CONVREQUEST ORDER BY [time] DESC");
+
+ //无结果则返回
+ if (dt is null || dt.Rows.Count == 0)
+ {
+ return false;
+ }
+
+ int sum = 0;
+
+ //计算源站点对应某列3行请求(允许)值的和
+ for (int i = 0; i < dt.Rows.Count; i++)
+ {
+ sum += (int)dt.Rows[i][line];
+ }
+
+ if (sum == 0)
+ {
+ //为0---无请求
+ return true;
+ }
+ else
+ {
+ //不等于0,请求存在或存在值跳变情况
+ return false;
+ }
+
+ }
+
+
+ ///
+ /// 手动禁止某条输送线下发任务(根据名称)
+ ///
+ /// 输送线名称
+ /// 0-禁止 1-允许
+ public static int LineTaskForPermission(string name)
+ {
+ using var context = new AppDbContext();
+
+ var lineState = context.LineState
+ .Where(p => p.Name == name)
+ .Select(p => p.IsEnable)
+ .FirstOrDefault();
+
+ return lineState;
+ }
+ ///
+ /// 手动禁止某条输送线下发任务(根据目标站)
+ ///
+ /// 源站点
+ /// 0-禁止 1-允许
+ public static int LineTaskForPermission(int target)
+ {
+ using var context = new AppDbContext();
+
+ var lineState = context.LineState
+ .Where(p => p.Target == target)
+ .Select(p => p.IsEnable)
+ .FirstOrDefault();
+
+ return lineState;
+ }
+
+
+
+ ///
+ /// 遍历环穿是否有某条输送线正在执行的(栈板)任务---即只要有该输送口的任务则不能生成新任务
+ /// 判断条件 1.站点 2.执行阶段 3.允许下发
+ /// (该方法会直接读取小车参数)
+ ///
+ /// 源站点(1至2位编号)
+ /// false-存在执行中的任务的设备 true-无在执行任务的设备
+ public static bool GetRGVTaskForPalletsIsExist(int targetLocation)
+ {
+ List? states = CircleRGVsViewModel.GetAllCircleRGVState();
+
+ if (states is null) return false;
+
+ //检查是否有符合条件的小车,如果有则标
+ //【源站点】匹配
+ // 任务处于【取货阶段】
+ // 无【允许下发】---表示小车在工作中
+ var count = states
+ .Where(a => a.Read_TargetLocation == (targetLocation - 1000).ToString() && !a.Read_Permission)
+ .Count();
+
+ if (count > 0)
+ {
+ return false;
+ }
+
+ //无满足条件的小车则表示所有设备无此任务
+ return true;
+ }
+
+
+
+
+ ///
+ /// 遍历环穿是否有某条输送线正在执行的(实垛)任务---某站点输送线存在【取货阶段】任务时不能生成新任务
+ /// 判断条件:
+ /// 1.站点匹配
+ /// 2.执行阶段--->取货阶段
+ /// 3.允许下发
+ /// (该方法会直接从地面站读取小车参数)
+ ///
+ /// 源站点(1至2位编号)
+ /// false-存在执行任务的设备(不能下发) true-无执行中的任务的设备(可下发)
+ public static bool GetRGVTaskForGoodsIsExist(int sourceLocation)
+ {
+ List states = CircleRGVsViewModel.GetAllCircleRGVState();
+
+ if (states is null) return false;
+
+ //检查是否有符合条件的小车,如果有则标
+ //【源站点】匹配
+ // 任务处于【取货阶段】
+ // 无【允许下发】---表示小车在工作中
+ var count = states
+ .Where(a => a.Read_SourceLocation == (sourceLocation - 1000).ToString() && a.Read_Phase < 3 && a.Read_Phase > 0 && !a.Read_Permission)
+ .Count();
+
+ if (count > 0)
+ {
+ return false;
+ }
+
+ //无满足条件的小车则表示所有设备无此任务
+ return true;
+ }
+
+
+
+
+ ///
+ /// 检查是否存在已经生成的处于【取货阶段】的【栈板】任务 --- 源站点每次请求仅生成一条任务
+ ///
+ /// true-无符合条件的任务(即可生成新任务) false-存在符合条件的任务
+ public static bool IsPalletConvHasGettingTask()
+ {
+ var context = new AppDbContext();
+
+ var count =context.Tasks
+ .Where(a=>a.SourceLocation == RGVStation.LineGH_Pallets_In.ToString() &&
+ (a.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Ready ||
+ a.ScheduleState == ScheduleStateCode.Trans_CircleRGV_PickOnTheWay ||
+ a.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Picking))
+ .Count();
+
+ if (count > 0)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+
+
+ }
+
+}
diff --git a/WPFWCSDemo/Schedules/CircleRGV/CircleRGVSchedule.cs b/WPFWCSDemo/Schedules/CircleRGV/CircleRGVSchedule.cs
new file mode 100644
index 0000000..0b7fdbd
--- /dev/null
+++ b/WPFWCSDemo/Schedules/CircleRGV/CircleRGVSchedule.cs
@@ -0,0 +1,44 @@
+using Quartz;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using WPFWCSDemo.Utilities;
+
+namespace WPFWCSDemo.Schedules.CircleRGV
+{
+ [DisallowConcurrentExecution]
+ public class CircleRGVSchedule : IJob
+ {
+ public async Task Execute(IJobExecutionContext context)
+ {
+ //Application.Current.Dispatcher.InvokeAsync(() =>
+ //{
+ await Task.Run(async () =>
+ {
+ bool b = await CommonTask.Common.GetPingForRGVStation("192.168.6.100");
+
+ if (b)
+ {
+ await Update.UpdateDeviceNumber();
+
+ await Update.UpdateScheduleState();
+
+ Excute.ExecuteTask();
+
+ Generate.GenerateTask();
+
+ // //Log.Information($"-----------------设备调度-----------------");
+ }
+ });
+
+ //});
+
+ //return Task.CompletedTask;
+ }
+ }
+}
diff --git a/WPFWCSDemo/Schedules/CircleRGV/Excute.cs b/WPFWCSDemo/Schedules/CircleRGV/Excute.cs
new file mode 100644
index 0000000..eecb935
--- /dev/null
+++ b/WPFWCSDemo/Schedules/CircleRGV/Excute.cs
@@ -0,0 +1,110 @@
+using Newtonsoft.Json;
+using Quartz;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Schedules.CircleRGV
+{
+ ///
+ /// 执行任务调度
+ ///
+ [DisallowConcurrentExecution]
+ public class Excute
+ {
+ static int count1;
+
+ static int count2;
+
+ ///
+ /// 执行任务
+ ///
+ public static void ExecuteTask()
+ {
+ //获取所有输送口请求状态
+ CircleRGVStationState? circleRGVStationState = CircleRGVsViewModel.GetCircleRGVStaionState();
+
+ //地面站对象是否为空
+ if (circleRGVStationState is null)
+ {
+ count1 += 1;
+
+ if (count1 >= 15)
+ {
+ Log.Warning($"【WCS<下发任务>获取输送口参数失败】地面站参数对象:null({count1})!");
+ }
+
+ return;
+ }
+
+ //下发任务前判断地面站【允许下发】
+ if (circleRGVStationState.Read_Permission == 0)
+ {
+ count2 += 1;
+
+ if (count2 >= 15)
+ {
+ Log.Warning($"【WCS<下发任务>失败】地面站【禁止下发】({count2})!");
+ Log.Warning($"【WCS<下发任务>失败】地面站参数:({JsonConvert.SerializeObject(circleRGVStationState)})!");
+
+ //using SiemensS7Net siemens = new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.100");
+ //siemens.ConnectServer();
+ //Log.Warning($"【WCS<下发任务>失败】地面站创建新对象测试读写是否成功:({siemens.ReadInt16("DB611.0").IsSuccess})!");
+ //Log.Warning($"【WCS<下发任务>失败】地面站创建新对象测试读写是否成功:({siemens.ReadInt16("DB611.0").Message})!");
+ //Log.Warning($"【WCS<下发任务>失败】地面站创建新对象测试读写值,允许下发:({siemens.ReadInt16("DB611.0").Content},AB供栈请求:{siemens.ReadInt16("DB2100.3.1").Content})!");
+ }
+
+ return;
+ }
+
+ count1 = 0;
+
+ count2 = 0;
+
+ using var context = new AppDbContext();
+
+ TaskRT? taskRT = context.Tasks
+ .OrderBy(t => t.CreateTime)
+ .FirstOrDefault(t => t.TaskState == TaskStateCode.Task_Ready && t.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Ready);
+
+ if (taskRT == null) return;
+
+ CircleRGVStationCommand? circleRGVStationCommand = new CircleRGVStationCommand()
+ {
+ Write_DeviceNumber = 0,
+ Write_TaskType = int.Parse(taskRT.TaskType.ToString()[..1]),
+ Write_TaskNumber = int.Parse(taskRT.TaskId),
+ Write_SourceLocation = int.Parse(taskRT.SourceLocation!),
+ Write_TargetLocation = int.Parse(taskRT.TargetLocation!),
+ Write_SendFinish = 0,
+ };
+
+ //circleRGVStationCommand.Write_Checksum = Checksum.GetChecksum(circleRGVStationCommand);
+
+ bool b = CircleRGVsViewModel.SendRGVStationCommand(circleRGVStationCommand);
+
+ if (b)
+ {
+ taskRT.TaskState = TaskStateCode.Task_Running;
+ taskRT.ScheduleTime = DateTime.Now;
+
+ context.SaveChanges();
+
+ //Log.Information($"【WCS更新任务状态】任务号:{taskRT.TaskId}环穿下发完成,等待设备执行");
+ }
+ else
+ {
+ //Log.Warning($"【WCS更新任务状态】任务号:{taskRT.TaskId}环穿下发失败");
+ }
+
+ }
+ }
+}
diff --git a/WPFWCSDemo/Schedules/CircleRGV/Generate.cs b/WPFWCSDemo/Schedules/CircleRGV/Generate.cs
new file mode 100644
index 0000000..6e70177
--- /dev/null
+++ b/WPFWCSDemo/Schedules/CircleRGV/Generate.cs
@@ -0,0 +1,217 @@
+using Quartz;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Schedules.CircleRGV
+{
+ ///
+ /// 生成任务
+ ///
+ [DisallowConcurrentExecution]
+ public class Generate
+ {
+ private static int count = 0;
+ public static void GenerateTask()
+ {
+ //获取所有输送口请求状态
+ CircleRGVStationState? circleRGVStationState = CircleRGVsViewModel.GetCircleRGVStaionState();
+
+ //地面站对象是否为空
+ if (circleRGVStationState is null)
+ {
+ count += 1;
+
+ if (count >= 30)
+ {
+ //Log.Warning($"【WCS<生成任务>获取输送口参数失败】地面站参数对象:null({count})!");
+ }
+ return;
+ }
+
+ count = 0;
+
+
+ //------------------------------------1001有出实垛请求------------------------------------
+ //------------------------------------1001有出实垛请求------------------------------------
+ if (Check.CanTaskGenerated(RGVStation.LineH_Goods_In, circleRGVStationState.Read_IsNotException_1001) && circleRGVStationState.Read_GetRequest_1001)
+ {
+ //检查该放货口是否由上位手动禁止生成任务
+ if (Check.LineTaskForPermission(RGVStation.LineH_Goods_Out) == 1)
+ {
+ InsertTask(RGVStation.LineH_Goods_In, RGVStation.LineH_Goods_Out, TaskType.Goods);
+ }
+ }
+
+ //****************************************************【2025.09修改】增加9#、10#立库入口****************************************************
+ //****************************************************【2025.09修改】增加9#、10#立库入口****************************************************
+ //****************************************************【2025.09修改】增加9#、10#立库入口****************************************************
+ //------------------------------------1003有出实垛请求------------------------------------
+ //------------------------------------1003有出实垛请求------------------------------------
+ if (circleRGVStationState.Read_GetRequest_1003 &&
+ circleRGVStationState.Read_PutRequest_1009 &&
+ Check.CanTaskGenerated(RGVStation.LineM_Goods_In, circleRGVStationState.Read_IsNotException_1003))
+ {
+ if (Check.LineTaskForPermission(RGVStation.LineToWarehouse1_Out) == 1)
+ {
+ InsertTask(RGVStation.LineM_Goods_In, RGVStation.LineToWarehouse1_Out, TaskType.Goods);
+ }
+ }
+
+ //------------------------------------1005有出实垛请求------------------------------------
+ //------------------------------------1005有出实垛请求------------------------------------
+ if (circleRGVStationState.Read_GetRequest_1005 &&
+ circleRGVStationState.Read_PutRequest_1010 &&
+ Check.CanTaskGenerated(RGVStation.LineL_Goods_In, circleRGVStationState.Read_IsNotException_1005))
+ {
+ if (Check.LineTaskForPermission(RGVStation.LineToWarehouse2_Out) == 1)
+ {
+ InsertTask(RGVStation.LineL_Goods_In, RGVStation.LineToWarehouse2_Out, TaskType.Goods);
+ }
+ }
+
+ //------------------------------------1007有出实垛请求------------------------------------
+ //------------------------------------1007有出实垛请求------------------------------------
+ if (Check.CanTaskGenerated(RGVStation.LineG1_Goods_In, circleRGVStationState.Read_IsNotException_1007) && circleRGVStationState.Read_GetRequest_1007)
+ {
+ //检查该放货口是否由上位手动禁止生成任务
+ if (Check.LineTaskForPermission(RGVStation.LineG_Goods_Out) == 1)
+ {
+ InsertTask(RGVStation.LineG1_Goods_In, RGVStation.LineG_Goods_Out, TaskType.Goods);
+ }
+ }
+
+ //------------------------------------1008有出实垛请求------------------------------------
+ //------------------------------------1008有出实垛请求------------------------------------
+ if (Check.CanTaskGenerated(RGVStation.LineG2_Goods_In, circleRGVStationState.Read_IsNotException_1008) && circleRGVStationState.Read_GetRequest_1008)
+ {
+ //检查该放货口是否由上位手动禁止生成任务
+ if (Check.LineTaskForPermission(RGVStation.LineG_Goods_Out) == 1)
+ {
+ InsertTask(RGVStation.LineG2_Goods_In, RGVStation.LineG_Goods_Out, TaskType.Goods);
+ }
+
+ }
+
+
+
+
+ //------------------------------------1006有回空托请求------------------------------------
+ if (circleRGVStationState.Read_PutRequest_1006 &&
+ circleRGVStationState.Read_GetRequest_1013 &&
+ Check.CanTaskGenerated(RGVStation.LineGH_Pallets_In, RGVStation.LineLM_Pallets_Out, circleRGVStationState.Read_IsNotException_1006))
+ {
+ InsertTask(RGVStation.LineGH_Pallets_In, RGVStation.LineLM_Pallets_Out, TaskType.Pallet);
+ }
+
+ //------------------------------------1004有回空托请求------------------------------------
+ if (circleRGVStationState.Read_PutRequest_1004 &&
+ circleRGVStationState.Read_GetRequest_1013 &&
+ Check.CanTaskGenerated(RGVStation.LineGH_Pallets_In, RGVStation.LineG_Pallets_Out, circleRGVStationState.Read_IsNotException_1004))
+ {
+ InsertTask(RGVStation.LineGH_Pallets_In, RGVStation.LineG_Pallets_Out, TaskType.Pallet);
+ }
+
+ //------------------------------------1002有空托请求------------------------------------
+ if (circleRGVStationState.Read_PutRequest_1002 &&
+ circleRGVStationState.Read_GetRequest_1013 &&
+ Check.CanTaskGenerated(RGVStation.LineGH_Pallets_In, RGVStation.LineH_Pallets_Out, circleRGVStationState.Read_IsNotException_1002))
+ {
+ InsertTask(RGVStation.LineGH_Pallets_In, RGVStation.LineH_Pallets_Out, TaskType.Pallet);
+ }
+
+
+
+
+
+
+ }
+
+
+
+
+
+
+
+
+ ///
+ /// 插入一条新任务
+ ///
+ /// 源站点
+ /// 任务类型 10-实垛 11-空托
+ public static void InsertTask(int sourceLocation,int targetLocation, int taskType)
+ {
+ using var context = new AppDbContext();
+
+ int taskNumber = SqlHelper.GetTaskIdByAutoGeneration();
+
+ string type = "";
+
+ if (taskType == TaskType.Goods) type = "<实垛>";
+ if (taskType == TaskType.Pallet) type = "<空托>";
+
+ try
+ {
+ TaskRT taskRT = new TaskRT()
+ {
+ TaskId = taskNumber.ToString(),
+ TaskType = taskType,
+ TaskState = TaskStateCode.Task_Ready,
+ ScheduleState = ScheduleStateCode.Trans_CircleRGV_Ready,
+ SourceLocation = sourceLocation.ToString(),
+ TargetLocation = targetLocation.ToString(),
+ CreateTime = DateTime.Now,
+ };
+
+ context.Tasks.Add(taskRT);
+
+ if (sourceLocation == RGVStation.LineGH_Pallets_In)
+ {
+ //更新取货状态---计算【空托】线相同输送口前后任务的间隔时间---用于避免生成重复任务
+ var loadedState = context.LoadedState
+ .FirstOrDefault(s => s.Station == targetLocation);
+
+ loadedState.GenerationTime = DateTime.Now;
+
+ context.SaveChanges();
+ }
+ else
+ {
+ //更新取货状态---计算【实垛】线相同输送口前后任务的间隔时间---用于避免生成重复任务
+ var loadedState = context.LoadedState
+ .FirstOrDefault(s => s.Station == sourceLocation);
+
+ loadedState.GenerationTime = DateTime.Now;
+ context.SaveChanges();
+ }
+
+
+
+ }
+ catch (Exception e)
+ {
+ Log.Warning($"【WCS生成{type}任务异常】任务号:{taskNumber},{e.Message}");
+ Log.Warning($"【WCS生成{type}任务异常】任务号:{taskNumber},{e.InnerException}");
+ return;
+ }
+
+ Log.Information($"【WCS生成{type}任务】任务号:{taskNumber},取货站点:{sourceLocation},放货站点:{targetLocation}");
+ }
+
+
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Schedules/CircleRGV/Update.cs b/WPFWCSDemo/Schedules/CircleRGV/Update.cs
new file mode 100644
index 0000000..278e318
--- /dev/null
+++ b/WPFWCSDemo/Schedules/CircleRGV/Update.cs
@@ -0,0 +1,191 @@
+using Quartz;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reactive.Concurrency;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Schedules.CircleRGV
+{
+ ///
+ /// 更新任务调度
+ ///
+ public class Update
+ {
+ static int deviceCount = RGVStation.RGVCount;
+
+ ///
+ /// 根据任务号获取正在执行任务环穿的编号
+ ///
+ public static Task UpdateDeviceNumber()
+ {
+ //根据任务号获取正在执行任务环穿的编号
+ for (int j = 1; j <= deviceCount; j++)
+ {
+ using CircleRGVState? circleRGVState = CircleRGVsViewModel.GetCircleRGVState(j);
+
+ if (circleRGVState == null) continue;
+
+ //有【允许下发】则表示无任务小车---跳过
+ if (circleRGVState.Read_Permission) continue;
+
+ using var context = new AppDbContext();
+
+ TaskRT? taskRT = context.Tasks.
+ FirstOrDefault(t => t.TaskId == circleRGVState.Read_TaskNumber.ToString());
+
+ if (taskRT == null) continue;
+
+ taskRT.JobId = j.ToString();
+
+ context.SaveChanges();
+
+ }
+
+ return Task.CompletedTask;
+ }
+
+
+ ///
+ /// 根据【执行阶段】实时更新环穿【调度状态】
+ ///
+ public static Task UpdateScheduleState()
+ {
+ for (int i = 1; i <= deviceCount; i++)
+ {
+ using CircleRGVState? circleRGVState = CircleRGVsViewModel.GetCircleRGVState(i);
+
+ if (circleRGVState == null) continue;
+
+ using var context = new AppDbContext();
+
+ //获取执行中的任务
+ TaskRT? taskRT = context.Tasks
+ .FirstOrDefault(t => t.TaskId == circleRGVState.Read_TaskNumber.ToString() && t.TaskState == TaskStateCode.Task_Running);
+
+ if (taskRT is null) continue;
+
+ //有【允许下发】
+ //if (circleRGVState.Read_Permission) continue;
+
+ //无【允许下发】---表示小车有执行中的任务
+ switch (circleRGVState.Read_Phase)
+ {
+ case 1:
+ if (taskRT.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Ready && !circleRGVState.Read_Permission)
+ {
+ taskRT.ScheduleState = ScheduleStateCode.Trans_CircleRGV_PickOnTheWay;
+
+ if (context.SaveChanges() == 1) Log.Information($"【WCS更新调度状态】任务号:{circleRGVState.Read_TaskNumber}--->取货途中");
+ }
+ continue;
+ case 2:
+ if (taskRT.ScheduleState != ScheduleStateCode.Trans_CircleRGV_Picking && !circleRGVState.Read_Permission)
+ {
+ taskRT.ScheduleState = ScheduleStateCode.Trans_CircleRGV_Picking;
+
+ if (context.SaveChanges() == 1) Log.Information($"【WCS更新调度状态】任务号:{circleRGVState.Read_TaskNumber}--->取货中");
+
+ //更新取货时间
+ if (taskRT.TaskType == TaskType.Goods)
+ {
+ var loadedState = context.LoadedState
+ .FirstOrDefault(s => s.Station.ToString() == taskRT.SourceLocation);
+
+ loadedState!.LoadingTime = DateTime.Now;
+ }
+ if (taskRT.TaskType == TaskType.Pallet)
+ {
+ var loadedState = context.LoadedState
+ .FirstOrDefault(s => s.Station.ToString() == taskRT.TargetLocation);
+
+ loadedState!.LoadingTime = DateTime.Now;
+ }
+
+ context.SaveChanges();
+ }
+ continue;
+ case 3:
+ if (taskRT.ScheduleState != ScheduleStateCode.Trans_CircleRGV_PutOnTheWay && !circleRGVState.Read_Permission)
+ {
+ taskRT.ScheduleState = ScheduleStateCode.Trans_CircleRGV_PutOnTheWay;
+ taskRT.JobId = i.ToString();
+
+ if (context.SaveChanges() == 1) Log.Information($"【WCS更新调度状态】任务号:{circleRGVState.Read_TaskNumber}--->放货途中");
+
+ //更新取货时间
+ if (taskRT.TaskType == TaskType.Goods)
+ {
+ var loadedState = context.LoadedState
+ .FirstOrDefault(s => s.Station.ToString() == taskRT.SourceLocation);
+
+ loadedState!.LoadedTime = DateTime.Now;
+ }
+ if (taskRT.TaskType == TaskType.Pallet)
+ {
+ var loadedState = context.LoadedState
+ .FirstOrDefault(s => s.Station.ToString() == taskRT.TargetLocation);
+
+ loadedState!.LoadedTime = DateTime.Now;
+ }
+
+ context.SaveChanges();
+
+ }
+ continue;
+ case 4:
+ if (taskRT.ScheduleState != ScheduleStateCode.Trans_CircleRGV_Putting && !circleRGVState.Read_Permission)
+ {
+ taskRT.ScheduleState = ScheduleStateCode.Trans_CircleRGV_Putting;
+
+ if (context.SaveChanges() == 1) Log.Information($"【WCS更新调度状态】任务号:{circleRGVState.Read_TaskNumber}--->放货中");
+
+ //更新取货时间
+ if (taskRT.TaskType == TaskType.Goods)
+ {
+ var loadedState = context.LoadedState
+ .FirstOrDefault(s => s.Station.ToString() == taskRT.SourceLocation);
+
+ loadedState!.PuttingTime = DateTime.Now;
+ }
+ if (taskRT.TaskType == TaskType.Pallet)
+ {
+ var loadedState = context.LoadedState
+ .FirstOrDefault(s => s.Station.ToString() == taskRT.TargetLocation);
+
+ loadedState!.PuttingTime = DateTime.Now;
+ }
+
+ context.SaveChanges();
+ }
+ continue;
+ case 5:
+ if (taskRT.ScheduleState != ScheduleStateCode.Trans_CircleRGV_Ready)
+ {
+ taskRT.ScheduleState = ScheduleStateCode.Trans_CircleRGV_Finish;
+
+ if (context.SaveChanges() == 1) Log.Information($"【WCS更新调度状态】任务号:{circleRGVState.Read_TaskNumber}--->放货完成");
+ }
+ continue;
+ }
+
+
+
+ }
+
+ return Task.CompletedTask;
+ }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Schedules/CommonTask/Common.cs b/WPFWCSDemo/Schedules/CommonTask/Common.cs
new file mode 100644
index 0000000..af02e67
--- /dev/null
+++ b/WPFWCSDemo/Schedules/CommonTask/Common.cs
@@ -0,0 +1,97 @@
+using Microsoft.EntityFrameworkCore;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.NetworkInformation;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Schedules.CommonTask
+{
+ public class Common
+ {
+ int deviceCount = RGVStation.RGVCount;
+
+ ///
+ /// 记录输送口请求值
+ ///
+ public static void RecordRequestValue()
+ {
+ //获取所有输送口请求状态
+ using CircleRGVStationState? circleRGVStationState = CircleRGVsViewModel.GetCircleRGVStaionState();
+
+ //地面站【允许下发】
+ if (circleRGVStationState is null) return;
+
+ int a = circleRGVStationState.Read_GetRequest_1001 == true ? 1 : 0;
+ int b = circleRGVStationState.Read_GetRequest_1003 == true ? 1 : 0;
+ int c = circleRGVStationState.Read_GetRequest_1005 == true ? 1 : 0;
+ int d = circleRGVStationState.Read_GetRequest_1007 == true ? 1 : 0;
+ int e = circleRGVStationState.Read_GetRequest_1008 == true ? 1 : 0;
+
+ int ab = circleRGVStationState.Read_GetRequest_1013 == true ? 1 : 0;
+ int bOut = circleRGVStationState.Read_PutRequest_1002 == true ? 1 : 0;
+ int cd = circleRGVStationState.Read_PutRequest_1004 == true ? 1 : 0;
+ int cOut = circleRGVStationState.Read_PutRequest_1006 == true ? 1 : 0;
+
+ //1009放货口
+ int f = circleRGVStationState.Read_PutRequest_1009 == true ? 1 : 0;
+ //1010放货口
+ int g = circleRGVStationState.Read_PutRequest_1010 == true ? 1 : 0;
+
+ using var context = new AppDbContext();
+
+ context.Database.ExecuteSqlInterpolated(
+ $"INSERT INTO CONVREQUEST VALUES({a},{b},{c},{d},{e},{DateTime.Now.ToString(TimeFormat.stringFormat)},{ab},{bOut},{cd},{cOut},{Guid.NewGuid()},{f},{g})");
+
+ context.Database.ExecuteSqlInterpolated(
+ $"DELETE FROM CONVREQUEST WHERE [TIME]<{DateTime.Now.AddHours(-24).ToString(TimeFormat.stringFormat)}");
+
+ }
+
+
+
+
+ ///
+ /// 检测plc网络
+ ///
+ /// ip地址
+ ///
+ ///
+ public static async Task GetPingForRGVStation(string ipAddress, int timeout = 5000)
+ {
+ try
+ {
+ using (Ping ping = new Ping())
+ {
+ PingReply reply = await ping.SendPingAsync(ipAddress, timeout);
+
+ return reply.Status == IPStatus.Success;
+ }
+ }
+ catch (PingException e)
+ {
+ Log.Error($"【地面站网络异常】{e.Message}");
+ Log.Error($"【地面站网络异常】{e.InnerException}");
+ return false;
+ }
+ catch (Exception e)
+ {
+ Log.Error($"【地面站网络异常】{e.Message}");
+ Log.Error($"【地面站网络异常】{e.InnerException}");
+ return false;
+ }
+
+ }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Schedules/CommonTask/CommonTask.cs b/WPFWCSDemo/Schedules/CommonTask/CommonTask.cs
new file mode 100644
index 0000000..814337c
--- /dev/null
+++ b/WPFWCSDemo/Schedules/CommonTask/CommonTask.cs
@@ -0,0 +1,28 @@
+using Quartz;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.Schedules.CircleRGV;
+using WPFWCSDemo.Schedules.CommonTask;
+
+namespace WPFWCSDemo.Schedules.CommonTask
+{
+ public class CommonTask : IJob
+ {
+ public async Task Execute(IJobExecutionContext context)
+ {
+ await Task.Run(() =>
+ {
+ //bool b = await Common.GetPingForRGVStation("192.168.6.100");
+
+ Common.RecordRequestValue();
+
+ });
+
+ //return Task.CompletedTask;
+ }
+ }
+}
diff --git a/WPFWCSDemo/Schedules/ConvSchedule.cs b/WPFWCSDemo/Schedules/ConvSchedule.cs
new file mode 100644
index 0000000..1bca052
--- /dev/null
+++ b/WPFWCSDemo/Schedules/ConvSchedule.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Schedules
+{
+ public class ConvSchedule
+ {
+ }
+}
diff --git a/WPFWCSDemo/Schedules/GlobalTask.cs b/WPFWCSDemo/Schedules/GlobalTask.cs
new file mode 100644
index 0000000..f616599
--- /dev/null
+++ b/WPFWCSDemo/Schedules/GlobalTask.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+
+namespace WPFWCSDemo.Schedules
+{
+ ///
+ /// 全局任务
+ ///
+ public static class GlobalTask
+ {
+ ///
+ /// 1\4\7\10月1日自动备份
+ ///
+ public static void SqlBackupForTime()
+ {
+ string time = DateTime.Now.ToString("MM-dd HH:mm");
+ if (time == "04-01 01:15" || time == "07-01 01:15" || time == "10-01 01:15" || time == "01-01 01:15")
+ {
+ SqlDatabaseMaintenance.SQLBackupAuto();
+ }
+ }
+
+ }
+}
diff --git a/WPFWCSDemo/Schedules/TaskFinish/Delete.cs b/WPFWCSDemo/Schedules/TaskFinish/Delete.cs
new file mode 100644
index 0000000..ec1edc6
--- /dev/null
+++ b/WPFWCSDemo/Schedules/TaskFinish/Delete.cs
@@ -0,0 +1,132 @@
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities.Table;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Schedules.TaskFinish
+{
+ ///
+ /// 任务移除
+ ///
+ public class Delete
+ {
+ ///
+ /// 完成的调度任务从实时表删除记入历史记录
+ ///
+ /// 当前已完成的任务
+ public static void TaskDelete()
+ {
+ using var context = new AppDbContext();
+
+ //查找符合【任务状态】和【调度状态】的记录
+ var taskRT = context.Tasks
+ .Where(t => t.TaskState == TaskStateCode.Task_Finish ||
+ t.TaskState == TaskStateCode.Task_Finish_Manual ||
+ t.TaskState == TaskStateCode.Task_Finish_Cancel ||
+ t.TaskState == TaskStateCode.Task_Cancel ||
+ t.TaskState == TaskStateCode.Task_Finish_Timeout)
+ .OrderBy(t => t.CreateTime)
+ .ToList();
+
+ if (taskRT is null || taskRT.Count == 0) return;
+
+ for (int i = 0; i < taskRT.Count; i++)
+ {
+ //任务完成状态文本
+ string strTaskState;
+
+ switch (taskRT[i].TaskState)
+ {
+ case TaskStateCode.Task_Finish:
+ strTaskState = "任务自动完成";
+ break;
+ case TaskStateCode.Task_Finish_Manual:
+ strTaskState = "任务手动完成";
+ break;
+ case TaskStateCode.Task_Finish_Cancel:
+ strTaskState = "任务手动取消";
+ break;
+ case TaskStateCode.Task_Cancel:
+ strTaskState = "任务自动作废";
+ break;
+ case TaskStateCode.Task_Finish_Timeout:
+ strTaskState = "任务超时自动完成";
+ break;
+ default:
+ strTaskState = "发生未知异常,请检查后手动处理";//其他状态:异常-手动处理
+ break;
+ }
+
+ Log.Information($"【WCS任务结束】【{strTaskState}】,任务号:{taskRT[i].TaskId}");
+
+
+
+ //---------------------------------------------反馈任务结束成功后:删除表任务添加至历史记录---------------------------------------------
+ int result = TaskManager.Delete(taskRT[i]);
+
+ if (result == 1)
+ {
+ if (taskRT[i].TaskType == TaskType.Goods)
+ Log.Information($"【常规任务-实垛】【{strTaskState}】,任务号:{taskRT[i].TaskId},历史任务记录已保存");
+
+ if (taskRT[i].TaskType == TaskType.Pallet)
+ Log.Information($"【常规任务-空托】【{strTaskState}】,任务号:{taskRT[i].TaskId},历史任务记录已保存");
+
+ if (taskRT[i].TaskType == TaskType.GoToRest)
+ Log.Information($"【进休息区】【{strTaskState}】,作业号:{taskRT[i].JobId} 任务号:{taskRT[i].TaskId},历史任务记录已保存");
+
+ if (taskRT[i].TaskType == TaskType.BackToRail)
+ Log.Information($"【返回轨道】【{strTaskState}】,作业号:{taskRT[i].JobId} 任务号:{taskRT[i].TaskId},历史任务记录已保存");
+
+ }
+ }
+
+ //LineFlagAutoReset();
+
+ }
+
+
+ /////
+ ///// 防错机制【可下发任务标志】---如果当前某条线无输送任务,则重置该输送线请求标志为true
+ /////
+ //public static void LineFlagAutoReset()
+ //{
+ // using var context = new AppDbContext();
+
+ // int lineA = context.Tasks.Where(t => t.SourceLocation == RGVStation.LineA_In.ToString()).Count();
+ // if (lineA == 0) LineAIsAvailable = true;
+
+ // int lineB = context.Tasks.Where(t => t.SourceLocation == RGVStation.LineB_In.ToString()).Count();
+ // if (lineB == 0) LineBIsAvailable = true;
+
+ // int lineC = context.Tasks.Where(t => t.SourceLocation == RGVStation.LineC_In.ToString()).Count();
+ // if (lineC == 0) LineCIsAvailable = true;
+
+ // int lineD = context.Tasks.Where(t => t.SourceLocation == RGVStation.LineD_In.ToString()).Count();
+ // if (lineD == 0) LineDIsAvailable = true;
+
+
+ // using CircleRGVStationState? circleRGVStationState = CircleRGVsViewModel.GetCircleRGVStaionState();
+
+ // //地面站【允许下发】
+ // if (circleRGVStationState is null || circleRGVStationState.Read_Permission == 0) return;
+
+ // int lineAB = context.Tasks.Where(t => t.SourceLocation == RGVStation.LineAB_In.ToString()).Count();
+ // if (lineAB == 0 && circleRGVStationState.Read_PutRequest_LineB) LineABIsAvailable = true;
+
+ // int lineCD = context.Tasks.Where(t => t.SourceLocation == RGVStation.LineCD_In.ToString()).Count();
+ // if (lineCD == 0 && circleRGVStationState.Read_PutRequest_LineC) LineCDIsAvailable = true;
+
+ //}
+
+
+ }
+}
diff --git a/WPFWCSDemo/Schedules/TaskFinish/Finish.cs b/WPFWCSDemo/Schedules/TaskFinish/Finish.cs
new file mode 100644
index 0000000..52f2b4d
--- /dev/null
+++ b/WPFWCSDemo/Schedules/TaskFinish/Finish.cs
@@ -0,0 +1,59 @@
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.StateCode;
+
+namespace WPFWCSDemo.Schedules.TaskFinish
+{
+ ///
+ /// 任务完成
+ ///
+ public class Finish
+ {
+ ///
+ /// 更新【任务自动完成】状态
+ ///
+ public static void TaskFinish()
+ {
+ using var context = new AppDbContext();
+
+ //---------------------------------------------查询【调度状态】为已完成的任务---------------------------------------------
+ //var query = context.Set()
+ // .Where(t => t.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Finish && t.TaskState == TaskStateCode.Task_Running)
+ // .OrderBy(t => t.CreateTime);
+
+ //string s = query.ToQueryString();
+
+ //查询
+ //调度状态【环穿-执行完成】
+ //任务状态【执行中】
+ //的符合条件的任务
+ var taskRT = context.Tasks?
+ .Where(t => t.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Finish && t.TaskState == TaskStateCode.Task_Running)
+ .OrderBy(t => t.CreateTime)
+ .ToList();
+
+
+ if (taskRT is null || taskRT.Count == 0) return;
+
+ //所有符合上述条件的任务
+ for (int i = 0; i < taskRT.Count; i++)
+ {
+ if (taskRT[i] is null) continue;
+
+ //任务状态更新为【自动完成】
+ taskRT[i].TaskState = TaskStateCode.Task_Finish;
+
+ Log.Information($"【WCS更新调度状态】任务号:{taskRT[i].TaskId},环穿输送完成");
+ }
+
+ context.SaveChanges();
+
+
+ }
+ }
+}
diff --git a/WPFWCSDemo/Schedules/TaskFinish/Handler.cs b/WPFWCSDemo/Schedules/TaskFinish/Handler.cs
new file mode 100644
index 0000000..091513f
--- /dev/null
+++ b/WPFWCSDemo/Schedules/TaskFinish/Handler.cs
@@ -0,0 +1,159 @@
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities.Table;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Schedules.TaskFinish
+{
+ ///
+ /// 任务处理
+ ///
+ public class Handler
+ {
+ static int deviceCount = RGVStation.RGVCount;
+
+ ///
+ /// 防错机制 ---
+ /// 任务状态 ->【执行中】
+ /// 调度状态 ->【环穿-待执行】
+ /// 取货状态 ->【未取货】
+ /// 同时满足的任务视为下发失败的任务
+ /// 将任务状态更新为【待执行】令其重新下发
+ ///
+ public static void TaskForSendFailedHandler()
+ {
+ using var context = new AppDbContext();
+
+ var tasks = context.Tasks
+ //.Set()
+ .OrderBy(t => t.CreateTime)
+ .Where(t => t.TaskState == TaskStateCode.Task_Running &&
+ t.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Ready &&
+ t.ScheduleTime <= DateTime.Now.AddSeconds(-30) &&
+ string.IsNullOrEmpty(t.JobId))
+ .ToList();
+
+ if (tasks is null || tasks.Count == 0) return;
+
+ for (int i = 0; i < tasks.Count; i++)
+ {
+ tasks[i].TaskState = TaskStateCode.Task_Ready;
+
+ if (context.SaveChanges() == 1) Log.Warning($"【向地面站下发任务】任务号:{tasks[i].TaskId}更新任务状态,尝试重新下发...");
+ }
+
+ }
+
+
+
+ ///
+ /// 防错机制 ---
+ /// 处理长时间未正常完成的遗留任务记录---获取下发时间距离当前一定时间的任务
+ /// 将其任务号与所有小车状态匹配
+ /// 判断该任务是否在执行中---否则视为遗留任务处理
+ ///
+ public static void TaskExceptionHandler()
+ {
+ //只处理一段时间前的任务
+ int diff = -5;
+
+ using var context = new AppDbContext();
+
+ //查询符合条件的任务
+ //任务状态---【执行中】
+ //生成时间---【执行中】
+ var tasks = context.Tasks
+ .Where(t => t.TaskState == TaskStateCode.Task_Running && t.CreateTime <= DateTime.Now.AddMinutes(diff))
+ .OrderBy(t => t.CreateTime)
+ .ToList();
+
+ //获取所有符合条件的任务记录
+ for (int i = 0; i < tasks.Count; i++)
+ {
+ List circleRGVStates = CircleRGVsViewModel.GetAllCircleRGVState();
+
+ if (circleRGVStates == null || circleRGVStates.Count < deviceCount) continue;
+
+ //查找匹配【任务号】和无【允许下发】的设备
+ var result = circleRGVStates
+ .Where(a => a.Read_TaskNumber.ToString() == tasks[i].TaskId && !a.Read_Permission)
+ .Count();
+
+ //有匹配结果---> 查询下一条记录
+ if (result > 0) continue;
+
+ //无匹配结果---> 移除遗留任务
+ int handlerResult = TaskManager.Delete(tasks[i]);
+
+ if (handlerResult == 1)
+ {
+ Log.Warning($"【WCS更新任务状态】任务号:{tasks[i].TaskId},执行中设备无匹配任务,已作为遗留任务超时处理");
+ }
+
+
+
+
+ #region 遍历小车状态参数(已弃用)
+ //每条记录与所有小车状态匹配
+ //for (int j = 1; j <= deviceCount; j++)
+ //{
+ // CircleRGVState circleRGVState = CircleRGVsViewModel.GetCircleRGVState(j);
+
+ // if (circleRGVState == null) continue;
+
+ // //过滤掉取货完成前的阶段
+ // if (circleRGVState.Read_Phase < 2) continue;
+
+ // //匹配到任务号 ---> 任务号不是设备的唯一标识,需要继续判断
+ // if (circleRGVState.Read_TaskNumber.ToString() == tasks[i].TaskId)
+ // {
+ // //无【允许下发】---表示有执行中任务---跳出并开始下一条任务记录的匹配处理
+ // if (!circleRGVState.Read_Permission) break;
+
+ // //1.有【允许下发】---> 必须匹配任务号的所有小车均有【允许下发】才能满足条件
+ // if (j == deviceCount)
+ // {
+ // int result = TaskManager.Delete(tasks[i]);
+
+ // if (result == 1)
+ // {
+ // Log.Warning($"【WCS更新任务状态】任务号:{tasks[i].TaskId},执行中设备无匹配任务号,已作为遗留任务超时处理");
+ // }
+ // }
+
+ // }
+ // else//无任务号匹配
+ // {
+ // //---所有车都无任务号匹配,表示该任务为遗留任务
+ // if (j == deviceCount)
+ // {
+ // int result = TaskManager.Delete(tasks[i]);
+
+ // if (result == 1)
+ // {
+ // Log.Warning($"【WCS更新任务状态】任务号:{tasks[i].TaskId},执行中设备无匹配任务号,已作为遗留任务超时处理");
+ // }
+ // }
+ // }
+
+
+
+ //}
+ #endregion
+
+
+ }
+ }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Schedules/TaskFinish/TaskFinishSchedule.cs b/WPFWCSDemo/Schedules/TaskFinish/TaskFinishSchedule.cs
new file mode 100644
index 0000000..5156487
--- /dev/null
+++ b/WPFWCSDemo/Schedules/TaskFinish/TaskFinishSchedule.cs
@@ -0,0 +1,29 @@
+using Quartz;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace WPFWCSDemo.Schedules.TaskFinish
+{
+ public class TaskFinishSchedule : IJob
+ {
+ public Task Execute(IJobExecutionContext context)
+ {
+ Application.Current.Dispatcher.InvokeAsync(() =>
+ {
+ Finish.TaskFinish();
+ Handler.TaskForSendFailedHandler();
+ Handler.TaskExceptionHandler();
+ Delete.TaskDelete();
+
+ //Log.Information($"-----------------任务处理调度-----------------");
+ });
+
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/WPFWCSDemo/Schedules/TaskFinishSchedule.cs b/WPFWCSDemo/Schedules/TaskFinishSchedule.cs
new file mode 100644
index 0000000..9ed651b
--- /dev/null
+++ b/WPFWCSDemo/Schedules/TaskFinishSchedule.cs
@@ -0,0 +1,195 @@
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.Utilities.Table;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Schedules
+{
+ [Obsolete("该类下的方法已经移至其他类中使用",true)]
+ public class TaskFinishSchedule
+ {
+ ///
+ /// A线单次请求标志
+ ///
+ public static bool LineAIsAvailable = true;
+ ///
+ /// B线单次请求标志
+ ///
+ public static bool LineBIsAvailable = true;
+ ///
+ /// C线单次请求标志
+ ///
+ public static bool LineCIsAvailable = true;
+ ///
+ /// D线单次请求标志
+ ///
+ public static bool LineDIsAvailable = true;
+ ///
+ /// AB线单次请求标志
+ ///
+ public static bool LineABIsAvailable = true;
+ ///
+ /// CD线单次请求标志
+ ///
+ public static bool LineCDIsAvailable = true;
+
+ ///
+ /// 自动完成处于一定时间内【放货中】状态的环穿【实垛】遗留任务
+ ///
+ public static void DeleteTaskForPuttingTimeout()
+ {
+ //查询【放货中】的任务
+ using DataTable? dt = SqlHelper.ExecuteTable("SELECT TOP 1 * FROM TASK WHERE SCHEDULESTATE=@ScheduleState",
+ new SqlParameter("@ScheduleState", ScheduleStateCode.Trans_CircleRGV_Putting)
+ );
+ if (dt is null || dt.Rows.Count == 0)
+ {
+ return;
+ }
+
+
+ for (int i = 0; i < dt.Rows.Count; i++)
+ {
+ //获取第i条记录
+ using TaskRT taskRT = TaskManager.ToModels(dt.Rows[i]);
+
+ TimeSpan diff = DateTime.Now - taskRT.ScheduleTime;
+
+ //处于【放货中】的实垛任务---如果旧任务放货时未正常自动完成,则出现新的同设备任务后,旧任务2分钟后自动完成
+ if (taskRT.TaskType == 10)
+ {
+ //if (diff.TotalMinutes >= 2)
+ //{
+ //查询是否有编号重复的任务
+ int count = SqlHelper.GetRowCount("SELECT * FROM TASK WHERE JOBID=@JobId",
+ new SqlParameter("@JobId", taskRT.JobId)
+ );
+
+ //如果存在编号重复的任务,表示小车已经分配了新任务---将【放货中】的任务设置为超时完成
+ if (count > 1)
+ {
+ //表示小车已接到新任务
+ SqlHelper.ExecuteNonQuery("UPDATE TASK SET TASKSTATE=@TaskState WHERE TASKID=@TaskId",
+ new SqlParameter("@TaskState", TaskStateCode.Task_Finish_Timeout),
+ new SqlParameter("@TaskId", taskRT.TaskId)
+ );
+
+ Log.Warning($"【WCS更新<放货中>状态】任务号:{taskRT.TaskId}已作为遗留任务处理");
+ }
+
+
+ //}
+ }
+
+
+
+ }
+
+ }
+
+
+ ///
+ /// 自动完成处于一定时间内【放货完成】状态的环穿遗留任务
+ /// 该原因可能是由于某些因素使程序意外关闭导致的
+ ///
+ public static void DeleteTaskForFinishTimeout()
+ {
+ //查询【放货完成】的任务
+ using DataTable? dt = SqlHelper.ExecuteTable("SELECT TOP 1 * FROM TASK WHERE SCHEDULESTATE=@ScheduleState AND CREATETIME<@CurrentTime",
+ new SqlParameter("@ScheduleState", ScheduleStateCode.Trans_CircleRGV_Finish),
+ new SqlParameter("@CurrentTime", DateTime.Now.AddMinutes(-8).ToString(TimeFormat.stringFormat))
+ );
+ if (dt is null || dt.Rows.Count == 0)
+ {
+ return;
+ }
+
+ //获取第i条记录
+ using TaskRT taskRT = TaskManager.ToModels(dt.Rows[0]);
+
+ if (taskRT is null) return;
+
+ //表示小车已接到新任务
+ SqlHelper.ExecuteNonQuery("UPDATE TASK SET TASKSTATE=@TaskState WHERE TASKID=@TaskId",
+ new SqlParameter("@TaskState", TaskStateCode.Task_Finish_Timeout),
+ new SqlParameter("@TaskId", taskRT.TaskId)
+ );
+
+ Log.Warning($"【WCS更新<放货完成>状态】任务号:{taskRT.TaskId}已作为遗留任务处理");
+ }
+
+ ///
+ /// 防错机制(处理长时间可能未正常完成遗留任务记录)---获取下发时间距离当前时间较长的任务
+ /// 将其任务号与执行中的小车匹配
+ /// 判断该任务是否已经执行完成---完成则视为遗留任务处理
+ ///
+ public static void DeleteTaskForDeviceTaskNumberIsNotExist()
+ {
+ //查找【放货途中】和【放货中】的任务
+ using DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM TASK WHERE (SCHEDULESTATE=@ScheduleState OR SCHEDULESTATE=@ScheduleState1) AND SCHEDULETIME<@CurrentTime",
+ new SqlParameter("@ScheduleState", ScheduleStateCode.Trans_CircleRGV_PutOnTheWay),
+ new SqlParameter("@ScheduleState1", ScheduleStateCode.Trans_CircleRGV_Putting),
+ new SqlParameter("@CurrentTime", DateTime.Now.AddMinutes(-30).ToString(TimeFormat.stringFormat))
+ );
+
+ if (dt is null || dt.Rows.Count == 0)
+ {
+ return;
+ }
+
+
+ for (int i = 0; i < dt.Rows.Count; i++)
+ {
+ using TaskRT? taskRT = TaskManager.ToModels(dt.Rows[i]);
+
+ //获取对应小车编号---此处需要保证小车编号正确性,在更新【放货】阶段的逻辑中再次更新了小车编号
+ if (string.IsNullOrEmpty(taskRT.JobId)) continue;
+
+ //数据类型正确
+ if (int.Parse(taskRT.JobId) > 0 && int.Parse(taskRT.JobId) < 10)
+ {
+ //获取任务表中编号对应的小车
+ CircleRGVState? circleRGVState = CircleRGVsViewModel.GetCircleRGVState(int.Parse(taskRT.JobId));
+
+ if (circleRGVState == null)
+ {
+ continue;
+ }
+
+ //判断设备任务号是否与任务表中的任务号匹配
+ //匹配---不执行操作
+ //不匹配---视为遗留任务处理
+ if (circleRGVState.Read_TaskNumber.ToString() != taskRT.TaskId)
+ {
+ //表示小车已接到新任务
+ SqlHelper.ExecuteNonQuery("UPDATE TASK SET TASKSTATE=@TaskState WHERE TASKID=@TaskId",
+ new SqlParameter("@TaskState", TaskStateCode.Task_Finish_Timeout),
+ new SqlParameter("@TaskId", taskRT.TaskId)
+ );
+
+ Log.Warning($"【WCS更新任务状态】任务号:{taskRT.TaskId}无法匹配与执行中设备任务号,已作为遗留任务超时处理");
+ }
+ }
+
+
+ }
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/Services/ManualOperation/DeleteTask.cs b/WPFWCSDemo/Services/ManualOperation/DeleteTask.cs
new file mode 100644
index 0000000..23c2104
--- /dev/null
+++ b/WPFWCSDemo/Services/ManualOperation/DeleteTask.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+
+namespace WPFWCSDemo.Services.ManualOperation
+{
+ public class DeleteTask :IDeleteTask
+ {
+ ///
+ /// 移除指定任务记录
+ ///
+ /// 任务历史记录
+ public void Delete(TaskHistory taskHistory)
+ {
+ SqlHelper.ExecuteNonQuery("UPDATE TASK_HISTORY SET TASKSTATE=@TaskState,FINISHTIME=@FinishTime WHERE TASKID=@TaskId",
+ new SqlParameter("@TaskId", taskHistory.TaskId),
+ new SqlParameter("@FinishTime", taskHistory.FinishTime),
+ new SqlParameter("@TaskState", TaskStateCode.Task_Finish_Cancel));
+
+
+
+ //SqlHelper.ExecuteNonQuery("INSERT INTO TASK_HISTORY " +
+ // "SELECT * FROM TASK WHERE (TaskId=@TaskId)",
+ // new SqlParameter("@TaskId", taskHistory.TaskId),
+ // new SqlParameter("@TaskState", taskHistory.TaskStateCode));
+
+ ////2--------------在历史表中响应任务数据中修改其【taskstate】值
+ //SqlHelper.ExecuteNonQuery("UPDATE TASK_HISTORY SET TASKSTATE=@TaskState,FINISHTIME=@FinishTime WHERE TASKID=@TaskId",
+ // new SqlParameter("@TaskId", taskHistory.TaskId),
+ // new SqlParameter("@FinishTime", taskHistory.FinishTime),
+ // new SqlParameter("@TaskState", taskHistory.TaskStateCode));
+
+ ////3--------------移除【调度管理】表数据
+ //SqlHelper.ExecuteNonQuery("DELETE FROM TASK WHERE TaskId=@TaskId",
+ // new SqlParameter("@TaskId", taskHistory.TaskId));
+ }
+ }
+}
diff --git a/WPFWCSDemo/Services/ManualOperation/IDeleteTask.cs b/WPFWCSDemo/Services/ManualOperation/IDeleteTask.cs
new file mode 100644
index 0000000..64aba2b
--- /dev/null
+++ b/WPFWCSDemo/Services/ManualOperation/IDeleteTask.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models;
+using WPFWCSDemo.Models.Tables;
+
+namespace WPFWCSDemo.Services.ManualOperation
+{
+ public interface IDeleteTask
+ {
+ void Delete(TaskHistory taskHistory);
+ }
+}
diff --git a/WPFWCSDemo/Services/ManualOperation/IInsertTask.cs b/WPFWCSDemo/Services/ManualOperation/IInsertTask.cs
new file mode 100644
index 0000000..4265ff6
--- /dev/null
+++ b/WPFWCSDemo/Services/ManualOperation/IInsertTask.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models;
+using WPFWCSDemo.Models.Tables;
+
+namespace WPFWCSDemo.Services.ManualOperation
+{
+ public interface IInsertTask
+ {
+ void Insert(TaskRT taskRT);
+ }
+}
diff --git a/WPFWCSDemo/Services/ManualOperation/IUpdateTask.cs b/WPFWCSDemo/Services/ManualOperation/IUpdateTask.cs
new file mode 100644
index 0000000..95ecefd
--- /dev/null
+++ b/WPFWCSDemo/Services/ManualOperation/IUpdateTask.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Services.ManualOperation
+{
+ public interface IUpdateTask
+ {
+ void Update();
+ }
+}
diff --git a/WPFWCSDemo/Services/ManualOperation/InsertTask.cs b/WPFWCSDemo/Services/ManualOperation/InsertTask.cs
new file mode 100644
index 0000000..0a28771
--- /dev/null
+++ b/WPFWCSDemo/Services/ManualOperation/InsertTask.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+
+namespace WPFWCSDemo.Services.ManualOperation
+{
+ public class InsertTask : IInsertTask
+ {
+ ///
+ /// 新插入一条记录
+ ///
+ /// 任务参数模型
+ public void Insert(TaskRT taskRT)
+ {
+ SqlHelper.ExecuteNonQuery(
+ "INSERT INTO TASK TASKID,PalletId,TASKTYPE,SourceLocation,TARGETLOCATION,CREATETIME " +
+ "VALUES(@TaskId,@PalletId,@TaskType,@SourceLocation,@TargetLocation,@CreateTime)",
+ new System.Data.SqlClient.SqlParameter("@TaskId", taskRT.TaskId),
+ new System.Data.SqlClient.SqlParameter("@PalletId", taskRT.PalletId),
+ new System.Data.SqlClient.SqlParameter("@TaskType", taskRT.TaskType),
+ new System.Data.SqlClient.SqlParameter("@SourceLocation", taskRT.SourceLocation),
+ new System.Data.SqlClient.SqlParameter("@TargetLocation", taskRT.TargetLocation),
+ new System.Data.SqlClient.SqlParameter("@CreateTime", DateTime.Now.ToString(TimeFormat.stringFormatfff)));
+ }
+ }
+}
diff --git a/WPFWCSDemo/Services/ManualOperation/UpdateTask.cs b/WPFWCSDemo/Services/ManualOperation/UpdateTask.cs
new file mode 100644
index 0000000..63d5560
--- /dev/null
+++ b/WPFWCSDemo/Services/ManualOperation/UpdateTask.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Services.ManualOperation
+{
+ public class UpdateTask : IUpdateTask
+ {
+ public void Update()
+ {
+
+ }
+ }
+}
diff --git a/WPFWCSDemo/StateCode/AlarmPriority.cs b/WPFWCSDemo/StateCode/AlarmPriority.cs
new file mode 100644
index 0000000..4d95b1d
--- /dev/null
+++ b/WPFWCSDemo/StateCode/AlarmPriority.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ ///
+ /// 报警优先级
+ ///
+ public class AlarmPriority
+ {
+ ///
+ /// 高
+ ///
+ public const int HIGH = 1;
+ ///
+ /// 中
+ ///
+ public const int MID = 2;
+ ///
+ /// 低
+ ///
+ public const int LOW = 3;
+ }
+}
diff --git a/WPFWCSDemo/StateCode/CargoState.cs b/WPFWCSDemo/StateCode/CargoState.cs
new file mode 100644
index 0000000..3212960
--- /dev/null
+++ b/WPFWCSDemo/StateCode/CargoState.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ ///
+ /// 库存状态
+ ///
+ public class CargoState
+ {
+ ///
+ /// 错误
+ ///
+ public const int ERROR = 0;
+ ///
+ /// 空闲
+ ///
+ public const int FREE = 1;
+ ///
+ /// 占用
+ ///
+ public const int FULL = 2;
+ ///
+ /// 入库重分
+ ///
+ public const int OUT_REDIST = 3;
+ ///
+ /// 入库盘点
+ ///
+ public const int IN_STOCKTAKING = 4;
+ ///
+ /// 入库障碍
+ ///
+ public const int IN_OBSTRUCT = 5;
+ ///
+ /// 出库取货无货
+ ///
+ public const int OUT_NOTHING = 6;
+ ///
+ /// 出库障碍
+ ///
+ public const int OUT_OBSTRUCT = 7;
+ ///
+ /// 异常(通用)
+ ///
+ public const string FAULT = "F";
+ }
+}
diff --git a/WPFWCSDemo/StateCode/ConvStation.cs b/WPFWCSDemo/StateCode/ConvStation.cs
new file mode 100644
index 0000000..1199edf
--- /dev/null
+++ b/WPFWCSDemo/StateCode/ConvStation.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ ///
+ /// 输送线站点
+ ///
+ public class ConvStation
+ {
+ ///
+ /// 1层输送口1-左侧
+ ///
+ public const string conv_1 = "C1001";
+ ///
+ /// 1层输送口2-右侧
+ ///
+ public const string conv_2 = "C1002";
+ ///
+ /// 2层输送口
+ ///
+ public const string conv_3 = "C2002";
+ ///
+ /// 3层输送口
+ ///
+ public const string conv_4 = "C2003";
+ ///
+ /// 4层输送口
+ ///
+ public const string conv_5 = "C2004";
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/StateCode/FaultCode.cs b/WPFWCSDemo/StateCode/FaultCode.cs
new file mode 100644
index 0000000..de7ad72
--- /dev/null
+++ b/WPFWCSDemo/StateCode/FaultCode.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ internal class FaultCode
+ {
+ }
+}
diff --git a/WPFWCSDemo/StateCode/ScheduleStateCode.cs b/WPFWCSDemo/StateCode/ScheduleStateCode.cs
new file mode 100644
index 0000000..52bd9a7
--- /dev/null
+++ b/WPFWCSDemo/StateCode/ScheduleStateCode.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ ///
+ /// 调度状态-与设备交互的标志状态
+ ///
+ public class ScheduleStateCode
+ {
+ //---------------设备编号---------------
+ //入口输送机 11
+ //出口输送机 12
+ //重分输送机 13
+ //巷道出口输送机 14
+ //四向车库内输送机 15
+ //拣选输送机(当拣选与出口独立时) 16
+ //双向穿梭车 2
+ //堆垛机 3
+ //提升机 4
+ //四向穿梭车 5
+ //环穿 6
+
+ //入库重分F1
+
+
+ //******************************************************入库******************************************************
+ ///
+ /// 入口输送机等待请求下发任务
+ ///
+ public const string StockIn_WaitingForTask = "R0";
+ ///
+ /// 入口输送机请求wms任务成功
+ ///
+ public const string StockIn_TaskRequestSuccessful = "R0-1";
+ ///
+ /// 入口输送机入库待执行
+ ///
+ public const string StockIn_EntryConv_Ready = "R11-0";
+ ///
+ /// 入口输送机入库执行中
+ ///
+ public const string StockIn_EntryConv_Running = "R11-1";
+ ///
+ /// 入口输送机入库到位
+ ///
+ public const string StockIn_EntryConv_Finish = "R11-2";
+ ///
+ /// 入库提升机待执行
+ ///
+ public const string StockIn_LFT_Ready = "R4-0";
+ ///
+ /// 入库提升机执行中
+ ///
+ public const string StockIn_LFT_Running = "R4-1";
+ ///
+ /// 入库提升机执行完成
+ ///
+ public const string StockIn_LFT_Finish = "R4-2";
+
+ ///
+ /// RGV入库执行中
+ ///
+ public const string StockIn_RGV_Running = "R2-1";
+ ///
+ /// RGV放货完成
+ ///
+ public const string StockIn_RGV_Finish = "R2-2";
+ ///
+ /// 巷道输送机入库执行中
+ ///
+ public const string StockIn_RoadConv_Running = "R14-1";
+ ///
+ /// 巷道输送机入库到位
+ ///
+ public const string StockIn_RoadConv_Finish = "R14-2";
+
+ ///
+ /// 堆垛机入库执行中
+ ///
+ public const string StockIn_STK_Running = "R3";
+ ///
+ /// 堆垛机入库待执行
+ ///
+ public const string StockIn_STK_Ready = "R3-0";
+ ///
+ /// 堆垛机入库取货途中
+ ///
+ public const string StockIn_STK_PickOnTheWay = "R3-1";
+ ///
+ /// 堆垛机取货
+ ///
+ public const string StockIn_STK_Picking = "R3-2";
+ ///
+ /// 堆垛机放货途中
+ ///
+ public const string StockIn_STK_PutOnTheWay = "R3-3";
+ ///
+ /// 堆垛机放货
+ ///
+ public const string StockIn_STK_Putting = "R3-4";
+ ///
+ /// 堆垛机入库执行完成
+ ///
+ public const string StockIn_STK_Finish = "R3-5";
+ ///
+ /// 入库重分
+ ///
+ public const string StockIn_STK_Redis = "RF";
+ ///
+ /// 入库重分完成
+ ///
+ public const string StockIn_STK_RedisFinish = "RFF";
+
+ //****************************************************************************************************************
+
+
+
+ //******************************************************出库******************************************************
+ ///
+ /// 堆垛机出库执行中
+ ///
+ public const string StockOut_STK_Running = "C3";
+ ///
+ /// 堆垛机出库待执行
+ ///
+ public const string StockOut_STK_Ready = "C3-0";
+ ///
+ /// 堆垛机出库取货途中
+ ///
+ public const string StockOut_STK_PickOnTheWay = "C3-1";
+ ///
+ /// 堆垛机出库取货
+ ///
+ public const string StockOut_STK_Picking = "C3-2";
+ ///
+ /// 堆垛机出库放货途中
+ ///
+ public const string StockOut_STK_PutOnTheWay = "C3-3";
+ ///
+ /// 堆垛机出库放货
+ ///
+ public const string StockOut_STK_Putting = "C3-4";
+ ///
+ /// 堆垛机出库完成
+ ///
+ public const string StockOut_STK_Finish = "C3-5";
+ ///
+ /// 巷道输送机出库执行中
+ ///
+ public const string StockOut_RoadConv_Running = "C14-1";
+ ///
+ /// 巷道输送机出库到位
+ ///
+ public const string StockOut_RoadConv_Finish = "C14-2";
+ ///
+ /// 穿梭车出库执行中
+ ///
+ public const string StockOut_RGV_Running = "C2-1";
+ ///
+ /// 穿梭车出库执行完成
+ ///
+ public const string StockOut_RGV_Finish = "C2-2";
+ ///
+ /// 提升机出库待执行
+ ///
+ public const string StockOut_LFT_Ready = "C4-0";
+ ///
+ /// 提升机出库执行中
+ ///
+ public const string StockOut_LFT_Running = "C4-1";
+ ///
+ /// 提升机出库完成
+ ///
+ public const string StockOut_LFT_Finish = "C4-2";
+ ///
+ /// 出库输送机执行中
+ ///
+ public const string StockOut_ExitConv_Running = "C12-1";
+ ///
+ /// 出库输送机出库到位
+ ///
+ public const string StockOut_ExitConv_Finish = "C12-2";
+ ///
+ /// 出库取货无货-需盘点
+ ///
+ public const string StockOut_STK_Empty = "CF";
+
+ //****************************************************************************************************************
+
+
+
+ //******************************************************转存******************************************************
+ ///
+ /// 转储任务待执行(一阶段出库)
+ ///
+ public const string Trans_ExitConv_Finish = "ZC3-0";
+ ///
+ /// 转储任务取货途中(一阶段出库)
+ ///
+ public const string Trans_STK_PickOnTheWay = "ZC3-1";
+ ///
+ /// 转储任务取货(一阶段出库)
+ ///
+ public const string Trans_STK_Picking = "ZC3-2";
+ ///
+ /// 转储任务放货途中(二阶段入库)
+ ///
+ public const string Trans_STK_PutOnTheWay = "ZR3-1";
+ ///
+ /// 转储任务放货(二阶段入库)
+ ///
+ public const string Trans_STK_Putting = "ZR3-2";
+ ///
+ /// 转储任务放货完成(二阶段入库)
+ ///
+ public const string Trans_STK_Finish = "ZR3-3";
+ ///
+ /// 入库重分
+ ///
+ public const string Trans_STK_Redis = "ZF";
+ //****************************************************************************************************************
+
+
+ //******************************************************环穿点到点******************************************************
+ ///
+ /// 环穿-待执行
+ ///
+ public const string Trans_CircleRGV_Ready = "T6-0";
+ ///
+ /// 环穿-执行中
+ ///
+ public const string Trans_CircleRGV_Running = "T6-1";
+ ///
+ /// 环穿-取货途中
+ ///
+ public const string Trans_CircleRGV_PickOnTheWay = "T6-2";
+ ///
+ /// 环穿-取货中
+ ///
+ public const string Trans_CircleRGV_Picking = "T6-3";
+ ///
+ /// 环穿-放货途中
+ ///
+ public const string Trans_CircleRGV_PutOnTheWay = "T6-4";
+ ///
+ /// 环穿-放货中
+ ///
+ public const string Trans_CircleRGV_Putting = "T6-5";
+ ///
+ /// 环穿-执行完成(送到执行站点)
+ ///
+ public const string Trans_CircleRGV_Finish = "T6-6";
+ //****************************************************************************************************************
+
+
+ }
+}
diff --git a/WPFWCSDemo/StateCode/TaskStateCode.cs b/WPFWCSDemo/StateCode/TaskStateCode.cs
new file mode 100644
index 0000000..0a2d178
--- /dev/null
+++ b/WPFWCSDemo/StateCode/TaskStateCode.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ ///
+ /// 任务状态-与WMS交互的标志状态
+ ///
+ public class TaskStateCode
+ {
+ ///
+ /// 任务待执行
+ ///
+ public const string Task_Ready = "100";
+ ///
+ /// 任务执行中
+ ///
+ public const string Task_Running = "101";
+ ///
+ /// 任务自动完成
+ ///
+ public const string Task_Finish = "102";
+ ///
+ /// 任务手动完成
+ ///
+ public const string Task_Finish_Manual = "103";
+ ///
+ /// 任务手动取消
+ ///
+ public const string Task_Finish_Cancel = "104";
+ ///
+ /// 任务作废
+ ///
+ public const string Task_Cancel = "105";
+ ///
+ /// 超时自动完成
+ ///
+ public const string Task_Finish_Timeout = "106";
+ ///
+ /// 任务异常-手动处理
+ ///
+ public const string Task_Exception = "F";
+
+
+ ///
+ /// 入库放货有货-已重分
+ ///
+ public const string Task_StockIn_Redis = "110";
+ ///
+ /// 入库有货-重分货位
+ ///
+ public const string Task_StockIn_Exist = "111";
+ ///
+ /// 入库近端障碍-重分货位
+ ///
+ public const string Task_StockIn_Block = "112";
+ ///
+ /// 出库无货
+ ///
+ public const string Task_StockOut_Empty = "121";
+ ///
+ /// 出库近端障碍
+ ///
+ public const string Task_StockOut_Block = "122";
+ }
+}
diff --git a/WPFWCSDemo/StateCode/TaskType.cs b/WPFWCSDemo/StateCode/TaskType.cs
new file mode 100644
index 0000000..11623a5
--- /dev/null
+++ b/WPFWCSDemo/StateCode/TaskType.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ ///
+ /// 任务类型
+ ///
+ public class TaskType
+ {
+ /////
+ ///// 入库-通用
+ /////
+ //public const int StockIn = 10;
+ /////
+ ///// 入库-货物
+ /////
+ //public const int StockIn_Goods = 11;
+ /////
+ ///// 托盘垛入库
+ /////
+ //public const int StockIn_Pallets = 12;
+ /////
+ ///// 出库-通用
+ /////
+ //public const int StockOut = 20;
+ /////
+ ///// 出库-货物
+ /////
+ //public const int StockOut_Goods = 21;
+ /////
+ ///// 托盘垛出库
+ /////
+ //public const int StockOut_Pallets = 22;
+ /////
+ ///// 移库-同巷道
+ /////
+ //public const int StockTransSameRoad = 30;
+ /////
+ ///// 移库-跨巷道
+ /////
+ //public const int StockTransDifferentRoad = 31;
+ /////
+ ///// 越库
+ /////
+ //public const int StockCross = 4;
+
+
+
+ ///
+ /// 环穿常规任务---实垛
+ ///
+ public const int Goods = 10;
+ ///
+ /// 环穿常规任务---空托
+ ///
+ public const int Pallet = 11;
+ ///
+ /// 环穿回休息区
+ ///
+ public const int GoToRest = 2;
+ ///
+ /// 环穿休息区返回轨道
+ ///
+ public const int BackToRail = 3;
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/StateCode/TimeFormat.cs b/WPFWCSDemo/StateCode/TimeFormat.cs
new file mode 100644
index 0000000..8923651
--- /dev/null
+++ b/WPFWCSDemo/StateCode/TimeFormat.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ ///
+ /// 时间格式字符串
+ ///
+ public class TimeFormat
+ {
+ ///
+ /// 日期
+ ///
+ public const string stringFormatDateOnly = "yyyy/MM/dd";
+ ///
+ /// 时间(时分秒)
+ ///
+ public const string stringFormatTimeOnly = "HH:mm:ss";
+ ///
+ /// 日期 时间
+ ///
+ public const string stringFormat = "yyyy/MM/dd HH:mm:ss";
+ ///
+ /// 日期 时间.毫秒(小数点2位)
+ ///
+ public const string stringFormatff = "yyyy/MM/dd HH:mm:ss.ff";
+ ///
+ /// 日期 时间.毫秒(小数点3位)
+ ///
+ public const string stringFormatfff = "yyyy/MM/dd HH:mm:ss.fff";
+ ///
+ /// 日期 时间.毫秒(小数点7位)
+ ///
+ public const string stringFormatfffffff = "yyyy/MM/dd HH:mm:ss.fffffff";
+
+ }
+
+}
diff --git a/WPFWCSDemo/StateCode/UserAccess.cs b/WPFWCSDemo/StateCode/UserAccess.cs
new file mode 100644
index 0000000..af62258
--- /dev/null
+++ b/WPFWCSDemo/StateCode/UserAccess.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.StateCode
+{
+ public class UserAccess
+ {
+ ///
+ /// 用户
+ ///
+ public const string USER = "USER";
+ ///
+ /// 主用户
+ ///
+ public const string ADMIN = "ADMIN";
+ ///
+ /// 管理员
+ ///
+ public const string SYSTEM = "SYSTEM";
+ ///
+ /// 开发者
+ ///
+ public const string DEVELOPER = "DEVELOPER";
+
+
+ public enum AccessType
+ {
+ USER,
+ ADMIN,
+ SYSTEM,
+ DEVELOPER
+ }
+ }
+}
diff --git a/WPFWCSDemo/Utilities/CargoTableInitialize.cs b/WPFWCSDemo/Utilities/CargoTableInitialize.cs
new file mode 100644
index 0000000..89e6d2b
--- /dev/null
+++ b/WPFWCSDemo/Utilities/CargoTableInitialize.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using WPFWCSDemo.StateCode;
+
+namespace WPFWCSDemo.Utilities
+{
+ ///
+ /// 初始化货位信息表
+ ///
+ public class CargoTableInitialize
+ {
+ ///
+ /// 向库表中添加货位
+ ///
+ /// 排
+ /// 列
+ /// 层
+ public static void CargoSpaceInit(int row, int column, int floor)
+ {
+ string s = "00";
+
+ if (MessageBox.Show("此操作会删除货位信息表中所有数据(可能会导致数据丢失),是否继续?","警告",MessageBoxButton.OKCancel)==MessageBoxResult.OK)
+ {
+ //删除
+ SqlHelper.ExecuteNonQuery("TRUNCATE TABLE CARGOSPACE");
+
+ //生成
+ for (int i = 1; i < row; i++)
+ {
+ for (int j = 1; j < column; j++)
+ {
+ for (int k = 1; k < floor; k++)
+ {
+ SqlHelper.ExecuteNonQuery($"INSERT INTO CARGOSPACE VALUES(" +
+ $"'{i.ToString(s)}{j.ToString(s)}{k.ToString(s)}','0{i}排{j.ToString(s)}列{k.ToString(s)}层',{null},'1','{i}','{j}','{k}',{null},'1',{DateTime.Now.ToString(TimeFormat.stringFormat)},'')");
+ }
+ }
+ }
+ }
+
+
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/Utilities/Checksum.cs b/WPFWCSDemo/Utilities/Checksum.cs
new file mode 100644
index 0000000..bb5d2d0
--- /dev/null
+++ b/WPFWCSDemo/Utilities/Checksum.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+
+namespace WPFWCSDemo.Utilities
+{
+ public class Checksum
+ {
+ ///
+ /// 字节数拆分求和
+ ///
+ ///
+ public static short GetChecksum(int number)
+ {
+ byte byte1 = (byte)(number >> 24);
+ byte byte2 = (byte)(number >> 16);
+ byte byte3 = (byte)(number >> 8);
+ byte byte4 = (byte)(number);
+
+ int sum = byte1 + byte2 + byte3 + byte4;
+
+ return (short)sum;
+ }
+
+ public static short GetChecksum(short number)
+ {
+ byte byte1 = (byte)(number >> 8);
+ byte byte2 = (byte)(number);
+
+ int sum = byte1 + byte2;
+
+ return (short)sum;
+ }
+
+
+
+ ///
+ /// 获取校验码---字节拆分求和
+ ///
+ ///
+ ///
+ public static short GetChecksum(CircleRGVStationCommand circleRGVStationCommand)
+ {
+ return Convert.ToInt16(GetChecksum((short)circleRGVStationCommand.Write_DeviceNumber) +
+ GetChecksum((short)circleRGVStationCommand.Write_SourceLocation) +
+ GetChecksum((short)circleRGVStationCommand.Write_TargetLocation) +
+ GetChecksum((short)circleRGVStationCommand.Write_TaskType) +
+ GetChecksum(circleRGVStationCommand.Write_TaskNumber) +
+ GetChecksum((short)1));
+ }
+
+ }
+}
diff --git a/WPFWCSDemo/Utilities/DataCheck.cs b/WPFWCSDemo/Utilities/DataCheck.cs
new file mode 100644
index 0000000..e0bf6db
--- /dev/null
+++ b/WPFWCSDemo/Utilities/DataCheck.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Utilities
+{
+ public class DataCheck
+ {
+ public static string IsBarcodeIllegal(string barcode)
+ {
+ return "条码格式错误!";
+ }
+ }
+}
diff --git a/WPFWCSDemo/Utilities/SqlDatabaseMaintenance.cs b/WPFWCSDemo/Utilities/SqlDatabaseMaintenance.cs
new file mode 100644
index 0000000..6540e74
--- /dev/null
+++ b/WPFWCSDemo/Utilities/SqlDatabaseMaintenance.cs
@@ -0,0 +1,308 @@
+using Microsoft.EntityFrameworkCore;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.IO;
+using System.Linq;
+using System.Security.AccessControl;
+using System.Security.Principal;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Xml.Linq;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.StateCode;
+
+namespace WPFWCSDemo.Utilities
+{
+ ///
+ /// 数据维护操作相关
+ ///
+ public class SqlDatabaseMaintenance
+ {
+ ///
+ /// 手动备份根文件夹路径
+ ///
+ static string rootPath = @"E:\SqlDataBackup";
+ ///
+ /// 自动备份根文件夹路径
+ ///
+ static string rootPathAuto = @"E:\SqlAutoBackup";
+ ///
+ /// sql库名
+ ///
+ static string dbName = "FT479";
+
+ ///
+ /// 备份当前数据库
+ ///
+ public static void SQLBackup()
+ {
+ try
+ {
+ // 连接字符串
+ string connectionString = SqlHelper.ConStr;
+
+ // 指定备份文件的路径
+ string backupPath = $@"{rootPath}\{dbName}_{DateTime.Now.ToString("yyyyMMdd_hhmmss")}.bak";
+
+ // SQL 查询备份数据库
+ string backupQuery = $"BACKUP DATABASE {dbName} TO DISK = '{backupPath}' WITH COPY_ONLY, STATS = 10;";
+
+
+ GetOrCreateDirectory(backupPath);
+
+ // 打开数据库连接
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ connection.Open();
+
+ // 执行备份查询
+ using (SqlCommand command = new SqlCommand(backupQuery, connection))
+ {
+ command.ExecuteNonQuery();
+ }
+
+ MessageBox.Show("数据库备份成功!");
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"数据库备份失败: {ex.Message}");
+ }
+ }
+ ///
+ /// 自动备份当前数据库
+ /// 包含删除旧数据功能
+ ///
+ public static void SQLBackupAuto()
+ {
+ try
+ {
+ // 连接字符串
+ string connectionString = SqlHelper.ConStr;
+
+ // 指定备份文件的路径
+ string backupPath = $@"{rootPathAuto}\{DateTime.Now.AddMonths(-4).ToString("yyyy")}\{dbName}_{DateTime.Now.AddMonths(-4).ToString("yyyy-MM")}.bak";
+
+ // SQL 查询备份数据库
+ string backupQuery = $"BACKUP DATABASE {dbName} TO DISK = '{backupPath}' WITH COPY_ONLY, STATS = 10;";
+
+ GetOrCreateDirectory(backupPath);
+
+ Log.Warning("【定期自动备份】自动备份数据中...");
+
+ using var context = new AppDbContext();
+
+ //备份前删除前3个月外的调度任务记录
+ context.TaskHistories
+ .Where(t => t.FinishTime < DateTime.Now.AddMonths(-3))
+ .ExecuteDelete();
+
+ //备份前删除前1年前的报警任务记录
+ context.AlarmHistories
+ .Where(t => t.End_Time < DateTime.Now.AddYears(-1))
+ .ExecuteDelete();
+
+ context.SaveChanges();
+
+ // 打开数据库连接
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ connection.Open();
+
+ // 执行备份查询
+ using (SqlCommand command = new SqlCommand(backupQuery, connection))
+ {
+ command.ExecuteNonQuery();
+
+ }
+
+ }
+
+ Log.Warning("【定期自动备份】备份完成!");
+ }
+ catch (Exception ex)
+ {
+ Log.Warning($"【定期自动备份】备份发生错误:{ex.Message}");
+ }
+
+ SqlHelper.NewEventLog("系统自动备份操作", "SYSTEM");
+
+ }
+
+
+
+
+ ///
+ /// SQL备份-调度任务表
+ ///
+ public static void SQLTaskBackup(string yearOrMonthOrDay,int count,bool delete)
+ {
+ try
+ {
+ // 连接字符串
+ string connectionString = SqlHelper.ConStr;
+
+ // 指定备份文件的路径
+ string backupPath = $"{rootPath}\\{dbName}_{DateTime.Now.ToString("yyyyMMdd_hhmmss")}.bak";
+
+ // SQL 查询备份数据库
+ string backupQuery = $"BACKUP DATABASE FT_WCS TO DISK = '{backupPath}' WITH COPY_ONLY, STATS = 10;" +
+ $"SELECT * FROM TASK_HISTORY WHERE CREATETIME >= DATEADD({yearOrMonthOrDay}, {count}, GETDATE())";
+
+
+ GetOrCreateDirectory(backupPath);
+
+ // 打开数据库连接
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ connection.Open();
+
+ // 执行备份查询
+ using (SqlCommand command = new SqlCommand(backupQuery, connection))
+ {
+ command.ExecuteNonQuery();
+
+ //选择是否删除已备份的数据
+ if (delete)
+ {
+ SQLClearByTime("TASK_HISTORY", yearOrMonthOrDay, count);
+ }
+ }
+
+ MessageBox.Show("数据库备份成功!");
+
+ Log.Warning($"【手动动备份】备份完成!");
+ }
+
+ SqlHelper.NewEventLog("发生了手动备份操作", "USER");
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"数据库备份失败: {ex.Message}");
+
+ Log.Warning($"【手动备份】备份发生错误:{ex.Message}");
+ }
+ }
+
+
+ ///
+ /// SQL备份-历史报警表
+ ///
+ public static void SQLAlarmBackup(string yearOrMonthOrDay, int count,bool delete)
+ {
+ try
+ {
+ // 连接字符串
+ string connectionString = SqlHelper.ConStr;
+
+ // 指定备份文件的路径
+ string backupPath = $"{rootPath}\\{dbName}_{DateTime.Now.ToString("yyyyMMdd_hhmmss")}.bak";
+
+ // SQL 查询备份数据库
+ string backupQuery = $"BACKUP DATABASE FT_WCS TO DISK = '{backupPath}' WITH COPY_ONLY, STATS = 10;" +
+ $"SELECT * FROM ALARM_LOG WHERE GEN_TIME >= DATEADD({yearOrMonthOrDay}, {count}, GETDATE())";
+
+ GetOrCreateDirectory(backupPath);
+
+ // 打开数据库连接
+ using (SqlConnection connection = new SqlConnection(connectionString))
+ {
+ connection.Open();
+
+ // 执行备份查询
+ using (SqlCommand command = new SqlCommand(backupQuery, connection))
+ {
+ command.ExecuteNonQuery();
+
+ //选择是否删除已备份的数据
+ if (delete)
+ {
+ SQLClearByTime("ALARM_LOG", yearOrMonthOrDay, count);
+ }
+ }
+
+ MessageBox.Show("数据库备份成功!");
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show($"数据库备份失败: {ex.Message}");
+ }
+ }
+
+
+
+ ///
+ /// 删除SQL数据
+ ///
+ public static void SQLClearByTime(string tableName, string yearOrMonthOrDay, int count)
+ {
+ SqlHelper.ExecuteNonQuery($"DELETE FROM {tableName} WHERE GEN_TIME >= DATEADD({yearOrMonthOrDay}, {count}, GETDATE()");
+ }
+
+
+
+ ///
+ /// 查找文件夹(不存在则创建)
+ /// 查找后为文件夹设定权限-完全控制
+ ///
+ ///
+ private static void GetOrCreateDirectory(string backupPath)
+ {
+ // 检查备份路径是否存在,如果不存在则创建
+ if (!Directory.Exists(Path.GetDirectoryName(backupPath)))
+ {
+ Directory.CreateDirectory(Path.GetDirectoryName(backupPath));
+
+ try
+ {
+ // 定义文件夹路径
+ string folderPath = rootPath;
+
+ // 获取文件夹信息
+ DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
+
+ // 获取当前文件夹的安全性设置
+ DirectorySecurity directorySecurity = directoryInfo.GetAccessControl();
+
+ // 定义 "Authenticated Users" 用户组
+ NTAccount authenticatedUsers = new NTAccount("Authenticated Users");
+
+ // 定义权限(这里使用读取和执行权限)
+ FileSystemRights fileSystemRights = FileSystemRights.FullControl;
+
+ // 定义授权类型
+ InheritanceFlags inheritanceFlags = InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit;
+ PropagationFlags propagationFlags = PropagationFlags.None;
+ AccessControlType accessControlType = AccessControlType.Allow;
+
+ // 创建权限规则
+ FileSystemAccessRule rule = new FileSystemAccessRule(authenticatedUsers, fileSystemRights, inheritanceFlags, propagationFlags, accessControlType);
+
+ // 添加权限规则到文件夹的安全性设置
+ directorySecurity.AddAccessRule(rule);
+
+ // 设置新的安全性设置到文件夹
+ directoryInfo.SetAccessControl(directorySecurity);
+
+ //Console.WriteLine("权限已成功添加到文件夹: " + folderPath);
+ }
+ catch
+ {
+ //Console.WriteLine("添加权限失败: " + ex.Message);
+ }
+ }
+ }
+
+
+
+
+
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Utilities/SqlHelper.cs b/WPFWCSDemo/Utilities/SqlHelper.cs
new file mode 100644
index 0000000..c84d980
--- /dev/null
+++ b/WPFWCSDemo/Utilities/SqlHelper.cs
@@ -0,0 +1,323 @@
+
+using Newtonsoft.Json;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Xml;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Utilities
+{
+ public class SqlHelper
+ {
+ ///
+ /// sql连接字符串,引用自【app.config】
+ ///
+ public static string? ConStr { get; set; }
+
+ ///
+ /// 检查数据库是否连接正常
+ ///
+ /// true-连接正常 false-连接失败
+ public static bool IsDBConnected()
+ {
+ using var context = new AppDbContext();
+
+ return context.Database.CanConnect();
+ }
+
+
+ ///
+ /// 获取数据集
+ ///
+ /// sql执行语句
+ /// 可选的sql参数
+ /// 查询目标的数据集
+ public static DataSet GetDataSet(string cmdText, params SqlParameter[] sqlParameters)
+ {
+ //创建sql连接
+ using SqlConnection conn = new SqlConnection(ConStr);
+ try
+ {
+ conn.Open();
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+
+ using SqlCommand cmd = new SqlCommand(cmdText, conn);
+ cmd.Parameters.AddRange(sqlParameters);
+ using SqlDataAdapter sda = new SqlDataAdapter(cmd);
+ using DataSet ds = new DataSet();
+ sda.Fill(ds);
+ //TableRefresh(cmdText);
+
+ return ds;
+ }
+
+
+ ///
+ /// 获取对应SQL查询的数据表
+ ///
+ /// sql执行语句
+ /// 查询目标的数据表名
+ public static DataTable? ExecuteTable(string cmdText, params SqlParameter[] sqlParameters)
+ {
+ return GetDataSet(cmdText, sqlParameters).Tables[0];
+ }
+
+
+
+
+ ///
+ /// 获取某个表字段的集合
+ ///
+ /// sql执行语句
+ /// 查询目标表字段/列名的值的集合
+ public static List GetColumns(string cmdText)
+ {
+ //创建用于存储列名的集合
+ List columns = new List();
+
+ //创建sql连接
+ using (SqlConnection conn = new SqlConnection(ConStr))
+ {
+ try
+ {
+ conn.Open();
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+
+
+ SqlCommand cmd = new SqlCommand(cmdText, conn);
+ SqlDataAdapter sda = new SqlDataAdapter(cmdText, conn);
+ DataSet ds = new DataSet();
+ sda.Fill(ds);
+
+ //将获取到的字段名添加到集合中
+ foreach (DataColumn colName in ds.Tables[0].Columns)
+ {
+ columns.Add(colName.ToString());
+ }
+
+ return columns;
+ }
+ }
+
+
+ ///
+ /// 操作获取受影响的行数
+ ///
+ /// sql语句
+ /// sql字段参数
+ ///
+ public static int ExecuteNonQuery(string cmdText, params SqlParameter[] sqlParameters)
+ {
+ //创建sql连接
+ using (SqlConnection conn = new SqlConnection(ConStr))
+ {
+ conn.Open();
+
+ using SqlCommand cmd = new SqlCommand(cmdText, conn);
+
+ //sql参数化设置
+ cmd.Parameters.AddRange(sqlParameters);
+ //MessageBox.Show(cmdText);
+ //返回执行sql受影响的行数
+ int rows = cmd.ExecuteNonQuery();
+ if (rows > -1)
+ {
+ //throw new Exception("获取数据失败!(错误代码:000001)");
+ }
+
+ //TableRefresh(cmdText);
+
+ return rows;
+ }
+ }
+
+
+ ///
+ /// 获取查询数据的行数
+ ///
+ /// SQL字符串
+ /// 目标行数
+ public static int GetRowCount(string cmdText, params SqlParameter[] sqlParameters)
+ {
+ using (DataTable dt = ExecuteTable(cmdText, sqlParameters))
+ {
+ if (dt == null)
+ {
+ return 0;
+ }
+ return dt.Rows.Count;
+ }
+
+ }
+
+
+
+ ///
+ /// 获取为当前任务【自动生成】的WCS本地任务号
+ ///
+ ///
+ public static int GetTaskIdByAutoGeneration()
+ {
+ using DataTable dt = ExecuteTable("SELECT TASKNO FROM TASKNUMBER");
+
+ int taskId = (int)dt.Rows[0][0];
+
+ //此处定义9开头的任务号为手动添加的任务,因此自动生成的任务号小于9000
+ if (taskId > 899999)
+ {
+ ExecuteNonQuery("UPDATE TASKNUMBER SET TASKNO=@TaskNo WHERE TASKNO=@TaskId",
+ new SqlParameter("@taskNo", 100001),
+ new SqlParameter("@taskId", taskId));
+ return 100001;
+ }
+ else
+ {
+ ExecuteNonQuery("UPDATE TASKNUMBER SET TASKNO=@TaskNo WHERE TASKNO=@TaskId",
+ new SqlParameter("@taskNo", taskId + 1),
+ new SqlParameter("@taskId", taskId));
+ }
+
+ return taskId;
+ }
+
+ ///
+ /// 获取为当前任务【手动添加】的WCS本地任务号
+ ///
+ ///
+ public static int GetTaskIdByManualGeneration()
+ {
+ using DataTable dt = ExecuteTable("SELECT MAN_TASKNO FROM TASKNUMBER");
+
+ int taskId = (int)dt.Rows[0][0];
+
+ //此处定义9开头的任务号为手动添加的任务
+ if (taskId > 999999)
+ {
+ ExecuteNonQuery("UPDATE TASKNUMBER SET MAN_TASKNO=@Man_TaskNo WHERE MAN_TASKNO=@TaskId",
+ new SqlParameter("@Man_TaskNo", 900000),
+ new SqlParameter("@taskId", taskId));
+ return 900000;
+ }
+ else
+ {
+ ExecuteNonQuery("UPDATE TASKNUMBER SET MAN_TASKNO=@Man_TaskNo WHERE MAN_TASKNO=@TaskId",
+ new SqlParameter("@Man_TaskNo", taskId + 1),
+ new SqlParameter("@taskId", taskId));
+ }
+
+ return taskId;
+ }
+
+
+
+ ///
+ /// 获取为当前事件【手动添加】的编号
+ ///
+ ///
+ public static int GetEventIdByAutoGeneration()
+ {
+ using DataTable? dt = ExecuteTable("SELECT EVENT_TASKNO FROM TASKNUMBER");
+
+ int taskId = (int)dt.Rows[0][0];
+
+ //此处定义9开头的任务号为手动添加的任务
+ if (taskId > 9999)
+ {
+ ExecuteNonQuery("UPDATE TASKNUMBER SET EVENT_TASKNO=@Event_TaskNo WHERE EVENT_TASKNO=@TaskId",
+ new SqlParameter("@Event_TaskNo", 1001),
+ new SqlParameter("@taskId", taskId));
+ return 1001;
+ }
+ else
+ {
+ ExecuteNonQuery("UPDATE TASKNUMBER SET EVENT_TASKNO=@Event_TaskNo WHERE EVENT_TASKNO=@TaskId",
+ new SqlParameter("@Event_TaskNo", taskId + 1),
+ new SqlParameter("@taskId", taskId));
+ }
+
+ return taskId;
+ }
+
+
+ ///
+ /// 记录当前操作事件
+ ///
+ /// 信息
+ /// 标识
+ /// 类型(登录、操作等)
+ /// 来源(名称、数据集等)
+ /// 级别
+ /// 状态(是否完成等)
+ public static void NewEventLog(string message,string userId, string type, string source, string level, string status)
+ {
+ using var context = new AppDbContext();
+
+ Event_Log event_Log = new Event_Log()
+ {
+ Id = Guid.NewGuid(),
+ Message = message,
+ TimeStamp = DateTime.Now.ToString(TimeFormat.stringFormat),
+ UserId = userId,
+ Type = type,
+ Source = source,
+ Level = level,
+ Status = status,
+ };
+
+ context.Event_Log.Add(event_Log);
+
+ context.SaveChanges();
+
+ Log.Warning($"【事件记录】{JsonConvert.SerializeObject(event_Log)}");
+ }
+ ///
+ /// 记录当前操作事件
+ ///
+ /// 信息
+ /// 标识
+ /// 类型(登录、操作等)
+ /// 来源(名称、数据集等)
+ /// 级别
+ /// 状态(是否完成等)
+ public static void NewEventLog(string message, string userId)
+ {
+ using var context = new AppDbContext();
+
+ Event_Log event_Log = new Event_Log()
+ {
+ Id = Guid.NewGuid(),
+ Message = message,
+ TimeStamp = DateTime.Now.ToString(TimeFormat.stringFormat),
+ UserId = userId,
+ };
+
+ context.Event_Log.Add(event_Log);
+
+ context.SaveChanges();
+
+ Log.Warning($"【事件记录】{event_Log.UserId}-{event_Log.Message}");
+ }
+
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Utilities/Table/AlarmManager.cs b/WPFWCSDemo/Utilities/Table/AlarmManager.cs
new file mode 100644
index 0000000..306c1cb
--- /dev/null
+++ b/WPFWCSDemo/Utilities/Table/AlarmManager.cs
@@ -0,0 +1,139 @@
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.Data;
+
+namespace WPFWCSDemo.Utilities.Table
+{
+ public class AlarmManager
+ {
+ ///
+ /// 获取【实时报警】表所有行数据集合
+ ///
+ /// 返回所有行的数据
+ public static List ListAll()
+ {
+
+ using (DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM ALARM ORDER BY GEN_TIME DESC"))
+ {
+ if (dt == null) return null;
+
+ List alarms = new List();
+
+ foreach (DataRow dr in dt.Rows)
+ {
+ alarms.Add(ToModels(dr));
+ }
+ #region 反射方法
+ /*
+ foreach (DataRow dr in dt.Rows)
+ {
+ tasks.Add(dr.DataRowToModel());
+ }
+ */
+ #endregion
+ return alarms;
+ }
+
+
+ }
+
+ ///
+ /// 将【调度管理】表的单行转换为实体数据对象
+ ///
+ /// 获取表的某行数据
+ /// 当前行所有字段的集合
+ public static Alarm ToModels(DataRow dr)
+ {
+ Alarm alarm = new Alarm();
+ alarm.Point_Id = dr["Point_Id"].ToString();
+ alarm.Description = dr["Description"].ToString();
+ alarm.Priority = dr["Priority"].ToString();
+ alarm.Device_Id = dr["Device_Id"].ToString();
+ alarm.Gen_Time = Convert.ToDateTime(dr["Generation_Time"]);
+
+
+ return alarm;
+ }
+
+
+
+ ///
+ /// 向【实时报警】表中插入数据
+ ///
+ ///
+ /// 返回受影响的行数
+ public static int Insert(Alarm alarm)
+ {
+ using var context = new AppDbContext();
+
+ int count = context.Set()
+ .Where(a => a.Point_Id == alarm.Point_Id)
+ .Count();
+
+ if (count > 0) return 0;
+
+ alarm.Gen_Time = DateTime.Now;
+ context.Set()
+ .Add(alarm);
+
+ if (context.SaveChanges() == 1)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+
+ }
+
+
+
+
+ ///
+ /// 从【实时报警】表中移除数据记入历史表
+ ///
+ /// 当前已结束的报警
+ /// 执行后受影响的行数
+ public static int Delete(Alarm alarm)
+ {
+ using var context = new AppDbContext();
+
+ int count = context.Set()
+ .Where(a => a.Point_Id == alarm.Point_Id)
+ .Count();
+
+ if(count == 0) return 0;
+
+ AlarmHistory alarmHistory = new AlarmHistory()
+ {
+ Point_Id = alarm.Point_Id,
+ Description = alarm.Description,
+ Priority = alarm.Priority,
+ Device_Id = alarm.Device_Id,
+ Gen_Time = alarm.Gen_Time,
+ End_Time = DateTime.Now,
+ };
+
+ context.Set()
+ .Add(alarmHistory);
+
+ context.Set()
+ .Remove(alarm);
+
+ return context.SaveChanges();
+
+
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/Utilities/Table/TaskHistoryManager.cs b/WPFWCSDemo/Utilities/Table/TaskHistoryManager.cs
new file mode 100644
index 0000000..db2d499
--- /dev/null
+++ b/WPFWCSDemo/Utilities/Table/TaskHistoryManager.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models.Tables;
+
+namespace WPFWCSDemo.Utilities.Table
+{
+ public class TaskHistoryManager
+ {
+ ///
+ /// 获取表数据
+ ///
+ ///
+ public static List ListAll()
+ {
+
+ using (DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM TASK_HISTORY ORDER BY CREATETIME DESC"))
+ {
+ if (dt == null || dt.Rows.Count == 0) return null;
+
+ List scheduleHistoryManagers = new List();
+
+ foreach (DataRow dr in dt.Rows)
+ {
+ scheduleHistoryManagers.Add(ToModels(dr));
+ }
+
+ #region 反射方法
+ /*
+ foreach (DataRow dr in dt.Rows)
+ {
+ tasks.Add(dr.DataRowToModel());
+ }
+ */
+ #endregion
+
+ return scheduleHistoryManagers;
+ }
+
+
+ }
+
+ ///
+ /// 将表行转换成实体数据
+ ///
+ ///
+ ///
+ public static TaskHistory ToModels(DataRow dr)
+ {
+ if (dr == null) return null;
+
+ TaskHistory taskHistory = new TaskHistory();
+
+ taskHistory.JobId = dr["jobId"].ToString();
+ taskHistory.TaskId = dr["TaskId"].ToString();
+ taskHistory.PalletId = dr["PalletId"].ToString();
+ taskHistory.SourceLocation = dr["SourceLocation"].ToString();
+ taskHistory.TargetLocation = dr["TargetLocation"].ToString();
+ taskHistory.TaskType = dr["TaskType"].ToString();
+ taskHistory.TaskState = dr["TaskState"].ToString();
+ //scheduleHistoryManager.ReportState = (int)dr["ReportResult"];
+ taskHistory.ScheduleState = dr["ScheduleState"].ToString();
+ taskHistory.CreateTime = Convert.ToDateTime(dr["ScheduleTime"]);
+ taskHistory.FinishTime = Convert.ToDateTime(dr["FinishTime"]);
+ //try
+ //{
+ // taskHistory.CreateTime = Convert.ToDateTime(dr["CreateTime"]);
+ // taskHistory.FinishTime = Convert.ToDateTime(dr["FinishTime"]);
+ //}
+ //catch (Exception)
+ //{
+ // //MessageBox.Show("查询的时间内容不能为空!(错误代码:3001)");
+ //}
+
+
+ return taskHistory;
+ }
+ }
+}
diff --git a/WPFWCSDemo/Utilities/Table/TaskManager.cs b/WPFWCSDemo/Utilities/Table/TaskManager.cs
new file mode 100644
index 0000000..c524d05
--- /dev/null
+++ b/WPFWCSDemo/Utilities/Table/TaskManager.cs
@@ -0,0 +1,184 @@
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+
+namespace WPFWCSDemo.Utilities.Table
+{
+ public class TaskManager
+ {
+ ///
+ /// 获取【调度管理】表所有行数据集合
+ ///
+ /// 返回所有行的数据
+ public static List ListAll()
+ {
+
+ using (DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM TASK ORDER BY CREATETIME DESC"))
+ {
+ if (dt == null || dt.Rows.Count == 0) return null;
+
+ List taskRTs = new List();
+
+ foreach (DataRow dr in dt.Rows)
+ {
+ taskRTs.Add(ToModels(dr));
+ }
+
+ #region 反射方法
+ /*
+ foreach (DataRow dr in dt.Rows)
+ {
+ tasks.Add(dr.DataRowToModel());
+ }
+ */
+ #endregion
+
+ return taskRTs;
+ }
+
+
+ }
+
+ ///
+ /// 将【调度管理】表的单行转换为实体数据对象
+ ///
+ /// 获取表的某行数据
+ /// 当前行所有字段的集合
+ public static TaskRT? ToModels(DataRow dr)
+ {
+ TaskRT taskRT = new TaskRT();
+
+ try
+ {
+ taskRT.JobId = dr["jobId"].ToString();
+ taskRT.TaskId = dr["TaskId"].ToString();
+ //taskRT.PalletId = dr["PalletId"].ToString();
+ //taskRT.Priority = (int)dr["Priority"];
+ taskRT.SourceLocation = dr["SourceLocation"].ToString();
+ taskRT.TargetLocation = dr["TargetLocation"].ToString();
+ taskRT.TaskType = (int)dr["TaskType"];
+ taskRT.TaskState = dr["TaskState"].ToString();
+ taskRT.ScheduleState = dr["ScheduleState"].ToString();
+ taskRT.CreateTime = Convert.ToDateTime(dr["CreateTime"]);
+ taskRT.ScheduleTime = Convert.ToDateTime(dr["ScheduleTime"]);
+ //taskRT.ReportState = (int)dr["ReportState"];
+
+ return taskRT;
+ }
+ catch (Exception e)
+ {
+ Log.Warning($"【TaskManager】实体类型转换失败:{e.Message}");
+ Log.Warning($"【TaskManager】{JsonConvert.SerializeObject(taskRT)}");
+ }
+
+ return null;
+
+ }
+
+
+ ///
+ /// 向【调度管理】表中插入数据
+ ///
+ ///
+ /// 返回受影响的行数
+ public static int Insert(TaskRT taskRT, int type)
+ {
+ switch (type)
+ {
+ case 1:
+ return SqlHelper.ExecuteNonQuery("INSERT INTO TASK(TASKID,PalletId,SourceLocation,TARGET,TASKTYPE)" +
+ "VALUES(@TaskId,@PalletId,@SourceLocation,@Target,@TaskType)",
+ new SqlParameter("@TaskId", taskRT.TaskId),
+ new SqlParameter("@PalletId", taskRT.PalletId),
+ new SqlParameter("@SourceLocation", taskRT.SourceLocation),
+ new SqlParameter("@TargetLocation", taskRT.TargetLocation),
+ new SqlParameter("@TaskType", taskRT.TaskType)
+ );
+
+ case 2:
+ return SqlHelper.ExecuteNonQuery("INSERT INTO TASK(TASKID,SourceLocation,TARGETLOCATION,TASKTYPE)" +
+ "VALUES(@TaskId,@Origin,@Target,@TaskType)",
+ new SqlParameter("@TaskId", taskRT.TaskId),
+ new SqlParameter("@SourceLocation", taskRT.SourceLocation),
+ new SqlParameter("@TargetLocation", taskRT.TargetLocation),
+ new SqlParameter("@TaskType", taskRT.TaskType)
+ );
+
+ case 3:
+ return SqlHelper.ExecuteNonQuery("INSERT INTO TASK(TASKID,SourceLocation,TARGETLOCATION,TASKTYPE)" +
+ "VALUES(@TaskId,@Origin,@Target,@TaskType)",
+ new SqlParameter("@TaskId", taskRT.TaskId),
+ new SqlParameter("@SourceLocation", taskRT.SourceLocation),
+ new SqlParameter("@TargetLocation", taskRT.TargetLocation),
+ new SqlParameter("@TaskType", taskRT.TaskType)
+ );
+ default:
+ Log.Error("[Schedule]下发任务错误[Schedule]");
+ return 0;
+ }
+
+ }
+
+
+ ///
+ /// 从【调度管理】表中移除数据记入历史表
+ ///
+ /// 当前已完成的任务
+ /// 执行后受影响的行数
+ public static int Delete(TaskRT taskRT)
+ {
+ try
+ {
+ using var context = new AppDbContext();
+
+ TaskHistory taskHistory = new TaskHistory()
+ {
+ JobId = taskRT.JobId,
+ TaskId = taskRT.TaskId,
+ //PalletId = taskRT.PalletId,
+ TaskType = taskRT.TaskType.ToString(),
+ TaskState = taskRT.TaskState,
+ ScheduleState = taskRT.ScheduleState,
+ SourceLocation = taskRT.SourceLocation,
+ TargetLocation = taskRT.TargetLocation,
+ CreateTime = taskRT.CreateTime,
+ ScheduleTime = taskRT.ScheduleTime,
+ FinishTime = DateTime.Now,
+ Id = Guid.NewGuid(),
+ };
+
+ //1--------------向【调度历史】表添加数据
+ context.TaskHistories.Add(taskHistory);
+
+ //2--------------移除【调度管理】表数据
+ context.Remove(taskRT);
+
+ context.SaveChanges();
+
+ return 1;
+ }
+ catch (DBConcurrencyException e)
+ {
+ Log.Error($"【WCS移除已完成任务<异常>】任务号:{taskRT.TaskId},{e.Message}");
+ Log.Error($"【WCS移除已完成任务<异常>】任务号:{taskRT.TaskId},{e.InnerException}");
+ }
+
+ return 0;
+
+
+ }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/Utilities/UserAccessControl.cs b/WPFWCSDemo/Utilities/UserAccessControl.cs
new file mode 100644
index 0000000..3c56462
--- /dev/null
+++ b/WPFWCSDemo/Utilities/UserAccessControl.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.Utilities
+{
+ ///
+ /// 用户权限管理
+ ///
+ public class UserAccessControl
+ {
+ public static void CheckAccess()
+ {
+
+ }
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/AlarmHistoryViewModel.cs b/WPFWCSDemo/ViewModels/AlarmHistoryViewModel.cs
new file mode 100644
index 0000000..6c4969a
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/AlarmHistoryViewModel.cs
@@ -0,0 +1,694 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data.SqlClient;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Utilities;
+using System.Windows;
+using WPFWCSDemo.StateCode;
+using Serilog;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.Data;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class AlarmHistoryViewModel:ObservableObject
+ {
+ public AlarmHistoryViewModel()
+ {
+ AlarmHistory = new ObservableCollection();
+
+ ColumnList = new ObservableCollection();
+
+ columnDic = new Dictionary();
+
+ Pages = new ObservableCollection();
+
+ DateStart = DateTime.Now.AddDays(-1).ToString(TimeFormat.stringFormatDateOnly);
+ TimeStart = DateTime.Now.AddDays(-1).ToString("HH:mm");
+ DateEnd = DateTime.Now.ToString(TimeFormat.stringFormatDateOnly);
+ TimeEnd = DateTime.Now.ToString("HH:mm");
+
+ LoadAlarmHistory(1);
+
+ LoadColumnName();
+
+ PageInput = 1;
+ PageCurrent = 1;
+ PageInfo = $"当前 {PageCurrent} 页";
+
+ }
+
+ ///
+ /// false-表示默认表数据集 true-表示执行查询操作后的表数据集
+ ///
+ bool b;
+
+ ///
+ /// 历史表数据
+ ///
+ [ObservableProperty]
+ ObservableCollection _alarmHistory;
+
+ ///
+ /// 起始日期
+ ///
+ [ObservableProperty]
+ string _dateStart;
+
+ ///
+ /// 起始时间
+ ///
+ [ObservableProperty]
+ string _timeStart;
+
+ ///
+ /// 结束日期
+ ///
+ [ObservableProperty]
+ string _dateEnd;
+
+ ///
+ /// 结束时间
+ ///
+ [ObservableProperty]
+ string _timeEnd;
+
+ ///
+ /// 报警级别选中项
+ ///
+ [ObservableProperty]
+ int _alarmLevelSelectedIndex;
+ ///
+ /// 报警级别选中项
+ ///
+ [ObservableProperty]
+ int _alarmLevelSelectedItem;
+ string alarmLevel;
+
+ ///
+ /// 查询字段名
+ ///
+ [ObservableProperty]
+ string _columnName;
+
+ ///
+ /// 查询关键词
+ ///
+ [ObservableProperty]
+ string _keywords;
+
+ ///
+ /// 查询字段选择项集合
+ ///
+ [ObservableProperty]
+ ObservableCollection _columnList;
+
+ ///
+ /// 查询字段名
+ ///
+ Dictionary columnDic;
+
+
+ ///
+ /// 显示表数据
+ ///
+ /// 页数
+
+ void LoadAlarmHistory(int page)
+ {
+ b = false;
+
+ using var context = new AppDbContext();
+
+ int dtCount = context.Set()
+ .OrderByDescending(t => t.End_Time)
+ .Count();
+
+ //var alarmHistories = context.Set()
+ // .OrderByDescending(t => t.End_Time)
+ // .Skip((page - 1) * countPerPage)
+ // .Take(countPerPage)
+ // .ToList();
+
+ //AlarmHistory.Clear();
+
+ //foreach (AlarmHistory a in alarmHistories)
+ //{
+ // AlarmHistory.Add(a);
+ //}
+
+
+ DataTable? dt = SqlHelper.ExecuteTable("SELECT POINT_ID,DESCRIPTION,PRIORITY,DEVICE_ID,GEN_TIME,END_TIME FROM ALARM_LOG ORDER BY END_TIME DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ new SqlParameter("@Rows", page - 1));
+
+ var datas = dt.Rows;
+
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in datas)
+ {
+ try
+ {
+ AlarmHistory a = new AlarmHistory();
+ a.Point_Id = data["Point_Id"].ToString();
+ a.Description = data["Description"].ToString();
+ a.Priority = data["Priority"].ToString();
+ a.Device_Id = data["Device_Id"].ToString();
+ a.Gen_Time = Convert.ToDateTime(data["Gen_Time"]);
+ a.End_Time = Convert.ToDateTime(data["End_Time"]);
+
+ AlarmHistory.Add(a);
+ }
+ catch (Exception)
+ {
+
+ }
+
+ }
+
+ UpdatePageInfo(dtCount, page);
+
+ }
+ void LoadAlarmHistory(DataTable dt)
+ {
+ AlarmHistory.Clear();
+
+ var datas = dt.Rows;
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in datas)
+ {
+ AlarmHistory a = new AlarmHistory();
+ a.Point_Id = data["Point_Id"].ToString();
+ a.Description = data["Description"].ToString();
+ a.Priority = data["Priority"].ToString();
+ a.Device_Id = data["Device_Id"].ToString();
+ a.Gen_Time = Convert.ToDateTime(data["Gen_Time"]);
+ a.End_Time = Convert.ToDateTime(data["End_Time"]);
+
+ AlarmHistory.Add(a);
+ }
+
+ }
+
+
+ ///
+ /// 加载可选的搜索字段
+ ///
+ void LoadColumnName()
+ {
+ //下拉框选项填充
+ ColumnList.Clear();
+ ColumnList.Add("报警名称");
+ ColumnList.Add("报警信息");
+ ColumnList.Add("优先级");
+ ColumnList.Add("设备类别");
+ ColumnList.Add("生成时间");
+ ColumnList.Add("结束时间");
+
+ //列名映射
+ columnDic.Clear();
+ columnDic.Add("报警名称", "Point_Id");
+ columnDic.Add("报警信息", "Description");
+ columnDic.Add("优先级", "Priority");
+ columnDic.Add("设备类别", "Device_Id");
+ columnDic.Add("生成时间", "Gen_Time");
+ columnDic.Add("结束时间", "End_Time");
+ }
+
+
+ [RelayCommand]
+ void AlarmLevelSelectItemChanged()
+ {
+ DataTable? dt;
+ if (AlarmLevelSelectedIndex == 0) alarmLevel = "HIGH";
+ if (AlarmLevelSelectedIndex == 1) alarmLevel = "MEDIUM";
+ if (AlarmLevelSelectedIndex == 2) alarmLevel = "LOW";
+
+ if (string.IsNullOrEmpty(Keywords))
+ {
+ dt = SqlHelper.ExecuteTable(
+ "SELECT POINT_ID,DESCRIPTION,PRIORITY,DEVICE_ID,GEN_TIME,END_TIME FROM ALARM_LOG WHERE PRIORITY=@Priority",
+ new SqlParameter("@Priority", alarmLevel));
+ }
+ else
+ {
+ dt = SqlHelper.ExecuteTable(
+ "SELECT POINT_ID,DESCRIPTION,PRIORITY,DEVICE_ID,GEN_TIME,END_TIME FROM ALARM_LOG WHERE PRIORITY=@Priority AND DESCRIPTION LIKE @Keywords",
+ new SqlParameter("@Priority", alarmLevel),
+ new SqlParameter("@Keywords", $"%{Keywords}%"));//此处代表如果未填写关键词则忽略该条件
+ }
+
+ var datas = dt.Rows;
+
+ AlarmHistory.Clear();
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in datas)
+ {
+ try
+ {
+ AlarmHistory a = new AlarmHistory();
+ a.Point_Id = data["Point_Id"].ToString();
+ a.Description = data["Description"].ToString();
+ a.Priority = data["Priority"].ToString();
+ a.Device_Id = data["Device_Id"].ToString();
+ a.Gen_Time = Convert.ToDateTime(data["Gen_Time"]);
+ //a.Reset_Time = data["Reset_Time"].ToString();
+ a.End_Time = Convert.ToDateTime(data["End_Time"]);
+
+ AlarmHistory.Add(a);
+ }
+ catch
+ {
+
+ }
+
+
+ }
+ }
+
+
+ ///
+ /// 查询
+ ///
+ [RelayCommand]
+ void Query(string num)
+ {
+ b = true;
+
+ AlarmHistory.Clear();
+
+ DataTable? dt;
+
+ DataTable? dtCount;
+
+ using var context = new AppDbContext();
+
+ //int dataCount;
+
+ if (!DateStringFormat())
+ {
+ return;
+ }
+
+ try
+ {
+ if (!string.IsNullOrEmpty(ColumnName) && !string.IsNullOrEmpty(Keywords))
+ {
+ //dataCount = context.Set()
+ // .Where(a => a.Description.Contains(Keywords) && a.End_Time >= strDateStartNew)
+ // .Count();
+
+ dtCount = SqlHelper.ExecuteTable(
+ $"SELECT * FROM ALARM_LOG WHERE DESCRIPTION like @Keywords AND END_TIME>=@StartTime AND END_TIME<@End_Time ORDER BY End_Time DESC",
+ new SqlParameter("@Keywords", $"%{Keywords}%"),
+ new SqlParameter("@StartTime", dateTimeStart),
+ new SqlParameter("@End_Time", dateTimeEnd)
+ );
+
+ dt = SqlHelper.ExecuteTable(
+ $"SELECT * FROM ALARM_LOG WHERE DESCRIPTION like @Keywords AND END_TIME>=@StartTime AND END_TIME<@End_Time ORDER BY End_Time DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ new SqlParameter("@Keywords", $"%{Keywords}%"),
+ new SqlParameter("@StartTime", dateTimeStart),
+ new SqlParameter("@End_Time", dateTimeEnd),
+ new SqlParameter("@Rows", int.Parse(num) - 1)
+ );
+ }
+ else
+ {
+ dtCount = SqlHelper.ExecuteTable(
+ $"SELECT * FROM ALARM_LOG WHERE END_TIME>=@StartTime AND End_Time<@End_Time ORDER BY End_Time DESC",
+ new SqlParameter("@StartTime", dateTimeStart),
+ new SqlParameter("@End_Time", dateTimeEnd)
+ );
+
+ dt = SqlHelper.ExecuteTable(
+ $"SELECT * FROM ALARM_LOG WHERE END_TIME>=@StartTime AND End_Time<@End_Time ORDER BY End_Time DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ new SqlParameter("@StartTime", dateTimeStart),
+ new SqlParameter("@End_Time", dateTimeEnd),
+ new SqlParameter("@Rows", int.Parse(num) - 1)
+ );
+ }
+
+ LoadAlarmHistory(dt);
+
+ UpdatePageInfo(dtCount, num);
+
+ }
+ catch (Exception)
+ {
+ }
+
+
+ }
+
+
+ ///
+ /// 重置选择
+ ///
+ [RelayCommand]
+ void Clear()
+ {
+ Keywords = string.Empty;
+
+ AlarmHistory.Clear();
+ LoadAlarmHistory(1);
+ }
+
+
+ //---------------------------------时间字符串格式化对象---------------------------------
+ DateTime dateTimeStart;
+
+ DateTime dateTimeEnd;
+
+ ///
+ /// 日期格式处理
+ ///
+ bool DateStringFormat()
+ {
+ //处理字符串格式,规范字符串类型的时间值
+ bool b = DateTime.TryParse($"{DateStart} {TimeStart}", out dateTimeStart);
+ bool b1 = DateTime.TryParse($"{DateEnd} {TimeEnd}", out dateTimeEnd);
+
+ if (!b || !b1)
+ {
+ MessageBox.Show("时间格式错误!");
+ return false;
+ }
+
+ return true;
+ }
+
+
+ //-----------------------------------------页面跳转/统计相关-----------------------------------------
+ //-----------------------------------------页面跳转/统计相关-----------------------------------------
+
+
+ ///
+ /// 每页条数
+ ///
+ const int countPerPage = 12;
+ ///
+ /// 总数据条数-显示文本
+ ///
+ [ObservableProperty]
+ string _dataCount;
+ ///
+ /// 查询后的总条数
+ ///
+ [ObservableProperty]
+ int _dataCountNumber;
+ ///
+ /// 总页数
+ ///
+ [ObservableProperty]
+ int _pageCount;
+ ///
+ /// 手动输入页数
+ ///
+ [ObservableProperty]
+ int _pageInput;
+ ///
+ /// 鼠标需要点击的页面跳转按钮值
+ ///
+ [ObservableProperty]
+ int _pageSelected;
+ ///
+ /// 要显示页码的集合
+ ///
+ [ObservableProperty]
+ ObservableCollection _pages;
+
+ ///
+ /// 当前页
+ ///
+ [ObservableProperty]
+ int _pageCurrent;
+ ///
+ /// 当前页信息-显示文本
+ ///
+ [ObservableProperty]
+ string _pageInfo;
+
+
+
+ ///
+ /// 点击页码至指定页
+ ///
+ [RelayCommand]
+ void PageClick(string pageNumber)
+ {
+ JumpToPage(int.Parse(pageNumber));
+
+ //MessageBox.Show(pageNumber.ToString());
+ }
+
+
+ ///
+ /// 动态更新页数-下方显示具体X-X页
+ ///
+ void DynamicPage()
+ {
+ //设置最多显示5页按钮
+ Pages.Clear();
+
+ //总页数小于8-显示1-X页
+ if (PageSelected < 8)
+ {
+ for (int i = 1; i <= PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ //总页数大于8
+ else
+ {
+ //距离尾页是否多于3页
+ if (PageCount - PageSelected >= 3)
+ {
+ //显示当前页的前3和后3页码
+ if (PageCount > 7)
+ {
+ for (int i = PageSelected - 3; i <= PageSelected + 3; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ else//7页内显示全部
+ {
+ for (int i = 1; i <= PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+
+ }
+ //距离尾页是否少于3页
+ else
+ {
+ if (PageCount - PageSelected == 2)
+ {
+ for (int i = PageSelected - 4; i <= PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ if (PageCount - PageSelected == 1)
+ {
+ for (int i = PageSelected - 5; i <= PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ if (PageCount == PageSelected)
+ {
+ for (int i = PageSelected - 6; i <= PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ }
+ }
+ }
+
+
+ ///
+ /// 获取数据集的总条数和页码数,更新属性
+ ///
+ /// 总数据条数
+ /// 当前页
+ void UpdatePageInfo(int dataCount, int pageCurrent)
+ {
+ //总数据条数
+ DataCountNumber = dataCount;
+
+ //文本显示
+ DataCount = $"共 {dataCount} 条";
+
+ //总页数
+ if (DataCountNumber % countPerPage == 0)
+ {
+ PageCount = DataCountNumber / countPerPage;
+ }
+ else
+ {
+ PageCount = DataCountNumber / countPerPage + 1;
+ }
+
+ PageCurrent = pageCurrent;
+
+ DynamicPage();
+ }
+ void UpdatePageInfo(DataTable dataCount, string pageCurrent)
+ {
+ //总数据条数
+ DataCountNumber = dataCount.Rows.Count;
+
+ //文本显示
+ DataCount = $"共 {DataCountNumber} 条";
+
+ //总页数
+ if (DataCountNumber % countPerPage == 0)
+ {
+ PageCount = DataCountNumber / countPerPage;
+ }
+ else
+ {
+ PageCount = DataCountNumber / countPerPage + 1;
+ }
+
+ PageCurrent = int.Parse(pageCurrent);
+
+ DynamicPage();
+ }
+
+
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+
+
+ ///
+ /// 跳转至指定页
+ ///
+ [RelayCommand]
+ void JumpPageClick(string pageNumber)
+ {
+ try
+ {
+ if (int.Parse(pageNumber) > PageCount)
+ {
+ MessageBox.Show("不能超过最大页码数!");
+ return;
+ }
+ if (int.Parse(pageNumber) < 1)
+ {
+ MessageBox.Show("请使用正确页码数查询!");
+ return;
+ }
+
+ JumpToPage(int.Parse(pageNumber));
+
+ }
+ catch (Exception)
+ {
+ Log.Warning("【瞎β操作】查询历史记录时,跳转页面输入错误!");
+ }
+
+ }
+
+ ///
+ /// 前页
+ ///
+ [RelayCommand]
+ void PageBefore()
+ {
+ if (PageCurrent == 1) return;
+
+ PageCurrent -= 1;
+
+ JumpToPage(PageCurrent);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 后一页
+ ///
+ [RelayCommand]
+ void PageNext()
+ {
+ if (PageCurrent == PageCount) return;
+
+ PageCurrent += 1;
+
+ JumpToPage(PageCurrent);
+
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 首页
+ ///
+ [RelayCommand]
+ void PageFirst()
+ {
+ PageCurrent = 1;
+
+ JumpToPage(PageCurrent);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 尾页
+ ///
+ [RelayCommand]
+ void PageLast()
+ {
+ if (PageCurrent == PageCount) return;
+
+ JumpToPage(PageCount);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+
+ ///
+ /// 跳转到指定页
+ ///
+ ///
+ void JumpToPage(int pageNumber)
+ {
+ //获取指定页数从具体第几条数据开始计数
+ int index = (pageNumber - 1) * 10 + 1;
+
+ if (b == false)
+ {
+ //默认数据集条件下跳转
+ LoadAlarmHistory(index);
+ }
+ else
+ {
+ //查询之后的数据集条件下跳转
+ Query(index.ToString());
+ }
+
+ if (pageNumber <= PageCount)
+ {
+ PageCurrent = pageNumber;
+ PageInfo = $"当前 {pageNumber} 页";
+ }
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/AlarmViewModel.cs b/WPFWCSDemo/ViewModels/AlarmViewModel.cs
new file mode 100644
index 0000000..fda6eff
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/AlarmViewModel.cs
@@ -0,0 +1,455 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows.Threading;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.Utilities.Table;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class AlarmViewModel : ObservableObject
+ {
+ ///
+ /// 用于报警的定时器
+ ///
+ private DispatcherTimer dispatcherTimer;
+
+ ///
+ /// 查询操作停止刷新页面标志 true-查询操作后停止刷新 false-正常定时刷新
+ ///
+ bool b;
+
+ public AlarmViewModel()
+ {
+ Alarm = new ObservableCollection();
+
+ b = false;
+
+ //AlarmInitialize();
+
+ LoadAlarm();
+
+ //Task.Run(() => AlarmMonitorAsync());
+
+ // 设置定时器属性
+ dispatcherTimer = new DispatcherTimer();
+ dispatcherTimer.Interval = TimeSpan.FromSeconds(2); // 设置时间间隔1秒
+ dispatcherTimer.Tick += AlarmDispatcherTimer_Tick; // 添加事件处理程序
+ dispatcherTimer.Start(); // 启动计时器
+
+ }
+
+
+ static Dictionary alarms = new Dictionary();
+
+
+ ///
+ /// 实时表数据
+ ///
+ [ObservableProperty]
+ ObservableCollection _alarm;
+
+
+ ///
+ /// 报警级别选中项
+ ///
+ [ObservableProperty]
+ int _alarmLevelSelectedIndex;
+ ///
+ /// 报警级别选中项
+ ///
+ [ObservableProperty]
+ int _alarmLevelSelectedItem;
+ string alarmLevel;
+
+ ///
+ /// 查询关键词
+ ///
+ [ObservableProperty]
+ string _keywords;
+
+
+ private void AlarmDispatcherTimer_Tick(object? sender, EventArgs e)
+ {
+ RealTimeAlarm();
+
+ if (!b)
+ {
+ LoadAlarm();
+ }
+ }
+
+
+ ///
+ /// 加载表数据
+ ///
+ [RelayCommand]
+ void LoadAlarm()
+ {
+ using var context = new AppDbContext();
+
+ var alarms = context.Set()
+ .OrderBy(t => t.Gen_Time)
+ .ToList();
+
+ Alarm.Clear();
+
+ if (alarms is null || alarms.Count == 0) return;
+
+ foreach (var alarm in alarms)
+ {
+ Alarm.Add(alarm);
+ }
+
+ }
+
+
+ ///
+ /// 切换优先级筛选报警
+ ///
+ [RelayCommand]
+ void AlarmLevelSelectItemChanged()
+ {
+ Alarm.Clear();
+
+ DataTable? dt;
+
+ if (AlarmLevelSelectedIndex == 0) alarmLevel = "HIGH";
+ if (AlarmLevelSelectedIndex == 1) alarmLevel = "MEDIUM";
+ if (AlarmLevelSelectedIndex == 2) alarmLevel = "LOW";
+
+
+ if (string.IsNullOrEmpty(Keywords))
+ {
+ dt = SqlHelper.ExecuteTable(
+ "SELECT POINT_ID,DESCRIPTION,PRIORITY,DEVICE_ID,GEN_TIME FROM ALARM WHERE PRIORITY=@Priority",
+ new SqlParameter("@Priority", alarmLevel));
+ }
+ else
+ {
+ dt = SqlHelper.ExecuteTable(
+ "SELECT POINT_ID,DESCRIPTION,PRIORITY,DEVICE_ID,GEN_TIME FROM ALARM WHERE PRIORITY=@Priority AND DESCRIPTION LIKE @Keywords",
+ new SqlParameter("@Priority", alarmLevel),
+ new SqlParameter("@Keywords", $"%{Keywords}%"));//此处代表如果未填写关键词则忽略该条件
+ }
+
+ var datas = dt.Rows;
+
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in datas)
+ {
+ Alarm a = new Alarm();
+ a.Point_Id = data["Point_Id"].ToString();
+ a.Description = data["Description"].ToString();
+ a.Priority = data["Priority"].ToString();
+ a.Device_Id = data["Device_Id"].ToString();
+ a.Gen_Time = Convert.ToDateTime(data["Gen_Time"]);
+
+ Alarm.Add(a);
+ }
+
+ LoadAlarm();
+
+ b = true;
+ }
+
+
+ ///
+ /// 查询
+ ///
+ [RelayCommand]
+ void Query()
+ {
+ Alarm.Clear();
+
+ DataTable? dt;
+
+
+ if (!string.IsNullOrEmpty(Keywords))
+ {
+ dt = SqlHelper.ExecuteTable(
+ $"SELECT * FROM ALARM WHERE DESCRIPTION like @Keywords ORDER BY Gen_Time DESC",
+ new SqlParameter("@Keywords", $"%{Keywords}%"));
+ }
+ else
+ {
+ dt = SqlHelper.ExecuteTable("SELECT * FROM ALARM");
+ }
+
+
+ var datas = dt.Rows;
+
+ foreach (DataRow data in datas)
+ {
+ Alarm a = new Alarm();
+ a.Point_Id = data["Point_Id"].ToString();
+ a.Description = data["Description"].ToString();
+ a.Priority = data["Priority"].ToString();
+ a.Device_Id = data["Device_Id"].ToString();
+ try
+ {
+ a.Gen_Time = Convert.ToDateTime(data["Gen_Time"]);
+ }
+ catch
+ {
+
+ }
+
+
+ Alarm.Add(a);
+ }
+
+ b = true;
+ }
+
+
+ ///
+ /// 重置选择
+ ///
+ [RelayCommand]
+ void Clear()
+ {
+
+ Keywords = string.Empty;
+
+ Alarm.Clear();
+ LoadAlarm();
+
+ b = false;
+ }
+
+
+
+ ///
+ /// 触发报警-显示在报警表中
+ ///
+ public static void RealTimeAlarm()
+ {
+ AlarmTrigger("DB622.0.2", false);
+ AlarmTrigger("DB622.8.1", false);
+ AlarmTrigger("DB622.10.1", false);
+ AlarmTrigger("DB622.2.2", false);
+ AlarmTrigger("DB622.2.3", false);
+ AlarmTrigger("DB622.6.1", false);
+ AlarmTrigger("DB622.0.1", false);
+ AlarmTrigger("DB622.2.1", false);
+
+ for (int i = 1; i <= RGVStation.RGVCount; i++)
+ {
+ AlarmTrigger($"DB" + (300 + i) + ".24.0", true);
+ AlarmTrigger($"DB" + (300 + i) + ".24.1", true);
+ AlarmTrigger($"DB" + (300 + i) + ".24.2", true);
+ AlarmTrigger($"DB" + (300 + i) + ".24.3", true);
+ AlarmTrigger($"DB" + (300 + i) + ".24.4", true);
+ AlarmTrigger($"DB" + (300 + i) + ".24.5", true);
+ AlarmTrigger($"DB" + (300 + i) + ".24.6", true);
+
+ AlarmTrigger($"DB" + (300 + i) + ".25.0", true);
+ AlarmTrigger($"DB" + (300 + i) + ".25.1", true);
+ AlarmTrigger($"DB" + (300 + i) + ".25.2", true);
+ AlarmTrigger($"DB" + (300 + i) + ".25.3", true);
+ AlarmTrigger($"DB" + (300 + i) + ".25.4", true);
+ AlarmTrigger($"DB" + (300 + i) + ".25.5", true);
+ AlarmTrigger($"DB" + (300 + i) + ".25.6", true);
+ AlarmTrigger($"DB" + (300 + i) + ".25.7", true);
+ }
+
+ AlarmTrigger($"DB500.1.0", true);
+ AlarmTrigger($"DB500.1.1", true);
+ AlarmTrigger($"DB500.1.2", true);
+ AlarmTrigger($"DB500.1.3", true);
+
+ }
+
+
+
+ ///
+ /// 实时报警触发(读PLC地址)
+ ///
+ /// 报警地址
+ /// 报警触发值:true-正常触发(0-正常 1-报警) false-取反触发(0-报警 1-正常)
+ public static void AlarmTrigger(string address, bool b)
+ {
+ try
+ {
+ //正常触发 即true-报警 false-正常
+ if (b)
+ {
+ if (CircleRGVsViewModel.Instance.GetStationConnection().ReadBool(address).Content)
+ {
+ int result = AlarmManager.Insert(alarms[address]);
+
+ if (result == 1 && alarms[address].Priority=="HIGH")
+ {
+ Log.Warning($"【报警信息】触发{alarms[address].Description}");
+ }
+ }
+ else
+ {
+ int result = AlarmManager.Delete(alarms[address]);
+
+ if (result == 1 && alarms[address].Priority == "HIGH")
+ {
+ Log.Warning($"【报警信息】{alarms[address].Description}已复位");
+ }
+ }
+ }
+ //取反触发 即true-正常 false-触发
+ else
+ {
+ if (!CircleRGVsViewModel.Instance.GetStationConnection().ReadBool(address).Content)
+ {
+ int result = AlarmManager.Insert(alarms[address]);
+
+ if (result == 1 && alarms[address].Priority == "HIGH")
+ {
+ Log.Warning($"【报警信息】触发{alarms[address].Description}");
+ }
+ }
+ else
+ {
+ int result = AlarmManager.Delete(alarms[address]);
+
+ if (result == 1 && alarms[address].Priority == "HIGH")
+ {
+ Log.Warning($"【报警信息】{alarms[address].Description}已复位");
+ }
+ }
+ }
+ }
+ catch (Exception)
+ {
+
+ }
+
+
+ }
+
+
+
+ ///
+ /// 实时报警触发(自定义报警)
+ ///
+ ///
+ /// 报警触发值:true-正常触发(0-正常 1-报警) false-取反触发(0-报警 1-正常)
+ public void AlarmTrigger(bool b)
+ {
+ try
+ {
+ //正常触发 即true-报警 false-正常
+ //if (b)
+ //{
+ // if (CircleRGVsViewModel.stationConnection.ReadBool(address).Content)
+ // {
+ // int result = AlarmManager.Insert(alarms[address]);
+
+ // if (result == 1 && alarms[address].Priority == "HIGH")
+ // {
+ // Log.Warning($"【报警信息】触发{alarms[address].Description}");
+ // }
+ // }
+ // else
+ // {
+ // int result = AlarmManager.Delete(alarms[address]);
+
+ // if (result == 1 && alarms[address].Priority == "HIGH")
+ // {
+ // Log.Warning($"【报警信息】{alarms[address].Description}已复位");
+ // }
+ // }
+ //}
+ ////取反触发 即true-正常 false-触发
+ //else
+ //{
+ // if (!CircleRGVsViewModel.stationConnection.ReadBool(address).Content)
+ // {
+ // int result = AlarmManager.Insert(alarms[address]);
+
+ // if (result == 1 && alarms[address].Priority == "HIGH")
+ // {
+ // Log.Warning($"【报警信息】触发{alarms[address].Description}");
+ // }
+ // }
+ // else
+ // {
+ // int result = AlarmManager.Delete(alarms[address]);
+
+ // if (result == 1 && alarms[address].Priority == "HIGH")
+ // {
+ // Log.Warning($"【报警信息】{alarms[address].Description}已复位");
+ // }
+ // }
+ //}
+ }
+ catch (Exception)
+ {
+
+ }
+ }
+
+
+
+
+ ///
+ /// 将某条报警添加到集合中在表中显示,若该集合中已存在当前报警,则不执行
+ ///
+ /// 报警对象
+ public static void AlarmInitialize()
+ {
+ alarms.Clear();
+
+ //alarms.Add("DB610.64.0", new Alarm() { Point_Id = "AlarmTest", Description = "报警功能测试", Device_Id = "环穿", Priority = "HIGH" });
+
+ alarms.Add("DB622.0.2", new Alarm() { Point_Id = "Conv_Alarm1", Description = "无法下发任务-1001供实垛输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+ alarms.Add("DB622.8.1", new Alarm() { Point_Id = "Conv_Alarm2", Description = "无法下发任务-1003供实垛/1004放空托输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+ alarms.Add("DB622.10.1", new Alarm() { Point_Id = "Conv_Alarm3", Description = "无法下发任务-1005供实垛输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+ alarms.Add("DB622.2.2", new Alarm() { Point_Id = "Conv_Alarm4", Description = "无法下发任务-1007放实垛输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+ alarms.Add("DB622.2.3", new Alarm() { Point_Id = "Conv_Alarm5", Description = "无法下发任务-1008放实垛输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+ alarms.Add("DB622.6.1", new Alarm() { Point_Id = "Conv_Alarm6", Description = "无法下发任务-1013供空托输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+ alarms.Add("DB622.0.1", new Alarm() { Point_Id = "Conv_Alarm7", Description = "无法下发任务-1002放空托输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+ //alarms.Add("DB622.8.1", new Alarm() { Point_Id = "Conv_Alarm6", Description = "无法下发任务-1004供空托输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+ alarms.Add("DB622.2.1", new Alarm() { Point_Id = "Conv_Alarm8", Description = "无法下发任务-1006放空托输送机系统异常", Device_Id = "输送线", Priority = "MEDIUM" });
+
+ for (int i = 1; i <= RGVStation.RGVCount; i++)
+ {
+ alarms.Add($"DB" + (300 + i) + ".25.0", new Alarm() { Point_Id = $"RGV{i}_Alarm1", Description = $"{i}#环穿 急停触发", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".25.1", new Alarm() { Point_Id = $"RGV{i}_Alarm2", Description = $"{i}#环穿 运行变频报警", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".25.2", new Alarm() { Point_Id = $"RGV{i}_Alarm3", Description = $"{i}#环穿 输送变频报警", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".25.3", new Alarm() { Point_Id = $"RGV{i}_Alarm4", Description = $"{i}#环穿 取货超时", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".25.4", new Alarm() { Point_Id = $"RGV{i}_Alarm5", Description = $"{i}#环穿 放货超时", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".25.5", new Alarm() { Point_Id = $"RGV{i}_Alarm6", Description = $"{i}#环穿 BPS出错", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".25.6", new Alarm() { Point_Id = $"RGV{i}_Alarm7", Description = $"{i}#环穿 输送超时", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".25.7", new Alarm() { Point_Id = $"RGV{i}_Alarm8", Description = $"{i}#环穿 安全门打开", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".24.0", new Alarm() { Point_Id = $"RGV{i}_Alarm9", Description = $"{i}#环穿 输送机超界", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".24.1", new Alarm() { Point_Id = $"RGV{i}_Alarm10", Description = $"{i}#环穿 货物探测状态异常", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".24.2", new Alarm() { Point_Id = $"RGV{i}_Alarm11", Description = $"{i}#环穿 防撞触发", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".24.3", new Alarm() { Point_Id = $"RGV{i}_Alarm12", Description = $"{i}#环穿 触边保护", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".24.4", new Alarm() { Point_Id = $"RGV{i}_Alarm13", Description = $"{i}#环穿 倾斜检测触发", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".24.5", new Alarm() { Point_Id = $"RGV{i}_Alarm14", Description = $"{i}#环穿 维修小车移位", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".24.6", new Alarm() { Point_Id = $"RGV{i}_Alarm15", Description = $"{i}#环穿 卡阻标志", Device_Id = "环穿", Priority = "HIGH" });
+ alarms.Add($"DB" + (300 + i) + ".24.7", new Alarm() { Point_Id = $"RGV{i}_Alarm16", Description = $"{i}#环穿 安全光栅触发", Device_Id = "环穿", Priority = "HIGH" });
+ }
+
+ //alarms.Add($"DB500.1.0", new Alarm() { Point_Id = $"Conv_A_Alarm1", Description = $"实垛A线 下发任务超时", Device_Id = "系统", Priority = "HIGH" });
+ //alarms.Add($"DB500.1.1", new Alarm() { Point_Id = $"Conv_B_Alarm1", Description = $"实垛B线 下发任务超时", Device_Id = "系统", Priority = "HIGH" });
+ //alarms.Add($"DB500.1.2", new Alarm() { Point_Id = $"Conv_C_Alarm1", Description = $"实垛C线 下发任务超时", Device_Id = "系统", Priority = "HIGH" });
+ //alarms.Add($"DB500.1.3", new Alarm() { Point_Id = $"Conv_D_Alarm1", Description = $"实垛D线 下发任务超时", Device_Id = "系统", Priority = "HIGH" });
+
+
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/CircleRGVsViewModel.cs b/WPFWCSDemo/ViewModels/CircleRGVsViewModel.cs
new file mode 100644
index 0000000..dbb9af5
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/CircleRGVsViewModel.cs
@@ -0,0 +1,1115 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using HslCommunication;
+using HslCommunication.Profinet.Siemens;
+using S7.Net;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Windows.Threading;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.Views.Devices;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class CircleRGVsViewModel : ObservableObject
+ {
+ ///
+ /// 用于监控环穿状态参数的定时器
+ ///
+ private DispatcherTimer dispatcherTimer;
+
+ static int deviceCount = RGVStation.RGVCount;
+
+ private CircleRGVsViewModel()
+ {
+ States = new ObservableCollection();
+
+ CircleRGVStates = new ObservableCollection();
+
+ CircleRGVStateInitialize();
+
+ dispatcherTimer = new DispatcherTimer();
+ dispatcherTimer.Interval=TimeSpan.FromSeconds(2);
+ dispatcherTimer.Tick += DispatcherTimer_Tick;
+ dispatcherTimer.Start();
+
+ }
+
+ private void DispatcherTimer_Tick(object? sender, EventArgs e)
+ {
+ States.Clear();
+
+ for (int i = 1; i <= deviceCount; i++)
+ {
+ States.Add(GetCircleRGVState(i));
+ }
+
+ for (int i = 0; i < States.Count; i++)
+ {
+ try
+ {
+ if (States[i] is null) continue;
+
+ CircleRGVStates[i].Read_Phase = States[i].Read_Phase;
+ CircleRGVStates[i].Read_DeviceState = States[i].Read_DeviceState;
+ CircleRGVStates[i].Read_TaskNumber = States[i].Read_TaskNumber;
+ //CircleRGVStates[i].Read_TaskType = 1;
+ CircleRGVStates[i].Read_Mode = States[i].Read_Mode;
+ CircleRGVStates[i].Read_SourceLocation = States[i].Read_SourceLocation;
+ CircleRGVStates[i].Read_TargetLocation = States[i].Read_TargetLocation;
+ }
+ catch
+ {
+ //Log.Warning($"【读取环穿状态】{i + 1}#环穿读取错误!");
+ }
+
+ }
+
+
+ }
+
+ ///
+ /// 状态参数监控集合
+ ///
+ [ObservableProperty]
+ ObservableCollection _states;
+
+
+ ///
+ /// 环穿入出对应的路径
+ ///
+ public static Dictionary route = new Dictionary()
+ {
+ {1001, 1012},
+ {1003, 1009},
+ {1005, 1010},
+ {1007, 1011},
+ {1008, 1011},
+ };
+
+
+ ///
+ /// 环穿状态集合
+ ///
+ [ObservableProperty]
+ ObservableCollection _circleRGVStates;
+
+
+ ///
+ /// 穿梭车plc连接
+ ///
+ [Obsolete]
+ private static SiemensS7Net[] circleRgvConnection = new SiemensS7Net[9]
+ {
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.120"),
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.123"),
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.126"),
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.129"),
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.132"),
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.135"),
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.138"),
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.141"),
+ new SiemensS7Net(SiemensPLCS.S1500, "192.168.6.144"),
+ };
+
+ ///
+ /// 地面站plc连接
+ ///
+ private static SiemensS7Net stationConnection = new SiemensS7Net(SiemensPLCS.S1500, ipStation);
+
+ //初始化懒加载---保证线程安全
+ private static readonly Lazy instanceHolder =
+ new(()=>new CircleRGVsViewModel(),LazyThreadSafetyMode.ExecutionAndPublication);
+
+ //外部获取类实例
+ public static CircleRGVsViewModel Instance
+ {
+ get { return instanceHolder.Value; }
+ }
+
+
+ ///
+ /// 地面站plc IP
+ ///
+ const string ipStation = "192.168.6.100";
+
+
+ #region 地面站plc参数地址
+ //====================环穿写入:plc地址====================
+ ///
+ /// 任务号
+ ///
+ const string plcWriteStation_TaskNumber = $"DB610.0";
+ ///
+ /// 取货站点
+ ///
+ const string plcWriteStation_SourceLocation = $"DB610.4";
+ ///
+ /// 放货站点
+ ///
+ const string plcWriteStation_TargetLocation = $"DB610.6";
+ ///
+ /// 任务类型
+ ///
+ const string plcWriteStation_TaskType = $"DB610.8";
+ ///
+ /// 小车编号(任意数字-plc自行判断)
+ ///
+ const string plcWriteStation_DeviceNumber = $"DB610.10";
+ ///
+ /// 下发完成
+ ///
+ const string plcWriteStation_SendFinish = $"DB610.12";
+ ///
+ /// 检验码
+ ///
+ const string plcWriteStation_Checksum = $"DB610.14";
+
+
+
+ //====================环穿读取:plc地址====================
+ ///
+ /// 允许下发
+ ///
+ const string plcReadStation_Permission = $"DB611.0";
+ ///
+ /// 下发状态
+ ///
+ const string plcReadStation_SendState = $"DB611.2";
+ ///
+ /// 任务号
+ ///
+ const string plcReadStation_TaskNumber = $"DB611.4";
+
+ #endregion
+
+
+ #region 输送请求
+ ///
+ /// 取货请求---1001供应实垛 --- √
+ ///
+ const string plcReadStation_GetRequest1001 = $"DB622.0.4";
+ ///
+ /// 取货请求---1003供应实垛 --- √
+ ///
+ const string plcReadStation_GetRequest1003 = $"DB622.9.1";
+ ///
+ /// 取货请求---1005供应实垛 --- √
+ ///
+ const string plcReadStation_GetRequest1005 = $"DB622.11.1";
+ ///
+ /// 取货请求---1007供应实垛 --- √
+ ///
+ const string plcReadStation_GetRequest1007 = $"DB622.2.5";
+ ///
+ /// 取货请求---1008供应实垛 --- √
+ ///
+ const string plcReadStation_GetRequest1008 = $"DB622.2.6";
+
+ ///
+ /// 系统正常---1001供实垛 --- √
+ ///
+ const string plcReadStation_IsNotException1001 = $"DB622.0.2";
+ ///
+ /// 系统正常---1003供实垛 --- √ --- 同1004
+ ///
+ const string plcReadStation_IsNotException1003 = $"DB622.8.1";
+ ///
+ /// 系统正常---1005供实垛 --- √
+ ///
+ const string plcReadStation_IsNotException1005 = $"DB622.10.1";
+ ///
+ /// 系统正常---1007供实垛 --- √
+ ///
+ const string plcReadStation_IsNotException1007 = $"DB622.2.2";
+ ///
+ /// 系统正常---1008供实垛 --- √
+ ///
+ const string plcReadStation_IsNotException1008 = $"DB622.2.3";
+
+
+ ///
+ /// 空托供应请求---1013供空托 --- √
+ ///
+ const string plcReadStation_GetRequest1013 = $"DB622.7.1";
+ ///
+ /// 空托供应请求---1002放空托 --- √
+ ///
+ const string plcReadStation_PutRequest1002 = $"DB622.0.3";
+ ///
+ /// 空托供应请求---1004放空托 --- √
+ ///
+ const string plcReadStation_PutRequest1004 = $"DB622.9.2";
+ ///
+ /// 空托供应请求---1006放空托 --- √
+ ///
+ const string plcReadStation_PutRequest1006 = $"DB622.2.4";
+
+ ///
+ /// 空托供应请求---1013供空托 --- √
+ ///
+ const string plcReadStation_IsNotException1013 = $"DB622.6.1";
+ ///
+ /// 系统正常---1002供空托 --- √
+ ///
+ const string plcReadStation_IsNotException1002 = $"DB622.0.1";
+ ///
+ /// 系统正常---1004供空托 --- √ --- 同1003
+ ///
+ const string plcReadStation_IsNotException1004 = $"DB622.8.1";
+ ///
+ /// 系统正常---1006供空托 --- √
+ ///
+ const string plcReadStation_IsNotException1006 = $"DB622.2.1";
+
+ //******************************************2025.9新增1009、1010输送口放货允许信号******************************************
+
+ ///
+ /// 放货允许---1009 --- √
+ ///
+ const string plcReadStation_PutRequest1009 = $"DB2200.0.0";
+ ///
+ /// 放货允许---1010 --- √
+ ///
+ const string plcReadStation_PutRequest1010 = $"DB2200.4.0";
+
+ #endregion
+
+
+ ///
+ /// 通过外部获取PLC连接对象
+ ///
+ ///
+ public SiemensS7Net GetStationConnection()
+ {
+ return stationConnection;
+ }
+
+
+ ///
+ /// 穿梭车初始化连接
+ ///
+ public static void InitializeRgv()
+ {
+ #region 直读小车状态(已弃用)
+ //for (int i = 0; i < circleRgvConnection.Length; i++)
+ //{
+ // circleRgvConnection[i].ConnectTimeOut = 100;
+
+ // OperateResult result = circleRgvConnection[i].ConnectServer();
+
+ // if (result.IsSuccess)
+ // {
+ // Log.Warning($"【设备连接初始化】{i + 1}#环穿初始化连接成功!");
+ // continue;
+ // }
+ // else
+ // {
+ // Log.Warning($"【设备连接初始化】{i + 1}#环穿初始化连接失败,{result.Message},错误代码:RgvData0001");
+ // }
+ //}
+ #endregion
+
+
+ //Instance.GetStationConnection().ConnectTimeOut = 5000;
+ Instance.GetStationConnection().ConnectTimeOut = 50;
+
+ OperateResult result = stationConnection.ConnectServer();
+
+ if (result.IsSuccess)
+ {
+ Log.Warning($"【设备连接初始化】地面站初始化连接成功!");
+ return;
+ }
+ else
+ {
+ Log.Warning($"【设备连接初始化】地面站初始化连接失败,{result.Message},错误代码:RgvStationData0001");
+ }
+
+ }
+
+
+
+ ///
+ /// 环穿plc连接---地面站
+ ///
+ /// 1--正常 -1--失败 0-未知异常
+ [Obsolete]
+ public static int PlcConnect()
+ {
+ if (stationConnection is null)
+ {
+ stationConnection = new SiemensS7Net(SiemensPLCS.S1500, ipStation);
+ }
+
+ try
+ {
+ stationConnection.ConnectTimeOut = 5000;
+
+ //切换长连接
+ OperateResult result = Instance.GetStationConnection().ConnectServer();
+
+ if (result.IsSuccess)
+ {
+ return 1;
+ }
+ else
+ {
+ Instance.GetStationConnection().ConnectClose();
+ return 0;
+ }
+ }
+ catch (Exception e)
+ {
+ Log.Warning($"地面站连接异常,{e.Message},错误代码:RGVStationData0003");
+ return -1;
+ }
+
+ }
+
+
+
+
+ ///
+ /// 获取环穿状态参数
+ ///
+ /// 设备编号
+ /// 环穿状态参数
+ public static CircleRGVState? GetCircleRGVState(int id)
+ {
+ //if (PlcConnect(id) == -1)
+ //{
+ // return null;
+ //}
+
+ using CircleRGVState circleRGVState = new CircleRGVState();
+
+ try
+ {
+
+ //设备状态
+ circleRGVState.Read_DeviceState = stationConnection.ReadInt16($"DB611.{20 + (id - 1) * 30}").Content;
+ //任务号
+ circleRGVState.Read_TaskNumber = stationConnection.ReadInt32($"DB611.{34 + (id - 1) * 30}").Content;
+ //任务类型
+ circleRGVState.Read_TaskType = 1;
+ //操作模式
+ circleRGVState.Read_Mode = stationConnection.ReadInt16($"DB611.{22 + (id - 1) * 30}").Content;
+ //执行阶段
+ circleRGVState.Read_Phase = stationConnection.ReadInt16($"DB611.{42 + (id - 1) * 30}").Content;
+ //取货站点
+ circleRGVState.Read_SourceLocation = stationConnection.ReadInt16($"DB611.{38 + (id - 1) * 30}").Content.ToString();
+ //目标站点
+ circleRGVState.Read_TargetLocation = stationConnection.ReadInt16($"DB611.{40 + (id - 1) * 30}").Content.ToString();
+ //允许下发
+ circleRGVState.Read_Permission = stationConnection.ReadBool($"DB611.{44 + (id - 1) * 30}").Content;
+
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+
+ return circleRGVState;
+
+ }
+
+ ///
+ /// 获取全部环穿状态参数
+ ///
+ /// 设备编号
+ /// 环穿状态参数
+ public static List? GetAllCircleRGVState()
+ {
+ //if (PlcConnect(id) == -1)
+ //{
+ // return null;
+ //}
+
+ List circleRGVStates = new List();
+
+ for (int i = 1; i <= deviceCount; i++)
+ {
+ CircleRGVState circleRGVState = new CircleRGVState();
+
+ try
+ {
+ //设备状态
+ circleRGVState.Read_DeviceState = stationConnection.ReadInt16($"DB611.{20 + (i - 1) * 30}").Content;
+ //任务号
+ circleRGVState.Read_TaskNumber = stationConnection.ReadInt32($"DB611.{34 + (i - 1) * 30}").Content;
+ //任务类型
+ circleRGVState.Read_TaskType = 1;
+ //操作模式
+ circleRGVState.Read_Mode = stationConnection.ReadInt16($"DB611.{22 + (i - 1) * 30}").Content;
+ //执行阶段
+ circleRGVState.Read_Phase = stationConnection.ReadInt16($"DB611.{42 + (i - 1) * 30}").Content;
+ //取货站点
+ circleRGVState.Read_SourceLocation = stationConnection.ReadInt16($"DB611.{38 + (i - 1) * 30}").Content.ToString();
+ //目标站点
+ circleRGVState.Read_TargetLocation = stationConnection.ReadInt16($"DB611.{40 + (i - 1) * 30}").Content.ToString();
+ //允许下发
+ circleRGVState.Read_Permission = stationConnection.ReadBool($"DB611.{44 + (i - 1) * 30}").Content;
+ //里程
+ circleRGVState.Read_Mileage = stationConnection.ReadDouble($"DB{300 + i}.36").Content;
+
+ circleRGVStates.Add(circleRGVState);
+
+ }
+ catch (Exception)
+ {
+ return null;
+ }
+
+ }
+
+ return circleRGVStates;
+
+ }
+
+
+ ///
+ /// 获取设备运行里程数
+ ///
+ ///
+ public List GetDeviceMileage()
+ {
+ List lists = new List(new double[deviceCount]);
+
+ for (int i = 0; i < lists.Count; i++)
+ {
+ lists.Add(stationConnection.ReadDouble($"DB{300 + i + 1}.36").Content);
+ }
+
+ return lists;
+
+ }
+
+
+ ///
+ /// 获取环穿地面站状态参数
+ ///
+ /// 环穿状态参数
+ public static CircleRGVStationState? GetCircleRGVStaionState()
+ {
+ //if (PlcConnect() == -1)
+ //{
+ // Log.Warning("【尝试获取地面站请求状态】地面站连接失败!");
+ // return null;
+ //}
+
+ CircleRGVStationState circleRGVStationState = new CircleRGVStationState();
+
+ try
+ {
+ //允许下发
+ circleRGVStationState.Read_Permission = stationConnection.ReadInt16(plcReadStation_Permission).Content;
+ //下发状态
+ circleRGVStationState.Read_SendState = stationConnection.ReadInt16(plcReadStation_SendState).Content;
+ //任务号
+ circleRGVStationState.Read_TaskNumber = stationConnection.ReadInt32(plcReadStation_TaskNumber).Content;
+
+ //取货请求---1001出实垛
+ circleRGVStationState.Read_GetRequest_1001 = stationConnection.ReadBool(plcReadStation_GetRequest1001).Content;
+ //取货请求---1003出实垛
+ circleRGVStationState.Read_GetRequest_1003 = stationConnection.ReadBool(plcReadStation_GetRequest1003).Content;
+ //取货请求---1005出实垛
+ circleRGVStationState.Read_GetRequest_1005 = stationConnection.ReadBool(plcReadStation_GetRequest1005).Content;
+ //取货请求---1007出实垛
+ circleRGVStationState.Read_GetRequest_1007 = stationConnection.ReadBool(plcReadStation_GetRequest1007).Content;
+ //取货请求---1008出实垛
+ circleRGVStationState.Read_GetRequest_1008 = stationConnection.ReadBool(plcReadStation_GetRequest1008).Content;
+
+ //系统正常---1001出实垛
+ circleRGVStationState.Read_IsNotException_1001 = stationConnection.ReadBool(plcReadStation_IsNotException1001).Content;
+ //系统正常---1003出实垛
+ circleRGVStationState.Read_IsNotException_1003 = stationConnection.ReadBool(plcReadStation_IsNotException1003).Content;
+ //系统正常---1005出实垛
+ circleRGVStationState.Read_IsNotException_1005 = stationConnection.ReadBool(plcReadStation_IsNotException1005).Content;
+ //系统正常---1007出实垛
+ circleRGVStationState.Read_IsNotException_1007 = stationConnection.ReadBool(plcReadStation_IsNotException1007).Content;
+ //系统正常---1008出实垛
+ circleRGVStationState.Read_IsNotException_1008 = stationConnection.ReadBool(plcReadStation_IsNotException1008).Content;
+
+
+ //回空托请求---1013供空托请求
+ circleRGVStationState.Read_GetRequest_1013 = stationConnection.ReadBool(plcReadStation_GetRequest1013).Content;
+ //回空托请求---1002空托请求
+ circleRGVStationState.Read_PutRequest_1002 = stationConnection.ReadBool(plcReadStation_PutRequest1002).Content;
+ //回空托请求---1004空托请求
+ circleRGVStationState.Read_PutRequest_1004 = stationConnection.ReadBool(plcReadStation_PutRequest1004).Content;
+ //回空托请求---1006空托请求
+ circleRGVStationState.Read_PutRequest_1006 = stationConnection.ReadBool(plcReadStation_PutRequest1006).Content;
+
+ //系统正常---1002放空托
+ circleRGVStationState.Read_IsNotException_1002 = stationConnection.ReadBool(plcReadStation_IsNotException1002).Content;
+ //系统正常---1004放空托
+ circleRGVStationState.Read_IsNotException_1004 = stationConnection.ReadBool(plcReadStation_IsNotException1004).Content;
+ //系统正常---1006放空托
+ circleRGVStationState.Read_IsNotException_1006 = stationConnection.ReadBool(plcReadStation_IsNotException1006).Content;
+
+ //**************************************************2025.9新增1009、1010输送口放货允许**************************************************
+
+ //回空托请求---1004空托请求
+ circleRGVStationState.Read_PutRequest_1009 = stationConnection.ReadBool(plcReadStation_PutRequest1009).Content;
+ //回空托请求---1006空托请求
+ circleRGVStationState.Read_PutRequest_1010 = stationConnection.ReadBool(plcReadStation_PutRequest1010).Content;
+
+ }
+ catch (Exception e)
+ {
+ Log.Warning($"【尝试获取地面站请求状态】读取地面站请求值失败!{e.Message}");
+ Log.Warning($"【尝试获取地面站请求状态】{e.InnerException}");
+ return null;
+ }
+
+ return circleRGVStationState;
+
+ }
+
+
+ ///
+ /// 向环穿地面站下发指令
+ ///
+ /// 指定下发环穿的编号
+ /// 环穿指令
+ public static bool SendRGVStationCommand(CircleRGVStationCommand circleRGVStationCommand)
+ {
+ //if (PlcConnect() == -1)
+ //{
+ // //Log.Warning("【向地面站下发指令】尝试连接地面站失败!");
+ // return false;
+ //}
+
+ if (circleRGVStationCommand is null)
+ {
+ Log.Warning("【向地面站下发指令】下发指令为空【command is null】!");
+ return false;
+ }
+
+ //CircleRGVStationCommand circleRGVStationCommand1 = new CircleRGVStationCommand();
+ //circleRGVStationCommand1.Write_SourceLocation = (ushort)1009;
+ //circleRGVStationCommand1.Write_TargetLocation = (ushort)1004;
+ //circleRGVStationCommand1.Write_TaskNumber = 138181;
+ //circleRGVStationCommand1.Write_DeviceNumber = (ushort)0;
+ //circleRGVStationCommand1.Write_TaskType = (ushort)1;
+ //int i = Checksum.GetChecksum(circleRGVStationCommand1);
+
+ #region 有写入校验
+
+ //1. 校验写入是否成功
+ bool bTaskNumber = WritePlcForCheck(stationConnection, plcWriteStation_TaskNumber, circleRGVStationCommand.Write_TaskNumber);
+ bool bSourceLocation = WritePlcForCheck(stationConnection, plcWriteStation_SourceLocation, (ushort)circleRGVStationCommand.Write_SourceLocation);
+ bool bTargetLocation = WritePlcForCheck(stationConnection, plcWriteStation_TargetLocation, (ushort)circleRGVStationCommand.Write_TargetLocation);
+ bool bTaskType = WritePlcForCheck(stationConnection, plcWriteStation_TaskType, (short)circleRGVStationCommand.Write_TaskType);
+ bool bDeviceNumber = WritePlcForCheck(stationConnection, plcWriteStation_DeviceNumber, (short)circleRGVStationCommand.Write_DeviceNumber);
+ bool bChecksum = WritePlcForCheck(stationConnection, plcWriteStation_Checksum, Checksum.GetChecksum(circleRGVStationCommand));
+
+ //以此判断地面站参数是否写入成功
+ if (!bTaskNumber)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},任务号读写错误!");
+ return false;
+ }
+
+ if (!bSourceLocation)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},源站点读写错误!");
+ return false;
+ }
+
+ if (!bTargetLocation)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},目标站点读写错误!");
+ return false;
+ }
+
+ if (!bTaskType)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},任务类型读写错误!");
+ return false;
+ }
+
+ if (!bDeviceNumber)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},设备编号读写错误!");
+ return false;
+ }
+
+ if (!bChecksum)
+ {
+ Log.Warning($"【WCS写入信息至地面站<写入异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码读写错误!");
+ return false;
+ }
+
+ //2. 检查下发站点是否合法
+ short sourceLocation = stationConnection.ReadInt16(plcWriteStation_SourceLocation).Content;
+ short targetLocation = stationConnection.ReadInt16(plcWriteStation_TargetLocation).Content;
+
+ //查找下发的源站点是否有对应的目标站点
+ var context = new AppDbContext();
+ var tar = context.LineState
+ .Where(a => a.Source == sourceLocation && a.Target == targetLocation)
+ .Count();
+
+ //站点非法---禁止下发
+ if (tar == 0)
+ {
+ Log.Warning(
+ $"【WCS写入信息至地面站<检查到异常:非法站点>】任务号:{circleRGVStationCommand.Write_TaskNumber}," +
+ $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " +
+ $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " +
+ $"取货站点:{(ushort)sourceLocation}, " +
+ $"放货站点:{(ushort)targetLocation}, " +
+ $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},下发失败!"
+ );
+
+ return false;
+ }
+
+ //3. 写【下发完成】
+ OperateResult result = stationConnection.Write(plcWriteStation_SendFinish, (short)1);
+
+ //下发完成写入成功
+ Log.Information(
+ $"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber}," +
+ $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " +
+ $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " +
+ $"取货站点:{(ushort)sourceLocation}, " +
+ $"放货站点:{(ushort)targetLocation}, " +
+ $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},尝试下发任务!"
+ );
+
+ //todo @@@可能需要判断设备是否已经开始执行
+ //todo @@@可能需要判断设备是否已经开始执行
+ //todo @@@可能需要判断设备是否已经开始执行
+
+ Task.Delay(100).Wait();
+
+ //【下发完成】写入操作成功
+ if (result.IsSuccess)
+ {
+ //获取所有输送口请求状态
+ CircleRGVStationState circleRGVStationState = GetCircleRGVStaionState();
+
+ //4. 获取地面站【下发状态】
+ int number = circleRGVStationState.Read_SendState;
+
+ if (number == 1)
+ {
+ //下发完成写入成功
+ Log.Information(
+ $"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber}," +
+ $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " +
+ $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " +
+ $"取货站点:{(ushort)sourceLocation}, " +
+ $"放货站点:{(ushort)targetLocation}, " +
+ $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},PLC反馈【接收正常】,下发成功!"
+ );
+
+ //Log.Warning($"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码写:{Checksum.GetChecksum(circleRGVStationCommand)},读:{stationConnection.ReadInt16("DB60.904").Content},测试测试测试");
+ }
+ else
+ {
+ //需要详细了解可能【接收异常】的情况
+ //需要详细了解可能【接收异常】的情况
+ //需要详细了解可能【接收异常】的情况
+ Log.Warning($"【WCS写入信息至地面站<接收异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},PLC反馈【接收异常】!");
+ Log.Warning($"【WCS写入信息至地面站<接收异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码写入:{Checksum.GetChecksum(circleRGVStationCommand)},读取:{stationConnection.ReadInt16("DB60.904").Content},PLC反馈【接收异常】!");
+ }
+
+ //此处更新true的作用:就算【接收异常】,也可以更新任务状态,如果更新状态之后设备未执行,那么更新状态之后仍然可以定时重新下发
+ //可以避免由于某种意外原因导致的结果为false后设备执行但状态不更新的情况
+ return true;
+ }
+ else
+ {
+ Log.Warning($"【WCS写入信息至地面站<写入失败>】任务号:{circleRGVStationCommand.Write_TaskNumber},【下发完成】写入失败!");
+ return false;
+ }
+
+
+ #endregion
+
+ }
+ ///
+ /// 向环穿地面站下发指令(手动无站点校验)
+ ///
+ /// 指定下发环穿的编号
+ /// 任意字符串
+ /// 环穿指令
+ public static bool SendRGVStationCommand(CircleRGVStationCommand circleRGVStationCommand, string msg)
+ {
+ //if (PlcConnect() == -1)
+ //{
+ // //Log.Warning("【向地面站下发指令】尝试连接地面站失败!");
+ // return false;
+ //}
+
+ if (circleRGVStationCommand is null)
+ {
+ Log.Warning("【向地面站下发指令】下发指令为空【command is null】!");
+ return false;
+ }
+
+ //CircleRGVStationCommand circleRGVStationCommand1 = new CircleRGVStationCommand();
+ //circleRGVStationCommand1.Write_SourceLocation = (ushort)1009;
+ //circleRGVStationCommand1.Write_TargetLocation = (ushort)1004;
+ //circleRGVStationCommand1.Write_TaskNumber = 138181;
+ //circleRGVStationCommand1.Write_DeviceNumber = (ushort)0;
+ //circleRGVStationCommand1.Write_TaskType = (ushort)1;
+ //int i = Checksum.GetChecksum(circleRGVStationCommand1);
+
+ #region 有写入校验
+
+ //1. 校验写入是否成功
+ bool bTaskNumber = WritePlcForCheck(stationConnection, plcWriteStation_TaskNumber, circleRGVStationCommand.Write_TaskNumber);
+ bool bSourceLocation = WritePlcForCheck(stationConnection, plcWriteStation_SourceLocation, (ushort)circleRGVStationCommand.Write_SourceLocation);
+ bool bTargetLocation = WritePlcForCheck(stationConnection, plcWriteStation_TargetLocation, (ushort)circleRGVStationCommand.Write_TargetLocation);
+ bool bTaskType = WritePlcForCheck(stationConnection, plcWriteStation_TaskType, (short)circleRGVStationCommand.Write_TaskType);
+ bool bDeviceNumber = WritePlcForCheck(stationConnection, plcWriteStation_DeviceNumber, (short)circleRGVStationCommand.Write_DeviceNumber);
+ bool bChecksum = WritePlcForCheck(stationConnection, plcWriteStation_Checksum, Checksum.GetChecksum(circleRGVStationCommand));
+
+ //以此判断地面站参数是否写入成功
+ if (!bTaskNumber)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},任务号读写错误!");
+ return false;
+ }
+
+ if (!bSourceLocation)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},源站点读写错误!");
+ return false;
+ }
+
+ if (!bTargetLocation)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},目标站点读写错误!");
+ return false;
+ }
+
+ if (!bTaskType)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},任务类型读写错误!");
+ return false;
+ }
+
+ if (!bDeviceNumber)
+ {
+ Log.Warning($"【WCS写入信息至地面站<读写异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},设备编号读写错误!");
+ return false;
+ }
+
+ if (!bChecksum)
+ {
+ Log.Warning($"【WCS写入信息至地面站<写入异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码读写错误!");
+ return false;
+ }
+
+ //2. 检查下发站点是否合法
+ short sourceLocation = stationConnection.ReadInt16(plcWriteStation_SourceLocation).Content;
+ short targetLocation = stationConnection.ReadInt16(plcWriteStation_TargetLocation).Content;
+
+ //查找下发的源站点是否有对应的目标站点
+ var context = new AppDbContext();
+ var tar = context.LineState
+ .Where(a => a.Source == sourceLocation)
+ .Select(a => a.Target)
+ .FirstOrDefault();
+
+ //站点非法 --- 禁止下发
+ if (tar != targetLocation || tar == 0)
+ {
+ Log.Warning(
+ $"【WCS写入信息至地面站<检查到异常:非法站点>】任务号:{circleRGVStationCommand.Write_TaskNumber}," +
+ $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " +
+ $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " +
+ $"取货站点:{(ushort)sourceLocation}, " +
+ $"放货站点:{(ushort)targetLocation}, " +
+ $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},下发失败!"
+ );
+
+ return false;
+ }
+
+ //3. 写【下发完成】
+ OperateResult result = stationConnection.Write(plcWriteStation_SendFinish, (short)1);
+
+ //下发完成写入成功
+ Log.Information(
+ $"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber}," +
+ $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " +
+ $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " +
+ $"取货站点:{(ushort)sourceLocation}, " +
+ $"放货站点:{(ushort)targetLocation}, " +
+ $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},尝试下发任务!"
+ );
+
+ //todo @@@可能需要判断设备是否已经开始执行
+ //todo @@@可能需要判断设备是否已经开始执行
+ //todo @@@可能需要判断设备是否已经开始执行
+
+ Task.Delay(100).Wait();
+
+ //【下发完成】写入操作成功
+ if (result.IsSuccess)
+ {
+ //获取所有输送口请求状态
+ CircleRGVStationState circleRGVStationState = GetCircleRGVStaionState();
+
+ //4. 获取地面站【下发状态】
+ int number = circleRGVStationState.Read_SendState;
+
+ if (number == 1)
+ {
+ //下发完成写入成功
+ Log.Information(
+ $"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber}," +
+ $"设备编号:{(short)circleRGVStationCommand.Write_DeviceNumber}, " +
+ $"任务类型:{(short)circleRGVStationCommand.Write_TaskType}, " +
+ $"取货站点:{(ushort)sourceLocation}, " +
+ $"放货站点:{(ushort)targetLocation}, " +
+ $"检验码:{Checksum.GetChecksum(circleRGVStationCommand)},PLC反馈【接收正常】,下发成功!"
+ );
+
+ //Log.Warning($"【WCS写入信息至地面站】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码写:{Checksum.GetChecksum(circleRGVStationCommand)},读:{stationConnection.ReadInt16("DB60.904").Content},测试测试测试");
+ }
+ else
+ {
+ //需要详细了解可能【接收异常】的情况
+ //需要详细了解可能【接收异常】的情况
+ //需要详细了解可能【接收异常】的情况
+ Log.Warning($"【WCS写入信息至地面站<接收异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},PLC反馈【接收异常】!");
+ Log.Warning($"【WCS写入信息至地面站<接收异常>】任务号:{circleRGVStationCommand.Write_TaskNumber},校验码写入:{Checksum.GetChecksum(circleRGVStationCommand)},读取:{stationConnection.ReadInt16("DB60.904").Content},PLC反馈【接收异常】!");
+ }
+
+ //此处更新true的作用:就算【接收异常】,也可以更新任务状态,如果更新状态之后设备未执行,那么更新状态之后仍然可以定时重新下发
+ //可以避免由于某种意外原因导致的结果为false后设备执行但状态不更新的情况
+ return true;
+ }
+ else
+ {
+ Log.Warning($"【WCS写入信息至地面站<写入失败>】任务号:{circleRGVStationCommand.Write_TaskNumber},【下发完成】写入失败!");
+ return false;
+ }
+
+
+ #endregion
+
+ }
+
+
+
+
+ #region 环穿显示在界面的状态参数/属性
+ //---------------执行阶段---------------
+ [ObservableProperty]
+ ObservableCollection _phases = new ObservableCollection(new short[RGVStation.RGVCount]);
+
+ //---------------设备状态---------------
+ [ObservableProperty]
+ ObservableCollection _deviceStates = new ObservableCollection(new short[RGVStation.RGVCount]);
+
+
+ //----------------任务号----------------
+ [ObservableProperty]
+ ObservableCollection _taskNumbers = new ObservableCollection(new int[RGVStation.RGVCount]);
+
+
+ //---------------任务类型---------------
+ [ObservableProperty]
+ ObservableCollection _taskTypes = new ObservableCollection(new short[RGVStation.RGVCount]);
+
+ //---------------操作模式---------------
+ [ObservableProperty]
+ ObservableCollection _mode = new ObservableCollection(new short[RGVStation.RGVCount]);
+
+
+ //---------------源站点---------------
+ [ObservableProperty]
+ ObservableCollection _sourceLocations = new ObservableCollection(new string[RGVStation.RGVCount]);
+
+ //---------------目标站点---------------
+ [ObservableProperty]
+ ObservableCollection _targetLocations = new ObservableCollection(new string[RGVStation.RGVCount]);
+
+ #endregion
+
+
+ ///
+ /// 环穿状态初始化/加载
+ ///
+ void CircleRGVStateInitialize()
+ {
+
+ CircleRGVStates.Clear();
+
+ for (int i = 0; i < RGVStation.RGVCount; i++)
+ {
+ CircleRGVStates.Add(new CircleRGVState() { Title = $"{i + 1}#环穿", Read_Phase = Phases[i], Read_DeviceState = DeviceStates[i], Read_TaskNumber = TaskNumbers[i], Read_Mode = Mode[i], Read_SourceLocation = SourceLocations[i], Read_TargetLocation = TargetLocations[i] });
+ }
+
+ #region
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "1#环穿", Read_Phase = Phases[0], Read_DeviceState = DeviceStates[0], Read_TaskNumber = TaskNumbers[0], Read_Mode = Mode[0], Read_SourceLocation = SourceLocations[0], Read_TargetLocation = TargetLocations[0] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "2#环穿", Read_Phase = Phases[1], Read_DeviceState = DeviceStates[1], Read_TaskNumber = TaskNumbers[1], Read_Mode = Mode[1], Read_SourceLocation = SourceLocations[1], Read_TargetLocation = TargetLocations[1] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "3#环穿", Read_Phase = Phases[2], Read_DeviceState = DeviceStates[2], Read_TaskNumber = TaskNumbers[2], Read_Mode = Mode[2], Read_SourceLocation = SourceLocations[2], Read_TargetLocation = TargetLocations[2] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "4#环穿", Read_Phase = Phases[3], Read_DeviceState = DeviceStates[3], Read_TaskNumber = TaskNumbers[3], Read_Mode = Mode[3], Read_SourceLocation = SourceLocations[3], Read_TargetLocation = TargetLocations[3] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "5#环穿", Read_Phase = Phases[4], Read_DeviceState = DeviceStates[4], Read_TaskNumber = TaskNumbers[4], Read_Mode = Mode[4], Read_SourceLocation = SourceLocations[4], Read_TargetLocation = TargetLocations[4] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "6#环穿", Read_Phase = Phases[5], Read_DeviceState = DeviceStates[5], Read_TaskNumber = TaskNumbers[5], Read_Mode = Mode[5], Read_SourceLocation = SourceLocations[5], Read_TargetLocation = TargetLocations[5] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "7#环穿", Read_Phase = Phases[6], Read_DeviceState = DeviceStates[6], Read_TaskNumber = TaskNumbers[6], Read_Mode = Mode[6], Read_SourceLocation = SourceLocations[6], Read_TargetLocation = TargetLocations[6] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "8#环穿", Read_Phase = Phases[7], Read_DeviceState = DeviceStates[7], Read_TaskNumber = TaskNumbers[7], Read_Mode = Mode[7], Read_SourceLocation = SourceLocations[7], Read_TargetLocation = TargetLocations[7] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "9#环穿", Read_Phase = Phases[8], Read_DeviceState = DeviceStates[8], Read_TaskNumber = TaskNumbers[8], Read_Mode = Mode[8], Read_SourceLocation = SourceLocations[8], Read_TargetLocation = TargetLocations[8] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "10#环穿", Read_Phase = Phases[9], Read_DeviceState = DeviceStates[9], Read_TaskNumber = TaskNumbers[9], Read_Mode = Mode[9], Read_SourceLocation = SourceLocations[9], Read_TargetLocation = TargetLocations[9] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "11#环穿", Read_Phase = Phases[10], Read_DeviceState = DeviceStates[10], Read_TaskNumber = TaskNumbers[10], Read_Mode = Mode[10], Read_SourceLocation = SourceLocations[10], Read_TargetLocation = TargetLocations[10] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "12#环穿", Read_Phase = Phases[11], Read_DeviceState = DeviceStates[11], Read_TaskNumber = TaskNumbers[11], Read_Mode = Mode[11], Read_SourceLocation = SourceLocations[11], Read_TargetLocation = TargetLocations[11] });
+ //CircleRGVStates.Add(new CircleRGVState() { Title = "13#环穿", Read_Phase = Phases[12], Read_DeviceState = DeviceStates[12], Read_TaskNumber = TaskNumbers[12], Read_Mode = Mode[12], Read_SourceLocation = SourceLocations[12], Read_TargetLocation = TargetLocations[12] });
+ #endregion
+
+ }
+
+
+
+
+ //================需要校验【是否写入成功】的写入操作================
+
+ private static bool WritePlcForCheck(SiemensS7Net siemens, string address, bool value)
+ {
+ if (siemens.Write(address, value).IsSuccess)
+ {
+ if (value == siemens.ReadBool(address).Content)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private static bool WritePlcForCheck(SiemensS7Net siemens, string address, short value)
+ {
+
+ if (siemens.Write(address, value).IsSuccess)
+ {
+ OperateResult result = siemens.ReadInt16(address);
+
+ if (value == result.Content)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+
+
+
+ }
+
+ private static bool WritePlcForCheck(SiemensS7Net siemens, string address, ushort value)
+ {
+ if (siemens.Write(address, value).IsSuccess)
+ {
+ OperateResult result = siemens.ReadUInt16(address);
+
+ if (value == result.Content)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private static bool WritePlcForCheck(SiemensS7Net siemens, string address, int value)
+ {
+ if (siemens.Write(address, value).IsSuccess)
+ {
+ OperateResult result = siemens.ReadInt32(address);
+
+ if (value == result.Content)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private static bool WritePlcForCheck(SiemensS7Net siemens, string address, uint value)
+ {
+ if (siemens.Write(address, value).IsSuccess)
+ {
+ if (value == siemens.ReadUInt32(address).Content)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ private static bool WritePlcForCheck(SiemensS7Net siemens, string address, string value)
+ {
+ if (siemens.Write(address, value).IsSuccess)
+ {
+ if (value == siemens.ReadString(address).Content)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/ControllerViewModel.cs b/WPFWCSDemo/ViewModels/ControllerViewModel.cs
new file mode 100644
index 0000000..7d9c946
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/ControllerViewModel.cs
@@ -0,0 +1,16 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class ControllerViewModel:ObservableObject
+ {
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/ConvsViewModel.cs b/WPFWCSDemo/ViewModels/ConvsViewModel.cs
new file mode 100644
index 0000000..23b175a
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/ConvsViewModel.cs
@@ -0,0 +1,75 @@
+using HslCommunication;
+using HslCommunication.Profinet.Siemens;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.NetworkInformation;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.Models.Devices.Conv;
+using WPFWCSDemo.Models.Devices.Conv.ConvGet;
+using WPFWCSDemo.Models.Devices.Conv.ConvPut;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public class ConvsViewModel
+ {
+ public static SiemensS7Net? convConnection;
+
+ public static string ip;
+
+ public static void InitializeConv()
+ {
+ ip = "192.168.10.5";
+
+ convConnection = new SiemensS7Net(SiemensPLCS.S1500, ip);
+
+ //设置连接超时时间
+ convConnection.ConnectTimeOut = 2000;
+
+ OperateResult result = convConnection.ConnectServer();
+
+ if (result.IsSuccess)
+ {
+ Log.Warning($"输送机初始化连接成功!");
+ return;
+ }
+ else
+ {
+ Log.Warning($"输送机初始化连接失败,{result.Message},错误代码:ConvData0001");
+ }
+
+ }
+
+
+
+ ///
+ /// 输送机plc连接
+ ///
+ /// 1--正常 -1--失败 0-未知异常
+ public static int PlcConnect()
+ {
+ if (convConnection is null)
+ {
+ convConnection = new SiemensS7Net(SiemensPLCS.S1500, ip);
+ }
+
+ try
+ {
+ convConnection.ConnectServer();
+ //Log.Warning($"输送机连接成功");
+ return 1;
+ }
+ catch (Exception e)
+ {
+ Log.Warning($"输送机连接失败,{e.Message},错误代码:ConvData0002");
+ return -1;
+ }
+
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/CustomComponent/InputDialogViewModel.cs b/WPFWCSDemo/ViewModels/CustomComponent/InputDialogViewModel.cs
new file mode 100644
index 0000000..1db92e5
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/CustomComponent/InputDialogViewModel.cs
@@ -0,0 +1,72 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Metadata;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace WPFWCSDemo.ViewModels.CustomComponent
+{
+ public partial class InputDialogViewModel : ObservableObject
+ {
+
+ public InputDialogViewModel(Window window,Action action)
+ {
+ Caption = "验证";
+ InputDialog = window;
+ _task = action;
+ }
+
+ ///
+ /// 标题
+ ///
+ [ObservableProperty]
+ string _caption;
+ ///
+ /// 内容
+ ///
+ [ObservableProperty]
+ string _content;
+ ///
+ /// 当前页面
+ ///
+ [ObservableProperty]
+ Window _inputDialog;
+
+ [ObservableProperty]
+ Action? _task;
+
+ ///
+ /// 关闭窗口
+ ///
+ ///
+ [RelayCommand]
+ void Cancel(Window window)
+ {
+ window.Close();
+ }
+
+ ///
+ /// 输入密码
+ ///
+ [RelayCommand]
+ void Accept(string taskId)
+ {
+ if (Content == "472")
+ {
+ MessageBox.Show("密码正确");
+ //Task.Invoke(taskId);
+ }
+ else
+ {
+ MessageBox.Show("密码错误");
+
+ }
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/CustomComponent/MessageDialogViewModel.cs b/WPFWCSDemo/ViewModels/CustomComponent/MessageDialogViewModel.cs
new file mode 100644
index 0000000..1fce7ba
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/CustomComponent/MessageDialogViewModel.cs
@@ -0,0 +1,71 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection.Metadata;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using WPFWCSDemo.Views;
+
+namespace WPFWCSDemo.ViewModels.CustomComponent
+{
+ public partial class MessageDialogViewModel:ObservableObject
+ {
+ public MessageDialogViewModel(Window window)
+ {
+ Caption = "消息";
+ Content = "关闭该系统可能导致执行中的任务中断,是否确认要退出程序?";
+ MessageDialog = window;
+
+ }
+
+ ///
+ /// 标题
+ ///
+ [ObservableProperty]
+ string _caption;
+ ///
+ /// 内容
+ ///
+ [ObservableProperty]
+ string _content;
+ ///
+ /// 当前页面
+ ///
+ [ObservableProperty]
+ Window _messageDialog;
+
+ ///
+ /// 关闭窗口
+ ///
+ ///
+ [RelayCommand]
+ void Cancel(Window window)
+ {
+ window.Close();
+ }
+
+ ///
+ /// 终止程序
+ ///
+ [RelayCommand]
+ void Accept()
+ {
+ Application.Current.Shutdown();
+ }
+
+
+ public void GetMessageInfo(string content)
+ {
+ Caption = "消息";
+ Content = content;
+ }
+ public void GetMessageInfo(string caption,string content)
+ {
+ Caption = caption;
+ Content = content;
+ }
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/DataInfoViewModel.cs b/WPFWCSDemo/ViewModels/DataInfoViewModel.cs
new file mode 100644
index 0000000..01a006b
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/DataInfoViewModel.cs
@@ -0,0 +1,566 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using LiveCharts.Wpf;
+using LiveCharts;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using WPFWCSDemo.Models;
+using System.Threading;
+using WPFWCSDemo.Utilities.Table;
+using System.Data;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.StateCode;
+using System.Windows;
+using System.ComponentModel;
+using System.Windows.Threading;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using System.Windows.Media;
+
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class DataInfoViewModel : ObservableObject
+ {
+ ///
+ /// 用于监控环穿参数面板的定时器
+ ///
+ private DispatcherTimer dispatcherTimer;
+
+
+ public DataInfoViewModel()
+ {
+ //传递frame控件用于顶部面板点击事件跳转
+ //_navigationFrame = navigationFrame;
+
+ TaskBars = new ObservableCollection();
+
+ Tasks = new ObservableCollection();
+
+ RowSeriesTitles = new string[13];
+
+ RowSeriesCollection = new SeriesCollection(new Series[13]);
+
+ RowValues = new ChartValues(new double[13]);
+
+ PieSeriesCollection = new SeriesCollection();
+
+ PieValuesCount = new ChartValues(new int[4]);
+
+ LineValuesCount = new ChartValues(new int[4]);
+
+ LineValuesPallets = new ChartValues(new int[7]);
+
+ LineValuesGoods = new ChartValues(new int[7]);
+
+ CreateTaskBars();
+
+ TaskAscRecord();
+
+ Data_TaskBar();
+
+ Data_TaskRecord();
+
+ GetPie();
+
+ GetRowsInitialize();
+
+ GetLineCountOfWeek();
+
+ GetLineOfTaskCompare();
+
+ //Task.Run(() => DataMonitorAsync());
+
+ // 设置定时器属性
+ dispatcherTimer = new DispatcherTimer();
+ dispatcherTimer.Interval = TimeSpan.FromSeconds(2); // 设置时间间隔为1秒
+ dispatcherTimer.Tick += DispatcherTimer_Tick; // 添加事件处理程序
+ dispatcherTimer.Start(); // 启动计时器
+
+
+ //MessageBox.Show(GetDate(0));
+ }
+
+
+ public async Task DataMonitorAsync()
+ {
+ while (true)
+ {
+ Application.Current.Dispatcher.Invoke(() =>
+ {
+ Data_TaskBar();
+
+ TaskAscRecord();
+
+ Data_TaskRecord();
+
+ GetLineCountOfWeek();
+
+ GetLineOfTaskCompare();
+ });
+
+ await Task.Delay(1000);
+ }
+ }
+
+
+
+ private void DispatcherTimer_Tick(object? sender, EventArgs e)
+ {
+ Data_TaskBar();
+
+ TaskAscRecord();
+
+ Data_TaskRecord();
+
+ GetLineCountOfWeek();
+
+ GetLineOfTaskCompare();
+
+ GetRows();
+
+ //GetRowsInitialize();
+
+ }
+
+ ///
+ /// 执行中任务动态转圈元素显示
+ ///
+ [ObservableProperty]
+ Visibility _taskExecutingProgressIsVisible;
+
+ ///
+ /// 报警动态转圈元素显示
+ ///
+ [ObservableProperty]
+ Visibility _alarmProgressIsVisible;
+
+
+ ///
+ /// 上方任务面板对象
+ ///
+ [ObservableProperty]
+ ObservableCollection _taskBars;
+
+
+ ///
+ /// 顶部参数面板属性
+ ///
+ void CreateTaskBars()
+ {
+ TaskBars.Add(new DataInfoTaskbar() { Icon = "FormatListBulleted", Title = "待执行", Content = 0, Color = "#FF0CA0FF", Target = "Task" });
+ TaskBars.Add(new DataInfoTaskbar() { Icon = "Reload", Title = "执行中", Content = 0, Color = "#FF1ECA3A", Target = "Task" });
+ TaskBars.Add(new DataInfoTaskbar() { Icon = "ClockCheckOutLine", Title = "今日已完成", Content = 0, Color = "#FF02C6DC", Target = "TaskHistory" });
+ TaskBars.Add(new DataInfoTaskbar() { Icon = "AlarmLightOutline", Title = "实时报警", Content = 0, Color = "Tomato", Target = "Alarm" });//"#FFFFA000"
+ }
+
+
+ ///
+ /// 数据展示1---顶部参数面板数据
+ ///
+ void Data_TaskBar()
+ {
+ using DataTable? dt = SqlHelper.ExecuteTable("SELECT COUNT(TASKID) FROM TASK WHERE TASKSTATE=@TaskState UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK WHERE TASKSTATE=@TaskState1 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=@TaskState2 OR TASKSTATE=@TaskState3 OR TASKSTATE=@TaskState4) AND FINISHTIME>=@FinishTime UNION ALL " +
+ "SELECT COUNT(*) FROM ALARM",
+ new System.Data.SqlClient.SqlParameter("@TaskState", TaskStateCode.Task_Ready),
+ new System.Data.SqlClient.SqlParameter("@TaskState1", TaskStateCode.Task_Running),
+ new System.Data.SqlClient.SqlParameter("@FinishTime", $"{DateTime.Now.Date}"),
+ new System.Data.SqlClient.SqlParameter("@TaskState2", TaskStateCode.Task_Finish),
+ new System.Data.SqlClient.SqlParameter("@TaskState3", TaskStateCode.Task_Finish_Manual),
+ new System.Data.SqlClient.SqlParameter("@TaskState4", TaskStateCode.Task_Finish_Timeout)
+ );
+ if (dt == null) return;
+
+ TaskBars[0].Content = (int)dt.Rows[0][0];//待执行
+ TaskBars[1].Content = (int)dt.Rows[1][0];//执行中
+ TaskBars[2].Content = (int)dt.Rows[2][0];//当日已完成
+ TaskBars[3].Content = (int)dt.Rows[3][0];//报警
+
+ //值为0---面板显示灰色,否则其他颜色
+ TaskBars[0].Color = (int)dt.Rows[0][0] > 0 ? "Teal" : "DarkGray";
+ TaskBars[1].Color = (int)dt.Rows[1][0] > 0 ? "#FF1ECA3A" : "DarkGray";
+ TaskBars[2].Color = (int)dt.Rows[2][0] > 0 ? "#FF02C6DC" : "DarkGray";
+ TaskBars[3].Color = (int)dt.Rows[3][0] > 0 ? "OrangeRed" : "DarkGray";
+
+ AlarmProgressIsVisible = (int)dt.Rows[3][0] > 0 ? Visibility.Visible : Visibility.Hidden;
+ TaskExecutingProgressIsVisible = (int)dt.Rows[1][0] > 0 ? Visibility.Visible : Visibility.Hidden;
+
+
+ }
+
+ [ObservableProperty]
+ ObservableCollection _tasks;
+
+ ///
+ /// 部分执行中任务展示面板
+ ///
+ void TaskAscRecord()
+ {
+ Tasks.Clear();
+ Tasks.Add(new DataInfoTaskAsc() { JobId = string.Empty, TaskId = string.Empty, TaskType = 0, ScheduleState = string.Empty, SourceLocation = string.Empty, TargetLocation = string.Empty });
+ Tasks.Add(new DataInfoTaskAsc() { JobId = string.Empty, TaskId = string.Empty, TaskType = 0, ScheduleState = string.Empty, SourceLocation = string.Empty, TargetLocation = string.Empty });
+ Tasks.Add(new DataInfoTaskAsc() { JobId = string.Empty, TaskId = string.Empty, TaskType = 0, ScheduleState = string.Empty, SourceLocation = string.Empty, TargetLocation = string.Empty });
+
+ }
+
+ ///
+ /// 数据展示2---获取日期最早的3条任务
+ ///
+ public void Data_TaskRecord()
+ {
+ using DataTable? dt = SqlHelper.ExecuteTable("SELECT TOP 3 * FROM TASK ORDER BY CREATETIME ASC");
+ if (dt == null) return;
+
+ if (dt.Rows.Count == 0) return;
+
+ //任务1
+ using TaskRT? taskRT = TaskManager.ToModels(dt.Rows[0]);
+ Tasks[0].JobId = taskRT.JobId;
+ Tasks[0].TaskId = taskRT.TaskId.ToString();
+ Tasks[0].TaskType = taskRT.TaskType;
+ Tasks[0].ScheduleState = taskRT.ScheduleState;
+ Tasks[0].SourceLocation = taskRT.SourceLocation;
+ Tasks[0].TargetLocation = taskRT.TargetLocation;
+
+ if (dt.Rows.Count == 1) return;
+ //任务2
+ using TaskRT? taskRT1 = TaskManager.ToModels(dt.Rows[1]);
+ Tasks[1].JobId = taskRT1.JobId;
+ Tasks[1].TaskId = taskRT1.TaskId.ToString();
+ Tasks[1].TaskType = taskRT1.TaskType;
+ Tasks[1].ScheduleState = taskRT1.ScheduleState;
+ Tasks[1].SourceLocation = taskRT1.SourceLocation;
+ Tasks[1].TargetLocation = taskRT1.TargetLocation;
+
+ if (dt.Rows.Count == 2) return;
+ //任务3
+ using TaskRT? taskRT2 = TaskManager.ToModels(dt.Rows[2]);
+ Tasks[2].JobId = taskRT2.JobId;
+ Tasks[2].TaskId = taskRT2.TaskId.ToString();
+ Tasks[2].TaskType = taskRT2.TaskType;
+ Tasks[2].ScheduleState = taskRT2.ScheduleState;
+ Tasks[2].SourceLocation = taskRT2.SourceLocation;
+ Tasks[2].TargetLocation = taskRT2.TargetLocation;
+
+
+ }
+
+
+ ///
+ /// 饼图数据集合
+ ///
+ [ObservableProperty]
+ SeriesCollection _pieSeriesCollection;
+ ///
+ /// 数据集合值
+ ///
+ [ObservableProperty]
+ double[] pieValues = new double[4];
+ //设备使用次数
+ [ObservableProperty]
+ ChartValues _pieValuesCount;
+
+ string[] s = new string[] { "1009线", "1010线", "1011线", "1012线" };
+
+ int[] dValuesPie = new int[4];
+ ///
+ /// 数据展示4---饼图面板
+ ///
+ private void GetPie()
+ {
+ using DataTable? dt = SqlHelper.ExecuteTable(
+ "SELECT COUNT(SOURCELOCATION) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TARGETLOCATION='1009' AND FINISHTIME>=@FinishTime UNION ALL " +
+ "SELECT COUNT(SOURCELOCATION) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TARGETLOCATION='1010' AND FINISHTIME>=@FinishTime UNION ALL " +
+ "SELECT COUNT(SOURCELOCATION) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TARGETLOCATION='1011' AND FINISHTIME>=@FinishTime UNION ALL " +
+ "SELECT COUNT(SOURCELOCATION) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TARGETLOCATION='1012' AND FINISHTIME>=@FinishTime ",
+ new System.Data.SqlClient.SqlParameter("@FinishTime", DateTime.Now.AddDays(-7).ToString(TimeFormat.stringFormatDateOnly)));
+
+ //int[] dValues = new int[]
+ //{
+ // (int)dt.Rows[0][0],
+ // (int)dt.Rows[1][0],
+ // (int)dt.Rows[2][0],
+ // (int)dt.Rows[3][0]
+ //};
+
+ for (int i = 0; i < dValuesPie.Length; i++)
+ {
+ dValuesPie[i] = (int)dt.Rows[i][0];
+ }
+
+ //前台数据赋值
+ for (int i = 0; i < dValuesPie.Length; i++)
+ {
+ PieValuesCount[i] = dValuesPie[i];
+ }
+
+ //PieSeriesCollection = new SeriesCollection();
+ //int[] pieValues = new int[] { 25, 36, 85, 45, 69, 45, 85, 33, 79 };
+
+
+ PieSeriesCollection.Clear();
+
+ for (int i = 0; i < PieValues.Length; i++)
+ {
+ PieSeriesCollection.Add(new PieSeries
+ {
+ Title = s[i],
+ Values = new ChartValues { PieValuesCount[i] },
+ DataLabels = false,
+ });
+ }
+
+ }
+
+
+
+ ///
+ /// 图形数据集合
+ ///
+ [ObservableProperty]
+ SeriesCollection _rowSeriesCollection;
+
+ ///
+ /// 运行里程集合
+ ///
+ [ObservableProperty]
+ ChartValues _rowValues;
+
+ List brushes = new List()
+ {
+ Brushes.DarkGreen,
+ Brushes.Salmon,
+ Brushes.MediumSpringGreen,
+ Brushes.SlateBlue,
+ Brushes.Purple,
+ Brushes.LightPink,
+ Brushes.Firebrick,
+ Brushes.DarkOrange,
+ Brushes.DeepSkyBlue,
+ Brushes.Yellow,
+ Brushes.Blue,
+ Brushes.OliveDrab,
+ Brushes.Tan,
+ };
+
+ ///
+ /// 标题集合
+ ///
+ [ObservableProperty]
+ string[] _rowSeriesTitles;
+
+ ///
+ /// 里程统计条形图初始化
+ ///
+ private void GetRowsInitialize()
+ {
+ List states = CircleRGVsViewModel.GetAllCircleRGVState();
+
+ if (states == null) return;
+
+ RowSeriesCollection.Clear();
+
+ //前台数据赋值
+ for (int i = 0; i < states.Count; i++)
+ {
+ RowValues[i] = states[i].Read_Mileage;
+
+ RowSeriesTitles[i] = ($"{i + 1}#环穿");
+ }
+
+ RowSeriesCollection = new SeriesCollection
+ {
+ new RowSeries()
+ {
+ Title = "运行里程(km):",
+ Values = RowValues,
+ RowPadding = 10,
+ MinHeight = 30,
+ Foreground = Brushes.Gray,
+ Fill=Brushes.Transparent,
+ DataLabels = true,
+ Configuration=new LiveCharts.Configurations.CartesianMapper()
+ .Y((value,index)=>index)
+ .X(value=>value)
+ .Fill((value, index) => brushes[index])
+ }
+ };
+
+ //for (int i = 0; i < RowSeriesTitles.Length; i++)
+ //{
+ //RowSeriesCollection.Add(new RowSeries()
+ //{
+ // Title = RowSeriesTitles[i],
+ // Values = new ChartValues { RowValues[i] },
+ // RowPadding = 10,
+ // MinHeight = 30,
+ //});
+
+ //}
+ }
+
+ private void GetRows()
+ {
+ List states = CircleRGVsViewModel.GetAllCircleRGVState();
+
+ if (states == null) return;
+
+ //前台数据赋值
+ for (int i = 0; i < states.Count; i++)
+ {
+ RowValues[i] = states[i].Read_Mileage;
+
+ //RowSeriesTitles[i] = ($"{i + 1}#环穿");
+ }
+ }
+
+
+
+
+
+
+ [ObservableProperty]
+ string[] lineLabels = new[] { "第一周", "第二周", "第三周", "第四周" };
+
+ [ObservableProperty]
+ ChartValues lineValuesCount;
+
+ int[] dValuesWeekLine = new int[4];
+ ///
+ /// 数据展示3---曲线图面板1---月内(每周)任务数量
+ ///
+ private void GetLineCountOfWeek()
+ {
+ //X轴---日期
+ //LineLabels = new[] { "第一周", "第二周", "第三周", "第四周" };
+
+ using DataTable? dt = SqlHelper.ExecuteTable(
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND FINISHTIME>=@FinishTime1 AND FINISHTIME<@FinishTime UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND FINISHTIME>=@FinishTime2 AND FINISHTIME<@FinishTime1 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND FINISHTIME>=@FinishTime3 AND FINISHTIME<@FinishTime2 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND FINISHTIME>=@FinishTime4 AND FINISHTIME<@FinishTime3 "
+ ,
+ new System.Data.SqlClient.SqlParameter("@FinishTime", $"{DateTime.Now.AddMonths(1).ToString("yyyy-MM")}-01"),
+ new System.Data.SqlClient.SqlParameter("@FinishTime1", $"{DateTime.Now.ToString("yyyy-MM")}-22"),
+ new System.Data.SqlClient.SqlParameter("@FinishTime2", $"{DateTime.Now.ToString("yyyy-MM")}-15"),
+ new System.Data.SqlClient.SqlParameter("@FinishTime3", $"{DateTime.Now.ToString("yyyy-MM")}-08"),
+ new System.Data.SqlClient.SqlParameter("@FinishTime4", $"{DateTime.Now.ToString("yyyy-MM")}-01")
+ );
+
+ //当日任务量
+ for (int i = 0; i < dValuesWeekLine.Length; i++)
+ {
+ dValuesWeekLine[i] = (int)dt.Rows[3 - i][0];
+ }
+
+ //LineValuesCount.Clear();
+
+ for (int i = 0; i < dValuesWeekLine.Length; i++)
+ {
+ //LineValuesCount.Add(dValues[i]);
+ LineValuesCount[i] = dValuesWeekLine[i];
+ }
+
+ }
+
+
+ [ObservableProperty]
+ string[] lineLabels1;
+
+ ///
+ /// 空托任务曲线集合初始化
+ ///
+ [ObservableProperty]
+ ChartValues lineValuesPallets;
+
+ ///
+ /// 实垛任务曲线集合初始化
+ ///
+ [ObservableProperty]
+ ChartValues lineValuesGoods;
+
+ int[] dValuesTask = new int[7];
+
+ int[] dValuesTask1 = new int[7];
+
+ ///
+ /// 数据展示5---曲线图面板2---当日各类型任务数量
+ ///
+ private void GetLineOfTaskCompare()
+ {
+ LineLabels1 = new[] { GetDate(-6), GetDate(-5), GetDate(-4), GetDate(-3), GetDate(-2), GetDate(-1), GetDate(0) };
+
+ using DataTable? dt = SqlHelper.ExecuteTable(
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType AND FINISHTIME>@FinishTime1 AND FINISHTIME<@FinishTime UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType AND FINISHTIME>@FinishTime2 AND FINISHTIME<@FinishTime1 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType AND FINISHTIME>@FinishTime3 AND FINISHTIME<@FinishTime2 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType AND FINISHTIME>@FinishTime4 AND FINISHTIME<@FinishTime3 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType AND FINISHTIME>@FinishTime5 AND FINISHTIME<@FinishTime4 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType AND FINISHTIME>@FinishTime6 AND FINISHTIME<@FinishTime5 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType AND FINISHTIME>@FinishTime7 AND FINISHTIME<@FinishTime6 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType1 AND FINISHTIME>@FinishTime1 AND FINISHTIME<@FinishTime UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType1 AND FINISHTIME>@FinishTime2 AND FINISHTIME<@FinishTime1 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType1 AND FINISHTIME>@FinishTime3 AND FINISHTIME<@FinishTime2 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType1 AND FINISHTIME>@FinishTime4 AND FINISHTIME<@FinishTime3 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType1 AND FINISHTIME>@FinishTime5 AND FINISHTIME<@FinishTime4 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType1 AND FINISHTIME>@FinishTime6 AND FINISHTIME<@FinishTime5 UNION ALL " +
+ "SELECT COUNT(TASKID) FROM TASK_HISTORY WHERE (TASKSTATE=102 OR TASKSTATE=103 OR TASKSTATE=106) AND TASKTYPE LIKE @TaskType1 AND FINISHTIME>@FinishTime7 AND FINISHTIME<@FinishTime6",
+ new System.Data.SqlClient.SqlParameter("@TaskType", "10%"),
+ new System.Data.SqlClient.SqlParameter("@TaskType1", "11%"),
+ new System.Data.SqlClient.SqlParameter("@FinishTime", GetDate(1)),
+ new System.Data.SqlClient.SqlParameter("@FinishTime1", GetDate(0)),
+ new System.Data.SqlClient.SqlParameter("@FinishTime2", GetDate(-1)),
+ new System.Data.SqlClient.SqlParameter("@FinishTime3", GetDate(-2)),
+ new System.Data.SqlClient.SqlParameter("@FinishTime4", GetDate(-3)),
+ new System.Data.SqlClient.SqlParameter("@FinishTime5", GetDate(-4)),
+ new System.Data.SqlClient.SqlParameter("@FinishTime6", GetDate(-5)),
+ new System.Data.SqlClient.SqlParameter("@FinishTime7", GetDate(-6))
+ );
+
+ //各类型任务数据
+ for (int i = 0; i < dValuesTask.Length; i++)
+ {
+ dValuesTask[i] = (int)dt.Rows[6 - i][0];
+ }
+
+
+ for (int i = 0; i < dValuesTask.Length; i++)
+ {
+ //LineValuesStockIn.Add(dValues[i]);
+ LineValuesPallets[i] = dValuesTask[i];
+ }
+
+ //重置数据
+ for (int i = 0; i < dValuesTask1.Length; i++)
+ {
+ dValuesTask1[i] = (int)dt.Rows[6 + 7 - i][0];
+ }
+
+ for (int i = 0; i < dValuesTask1.Length; i++)
+ {
+ //LineValuesStockOut.Add(dValues2[i]);
+ LineValuesGoods[i] = dValuesTask1[i];
+ }
+
+
+ }
+
+ ///
+ /// 获取时间字符串
+ ///
+ /// 以当天为准偏移i天
+ /// 偏移天数
+ string GetDate(int i)
+ {
+ return DateTime.Now.AddDays(i).ToString(TimeFormat.stringFormatDateOnly);
+ }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/DbViews/TaskDbViewModel.cs b/WPFWCSDemo/ViewModels/DbViews/TaskDbViewModel.cs
new file mode 100644
index 0000000..341ad3a
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/DbViews/TaskDbViewModel.cs
@@ -0,0 +1,772 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Microsoft.EntityFrameworkCore;
+using Newtonsoft.Json;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Threading;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.Utilities.Table;
+using WPFWCSDemo.Views.CustomComponent;
+
+namespace WPFWCSDemo.ViewModels.DbViews
+{
+ public partial class TaskDbViewModel : ObservableObject
+ {
+ ///
+ /// 用于实时更新任务表的定时器
+ ///
+ private DispatcherTimer dispatcherTimer;
+
+ public TaskDbViewModel()
+ {
+ TaskView = new ObservableCollection();
+
+ ColumnList = new List();
+
+ col = new Dictionary();
+
+ SourceLocations = new List();
+
+ TargetLocations = new List();
+
+ RGVNumbers = new List();
+
+ LoadTaskGrid();
+
+ LoadColumns();
+
+ LocationInitialize();
+
+ //Task.Run(() => LoadTaskGridAsync());
+
+ b = true;
+
+ // 设置定时器属性
+ dispatcherTimer = new DispatcherTimer();
+ dispatcherTimer.Interval = TimeSpan.FromSeconds(5); // 设置时间间隔
+ dispatcherTimer.Tick += DispatcherTimer_Tick; // 添加事件处理程序
+ dispatcherTimer.Start(); // 启动计时器
+ }
+
+
+ //调度任务表刷新参数
+ private void DispatcherTimer_Tick(object? sender, EventArgs e)
+ {
+ if (b)
+ {
+ LoadTaskGrid();
+ }
+
+ }
+
+
+
+ ///
+ /// 是否更新任务表的标志
+ ///
+ bool b;
+
+ ///
+ /// 调度任务字段---原数据/视图数据
+ ///
+ [ObservableProperty]
+ ObservableCollection _taskView;
+
+ ///
+ /// 搜索关键字
+ ///
+ [ObservableProperty]
+ string? _keywords;
+
+ ///
+ /// 筛选列表集合
+ ///
+ [ObservableProperty]
+ List _columnList;
+
+ ///
+ /// 筛选列表集合对应的查询字段
+ ///
+ Dictionary col;
+
+ ///
+ /// 筛选列表文本
+ ///
+ [ObservableProperty]
+ string? _columnName;
+
+ ///
+ /// 筛选列表文本选择项
+ ///
+ [ObservableProperty]
+ string? _columnNameSelected;
+
+ ///
+ /// 筛选列表选项
+ ///
+ [ObservableProperty]
+ int _taskTypeSelectedIndex;
+
+ ///
+ /// 右侧对话框弹出属性
+ ///
+ [ObservableProperty]
+ bool _isRightDrawerOpen;
+
+ ///
+ /// 顶部对话框弹出属性
+ ///
+ [ObservableProperty]
+ bool _isTopDrawerOpen;
+
+
+
+ ///
+ /// 站点初始化集合
+ ///
+ [ObservableProperty]
+ int _rowCount;
+ [ObservableProperty]
+ int _columnCount;
+ [ObservableProperty]
+ int _floorCount;
+ [ObservableProperty]
+ List _rows;
+ [ObservableProperty]
+ List _columns;
+ [ObservableProperty]
+ List _floors;
+
+ ///
+ /// 取放货站点集合
+ ///
+ [ObservableProperty]
+ List _sourceLocations;
+ [ObservableProperty]
+ List _targetLocations;
+
+
+
+ ///
+ /// 测试下发界面任务类型
+ ///
+ [ObservableProperty]
+ int _testingTaskTypeIndex;
+ ///
+ /// 任务类型
+ ///
+ [ObservableProperty]
+ int _selectedTaskTypeIndex;
+ ///
+ /// 输入托盘号
+ ///
+ [ObservableProperty]
+ string _inputTaskId;
+ ///
+ /// 取货站点
+ ///
+ [ObservableProperty]
+ int _selectedSourceLocation;
+ ///
+ /// 放货站点
+ ///
+ [ObservableProperty]
+ int _selectedTargetLocation;
+
+ ///
+ /// 小车编号集合
+ ///
+ [ObservableProperty]
+ List _rGVNumbers;
+ ///
+ /// 选中小车编号
+ ///
+ [ObservableProperty]
+ int _selectedRGVNumber;
+
+
+
+ ///
+ /// 右侧对话框弹出命令
+ ///
+ [RelayCommand]
+ private void NewTask()
+ {
+ IsRightDrawerOpen = true;
+ }
+
+
+ ///
+ /// 顶部对话框弹出命令---堆垛机测试
+ ///
+ [RelayCommand]
+ private void StackerTesting()
+ {
+ IsTopDrawerOpen = true;
+ }
+
+
+ ///
+ /// 更改任务类型选项直接更新表
+ ///
+ //[RelayCommand]
+ void TaskTypeSelectItemChanged()
+ {
+ //------------------------------------------------------------------视图-----------------------------------------------------------------
+ //------------------------------------------------------------------视图-----------------------------------------------------------------
+ //------------------------------------------------------------------视图-----------------------------------------------------------------
+
+
+ DataTable? dtView;
+ if (TaskTypeSelectedIndex == 1)
+ {
+ dtView = SqlHelper.ExecuteTable("SELECT * FROM TASK_VIEW WHERE 任务类型 LIKE @TaskType ORDER BY 生成时间 DESC",
+ new SqlParameter("@TaskType", TaskTypeSelectedIndex + "%"));
+ }
+ else if (TaskTypeSelectedIndex == 2)
+ {
+ dtView = SqlHelper.ExecuteTable("SELECT * FROM TASK_VIEW WHERE 任务类型<>@TaskType ORDER BY 生成时间 DESC",
+ new SqlParameter("@TaskType", 1));
+ }
+ else
+ {
+ dtView = SqlHelper.ExecuteTable("SELECT * FROM TASK_VIEW ORDER BY 生成时间 DESC");
+ }
+
+ //获取查询语句对应的数据表DataTable
+
+ var dataViews = dtView.Rows;
+
+ TaskView.Clear();
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in dataViews)
+ {
+ TaskView taskView = new TaskView();
+ taskView.JobId = data["环穿编号"].ToString();
+ taskView.TaskId = data["任务号"].ToString();
+ //taskView.PalletId = data["PalletId"].ToString();
+ taskView.SourceLocation = data["源站点"].ToString();
+ taskView.TargetLocation = data["目标站点"].ToString();
+ taskView.TaskType = data["任务类型"].ToString();
+ taskView.TaskState = data["任务状态"].ToString();
+ taskView.ScheduleState = data["调度状态"].ToString();
+ taskView.CreateTime = Convert.ToDateTime(data["生成时间"]);
+ taskView.ScheduleTime = Convert.ToDateTime(data["调度时间"]);
+ taskView.ReportState = data["取货状态"].ToString();
+ TaskView.Add(taskView);
+ }
+
+ }
+
+
+
+ ///
+ /// 查询任务
+ ///
+ [RelayCommand]
+ public void Query()
+ {
+ //关键词不为空且列名不为空
+ if (!string.IsNullOrEmpty(Keywords) && !string.IsNullOrEmpty(ColumnName))
+ {
+ using var context = new AppDbContext();
+
+ var tasks = context.Set()
+ .FromSqlInterpolated($"SELECT * FROM TASK_VIEW WHERE {col[ColumnName]} LIKE %{Keywords}% ORDER BY 生成时间 DESC")
+ .ToList();
+
+ TaskView.Clear();
+
+ //遍历表中每行数据并初始化值
+ foreach (TaskView task in tasks)
+ {
+ TaskView.Add(task);
+ }
+
+ }
+ else
+ {
+ LoadTaskGrid();
+ }
+
+ b = false;
+
+ }
+
+
+ ///
+ /// 重置筛选项
+ ///
+ [RelayCommand]
+ void Clear()
+ {
+ Keywords = string.Empty;
+ ColumnName = string.Empty;
+
+ LoadTaskGrid();
+
+ b = true;
+ }
+
+ #region 添加新任务相关
+
+
+ // 下拉框获取值属性 (源/目标排、列、层)
+
+
+
+ ///
+ /// 点击新建任务按钮命令
+ ///
+ [RelayCommand]
+ public void AddTask()
+ {
+ InputCheck();
+ //MessageBox.Show(SelectedTaskType);
+ //获取任务参数值
+ TaskRT taskRT = new TaskRT
+ {
+ TaskId = SqlHelper.GetTaskIdByManualGeneration().ToString(),//使用int类型初始值不是空 指定9起始的任务号为人工操作标识
+ SourceLocation = SelectedSourceLocation.ToString(),
+ TargetLocation = SelectedTargetLocation.ToString(),
+ ScheduleState = ScheduleStateCode.Trans_CircleRGV_Ready,
+ TaskState = TaskStateCode.Task_Running,
+ CreateTime = DateTime.Now,
+ //ReportState = 0
+
+ };
+
+ //任务校验和添加新任务(区分任务类型)
+ if (SelectedTaskTypeIndex == 0)
+ {
+ taskRT.TaskType = 10;
+ }
+ else if (SelectedTaskTypeIndex == 1)
+ {
+ taskRT.TaskType = 11;
+ }
+ else if (SelectedTaskTypeIndex == 2 || SelectedTaskTypeIndex == 3)
+ {
+ taskRT.TaskType = SelectedTaskTypeIndex;
+ }
+ else
+ {
+ MessageBox.Show("任务类型错误!");
+ return;
+ }
+
+ Insert(taskRT, taskRT.TaskType);
+
+ SqlHelper.NewEventLog($"手动下发调度任务:任务号:{taskRT.TaskId}", "USER");
+
+ //重载任务表
+ LoadTaskGrid();
+
+ }
+ #endregion
+
+
+ ///
+ /// 加载下拉框内容
+ ///
+ public void LoadColumns()
+ {
+ ColumnList.Clear();
+ //ColumnList.Add("作业号");
+ ColumnList.Add("任务号");
+ //ColumnList.Add("托盘号");
+ ColumnList.Add("任务类型");
+ ColumnList.Add("源站点");
+ ColumnList.Add("目标站点");
+ ColumnList.Add("任务状态");
+ //ColumnList.Add("生成时间");
+
+ col.Clear();
+ //col.Add("作业号", "JobId");
+ col.Add("任务号", "任务号");
+ //col.Add("托盘号", "PalletId");
+ col.Add("任务类型", "任务类型");
+ col.Add("源站点", "源站点");
+ col.Add("目标站点", "目标站点");
+ col.Add("任务状态", "任务状态");
+ //col.Add("生成时间", "CreateTime");
+
+ RGVNumbers.Clear();
+ for (int i = 0; i < RGVStation.RGVCount; i++)
+ {
+ RGVNumbers.Add(i);
+ }
+
+ }
+
+
+
+ ///
+ /// 加载表格内容
+ ///
+ public void LoadTaskGrid()
+ {
+ //-------------------------------------------------------------------------视图----------------------------------------------------------------------
+ //-------------------------------------------------------------------------视图----------------------------------------------------------------------
+ //-------------------------------------------------------------------------视图----------------------------------------------------------------------
+
+ using var context = new AppDbContext();
+
+ var tasks = context.Set()
+ .OrderByDescending(t => t.CreateTime)
+ .ToList();
+
+ TaskView.Clear();
+
+ //遍历表中每行数据并初始化值
+ foreach (TaskView task in tasks)
+ {
+ TaskView.Add(task);
+ }
+
+ }
+
+
+
+ ///
+ /// 向调度表中插入任务
+ ///
+ /// TaskRT类的实例化对象
+ /// 任务类型
+ ///
+ public void Insert(TaskRT taskRT, int taskType)
+ {
+ try
+ {
+ using var context = new AppDbContext();
+
+ context.Set()
+ .Add(taskRT);
+
+ int result = context.SaveChanges();
+
+ if (result == 1) Log.Warning($"【手动添加调度任务】任务号:{taskRT.TaskId},{JsonConvert.SerializeObject(taskRT)}");
+
+ }
+ catch (DbUpdateException e)
+ {
+ MessageBox.Show($"发生了预期之外的错误:{e.Message}(错误代码:TVM000002)");
+ }
+
+ LoadTaskGrid();
+
+ }
+
+
+
+ ///
+ /// 站点信息初始化
+ ///
+ void LocationInitialize()
+ {
+ //Rows = new List();
+ //Columns = new List();
+ //Floors = new List();
+
+ //RowCount = int.Parse(ConfigurationManager.AppSettings["Row"]);
+ //for (int i = 1; i <= RowCount; i++)
+ //{
+ // Rows.Add(i);
+ //}
+ //ColumnCount = int.Parse(ConfigurationManager.AppSettings["Column"]);
+ //for (int i = 1; i <= ColumnCount; i++)
+ //{
+ // Columns.Add(i);
+ //}
+ //FloorCount = int.Parse(ConfigurationManager.AppSettings["Floor"]);
+ //for (int i = 1; i <= FloorCount; i++)
+ //{
+ // Floors.Add(i);
+ //}
+
+ SourceLocations.Clear();
+
+ foreach (var item in CircleRGVsViewModel.route)
+ {
+ SourceLocations.Add(item.Key);
+ }
+
+ }
+
+ ///
+ /// 取货站点对应放货站点
+ ///
+ [RelayCommand]
+ void SourceToTarget()
+ {
+ try
+ {
+ SelectedTargetLocation = CircleRGVsViewModel.route[SelectedSourceLocation];
+ }
+ catch (Exception)
+ {
+
+ }
+
+ }
+
+
+ ///
+ /// 下发测试任务
+ ///
+ [RelayCommand]
+ void SendRGVTest()
+ {
+ if (MessageBox.Show("此操作会向环穿地面站PLC直接写入命令!是否继续?", "", MessageBoxButton.YesNo) != MessageBoxResult.Yes)
+ {
+ return;
+ }
+
+ CircleRGVStationCommand circleRGVStationCommand = new CircleRGVStationCommand()
+ {
+ Write_DeviceNumber = SelectedRGVNumber,
+ Write_TaskNumber = SqlHelper.GetTaskIdByManualGeneration(),
+ Write_TaskType = TestingTaskTypeIndex + 1,
+ Write_SourceLocation = SelectedSourceLocation,
+ Write_TargetLocation = SelectedTargetLocation,
+ };
+
+ CircleRGVsViewModel.SendRGVStationCommand(circleRGVStationCommand);
+
+ Log.Information($"【环穿下发任务测试】直接向地面站下发任务:{JsonConvert.SerializeObject(circleRGVStationCommand)}");
+
+ SqlHelper.NewEventLog($"向地面站PLC直接写入测试任务:任务号:{circleRGVStationCommand.Write_TaskNumber}", "USER");
+
+ IsTopDrawerOpen = false;
+
+ }
+
+
+ ///
+ /// 清空选择项
+ ///
+ [RelayCommand]
+ void TestClear()
+ {
+ SelectedRGVNumber = 0;
+ SelectedSourceLocation = 0;
+ SelectedTargetLocation = 0;
+ }
+
+
+ ///
+ /// 新任务输入校验
+ ///
+ public void InputCheck()
+ {
+ //跨巷道使用
+ if (string.IsNullOrEmpty(SelectedSourceLocation.ToString().Trim()))
+ {
+ MessageBox.Show("请选择取货站点!");
+ return;
+ }
+ if (string.IsNullOrEmpty(SelectedTargetLocation.ToString().Trim()))
+ {
+ MessageBox.Show("请选择目标站点!");
+ return;
+
+ }
+
+
+ }
+
+ Action action;
+
+ //[RelayCommand]
+ void TaskFinishHandler()
+ {
+ InputDialog inputDialog = new InputDialog();
+ inputDialog.ShowDialog();
+
+ action = TaskFinish;
+ }
+
+ void TaskCancelHandler()
+ {
+ InputDialog inputDialog = new InputDialog();
+ inputDialog.ShowDialog();
+
+ action = TaskDelete;
+ }
+
+ void UpdateTaskStateToReadyHandler()
+ {
+ InputDialog inputDialog = new InputDialog();
+ inputDialog.ShowDialog();
+
+ action = UpdateTaskStateToReady;
+ }
+
+
+ ///
+ /// 手动完成任务
+ ///
+ [RelayCommand]
+ void TaskFinish(string taskId)
+ {
+ using var context = new AppDbContext();
+
+ var task = context.Set()
+ .Where(t => t.TaskId == taskId)
+ .FirstOrDefault();
+
+ if (task == null)
+ {
+ MessageBox.Show("获取任务号错误!自动移除该任务");
+
+ context.Database
+ .ExecuteSqlInterpolated($"DELETE FROM TASK WHERE TASKID={taskId}");
+
+ context.SaveChanges();
+
+ return;
+ }
+
+
+ string taskType = "";
+
+ switch (task.TaskType)
+ {
+ case 10:
+ taskType = "实垛";
+ break;
+ case 11:
+ taskType = "空托";
+ break;
+ default:
+ break;
+ }
+
+ if (MessageBox.Show($"确认人工完成任务号:{taskId}的任务?\r\n(错误的操作时机可能会导致生成空任务)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ task.TaskState = TaskStateCode.Task_Finish_Manual;
+
+ if (context.SaveChanges() == 1)
+ {
+ Log.Information($"【人工操作】手动完成任务,任务号:{taskId}");
+
+ SqlHelper.NewEventLog($"人工完成{taskType}任务:{taskId}", "USER");
+ }
+
+ }
+
+ LoadTaskGrid();
+
+ }
+ ///
+ /// 手动删除(取消)任务
+ ///
+ [RelayCommand]
+ void TaskDelete(string taskId)
+ {
+ using var context = new AppDbContext();
+
+ var task = context.Set()
+ .Where(t => t.TaskId == taskId)
+ .FirstOrDefault();
+
+ if (task == null)
+ {
+ MessageBox.Show("获取任务号错误!自动移除该任务");
+
+ context.Database
+ .ExecuteSqlInterpolated($"DELETE FROM TASK WHERE TASKID={taskId}");
+
+ context.SaveChanges();
+
+ return;
+ }
+
+
+ string taskType = "";
+
+ switch (task.TaskType)
+ {
+ case 10:
+ taskType = "实垛";
+ break;
+ case 11:
+ taskType = "空托";
+ break;
+ default:
+ break;
+ }
+
+ if (MessageBox.Show($"确认人工取消任务号:{taskId}的任务?\r\n(错误的操作时机可能会导致生成空任务)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ task.TaskState = TaskStateCode.Task_Finish_Cancel;
+
+ if (context.SaveChanges() == 1)
+ {
+ Log.Information($"【人工操作】手动取消任务,任务号:{taskId}");
+
+ SqlHelper.NewEventLog($"人工取消{taskType}任务:{taskId}", "USER");
+ }
+
+ }
+
+ LoadTaskGrid();
+
+
+ }
+
+
+ ///
+ /// 当向环穿下发任务失败时,可以选择重新下发
+ /// 只能在调度状态为【环穿-待执行】时可用
+ ///
+ ///
+ [RelayCommand]
+ void UpdateTaskStateToReady(string taskId)
+ {
+ using var context = new AppDbContext();
+
+ var task = context.Set()
+ .Where(t => t.TaskId == taskId && t.ScheduleState == ScheduleStateCode.Trans_CircleRGV_Ready)
+ .FirstOrDefault();
+
+ if (task == null)
+ {
+ MessageBox.Show("设备运行时的任务无法重下!");
+ return;
+ }
+
+ if (MessageBox.Show($"确认将任务:{taskId}的任务状态更改为【待执行】?\r\n此操作会重新下发当前任务(仅在环穿调度状态为【环穿-待执行】时生效)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ task.TaskState = TaskStateCode.Task_Ready;
+
+ if (context.SaveChanges() == 1)
+ {
+ Log.Information($"【人工操作】重新下发任务,任务号:{taskId}");
+
+ SqlHelper.NewEventLog($"人工重下任务:{taskId}", "USER");
+ }
+
+ }
+
+ LoadTaskGrid();
+
+ }
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/DbViews/TaskHistoryDbViewModel.cs b/WPFWCSDemo/ViewModels/DbViews/TaskHistoryDbViewModel.cs
new file mode 100644
index 0000000..8fd08d0
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/DbViews/TaskHistoryDbViewModel.cs
@@ -0,0 +1,641 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+
+namespace WPFWCSDemo.ViewModels.DbViews
+{
+ public partial class TaskHistoryDbViewModel : ObservableObject
+ {
+ public TaskHistoryDbViewModel()
+ {
+ TaskHistory = new ObservableCollection();
+ Pages = new ObservableCollection();
+
+ DateStart = DateTime.Now.AddDays(-1).ToString(TimeFormat.stringFormatDateOnly);
+ TimeStart = DateTime.Now.AddDays(-1).ToString("HH:mm");
+ DateEnd = DateTime.Now.ToString(TimeFormat.stringFormatDateOnly);
+ TimeEnd = DateTime.Now.ToString("HH:mm");
+
+ LoadTaskHistory(1);
+
+ LoadColumnName();
+
+
+ PageInput = 1;
+ PageCurrent = 1;
+ PageInfo = $"当前 {PageCurrent} 页";
+ DynamicPage(PageCurrent);
+ }
+
+
+
+ ///
+ /// false-表示默认表数据集 true-表示查询后的表数据集
+ ///
+ bool b;
+
+ ///
+ /// 历史表数据
+ ///
+ [ObservableProperty]
+ ObservableCollection _taskHistory;
+
+ ///
+ /// 起始日期
+ ///
+ [ObservableProperty]
+ string? _dateStart;
+ ///
+ /// 起始时间
+ ///
+ [ObservableProperty]
+ string? _timeStart;
+ ///
+ /// 结束日期
+ ///
+ [ObservableProperty]
+ string? _dateEnd;
+ ///
+ /// 结束时间
+ ///
+ [ObservableProperty]
+ string? _timeEnd;
+ ///
+ /// 默认值-起始日期
+ ///
+ [ObservableProperty]
+ string? _txtDateStart;
+ ///
+ /// 默认值-起始时间
+ ///
+ [ObservableProperty]
+ string? _txtTimeStart;
+ ///
+ /// 默认值-结束日期
+ ///
+ [ObservableProperty]
+ string? _txtDateEnd;
+ ///
+ /// 默认值-结束时间
+ ///
+ [ObservableProperty]
+ string? _txtTimeEnd;
+
+
+ ///
+ /// 查询字段选择项集合
+ ///
+ [ObservableProperty]
+ ObservableCollection _columnList = new ObservableCollection();
+
+ ///
+ /// 查询字段名
+ ///
+ [ObservableProperty]
+ string _columnName;
+
+ ///
+ /// 查询字段名
+ ///
+ Dictionary columnDic = new Dictionary();
+
+ ///
+ /// 查询关键词
+ ///
+ [ObservableProperty]
+ string _keywords;
+
+
+
+
+ ///
+ /// 加载/重载表数据
+ ///
+ /// 页数
+ void LoadTaskHistory(int page)
+ {
+ b = false;
+
+ TaskHistory.Clear();
+
+ DataTable? dtCount = SqlHelper.ExecuteTable("SELECT * FROM TASK_HISTORY_VIEW ORDER BY 结束时间 DESC");
+
+ DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM TASK_HISTORY_VIEW ORDER BY 结束时间 DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ new SqlParameter("@Rows", page - 1));
+
+ var datas = dt.Rows;
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in datas)
+ {
+ TaskHistory t = new TaskHistory();
+
+ t.JobId = data["环穿编号"].ToString();
+ t.TaskId = data["任务号"].ToString();
+ //t.PalletId = data["PalletId"].ToString();
+ t.SourceLocation = data["源站点"].ToString();
+ t.TargetLocation = data["目标站点"].ToString();
+ t.TaskType = data["任务类型"].ToString();
+ t.TaskState = data["任务状态"].ToString();
+ t.ScheduleState = data["调度状态"].ToString();
+ //t.ReportState = data["取货状态"].ToString();
+ t.CreateTime = Convert.ToDateTime(data["生成时间"]);
+ t.ScheduleTime = Convert.ToDateTime(data["调度时间"]);
+ t.FinishTime = Convert.ToDateTime(data["结束时间"]);
+
+
+ //数据结果
+ TaskHistory.Add(t);
+
+ }
+
+ UpdatePageInfo(dtCount, page);
+
+ }
+ ///
+ /// 加载/重载表数据---指定数据集
+ ///
+ void LoadTaskHistory(DataTable dt)
+ {
+ TaskHistory.Clear();
+ var datas = dt.Rows;
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in datas)
+ {
+ TaskHistory t = new()
+ {
+ JobId = data["环穿编号"].ToString(),
+ TaskId = data["任务号"].ToString(),
+ //t.PalletId = data["PalletId"].ToString(),
+ SourceLocation = data["源站点"].ToString(),
+ TargetLocation = data["目标站点"].ToString(),
+ TaskType = data["任务类型"].ToString(),
+ TaskState = data["任务状态"].ToString(),
+ ScheduleState = data["调度状态"].ToString(),
+ //ReportState = data["取货状态"].ToString(),
+ CreateTime = Convert.ToDateTime(data["生成时间"]),
+ ScheduleTime = Convert.ToDateTime(data["调度时间"]),
+ FinishTime = Convert.ToDateTime(data["结束时间"]),
+ };
+
+ //数据结果
+ TaskHistory.Add(t);
+ }
+
+ }
+
+
+
+ ///
+ /// 加载可选的搜索字段
+ ///
+ void LoadColumnName()
+ {
+ //下拉框选项填充
+ ColumnList.Clear();
+ ColumnList.Add("环穿编号");
+ ColumnList.Add("任务号");
+ //ColumnList.Add("托盘号");
+ ColumnList.Add("任务类型");
+ ColumnList.Add("源站点");
+ ColumnList.Add("目标站点");
+ ColumnList.Add("任务状态");
+ ColumnList.Add("生成时间");
+ ColumnList.Add("调度时间");
+ ColumnList.Add("完成时间");
+
+ //列名映射
+ columnDic.Clear();
+ columnDic.Add("环穿编号", "环穿编号");
+ columnDic.Add("任务号", "任务号");
+ //columnDic.Add("托盘号", "PalletId");
+ columnDic.Add("任务类型", "任务类型");
+ columnDic.Add("源站点", "源站点");
+ columnDic.Add("目标站点", "目标站点");
+ columnDic.Add("任务状态", "任务状态");
+ columnDic.Add("生成时间", "生成时间");
+ columnDic.Add("调度时间", "调度时间");
+ columnDic.Add("完成时间", "完成时间");
+ }
+
+
+ ///
+ /// 查询指令获取显示结果
+ ///
+ /// 页数
+ [RelayCommand]
+ void Query(string num)
+ {
+ b = true;
+
+ TaskHistory.Clear();
+
+ DataTable? dt;
+
+ DataTable? dtCount;
+
+ if (!DateStringFormat())
+ {
+ return;
+ }
+
+ try
+ {
+ //搜索条件为空或其他
+ if (!string.IsNullOrEmpty(ColumnName) && !string.IsNullOrEmpty(Keywords.Trim()))
+ {
+ dtCount = SqlHelper.ExecuteTable(
+ $"SELECT * FROM TASK_HISTORY_VIEW WHERE {ColumnName} LIKE @Keywords AND 结束时间>=@FinishTime1 AND 结束时间<@FinishTime2 ORDER BY 结束时间 DESC",
+ new SqlParameter("@Keywords", $"%{Keywords.Trim()}%"),
+ new SqlParameter("@FinishTime1", dateTimeStart),
+ new SqlParameter("@FinishTime2", dateTimeEnd)
+ );
+
+ dt = SqlHelper.ExecuteTable(
+ $"SELECT * FROM TASK_HISTORY_VIEW WHERE {ColumnName} LIKE @Keywords AND 结束时间>=@FinishTime1 AND 结束时间<@FinishTime2 ORDER BY 结束时间 DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ new SqlParameter("@Keywords", $"%{Keywords.Trim()}%"),
+ new SqlParameter("@FinishTime1", dateTimeStart),
+ new SqlParameter("@FinishTime2", dateTimeEnd),
+ new SqlParameter("@Rows", int.Parse(num) - 1)
+ );
+ }
+ else
+ {
+ dtCount = SqlHelper.ExecuteTable(
+ $"SELECT * FROM TASK_HISTORY_VIEW WHERE 结束时间>=@FinishTime1 AND 结束时间<@FinishTime2 ORDER BY 结束时间 DESC",
+ new SqlParameter("@FinishTime1", dateTimeStart),
+ new SqlParameter("@FinishTime2", dateTimeEnd)
+ );
+
+ dt = SqlHelper.ExecuteTable(
+ $"SELECT * FROM TASK_HISTORY_VIEW WHERE 结束时间>=@FinishTime1 AND 结束时间<@FinishTime2 ORDER BY 结束时间 DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ new SqlParameter("@FinishTime1", dateTimeStart),
+ new SqlParameter("@FinishTime2", dateTimeEnd),
+ new SqlParameter("@Rows", int.Parse(num) - 1)
+ );
+ }
+
+ LoadTaskHistory(dt);
+
+ UpdatePageInfo(dtCount, num);
+ }
+ catch (Exception)
+ {
+
+ }
+
+
+
+ }
+
+
+
+ ///
+ /// 重置选择
+ ///
+ [RelayCommand]
+ void Clear()
+ {
+ ColumnName = string.Empty;
+ Keywords = string.Empty;
+
+ TaskHistory.Clear();
+ LoadTaskHistory(1);
+
+ }
+
+
+ //---------------------------------时间字符串格式化对象---------------------------------
+ DateTime dateTimeStart;
+
+ DateTime dateTimeEnd;
+
+ ///
+ /// 日期格式处理
+ ///
+ /// 格式是否正确 true-正确 false-错误
+ bool DateStringFormat()
+ {
+ //处理字符串格式,规范字符串类型的时间值
+ bool b = DateTime.TryParse($"{DateStart} {TimeStart}", out dateTimeStart);
+ bool b1 = DateTime.TryParse($"{DateEnd} {TimeEnd}", out dateTimeEnd);
+
+ if (!b || !b1)
+ {
+ MessageBox.Show("时间格式错误!");
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ //-----------------------------------------页面跳转/统计相关-----------------------------------------
+ //-----------------------------------------页面跳转/统计相关-----------------------------------------
+
+
+ ///
+ /// 每页条数
+ ///
+ const int countPerPage = 10;
+ ///
+ /// 总数据条数-显示文本
+ ///
+ [ObservableProperty]
+ string _dataCount;
+ ///
+ /// 查询后的总条数
+ ///
+ [ObservableProperty]
+ int _dataCountNumber;
+ ///
+ /// 总页数
+ ///
+ [ObservableProperty]
+ int _pageCount;
+ ///
+ /// 手动输入页数
+ ///
+ [ObservableProperty]
+ int _pageInput;
+ ///
+ /// 鼠标需要点击的页面跳转按钮值
+ ///
+ [ObservableProperty]
+ int _pageSelected;
+ ///
+ /// 要显示页码的集合
+ ///
+ [ObservableProperty]
+ ObservableCollection _pages;
+
+ ///
+ /// 当前页
+ ///
+ [ObservableProperty]
+ int _pageCurrent;
+ ///
+ /// 当前页信息-显示文本
+ ///
+ [ObservableProperty]
+ string _pageInfo;
+
+
+
+ ///
+ /// 点击页码至指定页
+ ///
+ [RelayCommand]
+ void PageClick(string pageNumber)
+ {
+ JumpToPage(int.Parse(pageNumber));
+
+ //MessageBox.Show(pageNumber.ToString());
+ }
+
+
+ ///
+ /// 动态更新页数-下方显示具体X-X页
+ ///
+ /// 跳转后的页数
+ void DynamicPage(int pageCurrent)
+ {
+ //设置最多显示5页按钮
+ Pages.Clear();
+
+ //总页数小于8-显示1-X页
+ if (PageCount < 8 && pageCurrent < 8)
+ {
+ for (int i = 1; i < PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+
+ //总页数大于等于8
+ else
+ {
+ //距离尾页多于3页
+ if (PageCount - pageCurrent >= 3)
+ {
+ //1---显示前7页
+ if (pageCurrent < 8)
+ {
+ for (int i = 1; i < 8; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ else
+ {
+ //显示当前页的前3和后3页码
+ for (int i = pageCurrent - 3; i <= pageCurrent + 3; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+
+ }
+ //距离尾页是否少于3页---显示尾页前7页
+ else
+ {
+ if (PageCount - pageCurrent <= 2)
+ {
+ for (int i = PageCount - 6; i <= PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ }
+ }
+ }
+
+
+ ///
+ /// 获取数据集的总条数和页码数,更新属性
+ ///
+ ///
+ /// 当前页
+ void UpdatePageInfo(DataTable dt, int pageCurrent)
+ {
+ //总数据条数
+ DataCountNumber = dt.Rows.Count;
+
+ //文本显示
+ DataCount = $"共 {DataCountNumber} 条";
+
+ //总页数
+ if (DataCountNumber % countPerPage == 0)
+ {
+ PageCount = DataCountNumber / countPerPage;
+ }
+ else
+ {
+ PageCount = DataCountNumber / countPerPage + 1;
+ }
+
+ PageCurrent = pageCurrent;
+
+ DynamicPage(pageCurrent);
+ }
+ void UpdatePageInfo(DataTable dt, string pageCurrent)
+ {
+ //总数据条数
+ DataCountNumber = dt.Rows.Count;
+
+ //文本显示
+ DataCount = $"共 {DataCountNumber} 条";
+
+ //总页数
+ if (DataCountNumber % countPerPage == 0)
+ {
+ PageCount = DataCountNumber / countPerPage;
+ }
+ else
+ {
+ PageCount = DataCountNumber / countPerPage + 1;
+ }
+
+ PageCurrent = int.Parse(pageCurrent);
+
+ DynamicPage(int.Parse(pageCurrent));
+ }
+
+
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+
+
+ ///
+ /// 跳转至指定页
+ ///
+ [RelayCommand]
+ void JumpPageClick(string pageNumber)
+ {
+ try
+ {
+ if (int.Parse(pageNumber) > PageCount)
+ {
+ MessageBox.Show("不能超过最大页码数!");
+ return;
+ }
+ if (int.Parse(pageNumber) < 1)
+ {
+ MessageBox.Show("请使用正确页码数查询!");
+ return;
+ }
+
+ JumpToPage(int.Parse(pageNumber));
+
+ }
+ catch (Exception)
+ {
+ Log.Warning("【瞎β操作】查询历史记录时,跳转页面输入错误!");
+ }
+
+ }
+
+ ///
+ /// 前页
+ ///
+ [RelayCommand]
+ void PageBefore()
+ {
+ if (PageCurrent == 1) return;
+
+ PageCurrent -= 1;
+
+ JumpToPage(PageCurrent);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 后一页
+ ///
+ [RelayCommand]
+ void PageNext()
+ {
+ if (PageCurrent == PageCount) return;
+
+ PageCurrent += 1;
+
+ JumpToPage(PageCurrent);
+
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 首页
+ ///
+ [RelayCommand]
+ void PageFirst()
+ {
+ PageCurrent = 1;
+
+ JumpToPage(PageCurrent);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 尾页
+ ///
+ [RelayCommand]
+ void PageLast()
+ {
+ if (PageCurrent == PageCount) return;
+
+ JumpToPage(PageCount);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+
+ ///
+ /// 输入页码---跳转到指定页
+ ///
+ ///
+ void JumpToPage(int pageNumber)
+ {
+ //获取指定页数从具体第几条数据开始计数
+ int index = (pageNumber - 1) * 10 + 1;
+
+ if (b == false)
+ {
+ //默认数据集条件下跳转
+ LoadTaskHistory(index);
+ }
+ else
+ {
+ //查询之后的数据集条件下跳转
+ Query(index.ToString());
+ }
+
+ if (pageNumber <= PageCount)
+ {
+ PageCurrent = pageNumber;
+ PageInfo = $"当前 {pageNumber} 页";
+ }
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/DevicesNavigationViewModel.cs b/WPFWCSDemo/ViewModels/DevicesNavigationViewModel.cs
new file mode 100644
index 0000000..fa2d11e
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/DevicesNavigationViewModel.cs
@@ -0,0 +1,66 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class DevicesNavigationViewModel:ObservableObject
+ {
+ private readonly Frame _navigationFrame;
+ public DevicesNavigationViewModel(Frame navigationFrame)
+ {
+ _navigationFrame = navigationFrame;
+ }
+
+ ///
+ /// 打开设备清单
+ ///
+ [RelayCommand]
+ void OpenDevicePage()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\Devices\\DeviceListView.xaml", UriKind.Relative));
+ }
+
+ ///
+ /// 打开堆垛机窗口
+ ///
+ [RelayCommand]
+ void OpenStackerPage()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\Devices\\StackersView.xaml", UriKind.Relative));
+ }
+
+ ///
+ /// 打开输送机窗口
+ ///
+ [RelayCommand]
+ void OpenConvPage()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\Devices\\ConvsView.xaml", UriKind.Relative));
+ }
+
+ ///
+ /// 打开提升机窗口
+ ///
+ [RelayCommand]
+ void OpenLiftPage()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\Devices\\LiftsView.xaml", UriKind.Relative));
+ }
+
+ ///
+ /// 打开RGV窗口
+ ///
+ [RelayCommand]
+ void OpenRGVPage()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\Devices\\RGVsView.xaml", UriKind.Relative));
+ }
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/DevicesViewModel.cs b/WPFWCSDemo/ViewModels/DevicesViewModel.cs
new file mode 100644
index 0000000..53a2170
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/DevicesViewModel.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public class DevicesViewModel
+ {
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/HelperViewModel.cs b/WPFWCSDemo/ViewModels/HelperViewModel.cs
new file mode 100644
index 0000000..af94775
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/HelperViewModel.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace WPFWCSDemo.ViewModels
+{
+ class HelperViewModel
+ {
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/LineManagementViewModel.cs b/WPFWCSDemo/ViewModels/LineManagementViewModel.cs
new file mode 100644
index 0000000..bac98d1
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/LineManagementViewModel.cs
@@ -0,0 +1,141 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.ObjectModel;
+using System.Drawing;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using WPFWCSDemo.Data;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class LineManagementViewModel:ObservableObject
+ {
+ public LineManagementViewModel(Window window)
+ {
+ LineManagementDialog = window;
+
+ Caption = "输送线管理";
+
+ Enables = new ObservableCollection();
+
+ InitializeStyle();
+ }
+
+
+ ///
+ /// 当前页面
+ ///
+ [ObservableProperty]
+ string _caption;
+
+ ///
+ /// 当前页面
+ ///
+ [ObservableProperty]
+ Window _lineManagementDialog;
+
+ ///
+ /// 当前页面
+ ///
+ [ObservableProperty]
+ Color _btnColor;
+
+
+ [RelayCommand]
+ void Accept(Window window)
+ {
+ window.Close();
+ }
+
+
+ [ObservableProperty]
+ ObservableCollection _enables;
+
+ [ObservableProperty]
+ int _e1009;
+ [ObservableProperty]
+ int _e1010;
+ [ObservableProperty]
+ int _e1011;
+ [ObservableProperty]
+ int _e1012;
+
+
+ [ObservableProperty]
+ int _e1002;
+ [ObservableProperty]
+ int _e1004;
+ [ObservableProperty]
+ int _e1006;
+
+
+ [RelayCommand]
+ void StateChange(string targetLocation)
+ {
+ var context = new AppDbContext();
+
+ var res = context.LineState
+ .Where(a => a.Target == int.Parse(targetLocation))
+ .ToList();
+
+ if (res == null) return;
+
+ for (int i = 0; i < res.Count; i++)
+ {
+ if (res[i].IsEnable == 0)
+ {
+ if (MessageBox.Show($"确认要恢复{targetLocation}输送口允许进垛吗?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ res[i].IsEnable = 1;
+ }
+ }
+ else
+ {
+ if (MessageBox.Show($"确认要禁止{targetLocation}输送口进垛吗?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ res[i].IsEnable = 0;
+ }
+ }
+ }
+
+ context.SaveChanges();
+
+ InitializeStyle();
+
+ }
+
+ ///
+ /// 按钮样式初始化
+ ///
+ void InitializeStyle()
+ {
+ var context = new AppDbContext();
+
+ var results = context.LineState
+ .Select(a=>a.IsEnable)
+ .ToList();
+
+ Enables.Clear();
+
+ foreach (var result in results)
+ {
+ Enables.Add(result);
+ }
+
+ E1009 = Enables[1];
+ E1010 = Enables[2];
+ E1011 = Enables[3];
+ E1012 = Enables[0];
+ E1002 = Enables[5];
+ E1004 = Enables[6];
+ E1006 = Enables[7];
+
+ }
+
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/LogViewModel.cs b/WPFWCSDemo/ViewModels/LogViewModel.cs
new file mode 100644
index 0000000..42d0846
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/LogViewModel.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection.Metadata;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+using System.Windows;
+using CommunityToolkit.Mvvm.ComponentModel;
+using System.Reactive.Linq;
+using System.Diagnostics;
+using System.Threading;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class LogViewModel : ObservableObject
+ {
+ public LogViewModel()
+ {
+ //更新(当日)日志
+ //Task.Run(() =>
+ //{
+
+ // while (true)
+ // {
+ // try
+ // {
+ // //获取存储日志的字符串
+ // Content = File.ReadAllText(dirPath + @"logs\2024-10-09\Debug.txt");
+
+ // Task.Delay(1000);
+ // }
+ // catch (Exception)
+ // {
+
+ // }
+
+ // }
+ //});
+
+ }
+
+
+ //存放日志文件路径
+ //readonly string dirPath = @"E:\VSProject\WPF\FT472\WPFWCSDemo\bin\Debug\net6.0-windows\";
+
+ //[ObservableProperty]
+ //string _content;
+
+
+ /*
+ #region 下拉框内容初始化
+ //月份选择下拉框
+ cbxMonth.Items.Clear();
+ cbxMonth.Items.Add("-请选择月份-");
+ cbxMonth.Items.Add("一月");
+ cbxMonth.Items.Add("二月");
+ cbxMonth.Items.Add("三月");
+ cbxMonth.Items.Add("四月");
+ cbxMonth.Items.Add("五月");
+ cbxMonth.Items.Add("六月");
+ cbxMonth.Items.Add("七月");
+ cbxMonth.Items.Add("八月");
+ cbxMonth.Items.Add("九月");
+ cbxMonth.Items.Add("十月");
+ cbxMonth.Items.Add("十一月");
+ cbxMonth.Items.Add("十二月");
+
+ //下拉框选择初始化
+ cbxMonth.SelectedIndex = 0;
+ cbxLogName.SelectedIndex = 0;
+
+ #endregion
+
+ }
+
+ ///
+ /// 实时日志【内容更新】事件触发
+ ///
+ ///
+ ///
+ private void txtLog_TextChanged(object sender, EventArgs e)
+ {
+ //【搜索】按钮打开当天日志时,令滚动条位于最下
+ txtLog.SelectionStart = txtLog.Text.Length;
+ txtLog.ScrollToCaret();
+ }
+
+
+ ///
+ /// 【月份】下拉框的值改变事件--→【日志】名称选择的下拉框也随之变化
+ ///
+ ///
+ ///
+ private void cbxMonth_TextChanged(object sender, EventArgs e)
+ {
+ //日志文件名选择下拉框
+ cbxLogName.Items.Clear();
+ //获取存放日志文件夹所有文件全路径
+ try
+ {
+ //尝试获取路径,否则报错
+ string[] name = Directory.GetDirectories(dirPath);
+ //添加到下拉框
+ cbxLogName.Items.Add("-请选择日志-");
+ for (int i = 0; i < name.Length; i++)
+ {
+ //从文件名筛选符合月份条件的项
+ if (Path.GetFileNameWithoutExtension(name[i]).Contains("-" + cbxMonth.SelectedIndex.ToString("00") + "-"))
+ {
+ //添加当月日志的文件名
+ cbxLogName.Items.Add(Path.GetFileNameWithoutExtension(name[i]));
+ }
+
+ }
+ cbxLogName.SelectedIndex = 0;
+ }
+ catch (Exception)
+ {
+ return;
+ }
+ }
+
+
+ ///
+ /// 【搜索】按钮
+ ///
+ ///
+ ///
+ private void btnSearch_Click(object sender, EventArgs e)
+ {
+ if (cbxMonth.SelectedIndex != 0 && cbxLogName.SelectedIndex == 0)
+ {
+ MessageBox.Show("请选择要查找历史日志的时间!");
+ return;
+ }
+ if (cbxMonth.SelectedIndex == 0 && cbxLogName.SelectedIndex == 0) return;
+ try
+ {
+ //判断选择的日志文件日期是否为当天
+ if (cbxLogName.Text.Equals(DateTime.Now.ToString("yyyy-MM-dd")))
+ {
+ //显示实时日志
+ txtLog.Visible = true;
+ }
+ else
+ {
+ if (cbxMonth.SelectedIndex == 0 && cbxLogName.SelectedIndex == 0) return;
+ //获取选中的路径文件内容
+ txtLogHistory.Text = File.ReadAllText(dirPath + cbxLogName.Text + @"/Info.log", Encoding.Default);
+ //隐藏实时日志---显示历史日志
+ txtLog.Visible = false;
+ }
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.Message);
+ return;
+ }
+
+ }
+
+
+ ///
+ /// 【取消/刷新】页面按钮
+ ///
+ ///
+ ///
+ private void btnCancel_Click(object sender, EventArgs e)
+ {
+ //【搜索】按钮打开当天日志时,令滚动条位于最下,相比根据【内容更新】事件触发此效果可能存在的时间间隔有观感提升
+ txtLog.SelectionStart = txtLog.Text.Length;
+ txtLog.ScrollToCaret();
+ //显示实时日志
+ txtLog.Visible = true;
+ }
+
+
+ ///
+ /// 打开当日的日志文档
+ ///
+ ///
+ ///
+ private void btnOpenFile_Click(object sender, EventArgs e)
+ {
+ //打开当日的日志文档
+ //Process.Start("notepad", dirPath + DateTime.Now.ToString("yyyy-MM-dd") + "/Info.log");
+ if (Directory.Exists(dirPath + DateTime.Now.ToString("yyyy-MM-dd")))
+ {
+ Process.Start(dirPath + DateTime.Now.ToString("yyyy-MM-dd"));
+ }
+ else
+ {
+ Process.Start(dirPath);
+ }
+ }
+ */
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/MainViewModel.cs b/WPFWCSDemo/ViewModels/MainViewModel.cs
new file mode 100644
index 0000000..d364ec6
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/MainViewModel.cs
@@ -0,0 +1,454 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using MaterialDesignThemes.Wpf;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Navigation;
+using System.Windows.Threading;
+using System.Xml.Linq;
+using WPFWCSDemo.Models;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.Schedules;
+using WPFWCSDemo.Schedules.CircleRGV;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.Views;
+using WPFWCSDemo.Views.CustomComponent;
+using WPFWCSDemo.Views.Devices;
+
+namespace WPFWCSDemo.ViewModels
+{
+ ///
+ /// 母窗体
+ public partial class MainViewModel : ObservableObject
+ {
+ ///
+ /// 用于监控请求值的定时器
+ ///
+ private readonly DispatcherTimer dispatcherTimer;
+
+ ///
+ /// 用于接收View中导航用的Frame控件,此项目中使用Frame作为导航母控件
+ ///
+ private readonly Frame _navigationFrame;
+
+ ///
+ public MainViewModel(Frame navigationFrame)
+ {
+ _menuBar = new ObservableCollection();
+ CreateMenu();
+
+ _navigationFrame = navigationFrame;
+
+
+ // 设置定时器属性
+ dispatcherTimer = new DispatcherTimer();
+ dispatcherTimer.Interval = TimeSpan.FromSeconds(1); // 设置时间间隔为1秒
+ dispatcherTimer.Tick += DispatcherTimer_Tick; // 添加事件处理程序
+ dispatcherTimer.Start(); // 启动计时器
+
+ //ScheduleTask();
+
+ }
+
+
+ ///
+ /// 定时执行的调度任务
+ ///
+ private static void ScheduleTask()
+ {
+
+ Task.Factory.StartNew(() =>
+ {
+ while (true)
+ {
+
+ // //更新任务状态
+ // CircleRGVSchedule.UpdateScheduleState();
+
+ //Excute.ExecuteTask();
+
+ //Update.UpdateDeviceNumber();
+
+ //Update.UpdateScheduleState();
+
+ //Generate.GenerateTask();
+
+ ////Common.RecordRequestValue();
+ //Log.Information($"-----------------设备调度-----------------");
+
+ // ////任务处理
+ // TaskFinishSchedule.TaskFinish();
+
+ // TaskFinishSchedule.TaskDelete();
+
+ // TaskFinishSchedule.TaskForSendFailedHandler();
+
+ // TaskFinishSchedule.TaskExceptionHandler();
+
+ // //RGV调度
+ // CircleRGVSchedule.GenerateTask();
+
+ // CircleRGVSchedule.ExecuteTask();
+
+ // Task.Delay(200).Wait();
+
+ }
+ }, TaskCreationOptions.LongRunning);
+
+
+ Task.Factory.StartNew(() =>
+ {
+ while (true)
+ {
+ //实时报警
+ AlarmViewModel.RealTimeAlarm();
+
+ Task.Delay(1000).Wait();
+ }
+ }, TaskCreationOptions.LongRunning);
+
+
+ //自动备份
+ //Task.Run(() =>
+ //{
+ // while (true)
+ // {
+ // GlobalTask.SqlBackupForTime();
+
+ // Task.Delay(TimeSpan.FromHours(5)).Wait();
+ // }
+ //});
+ }
+
+
+
+ ///
+ /// ListBox选择项
+ ///
+ [ObservableProperty]
+ MenuBar? _selectedMenuBar;
+
+ [ObservableProperty]
+ ObservableCollection _menuBar;
+
+ #region 输送口请求指示
+
+ [ObservableProperty]
+ bool _getRequest_1001;
+
+ [ObservableProperty]
+ bool _getRequest_1003;
+
+ [ObservableProperty]
+ bool _getRequest_1005;
+
+ [ObservableProperty]
+ bool _getRequest_1007;
+
+ [ObservableProperty]
+ bool _getRequest_1008;
+
+ [ObservableProperty]
+ bool _getRequest_1013;
+
+ [ObservableProperty]
+ bool _putRequest_1002;
+
+ [ObservableProperty]
+ bool _putRequest_1004;
+
+ [ObservableProperty]
+ bool _putRequest_1006;
+
+ [ObservableProperty]
+ bool _putRequest_1009;
+
+ [ObservableProperty]
+ bool _putRequest_1010;
+
+
+ [ObservableProperty]
+ int _permission_Station;
+
+ #endregion
+
+ #region 输送口请求 - 显隐性
+
+ [ObservableProperty]
+ Visibility _getRequest_LineA_Visible;
+
+ [ObservableProperty]
+ Visibility _getRequest_LineB_Visible;
+
+ [ObservableProperty]
+ Visibility _getRequest_LineC_Visible;
+
+ [ObservableProperty]
+ Visibility _getRequest_LineD_Visible;
+
+ [ObservableProperty]
+ Visibility _getRequest_LineAB_Visible;
+
+ [ObservableProperty]
+ Visibility _putRequest_LineB_Visible;
+
+ [ObservableProperty]
+ Visibility _getRequest_LineCD_Visible;
+
+ [ObservableProperty]
+ Visibility _putRequest_LineC_Visible;
+
+ #endregion
+
+ private void DispatcherTimer_Tick(object? sender, EventArgs e)
+ {
+ using CircleRGVStationState circleRGVStationState = CircleRGVsViewModel.GetCircleRGVStaionState();
+
+ if (circleRGVStationState == null) return;
+
+ GetRequest_1001 = circleRGVStationState.Read_GetRequest_1001;
+ GetRequest_1003 = circleRGVStationState.Read_GetRequest_1003;
+ GetRequest_1005 = circleRGVStationState.Read_GetRequest_1005;
+ GetRequest_1007 = circleRGVStationState.Read_GetRequest_1007;
+ GetRequest_1008 = circleRGVStationState.Read_GetRequest_1008;
+
+ GetRequest_1007 = circleRGVStationState.Read_GetRequest_1007;
+ GetRequest_1008 = circleRGVStationState.Read_GetRequest_1008;
+
+ GetRequest_1013 = circleRGVStationState.Read_GetRequest_1013;
+ PutRequest_1002 = circleRGVStationState.Read_PutRequest_1002;
+ PutRequest_1004 = circleRGVStationState.Read_PutRequest_1004;
+ PutRequest_1006 = circleRGVStationState.Read_PutRequest_1006;
+
+ PutRequest_1009 = circleRGVStationState.Read_PutRequest_1009;
+ PutRequest_1010 = circleRGVStationState.Read_PutRequest_1010;
+
+ Permission_Station = circleRGVStationState.Read_Permission;
+
+
+ }
+
+
+
+
+ bool b = false;
+
+ ///
+ /// ListBox按键导航
+ ///
+ ///
+ [RelayCommand]
+ void Navigation(string name)
+ {
+ if (string.IsNullOrEmpty(name)) return;
+
+ //【设置】子页导航
+ if (name == "SettingView")
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\Settings\\{name}.xaml", UriKind.Relative));
+ return;
+ }
+
+ try
+ {
+ if (name == nameof(AlarmView) || name == nameof(TaskView)
+ || name == nameof(AlarmHistoryView) || name == nameof(TaskHistoryView))
+ {
+ if (!SqlHelper.IsDBConnected())
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\BlankView.xaml", UriKind.Relative));
+
+ b = true;
+
+ return;
+ }
+ }
+ //导航页面
+ _navigationFrame.Navigate(new Uri($"Views\\{name}.xaml", UriKind.Relative));
+
+ }
+ catch
+ {
+
+ }
+
+
+ }
+
+ ///
+ /// 后退
+ ///
+ [RelayCommand]
+ void GoBack()
+ {
+ if (b)
+ {
+ //删除【连接错误页面】的导航记录
+ _navigationFrame.NavigationService.RemoveBackEntry();
+ b = false;
+ }
+
+ try
+ {
+ _navigationFrame.NavigationService.GoBack();
+ }
+ catch
+ {
+
+ }
+
+ }
+
+ ///
+ /// 前进
+ ///
+ [RelayCommand]
+ void GoForward()
+ {
+ try
+ {
+ _navigationFrame.NavigationService.GoForward();
+ }
+ catch
+ {
+
+ }
+
+ }
+
+ ///
+ /// 主页
+ ///
+ [RelayCommand]
+ void Home()
+ {
+ //主页面
+ _navigationFrame.Navigate(new Uri($"Views\\DataInfoView.xaml", UriKind.Relative));
+ }
+
+
+ public void TaskPage()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\TaskView.xaml", UriKind.Relative));
+ }
+
+ public void TaskHistoryPage()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\TaskHistoryView.xaml", UriKind.Relative));
+ }
+
+ public void AlarmPage()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\AlarmView.xaml", UriKind.Relative));
+ }
+
+
+
+ ///
+ /// 设备测试
+ ///
+ [RelayCommand]
+ void DeviceTest()
+ {
+ //ControllerView controllerView = new ControllerView();
+ //controllerView.ShowDialog(1);
+ }
+
+ ///
+ /// 顶部工具栏打开日志文件夹
+ ///
+ [RelayCommand]
+ void OpenLog()
+ {
+ string dirPath = @"D:\Logs";
+ if (Directory.Exists(dirPath))
+ {
+ Process.Start("explorer.exe",dirPath);
+ }
+
+ }
+
+ ///
+ /// 顶部工具栏打开设置页
+ ///
+ [RelayCommand]
+ void OpenSetting()
+ {
+ _navigationFrame.Navigate(new Uri($"Views\\Settings\\SettingView.xaml", UriKind.Relative));
+ }
+
+
+ ///
+ /// 输送线管理
+ ///
+ [RelayCommand]
+ void LineControl()
+ {
+ LineControlDialog dialog = new LineControlDialog();
+ dialog.ShowDialog();
+ }
+
+ ///
+ /// 打开操作手册
+ ///
+ [RelayCommand]
+ void Helper()
+ {
+ try
+ {
+ string dirPath = @"D:\滁州东鹏饮料二厂环穿WCS系统使用手册.doc";
+ string processPath = @"C:\Program Files\Microsoft Office\Office16\WINWORD.exe";
+ if (File.Exists(dirPath))
+ {
+ Process.Start(processPath,dirPath);
+ }
+ }
+ catch
+ {
+
+ }
+
+ }
+
+
+
+ ///
+ /// 导航菜单初始化
+ ///
+ void CreateMenu()
+ {
+ //生产类画面
+ MenuBar.Add(new MenuBar() { Icon = "Home", Title = "生产看板", NameSpace = nameof(DataInfoView) });
+ //MenuBar.Add(new MenuBar() { Icon = "MonitorScreenshot", Title = "生产监控", NameSpace = nameof(MonitorView) });
+ //MenuBar.Add(new MenuBar() { Icon = "MonitorDashboard", Title = "设备信息", NameSpace = nameof(DevicesNavigationView) });
+ MenuBar.Add(new MenuBar() { Icon = "MonitorDashboard", Title = "环穿状态", NameSpace = nameof(CircleRGVsView) });
+ //报表类画面
+ //MenuBar.Add(new MenuBar() { Icon = "Warehouse", Title = "库存信息", NameSpace = nameof(CargoView) });
+ MenuBar.Add(new MenuBar() { Icon = "AlarmLightOutline", Title = "实时报警", NameSpace = nameof(AlarmView) });
+ MenuBar.Add(new MenuBar() { Icon = "History", Title = "历史报警", NameSpace = nameof(AlarmHistoryView) });
+ MenuBar.Add(new MenuBar() { Icon = "ClipboardTextOutline", Title = "调度任务", NameSpace = nameof(Views.TaskView) });
+ MenuBar.Add(new MenuBar() { Icon = "ClipboardTextClockOutline", Title = "历史任务", NameSpace = nameof(TaskHistoryView) });
+ //其他
+ //MenuBar.Add(new MenuBar() { Icon = "Book", Title = "日志", NameSpace = nameof(LogView) });
+ //MenuBar.Add(new MenuBar() { Icon = "Tools", Title = "设置", NameSpace = nameof(SettingView) });
+ //MenuBar.Add(new MenuBar() { Icon = "CommentQuestionOutline", Title = "帮助", NameSpace = nameof(HelperView) });
+
+
+ }
+
+
+
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/MonitorViewModel.cs b/WPFWCSDemo/ViewModels/MonitorViewModel.cs
new file mode 100644
index 0000000..d5449ce
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/MonitorViewModel.cs
@@ -0,0 +1,138 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using WPFWCSDemo.Models;
+using WPFWCSDemo.Utilities;
+
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class MonitorViewModel : ObservableObject
+ {
+ public MonitorViewModel()
+ {
+ WarehouseLayout = new ObservableCollection();
+ CargoState = new ObservableCollection();
+ InitializeWarehouseLayout(LayersSelectedIndex);
+ }
+
+
+ ///
+ /// 货位信息
+ ///
+ [ObservableProperty]
+ ObservableCollection _warehouseLayout;
+
+ ///
+ /// 货位状态
+ ///
+ [ObservableProperty]
+ ObservableCollection _cargoState;
+
+
+ ///
+ /// 层数选择
+ ///
+ [ObservableProperty]
+ int _layersSelectedIndex;
+
+
+ ///
+ /// 货位状态绘图初始化
+ ///
+ private void InitializeWarehouseLayout(int layer)
+ {
+ WarehouseLayout.Clear();
+ CargoState.Clear();
+
+ double cellWidth = 36;
+ double cellHeight = 25;
+
+ DataTable dt = SqlHelper.ExecuteTable("SELECT STATUS FROM CARGOSPACE WHERE FLOOR=@Floor ORDER BY ROW ASC,[COLUMN] ASC ",
+ new System.Data.SqlClient.SqlParameter("@Floor", layer + 1));
+
+ foreach (DataRow item in dt.Rows)
+ {
+ Cargo cargo = new Cargo();
+ cargo.Status = int.Parse(item["Status"].ToString());
+
+ CargoState.Add(cargo);
+ }
+
+ for (int row = 0; row < 8; row++)
+ {
+ for (int col = 0; col < 22; col++)
+ {
+ WareHouseInfo wareHouseInfo = new WareHouseInfo();
+
+ wareHouseInfo.Tooltip = $"排: {row + 1}, 列: {col + 1}, 层: {layer + 1}";
+
+ if (CargoState.First().Status == 1)
+ {
+ //仓位空
+ wareHouseInfo.FillColor = Brushes.Silver;
+ }
+ else if (CargoState.First().Status == 2)
+ {
+ //仓位占用
+ wareHouseInfo.FillColor = Brushes.LawnGreen;
+ }
+ else if (CargoState.First().Status == 3)
+ {
+ //仓位盘点
+ wareHouseInfo.FillColor = Brushes.Orange;
+ }
+ else
+ {
+ //仓位异常
+ wareHouseInfo.FillColor = Brushes.Red;
+ }
+
+ CargoState.RemoveAt(0);
+
+ //设备排列图形间隔
+ wareHouseInfo.X = col * cellWidth + 1 + cellWidth;
+ //wareHouseInfo.Y = row * cellHeight;
+
+ //设置奇偶数排图形间隔
+ if (row % 2 == 0)
+ {
+ wareHouseInfo.Y = (row + (row * 1)) * cellHeight + 40;
+ }
+ else
+ {
+ wareHouseInfo.Y = (row + (row - 1) * 1) * cellHeight + 50;
+ }
+
+ //设置仓位图形缩放中心
+ wareHouseInfo.RenderCenter = new System.Drawing.Point((int)wareHouseInfo.X + (int)(cellWidth / 2 - 3), (int)wareHouseInfo.Y + (int)(cellWidth / 2 - 3));
+
+ WarehouseLayout.Add(wareHouseInfo);
+ }
+ }
+
+ }
+
+
+ ///
+ /// 点击层数切换库存显示
+ ///
+ [RelayCommand]
+ void LayersSelect()
+ {
+ InitializeWarehouseLayout(LayersSelectedIndex);
+ }
+
+
+
+ }
+
+
+}
diff --git a/WPFWCSDemo/ViewModels/Settings/AboutViewModel.cs b/WPFWCSDemo/ViewModels/Settings/AboutViewModel.cs
new file mode 100644
index 0000000..93d50f9
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/Settings/AboutViewModel.cs
@@ -0,0 +1,31 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Security.Policy;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+
+namespace WPFWCSDemo.ViewModels.Settings
+{
+ public partial class AboutViewModel:ObservableObject
+ {
+ [RelayCommand]
+ void WebNavigation()
+ {
+ string url = "http://www.yctd.cn/";
+
+ Uri uri = new Uri(url);
+
+ // 使用Process.Start打开默认浏览器
+ Process.Start(new ProcessStartInfo
+ {
+ FileName = uri.ToString(),
+ UseShellExecute = true
+ });
+ }
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/Settings/SettingViewModel.cs b/WPFWCSDemo/ViewModels/Settings/SettingViewModel.cs
new file mode 100644
index 0000000..3a1e649
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/Settings/SettingViewModel.cs
@@ -0,0 +1,71 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Xml.Linq;
+using WPFWCSDemo.Models;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.ViewModels.Settings;
+using WPFWCSDemo.Views.Settings;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class SettingViewModel : ObservableObject
+ {
+ private readonly Frame frame;
+ public SettingViewModel(Frame navigationFrame)
+ {
+ frame = navigationFrame;
+
+ Menu = new ObservableCollection();
+ CreateSettingMenu();
+
+ SkinViewModel.GetFrame(frame);
+
+ frame.Navigate(new Uri($"Views\\Settings\\SystemView.xaml", UriKind.Relative));
+ }
+
+
+ ///
+ /// 菜单选择项
+ ///
+ [ObservableProperty]
+ ObservableCollection _menu;
+
+
+ void CreateSettingMenu()
+ {
+ Menu.Add(new SettingMenu() { Icon = "Pencil", Title = "个性化", NameSpace = "SkinView"/*nameof(SkinView)*/ });
+ Menu.Add(new SettingMenu() { Icon = "Tools", Title = "系统设置", NameSpace = "SystemView" });
+ Menu.Add(new SettingMenu() { Icon = "ExclamationThick", Title = "关于", NameSpace = "AboutView" });
+ }
+
+ ///
+ /// 切换导航
+ ///
+ ///
+ [RelayCommand]
+ void SettingNavigate(SettingMenu menu)
+ {
+ try
+ {
+ frame.Navigate(new Uri($"Views\\Settings\\{menu.NameSpace}.xaml", UriKind.Relative));
+ }
+ catch
+ {
+
+ }
+
+ }
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/Settings/SkinViewModel.cs b/WPFWCSDemo/ViewModels/Settings/SkinViewModel.cs
new file mode 100644
index 0000000..42ae64d
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/Settings/SkinViewModel.cs
@@ -0,0 +1,77 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using MaterialDesignColors;
+using MaterialDesignColors.ColorManipulation;
+using MaterialDesignThemes.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace WPFWCSDemo.ViewModels.Settings
+{
+ public partial class SkinViewModel:ObservableObject
+ {
+ [ObservableProperty]
+ static Frame frame;
+
+ public IEnumerable Swatches { get; } = SwatchHelper.Swatches;
+
+
+ //深浅色切换
+ private bool _isDarkTheme;
+ public bool IsDarkTheme
+ {
+ get => _isDarkTheme;
+ set
+ {
+ if (SetProperty(ref _isDarkTheme, value))
+ {
+ ModifyTheme(theme => theme.SetBaseTheme(value ? Theme.Dark : Theme.Light));
+ }
+ }
+ }
+ //切换主题
+ private static void ModifyTheme(Action modificationAction)
+ {
+ var paletteHelper = new PaletteHelper();
+ ITheme theme = paletteHelper.GetTheme();
+
+ modificationAction?.Invoke(theme);
+
+ paletteHelper.SetTheme(theme);
+ }
+
+
+
+ private readonly PaletteHelper paletteHelper = new PaletteHelper();
+
+ ///
+ /// 改变颜色
+ ///
+ ///
+ [RelayCommand]
+ public void ChangeHue(object? obj)
+ {
+ var hue = (Color)obj!;
+
+ ITheme theme = paletteHelper.GetTheme();
+
+ theme.PrimaryLight = new ColorPair(hue.Lighten());
+ theme.PrimaryMid = new ColorPair(hue);
+ theme.PrimaryDark = new ColorPair(hue.Darken());
+
+ paletteHelper.SetTheme(theme);
+ }
+
+
+ public static void GetFrame(Frame navigationFrame)
+ {
+ frame = navigationFrame;
+ }
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/Settings/SystemViewModel.cs b/WPFWCSDemo/ViewModels/Settings/SystemViewModel.cs
new file mode 100644
index 0000000..5ff4d6b
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/Settings/SystemViewModel.cs
@@ -0,0 +1,389 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using MaterialDesignThemes.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using WPFWCSDemo.Models;
+using WPFWCSDemo.Schedules;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.Views;
+
+namespace WPFWCSDemo.ViewModels.Settings
+{
+ public partial class SystemViewModel:ObservableObject
+ {
+
+ ///
+ /// 选中删除任务数据
+ ///
+ [ObservableProperty]
+ bool _isTaskDataDelete;
+
+ ///
+ /// 选中删除报警数据
+ ///
+ [ObservableProperty]
+ bool _isAlarmDataDelete;
+
+ ///
+ /// 实垛A线显示文本
+ ///
+ [ObservableProperty]
+ string _lineAStr = "重置A线请求标志";
+ ///
+ /// 实垛B线显示文本
+ ///
+ [ObservableProperty]
+ string _lineBStr = "重置B线请求标志";
+ ///
+ /// 实垛C线显示文本
+ ///
+ [ObservableProperty]
+ string _lineCStr = "重置C线请求标志";
+ ///
+ /// 实垛D线显示文本
+ ///
+ [ObservableProperty]
+ string _lineDStr = "重置D线请求标志";
+ ///
+ /// 实垛AB线显示文本
+ ///
+ [ObservableProperty]
+ string _lineABStr = "重置AB线请求标志";
+ ///
+ /// 实垛CD线显示文本
+ ///
+ [ObservableProperty]
+ string _lineCDStr = "重置CD线请求标志";
+
+
+ ///
+ /// 是否限制实垛A线生成任务 0-解禁 1-禁止
+ ///
+ [ObservableProperty]
+ bool _lineAIsEnable = true;
+ ///
+ /// 是否限制实垛B线生成任务 0-解禁 1-禁止
+ ///
+ [ObservableProperty]
+ bool _lineBIsEnable = true;
+ ///
+ /// 是否限制实垛C线生成任务 0-解禁 1-禁止
+ ///
+ [ObservableProperty]
+ bool _lineCIsEnable = true;
+ ///
+ /// 是否限制实垛D线生成任务 0-解禁 1-禁止
+ ///
+ [ObservableProperty]
+ bool _lineDIsEnable = true;
+ ///
+ /// 是否限制空托AB线生成任务 0-解禁 1-禁止
+ ///
+ [ObservableProperty]
+ bool _lineABIsEnable = true;
+ ///
+ /// 是否限制空托CD线生成任务 0-解禁 1-禁止
+ ///
+ [ObservableProperty]
+ bool _lineCDIsEnable = true;
+
+ ///
+ /// A手动允许下发标志
+ ///
+ public static bool lineAIsEnable = true;
+ ///
+ /// B手动允许下发标志
+ ///
+ public static bool lineBIsEnable = true;
+ ///
+ /// C手动允许下发标志
+ ///
+ public static bool lineCIsEnable = true;
+ ///
+ /// D手动允许下发标志
+ ///
+ public static bool lineDIsEnable = true;
+ ///
+ /// AB手动允许下发标志
+ ///
+ public static bool lineABIsEnable = true;
+ ///
+ /// CD手动允许下发标志
+ ///
+ public static bool lineCDIsEnable = true;
+
+
+ ///
+ /// 手动备份当前数据库
+ ///
+ [RelayCommand]
+ void GetSqlDBBackup()
+ {
+ if (MessageBox.Show("确定创建备份文件吗(此操作会生成一份备份文件)?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+ {
+ SqlDatabaseMaintenance.SQLBackup();
+ }
+ else
+ {
+ MessageBox.Show("操作已取消");
+ }
+ }
+
+ ///
+ /// 清除近3个月之外所有任务记录(保留最近3个月内数据)
+ ///
+ [RelayCommand]
+ void DeleteDataOutOfTreeMouths()
+ {
+ if (MessageBox.Show("确定删除数据吗(此操作会保留最近3个月内的数据,且删除最近3个月之外的数据)?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+ {
+ SqlHelper.ExecuteNonQuery("DELETE FROM TASK_HISTORY WHERE FINISHTIME<@FinishTime",
+ new SqlParameter("@FinishTime", DateTime.Now.AddMonths(-3).ToString("yyyy-MM"))
+ );
+ }
+
+ }
+
+
+ ///
+ /// 调度任务备份
+ ///
+ [RelayCommand]
+ void TaskBackup()
+ {
+ if (MessageBox.Show("确定创建备份文件吗?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+ {
+ if (IsTaskDataDelete)
+ {
+ if (MessageBox.Show("将删除已备份的【调度任务历史记录】数据,是否继续?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+ {
+ SqlDatabaseMaintenance.SQLTaskBackup("Month", -6, IsTaskDataDelete);
+ }
+ else
+ {
+ MessageBox.Show("备份操作已取消");
+ }
+ }
+ else
+ {
+ //选择仅备份不删除数据
+ SqlDatabaseMaintenance.SQLTaskBackup("Month", -6, false);
+ }
+
+ }
+ }
+
+ ///
+ /// 历史报警备份
+ ///
+ [RelayCommand]
+ void AlarmBackup()
+ {
+ if (MessageBox.Show("确定创建备份文件吗?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+ {
+ if (IsAlarmDataDelete)
+ {
+ if (MessageBox.Show("将删除已备份的【报警历史记录】数据,是否继续?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
+ {
+ SqlDatabaseMaintenance.SQLAlarmBackup("Month", -6, IsAlarmDataDelete);
+ }
+ else
+ {
+ MessageBox.Show("备份操作已取消");
+ }
+ }
+ else
+ {
+ //选择仅备份不删除数据
+ SqlDatabaseMaintenance.SQLAlarmBackup("Month", -6, false);
+ }
+
+ }
+ }
+
+
+ ///
+ /// 货位初始化
+ ///
+ [RelayCommand]
+ void CargoInitialize()
+ {
+ string result = Microsoft.VisualBasic.Interaction.InputBox("Enter something:", "Input Dialog", "");
+ MessageBox.Show("You entered: " + result);
+ CargoTableInitialize.CargoSpaceInit(10,50,5);
+ }
+
+
+
+ ///
+ /// 手动控制输送线是否允许下发任务 true-允许 false-禁止
+ ///
+ /// 实垛:A,B,C,D 空托:AB,CD
+ [RelayCommand]
+ void LineIsEnabled(string lineName)
+ {
+ switch (lineName)
+ {
+ case "A":
+ if (LineAIsEnable)
+ {
+ if (MessageBox.Show("是否禁止A线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineAIsEnable = false;
+ lineAIsEnable = false;
+ LineAStr = "禁止下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineAStr}】", "USER");
+ }
+ }
+ else
+ {
+ if (MessageBox.Show("是否允许A线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineAIsEnable = true;
+ lineAIsEnable = true;
+ LineAStr = "允许下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineAStr}】", "USER");
+ }
+ }
+ break;
+ case "B":
+ if (LineBIsEnable)
+ {
+ if (MessageBox.Show("是否禁止B线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineBIsEnable = false;
+ lineBIsEnable = false;
+ LineBStr = "禁止下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineBStr}】", "USER");
+ }
+ }
+ else
+ {
+ if (MessageBox.Show("是否允许B线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineBIsEnable = true;
+ lineBIsEnable = true;
+ LineBStr = "允许下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineBStr}】", "USER");
+ }
+ }
+ break;
+ case "C":
+ if (LineCIsEnable)
+ {
+ if (MessageBox.Show("是否禁止C线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineCIsEnable = false;
+ lineCIsEnable = false;
+ LineCStr = "禁止下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineCStr}】", "USER");
+ }
+ }
+ else
+ {
+ if (MessageBox.Show("是否允许C线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineCIsEnable = true;
+ lineCIsEnable = true;
+ LineCStr = "允许下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineCStr}】", "USER");
+ }
+ }
+ break;
+ case "D":
+ if (LineDIsEnable)
+ {
+ if (MessageBox.Show("是否禁止D线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineDIsEnable = false;
+ lineDIsEnable = false;
+ LineDStr = "禁止下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineDStr}】", "USER");
+ }
+ }
+ else
+ {
+ if (MessageBox.Show("是否允许D线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineDIsEnable = true;
+ lineDIsEnable = true;
+ LineDStr = "允许下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineDStr}】", "USER");
+ }
+ }
+ break;
+ case "AB":
+ if (LineABIsEnable)
+ {
+ if (MessageBox.Show("是否禁止AB线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineABIsEnable = false;
+ lineABIsEnable = false;
+ LineABStr = "禁止下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineABStr}】", "USER");
+ }
+ }
+ else
+ {
+ if (MessageBox.Show("是否允许AB线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineABIsEnable = true;
+ lineABIsEnable = true;
+ LineABStr = "允许下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineABStr}】", "USER");
+ }
+ }
+ break;
+ case "CD":
+ if (LineCDIsEnable)
+ {
+ if (MessageBox.Show("是否禁止CD线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineCDIsEnable = false;
+ lineCDIsEnable = false;
+ LineCDStr = "禁止下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineCDStr}】", "USER");
+ }
+ }
+ else
+ {
+ if (MessageBox.Show("是否允许CD线生成任务?", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ LineCDIsEnable = true;
+ lineCDIsEnable = true;
+ LineCDStr = "允许下发";
+
+ SqlHelper.NewEventLog($"人工完成任务:{lineName}线切换为【{LineCDStr}】", "USER");
+ }
+ }
+ break;
+ }
+
+
+ }
+
+
+
+
+
+ }
+}
diff --git a/WPFWCSDemo/ViewModels/TaskHistoryViewModel.cs b/WPFWCSDemo/ViewModels/TaskHistoryViewModel.cs
new file mode 100644
index 0000000..9053f8f
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/TaskHistoryViewModel.cs
@@ -0,0 +1,673 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Data;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class TaskHistoryViewModel : ObservableObject
+ {
+ public TaskHistoryViewModel()
+ {
+ TaskHistory = new ObservableCollection();
+ Pages = new ObservableCollection();
+
+ DateStart = DateTime.Now.AddDays(-1).ToString(TimeFormat.stringFormatDateOnly);
+ TimeStart = DateTime.Now.AddDays(-1).ToString("HH:mm");
+ DateEnd = DateTime.Now.ToString(TimeFormat.stringFormatDateOnly);
+ TimeEnd = DateTime.Now.ToString("HH:mm");
+
+ LoadTaskHistory(1);
+
+ LoadColumnName();
+
+
+ PageInput = 1;
+ PageCurrent = 1;
+ PageInfo = $"当前 {PageCurrent} 页";
+ DynamicPage(PageCurrent);
+ }
+
+ ///
+ /// false-表示默认表数据集 true-表示查询后的表数据集
+ ///
+ bool b;
+
+ ///
+ /// 历史表数据
+ ///
+ [ObservableProperty]
+ ObservableCollection _taskHistory;
+
+ ///
+ /// 起始日期
+ ///
+ [ObservableProperty]
+ string? _dateStart;
+ ///
+ /// 起始时间
+ ///
+ [ObservableProperty]
+ string? _timeStart;
+ ///
+ /// 结束日期
+ ///
+ [ObservableProperty]
+ string? _dateEnd;
+ ///
+ /// 结束时间
+ ///
+ [ObservableProperty]
+ string? _timeEnd;
+ ///
+ /// 默认值-起始日期
+ ///
+ [ObservableProperty]
+ string? _txtDateStart;
+ ///
+ /// 默认值-起始时间
+ ///
+ [ObservableProperty]
+ string? _txtTimeStart;
+ ///
+ /// 默认值-结束日期
+ ///
+ [ObservableProperty]
+ string? _txtDateEnd;
+ ///
+ /// 默认值-结束时间
+ ///
+ [ObservableProperty]
+ string? _txtTimeEnd;
+
+
+ ///
+ /// 查询字段选择项集合
+ ///
+ [ObservableProperty]
+ ObservableCollection _columnList = new ObservableCollection();
+
+ ///
+ /// 查询字段名
+ ///
+ [ObservableProperty]
+ string _columnName;
+
+ ///
+ /// 查询字段名
+ ///
+ Dictionary columnDic = new Dictionary();
+
+ ///
+ /// 查询关键词
+ ///
+ [ObservableProperty]
+ string _keywords;
+
+
+
+
+ ///
+ /// 加载/重载表数据
+ ///
+ /// 页数
+ void LoadTaskHistory(int page)
+ {
+ b = false;
+
+ TaskHistory.Clear();
+
+ //DataTable? dtCount = SqlHelper.ExecuteTable("SELECT * FROM TASK_HISTORY ORDER BY CREATETIME DESC");
+ DataTable? dtCount = SqlHelper.ExecuteTable("SELECT * FROM TASK_HISTORY_VIEW ORDER BY 结束时间 DESC");
+
+ //DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM TASK_HISTORY ORDER BY CREATETIME DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM TASK_HISTORY_VIEW ORDER BY 结束时间 DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ new SqlParameter("@Rows",page - 1));
+
+ var datas = dt.Rows;
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in datas)
+ {
+ TaskHistory t = new TaskHistory();
+ //t.JobId = data["JobId"].ToString();
+ //t.TaskId = data["TaskId"].ToString();
+ ////t.PalletId = data["PalletId"].ToString();
+ //t.SourceLocation = data["SourceLocation"].ToString();
+ //t.TargetLocation = data["TargetLocation"].ToString();
+ //t.TaskType = data["TaskType"].ToString();
+ //t.TaskState = data["TaskState"].ToString();
+ //t.ScheduleState = data["ScheduleState"].ToString();
+ //t.ReportState = (int)data["ReportState"];
+ //t.CreateTime = data["CreateTime"].ToString();
+ //t.ScheduleTime = data["ScheduleTime"].ToString();
+ //t.FinishTime = data["FinishTime"].ToString();
+
+ t.JobId = data["环穿编号"].ToString();
+ t.TaskId = data["任务号"].ToString();
+ //t.PalletId = data["PalletId"].ToString();
+ t.SourceLocation = data["源站点"].ToString();
+ t.TargetLocation = data["目标站点"].ToString();
+ t.TaskType = data["任务类型"].ToString();
+ t.TaskState = data["任务状态"].ToString();
+ t.ScheduleState = data["调度状态"].ToString();
+ //t.ReportState = data["取货状态"].ToString();
+ t.CreateTime = Convert.ToDateTime(data["生成时间"]);
+ t.ScheduleTime = Convert.ToDateTime(data["调度时间"]);
+ t.FinishTime = Convert.ToDateTime(data["结束时间"]);
+
+
+ //数据结果
+ TaskHistory.Add(t);
+
+ }
+
+ UpdatePageInfo(dtCount, page);
+
+ }
+ ///
+ /// 加载/重载表数据---指定数据集
+ ///
+ void LoadTaskHistory(DataTable dt)
+ {
+ TaskHistory.Clear();
+ var datas = dt.Rows;
+
+ //遍历表中每行数据并初始化值
+ foreach (DataRow data in datas)
+ {
+ TaskHistory t = new()
+ {
+ //JobId = data["JobId"].ToString(),
+ //TaskId = data["TaskId"].ToString(),
+ ////PalletId = data["PalletId"].ToString(),
+ //SourceLocation = data["SourceLocation"].ToString(),
+ //TargetLocation = data["TargetLocation"].ToString(),
+ //TaskType = data["TaskType"].ToString(),
+ //TaskState = data["TaskState"].ToString(),
+ //ScheduleState = data["ScheduleState"].ToString(),
+ //ReportState = (int)data["ReportState"],
+ //CreateTime = data["CreateTime"].ToString(),
+ //ScheduleTime = data["ScheduleTime"].ToString(),
+ //FinishTime = data["FinishTime"].ToString()
+
+ JobId = data["环穿编号"].ToString(),
+ TaskId = data["任务号"].ToString(),
+ //t.PalletId = data["PalletId"].ToString(),
+ SourceLocation = data["源站点"].ToString(),
+ TargetLocation = data["目标站点"].ToString(),
+ TaskType = data["任务类型"].ToString(),
+ TaskState = data["任务状态"].ToString(),
+ ScheduleState = data["调度状态"].ToString(),
+ ReportState = data["取货状态"].ToString(),
+ CreateTime = Convert.ToDateTime(data["生成时间"]),
+ ScheduleTime = Convert.ToDateTime(data["调度时间"]),
+ FinishTime = Convert.ToDateTime(data["结束时间"]),
+ };
+
+ //数据结果
+ TaskHistory.Add(t);
+ }
+
+ }
+
+
+
+ ///
+ /// 加载可选的搜索字段
+ ///
+ void LoadColumnName()
+ {
+ //下拉框选项填充
+ ColumnList.Clear();
+ ColumnList.Add("环穿编号");
+ ColumnList.Add("任务号");
+ //ColumnList.Add("托盘号");
+ ColumnList.Add("任务类型");
+ ColumnList.Add("源站点");
+ ColumnList.Add("目标站点");
+ ColumnList.Add("任务状态");
+ ColumnList.Add("生成时间");
+ ColumnList.Add("调度时间");
+ ColumnList.Add("完成时间");
+
+ //列名映射
+ columnDic.Clear();
+ columnDic.Add("环穿编号", "环穿编号");
+ columnDic.Add("任务号", "任务号");
+ //columnDic.Add("托盘号", "PalletId");
+ columnDic.Add("任务类型", "任务类型");
+ columnDic.Add("源站点", "源站点");
+ columnDic.Add("目标站点", "目标站点");
+ columnDic.Add("任务状态", "任务状态");
+ columnDic.Add("生成时间", "生成时间");
+ columnDic.Add("调度时间", "调度时间");
+ columnDic.Add("完成时间", "完成时间");
+ }
+
+
+ ///
+ /// 查询指令获取显示结果
+ ///
+ /// 页数
+ [RelayCommand]
+ void Query(string num)
+ {
+ b = true;
+
+ TaskHistory.Clear();
+
+ DataTable? dt;
+
+ DataTable? dtCount;
+
+ if (!DateStringFormat())
+ {
+ return;
+ }
+
+ try
+ {
+ //搜索条件为空或其他
+ if (!string.IsNullOrEmpty(ColumnName) && !string.IsNullOrEmpty(Keywords.Trim()))
+ {
+ dtCount = SqlHelper.ExecuteTable(
+ //$"SELECT * FROM TASK_HISTORY WHERE @ColumnName like @Keywords AND FINISHTIME>=@StartTime AND FINISHTIME<@FinishTime ORDER BY CREATETIME DESC",
+ $"SELECT * FROM TASK_HISTORY_VIEW WHERE {ColumnName} LIKE @Keywords AND 结束时间>=@StartTime AND 结束时间<@FinishTime ORDER BY 结束时间 DESC",
+ //new SqlParameter("@ColumnName", ColumnName),
+ new SqlParameter("@Keywords", $"%{Keywords.Trim()}%"),
+ new SqlParameter("@StartTime", dateTimeStart),
+ new SqlParameter("@FinishTime", dateTimeEnd)
+ );
+
+ dt = SqlHelper.ExecuteTable(
+ //$"SELECT * FROM TASK_HISTORY WHERE @ColumnName like @Keywords AND FINISHTIME>=@StartTime AND FINISHTIME<@FinishTime ORDER BY CREATETIME DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ $"SELECT * FROM TASK_HISTORY_VIEW WHERE {ColumnName} LIKE @Keywords AND 结束时间>=@StartTime AND 结束时间<@FinishTime ORDER BY 结束时间 DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ //new SqlParameter("@ColumnName", ColumnName),
+ new SqlParameter("@Keywords", $"%{Keywords.Trim()}%"),
+ new SqlParameter("@StartTime", dateTimeStart),
+ new SqlParameter("@FinishTime", dateTimeEnd),
+ new SqlParameter("@Rows", int.Parse(num) - 1)
+ );
+ }
+ else
+ {
+ dtCount = SqlHelper.ExecuteTable(
+ //$"SELECT * FROM TASK_HISTORY WHERE FINISHTIME>=@StartTime AND FINISHTIME<@FinishTime ORDER BY CREATETIME DESC",
+ $"SELECT * FROM TASK_HISTORY_VIEW WHERE 结束时间>=@StartTime AND 结束时间<@FinishTime ORDER BY 结束时间 DESC",
+ new SqlParameter("@StartTime", dateTimeStart),
+ new SqlParameter("@FinishTime", dateTimeEnd)
+ );
+
+ dt = SqlHelper.ExecuteTable(
+ //$"SELECT * FROM TASK_HISTORY WHERE FINISHTIME>=@StartTime AND FINISHTIME<@FinishTime ORDER BY CREATETIME DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ $"SELECT * FROM TASK_HISTORY_VIEW WHERE 结束时间>=@StartTime AND 结束时间<@FinishTime ORDER BY 结束时间 DESC OFFSET @Rows ROW FETCH NEXT 10 ROW ONLY",
+ new SqlParameter("@StartTime", dateTimeStart),
+ new SqlParameter("@FinishTime", dateTimeEnd),
+ new SqlParameter("@Rows", int.Parse(num) - 1)
+ );
+ }
+
+ LoadTaskHistory(dt);
+
+ UpdatePageInfo(dtCount, num);
+ }
+ catch (Exception)
+ {
+
+ }
+
+
+
+ }
+
+
+
+ ///
+ /// 重置选择
+ ///
+ [RelayCommand]
+ void Clear()
+ {
+ ColumnName = string.Empty;
+ Keywords = string.Empty;
+
+ TaskHistory.Clear();
+ LoadTaskHistory(1);
+
+ }
+
+
+ //---------------------------------时间字符串格式化对象---------------------------------
+ DateTime dateTimeStart;
+
+ DateTime dateTimeEnd;
+
+ ///
+ /// 日期格式处理
+ ///
+ /// 格式是否正确 true-正确 false-错误
+ bool DateStringFormat()
+ {
+ //处理字符串格式,规范字符串类型的时间值
+ bool b = DateTime.TryParse($"{DateStart} {TimeStart}", out dateTimeStart);
+ bool b1 = DateTime.TryParse($"{DateEnd} {TimeEnd}", out dateTimeEnd);
+
+ if (!b || !b1)
+ {
+ MessageBox.Show("时间格式错误!");
+ return false;
+ }
+
+ return true;
+ }
+
+
+
+ //-----------------------------------------页面跳转/统计相关-----------------------------------------
+ //-----------------------------------------页面跳转/统计相关-----------------------------------------
+
+
+ ///
+ /// 每页条数
+ ///
+ const int countPerPage = 10;
+ ///
+ /// 总数据条数-显示文本
+ ///
+ [ObservableProperty]
+ string _dataCount;
+ ///
+ /// 查询后的总条数
+ ///
+ [ObservableProperty]
+ int _dataCountNumber;
+ ///
+ /// 总页数
+ ///
+ [ObservableProperty]
+ int _pageCount;
+ ///
+ /// 手动输入页数
+ ///
+ [ObservableProperty]
+ int _pageInput;
+ ///
+ /// 鼠标需要点击的页面跳转按钮值
+ ///
+ [ObservableProperty]
+ int _pageSelected;
+ ///
+ /// 要显示页码的集合
+ ///
+ [ObservableProperty]
+ ObservableCollection _pages;
+
+ ///
+ /// 当前页
+ ///
+ [ObservableProperty]
+ int _pageCurrent;
+ ///
+ /// 当前页信息-显示文本
+ ///
+ [ObservableProperty]
+ string _pageInfo;
+
+
+
+ ///
+ /// 点击页码至指定页
+ ///
+ [RelayCommand]
+ void PageClick(string pageNumber)
+ {
+ JumpToPage(int.Parse(pageNumber));
+
+ //MessageBox.Show(pageNumber.ToString());
+ }
+
+
+ ///
+ /// 动态更新页数-下方显示具体X-X页
+ ///
+ /// 跳转后的页数
+ void DynamicPage(int pageCurrent)
+ {
+ //设置最多显示5页按钮
+ Pages.Clear();
+
+ //总页数小于8-显示1-X页
+ if (PageCount < 8 && pageCurrent < 8)
+ {
+ for (int i = 1; i < PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+
+ //总页数大于等于8
+ else
+ {
+ //距离尾页多于3页
+ if (PageCount - pageCurrent >= 3)
+ {
+ //1---显示前7页
+ if (pageCurrent < 8)
+ {
+ for (int i = 1; i < 8; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ else
+ {
+ //显示当前页的前3和后3页码
+ for (int i = pageCurrent - 3; i <= pageCurrent + 3; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+
+ }
+ //距离尾页是否少于3页---显示尾页前7页
+ else
+ {
+ if (PageCount - pageCurrent <= 2)
+ {
+ for (int i = PageCount - 6; i <= PageCount; i++)
+ {
+ Pages.Add(i.ToString());
+ }
+ }
+ }
+ }
+ }
+
+
+ ///
+ /// 获取数据集的总条数和页码数,更新属性
+ ///
+ ///
+ /// 当前页
+ void UpdatePageInfo(DataTable dt, int pageCurrent)
+ {
+ //总数据条数
+ DataCountNumber = dt.Rows.Count;
+
+ //文本显示
+ DataCount = $"共 {DataCountNumber} 条";
+
+ //总页数
+ if (DataCountNumber % countPerPage == 0)
+ {
+ PageCount = DataCountNumber / countPerPage;
+ }
+ else
+ {
+ PageCount = DataCountNumber / countPerPage + 1;
+ }
+
+ PageCurrent = pageCurrent;
+
+ DynamicPage(pageCurrent);
+ }
+ void UpdatePageInfo(DataTable dt, string pageCurrent)
+ {
+ //总数据条数
+ DataCountNumber = dt.Rows.Count;
+
+ //文本显示
+ DataCount = $"共 {DataCountNumber} 条";
+
+ //总页数
+ if (DataCountNumber % countPerPage == 0)
+ {
+ PageCount = DataCountNumber / countPerPage;
+ }
+ else
+ {
+ PageCount = DataCountNumber / countPerPage + 1;
+ }
+
+ PageCurrent = int.Parse(pageCurrent);
+
+ DynamicPage(int.Parse(pageCurrent));
+ }
+
+
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+ //********************************************跳转页码时查询要附加顶部查询条件获取共同查询结果显示*******************************************
+
+
+ ///
+ /// 跳转至指定页
+ ///
+ [RelayCommand]
+ void JumpPageClick(string pageNumber)
+ {
+ try
+ {
+ if (int.Parse(pageNumber) > PageCount )
+ {
+ MessageBox.Show("不能超过最大页码数!");
+ return;
+ }
+ if (int.Parse(pageNumber) < 1)
+ {
+ MessageBox.Show("请使用正确页码数查询!");
+ return;
+ }
+
+ JumpToPage(int.Parse(pageNumber));
+
+ }
+ catch (Exception)
+ {
+ Log.Warning("【瞎β操作】查询历史记录时,跳转页面输入错误!");
+ }
+
+ }
+
+ ///
+ /// 前页
+ ///
+ [RelayCommand]
+ void PageBefore()
+ {
+ if (PageCurrent == 1) return;
+
+ PageCurrent -= 1;
+
+ JumpToPage(PageCurrent);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 后一页
+ ///
+ [RelayCommand]
+ void PageNext()
+ {
+ if (PageCurrent == PageCount) return;
+
+ PageCurrent += 1;
+
+ JumpToPage(PageCurrent);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 首页
+ ///
+ [RelayCommand]
+ void PageFirst()
+ {
+ PageCurrent = 1;
+
+ JumpToPage(PageCurrent);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+ ///
+ /// 尾页
+ ///
+ [RelayCommand]
+ void PageLast()
+ {
+ if (PageCurrent == PageCount) return;
+
+ JumpToPage(PageCount);
+
+ PageInfo = $"当前 {PageCurrent} 页";
+ }
+
+
+ ///
+ /// 输入页码---跳转到指定页
+ ///
+ ///
+ void JumpToPage(int pageNumber)
+ {
+ //获取指定页数从具体第几条数据开始计数
+ int index = (pageNumber - 1) * 10 + 1;
+
+ if (b == false)
+ {
+ //默认数据集条件下跳转
+ LoadTaskHistory(index);
+ }
+ else
+ {
+ //查询之后的数据集条件下跳转
+ Query(index.ToString());
+ }
+
+ if (pageNumber <= PageCount)
+ {
+ PageCurrent = pageNumber;
+ PageInfo = $"当前 {pageNumber} 页";
+ }
+ }
+
+ }
+
+}
+
+
diff --git a/WPFWCSDemo/ViewModels/TaskViewModel.cs b/WPFWCSDemo/ViewModels/TaskViewModel.cs
new file mode 100644
index 0000000..2b29c59
--- /dev/null
+++ b/WPFWCSDemo/ViewModels/TaskViewModel.cs
@@ -0,0 +1,763 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Xaml.Behaviors.Layout;
+using Newtonsoft.Json;
+using Serilog;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Configuration;
+using System.Data;
+using System.Data.Common;
+using System.Data.SqlClient;
+using System.Linq;
+using System.Text;
+using System.Text.Json.Serialization;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Threading;
+using WPFWCSDemo.Common;
+using WPFWCSDemo.Data;
+using WPFWCSDemo.Models.Devices.CircleRGV;
+using WPFWCSDemo.Models.Devices.CircleRGVStation;
+using WPFWCSDemo.Models.Tables;
+using WPFWCSDemo.StateCode;
+using WPFWCSDemo.Utilities;
+using WPFWCSDemo.Utilities.Table;
+using WPFWCSDemo.Views.CustomComponent;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;
+
+namespace WPFWCSDemo.ViewModels
+{
+ public partial class TaskViewModel : ObservableObject
+ {
+ ///
+ /// 用于实时更新任务表的定时器
+ ///
+ private DispatcherTimer dispatcherTimer;
+
+ public TaskViewModel()
+ {
+ TaskRT = new ObservableCollection();
+
+ ColumnList = new List();
+
+ col = new Dictionary();
+
+ SourceLocations = new List();
+
+ TargetLocations = new List();
+
+ RGVNumbers = new List();
+
+ LoadTaskGrid();
+
+ LoadColumns();
+
+ LocationInitialize();
+
+ //Task.Run(() => LoadTaskGridAsync());
+
+ b = true;
+
+ // 设置定时器属性
+ dispatcherTimer = new DispatcherTimer();
+ dispatcherTimer.Interval = TimeSpan.FromSeconds(6); // 设置时间间隔
+ dispatcherTimer.Tick += DispatcherTimer_Tick; // 添加事件处理程序
+ dispatcherTimer.Start(); // 启动计时器
+
+ }
+
+
+ //调度任务表刷新参数
+ private void DispatcherTimer_Tick(object? sender, EventArgs e)
+ {
+ if (b)
+ {
+ LoadTaskGrid();
+ }
+
+ }
+
+
+
+ ///
+ /// 是否更新任务表的标志
+ ///
+ bool b;
+
+ ///
+ /// 调度任务字段---原数据/视图数据
+ ///
+ [ObservableProperty]
+ ObservableCollection _taskRT;
+
+ ///
+ /// 搜索关键字
+ ///
+ [ObservableProperty]
+ string? _keywords;
+
+ ///
+ /// 筛选列表集合
+ ///
+ [ObservableProperty]
+ List _columnList;
+
+ ///
+ /// 筛选列表集合对应的查询字段
+ ///
+ Dictionary col;
+
+ ///
+ /// 筛选列表文本
+ ///
+ [ObservableProperty]
+ string? _columnName;
+
+ ///
+ /// 筛选列表文本选择项
+ ///
+ [ObservableProperty]
+ string? _columnNameSelected;
+
+ ///
+ /// 筛选列表选项
+ ///
+ [ObservableProperty]
+ int _taskTypeSelectedIndex;
+
+ ///
+ /// 右侧对话框弹出属性
+ ///
+ [ObservableProperty]
+ bool _isRightDrawerOpen;
+
+ ///
+ /// 顶部对话框弹出属性
+ ///
+ [ObservableProperty]
+ bool _isTopDrawerOpen;
+
+
+
+ ///
+ /// 站点初始化集合
+ ///
+ [ObservableProperty]
+ int _rowCount;
+ [ObservableProperty]
+ int _columnCount;
+ [ObservableProperty]
+ int _floorCount;
+ [ObservableProperty]
+ List _rows;
+ [ObservableProperty]
+ List _columns;
+ [ObservableProperty]
+ List _floors;
+
+ ///
+ /// 取放货站点集合
+ ///
+ [ObservableProperty]
+ List _sourceLocations;
+ [ObservableProperty]
+ List _targetLocations;
+
+
+
+ ///
+ /// 测试下发界面任务类型
+ ///
+ [ObservableProperty]
+ int _testingTaskTypeIndex;
+ ///
+ /// 任务类型
+ ///
+ [ObservableProperty]
+ int _selectedTaskTypeIndex;
+ ///
+ /// 输入托盘号
+ ///
+ [ObservableProperty]
+ string _inputTaskId;
+ ///
+ /// 取货站点
+ ///
+ [ObservableProperty]
+ int _selectedSourceLocation;
+ ///
+ /// 放货站点
+ ///
+ [ObservableProperty]
+ int _selectedTargetLocation;
+
+ ///
+ /// 小车编号集合
+ ///
+ [ObservableProperty]
+ List _rGVNumbers;
+ ///
+ /// 选中小车编号
+ ///
+ [ObservableProperty]
+ int _selectedRGVNumber;
+
+
+
+ ///
+ /// 右侧对话框弹出命令
+ ///
+ [RelayCommand]
+ private void NewTask()
+ {
+ IsRightDrawerOpen = true;
+ }
+
+
+ ///
+ /// 顶部对话框弹出命令---堆垛机测试
+ ///
+ [RelayCommand]
+ private void StackerTesting()
+ {
+ IsTopDrawerOpen = true;
+ }
+
+
+ ///
+ /// 更改任务类型选项直接更新表
+ ///
+ //[RelayCommand]
+ void TaskTypeSelectItemChanged()
+ {
+ using var context = new AppDbContext();
+
+ List tasks;
+
+ if (TaskTypeSelectedIndex == 1)
+ {
+ tasks = context.Set()
+ .OrderByDescending(t => t.CreateTime)
+ .Where(t => t.TaskType == 10)
+ .ToList();
+ }
+ else if (TaskTypeSelectedIndex == 2)
+ {
+ tasks = context.Set()
+ .OrderByDescending(t => t.CreateTime)
+ .Where(t => t.TaskType == 11)
+ .ToList();
+ }
+ else
+ {
+ tasks = context.Set()
+ .OrderByDescending(t => t.CreateTime)
+ .ToList();
+ }
+
+ TaskRT.Clear();
+
+ //遍历表中每行数据并初始化值
+ foreach (TaskRT task in tasks)
+ {
+ TaskRT.Add(task);
+ }
+
+ }
+
+
+
+ ///
+ /// 查询任务
+ ///
+ [RelayCommand]
+ public void Query()
+ {
+ //关键词不为空且列名不为空
+ if (!string.IsNullOrEmpty(Keywords) && !string.IsNullOrEmpty(ColumnName))
+ {
+ using var context = new AppDbContext();
+
+ var tasks=context.Set()
+ .FromSqlInterpolated($"SELECT * FROM TASK WHERE {col[ColumnName]} LIKE %{Keywords}% ORDER BY CREATETIME DESC")
+ .ToList();
+
+ TaskRT.Clear();
+
+ //遍历表中每行数据并初始化值
+ foreach (TaskRT task in tasks)
+ {
+ TaskRT.Add(task);
+ }
+
+ }
+ else
+ {
+ LoadTaskGrid();
+ }
+
+ b = false;
+
+ }
+
+
+ ///
+ /// 重置筛选项
+ ///
+ [RelayCommand]
+ void Clear()
+ {
+ Keywords = string.Empty;
+ ColumnName = string.Empty;
+
+ LoadTaskGrid();
+
+ b = true;
+ }
+
+ #region 添加新任务相关
+
+
+ // 下拉框获取值属性 (源/目标排、列、层)
+
+
+
+ ///
+ /// 点击新建任务按钮命令
+ ///
+ [RelayCommand]
+ public void AddTask()
+ {
+ InputCheck();
+ //MessageBox.Show(SelectedTaskType);
+ //获取任务参数值
+ TaskRT taskRT = new TaskRT
+ {
+ TaskId = SqlHelper.GetTaskIdByManualGeneration().ToString(),//使用int类型初始值不是空 指定9起始的任务号为人工操作标识
+ SourceLocation = SelectedSourceLocation.ToString(),
+ TargetLocation = SelectedTargetLocation.ToString(),
+ TaskState = TaskStateCode.Task_Running,
+ CreateTime = DateTime.Now,
+ //ReportState = 0
+
+ };
+
+ //任务校验和添加新任务(区分任务类型)
+ if (SelectedTaskTypeIndex == 0)
+ {
+ taskRT.TaskType = 10;
+ }
+ else if (SelectedTaskTypeIndex == 1)
+ {
+ taskRT.TaskType = 11;
+ }
+ else if (SelectedTaskTypeIndex == 2 || SelectedTaskTypeIndex == 3)
+ {
+ taskRT.TaskType = SelectedTaskTypeIndex;
+ }
+ else
+ {
+ MessageBox.Show("任务类型错误!");
+ return;
+ }
+
+ Insert(taskRT, taskRT.TaskType);
+
+ SqlHelper.NewEventLog($"手动下发调度任务:任务号:{taskRT.TaskId}", "USER");
+
+ //重载任务表
+ LoadTaskGrid();
+ }
+ #endregion
+
+
+ ///
+ /// 加载下拉框内容
+ ///
+ public void LoadColumns()
+ {
+ ColumnList.Clear();
+ //ColumnList.Add("作业号");
+ ColumnList.Add("任务号");
+ //ColumnList.Add("托盘号");
+ ColumnList.Add("任务类型");
+ ColumnList.Add("源站点");
+ ColumnList.Add("目标站点");
+ ColumnList.Add("任务状态");
+ //ColumnList.Add("生成时间");
+
+ col.Clear();
+ //col.Add("作业号", "JobId");
+ col.Add("任务号", "TaskId");
+ //col.Add("托盘号", "PalletId");
+ col.Add("任务类型", "TaskType");
+ col.Add("源站点", "SourceLocation");
+ col.Add("目标站点", "TargetLocation");
+ col.Add("任务状态", "TaskState");
+ //col.Add("生成时间", "CreateTime");
+
+ RGVNumbers.Clear();
+ for (int i = 0; i < RGVStation.RGVCount; i++)
+ {
+ RGVNumbers.Add(i);
+ }
+
+ }
+
+
+
+ ///
+ /// 加载表格内容
+ ///
+ public void LoadTaskGrid()
+ {
+ using var context = new AppDbContext();
+
+ var tasks = context.Set()
+ .OrderByDescending(t => t.CreateTime)
+ .ToList();
+
+ TaskRT.Clear();
+
+ //遍历表中每行数据并初始化值
+ foreach (TaskRT task in tasks)
+ {
+ TaskRT.Add(task);
+ }
+
+ }
+
+
+
+ ///
+ /// 向调度表中插入任务
+ ///
+ /// TaskRT类的实例化对象
+ /// 任务类型
+ ///
+ public void Insert(TaskRT taskRT, int taskType)
+ {
+ try
+ {
+ using var context = new AppDbContext();
+
+ context.Set()
+ .Add(taskRT);
+
+ int result = context.SaveChanges();
+
+ if (result == 1) Log.Warning($"【手动添加调度任务】任务号:{taskRT.TaskId},{JsonConvert.SerializeObject(taskRT)}");
+
+ }
+ catch (DbUpdateException e)
+ {
+ MessageBox.Show($"发生了预期之外的错误:{e.Message}(错误代码:TVM000002)");
+ }
+
+ LoadTaskGrid();
+
+ }
+
+
+
+ ///
+ /// 站点信息初始化
+ ///
+ void LocationInitialize()
+ {
+ //Rows = new List();
+ //Columns = new List();
+ //Floors = new List();
+
+ //RowCount = int.Parse(ConfigurationManager.AppSettings["Row"]);
+ //for (int i = 1; i <= RowCount; i++)
+ //{
+ // Rows.Add(i);
+ //}
+ //ColumnCount = int.Parse(ConfigurationManager.AppSettings["Column"]);
+ //for (int i = 1; i <= ColumnCount; i++)
+ //{
+ // Columns.Add(i);
+ //}
+ //FloorCount = int.Parse(ConfigurationManager.AppSettings["Floor"]);
+ //for (int i = 1; i <= FloorCount; i++)
+ //{
+ // Floors.Add(i);
+ //}
+
+ SourceLocations.Clear();
+
+ foreach (var item in CircleRGVsViewModel.route)
+ {
+ SourceLocations.Add(item.Key);
+ }
+
+ }
+
+ ///
+ /// 取货站点对应放货站点
+ ///
+ [RelayCommand]
+ void SourceToTarget()
+ {
+ try
+ {
+ SelectedTargetLocation = CircleRGVsViewModel.route[SelectedSourceLocation];
+ }
+ catch
+ {
+
+ }
+
+ }
+
+
+ ///
+ /// 下发测试任务
+ ///
+ [RelayCommand]
+ void SendRGVTest()
+ {
+ if (MessageBox.Show("此操作会向环穿地面站PLC直接写入命令!是否继续?","",MessageBoxButton.YesNo) != MessageBoxResult.OK)
+ {
+ return;
+ }
+
+ CircleRGVStationCommand circleRGVStationCommand = new CircleRGVStationCommand()
+ {
+ Write_DeviceNumber = SelectedRGVNumber,
+ Write_TaskNumber = SqlHelper.GetTaskIdByManualGeneration(),
+ Write_TaskType = TestingTaskTypeIndex + 1,
+ Write_SourceLocation = SelectedSourceLocation,
+ Write_TargetLocation = SelectedTargetLocation,
+ };
+
+ CircleRGVsViewModel.SendRGVStationCommand(circleRGVStationCommand);
+
+ Log.Information($"【环穿下发任务测试】直接向地面站PLC下发任务:{JsonConvert.SerializeObject(circleRGVStationCommand)}");
+
+ SqlHelper.NewEventLog($"向地面站PLC直接写入测试任务:任务号:{circleRGVStationCommand.Write_TaskNumber}", "USER");
+
+ IsTopDrawerOpen = false;
+
+ }
+
+
+ ///
+ /// 清空选择项
+ ///
+ [RelayCommand]
+ void TestClear()
+ {
+ SelectedRGVNumber = 0;
+ SelectedSourceLocation = 0;
+ SelectedTargetLocation = 0;
+ }
+
+
+ ///
+ /// 新任务输入校验
+ ///
+ public void InputCheck()
+ {
+ //跨巷道使用
+ if (string.IsNullOrEmpty(SelectedSourceLocation.ToString().Trim()))
+ {
+ MessageBox.Show("请选择取货站点!");
+ return;
+ }
+ if (string.IsNullOrEmpty(SelectedTargetLocation.ToString().Trim()))
+ {
+ MessageBox.Show("请选择目标站点!");
+ return;
+
+ }
+
+
+ }
+
+ Action action;
+
+ //[RelayCommand]
+ void TaskFinishHandler()
+ {
+ InputDialog inputDialog = new InputDialog();
+ inputDialog.ShowDialog();
+
+ action = TaskFinish;
+ }
+
+ void TaskCancelHandler()
+ {
+ InputDialog inputDialog = new InputDialog();
+ inputDialog.ShowDialog();
+
+ action = TaskDelete;
+ }
+
+ void UpdateTaskStateToReadyHandler()
+ {
+ InputDialog inputDialog = new InputDialog();
+ inputDialog.ShowDialog();
+
+ action = UpdateTaskStateToReady;
+ }
+
+
+ ///
+ /// 手动完成任务
+ ///
+ [RelayCommand]
+ void TaskFinish(string taskId)
+ {
+ using var context = new AppDbContext();
+
+ var task = context.Set()
+ .Where(t => t.TaskId == taskId)
+ .FirstOrDefault();
+
+ if (task == null)
+ {
+ MessageBox.Show("获取任务号错误!自动移除该任务");
+
+ context.Database
+ .ExecuteSqlInterpolated($"DELETE FROM TASK WHERE TASKID={taskId}");
+
+ context.SaveChanges();
+
+ return;
+ }
+
+
+ string taskType = "";
+
+ switch (task.TaskType)
+ {
+ case 10:
+ taskType = "实垛";
+ break;
+ case 11:
+ taskType = "空托";
+ break;
+ default:
+ break;
+ }
+
+ if (MessageBox.Show($"确认人工完成任务号:{taskId}的任务?\r\n(错误的操作时机可能会导致生成空任务)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ task.TaskState = TaskStateCode.Task_Finish_Manual;
+
+ if (context.SaveChanges() == 1)
+ {
+ Log.Information($"【人工操作】手动完成任务,任务号:{taskId}");
+
+ SqlHelper.NewEventLog($"人工完成{taskType}任务:{taskId}", "USER");
+ }
+
+ }
+
+ LoadTaskGrid();
+
+ }
+
+
+ ///
+ /// 手动删除(取消)任务
+ ///
+ [RelayCommand]
+ void TaskDelete(string taskId)
+ {
+ using var context = new AppDbContext();
+
+ var task = context.Set()
+ .Where(t => t.TaskId == taskId)
+ .FirstOrDefault();
+
+ if (task == null)
+ {
+ MessageBox.Show("获取任务号错误!自动移除该任务");
+
+ context.Database
+ .ExecuteSqlInterpolated($"DELETE FROM TASK WHERE TASKID={taskId}");
+
+ context.SaveChanges();
+
+ return;
+ }
+
+
+ string taskType = "";
+
+ switch (task.TaskType)
+ {
+ case 10:
+ taskType = "实垛";
+ break;
+ case 11:
+ taskType = "空托";
+ break;
+ default:
+ break;
+ }
+
+ if (MessageBox.Show($"确认人工取消任务号:{taskId}的任务?\r\n(错误的操作时机可能会导致生成空任务)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ task.TaskState = TaskStateCode.Task_Finish_Cancel;
+
+ if (context.SaveChanges() == 1)
+ {
+ Log.Information($"【人工操作】手动取消任务,任务号:{taskId}");
+
+ SqlHelper.NewEventLog($"人工取消{taskType}任务:{taskId}", "USER");
+ }
+
+ }
+
+ LoadTaskGrid();
+
+ }
+
+
+ ///
+ /// 当向环穿下发任务失败时,可以选择重新下发
+ /// 只能在调度状态为【环穿-待执行】时可用
+ ///
+ ///
+ [RelayCommand]
+ void UpdateTaskStateToReady(string taskId)
+ {
+ using var context = new AppDbContext();
+
+ var task = context.Set()
+ .Where(t => t.TaskId == taskId && t.ScheduleState== ScheduleStateCode.Trans_CircleRGV_Ready)
+ .FirstOrDefault();
+
+ if (task == null)
+ {
+ MessageBox.Show("设备运行时的任务无法重下!");
+ return;
+ }
+
+ if (MessageBox.Show($"确认将任务:{taskId}的任务状态更改为【待执行】?\r\n此操作会重新下发当前任务(仅在环穿调度状态为【环穿-待执行】时生效)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
+ {
+ task.TaskState= TaskStateCode.Task_Ready;
+
+ if (context.SaveChanges() == 1)
+ {
+ Log.Information($"【人工操作】重新下发任务,任务号:{taskId}");
+
+ SqlHelper.NewEventLog($"人工重下任务:{taskId}", "USER");
+ }
+
+ }
+
+ LoadTaskGrid();
+
+ }
+
+
+ }
+}
diff --git a/WPFWCSDemo/Views/AlarmHistoryView.xaml b/WPFWCSDemo/Views/AlarmHistoryView.xaml
new file mode 100644
index 0000000..4a16695
--- /dev/null
+++ b/WPFWCSDemo/Views/AlarmHistoryView.xaml
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/AlarmHistoryView.xaml.cs b/WPFWCSDemo/Views/AlarmHistoryView.xaml.cs
new file mode 100644
index 0000000..f6a027a
--- /dev/null
+++ b/WPFWCSDemo/Views/AlarmHistoryView.xaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// AlarmHistoryView.xaml 的交互逻辑
+ ///
+ public partial class AlarmHistoryView : Page
+ {
+ public AlarmHistoryView()
+ {
+ InitializeComponent();
+ DataContext = new ViewModels.AlarmHistoryViewModel();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/AlarmView.xaml b/WPFWCSDemo/Views/AlarmView.xaml
new file mode 100644
index 0000000..c7bcbdb
--- /dev/null
+++ b/WPFWCSDemo/Views/AlarmView.xaml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/AlarmView.xaml.cs b/WPFWCSDemo/Views/AlarmView.xaml.cs
new file mode 100644
index 0000000..55245dc
--- /dev/null
+++ b/WPFWCSDemo/Views/AlarmView.xaml.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// AlarmView.xaml 的交互逻辑
+ ///
+ public partial class AlarmView : Page
+ {
+ public AlarmView()
+ {
+ InitializeComponent();
+ DataContext = new AlarmViewModel();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/BlankView.xaml b/WPFWCSDemo/Views/BlankView.xaml
new file mode 100644
index 0000000..3df32e9
--- /dev/null
+++ b/WPFWCSDemo/Views/BlankView.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/BlankView.xaml.cs b/WPFWCSDemo/Views/BlankView.xaml.cs
new file mode 100644
index 0000000..9e6282f
--- /dev/null
+++ b/WPFWCSDemo/Views/BlankView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// BlankView.xaml 的交互逻辑
+ ///
+ public partial class BlankView : Page
+ {
+ public BlankView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/CircleRGVsView.xaml b/WPFWCSDemo/Views/CircleRGVsView.xaml
new file mode 100644
index 0000000..0f9987b
--- /dev/null
+++ b/WPFWCSDemo/Views/CircleRGVsView.xaml
@@ -0,0 +1,266 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/CircleRGVsView.xaml.cs b/WPFWCSDemo/Views/CircleRGVsView.xaml.cs
new file mode 100644
index 0000000..de82f30
--- /dev/null
+++ b/WPFWCSDemo/Views/CircleRGVsView.xaml.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views.Devices
+{
+ ///
+ /// CircleRGVsView.xaml 的交互逻辑
+ ///
+ public partial class CircleRGVsView : Page
+ {
+ public CircleRGVsView()
+ {
+ InitializeComponent();
+
+ DataContext = ViewModels.CircleRGVsViewModel.Instance;
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/ControllerView.xaml b/WPFWCSDemo/Views/ControllerView.xaml
new file mode 100644
index 0000000..47b01f6
--- /dev/null
+++ b/WPFWCSDemo/Views/ControllerView.xaml
@@ -0,0 +1,203 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/ControllerView.xaml.cs b/WPFWCSDemo/Views/ControllerView.xaml.cs
new file mode 100644
index 0000000..b9b80ac
--- /dev/null
+++ b/WPFWCSDemo/Views/ControllerView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// ControllerView.xaml 的交互逻辑
+ ///
+ public partial class ControllerView : Window
+ {
+ public ControllerView()
+ {
+ InitializeComponent();
+ //DataContext=new ViewModels.ControllerViewModel(DeviceController);
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/CustomComponent/InputDialog.xaml b/WPFWCSDemo/Views/CustomComponent/InputDialog.xaml
new file mode 100644
index 0000000..be97d72
--- /dev/null
+++ b/WPFWCSDemo/Views/CustomComponent/InputDialog.xaml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/CustomComponent/InputDialog.xaml.cs b/WPFWCSDemo/Views/CustomComponent/InputDialog.xaml.cs
new file mode 100644
index 0000000..3c72317
--- /dev/null
+++ b/WPFWCSDemo/Views/CustomComponent/InputDialog.xaml.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views.CustomComponent
+{
+ ///
+ /// InputDialog.xaml 的交互逻辑
+ ///
+ public partial class InputDialog : Window
+ {
+ Action action;
+ public InputDialog()
+ {
+ InitializeComponent();
+ DataContext = new ViewModels.CustomComponent.InputDialogViewModel(inputWindow,action);
+
+ colorZone.MouseMove += (s, e) =>
+ {
+ if (e.LeftButton == MouseButtonState.Pressed) DragMove();
+ };
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/CustomComponent/LineControlDialog.xaml b/WPFWCSDemo/Views/CustomComponent/LineControlDialog.xaml
new file mode 100644
index 0000000..b9cee6b
--- /dev/null
+++ b/WPFWCSDemo/Views/CustomComponent/LineControlDialog.xaml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/CustomComponent/LineControlDialog.xaml.cs b/WPFWCSDemo/Views/CustomComponent/LineControlDialog.xaml.cs
new file mode 100644
index 0000000..f9f4ea6
--- /dev/null
+++ b/WPFWCSDemo/Views/CustomComponent/LineControlDialog.xaml.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Input;
+using System.Windows.Shapes;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Views.CustomComponent
+{
+ ///
+ /// LineControlDialog.xaml 的交互逻辑
+ ///
+ public partial class LineControlDialog : Window
+ {
+ public LineControlDialog()
+ {
+ InitializeComponent();
+ DataContext = new LineManagementViewModel(lineControlWindow);
+
+ colorZone.MouseMove += (s, e) =>
+ {
+ if (e.LeftButton == MouseButtonState.Pressed) DragMove();
+ };
+
+ btnClose.Click += (s, e) =>
+ {
+ Close();
+ };
+
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/CustomComponent/MessageDialog.xaml b/WPFWCSDemo/Views/CustomComponent/MessageDialog.xaml
new file mode 100644
index 0000000..4c81113
--- /dev/null
+++ b/WPFWCSDemo/Views/CustomComponent/MessageDialog.xaml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/CustomComponent/MessageDialog.xaml.cs b/WPFWCSDemo/Views/CustomComponent/MessageDialog.xaml.cs
new file mode 100644
index 0000000..6e6a283
--- /dev/null
+++ b/WPFWCSDemo/Views/CustomComponent/MessageDialog.xaml.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using WPFWCSDemo.Models;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// MessageDialog.xaml 的交互逻辑
+ ///
+ public partial class MessageDialog : Window
+ {
+ public MessageDialog()
+ {
+ InitializeComponent();
+ DataContext = new ViewModels.CustomComponent.MessageDialogViewModel(messageWindow);
+
+ colorZone.MouseMove += (s, e) =>
+ {
+ if (e.LeftButton == MouseButtonState.Pressed) DragMove();
+ };
+
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/DataInfoView.xaml b/WPFWCSDemo/Views/DataInfoView.xaml
new file mode 100644
index 0000000..2a935d1
--- /dev/null
+++ b/WPFWCSDemo/Views/DataInfoView.xaml
@@ -0,0 +1,438 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/DataInfoView.xaml.cs b/WPFWCSDemo/Views/DataInfoView.xaml.cs
new file mode 100644
index 0000000..124605e
--- /dev/null
+++ b/WPFWCSDemo/Views/DataInfoView.xaml.cs
@@ -0,0 +1,35 @@
+using LiveCharts;
+using LiveCharts.Wpf;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// DataInfoView.xaml 的交互逻辑
+ ///
+ public partial class DataInfoView : Page
+ {
+
+
+ public DataInfoView()
+ {
+ InitializeComponent();
+
+ DataContext = new ViewModels.DataInfoViewModel();
+ }
+
+ }
+}
diff --git a/WPFWCSDemo/Views/Devices/DeviceListView.xaml b/WPFWCSDemo/Views/Devices/DeviceListView.xaml
new file mode 100644
index 0000000..aff4fde
--- /dev/null
+++ b/WPFWCSDemo/Views/Devices/DeviceListView.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/Devices/DeviceListView.xaml.cs b/WPFWCSDemo/Views/Devices/DeviceListView.xaml.cs
new file mode 100644
index 0000000..b5a0e14
--- /dev/null
+++ b/WPFWCSDemo/Views/Devices/DeviceListView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views.Devices
+{
+ ///
+ /// DeviceListView.xaml 的交互逻辑
+ ///
+ public partial class DeviceListView : Page
+ {
+ public DeviceListView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/Devices/RGVsView.xaml b/WPFWCSDemo/Views/Devices/RGVsView.xaml
new file mode 100644
index 0000000..2a08462
--- /dev/null
+++ b/WPFWCSDemo/Views/Devices/RGVsView.xaml
@@ -0,0 +1,216 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/Devices/RGVsView.xaml.cs b/WPFWCSDemo/Views/Devices/RGVsView.xaml.cs
new file mode 100644
index 0000000..d1be626
--- /dev/null
+++ b/WPFWCSDemo/Views/Devices/RGVsView.xaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views.Devices
+{
+ ///
+ /// RGVsView.xaml 的交互逻辑
+ ///
+ public partial class RGVsView : Page
+ {
+ public RGVsView()
+ {
+ InitializeComponent();
+ //DataContext = new ViewModels.Devices.RGVsViewModel();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/DevicesNavigationView.xaml b/WPFWCSDemo/Views/DevicesNavigationView.xaml
new file mode 100644
index 0000000..ac56cdf
--- /dev/null
+++ b/WPFWCSDemo/Views/DevicesNavigationView.xaml
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/DevicesNavigationView.xaml.cs b/WPFWCSDemo/Views/DevicesNavigationView.xaml.cs
new file mode 100644
index 0000000..cafccd2
--- /dev/null
+++ b/WPFWCSDemo/Views/DevicesNavigationView.xaml.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// DevicesNavigationView.xaml 的交互逻辑
+ ///
+ public partial class DevicesNavigationView : Page
+ {
+ private static Frame _navagationFrame;
+ public DevicesNavigationView()
+ {
+ InitializeComponent();
+ DataContext = new ViewModels.DevicesNavigationViewModel(_navagationFrame);
+ }
+
+ ///
+ /// 获取主页导航的Frame对象
+ ///
+ ///
+ public static void GetMainFrame(Frame frame)
+ {
+ _navagationFrame = frame;
+ }
+
+ }
+}
diff --git a/WPFWCSDemo/Views/DevicesView.xaml b/WPFWCSDemo/Views/DevicesView.xaml
new file mode 100644
index 0000000..039e9da
--- /dev/null
+++ b/WPFWCSDemo/Views/DevicesView.xaml
@@ -0,0 +1,328 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/DevicesView.xaml.cs b/WPFWCSDemo/Views/DevicesView.xaml.cs
new file mode 100644
index 0000000..b8cd70f
--- /dev/null
+++ b/WPFWCSDemo/Views/DevicesView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// DevicesView.xaml 的交互逻辑
+ ///
+ public partial class DevicesView : Page
+ {
+ public DevicesView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/HelperView.xaml b/WPFWCSDemo/Views/HelperView.xaml
new file mode 100644
index 0000000..6b40cd2
--- /dev/null
+++ b/WPFWCSDemo/Views/HelperView.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/HelperView.xaml.cs b/WPFWCSDemo/Views/HelperView.xaml.cs
new file mode 100644
index 0000000..0c36430
--- /dev/null
+++ b/WPFWCSDemo/Views/HelperView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// HelperView.xaml 的交互逻辑
+ ///
+ public partial class HelperView : Page
+ {
+ public HelperView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/LineManagementView.xaml b/WPFWCSDemo/Views/LineManagementView.xaml
new file mode 100644
index 0000000..3c529d3
--- /dev/null
+++ b/WPFWCSDemo/Views/LineManagementView.xaml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/LineManagementView.xaml.cs b/WPFWCSDemo/Views/LineManagementView.xaml.cs
new file mode 100644
index 0000000..6029d79
--- /dev/null
+++ b/WPFWCSDemo/Views/LineManagementView.xaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// LineManagementView.xaml 的交互逻辑
+ ///
+ public partial class LineManagementView : Page
+ {
+ public LineManagementView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/LogView.xaml b/WPFWCSDemo/Views/LogView.xaml
new file mode 100644
index 0000000..d1cb7ac
--- /dev/null
+++ b/WPFWCSDemo/Views/LogView.xaml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/LogView.xaml.cs b/WPFWCSDemo/Views/LogView.xaml.cs
new file mode 100644
index 0000000..92f276e
--- /dev/null
+++ b/WPFWCSDemo/Views/LogView.xaml.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// LogView.xaml 的交互逻辑
+ ///
+ public partial class LogView : Page
+ {
+ public LogView()
+ {
+ InitializeComponent();
+ DataContext = new LogViewModel();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/MonitorView.xaml b/WPFWCSDemo/Views/MonitorView.xaml
new file mode 100644
index 0000000..3af4cc3
--- /dev/null
+++ b/WPFWCSDemo/Views/MonitorView.xaml
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/MonitorView.xaml.cs b/WPFWCSDemo/Views/MonitorView.xaml.cs
new file mode 100644
index 0000000..649032d
--- /dev/null
+++ b/WPFWCSDemo/Views/MonitorView.xaml.cs
@@ -0,0 +1,33 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using WPFWCSDemo.ViewModels;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// MonitorView.xaml 的交互逻辑
+ ///
+ public partial class MonitorView : Page
+ {
+ public MonitorView()
+ {
+ InitializeComponent();
+ DataContext = new MonitorViewModel();
+ }
+ }
+
+}
diff --git a/WPFWCSDemo/Views/Settings/AboutView.xaml b/WPFWCSDemo/Views/Settings/AboutView.xaml
new file mode 100644
index 0000000..f0474d4
--- /dev/null
+++ b/WPFWCSDemo/Views/Settings/AboutView.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ http://www.yctd.cn/
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/Settings/AboutView.xaml.cs b/WPFWCSDemo/Views/Settings/AboutView.xaml.cs
new file mode 100644
index 0000000..775d3ec
--- /dev/null
+++ b/WPFWCSDemo/Views/Settings/AboutView.xaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views.Settings
+{
+ ///
+ /// AboutView.xaml 的交互逻辑
+ ///
+ public partial class AboutView : Page
+ {
+ public AboutView()
+ {
+ InitializeComponent();
+ DataContext = new ViewModels.Settings.AboutViewModel();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/Settings/SettingView.xaml b/WPFWCSDemo/Views/Settings/SettingView.xaml
new file mode 100644
index 0000000..8976af9
--- /dev/null
+++ b/WPFWCSDemo/Views/Settings/SettingView.xaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/Settings/SettingView.xaml.cs b/WPFWCSDemo/Views/Settings/SettingView.xaml.cs
new file mode 100644
index 0000000..b03f74d
--- /dev/null
+++ b/WPFWCSDemo/Views/Settings/SettingView.xaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// SettingView.xaml 的交互逻辑
+ ///
+ public partial class SettingView : Page
+ {
+ public SettingView()
+ {
+ InitializeComponent();
+ DataContext = new ViewModels.SettingViewModel(settingFrame);
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/Settings/SkinView.xaml b/WPFWCSDemo/Views/Settings/SkinView.xaml
new file mode 100644
index 0000000..529c4ee
--- /dev/null
+++ b/WPFWCSDemo/Views/Settings/SkinView.xaml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/Settings/SkinView.xaml.cs b/WPFWCSDemo/Views/Settings/SkinView.xaml.cs
new file mode 100644
index 0000000..4e0cf60
--- /dev/null
+++ b/WPFWCSDemo/Views/Settings/SkinView.xaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views.Settings
+{
+ ///
+ /// SkinView.xaml 的交互逻辑
+ ///
+ public partial class SkinView : Page
+ {
+ public SkinView()
+ {
+ InitializeComponent();
+ DataContext = new ViewModels.Settings.SkinViewModel();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/Settings/SystemView.xaml b/WPFWCSDemo/Views/Settings/SystemView.xaml
new file mode 100644
index 0000000..ad0cd78
--- /dev/null
+++ b/WPFWCSDemo/Views/Settings/SystemView.xaml
@@ -0,0 +1,121 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/Settings/SystemView.xaml.cs b/WPFWCSDemo/Views/Settings/SystemView.xaml.cs
new file mode 100644
index 0000000..9c15c9a
--- /dev/null
+++ b/WPFWCSDemo/Views/Settings/SystemView.xaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace WPFWCSDemo.Views.Settings
+{
+ ///
+ /// SystemView.xaml 的交互逻辑
+ ///
+ public partial class SystemView : Page
+ {
+ public SystemView()
+ {
+ InitializeComponent();
+ DataContext = new ViewModels.Settings.SystemViewModel();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/TaskHistoryView.xaml b/WPFWCSDemo/Views/TaskHistoryView.xaml
new file mode 100644
index 0000000..7d0f242
--- /dev/null
+++ b/WPFWCSDemo/Views/TaskHistoryView.xaml
@@ -0,0 +1,165 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/TaskHistoryView.xaml.cs b/WPFWCSDemo/Views/TaskHistoryView.xaml.cs
new file mode 100644
index 0000000..cb68ded
--- /dev/null
+++ b/WPFWCSDemo/Views/TaskHistoryView.xaml.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using WPFWCSDemo.ViewModels;
+using WPFWCSDemo.ViewModels.DbViews;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// TaskHistoryView.xaml 的交互逻辑
+ ///
+ public partial class TaskHistoryView : Page
+ {
+ public TaskHistoryView()
+ {
+ InitializeComponent();
+ DataContext = new TaskHistoryViewModel();
+ DataContext = new TaskHistoryDbViewModel();
+ }
+ }
+}
diff --git a/WPFWCSDemo/Views/TaskView.xaml b/WPFWCSDemo/Views/TaskView.xaml
new file mode 100644
index 0000000..a768069
--- /dev/null
+++ b/WPFWCSDemo/Views/TaskView.xaml
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/WPFWCSDemo/Views/TaskView.xaml.cs b/WPFWCSDemo/Views/TaskView.xaml.cs
new file mode 100644
index 0000000..0a5592c
--- /dev/null
+++ b/WPFWCSDemo/Views/TaskView.xaml.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using WPFWCSDemo.ViewModels;
+using WPFWCSDemo.ViewModels.DbViews;
+
+namespace WPFWCSDemo.Views
+{
+ ///
+ /// TaskView.xaml 的交互逻辑
+ ///
+ public partial class TaskView : Page
+ {
+ public TaskView()
+ {
+ InitializeComponent();
+ DataContext = new TaskViewModel();
+ DataContext = new TaskDbViewModel();
+ }
+
+ }
+}
diff --git a/WPFWCSDemo/WPFWCSDemo.csproj b/WPFWCSDemo/WPFWCSDemo.csproj
new file mode 100644
index 0000000..4a6367b
--- /dev/null
+++ b/WPFWCSDemo/WPFWCSDemo.csproj
@@ -0,0 +1,64 @@
+
+
+
+ WinExe
+ net6.0-windows
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ S7.Net.dll
+
+
+
+
+
+
+
+ Always
+
+
+
+
+
+
+
+
+
+