using MECF.Framework.Common.DataCenter; using System; using System.Collections.Generic; using System.Data; using System.Windows.Media; using System.Linq; using System.Text; using System.Threading.Tasks; using CyberX8_Core; using Prism.Commands; using Prism.Mvvm; using CyberX8_MainPages.Unity; using CyberX8_MainPages.Views; using System.Collections.ObjectModel; using System.Windows.Threading; using System.Windows; using Aitex.Core.RT.Log; using Aitex.Core.UI.ControlDataContext; using WPF.Themes.UserControls; using System.IO; using System.Diagnostics; using Aitex.Core.RT.Routine; using System.Xml.Linq; using System.Windows.Forms; using ExcelLibrary.BinaryFileFormat; using Aitex.Core.UI.View.Common; using Aitex.Core.RT.DataCenter; using System.Xml; using System.Security.Cryptography.X509Certificates; using System.Reflection; using Newtonsoft.Json; using CyberX8_Themes.UserControls; using Aitex.Core.UI.Control; using System.Windows.Annotations; using System.Runtime.Serialization; namespace CyberX8_MainPages.ViewModels { public class ProcessHistoryViewModel : BindableBase { #region 私有字段 private ProcessHistoryView view; List keys = new List(); RealtimeProvider _provider = new RealtimeProvider(); private ObservableCollection _ParameterNodes; DispatcherTimer timer = new DispatcherTimer(); ObservableCollection _PdKeyDataObservation = new ObservableCollection(); public List RecipesAdd = new List(); public List solidColorBrushes = new List(); //DateTime currentTime; private RecipeItem selectedRecipeItem; #endregion #region 属性 public List ProcessData { get; set; } public List CheboxRecipes { get; set; } public ProcessDataChartDataItem ProcessChartData { get; set; } public DateTime StartDateTime { get; set; } public DateTime EndDateTime { get; set; } public string SelectedValuePM { get; set; } public string RecipeName { get; set; } public ObservableCollection OldPdKeyDataCollection { get; set; } public ObservableCollection Recipes { get; set; } public class Recipeslist { public string BoxName { get; set; } } public class RecipeAdd { public string Recipesname { get; set; } } public ObservableCollection ParameterNodes { get { return _ParameterNodes; } set { SetProperty(ref _ParameterNodes, value); } } public ObservableCollection PdKeyDataCollection { get { return _PdKeyDataObservation; } set { SetProperty(ref _PdKeyDataObservation, value); } } #endregion #region 命令 private DelegateCommand _LoadCommandPD; public DelegateCommand LoadCommandPD => _LoadCommandPD ?? (_LoadCommandPD = new DelegateCommand(OnLoadPd)); private DelegateCommand _SearchRecipeCommand; public DelegateCommand SearchRecipeCommand => _SearchRecipeCommand ?? (_SearchRecipeCommand = new DelegateCommand(SearchRecipes)); private DelegateCommand _PdParameterCheckCommand; public DelegateCommand PdParameterCheckCommand => _PdParameterCheckCommand ?? (_PdParameterCheckCommand = new DelegateCommand(OnParameterCheck)); private DelegateCommand _DataGridSelectionChangedCommand; public DelegateCommand DataGridSelectionChangedCommand => _DataGridSelectionChangedCommand ?? (_DataGridSelectionChangedCommand = new DelegateCommand(OnDataGridSelectionChanged)); private DelegateCommand _SearchDataCommand; public DelegateCommand SearchDataCommand => _SearchDataCommand ?? (_SearchDataCommand = new DelegateCommand(OnSearchData)); private DelegateCommand _ClearDataCommand; public DelegateCommand ClearDataCommand => _ClearDataCommand ?? (_ClearDataCommand = new DelegateCommand(OnClearData)); #endregion #region 构造函数 public ProcessHistoryViewModel() { ProcessData = new List() { }; ProcessChartData = new ProcessDataChartDataItem(60000); Recipes = new ObservableCollection(); timer.Interval = TimeSpan.FromSeconds(0.5); OldPdKeyDataCollection = new ObservableCollection(); CheboxRecipes = new List(); 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)); } #endregion #region 命令方法 private void OnLoadPd(Object eventView) { this.view = (ProcessHistoryView)eventView; this.view.wfTimeFrom.Value = DateTime.Today; this.view.wfTimeTo.Value = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day, 23, 59, 59, 999); this.LoadRecipeCheckBox(); } private void LoadRecipeCheckBox() { List chamber = new List() { "PMA", "PMB", "PMC", "PMD" }; CheboxRecipes.Clear(); foreach (string item in chamber) { string path = Path.Combine(QueryDataClient.Instance.Service.GetData("GetRTPath").ToString(), "Recipes", item); if (Directory.Exists(path)) { string[] dir = Directory.GetFiles(path); for (int i = 0; i < dir.Length; i++) { CheboxRecipes.Add(new Recipeslist { BoxName = Path.GetFileName(dir[i]) }); } } } } public void SearchRecipes() { SearchRecipe(this.view.wfTimeFrom.Value, this.view.wfTimeTo.Value); } public void searchlot(string id) { Recipes.Clear(); try { string sql1 = string.Format($"SELECT * FROM \"lot_wafer_data\" where guid ='{id}'; "); DataTable dbData1 = QueryDataClient.Instance.Service.QueryData(sql1); string lot_data_guid = dbData1.Rows[0]["wafer_data_guid"].ToString(); string sql = string.Format($"SELECT * FROM \"process_data\" where wafer_data_guid ='{lot_data_guid}'"); if (!string.IsNullOrEmpty(SelectedValuePM)) { string[] pms = SelectedValuePM.Split(','); if (pms.Length > 0) { sql += " and (FALSE "; foreach (var pm in pms) { sql += $" OR \"process_in\"='{pm}' "; } sql += " ) "; } } if (!string.IsNullOrEmpty(RecipeName)) { sql += string.Format(" and lower(\"recipe_name\") like '%{0}%'", RecipeName.ToLower()); } sql += " order by \"process_begin_time\" ASC;"; DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql); System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { if (dbData == null || dbData.Rows.Count == 0) return; for (int i = 0; i < dbData.Rows.Count; i++) { RecipeItem item = new RecipeItem(); item.Selected = false; item.Recipe = dbData.Rows[i]["recipe_name"].ToString(); item.Guid = dbData.Rows[i]["guid"].ToString(); item.RecipeRunGuid = dbData.Rows[i]["wafer_data_guid"].ToString(); item.Chamber = dbData.Rows[i]["process_in"].ToString(); item.Status = dbData.Rows[i]["process_status"].ToString(); item.SlotID = dbData.Rows[i]["slot_id"].ToString(); item.LotID = dbData.Rows[i]["lot_id"].ToString(); 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"); 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"); Recipes.Add(item); } })); } catch (Exception e) { LOG.WriteExeption(e); } } public void SearchRecipe(DateTime start, DateTime end) { this.StartDateTime = start; this.EndDateTime = end; Recipes.Clear(); try { string sql = $"SELECT * FROM \"process_data\" where \"process_begin_time\" >='{StartDateTime.ToString("yyyy/MM/dd HH:mm:ss.fff")}' and \"process_begin_time\" <='{EndDateTime.ToString("yyyy/MM/dd HH:mm:ss.fff")}' "; if (!string.IsNullOrEmpty(SelectedValuePM)) { string[] pms = SelectedValuePM.Split(','); if (pms.Length > 0) { sql += " and (FALSE "; foreach (var pm in pms) { sql += $" OR \"process_in\"='{pm}' "; } sql += " ) "; } } if (!string.IsNullOrEmpty(RecipeName)) { sql += string.Format(" and lower(\"recipe_name\") like '%{0}%'", RecipeName.ToLower()); } sql += " order by \"process_begin_time\" ASC;"; DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql); System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() => { if (dbData == null || dbData.Rows.Count == 0) return; for (int i = 0; i < dbData.Rows.Count; i++) { RecipeItem item = new RecipeItem(); item.Selected = false; item.Recipe = dbData.Rows[i]["recipe_name"].ToString(); item.Guid = dbData.Rows[i]["guid"].ToString(); item.RecipeRunGuid = dbData.Rows[i]["wafer_data_guid"].ToString(); item.Chamber = dbData.Rows[i]["process_in"].ToString(); item.Status = dbData.Rows[i]["process_status"].ToString(); item.SlotID = dbData.Rows[i]["slot_id"].ToString(); item.LotID = dbData.Rows[i]["lot_id"].ToString(); 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"); 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"); Recipes.Add(item); } })); } catch (Exception e) { LOG.WriteExeption(e); } } 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 Dictionary> GetData(List keys, DateTime from, DateTime to) { string 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); 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 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); } } public static T DeepCopyJson(T obj) { // 序列化 string json = JsonConvert.SerializeObject(obj); // 反序列化 return JsonConvert.DeserializeObject(json); } private void OnParameterCheck(object obj) { 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]); } if (keys.Count > 10) { WPFMessageBox.ShowWarning("最多显示10个数据"); return; } OldPdKeyDataCollection.Clear(); OldPdKeyDataCollection = DeepCopyJson(PdKeyDataCollection); PdKeyDataCollection.Clear(); for (int i = 0; i < keys.Count; i++) { if (i == 10) { break; } PdKeyDataCollection.Add(new PdKeyData() { Key = keys[i], Color = solidColorBrushes[i], UniqueId = i }); } Compare(OldPdKeyDataCollection, PdKeyDataCollection); PdKeyDataCollection = DeepCopyJson(OldPdKeyDataCollection); } 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 PdKeyData() { 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 void UpdateData(RecipeItem dataLog) { OnClearData(); //CheckRecipe(dataLog.Guid); } public void CheckRecipe(string RecipeGuid) { string sql = $"SELECT * FROM \"recipe_step_data\" where \"process_data_guid\" = '{RecipeGuid}' order by step_number ASC;"; var dbData = QueryDataClient.Instance.Service.QueryData(sql); List steps = new List(); if (dbData != null && dbData.Rows.Count > 0) { for (int i = 0; i < dbData.Rows.Count; i++) { StepData item = new StepData(); item.No = int.Parse(dbData.Rows[i]["step_number"].ToString()); item.Name = dbData.Rows[i]["step_name"].ToString(); if (!dbData.Rows[i]["step_begin_time"].Equals(DBNull.Value)) item.StartTime = (DateTime)dbData.Rows[i]["step_begin_time"]; if (!dbData.Rows[i]["step_end_time"].Equals(DBNull.Value)) item.EndTime = (DateTime)dbData.Rows[i]["step_end_time"]; item.ActualTime = item.EndTime.CompareTo(item.StartTime) <= 0 ? "" : item.EndTime.Subtract(item.StartTime).TotalSeconds.ToString(); item.SettingTime = dbData.Rows[i]["step_time"].ToString(); //annotation.Add(VerLine(Brushes.Blue, item.StartTime, Brushes.Blue, $"{item.No}:{item.Name}")); } } } public void OnDataGridSelectionChanged(object obj) { selectedRecipeItem = obj as RecipeItem; ParameterNodes = new ObservableCollection(_provider.GetParameters().Where(x => x.Name == selectedRecipeItem?.Chamber)); } public void OnSearchData() { ProcessData.Clear(); this.view.MyDrawGraphicsControl.ClearPlotPoints(); var Keys = new List(); PdKeyDataCollection.ToList().ForEach(key => { Keys.Add(key.Key); }); if (keys.Count == 0) { return; } var result = GetData(Keys.Distinct().ToList(), Convert.ToDateTime(selectedRecipeItem?.StartTime), Convert.ToDateTime(selectedRecipeItem?.EndTime)); 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 => { ProcessData.Add(new HistoryDataItem() { dateTime= point.dateTime, dbName= Keys[i],value= point.value }); points.Add(new Point() { X = point.dateTime.ToOADate(), Y = point.value }); k += 1; }); cls.Add(points); } for (int i = 0; i { this.view.MyDrawGraphicsControl.YPoints.Add(new CyberX8_Core.StepItem() { StartValue = x.StartTime.ToOADate(), Information = $"{x.RecipeId}:{x.StepNo}" }); }); } } private void CloseAll(ObservableCollection parameterNodes) { if (parameterNodes != null) { foreach (var item in parameterNodes) { item.Selected = false; if (item.ChildNodes.Count > 0) { CloseAll(item.ChildNodes); } } } } private void OnClearData() { this.view.MyDrawGraphicsControl.YPoints.Clear(); PdKeyDataCollection.Clear(); this.view.MyDrawGraphicsControl.ClearPlotPoints(); CloseAll(ParameterNodes); } } #endregion #region 数据类 public class RecipeItem : BindableBase { public bool Selected { get; set; } public string Recipe { get; set; } public string Guid { get; set; } public string RecipeRunGuid { get; set; } public string Chamber { get; set; } public string Status { get; set; } public string StartTime { get; set; } public string EndTime { get; set; } public string LotID { get; set; } public string SlotID { get; set; } } public class StepData { [DataMember] public int No { get; set; } [DataMember] public string Name { get; set; } [DataMember] public DateTime StartTime { get; set; } [DataMember] public DateTime EndTime { get; set; } [DataMember] public string ActualTime { get; set; } [DataMember] public string SettingTime { get; set; } } public class PdKeyData : BindableBase, ICloneable { public string Key { get; set; } public SolidColorBrush _Color; public SolidColorBrush Color { get { return _Color; } set { SetProperty(ref _Color, value); } } public int UniqueId { get; set; } public object Clone() { return MemberwiseClone(); } } #endregion }