WaferHistoryDBViewModel.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. using Aitex.Sorter.Common;
  2. using MECF.Framework.Common.DataCenter;
  3. using MECF.Framework.UI.Client.ClientBase;
  4. using OpenSEMI.ClientBase.Command;
  5. using SciChart.Core.Extensions;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Collections.ObjectModel;
  9. using System.ComponentModel;
  10. using System.Data;
  11. using System.Diagnostics.Eventing.Reader;
  12. using System.Linq;
  13. using System.Windows.Forms;
  14. using System.Windows.Input;
  15. namespace MECF.Framework.UI.Client.CenterViews.DataLogs.WaferHistory
  16. {
  17. public class WaferHistoryDBViewModel : BaseModel
  18. {
  19. public WaferHistoryDBViewModel()
  20. {
  21. SelectionChangedCommand = new BaseCommand<WaferHistoryItem>(SelectionChanged);
  22. QueryCommand = new BaseCommand<object>(QueryLots);
  23. ToChartCommand = new BaseCommand<object>(GoToChart);
  24. HistoryData = new ObservableCollection<LazyTreeItem<WaferHistoryItem>>();
  25. InitTime();
  26. }
  27. private ObservableCollection<LazyTreeItem<WaferHistoryItem>> _historyData;
  28. public ObservableCollection<LazyTreeItem<WaferHistoryItem>> HistoryData
  29. {
  30. get { return _historyData; }
  31. set
  32. {
  33. _historyData = value;
  34. NotifyOfPropertyChange("HistoryData");
  35. }
  36. }
  37. private WaferHistoryItem _selectedItem;
  38. public WaferHistoryItem SelectedItem
  39. {
  40. get { return _selectedItem; }
  41. set
  42. {
  43. _selectedItem = value;
  44. NotifyOfPropertyChange("SelectedItem");
  45. }
  46. }
  47. private ObservableCollection<WaferHistoryLot> _lots = new ObservableCollection<WaferHistoryLot>();
  48. public ObservableCollection<WaferHistoryLot> Lots
  49. {
  50. get { return _lots; }
  51. set
  52. {
  53. _lots = value;
  54. NotifyOfPropertyChange("Lots");
  55. }
  56. }
  57. private ObservableCollection<WaferHistoryWafer> _wafers = new ObservableCollection<WaferHistoryWafer>();
  58. public ObservableCollection<WaferHistoryWafer> Wafers
  59. {
  60. get { return _wafers; }
  61. set
  62. {
  63. _wafers = value;
  64. NotifyOfPropertyChange("Wafers");
  65. }
  66. }
  67. private ObservableCollection<WaferHistoryMovement> _movements = new ObservableCollection<WaferHistoryMovement>();
  68. public ObservableCollection<WaferHistoryMovement> Movements
  69. {
  70. get { return _movements; }
  71. set
  72. {
  73. _movements = value;
  74. NotifyOfPropertyChange("Movements");
  75. }
  76. }
  77. private WaferHistoryRecipe _recipe;
  78. public WaferHistoryRecipe Recipe
  79. {
  80. get { return _recipe; }
  81. set
  82. {
  83. _recipe = value;
  84. NotifyOfPropertyChange("Recipe");
  85. }
  86. }
  87. public ObservableCollection<WaferHistoryRecipe> _recipes = new ObservableCollection<WaferHistoryRecipe>();
  88. public ObservableCollection<WaferHistoryRecipe> Recipes
  89. {
  90. get { return _recipes; }
  91. set
  92. {
  93. _recipes = value;
  94. NotifyOfPropertyChange("Recipes");
  95. }
  96. }
  97. private DateTime _searchBeginTime;
  98. public DateTime SearchBeginTime
  99. {
  100. get { return _searchBeginTime; }
  101. set
  102. {
  103. _searchBeginTime = value;
  104. NotifyOfPropertyChange("SearchBeginTime");
  105. }
  106. }
  107. private DateTime _searchEndTime;
  108. public DateTime SearchEndTime
  109. {
  110. get { return _searchEndTime; }
  111. set
  112. {
  113. _searchEndTime = value;
  114. NotifyOfPropertyChange("SearchEndTime");
  115. }
  116. }
  117. private string keyWord;
  118. private WaferHistoryDBView view;
  119. public string KeyWord
  120. {
  121. get { return keyWord; }
  122. set
  123. {
  124. keyWord = value;
  125. NotifyOfPropertyChange("KeyWord");
  126. }
  127. }
  128. public ICommand SelectionChangedCommand { get; set; }
  129. public ICommand QueryCommand { get; set; }
  130. public ICommand ToChartCommand { get; set; }
  131. void InitTime()
  132. {
  133. SearchBeginTime = DateTime.Now.Date;
  134. SearchEndTime = DateTime.Now.Date.AddDays(1).Date;
  135. }
  136. void QueryLots(object e)
  137. {
  138. this.SearchBeginTime = this.view.wfTimeFrom.Value;
  139. this.SearchEndTime = this.view.wfTimeTo.Value;
  140. if (SearchBeginTime > SearchEndTime)
  141. {
  142. MessageBox.Show("Time range invalid, start time should be early than end time");
  143. return;
  144. }
  145. Lots = new ObservableCollection<WaferHistoryLot>(QueryLot(SearchBeginTime, SearchEndTime, KeyWord));//.OrderByDescending(lot => lot.StartTime).ToArray();
  146. HistoryData.Clear();
  147. var lotsItem = new WaferHistoryItem() { Name = "Lots", };
  148. var root = new LazyTreeItem<WaferHistoryItem>(lotsItem, x => LoadSubItem(x));
  149. root.SubItems = new ObservableCollection<LazyTreeItem<WaferHistoryItem>>(Lots.Select(x => new LazyTreeItem<WaferHistoryItem>(new WaferHistoryItem() { ID = x.ID, Name = x.Name, StartTime = x.StartTime, EndTime = x.EndTime, Type = WaferHistoryItemType.Lot }, LoadSubItem)));
  150. root.IsExpanded = true;
  151. HistoryData.Add(root);
  152. SelectedItem = lotsItem;
  153. }
  154. /// <summary>
  155. /// Notify chart page to prepare datas
  156. /// </summary>
  157. /// <param name="o"></param>
  158. void GoToChart(object o)
  159. {
  160. WaferHistoryRecipe chartQuery = null;
  161. if (o is string name)
  162. {
  163. var query = _recipes.FirstOrDefault(t => t.Recipe == name);
  164. if (query is null) return;
  165. chartQuery = query;
  166. }
  167. if (o is WaferHistoryLot waferLot)
  168. {
  169. DateTime start = waferLot.StartTime;
  170. double.TryParse(waferLot.Duration, out double duration);
  171. DateTime end = start.AddSeconds(duration);
  172. chartQuery = new WaferHistoryRecipe() { StartTime = start, EndTime = end, /*Chamber = waferLot.CarrierID */};
  173. }
  174. else if (o is WaferHistoryWafer wafer)
  175. {
  176. chartQuery = new WaferHistoryRecipe() { StartTime = wafer.StartTime, EndTime = wafer.EndTime/*,Chamber = waferLot.CarrierID*/ };
  177. }
  178. //导航切换到chart页面
  179. BaseApp.Instance.SwitchPage("DataLog", "DataHistory", chartQuery);
  180. }
  181. public List<WaferHistoryLot> QueryLot(DateTime from, DateTime to, string key)
  182. {
  183. List<WaferHistoryLot> result = new List<WaferHistoryLot>();
  184. string sql = $"SELECT * FROM \"lot_data\" where \"start_time\" >= '{from:yyyy/MM/dd HH:mm:ss.fff}' and \"start_time\" <= '{to:yyyy/MM/dd HH:mm:ss.fff}' order by \"start_time\" ASC;";
  185. //Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  186. //{
  187. DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
  188. if (dbData != null && dbData.Rows.Count > 0)
  189. {
  190. for (int i = 0; i < dbData.Rows.Count; i++)
  191. {
  192. WaferHistoryLot item = new WaferHistoryLot();
  193. string name = dbData.Rows[i]["name"].ToString();
  194. string time = "";
  195. item.WaferCount = (int)dbData.Rows[i]["total_wafer_count"];
  196. item.ID = dbData.Rows[i]["guid"].ToString();
  197. if (!dbData.Rows[i]["start_time"].Equals(DBNull.Value))
  198. {
  199. item.StartTime = ((DateTime)dbData.Rows[i]["start_time"]);
  200. time = item.StartTime.ToString("yyyy-MM-dd HH:mm:ss");
  201. }
  202. if (!dbData.Rows[i]["end_time"].Equals(DBNull.Value))
  203. {
  204. item.EndTime = ((DateTime)dbData.Rows[i]["end_time"]);
  205. }
  206. item.Name = $"{name} - {time}";
  207. result.Add(item);
  208. }
  209. }
  210. //}));
  211. return result;
  212. }
  213. public List<WaferHistoryWafer> QueryLotWafer(string lotGuid)
  214. {
  215. List<WaferHistoryWafer> result = new List<WaferHistoryWafer>();
  216. string sql = $"SELECT * FROM \"wafer_data\",\"lot_wafer_data\" where \"lot_wafer_data\".\"lot_data_guid\" = '{lotGuid}' and \"lot_wafer_data\".\"wafer_data_guid\" = \"wafer_data\".\"guid\" order by \"wafer_data\".\"create_time\" ASC;;";
  217. Wafers.Clear();
  218. //Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  219. //{
  220. DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
  221. if (dbData != null && dbData.Rows.Count > 0)
  222. {
  223. for (int i = 0; i < dbData.Rows.Count; i++)
  224. {
  225. WaferHistoryWafer item = new WaferHistoryWafer();
  226. item.ID = dbData.Rows[i]["guid"].ToString();
  227. var itemLoadPort = dbData.Rows[i]["create_station"].ToString();
  228. var itemSlot = dbData.Rows[i]["create_slot"].ToString();
  229. //item.CarrierID = dbData.Rows[i]["rfid"].ToString();
  230. //item.LotID = dbData.Rows[i]["lot_id"].ToString();
  231. var itemWaferID = dbData.Rows[i]["wafer_id"].ToString();
  232. item.Sequence = dbData.Rows[i]["sequence_name"].ToString();
  233. item.Status = dbData.Rows[i]["process_status"].ToString();
  234. if (!dbData.Rows[i]["create_time"].Equals(DBNull.Value))
  235. {
  236. item.StartTime = ((DateTime)dbData.Rows[i]["create_time"]);
  237. }
  238. if (!dbData.Rows[i]["delete_time"].Equals(DBNull.Value))
  239. item.EndTime = ((DateTime)dbData.Rows[i]["delete_time"]);
  240. item.Name = $"{itemLoadPort} - {itemSlot} - {itemWaferID}";
  241. item.Type = WaferHistoryItemType.Wafer;
  242. Wafers.Add(item);
  243. result.Add(item);
  244. }
  245. }
  246. //}));
  247. return result;
  248. }
  249. public List<WaferHistoryRecipe> QueryWaferRecipe(string waferGuid)
  250. {
  251. List<WaferHistoryRecipe> result = new List<WaferHistoryRecipe>();
  252. string sql = $"SELECT * FROM \"process_data\" where \"wafer_data_guid\" = '{waferGuid}';";
  253. Recipes.Clear();
  254. //Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  255. //{
  256. DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
  257. if (dbData != null && dbData.Rows.Count > 0)
  258. {
  259. for (int i = 0; i < dbData.Rows.Count; i++)
  260. {
  261. WaferHistoryRecipe item = new WaferHistoryRecipe();
  262. item.ID = dbData.Rows[i]["guid"].ToString();
  263. var itemName = dbData.Rows[i]["recipe_name"].ToString();
  264. if (!dbData.Rows[i]["process_begin_time"].Equals(DBNull.Value))
  265. item.StartTime = (DateTime)dbData.Rows[i]["process_begin_time"];
  266. if (dbData.Rows[i].Table.Columns.Contains("process_end_time") && !dbData.Rows[i]["process_end_time"].Equals(DBNull.Value))
  267. item.EndTime = (DateTime)dbData.Rows[i]["process_end_time"];
  268. if (dbData.Rows[i].Table.Columns.Contains("recipe_setting_time") && !dbData.Rows[i]["recipe_setting_time"].Equals(DBNull.Value))
  269. item.SettingTime = dbData.Rows[i]["recipe_setting_time"].ToString();
  270. item.ActualTime = item.Duration;
  271. item.Recipe = itemName;
  272. item.Chamber = dbData.Rows[i]["process_in"].ToString();
  273. item.Name = itemName;
  274. item.Type = WaferHistoryItemType.Recipe;
  275. Recipes.Add(item);
  276. result.Add(item);
  277. }
  278. }
  279. //}));
  280. return result;
  281. }
  282. public List<WaferHistoryMovement> QueryWaferMovement(string waferGuid)
  283. {
  284. List<WaferHistoryMovement> result = new List<WaferHistoryMovement>();
  285. string sql = $"SELECT * FROM \"wafer_move_history\" where \"wafer_data_guid\" = '{waferGuid}' order by \"arrive_time\" ASC limit 1000;";
  286. Movements.Clear();
  287. //Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  288. //{
  289. DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
  290. if (dbData != null && dbData.Rows.Count > 0)
  291. {
  292. for (int i = 0; i < dbData.Rows.Count - 1; i++)
  293. {
  294. WaferHistoryMovement item = new WaferHistoryMovement();
  295. item.Source = $"station : {dbData.Rows[i]["station"]} slot : {dbData.Rows[i]["slot"]}";
  296. item.Destination = $"station : {dbData.Rows[i + 1]["station"]} slot : {dbData.Rows[i + 1]["slot"]}";
  297. item.InTime = dbData.Rows[i]["arrive_time"].ToString();
  298. result.Add(item);
  299. Movements.Add(item);
  300. }
  301. }
  302. //}));
  303. return result;
  304. }
  305. public WaferHistoryRecipe QueryRecipe(string recipeGuid)
  306. {
  307. WaferHistoryRecipe result = new WaferHistoryRecipe();
  308. string sql = $"SELECT * FROM \"process_data\" where \"guid\" = '{recipeGuid}';";
  309. //Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  310. //{
  311. DataTable dbData = QueryDataClient.Instance.Service.QueryData(sql);
  312. if (dbData != null && dbData.Rows.Count > 0)
  313. {
  314. for (int i = 0; i < dbData.Rows.Count; i++)
  315. {
  316. WaferHistoryRecipe item = new WaferHistoryRecipe();
  317. item.ID = dbData.Rows[i]["guid"].ToString();
  318. var itemName = dbData.Rows[i]["recipe_name"].ToString();
  319. if (!dbData.Rows[i]["process_begin_time"].Equals(DBNull.Value))
  320. item.StartTime = (DateTime)dbData.Rows[i]["process_begin_time"];
  321. if (!dbData.Rows[i]["process_end_time"].Equals(DBNull.Value))
  322. item.EndTime = (DateTime)dbData.Rows[i]["process_end_time"];
  323. if (dbData.Rows[i].Table.Columns.Contains("recipe_setting_time") && !dbData.Rows[i]["recipe_setting_time"].Equals(DBNull.Value))
  324. item.SettingTime = dbData.Rows[i]["recipe_setting_time"].ToString();
  325. item.ActualTime = item.Duration;
  326. item.Recipe = itemName;
  327. item.Chamber = dbData.Rows[i]["process_in"].ToString();
  328. item.Name = itemName;
  329. item.Type = WaferHistoryItemType.Recipe;
  330. result = item;
  331. }
  332. }
  333. sql = $"SELECT * FROM \"recipe_step_data\" where \"process_data_guid\" = '{recipeGuid}' order by step_number ASC;";
  334. dbData = QueryDataClient.Instance.Service.QueryData(sql);
  335. List<RecipeStep> steps = new List<RecipeStep>();
  336. if (dbData != null && dbData.Rows.Count > 0)
  337. {
  338. for (int i = 0; i < dbData.Rows.Count; i++)
  339. {
  340. RecipeStep item = new RecipeStep();
  341. item.No = int.Parse(dbData.Rows[i]["step_number"].ToString());
  342. item.Name = dbData.Rows[i]["step_name"].ToString();
  343. if (!dbData.Rows[i]["step_begin_time"].Equals(DBNull.Value))
  344. item.StartTime = (DateTime)dbData.Rows[i]["step_begin_time"];
  345. if (!dbData.Rows[i]["step_end_time"].Equals(DBNull.Value))
  346. item.EndTime = (DateTime)dbData.Rows[i]["step_end_time"];
  347. item.ActualTime = item.EndTime.CompareTo(item.StartTime) <= 0 ? "" : item.EndTime.Subtract(item.StartTime).TotalSeconds.ToString();
  348. item.SettingTime = dbData.Rows[i]["step_time"].ToString();
  349. steps.Add(item);
  350. }
  351. }
  352. sql = $"SELECT * FROM \"step_fdc_data\" where \"process_data_guid\" = '{recipeGuid}' order by step_number ASC;";
  353. dbData = QueryDataClient.Instance.Service.QueryData(sql);
  354. List<RecipeStepFdcData> fdcs = new List<RecipeStepFdcData>();
  355. if (dbData != null && dbData.Rows.Count > 0)
  356. {
  357. for (int i = 0; i < dbData.Rows.Count; i++)
  358. {
  359. RecipeStepFdcData item = new RecipeStepFdcData();
  360. item.StepNumber = int.Parse(dbData.Rows[i]["step_number"].ToString());
  361. item.Name = dbData.Rows[i]["parameter_name"].ToString();
  362. if (!dbData.Rows[i]["sample_count"].Equals(DBNull.Value))
  363. item.SampleCount = (int)dbData.Rows[i]["sample_count"];
  364. if (!dbData.Rows[i]["setpoint"].Equals(DBNull.Value))
  365. item.SetPoint = (float)dbData.Rows[i]["setpoint"];
  366. if (!dbData.Rows[i]["min_value"].Equals(DBNull.Value))
  367. item.MinValue = (float)dbData.Rows[i]["min_value"];
  368. if (!dbData.Rows[i]["max_value"].Equals(DBNull.Value))
  369. item.MaxValue = (float)dbData.Rows[i]["max_value"];
  370. if (!dbData.Rows[i]["std_value"].Equals(DBNull.Value))
  371. item.StdValue = (float)dbData.Rows[i]["std_value"];
  372. if (!dbData.Rows[i]["mean_value"].Equals(DBNull.Value))
  373. item.MeanValue = (float)dbData.Rows[i]["mean_value"];
  374. fdcs.Add(item);
  375. }
  376. }
  377. result.Steps = steps;
  378. result.Fdcs = fdcs;
  379. Recipe = result;
  380. return result;
  381. }
  382. private void SelectionChanged(WaferHistoryItem item)
  383. {
  384. switch (item.Type)
  385. {
  386. case WaferHistoryItemType.Lot:
  387. QueryLotWafer(item.ID);
  388. break;
  389. case WaferHistoryItemType.Wafer:
  390. QueryWaferRecipe(item.ID);
  391. QueryWaferMovement(item.ID);
  392. break;
  393. case WaferHistoryItemType.Recipe:
  394. QueryRecipe(item.ID);
  395. break;
  396. default:
  397. break;
  398. }
  399. SelectedItem = item;
  400. }
  401. protected List<LazyTreeItem<WaferHistoryItem>> LoadSubItem(WaferHistoryItem item)
  402. {
  403. switch (item.Type)
  404. {
  405. case WaferHistoryItemType.Lot:
  406. var wafers = QueryLotWafer(item.ID);
  407. return wafers.Select(x => new LazyTreeItem<WaferHistoryItem>(x, y => LoadSubItem(y))).OrderBy(s => s.Data.StartTime).ToList();
  408. case WaferHistoryItemType.Wafer:
  409. var recipes = QueryWaferRecipe(item.ID);
  410. return recipes.Select(x => new LazyTreeItem<WaferHistoryItem>(x, y => LoadSubItem(y))).OrderBy(s => s.Data.StartTime).ToList();
  411. default:
  412. break;
  413. }
  414. return new List<LazyTreeItem<WaferHistoryItem>> { };
  415. }
  416. protected override void OnViewLoaded(object _view)
  417. {
  418. base.OnViewLoaded(_view);
  419. this.view = (WaferHistoryDBView)_view;
  420. this.view.wfTimeFrom.Value = this.SearchBeginTime;
  421. this.view.wfTimeTo.Value = this.SearchEndTime;
  422. QueryLots(new object());
  423. SelectionChanged(SelectedItem);
  424. }
  425. }
  426. public class LazyTreeItem<T> : INotifyPropertyChanged where T : ITreeItem<T>, new()
  427. {
  428. private LazyTreeItem<T> dummyChild;
  429. private T data;
  430. private Func<T, List<LazyTreeItem<T>>> loader;
  431. private LazyTreeItem()
  432. {
  433. data = new T();
  434. data.ID = Guid.NewGuid().ToString();
  435. }
  436. public LazyTreeItem(T data, Func<T, List<LazyTreeItem<T>>> loader)
  437. {
  438. this.data = data;
  439. this.loader = loader;
  440. dummyChild = new LazyTreeItem<T>();
  441. SubItems = new ObservableCollection<LazyTreeItem<T>>();
  442. SubItems.Add(dummyChild);
  443. }
  444. public T Data
  445. {
  446. get
  447. {
  448. return data;
  449. }
  450. }
  451. public ObservableCollection<LazyTreeItem<T>> SubItems
  452. {
  453. get; set;
  454. }
  455. private bool isExpanded;
  456. public event PropertyChangedEventHandler PropertyChanged;
  457. private void OnPropertyChanged(string name)
  458. {
  459. if (PropertyChanged != null)
  460. {
  461. PropertyChanged.Invoke(this, new PropertyChangedEventArgs(name));
  462. }
  463. }
  464. public bool HasDummyChild
  465. {
  466. get { return SubItems.Count == 1 && SubItems.First().data.ID == dummyChild.data.ID; }
  467. }
  468. public bool IsExpanded
  469. {
  470. get { return isExpanded; }
  471. set
  472. {
  473. if (value != isExpanded)
  474. {
  475. isExpanded = value;
  476. OnPropertyChanged("IsExpanded");
  477. }
  478. if (HasDummyChild)
  479. {
  480. SubItems.Remove(dummyChild);
  481. var items = loader(data);
  482. items.ForEachDo(x => SubItems.Add(x));
  483. }
  484. }
  485. }
  486. }
  487. }