完善数据报表模块
This commit is contained in:
@@ -7,6 +7,10 @@
|
|||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="ClosedXML" Version="0.104.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\ORM\ORM.csproj" />
|
<ProjectReference Include="..\ORM\ORM.csproj" />
|
||||||
<ProjectReference Include="..\Service\Service.csproj" />
|
<ProjectReference Include="..\Service\Service.csproj" />
|
||||||
|
|||||||
@@ -1,24 +1,16 @@
|
|||||||
using Logger;
|
using ClosedXML.Excel;
|
||||||
using MahApps.Metro.Controls;
|
using Logger;
|
||||||
|
using Microsoft.Win32;
|
||||||
using Model;
|
using Model;
|
||||||
using Model.Entity;
|
using Model.Entity;
|
||||||
using Model.Models;
|
using Model.Models;
|
||||||
using NLog.Targets;
|
|
||||||
using OxyPlot;
|
|
||||||
using Service.Interface;
|
using Service.Interface;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Data;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Threading;
|
|
||||||
using UIShare.GlobalVariable;
|
|
||||||
using UIShare.UIViewModel;
|
|
||||||
using UIShare.ViewModelBase;
|
using UIShare.ViewModelBase;
|
||||||
|
|
||||||
namespace ExportModule.ViewModels
|
namespace ExportModule.ViewModels
|
||||||
@@ -36,56 +28,231 @@ namespace ExportModule.ViewModels
|
|||||||
set { SetProperty(ref _testReportModelList, value); }
|
set { SetProperty(ref _testReportModelList, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DateTime? _startTime;
|
||||||
|
public DateTime? StartTime
|
||||||
|
{
|
||||||
|
get => _startTime;
|
||||||
|
set => SetProperty(ref _startTime, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private DateTime? _endTime;
|
||||||
|
public DateTime? EndTime
|
||||||
|
{
|
||||||
|
get => _endTime;
|
||||||
|
set => SetProperty(ref _endTime, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _selectedScope = "全部";
|
||||||
|
public string SelectedScope
|
||||||
|
{
|
||||||
|
get => _selectedScope;
|
||||||
|
set => SetProperty(ref _selectedScope, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObservableCollection<string> ScopeOptions { get; } = new()
|
||||||
|
{
|
||||||
|
"全部",
|
||||||
|
"TestCell1", "TestCell2", "TestCell3", "TestCell4",
|
||||||
|
"TestCell5", "TestCell6", "TestCell7", "TestCell8"
|
||||||
|
};
|
||||||
|
|
||||||
|
private string _statusMessage = "就绪";
|
||||||
|
public string StatusMessage
|
||||||
|
{
|
||||||
|
get => _statusMessage;
|
||||||
|
set => SetProperty(ref _statusMessage, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int _totalCount;
|
||||||
|
public int TotalCount
|
||||||
|
{
|
||||||
|
get => _totalCount;
|
||||||
|
set => SetProperty(ref _totalCount, value);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 命令
|
#region 命令
|
||||||
|
public ICommand LoadedCommand { get; }
|
||||||
|
public ICommand QueryCommand { get; }
|
||||||
|
public ICommand ExportCommand { get; }
|
||||||
|
#endregion
|
||||||
|
|
||||||
#endregion
|
|
||||||
public ICommand LoadedCommand { get; set; }
|
|
||||||
#region 私有字段
|
#region 私有字段
|
||||||
ITestReportService _testReportService { get; set; }
|
private readonly ITestReportService _testReportService;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public ExportViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
public ExportViewModel(IContainerProvider containerProvider) : base(containerProvider)
|
||||||
{
|
{
|
||||||
_testReportService = containerProvider.Resolve<ITestReportService>();
|
_testReportService = containerProvider.Resolve<ITestReportService>();
|
||||||
|
|
||||||
LoadedCommand = new AsyncDelegateCommand(OnLoad);
|
LoadedCommand = new AsyncDelegateCommand(OnLoad);
|
||||||
|
QueryCommand = new AsyncDelegateCommand(OnQuery);
|
||||||
|
ExportCommand = new AsyncDelegateCommand(OnExport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#region 命令处理
|
#region 命令处理
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载全部(无筛选条件)
|
||||||
|
/// </summary>
|
||||||
private async Task OnLoad()
|
private async Task OnLoad()
|
||||||
{
|
{
|
||||||
var result=await _testReportService.GetFilterList();
|
var result = await _testReportService.GetFilterList();
|
||||||
if (result.IsSuccess)
|
if (result.IsSuccess)
|
||||||
{
|
{
|
||||||
IList<TestReportModel> reportList = result.Data;
|
TestReportModelList = new ObservableCollection<TestReportModel>(result.Data ?? new List<TestReportModel>());
|
||||||
TestReportModelList = new ObservableCollection<TestReportModel>(reportList);
|
TotalCount = TestReportModelList.Count;
|
||||||
|
ShowInfoMessageBox($"加载完成,共 {TotalCount} 条记录", () => { });
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TestReportModelList = new();
|
TestReportModelList = new ObservableCollection<TestReportModel>();
|
||||||
|
TotalCount = 0;
|
||||||
|
ShowErrorMessageBox($"加载失败:{result.Msg}", () => { });
|
||||||
|
LoggerHelper.Error(result.Msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询(根据开始日期、结束日期、台架名称筛选)
|
||||||
|
/// </summary>
|
||||||
|
private async Task OnQuery()
|
||||||
|
{
|
||||||
|
// 处理结束日期:若用户只选了日期没选时间,默认到当天末尾
|
||||||
|
DateTime? queryEnd = EndTime;
|
||||||
|
if (queryEnd.HasValue)
|
||||||
|
{
|
||||||
|
queryEnd = queryEnd.Value.Date.AddDays(1).AddSeconds(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
string? scope = SelectedScope == "全部" ? null : SelectedScope;
|
||||||
|
|
||||||
|
var result = await _testReportService.GetFilterList(StartTime, queryEnd, scope);
|
||||||
|
if (result.IsSuccess)
|
||||||
|
{
|
||||||
|
TestReportModelList = new ObservableCollection<TestReportModel>(result.Data ?? new List<TestReportModel>());
|
||||||
|
TotalCount = TestReportModelList.Count;
|
||||||
|
ShowInfoMessageBox($"查询完成,共 {TotalCount} 条记录", () => { });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TestReportModelList = new ObservableCollection<TestReportModel>();
|
||||||
|
TotalCount = 0;
|
||||||
|
ShowErrorMessageBox($"查询失败:{result.Msg}", () => { });
|
||||||
|
LoggerHelper.Error(result.Msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 导出 Excel(根据当前筛选条件导出完整实体数据)
|
||||||
|
/// </summary>
|
||||||
|
private async Task OnExport()
|
||||||
|
{
|
||||||
|
DateTime? queryEnd = EndTime;
|
||||||
|
if (queryEnd.HasValue)
|
||||||
|
{
|
||||||
|
queryEnd = queryEnd.Value.Date.AddDays(1).AddSeconds(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
string? scope = SelectedScope == "全部" ? null : SelectedScope;
|
||||||
|
|
||||||
|
// 查询全量实体数据
|
||||||
|
StatusMessage = "正在查询导出数据...";
|
||||||
|
var entityResult = await _testReportService.GetEntitiesByFilter(StartTime, queryEnd, scope);
|
||||||
|
if (!entityResult.IsSuccess || entityResult.Data == null || entityResult.Data.Count == 0)
|
||||||
|
{
|
||||||
|
ShowErrorMessageBox("没有数据可导出,请先查询或调整筛选条件。", () => { });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dialog = new SaveFileDialog
|
||||||
|
{
|
||||||
|
Filter = "Excel 工作簿 (*.xlsx)|*.xlsx|所有文件 (*.*)|*.*",
|
||||||
|
DefaultExt = ".xlsx",
|
||||||
|
FileName = $"测试报告_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() != true) return;
|
||||||
|
|
||||||
|
var entities = entityResult.Data;
|
||||||
|
StatusMessage = $"正在导出 {entities.Count} 条记录...";
|
||||||
|
await Task.Run(() => ExportToExcel(dialog.FileName, entities));
|
||||||
|
ShowInfoMessageBox($"导出完成,共 {entities.Count} 条记录,已保存至:{dialog.FileName}", () => { });
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 辅助方法
|
#region 辅助方法
|
||||||
|
|
||||||
|
private static void ExportToExcel(string filePath, List<TestReportEntity> entities)
|
||||||
|
{
|
||||||
|
using var workbook = new XLWorkbook();
|
||||||
|
var ws = workbook.Worksheets.Add("测试报告");
|
||||||
|
|
||||||
|
// 表头
|
||||||
|
string[] headers = {
|
||||||
|
"Id", "CreateTime", "TestRoundId", "Scope", "FileName",
|
||||||
|
"StepIndex", "StepName", "StepType", "MethodName", "MethodFullName",
|
||||||
|
"Result", "RunTimeMs", "OutputValue", "Depth", "IsErrorStep", "LoopRemaining"
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int c = 0; c < headers.Length; c++)
|
||||||
|
{
|
||||||
|
ws.Cell(1, c + 1).Value = headers[c];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 标题行样式
|
||||||
|
var headerRange = ws.Range(1, 1, 1, headers.Length);
|
||||||
|
headerRange.Style.Font.Bold = true;
|
||||||
|
headerRange.Style.Fill.BackgroundColor = XLColor.FromArgb(0xECEFF4);
|
||||||
|
headerRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
|
||||||
|
headerRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
|
||||||
|
|
||||||
|
// 填充数据
|
||||||
|
for (int i = 0; i < entities.Count; i++)
|
||||||
|
{
|
||||||
|
var e = entities[i];
|
||||||
|
int row = i + 2;
|
||||||
|
|
||||||
|
ws.Cell(row, 1).Value = e.Id;
|
||||||
|
ws.Cell(row, 2).Value = e.CreateTime.ToString("yyyy-MM-dd HH:mm:ss");
|
||||||
|
ws.Cell(row, 3).Value = e.TestRoundId.ToString();
|
||||||
|
ws.Cell(row, 4).Value = e.Scope ?? "";
|
||||||
|
ws.Cell(row, 5).Value = e.FileName ?? "";
|
||||||
|
ws.Cell(row, 6).Value = e.StepIndex;
|
||||||
|
ws.Cell(row, 7).Value = e.StepName ?? "";
|
||||||
|
ws.Cell(row, 8).Value = e.StepType ?? "";
|
||||||
|
ws.Cell(row, 9).Value = e.MethodName ?? "";
|
||||||
|
ws.Cell(row, 10).Value = e.MethodFullName ?? "";
|
||||||
|
ws.Cell(row, 11).Value = e.Result;
|
||||||
|
ws.Cell(row, 12).Value = e.RunTimeMs;
|
||||||
|
ws.Cell(row, 13).Value = e.OutputValue ?? "";
|
||||||
|
ws.Cell(row, 14).Value = e.Depth;
|
||||||
|
ws.Cell(row, 15).Value = e.IsErrorStep ? "是" : "否";
|
||||||
|
ws.Cell(row, 16).Value = e.LoopRemaining;
|
||||||
|
|
||||||
|
// 数据行边框
|
||||||
|
var dataRange = ws.Range(row, 1, row, headers.Length);
|
||||||
|
dataRange.Style.Border.OutsideBorder = XLBorderStyleValues.Thin;
|
||||||
|
dataRange.Style.Border.InsideBorder = XLBorderStyleValues.Thin;
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.Columns().AdjustToContents();
|
||||||
|
workbook.SaveAs(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 生命周期
|
#region 生命周期
|
||||||
|
|
||||||
public override void OnNavigatedTo(NavigationContext navigationContext)
|
public override void OnNavigatedTo(NavigationContext navigationContext)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,203 @@
|
|||||||
<UserControl x:Class="ExportModule.Views.ExportView"
|
<UserControl x:Class="ExportModule.Views.ExportView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
||||||
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
mc:Ignorable="d"
|
xmlns:prism="http://prismlibrary.com/"
|
||||||
xmlns:prism="http://prismlibrary.com/"
|
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
||||||
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
|
xmlns:converters="clr-namespace:UIShare.Converters;assembly=UIShare"
|
||||||
prism:ViewModelLocator.AutoWireViewModel="True"
|
prism:ViewModelLocator.AutoWireViewModel="True"
|
||||||
d:DesignHeight="1080" d:DesignWidth="1920">
|
mc:Ignorable="d"
|
||||||
<i:Interaction.Triggers>
|
d:DesignHeight="700"
|
||||||
<i:EventTrigger EventName="Loaded">
|
d:DesignWidth="1200">
|
||||||
<i:InvokeCommandAction Command="{Binding LoadedCommand}"/>
|
<UserControl.Resources>
|
||||||
</i:EventTrigger>
|
<converters:LessThanConverter x:Key="LessThanConverter"/>
|
||||||
</i:Interaction.Triggers>
|
</UserControl.Resources>
|
||||||
<Grid>
|
|
||||||
|
<Border Background="#F5F7FA">
|
||||||
</Grid>
|
<Grid x:Name="RootGrid" Margin="8">
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- ========== 标题 ========== -->
|
||||||
|
<TextBlock Grid.Row="0"
|
||||||
|
Text="测试报告导出"
|
||||||
|
FontSize="20" FontWeight="Bold"
|
||||||
|
Margin="4,4,0,12"/>
|
||||||
|
|
||||||
|
<!-- ========== 主内容卡片 ========== -->
|
||||||
|
<Border Grid.Row="1"
|
||||||
|
Background="White"
|
||||||
|
BorderBrush="#DDD" BorderThickness="1"
|
||||||
|
CornerRadius="4">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<!-- 工具栏 -->
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
|
<!-- 数据表格 -->
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- ====== 工具栏(筛选条件 + 操作按钮) ====== -->
|
||||||
|
<Border Grid.Row="0"
|
||||||
|
Background="#ECEFF4"
|
||||||
|
Padding="12,8"
|
||||||
|
BorderBrush="#DDD" BorderThickness="0,0,0,1">
|
||||||
|
|
||||||
|
<!-- 第一行:筛选条件 -->
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="160"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="160"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="120"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<!-- 开始日期 -->
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
Text="开始日期:"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Margin="0,0,4,0"/>
|
||||||
|
<DatePicker Grid.Column="1"
|
||||||
|
materialDesign:HintAssist.Hint=""
|
||||||
|
SelectedDate="{Binding StartTime}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0,0,16,0"/>
|
||||||
|
|
||||||
|
<!-- 结束日期 -->
|
||||||
|
<TextBlock Grid.Column="2"
|
||||||
|
Text="结束日期:"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Margin="0,0,4,0"/>
|
||||||
|
<DatePicker Grid.Column="3"
|
||||||
|
materialDesign:HintAssist.Hint=""
|
||||||
|
SelectedDate="{Binding EndTime}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0,0,16,0"/>
|
||||||
|
|
||||||
|
<!-- 台架选择 -->
|
||||||
|
<TextBlock Grid.Column="4"
|
||||||
|
Text="台架:"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontWeight="SemiBold"
|
||||||
|
Margin="0,0,4,0"/>
|
||||||
|
<ComboBox Grid.Column="5"
|
||||||
|
materialDesign:HintAssist.Hint=""
|
||||||
|
ItemsSource="{Binding ScopeOptions}"
|
||||||
|
SelectedItem="{Binding SelectedScope}"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="0,0,16,0"/>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<Button Grid.Column="6"
|
||||||
|
Content="查询"
|
||||||
|
Command="{Binding QueryCommand}"
|
||||||
|
Style="{StaticResource MaterialDesignFlatButton}"
|
||||||
|
Padding="16,6"
|
||||||
|
Margin="4,0"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Button Grid.Column="7"
|
||||||
|
Content="导出 Excel"
|
||||||
|
Command="{Binding ExportCommand}"
|
||||||
|
Style="{StaticResource MaterialDesignFlatButton}"
|
||||||
|
Padding="16,6"
|
||||||
|
Margin="4,0"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Button Grid.Column="8"
|
||||||
|
Content="加载全部"
|
||||||
|
Command="{Binding LoadedCommand}"
|
||||||
|
Style="{StaticResource MaterialDesignFlatButton}"
|
||||||
|
Padding="16,6"
|
||||||
|
Margin="4,0"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- ====== 数据展示区 ====== -->
|
||||||
|
<DataGrid Grid.Row="1"
|
||||||
|
ItemsSource="{Binding TestReportModelList}"
|
||||||
|
AutoGenerateColumns="False"
|
||||||
|
IsReadOnly="True"
|
||||||
|
RowHeaderWidth="0"
|
||||||
|
BorderThickness="0"
|
||||||
|
Background="White"
|
||||||
|
AlternatingRowBackground="#F5F7FA"
|
||||||
|
SelectionMode="Single"
|
||||||
|
Margin="8">
|
||||||
|
<DataGrid.Columns>
|
||||||
|
<DataGridTextColumn Header="TestRoundId"
|
||||||
|
Width="280"
|
||||||
|
Binding="{Binding TestRoundId}"/>
|
||||||
|
<DataGridTextColumn Header="台架名称"
|
||||||
|
Width="120"
|
||||||
|
Binding="{Binding Scope}"/>
|
||||||
|
<DataGridTextColumn Header="开始时间"
|
||||||
|
Width="180"
|
||||||
|
Binding="{Binding StartTime, StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}"/>
|
||||||
|
<DataGridTextColumn Header="结束时间"
|
||||||
|
Width="180"
|
||||||
|
Binding="{Binding EndTime, StringFormat={}{0:yyyy-MM-dd HH:mm:ss}}"/>
|
||||||
|
<DataGridTextColumn Header="文件名"
|
||||||
|
Width="*"
|
||||||
|
Binding="{Binding FileName}"/>
|
||||||
|
</DataGrid.Columns>
|
||||||
|
<DataGrid.Resources>
|
||||||
|
<!-- 标题行样式:与项目风格一致 -->
|
||||||
|
<Style TargetType="DataGridColumnHeader">
|
||||||
|
<Setter Property="Background" Value="#ECEFF4"/>
|
||||||
|
<Setter Property="FontWeight" Value="Bold"/>
|
||||||
|
<Setter Property="BorderBrush" Value="#DDD"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0,0,1,1"/>
|
||||||
|
<Setter Property="Padding" Value="8,6"/>
|
||||||
|
</Style>
|
||||||
|
<Style TargetType="DataGridCell">
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Setter Property="Padding" Value="8,4"/>
|
||||||
|
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||||
|
</Style>
|
||||||
|
</DataGrid.Resources>
|
||||||
|
</DataGrid>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- ========== 状态栏 ========== -->
|
||||||
|
<Border Grid.Row="2"
|
||||||
|
Background="#ECEFF4"
|
||||||
|
Padding="10,6"
|
||||||
|
Margin="0,8,0,0"
|
||||||
|
CornerRadius="2">
|
||||||
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<TextBlock Grid.Column="0"
|
||||||
|
Text="{Binding StatusMessage}"
|
||||||
|
Foreground="#444"
|
||||||
|
FontSize="12"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<TextBlock Grid.Column="1"
|
||||||
|
Foreground="#666"
|
||||||
|
FontSize="12"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Margin="8,0,0,0">
|
||||||
|
<Run Text="记录数:"/>
|
||||||
|
<Run Text="{Binding TotalCount}"/>
|
||||||
|
</TextBlock>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -38,22 +38,35 @@ namespace Service.Implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据 TestRoundId 分组,获取唯一记录并按分组统计最大与最小时间
|
/// 根据 TestRoundId 分组,获取唯一记录并按分组统计最大与最小时间,
|
||||||
|
/// 支持按日期范围与台架名称筛选。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<Result<IList<TestReportModel>>> GetFilterList()
|
public async Task<Result<IList<TestReportModel>>> GetFilterList(DateTime? startTime = null, DateTime? endTime = null, string? scope = null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 使用 SqlSugar 的 GroupBy 查询,聚合最大/最小时间
|
// 使用 SqlSugar 的 GroupBy 查询,聚合最大/最小时间
|
||||||
// 推荐采用这种按组投影的方式,将分组计算交由数据库处理,性能最佳
|
// 推荐采用这种按组投影的方式,将分组计算交由数据库处理,性能最佳
|
||||||
var list = await _repository.Context.Queryable<TestReportEntity>()
|
var query = _repository.Context.Queryable<TestReportEntity>();
|
||||||
|
|
||||||
|
// 日期范围筛选
|
||||||
|
if (startTime.HasValue)
|
||||||
|
query = query.Where(x => x.CreateTime >= startTime.Value);
|
||||||
|
if (endTime.HasValue)
|
||||||
|
query = query.Where(x => x.CreateTime <= endTime.Value);
|
||||||
|
|
||||||
|
// 台架名称筛选
|
||||||
|
if (!string.IsNullOrEmpty(scope))
|
||||||
|
query = query.Where(x => x.Scope == scope);
|
||||||
|
|
||||||
|
var list = await query
|
||||||
.GroupBy(x => x.TestRoundId)
|
.GroupBy(x => x.TestRoundId)
|
||||||
.Select(x => new TestReportModel
|
.Select(x => new TestReportModel
|
||||||
{
|
{
|
||||||
TestRoundId = x.TestRoundId,
|
TestRoundId = x.TestRoundId,
|
||||||
StartTime = SqlFunc.AggregateMin(x.CreateTime),
|
StartTime = SqlFunc.AggregateMin(x.CreateTime),
|
||||||
EndTime = SqlFunc.AggregateMax(x.CreateTime),
|
EndTime = SqlFunc.AggregateMax(x.CreateTime),
|
||||||
Scope=x.Scope,
|
Scope = x.Scope,
|
||||||
FileName = x.FileName,
|
FileName = x.FileName,
|
||||||
})
|
})
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
@@ -65,5 +78,32 @@ namespace Service.Implement
|
|||||||
return Result<IList<TestReportModel>>.Error("获取分组过滤列表失败", ex);
|
return Result<IList<TestReportModel>>.Error("获取分组过滤列表失败", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 根据日期和台架名称筛选获取完整的测试步骤实体列表(无分组,用于导出)
|
||||||
|
/// </summary>
|
||||||
|
public async Task<Result<List<TestReportEntity>>> GetEntitiesByFilter(DateTime? startTime = null, DateTime? endTime = null, string? scope = null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var query = _repository.Context.Queryable<TestReportEntity>();
|
||||||
|
|
||||||
|
if (startTime.HasValue)
|
||||||
|
query = query.Where(x => x.CreateTime >= startTime.Value);
|
||||||
|
if (endTime.HasValue)
|
||||||
|
query = query.Where(x => x.CreateTime <= endTime.Value);
|
||||||
|
if (!string.IsNullOrEmpty(scope))
|
||||||
|
query = query.Where(x => x.Scope == scope);
|
||||||
|
|
||||||
|
var list = await query
|
||||||
|
.OrderBy(x => x.CreateTime)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Result<List<TestReportEntity>>.Success(list);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return Result<List<TestReportEntity>>.Error("获取导出数据失败", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,17 @@ namespace Service.Interface
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 根据 TestRoundId 分组,获取唯一记录并按分组统计最大与最小时间
|
/// 根据 TestRoundId 分组,获取唯一记录并按分组统计最大与最小时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Task<Result<IList<TestReportModel>>> GetFilterList();
|
/// <param name="startTime">开始日期筛选(可选)</param>
|
||||||
|
/// <param name="endTime">结束日期筛选(可选)</param>
|
||||||
|
/// <param name="scope">台架名称筛选(可选)</param>
|
||||||
|
Task<Result<IList<TestReportModel>>> GetFilterList(DateTime? startTime = null, DateTime? endTime = null, string? scope = null);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据日期和台架名称筛选获取完整的测试步骤实体列表(无分组,用于导出)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="startTime">开始日期筛选(可选)</param>
|
||||||
|
/// <param name="endTime">结束日期筛选(可选)</param>
|
||||||
|
/// <param name="scope">台架名称筛选(可选)</param>
|
||||||
|
Task<Result<List<TestReportEntity>>> GetEntitiesByFilter(DateTime? startTime = null, DateTime? endTime = null, string? scope = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user