Files
6098/Cowain.Bake.Main/ViewModels/EquipmentMonitorViewModel.cs

1674 lines
72 KiB
C#
Raw Normal View History

using Cowain.Bake.BLL;
using Cowain.Bake.Common;
using Cowain.Bake.Common.Core;
using Cowain.Bake.Common.Enums;
using Cowain.Bake.Common.Interface;
using Cowain.Bake.Common.Models;
using Cowain.Bake.Communication.Interface;
using Cowain.Bake.Main.Common;
using Cowain.Bake.Main.Models;
using Cowain.Bake.Main.Station;
using Cowain.Bake.Main.Views;
using Cowain.Bake.Model;
using Cowain.Bake.Model.Models;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using Prism.Regions;
using Prism.Services.Dialogs;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Shapes;
using Unity;
using JSON = Newtonsoft.Json.JsonConvert;
namespace Cowain.Bake.Main.ViewModels
{
public partial class EquipmentMonitorViewModel : BindableBase
{
readonly IUnityContainer _unityContainer;
IRegionManager _regionManager;
public Canvas mainCanvas;
public Canvas pathCanvas;
public EAgvMoveStatus? lastAgvStatus = null ;
readonly CmdFactories cmdFactories;
public FrameworkElement frameworkElement;
public TranslateTransform machineAnimation;
readonly Dictionary<string, ContextMenu> contextMenuDic = new Dictionary<string, ContextMenu>();
private readonly Dictionary<string, Button> buttonDic = new Dictionary<string, Button>(); //全部
private readonly Dictionary<int, Path> dicStationStatus = new Dictionary<int, Path>();
private readonly Dictionary<int, SizeAndLocationModel> dicSizeLocal = new Dictionary<int, SizeAndLocationModel>(); //扫码独立 132个元素
private readonly Dictionary<int, SolidColorBrush> dicStatusColor = new Dictionary<int, SolidColorBrush>();
private readonly List<TTaskType> _taskTypes = null;
private readonly List<TStation> _stationList;
private readonly List<CavityInfoModel> _exCavityInfo;
double _trackPositionY = 0;
public double _localScreenWidth;
public double _localScreenHeight;
private int stepIndex;
public int StepIndex
{
get => stepIndex;
set => SetProperty(ref stepIndex, value);
}
private double handMachineYLocation;
public double HandMachineYLocation
{
get => handMachineYLocation;
set => SetProperty(ref handMachineYLocation, value);
}
private string palletCode;
public string PalletCode
{
get => palletCode;
set => SetProperty(ref palletCode, value);
}
private string rgvPalletCode;
public string RgvPalletCode
{
get => rgvPalletCode;
set => SetProperty(ref rgvPalletCode, value);
}
private string cavitySourceName;
public string CavitySourceName
{
get => cavitySourceName;
set => SetProperty(ref cavitySourceName, value);
}
private string taskStatusName;
public string TaskStatusName
{
get => taskStatusName;
set => SetProperty(ref taskStatusName, value);
}
private string taskTypeName;
public string TaskTypeName
{
get => taskTypeName;
set => SetProperty(ref taskTypeName, value);
}
private string cavityTargetName;
public string CavityTargetName
{
get => cavityTargetName;
set => SetProperty(ref cavityTargetName, value);
}
private DateTime startTime;
public DateTime StartTime
{
get => startTime;
set => SetProperty(ref startTime, value);
}
private string _imageSource;
public string ImageSource
{
get => _imageSource;
//set => SetProperty(ref imageSource, value);
set
{
if (Application.Current.Dispatcher.CheckAccess()) // 检查是否在 UI 线程
{
SetProperty(ref _imageSource, value); // 直接更新
}
else
{
Application.Current.Dispatcher.Invoke(() =>
{
SetProperty(ref _imageSource, value); // 切换到 UI 线程更新
});
}
}
}
public ConcurrentDictionary<int, StoveDataModel> CacheStoveData { set; get; } = new ConcurrentDictionary<int, StoveDataModel>();
private SubscriptionToken _subscriptionToken;
private readonly IEventAggregator _eventAggregator;
private readonly IDialogService _dialogService;
public EquipmentMonitorViewModel(IUnityContainer container, IRegionManager regionManager ,IEventAggregator eventAggregator, IDialogService dialogService)
{
_unityContainer = container;
_regionManager = regionManager;
_dialogService = dialogService;
cmdFactories = _unityContainer.Resolve<CmdFactories>();
_taskTypes = _unityContainer.Resolve<TaskTypeService>().GetAll();
_stationList = _unityContainer.Resolve<StationService>().GetAll(); //工站信息
_exCavityInfo = _unityContainer.Resolve<CavityInfoService>().GetExAll().
OrderBy(p => p.Number).ThenBy(x => x.Column).ToList(); //工站详细信息
SetAgvImage((int)EAgvMoveStatus.Wait);
StepIndex = 0;
_eventAggregator = eventAggregator;
_subscriptionToken = _eventAggregator.GetEvent<StoveDataEvent>() //Unsubscribe: 取消订阅(如在组件销毁时)
.Subscribe(OnStoveData, ThreadOption.UIThread); //事件触发时执行的方法,ThreadOption.UIThread,(默认):在发布事件的线程执行
}
// 事件处理方法(接收传递的数据)
private void OnStoveData(Dictionary<int, StoveDataModel> models)
{
CacheStoveData.Clear();
foreach (var kvp in models)
{
CacheStoveData.TryAdd(kvp.Key, kvp.Value);
}
}
public void SetAgvImage(int status)
{
if (lastAgvStatus == (EAgvMoveStatus)status)
{
return;
}
lastAgvStatus = (EAgvMoveStatus)status;
if ((int)EAgvMoveStatus.Wait == status)
{
ImageSource = MyAgvPath.Wait;
}
else if((int)EAgvMoveStatus.Error == status)
{
ImageSource = MyAgvPath.Error;
}
else
{
ImageSource = MyAgvPath.Normal;
}
}
public void Init()
{
GenBrushColor();
GenPopupMenu();
DrawMainWindow();
Task.Run(() => RefreshStoveStatus());
Task.Run(() => RefreshStoveInfo());
Task.Run(() => RefreshAgv());
GetDeviceUnEnable();
}
private void GetDeviceUnEnable()
{
var devices = _unityContainer.Resolve<DeviceConfigService>().GetUnEnableAll();
foreach(var item in devices)
{
CommonCoreHelper.Instance.BlockStatusColor.Add(item);
}
}
private void GenBrushColor()
{
//dicStatusColor.Add((int)EPalletStatus.Init, Brushes.White);
dicStatusColor.Add((int)EPalletStatus.Loading, Brushes.Bisque);
dicStatusColor.Add((int)EPalletStatus.Advisable, Brushes.Purple);
dicStatusColor.Add((int)EPalletStatus.Bake, Brushes.DarkOrange);
dicStatusColor.Add((int)EPalletStatus.BakeOver, Brushes.Green);
dicStatusColor.Add((int)EPalletStatus.WaitTest, Brushes.Gold);
dicStatusColor.Add((int)EPalletStatus.TestOK, Brushes.PaleGreen);
dicStatusColor.Add((int)EPalletStatus.TestNG, Brushes.DeepPink);
dicStatusColor.Add((int)EPalletStatus.Blank, Brushes.LightSteelBlue);
dicStatusColor.Add((int)EPalletStatus.BlankOver, Brushes.White);
dicStatusColor.Add((int)EPalletStatus.Maintain, Brushes.Tan);
}
void ClearDispTask()
{
TaskStatusName = "";
CavitySourceName = "";
CavityTargetName = "";
PalletCode = "";
TaskTypeName = "";
RgvPalletCode = "";
ClearAgvPath();
}
/// <summary>
/// 机器人相关信息刷新
/// </summary>
private void RefreshAgv()
{
var machinMove = new Action<double>(toLocation =>
{
MachineMoveAnimation(toLocation);
});
var task = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask(); //从数据库捞任务
if (null != task)
{
//task.StepId表示正在执行的步
var actions = _unityContainer.Resolve<RgvActionService>().GetPreviousActions(task.StepId);
foreach (var item in actions) //为了刷新界面, 要恢复之前的步信息
{
TTaskRecord newRecord = new TTaskRecord();
newRecord = JSON.DeserializeObject<TTaskRecord>(JSON.SerializeObject(task));
newRecord.StepId = item.StepId;
CommonCoreHelper.Instance.BlockTask.Add(newRecord);
}
}
while (true)
{
if (Global.AppExit)
{
return;
}
//画路径,界面文字信息,机器人位置
TTaskRecord item = CommonCoreHelper.Instance.BlockTask.Take(); //获取并移除元素,当集合为空时会阻塞
LogHelper.Instance.Warn($"{item.Id}-----------------------------item.StepId:{item.StepId}");
if (item.StepId == (int)ETaskStep.None) //删除任务时,界面要清除
{
ClearDispTask();
StepIndex = 0;
continue;
}
SizeAndLocationModel localSoure = dicSizeLocal[item.Source];
SizeAndLocationModel localTarget = dicSizeLocal[item.Target];
TaskStatusName = ((ETaskStep)item.StepId).GetDescription();
if (item.StepId == (int)ETaskStep.Unexecuted) //新任务:界面文字信息, 画路径,为1却执行不到
{
RefreshRgvWindows(item);
}
else if(item.StepId == (int)ETaskStep.MoveFrom) //机器人位置:Form的动画
{
if (string.IsNullOrEmpty(PalletCode))
{
RefreshRgvWindows(item);
}
StartTime = item.BuildTime;
}
else if (item.StepId == (int)ETaskStep.Pick) //正在取盘,还没有取完,所以机器人的托盘号发在下一步
{
machineAnimation.Dispatcher.BeginInvoke(machinMove, localSoure.Left);//Form的动画
}
else if(item.StepId == (int)ETaskStep.MoveTo) //机器人位置:To的动画
{
TPalletInfo pallet = _unityContainer.Resolve<PalletInfoService>().GetPalletInfo(item.PalletId);
RgvPalletCode = pallet.PalletCode;
}
else if (item.StepId == (int)ETaskStep.Place) //
{
machineAnimation.Dispatcher.BeginInvoke(machinMove, localTarget.Left);//To的动画
}
else if (item.StepId == (int)ETaskStep.Finish)
{
ClearDispTask();
}
StepIndex = _unityContainer.Resolve<RgvActionService>().GetAction(item.StepId).Id - 2;
}
}
private void RefreshRgvWindows(TTaskRecord item)
{
LogHelper.Instance.Warn($"--{item.Id}-----------------------------item.StepId:{item.StepId}");
CavityInfoModel cavitySource = _exCavityInfo.Where(x => x.Id == item.Source).FirstOrDefault(); //取位置
CavityInfoModel cavityTarget = _exCavityInfo.Where(x => x.Id == item.Target).FirstOrDefault(); //放位置
TTaskType taskType = _taskTypes.Where(x => x.Id == item.TaskTypeId).FirstOrDefault(); //任务类型
TaskTypeName = (null == taskType) ? "手动任务!" : taskType.Name;//手动任务会为空
CavitySourceName = cavitySource.CavityName;
CavityTargetName = cavityTarget.CavityName;
TPalletInfo pallet = _unityContainer.Resolve<PalletInfoService>().GetPalletInfo(item.PalletId);
PalletCode = pallet.PalletCode;
DrawAgvPath(item); //画路径
}
private void MachineMoveAnimation(double toX)
{
DoubleAnimation x = new DoubleAnimation();
x.To = toX;
Duration duration = new Duration(TimeSpan.FromMilliseconds(5000));
x.Duration = duration;
machineAnimation.BeginAnimation(TranslateTransform.XProperty, x);
}
/// <summary>
/// 连接PLC状态
/// </summary>
private void RefreshStoveStatus()
{
while (true)
{
TDeviceConfig config = CommonCoreHelper.Instance.BlockStatusColor.Take(); //
var stations = _unityContainer.Resolve<StationService>().GetStaions(config.Id);
if (Global.AppExit)
{
return;
}
if (null == stations) continue;
foreach (var station in stations)
{
if (!dicStationStatus.ContainsKey(station.Id)) //这里会导致机器人退出
{
continue;
}
if (!config.Enable) //因为这个只是通讯 (!station.Enable)
{
SetStationColor(station.Id, Colors.Gray);
continue;
}
if (config.IsConnect)
{
SetStationColor(station.Id, Colors.Green);
}
else
{
SetStationColor(station.Id, Colors.Red);
}
}
}
}
private void SetStationColor(int stationId, Color color)
{
if (null == Application.Current
|| null == Application.Current.Dispatcher)
{
return;
}
Application.Current.Dispatcher.Invoke(() =>
{
dicStationStatus[stationId].Fill = new SolidColorBrush(color);
});
}
private void RefreshStoveInfo()
{
bool trigContent = false;
string lastButtonHashValue = "";
string lastToolTipHashValue = "" ;
List<ExCavityInfoModel> cavityInfos = null;
while (true)
{
trigContent = false;
CommonCoreHelper.Instance.MainViewAutoEvent.WaitOne(5000); //没有信息,也二秒刷新一下界面; 有消息,马上能刷
cavityInfos = _unityContainer.Resolve<CavityInfoService>().GetAllExInfo().Where(x=>x.Type != (int)EStationType.AGV).ToList();
string buttonHashValue = JSON.SerializeObject(cavityInfos) ;
string toolTipHashValue = JSON.SerializeObject(CacheStoveData);
Application.Current.Dispatcher.Invoke(() =>
{
if (!string.Equals(lastButtonHashValue, buttonHashValue))
{
trigContent = true;
lastButtonHashValue = buttonHashValue;
foreach (var item in cavityInfos)
{
var button = buttonDic[item.CavityName];
if (!item.Enable || !item.CavityEnable)
{
button.Background = new SolidColorBrush(Colors.Gray);
button.Content = "禁用" + item.PalletCode;
button.ToolTip = null;
continue;
}
else if (item.Lock)
{
button.Background = new SolidColorBrush(Colors.Gray);
button.Content = "锁定" + item.PalletCode;
button.ToolTip = null;
continue;
}
if (dicStatusColor.TryGetValue(item.PalletStatus ?? 0, out SolidColorBrush colorValue))
{
button.Background = colorValue;
}
else //没有夹具item.PalletStatus为0
{
button.Background = new SolidColorBrush(Colors.White);
}
button.Content = item.PalletCode;
//button.ToolTip = ConcatToolTip(item);
if (IsCurrentStation(item))
{
continue;
}
if (item.IsLoad && 0 == item.PalletId)
{
button.Background = new SolidColorBrush(Colors.Red);
button.Content = "有信号|无记忆";
}
else if (!item.IsLoad && 0 != item.PalletId)
{
button.Background = new SolidColorBrush(Colors.Red);
button.Content = "无信号|有记忆";
}
}
}
if (!string.Equals(lastToolTipHashValue, toolTipHashValue)
|| trigContent) //温度变化,刷新
{
lastToolTipHashValue = toolTipHashValue;
foreach (var item in cavityInfos)
{
var button = buttonDic[item.CavityName];
button.ToolTip = ConcatToolTip(item);
}
}
});
}
}
public bool IsCurrentStation(ExCavityInfoModel cavityInfo)
{
TTaskRecord taskRecord = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
if (null == taskRecord)
{
return false;
}
if (taskRecord.Source == cavityInfo.Id
|| taskRecord.Target == cavityInfo.Id)
{
return true;
}
return false;
}
private TextBlock ConcatToolTip(ExCavityInfoModel item)
{
StringBuilder sb = new StringBuilder(200);
sb.AppendLine($"工站名称:{item.CavityName}");
if (!string.IsNullOrEmpty(item.PalletCode))
{
sb.AppendLine($"托盘条码:{item.PalletCode}");
sb.AppendLine($"电池数量:{item.BatteryQty ?? 0}");
if (item.Type == (int)EStationType.Loading)
{
sb.AppendLine($"上料开始时间:{item.LoadingBegingTime}");
}
if (null != item.LoadingOverTime)
{
sb.AppendLine($"上料结束时间:{item.LoadingOverTime}");
}
if (null != item.BakingBeginTime)
{
sb.AppendLine($"开始烘烤:{item.BakingBeginTime}");
}
var datas = JSON.DeserializeObject<ConcurrentDictionary<int, StoveDataModel>>(JSON.SerializeObject(CacheStoveData)); //深拷贝
if (datas.TryGetValue(item.Id, out StoveDataModel data))
{
if (null != data)
{
sb.AppendLine($"温度:{string.Join(",", Math.Round(data.Temps.Average(), 2))}");
sb.AppendLine($"真空值:{string.Join(",", data.Vacuum)}");
if ((int)EPalletStatus.Bake == item.PalletStatus) //烘烤中,才有工作时长
{
sb.AppendLine($"烘烤时长:{data.WorkTime / 60}小时{data.WorkTime % 60}分钟");
sb.AppendLine($"预计结束烘烤:{DateTime.Now.AddMinutes(data.TotalWorkTime - data.WorkTime).ToString("yyyy-MM-dd HH:mm")}");
}
}
}
if (null != item.BakingOverTime)
{
sb.AppendLine($"结束烘烤:{item.BakingOverTime}");
}
}
sb.Length -= Environment.NewLine.Length;
return new TextBlock
{
Text = sb.ToString(),
Foreground = Brushes.White,
Background = Brushes.Blue,
TextWrapping = TextWrapping.Wrap
};
}
private void GenPopupMenu()
{
foreach (var item in _exCavityInfo)
{
ContextMenu menu = new ContextMenu();
menu.Width = 180;
if (item.Type == (int)EStationType.AGV)
{
GenMenuItem("删除当前任务", DeleteCurrentTask_Click, menu);
}
else
{
GenMenuItem("机器人调度", RobotMove_Click, menu);
if (item.Type == (int)EStationType.Stove)
{
GenMenuItem("腔体解锁", DispatchUnlock_Click, menu);
GenMenuItem("初始化", Init_Click, menu);
GenMenuItem("发送配方", SendBakingParam_Click, menu);
GenMenuItem("开始烘烤", StartBaking_Click, menu);
//GenMenuItem("结束烘烤", EndBaking_Click, menu);
GenMenuItem("开门", OpenDoor_Click, menu);
GenMenuItem("关门", CloseDoor_Click, menu);
}
GenMenuItem("禁用", Disenable_Click, menu);
GenMenuItem("可用", Enable_Click, menu);
GenMenuItem("请求取盘", ReqPick_Click, menu);
GenMenuItem("请求放盘", ReqPlace_Click, menu);
}
contextMenuDic.Add(item.CavityName, menu);
}
}
private void SendBakingParam_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
CavityInfoModel cavityInfo = _exCavityInfo.Where(x => x.CavityName == stationName).FirstOrDefault(); //不会刷新
if (MessageBoxResult.OK != HandyControl.Controls.MessageBox.Ask("确认执行发送烘烤配方参数!", "操作提示"))
{
return;
}
TDeviceConfig conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(cavityInfo.StationId);
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
//if (plc == null || !plc.IsConnect)
//{
// LogHelper.Instance.Error($"连接PLC失败plc:{plc.Name}", true);
// return;
//}
ExCavityInfoModel detail = _unityContainer.Resolve<CavityInfoService>().GetAllExInfo().Where(
x => x.Id == cavityInfo.Id && !string.IsNullOrEmpty(x.JobNum)).FirstOrDefault(); //这个腔体的夹具信息
StoveProcessParam processParam = _unityContainer.Resolve<StoveProcessParam>();
if (null == detail)
{
LogHelper.Instance.Error($"{stationName}的夹具没有绑定工单,不能下发烘烤配方!", true);
return;
}
if (!processParam.SendStoveProcessParam(plc, detail))
{
LogHelper.Instance.Error($"{stationName}工站发送配方失败", true);
return;
}
LogHelper.Instance.Info($"【{stationName}】工站发送配方成功", true);
}
private void StartBaking_Click(object sender, RoutedEventArgs e)
{
bool[] bakeEnable = new bool[Global.STOVE_MAX_LAYERS];
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
CavityInfoModel cavityInfo = _exCavityInfo.Where(x => x.CavityName == stationName).FirstOrDefault();
if (MessageBoxResult.OK != HandyControl.Controls.MessageBox.Ask("确认执行开始烘烤", "操作提示"))
{
return;
}
TDeviceConfig conf = _unityContainer.Resolve<DeviceConfigService>().GetConfig(cavityInfo.StationId);
IPLCDevice plc = _unityContainer.Resolve<IPLCDevice>(conf.Name);
if (plc == null || !plc.IsConnect)
{
LogHelper.Instance.Error($"连接PLC失败plc:{plc.Name}", true);
return;
}
List<ExCavityInfoModel> details = _unityContainer.Resolve<CavityInfoService>().GetAllExInfo().Where(
x => x.StationId == cavityInfo.StationId).ToList(); //这个腔体的夹具信息
//待烘烤的夹具
details = details.Where(x => x.PalletStatus == (int)EPalletStatus.Advisable || x.PalletStatus == (int)EPalletStatus.TestNG).ToList();
if (0 == details.Count)
{
LogHelper.Instance.Warn($"烤箱夹具没有状态为【{EPalletStatus.Advisable.GetDescription()},{EPalletStatus.TestNG.GetDescription()}】,不具备烘烤条件!", true);
return;
}
foreach(var item in details)
{
bakeEnable[item.Layer] = true;
}
cmdFactories.StartBaking(plc , cavityInfo.StationId, bakeEnable, true);
int updateResult = _unityContainer.Resolve<PalletInfoService>().UpdateStartBakingInfo(details); //托盘绑定烤箱位置,状态,时间
if (updateResult <= 0)
{
LogHelper.Instance.Warn($"修改烤箱{cavityInfo.StationId},状态失败!");
}
}
//private void EndBaking_Click(object sender, RoutedEventArgs e)
//{
// MenuItem menuItem = (MenuItem)sender;
// ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
// string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
// CavityInfoModel sd = _exCavityInfo.Where(x => x.CavityName == stationName).FirstOrDefault();
// if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认执行结束烘烤", "操作提示"))
// {
// //cmdFactories.EndBaking(sd.StationId);
// }
//}
private void OpenDoor_Click(object sender, RoutedEventArgs e)
{
if (SettingProvider.Instance.DispMode == EDispatchMode.Auto)
{
LogHelper.Instance.Error("自动状态不能开关门!", true);
return;
}
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
CavityInfoModel sd = _exCavityInfo.Where(x=>x.CavityName == stationName).FirstOrDefault();
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认开门", "操作提示"))
{
cmdFactories.OpenDoor(sd.StationId, sd.Layer);
}
}
private void RobotMove_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string buttonName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
var task = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
if (null != task)
{
if (!DeleteTask(task, buttonName))
{
return;
}
}
Views.ManualTask f = new Views.ManualTask(buttonName, _unityContainer);
f.ShowDialog();
}
bool DeleteTask(TTaskRecord task,string stationName)
{
if (MessageBoxResult.Cancel == HandyControl.Controls.MessageBox.Ask("是否删除未执行完成的任务?", "操作提示"))
{
return false;
}
_unityContainer.Resolve<CavityInfoService>().UpdateUnBinding(stationName);
_unityContainer.Resolve<TaskRecordService>().DeleteTask(task.Id);
task.StepId = (int)ETaskStep.None;
CommonCoreHelper.Instance.BlockTask.Add(task);
return true;
}
private void DeleteCurrentTask_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string buttonName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
var task = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
if (null == task)
{
HandyControl.Controls.MessageBox.Info("当前没有未执行完成的任务", "操作提示");
return;
}
DeleteTask(task, buttonName);
}
private void DispatchUnlock_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string cavityName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
CavityInfoModel sd = _exCavityInfo.Where(x => x.CavityName == cavityName).FirstOrDefault();
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认解除调度锁定吗?", "操作提示"))
{
_unityContainer.Resolve<CavityInfoService>().UnLockStation(sd.StationId, (sbyte)sd.Layer, sd.Column);
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
}
}
private void Init_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
CavityInfoModel sd = _exCavityInfo.Where(x => x.CavityName == stationName).FirstOrDefault();
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认初始化?", "操作提示"))
{
cmdFactories.InitStove(sd.StationId, sd.Layer);
}
}
private void DrawStation()
{
foreach (var item in _exCavityInfo)
{
if (item.PosX == (int)EWindowsRowType.Mid)
{
DrawTrack();
}
else
{
var station = _stationList.Where(x => x.Id == item.StationId).FirstOrDefault();
SizeAndLocationModel drawingInfo = GetDrawingLayout(station, item.Layer, item.Column);
dicSizeLocal[item.Id] = drawingInfo; //保存控件位置信息
DrawCanvasButton(item, drawingInfo);
}
}
}
private void SetAgvButton(string name)
{
Button btn = (Button)mainCanvas.FindName(name);
btn.ContextMenu = contextMenuDic[name];
btn.Click += ShowDtl_Click;
}
private void DrawStationTitle()
{
foreach (var item in _stationList.OrderBy(x => x.Id))
{
if (item.PosX != (int)EWindowsRowType.Mid)
{
var drawingInfos = GetDrawingPointTitle(item);
DrawCanvasLabelButton(item, drawingInfos); //画工站控件标题
DrawCanvasStationStatus(item, drawingInfos);//画工站圆圈,状态
}
}
}
private double GetWindowsLastInterval()
{
int maxY = _stationList.Max(s => s.PosY); //最多有多少列
var stationMaxY = _stationList.Where(s => s.PosY == maxY).FirstOrDefault();
int widthSpace = _stationList.Where(x => x.PosX == stationMaxY.PosX).Sum(s => s.LeftMargin); //算出列数最多的一行的间隔
return (widthSpace / maxY); //给最右边的间隔分配宽度
}
/// <summary>
/// 画机器人走的的路径
/// </summary>
private void DrawAgvPath(TTaskRecord task)
{
var sourceInfo = _exCavityInfo.Where(x => x.Id == task.Source).FirstOrDefault();
var targetInfo = _exCavityInfo.Where(x => x.Id == task.Target).FirstOrDefault();
pathCanvas.Dispatcher.BeginInvoke(new Action(delegate
{
pathCanvas.Children.Clear();
CalcFromToPoint(sourceInfo, targetInfo); //by lsm 画机器人走的路径坐标线
}));
}
private void ClearAgvPath()
{
pathCanvas.Dispatcher.BeginInvoke(new Action(delegate
{
pathCanvas.Children.Clear();
}));
}
#region
private void CalcFromToPoint(CavityInfoModel sourceInfo, CavityInfoModel targetInfo)
{
Point pointFrom = GetButtonCenter(sourceInfo.Id);
Point pointTo = GetButtonCenter(targetInfo.Id);
Point point1 = new Point { X = pointFrom.X, Y = _trackPositionY + 9.5 };
Point point2 = new Point { X = pointTo.X, Y = _trackPositionY + 9.5 };
DrawPath(pointFrom, point1, point2, pointTo);
}
private Point GetButtonCenter(int cavityId)
{
var data = dicSizeLocal[cavityId];
double width = data.Width;
double height = data.Height;
double left = data.Left;
double top = data.Top;
return new Point
{
X = (left + width / 2),
Y = (top + height / 2)
};
}
private void DrawPath(Point point01, Point point02, Point point03, Point point04)
{
Polyline polyline = new Polyline()
{
Stroke = Brushes.Green,
StrokeThickness = 3,
FillRule = FillRule.EvenOdd
};
polyline.Points.Add(point01);
polyline.Points.Add(point02);
polyline.Points.Add(point03);
polyline.Points.Add(point04);
pathCanvas.Children.Add(polyline);
DrawTriangle(point02, point02.Y > point01.Y ? Direction.Down : Direction.Up);
DrawTriangle(point03, point02.X < point03.X ? Direction.Right : Direction.Left);
if (Math.Abs(point02.X - point03.X) > 40)
{
int i = 1;
while (point02.X + 30 * i < point03.X)
{
DrawTriangle(new Point(point02.X + 30 * i, point03.Y), Direction.Right);
i++;
}
i = 1;
while (point02.X - 30 * i > point03.X)
{
DrawTriangle(new Point(point02.X - 30 * i, point03.Y), Direction.Left);
i++;
}
}
DrawTriangle(point04, point03.Y < point04.Y ? Direction.Down : Direction.Up);
}
private void DrawTriangle(Point point, Direction direction)
{
double length = 6;
int thickness = 3;
Polyline polyline = new Polyline
{
Stroke = Brushes.Yellow,
StrokeThickness = thickness,
FillRule = FillRule.EvenOdd
};
PointCollection points = new PointCollection();
switch (direction)
{
case Direction.Right:
points.Add(new Point(point.X - length, point.Y - length));
points.Add(point);
points.Add(new Point(point.X - length, point.Y + length));
break;
case Direction.Left:
points.Add(new Point(point.X + length, point.Y - length));
points.Add(point);
points.Add(new Point(point.X + length, point.Y + length));
break;
case Direction.Down:
points.Add(new Point(point.X - length, point.Y - length));
points.Add(point);
points.Add(new Point(point.X + length, point.Y - length));
break;
case Direction.Up:
points.Add(new Point(point.X - length, point.Y + length));
points.Add(point);
points.Add(new Point(point.X + length, point.Y + length));
break;
}
polyline.Points = points;
pathCanvas.Children.Add(polyline);
}
#endregion
private void DrawTrack()
{
double spacing = 15;
var agv = _exCavityInfo.Where(x => x.PosX == (int)EWindowsRowType.Mid).FirstOrDefault();
SetAgvButton(agv.CavityName); //设置下拉框
SizeAndLocationModel drawingInfo = GetDrawingLayout(agv, agv.Layer, agv.Column);
double startX = drawingInfo.Left;
double endX = _localScreenWidth - GetWindowsLastInterval();
double topY = drawingInfo.Top + 20;
double bottomY = drawingInfo.Top + drawingInfo.Height - 20;
_trackPositionY = drawingInfo.Top + drawingInfo.Height / 2 - 10;
//HandMachineYLocation = drawingInfo.Top; //机器人的Y坐标(有偏差,如何修正)控制高73
HandMachineYLocation = _trackPositionY + 9 - 73 / 2; //控制高73:为图片的高度,界面写死了
Path path = new Path
{
Stroke = Brushes.Black,
StrokeThickness = 2
};
// 1. 绘制两条平行轨道
path.Data = Geometry.Parse($"M {startX},{topY} L {endX},{topY}");
path.Data = Geometry.Parse($"{path.Data} M {startX},{bottomY} L {endX},{bottomY}");
// 2. 绘制轨枕(竖线)
for (double x = startX; x <= endX; x += spacing)
{
path.Data = Geometry.Parse($"{path.Data} M {x},{topY - 5} L {x},{bottomY + 5}"); //如果不需要突出来,-5可以去掉
}
mainCanvas.Children.Add(path);
}
private void DrawMainWindow()
{
DrawStation();
DrawStationTitle();
DrawLegend();
//DrawTrack();
//DrawAgvPath(); //
}
private void DrawLegend()
{
TStation station = _stationList.Find(x => x.Type == (int)EStationType.ManualPlat); //在【人工夹具平台】上面。
var cavity = _exCavityInfo.Find(x => x.StationId == station.Id);
var drawingInfo = dicSizeLocal[cavity.Id];
var legendEntries = new[]
{
new LegendEntry { Status = "OKStatus", Left = drawingInfo.Left , Top = 100d, Color = Colors.Green, Description = "正常" },
new LegendEntry { Status = "NGStatus", Left = drawingInfo.Left, Top = 120d, Color = Colors.Red, Description = "中断" },
new LegendEntry { Status = "DisableStatus", Left = drawingInfo.Left, Top = 139d, Color = Colors.Gray, Description = "禁用" }
};
foreach (var entry in legendEntries)
{
DrawLegendEntry(entry);
}
}
private void DrawLegendEntry(LegendEntry entry)
{
var drawingInfo = new SizeAndLocationModel { Left = entry.Left, Top = entry.Top, Width = 10d, Height = 10d };
DrawCanvasStationStatusWithLalel(entry.Status, new List<SizeAndLocationModel> { drawingInfo }, entry.Color, entry.Description);
}
private void DrawCanvasStationStatusWithLalel(string name, List<SizeAndLocationModel> drawingInfoModels, Color color, string labelName)
{
foreach (var item in drawingInfoModels)
{
var arrow = CreateArrow(name, item, color);
mainCanvas.Children.Add(arrow);
var label = CreateLabel(labelName, item);
mainCanvas.Children.Add(label);
}
}
private Label CreateLabel(string labelName, SizeAndLocationModel drawingInfo)
{
double x = (drawingInfo.Left + 20) ;
double y = (drawingInfo.Top + 13) ;
var label = new Label
{
Content = labelName,
Background = new SolidColorBrush(TransparentColor),
BorderThickness = BorderThickness,
FontSize = 16,
};
label.SetValue(Window.LeftProperty, x);
label.SetValue(Window.TopProperty, y - 13);
return label;
}
private const double ArrowRadius = 7;
private static readonly Color TransparentColor = Colors.Transparent;
private static readonly Thickness BorderThickness = new Thickness(0);
private System.Windows.Shapes.Path CreateArrow(string name, SizeAndLocationModel drawingInfo, Color color)
{
var arrow = new System.Windows.Shapes.Path
{
Name = name + "状态",
Fill = new SolidColorBrush(color)
};
double x = (drawingInfo.Left + 20);
double y = (drawingInfo.Top + 13);
var figure = new PathFigure { IsClosed = true, StartPoint = new Point(x, y) };
figure.Segments.Add(new ArcSegment(new Point(x, y + ArrowRadius / 2), new Size(ArrowRadius, ArrowRadius), 1, true, SweepDirection.Counterclockwise, true));
var geometry = new PathGeometry { Figures = { figure } };
arrow.Data = geometry;
return arrow;
}
private LinearGradientBrush CreateLinearGradientBrush()
{
var brush = new LinearGradientBrush
{
StartPoint = new Point(0, 0.5),
EndPoint = new Point(1, 0.5),
GradientStops = GradientStops
};
return brush;
}
private static readonly GradientStopCollection GradientStops = new GradientStopCollection
{
new GradientStop(Colors.White, 0.0),
new GradientStop(Colors.MediumSlateBlue, 0.3),
new GradientStop(Colors.MediumSlateBlue, 0.7),
new GradientStop(Colors.White, 1.0)
};
/// <summary>
/// 绘制画布工站标签名称图标
/// </summary>
/// <param name="Name">标签名称</param>
/// <param name="drawingInfoModels">工站位置</param>
private void DrawCanvasLabelButton(TStation station, SizeAndLocationModel drawingInfo)
{
var button = new Button
{
Name = $"{station.Name}",
Content = $"{station.Desc}",
FontSize = 10,
Width = drawingInfo.Width,
Height = drawingInfo.Height ,
Foreground = new SolidColorBrush(Colors.White),
Background = CreateLinearGradientBrush()
};
button.SetValue(Window.LeftProperty, drawingInfo.Left);
button.SetValue(Window.TopProperty, drawingInfo.Top);
mainCanvas.Children.Add(button);
}
/// <summary>
/// 绘制画布工站每行每列电池信息图标
/// </summary>
/// <param name="Name"></param>
/// <param name="drawingInfoModels"></param>
private void DrawCanvasButton(CavityInfoModel cavityInfo, SizeAndLocationModel drawingInfo)
{
int number = 0;
Button button = new Button
{
Name = cavityInfo.CavityName,
Width = drawingInfo.Width ,
Height = drawingInfo.Height,
Background = new SolidColorBrush(Colors.White),
Foreground = new SolidColorBrush(Colors.Black),
Style = frameworkElement.FindResource("MyButton") as Style,
ContextMenu = contextMenuDic[cavityInfo.CavityName],
};
button.Click += ShowDtl_Click;
button.SetValue(Window.LeftProperty, drawingInfo.Left);
button.SetValue(Window.TopProperty, drawingInfo.Top);
ToolTipService.SetShowDuration(button, 20_000);
ToolTipService.SetHorizontalOffset(button, 0);
ToolTipService.SetVerticalOffset(button, 0);
// 2. 构建Button的自定义模板核心左侧显示"1"
if (cavityInfo.Type == (int)EStationType.Stove)
{
number = cavityInfo.Layer;
}
else
{
number = cavityInfo.Column;
}
ControlTemplate buttonTemplate = CreateButtonTemplateWithLeftNumber(number);
//ControlTemplate buttonTemplate = SetButtonTemplateWithCursor();
button.Template = buttonTemplate;
//button.OverridesDefaultStyle = true;
mainCanvas.Children.Add(button);
buttonDic.Add(button.Name, button);
}
public ControlTemplate SetButtonTemplateWithCursor()
{
// 2. 构造模板根Border
FrameworkElementFactory border = new FrameworkElementFactory(typeof(Border));
border.Name = "root";
border.SetValue(Border.BackgroundProperty, Brushes.LightGray);
border.SetValue(Border.BorderBrushProperty, Brushes.Gray);
border.SetValue(Border.BorderThicknessProperty, new Thickness(1));
border.SetValue(Border.CornerRadiusProperty, new CornerRadius(2));
// 3. 构造内容区ContentPresenter
FrameworkElementFactory presenter = new FrameworkElementFactory(typeof(ContentPresenter));
presenter.SetValue(ContentPresenter.HorizontalAlignmentProperty, HorizontalAlignment.Center);
presenter.SetValue(ContentPresenter.VerticalAlignmentProperty, VerticalAlignment.Center);
border.AppendChild(presenter);
// 4. 把模板树装进 ControlTemplate
ControlTemplate template = new ControlTemplate(typeof(Button));
template.VisualTree = border;
// 5. 准备两个触发器:鼠标进入/离开
Trigger overTrigger = new Trigger
{
Property = UIElement.IsMouseOverProperty,
Value = true
};
overTrigger.Setters.Add(new Setter(Control.CursorProperty, Cursors.Hand));
overTrigger.Setters.Add(new Setter(Border.BackgroundProperty, Brushes.DodgerBlue)
{ TargetName = "root" });
Trigger leaveTrigger = new Trigger
{
Property = UIElement.IsMouseOverProperty,
Value = false
};
leaveTrigger.Setters.Add(new Setter(System.Windows.Controls.Control.CursorProperty, Cursors.Arrow));
leaveTrigger.Setters.Add(new Setter(Border.BackgroundProperty, Brushes.LightGray)
{ TargetName = "root" });
template.Triggers.Add(overTrigger);
template.Triggers.Add(leaveTrigger);
return template;
}
private ControlTemplate CreateButtonTemplateWithLeftNumber(int layer)
{
// 1. 创建模板指定目标类型为Button
ControlTemplate template = new ControlTemplate(typeof(Button));
// 2. 创建Grid作为模板的根元素分两列布局
FrameworkElementFactory gridFactory = new FrameworkElementFactory(typeof(Grid));
gridFactory.SetValue(Grid.SnapsToDevicePixelsProperty, true);
//// 绑定Grid的Background到Button的Background属性
gridFactory.SetBinding(Grid.BackgroundProperty, new System.Windows.Data.Binding("Background") { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent });
// 3. 定义Grid的两列左列固定宽度右列自适应
// 左列(显示"1"
FrameworkElementFactory col1 = new FrameworkElementFactory(typeof(ColumnDefinition));
col1.SetValue(ColumnDefinition.WidthProperty, new GridLength(16));
// 右列显示Content
FrameworkElementFactory col2 = new FrameworkElementFactory(typeof(ColumnDefinition));
col2.SetValue(ColumnDefinition.WidthProperty, new GridLength(1, GridUnitType.Star));
gridFactory.AppendChild(col1);
gridFactory.AppendChild(col2);
// 4. 创建左侧显示"1"的TextBlock
FrameworkElementFactory numberText = new FrameworkElementFactory(typeof(TextBlock));
numberText.SetValue(TextBlock.TextProperty, layer.ToString());
numberText.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Left);
numberText.SetValue(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center);
numberText.SetValue(TextBlock.FontSizeProperty, 14.0);
numberText.SetValue(TextBlock.ForegroundProperty, Brushes.Blue);
numberText.SetValue(Grid.ColumnProperty, 0); // 放在第一列
gridFactory.AppendChild(numberText);
// 5. 创建ContentPresenter显示Button原有Content放在第二列
FrameworkElementFactory contentPresenter = new FrameworkElementFactory(typeof(ContentPresenter));
contentPresenter.SetValue(Grid.ColumnProperty, 1);
// 绑定ContentPresenter的对齐方式和内边距到Button的原有属性
contentPresenter.SetBinding(ContentPresenter.HorizontalAlignmentProperty, new System.Windows.Data.Binding("HorizontalContentAlignment") { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent });
contentPresenter.SetBinding(ContentPresenter.VerticalAlignmentProperty, new System.Windows.Data.Binding("VerticalContentAlignment") { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent });
contentPresenter.SetBinding(ContentPresenter.MarginProperty, new System.Windows.Data.Binding("Padding") { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent });
gridFactory.AppendChild(contentPresenter);
// 6. 添加边框保留Button的边框样式可选
FrameworkElementFactory border = new FrameworkElementFactory(typeof(Border));
border.Name = "border";
border.SetValue(Grid.ColumnSpanProperty, 2); // 跨两列
border.SetBinding(Border.BorderBrushProperty, new System.Windows.Data.Binding("BorderBrush") { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent });
border.SetBinding(Border.BorderThicknessProperty, new System.Windows.Data.Binding("BorderThickness") { RelativeSource = System.Windows.Data.RelativeSource.TemplatedParent });
border.SetValue(Border.BackgroundProperty, Brushes.Transparent);
gridFactory.AppendChild(border);
template.Triggers.Add(CreateTriggers());
// 7. 将Grid设为模板的视觉树根
template.VisualTree = gridFactory;
return template;
}
#region
Trigger CreateTriggers()
{
var mouseOverTrigger = new Trigger
{
Property = Button.IsMouseOverProperty,
Value = true
};
//mouseOverTrigger.Setters.Add(new Setter(Control.CursorProperty, Cursors.Hand));
// 悬停时修改背景
//mouseOverTrigger.Setters.Add(new Setter
//{
// TargetName = "border",
// Property = Border.BackgroundProperty,
// Value = Brushes.DodgerBlue
//});
// 悬停时修改边框
mouseOverTrigger.Setters.Add(new Setter
{
TargetName = "border",
Property = Border.BorderBrushProperty,
Value = Brushes.Blue //.DeepSkyBlue
});
// 悬停时修改文字颜色直接改Button的ForegroundContentPresenter会继承
//mouseOverTrigger.Setters.Add(new Setter
//{
// Property = Button.ForegroundProperty,
// Value = Brushes.Red
//});
//// 可选:悬停添加阴影
mouseOverTrigger.Setters.Add(new Setter
{
TargetName = "border",
Property = Border.EffectProperty,
Value = new DropShadowEffect { BlurRadius = 15, Color = Color.FromRgb(255, 0, 0), Opacity = 10.6 }
});
return mouseOverTrigger;
}
#endregion
/// <summary>
/// 绘制工站通信状态图标
/// </summary>
/// <param name="stationInfoAndDetail"></param>
/// <param name="drawLeft"></param>
/// <param name="drawTop"></param>
private void DrawCanvasStationStatus(TStation station, SizeAndLocationModel item) //index=0开始
{
System.Windows.Shapes.Path x_Arrow = new System.Windows.Shapes.Path();//x轴箭头
x_Arrow.Name = $"{station.Name}状态";
x_Arrow.Fill = new SolidColorBrush(Colors.Red); //station.Enable ? Colors.Red : Colors.Gray
PathFigure x_Figure = new PathFigure();
x_Figure.IsClosed = true;
double x = (item.Left + 20) ;
double y = (item.Top + 13);
double r = 7;//圆的半径
x_Figure.StartPoint = new Point(x, y);//路径的起点
x_Figure.Segments.Add(new ArcSegment(new Point(x, y + r / 2), new Size(r, r), 1, true, SweepDirection.Counterclockwise, true));
PathGeometry x_Geometry = new PathGeometry();
x_Geometry.Figures.Add(x_Figure);
x_Arrow.Data = x_Geometry;
mainCanvas.Children.Add(x_Arrow);
dicStationStatus.Add(station.Id, x_Arrow);
}
#region /
/// <summary>
/// 左键单击
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ShowDtl_Click(object sender, RoutedEventArgs e)
{
string buttonName = (sender as Button).Name;
Views.CavityDtlView dlg = new Views.CavityDtlView(buttonName, _unityContainer);
dlg.ShowDialog();
//var p = new DialogParameters();
//p.Add("StatinName", buttonName);
//_dialogService.ShowDialog(nameof(CavityDtlView), p, r => { /*回调*/ });
}
/// <summary>
/// 右键禁用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Disenable_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认" + stationName + "禁用?", "操作提示"))
{
_unityContainer.Resolve<CavityInfoService>().ChangeStationStatus(stationName, 0);
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
HandyControl.Controls.Growl.Info(stationName + " 已经禁用。");
}
}
private void CloseDoor_Click(object sender, RoutedEventArgs e)
{
if (SettingProvider.Instance.DispMode == EDispatchMode.Auto)
{
LogHelper.Instance.Error("自动状态不能开关门!", true);
return;
}
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
CavityInfoModel sd = _exCavityInfo.Where(x => x.CavityName == stationName).FirstOrDefault();
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认关门?", "操作提示"))
{
cmdFactories.CloseDoor(sd.StationId, sd.Layer);
}
}
private void DeleteTask_Click(object sender, RoutedEventArgs e)
{
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认要删除当前任务?", "操作提示"))
{
if (0 >= _unityContainer.Resolve<TaskRecordService>().DeleteUnexecuteTask())
{
LogHelper.Instance.Error($"当前没有可执行的任务或当前任务删除失败", true);
}
else
{
LogHelper.Instance.Info($"当前任务已删除", true);
}
}
}
/// <summary>
/// 右键可用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Enable_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认" + stationName + "可用?", "操作提示"))
{
_unityContainer.Resolve<CavityInfoService>().ChangeStationStatus(stationName, 1);
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
HandyControl.Controls.Growl.Info(stationName + " 已经可用。");
}
}
private void ReqPick_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认" + stationName + "请求取盘?", "操作提示"))
{
_unityContainer.Resolve<CavityInfoService>().UpdateStationReq(stationName, (sbyte)ECavityStatus.RequestPick);
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
HandyControl.Controls.Growl.Info(stationName + " 已经请求取盘。");
}
}
private void ReqPlace_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = (MenuItem)sender;
ContextMenu popupMenu = (ContextMenu)menuItem.Parent;
string stationName = ((FrameworkElement)popupMenu.PlacementTarget).Name;
if (MessageBoxResult.OK == HandyControl.Controls.MessageBox.Ask("确认" + stationName + "请求放盘?", "操作提示"))
{
_unityContainer.Resolve<CavityInfoService>().UpdateStationReq(stationName, (sbyte)ECavityStatus.RequestPlace);
CommonCoreHelper.Instance.MainViewAutoEvent.Set();
HandyControl.Controls.Growl.Info(stationName + " 已经请求放盘。");
}
}
private void GenMenuItem(string menuText, RoutedEventHandler click, ContextMenu contextMenu)
{
MenuItem menu = new MenuItem();
menu.Header = menuText;
menu.Foreground = new SolidColorBrush(Colors.Purple);
menu.Click += click;
contextMenu.Items.Add(menu);
}
#endregion
#region
/// <summary>
/// 获取工站长度
/// </summary>
/// <param name="stationPosX">工站当前行号</param>staionDetail.PosX, staionDetail.PosX == (int)EWindowsRowType.Mid
/// <returns></returns>
private double GetDrawPointWidth()
{
int maxY = _stationList.Max(s => s.PosY); //一起有多少列
var stationMaxY = _stationList.Where(s => s.PosY == maxY).FirstOrDefault() ;
int widthSpace = _stationList.Where(x=>x.PosX == stationMaxY.PosX).Sum(s => s.LeftMargin); //算出列数最多的一行的间隔
widthSpace += (widthSpace / maxY); //给最右边的间隔分配宽度
return (_localScreenWidth - widthSpace) / maxY; //_localScreenWidth - widthSpace:减去左右之间的间隔
}
/// <summary>
/// 获取工站明细左边距
/// </summary>
/// <param name="stationPosX">工站当前行号</param>
/// <param name="stationPosY">工站当前列位置</param> int stationPosX, int stationPosY, double widthPoint
/// <param name="widthPoint">工站明细宽度</param>
/// <returns></returns>
private double GetDrawPointLeft(TStation staionDetail, double controlWidth, int cavityColunm )
{
int leftCavityCols = 0;
double leftPoints = 0;
int widthSpace = 0;
if (SettingProvider.Instance.StoveDispDirection == EIsReverseOrder.Positive)
{
widthSpace = _stationList.Where(x => x.PosY <= staionDetail.PosY && x.PosX == staionDetail.PosX).Sum(s => s.LeftMargin);
}
else
{
widthSpace = _stationList.Where(x => x.PosY >= staionDetail.PosY && x.PosX == staionDetail.PosX).Sum(s => s.LeftMargin);
}
if (staionDetail.PosX == (int)EWindowsRowType.Mid)
{
leftPoints = staionDetail.LeftMargin;
}
else if (staionDetail.PosX == (int)EWindowsRowType.Upper)
{
if (staionDetail.Type == (int)EStationType.Loading
|| staionDetail.Type == (int)EStationType.UnLoading)
{
leftCavityCols = ((SettingProvider.Instance.IsReverseOrder == EIsReverseOrder.Positive) ?
cavityColunm : (1 == cavityColunm ? 2 : 1) - 1);
leftPoints = widthSpace + GetLeftStationWidth(staionDetail, controlWidth) + controlWidth * leftCavityCols;
}
else
{
leftPoints = widthSpace + GetLeftStationWidth(staionDetail, controlWidth) + controlWidth * (cavityColunm - 1);
}
}
else if (staionDetail.PosX == (int)EWindowsRowType.Lower)
{
if (staionDetail.Type == (int)EStationType.Loading
|| staionDetail.Type == (int)EStationType.UnLoading)
{
leftCavityCols = ((SettingProvider.Instance.IsReverseOrder == EIsReverseOrder.Positive) ?
cavityColunm : (1 == cavityColunm ? 2 : 1) - 1);
leftPoints = widthSpace + GetLeftStationWidth(staionDetail, controlWidth) + controlWidth * leftCavityCols;
}
else
{
leftPoints = widthSpace + GetLeftStationWidth(staionDetail, controlWidth) + controlWidth * (cavityColunm - 1);
}
}
return leftPoints;
}
private double GetLeftStationWidth(TStation staionDetail, double controlWidth)
{
double w = 0;
List<TStation> stations = null;
if (SettingProvider.Instance.StoveDispDirection == EIsReverseOrder.Positive)
{
stations = _stationList.Where(x => x.PosX == staionDetail.PosX && x.PosY < staionDetail.PosY).ToList();
}
else
{
stations = _stationList.Where(x => x.PosX == staionDetail.PosX && x.PosY > staionDetail.PosY).ToList();
}
if (0 == stations.Count) //表示左边没有控件
{
return w;
}
foreach (var item in stations)
{
w += item.Columns * controlWidth;
}
return w;
}
/// <summary>
/// 获取工站明细高度
/// </summary>
/// <param name="stationLayerCount">每个工站包含工站明细数量</param>
/// <returns></returns>
private double GetDrawPointHeight(int PosX)
{
//double screenHeightAvg = 0;
//if (staionDetail.PosX == (int)EWindowsRowType.Upper)
//{
// screenHeightAvg = _localScreenHeight / MainRowDefinition.TotalHeight * MainRowDefinition.UpperHeight;
//}
//else if (staionDetail.PosX == (int)EWindowsRowType.Mid)
//{
// screenHeightAvg = _localScreenHeight / MainRowDefinition.TotalHeight * MainRowDefinition.MidHeight;
//}
//else
//{
// screenHeightAvg = _localScreenHeight / MainRowDefinition.TotalHeight * MainRowDefinition.LowerHeight;
//}
//return screenHeightAvg / staionDetail.Layers;
double screenHeightAvg = 0;
int Layer = 0;
if (PosX == (int)EWindowsRowType.Mid)
{
Layer = 1;
screenHeightAvg = _localScreenHeight / MainRowDefinition.TotalHeight * MainRowDefinition.MidHeight;
}
else
{
Layer = _stationList.Max(s => s.Layers); //一起有多少列
var stationLayers = _stationList.Where(s => s.Layers == Layer).FirstOrDefault();
if (stationLayers.PosX == (int)EWindowsRowType.Upper)
{
screenHeightAvg = _localScreenHeight / MainRowDefinition.TotalHeight * MainRowDefinition.UpperHeight;
}
else
{
screenHeightAvg = _localScreenHeight / MainRowDefinition.TotalHeight * MainRowDefinition.LowerHeight;
}
}
return screenHeightAvg / Layer;
}
/// <summary>
/// 获取工站明细上边距
/// </summary>
/// <param name="stationPosX">工站当前行号</param>
/// <param name="stationDetailNumber">工站明细编号</param>
/// <param name="stationLayerHeight">工站明细层高</param>
/// <param name="isMaxStationColumns">最大层高数量</param>
/// <returns></returns>
private double GetDrawPointTop(TStation staionDetail, double height, int Layer)
{
double topPoints = 0;
if (staionDetail.PosX == (int)EWindowsRowType.Mid)
{
topPoints = _localScreenHeight / MainRowDefinition.TotalHeight * (MainRowDefinition.UpperHeight + MainRowDefinition.UpperSpacing) //控件的第一行
+ (staionDetail.Layers - Layer) * height;
}
else if (staionDetail.PosX == (int)EWindowsRowType.Upper)
{
int totalRows = _stationList.Where(x => x.PosX == staionDetail.PosX).Max(x => x.Layers);
topPoints = _localScreenHeight / MainRowDefinition.TotalHeight * MainRowDefinition.UpperSpacing
+ (totalRows - Layer) * height;
//+ (staionDetail.Layers - Layer) * height;
}
else if (staionDetail.PosX == (int)EWindowsRowType.Lower)
{
topPoints = _localScreenHeight / MainRowDefinition.TotalHeight * (MainRowDefinition.UpperHeight + MainRowDefinition.UpperSpacing + MainRowDefinition.MidHeight)
+ (staionDetail.Layers - Layer) * height;
}
return topPoints;
}
/// <summary>
/// 获取工站标签上边距
/// </summary>
/// <param name="station">工站</param>
/// <param name="drawingInfoHeight">工站标签高度</param>
/// <returns></returns>
private SizeAndLocationModel GetDrawingPointTitle(TStation station)
{
int? cavitylId = 0;
double drawingInfoTop = 0;
SizeAndLocationModel drawingInfo = new SizeAndLocationModel();
if (SettingProvider.Instance.IsReverseOrder == EIsReverseOrder.Positive)
{
cavitylId = _exCavityInfo.OrderBy(p => p.Column).FirstOrDefault(s => s.StationId == station.Id)?.Id;
}
else
{
cavitylId = _exCavityInfo.OrderByDescending(p => p.Column).FirstOrDefault(s => s.StationId == station.Id)?.Id;
}
drawingInfo = dicSizeLocal[cavitylId ?? 0];
if (station.PosX == (int)EWindowsRowType.Lower)
{
drawingInfoTop = drawingInfo.Top + drawingInfo.Height;
}
else
{
drawingInfoTop = drawingInfo.Top - (drawingInfo.Height * (station.Layers - 1)) - Global.WINDOWS_CONTROLS_HEAD_HIGHT;
}
return new SizeAndLocationModel
{
Width = drawingInfo.Width * station.Columns,
Left = drawingInfo.Left,
Top = drawingInfoTop,
Height = Global.WINDOWS_CONTROLS_HEAD_HIGHT
};
}
public DelegateCommand<object> ReSendCommand => new DelegateCommand<object>((x) =>
{
short stepId = short.Parse((string)x);
var SelectTaskRecord = _unityContainer.Resolve<TaskRecordService>().UnexecuteTask();
if (null == SelectTaskRecord
|| 0 == SelectTaskRecord.Id
|| 0 == SelectTaskRecord.Target)
{
HandyControl.Controls.MessageBox.Warning("当前没有未完成的任务!", "警告");
return;
}
if ((int)ETaskStatus.ExecutionCompleted == SelectTaskRecord.Status)
{
HandyControl.Controls.MessageBox.Warning("已经完成的任务不能再发送!", "警告");
return;
}
if (System.Windows.MessageBoxResult.OK ==
HandyControl.Controls.MessageBox.Ask($"你确定重新发送【{((ETaskStep)stepId).GetDescription()}】指令到PLC", "发送指令"))
{
if (_unityContainer.Resolve<ICommonFun>().ManualTaskCmd(SelectTaskRecord, stepId))
{
HandyControl.Controls.MessageBox.Info("发送成功");
}
else
{
HandyControl.Controls.MessageBox.Fatal("发送失败,请重新发送!", "警示");
}
}
});
/// <summary>
/// 获取一行一列的位置
/// </summary>
/// <param name="stationInfoAndDetails"></param>
/// <param name="drawingInfo"></param>
private SizeAndLocationModel GetDrawingLayout(TStation staionDetail, int layer, int colunm)
{
SizeAndLocationModel drawingInfo = new SizeAndLocationModel();
drawingInfo.Width = GetDrawPointWidth();
drawingInfo.Height = GetDrawPointHeight(staionDetail.PosX);
drawingInfo.Left = GetDrawPointLeft(staionDetail, drawingInfo.Width, colunm);
drawingInfo.Top = GetDrawPointTop(staionDetail, drawingInfo.Height, layer);
return drawingInfo;
}
#endregion
}
}