764 lines
20 KiB
C#
764 lines
20 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
||
using CommunityToolkit.Mvvm.Input;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using Microsoft.Xaml.Behaviors.Layout;
|
||
using Newtonsoft.Json;
|
||
using Serilog;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Collections.ObjectModel;
|
||
using System.Configuration;
|
||
using System.Data;
|
||
using System.Data.Common;
|
||
using System.Data.SqlClient;
|
||
using System.Linq;
|
||
using System.Text;
|
||
using System.Text.Json.Serialization;
|
||
using System.Threading.Tasks;
|
||
using System.Windows;
|
||
using System.Windows.Threading;
|
||
using WPFWCSDemo.Common;
|
||
using WPFWCSDemo.Data;
|
||
using WPFWCSDemo.Models.Devices.CircleRGV;
|
||
using WPFWCSDemo.Models.Devices.CircleRGVStation;
|
||
using WPFWCSDemo.Models.Tables;
|
||
using WPFWCSDemo.StateCode;
|
||
using WPFWCSDemo.Utilities;
|
||
using WPFWCSDemo.Utilities.Table;
|
||
using WPFWCSDemo.Views.CustomComponent;
|
||
using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;
|
||
|
||
namespace WPFWCSDemo.ViewModels
|
||
{
|
||
public partial class TaskViewModel : ObservableObject
|
||
{
|
||
/// <summary>
|
||
/// 用于实时更新任务表的定时器
|
||
/// </summary>
|
||
private DispatcherTimer dispatcherTimer;
|
||
|
||
public TaskViewModel()
|
||
{
|
||
TaskRT = new ObservableCollection<TaskRT>();
|
||
|
||
ColumnList = new List<string>();
|
||
|
||
col = new Dictionary<string, string>();
|
||
|
||
SourceLocations = new List<int>();
|
||
|
||
TargetLocations = new List<int>();
|
||
|
||
RGVNumbers = new List<int>();
|
||
|
||
LoadTaskGrid();
|
||
|
||
LoadColumns();
|
||
|
||
LocationInitialize();
|
||
|
||
//Task.Run(() => LoadTaskGridAsync());
|
||
|
||
b = true;
|
||
|
||
// 设置定时器属性
|
||
dispatcherTimer = new DispatcherTimer();
|
||
dispatcherTimer.Interval = TimeSpan.FromSeconds(6); // 设置时间间隔
|
||
dispatcherTimer.Tick += DispatcherTimer_Tick; // 添加事件处理程序
|
||
dispatcherTimer.Start(); // 启动计时器
|
||
|
||
}
|
||
|
||
|
||
//调度任务表刷新参数
|
||
private void DispatcherTimer_Tick(object? sender, EventArgs e)
|
||
{
|
||
if (b)
|
||
{
|
||
LoadTaskGrid();
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 是否更新任务表的标志
|
||
/// </summary>
|
||
bool b;
|
||
|
||
/// <summary>
|
||
/// 调度任务字段---原数据/视图数据
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
ObservableCollection<TaskRT> _taskRT;
|
||
|
||
/// <summary>
|
||
/// 搜索关键字
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
string? _keywords;
|
||
|
||
/// <summary>
|
||
/// 筛选列表集合
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
List<string> _columnList;
|
||
|
||
/// <summary>
|
||
/// 筛选列表集合对应的查询字段
|
||
/// </summary>
|
||
Dictionary<string, string> col;
|
||
|
||
/// <summary>
|
||
/// 筛选列表文本
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
string? _columnName;
|
||
|
||
/// <summary>
|
||
/// 筛选列表文本选择项
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
string? _columnNameSelected;
|
||
|
||
/// <summary>
|
||
/// 筛选列表选项
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
int _taskTypeSelectedIndex;
|
||
|
||
/// <summary>
|
||
/// 右侧对话框弹出属性
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
bool _isRightDrawerOpen;
|
||
|
||
/// <summary>
|
||
/// 顶部对话框弹出属性
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
bool _isTopDrawerOpen;
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 站点初始化集合
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
int _rowCount;
|
||
[ObservableProperty]
|
||
int _columnCount;
|
||
[ObservableProperty]
|
||
int _floorCount;
|
||
[ObservableProperty]
|
||
List<int> _rows;
|
||
[ObservableProperty]
|
||
List<int> _columns;
|
||
[ObservableProperty]
|
||
List<int> _floors;
|
||
|
||
/// <summary>
|
||
/// 取放货站点集合
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
List<int> _sourceLocations;
|
||
[ObservableProperty]
|
||
List<int> _targetLocations;
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 测试下发界面任务类型
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
int _testingTaskTypeIndex;
|
||
/// <summary>
|
||
/// 任务类型
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
int _selectedTaskTypeIndex;
|
||
/// <summary>
|
||
/// 输入托盘号
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
string _inputTaskId;
|
||
/// <summary>
|
||
/// 取货站点
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
int _selectedSourceLocation;
|
||
/// <summary>
|
||
/// 放货站点
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
int _selectedTargetLocation;
|
||
|
||
/// <summary>
|
||
/// 小车编号集合
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
List<int> _rGVNumbers;
|
||
/// <summary>
|
||
/// 选中小车编号
|
||
/// </summary>
|
||
[ObservableProperty]
|
||
int _selectedRGVNumber;
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 右侧对话框弹出命令
|
||
/// </summary>
|
||
[RelayCommand]
|
||
private void NewTask()
|
||
{
|
||
IsRightDrawerOpen = true;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 顶部对话框弹出命令---堆垛机测试
|
||
/// </summary>
|
||
[RelayCommand]
|
||
private void StackerTesting()
|
||
{
|
||
IsTopDrawerOpen = true;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 更改任务类型选项直接更新表
|
||
/// </summary>
|
||
//[RelayCommand]
|
||
void TaskTypeSelectItemChanged()
|
||
{
|
||
using var context = new AppDbContext();
|
||
|
||
List<TaskRT> tasks;
|
||
|
||
if (TaskTypeSelectedIndex == 1)
|
||
{
|
||
tasks = context.Set<TaskRT>()
|
||
.OrderByDescending(t => t.CreateTime)
|
||
.Where(t => t.TaskType == 10)
|
||
.ToList();
|
||
}
|
||
else if (TaskTypeSelectedIndex == 2)
|
||
{
|
||
tasks = context.Set<TaskRT>()
|
||
.OrderByDescending(t => t.CreateTime)
|
||
.Where(t => t.TaskType == 11)
|
||
.ToList();
|
||
}
|
||
else
|
||
{
|
||
tasks = context.Set<TaskRT>()
|
||
.OrderByDescending(t => t.CreateTime)
|
||
.ToList();
|
||
}
|
||
|
||
TaskRT.Clear();
|
||
|
||
//遍历表中每行数据并初始化值
|
||
foreach (TaskRT task in tasks)
|
||
{
|
||
TaskRT.Add(task);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 查询任务
|
||
/// </summary>
|
||
[RelayCommand]
|
||
public void Query()
|
||
{
|
||
//关键词不为空且列名不为空
|
||
if (!string.IsNullOrEmpty(Keywords) && !string.IsNullOrEmpty(ColumnName))
|
||
{
|
||
using var context = new AppDbContext();
|
||
|
||
var tasks=context.Set<TaskRT>()
|
||
.FromSqlInterpolated($"SELECT * FROM TASK WHERE {col[ColumnName]} LIKE %{Keywords}% ORDER BY CREATETIME DESC")
|
||
.ToList();
|
||
|
||
TaskRT.Clear();
|
||
|
||
//遍历表中每行数据并初始化值
|
||
foreach (TaskRT task in tasks)
|
||
{
|
||
TaskRT.Add(task);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
LoadTaskGrid();
|
||
}
|
||
|
||
b = false;
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 重置筛选项
|
||
/// </summary>
|
||
[RelayCommand]
|
||
void Clear()
|
||
{
|
||
Keywords = string.Empty;
|
||
ColumnName = string.Empty;
|
||
|
||
LoadTaskGrid();
|
||
|
||
b = true;
|
||
}
|
||
|
||
#region 添加新任务相关
|
||
|
||
|
||
// 下拉框获取值属性 (源/目标排、列、层)
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 点击新建任务按钮命令
|
||
/// </summary>
|
||
[RelayCommand]
|
||
public void AddTask()
|
||
{
|
||
InputCheck();
|
||
//MessageBox.Show(SelectedTaskType);
|
||
//获取任务参数值
|
||
TaskRT taskRT = new TaskRT
|
||
{
|
||
TaskId = SqlHelper.GetTaskIdByManualGeneration().ToString(),//使用int类型初始值不是空 指定9起始的任务号为人工操作标识
|
||
SourceLocation = SelectedSourceLocation.ToString(),
|
||
TargetLocation = SelectedTargetLocation.ToString(),
|
||
TaskState = TaskStateCode.Task_Running,
|
||
CreateTime = DateTime.Now,
|
||
//ReportState = 0
|
||
|
||
};
|
||
|
||
//任务校验和添加新任务(区分任务类型)
|
||
if (SelectedTaskTypeIndex == 0)
|
||
{
|
||
taskRT.TaskType = 10;
|
||
}
|
||
else if (SelectedTaskTypeIndex == 1)
|
||
{
|
||
taskRT.TaskType = 11;
|
||
}
|
||
else if (SelectedTaskTypeIndex == 2 || SelectedTaskTypeIndex == 3)
|
||
{
|
||
taskRT.TaskType = SelectedTaskTypeIndex;
|
||
}
|
||
else
|
||
{
|
||
MessageBox.Show("任务类型错误!");
|
||
return;
|
||
}
|
||
|
||
Insert(taskRT, taskRT.TaskType);
|
||
|
||
SqlHelper.NewEventLog($"手动下发调度任务:任务号:{taskRT.TaskId}", "USER");
|
||
|
||
//重载任务表
|
||
LoadTaskGrid();
|
||
}
|
||
#endregion
|
||
|
||
|
||
/// <summary>
|
||
/// 加载下拉框内容
|
||
/// </summary>
|
||
public void LoadColumns()
|
||
{
|
||
ColumnList.Clear();
|
||
//ColumnList.Add("作业号");
|
||
ColumnList.Add("任务号");
|
||
//ColumnList.Add("托盘号");
|
||
ColumnList.Add("任务类型");
|
||
ColumnList.Add("源站点");
|
||
ColumnList.Add("目标站点");
|
||
ColumnList.Add("任务状态");
|
||
//ColumnList.Add("生成时间");
|
||
|
||
col.Clear();
|
||
//col.Add("作业号", "JobId");
|
||
col.Add("任务号", "TaskId");
|
||
//col.Add("托盘号", "PalletId");
|
||
col.Add("任务类型", "TaskType");
|
||
col.Add("源站点", "SourceLocation");
|
||
col.Add("目标站点", "TargetLocation");
|
||
col.Add("任务状态", "TaskState");
|
||
//col.Add("生成时间", "CreateTime");
|
||
|
||
RGVNumbers.Clear();
|
||
for (int i = 0; i < RGVStation.RGVCount; i++)
|
||
{
|
||
RGVNumbers.Add(i);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 加载表格内容
|
||
/// </summary>
|
||
public void LoadTaskGrid()
|
||
{
|
||
using var context = new AppDbContext();
|
||
|
||
var tasks = context.Set<TaskRT>()
|
||
.OrderByDescending(t => t.CreateTime)
|
||
.ToList();
|
||
|
||
TaskRT.Clear();
|
||
|
||
//遍历表中每行数据并初始化值
|
||
foreach (TaskRT task in tasks)
|
||
{
|
||
TaskRT.Add(task);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 向调度表中插入任务
|
||
/// </summary>
|
||
/// <param name="TaskRT">TaskRT类的实例化对象</param>
|
||
/// <param name="taskType">任务类型</param>
|
||
/// <returns></returns>
|
||
public void Insert(TaskRT taskRT, int taskType)
|
||
{
|
||
try
|
||
{
|
||
using var context = new AppDbContext();
|
||
|
||
context.Set<TaskRT>()
|
||
.Add(taskRT);
|
||
|
||
int result = context.SaveChanges();
|
||
|
||
if (result == 1) Log.Warning($"【手动添加调度任务】任务号:{taskRT.TaskId},{JsonConvert.SerializeObject(taskRT)}");
|
||
|
||
}
|
||
catch (DbUpdateException e)
|
||
{
|
||
MessageBox.Show($"发生了预期之外的错误:{e.Message}(错误代码:TVM000002)");
|
||
}
|
||
|
||
LoadTaskGrid();
|
||
|
||
}
|
||
|
||
|
||
|
||
/// <summary>
|
||
/// 站点信息初始化
|
||
/// </summary>
|
||
void LocationInitialize()
|
||
{
|
||
//Rows = new List<int>();
|
||
//Columns = new List<int>();
|
||
//Floors = new List<int>();
|
||
|
||
//RowCount = int.Parse(ConfigurationManager.AppSettings["Row"]);
|
||
//for (int i = 1; i <= RowCount; i++)
|
||
//{
|
||
// Rows.Add(i);
|
||
//}
|
||
//ColumnCount = int.Parse(ConfigurationManager.AppSettings["Column"]);
|
||
//for (int i = 1; i <= ColumnCount; i++)
|
||
//{
|
||
// Columns.Add(i);
|
||
//}
|
||
//FloorCount = int.Parse(ConfigurationManager.AppSettings["Floor"]);
|
||
//for (int i = 1; i <= FloorCount; i++)
|
||
//{
|
||
// Floors.Add(i);
|
||
//}
|
||
|
||
SourceLocations.Clear();
|
||
|
||
foreach (var item in CircleRGVsViewModel.route)
|
||
{
|
||
SourceLocations.Add(item.Key);
|
||
}
|
||
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取货站点对应放货站点
|
||
/// </summary>
|
||
[RelayCommand]
|
||
void SourceToTarget()
|
||
{
|
||
try
|
||
{
|
||
SelectedTargetLocation = CircleRGVsViewModel.route[SelectedSourceLocation];
|
||
}
|
||
catch
|
||
{
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 下发测试任务
|
||
/// </summary>
|
||
[RelayCommand]
|
||
void SendRGVTest()
|
||
{
|
||
if (MessageBox.Show("此操作会向环穿地面站PLC直接写入命令!是否继续?","",MessageBoxButton.YesNo) != MessageBoxResult.OK)
|
||
{
|
||
return;
|
||
}
|
||
|
||
CircleRGVStationCommand circleRGVStationCommand = new CircleRGVStationCommand()
|
||
{
|
||
Write_DeviceNumber = SelectedRGVNumber,
|
||
Write_TaskNumber = SqlHelper.GetTaskIdByManualGeneration(),
|
||
Write_TaskType = TestingTaskTypeIndex + 1,
|
||
Write_SourceLocation = SelectedSourceLocation,
|
||
Write_TargetLocation = SelectedTargetLocation,
|
||
};
|
||
|
||
CircleRGVsViewModel.SendRGVStationCommand(circleRGVStationCommand);
|
||
|
||
Log.Information($"【环穿下发任务测试】直接向地面站PLC下发任务:{JsonConvert.SerializeObject(circleRGVStationCommand)}");
|
||
|
||
SqlHelper.NewEventLog($"向地面站PLC直接写入测试任务:任务号:{circleRGVStationCommand.Write_TaskNumber}", "USER");
|
||
|
||
IsTopDrawerOpen = false;
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 清空选择项
|
||
/// </summary>
|
||
[RelayCommand]
|
||
void TestClear()
|
||
{
|
||
SelectedRGVNumber = 0;
|
||
SelectedSourceLocation = 0;
|
||
SelectedTargetLocation = 0;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 新任务输入校验
|
||
/// </summary>
|
||
public void InputCheck()
|
||
{
|
||
//跨巷道使用
|
||
if (string.IsNullOrEmpty(SelectedSourceLocation.ToString().Trim()))
|
||
{
|
||
MessageBox.Show("请选择取货站点!");
|
||
return;
|
||
}
|
||
if (string.IsNullOrEmpty(SelectedTargetLocation.ToString().Trim()))
|
||
{
|
||
MessageBox.Show("请选择目标站点!");
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
}
|
||
|
||
Action<string> action;
|
||
|
||
//[RelayCommand]
|
||
void TaskFinishHandler()
|
||
{
|
||
InputDialog inputDialog = new InputDialog();
|
||
inputDialog.ShowDialog();
|
||
|
||
action = TaskFinish;
|
||
}
|
||
|
||
void TaskCancelHandler()
|
||
{
|
||
InputDialog inputDialog = new InputDialog();
|
||
inputDialog.ShowDialog();
|
||
|
||
action = TaskDelete;
|
||
}
|
||
|
||
void UpdateTaskStateToReadyHandler()
|
||
{
|
||
InputDialog inputDialog = new InputDialog();
|
||
inputDialog.ShowDialog();
|
||
|
||
action = UpdateTaskStateToReady;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 手动完成任务
|
||
/// </summary>
|
||
[RelayCommand]
|
||
void TaskFinish(string taskId)
|
||
{
|
||
using var context = new AppDbContext();
|
||
|
||
var task = context.Set<TaskRT>()
|
||
.Where(t => t.TaskId == taskId)
|
||
.FirstOrDefault();
|
||
|
||
if (task == null)
|
||
{
|
||
MessageBox.Show("获取任务号错误!自动移除该任务");
|
||
|
||
context.Database
|
||
.ExecuteSqlInterpolated($"DELETE FROM TASK WHERE TASKID={taskId}");
|
||
|
||
context.SaveChanges();
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
string taskType = "";
|
||
|
||
switch (task.TaskType)
|
||
{
|
||
case 10:
|
||
taskType = "实垛";
|
||
break;
|
||
case 11:
|
||
taskType = "空托";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (MessageBox.Show($"确认人工完成任务号:{taskId}的任务?\r\n(错误的操作时机可能会导致生成空任务)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
|
||
{
|
||
task.TaskState = TaskStateCode.Task_Finish_Manual;
|
||
|
||
if (context.SaveChanges() == 1)
|
||
{
|
||
Log.Information($"【人工操作】手动完成任务,任务号:{taskId}");
|
||
|
||
SqlHelper.NewEventLog($"人工完成{taskType}任务:{taskId}", "USER");
|
||
}
|
||
|
||
}
|
||
|
||
LoadTaskGrid();
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 手动删除(取消)任务
|
||
/// </summary>
|
||
[RelayCommand]
|
||
void TaskDelete(string taskId)
|
||
{
|
||
using var context = new AppDbContext();
|
||
|
||
var task = context.Set<TaskRT>()
|
||
.Where(t => t.TaskId == taskId)
|
||
.FirstOrDefault();
|
||
|
||
if (task == null)
|
||
{
|
||
MessageBox.Show("获取任务号错误!自动移除该任务");
|
||
|
||
context.Database
|
||
.ExecuteSqlInterpolated($"DELETE FROM TASK WHERE TASKID={taskId}");
|
||
|
||
context.SaveChanges();
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
string taskType = "";
|
||
|
||
switch (task.TaskType)
|
||
{
|
||
case 10:
|
||
taskType = "实垛";
|
||
break;
|
||
case 11:
|
||
taskType = "空托";
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
if (MessageBox.Show($"确认人工取消任务号:{taskId}的任务?\r\n(错误的操作时机可能会导致生成空任务)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
|
||
{
|
||
task.TaskState = TaskStateCode.Task_Finish_Cancel;
|
||
|
||
if (context.SaveChanges() == 1)
|
||
{
|
||
Log.Information($"【人工操作】手动取消任务,任务号:{taskId}");
|
||
|
||
SqlHelper.NewEventLog($"人工取消{taskType}任务:{taskId}", "USER");
|
||
}
|
||
|
||
}
|
||
|
||
LoadTaskGrid();
|
||
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 当向环穿下发任务失败时,可以选择重新下发
|
||
/// 只能在调度状态为【环穿-待执行】时可用
|
||
/// </summary>
|
||
/// <param name="taskId"></param>
|
||
[RelayCommand]
|
||
void UpdateTaskStateToReady(string taskId)
|
||
{
|
||
using var context = new AppDbContext();
|
||
|
||
var task = context.Set<TaskRT>()
|
||
.Where(t => t.TaskId == taskId && t.ScheduleState== ScheduleStateCode.Trans_CircleRGV_Ready)
|
||
.FirstOrDefault();
|
||
|
||
if (task == null)
|
||
{
|
||
MessageBox.Show("设备运行时的任务无法重下!");
|
||
return;
|
||
}
|
||
|
||
if (MessageBox.Show($"确认将任务:{taskId}的任务状态更改为【待执行】?\r\n此操作会重新下发当前任务(仅在环穿调度状态为【环穿-待执行】时生效)", "警告", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
|
||
{
|
||
task.TaskState= TaskStateCode.Task_Ready;
|
||
|
||
if (context.SaveChanges() == 1)
|
||
{
|
||
Log.Information($"【人工操作】重新下发任务,任务号:{taskId}");
|
||
|
||
SqlHelper.NewEventLog($"人工重下任务:{taskId}", "USER");
|
||
}
|
||
|
||
}
|
||
|
||
LoadTaskGrid();
|
||
|
||
}
|
||
|
||
|
||
}
|
||
}
|