1674 lines
72 KiB
C#
1674 lines
72 KiB
C#
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的Foreground,ContentPresenter会继承)
|
||
//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
|
||
}
|
||
}
|