UCPatchGrid.xaml.cs 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224
  1. using MeterVision.Config;
  2. using MeterVision.db;
  3. using MeterVision.Dlg;
  4. using MeterVision.FreeAi;
  5. using MeterVision.Helper;
  6. using MeterVision.model;
  7. using MeterVision.Util;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Collections.ObjectModel;
  11. using System.ComponentModel;
  12. using System.IO;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using System.Windows;
  18. using System.Windows.Controls;
  19. using System.Windows.Data;
  20. using System.Windows.Documents;
  21. using System.Windows.Input;
  22. using System.Windows.Media;
  23. using System.Windows.Media.Imaging;
  24. using System.Windows.Navigation;
  25. using System.Windows.Shapes;
  26. namespace MeterVision.Patch
  27. {
  28. /// <summary>
  29. /// UCPatchGrid.xaml 的交互逻辑
  30. /// </summary>
  31. public partial class UCPatchGrid : UserControl, INotifyPropertyChanged
  32. {
  33. public event PropertyChangedEventHandler PropertyChanged;
  34. protected void OnPropertyChanged(string propertyName)
  35. {
  36. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  37. }
  38. private SemaphoreSlim _loadLock = new SemaphoreSlim(1, 1);
  39. private bool _isLoading = false;
  40. //定义任务详情数据源
  41. public BulkObservableCollection<PatchDetailItem> PatchDetailItemList { get; set; }
  42. // 定义事件,用于通知外部组件选中项已更改
  43. public event EventHandler<PatchDetailItemChangedEventArgs> OnSelectedPatchDetailItemChanged;
  44. public event Action<string> OnRefreshPatchItem;
  45. //删除标准模板明细事件
  46. public static event Action<string> OnDeleteStandDetail;
  47. //修改标准模板值事件
  48. public static event Action<string,string> OnUpdateStandValue;
  49. private PatchDetailItem _selectedPatchDetailItem;
  50. //定义SelectedDataItem属性,并在值变化时触发事件
  51. public PatchDetailItem SelectedPatchDetailItem
  52. {
  53. get => _selectedPatchDetailItem;
  54. set
  55. {
  56. if (_selectedPatchDetailItem != value)
  57. {
  58. _selectedPatchDetailItem = value;
  59. OnPropertyChanged(nameof(SelectedPatchDetailItem));
  60. OnSelectedPatchDetailItemChanged?.Invoke(this, new PatchDetailItemChangedEventArgs(value));
  61. }
  62. }
  63. }
  64. private PatchItem _curPatchItem;
  65. private PatchItem CurPatchItem
  66. {
  67. get => _curPatchItem;
  68. set
  69. {
  70. if (_curPatchItem != value)
  71. {
  72. _curPatchItem = value;
  73. //PatchDetailPage.InitDefaulValue(mConfigItem.PatchPageSize);
  74. //PatchDetailPage.InitDefaulValue();
  75. //LoadPatchDetailItemList();
  76. }
  77. }
  78. }
  79. //此属性只在函数内部调用
  80. private VPatchStation _curStationItem;
  81. private VPatchStation CurStationItem
  82. {
  83. get => _curStationItem;
  84. set
  85. {
  86. if (_curStationItem != value)
  87. {
  88. _curStationItem = value;
  89. //PatchDetailPage.InitDefaulValue(mConfigItem.StandPageSize);
  90. //LoadStandDetailItemList();
  91. }
  92. }
  93. }
  94. private PatchFindType _selectedPatchFindType;
  95. private PatchFindType SelectedPatchFindType
  96. {
  97. get => _selectedPatchFindType;
  98. set
  99. {
  100. if (_selectedPatchFindType != value)
  101. {
  102. _selectedPatchFindType = value;
  103. //OnPropertyChanged(nameof(SelectedPatchFindType));
  104. //PatchDetailPage.InitDefaulValue();
  105. }
  106. }
  107. }
  108. //改变PatchItem或PatchFinType
  109. public void ChangePatchItemOrFinType(PatchItem curPatchItem,VPatchStation curStationItem,PatchFindType patchFindType)
  110. {
  111. //bool blPatchItemChanged = false;
  112. //bool blPatchFindTypeChanged = false;
  113. //bool blStationChanged = false;
  114. //判断是否数据发生变化
  115. if(curPatchItem != _curPatchItem)
  116. {
  117. CurPatchItem = curPatchItem;
  118. //blPatchItemChanged = true;
  119. }
  120. if(curStationItem != _curStationItem)
  121. {
  122. CurStationItem = curStationItem;
  123. //blStationChanged = true;
  124. }
  125. if(patchFindType != _selectedPatchFindType)
  126. {
  127. SelectedPatchFindType = patchFindType;
  128. //blPatchFindTypeChanged = true;
  129. }
  130. //if(blPatchItemChanged || blPatchFindTypeChanged || blStationChanged)
  131. {
  132. PatchDetailPage.InitDefaulValue();
  133. LoadPatchDetailItemList(true);
  134. }
  135. }
  136. public CfginiItem mConfigItem { get; set; }
  137. public PageModel PatchDetailPage { get; set; }
  138. private int _totalRecord;
  139. public int TotalRecords
  140. {
  141. get => _totalRecord;
  142. set
  143. {
  144. if (_totalRecord != value)
  145. {
  146. _totalRecord = value;
  147. OnPropertyChanged(nameof(TotalRecords));
  148. }
  149. }
  150. }
  151. public UCPatchGrid()
  152. {
  153. InitializeComponent();
  154. PatchDetailItemList = new BulkObservableCollection<PatchDetailItem>();
  155. dgPatchDetail.ItemsSource = PatchDetailItemList;
  156. mConfigItem = CfginiItem.GetConfigItem();
  157. PatchDetailPage = new PageModel
  158. {
  159. PageSize = mConfigItem.PageSize3, //mConfigItem.PatchPageSize,
  160. PageNumber = 1
  161. };
  162. //mConfigItem.OnPatchPageSizeChanged += MConfigItem_OnPatchPageSizeChanged;
  163. //mConfigItem.OnPatchPageSizeChanged += MConfigItem_OnPatchPageSizeChanged;
  164. mConfigItem.OnPageSize3Changed += MConfigItem_OnPageSize3Changed;
  165. this.DataContext = this;
  166. }
  167. private void MConfigItem_OnPageSize3Changed(int pageSize3)
  168. {
  169. if (_isLoading) return;
  170. try
  171. {
  172. _isLoading = true;
  173. //throw new NotImplementedException();
  174. PatchDetailPage.InitDefaulValue(pageSize3);
  175. LoadPatchDetailItemList(true);
  176. }
  177. catch { }
  178. finally
  179. {
  180. _isLoading = false;
  181. }
  182. }
  183. //private void MConfigItem_OnPatchPageSizeChanged(int pageSize)
  184. //{
  185. // PatchDetailPage.InitDefaulValue(pageSize);
  186. // LoadPatchDetailItemList(true);
  187. //}
  188. //private void MConfigItem_OnPatchPageSizeChanged(object sender, PageSizeChangedEventArgs e)
  189. //{
  190. // PatchDetailPage.InitDefaulValue(e.PageSize);
  191. // LoadPatchDetailItemList(true);
  192. //}
  193. private async void LoadPatchDetailItemList(bool scrollTop)
  194. {
  195. if (!await _loadLock.WaitAsync(0)) return; // 如果已有任务在执行,则直接返回
  196. try
  197. {
  198. PatchDetailItemList.Clear();
  199. //if (CurPatchItem != null )
  200. if (CurStationItem != null)
  201. {
  202. try
  203. {
  204. var result = await Task.Run(() =>
  205. {
  206. //数据库查询
  207. //return DBPatch.GetPagedPatchDetails(
  208. // PatchDetailPage.PageNumber, PatchDetailPage.PageSize, CurPatchItem.PatchId);
  209. string stationId = CurStationItem == null ? "" : CurStationItem.StationId;
  210. PatchFindModel findModel = new PatchFindModel(PatchDetailPage.PageNumber, PatchDetailPage.PageSize,
  211. CurPatchItem.PatchId, stationId, SelectedPatchFindType);
  212. return DBPatch.GetPagedPatchDetails(findModel);
  213. });
  214. //var result = DBPatch.GetPagedPatchDetails(findModel);
  215. //更新分页信息
  216. TotalRecords = result.Item1;
  217. PatchDetailPage.PageCount = result.Item2;
  218. List<TPatchDetail> patchDetails = result.Item3;
  219. //更新数据需要在主线中进行
  220. //await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  221. //{
  222. //int index = 0;
  223. //foreach (TPatchDetail patchDetail in patchDetails)
  224. //{
  225. // index++;
  226. // PatchDetailItem item = new PatchDetailItem(patchDetail);
  227. // item.Index = index + ((PatchDetailPage.PageNumber - 1) * PatchDetailPage.PageSize);
  228. // PatchDetailItemList.Add(item);
  229. //}//foreach
  230. var patchDetailItems = patchDetails.Select((patchDetail, i) => new PatchDetailItem(patchDetail)
  231. {
  232. Index = (PatchDetailPage.PageNumber - 1) * PatchDetailPage.PageSize + i + 1
  233. }).ToList();
  234. PatchDetailItemList.AddRange(patchDetailItems);
  235. //SelectedPatchDetailItem = null;
  236. if (PatchDetailItemList.Count > 0 && scrollTop)
  237. {
  238. //await Task.Delay(50);
  239. //dgPatchDetail.UpdateLayout();
  240. //await Task.Yield();
  241. //await Dispatcher.InvokeAsync(() =>
  242. //{
  243. // dgPatchDetail.ScrollIntoView(dgPatchDetail.Items[0]);
  244. //});
  245. var scrollViewer = GetScrollViewer(dgPatchDetail);
  246. scrollViewer?.ScrollToTop();
  247. }
  248. ///}));
  249. }
  250. catch (Exception ex)
  251. {
  252. MessageBox.Show(Application.Current.MainWindow,
  253. $"d加载数据时发生错误:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  254. //return false;
  255. }
  256. }
  257. //if (PatchDetailItemList.Count > 0)
  258. //{
  259. // SelectedPatchDetailItem = PatchDetailItemList[0];
  260. //}
  261. //else
  262. //{
  263. // SelectedPatchDetailItem = null;
  264. //}
  265. }
  266. catch { }
  267. finally
  268. {
  269. _loadLock.Release();
  270. }
  271. }
  272. private void StandResultTextBlock_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  273. {
  274. // 检查是否是双击
  275. if (e.ClickCount == 2)
  276. {
  277. // 获取当前行的数据上下文
  278. var textBlock = sender as TextBlock;
  279. if (textBlock == null) return;
  280. var dataContext = textBlock.DataContext as PatchDetailItem; // 替换为你的数据类型
  281. if (dataContext == null) return;
  282. SelectedPatchDetailItem = dataContext;
  283. StandValueModel standValueModel = new StandValueModel(dataContext);
  284. var dialog = new EditStandValueDlg(standValueModel)
  285. {
  286. Owner = Application.Current.MainWindow,
  287. WindowStartupLocation = WindowStartupLocation.CenterOwner
  288. };
  289. //if(dialog.ShowDialog() == true)
  290. //{
  291. // UpdatePatchDetailStandValue(dataContext, standValueModel);
  292. //}//if showDialog
  293. dialog.OnEditStandValue += (value) =>
  294. {
  295. UpdatePatchDetailStandValue(dataContext, standValueModel);
  296. };
  297. dialog.Show();
  298. }//e.clickCount
  299. }
  300. private void UpdateStandvalue(PatchDetailItem detailItem)
  301. {
  302. StandValueModel standValueModel = new StandValueModel(detailItem);
  303. var dialog = new EditStandValueDlg(standValueModel)
  304. {
  305. Owner = Application.Current.MainWindow,
  306. WindowStartupLocation = WindowStartupLocation.CenterOwner
  307. };
  308. //if (dialog.ShowDialog() == true)
  309. //{
  310. // UpdatePatchDetailStandValue(detailItem, standValueModel);
  311. //}//if showDialog
  312. dialog.OnEditStandValue += (value) =>
  313. {
  314. UpdatePatchDetailStandValue(detailItem, standValueModel);
  315. };
  316. dialog.Show();
  317. }
  318. private void UpdatePatchDetailStandValue(PatchDetailItem detailItem, StandValueModel standValueModel)
  319. {
  320. try
  321. {
  322. //修改数据库
  323. //判断detailItem中的FinalValue与标准值是否相等
  324. int equalFlag = 0;
  325. if (string.IsNullOrWhiteSpace(standValueModel.StandValue))
  326. {
  327. equalFlag = 3;
  328. }
  329. else
  330. {
  331. if (double.TryParse(standValueModel.StandValue, out double dStandValue))
  332. {
  333. equalFlag = detailItem.GetEqualFlag(dStandValue, detailItem.FinalValue);
  334. }
  335. }
  336. bool updateStandValue1 = DBPatch.UpdatePatchDetailStandValue(detailItem.PatchDetailId, standValueModel.StandValue,equalFlag);
  337. bool updateStandValue2 = DBStand.UpdateStandDetailStandValue(detailItem.SrcImage, standValueModel.StandValue);
  338. if (updateStandValue1 && updateStandValue2)
  339. {
  340. detailItem.StandValue = standValueModel.StandValue;
  341. detailItem.EqualFlag = equalFlag;
  342. //MessageBox.Show(Application.Current.MainWindow, "修改标准值完成。", "提示", MessageBoxButton.OK,
  343. // MessageBoxImage.Information);
  344. //应该更新目录内容
  345. OnRefreshPatchItem?.Invoke(detailItem.PatchId);
  346. OnUpdateStandValue?.Invoke(detailItem.StandDetailId, detailItem.StandValue);
  347. }
  348. else
  349. {
  350. MessageBox.Show(Application.Current.MainWindow, "修改标准值失败。", "警告", MessageBoxButton.OK,
  351. MessageBoxImage.Warning);
  352. }
  353. }
  354. catch (Exception ex)
  355. {
  356. MessageBox.Show(Application.Current.MainWindow, $"修改标准值错误:{ex.Message}!", "警告", MessageBoxButton.OK,
  357. MessageBoxImage.Warning);
  358. }
  359. }
  360. private void SrcImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  361. {
  362. var image = sender as Image;
  363. if (image == null) return;
  364. var dataContext = image.DataContext as PatchDetailItem;
  365. if (dataContext == null) return;
  366. //var dialog = new ImageViewerWindow(dataContext.SourceImagePath)
  367. if (!File.Exists(dataContext.SrcImage)) return;
  368. var dialog = new imgWindow(dataContext.SrcImage)
  369. {
  370. Owner = Application.Current.MainWindow
  371. };
  372. dialog.Show();
  373. }
  374. private void DstImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  375. {
  376. var image = sender as Image;
  377. if (image == null) return;
  378. var dataContext = image.DataContext as PatchDetailItem;
  379. if (dataContext == null) return;
  380. //var dialog = new ImageViewerWindow(dataContext.SourceImagePath)
  381. if (!File.Exists(dataContext.DstImage)) return;
  382. var dialog = new imgWindow(dataContext.DstImage)
  383. {
  384. Owner = Application.Current.MainWindow
  385. };
  386. dialog.Show();
  387. }
  388. public void NextPage()
  389. {
  390. //if (!await _loadLock.WaitAsync(0)) return; // 如果已有任务在执行,则直接返回
  391. if (_isLoading) return; // 如果正在加载,直接返回
  392. try
  393. {
  394. _isLoading = true;
  395. if (PatchDetailPage.PageNumber < PatchDetailPage.PageCount)
  396. {
  397. PatchDetailPage.PageNumber += 1;
  398. LoadPatchDetailItemList(true);
  399. }
  400. }
  401. catch { }
  402. finally
  403. {
  404. _isLoading = false;
  405. }
  406. }
  407. public void PrePage()
  408. {
  409. if (_isLoading) return; // 如果正在加载,直接返回
  410. try
  411. {
  412. _isLoading = true;
  413. if (PatchDetailPage.PageNumber > 1)
  414. {
  415. PatchDetailPage.PageNumber -= 1;
  416. LoadPatchDetailItemList(true);
  417. }
  418. }
  419. catch { }
  420. finally
  421. {
  422. _isLoading = false;
  423. }
  424. }
  425. public void FirstPage()
  426. {
  427. if (_isLoading) return; // 如果正在加载,直接返回
  428. try
  429. {
  430. _isLoading = true;
  431. if (PatchDetailPage.PageNumber > 1)
  432. {
  433. PatchDetailPage.PageNumber = 1;
  434. LoadPatchDetailItemList(true);
  435. }
  436. }
  437. catch { }
  438. finally
  439. {
  440. _isLoading = false;
  441. }
  442. }
  443. public void LastPage()
  444. {
  445. if (_isLoading) return; // 如果正在加载,直接返回
  446. try
  447. {
  448. _isLoading = true;
  449. if (PatchDetailPage.PageNumber < PatchDetailPage.PageCount)
  450. {
  451. PatchDetailPage.PageNumber = PatchDetailPage.PageCount;
  452. LoadPatchDetailItemList(true);
  453. }
  454. }
  455. catch { }
  456. finally
  457. {
  458. _isLoading = false;
  459. }
  460. }
  461. public void SpeciPage(int pageNumber)
  462. {
  463. if (_isLoading) return; // 如果正在加载,直接返回
  464. try
  465. {
  466. _isLoading = true;
  467. if (pageNumber != PatchDetailPage.PageNumber &&
  468. pageNumber > 0 && pageNumber <= PatchDetailPage.PageCount)
  469. {
  470. PatchDetailPage.PageNumber = pageNumber;
  471. LoadPatchDetailItemList(true);
  472. }
  473. }
  474. catch { }
  475. finally
  476. {
  477. _isLoading = false;
  478. }
  479. }
  480. private bool IsProcessingTask = false;
  481. public async Task<bool> StartPatchTask()
  482. {
  483. if (CurPatchItem == null) return false;
  484. int taskCount = await GetTaskCount();
  485. if(taskCount == 0)
  486. {
  487. MessageBox.Show(Application.Current.MainWindow, "没有任务可执行。", "提示",
  488. MessageBoxButton.OK, MessageBoxImage.Information);
  489. return false;
  490. }
  491. //先查询是否有需要识别的任务
  492. PatchTaskDlg patchTaskDlg = new PatchTaskDlg()
  493. {
  494. Owner = Application.Current.MainWindow,
  495. WindowStartupLocation = WindowStartupLocation.CenterOwner
  496. };
  497. patchTaskDlg.OnStopTask += PatchTaskDlg_OnStopTask;
  498. patchTaskDlg.Show();
  499. Application.Current.MainWindow.IsEnabled = false;
  500. try
  501. {
  502. IsProcessingTask = true;
  503. int runCount = 0;
  504. await Task.Run(() =>
  505. {
  506. string stationId = CurStationItem == null ? "" : CurStationItem.StationId;
  507. //查询任务
  508. List<TPatchDetail> patchDetails = DBPatch.GetPatchDetailsWithRunFlag(CurPatchItem.PatchId,stationId,0);
  509. for(int i = 0; i < patchDetails.Count; i++)
  510. {
  511. if (!IsProcessingTask)
  512. {
  513. return;
  514. }
  515. FaRun faRun = new FaRun();
  516. faRun.OnAiRealLogInfo += (sender,e) =>
  517. {
  518. Console.WriteLine(e.mLogInfo);
  519. };
  520. ResultModel resultModel = null;
  521. try
  522. {
  523. resultModel = faRun.StartRecognition(patchDetails[i]);
  524. }
  525. catch(Exception ex)
  526. {
  527. Console.WriteLine(ex.Message);
  528. }
  529. if (resultModel == null) continue;
  530. patchDetails[i].SetResult(resultModel);
  531. bool blUpdate = DBPatch.UpdatePatchDetailWithResult(patchDetails[i]);
  532. //修改下一条记录的最近一次正确值(判断下一条数据的站点与本站点相同)
  533. if( i + 1 < patchDetails.Count && patchDetails[i + 1].StationId == patchDetails[i].StationId)
  534. {
  535. if (patchDetails[i + 1].LatestValue == -1)
  536. {
  537. patchDetails[i + 1].LastCompress = resultModel.CompressIndex;
  538. if (patchDetails[i].IsGoodResult())
  539. {
  540. patchDetails[i + 1].LatestValue = (long)resultModel.FinalValue;
  541. patchDetails[i + 1].LatestComplete = (long)resultModel.CompleteValue;
  542. patchDetails[i + 1].LatestTime = patchDetails[i].SampleTime;
  543. }
  544. else
  545. {
  546. patchDetails[i + 1].LatestValue = patchDetails[i].LatestValue;
  547. patchDetails[i + 1].LatestComplete = patchDetails[i].LatestComplete;
  548. patchDetails[i + 1].LatestTime = patchDetails[i].LatestTime;
  549. }
  550. }
  551. //根据当前的识别结果修改下一条的表盘、数字域或首尾坐标域
  552. if(string.IsNullOrEmpty(patchDetails[i + 1].MeterRegion) &&
  553. patchDetails[i+1].MeterType == patchDetails[i].MeterType)
  554. {
  555. patchDetails[i + 1].MeterRegion = resultModel.MeterRegions;
  556. patchDetails[i + 1].FeatureRegion = resultModel.FeatureRegions;
  557. }
  558. //更新改变了Latest的数据
  559. if (DBPatch.UpdatePatchDetails_Latest(patchDetails[i + 1]))
  560. {
  561. foreach (PatchDetailItem detailItem in PatchDetailItemList)
  562. {
  563. if (detailItem.PatchDetailId == patchDetails[i + 1].PatchDetailId)
  564. {
  565. ObjectHelper.CopyMatchingFields(patchDetails[i + 1], detailItem);
  566. break;
  567. }
  568. }//foreach
  569. }
  570. }//i+1
  571. if (blUpdate)
  572. {
  573. runCount++;
  574. }
  575. //根据结果更新表内容,暂且模拟
  576. //Thread.Sleep(300);
  577. //这里需要同步
  578. //Application.Current.Dispatcher.Invoke(() =>
  579. //{
  580. patchTaskDlg.UpdateProgress(i + 1, taskCount);
  581. ////更新背后的数据
  582. if (blUpdate)
  583. {
  584. //如果界面中存在本条数据,则更新。意义不大
  585. foreach (PatchDetailItem detailItem in PatchDetailItemList)
  586. {
  587. if (detailItem.PatchDetailId == patchDetails[i].PatchDetailId)
  588. {
  589. ObjectHelper.CopyMatchingFields(patchDetails[i], detailItem);
  590. break;
  591. }
  592. }//foreach
  593. }//if
  594. //});
  595. //Thread.Sleep(3000);
  596. }//for i
  597. });
  598. return runCount > 0;
  599. }
  600. catch(Exception ex)
  601. {
  602. MessageBox.Show(Application.Current.MainWindow, $"执行批量识别任务:{ex.Message}", "错误",
  603. MessageBoxButton.OK, MessageBoxImage.Error);
  604. return false;
  605. }
  606. finally
  607. {
  608. // 执行完毕后恢复主界面交互
  609. Application.Current.MainWindow.IsEnabled = true;
  610. patchTaskDlg.Close();
  611. }
  612. }
  613. //如果是存在已执行的任务,恢复未执行任务的数据状态
  614. public async Task<bool> ResetPatchTask()
  615. {
  616. if (CurPatchItem == null) return false;
  617. string titleInfo = "正在恢复为任务未执行的状态,请稍后...";
  618. WaitWindow waitWindow = new WaitWindow(titleInfo)
  619. {
  620. Owner = Application.Current.MainWindow,
  621. WindowStartupLocation = WindowStartupLocation.CenterOwner
  622. };
  623. waitWindow.Show();
  624. try
  625. {
  626. List<TPatchDetail> patchDetails = null;
  627. bool blUpdate = false;
  628. await Task.Run(() =>
  629. {
  630. string stationId = CurStationItem == null ? "" : CurStationItem.StationId;
  631. //查询数据
  632. //patchDetails = DBPatch.GetPatchDetailsWithRunFlag(CurPatchItem.PatchId, stationId,1);
  633. patchDetails = DBPatch.GetPatchDetailsWithRunFlag_StandDetal(CurPatchItem.PatchId, stationId, 1);
  634. foreach (var patchDetail in patchDetails)
  635. {
  636. //删除目标图像及识别日志
  637. try
  638. {
  639. if (File.Exists(patchDetail.DstImage))
  640. {
  641. File.Delete(patchDetail.DstImage);
  642. }
  643. if (File.Exists(patchDetail.LogPath))
  644. {
  645. File.Delete(patchDetail.LogPath);
  646. }
  647. }
  648. catch
  649. {
  650. }
  651. patchDetail.ResetRunValue(); //恢复初始值
  652. //查找原始t_stand_detail中表盘等坐标
  653. }
  654. if (patchDetails.Count > 0)
  655. {
  656. blUpdate = DBPatch.UpdatePatchDetails(patchDetails);
  657. }
  658. });
  659. if (blUpdate && patchDetails != null)
  660. {
  661. foreach (PatchDetailItem detailItem in PatchDetailItemList)
  662. {
  663. var findItem = patchDetails.Find((a) => a.PatchDetailId == detailItem.PatchDetailId);
  664. if(findItem!= null)
  665. {
  666. ObjectHelper.CopyMatchingFields(findItem, detailItem);
  667. }
  668. }//foreach
  669. }
  670. return true;
  671. }
  672. catch(Exception ex)
  673. {
  674. MessageBox.Show(Application.Current.MainWindow, $"失败:{ex.Message}", "错误",
  675. MessageBoxButton.OK, MessageBoxImage.Error);
  676. return false;
  677. }
  678. finally
  679. {
  680. waitWindow.Close();
  681. }
  682. }
  683. private void PatchTaskDlg_OnStopTask()
  684. {
  685. IsProcessingTask = false;
  686. //throw new NotImplementedException();
  687. }
  688. //获取任务数量
  689. private async Task<int> GetTaskCount()
  690. {
  691. if (CurPatchItem == null) return 0;
  692. string titleInfo = "正在获取任务数量,请稍后...";
  693. WaitWindow waitWindow = new WaitWindow(titleInfo)
  694. {
  695. Owner = Application.Current.MainWindow,
  696. WindowStartupLocation = WindowStartupLocation.CenterOwner
  697. };
  698. waitWindow.Show();
  699. try
  700. {
  701. int taskCount = await Task.Run(() =>
  702. {
  703. string stationId = CurStationItem == null ? "" : CurStationItem.StationId;
  704. return DBPatch.GetPatchDetailsCountWithRunFlagZero(CurPatchItem.PatchId,stationId);
  705. });
  706. return taskCount;
  707. }
  708. catch (Exception ex)
  709. {
  710. MessageBox.Show(Application.Current.MainWindow, $"获取任务数量:{ex.Message}", "错误",
  711. MessageBoxButton.OK, MessageBoxImage.Error);
  712. return 0;
  713. }
  714. finally
  715. {
  716. waitWindow.Close();
  717. }
  718. }
  719. private void BtnLogViewer_Click(object sender, RoutedEventArgs e)
  720. {
  721. Button button = sender as Button;
  722. if (button == null) return;
  723. DataGridRow row = FindAncestor<DataGridRow>(button);
  724. if (row == null) return;
  725. //获取当前行绑定的数据项
  726. PatchDetailItem selectedItem = row.Item as PatchDetailItem;
  727. ShowLogViewer(selectedItem);
  728. }
  729. private void ShowLogViewer(PatchDetailItem selectedItem)
  730. {
  731. if (selectedItem.LogPath != null && File.Exists(selectedItem.LogPath))
  732. {
  733. //LogViewerWindow dialog = new LogViewerWindow(selectedItem.DstImage, selectedItem.LogPath)
  734. var dialog = new LogViewerWindow(selectedItem)
  735. {
  736. Owner = Application.Current.MainWindow,
  737. WindowStartupLocation = WindowStartupLocation.CenterOwner
  738. };
  739. //dialog.ShowDialog();
  740. dialog.Show();
  741. }
  742. }
  743. private void BtnDelDetailItem_Click(object sender, RoutedEventArgs e)
  744. {
  745. //删除选中项
  746. Button button = sender as Button;
  747. if (button == null) return;
  748. DataGridRow row = FindAncestor<DataGridRow>(button);
  749. if (row == null) return;
  750. //获取当前行绑定的数据项
  751. PatchDetailItem selectedItem = row.Item as PatchDetailItem;
  752. DeleteSelectedItem(selectedItem);
  753. }
  754. private async void DeleteSelectedItem(PatchDetailItem selectedItem)
  755. {
  756. if (selectedItem == null) return;
  757. MessageBoxResult result = MessageBox.Show("确定要删除此条目吗?", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Question);
  758. if (result != MessageBoxResult.Yes) return;
  759. string titleInfo = "正在删除,请稍后...";
  760. WaitWindow waitWindow = new WaitWindow(titleInfo)
  761. {
  762. Owner = Application.Current.MainWindow,
  763. WindowStartupLocation = WindowStartupLocation.CenterOwner
  764. };
  765. waitWindow.Show();
  766. try
  767. {
  768. bool deleteSuccess = false;
  769. await Task.Run(() =>
  770. {
  771. deleteSuccess = DBPatch.Delete_TPatchDetail_TStandDetail_ByStand(selectedItem.StandDetailId);
  772. //deleteSuccess = DBPatch.DeleteTPatchDetailById(selectedItem.PatchDetailId);
  773. });
  774. if (deleteSuccess)
  775. {
  776. //Application.Current.Dispatcher.Invoke(() =>
  777. //{
  778. // 从数据源中移除该条目
  779. int selectedIndex = PatchDetailItemList.IndexOf(selectedItem);
  780. //PatchDetailItemList.Remove(selectedItem); 改为从新加载页面
  781. SelectedPatchDetailItem = null;
  782. OnRefreshPatchItem?.Invoke(selectedItem.PatchId);
  783. OnDeleteStandDetail?.Invoke(selectedItem.StandDetailId);
  784. //重新加载数据
  785. LoadPatchDetailItemList(false);
  786. //if (PatchDetailItemList.Count > selectedIndex)
  787. //{
  788. // dgPatchDetail.ScrollIntoView(dgPatchDetail.Items[selectedIndex]);
  789. //}
  790. //});
  791. }
  792. }
  793. catch (Exception ex)
  794. {
  795. MessageBox.Show(Application.Current.MainWindow, $"删除失败:{ex.Message}", "错误",
  796. MessageBoxButton.OK, MessageBoxImage.Error);
  797. }
  798. finally
  799. {
  800. waitWindow.Close();
  801. }
  802. }
  803. public static T FindAncestor<T>(DependencyObject dependencyObject) where T : DependencyObject
  804. {
  805. var parent = VisualTreeHelper.GetParent(dependencyObject);
  806. if (parent == null) return null;
  807. var parentT = parent as T;
  808. return parentT ?? FindAncestor<T>(parent);
  809. }
  810. private void MiViewLog_Click(object sender, RoutedEventArgs e)
  811. {
  812. if(SelectedPatchDetailItem != null)
  813. {
  814. ShowLogViewer(SelectedPatchDetailItem);
  815. }
  816. }
  817. private void MiDelteRow_Click(object sender, RoutedEventArgs e)
  818. {
  819. //获取当前行绑定的数据项
  820. if(SelectedPatchDetailItem != null)
  821. {
  822. DeleteSelectedItem(SelectedPatchDetailItem);
  823. }
  824. }
  825. private void BtnUpdateStandvalue_Click(object sender, RoutedEventArgs e)
  826. {
  827. Button button = sender as Button;
  828. if (button == null) return;
  829. DataGridRow row = FindAncestor<DataGridRow>(button);
  830. if (row == null) return;
  831. //获取当前行绑定的数据项
  832. var selectedItem = row.Item as PatchDetailItem;
  833. UpdateStandvalue(selectedItem);
  834. }
  835. private void MiUpdateStandvalue_Click(object sender, RoutedEventArgs e)
  836. {
  837. if (SelectedPatchDetailItem == null) return;
  838. UpdateStandvalue(SelectedPatchDetailItem);
  839. }
  840. private void MiAddMemo_Click(object sender, RoutedEventArgs e)
  841. {
  842. if (SelectedPatchDetailItem == null) return;
  843. AddMemo(SelectedPatchDetailItem);
  844. }
  845. private void AddMemo(PatchDetailItem detailItem)
  846. {
  847. if (detailItem == null) return;
  848. EditMemo editMemo = new EditMemo(detailItem.Memo)
  849. {
  850. Owner = Application.Current.MainWindow,
  851. WindowStartupLocation = WindowStartupLocation.CenterOwner
  852. };
  853. if (editMemo.ShowDialog() == true)
  854. {
  855. string memo = editMemo.Memo;
  856. if (DBPatch.UpdatePatchDetailMemo(detailItem.PatchDetailId, memo))
  857. {
  858. detailItem.Memo = memo;
  859. }
  860. }
  861. }
  862. private void Memo_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  863. {
  864. if (e.ClickCount == 2)
  865. {
  866. if (SelectedPatchDetailItem == null) return;
  867. AddMemo(SelectedPatchDetailItem);
  868. }
  869. }
  870. private void FaRun_OnAiRealLogInfo(object sender, AiRealLogEventArgs e)
  871. {
  872. Console.Write(e.mLogInfo);
  873. }
  874. private void MiRecong_Click(object sender, RoutedEventArgs e)
  875. {
  876. if (SelectedPatchDetailItem == null) return;
  877. RecongPatchDetail(SelectedPatchDetailItem);
  878. }
  879. private async void RecongPatchDetail(PatchDetailItem patchDetailItem)
  880. {
  881. string jpgFile = patchDetailItem.SrcImage;
  882. if (!File.Exists(jpgFile))
  883. {
  884. MessageBox.Show(Application.Current.MainWindow, $"文件:{jpgFile}不存在!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
  885. return;
  886. }
  887. bool blRun = await RunAI(patchDetailItem);
  888. if (blRun)
  889. {
  890. //MessageBox.Show(Application.Current.MainWindow, "识别成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
  891. }
  892. else
  893. {
  894. MessageBox.Show(Application.Current.MainWindow, "识别失败!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  895. }
  896. }
  897. private async Task<bool> RunAI(PatchDetailItem patchDetailItem)
  898. {
  899. FaRun faRun = new FaRun();
  900. faRun.OnAiRealLogInfo += FaRun_OnAiRealLogInfo;
  901. string titleInfo = "正在识别,请稍后...";
  902. WaitWindow waitWindow = new WaitWindow(titleInfo)
  903. {
  904. Owner = Application.Current.MainWindow,
  905. WindowStartupLocation = WindowStartupLocation.CenterOwner
  906. };
  907. waitWindow.Show();
  908. try
  909. {
  910. TPatchDetail newPatchDetail = null;
  911. bool blRun = await Task.Run(() =>
  912. {
  913. try
  914. {
  915. ResultModel resultModel = null;
  916. try
  917. {
  918. resultModel = faRun.StartRecognition(patchDetailItem);
  919. }
  920. catch (Exception ex)
  921. {
  922. Console.WriteLine(ex.Message);
  923. }
  924. if (resultModel == null) return false;
  925. newPatchDetail = new TPatchDetail(patchDetailItem, resultModel);
  926. //更新数据
  927. bool blUpdate = DBPatch.UpdatePatchDetailWithResult(newPatchDetail);
  928. return blUpdate;
  929. }
  930. catch (Exception ex)
  931. {
  932. Dispatcher.Invoke(() =>
  933. {
  934. MessageBox.Show(Application.Current.MainWindow, $"{ex.Message}", "错误",
  935. MessageBoxButton.OK, MessageBoxImage.Error);
  936. });
  937. return false;
  938. }
  939. });
  940. //------
  941. //在主线程中更新DataGrid的Row数据
  942. if (blRun && newPatchDetail != null)
  943. {
  944. ObjectHelper.CopyMatchingFields(newPatchDetail, patchDetailItem);
  945. }
  946. return blRun;
  947. }
  948. catch (Exception ex)
  949. {
  950. MessageBox.Show(Application.Current.MainWindow, $"识别[{patchDetailItem.SrcImage}]时出错:{ex.Message}", "错误",
  951. MessageBoxButton.OK, MessageBoxImage.Error);
  952. return false;
  953. }
  954. finally
  955. {
  956. waitWindow.Close();
  957. }
  958. }
  959. private ScrollViewer _scrollViewer;
  960. private ScrollViewer GetScrollViewer(DependencyObject obj)
  961. {
  962. if(_scrollViewer != null)
  963. {
  964. return _scrollViewer;
  965. }
  966. if (obj is ScrollViewer)
  967. {
  968. _scrollViewer = (ScrollViewer)obj;
  969. return obj as ScrollViewer;
  970. }
  971. for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
  972. {
  973. var child = VisualTreeHelper.GetChild(obj, i);
  974. var scrollViewer = GetScrollViewer(child);
  975. if (scrollViewer != null)
  976. {
  977. _scrollViewer = scrollViewer;
  978. return scrollViewer;
  979. }
  980. }
  981. return null;
  982. }
  983. ////-------------以下代码被作废,暂不使用此方法-------------------
  984. //private PatchPrgDialog PatchPrgDialog; // 用于弹出进度对话框
  985. //public event Action<int,int> OnProcessingProgressChanged; // 用于通知进度
  986. //public event Action OnProcessingCompleted; // 用于通知完成
  987. //public event Action OnProcessingStopped; // 用于通知停止
  988. //private BackgroundWorker worker;
  989. ////private bool isProcessing;
  990. //private bool cancelRequested;
  991. //private int TotalImages;
  992. ////开始批量识别任务
  993. //public void StartPatchTask2()
  994. //{
  995. // worker = new BackgroundWorker();
  996. // worker.DoWork += Worker_DoWork;
  997. // worker.RunWorkerCompleted += Worker_RunWorkerCompleted;
  998. // worker.ProgressChanged += Worker_ProgressChanged;
  999. // worker.WorkerReportsProgress = true;
  1000. // worker.WorkerSupportsCancellation = true;
  1001. // PatchPrgDialog = new PatchPrgDialog(this); // 传递 UserControl 实例给对话框
  1002. // PatchPrgDialog.StartProcessing();
  1003. //}
  1004. //// 启动处理
  1005. //public void StartProcessing()
  1006. //{
  1007. // //isProcessing = true;
  1008. // cancelRequested = false;
  1009. // worker.RunWorkerAsync();
  1010. //}
  1011. //// 停止处理
  1012. //public void StopProcessing()
  1013. //{
  1014. // cancelRequested = true;
  1015. // worker.CancelAsync();
  1016. //}
  1017. //// 执行后台处理任务
  1018. //private void Worker_DoWork(object sender, DoWorkEventArgs e)
  1019. //{
  1020. // //int totalImages = 100; // 假设有100张图片要处理
  1021. // TotalImages = 100;
  1022. // for (int i = 1; i <= TotalImages; i++)
  1023. // {
  1024. // if (cancelRequested)
  1025. // {
  1026. // e.Cancel = true;
  1027. // break;
  1028. // }
  1029. // // 模拟处理图片
  1030. // Thread.Sleep(1000); // 这里模拟了图片处理的延迟
  1031. // // 更新进度
  1032. // //worker.ReportProgress((i * 100) / totalImages);
  1033. // worker.ReportProgress(i);
  1034. // }
  1035. //}
  1036. //// 更新进度条
  1037. //private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
  1038. //{
  1039. // //progressBar.Value = e.ProgressPercentage;
  1040. // OnProcessingProgressChanged?.Invoke(e.ProgressPercentage,TotalImages);
  1041. //}
  1042. //// 处理完成或被取消
  1043. //private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  1044. //{
  1045. // if (e.Cancelled)
  1046. // {
  1047. // OnProcessingStopped?.Invoke();
  1048. // }
  1049. // else
  1050. // {
  1051. // OnProcessingCompleted?.Invoke();
  1052. // }
  1053. //}
  1054. //-----------------------------------------------------------------------------------
  1055. }
  1056. // 自定义事件参数类
  1057. public class PatchDetailItemChangedEventArgs : EventArgs
  1058. {
  1059. public PatchDetailItem SelectedPatchDetailItem { get; }
  1060. public PatchDetailItemChangedEventArgs(PatchDetailItem selectedData)
  1061. {
  1062. SelectedPatchDetailItem = selectedData;
  1063. }
  1064. }
  1065. }