ProcessHistoryViewModel.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Data;
  5. using System.Linq;
  6. using System.Windows;
  7. using System.Windows.Media;
  8. using Aitex.Core.RT.Log;
  9. using Aitex.Core.UI.ControlDataContext;
  10. using Aitex.Core.UI.MVVM;
  11. using Aitex.Sorter.Common;
  12. using MECF.Framework.Common.CommonData;
  13. using MECF.Framework.Common.ControlDataContext;
  14. using MECF.Framework.Common.DataCenter;
  15. using MECF.Framework.Common.Utilities;
  16. using SciChart.Charting.Visuals.Annotations;
  17. using SciChart.Charting.Visuals.Axes;
  18. using SciChart.Charting.Visuals.RenderableSeries;
  19. using SciChart.Data.Model;
  20. using VirgoUI.Client.Models.Sys;
  21. using Cali = Caliburn.Micro;
  22. namespace VirgoUI.Client.Models.History.ProcessHistory
  23. {
  24. public class ProcessHistoryViewModel : UiViewModelBase
  25. {
  26. private int MenuPermission;
  27. public ObservableCollection<RecipeItem> Recipes { get; set; }
  28. public List<HistoryDataItem> ProcessData { get; set; }
  29. public ObservableCollection<IRenderableSeries> SelectedData { get; set; }
  30. public ObservableCollection<RecipeItem> SelectedRecipes { get; set; }
  31. public DateTime StartDateTime { get; set; }
  32. public DateTime EndDateTime { get; set; }
  33. public string SelectedValuePM { get; set; }
  34. public string RecipeName { get; set; }
  35. public ProcessDataChartDataItem ProcessChartData
  36. {
  37. get;
  38. set;
  39. }
  40. public AutoRange ChartAutoRange
  41. {
  42. get { return EnableAutoZoom ? AutoRange.Always : AutoRange.Never; }
  43. }
  44. public AutoRange AutoRangeX
  45. {
  46. get => _autoRangeX;
  47. set
  48. {
  49. _autoRangeX = value;
  50. NotifyOfPropertyChange(nameof(AutoRangeX));
  51. }
  52. }
  53. public AutoRange AutoRangeY
  54. {
  55. get => _autoRangeY;
  56. set
  57. {
  58. _autoRangeY = value;
  59. NotifyOfPropertyChange(nameof(AutoRangeY));
  60. }
  61. }
  62. private bool _enableAutoZoom = true;
  63. public bool EnableAutoZoom
  64. {
  65. get { return _enableAutoZoom; }
  66. set
  67. {
  68. _enableAutoZoom = value;
  69. NotifyOfPropertyChange(nameof(EnableAutoZoom));
  70. NotifyOfPropertyChange(nameof(ChartAutoRange));
  71. }
  72. }
  73. private IRange _TimeRange;
  74. public IRange TimeRange
  75. {
  76. get { return _TimeRange; }
  77. set
  78. {
  79. _TimeRange = value;
  80. NotifyOfPropertyChange("TimeRange");
  81. }
  82. }
  83. private IRange _ValueRange;
  84. public IRange ValueRange
  85. {
  86. get { return _ValueRange; }
  87. set { _ValueRange = value; }
  88. }
  89. Cali.WindowManager wm = new Cali.WindowManager();
  90. SelectDataViewModel selectDataDlg = new SelectDataViewModel();
  91. private AutoRange _autoRangeX;
  92. private AutoRange _autoRangeY;
  93. private ProcessHistoryView view;
  94. public ProcessHistoryViewModel()
  95. {
  96. MenuPermission = ClientApp.Instance.GetPermission("ProcessHistory");
  97. var now = DateTime.Now;
  98. StartDateTime = now.AddHours(-2);
  99. EndDateTime = now;
  100. DisplayName = "Process History";
  101. ProcessChartData = new ProcessDataChartDataItem(60000);
  102. SelectedData = new ObservableCollection<IRenderableSeries>();
  103. SelectedRecipes = new ObservableCollection<RecipeItem>();
  104. Recipes = new ObservableCollection<RecipeItem>();
  105. TimeRange = new DateRange(DateTime.Now.AddMinutes(-1), DateTime.Now.AddMinutes(59));
  106. AutoRangeX = AutoRange.Once;
  107. AutoRangeY = AutoRange.Once;
  108. }
  109. public void SelectData()
  110. {
  111. selectDataDlg.SelectedRecipes.Clear();
  112. selectDataDlg.SelectedParameters.Clear();
  113. var settings = new Dictionary<string, object> { { "Title", "Select Recipe Data" } };
  114. bool? ret = wm.ShowDialog(selectDataDlg, null, settings);
  115. if (ret == null || !ret.Value) return;
  116. SelectedData.Clear();
  117. double valueMin = double.MaxValue;
  118. double valueMax = double.MinValue;
  119. DateTime dtMin = DateTime.MaxValue;
  120. DateTime dtMax = DateTime.MinValue;
  121. foreach (var recipe in selectDataDlg.SelectedRecipes)
  122. {
  123. if (Convert.ToDateTime(recipe.StartTime) < dtMin)
  124. dtMin = Convert.ToDateTime(recipe.StartTime);
  125. if (!string.IsNullOrEmpty(recipe.EndTime))
  126. {
  127. if (Convert.ToDateTime(recipe.EndTime) > dtMax)
  128. dtMax = Convert.ToDateTime(recipe.EndTime);
  129. }
  130. QueryData(recipe, selectDataDlg.SelectedParameters, ref valueMin, ref valueMax);
  131. }
  132. TimeRange = new DateRange(dtMin.AddMinutes(-1), dtMax.AddMinutes(5));
  133. ValueRange = new DoubleRange(valueMin - 5, valueMax + 5);
  134. }
  135. public void QueryData(RecipeItem recipe, ObservableCollection<string> keys, ref double min, ref double max)
  136. {
  137. if (string.IsNullOrEmpty(recipe.StartTime))
  138. {
  139. MessageBox.Show($"can not query recipe data, did not record {recipe.Recipe} start time");
  140. return;
  141. }
  142. DateTime dtFrom = Convert.ToDateTime(recipe.StartTime);
  143. DateTime dtTo = dtFrom.AddMinutes(10);
  144. if (!string.IsNullOrEmpty(recipe.EndTime))
  145. {
  146. dtTo = Convert.ToDateTime(recipe.EndTime);
  147. }
  148. Dictionary<string, List<Tuple<DateTime, double>>> result;
  149. if (GetDbData(recipe.Chamber, dtFrom, dtTo, keys, out result, ref min, ref max))
  150. {
  151. foreach (var data in result)
  152. {
  153. ChartDataLine line = new ChartDataLine(data.Key);
  154. line.DataSource = recipe.Recipe;
  155. foreach (var tuple in data.Value)
  156. {
  157. line.Append(tuple.Item1, tuple.Item2);
  158. }
  159. SelectedData.Add(line);
  160. }
  161. }
  162. }
  163. public bool GetDbData(string chamber, DateTime from, DateTime to, IEnumerable<string> dataIdList, out Dictionary<string, List<Tuple<DateTime, double>>> returnDatas, ref double min, ref double max)
  164. {
  165. returnDatas = new Dictionary<string, List<Tuple<DateTime, double>>>();
  166. for (DateTime dfrom = new DateTime(from.Year, from.Month, from.Day); dfrom < to; dfrom += new TimeSpan(1, 0, 0, 0))
  167. {
  168. DateTime begin = (dfrom.Year == from.Year && dfrom.Month == from.Month && dfrom.Day == from.Day) ? from : new DateTime(dfrom.Year, dfrom.Month, dfrom.Day, 0, 0, 0, 0);
  169. DateTime end = (dfrom.Date == to.Date) ? to : new DateTime(dfrom.Year, dfrom.Month, dfrom.Day, 23, 59, 59, 999);
  170. //if (begin.Date > DateTime.Today)
  171. // continue;
  172. try
  173. {
  174. string sql = "select time AS InternalTimeStamp";
  175. foreach (var dataId in dataIdList)
  176. {
  177. if (!returnDatas.Keys.Contains(dataId) && dataId.StartsWith($"{chamber}."))
  178. {
  179. returnDatas[dataId] = new List<Tuple<DateTime, double>>();
  180. sql += "," + string.Format("\"{0}\"", dataId);
  181. }
  182. }
  183. sql += string.Format(" from \"{0}\" where time > {1} and time <= {2} order by time asc;",
  184. begin.ToString("yyyyMMdd") + "." + chamber, begin.Ticks, end.Ticks);
  185. using (var table = QueryDataClient.Instance.Service.QueryData(sql))
  186. {
  187. if (table == null || table.Rows.Count == 0) continue;
  188. DateTime dt = new DateTime();
  189. Dictionary<int, string> colName = new Dictionary<int, string>();
  190. for (int colNo = 0; colNo < table.Columns.Count; colNo++)
  191. colName.Add(colNo, table.Columns[colNo].ColumnName);
  192. for (int rowNo = 0; rowNo < table.Rows.Count; rowNo++)
  193. {
  194. var row = table.Rows[rowNo];
  195. for (int i = 0; i < table.Columns.Count; i++)
  196. {
  197. if (i == 0)
  198. {
  199. long ticks = (long)row[i];
  200. dt = new DateTime(ticks);
  201. }
  202. else
  203. {
  204. string dataId = colName[i];
  205. double value = 0.0;
  206. if (row[i] is DBNull || row[i] == null)
  207. {
  208. value = 0.0;
  209. }
  210. else if (row[i] is bool)
  211. {
  212. value = (bool)row[i] ? 1.0 : 0;
  213. }
  214. else
  215. {
  216. value = (double)float.Parse(row[i].ToString());
  217. }
  218. returnDatas[dataId].Add(Tuple.Create(dt, value));
  219. if (value < min)
  220. min = value;
  221. if (value > max)
  222. max = value;
  223. }
  224. }
  225. }
  226. table.Clear();
  227. }
  228. }
  229. catch (Exception ex)
  230. {
  231. LOG.Write(ex);
  232. return false;
  233. }
  234. }
  235. return true;
  236. }
  237. public void SearchRecipe()
  238. {
  239. if (MenuPermission != 3) return;
  240. this.StartDateTime = this.view.wfTimeFrom.Value;
  241. this.EndDateTime = this.view.wfTimeTo.Value;
  242. Recipes.Clear();
  243. //ObservableCollection<RecipeItem> items = ProcessHistoryProvider.Instance.SearchRecipe();
  244. //foreach (RecipeItem item in items)
  245. // Recipes.Add(item);
  246. try
  247. {
  248. 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")}' ";
  249. if (!string.IsNullOrEmpty(SelectedValuePM))
  250. {
  251. string[] pms = SelectedValuePM.Split(',');
  252. if (pms.Length > 0)
  253. {
  254. sql += " and (FALSE ";
  255. foreach (var pm in pms)
  256. {
  257. sql += $" OR \"process_in\"='{pm}' ";
  258. }
  259. sql += " ) ";
  260. }
  261. }
  262. if (!string.IsNullOrEmpty(RecipeName))
  263. {
  264. sql += string.Format(" and lower(\"recipe_name\") like '%{0}%'", RecipeName.ToLower());
  265. }
  266. sql += " order by \"process_begin_time\" ASC;";
  267. DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
  268. Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  269. {
  270. if (dbData == null || dbData.Rows.Count == 0) return;
  271. for (int i = 0; i < dbData.Rows.Count; i++)
  272. {
  273. RecipeItem item = new RecipeItem();
  274. item.Recipe = dbData.Rows[i]["recipe_name"].ToString();
  275. item.Guid = dbData.Rows[i]["guid"].ToString();
  276. item.RecipeRunGuid = dbData.Rows[i]["wafer_data_guid"].ToString();
  277. item.Chamber = dbData.Rows[i]["process_in"].ToString();
  278. item.Status = dbData.Rows[i]["process_status"].ToString();
  279. item.SlotID = dbData.Rows[i]["slot_id"].ToString();
  280. item.LotID = dbData.Rows[i]["lot_id"].ToString();
  281. if (!dbData.Rows[i]["process_begin_time"].Equals(DBNull.Value))
  282. item.StartTime = ((DateTime)dbData.Rows[i]["process_begin_time"]).ToString("yyyy-MM-dd HH:mm:ss.fff");
  283. if (!dbData.Rows[i]["process_end_time"].Equals(DBNull.Value))
  284. item.EndTime = ((DateTime)dbData.Rows[i]["process_end_time"]).ToString("yyyy-MM-dd HH:mm:ss.fff");
  285. Recipes.Add(item);
  286. }
  287. }));
  288. }
  289. catch (Exception e)
  290. {
  291. LOG.Write(e);
  292. }
  293. }
  294. public void CheckRecipe(RecipeItem recipe)
  295. {
  296. if (recipe.Selected)
  297. {
  298. SelectedRecipes.Add(recipe);
  299. }
  300. else
  301. {
  302. RecipeItem item = SelectedRecipes.FirstOrDefault(t => t.Recipe == recipe.Recipe);
  303. if (item != null)
  304. SelectedRecipes.Remove(item);
  305. }
  306. }
  307. public void CheckAllRecipe()
  308. {
  309. }
  310. public void UpdateData(RecipeItem dataLog)
  311. {
  312. if (dataLog == null)
  313. {
  314. ProcessChartData.ClearData();
  315. return;
  316. }
  317. List<string> keys = new List<string>();
  318. Application.Current.Dispatcher.Invoke(new Action(() =>
  319. {
  320. Dictionary<string, Tuple<string, string, bool>> dicItems = GetDataElements("zh-CN");
  321. keys = dicItems.Keys.ToList();
  322. ProcessChartData.UpdateColumns(dicItems);
  323. }));
  324. ProcessData = QueryDataClient.Instance.Service.GetHistoryData(keys, dataLog.Guid, "Data");
  325. Application.Current.Dispatcher.Invoke(new Action(() =>
  326. {
  327. ProcessChartData.SetInfo(dataLog.Recipe);
  328. ProcessChartData.UpdateData(ProcessData);
  329. QueryRecipe(dataLog.Guid);
  330. if (DateTime.TryParse(dataLog.EndTime, out DateTime result))
  331. {
  332. ProcessChartData.Annotations.Add(VerLine(Brushes.Blue, result, Brushes.Blue, $"Recipe End"));
  333. }
  334. }));
  335. }
  336. public static VerticalLineAnnotation VerLine(Brush stroke, DateTime x, Brush color, string text)
  337. {
  338. var label = new AnnotationLabel()
  339. {
  340. LabelPlacement = LabelPlacement.TopRight,
  341. FontSize = 12,
  342. RotationAngle = 0,
  343. Foreground = color,
  344. Text = text
  345. };
  346. var line = new VerticalLineAnnotation()
  347. {
  348. Stroke = stroke,
  349. StrokeThickness = 1,
  350. X1 = x,
  351. IsEditable = false,
  352. VerticalAlignment = VerticalAlignment.Stretch,
  353. AnnotationLabels = new ObservableCollection<AnnotationLabel>() { label },
  354. };
  355. return line;
  356. }
  357. public void QueryRecipe(string recipeGuid)
  358. {
  359. AnnotationCollection annotation = new AnnotationCollection();
  360. string sql = $"SELECT * FROM \"recipe_step_data\" where \"process_data_guid\" = '{recipeGuid}' order by step_number ASC;";
  361. var dbData = QueryDataClient.Instance.Service.QueryData(sql);
  362. List<RecipeStep> steps = new List<RecipeStep>();
  363. if (dbData != null && dbData.Rows.Count > 0)
  364. {
  365. for (int i = 0; i < dbData.Rows.Count; i++)
  366. {
  367. RecipeStep item = new RecipeStep();
  368. item.No = int.Parse(dbData.Rows[i]["step_number"].ToString());
  369. item.Name = dbData.Rows[i]["step_name"].ToString();
  370. if (!dbData.Rows[i]["step_begin_time"].Equals(DBNull.Value))
  371. item.StartTime = (DateTime)dbData.Rows[i]["step_begin_time"];
  372. if (!dbData.Rows[i]["step_end_time"].Equals(DBNull.Value))
  373. item.EndTime = (DateTime)dbData.Rows[i]["step_end_time"];
  374. item.ActualTime = item.EndTime.CompareTo(item.StartTime) <= 0 ? "" : item.EndTime.Subtract(item.StartTime).TotalSeconds.ToString();
  375. item.SettingTime = dbData.Rows[i]["step_time"].ToString();
  376. annotation.Add(VerLine(Brushes.Blue, item.StartTime, Brushes.Blue, $"{item.No}:{item.Name}"));
  377. }
  378. }
  379. ProcessChartData.Annotations = annotation;
  380. }
  381. public void DeleteAll()
  382. {
  383. SelectedData.Clear();
  384. }
  385. public void Delete(ChartDataLine cp)
  386. {
  387. if (cp != null && SelectedData.Contains(cp))
  388. {
  389. SelectedData.Remove(cp);
  390. }
  391. }
  392. public void ExportAll()
  393. {
  394. try
  395. {
  396. Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
  397. dlg.DefaultExt = ".xlsx"; // Default file extension
  398. dlg.Filter = "Excel数据表格文件(*.xlsx)|*.xlsx"; // Filter files by extension
  399. dlg.FileName = $"Export_{DateTime.Now:yyyyMMdd_HHmmss}";
  400. Nullable<bool> result = dlg.ShowDialog();// Show open file dialog box
  401. if (result == true) // Process open file dialog box results
  402. {
  403. System.Data.DataSet ds = new System.Data.DataSet();
  404. ds.Tables.Add(new System.Data.DataTable($"Export_{DateTime.Now:yyyyMMdd_HHmmss}"));
  405. ds.Tables[0].Columns.Add("Time");
  406. ds.Tables[0].Columns[0].DataType = typeof(DateTime);
  407. Dictionary<DateTime, double[]> timeValue = new Dictionary<DateTime, double[]>();
  408. for (int i = 0; i < SelectedData.Count; i++)
  409. {
  410. List<Tuple<DateTime, double>> data = (SelectedData[i] as ChartDataLine).Points;
  411. foreach (var tuple in data)
  412. {
  413. if (!timeValue.ContainsKey(tuple.Item1))
  414. timeValue[tuple.Item1] = new double[SelectedData.Count];
  415. timeValue[tuple.Item1][i] = tuple.Item2;
  416. }
  417. ds.Tables[0].Columns.Add((SelectedData[i] as ChartDataLine).DataName);
  418. ds.Tables[0].Columns[i + 1].DataType = typeof(double);
  419. }
  420. foreach (var item in timeValue)
  421. {
  422. var row = ds.Tables[0].NewRow();
  423. row[0] = item.Key;
  424. for (int j = 0; j < item.Value.Length; j++)
  425. {
  426. row[j + 1] = item.Value[j];
  427. }
  428. ds.Tables[0].Rows.Add(row);
  429. }
  430. if (!ExcelHelper.ExportToExcel(dlg.FileName, ds, out string reason))
  431. {
  432. MessageBox.Show($"Export failed, {reason}", "Export", MessageBoxButton.OK,
  433. MessageBoxImage.Warning);
  434. return;
  435. }
  436. MessageBox.Show($"Export succeed, file save as {dlg.FileName}", "Export", MessageBoxButton.OK,
  437. MessageBoxImage.Information);
  438. }
  439. }
  440. catch (Exception ex)
  441. {
  442. LOG.Write(ex);
  443. MessageBox.Show("Write failed," + ex.Message, "export failed", MessageBoxButton.OK, MessageBoxImage.Warning);
  444. }
  445. }
  446. public void Export(ChartDataLine cp)
  447. {
  448. try
  449. {
  450. Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
  451. dlg.DefaultExt = ".xlsx"; // Default file extension
  452. dlg.Filter = "Excel数据表格文件(*.xlsx)|*.xlsx"; // Filter files by extension
  453. dlg.FileName = $"{cp.DataSource}_{DateTime.Now:yyyyMMdd_HHmmss}";
  454. Nullable<bool> result = dlg.ShowDialog();// Show open file dialog box
  455. if (result == true) // Process open file dialog box results
  456. {
  457. System.Data.DataSet ds = new System.Data.DataSet();
  458. ds.Tables.Add(new System.Data.DataTable(cp.DataName));
  459. ds.Tables[0].Columns.Add("Time");
  460. ds.Tables[0].Columns[0].DataType = typeof(DateTime);
  461. ds.Tables[0].Columns.Add(cp.DataName);
  462. ds.Tables[0].Columns[1].DataType = typeof(double);
  463. foreach (var item in cp.Points)
  464. {
  465. var row = ds.Tables[0].NewRow();
  466. row[0] = item.Item1;
  467. row[1] = item.Item2;
  468. ds.Tables[0].Rows.Add(row);
  469. }
  470. if (!ExcelHelper.ExportToExcel(dlg.FileName, ds, out string reason))
  471. {
  472. MessageBox.Show($"Export failed, {reason}", "Export", MessageBoxButton.OK, MessageBoxImage.Warning);
  473. return;
  474. }
  475. MessageBox.Show($"Export succeed, file save as {dlg.FileName}", "Export", MessageBoxButton.OK, MessageBoxImage.Information);
  476. }
  477. }
  478. catch (Exception ex)
  479. {
  480. LOG.Write(ex);
  481. MessageBox.Show("Write failed," + ex.Message, "export failed", MessageBoxButton.OK, MessageBoxImage.Warning);
  482. }
  483. }
  484. public void SelectColor(ChartDataLine cp)
  485. {
  486. if (cp == null) return;
  487. var dlg = new System.Windows.Forms.ColorDialog();
  488. if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
  489. {
  490. cp.Stroke = new System.Windows.Media.Color() { A = dlg.Color.A, B = dlg.Color.B, G = dlg.Color.G, R = dlg.Color.R };
  491. }
  492. }
  493. protected override void OnViewLoaded(object _view)
  494. {
  495. base.OnViewLoaded(_view);
  496. this.view = (ProcessHistoryView)_view;
  497. this.view.wfTimeFrom.Value = this.StartDateTime;
  498. this.view.wfTimeTo.Value = this.EndDateTime;
  499. //this.AppendData();
  500. }
  501. public void Query(object parameter)
  502. {
  503. WaferHistoryWafer waferHistoryRecipe = parameter as WaferHistoryWafer;
  504. if (waferHistoryRecipe != null)
  505. {
  506. Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  507. {
  508. if (waferHistoryRecipe.StartTime != DateTime.MinValue)
  509. this.view.wfTimeFrom.Value = waferHistoryRecipe.StartTime;
  510. if (waferHistoryRecipe.EndTime != DateTime.MinValue)
  511. this.view.wfTimeTo.Value = waferHistoryRecipe.EndTime;
  512. else
  513. this.view.wfTimeTo.Value = waferHistoryRecipe.StartTime.AddHours(1);
  514. SearchRecipe(waferHistoryRecipe);
  515. }));
  516. }
  517. }
  518. private void SearchRecipe(WaferHistoryWafer waferHistoryRecipe)
  519. {
  520. if (MenuPermission != 3) return;
  521. this.StartDateTime = this.view.wfTimeFrom.Value;
  522. this.EndDateTime = this.view.wfTimeTo.Value;
  523. Recipes.Clear();
  524. //ObservableCollection<RecipeItem> items = ProcessHistoryProvider.Instance.SearchRecipe();
  525. //foreach (RecipeItem item in items)
  526. // Recipes.Add(item);
  527. try
  528. {
  529. 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")}' ";
  530. if (!string.IsNullOrEmpty(SelectedValuePM))
  531. {
  532. string[] pms = SelectedValuePM.Split(',');
  533. if (pms.Length > 0)
  534. {
  535. sql += " and (FALSE ";
  536. foreach (var pm in pms)
  537. {
  538. sql += $" OR \"process_in\"='{pm}' ";
  539. }
  540. sql += " ) ";
  541. }
  542. }
  543. if (!string.IsNullOrEmpty(RecipeName))
  544. {
  545. sql += string.Format(" and lower(\"recipe_name\") like '%{0}%'", RecipeName.ToLower());
  546. }
  547. sql += " order by \"process_begin_time\" ASC;";
  548. DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
  549. Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  550. {
  551. if (dbData == null || dbData.Rows.Count == 0) return;
  552. for (int i = 0; i < dbData.Rows.Count; i++)
  553. {
  554. RecipeItem item = new RecipeItem();
  555. item.Recipe = dbData.Rows[i]["recipe_name"].ToString();
  556. item.Guid = dbData.Rows[i]["guid"].ToString();
  557. item.RecipeRunGuid = dbData.Rows[i]["wafer_data_guid"].ToString();
  558. item.Chamber = dbData.Rows[i]["process_in"].ToString();
  559. item.Status = dbData.Rows[i]["process_status"].ToString();
  560. item.SlotID = dbData.Rows[i]["slot_id"].ToString();
  561. item.LotID = dbData.Rows[i]["lot_id"].ToString();
  562. if (!dbData.Rows[i]["process_begin_time"].Equals(DBNull.Value))
  563. {
  564. item.StartTime = ((DateTime)dbData.Rows[i]["process_begin_time"]).ToString("yyyy-MM-dd HH:mm:ss.fff");
  565. if ((DateTime)dbData.Rows[i]["process_begin_time"] == waferHistoryRecipe.StartTime)
  566. {
  567. Recipes.Add(item);
  568. break;
  569. }
  570. }
  571. if (!dbData.Rows[i]["process_end_time"].Equals(DBNull.Value))
  572. item.EndTime = ((DateTime)dbData.Rows[i]["process_end_time"]).ToString("yyyy-MM-dd HH:mm:ss.fff");
  573. if (item.SlotID == waferHistoryRecipe.SlotID)
  574. {
  575. Recipes.Add(item);
  576. break;
  577. }
  578. }
  579. }));
  580. }
  581. catch (Exception e)
  582. {
  583. LOG.Write(e);
  584. }
  585. }
  586. }
  587. }