using Aitex.Core.UI.ControlDataContext; using ExcelLibrary.BinaryFileFormat; using MECF.Framework.Common.DataCenter; using Newtonsoft.Json; using Prism.Commands; using Prism.Mvvm; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Data; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; using System.Windows.Threading; using Venus_MainPages.Unity; using Venus_MainPages.Views; using WPF.Themes.UserControls; namespace Venus_MainPages.ViewModels { public class DataHistoryViewModel : BindableBase { #region 私有字段 private DataHistoryView DataHistoryView; private ObservableCollection _ParameterNodes; RealtimeProvider _provider = new RealtimeProvider(); //private object _lockSelection = new object(); //ConcurrentBag _lstTokenTimeData = new ConcurrentBag(); ObservableCollection m_Keys = new ObservableCollection(); ObservableCollection m_KeyDataObservableCollection = new ObservableCollection(); DispatcherTimer timer = new DispatcherTimer(); public List solidColorBrushes = new List(); DateTime currentTime; private bool firstFlag = true; private DateTime startTime = DateTime.Now; private bool m_IsShowStep; private bool m_IsPMAChecked = true; private bool m_IsPMBChecked = true; private bool m_IsPMCChecked = true; private bool m_IsPMDChecked = true; private bool m_PMAIsInstalled; private bool m_PMBIsInstalled; private bool m_PMCIsInstalled; private bool m_PMDIsInstalled; private bool m_IsEnter; #endregion #region 属性 public ObservableCollection OldKeyDataCollection { get; set; } public ObservableCollection ParameterNodes { get { return _ParameterNodes; } set { SetProperty(ref _ParameterNodes, value); } } public ObservableCollection Keys { get { return m_Keys; } set { SetProperty(ref m_Keys, value); } } public ObservableCollection KeyDataObservableCollection { get { return m_KeyDataObservableCollection; } set { SetProperty(ref m_KeyDataObservableCollection, value); } } public bool IsShowStep { get { return m_IsShowStep; } set { SetProperty(ref m_IsShowStep, value); } } public bool IsPMAChecked { get { return m_IsPMAChecked; } set { SetProperty(ref m_IsPMAChecked, value); } } public bool IsPMBChecked { get { return m_IsPMBChecked; } set { SetProperty(ref m_IsPMBChecked, value); } } public bool IsPMCChecked { get { return m_IsPMCChecked; } set { SetProperty(ref m_IsPMCChecked, value); } } public bool IsPMDChecked { get { return m_IsPMDChecked; } set { SetProperty(ref m_IsPMDChecked, value); } } public bool PMAIsInstalled { get { return m_PMAIsInstalled; } set { SetProperty(ref m_PMAIsInstalled, value); } } public bool PMBIsInstalled { get { return m_PMBIsInstalled; } set { SetProperty(ref m_PMBIsInstalled, value); } } public bool PMCIsInstalled { get { return m_PMCIsInstalled; } set { SetProperty(ref m_PMCIsInstalled, value); } } public bool PMDIsInstalled { get { return m_PMDIsInstalled; } set { SetProperty(ref m_PMDIsInstalled, value); } } #endregion #region 命令 private DelegateCommand _LoadCommand; public DelegateCommand LoadCommand => _LoadCommand ?? (_LoadCommand = new DelegateCommand(OnLoad)); private DelegateCommand _UnLoadCommand; public DelegateCommand UnLoadCommand => _UnLoadCommand ?? (_UnLoadCommand = new DelegateCommand(OnUnLoad)); private DelegateCommand _ParameterCheckCommand; public DelegateCommand ParameterCheckCommand => _ParameterCheckCommand ?? (_ParameterCheckCommand = new DelegateCommand(OnParameterCheck)); private DelegateCommand _StartCommand; public DelegateCommand StartCommand => _StartCommand ?? (_StartCommand = new DelegateCommand(OnStart)); private DelegateCommand _ClearCommand; public DelegateCommand ClearCommand => _ClearCommand ?? (_ClearCommand = new DelegateCommand(OnClear)); private DelegateCommand _StartRealTimeCommand; public DelegateCommand StartRealTimeCommand => _StartRealTimeCommand ?? (_StartRealTimeCommand = new DelegateCommand(OnStartRealTime)); private DelegateCommand _StopRealTimeCommand; public DelegateCommand StopRealTimeCommand => _StopRealTimeCommand ?? (_StopRealTimeCommand = new DelegateCommand(OnStopRealTime)); private DelegateCommand _ExportCommand; public DelegateCommand ExportCommand => _ExportCommand ?? (_ExportCommand = new DelegateCommand(OnExport)); #endregion #region 构造函数 public DataHistoryViewModel() { OldKeyDataCollection = new ObservableCollection(); ParameterNodes = _provider.GetParameters(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += Timer_Tick; solidColorBrushes.Add(new SolidColorBrush(Colors.Green)); solidColorBrushes.Add(new SolidColorBrush(Colors.Red)); solidColorBrushes.Add(new SolidColorBrush(Colors.Blue)); solidColorBrushes.Add(new SolidColorBrush(Colors.Orange)); solidColorBrushes.Add(new SolidColorBrush(Colors.Yellow)); solidColorBrushes.Add(new SolidColorBrush(Colors.YellowGreen)); solidColorBrushes.Add(new SolidColorBrush(Colors.AliceBlue)); solidColorBrushes.Add(new SolidColorBrush(Colors.Chocolate)); solidColorBrushes.Add(new SolidColorBrush(Colors.Cyan)); solidColorBrushes.Add(new SolidColorBrush(Colors.DarkGreen)); string allModules = QueryDataClient.Instance.Service.GetConfig($"System.InstalledModules").ToString(); PMAIsInstalled = allModules.Contains("PMA"); PMBIsInstalled = allModules.Contains("PMB"); PMCIsInstalled = allModules.Contains("PMC"); PMDIsInstalled = allModules.Contains("PMD"); } #endregion #region 命令方法 private void OnLoad(Object eventView) { if (firstFlag) { this.DataHistoryView = (DataHistoryView)eventView; this.DataHistoryView.wfTimeFrom.Value = DateTime.Today; this.DataHistoryView.wfTimeTo.Value = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 23, 59, 59, 999); //this.DataHistoryView.MyDrawGraphicsControl.PointCollections=new PointCollection(new Point[] {}) firstFlag = false; } } private void OnUnLoad() { GC.Collect(); // This should pick up the control removed at a previous MouseDown GC.WaitForPendingFinalizers(); // Doesn't help either GC.Collect(); GC.WaitForPendingFinalizers(); // Doesn't help either } private void OnParameterCheck(object obj) { startTime = DateTime.Now; ParameterNode node = obj as ParameterNode; if (!RefreshTreeStatusToChild(node)) { node.Selected = !node.Selected; } else { RefreshTreeStatusToParent(node); } Keys.Clear(); for (int i = 0; i < ParameterNodes.Count; i++) { CalKeys(ParameterNodes[i]); } OldKeyDataCollection.Clear(); OldKeyDataCollection = DeepCopyJson(KeyDataObservableCollection); KeyDataObservableCollection.Clear(); for (int i = 0; i < Keys.Count; i++) { if (i == 10) { break; } KeyDataObservableCollection.Add(new KeyData() { Key = Keys[i], Color = solidColorBrushes[i], UniqueId = i }); } //Compare(OldKeyDataCollection, KeyDataObservableCollection); //KeyDataObservableCollection = DeepCopyJson(OldKeyDataCollection); } public void Compare(ObservableCollection olddata, ObservableCollection newdata) { if (newdata != null) { for (int i = 0; i < newdata.Count; i++) { var lists = olddata.ToList().Find(t => t.Key == newdata[i].Key); if (lists == null) { olddata.Add(new KeyData() { Key = newdata[i].Key, Color = solidColorBrushes[i], UniqueId = olddata.Count + 1 }); } } for (int i = 0; i < olddata.Count; i++) { var lists = newdata.ToList().Find(t => t.Key == olddata[i].Key); if (lists == null) { olddata.Remove(olddata[i]); } } } } public static T DeepCopyJson(T obj) { // 序列化 string json = JsonConvert.SerializeObject(obj); // 反序列化 return JsonConvert.DeserializeObject(json); } private void OnStartRealTime(object obj) { if (Keys.Count > 10) { ((System.Windows.Controls.CheckBox)obj).IsChecked = false; timer.Stop(); WPFMessageBox.ShowWarning("最多显示10个数据"); return; } currentTime = DateTime.Now; timer.Start(); } private void OnStopRealTime() { timer.Stop(); } public async void OnStart() { if (Keys.Count > 10) { WPFMessageBox.ShowWarning("最多显示10个数据"); return; } TimeSpan sp = this.DataHistoryView.wfTimeTo.Value.Subtract(this.DataHistoryView.wfTimeFrom.Value); if (sp.TotalHours > 24) { WPFMessageBox.ShowWarning("数据差不能超过24小时"); return; } this.DataHistoryView.MyDrawGraphicsControl.ClearPlotPoints(); //Dispatcher dispatcher = Dispatcher.CurrentDispatcher; await Task.Run(() => { var result = GetData(Keys.Distinct().ToList(), this.DataHistoryView.wfTimeFrom.Value, this.DataHistoryView.wfTimeTo.Value); DataHistoryView.Dispatcher.Invoke(new Action(() => { if (result == null) { return; } List cls = new List(); for (int i = 0; i < Keys.Count; i++) { PointCollection points = new PointCollection(); int k = 1; result[Keys[i]].ForEach(point => { points.Add(new Point() { X = point.dateTime.ToOADate(), Y = point.value }); k += 1; }); cls.Add(points); } this.DataHistoryView.MyDrawGraphicsControl.PointCollections = cls; this.DataHistoryView.MyDrawGraphicsControl.FitControl(); this.DataHistoryView.MyDrawGraphicsControl.YPoints.Clear(); if (IsShowStep) { var item = QueryDataClient.Instance.Service.GetHistorySteps(this.DataHistoryView.wfTimeFrom.Value, this.DataHistoryView.wfTimeTo.Value); if (item != null) { var pmList = new List(); if (IsPMAChecked) { pmList.Add("PMA"); } if (IsPMBChecked) { pmList.Add("PMB"); } if (IsPMCChecked) { pmList.Add("PMC"); } if (IsPMDChecked) { pmList.Add("PMD"); } item.ForEach(x => { if (pmList.Contains(x.RecipeId)) { this.DataHistoryView.MyDrawGraphicsControl.YPoints.Add(new Venus_Core.StepItem() { StartValue = x.StartTime.ToOADate(), Information = $"{x.RecipeId}\n{x.StepNo}\n{x.StartTime.ToString("HH:mm:ss:fff")}" }); } }); } } })); }); } private void CloseAll(ObservableCollection parameterNodes) { foreach (var item in parameterNodes) { item.Selected = false; if (item.ChildNodes.Count > 0) { CloseAll(item.ChildNodes); } } } private void OnClear() { this.DataHistoryView.MyDrawGraphicsControl.ClearPlotPoints(); this.DataHistoryView.MyDrawGraphicsControl.YPoints = new List(); KeyDataObservableCollection.Clear(); CloseAll(ParameterNodes); Keys.Clear(); this.DataHistoryView.MyDrawGraphicsControl.InitPens(); } private void OnExport() { Task.Run(() => { try { Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog(); dlg.DefaultExt = ".xls"; // Default file extension dlg.Filter = "数据表格文件|*.xls"; // Filter files by extension Nullable result = dlg.ShowDialog();// Show open file dialog box if (result != true) // Process open file dialog box results return; System.Data.DataSet ds = new System.Data.DataSet(); ds.Tables.Add(new System.Data.DataTable("Data")); //var item = ProcessData; var result2 = GetData(Keys.Distinct().ToList(), this.DataHistoryView.wfTimeFrom.Value, this.DataHistoryView.wfTimeTo.Value); int columnIndex = 0; int rowIndex = 0; ds.Tables[0].Columns.Add($"Time"); foreach (var item in result2) { rowIndex = 0; if (item.Value.Count == 0) { continue; } ds.Tables[0].Columns.Add(item.Key); item.Value.ForEach(x => { if (columnIndex == 0) { var row = ds.Tables[0].NewRow(); row[0] = x.dateTime; row[columnIndex+1] = x.value; ds.Tables[0].Rows.Add(row); } else { ds.Tables[0].Rows[rowIndex][columnIndex+1]= x.value; } rowIndex += 1; }); columnIndex += 1; } ds.WriteXml(dlg.FileName); } catch (Exception ex) { WPFMessageBox.ShowError($"导出系统日志发生错误{ex.Message}"); } }); } #endregion #region 私有方法 private bool RefreshTreeStatusToChild(ParameterNode node) { if (node.ChildNodes.Count > 0) { for (int i = 0; i < node.ChildNodes.Count; i++) { ParameterNode n = node.ChildNodes[i]; n.Selected = node.Selected; if (!RefreshTreeStatusToChild(n)) { //uncheck left node for (int j = i; j < node.ChildNodes.Count; j++) { node.ChildNodes[j].Selected = !node.Selected; } //node.Selected = !node.Selected; return false; } } } //else //{ // if (node.Selected == true) // { // keys.Add(node.Name); // } // else // { // keys.Remove(node.Name); // } //} return true; } private void RefreshTreeStatusToParent(ParameterNode node) { if (node.ParentNode != null) { if (node.Selected) { bool flag = true; for (int i = 0; i < node.ParentNode.ChildNodes.Count; i++) { if (!node.ParentNode.ChildNodes[i].Selected) { flag = false; //as least one child is unselected break; } } if (flag) node.ParentNode.Selected = true; } else { node.ParentNode.Selected = false; } RefreshTreeStatusToParent(node.ParentNode); } } private Dictionary> GetData(List keys, DateTime from, DateTime to) { string sql = ""; if (from.ToString("yyyyMMdd") == to.ToString("yyyyMMdd")) { sql += "select time AS InternalTimeStamp"; foreach (var dataId in keys) { sql += "," + string.Format("\"{0}\"", dataId); } sql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc", from.ToString("yyyyMMdd") + "." + "Data", from.Ticks, to.Ticks); } else { sql += "select time AS InternalTimeStamp"; foreach (var dataId in keys) { sql += "," + string.Format("\"{0}\"", dataId); } sql += string.Format(" from \"{0}\" where time > {1}", from.ToString("yyyyMMdd") + "." + "Data", from.Ticks); sql += " UNION "; sql += "select time AS InternalTimeStamp"; foreach (var dataId in keys) { sql += "," + string.Format("\"{0}\"", dataId); } sql += string.Format(" from \"{0}\" where time < {1}", to.ToString("yyyyMMdd") + "." + "Data", to.Ticks); } DataTable dataTable = QueryDataClient.Instance.Service.QueryData(sql); Dictionary> historyData = new Dictionary>(); if (dataTable == null || dataTable.Rows.Count == 0) return null; DateTime dt = new DateTime(); Dictionary colName = new Dictionary(); for (int colNo = 0; colNo < dataTable.Columns.Count; colNo++) { colName.Add(colNo, dataTable.Columns[colNo].ColumnName); historyData[dataTable.Columns[colNo].ColumnName] = new List(); } for (int rowNo = 0; rowNo < dataTable.Rows.Count; rowNo++) { PointCollection points = new PointCollection(); var row = dataTable.Rows[rowNo]; for (int i = 0; i < dataTable.Columns.Count; i++) { HistoryDataItem data = new HistoryDataItem(); if (i == 0) { long ticks = (long)row[i]; dt = new DateTime(ticks); continue; } else { string dataId = colName[i]; if (row[i] is DBNull || row[i] == null) { data.dateTime = dt; data.dbName = colName[i]; data.value = 0; } else if (row[i] is bool) { data.dateTime = dt; data.dbName = colName[i]; data.value = (bool)row[i] ? 1 : 0; } else { data.dateTime = dt; data.dbName = colName[i]; data.value = float.Parse(row[i].ToString()); } } historyData[data.dbName].Add(data); } } foreach (var item in historyData) { item.Value.Sort((x, y) => DateTime.Compare(x.dateTime, y.dateTime)); } return historyData; } private void CalKeys(ParameterNode parameterNode) { if (parameterNode.ChildNodes.Count > 0) { foreach (var item in parameterNode.ChildNodes) { CalKeys(item); } } else { if (parameterNode.Selected == true) { Keys.Add(parameterNode.Name); } } } private void Timer_Tick(object sender, EventArgs e) { if (!m_IsEnter) { return; } if (Keys.Count > 10) { WPFMessageBox.ShowWarning("最多显示10个数据"); timer.Stop(); return; } this.DataHistoryView.MyDrawGraphicsControl.ClearPlotPoints(); var result = GetData(Keys.Distinct().ToList(), currentTime.AddMinutes(-1), DateTime.Now); if (result == null) { return; } List cls = new List(); for (int i = 0; i < Keys.Count; i++) { PointCollection points = new PointCollection(); int k = 1; result[Keys[i]].ForEach(point => { points.Add(new Point() { X = point.dateTime.ToOADate(), Y = point.value }); k += 1; }); cls.Add(points); } this.DataHistoryView.MyDrawGraphicsControl.PointCollections = cls; //if (this.DataHistoryView.MyDrawGraphicsControl.IsHorizontalNavigationEnabled == false && this.DataHistoryView.MyDrawGraphicsControl.IsVerticalNavigationEnabled == false) //{ // this.DataHistoryView.MyDrawGraphicsControl.FitControlWithoutDrawing(); //} //DateTime dateTimeNow = DateTime.Now; this.DataHistoryView.MyDrawGraphicsControl.YPoints.Clear(); if (IsShowStep) { var item = QueryDataClient.Instance.Service.GetHistorySteps(startTime, DateTime.Now); if (item.Count > 0) { var pmList = new List(); if (IsPMAChecked) { pmList.Add("PMA"); } if (IsPMBChecked) { pmList.Add("PMB"); } if (IsPMCChecked) { pmList.Add("PMC"); } if (IsPMDChecked) { pmList.Add("PMD"); } item.ForEach(x => { if (pmList.Contains(x.RecipeId)) { this.DataHistoryView.MyDrawGraphicsControl.YPoints.Add(new Venus_Core.StepItem() { StartValue = x.StartTime.ToOADate(), Information = $"{x.RecipeId}\n{x.StepNo}\n{x.StartTime.ToString("HH:mm:ss:fff")}" }); } }); } } else { this.DataHistoryView.MyDrawGraphicsControl.YPoints.Clear(); } } public void ColorChanged() { for (int i = 0; i < KeyDataObservableCollection.Count(); i++) { var _color = KeyDataObservableCollection[i].Color.Color; this.DataHistoryView.MyDrawGraphicsControl.m_PenCollencteions[i] = new System.Drawing.Pen(System.Drawing.Color.FromArgb(_color.A, _color.R, _color.G, _color.B), 2); } } public void EnterExitView(bool isEnter) { if (isEnter) { m_IsEnter = true; } else { m_IsEnter = false; } } #endregion } public class QueryIndexer { public DateTime TimeToken { get; set; } public List DataList { get; set; } public string Module { get; set; } } public class KeyData : BindableBase { public string Key { get; set; } public SolidColorBrush _Color; public SolidColorBrush Color { get { return _Color; } set { SetProperty(ref _Color, value); } } public int UniqueId { get; set; } } }