using Furion.DatabaseAccessor;
using Furion.DatabaseAccessor.Extensions;
using Furion.DependencyInjection;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Furion.TaskScheduler;
using iWare.Wms.Core;
using iWare.Wms.Core.Util;
using Mapster;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Diagnostics;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using static OfficeOpenXml.FormulaParsing.EpplusExcelDataProvider;
namespace iWare.Wms.Application
{
///
/// 工件加工追溯服务
///
[ApiDescriptionSettings("数据查询服务", Name = "WorkPieceProcess", Order = 100)]
[Route("api/[Controller]")]
[DisableOpLog]
public class WorkPieceProcessService : IWorkPieceProcessService, IDynamicApiController, ITransient
{
private readonly IRepository _workPieceProcessRep;
private readonly IRepository _workPieceInfoRep;
private readonly IRepository _equipmentBaseInfoRep;
private readonly IRepository _sysDictTypeRep;
private readonly IRepository _sysDictDataRep;
private readonly IRepository _workPieceLogRep;
///
/// 工件加工追溯构造
///
///
///
///
///
///
public WorkPieceProcessService(
IRepository workPieceLogRep,
IRepository workPieceProcessRep,
IRepository workPieceInfoRep,
IRepository equipmentBaseInfoRep,
IRepository sysDictTypeRep,
IRepository sysDictDataRep
)
{
_workPieceLogRep = workPieceLogRep;
_workPieceInfoRep = workPieceInfoRep;
_workPieceProcessRep = workPieceProcessRep;
_equipmentBaseInfoRep = equipmentBaseInfoRep;
_sysDictTypeRep = sysDictTypeRep;
_sysDictDataRep = sysDictDataRep;
}
///
/// 分页查询工件加工追溯(工件加工履历表)
///
///
///
[HttpGet("workPieceProcessMachiningPage")]
public async Task> WorkPieceProcessMachiningPage([FromQuery] WorkPieceProcessSearch input)
{
var workPieceProcesss = await (from process in _workPieceProcessRep.DetachedEntities
join baseinfo in _equipmentBaseInfoRep.DetachedEntities on process.EquipmentID equals baseinfo.EquipmentId into joinedEmpty
from baseinfo2 in joinedEmpty.DefaultIfEmpty()
join workPiece in _workPieceInfoRep.DetachedEntities on process.WorkPieceID equals workPiece.WorkPieceID into joined2Empty
from workPiece2 in joined2Empty.DefaultIfEmpty()
where process.IsDeleted == false && process.WorkPieceID.Contains(string.IsNullOrEmpty(input.WorkPieceID) ? "" : input.WorkPieceID)
&& process.QualityState == (input.QualityState.HasValue ? input.QualityState.Value : process.QualityState)
&& process.EquipmentID == (string.IsNullOrEmpty(input.EquipmentID) ? process.EquipmentID : input.EquipmentID)
&& process.WorkingProcedureCurrent == (string.IsNullOrEmpty(input.WorkingProcedureCurrent) ? process.WorkingProcedureCurrent : input.WorkingProcedureCurrent)
&& workPiece2.OP80NewCode == (string.IsNullOrEmpty(input.OP80NewCode) ? workPiece2.OP80NewCode : input.OP80NewCode)
&& process.CreatedUserName.Contains(string.IsNullOrEmpty(input.createUserName) ? "" : input.createUserName)
&& process.UpdatedUserName.Contains(string.IsNullOrEmpty(input.updatedUserName) ? "" : input.updatedUserName)
&& (
(input.IsHaveOP80Code == "N" && string.IsNullOrEmpty(workPiece2.OP80NewCode))
|| (input.IsHaveOP80Code == "Y" && !string.IsNullOrEmpty(workPiece2.OP80NewCode))
|| (string.IsNullOrEmpty(input.IsHaveOP80Code) && 1 == 1)
)
&& process.EquipmentID == (string.IsNullOrEmpty(input.EquipmentID) ? process.EquipmentID : input.EquipmentID)
&& process.OperationType == (string.IsNullOrEmpty(input.OperationType) ? process.OperationType : input.OperationType)
&& !string.IsNullOrEmpty(process.WorkPieceID)
&& process.StartTime >= (input.StartTimeBeginTime.HasValue ? input.StartTimeBeginTime : DateTime.MinValue)
&& process.StartTime <= (input.StartTimeEndTime.HasValue ? input.StartTimeEndTime : DateTime.MaxValue)
select new WorkPieceProcessOutput
{
UpdatedUserName = process.UpdatedUserName,
DataCapturePointCname = process.DataCapturePointCname,
UpdateDataCapturePointCname = process.UpdateDataCapturePointCname,
QualityNoOk = process.QualityNoOk,
QualityNoOkReason = process.QualityNoOkReason,
Id = process.Id,
WorkPieceID = process.WorkPieceID,
EquipmentID = process.EquipmentID,
EquipmentName = (baseinfo2 == null ? "" : baseinfo2.EquipmentName),
OP80NewCode = workPiece2.OP80NewCode,
WorkingProcedureCurrent = process.WorkingProcedureCurrent,
StartTime = process.StartTime,
EndTime = process.EndTime,
QualityState = process.QualityState,
QualityDataInfoID = process.QualityDataInfoID,
OperationType = process.OperationType,
CreateUserName = process.CreatedUserName
}).OrderByDescending(o => o.StartTime)
.ProjectToType()
.ToADPagedListAsync(input.PageNo, input.PageSize);
return workPieceProcesss;
}
///
/// 工件加工信息导出Excel(工件加工履历表)
///
///
/// 导出的Excel文件
[HttpGet("workPieceProcessMachiningPageToExcel")]
public async Task WorkPieceProcessMachiningPageToExcelAsync([FromQuery] WorkPieceProcessSearch input)
{
var workPieceMachiningInfos = await (from process in _workPieceProcessRep.DetachedEntities
join baseinfo in _equipmentBaseInfoRep.DetachedEntities
on process.EquipmentID equals baseinfo.EquipmentId into joinedEmpty
from baseinfo2 in joinedEmpty.DefaultIfEmpty()
join workPiece in _workPieceInfoRep.DetachedEntities on process.WorkPieceID equals workPiece.WorkPieceID into joined2Empty
from workPiece2 in joined2Empty.DefaultIfEmpty()
where process.IsDeleted == false && process.WorkPieceID.Contains(string.IsNullOrEmpty(input.WorkPieceID) ? "" : input.WorkPieceID)
&& process.QualityState == (input.QualityState.HasValue ? input.QualityState.Value : process.QualityState)
&& process.EquipmentID == (string.IsNullOrEmpty(input.EquipmentID) ? process.EquipmentID : input.EquipmentID)
&& process.WorkingProcedureCurrent == (string.IsNullOrEmpty(input.WorkingProcedureCurrent) ? process.WorkingProcedureCurrent : input.WorkingProcedureCurrent)
&& process.EquipmentID == (string.IsNullOrEmpty(input.EquipmentID) ? process.EquipmentID : input.EquipmentID)
&& workPiece2.OP80NewCode == (string.IsNullOrEmpty(input.OP80NewCode) ? workPiece2.OP80NewCode : input.OP80NewCode)
&& process.CreatedUserName.Contains(string.IsNullOrEmpty(input.createUserName) ? "" : input.createUserName)
&& process.UpdatedUserName.Contains(string.IsNullOrEmpty(input.updatedUserName) ? "" : input.updatedUserName)
&& (
(input.IsHaveOP80Code == "N" && string.IsNullOrEmpty(workPiece2.OP80NewCode))
|| (input.IsHaveOP80Code == "Y" && !string.IsNullOrEmpty(workPiece2.OP80NewCode))
|| (string.IsNullOrEmpty(input.IsHaveOP80Code) && 1 == 1)
)
&& process.OperationType == (string.IsNullOrEmpty(input.OperationType) ? process.OperationType : input.OperationType)
&& !string.IsNullOrEmpty(process.WorkPieceID)
&& process.StartTime >= (input.StartTimeBeginTime.HasValue ? input.StartTimeBeginTime : DateTime.MinValue)
&& process.StartTime <= (input.StartTimeEndTime.HasValue ? input.StartTimeEndTime : DateTime.MaxValue)
select new WorkPieceProcessExcelOutput
{
OP80NewCode = workPiece2.OP80NewCode,
Id = process.Id,
WorkPieceID = process.WorkPieceID,
//EquipmentID = process.EquipmentID,
EquipmentName = (baseinfo2 == null ? "" : baseinfo2.EquipmentName),
WorkingProcedureCurrent = process.WorkingProcedureCurrent,
StartTime = process.StartTime.ToString(),
EndTime = process.EndTime.ToString(),
//QualityState = process.QualityState,
CreateUserName = process.CreatedUserName
}).OrderByDescending(o => o.StartTime).Distinct()
.ProjectToType()
.ToListAsync();
foreach (WorkPieceProcessExcelOutput item in workPieceMachiningInfos)
{
item.StartTime = string.IsNullOrEmpty(item.StartTime) ? "" : Convert.ToDateTime(item.StartTime).ToString("yyyy-MM-dd hh:mm:ss");
item.EndTime = string.IsNullOrEmpty(item.EndTime) ? "" : Convert.ToDateTime(item.EndTime).ToString("yyyy-MM-dd hh:mm:ss");
}
MemoryStream ms = new();
DataConvertUtil.ToExcelData(workPieceMachiningInfos, _sysDictTypeRep, _sysDictDataRep, out List headers,
out List> data, out string sheetName);
ExcelUtil.ToExcel(headers, data, sheetName, ms);
ms.Position = 0;
var fileName = HttpUtility.UrlEncode($"{sheetName}[{DateTimeOffset.Now:yyyy-MM-dd}].xlsx", Encoding.GetEncoding("UTF-8"));
return new FileStreamResult(ms, "application/octet-stream") { FileDownloadName = fileName };
}
#region 产量查询 [Editby shaocx,2024-06-08]
///
/// 产量查询
///
///
///
[HttpGet("queryYield")]
public async Task> QueryYield([FromQuery] WorkPieceProcessSearch input)
{
var workPieceProcesss2 = await (from process in _workPieceProcessRep.DetachedEntities
//join baseinfo in _equipmentBaseInfoRep.DetachedEntities on process.EquipmentID equals baseinfo.EquipmentId into joinedEmpty
//from baseinfo2 in joinedEmpty.DefaultIfEmpty()
//join workPiece in _workPieceInfoRep.DetachedEntities on process.WorkPieceID equals workPiece.WorkPieceID into joined2Empty
//from workPiece2 in joined2Empty.DefaultIfEmpty()
where process.IsDeleted == false && process.WorkPieceID.Contains(string.IsNullOrEmpty(input.WorkPieceID) ? "" : input.WorkPieceID)
&& process.QualityState == (input.QualityState.HasValue ? input.QualityState.Value : process.QualityState)
&& process.EquipmentID == (string.IsNullOrEmpty(input.EquipmentID) ? process.EquipmentID : input.EquipmentID)
&& process.WorkingProcedureCurrent == (string.IsNullOrEmpty(input.WorkingProcedureCurrent) ? process.WorkingProcedureCurrent : input.WorkingProcedureCurrent)
//&& workPiece2.OP80NewCode == (string.IsNullOrEmpty(input.OP80NewCode) ? workPiece2.OP80NewCode : input.OP80NewCode)
&& process.EquipmentID == (string.IsNullOrEmpty(input.EquipmentID) ? process.EquipmentID : input.EquipmentID)
&& process.OperationType == (string.IsNullOrEmpty(input.OperationType) ? process.OperationType : input.OperationType)
&& !string.IsNullOrEmpty(process.WorkPieceID)
&& process.StartTime >= (input.StartTimeBeginTime.HasValue ? input.StartTimeBeginTime : DateTime.MinValue)
&& process.StartTime <= (input.StartTimeEndTime.HasValue ? input.StartTimeEndTime : DateTime.MaxValue)
select new QueryYieldOutput
{
//EquipmentID = process.EquipmentID,
//EquipmentName = baseinfo2.EquipmentName,
WorkingProcedureCurrent = process.WorkingProcedureCurrent,
WorkPieceID = process.WorkPieceID,
//StartTime = grouped.Key.StartTime,
YieldCount = 0
}).Distinct().ToListAsync();
var workPieceProcesss = workPieceProcesss2.GroupBy(x => new { x.WorkingProcedureCurrent }).Select(y => new QueryYieldOutput
{
//EquipmentID = y.Key.EquipmentID,
//EquipmentName = y.Key.EquipmentName,
WorkingProcedureCurrent = y.Key.WorkingProcedureCurrent,
//StartTime = grouped.Key.StartTime,
YieldCount = y.ToList().Count
})
.OrderBy(x => x.WorkingProcedureCurrent)
.ToADPagedList(input.PageNo, input.PageSize);
return workPieceProcesss;
}
///
/// 导出产量查询
///
///
/// 导出的Excel文件
[HttpGet("exportYield")]
public async Task ExportYield([FromQuery] WorkPieceProcessSearch input)
{
input.PageNo = 1;
input.PageSize = 1000000;
var workPieceMachiningInfos2 = QueryYield(input);
var workPieceMachiningInfos = workPieceMachiningInfos2.Result.Rows.ToList();
var daList = workPieceMachiningInfos.Adapt>();
MemoryStream ms = new();
DataConvertUtil.ToExcelData(daList, _sysDictTypeRep, _sysDictDataRep, out List headers,
out List> data, out string sheetName);
ExcelUtil.ToExcel(headers, data, sheetName, ms);
ms.Position = 0;
var fileName = HttpUtility.UrlEncode($"{sheetName}[{DateTimeOffset.Now:yyyy-MM-dd}].xlsx", Encoding.GetEncoding("UTF-8"));
return new FileStreamResult(ms, "application/octet-stream") { FileDownloadName = fileName };
}
#endregion
#region 采集日志查询 [Editby shaocx,2024-06-08]
///
/// 采集日志查询
///
///
///
[HttpGet("queryWorkPieceLogYield")]
public async Task> QueryWorkPieceLogYield([FromQuery] WorkPieceLogYieldInput input)
{
var resutlt = await _workPieceLogRep.DetachedEntities
.Where(!string.IsNullOrEmpty(input.WorkPieceID), u => u.WorkPieceID.Contains(input.WorkPieceID))
.Where(!string.IsNullOrEmpty(input.workingProcedure), u => u.WorkingProcedure.Contains(input.workingProcedure))
.Where(!string.IsNullOrEmpty(input.createdUserName), u => u.CreatedUserName.Contains(input.createdUserName))
.Where(!string.IsNullOrEmpty(input.DataCapturePointCname), u => u.DataCapturePointCname.Contains(input.DataCapturePointCname))
.Where(!string.IsNullOrEmpty(input.PieceLogTypeName), u => u.PieceLogTypeName.Contains(input.PieceLogTypeName))
.Where(input.PieceLogType != null, u => u.PieceLogType == input.PieceLogType)
.Where(!string.IsNullOrEmpty(input.remarks), u => u.Remarks.Contains(input.remarks))
.Where(!string.IsNullOrEmpty(input.StartTimeBeginTime.ToString()), u => u.CreatedTime >= input.StartTimeBeginTime)
.Where(!string.IsNullOrEmpty(input.StartTimeEndTime.ToString()), u => u.CreatedTime <= input.StartTimeEndTime)
.OrderBy(PageInputOrder.OrderBuilder(input))
.ProjectToType()
.ToADPagedListAsync(input.PageNo, input.PageSize);
return resutlt;
}
///
/// 导出采集日志查询
///
///
/// 导出的Excel文件
[HttpGet("exportWorkPieceLogYield")]
public async Task ExportWorkPieceLogYield([FromQuery] WorkPieceLogYieldInput input)
{
input.PageNo = 1;
input.PageSize = 1000000;
var workPieceMachiningInfos2 = QueryWorkPieceLogYield(input);
var workPieceMachiningInfos = workPieceMachiningInfos2.Result.Rows.ToList();
var daList = workPieceMachiningInfos.Adapt>();
MemoryStream ms = new();
DataConvertUtil.ToExcelData(daList, _sysDictTypeRep, _sysDictDataRep, out List headers,
out List> data, out string sheetName);
ExcelUtil.ToExcel(headers, data, sheetName, ms);
ms.Position = 0;
var fileName = HttpUtility.UrlEncode($"{sheetName}[{DateTimeOffset.Now:yyyy-MM-dd}].xlsx", Encoding.GetEncoding("UTF-8"));
return new FileStreamResult(ms, "application/octet-stream") { FileDownloadName = fileName };
}
#endregion
///
/// 分页查询工件加工(工件信息表)
///
///
///
[HttpGet("workPieceInfoMachiningPage")]
public async Task> WorkPieceInfoMachiningPage([FromQuery] WorkPieceProcessSearch input)
{
var workPieceInfos = await _workPieceInfoRep.DetachedEntities
.Join(_equipmentBaseInfoRep.DetachedEntities, a => a.EquipmentID, b => b.EquipmentId, (a, b) => new { a, b })
.Join(_sysDictDataRep.DetachedEntities, e => e.a.WorkPieceState.ToString(), f => f.Code, (e, f) => new { e, f })
.Join(_sysDictTypeRep.DetachedEntities, g => g.f.TypeId, h => h.Id, (f, g) => new { f, g })
.Where(x => (x.g.Code.Equals("workpiece_state") && (string.IsNullOrEmpty(input.WorkPieceState.ToString()) ? true : x.f.f.Code.Equals(input.WorkPieceState.ToString()))))
.Where(!string.IsNullOrEmpty(input.WorkPieceID), u => u.f.e.a.WorkPieceID.Contains(input.WorkPieceID))
.Where(!string.IsNullOrEmpty(input.OP80NewCode), u => u.f.e.a.OP80NewCode.Contains(input.OP80NewCode))
.Where(input.IsHaveOP80Code == "Y", u => !string.IsNullOrEmpty(u.f.e.a.OP80NewCode))
.Where(input.IsHaveOP80Code == "N", u => string.IsNullOrEmpty(u.f.e.a.OP80NewCode))
.Where(!string.IsNullOrEmpty(input.WorkPieceState.ToString()), u => u.f.e.a.WorkPieceState == input.WorkPieceState)
.Where(!string.IsNullOrEmpty(input.EquipmentID), u => u.f.e.a.EquipmentID.Equals(input.EquipmentID))
.Where(!string.IsNullOrEmpty(input.WorkingProcedureCurrent), u => u.f.e.a.WorkingProcedureCurrent.Equals(input.WorkingProcedureCurrent))
.Where(!string.IsNullOrEmpty(input.StartTimeBeginTime.ToString()), u => u.f.e.a.WorkPieceinitOnlineTime >= input.StartTimeBeginTime)
.Where(!string.IsNullOrEmpty(input.StartTimeEndTime.ToString()), u => u.f.e.a.WorkPieceinitOnlineTime <= input.StartTimeEndTime)
.Where(o => !string.IsNullOrEmpty(o.f.e.a.WorkPieceID))
.Where(o => o.f.e.a.QualityState == (input.QualityState.HasValue ? input.QualityState.Value : o.f.e.a.QualityState))
.Select(s => new WorkPieceInfoMachiningPageOutput
{
QualityNoOk = s.f.e.a.QualityNoOk,
QualityNoOkReason = s.f.e.a.QualityNoOkReason,
Id = s.f.e.a.Id,
WorkPieceID = s.f.e.a.WorkPieceID,
WorkPieceState = s.f.e.a.WorkPieceState,
WorkPieceStateName = s.f.f.Value,
WorkingProcedureCurrent = s.f.e.a.WorkingProcedureCurrent,
WorkPieceCurrentPosition = s.f.e.a.WorkPieceCurrentPosition,
WorkPieceinitOnlineTime = s.f.e.a.WorkPieceinitOnlineTime.ToString(),
WorkPieceLastOfflineTime = s.f.e.a.WorkPieceLastOfflineTime.ToString(),
ProcessingDurationForCurrent = s.f.e.a.ProcessingDurationForCurrent,
QualityState = s.f.e.a.QualityState,
EquipmentID = s.f.e.a.EquipmentID,
EquipmentName = s.f.e.b.EquipmentName,
OperationType = "正常",
OP80NewCode = s.f.e.a.OP80NewCode,
})
.OrderBy(PageInputOrder.OrderBuilder(input))
.ProjectToType()
.ToADPagedListAsync(input.PageNo, input.PageSize);
return workPieceInfos;
}
///
/// 工件加工信息导出Excel(工件信息表)
///
///
/// 导出的Excel文件
[HttpGet("workPieceInfoMachiningToExcel")]
public async Task WorkPieceInfoMachiningToExcelAsync([FromQuery] WorkPieceProcessSearch input)
{
var workPieceMachiningInfos = await _workPieceInfoRep.DetachedEntities
.Join(_equipmentBaseInfoRep.DetachedEntities, a => a.EquipmentID, b => b.EquipmentId, (a, b) => new { a, b })
.Join(_sysDictDataRep.DetachedEntities, e => e.a.WorkPieceState.ToString(), f => f.Code, (e, f) => new { e, f })
.Join(_sysDictTypeRep.DetachedEntities, g => g.f.TypeId, h => h.Id, (f, g) => new { f, g })
.Where(x => (x.g.Code.Equals("workpiece_state") && (string.IsNullOrEmpty(input.WorkPieceState.ToString()) ? true : x.f.f.Code.Equals(input.WorkPieceState.ToString()))))
.Where(!string.IsNullOrEmpty(input.WorkPieceID), u => u.f.e.a.WorkPieceID.Contains(input.WorkPieceID))
.Where(!string.IsNullOrEmpty(input.OP80NewCode), u => u.f.e.a.OP80NewCode.Contains(input.OP80NewCode))
.Where(input.IsHaveOP80Code == "Y", u => !string.IsNullOrEmpty(u.f.e.a.OP80NewCode))
.Where(input.IsHaveOP80Code == "N", u => string.IsNullOrEmpty(u.f.e.a.OP80NewCode))
.Where(!string.IsNullOrEmpty(input.WorkPieceState.ToString()), u => u.f.e.a.WorkPieceState == input.WorkPieceState)
.Where(!string.IsNullOrEmpty(input.EquipmentID), u => u.f.e.a.EquipmentID.Equals(input.EquipmentID))
.Where(!string.IsNullOrEmpty(input.WorkingProcedureCurrent), u => u.f.e.a.WorkingProcedureCurrent.Equals(input.WorkingProcedureCurrent))
.Where(!string.IsNullOrEmpty(input.StartTimeBeginTime.ToString()), u => u.f.e.a.WorkPieceinitOnlineTime >= input.StartTimeBeginTime)
.Where(!string.IsNullOrEmpty(input.StartTimeEndTime.ToString()), u => u.f.e.a.WorkPieceinitOnlineTime <= input.StartTimeEndTime)
.Where(o => !string.IsNullOrEmpty(o.f.e.a.WorkPieceID))
.Where(o => o.f.e.a.QualityState == (input.QualityState.HasValue ? input.QualityState.Value : o.f.e.a.QualityState))
.Select(s => new WorkPieceInfoMachiningExcelPageOutput
{
Id = s.f.e.a.Id,
WorkPieceID = s.f.e.a.WorkPieceID,
WorkingProcedureCurrent = s.f.e.a.WorkingProcedureCurrent,
WorkPieceinitOnlineTime = s.f.e.a.WorkPieceinitOnlineTime.ToString(),
WorkPieceLastOfflineTime = s.f.e.a.WorkPieceLastOfflineTime.ToString(),
WorkPieceStateName = s.f.f.Value,
EquipmentName = s.f.e.b.EquipmentName,
//QualityState = s.f.e.a.QualityState,
OP80NewCode = s.f.e.a.OP80NewCode,
})
.Distinct()
.OrderBy(PageInputOrder.OrderBuilder(input))
.ProjectToType()
.ToListAsync();
foreach (WorkPieceInfoMachiningExcelPageOutput item in workPieceMachiningInfos)
{
item.WorkPieceinitOnlineTime = string.IsNullOrEmpty(item.WorkPieceinitOnlineTime) ? "" : Convert.ToDateTime(item.WorkPieceinitOnlineTime).ToString("yyyy-MM-dd hh:mm:ss");
item.WorkPieceLastOfflineTime = string.IsNullOrEmpty(item.WorkPieceLastOfflineTime) ? "" : Convert.ToDateTime(item.WorkPieceLastOfflineTime).ToString("yyyy-MM-dd hh:mm:ss");
}
MemoryStream ms = new();
DataConvertUtil.ToExcelData(workPieceMachiningInfos, _sysDictTypeRep, _sysDictDataRep, out List headers,
out List> data, out string sheetName);
ExcelUtil.ToExcel(headers, data, sheetName, ms);
ms.Position = 0;
var fileName = HttpUtility.UrlEncode($"{sheetName}[{DateTimeOffset.Now:yyyy-MM-dd}].xlsx", Encoding.GetEncoding("UTF-8"));
return new FileStreamResult(ms, "application/octet-stream") { FileDownloadName = fileName };
}
}
}