[성현모] VPKI 페이징, csv 다운로드 수정
This commit is contained in:
Binary file not shown.
@ -95,6 +95,40 @@ namespace SystemX.Core.Communication
|
||||
return response;
|
||||
}
|
||||
|
||||
public virtual async Task<Stream?> GetStreamAsync(string url, string bearerToken = "", short timeOutSeconds = 10)
|
||||
{
|
||||
Guid guid = Guid.NewGuid();
|
||||
|
||||
Stream stream = null;
|
||||
|
||||
using (HttpClient httpClient = new HttpClient(GetClientHandler()))
|
||||
{
|
||||
try
|
||||
{
|
||||
var timeOutSec = SetTimeout(timeOutSeconds);
|
||||
httpClient.Timeout = new TimeSpan(0, 0, timeOutSec);
|
||||
httpClient.BaseAddress = new Uri($"{url}");
|
||||
|
||||
if (string.IsNullOrEmpty(bearerToken) == false)
|
||||
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", $"{bearerToken}");
|
||||
|
||||
Log4net.WriteLine($"[GET] Request({guid})::{url}", LogType.HTTP);
|
||||
|
||||
DateTime requestTime = DateTime.Now;
|
||||
var response = await httpClient.GetAsync(url);
|
||||
stream = await response.Content.ReadAsStreamAsync();
|
||||
|
||||
Log4net.WriteLine($"[GET] Rseponse({guid}) ({(DateTime.Now - requestTime).TotalSeconds} sec)::{url}", LogType.HTTP);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log4net.WriteLine(e);
|
||||
}
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
protected HttpClientHandler GetClientHandler()
|
||||
{
|
||||
|
||||
@ -14,5 +14,7 @@ namespace VPKI.Library.Model
|
||||
public TCertificate? TCertificate { get; set; }
|
||||
public TVerifyResult? TVerifyResult { get; set; }
|
||||
public TOcsp? TOcsp { get; set; }
|
||||
|
||||
public int TotalCount { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -575,11 +575,6 @@ namespace VPKI.Library.Services
|
||||
hashedCsr.EncodedSignedCsr = GetKeyBase64Encrypted(vnDEREncVal);
|
||||
hashedCsr.Verify = bVerfRst;
|
||||
|
||||
Log4net.WriteLine($"SignHashed02 csr::{csr}", LogType.Fatal);
|
||||
Log4net.WriteLine($"SignHashed02 Public Key::{GetKeyBase64Encrypted(GetPublicKeyBC(keyPair)!.Q.GetEncoded()!.ToList())}", LogType.Fatal);
|
||||
Log4net.WriteLine($"SignHashed02 SignedCsr::{hashedCsr.SignedCsr}", LogType.Fatal);
|
||||
Log4net.WriteLine($"SignHashed02 EncodedSignedCsr::{hashedCsr.EncodedSignedCsr}", LogType.Fatal);
|
||||
|
||||
var decoded = DecodeDERSignature_02(vnDEREncVal);
|
||||
|
||||
await Task.CompletedTask;
|
||||
@ -602,10 +597,6 @@ namespace VPKI.Library.Services
|
||||
List<byte> vnDEREncVal = EncodeDERSignature_20(vnSignedHash);
|
||||
bool bVerfRst = VerifyHashBC(vnSignedHash, vnRHashVal, GetPublicKeyBC(keyPair), ECDSAType.NONEWITHECDSA);
|
||||
|
||||
Log4net.WriteLine($"SignHashed20 csr::{csr}", LogType.Fatal);
|
||||
Log4net.WriteLine($"SignHashed20 Public Key::{GetKeyBase64Encrypted(GetPublicKeyBC(keyPair)!.Q.GetEncoded()!.ToList())}", LogType.Fatal);
|
||||
Log4net.WriteLine($"SignHashed20 bVerfRst::{bVerfRst}", LogType.Fatal);
|
||||
|
||||
hashedCsr.SignedCsr = GetKeyBase64Encrypted(vnSignedHash);
|
||||
hashedCsr.EncodedSignedCsr = GetKeyBase64Encrypted(vnDEREncVal);
|
||||
hashedCsr.Verify = bVerfRst;
|
||||
|
||||
@ -8,7 +8,7 @@ using VPKI.Library.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Controllers
|
||||
{
|
||||
public class CommonController
|
||||
public class CommonController : ControllerBase
|
||||
{
|
||||
public readonly IServiceProvider _serviceProvider;
|
||||
public readonly IHttpContextAccessor _httpContextAccessor;
|
||||
|
||||
@ -1,7 +1,12 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using DB.VPKI_DataDB;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Http.HttpResults;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using VPKI.Library.Enums;
|
||||
using VPKI.Library.Model;
|
||||
using VPKI.Library.Static;
|
||||
using VPKI.Web.Api.Services;
|
||||
|
||||
namespace VPKI.Web.Api.Controllers
|
||||
@ -19,7 +24,7 @@ namespace VPKI.Web.Api.Controllers
|
||||
[Tags("VPKI API Base")]
|
||||
[HttpGet]
|
||||
[Route("history")]
|
||||
public async Task<IResult> TbscsrHistory(DateTime startDate, DateTime endDate)
|
||||
public async Task<IResult> TbscsrHistory(DateTime startDate, DateTime endDate, [FromQuery] TTbscsr filter, int page = 1)
|
||||
{
|
||||
List<CertificateHistoryModel> response = new List<CertificateHistoryModel>();
|
||||
|
||||
@ -27,7 +32,7 @@ namespace VPKI.Web.Api.Controllers
|
||||
var service = _serviceProvider.GetService<VpkiBaseService>();
|
||||
if (service != null)
|
||||
{
|
||||
response = await service.History(DateOnly.FromDateTime(startDate), DateOnly.FromDateTime(endDate));
|
||||
response = await service.History(DateOnly.FromDateTime(startDate), DateOnly.FromDateTime(endDate), filter, page);
|
||||
}
|
||||
|
||||
long min = 0;
|
||||
@ -129,5 +134,40 @@ namespace VPKI.Web.Api.Controllers
|
||||
|
||||
return Results.Ok(response);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// csv
|
||||
/// </summary>
|
||||
[Tags("VPKI API Base")]
|
||||
[HttpGet]
|
||||
[Route("exportCsv")]
|
||||
[ApiExplorerSettings(IgnoreApi = false)]
|
||||
public async Task<IActionResult> ExportCsv(DateTime startDate, DateTime endDate, [FromQuery] TTbscsr filter)
|
||||
{
|
||||
Log4net.WriteLine(GetRequestLog().LogModelToString("Request"), LogType.CONTROLLER);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
int row = 0;
|
||||
|
||||
var service = _serviceProvider.GetService<VpkiBaseService>();
|
||||
if (service != null)
|
||||
{
|
||||
var csvData = await service.History(DateOnly.FromDateTime(startDate), DateOnly.FromDateTime(endDate), filter, -1);
|
||||
row = csvData.Count;
|
||||
|
||||
foreach (var line in csvData.ConvertToCsvFile())
|
||||
{
|
||||
sb.AppendLine(line);
|
||||
}
|
||||
}
|
||||
Log4net.WriteLine($"Response::Export CSV, {row} Rows", LogType.CONTROLLER);
|
||||
|
||||
// UTF-8 BOM 포함 (Excel에서 깨지지 않도록 하기 위해)
|
||||
var bom = Encoding.UTF8.GetPreamble();
|
||||
var csvBytes = Encoding.UTF8.GetBytes(sb.ToString());
|
||||
var resultBytes = bom.Concat(csvBytes).ToArray();
|
||||
|
||||
return File(resultBytes, "text/csv", $"VPKI_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.csv");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,10 +181,6 @@ namespace VPKI.Web.Api.Services
|
||||
else
|
||||
{
|
||||
var publicKeyPem = $"{_certificateService.ConvertToPEM(Convert.FromBase64String(csr.CPublickey))}";
|
||||
Log4net.WriteLine($"Failed HashedTbscsr::{csr.CHashedTbscsr}", LogType.Fatal);
|
||||
Log4net.WriteLine($"Failed Signature::{request.csrsignature}", LogType.Fatal);
|
||||
Log4net.WriteLine($"Failed PublicKey::{csr.CPublickey}", LogType.Fatal);
|
||||
Log4net.WriteLine($"Failed PublicKey::{publicKeyPem}", LogType.Fatal);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@ -42,10 +42,10 @@ namespace VPKI.Web.Api.Services
|
||||
request.certType = VpkiType.vehicle_cert.ToString();
|
||||
}
|
||||
|
||||
string pcid = _certificateService.CreatePCID(request, VpkiType.prov_v1);
|
||||
string dn = $"cn={_certificateService.CreatePCID(request, VpkiType.prov_cert)},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}";
|
||||
if (request.certType == VpkiType.vehicle_cert.ToString() || request.certType == VpkiType.evcc_cert.ToString())
|
||||
dn = $"cn={_certificateService.CreatePCID(request, VpkiType.vehicle_cert)},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}";
|
||||
string pcid = _certificateService.CreatePCID(request, VpkiType.vehicle_cert);
|
||||
if (request.certType == VpkiType.evcc_cert.ToString())
|
||||
pcid = _certificateService.CreatePCID(request, VpkiType.evcc_cert);
|
||||
string dn = $"cn={pcid},ou={request.certInfo.tierCode},ou={request.certInfo.unitCode},ou=ECC,o=HKMC,dc={request.certInfo.dc}";
|
||||
|
||||
string csrOrigin = _certificateService.CreateCsr512(dn, request.publickey);
|
||||
string tbaCsrHashed = string.Empty;
|
||||
@ -192,10 +192,6 @@ namespace VPKI.Web.Api.Services
|
||||
else
|
||||
{
|
||||
var publicKeyPem = $"{_certificateService.ConvertToPEM(Convert.FromBase64String(csr.CPublickey))}";
|
||||
Log4net.WriteLine($"Failed HashedTbscsr::{csr.CHashedTbscsr}", LogType.Fatal);
|
||||
Log4net.WriteLine($"Failed Signature::{request.csrsignature}", LogType.Fatal);
|
||||
Log4net.WriteLine($"Failed PublicKey::{csr.CPublickey}", LogType.Fatal);
|
||||
Log4net.WriteLine($"Failed PublicKey::{publicKeyPem}", LogType.Fatal);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
using Azure;
|
||||
using DB.VPKI_DataDB;
|
||||
using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage;
|
||||
using Microsoft.AspNetCore.Mvc.ViewEngines;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion.Internal;
|
||||
using Microsoft.Extensions.FileSystemGlobbing.Internal;
|
||||
using Microsoft.Identity.Client;
|
||||
using Org.BouncyCastle.Crypto.Macs;
|
||||
using Org.BouncyCastle.Crypto.Signers;
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
using System.Collections.Generic;
|
||||
@ -44,10 +46,13 @@ namespace VPKI.Web.Api.Services
|
||||
}
|
||||
|
||||
#region 공통 사용 함수
|
||||
public async Task<List<CertificateHistoryModel>> History(DateOnly startDate, DateOnly endDate)
|
||||
public async Task<List<CertificateHistoryModel>> History(DateOnly startDate, DateOnly endDate, TTbscsr filter, int page = 1)
|
||||
{
|
||||
List<CertificateHistoryModel> response = new List<CertificateHistoryModel>();
|
||||
|
||||
int rowCount = 20;
|
||||
int totalCount = 0;
|
||||
|
||||
using (var scope = _scopeFactory.CreateScope())
|
||||
{
|
||||
var context = scope.ServiceProvider.GetRequiredService<VpkiDataDbContext>();
|
||||
@ -56,7 +61,22 @@ namespace VPKI.Web.Api.Services
|
||||
using (var transaction = await context.CreateTransactionAsync(System.Data.IsolationLevel.ReadUncommitted))
|
||||
{
|
||||
var getList = await context.TTbscsrs.AsNoTracking().Where(x => startDate <= DateOnly.FromDateTime(x.CDateTime.Date)
|
||||
&& DateOnly.FromDateTime(x.CDateTime.Date) <= endDate).ToListAsync();
|
||||
&& DateOnly.FromDateTime(x.CDateTime.Date) <= endDate
|
||||
&& EF.Functions.Like(x.CIftid, $"%{filter.CIftid}%")
|
||||
&& EF.Functions.Like(x.CMacaddr, $"%{filter.CMacaddr}%")
|
||||
&& EF.Functions.Like(x.CWmi, $"%{filter.CWmi}%")
|
||||
&& EF.Functions.Like(x.CIdType, $"%{filter.CIdType}%")
|
||||
&& EF.Functions.Like(x.CSupplierId, $"%{filter.CSupplierId}%")
|
||||
&& EF.Functions.Like(x.CDc, $"%{filter.CDc}%")
|
||||
&& EF.Functions.Like(x.CTierCode, $"%{filter.CTierCode}%")
|
||||
&& EF.Functions.Like(x.CUnitCode, $"%{filter.CUnitCode}%")
|
||||
&& EF.Functions.Like(x.CCertType, $"%{filter.CCertType}%")
|
||||
&& EF.Functions.Like(x.CPcid, $"%{filter.CPcid}%")).OrderByDescending(x=>x.CCuid).ToListAsync();
|
||||
|
||||
totalCount = getList.Count;
|
||||
if(page >= 0)
|
||||
getList = getList.Skip((page - 1) * rowCount).Take(rowCount).ToList();
|
||||
|
||||
response.AddRange(getList.Select(x => new CertificateHistoryModel { TTbscsr = x, TCertificate = null }));
|
||||
|
||||
foreach (var r in response)
|
||||
@ -72,6 +92,8 @@ namespace VPKI.Web.Api.Services
|
||||
var ocspResult = await context.TOcsps.AsNoTracking().FirstOrDefaultAsync(x => x.CCuid == r!.TTbscsr!.CCuid);
|
||||
if (ocspResult != null)
|
||||
r.TOcsp = ocspResult;
|
||||
|
||||
r.TotalCount = totalCount;
|
||||
}
|
||||
|
||||
await context.CloseTransactionAsync(transaction);
|
||||
|
||||
@ -31,38 +31,29 @@
|
||||
<RadzenLabel Style="margin-right: 5px;" Text="~"></RadzenLabel>
|
||||
<RadzenDatePicker Style="margin-right: 10px;" @bind-Value="@SearchEndDate" DateFormat="yyyy/MM/dd" />
|
||||
|
||||
<RadzenButton Style="margin-right: 30px;" Click="@(()=>Search(0))">Search</RadzenButton>
|
||||
<RadzenButton Style="margin-right: 30px;" Click="@(()=>Search())">Search</RadzenButton>
|
||||
|
||||
<!--vew Count-->
|
||||
<RadzenLabel Style="margin-right: 5px;" Text="ViewCount (20~100)"></RadzenLabel>
|
||||
<RadzenNumeric @bind-Value=@ViewCount Min=20 Max=100></RadzenNumeric>
|
||||
@* <RadzenLabel Style="margin-right: 5px;" Text="ViewCount (20~100)"></RadzenLabel>
|
||||
<RadzenNumeric @bind-Value=@ViewCount Min=20 Max=100></RadzenNumeric> *@
|
||||
</div>
|
||||
</RadzenFieldset>
|
||||
<br />
|
||||
<!--count-->
|
||||
<div style="display: flex; justify-content: space-between; margin-bottom: 0.7rem;">
|
||||
<div style="display: flex; align-items:center;">
|
||||
@* <div style="display: flex; align-items:center;">
|
||||
<RadzenLabel Style="color:#BA68C8; font-weight: 600; font-size: 1.1rem; margin-right: 1.2rem;" Text=@($"Total Count: {history.Count}")></RadzenLabel>
|
||||
<RadzenLabel Style="color:#64B5F6; font-weight: 600; font-size: 1.1rem;" Text=@($"Filter Count: {grid.View.Count()}")></RadzenLabel>
|
||||
</div>
|
||||
</div> *@
|
||||
<div>
|
||||
<RadzenButton Style="background: #7E57C2; margin-right: 0.5rem;" Text="Export CSV(Full Data)" Click="@(()=>OnClickExportCSV(false))"></RadzenButton>
|
||||
<RadzenButton Style="background: #1976D2;" Text="Export CSV(Filter Data)" Click="@(()=>OnClickExportCSV(true))"></RadzenButton>
|
||||
<RadzenButton Style="background: #7E57C2; margin-right: 0.5rem;" Text="Export CSV" Click="@(()=>OnClickExportCSV())"></RadzenButton>
|
||||
@* <RadzenButton Style="background: #1976D2;" Text="Export CSV(Filter Data)" Click="@(()=>OnClickExportCSV(true))"></RadzenButton> *@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RadzenDataGrid @ref="@grid" Data="@history" TItem="CertificateHistoryModel" AllowFiltering FilterMode="FilterMode.Simple"
|
||||
AllowPaging PageNumbersCount="10" PageSize="@ViewCount" PagerHorizontalAlign="HorizontalAlign.Center" AllowSorting RowExpand="@((args)=>OnExpand(args))"
|
||||
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" Filter="@OnChangeFilter" FilterCleared="@OnChangeFilter">
|
||||
<RadzenDataGrid @ref="@grid" Data="@history" TItem="CertificateHistoryModel" AllowFiltering FilterMode="FilterMode.Simple" Filter="OnChangeFilter" RowExpand="@((args)=>OnExpand(args))"
|
||||
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive">
|
||||
<Columns>
|
||||
|
||||
<!--index or no-->
|
||||
@* <RadzenDataGridColumn Title="No">
|
||||
<Template>
|
||||
@(history.IndexOf(context)+1)
|
||||
</Template>
|
||||
</RadzenDataGridColumn> *@
|
||||
|
||||
<!--data-->
|
||||
@foreach (var prop in typeof(TTbscsr).GetProperties())
|
||||
{
|
||||
@ -71,7 +62,29 @@
|
||||
continue;
|
||||
|
||||
string propName = $"{prop.Name}";
|
||||
<RadzenDataGridColumn Title="@propName" Property=@($"TTbscsr.{propName}") />
|
||||
//filter 없음
|
||||
if (propName.ToLower().Contains("ccuid"))
|
||||
{
|
||||
<RadzenDataGridColumn Title="@propName">
|
||||
<Template>
|
||||
<RadzenLabel Text=@($"{context.TTbscsr.CCuid}")></RadzenLabel>
|
||||
</Template>
|
||||
</RadzenDataGridColumn>
|
||||
}
|
||||
else if (propName.ToLower().Contains("chascertificate"))
|
||||
{
|
||||
<RadzenDataGridColumn Title="@propName">
|
||||
<Template>
|
||||
<RadzenLabel Text=@($"{context.TTbscsr.CHasCertificate}")></RadzenLabel>
|
||||
</Template>
|
||||
</RadzenDataGridColumn>
|
||||
}
|
||||
//filter 있음
|
||||
else
|
||||
{
|
||||
<RadzenDataGridColumn Title="@propName" Property=@($"TTbscsr.{propName}")>
|
||||
</RadzenDataGridColumn>
|
||||
}
|
||||
}
|
||||
<!--date time-->
|
||||
<RadzenDataGridColumn Width="9rem" Title="CDATETIME">
|
||||
@ -160,6 +173,8 @@
|
||||
}
|
||||
</Template>
|
||||
</RadzenDataGrid>
|
||||
<RadzenPager ShowPagingSummary="true" PagingSummaryFormat="@pagingSummaryFormat" HorizontalAlign="HorizontalAlign.Center" Count="@PageTotalRowCount" PageSize="@PageSizeCount" PageNumbersCount="@PageViewCount" PageChanged="@PageChanged" />
|
||||
|
||||
</Authorized>
|
||||
<NotAuthorized>
|
||||
<RadzenLabel Text="Not Authorized"></RadzenLabel>
|
||||
@ -172,16 +187,17 @@
|
||||
private DateOnly SearchStartDate = DateOnly.FromDateTime(DateTime.Now.AddDays(-7));
|
||||
private DateOnly SearchEndDate = DateOnly.FromDateTime(DateTime.Now);
|
||||
|
||||
private string FilterIft = string.Empty;
|
||||
private string FilterWMI = string.Empty;
|
||||
private string FilterDC = string.Empty;
|
||||
private string FilterCertType = string.Empty;
|
||||
string pagingSummaryFormat = "Page{0}/{1} (Total:{2} Rows)";
|
||||
|
||||
private int ViewCount = 20;
|
||||
private int PageTotalRowCount = 0;
|
||||
private int PageViewCount = 10;
|
||||
private int PageSizeCount = 20;
|
||||
|
||||
List<CertificateHistoryModel> history = new List<CertificateHistoryModel>();
|
||||
RadzenDataGrid<CertificateHistoryModel> grid = new();
|
||||
|
||||
Dictionary<string, string> DicFilter = new Dictionary<string, string>();
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
@ -191,7 +207,7 @@
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private async Task Search(int startCcuid)
|
||||
private async Task Search(int page = 1)
|
||||
{
|
||||
DialogService.OpenIndicator("Search History");
|
||||
|
||||
@ -200,33 +216,23 @@
|
||||
//Default filter
|
||||
requestUrl += $"startDate={SearchStartDate}&";
|
||||
requestUrl += $"endDate={SearchEndDate}&";
|
||||
|
||||
// requestUrl += $"startCcuid={startCcuid}&";
|
||||
|
||||
//optional filter
|
||||
// if (string.IsNullOrEmpty(FilterIft) == false)
|
||||
// {
|
||||
// requestUrl += $"ift={FilterIft}&";
|
||||
// }
|
||||
// if (string.IsNullOrEmpty(FilterWMI) == false)
|
||||
// {
|
||||
// requestUrl += $"wmi={FilterWMI}&";
|
||||
// }
|
||||
// if (string.IsNullOrEmpty(FilterDC) == false)
|
||||
// {
|
||||
// requestUrl += $"dc={FilterDC}&";
|
||||
// }
|
||||
// if (string.IsNullOrEmpty(FilterCertType) == false)
|
||||
// {
|
||||
// requestUrl += $"certType={FilterCertType}&";
|
||||
// }
|
||||
foreach (var filter in grid.Query.Filters)
|
||||
{
|
||||
requestUrl += $"{filter.Property.Split('.').Last()}={filter.FilterValue}&";
|
||||
}
|
||||
requestUrl += $"page={page}";
|
||||
|
||||
history?.Clear();
|
||||
var http = new Http();
|
||||
var result = await http.GetJsonAsync<List<CertificateHistoryModel>>(requestUrl);
|
||||
if (result != null)
|
||||
if (result?.Count > 0)
|
||||
{
|
||||
PageTotalRowCount = result.First().TotalCount;
|
||||
history.AddRange(result);
|
||||
history.Reverse();
|
||||
}
|
||||
grid?.Reload();
|
||||
|
||||
@ -345,26 +351,31 @@
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
async Task OnClickExportCSV(bool isFilter = false)
|
||||
async Task OnClickExportCSV()
|
||||
{
|
||||
DialogService.OpenIndicator("Export to CSV");
|
||||
List<string> exportData = new List<string>();
|
||||
var http = new Http();
|
||||
string requestUrl = $"https://{ServerAddress}/exportCsv?";
|
||||
|
||||
if (isFilter == true)
|
||||
{
|
||||
//필터링된 데이터만
|
||||
exportData.AddRange(grid.View.ToList().ConvertToCsvFile());
|
||||
}
|
||||
else
|
||||
{
|
||||
//전체 데이터
|
||||
exportData.AddRange(history.ConvertToCsvFile());
|
||||
}
|
||||
//Default filter
|
||||
requestUrl += $"startDate={SearchStartDate}&";
|
||||
requestUrl += $"endDate={SearchEndDate}&";
|
||||
|
||||
if (exportData?.Count > 0)
|
||||
// requestUrl += $"startCcuid={startCcuid}&";
|
||||
|
||||
//optional filter
|
||||
foreach (var filter in grid.Query.Filters)
|
||||
{
|
||||
requestUrl += $"{filter.Property.Split('.').Last()}={filter.FilterValue}&";
|
||||
}
|
||||
var csv = await http.GetStreamAsync(requestUrl, timeOutSeconds: 30);
|
||||
|
||||
string fileName = $"VPKI_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.csv";
|
||||
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileCSV", fileName, exportData.ToJson());
|
||||
if(csv != null)
|
||||
{
|
||||
using var streamRef = new DotNetStreamReference(stream: csv);
|
||||
|
||||
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileCSV", fileName, streamRef);
|
||||
if (exportResult == true)
|
||||
{
|
||||
NotiService.Notify(new NotificationMessage
|
||||
@ -388,8 +399,10 @@
|
||||
DialogService.CloseIndicator();
|
||||
}
|
||||
|
||||
void OnChangeFilter()
|
||||
void OnChangeFilter<T>(DataGridColumnFilterEventArgs<T> args)
|
||||
{
|
||||
PageTotalRowCount = 0;
|
||||
history?.Clear();
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
@ -523,4 +536,9 @@
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PageChanged(PagerEventArgs args)
|
||||
{
|
||||
await Search(args.PageIndex + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,16 @@
|
||||
window.openSaveFileCSV = async function (fileName, writeData) {
|
||||
try {
|
||||
const handle = await window.showSaveFilePicker({
|
||||
suggestedName: fileName, // 파일의 기본 이름
|
||||
types: [
|
||||
{
|
||||
description: "csv",
|
||||
accept: { "text/plain": [".csv" ] }
|
||||
}
|
||||
]
|
||||
});
|
||||
const arrayBuffer = await writeData.arrayBuffer();
|
||||
const blob = new Blob([arrayBuffer]);
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
// 파일을 선택한 후 처리 (파일 핸들러)
|
||||
const writableStream = await handle.createWritable();
|
||||
const jsonData = JSON.parse(writeData)
|
||||
const anchorElement = document.createElement("a");
|
||||
anchorElement.href = url;
|
||||
anchorElement.download = fileName ?? "download.csv";
|
||||
anchorElement.click();
|
||||
|
||||
for (var i = 0; i < jsonData.length; i++) {
|
||||
await writableStream.write(jsonData[i] + "\r\n");
|
||||
}
|
||||
await writableStream.close();
|
||||
anchorElement.remove();
|
||||
URL.revokeObjectURL(url);
|
||||
|
||||
return true; // 선택된 파일 이름을 반환
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user