UCSingleGrid.xaml.cs 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157
  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.RemoteApi;
  8. using MeterVision.Util;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Collections.ObjectModel;
  12. using System.ComponentModel;
  13. using System.IO;
  14. using System.Linq;
  15. using System.Net;
  16. using System.Text.RegularExpressions;
  17. using System.Threading;
  18. using System.Threading.Tasks;
  19. //using System.Linq;
  20. //using System.Text;
  21. //using System.Threading.Tasks;
  22. using System.Windows;
  23. using System.Windows.Controls;
  24. using System.Windows.Data;
  25. //using System.Windows.Data;
  26. //using System.Windows.Documents;
  27. using System.Windows.Input;
  28. using System.Windows.Media;
  29. using System.Windows.Media.Imaging;
  30. //using System.Windows.Media;
  31. //using System.Windows.Media.Imaging;
  32. //using System.Windows.Navigation;
  33. //using System.Windows.Shapes;
  34. namespace MeterVision.Single
  35. {
  36. /// <summary>
  37. /// UCSingleGrid.xaml 的交互逻辑
  38. /// </summary>
  39. public partial class UCSingleGrid : UserControl, INotifyPropertyChanged
  40. {
  41. public event PropertyChangedEventHandler PropertyChanged;
  42. protected void OnPropertyChanged(string propertyName)
  43. {
  44. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  45. }
  46. private SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
  47. //定义数据源
  48. public BulkObservableCollection<SingleDetailItem> SingleDetailItemList { get; set; }
  49. //定义事件,用于通知外部组件选中项已更改(用于其它窗体或用户控件注册)
  50. public event EventHandler<SingleDetailItemChangedEventArgs> OnSelectedSingDetailItemChanged;
  51. private SingleDetailItem _selectedSingleDetailItem;
  52. public SingleDetailItem SelectedSingleDetailItem
  53. {
  54. get => _selectedSingleDetailItem;
  55. set
  56. {
  57. if(_selectedSingleDetailItem != value)
  58. {
  59. _selectedSingleDetailItem = value;
  60. OnPropertyChanged(nameof(SelectedSingleDetailItem));
  61. OnSelectedSingDetailItemChanged?.Invoke(this, new SingleDetailItemChangedEventArgs(value));
  62. }
  63. }
  64. }
  65. public CfginiItem mConfigItem { get; set; }
  66. public PageModel SingleDetailPage { get; set; }
  67. private int _totalRecord;
  68. public int TotalRecords
  69. {
  70. get => _totalRecord;
  71. set
  72. {
  73. if (_totalRecord != value)
  74. {
  75. _totalRecord = value;
  76. OnPropertyChanged(nameof(TotalRecords));
  77. }
  78. }
  79. }
  80. public UCSingleGrid()
  81. {
  82. InitializeComponent();
  83. SingleDetailItemList = new BulkObservableCollection<SingleDetailItem>();
  84. dgSingle.ItemsSource = SingleDetailItemList;
  85. mConfigItem = CfginiItem.GetConfigItem();
  86. SingleDetailPage = new PageModel
  87. {
  88. PageSize = mConfigItem.PageSize3, //mConfigItem.SinglePageSize,
  89. PageNumber = 1
  90. };
  91. //mConfigItem.OnSinglePageSizeChanged += MConfigItem_OnSinglePageSizeChanged;
  92. //mConfigItem.OnSinglePageSizeChanged += MConfigItem_OnSinglePageSizeChanged1;
  93. mConfigItem.OnPageSize3Changed += MConfigItem_OnPageSize1Changed;
  94. //InitializeAsync();
  95. LoadSingleDetailItemList();
  96. //LoadSingleDetailItemList_sync();
  97. //CreateDemoData();
  98. this.DataContext = this;
  99. }
  100. private void MConfigItem_OnPageSize1Changed(int pageSize3)
  101. {
  102. if (!_semaphore.Wait(0)) return; // 防止重复调用
  103. try
  104. {
  105. SingleDetailPage.InitDefaulValue(pageSize3);
  106. LoadSingleDetailItemList();
  107. //LoadSingleDetailItemList_sync();
  108. }
  109. catch { }
  110. finally
  111. {
  112. _semaphore.Release();
  113. }
  114. }
  115. //private async void LoadSingleDetailItemList_sync()
  116. //{
  117. // await LoadSingleDetailItemList();
  118. //}
  119. //private async void InitializeAsync()
  120. //{
  121. // await LoadSingleDetailItemList();
  122. //}
  123. //private async void MConfigItem_OnSinglePageSizeChanged(object sender, PageSizeChangedEventArgs e)
  124. //{
  125. // SingleDetailPage.InitDefaulValue(e.PageSize);
  126. // await LoadSingleDetailItemList();
  127. //}
  128. public void RefreshData()
  129. {
  130. if (!_semaphore.Wait(0)) return; // 防止重复调用
  131. try
  132. {
  133. SingleDetailPage.InitDefaulValue();
  134. //await LoadSingleDetailItemList();
  135. LoadSingleDetailItemList();
  136. }
  137. catch { }
  138. finally
  139. {
  140. _semaphore.Release();
  141. }
  142. }
  143. public async void LoadSingleDetailItemList()
  144. {
  145. SingleDetailItemList.Clear();
  146. try
  147. {
  148. var result = await Task.Run(() =>
  149. {
  150. return DBSingle.GetPagedSingleDetails(SingleDetailPage.PageNumber, SingleDetailPage.PageSize);
  151. });
  152. TotalRecords = result.Item1;
  153. SingleDetailPage.PageCount = result.Item2;
  154. List<TSingleDetail> singleDetails = result.Item3;
  155. //更新数据需要在主线中进行
  156. //await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  157. //{
  158. //int index = 0;
  159. //foreach (TSingleDetail singleDetail in singleDetails)
  160. //{
  161. // index++;
  162. // SingleDetailItem item = new SingleDetailItem(singleDetail);
  163. // item.Index = index + ((SingleDetailPage.PageNumber - 1) * SingleDetailPage.PageSize);
  164. // SingleDetailItemList.Add(item);
  165. //}//foreach
  166. var patchDetailItems = singleDetails.Select((singleDetail, i) => new SingleDetailItem(singleDetail)
  167. {
  168. Index = (SingleDetailPage.PageNumber - 1) * SingleDetailPage.PageSize + i + 1
  169. }).ToList();
  170. SingleDetailItemList.AddRange(patchDetailItems);
  171. SelectedSingleDetailItem = null;
  172. //}));
  173. //return true;
  174. }
  175. catch (Exception ex)
  176. {
  177. MessageBox.Show(Application.Current.MainWindow,
  178. $"加载数据时发生错误:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  179. //return false;
  180. }
  181. }
  182. public async Task LoadSingleDetailItemListAsync()
  183. {
  184. SingleDetailItemList.Clear();
  185. try
  186. {
  187. var result = await Task.Run(() =>
  188. {
  189. return DBSingle.GetPagedSingleDetails(SingleDetailPage.PageNumber, SingleDetailPage.PageSize);
  190. });
  191. TotalRecords = result.Item1;
  192. SingleDetailPage.PageCount = result.Item2;
  193. List<TSingleDetail> singleDetails = result.Item3;
  194. var patchDetailItems = singleDetails.Select((singleDetail, i) => new SingleDetailItem(singleDetail)
  195. {
  196. Index = (SingleDetailPage.PageNumber - 1) * SingleDetailPage.PageSize + i + 1
  197. }).ToList();
  198. SingleDetailItemList.AddRange(patchDetailItems);
  199. SelectedSingleDetailItem = null;
  200. }
  201. catch (Exception ex)
  202. {
  203. MessageBox.Show(Application.Current.MainWindow,
  204. $"加载数据时发生错误:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  205. //return false;
  206. }
  207. }
  208. //private imgWindow mImgWindow;
  209. private void SrcImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  210. {
  211. var image = sender as Image;
  212. if (image == null) return;
  213. var dataContext = image.DataContext as SingleDetailItem;
  214. if (dataContext == null) return;
  215. //var dialog = new ImageViewerWindow(dataContext.SourceImagePath)
  216. if (!File.Exists(dataContext.SrcImage)) return;
  217. //((MainWindow)Application.Current.MainWindow).overlay.Visibility = Visibility.Visible;
  218. imgWindow dialog = new imgWindow(dataContext.SrcImage)
  219. {
  220. Owner = Application.Current.MainWindow
  221. };
  222. //dialog.ShowDialog();
  223. dialog.Show();
  224. //this.PreviewMouseDown += UCSingleGrid_PreviewMouseDown;
  225. // 添加事件监听器来监听鼠标点击事件
  226. //dialog.PreviewMouseDown += Dialog_PreviewMouseDown;
  227. //// 添加事件监听器来监听键盘按键事件
  228. //dialog.PreviewKeyDown += Dialog_PreviewKeyDown;
  229. //// 对话框关闭后隐藏覆盖层
  230. //((MainWindow)Application.Current.MainWindow).overlay.Visibility = Visibility.Visible;
  231. //this.dialog
  232. }
  233. private void UCSingleGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
  234. {
  235. //var dialog = (imgWindow)sender;
  236. //if(mImgWindow != null)
  237. //{
  238. // mImgWindow.Close();
  239. //}
  240. //// 检查点击是否发生在对话框外部
  241. ////if (e.OriginalSource == dialog && !dialog.Content.IsMouseOver)
  242. ////{
  243. //// dialog.Close();
  244. ////}
  245. }
  246. //private void Dialog_PreviewMouseDown(object sender, MouseButtonEventArgs e)
  247. //{
  248. // var dialog = (imgWindow)sender;
  249. // // 检查点击是否发生在对话框外部
  250. // if (e.OriginalSource == dialog && !dialog.Content.IsMouseOver)
  251. // {
  252. // dialog.Close();
  253. // }
  254. //}
  255. //private void Dialog_PreviewKeyDown(object sender, KeyEventArgs e)
  256. //{
  257. // var dialog = (imgWindow)sender;
  258. // // 当按下 Esc 键时关闭对话框
  259. // if (e.Key == Key.Escape)
  260. // {
  261. // dialog.Close();
  262. // }
  263. //}
  264. private void DstImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  265. {
  266. var image = sender as Image;
  267. if (image == null) return;
  268. var dataContext = image.DataContext as SingleDetailItem;
  269. if (dataContext == null) return;
  270. //var dialog = new ImageViewerWindow(dataContext.SourceImagePath)
  271. if (!File.Exists(dataContext.DstImage)) return;
  272. var dialog = new imgWindow(dataContext.DstImage)
  273. {
  274. Owner = Application.Current.MainWindow
  275. };
  276. dialog.Show();
  277. }
  278. private void UserControl_DragEnter(object sender, DragEventArgs e)
  279. {
  280. // 处理网页拖拽
  281. //if (e.Data.GetDataPresent(DataFormats.Text) || e.Data.GetDataPresent(DataFormats.Bitmap))
  282. if (e.Data.GetDataPresent(DataFormats.Text))
  283. {
  284. e.Effects = DragDropEffects.Copy;
  285. }
  286. else if (e.Data.GetDataPresent(DataFormats.FileDrop))
  287. {
  288. e.Effects = DragDropEffects.Copy; // 如果是文件拖拽,允许复制
  289. }
  290. else
  291. {
  292. e.Effects = DragDropEffects.None; // 不支持的格式
  293. }
  294. e.Handled = true;
  295. }
  296. private void UserControl_PreviewDragOver(object sender, DragEventArgs e)
  297. {
  298. //if (e.Data.GetDataPresent(DataFormats.FileDrop))
  299. //{
  300. // // 获取拖拽的文件数组
  301. // string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
  302. // // 检查是否只拖拽了一个文件,并且该文件不是文件夹
  303. // if (files.Length == 1 && File.Exists(files[0]))
  304. // {
  305. // e.Effects = DragDropEffects.Copy;
  306. // }
  307. // else
  308. // {
  309. // e.Effects = DragDropEffects.None;
  310. // }
  311. //}
  312. //else
  313. //{
  314. // e.Effects = DragDropEffects.None;
  315. //}
  316. //e.Handled = true;
  317. //if (e.Data.GetDataPresent(DataFormats.Text) || e.Data.GetDataPresent(DataFormats.Bitmap))
  318. if (e.Data.GetDataPresent(DataFormats.Text))
  319. {
  320. e.Effects = DragDropEffects.Copy;
  321. }
  322. else if (e.Data.GetDataPresent(DataFormats.FileDrop))
  323. {
  324. string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
  325. if (files.Length == 1 && File.Exists(files[0]))
  326. {
  327. e.Effects = DragDropEffects.Copy;
  328. }
  329. else
  330. {
  331. e.Effects = DragDropEffects.None;
  332. }
  333. }
  334. else
  335. {
  336. e.Effects = DragDropEffects.None;
  337. }
  338. e.Handled = true;
  339. }
  340. private void UserControl_Drop(object sender, DragEventArgs e)
  341. {
  342. if (e.Data.GetDataPresent(DataFormats.FileDrop))
  343. {
  344. // 获取拖拽的文件数组
  345. string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
  346. // 确保只拖拽了一个文件
  347. if (files.Length != 1)
  348. {
  349. //MessageBox.Show("只能拖拽一个文件。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  350. MessageBox.Show(Application.Current.MainWindow,
  351. "只能拖拽一个文件。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  352. return;
  353. }
  354. // 获取单个文件路径
  355. string file = files[0];
  356. // 验证文件是否为有效的 JPG 文件,并且文件大小不超过 100KB
  357. if ( (ThisApp.IsJpgFile(file) || ThisApp.IsBmpFile(file) ) &&
  358. ThisApp.IsFileSizeValid(file) && ThisApp.IsImageDimensionsValid(file))
  359. {
  360. // 调用图像处理方法
  361. //ProcessDragFile(file);
  362. DragRecong(file);
  363. }
  364. else
  365. {
  366. MessageBox.Show(Application.Current.MainWindow,
  367. $"文件 {file} 不符合要求:必须是小于 300KB 的 JPG 文件,且图像尺寸必须为 320x240。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  368. }
  369. }
  370. else if (e.Data.GetDataPresent(DataFormats.Text))
  371. {
  372. // 处理网页拖拽的图像(URL)
  373. string imageUrl = e.Data.GetData(DataFormats.Text).ToString();
  374. // 如果需要,你可以检查 URL 是否以图像文件类型(例如 .jpg, .png)结尾
  375. if (Uri.IsWellFormedUriString(imageUrl, UriKind.Absolute))
  376. {
  377. // 处理图像 URL
  378. string localFilePath = ProcessImageFromUrl(imageUrl);
  379. if (localFilePath != null)
  380. {
  381. DragRecong(localFilePath);
  382. }
  383. }
  384. }//else if
  385. }
  386. private string ProcessImageFromUrl(string imageUrl)
  387. {
  388. // 你可以通过 WebRequest 下载并显示图像,或者直接显示 URL
  389. try
  390. {
  391. string saveFilePath = null;
  392. using (var client = new WebClient())
  393. {
  394. byte[] imageData = client.DownloadData(imageUrl);
  395. MemoryStream memoryStream = new MemoryStream(imageData);
  396. BitmapImage bitmapImage = new BitmapImage();
  397. bitmapImage.BeginInit();
  398. bitmapImage.StreamSource = memoryStream;
  399. bitmapImage.EndInit();
  400. // 获取图像的宽度和高度
  401. Console.WriteLine($"Width: {bitmapImage.PixelWidth}");
  402. Console.WriteLine($"Height: {bitmapImage.PixelHeight}");
  403. if(bitmapImage.PixelWidth != ThisApp.RequiredWidth ||
  404. bitmapImage.PixelHeight != ThisApp.RequiredHeight)
  405. {
  406. MessageBox.Show(Application.Current.MainWindow,
  407. "图像尺寸不符合320*240的要求。", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
  408. return null;
  409. }
  410. if(memoryStream.Length > ThisApp.MaxFileSize)
  411. {
  412. MessageBox.Show(Application.Current.MainWindow,
  413. "图像的文件大小不符合要求。", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
  414. return null;
  415. }
  416. //判读文件名称是否符号要求,暂时不管
  417. //获取保存网络图片的路径
  418. string folerPath = Path.Combine(mConfigItem.TransImgPath, "www");
  419. if (!Directory.Exists(folerPath))
  420. {
  421. Directory.CreateDirectory(folerPath);
  422. }
  423. //在这里保存成本地文件,并能保留imageUrl中的文件名
  424. // 提取文件名(从 URL 获取文件名部分)
  425. string fileName = Path.GetFileName(new Uri(imageUrl).LocalPath);
  426. saveFilePath = Path.Combine(folerPath, fileName);
  427. // 保存图像到本地文件
  428. if (!File.Exists(saveFilePath))
  429. {
  430. File.WriteAllBytes(saveFilePath, imageData);
  431. }
  432. // 打印保存路径
  433. Console.WriteLine($"Image saved to: {saveFilePath}");
  434. }
  435. return saveFilePath;
  436. }
  437. catch (Exception ex)
  438. {
  439. MessageBox.Show(Application.Current.MainWindow,
  440. $"加载图像失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  441. return null;
  442. }
  443. }
  444. public async void DragRecong(string srcImagePath)
  445. {
  446. if (!_semaphore.Wait(0)) return; // 防止重复调用
  447. try
  448. {
  449. var singleDetailItem = new SingleDetailItem()
  450. {
  451. SingleDetailId = Guid.NewGuid().ToString(),
  452. CreateTime = ThisApp.GetNowTime_yyyyMMddHHmmss(),
  453. SrcImage = srcImagePath,
  454. DeviceSn = "",
  455. SampleTime = ""
  456. };
  457. if (TryExtractNumbers(srcImagePath, out string deviceSn, out string sampleTime))
  458. {
  459. singleDetailItem.DeviceSn = deviceSn;
  460. singleDetailItem.SampleTime = sampleTime;
  461. }
  462. TSingleDetail singleDetail = new TSingleDetail();
  463. ObjectHelper.CopyMatchingFields(singleDetailItem, singleDetail);
  464. if (DBSingle.InsertTSingleDetail0(singleDetail))
  465. {
  466. SingleDetailPage.PageNumber = 1;
  467. //LoadSingleDetailItemList();
  468. await LoadSingleDetailItemListAsync();
  469. if (SingleDetailItemList.Count > 0)
  470. {
  471. SelectedSingleDetailItem = SingleDetailItemList[0];
  472. //dgSingle.ScrollIntoView(dgSingle.Items[0]);
  473. var scrollViewer = GetDgSingleScrollViewer(dgSingle);
  474. scrollViewer?.ScrollToTop();
  475. //插入成功后进行识别20250725后新加的
  476. RecongSingleDetail(false, SelectedSingleDetailItem);
  477. }
  478. }
  479. }
  480. catch { }
  481. finally
  482. {
  483. _semaphore.Release();
  484. }
  485. }
  486. static bool TryExtractNumbers(string fileName, out string deviceSn, out string recvTime)
  487. {
  488. deviceSn = string.Empty;
  489. recvTime = string.Empty;
  490. string pattern = @"^(\d{11})_(\d{14})_.*$";
  491. Match match = Regex.Match(fileName, pattern);
  492. if (match.Success)
  493. {
  494. deviceSn = match.Groups[1].Value;
  495. recvTime = match.Groups[2].Value;
  496. return true;
  497. }
  498. return false;
  499. }
  500. public void InsertFilesToDatabase(List<string> filePaths, ProgressDialog progressDialog)
  501. {
  502. int totalFiles = filePaths.Count;
  503. int currentFile = 0;
  504. foreach (var filePath in filePaths)
  505. {
  506. // 插入文件路径到数据库
  507. //InsertFileToDatabase(filePath);
  508. TSingleDetail singleDetail = new TSingleDetail()
  509. {
  510. SingleDetailId = Guid.NewGuid().ToString(),
  511. CreateTime = ThisApp.GetNowTime_yyyyMMddHHmmss(),
  512. SrcImage = filePath
  513. };
  514. DBSingle.InsertTSingleDetail0(singleDetail);
  515. // 更新进度条
  516. currentFile++;
  517. UpdateProgress(progressDialog, currentFile, totalFiles);
  518. }
  519. }
  520. public void UpdateProgress(ProgressDialog progressDialog, int currentFile, int totalFiles)
  521. {
  522. // 更新进度条的进度
  523. double progress = (double)currentFile / totalFiles * 100;
  524. progressDialog.UpdateProgress(progress);
  525. }
  526. public void NextPage()
  527. {
  528. if (!_semaphore.Wait(0)) return; // 防止重复调用
  529. try
  530. {
  531. if (SingleDetailPage.PageNumber < SingleDetailPage.PageCount)
  532. {
  533. SingleDetailPage.PageNumber += 1;
  534. LoadSingleDetailItemList();
  535. }
  536. }
  537. catch { }
  538. finally
  539. {
  540. _semaphore.Release();
  541. }
  542. }
  543. public void PrePage()
  544. {
  545. if (!_semaphore.Wait(0)) return; // 防止重复调用
  546. try
  547. {
  548. if (SingleDetailPage.PageNumber > 1)
  549. {
  550. SingleDetailPage.PageNumber -= 1;
  551. LoadSingleDetailItemList();
  552. }
  553. }
  554. catch { }
  555. finally
  556. {
  557. _semaphore.Release();
  558. }
  559. }
  560. public void FirstPage()
  561. {
  562. if (!_semaphore.Wait(0)) return; // 防止重复调用
  563. try
  564. {
  565. if (SingleDetailPage.PageNumber > 1)
  566. {
  567. SingleDetailPage.PageNumber = 1;
  568. LoadSingleDetailItemList();
  569. }
  570. }
  571. catch { }
  572. finally
  573. {
  574. _semaphore.Release();
  575. }
  576. }
  577. public void LastPage()
  578. {
  579. if (!_semaphore.Wait(0)) return; // 防止重复调用
  580. try
  581. {
  582. if (SingleDetailPage.PageNumber < SingleDetailPage.PageCount)
  583. {
  584. SingleDetailPage.PageNumber = SingleDetailPage.PageCount;
  585. LoadSingleDetailItemList();
  586. }
  587. }
  588. catch { }
  589. finally
  590. {
  591. _semaphore.Release();
  592. }
  593. }
  594. public void SpeciPage(int pageNumber)
  595. {
  596. if (!_semaphore.Wait(0)) return; // 防止重复调用
  597. try
  598. {
  599. if (pageNumber != SingleDetailPage.PageNumber &&
  600. pageNumber > 0 && pageNumber <= SingleDetailPage.PageCount)
  601. {
  602. SingleDetailPage.PageNumber = pageNumber;
  603. LoadSingleDetailItemList();
  604. }
  605. }
  606. catch { }
  607. finally
  608. {
  609. _semaphore.Release();
  610. }
  611. }
  612. // 辅助方法:查找指定类型的祖先元素
  613. public static T FindAncestor<T>(DependencyObject dependencyObject) where T : DependencyObject
  614. {
  615. var parent = VisualTreeHelper.GetParent(dependencyObject);
  616. if (parent == null) return null;
  617. var parentT = parent as T;
  618. return parentT ?? FindAncestor<T>(parent);
  619. }
  620. private void BtnDelDetailItem_Click(object sender, RoutedEventArgs e)
  621. {
  622. //删除选中项
  623. Button button = sender as Button;
  624. if (button == null) return;
  625. DataGridRow row = FindAncestor<DataGridRow>(button);
  626. if (row == null) return;
  627. //获取当前行绑定的数据项
  628. SingleDetailItem selectedItem = row.Item as SingleDetailItem;
  629. DeleteSelectedItem(selectedItem);
  630. }
  631. private void BtnRecongDetailItem_Click(object sender, RoutedEventArgs e)
  632. {
  633. Button button = sender as Button;
  634. if (button == null) return;
  635. DataGridRow row = FindAncestor<DataGridRow>(button);
  636. if (row == null) return;
  637. //获取当前行绑定的数据项
  638. SingleDetailItem selectedItem = row.Item as SingleDetailItem;
  639. RecongSingleDetail(false, SelectedSingleDetailItem);
  640. }
  641. private void BtnLogViewer_Click(object sender, RoutedEventArgs e)
  642. {
  643. Button button = sender as Button;
  644. if (button == null) return;
  645. DataGridRow row = FindAncestor<DataGridRow>(button);
  646. if (row == null) return;
  647. //获取当前行绑定的数据项
  648. SingleDetailItem selectedItem = row.Item as SingleDetailItem;
  649. ShowLogViewer(selectedItem);
  650. }
  651. private void ShowLogViewer(SingleDetailItem selectedItem)
  652. {
  653. if (selectedItem.LogPath != null && File.Exists(selectedItem.LogPath))
  654. {
  655. //LogViewerWindow dialog = new LogViewerWindow(selectedItem.DstImage, selectedItem.LogPath)
  656. var dialog = new LogViewerWindow(selectedItem)
  657. {
  658. Owner = Application.Current.MainWindow,
  659. WindowStartupLocation = WindowStartupLocation.CenterOwner
  660. };
  661. //dialog.ShowDialog();
  662. dialog.Show();
  663. }
  664. }
  665. private async void DeleteSelectedItem(SingleDetailItem selectedItem)
  666. {
  667. if (selectedItem == null) return;
  668. MessageBoxResult result = MessageBox.Show("确定要删除此条目吗?", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Question);
  669. if (result != MessageBoxResult.Yes) return;
  670. string titleInfo = "正在删除,请稍后...";
  671. WaitWindow waitWindow = new WaitWindow(titleInfo)
  672. {
  673. Owner = Application.Current.MainWindow,
  674. WindowStartupLocation = WindowStartupLocation.CenterOwner
  675. };
  676. waitWindow.Show();
  677. try
  678. {
  679. bool deleteSuccess = false;
  680. await Task.Run(() =>
  681. {
  682. deleteSuccess = DBSingle.DeleteTSingleDetailById(selectedItem.SingleDetailId);
  683. });
  684. if (deleteSuccess)
  685. {
  686. //await Application.Current.Dispatcher.BeginInvoke(new Action(() =>
  687. //{
  688. // 从数据源中移除该条目
  689. SingleDetailItemList.Remove(selectedItem);
  690. SelectedSingleDetailItem = null;
  691. //}));
  692. }
  693. }
  694. catch (Exception ex)
  695. {
  696. MessageBox.Show(Application.Current.MainWindow, $"删除失败:{ex.Message}", "错误",
  697. MessageBoxButton.OK, MessageBoxImage.Error);
  698. }
  699. finally
  700. {
  701. waitWindow.Close();
  702. }
  703. }
  704. //清空所有的列表数据
  705. public async void ClearAllSingleDetail()
  706. {
  707. if (!_semaphore.Wait(0)) return; // 防止重复调用
  708. try
  709. {
  710. //清空提示
  711. MessageBoxResult result = MessageBox.Show("确定要清空所有数据吗?", "确认清空", MessageBoxButton.YesNo, MessageBoxImage.Question);
  712. if (result != MessageBoxResult.Yes) return;
  713. string titleInfo = "正在清空数据,请稍后...";
  714. WaitWindow waitWindow = new WaitWindow(titleInfo)
  715. {
  716. Owner = Application.Current.MainWindow,
  717. WindowStartupLocation = WindowStartupLocation.CenterOwner
  718. };
  719. waitWindow.Show();
  720. try
  721. {
  722. bool blClearAll = false;
  723. await Task.Run(() =>
  724. {
  725. blClearAll = DBSingle.ClearTSingleDetailTable();
  726. });
  727. if (blClearAll)
  728. {
  729. SingleDetailPage.InitDefaulValue();
  730. LoadSingleDetailItemList();
  731. }
  732. }
  733. catch (Exception ex)
  734. {
  735. MessageBox.Show(Application.Current.MainWindow, $"清空失败:{ex.Message}", "错误",
  736. MessageBoxButton.OK, MessageBoxImage.Error);
  737. }
  738. finally
  739. {
  740. waitWindow.Close();
  741. }
  742. }
  743. catch { }
  744. finally
  745. {
  746. _semaphore.Release();
  747. }
  748. }
  749. private void MiDelete_Click(object sender, RoutedEventArgs e)
  750. {
  751. if (SelectedSingleDetailItem == null) return;
  752. //获取当前行绑定的数据项
  753. DeleteSelectedItem(SelectedSingleDetailItem);
  754. }
  755. private void MiRecong_Click(object sender, RoutedEventArgs e)
  756. {
  757. if (SelectedSingleDetailItem == null) return;
  758. RecongSingleDetail(false, SelectedSingleDetailItem);
  759. }
  760. private async void RecongSingleDetail(bool isAdd, SingleDetailItem singleDetailIte)
  761. {
  762. string jpgFile = singleDetailIte.SrcImage;
  763. if (!File.Exists(jpgFile))
  764. {
  765. MessageBox.Show(Application.Current.MainWindow, $"文件:{jpgFile}不存在!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
  766. return;
  767. }
  768. //bool blRun = await RunAI(isAdd, singleDetailIte);
  769. bool blRun = await Run_HttpApi_Recogn(isAdd, singleDetailIte);
  770. if (blRun)
  771. {
  772. //MessageBox.Show(Application.Current.MainWindow, "识别成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
  773. }
  774. else
  775. {
  776. MessageBox.Show(Application.Current.MainWindow, "识别失败!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  777. }
  778. }
  779. //允许http的远程识别
  780. private async Task<bool> Run_HttpApi_Recogn(bool isAdd,SingleDetailItem singleDetailItem)
  781. {
  782. string titleInfo = "正在识别,请稍后...";
  783. WaitWindow waitWindow = new WaitWindow(titleInfo)
  784. {
  785. Owner = Application.Current.MainWindow,
  786. WindowStartupLocation = WindowStartupLocation.CenterOwner
  787. };
  788. waitWindow.Show();
  789. try
  790. {
  791. TSingleDetail newSingleDetail = null;
  792. //调用不会出现错误,函数中已增加try catch
  793. CallApiResult apiResult = await RecogApi.CallRecogn(singleDetailItem.SrcImage, new MetaData());
  794. if(apiResult.callResult == 0)
  795. {
  796. Console.WriteLine(apiResult.errorMessage);
  797. MessageBox.Show(Application.Current.MainWindow, $"识别[{singleDetailItem.SrcImage}]时出错:{apiResult.errorMessage}", "错误",
  798. MessageBoxButton.OK, MessageBoxImage.Error);
  799. return false;
  800. }
  801. newSingleDetail = new TSingleDetail(singleDetailItem, apiResult);
  802. //更新数据
  803. bool blOpration;
  804. //实际传输的isAdd总是false
  805. if (isAdd)
  806. {
  807. blOpration = DBSingle.InsertSingleDetail(newSingleDetail);
  808. }
  809. else
  810. {
  811. blOpration = DBSingle.UpdateSingleDetailByResult(newSingleDetail);
  812. }
  813. //return blOpration;
  814. //在主线程中更新DataGrid的Row数据
  815. if (blOpration && !isAdd && newSingleDetail != null)
  816. {
  817. //singleDetailItem = newSingleDetail;
  818. ObjectHelper.CopyMatchingFields(newSingleDetail, singleDetailItem);
  819. //singleDetailItem.MeterType = 2;
  820. }
  821. return blOpration;
  822. }
  823. catch(Exception ex)
  824. {
  825. Dispatcher.Invoke(()=>
  826. {
  827. MessageBox.Show(Application.Current.MainWindow, $"识别[{singleDetailItem.SrcImage}]时出错:{ex.Message}", "错误",
  828. MessageBoxButton.OK, MessageBoxImage.Error);
  829. });
  830. return false;
  831. }
  832. finally
  833. {
  834. waitWindow.Close();
  835. }
  836. }
  837. private async Task<bool> RunAI(bool isAdd,SingleDetailItem singleDetailItem)
  838. {
  839. FaRun faRun = new FaRun();
  840. faRun.OnAiRealLogInfo += FaRun_OnAiRealLogInfo;
  841. string titleInfo = "正在识别,请稍后...";
  842. WaitWindow waitWindow = new WaitWindow(titleInfo)
  843. {
  844. Owner = Application.Current.MainWindow,
  845. WindowStartupLocation = WindowStartupLocation.CenterOwner
  846. };
  847. waitWindow.Show();
  848. try
  849. {
  850. TSingleDetail newSingleDetail = null;
  851. bool blRun = await Task.Run(() =>
  852. {
  853. try
  854. {
  855. ResultModel resultModel = null;
  856. try
  857. {
  858. resultModel = faRun.StartRecognition(singleDetailItem);
  859. }
  860. catch (Exception ex)
  861. {
  862. Console.WriteLine(ex.Message);
  863. }
  864. if (resultModel == null) return false;
  865. newSingleDetail = new TSingleDetail(singleDetailItem, resultModel);
  866. //更新数据
  867. bool blOpration;
  868. //实际传输的isAdd总是false
  869. if (isAdd)
  870. {
  871. blOpration = DBSingle.InsertSingleDetail(newSingleDetail);
  872. }
  873. else
  874. {
  875. blOpration = DBSingle.UpdateSingleDetailByResult(newSingleDetail);
  876. }
  877. return blOpration;
  878. }
  879. catch(Exception ex)
  880. {
  881. Dispatcher.Invoke(() =>
  882. {
  883. MessageBox.Show(Application.Current.MainWindow, $"{ex.Message}", "错误",
  884. MessageBoxButton.OK, MessageBoxImage.Error);
  885. });
  886. return false;
  887. }
  888. });
  889. //------
  890. //在主线程中更新DataGrid的Row数据
  891. if (blRun && !isAdd && newSingleDetail != null)
  892. {
  893. //singleDetailItem = newSingleDetail;
  894. ObjectHelper.CopyMatchingFields(newSingleDetail, singleDetailItem);
  895. //singleDetailItem.MeterType = 2;
  896. }
  897. return blRun;
  898. }
  899. catch (Exception ex)
  900. {
  901. MessageBox.Show(Application.Current.MainWindow, $"识别[{singleDetailItem.SrcImage}]时出错:{ex.Message}", "错误",
  902. MessageBoxButton.OK, MessageBoxImage.Error);
  903. return false;
  904. }
  905. finally
  906. {
  907. waitWindow.Close();
  908. }
  909. }
  910. private void FaRun_OnAiRealLogInfo(object sender, AiRealLogEventArgs e)
  911. {
  912. Console.Write(e.mLogInfo);
  913. }
  914. private void MiViewLog_Click(object sender, RoutedEventArgs e)
  915. {
  916. if(SelectedSingleDetailItem != null)
  917. {
  918. ShowLogViewer(SelectedSingleDetailItem);
  919. }
  920. }
  921. private void MiAddMemo_Click(object sender, RoutedEventArgs e)
  922. {
  923. if (SelectedSingleDetailItem == null) return;
  924. AddMemo(SelectedSingleDetailItem);
  925. }
  926. private void AddMemo(SingleDetailItem detailItem)
  927. {
  928. if (detailItem == null) return;
  929. EditMemo editMemo = new EditMemo(detailItem.Memo)
  930. {
  931. Owner = Application.Current.MainWindow,
  932. WindowStartupLocation = WindowStartupLocation.CenterOwner
  933. };
  934. if (editMemo.ShowDialog() == true)
  935. {
  936. string memo = editMemo.Memo;
  937. if (DBSingle.UpdateSingleDetailMemo(detailItem.SingleDetailId, memo))
  938. {
  939. detailItem.Memo = memo;
  940. }
  941. }
  942. }
  943. private void Memo_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  944. {
  945. if(e.ClickCount == 2)
  946. {
  947. if (SelectedSingleDetailItem == null) return;
  948. AddMemo(SelectedSingleDetailItem);
  949. }
  950. }
  951. private void BtnConfig_Click(object sender, RoutedEventArgs e)
  952. {
  953. Button button = sender as Button;
  954. if (button == null) return;
  955. DataGridRow row = FindAncestor<DataGridRow>(button);
  956. if (row == null) return;
  957. SingleDetailItem detailItem = row.Item as SingleDetailItem;
  958. EditSingleConfig dialog = new EditSingleConfig(detailItem)
  959. {
  960. Owner = Application.Current.MainWindow,
  961. WindowStartupLocation = WindowStartupLocation.CenterOwner
  962. };
  963. if (dialog.ShowDialog() == true)
  964. {
  965. detailItem = dialog.mDetailItem;
  966. }
  967. }
  968. private ScrollViewer _dgSingleScrollViewer;
  969. private ScrollViewer GetDgSingleScrollViewer(DependencyObject obj)
  970. {
  971. if (_dgSingleScrollViewer != null)
  972. {
  973. return _dgSingleScrollViewer;
  974. }
  975. if (obj is ScrollViewer)
  976. {
  977. _dgSingleScrollViewer = (ScrollViewer)obj;
  978. return obj as ScrollViewer;
  979. }
  980. for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
  981. {
  982. var child = VisualTreeHelper.GetChild(obj, i);
  983. var scrollViewer = GetDgSingleScrollViewer(child);
  984. if (scrollViewer != null)
  985. {
  986. _dgSingleScrollViewer = scrollViewer;
  987. return scrollViewer;
  988. }
  989. }
  990. return null;
  991. }
  992. ///////////////////////////////////////////////////////////////////////////
  993. }
  994. //自定义事件参数类
  995. public class SingleDetailItemChangedEventArgs : EventArgs
  996. {
  997. public SingleDetailItem SelectedSingleDetailItem { get; }
  998. public SingleDetailItemChangedEventArgs(SingleDetailItem selectedData)
  999. {
  1000. SelectedSingleDetailItem = selectedData;
  1001. }
  1002. }
  1003. }