using MeterVision.Config;
using MeterVision.db;
using MeterVision.Dlg;
using MeterVision.FreeAi;
using MeterVision.model;
using MeterVision.Util;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
//using System.Linq;
//using System.Text;
//using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
//using System.Windows.Data;
//using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
//using System.Windows.Media;
//using System.Windows.Media.Imaging;
//using System.Windows.Navigation;
//using System.Windows.Shapes;
namespace MeterVision.Single
{
///
/// UCSingleGrid.xaml 的交互逻辑
///
public partial class UCSingleGrid : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
//定义数据源
public ObservableCollection SingleDetailItemList { get; set; }
//定义事件,用于通知外部组件选中项已更改(用于其它窗体或用户控件注册)
public event EventHandler OnSelectedSingDetailItemChanged;
private SingleDetailItem _selectedSingleDetailItem;
public SingleDetailItem SelectedSingleDetailItem
{
get => _selectedSingleDetailItem;
set
{
if(_selectedSingleDetailItem != value)
{
_selectedSingleDetailItem = value;
OnPropertyChanged(nameof(SelectedSingleDetailItem));
OnSelectedSingDetailItemChanged?.Invoke(this, new SingleDetailItemChangedEventArgs(value));
}
}
}
public ConfigItem mConfigItem { get; set; }
public PageModel SingleDetailPage { get; set; }
private int _totalRecord;
public int TotalRecords
{
get => _totalRecord;
set
{
if (_totalRecord != value)
{
_totalRecord = value;
OnPropertyChanged(nameof(TotalRecords));
}
}
}
public UCSingleGrid()
{
InitializeComponent();
SingleDetailItemList = new ObservableCollection();
dgSingle.ItemsSource = SingleDetailItemList;
mConfigItem = ConfigItem.GetConfigItem();
SingleDetailPage = new PageModel
{
PageSize = mConfigItem.SinglePageSize,
PageNumber = 1
};
mConfigItem.OnSinglePageSizeChanged += MConfigItem_OnSinglePageSizeChanged;
InitializeAsync();
//CreateDemoData();
this.DataContext = this;
}
private async void InitializeAsync()
{
await LoadSingleDetailItemList();
}
private async void MConfigItem_OnSinglePageSizeChanged(object sender, PageSizeChangedEventArgs e)
{
SingleDetailPage.InitDefaulValue(e.PageSize);
await LoadSingleDetailItemList();
}
public async void RefreshData()
{
SingleDetailPage.InitDefaulValue();
await LoadSingleDetailItemList();
}
public async Task LoadSingleDetailItemList()
{
SingleDetailItemList.Clear();
try
{
var result = await Task.Run(() =>
{
return DBSingle.GetPagedSingleDetails(SingleDetailPage.PageNumber, SingleDetailPage.PageSize);
});
TotalRecords = result.Item1;
SingleDetailPage.PageCount = result.Item2;
List singleDetails = result.Item3;
//更新数据需要在主线中进行
Application.Current.Dispatcher.Invoke(() =>
{
int index = 0;
foreach (TSingleDetail singleDetail in singleDetails)
{
index++;
SingleDetailItem item = new SingleDetailItem(singleDetail);
item.Index = index + ((SingleDetailPage.PageNumber - 1) * SingleDetailPage.PageSize);
SingleDetailItemList.Add(item);
}//foreach
SelectedSingleDetailItem = null;
});
return true;
}
catch (Exception ex)
{
MessageBox.Show(Application.Current.MainWindow,
$"加载数据时发生错误:{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
}
private void SrcImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var image = sender as Image;
if (image == null) return;
var dataContext = image.DataContext as SingleDetailItem;
if (dataContext == null) return;
//var dialog = new ImageViewerWindow(dataContext.SourceImagePath)
if (!File.Exists(dataContext.SrcImage)) return;
var dialog = new imgWindow(dataContext.SrcImage)
{
Owner = Application.Current.MainWindow
};
if(dialog.ShowDialog() == true)
{
}
}
private void DstImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var image = sender as Image;
if (image == null) return;
var dataContext = image.DataContext as SingleDetailItem;
if (dataContext == null) return;
//var dialog = new ImageViewerWindow(dataContext.SourceImagePath)
if (!File.Exists(dataContext.DstImage)) return;
var dialog = new imgWindow(dataContext.DstImage)
{
Owner = Application.Current.MainWindow
};
if (dialog.ShowDialog() == true)
{
}
}
private void UserControl_DragEnter(object sender, DragEventArgs e)
{
}
private void UserControl_PreviewDragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
// 获取拖拽的文件数组
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
// 检查是否只拖拽了一个文件,并且该文件不是文件夹
if (files.Length == 1 && File.Exists(files[0]))
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
}
else
{
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
private void UserControl_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
// 获取拖拽的文件数组
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
// 确保只拖拽了一个文件
if (files.Length != 1)
{
//MessageBox.Show("只能拖拽一个文件。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
MessageBox.Show(Application.Current.MainWindow,
"只能拖拽一个文件。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}
// 获取单个文件路径
string file = files[0];
// 验证文件是否为 JPG 文件
//if (IsJpgFile(file))
// 验证文件是否为有效的 JPG 文件,并且文件大小不超过 100KB
if ( (ThisApp.IsJpgFile(file) || ThisApp.IsBmpFile(file) ) &&
ThisApp.IsFileSizeValid(file) && ThisApp.IsImageDimensionsValid(file))
{
// 调用图像处理方法
//ProcessDragFile(file);
DragRecong(file);
}
else
{
MessageBox.Show(Application.Current.MainWindow,
$"文件 {file} 不符合要求:必须是小于 200KB 的 JPG 文件,且图像尺寸必须为 320x240。", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
}
public async void DragRecong(string srcImagePath)
{
var singleDetail = new SingleDetailItem()
{
SingleDetailId = Guid.NewGuid().ToString(),
CreateTime = ThisApp.GetNowTime_yyyyMMddHHmmss(),
SrcImage = srcImagePath
};
//DBSingle.InsertTSingleDetail0(singleDetail);
bool blRun = await RunAI(true,singleDetail);
Console.Write($"Run:{blRun}");
if (blRun)
{
SingleDetailPage.PageNumber = 1;
await LoadSingleDetailItemList();
if (SingleDetailItemList.Count > 0)
{
SelectedSingleDetailItem = SingleDetailItemList[0];
dgSingle.ScrollIntoView(dgSingle.Items[0]);
}
MessageBox.Show(Application.Current.MainWindow, "识别成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
else
{
MessageBox.Show(Application.Current.MainWindow, "识别识别!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
//处理拖拽的文件
//private void ProcessDragFile(string filePath)
//{
// //AddNewSingTask(filePath);
// InsertFilesWithProgress(new List() { filePath });
//}
//public async void InsertFilesWithProgress(List filePaths)
//{
// // 弹出一个非模式对话框来显示进度
// ProgressDialog progressDialog = new ProgressDialog()
// {
// Owner = Application.Current.MainWindow
// };
// progressDialog.Show();
// // 任务来异步执行文件插入
// await Task.Run(() => InsertFilesToDatabase(filePaths, progressDialog));
// // 关闭进度对话框
// progressDialog.Close();
// //刷新CurItem
// //OnStandItemCountChanged?.Invoke(this, new StandItemCountChangedEventArgs(CurStandItem));
// //刷新数据(并定位第一条)
// SingleDetailPage.PageNumber = 1;
// LoadSingleDetailItemList();
// SelectedSingleDetailItem = SingleDetailItemList[0];
//}
public void InsertFilesToDatabase(List filePaths, ProgressDialog progressDialog)
{
int totalFiles = filePaths.Count;
int currentFile = 0;
foreach (var filePath in filePaths)
{
// 插入文件路径到数据库
//InsertFileToDatabase(filePath);
TSingleDetail singleDetail = new TSingleDetail()
{
SingleDetailId = Guid.NewGuid().ToString(),
CreateTime = ThisApp.GetNowTime_yyyyMMddHHmmss(),
SrcImage = filePath
};
DBSingle.InsertTSingleDetail0(singleDetail);
// 更新进度条
currentFile++;
UpdateProgress(progressDialog, currentFile, totalFiles);
}
}
public void UpdateProgress(ProgressDialog progressDialog, int currentFile, int totalFiles)
{
// 更新进度条的进度
double progress = (double)currentFile / totalFiles * 100;
progressDialog.UpdateProgress(progress);
}
public async void NextPage()
{
if (SingleDetailPage.PageNumber < SingleDetailPage.PageCount)
{
SingleDetailPage.PageNumber += 1;
await LoadSingleDetailItemList();
}
}
public async void PrePage()
{
if (SingleDetailPage.PageNumber > 1)
{
SingleDetailPage.PageNumber -= 1;
await LoadSingleDetailItemList();
}
}
public async void FirstPage()
{
if (SingleDetailPage.PageNumber > 1)
{
SingleDetailPage.PageNumber = 1;
await LoadSingleDetailItemList();
}
}
public async void LastPage()
{
if (SingleDetailPage.PageNumber < SingleDetailPage.PageCount)
{
SingleDetailPage.PageNumber = SingleDetailPage.PageCount;
await LoadSingleDetailItemList();
}
}
public async void SpeciPage(int pageNumber)
{
if (pageNumber != SingleDetailPage.PageNumber &&
pageNumber > 0 && pageNumber <= SingleDetailPage.PageCount)
{
SingleDetailPage.PageNumber = pageNumber;
await LoadSingleDetailItemList();
}
}
// 辅助方法:查找指定类型的祖先元素
public static T FindAncestor(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindAncestor(parent);
}
private void BtnDelDetailItem_Click(object sender, RoutedEventArgs e)
{
//删除选中项
Button button = sender as Button;
if (button == null) return;
DataGridRow row = FindAncestor(button);
if (row == null) return;
//获取当前行绑定的数据项
SingleDetailItem selectedItem = row.Item as SingleDetailItem;
DeleteSelectedItem(selectedItem);
}
private void BtnRecongDetailItem_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button == null) return;
DataGridRow row = FindAncestor(button);
if (row == null) return;
//获取当前行绑定的数据项
SingleDetailItem selectedItem = row.Item as SingleDetailItem;
RecongSingleDetail(false, SelectedSingleDetailItem);
}
private void BtnLogViewer_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button == null) return;
DataGridRow row = FindAncestor(button);
if (row == null) return;
//获取当前行绑定的数据项
SingleDetailItem selectedItem = row.Item as SingleDetailItem;
ShowLogViewer(selectedItem);
}
private void ShowLogViewer(SingleDetailItem selectedItem)
{
if (selectedItem.LogPath != null && File.Exists(selectedItem.LogPath))
{
LogViewerWindow dialog = new LogViewerWindow(selectedItem.DstImage, selectedItem.LogPath)
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
dialog.ShowDialog();
}
}
private async void DeleteSelectedItem(SingleDetailItem selectedItem)
{
if (selectedItem == null) return;
MessageBoxResult result = MessageBox.Show("确定要删除此条目吗?", "确认删除", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result != MessageBoxResult.Yes) return;
string titleInfo = "正在删除,请稍后...";
WaitWindow waitWindow = new WaitWindow(titleInfo)
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
waitWindow.Show();
try
{
bool deleteSuccess = false;
await Task.Run(() =>
{
deleteSuccess = DBSingle.DeleteTSingleDetailById(selectedItem.SingleDetailId);
});
if (deleteSuccess)
{
Application.Current.Dispatcher.Invoke(() =>
{
// 从数据源中移除该条目
SingleDetailItemList.Remove(selectedItem);
SelectedSingleDetailItem = null;
});
}
}
catch (Exception ex)
{
MessageBox.Show(Application.Current.MainWindow, $"删除失败:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
waitWindow.Close();
}
}
//清空所有的列表数据
public async void ClearAllSingleDetail()
{
//清空提示
MessageBoxResult result = MessageBox.Show("确定要清空所有数据吗?", "确认清空", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result != MessageBoxResult.Yes) return;
string titleInfo = "正在清空数据,请稍后...";
WaitWindow waitWindow = new WaitWindow(titleInfo)
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
waitWindow.Show();
try
{
bool blClearAll = false;
await Task.Run(() =>
{
blClearAll = DBSingle.ClearTSingleDetailTable();
});
if (blClearAll)
{
SingleDetailPage.InitDefaulValue();
await LoadSingleDetailItemList();
}
}
catch (Exception ex)
{
MessageBox.Show(Application.Current.MainWindow, $"清空失败:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
waitWindow.Close();
}
}
private void MiDelete_Click(object sender, RoutedEventArgs e)
{
if (SelectedSingleDetailItem == null) return;
//获取当前行绑定的数据项
DeleteSelectedItem(SelectedSingleDetailItem);
}
private void MiRecong_Click(object sender, RoutedEventArgs e)
{
if (SelectedSingleDetailItem == null) return;
RecongSingleDetail(false, SelectedSingleDetailItem);
}
private async void RecongSingleDetail(bool isAdd, SingleDetailItem singleDetailIte)
{
string jpgFile = singleDetailIte.SrcImage;
if (!File.Exists(jpgFile))
{
MessageBox.Show(Application.Current.MainWindow, $"文件:{jpgFile}不存在!", "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
bool blRun = await RunAI(isAdd, singleDetailIte);
if (blRun)
{
MessageBox.Show(Application.Current.MainWindow, "识别成功!", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
}
else
{
MessageBox.Show(Application.Current.MainWindow, "识别失败!", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private async Task RunAI(bool isAdd,SingleDetailItem singleDetailItem)
{
FaRun faRun = new FaRun();
faRun.OnAiRealLogInfo += FaRun_OnAiRealLogInfo;
string titleInfo = "正在识别,请稍后...";
WaitWindow waitWindow = new WaitWindow(titleInfo)
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
waitWindow.Show();
try
{
TSingleDetail newSingleDetail = null;
bool blRun = await Task.Run(() =>
{
try
{
ResultModel resultModel = faRun.StartRecognition(singleDetailItem.SrcImage);
if (resultModel == null) return false;
newSingleDetail = new TSingleDetail(singleDetailItem, resultModel);
//更新数据
bool blOpration;
if (isAdd)
{
blOpration = DBSingle.InsertSingleDetail(newSingleDetail);
}
else
{
blOpration = DBSingle.UpdateSingleDetail(newSingleDetail);
}
return blOpration;
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
});
//在主线程中更新DataGrid的Row数据
if (blRun && !isAdd && newSingleDetail != null)
{
//singleDetailItem = newSingleDetail;
ObjectHelper.CopyMatchingFields(newSingleDetail, singleDetailItem);
}
return blRun;
}
catch (Exception ex)
{
MessageBox.Show(Application.Current.MainWindow, $"识别[{singleDetailItem.SrcImage}]时出错:{ex.Message}", "错误",
MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
finally
{
waitWindow.Close();
}
}
private void FaRun_OnAiRealLogInfo(object sender, AiRealLogEventArgs e)
{
Console.Write(e.mLogInfo);
}
private void MiViewLog_Click(object sender, RoutedEventArgs e)
{
if(SelectedSingleDetailItem != null)
{
ShowLogViewer(SelectedSingleDetailItem);
}
}
///////////////////////////////////////////////////////////////////////////
}
//自定义事件参数类
public class SingleDetailItemChangedEventArgs : EventArgs
{
public SingleDetailItem SelectedSingleDetailItem { get; }
public SingleDetailItemChangedEventArgs(SingleDetailItem selectedData)
{
SelectedSingleDetailItem = selectedData;
}
}
}