using AllBase; using AllBase.Extension; using NaiBa.Util.Extension; using AllBase.Helper; using AllBase.Model.Config; using AllBase.Model.DBModel; using AllBase.Model.Param.WXParam; using AllBase.Model.Result; using AllBase.Model.Result.PDDResult; using AllBase.Model.Result.WXResult; using MAX.Core.Helpers; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Store.Product.Models.PublishParameters.Wx; using Store.Product.Publish; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Work; namespace Store.Product.Publish.Steps.Wx; /// /// 由 WXDBProdUploadForm.UploadProduct 的“初始化微信小店商品参数”区段迁移。 /// TODO(迁移): 原区段中的 TEMUKJD/WXUpload/窗体服务引用需按 Store.Product 运行时适配逐项核对。 /// public sealed class InitializeProductDataStep : WxProductPublishStepBase { public override string Description => "初始化微信小店商品参数"; protected override Task ExecuteProvider(WXPublishContext context, CancellationToken cancellationToken) { context.Parameters.ProdJObject = new JObject(); try { context.Parameters.ProdJObject = JObject.Parse(context.Product.ProductJson); var lstTitleReplaceText = new List(); if (!context.Parameters.FilterWords.IsNullOrEmpty()) lstTitleReplaceText.AddRange(context.Parameters.FilterWords.Split(new string[] { ",", ",", " ", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries)); // 过滤标题敏感词 if (lstTitleReplaceText.Count > 0) { if (context.Parameters.IsSkipHasFilterWordsProd) { if (lstTitleReplaceText.Any(t => context.Product.Title.Contains(t))) throw new Exception("命中敏感词"); var goods_name = context.Parameters.ProdJObject["detail"]["goods_name"].ParseToString(); if (lstTitleReplaceText.Any(t => goods_name.Contains(t))) throw new Exception("命中敏感词"); var tiny_name = context.Parameters.ProdJObject["detail"]["tiny_name"].ParseToString(); if (lstTitleReplaceText.Any(t => tiny_name.Contains(t))) throw new Exception("命中敏感词"); var goods_desc = context.Parameters.ProdJObject["detail"]["goods_desc"].ParseToString(); if (lstTitleReplaceText.Any(t => goods_desc.Contains(t))) throw new Exception("命中敏感词"); var share_desc = context.Parameters.ProdJObject["detail"]["share_desc"].ParseToString(); if (lstTitleReplaceText.Any(t => share_desc.Contains(t))) throw new Exception("命中敏感词"); } else { foreach (var txt in lstTitleReplaceText) { context.Product.Title = context.Product.Title.Replace(txt, ""); } var goods_name = context.Parameters.ProdJObject["detail"]["goods_name"].ParseToString(); foreach (var txt in lstTitleReplaceText) { goods_name = goods_name.Replace(txt, ""); } context.Parameters.ProdJObject["detail"]["goods_name"] = goods_name; var tiny_name = context.Parameters.ProdJObject["detail"]["tiny_name"].ParseToString(); foreach (var txt in lstTitleReplaceText) { tiny_name = tiny_name.Replace(txt, ""); } context.Parameters.ProdJObject["detail"]["tiny_name"] = tiny_name; var goods_desc = context.Parameters.ProdJObject["detail"]["goods_desc"].ParseToString(); foreach (var txt in lstTitleReplaceText) { goods_desc = goods_desc.Replace(txt, ""); } context.Parameters.ProdJObject["detail"]["goods_desc"] = goods_desc; var share_desc = context.Parameters.ProdJObject["detail"]["share_desc"].ParseToString(); foreach (var txt in lstTitleReplaceText) { share_desc = share_desc.Replace(txt, ""); } context.Parameters.ProdJObject["detail"]["share_desc"] = share_desc; } } // 过滤标题特殊字符 if (context.Parameters.IsRemoveSpecialChar) { var chLst = new List { ']', '】', ')', ')', '}', }; foreach (var ch in chLst) { if (context.Product.Title.Contains(ch) && context.Product.Title.IndexOf(ch) < context.Product.Title.Length / 2 && context.Product.Title.Length > 10) context.Product.Title = context.Product.Title.Substring(context.Product.Title.IndexOf(ch)).Trim(ch); var goods_name = context.Parameters.ProdJObject["detail"]["goods_name"].ParseToString(); if (goods_name.Contains(ch) && goods_name.IndexOf(ch) < goods_name.Length / 2 && goods_name.Length > 10) context.Parameters.ProdJObject["detail"]["goods_name"] = goods_name.Substring(goods_name.IndexOf(ch)).Trim(ch); } } // 替换货号 if (!string.IsNullOrEmpty(context.Product.ExtCode)) context.Parameters.ProdJObject["detail"]["out_goods_sn"] = context.Product.ExtCode; // 替换编辑过的sku if (!string.IsNullOrEmpty(context.Product.SkuEditJson)) context.Parameters.ProdJObject["detail"]["sku"] = JArray.Parse(JsonHelper.SerializeObject(JsonHelper.DeserializeJsonToList(context.Product.SkuEditJson))); // 过滤sku敏感词 if (lstTitleReplaceText.Count > 0) { var skuJArr = context.Parameters.ProdJObject["detail"]["sku"] as JArray; try { foreach (var skuJObj in skuJArr) { var specJArr = skuJObj["spec"] as JArray; for (int i = 0; i < specJArr.Count; i++) { foreach (var txt in lstTitleReplaceText) { specJArr[i]["spec_name"] = specJArr[i]["spec_name"].ParseToString().Replace(txt, ""); } } } } catch (Exception ex) { throw new Exception("商品数据初始化失败" + ex.Message); } } // 同颜色规格向上浮动同价格 if (context.Parameters.SameSpecSamePriceUp) { var priceTextLst = context.Product.PriceText.Split('-'); if (priceTextLst.Length != 2 || priceTextLst[0] != priceTextLst[1]) { Dictionary specPriceDic = new Dictionary(); Dictionary specMultiPriceDic = new Dictionary(); var skuJArr = context.Parameters.ProdJObject["detail"]["sku"] as JArray; try { // 计算主spec的最高价 foreach (var skuJObj in skuJArr) { var specJArr = skuJObj["spec"] as JArray; if (!specPriceDic.ContainsKey(specJArr[0]["spec_name"].ParseToString()) || skuJObj["price"].ParseToInt() > specPriceDic[specJArr[0]["spec_name"].ParseToString()]) { specPriceDic[specJArr[0]["spec_name"].ParseToString()] = skuJObj["price"].ParseToInt(); } if (!specMultiPriceDic.ContainsKey(specJArr[0]["spec_name"].ParseToString()) || skuJObj["multi_price"].ParseToInt() > specMultiPriceDic[specJArr[0]["spec_name"].ParseToString()]) { specMultiPriceDic[specJArr[0]["spec_name"].ParseToString()] = skuJObj["multi_price"].ParseToInt(); } } // 统一按最高价设置 foreach (var skuJObj in skuJArr) { var specJArr = skuJObj["spec"] as JArray; skuJObj["price"] = specPriceDic[specJArr[0]["spec_name"].ParseToString()]; skuJObj["multi_price"] = specMultiPriceDic[specJArr[0]["spec_name"].ParseToString()]; } } catch (Exception ex) { throw new Exception("商品数据初始化失败" + ex.Message); } } } // 同颜色规格向下浮动同价格 if (context.Parameters.SameSpecSamePriceDown) { var priceTextLst = context.Product.PriceText.Split('-'); if (priceTextLst.Length != 2 || priceTextLst[0] != priceTextLst[1]) { Dictionary specPriceDic = new Dictionary(); Dictionary specMultiPriceDic = new Dictionary(); var skuJArr = context.Parameters.ProdJObject["detail"]["sku"] as JArray; try { // 计算主spec的最低价 foreach (var skuJObj in skuJArr) { var specJArr = skuJObj["spec"] as JArray; if (!specPriceDic.ContainsKey(specJArr[0]["spec_name"].ParseToString()) || skuJObj["price"].ParseToInt() < specPriceDic[specJArr[0]["spec_name"].ParseToString()]) { specPriceDic[specJArr[0]["spec_name"].ParseToString()] = skuJObj["price"].ParseToInt(); } if (!specMultiPriceDic.ContainsKey(specJArr[0]["spec_name"].ParseToString()) || skuJObj["multi_price"].ParseToInt() < specMultiPriceDic[specJArr[0]["spec_name"].ParseToString()]) { specMultiPriceDic[specJArr[0]["spec_name"].ParseToString()] = skuJObj["multi_price"].ParseToInt(); } } // 统一按最低价设置 foreach (var skuJObj in skuJArr) { var specJArr = skuJObj["spec"] as JArray; skuJObj["price"] = specPriceDic[specJArr[0]["spec_name"].ParseToString()]; skuJObj["multi_price"] = specMultiPriceDic[specJArr[0]["spec_name"].ParseToString()]; } } catch (Exception ex) { throw new Exception("商品数据初始化失败" + ex.Message); } } } // 只保留最高价 if (context.Parameters.OnlyHighestPriceSku) { int price = 0; var skuJArr = context.Parameters.ProdJObject["detail"]["sku"] as JArray; try { // 计算主spec的最高价 foreach (var skuJObj in skuJArr) { if (price < skuJObj["multi_price"].ParseToInt()) price = skuJObj["multi_price"].ParseToInt(); } var product_json_tmp = JsonHelper.SerializeObject(context.Parameters.ProdJObject); // 移除第一组所有sku skuJArr.RemoveAll(); // 序列化第二组,从组中挑选符合价格条件的sku往第一组内填写 var prodJObj2 = JObject.Parse(product_json_tmp); var skuJArr2 = prodJObj2["detail"]["sku"] as JArray; foreach (var skuJObj2 in skuJArr2) { if (skuJObj2["multi_price"].ParseToInt() >= price) skuJArr.Add(skuJObj2); } if (skuJArr.Count == 0) { throw new Exception("商品sku差价不满足上货条件,跳过"); } } catch (Exception ex) { throw new Exception("商品数据初始化失败" + ex.Message); } } // 只保留最低价 if (context.Parameters.OnlyLowestPriceSku) { int price = 99999999; var skuJArr = context.Parameters.ProdJObject["detail"]["sku"] as JArray; try { // 计算主spec的最低价 foreach (var skuJObj in skuJArr) { if (price > skuJObj["multi_price"].ParseToInt()) price = skuJObj["multi_price"].ParseToInt(); } var product_json_tmp = JsonHelper.SerializeObject(context.Parameters.ProdJObject); // 移除第一组所有sku skuJArr.RemoveAll(); // 序列化第二组,从组中挑选符合价格条件的sku往第一组内填写 var prodJObj2 = JObject.Parse(product_json_tmp); var skuJArr2 = prodJObj2["detail"]["sku"] as JArray; foreach (var skuJObj2 in skuJArr2) { if (skuJObj2["multi_price"].ParseToInt() <= price) skuJArr.Add(skuJObj2); } if (skuJArr.Count == 0) { throw new Exception("商品sku差价不满足上货条件,跳过"); } } catch (Exception ex) { throw new Exception("商品数据初始化失败" + ex.Message); } } // 过滤低价sku,如果所有sku都不达标,跳过商品 if (context.Parameters.SkuMinPrice > 0) { var product_json_tmp = JsonHelper.SerializeObject(context.Parameters.ProdJObject); // 移除第一组所有sku var skuJArr = context.Parameters.ProdJObject["detail"]["sku"] as JArray; skuJArr.RemoveAll(); // 序列化第二组,从组中挑选符合价格条件的sku往第一组内填写 var prodJObj2 = JObject.Parse(product_json_tmp); var skuJArr2 = prodJObj2["detail"]["sku"] as JArray; foreach (var skuJObj2 in skuJArr2) { var limitMinPrice = context.Parameters.SkuMinPrice * 100; // 供应商价加价10%(最低1元)赚取差价 先加价后过滤,过滤条件也要相应增加10% //if (context.Product.ProductGetTypeText == "厂商直采") // limitPrice += Math.Max(100m, limitPrice * 0.1m); if (skuJObj2["multi_price"].ParseToInt() >= limitMinPrice) skuJArr.Add(skuJObj2); } if (skuJArr.Count == 0) { throw new Exception("商品sku价格不满足上货条件,跳过"); } } // 过滤高价sku,如果所有sku都不达标,跳过商品 if (context.Parameters.SkuMaxPrice < int.MaxValue) { var product_json_tmp = JsonHelper.SerializeObject(context.Parameters.ProdJObject); // 移除第一组所有sku var skuJArr = context.Parameters.ProdJObject["detail"]["sku"] as JArray; skuJArr.RemoveAll(); // 序列化第二组,从组中挑选符合价格条件的sku往第一组内填写 var prodJObj2 = JObject.Parse(product_json_tmp); var skuJArr2 = prodJObj2["detail"]["sku"] as JArray; foreach (var skuJObj2 in skuJArr2) { var limitMaxPrice = context.Parameters.SkuMaxPrice * 100; // 供应商价加价10%(最低1元)赚取差价 先加价后过滤,过滤条件也要相应增加10% //if (context.Product.ProductGetTypeText == "厂商直采") // limitPrice += Math.Max(100m, limitPrice * 0.1m); if (skuJObj2["multi_price"].ParseToInt() <= limitMaxPrice) skuJArr.Add(skuJObj2); } if (skuJArr.Count == 0) { throw new Exception("商品sku价格不满足上货条件,跳过"); } } context.Product.ProductJson = JsonHelper.SerializeObject(context.Parameters.ProdJObject); } catch (Exception ex) { throw new Exception("商品数据初始化失败" + ex.Message); } return Task.CompletedTask; } }