using HMI.Base; using HMI.Core.Util; using HMI.UI.Util; using HMI.Util; using Microsoft.Win32; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Timers; using System.Windows; using System.Windows.Controls; namespace HMI.LogViewer { /// /// UserControl1.xaml 的交互逻辑 /// public partial class LogViewer : PluginControl { private bool autoRfh; public bool AutoRfh { get { return autoRfh; } set { Set(ref autoRfh, value); if (autoRfhTimer != null) autoRfhTimer.Enabled = value; } } private Timer autoRfhTimer; private long pageSize = 50; private long currentPage = 1; public long CurrentPage { get => currentPage; set { Set(ref currentPage, value); Filtrate(value, pageSize); } } private long maxPage = 1; public long MaxPage { get => maxPage; set { Set(ref maxPage, value); } } public LogViewer() { DataContext = this; autoRfhTimer = new Timer { Enabled = false, Interval = 1500, AutoReset = false }; autoRfhTimer.Elapsed += AutoRfhTimer_Elapsed; InitializeComponent(); QueryReset(); } public override void InitFinish() { //base.InitFinish(); //string baseFile = Path.Combine(logDir, "log.db"); //try //{ // if (!File.Exists(baseFile)) // { // SqliteHelper.CreateDatabase(baseFile); // } // SqliteHelper sqliteHelper = new SqliteHelper(baseFile); // sqliteHelper.ExecuteSql(@"CREATE TABLE IF NOT EXISTS log ( // id INTEGER PRIMARY KEY AUTOINCREMENT, // level TEXT NOT NULL, // text TEXT NOT NULL, // source TEXT, // time TIME // );"); //} //catch (Exception ex) //{ // log.Error("Create Log File Failed.", ex); //} } private void UserControl_Loaded(object sender, RoutedEventArgs e) { Loaded -= UserControl_Loaded; } private void AutoRfhTimer_Elapsed(object sender, ElapsedEventArgs e) { Refresh100items(); } //private void RefreshTable() { // if(CurrentPage == ) //} private void Button_Click(object sender, RoutedEventArgs e) { Button btn = sender as Button; switch (btn.Name) { case "queryBtn": QueryLog(); break; case "resetBtn": QueryReset(); CurrentPage = 1; break; case "exportBtn": DoExport(); break; default: break; } } private void DoExport() { try { SaveFileDialog sfd = new SaveFileDialog { Filter = "Excel Files (*.xls)|*.xls", }; if (sfd.ShowDialog() == true) { var dt = GetDataTable(false, 1, 1, out long totalPage); ExcelHelper.ExportExcel(sfd.FileName, dt); ToastHelper.Success(this.lang("App.ExportSuccess")); } } catch (Exception ex) { log.Error("Export Log Failed.", ex); MsgBoxHelper2.Error($"导出失败: {ex.Message}"); } } private void QueryLog() { try { if (startTimeInput.SelectedDateTime == null && endTimeInput.SelectedDateTime == null) { ToastHelper.Error(this.lang("log.timeCantBeNull")); return; } if (endTimeInput.SelectedDateTime != null && startTimeInput.SelectedDateTime != null && endTimeInput.SelectedDateTime < startTimeInput.SelectedDateTime) { ToastHelper.Error(this.lang("log.timeRangeError")); return; } AutoRfh = false; //queryBtn.IsEnabled = false; //autoRfhInput.IsEnabled = false; CurrentPage = 1; } catch (Exception ex) { log.Error("Log Query Failed.", ex); this.Error($"查询失败!{ex.Message}"); } finally { queryBtn.IsEnabled = true; autoRfhInput.IsEnabled = true; } } private void QueryReset() { var today = DateTime.Now; var start = DateTime.Parse(today.ToString("yyyy-MM-dd 00:00:00")).AddDays(-7); var end = DateTime.Parse(today.ToString("yyyy-MM-dd 00:00:00")).AddDays(1); levelInput.Text = null; startTimeInput.SelectedDateTime = start; endTimeInput.SelectedDateTime = end; } public DataTable GetDataTable(bool usePage, long page, long size, out long totalPage) { totalPage = 0; var files = GetOldDbFiles(PathHelper.LogViewerDir, new DateTime?[] { startTimeInput.SelectedDateTime, endTimeInput.SelectedDateTime }); if (files.Length <= 0) { return new DataTable(); } using (Sqlite3Helper 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 ALL ", GetSqls(files)); string sortName = "time", sortDirection = "DESC"; string baseSql = $"SELECT level,time,source,text FROM ({sql}) as _temp"; string countSql = $"SELECT COUNT(1) FROM ({sql}) as __temp"; long total = (long)helper.SelectOne(countSql); totalPage = (total / pageSize) + ((total % pageSize) > 0 ? 1 : 0); if (usePage) { sql = $"{baseSql} ORDER BY {sortName} {sortDirection} LIMIT {size} OFFSET {(page - 1) * size} "; } else { sql = $"{baseSql} ORDER BY {sortName} {sortDirection}"; } DataTable dt = helper.GetDataTable(sql); return dt; } } private void Filtrate(long page, long size) { try { //var files = GetOldDbFiles(PathHelper.LogViewerDir, new DateTime?[] { startTimeInput.SelectedDateTime, //endTimeInput.SelectedDateTime }); //if (files.Length <= 0) //{ // table.ItemsSource = new DataTable().DefaultView; // return; //} //using (Sqlite3Helper 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 ALL ", GetSqls(files)); // string sortName = "time", sortDirection = "DESC"; // string baseSql = $"SELECT level,time,source,text FROM ({sql}) as _temp"; // string countSql = $"SELECT COUNT(1) FROM ({sql}) as __temp"; // long total = (long)helper.SelectOne(countSql); // long pages = (total/pageSize)+ ((total % pageSize) > 0 ? 1 : 0); // sql = $"{baseSql} ORDER BY {sortName} {sortDirection} LIMIT {size} OFFSET {(page - 1) * size} "; // DataTable dt = helper.GetDataTable(sql); // table.ItemsSource = dt.DefaultView; // MaxPage = pages; //} table.ItemsSource = GetDataTable(true, page, size, out long totalPage).DefaultView; MaxPage = totalPage; } catch (Exception ex) { log.Error("Select Log Error.", ex); MsgBoxHelper2.Error($"查询失败: {ex.Message}"); } } public static string[] GetOldDbFiles(string folderPath, DateTime?[] range) { if (!Directory.Exists(folderPath)) { return new string[0]; } // 获取所有.db文件并筛选出7天前更新的文件 var oldFiles = Directory.GetFiles(folderPath, "*.db"); try { oldFiles = oldFiles.Where(file => { var lastWriteTime = File.GetLastWriteTime(file); bool flag = true; if (range[0] != null) flag &= lastWriteTime >= range[0]; //if (range[1] != null) flag &= lastWriteTime <= range[1]; return flag; }).OrderByDescending(f => f).ToArray(); return oldFiles; } catch (Exception ex) { return new string[0]; } } /// /// /// /// /// private string[] GetSqls(string[] files) { string[] sqls = new string[files.Length]; for (int i = 0; i < files.Length; i++) { string sql = $"SELECT level,time,source,text FROM db{i}.log"; List datas = new List(); if (!string.IsNullOrEmpty(levelInput.Text)) { datas.Add($"level='{levelInput.Text}'"); } if (!string.IsNullOrEmpty(startTimeInput.Text)) { datas.Add($"time>='{startTimeInput.Text}'"); } if (!string.IsNullOrEmpty(endTimeInput.Text)) { datas.Add($"time<'{endTimeInput.Text}'"); } if (!string.IsNullOrEmpty(sourceInput.Text)) { datas.Add($"source='{sourceInput.Text}'"); } string condition = string.Join(" AND ", datas); condition = string.IsNullOrEmpty(condition) ? string.Empty : $" WHERE {condition}"; sql = $"{sql}{condition}"; sqls[i] = sql; } return sqls; } /// /// 刷新100条数据 /// private void Refresh100items() { autoRfhTimer.Enabled = false; Task.Run(() => { try { string todayLogFile = Path.Combine(PathHelper.LogViewerDir, $"log_{DateTime.Today:yyyy-MM-dd}.db"); if (!File.Exists(todayLogFile)) return; string str = "select level,time,source,text from log order by time desc limit 100"; using (SqliteHelper sql = new SqliteHelper(todayLogFile)) { var dt = sql.GetDataTable(str); this.Dispatcher.BeginInvoke((Action)delegate () { table.ItemsSource = dt.DefaultView; MaxPage = 1; }); } } catch (Exception ex) { log.Error("Log Auto Refresh Failed.", ex); this.Error($"自动刷新失败!{ex.Message}"); } finally { this.Dispatcher.BeginInvoke((Action)delegate () { autoRfhTimer.Enabled = AutoRfh; }); } }); } } }