UCSingleGrid.xaml - 副本.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. using MeterVision.Config;
  2. using MeterVision.db;
  3. using MeterVision.Dlg;
  4. using MeterVision.FreeAi;
  5. using MeterVision.model;
  6. using MeterVision.Util;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Collections.ObjectModel;
  10. using System.ComponentModel;
  11. using System.IO;
  12. using System.Threading.Tasks;
  13. //using System.Linq;
  14. //using System.Text;
  15. //using System.Threading.Tasks;
  16. using System.Windows;
  17. using System.Windows.Controls;
  18. using System.Windows.Data;
  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;
  24. //using System.Windows.Media.Imaging;
  25. //using System.Windows.Navigation;
  26. //using System.Windows.Shapes;
  27. namespace MeterVision.Single
  28. {
  29. /// <summary>
  30. /// UCSingleGrid.xaml 的交互逻辑
  31. /// </summary>
  32. public partial class UCSingleGrid : UserControl, INotifyPropertyChanged
  33. {
  34. public event PropertyChangedEventHandler PropertyChanged;
  35. protected void OnPropertyChanged(string propertyName)
  36. {
  37. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  38. }
  39. //定义数据源
  40. public ObservableCollection<SingleDetailItem> SingleDetailItemList { get; set; }
  41. //定义事件,用于通知外部组件选中项已更改(用于其它窗体或用户控件注册)
  42. public event EventHandler<SingleDetailItemChangedEventArgs> OnSelectedSingDetailItemChanged;
  43. private SingleDetailItem _selectedSingleDetailItem;
  44. public SingleDetailItem SelectedSingleDetailItem
  45. {
  46. get => _selectedSingleDetailItem;
  47. set
  48. {
  49. if(_selectedSingleDetailItem != value)
  50. {
  51. _selectedSingleDetailItem = value;
  52. OnPropertyChanged(nameof(SelectedSingleDetailItem));
  53. OnSelectedSingDetailItemChanged?.Invoke(this, new SingleDetailItemChangedEventArgs(value));
  54. }
  55. }
  56. }
  57. public ConfigItem mConfigItem { get; set; }
  58. public PageModel SingleDetailPage { get; set; }
  59. private int _totalRecord;
  60. public int TotalRecords
  61. {
  62. get => _totalRecord;
  63. set
  64. {
  65. if (_totalRecord != value)
  66. {
  67. _totalRecord = value;
  68. OnPropertyChanged(nameof(TotalRecords));
  69. }
  70. }
  71. }
  72. public UCSingleGrid()
  73. {
  74. InitializeComponent();
  75. SingleDetailItemList = new ObservableCollection<SingleDetailItem>();
  76. dgSingle.ItemsSource = SingleDetailItemList;
  77. mConfigItem = ConfigItem.GetConfigItem();
  78. SingleDetailPage = new PageModel
  79. {
  80. PageSize = mConfigItem.SinglePageSize,
  81. PageNumber = 1
  82. };
  83. mConfigItem.OnSinglePageSizeChanged += MConfigItem_OnSinglePageSizeChanged;
  84. InitializeAsync();
  85. //CreateDemoData();
  86. this.DataContext = this;
  87. }
  88. private async void InitializeAsync()
  89. {
  90. await LoadSingleDetailItemList();
  91. }
  92. private async void MConfigItem_OnSinglePageSizeChanged(object sender, PageSizeChangedEventArgs e)
  93. {
  94. SingleDetailPage.InitDefaulValue(e.PageSize);
  95. await LoadSingleDetailItemList();
  96. }
  97. public async void RefreshData()
  98. {
  99. SingleDetailPage.InitDefaulValue();
  100. await LoadSingleDetailItemList();
  101. }
  102. public async Task<bool> LoadSingleDetailItemList()
  103. {
  104. SingleDetailItemList.Clear();
  105. try
  106. {
  107. var result = await Task.Run(() =>
  108. {
  109. return DBSingle.GetPagedSingleDetails(SingleDetailPage.PageNumber, SingleDetailPage.PageSize);
  110. });
  111. TotalRecords = result.Item1;
  112. SingleDetailPage.PageCount = result.Item2;
  113. List<TSingleDetail> singleDetails = result.Item3;
  114. //更新数据需要在主线中进行
  115. Application.Current.Dispatcher.Invoke(() =>
  116. {
  117. int index = 0;
  118. foreach (TSingleDetail singleDetail in singleDetails)
  119. {
  120. index++;
  121. SingleDetailItem item = new SingleDetailItem(singleDetail);
  122. item.Index = index + ((SingleDetailPage.PageNumber - 1) * SingleDetailPage.PageSize);
  123. SingleDetailItemList.Add(item);
  124. }//foreach
  125. SelectedSingleDetailItem = null;
  126. });
  127. return true;
  128. }
  129. catch (Exception ex)
  130. {
  131. MessageBox.Show(Application.Current.MainWindow,
  132. $"加载数据时发生错误:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  133. return false;
  134. }
  135. }
  136. private void SrcImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  137. {
  138. var image = sender as Image;
  139. if (image == null) return;
  140. var dataContext = image.DataContext as SingleDetailItem;
  141. if (dataContext == null) return;
  142. //var dialog = new ImageViewerWindow(dataContext.SourceImagePath)
  143. if (!File.Exists(dataContext.SrcImage)) return;
  144. var dialog = new imgWindow(dataContext.SrcImage)
  145. {
  146. Owner = Application.Current.MainWindow
  147. };
  148. if(dialog.ShowDialog() == true)
  149. {
  150. }
  151. }
  152. private void DstImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  153. {
  154. var image = sender as Image;
  155. if (image == null) return;
  156. var dataContext = image.DataContext as SingleDetailItem;
  157. if (dataContext == null) return;
  158. //var dialog = new ImageViewerWindow(dataContext.SourceImagePath)
  159. if (!File.Exists(dataContext.DstImage)) return;
  160. var dialog = new imgWindow(dataContext.DstImage)
  161. {
  162. Owner = Application.Current.MainWindow
  163. };
  164. if (dialog.ShowDialog() == true)
  165. {
  166. }
  167. }
  168. private void UserControl_DragEnter(object sender, DragEventArgs e)
  169. {
  170. }
  171. private void UserControl_PreviewDragOver(object sender, DragEventArgs e)
  172. {
  173. if (e.Data.GetDataPresent(DataFormats.FileDrop))
  174. {
  175. // 获取拖拽的文件数组
  176. string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
  177. // 检查是否只拖拽了一个文件,并且该文件不是文件夹
  178. if (files.Length == 1 && File.Exists(files[0]))
  179. {
  180. e.Effects = DragDropEffects.Copy;
  181. }
  182. else
  183. {
  184. e.Effects = DragDropEffects.None;
  185. }
  186. }
  187. else
  188. {
  189. e.Effects = DragDropEffects.None;
  190. }
  191. e.Handled = true;
  192. }
  193. private void UserControl_Drop(object sender, DragEventArgs e)
  194. {
  195. if (e.Data.GetDataPresent(DataFormats.FileDrop))
  196. {
  197. // 获取拖拽的文件数组
  198. string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
  199. // 确保只拖拽了一个文件
  200. if (files.Length != 1)
  201. {
  202. //MessageBox.Show("只能拖拽一个文件。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  203. MessageBox.Show(Application.Current.MainWindow,
  204. "只能拖拽一个文件。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  205. return;
  206. }
  207. // 获取单个文件路径
  208. string file = files[0];
  209. // 验证文件是否为 JPG 文件
  210. //if (IsJpgFile(file))
  211. // 验证文件是否为有效的 JPG 文件,并且文件大小不超过 100KB
  212. if ( (ThisApp.IsJpgFile(file) || ThisApp.IsBmpFile(file) ) &&
  213. ThisApp.IsFileSizeValid(file) && ThisApp.IsImageDimensionsValid(file))
  214. {
  215. // 调用图像处理方法
  216. //ProcessDragFile(file);
  217. DragRecong(file);
  218. }
  219. else
  220. {
  221. MessageBox.Show(Application.Current.MainWindow,
  222. $"文件 {file} 不符合要求:必须是小于 200KB 的 JPG 文件,且图像尺寸必须为 320x240。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  223. }
  224. }
  225. }
  226. public async void DragRecong(string srcImagePath)
  227. {
  228. var singleDetail = new SingleDetailItem()
  229. {
  230. SingleDetailId = Guid.NewGuid().ToString(),
  231. CreateTime = ThisApp.GetNowTime_yyyyMMddHHmmss(),
  232. SrcImage = srcImagePath
  233. };
  234. //DBSingle.InsertTSingleDetail0(singleDetail);
  235. bool blRun = await RunAI(true,singleDetail);
  236. Console.Write($"Run:{blRun}");
  237. if (blRun)
  238. {
  239. SingleDetailPage.PageNumber = 1;
  240. await LoadSingleDetailItemList();
  241. if (SingleDetailItemList.Count > 0)
  242. {
  243. SelectedSingleDetailItem = SingleDetailItemList[0];
  244. dgSingle.ScrollIntoView(dgSingle.Items[0]);
  245. }
  246. MessageBox.Show(Application.Current.MainWindow, "识别成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
  247. }
  248. else
  249. {
  250. MessageBox.Show(Application.Current.MainWindow, "识别识别!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  251. }
  252. }
  253. //处理拖拽的文件
  254. //private void ProcessDragFile(string filePath)
  255. //{
  256. // //AddNewSingTask(filePath);
  257. // InsertFilesWithProgress(new List<string>() { filePath });
  258. //}
  259. //public async void InsertFilesWithProgress(List<string> filePaths)
  260. //{
  261. // // 弹出一个非模式对话框来显示进度
  262. // ProgressDialog progressDialog = new ProgressDialog()
  263. // {
  264. // Owner = Application.Current.MainWindow
  265. // };
  266. // progressDialog.Show();
  267. // // 任务来异步执行文件插入
  268. // await Task.Run(() => InsertFilesToDatabase(filePaths, progressDialog));
  269. // // 关闭进度对话框
  270. // progressDialog.Close();
  271. // //刷新CurItem
  272. // //OnStandItemCountChanged?.Invoke(this, new StandItemCountChangedEventArgs(CurStandItem));
  273. // //刷新数据(并定位第一条)
  274. // SingleDetailPage.PageNumber = 1;
  275. // LoadSingleDetailItemList();
  276. // SelectedSingleDetailItem = SingleDetailItemList[0];
  277. //}
  278. public void InsertFilesToDatabase(List<string> filePaths, ProgressDialog progressDialog)
  279. {
  280. int totalFiles = filePaths.Count;
  281. int currentFile = 0;
  282. foreach (var filePath in filePaths)
  283. {
  284. // 插入文件路径到数据库
  285. //InsertFileToDatabase(filePath);
  286. TSingleDetail singleDetail = new TSingleDetail()
  287. {
  288. SingleDetailId = Guid.NewGuid().ToString(),
  289. CreateTime = ThisApp.GetNowTime_yyyyMMddHHmmss(),
  290. SrcImage = filePath
  291. };
  292. DBSingle.InsertTSingleDetail0(singleDetail);
  293. // 更新进度条
  294. currentFile++;
  295. UpdateProgress(progressDialog, currentFile, totalFiles);
  296. }
  297. }
  298. public void UpdateProgress(ProgressDialog progressDialog, int currentFile, int totalFiles)
  299. {
  300. // 更新进度条的进度
  301. double progress = (double)currentFile / totalFiles * 100;
  302. progressDialog.UpdateProgress(progress);
  303. }
  304. public async void NextPage()
  305. {
  306. if (SingleDetailPage.PageNumber < SingleDetailPage.PageCount)
  307. {
  308. SingleDetailPage.PageNumber += 1;
  309. await LoadSingleDetailItemList();
  310. }
  311. }
  312. public async void PrePage()
  313. {
  314. if (SingleDetailPage.PageNumber > 1)
  315. {
  316. SingleDetailPage.PageNumber -= 1;
  317. await LoadSingleDetailItemList();
  318. }
  319. }
  320. public async void FirstPage()
  321. {
  322. if (SingleDetailPage.PageNumber > 1)
  323. {
  324. SingleDetailPage.PageNumber = 1;
  325. await LoadSingleDetailItemList();
  326. }
  327. }
  328. public async void LastPage()
  329. {
  330. if (SingleDetailPage.PageNumber < SingleDetailPage.PageCount)
  331. {
  332. SingleDetailPage.PageNumber = SingleDetailPage.PageCount;
  333. await LoadSingleDetailItemList();
  334. }
  335. }
  336. public async void SpeciPage(int pageNumber)
  337. {
  338. if (pageNumber != SingleDetailPage.PageNumber &&
  339. pageNumber > 0 && pageNumber <= SingleDetailPage.PageCount)
  340. {
  341. SingleDetailPage.PageNumber = pageNumber;
  342. await LoadSingleDetailItemList();
  343. }
  344. }
  345. // 辅助方法:查找指定类型的祖先元素
  346. public static T FindAncestor<T>(DependencyObject dependencyObject) where T : DependencyObject
  347. {
  348. var parent = VisualTreeHelper.GetParent(dependencyObject);
  349. if (parent == null) return null;
  350. var parentT = parent as T;
  351. return parentT ?? FindAncestor<T>(parent);
  352. }
  353. private void BtnDelDetailItem_Click(object sender, RoutedEventArgs e)
  354. {
  355. //删除选中项
  356. Button button = sender as Button;
  357. if (button == null) return;
  358. DataGridRow row = FindAncestor<DataGridRow>(button);
  359. if (row == null) return;
  360. //获取当前行绑定的数据项
  361. SingleDetailItem selectedItem = row.Item as SingleDetailItem;
  362. DeleteSelectedItem(selectedItem);
  363. }
  364. private void BtnRecongDetailItem_Click(object sender, RoutedEventArgs e)
  365. {
  366. Button button = sender as Button;
  367. if (button == null) return;
  368. DataGridRow row = FindAncestor<DataGridRow>(button);
  369. if (row == null) return;
  370. //获取当前行绑定的数据项
  371. SingleDetailItem selectedItem = row.Item as SingleDetailItem;
  372. RecongSingleDetail(false, SelectedSingleDetailItem);
  373. }
  374. private void BtnLogViewer_Click(object sender, RoutedEventArgs e)
  375. {
  376. Button button = sender as Button;
  377. if (button == null) return;
  378. DataGridRow row = FindAncestor<DataGridRow>(button);
  379. if (row == null) return;
  380. //获取当前行绑定的数据项
  381. SingleDetailItem selectedItem = row.Item as SingleDetailItem;
  382. ShowLogViewer(selectedItem);
  383. }
  384. private void ShowLogViewer(SingleDetailItem selectedItem)
  385. {
  386. if (selectedItem.LogPath != null && File.Exists(selectedItem.LogPath))
  387. {
  388. LogViewerWindow dialog = new LogViewerWindow(selectedItem.DstImage, selectedItem.LogPath)
  389. {
  390. Owner = Application.Current.MainWindow,
  391. WindowStartupLocation = WindowStartupLocation.CenterOwner
  392. };
  393. dialog.ShowDialog();
  394. }
  395. }
  396. private async void DeleteSelectedItem(SingleDetailItem selectedItem)
  397. {
  398. if (selectedItem == null) return;
  399. MessageBoxResult result = MessageBox.Show("确定要删除此条目吗?", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Question);
  400. if (result != MessageBoxResult.Yes) return;
  401. string titleInfo = "正在删除,请稍后...";
  402. WaitWindow waitWindow = new WaitWindow(titleInfo)
  403. {
  404. Owner = Application.Current.MainWindow,
  405. WindowStartupLocation = WindowStartupLocation.CenterOwner
  406. };
  407. waitWindow.Show();
  408. try
  409. {
  410. bool deleteSuccess = false;
  411. await Task.Run(() =>
  412. {
  413. deleteSuccess = DBSingle.DeleteTSingleDetailById(selectedItem.SingleDetailId);
  414. });
  415. if (deleteSuccess)
  416. {
  417. Application.Current.Dispatcher.Invoke(() =>
  418. {
  419. // 从数据源中移除该条目
  420. SingleDetailItemList.Remove(selectedItem);
  421. SelectedSingleDetailItem = null;
  422. });
  423. }
  424. }
  425. catch (Exception ex)
  426. {
  427. MessageBox.Show(Application.Current.MainWindow, $"删除失败:{ex.Message}", "错误",
  428. MessageBoxButton.OK, MessageBoxImage.Error);
  429. }
  430. finally
  431. {
  432. waitWindow.Close();
  433. }
  434. }
  435. //清空所有的列表数据
  436. public async void ClearAllSingleDetail()
  437. {
  438. //清空提示
  439. MessageBoxResult result = MessageBox.Show("确定要清空所有数据吗?", "确认清空", MessageBoxButton.YesNo, MessageBoxImage.Question);
  440. if (result != MessageBoxResult.Yes) return;
  441. string titleInfo = "正在清空数据,请稍后...";
  442. WaitWindow waitWindow = new WaitWindow(titleInfo)
  443. {
  444. Owner = Application.Current.MainWindow,
  445. WindowStartupLocation = WindowStartupLocation.CenterOwner
  446. };
  447. waitWindow.Show();
  448. try
  449. {
  450. bool blClearAll = false;
  451. await Task.Run(() =>
  452. {
  453. blClearAll = DBSingle.ClearTSingleDetailTable();
  454. });
  455. if (blClearAll)
  456. {
  457. SingleDetailPage.InitDefaulValue();
  458. await LoadSingleDetailItemList();
  459. }
  460. }
  461. catch (Exception ex)
  462. {
  463. MessageBox.Show(Application.Current.MainWindow, $"清空失败:{ex.Message}", "错误",
  464. MessageBoxButton.OK, MessageBoxImage.Error);
  465. }
  466. finally
  467. {
  468. waitWindow.Close();
  469. }
  470. }
  471. private void MiDelete_Click(object sender, RoutedEventArgs e)
  472. {
  473. if (SelectedSingleDetailItem == null) return;
  474. //获取当前行绑定的数据项
  475. DeleteSelectedItem(SelectedSingleDetailItem);
  476. }
  477. private void MiRecong_Click(object sender, RoutedEventArgs e)
  478. {
  479. if (SelectedSingleDetailItem == null) return;
  480. RecongSingleDetail(false, SelectedSingleDetailItem);
  481. }
  482. private async void RecongSingleDetail(bool isAdd, SingleDetailItem singleDetailIte)
  483. {
  484. string jpgFile = singleDetailIte.SrcImage;
  485. if (!File.Exists(jpgFile))
  486. {
  487. MessageBox.Show(Application.Current.MainWindow, $"文件:{jpgFile}不存在!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
  488. return;
  489. }
  490. bool blRun = await RunAI(isAdd, singleDetailIte);
  491. if (blRun)
  492. {
  493. MessageBox.Show(Application.Current.MainWindow, "识别成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
  494. }
  495. else
  496. {
  497. MessageBox.Show(Application.Current.MainWindow, "识别失败!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  498. }
  499. }
  500. private async Task<bool> RunAI(bool isAdd,SingleDetailItem singleDetailItem)
  501. {
  502. FaRun faRun = new FaRun();
  503. faRun.OnAiRealLogInfo += FaRun_OnAiRealLogInfo;
  504. string titleInfo = "正在识别,请稍后...";
  505. WaitWindow waitWindow = new WaitWindow(titleInfo)
  506. {
  507. Owner = Application.Current.MainWindow,
  508. WindowStartupLocation = WindowStartupLocation.CenterOwner
  509. };
  510. waitWindow.Show();
  511. try
  512. {
  513. TSingleDetail newSingleDetail = null;
  514. bool blRun = await Task.Run(() =>
  515. {
  516. try
  517. {
  518. ResultModel resultModel = faRun.StartRecognition(singleDetailItem.SrcImage);
  519. if (resultModel == null) return false;
  520. newSingleDetail = new TSingleDetail(singleDetailItem, resultModel);
  521. //更新数据
  522. bool blOpration;
  523. if (isAdd)
  524. {
  525. blOpration = DBSingle.InsertSingleDetail(newSingleDetail);
  526. }
  527. else
  528. {
  529. blOpration = DBSingle.UpdateSingleDetail(newSingleDetail);
  530. }
  531. return blOpration;
  532. }
  533. catch(Exception ex)
  534. {
  535. Console.WriteLine(ex.Message);
  536. return false;
  537. }
  538. });
  539. //在主线程中更新DataGrid的Row数据
  540. if (blRun && !isAdd && newSingleDetail != null)
  541. {
  542. //singleDetailItem = newSingleDetail;
  543. ObjectHelper.CopyMatchingFields(newSingleDetail, singleDetailItem);
  544. }
  545. return blRun;
  546. }
  547. catch (Exception ex)
  548. {
  549. MessageBox.Show(Application.Current.MainWindow, $"识别[{singleDetailItem.SrcImage}]时出错:{ex.Message}", "错误",
  550. MessageBoxButton.OK, MessageBoxImage.Error);
  551. return false;
  552. }
  553. finally
  554. {
  555. waitWindow.Close();
  556. }
  557. }
  558. private void FaRun_OnAiRealLogInfo(object sender, AiRealLogEventArgs e)
  559. {
  560. Console.Write(e.mLogInfo);
  561. }
  562. private void MiViewLog_Click(object sender, RoutedEventArgs e)
  563. {
  564. if(SelectedSingleDetailItem != null)
  565. {
  566. ShowLogViewer(SelectedSingleDetailItem);
  567. }
  568. }
  569. ///////////////////////////////////////////////////////////////////////////
  570. }
  571. //自定义事件参数类
  572. public class SingleDetailItemChangedEventArgs : EventArgs
  573. {
  574. public SingleDetailItem SelectedSingleDetailItem { get; }
  575. public SingleDetailItemChangedEventArgs(SingleDetailItem selectedData)
  576. {
  577. SelectedSingleDetailItem = selectedData;
  578. }
  579. }
  580. }