From c2a25dae69b60b255c327b00085fdf5eba512450 Mon Sep 17 00:00:00 2001 From: "SIC1016\\caipeilun" <123456> Date: Wed, 13 Sep 2023 17:28:59 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9PMCharting=E7=95=8C=E9=9D=A2?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96Charting=E5=8A=9F=E8=83=BD=201.?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E4=B8=8E=E5=9B=BE=E5=BD=A2=E6=95=B4=E5=90=88?= =?UTF-8?q?=E5=88=B0=E4=B8=80=E4=B8=AA=E7=95=8C=E9=9D=A2=E4=B8=AD=202.?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E4=B8=8D=E5=B8=B8=E7=94=A8=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E7=95=8C=E9=9D=A2=E6=95=B4=E7=90=86=203.=E9=80=89?= =?UTF-8?q?=E4=B8=AD=E6=9B=B2=E7=BA=BF=E5=90=8E=E7=82=B9=E5=87=BB=E5=9B=BE?= =?UTF-8?q?=E5=BD=A2=EF=BC=8C=E5=8F=AF=E4=BF=AE=E6=94=B9=E6=9B=B2=E7=BA=BF?= =?UTF-8?q?=E5=9D=90=E6=A0=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SicUI/Config/Menu.xml | 3 +- SicUI/Models/PMs/Charting/ChartDataLineX.cs | 4 +- .../Models/PMs/Charting/PMChartingV2View.xaml | 637 +++++++++++++++ .../PMs/Charting/PMChartingV2View.xaml.cs | 103 +++ .../PMs/Charting/PMChartingV2ViewModel.cs | 723 ++++++++++++++++++ SicUI/SicUI.csproj | 8 + 6 files changed, 1475 insertions(+), 3 deletions(-) create mode 100644 SicUI/Models/PMs/Charting/PMChartingV2View.xaml create mode 100644 SicUI/Models/PMs/Charting/PMChartingV2View.xaml.cs create mode 100644 SicUI/Models/PMs/Charting/PMChartingV2ViewModel.cs diff --git a/SicUI/Config/Menu.xml b/SicUI/Config/Menu.xml index e430e91c..6a9725cb 100644 --- a/SicUI/Config/Menu.xml +++ b/SicUI/Config/Menu.xml @@ -27,7 +27,8 @@ - + + diff --git a/SicUI/Models/PMs/Charting/ChartDataLineX.cs b/SicUI/Models/PMs/Charting/ChartDataLineX.cs index b65fd402..97be7a87 100644 --- a/SicUI/Models/PMs/Charting/ChartDataLineX.cs +++ b/SicUI/Models/PMs/Charting/ChartDataLineX.cs @@ -111,7 +111,7 @@ namespace SicUI.Models.PMs.Charting if (Math.Abs(_dataOffset - value) > 0.001) { _dataOffset = value; - InvokePropertyChanged(nameof(DataFactor)); + InvokePropertyChanged(nameof(DataOffset)); UpdateChartSeriesValue(); } } @@ -123,7 +123,7 @@ namespace SicUI.Models.PMs.Charting set { _dataxOffset = value; - InvokePropertyChanged(nameof(DataFactor)); + InvokePropertyChanged(nameof(DataXOffset)); RePaintChartSeriesValue(); } } diff --git a/SicUI/Models/PMs/Charting/PMChartingV2View.xaml b/SicUI/Models/PMs/Charting/PMChartingV2View.xaml new file mode 100644 index 00000000..4e307619 --- /dev/null +++ b/SicUI/Models/PMs/Charting/PMChartingV2View.xaml @@ -0,0 +1,637 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SicUI/Models/PMs/Charting/PMChartingV2View.xaml.cs b/SicUI/Models/PMs/Charting/PMChartingV2View.xaml.cs new file mode 100644 index 00000000..cdd163c1 --- /dev/null +++ b/SicUI/Models/PMs/Charting/PMChartingV2View.xaml.cs @@ -0,0 +1,103 @@ +using SciChart.Charting.Visuals.RenderableSeries; +using SciChart.Charting.Visuals; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Interactivity; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace SicUI.Models.PMs.Charting +{ + /// + /// PMChartingV2View.xaml 的交互逻辑 + /// + public partial class PMChartingV2View : UserControl + { + public PMChartingV2View() + { + InitializeComponent(); + } + } + + public class SciChartMouseDownChangingLocationBehavior : Behavior + { + + + + public AxisInfo YAxisInfo + { + get { return (AxisInfo)GetValue(YAxisInfoProperty); } + set { SetValue(YAxisInfoProperty, value); } + } + + public static readonly DependencyProperty YAxisInfoProperty = + DependencyProperty.Register("YAxisInfo", typeof(AxisInfo), typeof(SciChartMouseDownChangingLocationBehavior), new PropertyMetadata(null)); + + + + public AxisInfo XAxisInfo + { + get { return (AxisInfo)GetValue(XAxisInfoProperty); } + set { SetValue(XAxisInfoProperty, value); } + } + + // Using a DependencyProperty as the backing store for XAxisInfo. This enables animation, styling, binding, etc... + public static readonly DependencyProperty XAxisInfoProperty = + DependencyProperty.Register("XAxisInfo", typeof(AxisInfo), typeof(SciChartMouseDownChangingLocationBehavior), new PropertyMetadata(null)); + + + + + + public ObservableCollection Target + { + get { return (ObservableCollection)GetValue(TargetProperty); } + set { SetValue(TargetProperty, value); } + } + + public static readonly DependencyProperty TargetProperty = + DependencyProperty.Register("Target", typeof(ObservableCollection), typeof(SciChartMouseDownChangingLocationBehavior), new PropertyMetadata(null)); + + + protected override void OnAttached() + { + AssociatedObject.PreviewMouseDown += mousedown; + } + + private void mousedown(object sender, MouseButtonEventArgs e) + { + if (e.ChangedButton == MouseButton.Left) + { + foreach (IRenderableSeries series in Target) + { + if (series.IsSelected) + { + double xvalue = 0, yvalue = 0; + if (double.TryParse(XAxisInfo.CursorFormattedDataValue, out xvalue) && double.TryParse(YAxisInfo.CursorFormattedDataValue, out yvalue)) + { + ChartDataLineX s = series as ChartDataLineX; + + s.DataXOffset = xvalue; + s.DataOffset = yvalue; + s.IsSelected = false; + } + } + } + } + + e.Handled = true; //不写会失去焦点 + } + } + +} diff --git a/SicUI/Models/PMs/Charting/PMChartingV2ViewModel.cs b/SicUI/Models/PMs/Charting/PMChartingV2ViewModel.cs new file mode 100644 index 00000000..5adf7438 --- /dev/null +++ b/SicUI/Models/PMs/Charting/PMChartingV2ViewModel.cs @@ -0,0 +1,723 @@ +using MECF.Framework.Common.DataCenter; +using MECF.Framework.UI.Client.ClientBase; +using SciChart.Charting.Common.Helpers; +using SciChart.Charting.ViewportManagers; +using SciChart.Charting.Visuals.Annotations; +using SciChart.Charting.Visuals.Axes; +using SciChart.Charting.Visuals.RenderableSeries; +using SciChart.Data.Model; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using System.Windows; +using Cali = Caliburn.Micro; +using MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory; +using System.Reflection; +using SciChart.Charting.Model.ChartSeries; + +namespace SicUI.Models.PMs.Charting +{ + public class PMChartingV2ViewModel : SicModuleUIViewModelBase, ISupportMultipleSystem + { + private class QueryIndexer + { + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public string Module { get; set; } + public string ColumneName { get; set; } + public string ProcessGuid { get; set; } + public List DateList { get; set; } + public long currentTimeTicks { get; set; } + } + + /// + /// ViewModel绑定的View对象 + /// + private PMChartingV2View view; + + /// + /// 初始化界面 + /// + public PMChartingV2ViewModel() + { + DisplayName = "Process History"; + + var now = DateTime.Now; + this.StartDateTime = new DateTime(now.Year, now.Month, now.Day, 0, 0, 0, 0); + this.EndDateTime = new DateTime(now.Year, now.Month, now.Day, 23, 59, 59, 999); + + SourcePM = new ObservableCollection(new[] { "PM1", "PM2" }); + + //sci按钮操作 + DataDetailVisbleCommand = new ActionCommand(SetDataDetailVisble); + DefaultZoomCommand = new ActionCommand(Zoom); + ShowLegendCommand = new ActionCommand(SetLegendAvalible); + + //获取所有Device + GetPMNode(); + + SelectedData = new ObservableCollection(); + + SelectedRecipes = new ObservableCollection(); + Recipes = new ObservableCollection(); + + //x y always指zoom功能失效,总是自动调整大小 + //ChartAutoRange = AutoRange.Always; + + VisibleRangeX = new DoubleRange(-1000, 10000); + VisibleRangeY = new DoubleRange(-10, 500); + VisibleRangeXLimit = new DoubleRange(-1000, 10000); + VisibleRangeYLimit = new DoubleRange(-10, 500); + + _thread = new PeriodicJob(300, MonitorHistoryData, "History", true); + //_threadReal = new PeriodicJob(TrendInterval, MonitorRealTimeData, "RealTime", true); + } + + protected override void OnViewLoaded(object _view) + { + //获取绑定的View(wpf没有默认的日期时间控件,Winform日期控件无法通过绑定属性获取) + base.OnViewLoaded(_view); + this.view = (PMChartingV2View)_view; + this.view.wfTimeFrom.Value = this.StartDateTime; + this.view.wfTimeTo.Value = this.EndDateTime; + + } + + private PeriodicJob _thread; + //private PeriodicJob _threadReal; + //DeviceTimer dt = new DeviceTimer(); + + //设置允许同时显示的最多曲线数 + private const int MAX_PARAMETERS = 20; + + /// + /// sci图表的视图管理类 + /// + private readonly IViewportManager _viewportManager = new DefaultViewportManager(); + public IViewportManager ViewportManager + { + get { return _viewportManager; } + } + + #region Properties + + /// + /// 搜索条件:Recipe开始时间 + /// + public DateTime StartDateTime { get; set; } + + /// + /// 搜索条件:Recipe结束时间 + /// + public DateTime EndDateTime { get; set; } + + /// + /// 搜索条件:PM腔 + /// + public string SelectedValuePM { get; set; } + + /// + /// 搜索条件:PM腔 + /// + public ObservableCollection SourcePM { get; set; } + /// + /// 搜索条件:Recipe + /// + public string RecipeName { get; set; } + + /// + /// 查询曲线用点位组,每次有曲线变动时入队,生成曲线后出队 + /// + ConcurrentBag _lstTokenTimeData = new ConcurrentBag(); + + public ObservableCollection QueryDataDetail { get; set; } + + /// + /// 用户选中的曲线组,前台treeview和chart调用 + /// + public ObservableCollection SelectedData { get; set; } + + /// + /// 根据条件搜索的recipe + /// + public ObservableCollection Recipes { get; set; } + + /// + /// 用户选中查阅的recipe + /// + public ObservableCollection SelectedRecipes { get; set; } + + + private List Nodes = new List(); + /// + /// 获取设备需要监控的Device点 + /// + private ObservableCollection _configNodes = new ObservableCollection(); + public ObservableCollection ConfigNodes + { + get { return _configNodes; } + set { _configNodes = value; NotifyOfPropertyChange("ConfigNodes"); } + } + + private double _maxYValue = 0, _minYValue = 0; + + private IRange _visibleRangeXLimit; + public IRange VisibleRangeXLimit + { + get { return _visibleRangeXLimit;} + set { _visibleRangeXLimit = value; NotifyOfPropertyChange(nameof(VisibleRangeXLimit)); } + } + + private IRange _visibleRangeYLimit; + public IRange VisibleRangeYLimit + { + get { return _visibleRangeYLimit; } + set { _visibleRangeYLimit = value; NotifyOfPropertyChange(nameof(VisibleRangeYLimit)); } + } + + private IRange _visibleRangeX; + public IRange VisibleRangeX + { + get { return _visibleRangeX; } + set { _visibleRangeX = value; NotifyOfPropertyChange(nameof(VisibleRangeX)); } + } + private IRange _visibleRangeY; + public IRange VisibleRangeY + { + get { return _visibleRangeY; } + set { _visibleRangeY = value; NotifyOfPropertyChange(nameof(VisibleRangeY)); } + } + + private AutoRange _chartAutoRange = AutoRange.Never; + public AutoRange ChartAutoRange + { + get { return _chartAutoRange; } + set + { + _chartAutoRange = value; + NotifyOfPropertyChange(nameof(ChartAutoRange)); + } + } + + private Visibility _dataDetailVisbility = Visibility.Collapsed; + public Visibility DataDetailVisbility + { + get { return _dataDetailVisbility; } + set + { + _dataDetailVisbility = value; + NotifyOfPropertyChange(nameof(DataDetailVisbility)); + } + } + + private bool _showLegendInfo; + public bool ShowLegendInfo + { + get { return _showLegendInfo; } + set + { + _showLegendInfo = value; + NotifyOfPropertyChange(nameof(ShowLegendInfo)); + } + } + + private Queue colorQueue = new Queue(new Color[]{Color.Red,Color.Orange,Color.Green,Color.Blue,Color.Purple,Color.Aqua,Color.Bisque,Color.Brown,Color.BurlyWood,Color.CadetBlue, + Color.CornflowerBlue,Color.DarkBlue,Color.DarkCyan,Color.DarkGray,Color.DarkGreen,Color.DarkKhaki,Color.DarkMagenta,Color.DarkOliveGreen, Color.DarkOrange, + Color.DarkSeaGreen,Color.DarkSlateBlue,Color.DarkSlateGray,Color.DarkViolet,Color.DeepPink,Color.DeepSkyBlue,Color.DimGray, Color.DodgerBlue,Color.ForestGreen, Color.Gold, + Color.Gray,Color.GreenYellow,Color.HotPink,Color.Indigo,Color.Khaki, + Color.LimeGreen,Color.MediumOrchid,Color.MediumPurple,Color.MediumSeaGreen,Color.MediumSlateBlue,Color.MediumSpringGreen, + Color.MediumTurquoise,Color.Moccasin,Color.NavajoWhite,Color.Olive,Color.OliveDrab,Color.OrangeRed,Color.Orchid,Color.PaleGoldenrod,Color.PaleGreen, + Color.PeachPuff,Color.Peru,Color.Plum,Color.PowderBlue,Color.RosyBrown,Color.RoyalBlue,Color.SaddleBrown,Color.Salmon,Color.SeaGreen, Color.Sienna, + Color.SkyBlue,Color.SlateBlue,Color.SlateGray,Color.SpringGreen,Color.Teal,Color.Aquamarine,Color.Tomato,Color.Turquoise,Color.Violet,Color.Wheat, Color.YellowGreen}); + + #endregion Properties + + + #region 界面按钮 + + + /// + /// 重新搜索Recipe + /// + public void SearchRecipe() + { + this.StartDateTime = this.view.wfTimeFrom.Value; + this.EndDateTime = this.view.wfTimeTo.Value; + + if (StartDateTime > EndDateTime) + { + MessageBox.Show("Time range invalid, start time should be early than end time"); + return; + } + + Recipes.Clear(); + + try + { + string sql = $"SELECT * FROM \"process_data\" where \"process_data\".\"process_begin_time\" >='{StartDateTime:yyyyMMdd HHmmss}' and \"process_data\".\"process_end_time\" <='{EndDateTime:yyyyMMdd HHmmss}'"; + if (!string.IsNullOrEmpty(SelectedValuePM)) + { + string[] pms = SelectedValuePM.Split(','); + if (pms.Length > 0) + { + sql += " and (FALSE "; + foreach (var pm in pms) + { + sql += $" OR \"process_data\".\"process_in\"='{pm}' "; + } + sql += " ) "; + } + } + + if (!string.IsNullOrEmpty(RecipeName)) + { + sql += string.Format(" and lower( \"process_data\".\"recipe_name\") like '%{0}%'", RecipeName.ToLower()); + } + + sql += " order by \"process_data\".\"process_begin_time\" ASC;"; + + DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql); + + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + if (dbData == null || dbData.Rows.Count == 0) + return; + + double maxXValue = 0; + + for (int i = 0; i < dbData.Rows.Count; i++) + { + RecipeItemSic item = new RecipeItemSic(); + + item.Recipe = dbData.Rows[i]["recipe_name"].ToString(); + item.Chamber = dbData.Rows[i]["process_in"].ToString(); + item.Status = dbData.Rows[i]["process_status"].ToString(); + //item.ProcessGuid = dbData.Rows[i]["guid"].ToString(); + item.ProcessGuid = "Recipe"+i.ToString().PadLeft(3,'0'); + + if (!dbData.Rows[i]["process_begin_time"].Equals(DBNull.Value)) + item.StartTime = ((DateTime)dbData.Rows[i]["process_begin_time"]).ToString("yyyy/MM/dd HH:mm:ss.fff"); + if (!dbData.Rows[i]["process_end_time"].Equals(DBNull.Value)) + item.EndTime = ((DateTime)dbData.Rows[i]["process_end_time"]).ToString("yyyy/MM/dd HH:mm:ss.fff"); + + long curTickCount = (DateTime.Parse(item.EndTime).Ticks - DateTime.Parse(item.StartTime).Ticks) / 10000000; + if (maxXValue < curTickCount) + { + maxXValue = curTickCount; + } + //正确设置范围,否则曲线不显示 + VisibleRangeX = new DoubleRange(-0.2*maxXValue, maxXValue * 1.2); + VisibleRangeXLimit = new DoubleRange(-0.2 * maxXValue, maxXValue * 1.2);//X轴拉伸1.2倍 + + Recipes.Add(item); + } + })); + } + catch (Exception e) + { + LOG.Write(e); + } + } + + /// + /// 选择Recipe + /// + public void CheckRecipe(RecipeItemSic recipe) + { + if (recipe.Selected) //选中配方 + { + SelectedRecipes.Add(recipe); + //刷新曲线 + //GetXRange(); + foreach (PMNodeInfo node in ConfigNodes) + { + if (node.Selected) + { + ParameterCheck(node); + } + } + } + else //取消配方 + { + RecipeItemSic item = SelectedRecipes.FirstOrDefault(t => t.Recipe == recipe.Recipe); + if (item != null) + SelectedRecipes.Remove(item); + RemoveRecipeRelated(recipe); //移除配方相关曲线 + } + + + } + + /// + /// 移除配方相关曲线 + /// + /// + private void RemoveRecipeRelated(RecipeItemSic recipe) + { + lock (_lockSelection) //递减法移除列表内项,不会删错 + { + for (int i = SelectedData.Count - 1; i >= 0; i--) + { + if ((SelectedData[i] as ChartDataLineX).ProcessGuid.Contains(recipe.ProcessGuid)) + { + SelectedData.RemoveAt(i); + } + } + } + } + + /// + /// 清除所有选择的节点 + /// + public void RemoveAllLine() + { + this.SelectedData.Clear(); + foreach (PMNodeInfo node in ConfigNodes) + { + node.Selected = false; + } + } + + #endregion 界面按钮 + + private void SelectedDataChanged() + { + foreach (var item in SelectedData) + { + if (item.Stroke.Equals(System.Windows.Media.Color.FromArgb(255, 0, 0, 255))) + { + Color drawingColor = colorQueue.Peek(); + item.Stroke = System.Windows.Media.Color.FromRgb(drawingColor.R, drawingColor.G, drawingColor.B); + colorQueue.Enqueue(colorQueue.Dequeue()); + } + } + } + + /// + /// 加载PM的Device名称 + /// + private void GetPMNode() + { + Nodes.Clear(); + ConfigNodes.Clear(); + List dataList = (List)QueryDataClient.Instance.Service.GetConfig("System.NumericDataList"); + dataList.Sort(); + List lstNode = new List(); + foreach (string dataName in dataList) + { + string[] nodeName = dataName.Split('.'); + if (nodeName.Length > 1 && nodeName[0].IndexOf("PM") == 0) + { + string nodeStr = dataName.Substring(dataName.IndexOf('.') + 1); + if (!lstNode.Contains(nodeStr)) //不显示重复项 + { + lstNode.Add(nodeStr); + Nodes.Add(new PMNodeInfo() { NodeStr = nodeStr }); + ConfigNodes.Add(new PMNodeInfo() { NodeStr = nodeStr }); + } + } + } + } + + public void Find(string keyword) + { + ConfigNodes.Clear(); + //遍历所有node,隐藏不符合条件项 + foreach (var node in Nodes) + { + node.ApplyCriteria(keyword); + if (node.IsMatch) + { + ConfigNodes.Add(node); + } + } + } + private void SetDataDetailVisble() + { + if (DataDetailVisbility == Visibility.Collapsed) + { + DataDetailVisbility = Visibility.Visible; + } + else + { + DataDetailVisbility = Visibility.Collapsed; + } + } + + #region 获取HistoryData + + private object _lockSelection = new object(); + + protected bool MonitorHistoryData() + { + try + { + if (_lstTokenTimeData.Count > 0) + { + lock (_lockSelection) + { + foreach (var item in _lstTokenTimeData) + { + DateTime timeFrom = item.StartTime; + DateTime timeTo = item.EndTime; + + GetHistoryData(item.DateList, timeFrom, timeTo, item.Module, item.ColumneName, item.ProcessGuid); + _lstTokenTimeData.TryTake(out _); + } + } + } + + } + catch (Exception ex) + { + LOG.Error(ex.Message); + } + return true; + } + + private void GetHistoryData(List lstDayStr, DateTime from, DateTime to, string module, string colName, string processGuid) + { + Dictionary> historyData = new Dictionary>(); + List lstDataDetail = new List(); + + //db获取对应字段数据 + foreach (string cDate in lstDayStr) + { + string sql = String.Format("select time AS InternalTimeStamp,\"{0}\"", colName); + sql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc", + cDate + "." + module, from.Ticks, to.Ticks); + + DataTable dataTable = QueryDataClient.Instance.Service.QueryData(sql); + if (dataTable == null || dataTable.Rows.Count == 0 || dataTable.Columns.Count < 2) + { + return; + } + + for (int i = 0; i < dataTable.Rows.Count; i++) + { + DataDetail data = new DataDetail(); + long ticks = (long)dataTable.Rows[i][0] - from.Ticks; + data.xValue = ticks / 10000000; + if (dataTable.Rows[i][1] is DBNull || dataTable.Rows[i][1] is null) + { + data.yValue = 0; + } + else if (dataTable.Rows[i][1] is bool) + { + data.yValue = (bool)dataTable.Rows[i][1] ? 1 : 0; + } + else + { + data.yValue = float.Parse(dataTable.Rows[i][1].ToString()); + } + if (data.yValue > _maxYValue) + { + _maxYValue = data.yValue; + } + if (data.yValue < _minYValue) + { + _minYValue = data.yValue; + } + lstDataDetail.Add(data); + } + } + //正确设置范围,否则曲线不显示 + VisibleRangeY = new DoubleRange(_minYValue - _maxYValue * 0.5, _maxYValue * 2.1); + VisibleRangeYLimit = new DoubleRange(_minYValue - _maxYValue * 0.5, _maxYValue * 2.1);//Y轴拉伸1.2倍 + + //所有数据内存 + historyData.Add(processGuid, lstDataDetail); + + //数据绑定到曲线中 + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + try + { + foreach (var item in SelectedData) + { + var seriesItem = item as ChartDataLineX; + + if (seriesItem == null) + continue; + foreach (var data in historyData) + { + if (data.Key != seriesItem.ProcessGuid) + continue; + + seriesItem.Capacity += data.Value.Count; + + foreach (var detailDataItem in data.Value) + { + seriesItem.Append(detailDataItem.xValue, detailDataItem.yValue); + } + } + } + } + catch (Exception ex) + { + LOG.Write(ex); + } + })); + } + #endregion + + + /// + /// 更新Data变化 + /// + /// + /// + public bool ParameterCheck(PMNodeInfo node) + { + if (SelectedRecipes.Count == 0) + { + return false; + } + + if (node.Selected) + { + foreach (RecipeItemSic itemSic in SelectedRecipes) + { + string nodeStr = itemSic.Chamber + "." + node.NodeStr; //字段名称 + string nodeStr_1 = itemSic.LotID; //显示名称 + string nodeWithGuid = node.NodeStr + "_" + itemSic.ProcessGuid; //字段名+ Guid (唯一ID) + DateTime dtStartTime = DateTime.Parse(itemSic.StartTime); + DateTime dtEndTime = DateTime.Parse(itemSic.EndTime); + + lock (_lockSelection) + { + bool isExist = SelectedData.FirstOrDefault(x => (x as ChartDataLineX).ProcessGuid == nodeWithGuid) != null; + if (!isExist) + { + if (SelectedData.Count < MAX_PARAMETERS) + { + var line = new ChartDataLineX(nodeWithGuid); + if (itemSic.Chamber.StartsWith("PM1")) + line.Module = "PM1"; + else if (itemSic.Chamber.StartsWith("PM2")) + line.Module = "PM2"; + else + line.Module = "System"; + line.ProcessGuid = nodeWithGuid; + line.RecName = nodeStr_1; + line.Tag = node; + SelectedData.Add(line); + SelectedDataChanged(); + QueryIndexer indexer = _lstTokenTimeData.FirstOrDefault(x => x.ProcessGuid == line.ProcessGuid); + + if (indexer == null) + { + indexer = new QueryIndexer() + { + Module = line.Module, + StartTime = dtStartTime, + EndTime = dtEndTime, + ProcessGuid = line.ProcessGuid, + ColumneName = nodeStr, + DateList = GetDateList(dtStartTime, dtEndTime) + }; + + _lstTokenTimeData.Add(indexer); + } + } + else + { + return false; + } + } + } + } + } + else + { + lock (_lockSelection) + { + for (int i = SelectedData.Count - 1; i >= 0; i--) + { + if ((SelectedData[i] as ChartDataLineX).DataName.Contains(node.NodeStr)) + { + SelectedData.RemoveAt(i); + } + } + } + } + return true; + } + + public void SelectColor(ChartDataLineX cp) + { + if (cp == null) + return; + + var dlg = new System.Windows.Forms.ColorDialog(); + if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) + { + cp.Stroke = new System.Windows.Media.Color() { A = dlg.Color.A, B = dlg.Color.B, G = dlg.Color.G, R = dlg.Color.R }; + } + } + + /// + /// 获取开始时间和结束时间之间的所有日期 + /// + /// + /// + /// + private List GetDateList(DateTime timeStart, DateTime timeEnd) + { + List lstTime = new List(); + string dtEndStr = timeEnd.ToString("yyyyMMdd"); + int timeSpan = (int)(timeEnd - timeStart).TotalDays + 1; + for (int i = 0; i <= timeSpan; i++) + { + string dt = timeStart.AddDays(i).ToString("yyyyMMdd"); + lstTime.Add(dt); + if (dt == dtEndStr) + { + break; + } + } + + return lstTime; + } + + /// + /// 获取所有的列名 + /// + private List GetColumnList(string modleName) + { + List _seletedItemName = new List(); + foreach (PMNodeInfo node in ConfigNodes) + { + if (node.Selected) + { + _seletedItemName.Add("\"" + modleName + "." + node.NodeStr + "\""); + } + } + return _seletedItemName; + } + + public ActionCommand DefaultZoomCommand { get; private set; } + public ActionCommand ShowLegendCommand { get; private set; } + public ActionCommand DataDetailVisbleCommand { get; private set; } + public ActionCommand ShowAlarmCommand { get; private set; } + + + private void SetLegendAvalible() + { + ShowLegendInfo = !ShowLegendInfo; + } + + private void Zoom() + { + ViewportManager.AnimateZoomExtents(TimeSpan.FromMilliseconds(500)); + } + + } +} diff --git a/SicUI/SicUI.csproj b/SicUI/SicUI.csproj index 2a184398..b4bb09d2 100644 --- a/SicUI/SicUI.csproj +++ b/SicUI/SicUI.csproj @@ -283,6 +283,10 @@ if exist "$(ProjectDir)..\SicSetup\Packages\SicUI\PresetGroups" rd "$(ProjectDir + + PMChartingV2View.xaml + + ContinueSelectDialogView.xaml @@ -509,6 +513,10 @@ if exist "$(ProjectDir)..\SicSetup\Packages\SicUI\PresetGroups" rd "$(ProjectDir Designer MSBuild:Compile + + MSBuild:Compile + Designer + MSBuild:Compile Designer