@page "/tra" @rendermode InteractiveServer @using System.Collections.Concurrent @using System.Collections.Specialized @using System.Collections @using ClosedXML.Excel @using Web.Tra.Services @inject CPXV2LogService CPXV2LogService @inject PopupService PopupService @inject NavigationManager Navigation @inject IJSRuntime JS @foreach (var tab in Tabs.OrderBy(x=>x.Key.Id)) { @if (tab.Key.EnumTab == EnumTabs.OverviewC1 || tab.Key.EnumTab == EnumTabs.OverviewC1Merged) { } @if (tab.Key.EnumTab == EnumTabs.OverviewC1Detail || tab.Key.EnumTab == EnumTabs.OverviewC1DetailMerged) { } @if (tab.Key.EnumTab == EnumTabs.TestHistoryC1) { } @if (tab.Key.EnumTab == EnumTabs.TestResultC1) { @{ var history = tab.Key.Parent.Parent as TestHistory; if(history.TestResult.ToLower().Contains("ok") == true) { } else { } @foreach (var prop in history.GetType().GetProperties()) { @prop.Name } } @if(tab.Value?.Count > 0) { } } @if (tab.Key.EnumTab == EnumTabs.TestSummaryC1) { @{ var history = tab.Key.Parent.Parent as TestSummaryInformation; @foreach (var prop in history.GetType().GetProperties()) { @prop.Name } } @if (tab.Value?.Count > 0) { } } @if (tab.Key.EnumTab == EnumTabs.TestTrendC1) { @{ var trend = tab.Key.Parent.Parent as TestTrend; @foreach (var prop in trend.TestStepInfo.GetType().GetProperties()) { if (prop.Name.ToLower().Contains("min") || prop.Name.ToLower().Contains("max") || prop.Name.ToLower().Contains("average")) continue; @prop.Name } @foreach (var prop in trend.TestDataInfo.GetType().GetProperties()) { if (prop.Name.ToLower().Contains("min") || prop.Name.ToLower().Contains("max") || prop.Name.ToLower().Contains("average")) continue; @prop.Name } @foreach (var prop in trend.MesuredDataAnalysis.GetType().GetProperties()) { @prop.Name } } @if (tab.Value?.Count > 0) { new TrendPoint { Category = Convert.ToInt32(x.RowNo), Value = Convert.ToDouble(x.Value) }))" TItem="TrendPoint" LineType="LineType.Solid" ValueProperty="Value" CategoryProperty="Category" Title="Value" Stroke="rgba(255,0,0)"> new TrendPoint { Category = Convert.ToInt32(x.RowNo), Value = Convert.ToDouble(x.Min) }))" TItem="TrendPoint" LineType="LineType.Dashed" ValueProperty="Value" CategoryProperty="Category" Title="MIN" Stroke="#2196f3" > new TrendPoint { Category = Convert.ToInt32(x.RowNo), Value = Convert.ToDouble(x.Max) }))" TItem="TrendPoint" LineType="LineType.Dashed" ValueProperty="Value" CategoryProperty="Category" Title="MAX" Stroke="#2196f3"> } } } @code { private RequestSearch RequestSearch = new RequestSearch(); //selection private string SelectionStationName = string.Empty; private string SelectionProductNO = string.Empty; private string SelectionParentInfo = string.Empty; private string SelectionSearchBegin = string.Empty; private string SelectionSearchEnd = string.Empty; private string SelectionStepVersion = string.Empty; //options private bool IsMergePartNumberOption = false; private int PageSize = 30; //tab RadzenTabs tabs; int SelectedTabIndex = 0; ConcurrentDictionary> Tabs = new ConcurrentDictionary>(); //search data List SearchDataOverviews = new List(); private async Task OnSearch() { //날짜 오류 if(RequestSearch.SearchStart > RequestSearch.SearchEnd) { LogXnet.WriteLine("DateTime Set Error", LogXLabel.Error); return; } PopupService.OpenIndicator("Search Data"); SearchDataOverviews = await CPXV2LogService.GetSearchDataOverview(RequestSearch); await GetOverviews(); PopupService.CloseIndicator(); } private async Task GetOverviews() { List overviews = new(); int tabId = 0; if (Tabs.Count > 0) { tabId = Tabs.Max(x => x.Key.Id) + 1; } if (IsMergePartNumberOption == false) { overviews = await CPXV2LogService.GetOverviews(SearchDataOverviews); Tabs.AddOrUpdate( new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1} ({tabId})", EnumTab = EnumTabs.OverviewC1, Parent = null }, key => overviews.Cast().ToList(), (key, oldValue) => overviews.Cast().ToList()); } else { overviews = await CPXV2LogService.GetOverviewMerged(SearchDataOverviews); Tabs.AddOrUpdate( new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1} ({tabId})", EnumTab = EnumTabs.OverviewC1Merged, Parent = null }, key => overviews.Cast().ToList(), (key, oldValue) => overviews.Cast().ToList()); } SelectedTabIndex = Tabs.Count - 1; } private void OnSelectRowOverview(IDataModel overview) { var selectOverview = overview as Overview; if(selectOverview is not null) { SelectionStationName = $"{selectOverview.StationName} ({selectOverview.Host},{selectOverview.Section})"; SelectionProductNO = $"{selectOverview.ProductNo} ({selectOverview.TestCode})"; SelectionParentInfo = $"{selectOverview.ParentNo} ({selectOverview.FileVersion},{selectOverview.FileCode})"; SelectionSearchBegin = $"{selectOverview.TestDate?.ToString("yyyy-MM-dd")} {selectOverview.FirstTestTime}"; SelectionSearchEnd = $"{selectOverview.TestDate?.ToString("yyyy-MM-dd")} {selectOverview.FinalTestTime}"; SelectionStepVersion = $"{selectOverview.StepVersion}"; } } private async Task OnDoubleClickRowOverview(SelectRow row) { var selectRow = row.Row as Overview; if(selectRow is not null) { List detailOverviews = new(); if (IsMergePartNumberOption == false) { detailOverviews = await CPXV2LogService.GetDetailOverview(SearchDataOverviews, selectRow); int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1Detail} ({tabId})", EnumTab = EnumTabs.OverviewC1Detail, Parent = new ParentRow { TabID = row.ParentTabID, Parent = row.Row } }, key => detailOverviews.Cast().ToList(), (key, oldValue) => detailOverviews.Cast().ToList()); } else { detailOverviews = await CPXV2LogService.GetDetailOverviewMerged(SearchDataOverviews, selectRow); int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( new OrderdTab { Id = tabId, TabName = $"{EnumTabs.OverviewC1Detail} ({tabId})", EnumTab = EnumTabs.OverviewC1DetailMerged, Parent = new ParentRow { TabID = row.ParentTabID, Parent = row.Row } }, key => detailOverviews.Cast().ToList(), (key, oldValue) => detailOverviews.Cast().ToList()); } tabs.Reload(); SelectedTabIndex = Tabs.Count - 1; } } private async Task OnDoubleClickRowDetailOverview(SelectRow row) { List histories = new(); if (IsMergePartNumberOption == false) { histories = await CPXV2LogService.GetTestHistory(SearchDataOverviews, row.Row); } else { histories = await CPXV2LogService.GetTestHistoryMerged(SearchDataOverviews, row.Row); } //test summary int ok = histories.Count(x => x.TestResult.ToLower().Contains("ok")); int ng = histories.Count(x => !x.TestResult.ToLower().Contains("ok")); double ratio = (double)(ok) / (double)(ok + ng) * 100.0; double testTimeAvg = histories.Average(x => Convert.ToInt32(x.Duration)) / 1000.0; double testTimeMin = histories.Min(x => Convert.ToInt32(x.Duration)) / 1000.0; double testTimeMax = histories.Max(x => Convert.ToInt32(x.Duration)) / 1000.0; int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestHistoryC1}({tabId})", EnumTab = EnumTabs.TestHistoryC1, Parent = new ParentRow { TabID = row.ParentTabID, Parent = row.Row } , SummaryTestResult = $"Test Result: {ok + ng} (OK:{ok}/NG:{ng}) - Ratio:{ratio.ToString("F2")}%", SummaryTestTime = $"Test Time: Average={testTimeAvg.ToString("F2")}sec Min={testTimeMin.ToString("F2")}sec Max={testTimeMax.ToString("F2")}sec" }, key => histories.Cast().ToList(), (key, oldValue) => histories.Cast().ToList()); tabs.Reload(); SelectedTabIndex = Tabs.Count - 1; } private async Task OnDoubleClickRowHistory(SelectRow row) { var selectRow = row.Row as TestHistory; int testStepVersion = selectRow.StepVersion; if(Int32.TryParse(SelectionStepVersion, out var inputStepVersion) == true) { testStepVersion = inputStepVersion; } var s = await CPXV2LogService.GetTestResult(row.Row, testStepVersion); int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestResultC1}({tabId})", EnumTab = EnumTabs.TestResultC1, Parent = new ParentRow { TabID = row.ParentTabID, Parent = row.Row } }, key => s?.ParseTestResult?.Cast()?.ToList(), (key, oldValue) => s?.ParseTestResult?.Cast()?.ToList()); tabs.Reload(); SelectedTabIndex = Tabs.Count - 1; } private async Task OnSummary() { var selectedTab = Tabs.Select(x => x.Key)?.FirstOrDefault(x => x.Id == SelectedTabIndex); if (selectedTab is not null) { //history에서만 summary 사용 if (selectedTab.EnumTab == EnumTabs.TestHistoryC1) { if (Tabs.TryGetValue(selectedTab, out var data) == true) { if (Int32.TryParse(SelectionStepVersion, out int stepVersion) == true) { var testHistories = data.Cast().ToList(); var summary = await CPXV2LogService.GetTestSummary(testHistories, stepVersion); var summaryInformation = testHistories.GetTestSummaryInformation(); if (summary is not null && summaryInformation is not null) { summaryInformation.SearchRangeStart = (DateTime)new DateTime(RequestSearch.SearchStart, TimeOnly.MinValue); summaryInformation.SearchRangeEnd = (DateTime)new DateTime(RequestSearch.SearchEnd, TimeOnly.MaxValue); int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestSummaryC1}({tabId})", EnumTab = EnumTabs.TestSummaryC1, Parent = new ParentRow { TabID = selectedTab.Id, Parent = summaryInformation } }, key => summary?.ParseTestSummary?.Cast()?.ToList(), (key, oldValue) => summary?.ParseTestSummary?.Cast()?.ToList()); tabs.Reload(); SelectedTabIndex = Tabs.Count - 1; } } } } else { LogXnet.WriteLine("Not history", LogXLabel.Warning); } } } private async Task OnDoubleClickRowSummary(SelectRow row) { var selectRow = row.Row as ParseTestSummary; if(selectRow is not null) { var historyTabId = Tabs.Select(x => x.Key)?.FirstOrDefault(x => x.Id == row.ParentTabID); var selectedTab = Tabs.Select(x => x.Key)?.FirstOrDefault(x => x.Id == historyTabId.Id); if (selectedTab is not null) { if (selectedTab.EnumTab == EnumTabs.TestHistoryC1) { if (Tabs.TryGetValue(selectedTab, out var data) == true) { if (Int32.TryParse(SelectionStepVersion, out int stepVersion) == true) { var testHistories = data.Cast().ToList(); var trend = await CPXV2LogService.GetTestTrend(testHistories, stepVersion, selectRow.StepNo); int tabId = Tabs.Max(x => x.Key.Id) + 1; Tabs.AddOrUpdate( new OrderdTab { Id = tabId, TabName = $"{EnumTabs.TestTrendC1}({tabId})", EnumTab = EnumTabs.TestTrendC1, Parent = new ParentRow { TabID = selectedTab.Id, Parent = trend } }, key => trend?.ParseTestTrend?.Cast()?.ToList(), (key, oldValue) => trend?.ParseTestTrend?.Cast()?.ToList()); tabs.Reload(); SelectedTabIndex = Tabs.Count - 1; } } } else { LogXnet.WriteLine("Not history", LogXLabel.Warning); } } } } private void OnClickClose(int tabId) { CloseTab(tabId); } private void CloseTab(int tabId) { var removeTab = Tabs.Where(x => x.Key.Id == tabId)?.First().Key; //remove if (removeTab is not null) { Tabs.TryRemove(removeTab, out var value); } //select tab var currentTab = tabs.SelectedTab; if (Tabs.Where(x => x.Key.TabName == currentTab.Text)?.Count() > 0) { SelectedTabIndex = currentTab.Index; } else { SelectedTabIndex = Tabs.Count - 1; } tabs.Reload(); } private async Task OnChangeMergePartNumberOption() { PopupService.OpenIndicator(""); await GetOverviews(); await Task.Delay(300); PopupService.CloseIndicator(); } private async Task OnClickDisplayTestList(TestHistory history) { await JS.InvokeVoidAsync("open", $"/testlist/{history.ProductNo}/{history.TestCode}/{SelectionStepVersion}", "_blank"); } private async Task OnExportExcel() { var tab = Tabs.FirstOrDefault(x => x.Key.Id == SelectedTabIndex); if(tab.Value?.Count > 0) { if (tab.Key.EnumTab == EnumTabs.OverviewC1 || tab.Key.EnumTab == EnumTabs.OverviewC1Detail || tab.Key.EnumTab == EnumTabs.OverviewC1Merged || tab.Key.EnumTab == EnumTabs.OverviewC1DetailMerged) await ExportToExcelAsync(tab.Value.Cast()); if(tab.Key.EnumTab == EnumTabs.TestSummaryC1) await ExportToExcelAsync(tab.Value.Cast()); } } public async Task ExportToExcelAsync(IEnumerable data, string fileName = "export.xlsx") { using var workbook = new XLWorkbook(); var worksheet = workbook.Worksheets.Add("Sheet1"); var properties = typeof(T).GetProperties(); // 헤더 for (int i = 0; i < properties.Length; i++) { worksheet.Cell(1, i + 1).Value = properties[i].Name; } // 데이터 int row = 2; foreach (var item in data) { for (int col = 0; col < properties.Length; col++) { var value = properties[col].GetValue(item); // if(value is int) // worksheet.Cell(row, col + 1).Value = Convert.ToInt32(value); // else if (value is double) // worksheet.Cell(row, col + 1).Value = Convert.ToDouble(value); worksheet.Cell(row, col + 1).Value = $" {value}"; } row++; } using var stream = new MemoryStream(); workbook.SaveAs(stream); var bytes = stream.ToArray(); await JS.InvokeVoidAsync("downloadFile", fileName, Convert.ToBase64String(bytes)); } }