添加项目文件。

This commit is contained in:
Administrator
2026-06-29 14:46:32 +08:00
parent 9a9c508618
commit d9e0324b1d
175 changed files with 17983 additions and 0 deletions

View File

@@ -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
{
/// <summary>
/// 接收WMS推送的*入库*任务
/// </summary>
public class StockIn_Receive
{
/// <summary>
/// 流水号
/// </summary>
public string JobId { get; set; }
/// <summary>
/// 任务号
/// </summary>
public string TaskId { get; set; }
/// <summary>
/// 托盘编号
/// </summary>
public string PalletId { get; set; }
/// <summary>
/// 任务类型 1-入库 2-出库 3-移库
/// </summary>
public int TaskType { get; set; }
/// <summary>
/// 源站点
/// </summary>
public string SourceLocation { get; set; }
/// <summary>
/// 目标站点
/// </summary>
public string TargetLocation { get; set; }
/// <summary>
/// 优先级 1→3 高→低
/// </summary>
public int Priority { get; set; }
/// <summary>
/// 任务状态
/// </summary>
[JsonIgnore]
public string TaskCode { get; set; }
/// <summary>
/// 调度状态
/// </summary>
[JsonIgnore]
public string ScheduleCode { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 【接收*入库*推送后】向wms反馈消息
/// </summary>
public class StockIn_ReceiveResponse
{
/// <summary>
/// 作业号
/// </summary>
public string JobId { get; set; }
/// <summary>
/// 反馈信息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 返回结果 0-正常 1-异常
/// </summary>
public int Result { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// wcs主动向wms请求*入库*任务
/// </summary>
public class StockIn_Request
{
/// <summary>
/// 接口名称
/// </summary>
[JsonIgnore]
public string Name { get; set; }
/// <summary>
/// 任务号
/// </summary>
public string TaskId { get; set; }
/// <summary>
/// 托盘号
/// </summary>
public string PalletId { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public string TaskType { get; set; }
/// <summary>
/// 源站点
/// </summary>
public string SourceLocation { get; set; }
/// <summary>
/// 发送结果
/// </summary>
[JsonIgnore]
public string Result { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 【向wms请求*入库*后】wms的返回消息
/// </summary>
public class StockIn_RequestResponse
{
/// <summary>
/// 作业号
/// </summary>
public string JobId { get; set; }
/// <summary>
/// 反馈信息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 返回结果 0-正常 1-异常
/// </summary>
public int Result { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 接收WMS推送的*出库*任务
/// </summary>
public class StockOut_Receive
{
/// <summary>
/// 流水号
/// </summary>
public string JobId { get; set; }
/// <summary>
/// 任务号
/// </summary>
public string TaskId { get; set; }
/// <summary>
/// 托盘编号
/// </summary>
public string PalletId { get; set; }
/// <summary>
/// 任务类型 1-入库 2-出库 3-移库
/// </summary>
public int TaskType { get; set; }
/// <summary>
/// 源站点
/// </summary>
public string SourceLocation { get; set; }
/// <summary>
/// 目标站点
/// </summary>
public string TargetLocation { get; set; }
/// <summary>
/// 优先级 1→3 高→低
/// </summary>
public int Priority { get; set; }
/// <summary>
/// 任务状态
/// </summary>
[JsonIgnore]
public string TaskCode { get; set; }
/// <summary>
/// 调度状态
/// </summary>
[JsonIgnore]
public string ScheduleCode { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 【接收*出库*推送后】向wms反馈消息
/// </summary>
public class StockOut_ReceiveReponse
{
/// <summary>
/// 作业号
/// </summary>
public string JobId { get; set; }
/// <summary>
/// 反馈信息,可空
/// </summary>
public string Message { get; set; }
/// <summary>
/// 返回结果 0-正常 1-异常
/// </summary>
public int Result { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 接收wms推送任务
/// </summary>
public class Task_Receive
{
/// <summary>
/// 流水号
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 任务号
/// </summary>
[JsonIgnore]
public string? TaskId { get; set; }
/// <summary>
/// 托盘编号
/// </summary>
public string? PalletId { get; set; }
/// <summary>
/// 任务类型 1-入库 2-出库 3-移库
/// </summary>
public ushort TaskType { get; set; }
/// <summary>
/// 源站点
/// </summary>
public string? SourceLocation { get; set; }
/// <summary>
/// 目标站点
/// </summary>
public string? TargetLocation { get; set; }
/// <summary>
/// 优先级 1→3 高→低
/// </summary>
public int Priority { get; set; }
/// <summary>
/// 任务状态
/// </summary>
[JsonIgnore]
public string TaskState { get; set; }
/// <summary>
/// 调度状态
/// </summary>
[JsonIgnore]
public string ScheduleState { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.API.Task
{
/// <summary>
/// 【接收wms推送任务后】向wms反馈消息
/// </summary>
public class Task_Response
{
/// <summary>
/// 作业号
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 反馈信息,可空
/// </summary>
public string? Message { get; set; }
/// <summary>
/// 返回结果 0-成功 1-失败
/// </summary>
public int Result { get; set; }
}
}

View File

@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.API.Task
{
/// <summary>
/// 根据任务状态请求wms-向wms反馈执行结果
/// </summary>
public class Task_StateRequest
{
/// <summary>
/// 作业号
/// </summary>
public string JobId { get; set; }
/// <summary>
/// 反馈信息
/// </summary>
public string Message { get; set; }
/// <summary>
/// 状态码 111-放货有货 121-取货无货 102-任务正常完成 103-任务人工完成 104-人工取消任务
/// </summary>
public string Code { get; set; }
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.API.Task
{
/// <summary>
/// 向wms反馈任务状态(执行结果)后(完成、重分等)返回的消息
/// </summary>
public class Task_StateRequestResponse
{
/// <summary>
/// 作业号
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 【入库放货有货】重新分配的目标仓位
/// </summary>
public string? TargetLocation { get; set; }
/// <summary>
/// 反馈信息
/// </summary>
public string? Message { get; set; }
/// <summary>
/// 返回码 0-正常 1-异常
/// </summary>
public int Result { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// wcs向wms请求入库
/// </summary>
public class Task_StockInRequest
{
/// <summary>
/// 接口名称
/// </summary>
[JsonIgnore]
public string Name { get; set; }
/// <summary>
/// 任务号
/// </summary>
public string TaskId { get; set; }
/// <summary>
/// 托盘号
/// </summary>
public string PalletId { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public int TaskType { get; set; }
/// <summary>
/// 源站点
/// </summary>
public string SourceLocation { get; set; }
/// <summary>
/// 发送结果 0-成功 1-失败
/// </summary>
[JsonIgnore]
public int Result { get; set; }
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.API.Task
{
/// <summary>
/// 【wcs向wms请求入库后】wms的返回消息
/// </summary>
public class Task_StockInRequestResponse
{
/// <summary>
/// 流水号
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 目标站
/// </summary>
public string? TargetLocation { get; set; }
/// <summary>
/// 反馈信息
/// </summary>
public string? Message { get; set; }
/// <summary>
/// 反馈结果
/// </summary>
public int Result { get; set; }
}
}

37
WPFWCSDemo/App.config Normal file
View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<!--<add name="ConStr" connectionString="data source=127.0.0.1;database=FT_WCS;uid=sa;pwd=123456;" />-->
<add name="ConStr" connectionString="data source=CHINAMI-GPAM8GQ;database=FT479;uid=sa;pwd=123456;TrustServerCertificate=True;" />
</connectionStrings>
<appSettings>
<!--仓库规格-->
<add key="Row" value="10"/>
<add key="Column" value="50"/>
<add key="Floor" value="10"/>
<!--设备连接-->
<add key="WmsIP" value="https:\\127.0.0.1"/>
<add key="WmsPort" value="8080"/>
<add key="Conv" value="127.0.0.1"/>
<add key="Lift1" value="127.0.0.1"/>
<add key="Lift2" value="127.0.0.1"/>
<add key="Lift3" value="127.0.0.1"/>
<add key="RGV1" value="127.0.0.1"/>
<add key="RGV2" value="127.0.0.1"/>
<add key="RGV3" value="127.0.0.1"/>
<add key="Stacker1" value="127.0.0.1"/>
<add key="Stacker2" value="127.0.0.1"/>
<add key="Stacker3" value="127.0.0.1"/>
<!--入库货位分配-->
<add key="StorageAssignment_Default" value="SELECT CARGO_ID FROM CARGOSPACE WHERE ENABLE=1 AND STATUS=1 AND (TRAYCODE='' OR TRAYCODE=null) ORDER BY ROW ASC, FLOOR ASC,[COLUMN] ASC"/>
<add key="StorageAssignment_RowFirst" value="SELECT CARGO_ID FROM CARGOSPACE WHERE ENABLE=1 AND STATUS=1 AND (TRAYCODE='' OR TRAYCODE=null) ORDER BY ROW ASC, FLOOR ASC,[COLUMN] ASC"/>
<add key="StorageAssignment_ColumnFirst" value="SELECT CARGO_ID FROM CARGOSPACE WHERE ENABLE=1 AND STATUS=1 AND (TRAYCODE='' OR TRAYCODE=null) ORDER BY FLOOR ASC, [COLUMN] ASC,[ROW] ASC"/>
<add key="StorageAssignment_FloorFirst" value="SELECT CARGO_ID FROM CARGOSPACE WHERE ENABLE=1 AND STATUS=1 AND (TRAYCODE='' OR TRAYCODE=null) ORDER BY [COLUMN] ASC, row ASC,[FLOOR] ASC"/>
<!--任务类型-->
<add key="TaskType_StockIn" value=""/>
</appSettings>
</configuration>

95
WPFWCSDemo/App.xaml Normal file
View File

@@ -0,0 +1,95 @@
<Application x:Class="WPFWCSDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WPFWCSDemo"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<md:BundledTheme BaseTheme="Light" PrimaryColor="DeepPurple" SecondaryColor="Lime"/>
<ResourceDictionary Source="pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Defaults.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!--页面标题-->
<Style x:Key="screenTitle" TargetType="TextBlock">
<Setter Property="FontSize" Value="30"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Margin" Value="10,5"/>
</Style>
<!--////////////////////图例/////////////////////-->
<!--文本-->
<Style x:Key="standardSymbolText" TargetType="TextBlock">
<Setter Property="FontSize" Value="13"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="5,0,15,0"/>
</Style>
<!--图形-->
<Style x:Key="standardSymbolRectangle" TargetType="Rectangle">
<Setter Property="Stroke" Value="Black"/>
<Setter Property="StrokeThickness" Value="2"/>
<Setter Property="Height" Value="18"/>
<Setter Property="Width" Value="18"/>
<Setter Property="Margin" Value="5,0,5,0"/>
</Style>
<!--主画面-左侧弹出导航栏-->
<Style TargetType="ListBoxItem" x:Key="myListBoxItemStyle">
<Setter Property="FontSize" Value="15"/>
<Setter Property="MinHeight" Value="40"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<!--设置选中后的边框名称-->
<Border x:Name="borderHeader"/>
<!--选中后的名称-->
<Border x:Name="border"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}"/>
</Grid>
<!--悬停/选中动作触发器-->
<ControlTemplate.Triggers>
<!--鼠标悬停-->
<Trigger Property="IsMouseOver" Value="True">
<!--悬停颜色-->
<Setter Property="Background" Value="{DynamicResource PrimaryHueLightBrush}" TargetName="border"/>
<!--透明度-->
<Setter Property="Opacity" Value="0.3" TargetName="border"/>
</Trigger>
<!--鼠标选中-->
<Trigger Property="IsSelected" Value="True">
<!--只显示左侧竖线作为选中标识-->
<Setter Property="BorderThickness" Value="4 0 0 0" TargetName="borderHeader"/>
<!--竖线颜色-->
<Setter Property="BorderBrush" Value="{DynamicResource PrimaryHueDarkBrush}" TargetName="borderHeader"/>
<!--边距-->
<Setter Property="Margin" Value="3" TargetName="borderHeader"/>
<!--选中颜色-->
<Setter Property="Background" Value="{DynamicResource PrimaryHueLightBrush}" TargetName="border"/>
<!--选中透明度-->
<Setter Property="Opacity" Value="0.5" TargetName="border"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--报表样式-->
<!--列标题样式-->
<Style x:Key="defaultDataGridStyle" TargetType="DataGridColumnHeader">
<Setter Property="FontSize" Value="16"/>
<Setter Property="MinWidth" Value="100"/>
<Setter Property="Height" Value="30"/>
</Style>
<!--表格样式-->
<Style x:Key="defaultDataGridTextStyle" TargetType="DataGridCell">
<Setter Property="FontSize" Value="16"/>
<Setter Property="MinWidth" Value="100"/>
<Setter Property="Height" Value="30"/>
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>

193
WPFWCSDemo/App.xaml.cs Normal file
View File

@@ -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
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
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();
}
/// <summary>
/// Quartz调度任务注册
/// </summary>
/// <param name="className">类名</param>
/// <param name="jobName">作业名称</param>
/// <param name="triggerName">触发器名称</param>
/// <param name="group">任务组名称</param>
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<className>()
.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);
}
}
}

View File

@@ -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)
)]

View File

@@ -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
{
/// <summary>
/// wms连接url
/// </summary>
public static string wms = $"{ConfigurationManager.AppSettings["WmsIP"]}:{ConfigurationManager.AppSettings["WmsPort"]}";
/// <summary>
/// 输送机IP
/// </summary>
public static string Conv = $"{ConfigurationManager.AppSettings["Conv"]}";
/// <summary>
/// 1#提升机IP
/// </summary>
public static string lift1 = $"{ConfigurationManager.AppSettings["Lift1"]}";
/// <summary>
/// 2#提升机IP
/// </summary>
public static string lift2 = $"{ConfigurationManager.AppSettings["Lift2"]}";
/// <summary>
/// 1#穿梭车IP
/// </summary>
public static string rGV1 = $"{ConfigurationManager.AppSettings["RGV1"]}";
/// <summary>
/// 2#穿梭车IP
/// </summary>
public static string rGV2 = $"{ConfigurationManager.AppSettings["RGV2"]}";
/// <summary>
/// 1#堆垛机IP
/// </summary>
public static string stacker1 = $"{ConfigurationManager.AppSettings["Stacker1"]}";
/// <summary>
/// 2#堆垛机IP
/// </summary>
public static string stacker2 = $"{ConfigurationManager.AppSettings["Stacker2"]}";
/// <summary>
/// 3#堆垛机IP
/// </summary>
public static string stacker3 = $"{ConfigurationManager.AppSettings["Stacker3"]}";
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
/// <summary>
/// Quartz调度任务注册
/// </summary>
/// <param name="className">类名</param>
/// <param name="jobName">作业名称</param>
/// <param name="triggerName">触发器名称</param>
/// <param name="group">任务组名称</param>
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<className>()
.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);
}
}
}

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.Common
{
/// <summary>
/// RGV取放货站点
/// </summary>
public class RGVStation
{
/// <summary>
/// 环穿运行设备数量
/// </summary>
public const int RGVCount = 13;
/// <summary>
/// H线供实垛 1001
/// </summary>
public const int LineH_Goods_In = 1001;
/// <summary>
/// M线供实垛 1003
/// </summary>
public const int LineM_Goods_In = 1003;
/// <summary>
/// L线供实垛 1005
/// </summary>
public const int LineL_Goods_In = 1005;
/// <summary>
/// G1线供实垛 1007
/// </summary>
public const int LineG1_Goods_In = 1007;
/// <summary>
/// G2线供实垛 1008
/// </summary>
public const int LineG2_Goods_In = 1008;
/// <summary>
/// 立库口送实垛1-1009
/// </summary>
public const int LineToWarehouse1_Out = 1009;
/// <summary>
/// 立库口送实垛2-1010
/// </summary>
public const int LineToWarehouse2_Out = 1010;
/// <summary>
/// G线送实垛-1011
/// </summary>
public const int LineG_Goods_Out = 1011;
/// <summary>
/// H线送实垛-1012
/// </summary>
public const int LineH_Goods_Out = 1012;
//==============================================================================================
/// <summary>
/// 供空托 1013
/// </summary>
public const int LineGH_Pallets_In = 1013;
/// <summary>
/// 放空托1 1002
/// </summary>
public const int LineH_Pallets_Out = 1002;
/// <summary>
/// 放空托2 1004
/// </summary>
public const int LineG_Pallets_Out = 1004;
/// <summary>
/// 放空托3 1006
/// </summary>
public const int LineLM_Pallets_Out = 1006;
}
}

View File

@@ -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<TaskRT> Tasks { get; set; }
public DbSet<TaskView> TaskViews { get; set; }
public DbSet<TaskHistoryView> TaskHistoriesView { get; set; }
public DbSet<TaskHistory> TaskHistories { get; set; }
public DbSet<Alarm> Alarms { get; set; }
public DbSet<AlarmHistory> AlarmHistories { get; set; }
public DbSet<LoadedState> LoadedState { get; set; }
public DbSet<Event_Log> Event_Log { get; set; }
public DbSet<LineState> LineState { get; set; }
public DbSet<ConvRequest> ConvRequest { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["ConStr"].ConnectionString);
}
/// <summary>
/// 配置库与库表的映射关系
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
//TASK表配置
modelBuilder.Entity<TaskRT>(e =>
{
e.ToTable("TASK");
e.HasKey(t => t.TaskId);
});
//TASK_VIEW表配置
modelBuilder.Entity<TaskView>(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<TaskHistory>(e =>
{
e.ToTable("TASK_HISTORY");
e.HasKey(t => t.Id);
});
//TASK_HISTORY_VIEW表配置
modelBuilder.Entity<TaskHistoryView>(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<Alarm>(e =>
{
e.ToTable("ALARM");
e.HasKey(a => a.Point_Id);
});
//ALARM_LOG表配置
modelBuilder.Entity<AlarmHistory>(e =>
{
e.ToTable("ALARM_LOG");
e.HasKey(a => a.Id);
});
//LOADEDSTATE表配置
modelBuilder.Entity<LoadedState>(e =>
{
//e.ToTable("LoadedState");
e.HasKey(a => a.Station);
});
//EVENT_LOG表配置
modelBuilder.Entity<Event_Log>(e =>
{
e.ToTable("EVENT_LOG");
e.HasKey(a => a.Id);
});
//LINESTATE表配置
modelBuilder.Entity<LineState>(e =>
{
e.ToTable("LINESTATE");
e.HasKey(a => a.Name);
});
//CONVREQUEST表配置
modelBuilder.Entity<ConvRequest>(e =>
{
e.ToTable("CONVREQUEST");
e.HasKey(a => a.Id);
});
}
}
}

228
WPFWCSDemo/MainWindow.xaml Normal file
View File

@@ -0,0 +1,228 @@
<Window x:Class="WPFWCSDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
xmlns:local="clr-namespace:WPFWCSDemo"
xmlns:viewmodels="clr-namespace:WPFWCSDemo.ViewModels"
d:DataContext="{d:DesignInstance Type=viewmodels:MainViewModel}"
mc:Ignorable="d"
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
Background="{DynamicResource MaterialDesignPaper}"
FontFamily="微软雅黑"
AllowsTransparency="True"
ResizeMode="CanMinimize"
WindowStartupLocation="CenterScreen"
WindowStyle="None"
Title="MainWindow" Height="900" Width="1600">
<Window.Resources>
<Style x:Key="tblRequestName" TargetType="TextBlock">
<Setter Property="FontSize" Value="11"/>
<Setter Property="Foreground" Value="Gray"/>
<Setter Property="Margin" Value="0 0 10 0"/>
</Style>
<Style x:Key="tblRequestBorder" TargetType="Border">
<Setter Property="Height" Value="11"/>
<Setter Property="Width" Value="11"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0 1 0 0"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Tag}" Value="true">
<Setter Property="Background" Value="LimeGreen"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Tag}" Value="false">
<Setter Property="Background" Value="LightGray"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="tblPermissionBorder" TargetType="Border" BasedOn="{StaticResource tblRequestBorder}">
<Setter Property="Height" Value="11"/>
<Setter Property="Width" Value="11"/>
<Setter Property="CornerRadius" Value="20"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Margin" Value="0 0 0 3"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Tag}" Value="1">
<Setter Property="Background" Value="LimeGreen"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=Tag}" Value="0">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="tblRequestStackPanel" TargetType="StackPanel">
<Setter Property="Orientation" Value="Horizontal"/>
<Setter Property="Margin" Value="0 0 20 0"/>
</Style>
</Window.Resources>
<md:DialogHost DialogTheme="Dark" Identifier="RootDialog" SnackbarMessageQueue="{Binding ElementName=MainSnackbar, Path=MessageQueue}">
<!--左侧弹出导航绑定-->
<md:DrawerHost x:Name="drawerHost" IsLeftDrawerOpen="{Binding ElementName=menuToggleButton,Path=IsChecked}">
<!--左侧导航对话框-->
<md:DrawerHost.LeftDrawerContent>
<!--左侧导航面板-->
<DockPanel Width="240">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<StackPanel>
<StackPanel.Background>
<SolidColorBrush Opacity=".5"/>
</StackPanel.Background>
<Image Source="..\Resources\yctd.jpg" Margin="30 40">
<!--<Image.Clip>
<EllipseGeometry Center="40,40" RadiusX="40" RadiusY="40"/>
</Image.Clip>-->
</Image>
</StackPanel>
<!--左侧导航列表-->
<ListBox x:Name="menuBar" Grid.Row="1" ItemsSource="{Binding MenuBar}" Background="Lavender" SelectedItem="{Binding SelectedMenuBar, Mode=TwoWay}" ItemContainerStyle="{StaticResource myListBoxItemStyle}">
<!--添加行为触发(例:通过选中项的改变触发某个事件)-->
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<!--绑定动作对象的属性-->
<i:InvokeCommandAction Command="{Binding NavigationCommand}" CommandParameter="{Binding SelectedMenuBar.NameSpace}"/>
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeftButtonUp">
<!--绑定动作对象的属性-->
<i:InvokeCommandAction Command="{Binding NavigationCommand}" CommandParameter="{Binding SelectedMenuBar.NameSpace}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Background="Transparent" Margin="5">
<md:PackIcon Kind="{Binding Icon}" Margin="20,10" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Title}" Margin="10" VerticalAlignment="Center" FontFamily="微软雅黑"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<DockPanel Height="400" Grid.Row="2" Background="Lavender">
</DockPanel>
</Grid>
</DockPanel>
</md:DrawerHost.LeftDrawerContent>
<DockPanel>
<md:ColorZone x:Name="colorZone" CornerRadius="5" Padding="16" md:ElevationAssist.Elevation="Dp4" DockPanel.Dock="Top" Mode="PrimaryMid" Margin="0,-2">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--顶部导航【左侧按钮】-->
<StackPanel Orientation="Horizontal">
<ToggleButton x:Name="menuToggleButton" AutomationProperties.Name="HamburgerToggleButton" IsChecked="False" Style="{StaticResource MaterialDesignHamburgerToggleButton}" ToolTip="菜单"/>
<Button Margin="24,0,0,0" md:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self},Path=Foreground,Converter={StaticResource BrushRoundConverter}}" Command="{Binding GoBackCommand}" Content="{md:PackIcon Kind=ArrowLeftBold,Size=26}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}},Path=(TextElement.Foreground)}" Style="{StaticResource MaterialDesignToolButton}" ToolTip="后退"/>
<Button Margin="16,0,0,0" md:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}" Command="{Binding GoForwardCommand}" Content="{md:PackIcon Kind=ArrowRightBold, Size=26}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" Style="{StaticResource MaterialDesignToolButton}" ToolTip="前进" />
<Button Margin="14,0,0,0" md:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}" Command="{Binding HomeCommand}" Content="{md:PackIcon Kind=Home, Size=26}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" Style="{StaticResource MaterialDesignToolButton}" ToolTip="主画面" />
<Button x:Name="btnLog" Margin="16,0,0,0" md:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}" Command="{Binding OpenLogCommand}" Content="{md:PackIcon Kind=NoteMultiple, Size=20}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" Style="{StaticResource MaterialDesignToolButton}" ToolTip="日志" />
<Button x:Name="btnSetting" Margin="16,0,0,0" md:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}" Command="{Binding OpenSettingCommand}" Content="{md:PackIcon Kind=Wrench, Size=22}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" Style="{StaticResource MaterialDesignToolButton}" ToolTip="设置" />
<!--<Button x:Name="btnLine" Margin="16,0,0,0" md:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}" Command="{Binding OpenSettingCommand}" Content="{md:PackIcon Kind=WrenchOutline, Size=22}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" Style="{StaticResource MaterialDesignToolButton}" ToolTip="Setting" />-->
<Button x:Name="LineControl" Margin="16,0,0,0" md:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}" Command="{Binding LineControlCommand}" Content="{md:PackIcon Kind=Highway, Size=24}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" Style="{StaticResource MaterialDesignToolButton}" ToolTip="输送线管理"/>
<Button x:Name="Helper" Margin="16,0,0,0" md:RippleAssist.Feedback="{Binding RelativeSource={RelativeSource Self}, Path=Foreground, Converter={StaticResource BrushRoundConverter}}" Command="{Binding HelperCommand}" Content="{md:PackIcon Kind=HelpCircle, Size=24}" Foreground="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground)}" Style="{StaticResource MaterialDesignToolButton}" ToolTip="帮助"/>
</StackPanel>
<!--顶部导航【中间标题】-->
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock VerticalAlignment="Center" AutomationProperties.Name="Material Design In XAML Toolkit" FontSize="26" FontWeight="Bold" Text="滁州东鹏饮料二厂环穿调度系统"/>
</StackPanel>
<!--顶部导航【右侧按钮】-->
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="btnMin" Width="30" Height="30" Content="{md:PackIcon Kind=Minus, Size=16}" Margin="2" Style="{StaticResource MaterialDesignFloatingActionButton}"/>
<Button x:Name="btnMax" Width="30" Height="30" Content="{md:PackIcon Kind=WindowMaximize, Size=16}" Margin="2" Style="{StaticResource MaterialDesignFloatingActionButton}"/>
<Button x:Name="btnClose" Background="DarkOrange" Width="30" Height="30" Content="{md:PackIcon Kind=Close, Size=16}" Margin="2" Style="{StaticResource MaterialDesignFloatingActionButton}"/>
</StackPanel>
</Grid>
</md:ColorZone>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="auto"/>
</Grid.RowDefinitions>
<Frame x:Name="mainFrame" Margin="20" NavigationUIVisibility="Hidden"/>
<StackPanel Grid.Row="1" Style="{StaticResource tblRequestStackPanel}" Margin="50 0 30 0">
<TextBlock Text="地面允许下发" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding Permission_Station}" Style="{StaticResource tblPermissionBorder}"/>
</StackPanel>
<Rectangle Grid.Row="1" Width=".5" Height="15" Fill="DimGray" Margin="185 0 0 3" HorizontalAlignment="Left"/>
<StackPanel Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="160 0 0 5" Orientation="Horizontal">
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1001请求出垛" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding GetRequest_1001}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1003请求出垛" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding GetRequest_1003}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1005请求出垛" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding GetRequest_1005}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1007请求出垛" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding GetRequest_1007}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1008请求出垛" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding GetRequest_1008}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1009允许进垛" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding PutRequest_1009}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1010允许进垛" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding PutRequest_1010}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<Rectangle Width=".5" Height="15" Fill="DimGray" Margin="40 0 60 0"/>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1013请求入栈" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding GetRequest_1013}" Style="{StaticResource tblRequestBorder}" Visibility="{Binding GetRequest_LineAB_Visible}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1002请求出栈" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding PutRequest_1002}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1004请求入栈" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding PutRequest_1004}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
<StackPanel Style="{StaticResource tblRequestStackPanel}">
<TextBlock Text="1006请求出栈" Style="{StaticResource tblRequestName}"/>
<Border Tag="{Binding PutRequest_1006}" Style="{StaticResource tblRequestBorder}"/>
</StackPanel>
</StackPanel>
</Grid>
</DockPanel>
</md:DrawerHost>
</md:DialogHost>
</Window>

View File

@@ -0,0 +1,79 @@
using System.Windows;
using System.Windows.Input;
using WPFWCSDemo.Utilities;
using WPFWCSDemo.ViewModels;
using WPFWCSDemo.Views;
namespace WPFWCSDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
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
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.Models
{
/// <summary>
/// 货位状态表
/// </summary>
public class Cargo
{
/// <summary>
/// 货位编码
/// </summary>
public string Cargo_ID { get; set; }
/// <summary>
/// 货位名称
/// </summary>
public string Cargo_Name { get; set; }
/// <summary>
/// 货位区域
/// </summary>
public string Cargo_Area { get; set; }
/// <summary>
/// 货位状态
/// </summary>
public int Status { get; set; }
/// <summary>
/// 条码
/// </summary>
public string TrayCode { get; set; }
/// <summary>
/// 排
/// </summary>
public int Row { get; set; }
/// <summary>
/// 列
/// </summary>
public int Column { get; set; }
/// <summary>
/// 层
/// </summary>
public int Floor { get; set; }
/// <summary>
/// 巷道
/// </summary>
public int Road { get; set; }
/// <summary>
/// 是否可用
/// </summary>
public int Enable { get; set; }
/// <summary>
/// 更新时间
/// </summary>
public string UpdateTime { get; set; }
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.Models
{
/// <summary>
/// 看板页左侧部分任务展示
/// </summary>
public class DataInfoTaskAsc
{
/// <summary>
/// 作业号
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 任务号
/// </summary>
public string? TaskId { get; set; }
/// <summary>
/// 托盘条码
/// </summary>
public string? PalletId { get; set; }
/// <summary>
/// 调度状态
/// </summary>
public string? ScheduleState { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public int? TaskType { get; set; }
/// <summary>
/// 源站点
/// </summary>
public string? SourceLocation { get; set; }
/// <summary>
/// 目标站点
/// </summary>
public string? TargetLocation { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 看板顶部任务
/// </summary>
public partial class DataInfoTaskbar : ObservableObject
{
/// <summary>
/// 图标
/// </summary>
public string? Icon { get; set; }
/// <summary>
/// 标题
/// </summary>
public string? Title { get; set; }
/// <summary>
/// 内容
/// </summary>
[ObservableProperty]
//public int? Content { get; set; }
public int? _content;
/// <summary>
/// 颜色
/// </summary>
[ObservableProperty]
//public string? Color { get; set; }
public string? _color;
/// <summary>
/// 触发目标(点击可能触发一些功能,增加命名空间)
/// </summary>
public string? Target { get; set; }
}
}

View File

@@ -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
{
//*************************************************写入*************************************************
/// <summary>
/// 下发任务号
/// </summary>
public int Write_TaskNumber { get; set; }
/// <summary>
/// 下发穿梭车编号
/// </summary>
public int Write_DeviceNumber { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public int Write_TaskType { get; set; }
/// <summary>
/// 设备状态
/// </summary>
public int Write_DeviceState { get; set; }
/// <summary>
/// 下发取货站点
/// </summary>
public string? Write_SourceLocation { get; set; }
/// <summary>
/// 下发放货站点
/// </summary>
public string? Write_TargetLocation { get; set; }
/// <summary>
/// 下发完成
/// </summary>
public int Write_SendFinish { get; set; }
/// <summary>
/// 下发校验码
/// </summary>
public int Write_Checksum { get; set; }
}
}

View File

@@ -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
{
//*************************************************读取*************************************************
/// <summary>
/// 标题
/// </summary>
public string? Title { get; set; }
/// <summary>
/// 编号
/// </summary>
public int Number { get; set; }
/// <summary>
/// 操作模式 0-未知 1-工作 2-手动
/// </summary>
public short Read_Mode { get; set; }
/// <summary>
/// 设备状态 0-未知 1-工作 2-手动 3-自动待机 100-报警
/// </summary>
public short Read_DeviceState { get; set; }
/// <summary>
/// 执行阶段 1-取货途中,2-取货,3-送货途中,4-送货,5-完成
/// </summary>
public short Read_Phase { get; set; }
/// <summary>
/// 任务号
/// </summary>
public int Read_TaskNumber { get; set; }
/// <summary>
/// 允许下发 false-禁止 true-允许
/// </summary>
public bool Read_Permission { get; set; }
/// <summary>
/// 当前站点
/// </summary>
public string? Read_CurrentLocation { get; set; }
/// <summary>
/// 取货站点
/// </summary>
public string? Read_SourceLocation { get; set; }
/// <summary>
/// 放货站点
/// </summary>
public string? Read_TargetLocation { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public byte Read_TaskType { get; set; }
/// <summary>
/// BPS
/// </summary>
public int Read_BPSNumber { get; set; }
/// <summary>
/// 运行里程
/// </summary>
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);
}
}
}

View File

@@ -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
{
/// <summary>
/// 下发任务号
/// </summary>
public int Write_TaskNumber { get; set; }
/// <summary>
/// 下发穿梭车编号 常规任务-0 其他任务-环穿编号
/// </summary>
public int Write_DeviceNumber { get; set; }
/// <summary>
/// 任务类型 1-常规任务 2-小车回休息区 3-休息区小车上轨道
/// </summary>
public int Write_TaskType { get; set; }
/// <summary>
/// 下发取货站点
/// </summary>
public int Write_SourceLocation { get; set; }
/// <summary>
/// 下发放货站点
/// </summary>
public int Write_TargetLocation { get; set; }
/// <summary>
/// 下发完成
/// </summary>
public int Write_SendFinish { get; set; }
/// <summary>
/// 下发校验码-所有字节求和
/// </summary>
public short Write_Checksum { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 允许下发 0-禁止下发 1-允许下发
/// </summary>
public int Read_Permission { get; set; }
/// <summary>
/// 下发状态 0-其他,1-正常接收,2-接收异常
/// </summary>
public int Read_SendState { get; set; }
/// <summary>
/// 任务号
/// </summary>
public int Read_TaskNumber { get; set; }
//---------------------------------供实垛侧站点---------------------------------
//---------------------------------供实垛侧站点---------------------------------
//---------------------------------供实垛侧站点---------------------------------
/// <summary>
/// 取货请求---供实垛-1001
/// </summary>
public bool Read_GetRequest_1001 { get; set; }
/// <summary>
/// 1001供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1001 { get; set; }
/// <summary>
/// 取货请求---供实垛-1003
/// </summary>
public bool Read_GetRequest_1003 { get; set; }
/// <summary>
/// 1003供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1003 { get; set; }
/// <summary>
/// 取货请求---供实垛-1005
/// </summary>
public bool Read_GetRequest_1005 { get; set; }
/// <summary>
/// 1005供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1005 { get; set; }
/// <summary>
/// 取货请求---D线供实垛-1007
/// </summary>
public bool Read_GetRequest_1007 { get; set; }
/// <summary>
/// 1007供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1007 { get; set; }
/// <summary>
/// 取货请求---D线供实垛-1008
/// </summary>
public bool Read_GetRequest_1008 { get; set; }
/// <summary>
/// 1008供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1008 { get; set; }
//-------------------------------------------------------------------------------
/// <summary>
/// 放货请求---立库入口1供实垛-1009
/// </summary>
public bool Read_PutRequest_1009 { get; set; }
/// <summary>
/// 1009供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1009 { get; set; }
/// <summary>
/// 放货请求---立库入口2供实垛-1010
/// </summary>
public bool Read_PutRequest_1010 { get; set; }
/// <summary>
/// 1010供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1010 { get; set; }
/// <summary>
/// 放货请求---供实垛-1011
/// </summary>
public bool Read_PutRequest_1011 { get; set; }
/// <summary>
/// 1011供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1011 { get; set; }
/// <summary>
/// 放货请求---供实垛-1012
/// </summary>
public bool Read_PutRequest_1012 { get; set; }
/// <summary>
/// 1012供实垛系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1012 { get; set; }
//==========================================================================
/// <summary>
/// 空托请求---供空托-1013
/// </summary>
public bool Read_GetRequest_1013 { get; set; }
/// <summary>
/// 1013供空托系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1013 { get; set; }
//-------------------------------------------------------------------
/// <summary>
/// 空托请求---放空托-1002
/// </summary>
public bool Read_PutRequest_1002 { get; set; }
/// <summary>
/// 1002供空托系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1002 { get; set; }
/// <summary>
/// 空托请求---放空托-1004
/// </summary>
public bool Read_PutRequest_1004 { get; set; }
/// <summary>
/// 1004供空托系统正常 true-正常 false-异常
/// </summary>
public bool Read_IsNotException_1004 { get; set; }
/// <summary>
/// 空托请求---放空托-1006
/// </summary>
public bool Read_PutRequest_1006 { get; set; }
/// <summary>
/// 1006供空托系统正常 true-正常 false-异常
/// </summary>
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);
}
}
}

View File

@@ -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
{
}
}

View File

@@ -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
{
}
}

View File

@@ -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
{
/// <summary>
/// A线取货请求
/// </summary>
public bool A_InRequest { get; set; }
/// <summary>
/// A线供实垛系统正常
/// </summary>
public bool A_Exception { get; set; }
/// <summary>
/// B线取货请求
/// </summary>
public bool B_InRequest { get; set; }
/// <summary>
/// B线回空托请求
/// </summary>
public bool B_BackRequest { get; set; }
/// <summary>
/// B线供实垛系统正常
/// </summary>
public bool B_Exception { get; set; }
/// <summary>
/// C线取货请求
/// </summary>
public bool C_InRequest { get; set; }
/// <summary>
/// C线回空托请求
/// </summary>
public bool C_BackRequest { get; set; }
/// <summary>
/// C线供实垛系统正常
/// </summary>
public bool C_Exception { get; set; }
/// <summary>
/// D线取货请求
/// </summary>
public bool D_InRequest { get; set; }
/// <summary>
/// D线供实垛系统正常
/// </summary>
public bool D_Exception { get; set; }
}
}

View File

@@ -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
{
}
}

View File

@@ -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
{
/// <summary>
/// AB口请求出空托
/// </summary>
public bool AB_OutRequest { get; set; }
/// <summary>
/// AB输送机无故障
/// </summary>
public bool AB_Exception { get; set; }
/// <summary>
/// CD口请求出空托
/// </summary>
public bool CD_OutRequest { get; set; }
/// <summary>
/// CD输送机无故障
/// </summary>
public bool CD_Exception { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 任务号
/// </summary>
public int Read_TaskNumber { get; set; }
/// <summary>
/// 输送到位
/// </summary>
public int Read_InPosition { get; set; }
/// <summary>
/// 输送请求
/// </summary>
public int Read_TransRequest { get; set; }
}
}

19
WPFWCSDemo/Models/Menu.cs Normal file
View File

@@ -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; }
}
}

View File

@@ -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
{
/// <summary>
/// 标题
/// </summary>
public string Title { get; set; }
/// <summary>
/// 内容
/// </summary>
public string Message { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.Models
{
/// <summary>
/// 系统导航菜单实体类
/// </summary>
public class SettingMenu
{
/// <summary>
/// 菜单图标
/// </summary>
public string Icon { get; set; }
/// <summary>
/// 菜单名称
/// </summary>
public string Title { get; set; }
/// <summary>
/// 菜单命名空间
/// </summary>
public string NameSpace { get; set; }
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace WPFWCSDemo.Models.Tables
{
/// <summary>
/// 实时报警
/// </summary>
public class Alarm
{
/// <summary>
/// 报警名称
/// </summary>
[Key]
public string Point_Id { get; set; }
/// <summary>
/// 报警信息
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 优先级
/// </summary>
public string? Priority { get; set; }
/// <summary>
/// 设备类别
/// </summary>
public string? Device_Id { get; set; }
/// <summary>
/// 开始时间
/// </summary>
public DateTime? Gen_Time { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 历史报警
/// </summary>
public class AlarmHistory
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[AllowNull]
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>
/// 报警名称
/// </summary>
public string? Point_Id { get; set; }
/// <summary>
/// 报警信息
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 优先级
/// </summary>
[AllowNull]
public string? Priority { get; set; }
/// <summary>
/// 设备类别
/// </summary>
public string? Device_Id { get; set; }
/// <summary>
/// 开始时间
/// </summary>
[AllowNull]
public DateTime? Gen_Time { get; set; }
/// <summary>
/// 复位时间
/// </summary>
//public DateTime? Reset_Time { get; set; }
/// <summary>
/// 删除时间
/// </summary>
//public DateTime? Delete_Time { get; set; }
/// <summary>
/// 结束时间
/// </summary>
public DateTime? End_Time { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 输送口请求
/// </summary>
public class ConvRequest
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[AllowNull]
[JsonIgnore]
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>
/// 1001
/// </summary>
public int Conv_Goods_In_1001 { get; set; }
/// <summary>
/// 1003
/// </summary>
public int Conv_Goods_In_1003 { get; set; }
/// <summary>
/// 1005
/// </summary>
public int Conv_Goods_In_1005 { get; set; }
/// <summary>
/// 1007
/// </summary>
public int Conv_Goods_In_1007 { get; set; }
/// <summary>
/// 1008
/// </summary>
public int Conv_Goods_In_1008 { get; set; }
///// <summary>
///// 立库1-1009
///// </summary>
//public int Conv_Goods_Out_1009 { get; set; }
///// <summary>
///// 立库1-1010
///// </summary>
//public int Conv_Goods_Out_1010 { get; set; }
///// <summary>
///// 1011
///// </summary>
//public int Conv_Goods_Out_1011 { get; set; }
///// <summary>
///// 1012
///// </summary>
//public int Conv_Goods_Out_1012 { get; set; }
/// <summary>
/// 时间
/// </summary>
[JsonIgnore]
public string? Time { get; set; }
/// <summary>
/// 1013
/// </summary>
public int Conv_Pallet_In_1013 { get; set; }
/// <summary>
/// 1002
/// </summary>
public int Conv_Pallet_Out_1002 { get; set; }
/// <summary>
/// 1004
/// </summary>
public int Conv_Pallet_Out_1004 { get; set; }
/// <summary>
/// 1006
/// </summary>
public int Conv_Pallet_Out_1006 { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 事件标识
/// </summary>
[JsonIgnore]
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>
/// 事件信息
/// </summary>
public string? Message { get; set; }
/// <summary>
/// 时间
/// </summary>
public string? TimeStamp { get; set; }
/// <summary>
/// 操作角色
/// </summary>
public string? UserId { get; set; }
/// <summary>
/// 事件类型(登录、操作、错误等)
/// </summary>
public string? Type { get; set; }
/// <summary>
/// 事件来源(名称、控件等)
/// </summary>
public string? Source { get; set; }
/// <summary>
/// 重要程度(信息、警告、错误等)
/// </summary>
public string? Level { get; set; }
/// <summary>
/// 事件状态(完成、失败等)
/// </summary>
public string? Status { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 输送线名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 源站
/// </summary>
public int Source { get; set; }
/// <summary>
/// 目标站
/// </summary>
public int Target { get; set; }
/// <summary>
/// 输送线是否允许生成任务(由上位控制) 1-正常 0-禁止
/// </summary>
public int IsEnable { get; set; }
/// <summary>
/// 输送线功能
/// </summary>
public string? Property { get; set; }
/// <summary>
/// 备注
/// </summary>
public string? Description { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 站点
/// </summary>
public int Station { get; set; }
/// <summary>
/// 生成任务时间
/// </summary>
public DateTime? GenerationTime { get; set; }
/// <summary>
/// 开始取货时间
/// </summary>
public DateTime? LoadingTime { get; set; }
/// <summary>
/// 取货完成时间
/// </summary>
public DateTime? LoadedTime { get; set; }
/// <summary>
/// 开发放货时间
/// </summary>
public DateTime? PuttingTime { get; set; }
}
}

View File

@@ -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();
/// <summary>
/// 作业号
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 任务号
/// </summary>
public string? TaskId { get; set; }
/// <summary>
/// 条码
/// </summary>
public string? PalletId { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public string? TaskType { get; set; }
/// <summary>
/// 源站
/// </summary>
public string? SourceLocation { get; set; }
/// <summary>
/// 目标站
/// </summary>
public string? TargetLocation { get; set; }
/// <summary>
/// 优先级
/// </summary>
public int? Priority { get; set; }
/// <summary>
/// 任务状态
/// </summary>
public string? TaskState { get; set; }
/// <summary>
/// 调度状态
/// </summary>
public string? ScheduleState { get; set; }
/// <summary>
/// 生成时间
/// </summary>
public DateTime? CreateTime { get; set; }
/// <summary>
/// 调度时间
/// </summary>
public DateTime? ScheduleTime { get; set; }
/// <summary>
/// 完成时间
/// </summary>
public DateTime? FinishTime { get; set; }
/// <summary>
/// 反馈状态
/// </summary>
public string? ReportState { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 作业号
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 任务号
/// </summary>
public string? TaskId { get; set; }
/// <summary>
/// 条码
/// </summary>
public string? PalletId { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public string? TaskType { get; set; }
/// <summary>
/// 源站
/// </summary>
public string? SourceLocation { get; set; }
/// <summary>
/// 目标站
/// </summary>
public string? TargetLocation { get; set; }
/// <summary>
/// 优先级
/// </summary>
public int? Priority { get; set; }
/// <summary>
/// 任务状态
/// </summary>
public string? TaskState { get; set; }
/// <summary>
/// 调度状态
/// </summary>
public string? ScheduleState { get; set; }
/// <summary>
/// 生成时间
/// </summary>
public DateTime? CreateTime { get; set; }
/// <summary>
/// 调度时间
/// </summary>
public DateTime? ScheduleTime { get; set; }
/// <summary>
/// 完成时间
/// </summary>
public DateTime? FinishTime { get; set; }
/// <summary>
/// 反馈状态
/// </summary>
public string? ReportState { get; set; }
}
}

View File

@@ -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
{
/// <summary>
/// 作业号
/// </summary>
public string? JobId { get; set; }
/// <summary>
/// 任务号
/// </summary>
public string TaskId { get; set; }
///// <summary>
///// 任务号
///// </summary>
//public string TaskIdString { get; set; }
/// <summary>
/// 条码
/// </summary>
public string? PalletId { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public int TaskType { get; set; }
/// <summary>
/// 源站
/// </summary>
public string? SourceLocation { get; set; }
/// <summary>
/// 目标站
/// </summary>
public string? TargetLocation { get; set; }
/// <summary>
/// 优先级 1→3 高→低
/// </summary>
//public int Priority { get; set; }
/// <summary>
/// 任务状态
/// </summary>
public string? TaskState { get; set; }
/// <summary>
/// 调度状态
/// </summary>
public string? ScheduleState { get; set; }
/// <summary>
/// 生成时间
/// </summary>
[AllowNull]
public DateTime CreateTime { get; set; }
/// <summary>
/// 调度时间
/// </summary>
[AllowNull]
public DateTime ScheduleTime { get; set; }
/// <summary>
/// 报告状态
/// </summary>
//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);
}
}
}

View File

@@ -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
{
/// <summary>
/// 作业号
/// </summary>
[ObservableProperty]
//public string? JobId { get; set; }
public string? _jobId;
/// <summary>
/// 任务号
/// </summary>
public string? TaskId { get; set; }
/// <summary>
/// 条码
/// </summary>
public string? PalletId { get; set; }
/// <summary>
/// 任务类型
/// </summary>
public string? TaskType { get; set; }
/// <summary>
/// 源站
/// </summary>
public string? SourceLocation { get; set; }
/// <summary>
/// 目标站
/// </summary>
public string? TargetLocation { get; set; }
/// <summary>
/// 优先级 1→3 高→低
/// </summary>
public int Priority { get; set; }
/// <summary>
/// 任务状态
/// </summary>
[ObservableProperty]
//public string? TaskState { get; set; }
public string? _taskState;
/// <summary>
/// 调度状态
/// </summary>
[ObservableProperty]
//public string? ScheduleState { get; set; }
public string? _scheduleState;
/// <summary>
/// 生成时间
/// </summary>
public DateTime? CreateTime { get; set; }
/// <summary>
/// 调度时间
/// </summary>
public DateTime? ScheduleTime { get; set; }
/// <summary>
/// 报告状态
/// </summary>
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);
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Media;
namespace WPFWCSDemo.Models
{
/// <summary>
/// 仓位状态画面展示
/// </summary>
public class WareHouseInfo
{
/// <summary>
/// 填充颜色
/// </summary>
public System.Windows.Media.Brush FillColor { get; set; }
/// <summary>
/// 鼠标悬停提示
/// </summary>
public string Tooltip { get; set; }
/// <summary>
/// 悬停放大动画缩放中心点
/// </summary>
public System.Drawing.Point RenderCenter { get; set; }
/// <summary>
/// X坐标
/// </summary>
public double X { get; set; }
/// <summary>
/// Y坐标
/// </summary>
public double Y { get; set; }
}
}

View File

@@ -0,0 +1,60 @@
<UserControl x:Class="WPFWCSDemo.Resources.DevicesTemplate.StackerTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WPFWCSDemo.Resources.DevicesTemplate"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Rectangle Fill="Gold" Width="120" Height="110"/>
<Rectangle Fill="Gold" Width="220" Height="70" Margin="-20 0 0 0"/>
<Rectangle Fill="Gold" Width="200" Height="55" Margin="-160 0 0 0"/>
<Rectangle Fill="Gold" Width="200" Height="15" Margin="70 0 0 0"/>
<Rectangle Fill="Black" Width="10" Height="80" Margin="70 0 0 0"/>
<Rectangle Fill="Black" Width="10" Height="80" Margin="-70 0 0 0"/>
<Rectangle Fill="RoyalBlue" Width="90" Height="90" Margin="0 0 0 0" RadiusX="10" RadiusY="10" Visibility="Visible"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -60 60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -60 37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -60 12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -60 -12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -60 -37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -60 -60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -37 60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -37 37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -37 12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -37 -12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -37 -37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -37 -60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -12 60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -12 37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -12 12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -12 -12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -12 -37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 -12 -60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 60 60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 60 37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 60 12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 60 -12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 60 -37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 60 -60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 37 60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 37 37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 37 12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 37 -12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 37 -37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 37 -60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 12 60 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 12 37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 12 12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 12 -12 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 12 -37 0"/>
<Rectangle Fill="Gold" Width="8" Height="8" Margin="0 12 -60 0"/>
</Grid>
</UserControl>

View File

@@ -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
{
/// <summary>
/// StackerTemplate.xaml 的交互逻辑
/// </summary>
public partial class StackerTemplate : UserControl
{
public StackerTemplate()
{
InitializeComponent();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
WPFWCSDemo/S7.Net.dll Normal file

Binary file not shown.

View File

@@ -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
{
/// <summary>
/// 任务校验
/// </summary>
public class Check
{
static int deviceCount = RGVStation.RGVCount;
/// <summary>
/// 生成【空托】任务条件校验
/// </summary>
/// <param name="sourceLocation">源站点(可表示某条输送线)</param>
/// <param name="targetLocation">目标站点(可表示某条输送线)</param>
/// <param name="isNotException">输送口是否正常 true-系统正常 false-系统异常</param>
/// <returns>是否满足生成任务条件 true-可生成 false-禁止生成</returns>
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;
}
/// <summary>
/// 生成【实垛】任务校验条件
/// </summary>
/// <param name="sourceLocation">源站点(可表示某条输送线)</param>
/// <param name="isNotException">输送口是否正常 true-系统正常 false-系统异常</param>
/// <returns>是否满足生成任务条件 true-可生成 false-禁止生成</returns>
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;
}
/// <summary>
/// 防错机制【用于避免请求延迟的重复下发】--- 检测上一条【实垛】任务放货时间与当前时间是否相差x秒以上
/// </summary>
/// <param name="location">站点</param>
/// <returns> true-相差大于x秒 false-相差小于x秒</returns>
public static bool CheckSendTaskTimeInterval(int location)
{
int diff = -15;
using var context = new AppDbContext();
var loadedState = context
.Set<LoadedState>()
.Where(t => t.Station == location)
.FirstOrDefault();
if (DateTime.Now.AddSeconds(diff) >= loadedState!.LoadingTime)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 防错机制【用于避免请求延迟的重复下发】--- 检测上一条【空托】任务放货时间(完成时间)与当前时间是否相差x秒以上
/// </summary>
/// <param name="location">站点</param>
/// <returns> true-相差大于x秒 false-相差小于x秒</returns>
public static bool CheckSendTaskTimeInterval(int location, int num)
{
int diff = -30;
using var context = new AppDbContext();
var loadedState = context
.Set<LoadedState>()
.Where(t => t.Station == location)
.FirstOrDefault();
if (DateTime.Now.AddSeconds(diff) >= loadedState!.PuttingTime)
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// 防错机制【重复下发】--- 检测已经生成但未下发的任务是否存在
/// </summary>
/// <param name="sourceLocation">源站点</param>
/// <returns> true-同目标站点生成任务时间间隔合法 false-时间间隔过短</returns>
public static bool CheckSendTaskIsRepeat(int location, int type)
{
using var context = new AppDbContext();
//实垛
if (type == TaskType.Goods)
{
//生成的上一条【实垛】任务且同一个源站点 ---> 查找符合条件的记录
var count = context
.Set<TaskRT>()
.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<TaskRT>()
.Where(t => t.TargetLocation == location.ToString())
.Count();
if (count1 < 1)
{
return true;
}
}
return false;
}
/// <summary>
/// 计算某个输送口请求的值的和---用于确定该输送口在一定时间内请求是否已经复位
/// 用于避免信号也许存在的不稳定(跳变)的情况
/// </summary>
/// <param name="Location">源站点/目标站点---表示对应列</param>
/// <param name="count">计算的时间间隔(单位:秒)</param>
/// <returns>true-无请求---已复位 false-请求存在-未复位</returns>
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;
}
}
/// <summary>
/// 手动禁止某条输送线下发任务(根据名称)
/// </summary>
/// <param name="name">输送线名称</param>
/// <returns>0-禁止 1-允许</returns>
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;
}
/// <summary>
/// 手动禁止某条输送线下发任务(根据目标站)
/// </summary>
/// <param name="source">源站点</param>
/// <returns>0-禁止 1-允许</returns>
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;
}
/// <summary>
/// 遍历环穿是否有某条输送线正在执行的(栈板)任务---即只要有该输送口的任务则不能生成新任务
/// 判断条件 1.站点 2.执行阶段 3.允许下发
/// (该方法会直接读取小车参数)
/// </summary>
/// <param name="sourceLocation">源站点(1至2位编号)</param>
/// <returns>false-存在执行中的任务的设备 true-无在执行任务的设备</returns>
public static bool GetRGVTaskForPalletsIsExist(int targetLocation)
{
List<CircleRGVState>? 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;
}
/// <summary>
/// 遍历环穿是否有某条输送线正在执行的(实垛)任务---某站点输送线存在【取货阶段】任务时不能生成新任务
/// 判断条件:
/// 1.站点匹配
/// 2.执行阶段--->取货阶段
/// 3.允许下发
/// (该方法会直接从地面站读取小车参数)
/// </summary>
/// <param name="sourceLocation">源站点(1至2位编号)</param>
/// <returns>false-存在执行任务的设备(不能下发) true-无执行中的任务的设备(可下发)</returns>
public static bool GetRGVTaskForGoodsIsExist(int sourceLocation)
{
List<CircleRGVState> 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;
}
/// <summary>
/// 检查是否存在已经生成的处于【取货阶段】的【栈板】任务 --- 源站点每次请求仅生成一条任务
/// </summary>
/// <returns>true-无符合条件的任务(即可生成新任务) false-存在符合条件的任务</returns>
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;
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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
{
/// <summary>
/// 执行任务调度
/// </summary>
[DisallowConcurrentExecution]
public class Excute
{
static int count1;
static int count2;
/// <summary>
/// 执行任务
/// </summary>
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}环穿下发失败");
}
}
}
}

View File

@@ -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
{
/// <summary>
/// 生成任务
/// </summary>
[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);
}
}
/// <summary>
/// 插入一条新任务
/// </summary>
/// <param name="sourceLocation">源站点</param>
/// <param name="taskType">任务类型 10-实垛 11-空托</param>
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}");
}
}
}

View File

@@ -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
{
/// <summary>
/// 更新任务调度
/// </summary>
public class Update
{
static int deviceCount = RGVStation.RGVCount;
/// <summary>
/// 根据任务号获取正在执行任务环穿的编号
/// </summary>
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;
}
/// <summary>
/// 根据【执行阶段】实时更新环穿【调度状态】
/// </summary>
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;
}
}
}

View File

@@ -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;
/// <summary>
/// 记录输送口请求值
/// </summary>
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)}");
}
/// <summary>
/// 检测plc网络
/// </summary>
/// <param name="ipAddress">ip地址</param>
/// <param name="timeout"></param>
/// <returns></returns>
public static async Task<bool> 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;
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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
{
}
}

View File

@@ -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
{
/// <summary>
/// 全局任务
/// </summary>
public static class GlobalTask
{
/// <summary>
/// 1\4\7\10月1日自动备份
/// </summary>
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();
}
}
}
}

View File

@@ -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
{
/// <summary>
/// 任务移除
/// </summary>
public class Delete
{
/// <summary>
/// 完成的调度任务从实时表删除记入历史记录
/// </summary>
/// <param name="taskRT">当前已完成的任务</param>
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();
}
///// <summary>
///// 防错机制【可下发任务标志】---如果当前某条线无输送任务,则重置该输送线请求标志为true
///// </summary>
//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;
//}
}
}

View File

@@ -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
{
/// <summary>
/// 任务完成
/// </summary>
public class Finish
{
/// <summary>
/// 更新【任务自动完成】状态
/// </summary>
public static void TaskFinish()
{
using var context = new AppDbContext();
//---------------------------------------------查询【调度状态】为已完成的任务---------------------------------------------
//var query = context.Set<TaskRT>()
// .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();
}
}
}

View File

@@ -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
{
/// <summary>
/// 任务处理
/// </summary>
public class Handler
{
static int deviceCount = RGVStation.RGVCount;
/// <summary>
/// 防错机制 ---
/// 任务状态 ->【执行中】
/// 调度状态 ->【环穿-待执行】
/// 取货状态 ->【未取货】
/// 同时满足的任务视为下发失败的任务
/// 将任务状态更新为【待执行】令其重新下发
/// </summary>
public static void TaskForSendFailedHandler()
{
using var context = new AppDbContext();
var tasks = context.Tasks
//.Set<TaskRT>()
.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}更新任务状态,尝试重新下发...");
}
}
/// <summary>
/// 防错机制 ---
/// 处理长时间未正常完成的遗留任务记录---获取下发时间距离当前一定时间的任务
/// 将其任务号与所有小车状态匹配
/// 判断该任务是否在执行中---否则视为遗留任务处理
/// </summary>
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<CircleRGVState> 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
}
}
}
}

View File

@@ -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;
}
}
}

View File

@@ -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
{
/// <summary>
/// A线单次请求标志
/// </summary>
public static bool LineAIsAvailable = true;
/// <summary>
/// B线单次请求标志
/// </summary>
public static bool LineBIsAvailable = true;
/// <summary>
/// C线单次请求标志
/// </summary>
public static bool LineCIsAvailable = true;
/// <summary>
/// D线单次请求标志
/// </summary>
public static bool LineDIsAvailable = true;
/// <summary>
/// AB线单次请求标志
/// </summary>
public static bool LineABIsAvailable = true;
/// <summary>
/// CD线单次请求标志
/// </summary>
public static bool LineCDIsAvailable = true;
/// <summary>
/// 自动完成处于一定时间内【放货中】状态的环穿【实垛】遗留任务
/// </summary>
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}已作为遗留任务处理");
}
//}
}
}
}
/// <summary>
/// 自动完成处于一定时间内【放货完成】状态的环穿遗留任务
/// 该原因可能是由于某些因素使程序意外关闭导致的
/// </summary>
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}已作为遗留任务处理");
}
/// <summary>
/// 防错机制(处理长时间可能未正常完成遗留任务记录)---获取下发时间距离当前时间较长的任务
/// 将其任务号与执行中的小车匹配
/// 判断该任务是否已经执行完成---完成则视为遗留任务处理
/// </summary>
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}无法匹配与执行中设备任务号,已作为遗留任务超时处理");
}
}
}
}
}
}

View File

@@ -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
{
/// <summary>
/// 移除指定任务记录
/// </summary>
/// <param name="taskHistory">任务历史记录</param>
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));
}
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}

View File

@@ -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
{
/// <summary>
/// 新插入一条记录
/// </summary>
/// <param name="taskRT">任务参数模型</param>
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)));
}
}
}

View File

@@ -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()
{
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.StateCode
{
/// <summary>
/// 报警优先级
/// </summary>
public class AlarmPriority
{
/// <summary>
/// 高
/// </summary>
public const int HIGH = 1;
/// <summary>
/// 中
/// </summary>
public const int MID = 2;
/// <summary>
/// 低
/// </summary>
public const int LOW = 3;
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.StateCode
{
/// <summary>
/// 库存状态
/// </summary>
public class CargoState
{
/// <summary>
/// 错误
/// </summary>
public const int ERROR = 0;
/// <summary>
/// 空闲
/// </summary>
public const int FREE = 1;
/// <summary>
/// 占用
/// </summary>
public const int FULL = 2;
/// <summary>
/// 入库重分
/// </summary>
public const int OUT_REDIST = 3;
/// <summary>
/// 入库盘点
/// </summary>
public const int IN_STOCKTAKING = 4;
/// <summary>
/// 入库障碍
/// </summary>
public const int IN_OBSTRUCT = 5;
/// <summary>
/// 出库取货无货
/// </summary>
public const int OUT_NOTHING = 6;
/// <summary>
/// 出库障碍
/// </summary>
public const int OUT_OBSTRUCT = 7;
/// <summary>
/// 异常(通用)
/// </summary>
public const string FAULT = "F";
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.StateCode
{
/// <summary>
/// 输送线站点
/// </summary>
public class ConvStation
{
/// <summary>
/// 1层输送口1-左侧
/// </summary>
public const string conv_1 = "C1001";
/// <summary>
/// 1层输送口2-右侧
/// </summary>
public const string conv_2 = "C1002";
/// <summary>
/// 2层输送口
/// </summary>
public const string conv_3 = "C2002";
/// <summary>
/// 3层输送口
/// </summary>
public const string conv_4 = "C2003";
/// <summary>
/// 4层输送口
/// </summary>
public const string conv_5 = "C2004";
}
}

View File

@@ -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
{
}
}

View File

@@ -0,0 +1,261 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.StateCode
{
/// <summary>
/// 调度状态-与设备交互的标志状态
/// </summary>
public class ScheduleStateCode
{
//---------------设备编号---------------
//入口输送机 11
//出口输送机 12
//重分输送机 13
//巷道出口输送机 14
//四向车库内输送机 15
//拣选输送机(当拣选与出口独立时) 16
//双向穿梭车 2
//堆垛机 3
//提升机 4
//四向穿梭车 5
//环穿 6
//入库重分F1
//******************************************************入库******************************************************
/// <summary>
/// 入口输送机等待请求下发任务
/// </summary>
public const string StockIn_WaitingForTask = "R0";
/// <summary>
/// 入口输送机请求wms任务成功
/// </summary>
public const string StockIn_TaskRequestSuccessful = "R0-1";
/// <summary>
/// 入口输送机入库待执行
/// </summary>
public const string StockIn_EntryConv_Ready = "R11-0";
/// <summary>
/// 入口输送机入库执行中
/// </summary>
public const string StockIn_EntryConv_Running = "R11-1";
/// <summary>
/// 入口输送机入库到位
/// </summary>
public const string StockIn_EntryConv_Finish = "R11-2";
/// <summary>
/// 入库提升机待执行
/// </summary>
public const string StockIn_LFT_Ready = "R4-0";
/// <summary>
/// 入库提升机执行中
/// </summary>
public const string StockIn_LFT_Running = "R4-1";
/// <summary>
/// 入库提升机执行完成
/// </summary>
public const string StockIn_LFT_Finish = "R4-2";
/// <summary>
/// RGV入库执行中
/// </summary>
public const string StockIn_RGV_Running = "R2-1";
/// <summary>
/// RGV放货完成
/// </summary>
public const string StockIn_RGV_Finish = "R2-2";
/// <summary>
/// 巷道输送机入库执行中
/// </summary>
public const string StockIn_RoadConv_Running = "R14-1";
/// <summary>
/// 巷道输送机入库到位
/// </summary>
public const string StockIn_RoadConv_Finish = "R14-2";
/// <summary>
/// 堆垛机入库执行中
/// </summary>
public const string StockIn_STK_Running = "R3";
/// <summary>
/// 堆垛机入库待执行
/// </summary>
public const string StockIn_STK_Ready = "R3-0";
/// <summary>
/// 堆垛机入库取货途中
/// </summary>
public const string StockIn_STK_PickOnTheWay = "R3-1";
/// <summary>
/// 堆垛机取货
/// </summary>
public const string StockIn_STK_Picking = "R3-2";
/// <summary>
/// 堆垛机放货途中
/// </summary>
public const string StockIn_STK_PutOnTheWay = "R3-3";
/// <summary>
/// 堆垛机放货
/// </summary>
public const string StockIn_STK_Putting = "R3-4";
/// <summary>
/// 堆垛机入库执行完成
/// </summary>
public const string StockIn_STK_Finish = "R3-5";
/// <summary>
/// 入库重分
/// </summary>
public const string StockIn_STK_Redis = "RF";
/// <summary>
/// 入库重分完成
/// </summary>
public const string StockIn_STK_RedisFinish = "RFF";
//****************************************************************************************************************
//******************************************************出库******************************************************
/// <summary>
/// 堆垛机出库执行中
/// </summary>
public const string StockOut_STK_Running = "C3";
/// <summary>
/// 堆垛机出库待执行
/// </summary>
public const string StockOut_STK_Ready = "C3-0";
/// <summary>
/// 堆垛机出库取货途中
/// </summary>
public const string StockOut_STK_PickOnTheWay = "C3-1";
/// <summary>
/// 堆垛机出库取货
/// </summary>
public const string StockOut_STK_Picking = "C3-2";
/// <summary>
/// 堆垛机出库放货途中
/// </summary>
public const string StockOut_STK_PutOnTheWay = "C3-3";
/// <summary>
/// 堆垛机出库放货
/// </summary>
public const string StockOut_STK_Putting = "C3-4";
/// <summary>
/// 堆垛机出库完成
/// </summary>
public const string StockOut_STK_Finish = "C3-5";
/// <summary>
/// 巷道输送机出库执行中
/// </summary>
public const string StockOut_RoadConv_Running = "C14-1";
/// <summary>
/// 巷道输送机出库到位
/// </summary>
public const string StockOut_RoadConv_Finish = "C14-2";
/// <summary>
/// 穿梭车出库执行中
/// </summary>
public const string StockOut_RGV_Running = "C2-1";
/// <summary>
/// 穿梭车出库执行完成
/// </summary>
public const string StockOut_RGV_Finish = "C2-2";
/// <summary>
/// 提升机出库待执行
/// </summary>
public const string StockOut_LFT_Ready = "C4-0";
/// <summary>
/// 提升机出库执行中
/// </summary>
public const string StockOut_LFT_Running = "C4-1";
/// <summary>
/// 提升机出库完成
/// </summary>
public const string StockOut_LFT_Finish = "C4-2";
/// <summary>
/// 出库输送机执行中
/// </summary>
public const string StockOut_ExitConv_Running = "C12-1";
/// <summary>
/// 出库输送机出库到位
/// </summary>
public const string StockOut_ExitConv_Finish = "C12-2";
/// <summary>
/// 出库取货无货-需盘点
/// </summary>
public const string StockOut_STK_Empty = "CF";
//****************************************************************************************************************
//******************************************************转存******************************************************
/// <summary>
/// 转储任务待执行(一阶段出库)
/// </summary>
public const string Trans_ExitConv_Finish = "ZC3-0";
/// <summary>
/// 转储任务取货途中(一阶段出库)
/// </summary>
public const string Trans_STK_PickOnTheWay = "ZC3-1";
/// <summary>
/// 转储任务取货(一阶段出库)
/// </summary>
public const string Trans_STK_Picking = "ZC3-2";
/// <summary>
/// 转储任务放货途中(二阶段入库)
/// </summary>
public const string Trans_STK_PutOnTheWay = "ZR3-1";
/// <summary>
/// 转储任务放货(二阶段入库)
/// </summary>
public const string Trans_STK_Putting = "ZR3-2";
/// <summary>
/// 转储任务放货完成(二阶段入库)
/// </summary>
public const string Trans_STK_Finish = "ZR3-3";
/// <summary>
/// 入库重分
/// </summary>
public const string Trans_STK_Redis = "ZF";
//****************************************************************************************************************
//******************************************************环穿点到点******************************************************
/// <summary>
/// 环穿-待执行
/// </summary>
public const string Trans_CircleRGV_Ready = "T6-0";
/// <summary>
/// 环穿-执行中
/// </summary>
public const string Trans_CircleRGV_Running = "T6-1";
/// <summary>
/// 环穿-取货途中
/// </summary>
public const string Trans_CircleRGV_PickOnTheWay = "T6-2";
/// <summary>
/// 环穿-取货中
/// </summary>
public const string Trans_CircleRGV_Picking = "T6-3";
/// <summary>
/// 环穿-放货途中
/// </summary>
public const string Trans_CircleRGV_PutOnTheWay = "T6-4";
/// <summary>
/// 环穿-放货中
/// </summary>
public const string Trans_CircleRGV_Putting = "T6-5";
/// <summary>
/// 环穿-执行完成(送到执行站点)
/// </summary>
public const string Trans_CircleRGV_Finish = "T6-6";
//****************************************************************************************************************
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.StateCode
{
/// <summary>
/// 任务状态-与WMS交互的标志状态
/// </summary>
public class TaskStateCode
{
/// <summary>
/// 任务待执行
/// </summary>
public const string Task_Ready = "100";
/// <summary>
/// 任务执行中
/// </summary>
public const string Task_Running = "101";
/// <summary>
/// 任务自动完成
/// </summary>
public const string Task_Finish = "102";
/// <summary>
/// 任务手动完成
/// </summary>
public const string Task_Finish_Manual = "103";
/// <summary>
/// 任务手动取消
/// </summary>
public const string Task_Finish_Cancel = "104";
/// <summary>
/// 任务作废
/// </summary>
public const string Task_Cancel = "105";
/// <summary>
/// 超时自动完成
/// </summary>
public const string Task_Finish_Timeout = "106";
/// <summary>
/// 任务异常-手动处理
/// </summary>
public const string Task_Exception = "F";
/// <summary>
/// 入库放货有货-已重分
/// </summary>
public const string Task_StockIn_Redis = "110";
/// <summary>
/// 入库有货-重分货位
/// </summary>
public const string Task_StockIn_Exist = "111";
/// <summary>
/// 入库近端障碍-重分货位
/// </summary>
public const string Task_StockIn_Block = "112";
/// <summary>
/// 出库无货
/// </summary>
public const string Task_StockOut_Empty = "121";
/// <summary>
/// 出库近端障碍
/// </summary>
public const string Task_StockOut_Block = "122";
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.StateCode
{
/// <summary>
/// 任务类型
/// </summary>
public class TaskType
{
///// <summary>
///// 入库-通用
///// </summary>
//public const int StockIn = 10;
///// <summary>
///// 入库-货物
///// </summary>
//public const int StockIn_Goods = 11;
///// <summary>
///// 托盘垛入库
///// </summary>
//public const int StockIn_Pallets = 12;
///// <summary>
///// 出库-通用
///// </summary>
//public const int StockOut = 20;
///// <summary>
///// 出库-货物
///// </summary>
//public const int StockOut_Goods = 21;
///// <summary>
///// 托盘垛出库
///// </summary>
//public const int StockOut_Pallets = 22;
///// <summary>
///// 移库-同巷道
///// </summary>
//public const int StockTransSameRoad = 30;
///// <summary>
///// 移库-跨巷道
///// </summary>
//public const int StockTransDifferentRoad = 31;
///// <summary>
///// 越库
///// </summary>
//public const int StockCross = 4;
/// <summary>
/// 环穿常规任务---实垛
/// </summary>
public const int Goods = 10;
/// <summary>
/// 环穿常规任务---空托
/// </summary>
public const int Pallet = 11;
/// <summary>
/// 环穿回休息区
/// </summary>
public const int GoToRest = 2;
/// <summary>
/// 环穿休息区返回轨道
/// </summary>
public const int BackToRail = 3;
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.StateCode
{
/// <summary>
/// 时间格式字符串
/// </summary>
public class TimeFormat
{
/// <summary>
/// 日期
/// </summary>
public const string stringFormatDateOnly = "yyyy/MM/dd";
/// <summary>
/// 时间(时分秒)
/// </summary>
public const string stringFormatTimeOnly = "HH:mm:ss";
/// <summary>
/// 日期 时间
/// </summary>
public const string stringFormat = "yyyy/MM/dd HH:mm:ss";
/// <summary>
/// 日期 时间.毫秒(小数点2位)
/// </summary>
public const string stringFormatff = "yyyy/MM/dd HH:mm:ss.ff";
/// <summary>
/// 日期 时间.毫秒(小数点3位)
/// </summary>
public const string stringFormatfff = "yyyy/MM/dd HH:mm:ss.fff";
/// <summary>
/// 日期 时间.毫秒(小数点7位)
/// </summary>
public const string stringFormatfffffff = "yyyy/MM/dd HH:mm:ss.fffffff";
}
}

View File

@@ -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
{
/// <summary>
/// 用户
/// </summary>
public const string USER = "USER";
/// <summary>
/// 主用户
/// </summary>
public const string ADMIN = "ADMIN";
/// <summary>
/// 管理员
/// </summary>
public const string SYSTEM = "SYSTEM";
/// <summary>
/// 开发者
/// </summary>
public const string DEVELOPER = "DEVELOPER";
public enum AccessType
{
USER,
ADMIN,
SYSTEM,
DEVELOPER
}
}
}

View File

@@ -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
{
/// <summary>
/// 初始化货位信息表
/// </summary>
public class CargoTableInitialize
{
/// <summary>
/// 向库表中添加货位
/// </summary>
/// <param name="row">排</param>
/// <param name="column">列</param>
/// <param name="floor">层</param>
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)},'')");
}
}
}
}
}
}
}

View File

@@ -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
{
/// <summary>
/// 字节数拆分求和
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 获取校验码---字节拆分求和
/// </summary>
/// <param name="circleRGVStationCommand"></param>
/// <returns></returns>
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));
}
}
}

View File

@@ -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 "条码格式错误!";
}
}
}

View File

@@ -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
{
/// <summary>
/// 数据维护操作相关
/// </summary>
public class SqlDatabaseMaintenance
{
/// <summary>
/// 手动备份根文件夹路径
/// </summary>
static string rootPath = @"E:\SqlDataBackup";
/// <summary>
/// 自动备份根文件夹路径
/// </summary>
static string rootPathAuto = @"E:\SqlAutoBackup";
/// <summary>
/// sql库名
/// </summary>
static string dbName = "FT479";
/// <summary>
/// 备份当前数据库
/// </summary>
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}");
}
}
/// <summary>
/// 自动备份当前数据库
/// 包含删除旧数据功能
/// </summary>
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");
}
/// <summary>
/// SQL备份-调度任务表
/// </summary>
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}");
}
}
/// <summary>
/// SQL备份-历史报警表
/// </summary>
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}");
}
}
/// <summary>
/// 删除SQL数据
/// </summary>
public static void SQLClearByTime(string tableName, string yearOrMonthOrDay, int count)
{
SqlHelper.ExecuteNonQuery($"DELETE FROM {tableName} WHERE GEN_TIME >= DATEADD({yearOrMonthOrDay}, {count}, GETDATE()");
}
/// <summary>
/// 查找文件夹(不存在则创建)
/// 查找后为文件夹设定权限-完全控制
/// </summary>
/// <param name="backupPath"></param>
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);
}
}
}
}
}

View File

@@ -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
{
/// <summary>
/// sql连接字符串,引用自【app.config】
/// </summary>
public static string? ConStr { get; set; }
/// <summary>
/// 检查数据库是否连接正常
/// </summary>
/// <returns>true-连接正常 false-连接失败</returns>
public static bool IsDBConnected()
{
using var context = new AppDbContext();
return context.Database.CanConnect();
}
/// <summary>
/// 获取数据集
/// </summary>
/// <param name="cmdText">sql执行语句</param>
/// <param name="sqlParameters">可选的sql参数</param>
/// <returns>查询目标的数据集</returns>
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;
}
/// <summary>
/// 获取对应SQL查询的数据表
/// </summary>
/// <param name="cmdText">sql执行语句</param>
/// <returns>查询目标的数据表名</returns>
public static DataTable? ExecuteTable(string cmdText, params SqlParameter[] sqlParameters)
{
return GetDataSet(cmdText, sqlParameters).Tables[0];
}
/// <summary>
/// 获取某个表字段的集合
/// </summary>
/// <param name="cmdText">sql执行语句</param>
/// <returns>查询目标表字段/列名的值的集合</returns>
public static List<string> GetColumns(string cmdText)
{
//创建用于存储列名的集合
List<string> columns = new List<string>();
//创建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;
}
}
/// <summary>
/// 操作获取受影响的行数
/// </summary>
/// <param name="cmdText">sql语句</param>
/// <param name="sqlParameters">sql字段参数</param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 获取查询数据的行数
/// </summary>
/// <param name="cmdText">SQL字符串</param>
/// <returns>目标行数</returns>
public static int GetRowCount(string cmdText, params SqlParameter[] sqlParameters)
{
using (DataTable dt = ExecuteTable(cmdText, sqlParameters))
{
if (dt == null)
{
return 0;
}
return dt.Rows.Count;
}
}
/// <summary>
/// 获取为当前任务【自动生成】的WCS本地任务号
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 获取为当前任务【手动添加】的WCS本地任务号
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 获取为当前事件【手动添加】的编号
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 记录当前操作事件
/// </summary>
/// <param name="message">信息</param>
/// <param name="userId">标识</param>
/// <param name="type">类型(登录、操作等)</param>
/// <param name="source">来源(名称、数据集等)</param>
/// <param name="level">级别</param>
/// <param name="status">状态(是否完成等)</param>
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)}");
}
/// <summary>
/// 记录当前操作事件
/// </summary>
/// <param name="message">信息</param>
/// <param name="userId">标识</param>
/// <param name="type">类型(登录、操作等)</param>
/// <param name="source">来源(名称、数据集等)</param>
/// <param name="level">级别</param>
/// <param name="status">状态(是否完成等)</param>
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}");
}
}
}

View File

@@ -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
{
/// <summary>
/// 获取【实时报警】表所有行数据集合
/// </summary>
/// <returns>返回所有行的数据</returns>
public static List<Alarm> ListAll()
{
using (DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM ALARM ORDER BY GEN_TIME DESC"))
{
if (dt == null) return null;
List<Alarm> alarms = new List<Alarm>();
foreach (DataRow dr in dt.Rows)
{
alarms.Add(ToModels(dr));
}
#region 反射方法
/*
foreach (DataRow dr in dt.Rows)
{
tasks.Add(dr.DataRowToModel<ScheduleManager>());
}
*/
#endregion
return alarms;
}
}
/// <summary>
/// 将【调度管理】表的单行转换为实体数据对象
/// </summary>
/// <param name="dr">获取表的某行数据</param>
/// <returns>当前行所有字段的集合</returns>
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;
}
/// <summary>
/// 向【实时报警】表中插入数据
/// </summary>
/// <param name="alarm"></param>
/// <returns>返回受影响的行数</returns>
public static int Insert(Alarm alarm)
{
using var context = new AppDbContext();
int count = context.Set<Alarm>()
.Where(a => a.Point_Id == alarm.Point_Id)
.Count();
if (count > 0) return 0;
alarm.Gen_Time = DateTime.Now;
context.Set<Alarm>()
.Add(alarm);
if (context.SaveChanges() == 1)
{
return 1;
}
else
{
return 0;
}
}
/// <summary>
/// 从【实时报警】表中移除数据记入历史表
/// </summary>
/// <param name="alarm">当前已结束的报警</param>
/// <returns>执行后受影响的行数</returns>
public static int Delete(Alarm alarm)
{
using var context = new AppDbContext();
int count = context.Set<Alarm>()
.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<AlarmHistory>()
.Add(alarmHistory);
context.Set<Alarm>()
.Remove(alarm);
return context.SaveChanges();
}
}
}

View File

@@ -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
{
/// <summary>
/// 获取表数据
/// </summary>
/// <returns></returns>
public static List<TaskHistory> ListAll()
{
using (DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM TASK_HISTORY ORDER BY CREATETIME DESC"))
{
if (dt == null || dt.Rows.Count == 0) return null;
List<TaskHistory> scheduleHistoryManagers = new List<TaskHistory>();
foreach (DataRow dr in dt.Rows)
{
scheduleHistoryManagers.Add(ToModels(dr));
}
#region 反射方法
/*
foreach (DataRow dr in dt.Rows)
{
tasks.Add(dr.DataRowToModel<ScheduleManager>());
}
*/
#endregion
return scheduleHistoryManagers;
}
}
/// <summary>
/// 将表行转换成实体数据
/// </summary>
/// <param name="dr"></param>
/// <returns></returns>
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;
}
}
}

View File

@@ -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
{
/// <summary>
/// 获取【调度管理】表所有行数据集合
/// </summary>
/// <returns>返回所有行的数据</returns>
public static List<TaskRT> ListAll()
{
using (DataTable? dt = SqlHelper.ExecuteTable("SELECT * FROM TASK ORDER BY CREATETIME DESC"))
{
if (dt == null || dt.Rows.Count == 0) return null;
List<TaskRT> taskRTs = new List<TaskRT>();
foreach (DataRow dr in dt.Rows)
{
taskRTs.Add(ToModels(dr));
}
#region 反射方法
/*
foreach (DataRow dr in dt.Rows)
{
tasks.Add(dr.DataRowToModel<ScheduleManager>());
}
*/
#endregion
return taskRTs;
}
}
/// <summary>
/// 将【调度管理】表的单行转换为实体数据对象
/// </summary>
/// <param name="dr">获取表的某行数据</param>
/// <returns>当前行所有字段的集合</returns>
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;
}
/// <summary>
/// 向【调度管理】表中插入数据
/// </summary>
/// <param name="scheduleManager"></param>
/// <returns>返回受影响的行数</returns>
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;
}
}
/// <summary>
/// 从【调度管理】表中移除数据记入历史表
/// </summary>
/// <param name="scheduleManager">当前已完成的任务</param>
/// <returns>执行后受影响的行数</returns>
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;
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WPFWCSDemo.Utilities
{
/// <summary>
/// 用户权限管理
/// </summary>
public class UserAccessControl
{
public static void CheckAccess()
{
}
}
}

Some files were not shown because too many files have changed in this diff Show More