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

1674 lines
72 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
}