diff --git a/AllBase/AllBase.csproj b/AllBase/AllBase.csproj
index a2fb324..b56fb3c 100644
--- a/AllBase/AllBase.csproj
+++ b/AllBase/AllBase.csproj
@@ -233,6 +233,7 @@
+
diff --git a/AllBase/Model/Result/PDDResult/PDDFrontProductInfo5.cs b/AllBase/Model/Result/PDDResult/PDDFrontProductInfo5.cs
new file mode 100644
index 0000000..56d527c
--- /dev/null
+++ b/AllBase/Model/Result/PDDResult/PDDFrontProductInfo5.cs
@@ -0,0 +1,134 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data.SqlTypes;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace AllBase.Model.Result.PDDResult
+{
+ public class PDDFrontProductInfo5
+ {
+ [Description("商品编号")]
+ public long GoodsId { get; set; }
+
+ [Description("商品链接")]
+ public string GoodsUrl { get; set; }
+ [Description("品牌Id")]
+ public long BrandId { get; set; }
+
+ [Description("标题")]
+ public string Title { get; set; }
+
+ [Description("描述")]
+ public string Description { get; set; }
+
+ [Description("视频链接")]
+ public string VideoUrl { get; set; }
+
+ [Description("类目")]
+ public int CategoryId { get; set; }
+ [Description("所有类目")]
+ public List CategoryPath { get; set; }
+
+ [Description("商铺Id")]
+ public int MallId { get; set; }
+ [Description("商铺Name")]
+ public string MallName { get; set; }
+
+ [Description("属性")]
+ public List Propertys { get; set; }
+ [Description("缩略图")]
+ public string ThumbUrl { get; set; }
+ [Description("主图")]
+ public List MainImages { get; set; }
+
+ [Description("详情图")]
+ public List DetailImages { get; set; }
+ [Description("视频")]
+ public List Videos { get; set; }
+
+ [Description("规格")]
+ public List Specs { get; set; }
+
+ [Description("价格与库存")]
+ public List Skus { get; set; }
+ [Description("价格")]
+ public decimal Price { get; set; }
+ [Description("最低价")]
+ public decimal MinPrice
+ {
+ get
+ {
+ return Skus?.Min(a => a.Price) ?? 0;
+ }
+ }
+ [Description("最高价")]
+ public decimal MaxPrice
+ {
+ get
+ {
+ return Skus?.Max(a => a.Price) ?? 0;
+ }
+ }
+ }
+ ///
+ /// 属性
+ ///
+ public class Property
+ {
+ [Description("属性ID")]
+ public string Id { get; set; }
+
+ [Description("属性Key")]
+ public string Key { get; set; }
+
+ [Description("属性值")]
+ public string Value { get; set; }
+ }
+
+ ///
+ /// 规格
+ ///
+ public class SpecItem
+ {
+ [Description("规格KeyID")]
+ public long SpecKeyId { get; set; }
+
+ [Description("规格键名")]
+ public string SpecKey { get; set; }
+
+ [Description("规格值")]
+ public string SpecValue { get; set; }
+ [Description("规格值Id")]
+ public long SpecValueId { get; set; }
+ }
+ ///
+ /// SKU
+ ///
+ public class SkuItem
+ {
+ [Description("SKU编码")]
+ public string SkuId { get; set; }
+ [Description("规格值组合")]
+ public string Spec { get; set; }
+
+ [Description("价格")]
+ public decimal Price { get; set; }
+
+ [Description("原价")]
+ public string OriginalPrice { get; set; }
+
+ [Description("库存")]
+ public int Stock { get; set; }
+
+ [Description("规格图")]
+ public string SpecImage { get; set; }
+ }
+
+
+
+}
diff --git a/TEMUKJD/BLL/ImportConverters/ConvertToPddFactory.cs b/TEMUKJD/BLL/ImportConverters/ConvertToPddFactory.cs
new file mode 100644
index 0000000..ddff516
--- /dev/null
+++ b/TEMUKJD/BLL/ImportConverters/ConvertToPddFactory.cs
@@ -0,0 +1,38 @@
+using AllBase.Model.Result.PDDResult;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TemuKJD.BLL.ImportConverters;
+
+namespace TemuKJD.BLL.ImportConverts
+{
+ public class ConverterToPddFactory
+ {
+ private static List _converters = new List
+ {
+ new ConverterToPddV5(),
+ };
+ public static PDDFrontProductInfo5 Convert(string data)
+ {
+
+ foreach (var item in _converters)
+ {
+ try
+ {
+ if (item.IsMatch(data))
+ {
+ return item.Convert();
+ }
+ }
+ catch (Exception ex)
+ {
+ throw ex;
+ }
+ }
+ return null;
+
+ }
+ }
+}
diff --git a/TEMUKJD/BLL/ImportConverters/ConverterToPddV5.cs b/TEMUKJD/BLL/ImportConverters/ConverterToPddV5.cs
new file mode 100644
index 0000000..3bac6b4
--- /dev/null
+++ b/TEMUKJD/BLL/ImportConverters/ConverterToPddV5.cs
@@ -0,0 +1,315 @@
+using AllBase.Model.Result.PDDResult;
+using CefSharp.DevTools.CSS;
+using NaiBa.Util.Extension;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TemuKJD.BLL.ImportConverters;
+using Work.GoodDetail;
+
+namespace TemuKJD.BLL.ImportConverts
+{
+ internal class ConverterToPddV5 : GoodsConverterBase
+ {
+ private JObject jsonRoot;
+
+
+ public override string ConverterName => "To PDD V5";
+
+ public override PlatformType Platform => PlatformType.PDD;
+
+ protected override bool IsMatchProvider()
+ {
+ try
+ {
+ jsonRoot = JsonConvert.DeserializeObject(RawData);
+ return jsonRoot.SelectToken("$.store.initDataObj.goods") != null;
+ }
+ catch { return false; }
+ }
+
+ protected override PDDFrontProductInfo5 ConverterProvider()
+ {
+ var goodsToken = jsonRoot.SelectToken("$.store.initDataObj.goods");
+ var product = new PDDFrontProductInfo5();
+
+ // 逐个属性赋值,方便打断点调试
+ product.GoodsId = goodsToken["goodsID"].Value();
+
+ product.GoodsUrl = "";
+
+ product.BrandId = goodsToken["brandId"].ParseToLong();
+
+ product.Title = goodsToken["goodsName"]?.Value();
+
+ product.Description = goodsToken["short_name"]?.Value() ?? "";
+
+ product.ThumbUrl = goodsToken["thumbUrl"]?.Value() ?? "";
+
+ product.CategoryId = goodsToken["catID"]?.Value() ?? 0;
+
+ product.CategoryPath = GetCategoryPath(goodsToken);
+
+ product.MallId = goodsToken["mallID"]?.Value() ?? 0;
+
+ product.Price = goodsToken["linePrice"]?.Value() ?? 0;
+
+ product.Propertys = GetProperties(goodsToken);
+
+ product.MainImages = GetMainImages(goodsToken);
+
+ product.DetailImages = GetDetailImages(goodsToken);
+
+ product.Videos = GetVideos(goodsToken);
+
+ product.Specs = GetSpecs(goodsToken);
+
+ product.Skus = GetSkus(goodsToken);
+
+ return product;
+ }
+
+ ///
+ /// 获取类目路径
+ ///
+ private List GetCategoryPath(JToken goods)
+ {
+ var result = new List();
+
+ // JSON 中有 catID1 ~ catID4
+ for (int i = 1; i <= 4; i++)
+ {
+ var token = goods[$"catID{i}"];
+
+ if (token != null && token.Type != JTokenType.Null)
+ {
+ var value = token.Value();
+
+ if (value > 0)
+ result.Add(value);
+ }
+ }
+
+ // 如果没有,则至少加入当前类目
+ if (result.Count == 0)
+ {
+ var categoryId = goods["catID"]?.Value() ?? 0;
+
+ if (categoryId > 0)
+ result.Add(categoryId);
+ }
+
+ return result;
+ }
+ ///
+ /// 商品属性
+ ///
+ private List GetProperties(JToken goods)
+ {
+ var result = new List();
+
+ var propertyArray = goods["goodsProperty"] as JArray;
+
+ if (propertyArray == null)
+ return result;
+
+ foreach (var item in propertyArray)
+ {
+ var key = item["key"]?.Value();
+
+ var values = item["values"] as JArray;
+
+ result.Add(new Property
+ {
+ Key = key ?? "",
+ Value = string.Join(",", values?.Select(a => a))
+ });
+ }
+
+ return result;
+ }
+ ///
+ /// 主图
+ ///
+ private List GetMainImages(JToken goods)
+ {
+ var result = new List();
+
+ var images = goods["topGallery"] as JArray;
+
+ if (images != null)
+ {
+ foreach (var item in images)
+ {
+ var url = item["url"]?.Value();
+
+ if (!string.IsNullOrEmpty(url))
+ result.Add(url);
+ }
+ return result;
+ }
+
+ images = goods["viewImageData"] as JArray;
+ if (images != null)
+ {
+ foreach (var item in images)
+ {
+ var url = item.ToString();
+
+ if (!string.IsNullOrEmpty(url))
+ result.Add(url);
+ }
+ return result;
+ }
+ return result;
+ }
+ ///
+ /// 详情图
+ ///
+ private List GetDetailImages(JToken goods)
+ {
+ var result = new List();
+
+ var images = goods["detailGallery"] as JArray;
+
+ if (images == null)
+ return result;
+
+ foreach (var item in images)
+ {
+ var url = item["url"]?.Value();
+
+ if (!string.IsNullOrEmpty(url))
+ result.Add(url);
+ }
+
+ return result;
+ }
+ ///
+ /// 商品视频
+ ///
+ private List GetVideos(JToken goods)
+ {
+ var result = new List();
+
+ var videos = goods["videoGallery"] as JArray;
+
+ if (videos == null)
+ return result;
+
+ foreach (var item in videos)
+ {
+ var url =
+ item["videoUrl"]?.Value() ??
+ item["url"]?.Value();
+
+ if (!string.IsNullOrEmpty(url))
+ result.Add(url);
+ }
+
+ return result;
+ }
+
+ ///
+ /// 获取规格
+ ///
+ private List GetSpecs(JToken goods)
+ {
+ var result = new List();
+
+ var skus = goods["skus"] as JArray;
+
+ if (skus == null)
+ return result;
+
+ foreach (var sku in skus)
+ {
+ var specs = sku["specs"] as JArray;
+
+ if (specs == null)
+ continue;
+
+ foreach (var spec in specs)
+ {
+ var specKey = spec["spec_key"]?.Value() ?? "";
+ var specValue = spec["spec_value"]?.Value() ?? "";
+ var specKeyId = spec["spec_key_id"]?.Value() ?? 0;
+ var specValueId = spec["spec_value_id"]?.Value() ?? 0;
+
+ // 去重
+ if (result.Any(x => x.SpecKey == specKey && x.SpecValue == specValue))
+ continue;
+
+ result.Add(new SpecItem
+ {
+ SpecKey = specKey,
+ SpecValue = specValue,
+ SpecKeyId = specKeyId,
+ SpecValueId = specValueId,
+ });
+ }
+ }
+
+ return result;
+ }
+ ///
+ /// SKU
+ ///
+ private List GetSkus(JToken goods)
+ {
+ var result = new List();
+
+ var skus = goods["skus"] as JArray;
+
+ if (skus == null)
+ return result;
+
+ foreach (var sku in skus)
+ {
+ var specs = sku["specs"] as JArray;
+
+ var specValues = new List();
+
+ if (specs != null)
+ {
+ foreach (var spec in specs)
+ {
+ var key = spec["spec_key"]?.Value();
+ var value = spec["spec_value"]?.Value();
+
+ if (!string.IsNullOrEmpty(value))
+ specValues.Add($"{key}:{value}");
+ }
+ }
+
+ // 优先使用 normalPrice
+ var price = sku["normalPrice"].Value();
+
+ result.Add(new SkuItem
+ {
+ SkuId = sku["skuId"]?.Value() ?? "",
+
+ Spec = string.Join(";", specValues),
+
+ Price = price,
+
+ // oldGroupPrice 在这个 JSON 中是整数分价格,
+ // 这里暂时转成字符串
+ OriginalPrice = sku["oldGroupPrice"]?.Value() ?? "",
+
+ Stock = sku["quantity"]?.Value() ?? 0,
+
+ SpecImage = sku["thumbUrl"]?.Value() ?? "",
+ });
+ }
+
+ return result;
+ }
+
+
+ }
+}
diff --git a/TEMUKJD/BLL/ImportConverters/IGoodsConverter.cs b/TEMUKJD/BLL/ImportConverters/IGoodsConverter.cs
new file mode 100644
index 0000000..30fc6ce
--- /dev/null
+++ b/TEMUKJD/BLL/ImportConverters/IGoodsConverter.cs
@@ -0,0 +1,90 @@
+using AllBase.Model.Result.PDDResult;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TemuKJD.BLL.ImportConverters
+{
+ ///
+ /// 导入商品数据转换器
+ ///
+ public interface IGoodsConverter
+ {
+ ///
+ /// 原始数据
+ ///
+ string RawData { get; }
+
+ ///
+ /// 获取转换器名称
+ ///
+ string ConverterName { get; }
+
+ ///
+ /// 支持的平台类型
+ ///
+ PlatformType Platform { get; }
+ ///
+ /// 判断是否匹配当前转换器
+ ///
+ /// 是否匹配
+ bool IsMatch(string data);
+
+ ///
+ /// 转换为标准商品模型
+ ///
+ PDDFrontProductInfo5 Convert();
+ }
+
+ public abstract class GoodsConverterBase : IGoodsConverter
+ {
+ private bool _isMatch = false;
+ public string RawData { get; private set; }
+ public abstract string ConverterName { get; }
+ public abstract PlatformType Platform { get; }
+
+
+ public virtual bool IsMatch(string data)
+ {
+ _isMatch = true;
+ RawData = data;
+ return IsMatchProvider();
+ }
+ protected abstract bool IsMatchProvider();
+
+ ///
+ /// 带校验的转换(基类统一实现)
+ ///
+ public virtual PDDFrontProductInfo5 Convert()
+ {
+ if (_isMatch == false) throw new Exception("未校验数据");
+ try
+ {
+ JObject.Parse(RawData);
+ }
+ catch { throw new Exception("数据解析失败,不是有效的JSON格式"); }
+
+
+ var product = ConverterProvider();
+ if (product == null)
+ throw new Exception("转换失败");
+ // 基础校验
+ if (product.GoodsId == 0)
+ throw new Exception("商品ID不能为空");
+
+ if (product.Skus == null || !product.Skus.Any())
+ throw new Exception("至少需要一个SKU");
+
+ return product;
+ }
+
+ protected abstract PDDFrontProductInfo5 ConverterProvider();
+
+
+
+ }
+}
diff --git a/TEMUKJD/BLL/PDDProdFormConverter.cs b/TEMUKJD/BLL/PDDProdFormConverter.cs
index 0f5bfd9..0df3a65 100644
--- a/TEMUKJD/BLL/PDDProdFormConverter.cs
+++ b/TEMUKJD/BLL/PDDProdFormConverter.cs
@@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using TemuKJD.BLL.ImportConverts;
using Work;
namespace TemuKJD.BLL
@@ -721,7 +722,7 @@ namespace TemuKJD.BLL
shipment_limit_second_list = null,
sku69_code = "",
};
- if ((int)frontSku.sku_price.ParseToDecimal() > 0)
+ if ((int)frontSku.sku_price?.ParseToDecimal() > 0)
skuInfo.multi_price = Math.Min(skuInfo.multi_price.ParseToInt(), (int)frontSku.sku_price.ParseToDecimal());
//List specIds = frontSku.spec.Split(',').ToList();
@@ -1650,8 +1651,395 @@ namespace TemuKJD.BLL
}
+ ///
+ /// 外来格式V5
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public string PddFrontToPddBackConvertFactory(string outProdJson, bool UpdateOldData = true, string specialProdType = null, bool IsCollectAuthorityUser = false)
+ {
+ PDDFrontProductInfo5 frontProdInfo = null;
+ try
+ {
+ frontProdInfo = ConverterToPddFactory.Convert(outProdJson);
+ }
+ catch (Exception ex)
+ {
+ return "转换错误" + ex.Message;
+ }
+
+ if (frontProdInfo == null || frontProdInfo.GoodsId == null)
+ {
+ return "商品数据信息为空";
+ }
+ KJDDBProduct dbProd = new KJDDBProduct() { size_json = "{}" };
+ PDDProductInfo prodInfo = new PDDProductInfo()
+ {
+ //source_json = JsonHelper.JObjectParse(outProdJson),
+ source_json = null,
+ //sale_count = frontProdInfo.goods.sold_quantity.ParseToString(),
+ //sale_count_text = frontProdInfo.goods.side_sales_tip,
+ };
+ prodInfo.chance_id = null;
+ prodInfo.chance_refere = null;
+ prodInfo.chance_tab = null;
+ prodInfo.decoration = new PDDProductDecorationInfo() { floor_list = new List() };
+
+ // 商品详情
+ prodInfo.detail = new PDDProductDetailInfo();
+ prodInfo.detail.allergy_refund = 0;
+ prodInfo.detail.allowed_region = new List