UCStandMain.xaml.cs 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355
  1. using MeterVision.Config;
  2. using MeterVision.db;
  3. using MeterVision.Dlg;
  4. using MeterVision.Helper;
  5. using MeterVision.model;
  6. using MeterVision.Util;
  7. using Microsoft.Win32;
  8. using Newtonsoft.Json;
  9. using OfficeOpenXml;
  10. using OfficeOpenXml.Style;
  11. using Ookii.Dialogs.Wpf;
  12. using System;
  13. using System.Collections.Generic;
  14. using System.Collections.ObjectModel;
  15. using System.ComponentModel;
  16. using System.IO;
  17. using System.Linq;
  18. using System.Text;
  19. using System.Text.RegularExpressions;
  20. using System.Threading;
  21. using System.Threading.Tasks;
  22. using System.Windows;
  23. using System.Windows.Controls;
  24. using System.Windows.Data;
  25. using System.Windows.Documents;
  26. using System.Windows.Input;
  27. using System.Windows.Media;
  28. using System.Windows.Media.Imaging;
  29. using System.Windows.Navigation;
  30. //using System.Windows.Shapes;
  31. namespace MeterVision.Stand
  32. {
  33. /// <summary>
  34. /// UCStand.xaml 的交互逻辑
  35. /// </summary>
  36. public partial class UCStandMain : UserControl, INotifyPropertyChanged
  37. {
  38. private const int COLUMN_LEFT_WIDTH = 220;
  39. private const int COLUMN_RIGHT_WIDTH = 400;
  40. private bool LeftVisiable = true; //表示左侧的显示状态
  41. private bool RightVisiable = true; //表示右侧的显示状态
  42. public event PropertyChangedEventHandler PropertyChanged;
  43. protected void OnPropertyChanged(string propertyName)
  44. {
  45. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  46. }
  47. //ItemsSource="{Binding StationMarkTypeKVs}"
  48. // SelectedValue="{Binding SelectedStationMarkType,Mode=TwoWay}"
  49. private SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
  50. private SemaphoreSlim _semaphore2 = new SemaphoreSlim(1, 1);
  51. public ObservableCollection<KeyValuePair<MarkFindType, string>> StationMarkTypeKVs { get; set; }
  52. private void InitStationMarkTypeKVS()
  53. {
  54. StationMarkTypeKVs = new ObservableCollection<KeyValuePair<MarkFindType, string>>()
  55. {
  56. new KeyValuePair<MarkFindType, string>(MarkFindType.ALL,"所有"),
  57. new KeyValuePair<MarkFindType, string>(MarkFindType.MARK_YES,"已配置"),
  58. new KeyValuePair<MarkFindType, string>(MarkFindType.MARK_NO, "未配置")
  59. };
  60. }
  61. private MarkFindType _selectedStationMarkType;
  62. public MarkFindType SelectedStationMarkType
  63. {
  64. get => _selectedStationMarkType;
  65. set
  66. {
  67. if(_selectedStationMarkType != value)
  68. {
  69. _selectedStationMarkType = value;
  70. //OnPropertyChanged(nameof(SelectedStationMarkType));
  71. if (SelectedStandItem != null)
  72. {
  73. ucStationGrid.ChangeFindAsync(FindStationId, SelectedStationMarkType, SelectedStandItem.StandId);
  74. }
  75. }
  76. }
  77. }
  78. public PageModel StandPage { get; set; }
  79. //定义模板目录数据源
  80. public BulkObservableCollection<StandItem> StandItemList { get; set; }
  81. // 定义"标准答案编辑"依赖属性
  82. public static readonly DependencyProperty IsResultEditingProperty =
  83. DependencyProperty.Register("IsResultEditing", typeof(bool), typeof(UCStandMain), new PropertyMetadata(false));
  84. public bool IsResultEditing
  85. {
  86. get { return (bool)GetValue(IsResultEditingProperty); }
  87. set { SetValue(IsResultEditingProperty, value); }
  88. }
  89. private StandItem _selectedStandItem;
  90. public StandItem SelectedStandItem
  91. {
  92. get => _selectedStandItem;
  93. set
  94. {
  95. if (_selectedStandItem != value)
  96. {
  97. if (!_semaphore2.Wait(0)) return;
  98. try
  99. {
  100. _selectedStandItem = value;
  101. OnPropertyChanged(nameof(SelectedStandItem)); //通知更新
  102. if (_selectedStandItem != null)
  103. {
  104. ucStationGrid.ChangeFindAsync(FindStationId, SelectedStationMarkType, _selectedStandItem.StandId);
  105. }
  106. else
  107. {
  108. ucStationGrid.ChangeFindAsync(FindStationId, SelectedStationMarkType, "");
  109. }
  110. Apply_UCStandDetaisl_Title(value);
  111. }
  112. catch { }
  113. finally
  114. {
  115. _semaphore2.Release();
  116. }
  117. }
  118. }//set
  119. }
  120. private StationItem _selectedStationItem;
  121. public StationItem SelectedStationItem
  122. {
  123. get => _selectedStationItem;
  124. set
  125. {
  126. if(_selectedStationItem != value){
  127. _selectedStationItem = value;
  128. OnPropertyChanged(nameof(SelectedStationItem));
  129. ucStandGird.CurStationItem = value;
  130. //Apply_UCStandDetaisl_Title(value);
  131. Apply_Station_Title(value);
  132. }
  133. }
  134. }
  135. private int _totalStandRecords;
  136. public int TotalStandRecords
  137. {
  138. get => _totalStandRecords;
  139. set
  140. {
  141. if (_totalStandRecords != value)
  142. {
  143. _totalStandRecords = value;
  144. OnPropertyChanged(nameof(TotalStandRecords));
  145. }
  146. }
  147. }
  148. public CfginiItem mConfigItem { get; set; }
  149. private void Apply_UCStandDetaisl_Title(StandItem standItem)
  150. {
  151. txtStandName.Text = standItem == null ? "" : $"{standItem.Index}.";
  152. }
  153. //站点名称
  154. private void Apply_Station_Title(StationItem stationItem)
  155. {
  156. pnlDetailsFunc.Visibility = stationItem == null ? Visibility.Hidden : Visibility.Visible;
  157. txtStationName.Text = stationItem == null ? "请选择站点" : $"站点: {stationItem.StationId}";
  158. }
  159. private void InitRightControls(StandDetailItem standDetailsItem)
  160. {
  161. pnlImage.Visibility = txtRightItemIndex.Visibility =
  162. standDetailsItem == null ? Visibility.Collapsed : Visibility.Visible;
  163. //pnlResult.Visibility = Visibility.Hidden;
  164. }
  165. private string _findStationId;
  166. public string FindStationId
  167. {
  168. get => _findStationId;
  169. set
  170. {
  171. if (_findStationId != value)
  172. {
  173. _findStationId = value;
  174. OnPropertyChanged(nameof(FindStationId));
  175. //ucStationGrid.ChangeFindStationId(FindStationId);
  176. }
  177. }
  178. }
  179. public UCStandMain()
  180. {
  181. InitializeComponent();
  182. StandItemList = new BulkObservableCollection<StandItem>();
  183. dgStand.ItemsSource = StandItemList;
  184. //this.btnStandExport.Click += BtnStandExport_Click;
  185. ucStandGird.OnSelectedStandDetailItemChanged += UcStandGird_OnSelectedStandDetailsItemChanged;
  186. IsResultEditing = false;
  187. Apply_UCStandDetaisl_Title(null);
  188. Apply_Station_Title(null);
  189. //SelectedStandItem = null;
  190. txtFindStationId.Text = "";
  191. FindStationId = "";
  192. InitRightControls(null);
  193. mConfigItem = CfginiItem.GetConfigItem();
  194. StandPage = new PageModel
  195. {
  196. //PageSize = mConfigItem.CatalogPageSize,
  197. PageSize = mConfigItem.PageSize1, //mConfigItem.StandCatalogPageSize,
  198. PageNumber = 1,
  199. };
  200. //LoadStandItemList();
  201. //ucStandGird.OnStandItemCountChanged += UcStandGird_OnStandItemCountChanged1;
  202. //UcStandGird_OnStandItemCountChanged;
  203. ucStandGird.OnDeleteStandDetailItem += UcStandGird_OnDeleteStandDetailItem;
  204. //mConfigItem.OnStandCatalogPageSizeChanged += MConfigItem_OnStandCatalogPageSizeChanged;
  205. mConfigItem.OnPageSize1Changed += MConfigItem_OnPageSize1Changed;
  206. this.DataContext = this;
  207. // 启动异步初始化,确保不会阻塞构造函数
  208. LoadStandItemListAsync();
  209. InitStationMarkTypeKVS();
  210. SelectedStationMarkType = MarkFindType.ALL;
  211. //控制左右2侧栏目的显示
  212. LeftVisiable = true;
  213. ChangeLeftVisiable(LeftVisiable);
  214. RightVisiable = true;
  215. ChangeRightVisiable(RightVisiable);
  216. ucStationGrid.OnStationItemChange += UcStationGrid_OnStationItemChange;
  217. //ucStationGrid.Station_Config += UcStationGrid_Station_Config;
  218. ucStandGird.OnStandDetailMark += UcStandGird_OnStandDetailMark;
  219. }
  220. private void UcStandGird_OnStandDetailMark(string standId, string stationId)
  221. {
  222. //throw new NotImplementedException();
  223. ucStationGrid.ChangeMarkCount();
  224. }
  225. //修改参数
  226. //private void UcStationGrid_Station_Config(StationItem item)
  227. //{
  228. // //第一条数据
  229. // EditStationDlg2 dialog = new EditStationDlg2(item)
  230. // {
  231. // Owner = Application.Current.MainWindow,
  232. // WindowStartupLocation = WindowStartupLocation.CenterOwner
  233. // };
  234. // if (dialog.ShowDialog() == true)
  235. // {
  236. // //stationItem = dialog.mStationItem;
  237. // item = dialog.mStationItem;
  238. // }
  239. //}
  240. private void UcStationGrid_OnStationItemChange(StationItem stationItem)
  241. {
  242. SelectedStationItem = stationItem;
  243. }
  244. private async void MConfigItem_OnPageSize1Changed(int pageSize1)
  245. {
  246. if (!_semaphore.Wait(0)) return; // 防止重复点击
  247. try
  248. {
  249. StandPage.InitDefaulValue(pageSize1);
  250. bool blLoad = await LoadStandItemList();
  251. if (blLoad)
  252. {
  253. SelectedStandItem = null;
  254. }
  255. }
  256. catch { }
  257. finally
  258. {
  259. _semaphore.Release();
  260. }
  261. }
  262. //private async void MConfigItem_OnStandCatalogPageSizeChanged(int pageSize)
  263. //{
  264. // //throw new NotImplementedException();
  265. // StandPage.InitDefaulValue(pageSize);
  266. // bool blLoad = await LoadStandItemList();
  267. // if (blLoad)
  268. // {
  269. // SelectedStandItem = null;
  270. // }
  271. //}
  272. private async void LoadStandItemListAsync()
  273. {
  274. if (!_semaphore.Wait(0)) return; // 防止重复点击
  275. try
  276. {
  277. await LoadStandItemList();
  278. }
  279. catch { }
  280. finally
  281. {
  282. _semaphore.Release();
  283. }
  284. }
  285. //private void UcStandGird_OnStandItemCountChanged(object sender, StandItemCountChangedEventArgs e)
  286. //{
  287. // //Detail的数量发生变化
  288. // RefreshStandItemById(e.mStandItem.StandId);
  289. //}
  290. //private void UcStandGird_OnStandItemCountChanged1(StandItem standItem)
  291. //{
  292. // //Detail的数量发生变化
  293. // RefreshStandItemById(standItem.StandId);
  294. //}
  295. private void UcStandGird_OnDeleteStandDetailItem(string standId)
  296. {
  297. RefreshStandItemById(standId);
  298. }
  299. private async void RefreshStandItemById(string standId)
  300. {
  301. if ( string.IsNullOrWhiteSpace(standId) ) return;
  302. VStand vStand = null;
  303. await Task.Run(() =>
  304. {
  305. vStand = DBStand.GetVStandById(standId);
  306. });
  307. if (vStand != null)
  308. {
  309. //var NewStandItem = new StandItem(vStand);
  310. foreach (var standItem in StandItemList)
  311. {
  312. if (standItem.StandId == vStand.StandId)
  313. {
  314. // ObjectHelper.CopyMatchingFields(NewStandItem, standItem);
  315. ObjectHelper.CopyMatchingFields(vStand, standItem);
  316. break;
  317. }
  318. }//foreach
  319. }//if vpatch!=null
  320. }
  321. private async Task<bool> LoadStandItemList()
  322. {
  323. StandItemList.Clear();
  324. try
  325. {
  326. var result = await Task.Run(() =>
  327. {
  328. return DBStand.GetPagedVStands(StandPage.PageNumber, StandPage.PageSize);
  329. });
  330. TotalStandRecords = result.Item1;
  331. StandPage.PageCount = result.Item2;
  332. List<VStand> stands = result.Item3;
  333. //int index = 0;
  334. //foreach (VStand vStand in stands)
  335. //{
  336. // index++;
  337. // StandItem standItem = new StandItem(vStand);
  338. // standItem.Index = index + (StandPage.PageNumber - 1) * StandPage.PageSize;
  339. // StandItemList.Add(standItem);
  340. //}
  341. var standItems = stands.Select((vStand, i) => new StandItem(vStand)
  342. {
  343. Index = (StandPage.PageNumber - 1) * StandPage.PageSize + i + 1
  344. }).ToList();
  345. StandItemList.AddRange(standItems);
  346. if (StandItemList.Count > 0)
  347. {
  348. //dgStand.ScrollIntoView(StandItemList[0]);
  349. }
  350. return true;
  351. }
  352. catch (Exception ex)
  353. {
  354. MessageBox.Show(Application.Current.MainWindow,
  355. $"加载数据时发生错误:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  356. return false;
  357. }
  358. }
  359. private void UcStandGird_OnSelectedStandDetailsItemChanged(object sender, StandDetailItemChangedEventArgs e)
  360. {
  361. InitRightControls(e.SelectedDataItem);
  362. txtRightItemIndex.Text = string.Empty;
  363. if (e.SelectedDataItem != null)
  364. {
  365. ucImageSource.ImageSource = e.SelectedDataItem.SrcImage;
  366. ucImageSource.ImageName = "原始图片";
  367. //txtRightResult.Text = e.SelectedDataItem.StandValue;
  368. IsResultEditing = false;
  369. if(SelectedStandItem != null)
  370. {
  371. txtRightItemIndex.Text = $"{SelectedStandItem.Index}. - {e.SelectedDataItem.Index}.";
  372. }
  373. }
  374. }
  375. //导出模板
  376. private void BtnStandExport_Click(object sender, RoutedEventArgs e)
  377. {
  378. //查询所有的数据
  379. if (SelectedStandItem == null) return;
  380. List<TStandDetail> standDetails = DBStand.GetAllStandDetails(SelectedStandItem.StandId);
  381. if (standDetails.Count <= 0) return;
  382. string fileName = $"{SelectedStandItem.StandName}_{standDetails.Count}.xlsx";
  383. //创建保存文件对话框
  384. VistaSaveFileDialog saveFileDialog = new VistaSaveFileDialog
  385. {
  386. Filter = "Excel 文件 (*.xlsx)|*.xlsx",
  387. FileName = fileName,
  388. Title = "选择模板保存路径"
  389. };
  390. // 如果用户选择了路径并点击保存
  391. if (saveFileDialog.ShowDialog() == true){
  392. string titleInfo = "正在导出模板数据,请稍后...";
  393. WaitWindow waitWindow = new WaitWindow(titleInfo)
  394. {
  395. Owner = Application.Current.MainWindow,
  396. WindowStartupLocation = WindowStartupLocation.CenterOwner
  397. };
  398. waitWindow.Show();
  399. string filePath = saveFileDialog.FileName;
  400. try{
  401. // 创建Excel包
  402. using (ExcelPackage package = new ExcelPackage()){
  403. var worksheet = package.Workbook.Worksheets.Add("Sheet1");
  404. // 表头
  405. worksheet.Cells[1, 1].Value = "图像";
  406. worksheet.Cells[1, 2].Value = "标准答案";
  407. // 设置表头样式
  408. using (var range = worksheet.Cells[1, 1, 1, 2])
  409. {
  410. //range.Style.Font.Bold = false;
  411. range.Style.Font.Name = "等线";
  412. range.Style.Font.Size = 11;
  413. //range.Style.Fill.PatternType = ExcelFillStyle.Solid;
  414. //range.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightBlue);
  415. range.AutoFitColumns();
  416. }
  417. // 填充数据
  418. for (int i = 0; i < standDetails.Count; i++)
  419. {
  420. worksheet.Cells[i + 2, 1].Value = standDetails[i].SrcImage;
  421. worksheet.Cells[i + 2, 2].Value = standDetails[i].StandValue;
  422. // 设置行字体
  423. worksheet.Cells[i + 2, 1, i + 2, 2].Style.Font.Name = "等线";
  424. worksheet.Cells[i + 2, 1, i + 2, 2].Style.Font.Size = 11;
  425. //worksheet.Cells[i + 2, 1, i + 2, 2].Style.Font.Color.SetColor(System.Drawing.Color.Black);
  426. }
  427. // 设置列宽
  428. worksheet.Column(1).Width = 50; // 姓名列
  429. worksheet.Column(2).Width = 20; // 年龄列
  430. // 或者自动调整列宽
  431. //worksheet.Cells.AutoFitColumns();
  432. // 保存到用户选择的路径
  433. FileInfo excelFile = new FileInfo(filePath);
  434. package.SaveAs(excelFile);
  435. MessageBox.Show("Excel导出成功!");
  436. }
  437. }
  438. catch (Exception ex){
  439. MessageBox.Show($"导出失败: {ex.Message}");
  440. }
  441. waitWindow.Close();
  442. }
  443. }
  444. private void BtnStandImport_Click(object sender, RoutedEventArgs e)
  445. {
  446. //throw new NotImplementedException();
  447. }
  448. private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
  449. {
  450. // 只允许数字输入
  451. e.Handled = !Regex.IsMatch(e.Text, @"^\d$");
  452. }
  453. private void TxtRightResult_PreviewTextInput(object sender, TextCompositionEventArgs e)
  454. {
  455. // 只允许数字输入
  456. e.Handled = !Regex.IsMatch(e.Text, @"^\d$");
  457. }
  458. private void BtnEditRightResult_Click(object sender, RoutedEventArgs e)
  459. {
  460. IsResultEditing = true;
  461. }
  462. private void BtnSubmitRightResult_Click(object sender, RoutedEventArgs e)
  463. {
  464. IsResultEditing = false;
  465. }
  466. private void BtnCancelRightResult_Click(object sender, RoutedEventArgs e)
  467. {
  468. IsResultEditing = false;
  469. }
  470. private async void BtnStandNextPage_Click(object sender, RoutedEventArgs e)
  471. {
  472. if (!_semaphore.Wait(0)) return; // 防止重复点击
  473. try
  474. {
  475. if (StandPage.PageNumber < StandPage.PageCount)
  476. {
  477. StandPage.PageNumber += 1;
  478. bool blLoad = await LoadStandItemList();
  479. if (blLoad && StandItemList.Count > 0)
  480. {
  481. //dgStand.ScrollIntoView(StandItemList[0]);
  482. var scrollViewer = GetDgStandScrollViewer(dgStand);
  483. scrollViewer?.ScrollToTop();
  484. }
  485. }
  486. }
  487. catch { }
  488. finally
  489. {
  490. _semaphore.Release();
  491. }
  492. }
  493. private async void BtnStandPrePage_Click(object sender, RoutedEventArgs e)
  494. {
  495. if (!_semaphore.Wait(0)) return; // 防止重复点击
  496. try
  497. {
  498. if (StandPage.PageNumber > 1)
  499. {
  500. StandPage.PageNumber -= 1;
  501. bool blLoad = await LoadStandItemList();
  502. if (blLoad && StandItemList.Count > 0)
  503. {
  504. //dgStand.ScrollIntoView(StandItemList[0]);
  505. var scrollViewer = GetDgStandScrollViewer(dgStand);
  506. scrollViewer?.ScrollToTop();
  507. }
  508. }
  509. }
  510. catch { }
  511. finally
  512. {
  513. _semaphore.Release();
  514. }
  515. }
  516. private void BtnStandDetailFirstPage_Click(object sender, RoutedEventArgs e)
  517. {
  518. ucStandGird.FirstPage();
  519. }
  520. private void BtnStandDetailNextPage_Click(object sender, RoutedEventArgs e)
  521. {
  522. ucStandGird.NextPage();
  523. }
  524. private void BtnStanddetailPrePage_Click(object sender, RoutedEventArgs e)
  525. {
  526. ucStandGird.PrePage();
  527. }
  528. private void BtnStandDetailLastPage_Click(object sender, RoutedEventArgs e)
  529. {
  530. ucStandGird.LastPage();
  531. }
  532. private void BtnStandDetailSpeciPage_Click(object sender, RoutedEventArgs e)
  533. {
  534. try
  535. {
  536. int pageNumber = int.Parse(txtStandDetailPageNumber.Text.ToString());
  537. ucStandGird.SpeciPage(pageNumber);
  538. }
  539. catch
  540. {
  541. }
  542. }
  543. private async void BtnAddStand_Click(object sender, RoutedEventArgs e)
  544. {
  545. //List<string> tableNames = SQLiteHelper.GetAllTables();
  546. if (!_semaphore.Wait(0)) return; // 防止重复点击
  547. try
  548. {
  549. var dialog = new AddStandDialog()
  550. {
  551. Owner = Application.Current.MainWindow,
  552. WindowStartupLocation = WindowStartupLocation.CenterOwner
  553. };
  554. if (dialog.ShowDialog() == true)
  555. {
  556. StandPage.InitDefaulValue();
  557. bool blLoad = await LoadStandItemList();
  558. if (blLoad && StandItemList.Count > 0)
  559. {
  560. SelectedStandItem = StandItemList[0];
  561. //dgStand.ScrollIntoView(StandItemList[0]);
  562. var scrollViewer = GetDgStandScrollViewer(dgStand);
  563. scrollViewer?.ScrollToTop();
  564. }
  565. }
  566. }
  567. catch { }
  568. finally
  569. {
  570. _semaphore.Release();
  571. }
  572. }
  573. private void BtnDelStand_Click(object sender, RoutedEventArgs e)
  574. {
  575. DeleteStandItem();
  576. }
  577. private async void DeleteStandItem()
  578. {
  579. //bool blDelete = false;
  580. if (SelectedStandItem == null) return; // blDelete;
  581. MessageBoxResult result = MessageBox.Show(
  582. $"您确定要删除[{SelectedStandItem.StandName}]任务吗?\n此操作无法撤销。",
  583. "确认删除",
  584. MessageBoxButton.YesNo, // 提供“是”和“否”按钮
  585. MessageBoxImage.Warning // 使用警告图标
  586. );
  587. if (result != MessageBoxResult.Yes)
  588. {
  589. return; // blDelete;
  590. }
  591. //开始删除操作
  592. string titleInfo = "正在删除,请稍候...";
  593. WaitWindow waitWindow = new WaitWindow(titleInfo)
  594. {
  595. Owner = Application.Current.MainWindow,
  596. WindowStartupLocation = WindowStartupLocation.CenterOwner
  597. };
  598. waitWindow.Show();
  599. try
  600. {
  601. //执行异步删除逻辑
  602. bool deleteSuccess = false;
  603. await Task.Run(() =>
  604. {
  605. deleteSuccess = DBStand.DeleteStandAndDetails(SelectedStandItem.StandId);
  606. //Task.Delay(200).Wait(); // 模拟延迟
  607. });
  608. if (deleteSuccess)
  609. {
  610. StandItemList.Remove(SelectedStandItem);
  611. SelectedStandItem = null;
  612. TotalStandRecords -= 1;
  613. //blDelete = true;
  614. }
  615. }
  616. catch (Exception ex)
  617. {
  618. MessageBox.Show(Application.Current.MainWindow, $"删除失败:{ex.Message}", "错误",
  619. MessageBoxButton.OK, MessageBoxImage.Error);
  620. }
  621. finally
  622. {
  623. //关闭等待窗口
  624. waitWindow.Close();
  625. }
  626. //return blDelete;
  627. }
  628. private async void BtnRefresh_Click(object sender, RoutedEventArgs e)
  629. {
  630. if (!_semaphore.Wait(0)) return; // 防止重复点击
  631. try
  632. {
  633. StandPage.InitDefaulValue();
  634. bool blLoad = await LoadStandItemList();
  635. if (blLoad && StandItemList.Count > 0)
  636. {
  637. //dgStand.ScrollIntoView(StandItemList[0]);
  638. var scrollViewer = GetDgStandScrollViewer(dgStand);
  639. scrollViewer?.ScrollToTop();
  640. }
  641. }
  642. catch { }
  643. finally
  644. {
  645. _semaphore.Release();
  646. }
  647. }
  648. private void MiDeleteStand_Click(object sender, RoutedEventArgs e)
  649. {
  650. DeleteStandItem();
  651. }
  652. private void MiUpdateStandname_Click(object sender, RoutedEventArgs e)
  653. {
  654. if (SelectedStandItem == null) return;
  655. EditNameDlg editNameDlg = new EditNameDlg("模板", SelectedStandItem.StandName)
  656. {
  657. Owner = Application.Current.MainWindow,
  658. WindowStartupLocation = WindowStartupLocation.CenterOwner
  659. };
  660. if (editNameDlg.ShowDialog() == true)
  661. {
  662. UpdateStandName(SelectedStandItem, editNameDlg.EditName);
  663. }
  664. }
  665. private async void UpdateStandName(StandItem standItem,string newStandName)
  666. {
  667. try
  668. {
  669. bool blUpdate = false;
  670. await Task.Run(() =>
  671. {
  672. blUpdate = DBStand.UpdateStandName(standItem.StandId, newStandName);
  673. });
  674. if (blUpdate)
  675. {
  676. standItem.StandName = newStandName;
  677. }
  678. else
  679. {
  680. MessageBox.Show(Application.Current.MainWindow, $"修改模板名称失败。", "警告",
  681. MessageBoxButton.OK, MessageBoxImage.Warning);
  682. }
  683. }
  684. catch(Exception ex)
  685. {
  686. MessageBox.Show(Application.Current.MainWindow, $"修改模板名称:{ex.Message}错误", "错误",
  687. MessageBoxButton.OK, MessageBoxImage.Error);
  688. }
  689. }
  690. private void BtnRefreshDetail_Click(object sender, RoutedEventArgs e)
  691. {
  692. //ucStandGird.CurStandItem = null;
  693. //ucStandGird.CurStandItem = SelectedStandItem;
  694. //ucStandGird.CurStationItem = null;
  695. ucStandGird.CurStationItem = SelectedStationItem;
  696. }
  697. //private async void BtnSelectImageFloder_Click(object sender, RoutedEventArgs e)
  698. //{
  699. // // 创建 VistaFolderBrowserDialog 实例
  700. // var dialog = new VistaFolderBrowserDialog();
  701. // dialog.Description = "请选择模板图片文件夹";
  702. // dialog.UseDescriptionForTitle = true; // 使用 Description 作为窗口标题
  703. // // 显示对话框并检查用户是否点击了“确定”
  704. // if (dialog.ShowDialog() == true)
  705. // {
  706. // // 获取用户选择的文件夹路径
  707. // string selectedFolderPath = dialog.SelectedPath;
  708. // await ucStandGird.ImportStandImageFloder(selectedFolderPath);
  709. // }
  710. //}
  711. private void BtnLeftCtl_Click(object sender, RoutedEventArgs e)
  712. {
  713. bool visiable = !LeftVisiable;
  714. ChangeLeftVisiable(visiable);
  715. }
  716. private void BtnRightCtl_Click(object sender, RoutedEventArgs e)
  717. {
  718. bool visiable = !RightVisiable;
  719. ChangeRightVisiable(visiable);
  720. }
  721. private void ChangeLeftVisiable(bool visiable)
  722. {
  723. LeftVisiable = visiable;
  724. colLeft.Width = new GridLength(visiable ? COLUMN_LEFT_WIDTH : 0);
  725. btnLeftCtl.Content = visiable ? "◀️" : "▶️";
  726. btnLeftCtl.ToolTip = visiable ? "点击隐藏左侧栏" : "点击显示左侧栏";
  727. }
  728. private void ChangeRightVisiable(bool visiable)
  729. {
  730. RightVisiable = visiable;
  731. colRight.Width = new GridLength(visiable ? COLUMN_RIGHT_WIDTH : 0);
  732. btnRightCtl.Content = visiable ? "▶️" : "◀️";
  733. btnRightCtl.ToolTip = visiable ? "点击隐藏右侧栏" : "点击显示右侧栏";
  734. }
  735. private async void BtnStationFirstPage_Click(object sender, RoutedEventArgs e)
  736. {
  737. if (!await _semaphore2.WaitAsync(0)) return; // 防止重复点击
  738. try
  739. {
  740. await ucStationGrid.FirstPage();
  741. }
  742. catch { }
  743. finally
  744. {
  745. _semaphore2.Release();
  746. }
  747. }
  748. private async void BtnStationPrePage_Click(object sender, RoutedEventArgs e)
  749. {
  750. if (!await _semaphore2.WaitAsync(0)) return; // 防止重复点击
  751. try
  752. {
  753. await ucStationGrid.PrePage();
  754. }
  755. catch { }
  756. finally
  757. {
  758. _semaphore2.Release();
  759. }
  760. }
  761. private async void BtnStationNextPage_Click(object sender, RoutedEventArgs e)
  762. {
  763. if (!await _semaphore2.WaitAsync(0)) return; // 防止重复点击
  764. try
  765. {
  766. await ucStationGrid.NextPage();
  767. }
  768. catch { }
  769. finally
  770. {
  771. _semaphore2.Release();
  772. }
  773. }
  774. private async void BtnStationLastPage_Click(object sender, RoutedEventArgs e)
  775. {
  776. if (!await _semaphore2.WaitAsync(0)) return; // 防止重复点击
  777. try
  778. {
  779. await ucStationGrid.LastPage();
  780. }
  781. catch { }
  782. finally
  783. {
  784. _semaphore2.Release();
  785. }
  786. }
  787. private async void BtnStationSpeciPage_Click(object sender, RoutedEventArgs e)
  788. {
  789. if (!await _semaphore2.WaitAsync(0)) return; // 防止重复点击
  790. try
  791. {
  792. int pageNumber = int.Parse(txtStationPageNumber.Text.ToString());
  793. await ucStationGrid.SpeciPage(pageNumber);
  794. }
  795. catch{}
  796. finally
  797. {
  798. _semaphore2.Release();
  799. }
  800. }
  801. private async void BtnQuery_Click(object sender, RoutedEventArgs e)
  802. {
  803. if (!await _semaphore2.WaitAsync(0)) return; // 防止重复点击
  804. try
  805. {
  806. FindStationId = txtFindStationId.Text.Trim();
  807. await ucStationGrid.ChangeFind(FindStationId, SelectedStationMarkType, SelectedStandItem.StandId);
  808. //Apply_UCStandDetaisl_Title(SelectedStationItem);
  809. Apply_Station_Title(SelectedStationItem);
  810. }
  811. catch { }
  812. finally
  813. {
  814. _semaphore2.Release();
  815. }
  816. }
  817. private async void BtnRefreshStation_Click(object sender, RoutedEventArgs e)
  818. {
  819. if (!await _semaphore2.WaitAsync(0)) return; // 防止重复点击
  820. try
  821. {
  822. FindStationId = txtFindStationId.Text.Trim();
  823. await ucStationGrid.ChangeFind(FindStationId, SelectedStationMarkType, SelectedStandItem.StandId);
  824. //Apply_UCStandDetaisl_Title(SelectedStationItem);
  825. Apply_Station_Title(SelectedStationItem);
  826. }
  827. catch { }
  828. finally
  829. {
  830. _semaphore2.Release();
  831. }
  832. }
  833. private void BtnImportStand_Click(object sender, RoutedEventArgs e)
  834. {
  835. ImportStand(SelectedStandItem);
  836. }
  837. private void BtnExportStand_Click(object sender, RoutedEventArgs e)
  838. {
  839. ExportStand(SelectedStandItem,null);
  840. }
  841. //部分导出
  842. private void BtnPartExportStand_Click(object sender, RoutedEventArgs e)
  843. {
  844. //查找站点中MarkCount中大于>0的数据
  845. PartExportStand(SelectedStandItem);
  846. }
  847. private void MiExport_Click(object sender, RoutedEventArgs e)
  848. {
  849. ExportStand(SelectedStandItem,null);
  850. }
  851. private void MiImport_Click(object sender, RoutedEventArgs e)
  852. {
  853. ImportStand(SelectedStandItem);
  854. }
  855. private void MiPartExport_Click(object sender, RoutedEventArgs e)
  856. {
  857. PartExportStand(SelectedStandItem);
  858. }
  859. private void PartExportStand(StandItem standItem)
  860. {
  861. if (standItem == null)
  862. {
  863. MessageBox.Show(Application.Current.MainWindow, "请先选择模板!","提示", MessageBoxButton.OK, MessageBoxImage.Information);
  864. return;
  865. }
  866. btnPartExportStand.IsEnabled = false;
  867. List<TStation> stationList = DBStation.GetAllVStation(SelectedStandItem.StandId);
  868. SelecteStationDlg dialog = new SelecteStationDlg(stationList)
  869. {
  870. Owner = Application.Current.MainWindow,
  871. WindowStartupLocation = WindowStartupLocation.CenterOwner
  872. };
  873. if (dialog.ShowDialog() == true)
  874. {
  875. List<TStation> selctedStationList = dialog.StationList2.ToList();
  876. ExportStand(SelectedStandItem, selctedStationList);
  877. }
  878. btnPartExportStand.IsEnabled = true;
  879. }
  880. //导出
  881. private async void ExportStand(StandItem standItem,List<TStation> stations)
  882. {
  883. if (standItem == null)
  884. {
  885. MessageBox.Show(Application.Current.MainWindow, "请先选择模板!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
  886. return;
  887. }
  888. string fileName = $"{standItem.StandName}_{ThisApp.GetNowTime_yyyyMMddHHmmss()}.json";
  889. // 2. 弹出保存对话框
  890. VistaSaveFileDialog saveFileDialog = new VistaSaveFileDialog
  891. {
  892. FileName = fileName, //Path.GetFileName(sourcePath), // 默认文件名
  893. DefaultExt = Path.GetExtension(fileName),
  894. Filter = $"JSON Files (*{Path.GetExtension(fileName)})|*{Path.GetExtension(fileName)}|All Files (*.*)|*.*"
  895. };
  896. if (saveFileDialog.ShowDialog() != true)
  897. {
  898. return;
  899. }
  900. string titleInfo = "正在导出数据,请稍后...";
  901. WaitWindow waitWindow = new WaitWindow(titleInfo)
  902. {
  903. Owner = Application.Current.MainWindow,
  904. WindowStartupLocation = WindowStartupLocation.CenterOwner
  905. };
  906. waitWindow.Show();
  907. try
  908. {
  909. var blExport = await Task.Run(() =>
  910. {
  911. return ExportStand_to_json(standItem,stations,saveFileDialog.FileName);
  912. });
  913. string exportResult = "导出" + (blExport ? "成功" : "失败");
  914. MessageBox.Show(Application.Current.MainWindow, exportResult, "提示", MessageBoxButton.OK,
  915. MessageBoxImage.Information);
  916. }
  917. catch (Exception ex)
  918. {
  919. MessageBox.Show(Application.Current.MainWindow, $"失败:{ex.Message}", "错误",
  920. MessageBoxButton.OK, MessageBoxImage.Error);
  921. }
  922. finally
  923. {
  924. //关闭等待窗口
  925. waitWindow.Close();
  926. }
  927. }
  928. private bool ExportStand_to_json(StandItem standItem,List<TStation> stations,string fileName)
  929. {
  930. //查找站点中MarkCount中大于>0的数据
  931. List<TStation> stationList; // = DBStation.GetAllVStation(standItem.StandId);
  932. if(stations == null)
  933. {
  934. stationList = DBStation.GetAllVStation(standItem.StandId);
  935. }
  936. else
  937. {
  938. stationList = stations;
  939. }
  940. List<TStandDetail> allStandDetails = new List<TStandDetail>();
  941. foreach (var station in stationList)
  942. {
  943. var standDetails = DBStand.GetAllStandDetails(standItem.StandId, station.StationId);
  944. allStandDetails.AddRange(standDetails);
  945. }
  946. if (allStandDetails.Count <= 0)
  947. {
  948. Dispatcher.Invoke(() =>
  949. {
  950. MessageBox.Show(Application.Current.MainWindow, "没有已标注的数据可导出!", "提示", MessageBoxButton.OK,
  951. MessageBoxImage.Error);
  952. });
  953. return false;
  954. }
  955. string json = JsonConvert.SerializeObject(allStandDetails, Formatting.Indented); // 格式化 JSON
  956. File.WriteAllText(fileName, json);
  957. return true;
  958. }
  959. //导入
  960. private async void ImportStand(StandItem standItem)
  961. {
  962. if (standItem == null)
  963. {
  964. MessageBox.Show(Application.Current.MainWindow, "请先选择模板!","提示", MessageBoxButton.OK, MessageBoxImage.Information);
  965. return;
  966. }
  967. // 打开文件选择对话框
  968. var openFileDialog = new OpenFileDialog
  969. {
  970. //Filter = "Excel Files (*.xls;*.xlsx)|*.xls;*.xlsx",
  971. Filter = "Json Files (*.json)|*.json",
  972. Title = "选择JSON文件"
  973. };
  974. if (openFileDialog.ShowDialog() != true)
  975. {
  976. return;
  977. }
  978. string fileName = openFileDialog.FileName;
  979. string titleInfo = "正在导入数据,请稍后...";
  980. WaitWindow waitWindow = new WaitWindow(titleInfo)
  981. {
  982. Owner = Application.Current.MainWindow,
  983. WindowStartupLocation = WindowStartupLocation.CenterOwner
  984. };
  985. waitWindow.Show();
  986. try
  987. {
  988. var blExport = await Task.Run(() =>
  989. {
  990. return ImportStand_from_json(standItem, fileName);
  991. });
  992. string exportResult = "导入" + (blExport ? "成功" : "失败");
  993. MessageBox.Show(Application.Current.MainWindow, exportResult, "提示", MessageBoxButton.OK,
  994. MessageBoxImage.Information);
  995. //导入后要刷新数据
  996. //ucStationGrid.ChangeFind()
  997. //SelectedStandItem = null;
  998. //再获取数据更新
  999. VStand vStand = DBStand.GetVStandById(standItem.StandId);
  1000. StandItem newStandItem = new StandItem();
  1001. if(vStand != null)
  1002. {
  1003. ObjectHelper.CopyMatchingFields(vStand, SelectedStandItem);
  1004. }
  1005. //刷新一下
  1006. //ucStationGrid.ChangeFind(FindStationId, SelectedStationMarkType, "");
  1007. await ucStationGrid.ChangeFind(FindStationId, SelectedStationMarkType, _selectedStandItem.StandId);
  1008. //SelectedStandItem = newStandItem;
  1009. //dgStand.SelectedItem = SelectedStandItem;
  1010. }
  1011. catch (Exception ex)
  1012. {
  1013. MessageBox.Show(Application.Current.MainWindow, $"失败:{ex.Message}", "错误",
  1014. MessageBoxButton.OK, MessageBoxImage.Error);
  1015. }
  1016. finally
  1017. {
  1018. //关闭等待窗口
  1019. waitWindow.Close();
  1020. }
  1021. }
  1022. private bool ImportStand_from_json(StandItem standItem,string fileName)
  1023. {
  1024. string json = File.ReadAllText(fileName);
  1025. List<TStandDetail> standDetails = JsonConvert.DeserializeObject<List<TStandDetail>>(json) ?? new List<TStandDetail>();
  1026. if(standDetails == null || standDetails.Count == 0)
  1027. {
  1028. Dispatcher.Invoke(() =>
  1029. {
  1030. MessageBox.Show(Application.Current.MainWindow, "没有有效的数据可导入!", "提示", MessageBoxButton.OK,
  1031. MessageBoxImage.Error);
  1032. });
  1033. return false;
  1034. }
  1035. //使用新的stand_id值,即其它
  1036. foreach(var detail in standDetails)
  1037. {
  1038. detail.StandId = standItem.StandId;
  1039. detail.StandDetailId = Guid.NewGuid().ToString().Replace("-","");
  1040. detail.CreateTime = ThisApp.GetNowTime_yyyyMMddHHmmss();
  1041. }
  1042. //开始批量插入数据库
  1043. bool blInsert = DBStand.InsertStandDetails(standDetails);
  1044. if (blInsert)
  1045. {
  1046. //获取不重复的站点
  1047. List<StationInfo> stationInfos = DBStand.GetUniqueStationInfo(standItem.StandId);
  1048. //先删除属于standId的站点,再插入
  1049. blInsert = false;
  1050. //bool blDelete = DBStation.DeleteTStationByStandId(standItem.StandId);
  1051. //if(blDelete)
  1052. //{
  1053. blInsert = DBStation.InsertTStations(stationInfos);
  1054. //}
  1055. }
  1056. return blInsert;
  1057. }
  1058. private ScrollViewer _dgStandScrollViewer;
  1059. private ScrollViewer GetDgStandScrollViewer(DependencyObject obj)
  1060. {
  1061. if (_dgStandScrollViewer != null)
  1062. {
  1063. return _dgStandScrollViewer;
  1064. }
  1065. if (obj is ScrollViewer)
  1066. {
  1067. _dgStandScrollViewer = (ScrollViewer)obj;
  1068. return obj as ScrollViewer;
  1069. }
  1070. for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
  1071. {
  1072. var child = VisualTreeHelper.GetChild(obj, i);
  1073. var scrollViewer = GetDgStandScrollViewer(child);
  1074. if (scrollViewer != null)
  1075. {
  1076. _dgStandScrollViewer = scrollViewer;
  1077. return scrollViewer;
  1078. }
  1079. }
  1080. return null;
  1081. }
  1082. private void MiAppendExcel_Click(object sender, RoutedEventArgs e)
  1083. {
  1084. AppendExcel();
  1085. }
  1086. private async void AppendExcel()
  1087. {
  1088. var dialog = new AppendFromExcel()
  1089. {
  1090. Owner = Application.Current.MainWindow,
  1091. WindowStartupLocation = WindowStartupLocation.CenterOwner
  1092. };
  1093. if (dialog.ShowDialog() == true)
  1094. {
  1095. List<TStandDetail> standDetailList = dialog.mStandDetailList;
  1096. if(standDetailList == null || standDetailList.Count == 0)
  1097. {
  1098. MessageBox.Show(Application.Current.MainWindow, "Excel中没有查询到数据", "提示", MessageBoxButton.OK, MessageBoxImage.Warning);
  1099. return;
  1100. }
  1101. List<TStation> stationList = DBStation.GetAllVStation2(SelectedStandItem.StandId);
  1102. List<TStandDetail> allStandDetails = new List<TStandDetail>();
  1103. foreach(var station in stationList)
  1104. {
  1105. for(int i = 0; i < standDetailList.Count; i++)
  1106. {
  1107. if(standDetailList[i].StationId == station.StationId)
  1108. {
  1109. standDetailList[i].StandId = SelectedStandItem.StandId;
  1110. allStandDetails.Add(standDetailList[i]);
  1111. }
  1112. }//for i
  1113. }//foreach
  1114. bool blInsert = await InsertDatatBase(allStandDetails);
  1115. MessageBox.Show(Application.Current.MainWindow, $"追加Excel数据{(blInsert ? "成功" : "失败")}", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
  1116. //刷新模板
  1117. VStand vStand = DBStand.GetVStandById(SelectedStandItem.StandId);
  1118. StandItem standItem = new StandItem(vStand);
  1119. ObjectHelper.CopyMatchingFields(standItem, SelectedStandItem);
  1120. OnPropertyChanged(nameof(SelectedStandItem));
  1121. }
  1122. }
  1123. private async Task<bool> InsertDatatBase(List<TStandDetail> standDetails)
  1124. {
  1125. bool blInsert = false;
  1126. string titleInfo = "正在插入数据库,请稍候...";
  1127. WaitWindow waitWindow = new WaitWindow(titleInfo)
  1128. {
  1129. Owner = Application.Current.MainWindow,
  1130. WindowStartupLocation = WindowStartupLocation.CenterOwner
  1131. };
  1132. waitWindow.Show();
  1133. try
  1134. {
  1135. await Task.Run(() =>
  1136. {
  1137. blInsert = DBStand.InsertStandDetails(standDetails);
  1138. });
  1139. }
  1140. catch (Exception ex)
  1141. {
  1142. MessageBox.Show($"插入数据失败:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
  1143. }
  1144. finally
  1145. {
  1146. waitWindow.Close();
  1147. }
  1148. return blInsert;
  1149. }
  1150. /////////////////////////////////////////////////////////////////////////////
  1151. }
  1152. public enum MarkFindType
  1153. {
  1154. ALL = 1,
  1155. MARK_YES = 2,
  1156. MARK_NO = 3
  1157. }
  1158. //-----------------------------------------------------------
  1159. }