Files
YunTongJackYunTask/Reportapi/MyCode.Project.Services/BLL/ReportExport/BaseExport.cs

490 lines
18 KiB
C#
Raw Normal View History

2025-07-04 09:50:02 +08:00
using MiniExcelLibs;
using MiniExcelLibs.Attributes;
using MiniExcelLibs.OpenXml;
using MyCode.Project.Domain.Config;
using MyCode.Project.Domain.Message.Act.Common;
using MyCode.Project.Domain.Message.Response.LxmZHMDReport;
using MyCode.Project.Domain.Message.Response.User;
using MyCode.Project.Infrastructure;
using MyCode.Project.Infrastructure.Cache;
using MyCode.Project.Infrastructure.Common;
using MyCode.Project.Infrastructure.Constant;
using MyCode.Project.Infrastructure.Enumeration;
using MyCode.Project.Infrastructure.Exceptions;
using MyCode.Project.Infrastructure.UnityExtensions;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace MyCode.Project.Services.BLL.ReportExport
{
public abstract class BaseExport : MarshalByRefObject
{
private IMyCodeCacheService _myCodeCacheService
{
get {
return UnityHelper.GetService<IMyCodeCacheService>();
}
}
/// <summary>
/// 查询条件
/// </summary>
public object Condition { get; set; }
/// <summary>
/// 当前操作用户
/// </summary>
public LoginInfo CurrentUser { get; set; }
/// <summary>
/// 计算的id
/// </summary>
public long CalId { get; set; }
//DotNetLib压缩
List<string> PageZipFilePaths = new List<string>();
public BaseExport()
{
}
/// <summary>
/// 报表id
/// </summary>
public long ReportId
{
get;
set;
}
/// <summary>
/// 多个的数据
/// </summary>
private List<ExcelData> ListData = new List<ExcelData>();
/// <summary>
/// 确定导出类型,根据导出类型,来决定导出模板
/// </summary>
public int ReportType
{
get;
set;
}
/// <summary>
/// Excel文件类型 0:zip 1:xls
/// </summary>
public int ExcelFileType { get; set; }
#region AddExcelProcess(EXCEL处理)
/// <summary>
/// 增加EXCEL处理可能有多个需要处理
/// </summary>
/// <param name="fileName"></param>
/// <param name="data"></param>
public void AddExcelProcess(string fileName, dynamic data)
{
ListData.Add(new ExcelData() { FileName = fileName, DyData = data });
}
#endregion
#region GetPageSearch()
/// <summary>
/// 获取分页查询条件
/// </summary>
/// <typeparam name="T">条件类型</typeparam>
/// <param name="condition">查询条件</param>
/// <param name="queryCount">查询数量</param>
/// <returns></returns>
public PagedSearch<TEntity> GetPageSearch<TEntity>(object condition, int pagesize = 100000, int pageIndex = 1) where TEntity : class, new()
{
var tCondition = ((JObject)condition).ToObject<TEntity>();
return new PagedSearch<TEntity>(pagesize, pageIndex, tCondition);
}
#endregion
#region Execute()
/// <summary>
/// 多个保存的实体,最后保存为一个压缩文件,返回压缩文件路径
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public virtual string Execute()
{
if (ListData == null || ListData.Count == 0) { throw new BaseException("没有需要导出的数据"); }
//DotNetLib压缩
var zipFilePaths = new List<string>();
var zipFile = "";
//模板的路径
var filePath = SystemConfig.AppFilePath;
//模板路径
var templatePath = Path.Combine(filePath, $"ExportTemplate/{ReportType}.xlsx");
//保存的excel目录
var savePathFolder = Path.Combine(filePath, $"download/exceltemp/{DateTime.Now.ToString("yyyyMM")}/");
//数据量
var listCount = ListData.Count;
var resultData = new ReportCalRateResp()
{
Total = listCount
};
var result = new Result()
{
Data = resultData,
Code = ResultCode.Success
};
int i = 1;
//当前秒
int second = DateTime.Now.Second;
//是否是导出excel格式
foreach (var item in ListData)
{
var saveFileName = $"{item.FileName }_{DateTime.Now.ToString("HHmmssfff")}.xlsx";
var savePath = Path.Combine(savePathFolder, saveFileName);
if (!FileUtils.IsDirectoryExists(savePathFolder)) { Directory.CreateDirectory(savePathFolder); }
//加入进度发送websocket
MiniExcel.SaveAsByTemplate(savePath, templatePath, item.DyData);
if (ExcelFileType == (int)ExportFileType.Xls) { return savePath; }
zipFilePaths.Add(savePath);
resultData.CurQty = i;
var rate = Math.Round(resultData.CurQty * 1m / resultData.Total, 4);
//这里因为前面已经用了2%了比如获取数据什么的所以这里不能低于2%;并且压缩也是需要时间的所以最多就是99%
if (rate < 0.02m) { rate = 0.02m; }
else if (rate >= 1) { rate = 0.99m; }
resultData.Rate = rate;
//发送结果
var sendResult = WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true));
//发送失败了
if (!sendResult) { throw new BaseException($"当前id={ReportId}不在线"); }
//这里这么循环的话当导出1000个的时候会有点问题调用redis太频繁了;不同秒才需要
if (DateTime.Now.Second != second)
{
var existZipCacheFile = _myCodeCacheService.Exists($"{CacheKey.ReportZipFileCacheKey}{ReportId}");
if (!existZipCacheFile)
{
//移除正在下载
_myCodeCacheService.Delete($"{CacheKey.HasDownloadZipCacheKey}");
throw new BaseException($"用户已经取消id={ReportId}的导出");
}
second = DateTime.Now.Second;
}
i++;
}
//这里判断如果只有一个文件则直接导出为excel,不用压缩了
if (ExcelFileType == (int)ExportFileType.Zip)
{
//保存并压缩
zipFile = Path.Combine(savePathFolder, $"{EnumHelper.GetDescription<ReportType>(ReportType)}_{ReportId}.zip");
ZipHelper.Zip(zipFilePaths, zipFile);
//将zip路径放到RedisCache中
_myCodeCacheService.Set($"{CacheKey.ReportZipFileCacheKey}{ReportId}", zipFile, new TimeSpan(7, 1, 0, 0));
resultData.CurQty = listCount;
resultData.Rate = 1;
WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true));
//移除正在下载
_myCodeCacheService.Delete($"{CacheKey.HasDownloadZipCacheKey}");
}
return zipFile;
}
#endregion
#region PageListExecute()
/// <summary>
/// 多个保存的实体,最后保存为一个压缩文件,返回压缩文件路径
/// </summary>
/// <param name="totalCount"></param>
/// <returns></returns>
public string PageListExecute<T>(PageResult<T> pageResult,int pageIndex,int pageSize,int totalCount,string fileName,string hasDownloadZipCacheKey)
{
var dataList = pageResult.DataList;
if (dataList == null || dataList.Count == 0) { throw new BaseException("没有需要导出的数据"); }
var zipFile = "";
//模板的路径
var filePath = SystemConfig.AppFilePath;
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
//模板路径
var templatePath = Path.Combine(filePath, $"ExportTemplate/{ReportType}.xlsx");
//保存的excel目录
//string ServerMapPath = Environment.CurrentDirectory + @"/App_File/";
//string templatePath = Path.Combine(ServerMapPath, $"ExportTemplate/{ReportType}.xlsx");
var savePathFolder = Path.Combine(filePath, $"download/exceltemp/{DateTime.Now.ToString("yyyyMM")}/");
if (!FileUtils.IsDirectoryExists(savePathFolder)) { Directory.CreateDirectory(savePathFolder); }
var resultData = new ReportCalRateResp()
{
Total = totalCount
};
var result = new Result()
{
Data = resultData,
Code = ResultCode.Success
};
//当前秒
int second = DateTime.Now.Second;
ListData = new List<ExcelData>();
var dataResult = new
{
pro = dataList
};
AddExcelProcess(fileName, dataResult);
var saveFileName = $"{fileName }_{(pageIndex - 1) * pageSize+1}-{(pageIndex - 1) * pageSize + dataList.Count}_{DateTime.Now.ToString("HHmmssfff")}.xlsx";
var savePath = Path.Combine(savePathFolder, saveFileName);
//是否是导出excel格式
//加入进度发送websocket
MiniExcel.SaveAsByTemplate(savePath, templatePath, ListData.Select(t=>t.DyData).FirstOrDefault());
//这里判断如果只有一个文件则直接导出为excel,不用压缩了
if (ExcelFileType == (int)ExportFileType.Xls) { return savePath; }
PageZipFilePaths.Add(savePath);
resultData.CurQty =(pageIndex-1)* pageSize+ dataList.Count;
var rate = Math.Round(resultData.CurQty * 1m / resultData.Total, 4);
//这里因为前面已经用了2%了比如获取数据什么的所以这里不能低于2%;并且压缩也是需要时间的所以最多就是99%
if (rate < 0.02m) { rate = 0.02m; }
else if (rate >= 1) { rate = 0.99m; }
resultData.Rate = rate;
//发送结果
var sendResult = WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true));
//发送失败了
if (!sendResult) { throw new BaseException($"当前id={ReportId}不在线"); }
////这里这么循环的话当导出1000个的时候会有点问题调用redis太频繁了;不同秒才需要
if (DateTime.Now.Second != second)
{
var existZipCacheFile = _myCodeCacheService.Exists($"{CacheKey.ReportZipFileCacheKey}{ReportId}");
if (!existZipCacheFile)
{
//移除正在下载
_myCodeCacheService.Delete($"{hasDownloadZipCacheKey}");
throw new BaseException($"用户已经取消id={ReportId}的导出");
}
second = DateTime.Now.Second;
}
if (ExcelFileType == (int)ExportFileType.Zip && resultData.CurQty == totalCount)
{
//保存并压缩
zipFile = Path.Combine(savePathFolder, $"{fileName}_{ReportId}.zip");
ZipHelper.Zip(PageZipFilePaths, zipFile);
PageZipFilePaths = new List<string>();
//将zip路径放到RedisCache中
_myCodeCacheService.Set($"{CacheKey.ReportZipFileCacheKey}{ReportId}", zipFile, new TimeSpan(7, 1, 0, 0));
//resultData.CurQty = totalCount;
resultData.Rate = 1;
WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true));
//移除正在下载
_myCodeCacheService.Delete($"{hasDownloadZipCacheKey}");
}
return zipFile;
}
#endregion
#region Execute()
/// <summary>
/// 多个保存的实体,最后保存为一个压缩文件,返回压缩文件路径
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public virtual string Execute(List<string> columnNames)
{
if (ListData == null || ListData.Count == 0) { throw new BaseException("没有需要导出的数据"); }
//DotNetLib压缩
var zipFilePaths = new List<string>();
var zipFile = "";
//模板的路径
var filePath = SystemConfig.AppFilePath;
//模板路径
var templatePath = Path.Combine(filePath, $"ExportTemplate/{ReportType}.xlsx");
//保存的excel目录
var savePathFolder = Path.Combine(filePath, $"download/exceltemp/{DateTime.Now.ToString("yyyyMM")}/");
//数据量
var listCount = ListData.Count;
var resultData = new ReportCalRateResp()
{
Total = listCount
};
var result = new Result()
{
Data = resultData,
Code = ResultCode.Success
};
int i = 1;
//当前秒
int second = DateTime.Now.Second;
List<DynamicExcelColumn> dynamicExcelColumns=new List<DynamicExcelColumn>();
int index = 0;
columnNames.ForEach(name =>
{
DynamicExcelColumn column=new DynamicExcelColumn(name) { Index=index, Name = name };
dynamicExcelColumns.Add(column);
index++;
});
var config = new OpenXmlConfiguration
{
DynamicColumns = dynamicExcelColumns.ToArray()
//DynamicColumns = new DynamicExcelColumn[] {
// new DynamicExcelColumn("id") { Ignore = true },
// new DynamicExcelColumn("name") { Index = 1, Width = 10 },
// new DynamicExcelColumn("createdate") { Index = 0, Format = "yyyy-MM-dd", Width = 15 },
// new DynamicExcelColumn("point") { Index = 2, Name = "Account Point" },
//}
};
//config.FillMergedCells = true;
//是否是导出excel格式
foreach (var item in ListData)
{
var saveFileName = $"{item.FileName}_{DateTime.Now.ToString("HHmmssfff")}.xlsx";
var savePath = Path.Combine(savePathFolder, saveFileName);
if (!FileUtils.IsDirectoryExists(savePathFolder)) { Directory.CreateDirectory(savePathFolder); }
////加入进度发送websocket
//MiniExcel.SaveAsByTemplate(savePath, templatePath, item.DyData);
MiniExcel.SaveAs(savePath, item.DyData, configuration: config);
if (ExcelFileType == (int)ExportFileType.Xls) { return savePath; }
zipFilePaths.Add(savePath);
resultData.CurQty = i;
var rate = Math.Round(resultData.CurQty * 1m / resultData.Total, 4);
//这里因为前面已经用了2%了比如获取数据什么的所以这里不能低于2%;并且压缩也是需要时间的所以最多就是99%
if (rate < 0.02m) { rate = 0.02m; }
else if (rate >= 1) { rate = 0.99m; }
resultData.Rate = rate;
//发送结果
var sendResult = WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true));
//发送失败了
if (!sendResult) { throw new BaseException($"当前id={ReportId}不在线"); }
//这里这么循环的话当导出1000个的时候会有点问题调用redis太频繁了;不同秒才需要
if (DateTime.Now.Second != second)
{
var existZipCacheFile = _myCodeCacheService.Exists($"{CacheKey.ReportZipFileCacheKey}{ReportId}");
if (!existZipCacheFile)
{
//移除正在下载
_myCodeCacheService.Delete($"{CacheKey.HasDownloadZipCacheKey}");
throw new BaseException($"用户已经取消id={ReportId}的导出");
}
second = DateTime.Now.Second;
}
i++;
}
//这里判断如果只有一个文件则直接导出为excel,不用压缩了
if (ExcelFileType == (int)ExportFileType.Zip)
{
//保存并压缩
zipFile = Path.Combine(savePathFolder, $"{EnumHelper.GetDescription<ReportType>(ReportType)}_{ReportId}.zip");
ZipHelper.Zip(zipFilePaths, zipFile);
//将zip路径放到RedisCache中
_myCodeCacheService.Set($"{CacheKey.ReportZipFileCacheKey}{ReportId}", zipFile, new TimeSpan(7, 1, 0, 0));
resultData.CurQty = listCount;
resultData.Rate = 1;
WebSocketBLL.SendSocketMsg(ReportId, JsonHelper.ToJson(result, false, true));
//移除正在下载
_myCodeCacheService.Delete($"{CacheKey.HasDownloadZipCacheKey}");
}
return zipFile;
}
#endregion
}
}