Files
YunTongJackYunTask/Reportapi/MyCode.Project.Services/BLL/ReportExport/BaseExport.cs
2025-07-04 11:09:51 +08:00

490 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}
}