using Furion.DependencyInjection; using Furion.DynamicApiController; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Myshipping.Application.Entity; using Myshipping.Core.Entity; using Myshipping.Core.Service; using Myshipping.Core; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Furion.FriendlyException; using NPOI.POIFS.Storage; using Yitter.IdGenerator; using Furion.DistributedIDGenerator; using System.Text.RegularExpressions; using Furion; using Myshipping.Application.Helper; using HtmlAgilityPack; using Myshipping.Application.ConfigOption; using Myshipping.Application.Enum; using System.IO; using StackExchange.Profiling.Internal; using Furion.JsonSerialization; using MySqlX.XDevAPI.Common; using Furion.RemoteRequest.Extensions; using Newtonsoft.Json; using System.Net.Http; using SqlSugar; namespace Myshipping.Application { /// /// 船舶相关截止时间的通知 /// [ApiDescriptionSettings("Application", Name = "RouteChangeAdvisory", Order = 10)] public class RouteChangeAdvisoryService : IRouteChangeAdvisoryService, IDynamicApiController, ITransient { private readonly ISysCacheService _cache; private readonly ILogger _logger; private readonly SqlSugarRepository _taskBaseRepository; private readonly SqlSugarRepository _taskRouteChangeAdvisoryInfoRepository; private readonly SqlSugarRepository _taskRouteChangeAdvisoryDetailInfoRepository; private readonly SqlSugarRepository _djyUserMailAccount; private readonly SqlSugarRepository _bookingOrderRepository; private readonly SqlSugarRepository _bookingOrderContactRepository; private readonly SqlSugarRepository _sysUserRepository; private readonly SqlSugarRepository _repPrintTemplate; private readonly SqlSugarRepository _taskFileRepository; public RouteChangeAdvisoryService(ISysCacheService cache, ILogger logger, SqlSugarRepository taskBaseRepository, SqlSugarRepository taskRouteChangeAdvisoryInfoRepository, SqlSugarRepository taskRouteChangeAdvisoryDetailInfoRepository, SqlSugarRepository djyUserMailAccount, SqlSugarRepository bookingOrderContactRepository, SqlSugarRepository sysUserRepository, SqlSugarRepository repPrintTemplate, SqlSugarRepository taskFileRepository, SqlSugarRepository bookingOrderRepository) { _cache = cache; _logger = logger; _taskBaseRepository = taskBaseRepository; _taskRouteChangeAdvisoryInfoRepository = taskRouteChangeAdvisoryInfoRepository; _taskRouteChangeAdvisoryDetailInfoRepository = taskRouteChangeAdvisoryDetailInfoRepository; _djyUserMailAccount = djyUserMailAccount; _bookingOrderRepository = bookingOrderRepository; _bookingOrderContactRepository = bookingOrderContactRepository; _sysUserRepository = sysUserRepository; _repPrintTemplate = repPrintTemplate; _taskFileRepository = taskFileRepository; } #region 获取船舶相关截止时间的通知详情 /// /// 获取船舶相关截止时间的通知详情 /// /// 船舶相关截止时间的通知任务主键 /// 返回详情 [HttpGet("/RouteChangeAdvisory/GetInfoByTaskId")] public async Task GetInfoByTaskId(string taskPkId) { TaskRouteChangeAdvisoryShowDto dto = new TaskRouteChangeAdvisoryShowDto(); var taskBase = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskPkId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPkId}无法获取业务信息"); var advisoryInfo = _taskRouteChangeAdvisoryInfoRepository.AsQueryable().First(a => a.TASK_ID == taskBase.PK_ID); if (advisoryInfo == null) throw Oops.Oh($"船舶相关截止时间的通知主键{taskPkId}无法获取业务信息"); var detailList = _taskRouteChangeAdvisoryDetailInfoRepository.AsQueryable() .Where(a => a.P_ID == advisoryInfo.PK_ID).ToList(); dto = new TaskRouteChangeAdvisoryShowDto { PKId = advisoryInfo.PK_ID, TaskPKId = advisoryInfo.TASK_ID, CarrierId = advisoryInfo.CARRIER, CreateTime = advisoryInfo.CreatedTime, AdvisoryTitle = advisoryInfo.EMAIL_SUBJECT, CYCutDate = advisoryInfo.CY_CUT_DATE, ETA = advisoryInfo.ETA, ETD = advisoryInfo.ETD, MDGFCutDate = advisoryInfo.MDGF_CUT_DATE, origETD = advisoryInfo.ORIG_ETD, RouteCode = advisoryInfo.ROUTE_CODE, SICutDate = advisoryInfo.SI_CUT_DATE, Vessel = advisoryInfo.VESSEL, Voyno = advisoryInfo.VOYNO, VGMCutDate = advisoryInfo.VGM_CUTOFF_TIME, Week = advisoryInfo.WEEK, TerminalShiftCutDate = advisoryInfo.TM_SHIFT_CUT_DATE, LoadPort = advisoryInfo.READ_PORTLOAD, LoadPortId = advisoryInfo.PORTLOADID, LoadPortName = advisoryInfo.PORTLOAD, BuisList = new List() }; if (detailList.Count > 0) { var queryList = detailList.Where(a => a.BOOKING_ID.HasValue).Select(a => a.BOOKING_ID.Value).ToList(); if (queryList.Count > 0) { //查询整船的订舱订单列表 var bookList = _bookingOrderRepository.AsQueryable().Where(a => queryList.Contains(a.Id) && a.IsDeleted == false).ToList(); dto.BuisList = detailList.Select(p => { TaskRouteChangeAdvisoryBusiShowDto detail = new TaskRouteChangeAdvisoryBusiShowDto { PKId = p.PK_ID, LstTransferUserDate = p.LST_TRANSFER_USER_DATE, IsTransferUser = p.IS_TRANSFER_USER, LstTransferNote = p.LST_TRANSFER_NOTES, BookingId = p.BOOKING_ID.Value, IsEnable = p.IS_ENABLE, LstStatus = p.LST_STATUS, LstStatusName = p.LST_STATUS_NAME, }; var bookInfo = bookList.FirstOrDefault(x => x.Id == p.BOOKING_ID.Value); if (bookInfo != null) { detail.CustomerName = bookInfo.CUSTOMERNAME; detail.MBlNo = bookInfo.MBLNO; } else { //如果对应的订舱已被作废,只能标记不可发送 detail.IsEnable = false; } return detail; }).ToList(); } else { dto.BuisList = detailList.Select(p => { TaskRouteChangeAdvisoryBusiShowDto detail = new TaskRouteChangeAdvisoryBusiShowDto { PKId = p.PK_ID, LstTransferUserDate = p.LST_TRANSFER_USER_DATE, IsTransferUser = p.IS_TRANSFER_USER, LstTransferNote = p.LST_TRANSFER_NOTES, BookingId = p.BOOKING_ID.Value, IsEnable = false, LstStatus = p.LST_STATUS, LstStatusName = p.LST_STATUS_NAME, }; return detail; }).ToList(); } } return dto; } #endregion #region 自动转发船舶相关截止时间的通知 /// /// 自动转发船舶相关截止时间的通知 /// /// 船舶相关截止时间的通知任务主键 /// 返回回执 [HttpGet("/RouteChangeAdvisory/AutoTransferNotice")] public async Task AutoTransferNotice(string taskPKId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var queryRlt = await QueryVesselVoynoBookingOrder(taskPKId); _logger.LogInformation($"taskPKId={taskPKId} 检索对应的订舱记录完成,结果:{JSON.Serialize(queryRlt)}"); var model = _taskRouteChangeAdvisoryInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskPKId); var list =_taskRouteChangeAdvisoryDetailInfoRepository.AsQueryable().Filter(null,true).Where(a=>a.P_ID == model.PK_ID && a.IsDeleted == false).ToList(); var pkList = list.Select(a => a.PK_ID).ToList(); //如果没有配置批量,则按单票发送邮件 var rlt = BatchSendEmailToCustomer(pkList.ToArray()); _logger.LogInformation($"taskPKId={taskPKId} 推送邮件完成,结果:{JSON.Serialize(rlt)}"); } catch (Exception ex) { result.succ = false; result.msg = $"自动转发起运港未提箱失败,原因:{ex.Message}"; _logger.LogInformation($"taskPKId={taskPKId} 自动转发起运港未提箱失败,原因:{ex.Message}"); } return result; } #endregion #region 检索同一航次对应的订舱订单(并对应记录) /// /// 检索同一航次对应的订舱订单(并对应记录) /// /// 船舶相关截止时间的通知任务主键 /// 返回回执 [HttpGet("/RouteChangeAdvisory/QueryVesselVoynoBookingOrder")] public async Task QueryVesselVoynoBookingOrder(string taskPKId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var taskBase = _taskBaseRepository.AsQueryable().Filter(null,true).First(a => a.PK_ID == taskPKId); if (taskBase == null) throw Oops.Oh($"任务主键{taskPKId}无法获取业务信息"); var advisoryInfo = _taskRouteChangeAdvisoryInfoRepository.AsQueryable().Filter(null, true).First(a => a.TASK_ID == taskBase.PK_ID); if (advisoryInfo == null) throw Oops.Oh($"船舶相关截止时间的通知主键{taskPKId}无法获取业务信息"); var detailList = _taskRouteChangeAdvisoryDetailInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.P_ID == advisoryInfo.PK_ID).ToList(); //通过船名、航次、装货港、取是主单的订舱记录列表 var bookList = _bookingOrderRepository.AsQueryable().Filter(null, true).Where(a => a.VESSEL == advisoryInfo.VESSEL && (a.VOYNO == advisoryInfo.VOYNO || a.VOYNOINNER == advisoryInfo.VOYNO) && a.PORTLOADID == advisoryInfo.PORTLOADID && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0)).ToList(); //用查询到的订舱列表和明细记录标做匹配,如果没有需要新增记录表 var addList = bookList.GroupJoin(detailList, l => l.Id, r => r.BOOKING_ID.Value, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) { return new { IsAdd = true, book = l }; } return new { IsAdd = false, book = l }; }).Where(t => t.IsAdd).Select(t => t.book).ToList(); DateTime nowDate = DateTime.Now; if (addList.Count > 0) { addList.ForEach(t => { TaskRouteChangeAdvisoryDetailInfo detail = new TaskRouteChangeAdvisoryDetailInfo { PK_ID = IDGen.NextID().ToString(), P_ID = advisoryInfo.PK_ID, IsDeleted = false, BOOKING_ID = t.Id, MBL_NO = t.MBLNO, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TenantId = UserManager.TENANT_ID, IS_ENABLE = true, }; _taskRouteChangeAdvisoryDetailInfoRepository.Insert(detail); }); } } catch (Exception ex) { result.succ = false; result.msg = $"检索失败,原因:{ex.Message}"; _logger.LogInformation($"taskPKId={taskPKId} 检索同一航次对应的订舱订单(并对应记录) 处理异常,原因:{ex.Message}"); new EmailNoticeHelper().SendEmailNotice($"taskid={taskPKId} Advisory 换船提醒 转发通知邮件失败", $"taskid={taskPKId} 换船提醒 转发通知邮件失败,原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } return result; } #endregion #region 批量发送邮件通知给客户 /// /// 批量发送邮件通知给客户 /// /// 船舶相关截止时间的通知订舱明细记录主键组 /// 返回回执 [HttpPost("/RouteChangeAdvisory/BatchSendEmailToCustomer")] public async Task BatchSendEmailToCustomer([FromBody] string[] detailPKIds) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { if (detailPKIds == null || detailPKIds.Length == 0) throw Oops.Oh($"未选择需要发送订单明细"); var detailList = _taskRouteChangeAdvisoryDetailInfoRepository.AsQueryable().Filter(null, true) .Where(a => detailPKIds.Contains(a.PK_ID) && a.IsDeleted == false).ToList(); if (detailPKIds.Length != detailList.Count) { throw Oops.Oh($"检索明细数据失败,检索数据不存在或已作废"); } var pId = detailList.FirstOrDefault().P_ID; var advisoryModel = _taskRouteChangeAdvisoryInfoRepository.AsQueryable().Filter(null, true).First(a => a.PK_ID == pId); TaskBaseInfo taskBaskInfo = new TaskBaseInfo(); if (advisoryModel != null) { taskBaskInfo = _taskBaseRepository.AsQueryable().Filter(null, true).First(a => a.PK_ID == advisoryModel.TASK_ID); } var bookIdList = detailList.Where(t => t.IS_ENABLE == true) .Select(t => t.BOOKING_ID.Value).ToList(); if (detailList.Any(a => !a.BOOKING_ID.HasValue)) { throw Oops.Oh($"明细相关的订舱数据检索失败,请确认订舱数据是否存在"); } //需要根据订单的往来单位统一推送一封邮件,里面有提单号列表 var bookList = _bookingOrderRepository.AsQueryable().Filter(null, true).Where(a => bookIdList.Contains(a.Id) && a.IsDeleted == false && (a.ParentId == null || a.ParentId == 0)).ToList(); var checkList = detailList.GroupJoin(bookList, l => l.BOOKING_ID.Value, r => r.Id, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) return new { IsNoBooking = true, MblNo = l.MBL_NO }; return new { IsNoBooking = false, MblNo = l.MBL_NO }; }).Where(a => a.IsNoBooking).Select(a => a.MblNo).ToList(); if (checkList.Count > 0) { throw Oops.Oh($"明细提单号对应订舱没有记录,{string.Join(",", checkList.ToArray())}"); } var bookingContactList = _bookingOrderContactRepository.AsQueryable().Filter(null, true) .Where(a => bookIdList.Contains(a.BookingId.Value) && a.IsDeleted == false).ToList(); //还需要判断订舱是否录了客户联系人 var checkContactList = bookList.GroupJoin(bookingContactList, l => l.Id, r => r.BookingId.Value, (l, r) => { var currList = r.ToList(); if (currList.Count == 0) return new { IsNoContact = true,IsNoEmail = false, book = l }; if (currList.Count(p => string.IsNullOrWhiteSpace(p.Email)) > 0) return new { IsNoContact = true, IsNoEmail = true, book = l }; return new { IsNoContact = false, IsNoEmail = false, book = l }; }).Where(a=>a.IsNoContact).ToList(); if (checkContactList.Count > 0) { var currList = checkContactList.Select(a => a.book.MBLNO).ToList(); throw Oops.Oh($"以下订舱订单未指定往来单位联系人或联系人未填写邮箱,请修改订舱信息,{string.Join(",", checkList.ToArray())}"); } //按照往来单位来合并订单,一个客户一个邮件来提醒 var gList = bookList.GroupBy(a => a.CUSTOMERID).Select(a => { var currList = a.ToList(); return new { CustId = a.Key, CustName = currList.FirstOrDefault().CUSTOMERNAME, OrderList = currList }; }).ToList(); gList.ForEach(book => { var currBookIdList = book.OrderList.Select(x => x.Id).ToList(); var currContactList = bookingContactList.Where(p => currBookIdList.Contains(p.BookingId.Value)).ToList(); var rlt = GenerateSendEmail(advisoryModel,book.OrderList, currContactList, taskBaskInfo).GetAwaiter().GetResult(); }); } catch (Exception ex) { result.succ = false; result.msg = $"批量发送失败,原因:{ex.Message}"; _logger.LogInformation($"detailPKIds={string.Join(",", detailPKIds)} 批量发送邮件通知给客户 处理异常,原因:{ex.Message}"); new EmailNoticeHelper().SendEmailNotice($"taskid={detailPKIds.FirstOrDefault()} Advisory 换船提醒 转发通知邮件失败", $"taskid={detailPKIds.FirstOrDefault()} 换船提醒 detailPKIds={string.Join(",", detailPKIds)} 批量发送邮件通知给客户 处理异常,原因:{ex.Message}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } return result; } #endregion /// /// 生成并转发通知邮件 /// /// /// /// /// /// private async Task GenerateSendEmail(TaskRouteChangeAdvisoryInfo model,List bookingOrderList,List bookingContactList, TaskBaseInfo taskBaskInfo) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { //TO 邮件接收人 string toEmail = string.Empty; //订舱OP的邮箱 string opEmail = string.Empty; //去重客户联系人的邮箱 toEmail = string.Join(";", bookingContactList.Select(x => x.Email.Trim()).Distinct().ToArray()); List opEmailList = new List(); SysUser opUserInfo = null; bookingOrderList.ForEach(bk => { //获取操作OP的邮箱 if (!string.IsNullOrWhiteSpace(bk.OPID)) { var opId = long.Parse(bk.OPID); var opUser = _sysUserRepository.AsQueryable().Filter(null, true).First(a => a.Id == opId); if (opUser != null) { if (opUserInfo == null) opUserInfo = opUser; if (!string.IsNullOrWhiteSpace(opUser.Email)) { opEmailList.Add(opUser.Email.Trim()); _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 获取操作OP的邮箱,opEmail={opEmail} opid={opId} name={opUser.Name}"); } else { _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 获取操作OP的邮箱失败,opEmail={opUser.Email} opid={opId} name={opUser.Name}"); } } else { _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 检索操作OP信息失败,opid={opId} name={opUser.Name}"); } } //获取客服的邮箱 if (!string.IsNullOrWhiteSpace(bk.CUSTSERVICEID)) { var opId = long.Parse(bk.CUSTSERVICEID); var opUser = _sysUserRepository.AsQueryable().Filter(null, true).First(a => a.Id == opId); if (opUser != null) { if (!string.IsNullOrWhiteSpace(opUser.Email)) { opEmailList.Add(opUser.Email.Trim()); _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 获取客服的邮箱,opEmail={opEmail} opid={opId} name={opUser.Name}"); } else { _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 获取客服的邮箱失败,opEmail={opUser.Email} opid={opId} name={opUser.Name}"); } } else { _logger.LogInformation($"id={bk.Id} mblno={bk.MBLNO} 检索客服信息失败,opid={opId} name={opUser.Name}"); } } }); if (opEmailList.Count > 0) opEmail = string.Join(";", opEmailList.Distinct().ToArray()); string emailTitle = $"Advisory:{model.EMAIL_SUBJECT}"; //提取当前公共邮箱的配置 DjyUserMailAccount publicMailAccount = _djyUserMailAccount.AsQueryable().Filter(null, true).First(x => x.TenantId == UserManager.TENANT_ID && x.ShowName == "PublicSend" && x.SmtpPort > 0 && x.SmtpServer != null && x.SmtpServer != ""); _logger.LogInformation($"提取当前公共邮箱的配置完成,id={publicMailAccount.Id}"); if (publicMailAccount == null) { throw Oops.Oh($"提取公共邮箱配置失败,请在用户邮箱账号管理增加配置显示名为PublicSend或者配置个人邮箱"); } //获取邮件模板 var printTemplate = _repPrintTemplate.AsQueryable().Filter(null, true).First(x => x.CateCode.Contains("advisory_route_change_template") && x.TenantId == UserManager.TENANT_ID); if (printTemplate == null) { throw Oops.Bah(BookingErrorCode.BOOK115); } //读取邮件模板并填充数据 string emailHtml = GenerateSendEmailHtml(model, bookingOrderList, printTemplate.FilePath, opUserInfo, UserManager.TENANT_NAME).GetAwaiter().GetResult(); EmailApiUserDefinedDto emailApiUserDefinedDto = new EmailApiUserDefinedDto { SendTo = toEmail, CCTo = opEmail, Title = emailTitle, Body = emailHtml, Account = publicMailAccount.MailAccount?.Trim(), Password = publicMailAccount.Password?.Trim(), Server = publicMailAccount.SmtpServer?.Trim(), Port = publicMailAccount.SmtpPort.HasValue ? publicMailAccount.SmtpPort.Value : 465, UseSSL = publicMailAccount.SmtpSSL.HasValue ? publicMailAccount.SmtpSSL.Value : true, Attaches = new List() }; _logger.LogInformation($"生成请求邮件参数,结果:{JSON.Serialize(emailApiUserDefinedDto)}"); TaskFileInfo fileInfo = null; if (taskBaskInfo.TASK_BASE_TYPE == TaskBaseTypeEnum.ROUTE_CUT_CHANGE.ToString()) { fileInfo = _taskFileRepository.AsQueryable().Filter(null, true).Where(a => a.TASK_PKID == taskBaskInfo.PK_ID && a.FILE_CATEGORY.Contains("ADVISORY")) .OrderByDescending(a => a.CreatedTime).First(); } if (fileInfo == null) { throw Oops.Oh($"提取文件失败,不能发送邮件"); } _logger.LogInformation($"获取订舱附件地址,结果:{fileInfo.FILE_PATH}"); var opt = App.GetOptions(); var dirAbs = opt.basePath; if (string.IsNullOrEmpty(dirAbs)) { dirAbs = App.WebHostEnvironment.WebRootPath; } string filePath = Path.Combine(dirAbs, fileInfo.FILE_PATH); //推送邮件 var emailRlt = await PushEmail(emailApiUserDefinedDto, filePath); _logger.LogInformation($"推送邮件完成,结果:{JSON.Serialize(emailRlt)}"); if (emailRlt.succ) { result.succ = true; result.msg = "成功"; } else { result.succ = false; result.msg = emailRlt.msg; new EmailNoticeHelper().SendEmailNotice($"taskid={model.TASK_ID} Advisory 换船提醒 转发通知邮件失败", $"taskid={model.TASK_ID} 换船提醒 转发通知邮件失败,原因:{emailRlt.msg}", App.Configuration["EmailNoticeDefaultUser"].GetUserEmailList()); } } catch (Exception ex) { } return result; } #region 通过邮件模板生成HTML /// /// 通过邮件模板生成HTML /// /// /// /// /// /// /// public async Task GenerateSendEmailHtml(TaskRouteChangeAdvisoryInfo model, List bookingOrderList, string filePath, SysUser opUserInfo, string tenantName) { string result = string.Empty; string baseHtml = string.Empty; try { var opt = App.GetOptions(); var dirAbs = opt.basePath; if (string.IsNullOrEmpty(dirAbs)) { dirAbs = App.WebHostEnvironment.WebRootPath; } var fileAbsPath = Path.Combine(dirAbs, filePath); _logger.LogInformation($"查找模板文件:{fileAbsPath}"); if (!File.Exists(fileAbsPath)) { throw Oops.Bah(BookingErrorCode.BOOK115); } baseHtml = File.ReadAllText(fileAbsPath); if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Name)) { baseHtml = baseHtml.Replace("#opname#", opUserInfo.Name); } else { baseHtml = baseHtml.Replace("#opname#", "操作"); } if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Email)) { baseHtml = baseHtml.Replace("#opemail#", opUserInfo.Email); } else { baseHtml = baseHtml.Replace("#opemail#", ""); } if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Phone)) { baseHtml = baseHtml.Replace("#optel#", opUserInfo.Phone); } else if (opUserInfo != null && !string.IsNullOrWhiteSpace(opUserInfo.Tel)) { baseHtml = baseHtml.Replace("#optel#", opUserInfo.Tel); } else { baseHtml = baseHtml.Replace("#optel#", ""); } //标题 if (!string.IsNullOrWhiteSpace(model.EMAIL_SUBJECT)) { baseHtml = baseHtml.Replace("#AdvisorySubject#", model.EMAIL_SUBJECT); } else { baseHtml = baseHtml.Replace("#AdvisorySubject#", ""); } if (!string.IsNullOrWhiteSpace(tenantName)) { baseHtml = baseHtml.Replace("#TenantCompanyName#", tenantName); } else { baseHtml = baseHtml.Replace("#TenantCompanyName#", ""); } HtmlDocument html = new HtmlDocument(); html.LoadHtml(baseHtml); HtmlNode baseTable = html.DocumentNode.SelectNodes("//table[@class='billno-table']").FirstOrDefault(); if (baseTable == null) throw Oops.Oh($"读取邮件模板格式错误,定位base-table失败"); //var baseTrList = baseTable.SelectNodes(".//tr"); bookingOrderList.ForEach(b => { baseTable.ChildNodes.Add(HtmlNode.CreateNode($"{b.MBLNO}")); }); result = html.DocumentNode.OuterHtml; } catch (Exception ex) { _logger.LogInformation($"生成预甩通知邮件正文失败,原因:{ex.Message}"); throw Oops.Bah($"生成预甩通知邮件正文失败,原因:{ex.Message}"); } return result; } #endregion #region 推送邮件 /// /// 推送邮件 /// /// 自定义邮件详情 /// 文件路径 /// 返回回执 private async Task PushEmail(EmailApiUserDefinedDto emailApiUserDefinedDto, string filePath) { CommonWebApiResult result = new CommonWebApiResult { succ = true }; List emailList = new List(); var emailUrl = _cache.GetAllDictData().GetAwaiter().GetResult() .FirstOrDefault(x => x.TypeCode == "url_set" && x.Code == "email_api_url")?.Value; if (emailUrl == null) throw Oops.Bah("字典未配置 url_set->email_api_url 请联系管理员"); System.IO.FileStream file = new System.IO.FileStream(filePath, FileMode.Open, FileAccess.Read); int SplitSize = 5242880;//5M分片长度 int index = 1; //序号 第几片 long StartPosition = 5242880 * (index - 1); long lastLens = file.Length - StartPosition;//真不知道怎么起命了,就这样吧 if (lastLens < 5242880) { SplitSize = (int)lastLens; } byte[] heByte = new byte[SplitSize]; file.Seek(StartPosition, SeekOrigin.Begin); //第一个参数是 起始位置 file.Read(heByte, 0, SplitSize); //第三个参数是 读取长度(剩余长度) file.Close(); string base64Str = Convert.ToBase64String(heByte); string newFileName = Path.GetFileName(filePath); if (newFileName.Length > 12) newFileName = $"{Path.GetFileName(filePath).Substring(0, 12)}{Path.GetExtension(filePath)}"; emailApiUserDefinedDto.Attaches.Add(new AttachesInfo { AttachName = newFileName, AttachContent = base64Str }); emailList.Add(emailApiUserDefinedDto); //string strJoin = System.IO.File.ReadAllText(filePath); DateTime bDate = DateTime.Now; HttpResponseMessage res = null; try { res = await emailUrl.SetBody(emailList, "application/json").PostAsync(); } catch (Exception ex) { _logger.LogInformation($"发送邮件异常:{ex.Message}"); } DateTime eDate = DateTime.Now; TimeSpan ts = eDate.Subtract(bDate); var timeDiff = ts.TotalMilliseconds; _logger.LogInformation($"邮件上传完成 上传文件大小:{heByte.Length} 用时:{timeDiff}ms.,"); _logger.LogInformation($"发送邮件返回:{JSON.Serialize(res)}"); if (res != null && res.StatusCode == System.Net.HttpStatusCode.OK) { var userResult = await res.Content.ReadAsStringAsync(); var respObj = JsonConvert.DeserializeAnonymousType(userResult, new { Success = false, Message = string.Empty, Code = -9999, }); result.succ = respObj.Success; result.msg = respObj.Message; } return result; } #endregion } }