using BBWYB.Common.Log; using BBWYB.Common.Models; using BBWYB.Server.Model; using BBWYB.Server.Model.Db; using BBWYB.Server.Model.Dto; using FreeSql; using Newtonsoft.Json.Linq; using SDKAdapter; using SDKAdapter.OperationPlatform.Client; using SDKAdapter.OperationPlatform.Models; using Yitter.IdGenerator; namespace BBWYB.Server.Business.Sync { public class OrderSyncBusiness : BaseBusiness, IDenpendency { private OP_PlatformClientFactory opPlatformClientFactory; private VenderBusiness venderBusiness; private TaskSchedulerManager taskSchedulerManager; private List timeLimitTaskTypes; private TimeLimitRules timeLimitRules; public OrderSyncBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, OP_PlatformClientFactory opPlatformClientFactory, VenderBusiness venderBusiness, TaskSchedulerManager taskSchedulerManager, TimeLimitRules timeLimitRules) : base(fsql, nLogManager, idGenerator) { this.opPlatformClientFactory = opPlatformClientFactory; this.venderBusiness = venderBusiness; this.taskSchedulerManager = taskSchedulerManager; timeLimitTaskTypes = new List() { Enums.TimeLimitTaskType.采购任务, Enums.TimeLimitTaskType.待议价任务 }; this.timeLimitRules = timeLimitRules; } public void AutoOrderSync() { var shopList = venderBusiness.GetShopList(platform: Enums.Platform.拳探); foreach (var shop in shopList) { Task.Factory.StartNew(() => Sync(shop, string.Empty, DateTime.Now.AddHours(-3), DateTime.Now, AdapterEnums.SortTimeField.Modify, AdapterEnums.SortType.Desc), CancellationToken.None, TaskCreationOptions.LongRunning, taskSchedulerManager.SyncOrderTaskScheduler); } } public void ManualOrderSync(long shopId, string orderId, DateTime? startTime, DateTime? endTime) { var shop = venderBusiness.GetShopList(shopId, platform: Enums.Platform.拳探).FirstOrDefault(); if (shop == null) throw new BusinessException($"未找到店铺Id {shopId}"); Task.Factory.StartNew(() => Sync(shop, orderId, startTime, endTime, AdapterEnums.SortTimeField.Modify, AdapterEnums.SortType.Desc), CancellationToken.None, TaskCreationOptions.LongRunning, taskSchedulerManager.SyncOrderTaskScheduler); } public void ManualOrderSync(long shopId, DateTime startTime, DateTime endTime) { var shop = venderBusiness.GetShopList(shopId, platform: Enums.Platform.拳探).FirstOrDefault(); if (shop == null) throw new BusinessException($"未找到店铺Id {shopId}"); while (true) { var s = startTime; var e = s.AddHours(3); Sync(shop, string.Empty, s, e, AdapterEnums.SortTimeField.Modify, AdapterEnums.SortType.Desc); if (e >= endTime) break; startTime = startTime.AddHours(3); } } private void Sync(ShopResponse shop, string orderId, DateTime? startTime, DateTime? endTime, AdapterEnums.SortTimeField sortTimeField, AdapterEnums.SortType sortType) { var shopId = long.Parse(shop.ShopId); var loggerName = $"订单同步-{shop.ShopName}"; try { var qtOrderList = opPlatformClientFactory.GetClient(AdapterEnums.PlatformType.拳探).GetOrderList(new OP_QueryOrderRequest() { AppKey = shop.AppKey, AppSecret = shop.AppSecret, AppToken = shop.AppToken, OrderId = orderId, PageIndex = 1, PageSize = 100, Platform = AdapterEnums.PlatformType.拳探, SortTimeField = sortTimeField, SortType = sortType, StartDate = startTime, EndDate = endTime }); if (qtOrderList.Count == 0) return; var qtOrderIdList = qtOrderList.Items.Select(qto => qto.OrderId).ToList(); var dbOrderList = fsql.Select(qtOrderIdList).ToList(); var payedQTOrderIdList = qtOrderList.Items.Where(qto => qto.IsPay).Select(qto => qto.OrderId).ToList(); var payedQTSpuIdList = qtOrderList.Items.Where(qto => qto.IsPay).SelectMany(qto => qto.OrderSkuList).Select(qtos => qtos.ProductId).Distinct().ToList(); var payedQTSkuIdList = qtOrderList.Items.Where(qto => qto.IsPay).SelectMany(qto => qto.OrderSkuList).Select(qtos => qtos.SkuId).Distinct().ToList(); //限时任务列表 var dbTimeLimitTaskList = fsql.Select().Where(t => timeLimitTaskTypes.Contains(t.TaskType.Value) && payedQTOrderIdList.Contains(t.OrderId)).ToList(); //限时采购任务列表 var dbPurchaseTimeLimitTaskList = dbTimeLimitTaskList.Where(t => t.TaskType == Enums.TimeLimitTaskType.采购任务).ToList(); //限时议价任务列表 var dbOptimizationLimitTaskList = dbTimeLimitTaskList.Where(t => t.TaskType == Enums.TimeLimitTaskType.待议价任务).ToList(); //现有sku销量 var dbSkuTotalSaleInfoList = fsql.Select().Where(s => s.ShopId == shopId && s.IsEnabled == true && payedQTSkuIdList.Contains(s.SkuId)) .ToList(); //现有spu销量 var dbSpuTotalSaleInfoList = fsql.Select().Where(s => s.ShopId == shopId && s.IsEnabled == true && payedQTSpuIdList.Contains(s.ProductId)) .ToList(); #region DB Operation List insertOrderList = new List(); List insertOrderSkuList = new List(); //List updateOrderSkuIdList_OptimizationFlag = new List(); Dictionary> updateOSkuOptimizationFlagByReasonGroups = new Dictionary>(); List insertOrderConsigneeList = new List(); List insertTimeLimitTaskList = new List(); List deleteTimeLimitTaskOrderIdList = new List(); List> updateOrderList = new List>(); List insertSkuTotalSaleInfoList = new List(); IList updateSkuTotalSaleInfoList = new List(); List insertSpuTotalSaleInfoList = new List(); IList updateSpuTotalSaleInfoList = new List(); #endregion //等待检查sku销量的订单集合 List waitToCheckSkuSaleOrderList = new List(); IDictionary deductionSkuCountDictionary = new Dictionary(); IDictionary deductionSpuCountDictionary = new Dictionary(); #region 同步订单 foreach (var qtOrder in qtOrderList.Items) { var dbOrder = dbOrderList.FirstOrDefault(o => o.Id == qtOrder.OrderId); var orderState = ConvertQuanTanOrderState(qtOrder.OrderState, qtOrder.IsPay, dbOrder?.IsPurchased ?? false); if (dbOrder == null) { //新订单 dbOrder = new Model.Db.Order() { Id = qtOrder.OrderId, OrderSn = qtOrder.OrderSn, BuyerRemark = qtOrder.BuyerRemark, EndTime = qtOrder.EndTime, //ExpressName = qtOrder.DeliveryResponse.ExpressName, FreightPrice = qtOrder.FreightAmount, ModifyTime = qtOrder.ModifyTime, IsPurchased = false, OrderPayment = qtOrder.OrderPayment, OrderSellerPrice = qtOrder.OrderProductAmount, OrderTotalPrice = qtOrder.OrderTotalAmount, OrderType = 0, PayType = qtOrder.PayType, Platform = Enums.Platform.拳探, PreferentialAmount = qtOrder.PreferentialAmount, //PurchaseRemark = String.Empty, ShopId = shopId, SellerPreferentialAmount = qtOrder.SellerPreferentialAmount, StartTime = qtOrder.StartTime, VenderRemark = qtOrder.VenderRemark, //WaybillNo = qtOrder.DeliveryResponse.WayBillNo, OrderState = orderState, ClientOrderId = qtOrder.ClientOrderId, BuyerAccount = qtOrder.UserAccount, InPackAmount = qtOrder.PackAmount, PayTime = qtOrder.PayTime, }; JArray belongSkus = null; if (!string.IsNullOrEmpty(qtOrder.Extended)) { try { var jobject = JObject.Parse(qtOrder.Extended); //dbOrder.SourceSku = jobject.Value("SourceSku"); dbOrder.SourceShopName = jobject.Value("SourceShopName"); if (jobject.ContainsKey("BelongSkus")) belongSkus = jobject["BelongSkus"] as JArray; if (jobject.ContainsKey("IntoStoreType")) dbOrder.IntoStoreType = (Enums.IntoStoreType?)jobject.Value("IntoStoreType"); } catch (Exception ex) { } } if (!insertOrderList.Any(o => o.Id == dbOrder.Id)) insertOrderList.Add(dbOrder); //订单sku foreach (var qtOrderSku in qtOrder.OrderSkuList) { insertOrderSkuList.Add(new OrderSku() { //Id = idGenerator.NewLong(), Id = long.Parse(qtOrderSku.Id), CreateTime = DateTime.Now, SkuId = qtOrderSku.SkuId, ItemTotal = qtOrderSku.Quantity, Logo = qtOrderSku.SkuLogo, OrderId = qtOrder.OrderId, Price = qtOrderSku.SkuPrice, InitialPrice = qtOrderSku.SkuPrice, Title = qtOrderSku.SkuTitle, ShopId = shopId, ProductId = qtOrderSku.ProductId, BelongSkuId = belongSkus?.FirstOrDefault(j => j.Value("SkuId") == qtOrderSku.SkuId)?.Value("BelongSkuId") ?? string.Empty, InPackAmount = qtOrderSku.PackAmount, BuyerPayFreight = qtOrderSku.FreightAmount, IsNeedOptimization = 0, IsOptimizationCompleted = 0 }); } //收货人 insertOrderConsigneeList.Add(new OrderConsignee() { OrderId = qtOrder.OrderId, Address = qtOrder.Consignee.Address, City = qtOrder.Consignee.City, ContactName = qtOrder.Consignee.ContactName, County = qtOrder.Consignee.County, CreateTime = DateTime.Now, Mobile = qtOrder.Consignee.Mobile, Province = qtOrder.Consignee.Province, TelePhone = qtOrder.Consignee.Mobile, Town = qtOrder.Consignee.Town }); if (qtOrder.IsPay && !waitToCheckSkuSaleOrderList.Any(x => x.OrderId == qtOrder.OrderId)) waitToCheckSkuSaleOrderList.Add(qtOrder); } else { #region 订单状态脱离拳探 只处理付款和取消 Enums.OrderState? updateOrderState = null; if (orderState == Enums.OrderState.待付款 && dbOrder.OrderState != Enums.OrderState.待付款) { //dbOrder.OrderState = Enums.OrderState.待付款; updateOrderState = Enums.OrderState.待付款; } if (dbOrder.OrderState == Enums.OrderState.待付款 && orderState != Enums.OrderState.待付款 && orderState != Enums.OrderState.已取消) { updateOrderState = Enums.OrderState.等待采购; if (!waitToCheckSkuSaleOrderList.Any(x => x.OrderId == qtOrder.OrderId)) waitToCheckSkuSaleOrderList.Add(qtOrder); } if (dbOrder.OrderState != Enums.OrderState.已取消 && orderState == Enums.OrderState.已取消) { updateOrderState = Enums.OrderState.已取消; if (dbPurchaseTimeLimitTaskList.Any(t => t.OrderId == qtOrder.OrderId)) deleteTimeLimitTaskOrderIdList.Add(qtOrder.OrderId); foreach (var qtOrderSku in qtOrder.OrderSkuList) { if (!deductionSkuCountDictionary.ContainsKey(qtOrderSku.SkuId)) deductionSkuCountDictionary.Add(qtOrderSku.SkuId, 0); deductionSkuCountDictionary[qtOrderSku.SkuId] += qtOrderSku.Quantity; if (!deductionSpuCountDictionary.ContainsKey(qtOrderSku.ProductId)) deductionSpuCountDictionary.Add(qtOrderSku.ProductId, 0); deductionSpuCountDictionary[qtOrderSku.ProductId] += qtOrderSku.Quantity; } } #endregion var updateModifyTime = dbOrder.ModifyTime != qtOrder.ModifyTime; var updateBuyerRemark = dbOrder.BuyerRemark != qtOrder.BuyerRemark; var updateVenderRemark = dbOrder.VenderRemark != qtOrder.VenderRemark; var updateBuyerAccount = dbOrder.BuyerAccount != qtOrder.UserAccount; var updateOrderSn = dbOrder.OrderSn != qtOrder.OrderSn; var updatePayTime = dbOrder.PayTime != qtOrder.PayTime; if (updateOrderState != null || updateModifyTime || updateBuyerRemark || updateVenderRemark || updateBuyerAccount || updateOrderSn || updatePayTime) { var update = fsql.Update(dbOrder.Id).SetIf(updateOrderState != null, o => o.OrderState, updateOrderState) .SetIf(updateModifyTime, o => o.ModifyTime, qtOrder.ModifyTime) .SetIf(updateBuyerRemark, o => o.BuyerRemark, qtOrder.BuyerRemark) .SetIf(updateVenderRemark, o => o.VenderRemark, qtOrder.VenderRemark) .SetIf(updateBuyerAccount, o => o.BuyerAccount, qtOrder.UserAccount) .SetIf(updateOrderSn, o => o.OrderSn, qtOrder.OrderSn) .SetIf(updatePayTime, o => o.PayTime, qtOrder.PayTime); updateOrderList.Add(update); } } } #endregion #region 统计销量 foreach (var qtOrder in waitToCheckSkuSaleOrderList) { foreach (var qtOrderSku in qtOrder.OrderSkuList) { #region 统计sku销量 { var skuTotalSaleInfo = dbSkuTotalSaleInfoList.FirstOrDefault(s => s.SkuId == qtOrderSku.SkuId); if (skuTotalSaleInfo == null) { skuTotalSaleInfo = insertSkuTotalSaleInfoList.FirstOrDefault(s => s.SkuId == qtOrderSku.SkuId); if (skuTotalSaleInfo == null) { skuTotalSaleInfo = new SkuTotalSaleInfo() { SkuId = qtOrderSku.SkuId, CreateTime = DateTime.Now, IsEnabled = true, ItemCount = 0, ProductId = qtOrderSku.ProductId, ShopId = shopId, UpdateTime = DateTime.Now }; insertSkuTotalSaleInfoList.Add(skuTotalSaleInfo); } } else if (!updateSkuTotalSaleInfoList.Any(s => s.SkuId == qtOrderSku.SkuId)) { updateSkuTotalSaleInfoList.Add(skuTotalSaleInfo); } skuTotalSaleInfo.ItemCount += qtOrderSku.Quantity; } #endregion #region 统计spu销量 { var spuTotalSaleInfo = dbSpuTotalSaleInfoList.FirstOrDefault(s => s.ProductId == qtOrderSku.ProductId); if (spuTotalSaleInfo == null) { spuTotalSaleInfo = insertSpuTotalSaleInfoList.FirstOrDefault(s => s.ProductId == qtOrderSku.ProductId); if (spuTotalSaleInfo == null) { spuTotalSaleInfo = new SpuTotalSaleInfo() { CreateTime = DateTime.Now, IsEnabled = true, ItemCount = 0, ProductId = qtOrderSku.ProductId, ShopId = shopId, UpdateTime = DateTime.Now, LastOptimizationItemCount = 0 }; insertSpuTotalSaleInfoList.Add(spuTotalSaleInfo); } } else if (!updateSpuTotalSaleInfoList.Any(s => s.ProductId == qtOrderSku.ProductId)) { updateSpuTotalSaleInfoList.Add(spuTotalSaleInfo); } spuTotalSaleInfo.ItemCount += qtOrderSku.Quantity; } #endregion } } #endregion #region 检查待议价任务 { if (waitToCheckSkuSaleOrderList.Count() > 0) { var optimizationSpuSaleList = dbSpuTotalSaleInfoList.Union(insertSpuTotalSaleInfoList).Where(s => { //if (insertSpuTotalSaleInfoList.Any(x => x.ProductId == s.ProductId)) // return true; //首次触发 //if (s.LastOptimizationItemCount == 0 && s.ItemCount >= 20) // return true; //销量大于20 //if (s.LastOptimizationItemCount != 0 && s.ItemCount * 1.0 / s.LastOptimizationItemCount >= 2) // return true; //return false; return GetOptimizationReason(s) != null; }); if (optimizationSpuSaleList.Count() > 0) { foreach (var spuSale in optimizationSpuSaleList) { var orderList = waitToCheckSkuSaleOrderList.Where(o => o.OrderSkuList.Any(osku => osku.ProductId == spuSale.ProductId)).ToList(); foreach (var o in orderList) { foreach (var osku in o.OrderSkuList) { if (osku.ProductId != spuSale.ProductId) continue; var triggerOptimizationReason = GetOptimizationReason(spuSale); #region 更新sku优化标记 var oskuId = long.Parse(osku.Id); var insertOrderSku = insertOrderSkuList.FirstOrDefault(s => s.Id == oskuId); if (insertOrderSku != null) { insertOrderSku.IsNeedOptimization = 1; insertOrderSku.TriggerOptimizationReason = triggerOptimizationReason; } else { //updateOrderSkuIdList_OptimizationFlag.Add(oskuId); if (!updateOSkuOptimizationFlagByReasonGroups.TryGetValue(triggerOptimizationReason.Value, out var updateOSkuOptimizationFlagByReasonList)) { updateOSkuOptimizationFlagByReasonList = new List(); updateOSkuOptimizationFlagByReasonGroups.Add(triggerOptimizationReason.Value, updateOSkuOptimizationFlagByReasonList); } updateOSkuOptimizationFlagByReasonList.Add(oskuId); } #endregion #region 创建待议价任务 if (!dbOptimizationLimitTaskList.Any(t => t.OrderId == o.OrderId && t.SkuId == osku.SkuId)) { //判断sku是否首次采购 var isFirst = !dbSkuTotalSaleInfoList.Any(s => s.SkuId == osku.SkuId); insertTimeLimitTaskList.Add(new TimeLimitTask() { Id = idGenerator.NewLong(), CreateTme = DateTime.Now, //ExpirationTime = DateTime.Now.AddDays(isFirst ? 2 : 1), ExpirationTime = timeLimitRules.CalculateExpirationTime(Enums.TimeLimitTaskType.待议价任务, DateTime.Now.AddDays(isFirst ? 1 : 0)), OrderId = o.OrderId, OrderSn = o.OrderSn, ShopId = shopId, SkuId = osku.SkuId, TaskType = Enums.TimeLimitTaskType.待议价任务 }); } #endregion } } } } } } #endregion #region 检查限时采购任务 CheckPurchaseTimeLimitTask(shopId, qtOrderList.Items, dbPurchaseTimeLimitTaskList, insertTimeLimitTaskList); #endregion fsql.Transaction(() => { if (insertOrderList.Count > 0) fsql.Insert(insertOrderList).ExecuteAffrows(); if (insertOrderSkuList.Count() > 0) fsql.Insert(insertOrderSkuList).ExecuteAffrows(); if (insertOrderConsigneeList.Count() > 0) fsql.Insert(insertOrderConsigneeList).ExecuteAffrows(); if (insertTimeLimitTaskList.Count() > 0) fsql.Insert(insertTimeLimitTaskList).ExecuteAffrows(); if (updateOrderList.Count() > 0) foreach (var update in updateOrderList) update.ExecuteAffrows(); if (deleteTimeLimitTaskOrderIdList.Count() > 0) fsql.Delete().Where(t => deleteTimeLimitTaskOrderIdList.Contains(t.OrderId)).ExecuteAffrows(); if (insertSkuTotalSaleInfoList.Count() > 0) fsql.Insert(insertSkuTotalSaleInfoList).ExecuteAffrows(); if (updateSkuTotalSaleInfoList.Count() > 0) { foreach (var item in updateSkuTotalSaleInfoList) fsql.Update(item.SkuId).Set(s => s.ItemCount, item.ItemCount) .Set(s => s.UpdateTime, DateTime.Now) .ExecuteAffrows(); } if (insertSpuTotalSaleInfoList.Count() > 0) fsql.Insert(insertSpuTotalSaleInfoList).ExecuteAffrows(); if (updateSpuTotalSaleInfoList.Count() > 0) { foreach (var item in updateSpuTotalSaleInfoList) fsql.Update(item.ProductId).Set(s => s.ItemCount, item.ItemCount) .Set(s => s.UpdateTime, DateTime.Now) .ExecuteAffrows(); } //if (updateOrderSkuIdList_OptimizationFlag.Count() > 0) // fsql.Update(updateOrderSkuIdList_OptimizationFlag).Set(osku => osku.IsNeedOptimization, 1).ExecuteAffrows(); if (updateOSkuOptimizationFlagByReasonGroups.Keys.Count() > 0) { foreach (var triggerOptimizationReason in updateOSkuOptimizationFlagByReasonGroups.Keys) { var updateOSkuListOptimizationFlagList = updateOSkuOptimizationFlagByReasonGroups[triggerOptimizationReason]; if (updateOSkuListOptimizationFlagList != null && updateOSkuListOptimizationFlagList.Count > 0) { fsql.Update(updateOSkuListOptimizationFlagList).Set(osku => osku.IsNeedOptimization, 1) .Set(osku => osku.TriggerOptimizationReason, triggerOptimizationReason) .ExecuteAffrows(); } } } foreach (var key in deductionSkuCountDictionary.Keys) fsql.Update(key).Set(s => s.ItemCount - deductionSkuCountDictionary[key]).ExecuteAffrows(); foreach (var key in deductionSpuCountDictionary.Keys) fsql.Update(key).Set(s => s.ItemCount - deductionSpuCountDictionary[key]).ExecuteAffrows(); }); } catch (Exception ex) { nLogManager.GetLogger(loggerName).Error(ex); } } /// /// 检查限时采购任务 /// /// /// /// /// private void CheckPurchaseTimeLimitTask(long shopId, IList orderList, IList dbTimeLimits, List insertTimeLimitTasks) { foreach (var order in orderList) { if (!order.IsPay || order.PayTime == null || order.OrderState == "-1") continue; var waitInserTimeLimitTasks = order.OrderSkuList.Where(osku => !dbTimeLimits.Any(x => x.OrderId == order.OrderId && x.SkuId == osku.SkuId)) .Select(osku => new TimeLimitTask() { Id = idGenerator.NewLong(), CreateTme = DateTime.Now, OrderId = order.OrderId, OrderSn = order.OrderSn, SkuId = osku.SkuId, TaskType = Enums.TimeLimitTaskType.采购任务, ShopId = shopId, ExpirationTime = timeLimitRules.CalculateExpirationTime(Enums.TimeLimitTaskType.采购任务, order.PayTime.Value), PayTime = order.PayTime }).ToList(); if (waitInserTimeLimitTasks != null && waitInserTimeLimitTasks.Count() > 0) insertTimeLimitTasks.AddRange(waitInserTimeLimitTasks); } } /// /// 计算采购限时任务的到期时间 /// /// 付款时间 /// private DateTime CalculationPurcashTimeLimitTaskExpirationTime(DateTime payTime) { var addDays = 0; if (payTime.DayOfWeek == DayOfWeek.Sunday || payTime.DayOfWeek == DayOfWeek.Monday || payTime.DayOfWeek == DayOfWeek.Tuesday || payTime.DayOfWeek == DayOfWeek.Wednesday || payTime.DayOfWeek == DayOfWeek.Thursday || payTime.DayOfWeek == DayOfWeek.Friday) { if (payTime.Hour >= 0 && payTime.Hour < 15) addDays = 0; //当日 else addDays = payTime.DayOfWeek == DayOfWeek.Friday ? 2 : 1; //次日,星期五是后天 } else if (payTime.DayOfWeek == DayOfWeek.Saturday) addDays = 1; return payTime.Date.AddDays(addDays).AddHours(16); } private Enums.OrderState? ConvertQuanTanOrderState(string qtOrderState, bool isPay, bool isPurchased) { /* -1、已取消; 0、待发货; 1、待收货; 2、待评价; 3、已完成; */ if (qtOrderState == "-1") return Enums.OrderState.已取消; if (!isPay) return Enums.OrderState.待付款; if (qtOrderState == "0") { if (!isPurchased) return Enums.OrderState.等待采购; return Enums.OrderState.待发货; } if (qtOrderState == "1") return Enums.OrderState.待收货; if (qtOrderState == "2") return Enums.OrderState.待收货; if (qtOrderState == "3") return Enums.OrderState.已完成; return null; } public Enums.TriggerOptimizationReason? GetOptimizationReason(SpuTotalSaleInfo s) { if (s.IsFirstPurchaseCompleted == false) return Enums.TriggerOptimizationReason.首次采购; if (s.IsFirstPurchaseCompleted == true && s.IsFirstOptimizationCompleted == false && s.ItemCount - s.FirstPurchaseCompletedItemCount >= 20) return Enums.TriggerOptimizationReason.首次优化; if (s.IsFirstOptimizationCompleted == true && s.LastOptimizationItemCount != 0 && s.ItemCount * 1.0 / s.LastOptimizationItemCount >= 2) return Enums.TriggerOptimizationReason.再次优化; return null; } } }