using CommunityToolkit.Mvvm.ComponentModel;
using HMI.Base;
using HMI.Core;
using HMI.Core.Setting;
using HMI.Core.Util;
using HMI.UI.Util;
using HMI.Util;
using Microsoft.Win32;
using Panuon.WPF.UI;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
namespace Plugin.DataViewer
{
public class TestResult
{
[ExcelColumn("SN")]
public string sn { get; set; }
[ExcelColumn("穴位号")]
public string position { get; set; }
[ExcelColumn("型号")]
public string model { get; set; }
[ExcelColumn("测试结果")]
public string result { get; set; }
[ExcelColumn("测试时间")]
public string time { get; set; }
}
public class SerialData
{
[ExcelColumn("SN")]
public string sn { get; set; }
[ExcelColumn("穴位号")]
public string position { get; set; }
[ExcelColumn("型号")]
public string model { get; set; }
[ExcelColumn("测试项")]
public string step { get; set; }
[ExcelColumn("测试值")]
public string value { get; set; }
[ExcelColumn("下限")]
public string limitDown { get; set; }
[ExcelColumn("上限")]
public string limitUp { get; set; }
[ExcelColumn("结果")]
public string status { get; set; }
[ExcelColumn("单位")]
public string unit { get; set; }
[ExcelColumn("测试时间")]
public string time { get; set; }
}
public class SortParam
{
public string name { get; set; }
public ListSortDirection direction { get; set; }
public string sort { get; set; }
}
public class ResultData
{
public string sn { get; set; }
public string position { get; set; }
}
///
/// DataViewerControl.xaml 的交互逻辑
///
[ObservableObject]
public partial class DataViewerControl : SimpleMaskControl
{
[ObservableProperty]
private DataView resultView;
[ObservableProperty]
private ObservableCollection resultData;
[ObservableProperty]
private long currentPage = 1;
[ObservableProperty]
private long totalPage = 0;
private int pageSize = 30;
[ObservableProperty]
private long totalCount;
[ObservableProperty]
private long passCount;
[ObservableProperty]
private long failCount;
[ObservableProperty]
private long testItemPage = 1;
[ObservableProperty]
private long testItemTotalPage = 0;
[ObservableProperty]
private object selectedResult;
[ObservableProperty]
private string selectedStatus;
private SortParam sorter;
private SortParam itemSorter;
public DataViewerControl()
{
DataContext = this;
InitializeComponent();
Reset();
}
private string[] GetFiles(DateTime? startTime, DateTime? endTime)
{
string dir = ParamSetting.DataLogFolder;
string startName = $"Data_{startTime?.ToString("yyyyMMdd")}";
string endName = $"Data_{endTime?.ToString("yyyyMMdd")}";
var oldFiles = Directory.GetFiles(dir, "Data_*.db");
oldFiles = oldFiles.Where(file =>
{
var fileName = Path.GetFileNameWithoutExtension(file);
bool flag = true;
flag &= (string.Compare(fileName, startName) == 1 || fileName == startName);
flag &= (string.Compare(endName, fileName) == 1 || fileName == endName);
return flag;
}).ToArray();
return oldFiles;
}
private void Reset()
{
var today = DateTime.Now;
var startTime = today.AddDays(-7);
var end = today.AddDays(1);
snInput.Text = string.Empty;
positionInput.Text = string.Empty;
modelInput.Text = string.Empty;
resultInput.Text = string.Empty;
startTimeInput.SelectedDateTime = DateTime.Parse(startTime.ToString("yyyy-MM-dd 00:00:00"));
endTimeInput.SelectedDateTime = DateTime.Parse(end.ToString("yyyy-MM-dd 00:00:00"));
}
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
{
var btn = sender as Button;
if (btn.Name == "resetBtn")
{
Reset();
if (CurrentPage == 1)
{
SelectPage(1, this.pageSize);
}
else
{
CurrentPage = 1;
}
return;
}
if (btn.Name == "srhBtn")
{
if (CurrentPage == 1)
{
SelectPage(1, this.pageSize);
}
else
{
CurrentPage = 1;
}
return;
}
if (btn.Name == "srhItemBtn")
{
if (TestItemPage == 1)
{
RefreshTestItem(this.selectResultId, 1, this.pageSize);
}
else
{
TestItemPage = 1;
}
return;
}
if (btn.Name == "exportBtn")
{
TryExport();
}
if (btn.Name == "exportItemBtn")
{
TryExportItem();
}
}
private void TryExport()
{
SaveFileDialog sfd = new SaveFileDialog
{
Filter = "Excel 文件 (*.xls)|*.xls"
};
if (sfd.ShowDialog() != true)
{
return;
}
string filePath = sfd.FileName;
DateTime? startTime = startTimeInput.SelectedDateTime, endTime = endTimeInput.SelectedDateTime;
topMask.ShowMask(this, () =>
{
var table = SelectResult(startTime, endTime);
ExcelHelper.ExportExcel(filePath, table);
}, (ex) =>
{
log.Error("Export Result Failed.", ex);
Dispatcher.Invoke(() =>
{
MsgBoxHelper2.Error($"导出失败!{ex.Message}");
});
}, "导出中,请稍后...");
}
private void TryExportItem()
{
SaveFileDialog sfd = new SaveFileDialog
{
Filter = "Excel 文件 (*.xls)|*.xls"
};
if (sfd.ShowDialog() != true)
{
return;
}
string filePath = sfd.FileName;
DateTime? startTime = startTimeInput.SelectedDateTime, endTime = endTimeInput.SelectedDateTime;
topMask.ShowMask(this, () =>
{
var table = SelectItem(startTime, endTime);
ExcelHelper.ExportExcel(filePath, table);
}, (ex) =>
{
log.Error("Export Result Failed.", ex);
Dispatcher.Invoke(() =>
{
MsgBoxHelper2.Error($"导出失败!{ex.Message}");
});
}, "导出中,请稍后...");
}
private DataTable SelectResult(DateTime? startTime, DateTime? endTime)
{
var files = GetFiles(startTime, endTime);
if (files == null || files.Length <= 0)
{
return new DataTable();
}
using (var helper = new Sqlite3Helper(files[0]))
{
for (int i = 0; i < files.Length; i++)
{
var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'";
helper.Execute(attach);
}
for (int i = 0; i < files.Length; i++)
{
if (!helper.HasData($"SELECT 1 FROM pragma_table_info('testResult','db{i}') WHERE name = 'resultId';"))
{
helper.Execute($"ALTER TABLE db{i}.testResult ADD resultId TEXT;");
}
}
string sql = string.Join(" UNION ALL ", GetResultSqlsByFiles(files, startTime, endTime));
string sortName = "time", sortDirection = "DESC";
string baseSql = $"SELECT id,sn,model,station,position,result,time,resultId FROM ({sql}) as _temp";
sql = $"{baseSql} ORDER BY {sortName} {sortDirection}";
return helper.GetDataTable(sql);
//for (int i = 0; i < files.Length; i++)
//{
// helper.Execute($"DETACH DATABASE db{i}");
//}
}
}
private DataTable SelectItem(DateTime? startTime, DateTime? endTime)
{
if (string.IsNullOrEmpty(this.selectResultId))
{
return new DataTable();
}
var files = GetFiles(startTime, endTime);
if (files == null || files.Length <= 0)
{
return new DataTable();
}
using (var helper = new Sqlite3Helper(files[0]))
{
for (int i = 0; i < files.Length; i++)
{
var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'";
helper.Execute(attach);
}
for (int i = 0; i < files.Length; i++)
{
if (!helper.HasData($"SELECT 1 FROM pragma_table_info('serialData','db{i}') WHERE name = 'resultId';"))
{
helper.Execute($"ALTER TABLE db{i}.serialData ADD resultId TEXT;");
}
}
string sql = string.Join(" UNION ALL ", GetTestItemSqlsByFiles(this.selectResultId, files));
string sortName = "time", sortDirection = "DESC";
string baseSql = $"SELECT sn, position, model,step, limitDown, limitUp,unit, value,status,time FROM ({sql}) as _temp";
sql = $"{baseSql} ORDER BY {sortName} {sortDirection}";
return helper.GetDataTable(sql);
//for (int i = 0; i < files.Length; i++)
//{
// helper.Execute($"DETACH DATABASE db{i}");
//}
}
}
private void SelectPage(long page, long pageSize)
{
try
{
var files = GetFiles(startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime);
if (files == null || files.Length <= 0)
{
return;
}
using (var helper = new Sqlite3Helper(files[0]))
{
for (int i = 0; i < files.Length; i++)
{
var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'";
helper.Execute(attach);
}
for (int i = 0; i < files.Length; i++)
{
if (!helper.HasData($"SELECT 1 FROM pragma_table_info('testResult','db{i}') WHERE name = 'resultId';"))
{
helper.Execute($"ALTER TABLE db{i}.testResult ADD resultId TEXT;");
}
}
string sql = string.Join(" UNION ALL ", GetResultSqlsByFiles(files, startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime));
string sortName = "time", sortDirection = "DESC";
if (sorter != null)
{
sortName = sorter.name;
sortDirection = sorter.sort;
}
string countSql = $"SELECT COUNT(1) FROM ({sql}) as _temp";
long total = (long)helper.SelectOne(countSql);
string baseSql = $"SELECT id,sn,model,station,position,result,time,resultId FROM ({sql}) as _temp";
sql = $"{baseSql} ORDER BY {sortName} {sortDirection} LIMIT {pageSize} OFFSET {(page - 1) * pageSize}";
var dt = helper.GetDataTable(sql);
TotalPage = total / pageSize + (total % pageSize > 0 ? 1 : 0);
resultTable.ItemsSource = dt.DefaultView;
sql = $"SELECT result,COUNT(1) as num FROM ({baseSql}) GROUP BY result";
var nums = helper.GetDataTable(sql);
long all = 0, pass = 0, fail = 0;
foreach (DataRow row in nums.Rows)
{
if ("ok".Equals(row["result"].ToString(), StringComparison.OrdinalIgnoreCase)
|| "pass".Equals(row["result"].ToString(), StringComparison.OrdinalIgnoreCase))
{
pass += (long)row["num"];
all += (long)row["num"];
}
if ("ng".Equals(row["result"].ToString(), StringComparison.OrdinalIgnoreCase)
|| "fail".Equals(row["result"].ToString(), StringComparison.OrdinalIgnoreCase))
{
fail += (long)row["num"];
all += (long)row["num"];
}
}
TotalCount = all;
PassCount = pass;
FailCount = fail;
//for (int i = 0; i < files.Length; i++)
//{
// helper.Execute($"DETACH DATABASE db{i}");
//}
}
}
catch (Exception ex)
{
log.Error("Select TestResult Error.", ex);
}
}
private void RefreshTestItem(string resultId, long page, int pageSize)
{
try
{
if (string.IsNullOrEmpty(resultId))
{
testItemTable.ItemsSource = new DataTable().DefaultView;
return;
}
var files = GetFiles(startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime);
if (files == null || files.Length <= 0)
{
return;
}
string sql = string.Join(" UNION ALL ", GetTestItemSqlsByFiles(resultId, files));
string sortName = "time", sortDirection = "DESC";
if (itemSorter != null)
{
sortName = itemSorter.name;
sortDirection = itemSorter.sort;
}
mask2.ShowMask(null, () =>
{
using (var helper = new Sqlite3Helper(files[0]))
{
for (int i = 0; i < files.Length; i++)
{
var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'";
helper.Execute(attach);
}
for (int i = 0; i < files.Length; i++)
{
if (!helper.HasData($"SELECT 1 FROM pragma_table_info('serialData','db{i}') WHERE name = 'resultId';"))
{
helper.Execute($"ALTER TABLE db{i}.serialData ADD resultId TEXT;");
}
}
string countSql = $"SELECT COUNT(1) FROM ({sql}) as _temp";
long total = (long)helper.SelectOne(countSql);
string baseSql = $"SELECT sn, model,step, limitDown, limitUp,unit, value,status,time FROM ({sql}) as _temp";
sql = $"{baseSql} ORDER BY {sortName} {sortDirection} LIMIT {pageSize} OFFSET {(page - 1) * pageSize}";
var dt = helper.GetDataTable(sql);
//for (int i = 0; i < files.Length; i++)
//{
// helper.Execute($"DETACH DATABASE db{i}");
//}
Dispatcher.BeginInvoke(() =>
{
TestItemTotalPage = total / pageSize + (total % pageSize > 0 ? 1 : 0);
testItemTable.ItemsSource = dt.DefaultView;
}, System.Windows.Threading.DispatcherPriority.Normal);
}
}, (ex) =>
{
log.Error("Select TestItem Error.", ex);
},
"查询中...");
}
catch (Exception ex)
{
log.Error("Try Select TestItem Error.", ex);
}
}
public string[] GetResultSqlsByFiles(string[] files, DateTime? startTime, DateTime? endTime)
{
string sn = string.Empty, position = string.Empty, model = string.Empty, result = string.Empty;
Dispatcher.Invoke(() =>
{
sn = snInput.Text;
position = positionInput.Text;
model = modelInput.Text;
result = resultInput.Text;
});
string[] sqls = new string[files.Length];
List querys = new List();
if (!string.IsNullOrEmpty(sn))
{
querys.Add($"sn = '{sn}'");
}
if (!string.IsNullOrEmpty(position))
{
querys.Add($"position = '{position}'");
}
if (!string.IsNullOrEmpty(model))
{
querys.Add($"model = '{model}'");
}
if (!string.IsNullOrEmpty(result))
{
querys.Add($"result = '{result}'");
}
if (startTime != null)
{
querys.Add($"time >= '{startTime.Value.ToString("yyyy-MM-dd HH:mm:ss")}'");
}
if (endTime != null)
{
querys.Add($"time < '{endTime.Value.ToString("yyyy-MM-dd HH:mm:ss")}'");
}
string segment = "";
if (querys.Count > 0)
{
segment = $" WHERE {string.Join(" AND ", querys)}";
}
for (int i = 0; i < files.Length; i++)
{
sqls[i] = $"SELECT id,sn,model,station,position,result,time,resultId FROM db{i}.testResult {segment}";
}
return sqls;
}
private string[] GetTestItemSqlsByFiles(string resultId, string[] files)
{
List querys = new List() {
$"resultId = '{resultId}'"
};
string step = string.Empty, status = string.Empty;
Dispatcher.Invoke(() =>
{
step = stepInput.Text;
status = statusInput.Text;
});
if (!string.IsNullOrEmpty(step))
{
querys.Add($"step = '{step}'");
}
if (!string.IsNullOrEmpty(status))
{
querys.Add($"status = '{status}'");
}
string segment = string.Join(" AND ", querys); ;
string[] sqls = new string[files.Length];
for (int i = 0; i < files.Length; i++)
{
sqls[i] = $"SELECT sn, position, model,step, limitDown, limitUp,unit, value,status,time FROM db{i}.serialData WHERE {segment}";
}
return sqls;
}
public string[] GetSource(string[] files, string name, string tableName, string value)
{
try
{
if (files == null || files.Length <= 0)
{
return new string[0];
}
string[] GetModelSqls()
{
string[] sqls = new string[files.Length];
for (int i = 0; i < files.Length; i++)
{
sqls[i] = $"SELECT DISTINCT {name} FROM db{i}.{tableName} WHERE {name} LIKE '%{value}%'";
}
return sqls;
}
using (var helper = new Sqlite3Helper(files[0]))
{
for (int i = 0; i < files.Length; i++)
{
var attach = $"ATTACH DATABASE '{files[i]}' AS 'db{i}'";
helper.Execute(attach);
}
string sql = string.Join(" UNION ", GetModelSqls());
sql = $"SELECT DISTINCT {name} FROM ({sql}) LIMIT 10";
var dt = helper.GetDataTable(sql);
return dt.Select().Select(row => row[name].ToString()).ToArray();
}
return new string[0];
}
catch (Exception ex)
{
return new string[0];
}
}
private void SearchTextChanged(object sender, Panuon.WPF.SearchTextChangedRoutedEventArgs e)
{
SearchBox sb = sender as SearchBox;
string tag = sb.Tag.ToString(), value = sb.Text;
var files = GetFiles(startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime);
Task.Run(() =>
{
string[] items = new string[0];
if (tag == "step" || tag == "status")
{
items = GetSource(files, tag, "serialData", value);
}
else
{
items = GetSource(files, tag, "testResult", value);
}
Dispatcher.BeginInvoke(new Action(() =>
{
sb.ItemsSource = items;
}), System.Windows.Threading.DispatcherPriority.Normal);
});
}
private void Grid_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var border = sender as Border;
var header = border.Tag as DataGridColumnHeader;
var col = header.Column as ICustomSortColumn;
if (col == null) return;
col.UpdateOther(null);
var dataGrid = col.GetOwner();
if (col.IsAsc == null)
{
col.IsAsc = true;
if (dataGrid == resultTable)
{
sorter = new SortParam { name = header.Column.SortMemberPath, direction = ListSortDirection.Ascending, sort = "ASC" };
}
else {
itemSorter = new SortParam { name = header.Column.SortMemberPath, direction = ListSortDirection.Ascending, sort = "ASC" };
}
}
else if (col.IsAsc == true)
{
col.IsAsc = false;
if (dataGrid == resultTable)
{
sorter = new SortParam { name = header.Column.SortMemberPath, direction = ListSortDirection.Descending, sort = "DESC" };
}
else
{
itemSorter = new SortParam { name = header.Column.SortMemberPath, direction = ListSortDirection.Descending, sort = "DESC" };
}
}
else
{
col.IsAsc = null;
if (dataGrid == resultTable)
{
sorter = null;
}
else
{
itemSorter = null;
}
}
if (dataGrid == resultTable)
{
if (CurrentPage == 1)
{
SelectPage(1, this.pageSize);
}
else
{
CurrentPage = 1;
}
}
else
{
if (TestItemPage == 1)
{
RefreshTestItem(this.selectResultId, 1, this.pageSize);
}
else
{
TestItemPage = 1;
}
}
}
private void page_CurrentPageChanged(object sender, Panuon.WPF.SelectedValueChangedRoutedEventArgs e)
{
if (sender == page)
{
SelectPage(e.NewValue, this.pageSize);
}
else
{
RefreshTestItem(this.selectResultId, e.NewValue, this.pageSize);
}
}
private string selectResultId;
partial void OnSelectedResultChanged(object value)
{
if (value != null)
{
return;
}
var selectedRow = value as DataRowView;
var resultId = selectedRow?["resultId"]?.ToString();
this.SelectedStatus = selectedRow?["result"]?.ToString();
this.selectResultId = resultId;
if (TestItemPage == 1)
{
RefreshTestItem(resultId, 1, this.pageSize);
}
else
{
TestItemPage = 1;
}
}
private void resultTable_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var selectedRow = this.SelectedResult as DataRowView;
var resultId = selectedRow?["resultId"]?.ToString();
this.SelectedStatus = selectedRow?["result"]?.ToString();
this.selectResultId = resultId;
if (TestItemPage == 1)
{
RefreshTestItem(resultId, 1, this.pageSize);
}
else
{
TestItemPage = 1;
}
}
}
}