using Furion; using Furion.DependencyInjection; using Furion.DistributedIDGenerator; using Furion.DynamicApiController; using Furion.FriendlyException; using Mapster; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.StaticFiles.Infrastructure; using Microsoft.Extensions.Logging; using Myshipping.Application.ConfigOption; using Myshipping.Application.Entity; using Myshipping.Core; using Myshipping.Core.Service; using NPOI.Util; using StackExchange.Profiling.Internal; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace Myshipping.Application.Service.TaskManagePlat { /// /// 任务分享链接服务 /// [ApiDescriptionSettings("Application", Name = "TaskManageShareLink", Order = 10)] public class TaskManageShareLinkService : ITaskManageShareLinkService, IDynamicApiController, ITransient { private readonly ISysCacheService _cache; private readonly ILogger _logger; private readonly SqlSugarRepository _taskShareLinkInfoRepository; private readonly SqlSugarRepository _taskShareLinkDynamicDataInfoRepository; private readonly SqlSugarRepository _taskBaseRepository; private readonly SqlSugarRepository _taskRollingNominationInfoRepository; private readonly SqlSugarRepository _taskRollingNominationDispatchInfoRepository; private readonly SqlSugarRepository _taskRollingNominationShipInfoRepository; private readonly SqlSugarRepository _taskRollingNominationDetailInfoRepository; private const string SHARE_LINK_CACHE_KEY_TEMPLATE = "ShareLinkKeyIncrement"; public TaskManageShareLinkService(ISysCacheService cache, ILogger logger, SqlSugarRepository taskShareLinkInfoRepository, SqlSugarRepository taskShareLinkDynamicDataInfoRepository, SqlSugarRepository taskBaseRepository, SqlSugarRepository taskRollingNominationInfoRepository, SqlSugarRepository taskRollingNominationDispatchInfoRepository, SqlSugarRepository taskRollingNominationShipInfoRepository, SqlSugarRepository taskRollingNominationDetailInfoRepository) { _cache = cache; _logger = logger; _taskShareLinkInfoRepository = taskShareLinkInfoRepository; _taskShareLinkDynamicDataInfoRepository = taskShareLinkDynamicDataInfoRepository; _taskBaseRepository = taskBaseRepository; _taskRollingNominationInfoRepository = taskRollingNominationInfoRepository; _taskRollingNominationDispatchInfoRepository = taskRollingNominationDispatchInfoRepository; _taskRollingNominationShipInfoRepository = taskRollingNominationShipInfoRepository; _taskRollingNominationDetailInfoRepository = taskRollingNominationDetailInfoRepository; } #region 生成访问链接 /// /// 生成访问链接 /// /// 创建分享链接请求 /// 返回回执 [HttpPost("/TaskManageShareLink/CreateShareLink")] public async Task CreateShareLink([FromBody] ShareLinkRequestDto model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); /* 1、判断当前businessId是否有STATUS=ACTIVE的记录,如果有记录不允许重复分享。 2、创建分享记录,并生成动态数据(预甩需要生成免责声明) 3、判断有效期是否小于等于当前日期,如果是不能生成分享。 4、创建完记录后,把生成后的SHARE_LINK_KEY写入redis并用expireDate作为失效日期。 5、返回SHARE_LINK_KEY。 */ try { string shareKey = string.Empty; if (string.IsNullOrWhiteSpace(model.businessId)) throw Oops.Oh($"业务ID不能为空"); if (string.IsNullOrWhiteSpace(model.taskType)) throw Oops.Oh($"任务类型不能为空"); if (string.IsNullOrWhiteSpace(model.businessType)) throw Oops.Oh($"业务类型不能为空"); if (string.IsNullOrWhiteSpace(model.expireDate)) throw Oops.Oh($"失效时间不能为空"); DateTime expireDateTime = DateTime.MinValue; DateTime nowDate = DateTime.Now; if(!DateTime.TryParse(model.expireDate, out expireDateTime)) throw Oops.Oh($"失效时间格式错误,请参考格式yyyy-MM-dd HH:mm:ss"); if(expireDateTime <= DateTime.Now) throw Oops.Oh($"失效时间不能早于或等于当前时间"); if (!model.businessType.Equals("NOMI_DISPATCH", StringComparison.OrdinalIgnoreCase)) { throw Oops.Oh($"当前只支持预甩调度分享"); } var nomDispatchList = _taskRollingNominationDispatchInfoRepository.AsQueryable().Filter(null, true) .InnerJoin((dispatch,detail) => dispatch.DETAIL_ID == detail.PK_ID) .Where((dispatch,detail) => dispatch.BATCH_ID == model.businessId && detail.IsDeleted == false && dispatch.IsDeleted == false) .Select((dispatch, detail) => new { Detail = detail, Dispatch = dispatch }).ToList(); if (nomDispatchList.Count == 0) throw Oops.Oh($"预甩调度获取详情失败,已删除或不存在"); if (nomDispatchList.Any(a => !string.IsNullOrWhiteSpace(a.Dispatch.USER_OPINION))) throw Oops.Oh($"当前预甩调度已有用户反馈,不能创建分享"); var shareInfo = _taskShareLinkInfoRepository.AsQueryable() .First(a => a.BUSI_ID == model.businessId && a.TASK_TYPE == model.taskType && a.STATUS == TaskShareLinkStatusEnum.ACTIVE.ToString() && a.IsDeleted == false); if (!model.isRenew) { if (shareInfo != null) { throw Oops.Oh($"已有分享记录不能重复生成"); } } else { shareInfo.IsDeleted = true; shareInfo.UpdatedTime = nowDate; shareInfo.UpdatedUserId = UserManager.UserId; shareInfo.UpdatedUserName = UserManager.Name; await _taskShareLinkInfoRepository.AsUpdateable(shareInfo) .UpdateColumns(it => new { it.IsDeleted, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); } TaskShareLinkInfo taskShareLinkInfo = new TaskShareLinkInfo { EXPIRE_DATE = expireDateTime, STATUS = TaskShareLinkStatusEnum.ACTIVE.ToString(), BUSI_ID = model.businessId, IS_MANUAL = false, CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, TASK_TYPE = model.taskType, IS_USER_FEEDBACK = model.isUserFeedBack, }; //写入分享记录 await _taskShareLinkInfoRepository.InsertAsync(taskShareLinkInfo); _logger.LogInformation($"写入分享记录表完成,id={taskShareLinkInfo.Id}"); var autoIncrementKey = RedisHelper.IncrBy(SHARE_LINK_CACHE_KEY_TEMPLATE); //生成分享KEY SuperShortLinkHelper codeHelper = new SuperShortLinkHelper(); shareKey = codeHelper.Confuse(autoIncrementKey); _logger.LogInformation($"生成分享KEY完成,id={taskShareLinkInfo.Id} shareKey={shareKey}"); //更新分享表 var shareEntity = _taskShareLinkInfoRepository.AsQueryable().First(a => a.Id == taskShareLinkInfo.Id); string taskId = nomDispatchList.FirstOrDefault().Dispatch.TASK_ID; var taskInfo = _taskBaseRepository.AsQueryable().First(a => a.PK_ID == taskId); //写入redis缓存 string cacheVal = $"{taskShareLinkInfo.Id}_{taskInfo.TASK_TYPE}_{taskInfo.TASK_NO}_{nomDispatchList.FirstOrDefault().Detail.SHIPMENT}_{taskInfo.TenantName}_{model.expireDate}"; var expireTimeSpan = expireDateTime.Subtract(nowDate).Duration(); //new DateTimeOffset(expireDateTime).ToUnixTimeSeconds(); if (_cache.Exists(shareKey)) { shareEntity.SHARE_LINK_KEY = shareKey; shareEntity.STATUS = "REPEAT_KEY";//REPEAT_KEY-重复KEY被取消 shareEntity.INCREMENT_KEY = autoIncrementKey; await _taskShareLinkInfoRepository.AsUpdateable(shareEntity) .UpdateColumns(it => new { it.SHARE_LINK_KEY, it.STATUS, it.INCREMENT_KEY }).ExecuteCommandAsync(); _logger.LogInformation($"分享KEY存在重复终止生成分享(cache),id={taskShareLinkInfo.Id} shareKey={shareKey} cache={_cache.Get(shareKey)}"); throw Oops.Oh($"已有分享记录不能重复生成"); } else { shareEntity.SHARE_LINK_KEY = shareKey; shareEntity.INCREMENT_KEY = autoIncrementKey; await _taskShareLinkInfoRepository.AsUpdateable(shareEntity) .UpdateColumns(it => new { it.SHARE_LINK_KEY, it.INCREMENT_KEY }).ExecuteCommandAsync(); await _cache.SetTimeoutAsync(shareKey, cacheVal, expireTimeSpan); _logger.LogInformation($"分享KEY写入cache完成,id={taskShareLinkInfo.Id} shareKey={shareKey} cache={cacheVal}"); //这里生成动态数据 if (taskInfo.TASK_BASE_TYPE == TaskBaseTypeEnum.ROLLING_NOMINATION.ToString() || taskInfo.TASK_BASE_TYPE == TaskBaseTypeEnum.TRANSFER_NOMINATION.ToString()) { var shareTxt = GenerateShareDynamicData(expireDateTime, taskInfo.TenantName); TaskShareLinkDynamicDataInfo dataInfo = new TaskShareLinkDynamicDataInfo { SHARE_ID = shareEntity.Id, DATA_TYPE = "DISCLAIMERS", DATA_MSG = shareTxt, DATA_MSG_TYPE = "HTML", CreatedTime = nowDate, UpdatedTime = nowDate, CreatedUserId = UserManager.UserId, CreatedUserName = UserManager.Name, }; await _taskShareLinkDynamicDataInfoRepository.InsertAsync(dataInfo); } } result.succ = true; result.ext = shareKey; } catch (Exception ex) { _logger.LogError($"获取预甩详情异常,原因:{ex.Message}"); result.succ = false; result.msg = $"获取预甩详情异常,原因:{ex.Message}"; } return result; } #endregion #region 取消访问链接 /// /// 取消访问链接 /// /// 访问链接业务主键 /// 返回回执 [HttpGet("/TaskManageShareLink/CancelShareLink")] public async Task CancelShareLink(string busiId) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); try { var shareInfo = _taskShareLinkInfoRepository.AsQueryable() .First(a => a.BUSI_ID == busiId && a.IsDeleted == false); if(shareInfo == null) throw Oops.Oh($"分享链接不存在或已删除"); var statusArg = new string[] { RollingNominationDispatchStatusEnum.COMPLETE.ToString(), RollingNominationDispatchStatusEnum.EXPIRE.ToString(), RollingNominationDispatchStatusEnum.CANCEL.ToString() }; if(statusArg.Any(a=>a.Equals(shareInfo.STATUS,StringComparison.OrdinalIgnoreCase))) throw Oops.Oh($"分享链接状态{shareInfo.STATUS} 不需要取消"); shareInfo.STATUS = RollingNominationDispatchStatusEnum.CANCEL.ToString(); shareInfo.UpdatedTime = DateTime.Now; shareInfo.UpdatedUserId = UserManager.UserId; shareInfo.UpdatedUserName = UserManager.Name; await _taskShareLinkInfoRepository.AsUpdateable(shareInfo) .UpdateColumns(it => new { it.STATUS, it.UpdatedTime, it.UpdatedUserId, it.UpdatedUserName }).ExecuteCommandAsync(); if (_cache.Exists(shareInfo.SHARE_LINK_KEY)) await _cache.DelAsync(shareInfo.SHARE_LINK_KEY); result.succ = true; result.msg = "成功"; } catch (Exception ex) { _logger.LogError($"取消访问链接异常,原因:{ex.Message}"); result.succ = false; result.msg = $"取消访问链接异常,原因:{ex.Message}"; } return result; } #endregion #region 校验成访问链接 /// /// 校验成访问链接 /// /// 请求链接 /// 返回回执 [HttpGet("/TaskManageShareLink/ValidateShareLink")] public async Task ValidateShareLink(string Url) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); return result; } #endregion #region 访问链接 /// /// 访问链接 /// /// 请求链接 /// 返回回执 public async Task QueryShareLink(string Url) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); return result; } #endregion #region 获取分享详情 /// /// 获取分享详情 /// /// 链接分享KEY /// 返回回执 [AllowAnonymous,HttpGet("/TaskManageShareLink/GetInfo")] public async Task GetInfo([FromQuery] string shareKey) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); /* 1、先验证shareKey是否在缓存存在,存在继续,不存在返回错误。 2、获取分享的表记录,根据任务类型调取不同的接口,返回详情数据。 3、查看是否存在分享的声明内容,如果存在,需要返回。 */ try { if (string.IsNullOrWhiteSpace(shareKey)) throw Oops.Oh($"链接分享KEY不能为空"); if (!_cache.Exists(shareKey)) throw Oops.Oh($"链接分享已失效"); var cacheVal = _cache.Get(shareKey); long shareId = long.Parse(cacheVal.Split(new char[]{ '_'}).FirstOrDefault()); var shareEntity = _taskShareLinkInfoRepository.AsQueryable().Filter(null, true) .First(a => a.Id == shareId); if (shareEntity == null) throw Oops.Oh($"链接分享不存在"); var showModel = await InnerGetInfo(shareEntity.BUSI_ID); var list = _taskShareLinkDynamicDataInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.SHARE_ID == shareEntity.Id).ToList(); if (list.Count > 0) { var dyData = list.FirstOrDefault(a => a.DATA_TYPE == "DISCLAIMERS"); if (dyData != null) showModel.DynamicData = dyData.DATA_MSG; } result.succ = true; result.ext = showModel; } catch(Exception ex) { _logger.LogError($"获取分享详情异常,原因:{ex.Message}"); result.succ = false; result.msg = $"获取分享详情异常,原因:{ex.Message}"; } return result; } #endregion #region 生成分享的动态数据 /// /// 生成分享的动态数据 /// /// 最后失效时间 /// 企业名称 /// 返回填充模板后文本 private string GenerateShareDynamicData(DateTime expireDateTime,string TenantCompanyName) { string result = string.Empty; try { //调取模板 string templatePath = App.Configuration["EmailTemplateFilePath"]; var opt = App.GetOptions(); var dirAbs = opt.basePath; if (string.IsNullOrEmpty(dirAbs)) { dirAbs = App.WebHostEnvironment.WebRootPath; } templatePath = $"{dirAbs}{templatePath}\\NominationShareTemplate.html"; result = File.ReadAllText(templatePath); if (!string.IsNullOrWhiteSpace(result)) { if (Regex.IsMatch(result, "#DeadLineDate#")) result = Regex.Replace(result, "#DeadLineDate#", expireDateTime.ToString("yyyy-MM-dd HH:mm:ss")); if (Regex.IsMatch(result, "#TenantCompanyName#")) result = Regex.Replace(result, "#TenantCompanyName#", TenantCompanyName); } } catch (Exception ex) { _logger.LogError($"生成分享动态数据异常,原因:{ex.Message}"); } return result; } #endregion #region 获取预甩详情 /// /// 获取预甩详情 /// /// 预甩货详调度批次号 /// 返回详情 private async Task InnerGetInfo(string dispatchBatchId) { TaskRollingNominationShowDto model = null; try { List rollingPlanList = new List(); var list = _taskRollingNominationInfoRepository.AsQueryable().Filter(null, true) .InnerJoin((nom, dispatch) => nom.PK_ID == dispatch.NOM_ID) .InnerJoin((nom, dispatch, detail) => dispatch.DETAIL_ID == detail.PK_ID) .Where((nom, dispatch, detail) => dispatch.BATCH_ID == dispatchBatchId && nom.IsDeleted == false && detail.IsDeleted == false && dispatch.IsDeleted == false) .Select((nom, dispatch, detail) => new { Nom = nom, Detail = detail, Dispatch = dispatch }).ToList(); var rollModel = list.FirstOrDefault().Nom; if (!string.IsNullOrWhiteSpace(rollModel.PLAN_TXT)) { rollingPlanList = rollModel.PLAN_TXT.Split("\\n").ToList(); } model = new TaskRollingNominationShowDto { PlanType = rollModel.PLAN_TYPE, CarrierId = rollModel.CARRIERID, Carrier = rollModel.CARRIER, ConfirmDeadLine = rollModel.CONFIRM_DEAD_LINE, CreateTime = rollModel.READ_CREATE_TIME, RollingTouchDoubleRollRemark = rollModel.ROLL_DOUBLE_REMARK, LoadDetailList = new List(), RollingPlanList = rollingPlanList, PreBillList = new List() }; var shipList = _taskRollingNominationShipInfoRepository.AsQueryable().Filter(null, true) .Where(a => a.NOM_ID == rollModel.PK_ID && a.IsDeleted == false).ToList(); var fromEntity = shipList.Where(a => a.SHIP_TYPE.Equals("From", StringComparison.OrdinalIgnoreCase)).ToList(); if (fromEntity.Count > 0) model.From = fromEntity.Select(p => p.Adapt()).ToList(); var toEntity = shipList.Where(a => Regex.IsMatch(a.SHIP_TYPE, "To(\\s+[0-9]+)?" , RegexOptions.IgnoreCase)).ToList(); if (toEntity.Count > 0) model.To = toEntity.Select(p => p.Adapt()).ToList(); List fromToList = new List(); //优先PORT关联FROM和TO,也有PORT为空的情况,这种就需要用Terminal来关联 if (model.From.Any(t => string.IsNullOrWhiteSpace(t.Port))) { //这里为了前端原船和换船做了根据Terminal对应 fromToList = model.From.GroupJoin(model.To, l => l.Terminal?.Trim(), r => r.Terminal?.Trim(), (l, r) => { TaskRollingNominationShipFromToDto dto = new TaskRollingNominationShipFromToDto(); dto.FromShip = l; var currArg = r.ToList(); if (currArg.Count > 0) { dto.ToShipList = currArg.Select((p, idx) => { if (Regex.IsMatch(p.ShipType, "[0-9]+")) return new { SortNo = int.Parse(Regex.Match(p.ShipType, "[0-9]+").Value), Obj = p }; return new { SortNo = idx + 1, Obj = p }; }).OrderBy(p => p.SortNo).Select(p => p.Obj).ToList(); } return dto; }).ToList(); } else { //这里为了前端原船和换船做了根据PORT对应 fromToList = model.From.GroupJoin(model.To, l => l.Port?.Trim(), r => r.Port?.Trim(), (l, r) => { TaskRollingNominationShipFromToDto dto = new TaskRollingNominationShipFromToDto(); dto.FromShip = l; var currArg = r.ToList(); if (currArg.Count > 0) { dto.ToShipList = currArg.Select((p, idx) => { if (Regex.IsMatch(p.ShipType, "[0-9]+")) return new { SortNo = int.Parse(Regex.Match(p.ShipType, "[0-9]+").Value), Obj = p }; return new { SortNo = idx + 1, Obj = p }; }).OrderBy(p => p.SortNo).Select(p => p.Obj).ToList(); } return dto; }).ToList(); } List> tuples = new List>(); model.LoadDetailList = list.Select(a => a.Detail.Adapt()).ToList(); model.FromToList = new List(); if (model.LoadDetailList.Count > 0) { model.TotalLoadCtnStat = string.Join(",", model.LoadDetailList.GroupBy(x => x.CtnAll) .Select(x => $"{x.Key}*{x.Sum(t => t.CtnNum)}").ToArray()); string rollRegex = "Roll\\s+to\\s+\\w+\\s+\\w{3,}\\/\\w+,\\s?if\\s+cannot\\s+catch\\s?,\\s+roll\\s+to\\s+\\w{3,}\\s+next\\s+sailing"; string rollontoRegex = "Roll\\s+onto\\s+\\w{3,}\\s+\\w+,\\s+[0-9]+\\s+days\\s+delay\\."; bool isSelectRoll = false; bool isRoll = false; bool isRollOnto = false; model.LoadDetailList.ForEach(p => { string vslCode = string.Empty; string voyNo = string.Empty; string strCode = string.Empty; string strCode2 = string.Empty; if (Regex.IsMatch(p.Status, rollRegex, RegexOptions.IgnoreCase)) { string currS = Regex.Match(p.Status, "(?<=Roll\\sto\\s\\w+\\s)\\w{3,}\\/\\w+(?=,)").Value; vslCode = Regex.Split(currS, "\\/")[0]?.Trim(); voyNo = Regex.Split(currS, "\\/")[1]?.Trim(); strCode = Regex.Match(p.Status, "(?<=if\\scannot\\scatch\\s?,\\sroll\\sto\\s)\\w{3,}(?=\\s+next\\s+sailing)").Value?.Trim(); isSelectRoll = true; } else if (p.Status.Trim().Equals("roll", StringComparison.OrdinalIgnoreCase)) { isRoll = true; } else if(Regex.IsMatch(p.Status, rollontoRegex, RegexOptions.IgnoreCase)) { vslCode = Regex.Match(p.Status, "(?<=Roll\\sonto\\s)\\w{3,}(?=\\s+\\w+,)").Value?.Trim(); isRollOnto = true; } for (int i = 0; i < fromToList.Count; i++) { if(!string.IsNullOrWhiteSpace(fromToList[i].FromShip.Port)) { if (fromToList[i].FromShip.Port.Equals(p.PlaceOfReceipt, StringComparison.OrdinalIgnoreCase)) { var fromInfo = fromToList[i].FromShip.Adapt(); List toShipList = new List(); if (isSelectRoll) { for (int j = 0; j < fromToList[i].ToShipList.Count; j++) { if (fromToList[i].ToShipList[j].VslCode.Equals(vslCode, StringComparison.OrdinalIgnoreCase)) { toShipList.Add(fromToList[i].ToShipList[j].Adapt()); } else if (fromToList[i].ToShipList[j].ShipString.Equals(strCode, StringComparison.OrdinalIgnoreCase)) { toShipList.Add(fromToList[i].ToShipList[j].Adapt()); } } } else if (isRoll) { for (int j = 0; j < fromToList[i].ToShipList.Count; j++) { if (fromToList[i].ToShipList[j].Port.Equals(p.PlaceOfDelivery?.Trim(), StringComparison.OrdinalIgnoreCase)) { toShipList.Add(fromToList[i].ToShipList[j].Adapt()); } } } if (toShipList.Count == 0) { if (fromToList[i].ToShipList.Count == 1) { toShipList.Add(fromToList[i].ToShipList.FirstOrDefault().Adapt()); } } model.FromToList.Add(new TaskRollingNominationShipFromToDto { FromShip = fromInfo, ToShipList = toShipList }); } } else { if (fromToList[i].FromShip.Terminal.Contains(p.PlaceOfReceipt, StringComparison.OrdinalIgnoreCase)) { var fromInfo = fromToList[i].FromShip.Adapt(); List toShipList = new List(); if (isRollOnto) { for (int j = 0; j < fromToList[i].ToShipList.Count; j++) { if (fromToList[i].ToShipList[j].VslCode.Equals(vslCode, StringComparison.OrdinalIgnoreCase)) { toShipList.Add(fromToList[i].ToShipList[j].Adapt()); } } } model.FromToList.Add(new TaskRollingNominationShipFromToDto { FromShip = fromInfo, ToShipList = toShipList }); } } } }); } } catch (Exception ex) { _logger.LogError($"获取预甩详情异常,原因:{ex.Message}"); throw ex; } return model; } #endregion /// /// 推送分享链接反馈意见 /// /// 推送分享链接反馈意见请求 /// 返回回执 [AllowAnonymous, HttpPost("/TaskManageShareLink/PushShareLinkFeedBack")] public async Task PushShareLinkFeedBack(PushShareLinkFeedBackDto model) { TaskManageOrderResultDto result = new TaskManageOrderResultDto(); /* 1、验证shareKey是否有效。 2、查看分享记录找到对应的预甩调度详情。 3、用户已经提交过意见的不能再发起 3、更新用户反馈意见。 4、返回成功 */ try { if (string.IsNullOrWhiteSpace(model.shareKey)) throw Oops.Oh($"链接分享KEY不能为空"); if (!_cache.Exists(model.shareKey)) throw Oops.Oh($"链接分享已失效"); var shareEntity = _taskShareLinkInfoRepository.AsQueryable() .First(a => a.SHARE_LINK_KEY == model.shareKey); if (shareEntity == null) throw Oops.Oh($"链接分享不存在"); if(shareEntity.STATUS != TaskShareLinkStatusEnum.ACTIVE.ToString()) { if(shareEntity.STATUS != TaskShareLinkStatusEnum.COMPLETE.ToString()) throw Oops.Oh($"预甩通知用户已反馈,不能重复提交"); throw Oops.Oh($"分享链接已失效,请咨询操作重新获取"); } shareEntity.USER_OPINION = model.userOpinion; shareEntity.USER_OPINION_TXT = model.userOpinionTxt; shareEntity.CONFIRM_DATE = DateTime.Now; shareEntity.IS_MANUAL = model.isManual; await _taskShareLinkInfoRepository.AsUpdateable(shareEntity) .UpdateColumns(it => new { it.USER_OPINION, it.USER_OPINION_TXT, it.CONFIRM_DATE, it.IS_MANUAL, }).ExecuteCommandAsync(); //需要回写预甩任务的 result.succ = true; result.msg = "成功"; } catch (Exception ex) { _logger.LogError($"推送分享链接反馈意见异常,原因:{ex.Message}"); result.succ = false; result.msg = $"推送分享链接反馈意见异常,原因:{ex.Message}"; } return result; } } }