490 lines
18 KiB
C#
490 lines
18 KiB
C#
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
|
||
|
||
|
||
|
||
}
|
||
}
|