Files
KJD/TEMUKJD/WXForms/ProductForms/WXDBProdUploadForm.cs
T
2026-01-15 22:24:00 +08:00

2347 lines
114 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using AllBase;
using AllBase.Helper;
using AllBase.Model.Result;
using NaiBa.Util.Extension;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TemuKJD.Extension;
using TemuKJD.BaseForms;
using TemuKJD.ToolForms;
using Work;
using TemuKJD.BLL;
using System.Text.RegularExpressions;
using TemuKJD.PDDForms.ProductSelectForms;
using TemuKJD.WXForms.ShopForms;
using AllBase.Model.Result.PDDResult;
using AllBase.Model.Param.WXParam;
using AllBase.Model.Result.WXResult;
using Newtonsoft.Json;
using NaiBa.Util;
namespace TemuKJD.WXForms.ProductForms
{
public partial class WXDBProdUploadForm : BaseForm
{
public CancellationTokenSource cancellationTokenSource { get; set; } = null;
public bool IsLoadComplate { get; set; } = false;
bool isInit = false;
bool isStepAddPrice = false;
CheckBox chkSelectAll = null;
Dictionary<ShopLoginInfo, int> dicShopGetCount = new Dictionary<ShopLoginInfo, int>();
Dictionary<ShopLoginInfo, List<string>> dicNotSupportCate = new Dictionary<ShopLoginInfo, List<string>>();
public NaiBa.Util.ConcurrentList<TemuDBProductSelect> lstTemuDBProductSelect = new NaiBa.Util.ConcurrentList<TemuDBProductSelect>();
NaiBa.Util.ConcurrentList<AddPriceRule> lstAddPriceRule = new NaiBa.Util.ConcurrentList<AddPriceRule>();
AddPriceRule defaultAddPriceRule = null;
WXUploadRule wxUploadRule = null;
public WXDBProdUploadForm()
{
InitializeComponent();
}
private void UserSelectDbProductForm_Load(object sender, EventArgs e)
{
this.splitContainer1.Dock = DockStyle.Fill;
this.panel1.Location = new Point(40, 30);
this.panel1.Width = this.Width - 80;
this.panel1.Height = this.Height - 60;
this.panel1.SendToBack();
cmbWxSafe.SelectedIndex = 0;
lstTemuDBProductSelect = NaiBa.Util.Helper.ConfigHelper.LoadConfig<NaiBa.Util.ConcurrentList<TemuDBProductSelect>>("wx_db_prod_upload_list");
if (lstTemuDBProductSelect == null)
lstTemuDBProductSelect = new NaiBa.Util.ConcurrentList<TemuDBProductSelect>();
lstAddPriceRule = NaiBa.Util.Helper.ConfigHelper.LoadConfig<NaiBa.Util.ConcurrentList<AddPriceRule>>("wx_add_price_rules");
if (lstAddPriceRule == null)
{
lstAddPriceRule = new NaiBa.Util.ConcurrentList<AddPriceRule>();
lstAddPriceRule.Add(new AddPriceRule() { MoreThanPrice = 0, LessThanPrice = 10, AddPriceTimes = 2, AddMorePrice = 5, SinglePriceAdd = 1 });
lstAddPriceRule.Add(new AddPriceRule() { MoreThanPrice = 10, LessThanPrice = 20, AddPriceTimes = 2, AddMorePrice = 5, SinglePriceAdd = 1 });
lstAddPriceRule.Add(new AddPriceRule() { MoreThanPrice = 20, LessThanPrice = 999, AddPriceTimes = 2, AddMorePrice = 5, SinglePriceAdd = 1 });
}
this.fPnlPriceRule.Controls.Clear();
foreach (var priceItem in lstAddPriceRule)
{
var ucPrice = new UcAddPrice()
{
PriceEnd = priceItem.LessThanPrice,
PriceStart = priceItem.MoreThanPrice,
PriceAddTimes = priceItem.AddPriceTimes,
PriceAddMore = priceItem.AddMorePrice,
SinglePriceAdd = priceItem.SinglePriceAdd,
};
if (IsSetFontScaleNone)
{
Font of = ucPrice.Font;
Font nf = new Font(of.FontFamily, (of.Size * 96.0 / FormDpi).ParseToFloat(), of.Style, of.Unit, of.GdiCharSet, of.Bold);
ucPrice.Font = nf;
}
this.fPnlPriceRule.Controls.Add(ucPrice);
ucPrice.PriceChange += ucAddPrice_PriceChange;
}
defaultAddPriceRule = NaiBa.Util.Helper.ConfigHelper.LoadConfig<AddPriceRule>("wx_default_add_price_rule");
if (defaultAddPriceRule == null)
{
defaultAddPriceRule = new AddPriceRule() { AddPriceTimes = 1.3m, AddMorePrice = 1, SinglePriceAdd = 1 };
}
this.txtAddTimes.Text = defaultAddPriceRule.AddPriceTimes.ToString();
this.txtAddMorePrice.Text = defaultAddPriceRule.AddMorePrice.ToString();
this.txtSinglePriceAdd.Text = defaultAddPriceRule.SinglePriceAdd.ToString();
this.txtStockNum.Text = defaultAddPriceRule.StockNum.ToString();
this.chkAddMorePriceFirst.Checked = defaultAddPriceRule.AddMorePriceFirst;
wxUploadRule = NaiBa.Util.Helper.ConfigHelper.LoadConfig<WXUploadRule>("wx_upload_rule");
if (wxUploadRule == null)
wxUploadRule = new WXUploadRule();
this.lblWaitToUp.Text = "待上传 " + lstTemuDBProductSelect.Count + " 件";
int prodCount = 0;
var list = GetRandomProductList(out prodCount, 1, 1);
lblGoodsCount.Text = "产品库 " + prodCount + " 件";
this.panel1.SendToBack();
chkSelectAll = dgvShop.Columns["colSelect"].AddHeaderCheckBox(HorizontalAlignment.Center, 0, 0, null, null, false);
dgvShop.Columns["colSelect"].HeaderText = "";
//chkSelectAll.Width = chkSelectAll.Height = 13;
chkSelectAll.CheckedChanged += chkSelectAll_CheckedChanged;
chkSelectAll.Checked = true;
this.dgvSelectProduct.AddSelectorColumn("colCheck");
dgvSelectProduct.AddImgColumn("colProductSkcPic", "colImgUrl");
dgvSelectProduct.AddImgColumn("colSkuFakeImg", "colSkuFakeImgUrl");
dgvSelectProduct.Columns["colSkuFakeImg"].Visible = false;
// if (BaseClass.SaLevel == 1)
// {
// dgvSelectProduct.Columns["colSkuFakeImg"].Visible = true;
// }
//#if DEBUG
// dgvSelectProduct.Columns["colSkuFakeImg"].Visible = true;
//#endif
IsLoadComplate = true;
}
private void chkSelectAll_CheckedChanged(object sender, EventArgs e)
{
if (!chkSelectAll.Checked)
{
foreach (DataGridViewRow row in dgvShop.Rows)
{
row.Cells["colSelect"].Value = false;
}
}
else
{
//var list = GlobalConfig.ShopLoginList.Where(s => s.LoginStatus == "登录成功").Select(ss => ss.ShopId);
foreach (DataGridViewRow row in dgvShop.Rows)
{
//if (list.Any(l => l == row.Cells["colShopId"]?.Value?.ToString()))
row.Cells["colSelect"].Value = true;
}
}
}
private void btnRefreshShop_Click(object sender, EventArgs e)
{
RefreshShop();
RefreshDbProd();
}
private void UserSelectDbProductForm_VisibleChanged(object sender, EventArgs e)
{
if (Visible == true)
{
RefreshShop();
RefreshDbProd();
isInit = true;
}
}
private void RefreshDbProd()
{
Task.Run(() =>
{
PDDDBProdListForm.GetPDDProductGroup(cmbGroupFilter); // 同时刷新下商品分组
GetPddProductCate();
});
}
/// <summary>
/// 获取商品所有类目
/// </summary>
void GetPddProductCate()
{
var url = BaseClass.BuildObjString("product/get_pdd_product_cates");
var data = UserLogin.GetSignaturex();
var html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
{
//BaseMsgForm.ShowError("商品分组获取失败,请重试!" + BaseRegex.GetStringJson(ref html, "msg"));
}
else
{
Invoke(new Action(() =>
{
cmbCateFilter.Items.Clear();
var groups = BaseRegex.GetStringJson(ref html, "data");
foreach (var item in groups.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries))
{
cmbCateFilter.Items.Add(item);
}
cmbCateFilter.Items.Add("");
}));
}
}
private void RefreshShop()
{
// 店铺Id
var selectIds = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colSelect"]?.Value.ParseToBool() == true).Select(r => r.Cells["colShopId"]?.Value.ToString()).ToList();
// 获取被删除的店铺
List<DataGridViewRow> dgvRowList = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> !GlobalConfig.ShopLoginList.Any(s => s.ShopId == row.Cells["colShopId"]?.Value?.ToString())).ToList();
// 更新被删除的店铺列表
foreach (var row in dgvRowList)
{
dgvShop.Rows.Remove(row);
}
// 绑定其他店铺(含新导入的店铺)
foreach (ShopLoginInfo shopEntity in GlobalConfig.ShopLoginList)
{
if (!string.IsNullOrEmpty(shopEntity.ShopId))
BindShop(shopEntity, selectIds);
}
}
private void BindShop(ShopLoginInfo shopEntity, List<string> selectShopId = null)
{
if (shopEntity == null)
return;
if (selectShopId == null)
selectShopId = new List<string>();
bool canUse = shopEntity.LoginStatus == "登录成功";
//canUse = true; // 内部库不需要校验登录状态
var row = dgvShop.Rows.Cast<DataGridViewRow>().FirstOrDefault(p => p.Cells.GetCellValueFromColumnName("colShopId").ParseToString() == shopEntity.ShopId);
if (row == null)
{
this.dgvShop.Rows.Add(
!isInit || (selectShopId.Contains(shopEntity.ShopId) && canUse),
shopEntity.LoginName,
shopEntity.ShopId,
shopEntity.ShopAccount,
shopEntity.Notes,
"选择商品",
canUse ? "在线" : "掉线",
canUse,
0,
shopEntity.AddProductRemaining,
string.Empty
);
}
else
{
row.Cells["colSelect"].Value = !isInit || (selectShopId.Contains(shopEntity.ShopId) && canUse);
row.Cells["colShopLoginName"].Value = shopEntity.LoginName;
row.Cells["colShopName"].Value = shopEntity.ShopAccount;
row.Cells["colShopNotes"].Value = shopEntity.Notes;
row.Cells["colLoginStatus"].Value = canUse ? "在线" : "掉线";
row.Cells["colLoginStatus"].Style.ForeColor = canUse ? Color.Green : Color.Red;
row.Cells["colCanUse"].Value = canUse;
row.Cells["colRemaining"].Value = shopEntity.AddProductRemaining;
}
}
private void dgvShop_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0)
return;
string headerText = dgvShop.Columns[e.ColumnIndex].HeaderText;
string columnName = dgvShop.Columns[e.ColumnIndex].Name;
string shopId = dgvShop.Rows[e.RowIndex].Cells["colShopId"].Value.ParseToString();
string shopAccount = dgvShop.Rows[e.RowIndex].Cells["colShopName"].Value.ToString();
var shop = GlobalConfig.ShopLoginList.FirstOrDefault(s => s.ShopId == shopId.ToString());
var row = dgvShop.Rows[e.RowIndex];
switch (columnName)
{
case "colSelect":
//if (row.Cells["colCanUse"].Value.ParseToBool())
{
row.Cells["colSelect"].Value = !row.Cells["colSelect"].Value.ParseToBool();
chkSelectAll.CheckedChanged -= chkSelectAll_CheckedChanged;
if (dgvShop.Rows.Cast<DataGridViewRow>().All(r => r.Cells["colSelect"].Value.ParseToBool()))
chkSelectAll.Checked = true;
else
chkSelectAll.Checked = false;
chkSelectAll.CheckedChanged += chkSelectAll_CheckedChanged;
}
//else
{
//BaseMsgForm.ShowInfo("店铺未登录!");
}
break;
case "colLoginStatus":
if (WXShopListForm.Instance == null)
WXShopListForm.Instance = new WXShopListForm();
WXShopListForm.Instance.CheckShopLogin(new string[] { shop.LoginName }, false);
WXShopLoginForm shopLoginForm = new WXShopLoginForm(shop);
//shopLoginForm.prodUserSelectForm = this;
if (shop.LoginStatus != "登录成功")
{
shopLoginForm.openType = EnumOpenType.login;
shopLoginForm.ShowDialog();
RefreshShop();
}
else
{
shopLoginForm.openType = EnumOpenType.manage;
shopLoginForm.WindowState = FormWindowState.Maximized;
shopLoginForm.Show();
}
break;
}
}
private void btnSearch_Click(object sender, EventArgs e)
{
var lstShopId = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colSelect"]?.Value.ParseToBool() == true).Select(r => r.Cells["colShopId"]?.Value.ToString()).ToList();
if (lstShopId.Count == 0)
{
BaseMsgForm.ShowInfo("请选择店铺!");
return;
}
}
private void dgvSelectProduct_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex < 0 || e.RowIndex < 0)
return;
string headerText = dgvSelectProduct.Columns[e.ColumnIndex].HeaderText;
var dbId = dgvSelectProduct.Rows[e.RowIndex].Cells["colSelectId"].Value.ParseToString();
var dbProduct = lstTemuDBProductSelect.FirstOrDefault(p => p.id.ToString() == dbId);
var shopId = dgvSelectProduct.Rows[e.RowIndex].Cells["colSupplierId"].Value.ParseToString();
var draftId = dgvSelectProduct.Rows[e.RowIndex].Cells["colDraftId"].Value.ParseToString();
var shop = GlobalConfig.ShopLoginList.FirstOrDefault(s => s.ShopId == shopId);
switch (headerText)
{
case "删除":
break;
case "登录":
{
WXShopLoginForm shopLoginForm = new WXShopLoginForm(shop);
//shopLoginForm.prodUserSelectForm = this;
shopLoginForm.openType = EnumOpenType.login;
shopLoginForm.ShowDialog();
RefreshShop();
}
break;
case "进店":
{
WXShopLoginForm shopLoginForm = new WXShopLoginForm(shop);
//shopLoginForm.prodUserSelectForm = this;
shopLoginForm.openType = EnumOpenType.manage;
shopLoginForm.WindowState = FormWindowState.Maximized;
shopLoginForm.InitUrl = "https://store.weixin.qq.com/shop/home";
shopLoginForm.Show();
}
break;
case "上传商品Id":
//if (!string.IsNullOrEmpty(draftId) && shop != null)
//{
// ShopLoginForm shopLoginForm = new ShopLoginForm(shop);
// shopLoginForm.InitUrl = "https://seller.kuajingmaihuo.com/goods/product-create/product-edit?productDraftId=" +
// draftId + "&from=productDraftList";
// shopLoginForm.openType = EnumOpenType.manage;
// shopLoginForm.WindowState = FormWindowState.Maximized;
// shopLoginForm.ShowDialog();
//}
break;
case "图片":
{
ShowImgForm imgFrom = new ShowImgForm(dgvSelectProduct.Rows[e.RowIndex].Cells["colImgUrl"].Value.ParseToString());
imgFrom.ShowDialog();
break;
}
case "SKU替换图":
{
ShowImgForm imgFrom = new ShowImgForm(dgvSelectProduct.Rows[e.RowIndex].Cells["colSkuFakeImgUrl"].Value.ParseToString());
imgFrom.ShowDialog();
break;
}
case "":
dgvSelectProduct.Rows[e.RowIndex].Cells["colCheck"].Value = !(bool)dgvSelectProduct.Rows[e.RowIndex].Cells["colCheck"].Value;
break;
default:
break;
}
}
private void btnUpload_Click(object sender, EventArgs e)
{
var shopIdLst = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colSelect"]?.Value.ParseToBool() == true).Select(r => r.Cells["colShopId"]?.Value.ToString()).ToList();
if (shopIdLst.Count <= 0)
{
BaseMsgForm.ShowError("未勾选上传店铺!");
return;
}
if (lstTemuDBProductSelect.Count() > 0)
{
if (WXShopLoginForm.shopLoginInstance != null && WXShopLoginForm.shopLoginInstance.IsDisposed != true)
WXShopLoginForm.shopLoginInstance.Dispose();
this.btnUpload.Enabled = false;
cancellationTokenSource = new CancellationTokenSource();
Task.Run(() =>
{
AddProductArr(shopIdLst);
Invoke(new Action(() =>
{
this.btnUpload.Enabled = true;
}));
}, cancellationTokenSource.Token);
}
else
{
BaseMsgForm.ShowError("请选择要上传的商品!");
}
}
void AddProductArr(List<string> shopIdLst)
{
Invoke(new Action(() =>
{
this.pbLoading.Visible = true;
this.statusBar.lblTaskStatus.Text = "正在上传" + "...".Substring(0, DateTime.Now.Second % 4);
this.statusBar.pgbTaskProgress.Maximum = lstTemuDBProductSelect.Count;
this.statusBar.UpdateProgressBar(0);
}));
NaiBa.Util.ConcurrentList<ShopLoginInfo> currentShopList = new NaiBa.Util.ConcurrentList<ShopLoginInfo>();
while (lstTemuDBProductSelect.Count > 0)
{
if (cancellationTokenSource.IsCancellationRequested)
break;
Invoke(new Action(() =>
{
shopIdLst = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colSelect"]?.Value.ParseToBool() == true).Select(r => r.Cells["colShopId"]?.Value.ToString()).ToList();
}));
while (shopIdLst.Count <= 0)
{
Invoke(new Action(() =>
{
this.statusBar.lblTaskStatus.Text = "请至少勾选一个店铺";
shopIdLst = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colSelect"]?.Value.ParseToBool() == true).Select(r => r.Cells["colShopId"]?.Value.ToString()).ToList();
}));
Thread.Sleep(1000);
if (cancellationTokenSource.IsCancellationRequested)
break;
}
var randomShopLst = new NaiBa.Util.ConcurrentList<ShopLoginInfo>();
randomShopLst.AddRange(GlobalConfig.ShopLoginList.Where(s => shopIdLst.Contains(s.ShopId) && s.LoginStatus == "登录成功"));
while (randomShopLst.Count <= 0)
{
Thread.Sleep(1000);
Invoke(new Action(() =>
{
shopIdLst = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colSelect"]?.Value.ParseToBool() == true).Select(r => r.Cells["colShopId"]?.Value.ToString()).ToList();
}));
Invoke(new Action(() =>
{
this.statusBar.lblTaskStatus.Text = "所有店铺都已掉线,请登录店铺";
randomShopLst.Clear();
randomShopLst.AddRange(GlobalConfig.ShopLoginList.Where(s => shopIdLst.Contains(s.ShopId) && s.LoginStatus == "登录成功"));
}));
if (cancellationTokenSource.IsCancellationRequested)
break;
}
if (cancellationTokenSource.IsCancellationRequested)
break;
while (currentShopList.Count >= 5) // 最多5店同传
{
Thread.Sleep(100);
}
if (cancellationTokenSource.IsCancellationRequested)
break;
var randomShop = randomShopLst[Randomx.GetId(randomShopLst.Count)];
while (currentShopList.Any(s => s.ShopId == randomShop.ShopId))
{
Thread.Sleep(500);
var randomShopTmpLst = randomShopLst.Where(s => !currentShopList.Contains(s)).ToList();
if (randomShopTmpLst.Count == 0)
continue;
randomShop = randomShopTmpLst[Randomx.GetId(randomShopTmpLst.Count)];
}
currentShopList.Add(randomShop);
if (cancellationTokenSource.IsCancellationRequested)
break;
// 商品已全部上传,退出
if (lstTemuDBProductSelect.Count <= 0)
{
currentShopList.Remove(randomShop);
break;
}
var selectProd = lstTemuDBProductSelect[0];
if (randomShop != null)
{
selectProd.shop_id = randomShop.ShopId;
selectProd.shop_account = randomShop.ShopAccount = randomShop.ShopAccount;
}
else
{
currentShopList.Remove(randomShop);
continue;
}
if (cancellationTokenSource.IsCancellationRequested)
break;
lstTemuDBProductSelect.RemoveAt(0);
NaiBa.Util.Helper.ConfigHelper.SaveConfig("wx_db_prod_upload_list", this.lstTemuDBProductSelect);
Invoke(new Action(() =>
{
lblWaitToUp.Text = "待上传 " + lstTemuDBProductSelect.Count + " 件";
}));
Invoke(new Action(() =>
{
this.statusBar.lblTaskStatus.Text = "正在上传" + "...".Substring(0, DateTime.Now.Second % 4);
this.statusBar.pgbTaskProgress.Maximum = lstTemuDBProductSelect.Count + this.statusBar.pgbTaskProgress.Value + 1;
this.statusBar.UpdateProgressBar(this.statusBar.pgbTaskProgress.Value + 1);
}));
if (selectProd == null)
{
Invoke(new Action(() =>
{
BaseMsgForm.ShowError("商品为空,将为您跳过该商品!");
}));
currentShopList.Remove(randomShop);
continue;
}
// 过滤标题
var lstTitleReplaceText = new List<string>();
lstTitleReplaceText.Clear();
if (!txtReplaceText.Text.Trim().IsNullOrEmpty())
lstTitleReplaceText.AddRange(txtReplaceText.Text.Trim().Split(new string[] { ",", ",", " " }, StringSplitOptions.RemoveEmptyEntries));
// 过滤标题内指定词语
if (lstTitleReplaceText.Count > 0)
{
foreach (var txt in lstTitleReplaceText)
{
selectProd.product_name = selectProd.product_name.Replace(txt, "");
}
}
Invoke(new Action(() =>
{
int rowIndex = 0;
this.dgvSelectProduct.Rows.Insert(rowIndex,
true,
selectProd.id,
selectProd.shop_id,
selectProd.shop_account,
"登录",
"进店",
selectProd.spu_id,
selectProd.skc_id,
selectProd.main_img,
null,
"",
null,
selectProd.product_name, // 用户端显示商品原名
selectProd.cat_name,
selectProd.ext_code,
selectProd.status,
selectProd.draft_id,
selectProd.notes,
(selectProd.user_notes + " 编辑").Trim(),
"删除",
"",
"");
dgvSelectProduct.Rows[rowIndex].Height = 60;
int maxRowCount = 10000;
while (dgvSelectProduct.Rows.Count > maxRowCount)
{
dgvSelectProduct.Rows.RemoveAt(maxRowCount);
}
}));
Invoke(new Action(() =>
{
this.pbLoading.Visible = false;
}));
Task.Run(() =>
{
DateTime startTime = DateTime.Now;
for (int j = 0; j < 1; j++)
{
var shop = GlobalConfig.ShopLoginList.FirstOrDefault(s => s.ShopId == selectProd.shop_id);
if (shop == null)
continue;
var row = dgvSelectProduct.Rows.Cast<DataGridViewRow>().FirstOrDefault(r =>
r.Cells["colSelectId"]?.Value.ToString() == selectProd.id.ToString());
double duration = 0;
if (row == null)
{
Invoke(new Action(() =>
{
BaseMsgForm.ShowError("商品已被清除,将为您跳过该商品!");
}));
continue;
}
KJDDBProduct kjdDbProd = selectProd.kjdDbProduct;
if (kjdDbProd == null)
kjdDbProd = GetProductDetail(selectProd.out_product_Id.ToString());
if (kjdDbProd == null || kjdDbProd.id == 0)
{
if (kjdDbProd?.id == 0)
{
selectProd.status = "已清除";
}
Invoke(new Action(() =>
{
if (row.Index >= 0)
{
row.Cells["colOpResult"].Value = "选品数据库商品已被清除";
if (kjdDbProd?.id == 0)
row.Cells["colStatus"].Value = "已清除";
}
}));
continue;
}
var result = "";
try
{
WXShopListForm.Instance.CheckShopLogin(new ShopLoginInfo[] { shop }, false);
if (shop.LoginStatus != "登录成功")
{
Invoke(new Action(() =>
{
if (row.Index >= 0)
{
row.Cells["colOpResult"].Value = "店铺掉线";
}
}));
continue;
}
if (cancellationTokenSource.IsCancellationRequested)
break;
//将商品上传
result = UploadProduct(shop, kjdDbProd, selectProd, row.Cells["colOpResult"], startTime);
Invoke(new Action(() =>
{
row.Cells["colSkuFakeImgUrl"].Value = kjdDbProd.sku_img_replace_url;
if (row.Displayed)
{
string getImgError = "";
Image img = GetHtml.GetUrlImg(kjdDbProd.sku_img_replace_url.Replace("https://", "http://"), out getImgError);
if (string.IsNullOrEmpty(getImgError))
row.Cells["colSkuFakeImg"].Value = img;
}
}));
if (!result.Contains("success"))
{
WXShopListForm.Instance.CheckShopLogin(new ShopLoginInfo[] { shop }, false);
}
}
catch (Exception ex)
{
result = "{\"success\":false,\"status\":\"未上传\",\"errMsg\":\"" + ex.Message + "\"}";
}
Thread.Sleep(Randomx.GetId(200, 300));
//额外等待时间(无论失败与否)
var waitTime = 0;
Invoke(new Action(() => { waitTime = txtWaitSeconds.Text.Trim().ParseToInt(); }));
if (waitTime > 0)
Thread.Sleep(Randomx.GetId(waitTime * 1000, (waitTime + 10) * 1000));
selectProd.status = BaseRegex.GetStringJson(ref result, "status");
if (string.IsNullOrWhiteSpace(selectProd.status))
selectProd.status = "待上传";
var productDraftId = BaseRegex.GetStringJson(ref result, "draftId");
var timeSpan = DateTime.Now - startTime;
duration = timeSpan.TotalSeconds;
// 至少15秒才完成一件商品
while (duration < 15)
{
Thread.Sleep(1000);
timeSpan = DateTime.Now - startTime;
duration = timeSpan.TotalSeconds;
}
var error = BaseRegex.GetStringJson(ref result, "errMsg");
// 上传失败
if (!result.Contains("\"success\":true") && !result.Contains("上传成功"))
{
if (string.IsNullOrWhiteSpace(error))
error = result;
Invoke(new Action(() =>
{
if (row.Index >= 0)
{
row.Cells["colDraftId"].Value = productDraftId; // 草稿箱id
row.Cells["colOpResult"].Value = error + " " + duration.ParseToInt() + "秒";
}
}));
}
// 上传成功/上传到草稿箱
else
{
Invoke(new Action(() =>
{
if (row.Index >= 0)
{
row.Cells["colDraftId"].Value = productDraftId; // 草稿箱id
row.Cells["colAddTime"].Value = DateTime.Now.ToString("yy-MM-dd HH:mm:ss");
row.Cells["colOpResult"].Value = (selectProd.status == "已上传" ? "已成功上传" : "已上传 发生错误:") + (" " + error).TrimEnd(' ') + " " + duration.ParseToInt() + "秒";
row.Cells["colMsg"].Value = selectProd.status;
}
}));
}
}
currentShopList.Remove(randomShop);
});
}
for (int i = 0; i < 300 && currentShopList.Count > 0; i++)
{
Thread.Sleep(1000);
if (cancellationTokenSource.IsCancellationRequested)
break;
}
Invoke(new Action(() =>
{
if (cancellationTokenSource.IsCancellationRequested)
BaseMsgForm.ShowInfo("上传停止!");
else
BaseMsgForm.ShowInfo("上传完成!");
}));
Invoke(new Action(() =>
{
this.pbLoading.Visible = false;
if (cancellationTokenSource.IsCancellationRequested)
this.statusBar.lblTaskStatus.Text = "上传停止";
else
this.statusBar.lblTaskStatus.Text = "上传完成";
//this.statusBar.UpdateProgressBar(lstTemuDBProductSelect.Count);
}));
}
public static KJDDBProduct GetProductDetail(string prodDbId)
{
if (string.IsNullOrEmpty(prodDbId))
return new KJDDBProduct();
List<KJDDBProduct> list = new List<KJDDBProduct>();
var url = BaseClass.BuildObjString("product/get_pdd_product_detail_list");
var data = "";
data = UserLogin.GetSignaturex() + "&search_db_ids=" + prodDbId;
var html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
{
return null;
}
var jArr = JObject.Parse(html)["data"];
if (jArr.Count() == 0)
return null;
var sProd = JsonHelper.SerializeObject(jArr);
try
{
list = JsonHelper.DeserializeJsonToList<KJDDBProduct>(sProd);
var item = list.FirstOrDefault();
if (item == null)
item = new KJDDBProduct();
return item;
}
catch (Exception ex)
{
return null;
}
}
string UploadProduct(ShopLoginInfo shop, KJDDBProduct dbProd, TemuDBProductSelect selectProd, DataGridViewCell cell, DateTime startTime)
{
Thread.Sleep(Randomx.GetId(200, 300));
if (shop == null || string.IsNullOrEmpty(shop.ShopId) || shop.LoginStatus != "登录成功")
{
return "店铺为空或未登录!";
}
if (cell != null)
{
Invoke(new Action(() =>
{
cell.Value = "正在初始化上传";
}));
}
if (chkSkipUploaded.Checked)
{
var searchExtCode = "EC1" + dbProd.spu_id + "A";
var searchRst = WXUpload.searchProduct(shop, searchExtCode);
if (!searchRst.Contains("\"code\":0") && !searchRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref searchRst, "msg");
if (string.IsNullOrEmpty(error))
error = searchRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"商品查询错误 " + error + "\"}";
}
try
{
var num = JObject.Parse(searchRst)["totalNum"].ParseToInt();
if (num > 0)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"商品已存在,选择跳过\"}";
}
}
catch (Exception ex)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"商品查询错误 " + ex.Message + "\"}";
}
}
#region 将产品数据初始化成微信小店支持的参数
JObject prodJObj = new JObject();
try
{
prodJObj = JObject.Parse(dbProd.product_json);
var lstTitleReplaceText = new List<string>();
lstTitleReplaceText.Clear();
if (!txtReplaceText.Text.Trim().IsNullOrEmpty())
lstTitleReplaceText.AddRange(txtReplaceText.Text.Trim().Split(new string[] { ",", ",", " " }, StringSplitOptions.RemoveEmptyEntries));
// 过滤标题内指定词语
if (lstTitleReplaceText.Count > 0)
{
foreach (var txt in lstTitleReplaceText)
{
dbProd.product_name = dbProd.product_name.Replace(txt, "");
}
var goods_name = prodJObj["detail"]["goods_name"].ParseToString();
foreach (var txt in lstTitleReplaceText)
{
goods_name = goods_name.Replace(txt, "");
}
prodJObj["detail"]["goods_name"] = goods_name;
var tiny_name = prodJObj["detail"]["tiny_name"].ParseToString();
foreach (var txt in lstTitleReplaceText)
{
tiny_name = tiny_name.Replace(txt, "");
}
prodJObj["detail"]["tiny_name"] = tiny_name;
var goods_desc = prodJObj["detail"]["goods_desc"].ParseToString();
foreach (var txt in lstTitleReplaceText)
{
goods_desc = goods_desc.Replace(txt, "");
}
prodJObj["detail"]["goods_desc"] = goods_desc;
var share_desc = prodJObj["detail"]["share_desc"].ParseToString();
foreach (var txt in lstTitleReplaceText)
{
share_desc = share_desc.Replace(txt, "");
}
prodJObj["detail"]["share_desc"] = share_desc;
}
// 替换货号
if (!string.IsNullOrEmpty(dbProd.ext_code))
prodJObj["detail"]["out_goods_sn"] = dbProd.ext_code;
// 替换编辑过的sku
if (!string.IsNullOrEmpty(dbProd.sku_edit_json))
prodJObj["detail"]["sku"] = JArray.Parse(JsonHelper.SerializeObject(JsonHelper.DeserializeJsonToList<sku_item>(dbProd.sku_edit_json)));
if (chkSameSpecPrice.Checked)
{
var priceTextLst = dbProd.price_text.Split('-');
if (priceTextLst.Length != 2 || priceTextLst[0] != priceTextLst[1])
{
Dictionary<string, int> specPriceDic = new Dictionary<string, int>();
Dictionary<string, int> specMultiPriceDic = new Dictionary<string, int>();
var skuJArr = prodJObj["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)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"商品数据初始化失败" + ex.Message + "\"}";
}
}
}
if (chkHighestPriceSku.Checked)
{
int price = 0;
var skuJArr = prodJObj["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(prodJObj);
// 移除第一组所有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)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"商品sku差价不满足上货条件,跳过\"}";
}
}
catch (Exception ex)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"商品数据初始化失败" + ex.Message + "\"}";
}
}
// 过滤低价sku,如果所有sku都不达标,跳过商品
if (!string.IsNullOrEmpty(txtMinPrice.Text))
{
var product_json_tmp = JsonHelper.SerializeObject(prodJObj);
// 移除第一组所有sku
var skuJArr = prodJObj["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)
{
if (skuJObj2["multi_price"].ParseToInt() >= this.txtMinPrice.Text.Trim().ParseToDecimal() * 100)
skuJArr.Add(skuJObj2);
}
if (skuJArr.Count == 0)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"商品sku价格不满足上货条件,跳过\"}";
}
}
dbProd.product_json = JsonHelper.SerializeObject(prodJObj);
}
catch (Exception ex)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"商品数据初始化失败" + ex.Message + "\"}";
}
#endregion
var prodInfo = JsonHelper.DeserializeJsonToObject<PDDProductInfo>(dbProd.product_json);
prodInfo.detail.galleries.RemoveAll(g => g.type == 6); // 视频暂时移除,以后再视情况加上
int mainImgCount = (prodInfo?.detail?.galleries?.Where(g => g.type == 1).Count()).ParseToInt();
if (mainImgCount > 0 && mainImgCount < 3)
{
var gallery1 = prodInfo?.detail?.galleries?.Where(g => g.type == 2).FirstOrDefault();
if (gallery1 != null)
{
prodInfo.detail.galleries.Add(new gallery_item()
{
type = 1,
url = gallery1.url,
width = gallery1.width,
height = gallery1.height,
});
}
if (mainImgCount == 1 && (prodInfo?.detail?.galleries?.Where(g => g.type == 1).Count()).ParseToInt() > 1)
{
var gallery2 = prodInfo?.detail?.galleries?[1];
if (gallery2 != null)
{
prodInfo.detail.galleries.Add(new gallery_item()
{
type = 1,
url = gallery2.url,
width = gallery2.width,
height = gallery2.height,
});
}
}
}
if ((prodInfo?.detail?.galleries?.Where(g => g.type == 1).Count()).ParseToInt() < 3)
{
Invoke(new Action(() =>
{
cell.Value = "主图数量少于三张";
}));
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"主图数量少于三张\"}";
}
// 生成初始化上传商品对象
var upProdInitParam = new WXUploadProductInitParam();
// 生成上传商品对象
var upProdParam = new WXUploadProductParam();
// 设置标题
upProdInitParam.product.info.title = dbProd.product_name.IsNullOrEmpty() ? prodInfo.detail.goods_name : dbProd.product_name;
upProdParam.product.info.title = dbProd.product_name.IsNullOrEmpty() ? prodInfo.detail.goods_name : dbProd.product_name;
upProdParam.sessionInfo.sessionId = upProdInitParam.product.sessionId;
// 设置货号
var extCode = dbProd.ext_code.IsNullOrEmpty() ? prodInfo.detail.out_goods_sn : dbProd.ext_code;
if (extCode.IsNullOrEmpty())
{
//extCode = "EC" + Randomx.GetId(1000).ToString().PadLeft(3, '0') + dbProd.spu_id + "C";
extCode = "EC1" + dbProd.spu_id + "A";
}
upProdParam.product.info.spuCode = extCode;
if (cell != null)
{
Invoke(new Action(() =>
{
cell.Value = "正在识别商品";
}));
}
Thread.Sleep(Randomx.GetId(500, 800));
//-------------------------------------------------------------------------------------------------------------------------------------
// ai识别类目暂存主图位置
int imgId = 0;
string tempImgPath = Path.GetTempPath() + "\\";
string folderLetters = "abcdefghijklmnopqrstuvwxyz1234567890";
for (int i = 0; i < 8; i++)
{
tempImgPath += folderLetters[Randomx.GetId(folderLetters.Length)];
}
List<string> tempImgFullPathLst = new List<string>();
//-------------------------------------------------------------------------------------------------------------------------------------
// 上传主图
foreach (var gallery_item in prodInfo.detail.galleries.Where(g => g.type == 1).Take(9)) // 9张主图
{
var upImgAuthRst = WXUpload.getUploadTempImgAuth(shop);
for (int i = 0; i < 10 && upImgAuthRst.Contains("LogicError"); i++)
{
Thread.Sleep(Randomx.GetId(3000, 6000));
upImgAuthRst = WXUpload.getUploadTempImgAuth(shop);
Invoke(new Action(() =>
{
cell.Value = "图片提报失败,正在重试。";
}));
}
if (!upImgAuthRst.Contains("\"code\":0"))
{
var error = BaseRegex.GetStringJson(ref upImgAuthRst, "msg");
if (string.IsNullOrEmpty(error))
error = upImgAuthRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"申请上传主图失败 " + error + "\"}";
}
string disK = BaseRegex.GetStringJson(ref upImgAuthRst, "disK");
long disT = BaseRegex.GetLongJson(ref upImgAuthRst, "disT");
string ext = BaseRegex.GetStringJson(ref upImgAuthRst, "ext");
string imgBase64 = "";
//-------------------------------------------------------------------------------------------------------------------------------------
//生成主图base64字符串
string getImgError;
var image = GetHtml.GetUrlImg(gallery_item.url.Replace("https://", "http://"), out getImgError);
var imageBg = new Bitmap(800, 800);
if (!string.IsNullOrEmpty(getImgError) || image == null)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"初始化主图上传失败\"}";
}
try
{
using (Graphics g = Graphics.FromImage(imageBg))
{
g.DrawImage(image, new Rectangle(0, 0, imageBg.Width, imageBg.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
}
// 取前三张图片保存到系统temp路径,配合商品标题获取商品类目
if (imgId < 3)
{
imgId++;
if (!Directory.Exists(tempImgPath))
Directory.CreateDirectory(tempImgPath);
string imgFullPath = tempImgPath + "\\图片" + imgId + ".jpg";
tempImgFullPathLst.Add(imgFullPath);
if (imgId == 1)
image.Save(imgFullPath, System.Drawing.Imaging.ImageFormat.Jpeg);
else
{
// 只需要传一张真实图像即可
int fileSize = Randomx.GetId(1024, 10240);
using (BinaryWriter writer = new BinaryWriter(File.Create(imgFullPath)))
{
for (int i = 0; i < fileSize; i++)
{
writer.Write((byte)Randomx.GetId(256)); // 生成0到255之间的随机字节
}
}
}
}
using (MemoryStream memoryStream = new MemoryStream())
{
imageBg.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] imageBytes = memoryStream.ToArray();
imgBase64 = Convert.ToBase64String(imageBytes);
}
}
catch (Exception ex)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"修改主图失败 " + ex.Message + "\"}";
}
//-------------------------------------------------------------------------------------------------------------------------------------
//上传主图获取路径
var upImgRst = WXUpload.adtimageupload(shop, imgBase64, disK, disT, ext).ParseToString();
var location = BaseRegex.GetStringJson(ref upImgRst, "Location");
if (string.IsNullOrEmpty(location))
{
var error = BaseRegex.GetStringJson(ref upImgAuthRst, "msg");
if (string.IsNullOrEmpty(error))
error = upImgAuthRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"主图上传失败 " + error + "\"}";
}
upProdInitParam.product.info.headImg.Add(location);
upProdParam.product.info.headImg.Add(location);
Thread.Sleep(Randomx.GetId(10, 50));
}
if (cell != null)
{
Invoke(new Action(() =>
{
cell.Value = "正在生成类目属性";
}));
}
Thread.Sleep(Randomx.GetId(500, 800));
//-------------------------------------------------------------------------------------------------------------------------------------
// 根据Ai分类,获取类目信息
//{"code":0,"predInfo":{"firstCatRes":[{"catId":10000111,"catName":"服饰内衣","level":1},{"catId":10000111,"catName":"服饰内衣","level":1},{"catId":10000111,"catName":"服饰内衣","level":1}],"secondCatRes":[{"catId":10000113,"catName":"女装","level":2},{"catId":10000113,"catName":"女装","level":2},{"catId":10000113,"catName":"女装","level":2}],"thirdCatRes":[{"catId":547705,"catName":"牛仔裤","level":3,"modelVersion":""},{"catId":547704,"catName":"加绒裤","level":3,"modelVersion":"商品标题含'加绒加厚、保暖'等关键词,这表示裤子具备加绒保暖功能。主图展示了加绒内衬,也符合【服饰内衣:女装:裤子:加绒裤】类目特征。"},{"catId":547701,"catName":"休闲裤","level":3,"modelVersion":""}],"singleSecondCatRes":[],"singleFirstCatRes":[],"isSupportedCate":1},"aiCategoryList":[{"id":547705,"paths":[{"id":"10000111","name":"服饰内衣","sonIdList":["10000397","10000115","10000112","10000113","10000114"],"fId":"0","level":1,"leaf":false},{"id":"10000113","name":"女装","sonIdList":["546810","546811","530041","547706","6090","6089","6088","6087","6083","6076","6073","6070","6065","6063","6058","10000672","10000671","10000670","10000669","10000668","10000667","10000666","10000665","10000664","10000663","10000662","10000661","10000660","10000659","10000658","10000657","10000656","10000655"],"fId":"10000111","level":2,"leaf":false},{"id":"10000672","name":"裤子","sonIdList":["547699","547700","547701","547702","547703","547704","547705"],"fId":"10000113","level":3,"leaf":false},{"id":"547705","name":"牛仔裤","fId":"10000672","level":4,"leaf":true,"state":0,"hasTrialCategory":false,"isTrialCategory":false,"isLocalLife":false}],"depositAmount":0,"catAuth":true,"limitSubjectTypes":[]},{"id":547704,"paths":[{"id":"10000111","name":"服饰内衣","sonIdList":["10000397","10000115","10000112","10000113","10000114"],"fId":"0","level":1,"leaf":false},{"id":"10000113","name":"女装","sonIdList":["546810","546811","530041","547706","6090","6089","6088","6087","6083","6076","6073","6070","6065","6063","6058","10000672","10000671","10000670","10000669","10000668","10000667","10000666","10000665","10000664","10000663","10000662","10000661","10000660","10000659","10000658","10000657","10000656","10000655"],"fId":"10000111","level":2,"leaf":false},{"id":"10000672","name":"裤子","sonIdList":["547699","547700","547701","547702","547703","547704","547705"],"fId":"10000113","level":3,"leaf":false},{"id":"547704","name":"加绒裤","fId":"10000672","level":4,"leaf":true,"state":0,"hasTrialCategory":false,"isTrialCategory":false,"isLocalLife":false}],"depositAmount":0,"catAuth":true,"limitSubjectTypes":[]},{"id":547701,"paths":[{"id":"10000111","name":"服饰内衣","sonIdList":["10000397","10000115","10000112","10000113","10000114"],"fId":"0","level":1,"leaf":false},{"id":"10000113","name":"女装","sonIdList":["546810","546811","530041","547706","6090","6089","6088","6087","6083","6076","6073","6070","6065","6063","6058","10000672","10000671","10000670","10000669","10000668","10000667","10000666","10000665","10000664","10000663","10000662","10000661","10000660","10000659","10000658","10000657","10000656","10000655"],"fId":"10000111","level":2,"leaf":false},{"id":"10000672","name":"裤子","sonIdList":["547699","547700","547701","547702","547703","547704","547705"],"fId":"10000113","level":3,"leaf":false},{"id":"547701","name":"休闲裤","fId":"10000672","level":4,"leaf":true,"state":0,"hasTrialCategory":false,"isTrialCategory":false,"isLocalLife":false}],"depositAmount":0,"catAuth":true,"limitSubjectTypes":[]}],"version":"ProductClsRAG","noQualificationCatIds":[547705,547704,547701],"depositCatInfos":[{"catId":547705,"amountToPay":0,"error":false},{"catId":547704,"amountToPay":0,"error":false},{"catId":547701,"amountToPay":0,"error":false}],"visionCallMethod":"ProductClsRAG"}
var productClassifyRst = WXUpload.getProductClassify(shop, upProdInitParam.product.info.title, tempImgFullPathLst);
if (!productClassifyRst.Contains("\"code\":0"))
{
var error = BaseRegex.GetStringJson(ref productClassifyRst, "msg");
if (string.IsNullOrEmpty(error))
error = productClassifyRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"获取类目失败 " + error + "\"}";
}
WXGetProdCateInfo cateInfo = new WXGetProdCateInfo();
List<long> aiCateIdLst = new List<long>();
try
{
cateInfo = JsonHelper.DeserializeJsonToObject<WXGetProdCateInfo>(productClassifyRst);
foreach (var catePath in cateInfo.aiCategoryList.FirstOrDefault().paths)
{
aiCateIdLst.Add(catePath.id.ParseToLong());
}
string getCateRst = WXUpload.getCategoryOnShelf(shop, aiCateIdLst);
if (!getCateRst.Contains("\"code\":0"))
{
var error = BaseRegex.GetStringJson(ref getCateRst, "msg");
if (string.IsNullOrEmpty(error))
error = getCateRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"获取类目模板失败" + error + "\"}";
}
JObject jCateRst = JObject.Parse(getCateRst);
upProdParam.product.info.category = JsonHelper.DeserializeJsonToList<categoryParam>(JsonHelper.SerializeObject(jCateRst["category"]));
// 这里用了ai获取类目,如下填写
upProdParam.product.info.recommendCategory = new recommendCategoryParam()
{
isAccepted = true,
categoryNames = new List<string>(),
recommendSource = "ai",
interfaceName = "ProductClsRAG",
useNewInterface = 1,
};
foreach (var cateParam in upProdParam.product.info.category)
{
upProdParam.product.info.recommendCategory.categoryNames.Add(cateParam.name);
}
}
catch (Exception ex)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"" + "根据图片获取类目失败 " + ex.Message + "\"}";
}
// 检测是否有类目上传权限
long leafCatId = (upProdParam.product.info.category.LastOrDefault()?.catId).ParseToLong();
var cateUpCheckRst = WXUpload.batchCheckCategoryRelation(shop, leafCatId);
if (!cateUpCheckRst.Contains("\"code\":0") && !cateUpCheckRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref cateUpCheckRst, "msg");
if (string.IsNullOrEmpty(error))
error = cateUpCheckRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"类目校验错误 " + error + "\"}";
}
if (!cateUpCheckRst.Contains("\"result\":1"))
{
Thread.Sleep(Randomx.GetId(1000, 2000));
var cateAuthorRst = WXUpload.addFinderCategoryV2(shop, leafCatId);
if (!cateAuthorRst.Contains("\"code\":0") && !cateAuthorRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref cateAuthorRst, "msg");
if (string.IsNullOrEmpty(error))
error = cateAuthorRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"类目申请错误 " + error + "\"}";
}
}
//todo //客服地址https://store.weixin.qq.com/shop/kf
// ai获取短标题
#region 短标题
WXGetShortTitleParam titleParam = new WXGetShortTitleParam()
{
categories = new List<categorieParam>(),
headImgUrls = upProdParam.product.info.headImg,
productTitle = upProdParam.product.info.title,
};
foreach (var cate in upProdParam.product.info.category)
{
titleParam.categories.Add(new categorieParam() { catId = cate.catId, catName = cate.name });
}
var shortTitleRst = WXUpload.genProductShortTitle(shop, titleParam);
if (!shortTitleRst.Contains("\"code\":0") && !shortTitleRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref shortTitleRst, "msg");
if (string.IsNullOrEmpty(error))
error = shortTitleRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"短标题获取失败 " + error + "\"}";
}
upProdParam.product.info.shortTitle = BaseRegex.GetStringJson(ref shortTitleRst, "shortTitle");
upProdParam.product.info.aiGenShortTitle = upProdParam.product.info.shortTitle;
#endregion
#region 售后信息
var addressRst = WXUpload.getAddress(shop);
if (!addressRst.Contains("\"code\":0") && !addressRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref addressRst, "msg");
if (string.IsNullOrEmpty(error))
error = addressRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"售后地址获取失败 " + error + "\"}";
}
upProdParam.product.info.afterSaleInfo = new afterSaleInfoParam();
upProdParam.product.info.afterSaleInfo.afterSaleAddressId = BaseRegex.GetStringJson(ref addressRst, "addressId");
#endregion
#region 运费模板
var expressRst = WXUpload.getFreightTemplate(shop);
if (!expressRst.Contains("\"code\":0") && !expressRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref expressRst, "msg");
if (string.IsNullOrEmpty(error))
error = expressRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"运费模板获取失败 " + error + "\"}";
}
upProdParam.product.info.expressInfo = new expressInfoParam();
upProdParam.product.info.expressInfo.templateId = BaseRegex.GetStringJson(ref expressRst, "templateId");
#endregion
if (cell != null)
{
Invoke(new Action(() =>
{
cell.Value = "正在生成商品详情";
}));
}
Thread.Sleep(Randomx.GetId(500, 800));
#region 详情图
upProdParam.product.info.detail = new productDetailParam(); // 详情图
foreach (var gallery_item in prodInfo.detail.galleries.Where(g => g.type == 2))
{
var locationStr = UploadImg(shop, gallery_item.url, cell);
if (!locationStr.Contains("\"success\":true"))
return locationStr;
var location = BaseRegex.GetStringJson(ref locationStr, "Location");
upProdParam.product.info.detail.detailImg.Add(location);
Thread.Sleep(Randomx.GetId(10, 50));
}
#endregion
#region 匹配产品属性
//真丝、蚕丝、香云纱、羊绒、羊毛、羊羔毛、羽绒、皮草
upProdParam.product.info.param = new List<propParam>(); // 商品属性值
var productAttr = upProdParam.product.info.category.LastOrDefault().catInfo.productAttr;
foreach (var propInfo in prodInfo.property.goods_properties)
{
var attr = productAttr.attr.FirstOrDefault(r => r.name == propInfo.name);
if (attr == null)
{
if (propInfo.name.Contains("面料俗称"))
{
attr = productAttr.attr.FirstOrDefault(r => r.name == "面料材质");
}
if (propInfo.name.Contains("适用年龄"))
{
attr = productAttr.attr.FirstOrDefault(r => r.name == "适用年龄" || r.name == "适用年龄段");
}
if (propInfo.name.Contains("填充物"))
{
attr = productAttr.attr.FirstOrDefault(r => r.name == "填充物种类" || r.name == "填充物");
}
}
if (attr == null)
{
continue;
}
var attrValueLst = attr.value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries).ToList();
var attrValue = attrValueLst.FirstOrDefault(v => v == propInfo.values.FirstOrDefault().value);
if (propInfo.name == "风格" && attrValue == null)
{
attrValue = attrValueLst.FirstOrDefault(v => v == propInfo.values.FirstOrDefault().value + "风");
}
if (attr.type == "string")
{
attrValue = propInfo.values.FirstOrDefault()?.value;
}
if (attrValue.IsNullOrEmpty() && attr.isRequired == true)
{
if (attrValueLst.Contains("其他"))
attrValue = "其他";
else if (attrValueLst.Contains("常规"))
attrValue = "常规";
else if (attrValueLst.Contains("通用"))
attrValue = "通用";
else
attrValue = attrValueLst.Where(v => !"真丝、蚕丝、香云纱、羊绒、羊毛、羊羔绒、羊羔毛、羽绒、皮草".Contains(v)).OrderBy(x => Guid.NewGuid()).FirstOrDefault();
}
if (attrValue.IsNullOrEmpty())
{
if (attrValueLst.Contains("其他"))
attrValue = "其他";
else if (attrValueLst.Contains("通用"))
attrValue = "通用";
}
if (attrValue.IsNullOrEmpty() && attr.type == "string")
{
attrValue = propInfo.values.FirstOrDefault()?.value;
}
if (attr.type == "decimal4_unit" || attr.type == "integer_unit")
{
if (attr.value == "%")
attrValue = "10 %";
else if (attr.value == "g;kg")
attrValue = "50 g";
else if (attr.value == "g")
attrValue = "10 g";
else if (attr.value == "kg")
attrValue = "1 kg";
}
if (string.IsNullOrEmpty(attrValue))
continue;
var wxPropParam = new propParam();
upProdParam.product.info.param.Add(wxPropParam);
var wxCategoryParam1 = new categoryPropParam()
{
catType = 7,
name = attr.name,
catInfo = new catInfoParam() { inputType = attr.normalRelease.ruleType, isRequired = attr.isRequired == true ? 1 : 0, isCustomize = 0 }
};
var wxCategoryParam2 = new categoryPropParam()
{
catType = 7,
name = attrValue,
catInfo = new catInfoParam() { inputType = attr.normalRelease.ruleType, isRequired = attr.isRequired == true ? 1 : 0, isCustomize = 0 }
};
wxPropParam.categorys.Add(wxCategoryParam1);
wxPropParam.categorys.Add(wxCategoryParam2);
}
foreach (var attr in productAttr.attr)
{
if (attr.isRequired != true)
continue;
// 已填写内没有但是必填属性
if (upProdParam.product.info.param.Any(p => p.categorys.FirstOrDefault()?.name == attr.name))
continue;
var attrValueLst = attr.value.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries).ToList();
string attrValue = "";
if (attr.type == "string")
{
attrValue = "其他";
}
if (attrValue.IsNullOrEmpty() && attr.isRequired == true)
{
if (attrValueLst.Contains("其他"))
attrValue = "其他";
else if (attrValueLst.Contains("常规"))
attrValue = "常规";
else if (attrValueLst.Contains("通用"))
attrValue = "通用";
else if (attr.value.Contains("绒丝;羽毛;白鸭绒;白鹅绒;灰鸭绒;灰鹅绒;鸭毛片;鹅毛片"))
{
attrValue = "绒丝";
}
else if (attrValueLst.Any(v => v.Contains("%")))
{
attrValue = attrValueLst.FirstOrDefault();
}
else
attrValue = attrValueLst.Where(v => !"真丝、蚕丝、香云纱、羊绒、羊毛、羊羔绒、羊羔毛、羽绒、皮草".Contains(v)).OrderBy(x => Guid.NewGuid()).FirstOrDefault();
}
if (attr.type == "decimal4_unit" || attr.type == "integer_unit")
{
if (attr.value == "%")
attrValue = "10 %";
else if (attr.value == "g;kg")
attrValue = "50 g";
else if (attr.value == "g")
attrValue = "10 g";
else if (attr.value == "kg")
attrValue = "1 kg";
}
var wxPropParam = new propParam();
upProdParam.product.info.param.Add(wxPropParam);
var wxCategoryParam1 = new categoryPropParam()
{
catType = 7,
name = attr.name,
catInfo = new catInfoParam() { inputType = attr.normalRelease.ruleType, isRequired = attr.isRequired == true ? 1 : 0, isCustomize = 0 }
};
var wxCategoryParam2 = new categoryPropParam()
{
catType = 7,
name = attrValue,
catInfo = new catInfoParam() { inputType = attr.normalRelease.ruleType, isRequired = attr.isRequired == true ? 1 : 0, isCustomize = 0 }
};
wxPropParam.categorys.Add(wxCategoryParam1);
wxPropParam.categorys.Add(wxCategoryParam2);
}
#endregion
if (cell != null)
{
Invoke(new Action(() =>
{
cell.Value = "正在生成sku";
}));
}
Thread.Sleep(1000);
#region sku规格属性
upProdParam.product.info.productSaleAttrs = new List<productSaleAttrParam>();
if (prodInfo.detail.sku.FirstOrDefault()?.spec?.Count > 0)
{
productSaleAttrParam attrParam = new productSaleAttrParam()
{
key = prodInfo.detail.sku.FirstOrDefault()?.spec[0].parent_name,
hasImg = true,
items = new List<productSaleAttrItemParam>()
};
upProdParam.product.info.productSaleAttrs.Add(attrParam);
foreach (var sku in prodInfo.detail.sku)
{
var spec = sku.spec[0];
if (!attrParam.items.Any(it => it.value == spec.spec_name))
{
// 上传sku图
var locationStr = UploadImg(shop, sku.thumb_url, cell);
if (!locationStr.Contains("\"success\":true"))
return locationStr;
var location = BaseRegex.GetStringJson(ref locationStr, "Location");
Thread.Sleep(Randomx.GetId(10, 50));
attrParam.items.Add(new productSaleAttrItemParam() { value = spec.spec_name, imgUrl = location, });
}
}
}
if (prodInfo.detail.sku.FirstOrDefault()?.spec?.Count > 1)
{
productSaleAttrParam attrParam = new productSaleAttrParam()
{
key = prodInfo.detail.sku.FirstOrDefault()?.spec[1].parent_name,
hasImg = false,
items = new List<productSaleAttrItemParam>()
};
upProdParam.product.info.productSaleAttrs.Add(attrParam);
foreach (var sku in prodInfo.detail.sku)
{
var spec = sku.spec[1];
if (!attrParam.items.Any(it => it.value == spec.spec_name))
attrParam.items.Add(new productSaleAttrItemParam() { value = spec.spec_name });
}
}
#endregion
#region sku信息
upProdParam.product.productSkus = new List<productSkuParam>();
int skuIndex = 0;
int id = 3;
long catId = 200000000003;
long fCatId = 200000000003;
long valueCatId = (17 + Randomx.GetNumber(11)).ParseToLong();
Dictionary<string, long> dicSpecParentNameId = new Dictionary<string, long>();
Dictionary<string, long> dicSpecParentNameCatId = new Dictionary<string, long>();
Dictionary<string, long> dicSpecNamefCatId = new Dictionary<string, long>();
Dictionary<string, long> dicSpecNameCatId = new Dictionary<string, long>();
foreach (var skuInfo in prodInfo.detail.sku)
{
foreach (var spec in skuInfo.spec)
{
if (!dicSpecParentNameId.Keys.Contains(spec.parent_name))
{
dicSpecParentNameId[spec.parent_name] = id++;
dicSpecParentNameCatId[spec.parent_name] = catId++;
}
if (!dicSpecNamefCatId.Keys.Contains(spec.spec_name))
{
dicSpecNamefCatId[spec.spec_name] = fCatId++;
dicSpecNameCatId[spec.spec_name] = valueCatId++;
}
}
}
foreach (var skuInfo in prodInfo.detail.sku)
{
productSkuParam skuParam = new productSkuParam();
upProdParam.product.productSkus.Add(skuParam);
for (int i = skuInfo.spec.Count - 1; i >= 0; i--)
{
var specInfo = skuInfo.spec[i];
skuParam.__skuKey = specInfo.parent_name + "." + specInfo.spec_name + "_";
skuParam.__skuKey += specInfo.spec_name;
}
skuParam.__skuKey.TrimEnd('_');
skuParam.index = skuIndex++;
skuParam.productSkuInfo = new productSkuInfoParam();
// 加价
skuParam.productSkuInfo.salePrice = (skuInfo.multi_price * defaultAddPriceRule.AddPriceTimes + defaultAddPriceRule.AddMorePrice * 100).ParseToInt();
if (defaultAddPriceRule.AddMorePriceFirst)
skuParam.productSkuInfo.salePrice = ((skuInfo.multi_price + defaultAddPriceRule.AddMorePrice * 100) * defaultAddPriceRule.AddPriceTimes).ParseToInt();
// 阶梯式加价,如果命中则按阶梯式加价进行
if (isStepAddPrice)
{
foreach (var addPrice in lstAddPriceRule)
{
if (skuInfo.multi_price > addPrice.MoreThanPrice * 100 && skuInfo.multi_price <= addPrice.LessThanPrice * 100)
{
if (defaultAddPriceRule.AddMorePriceFirst) // 先加后乘
skuParam.productSkuInfo.salePrice = ((skuInfo.multi_price + addPrice.AddMorePrice * 100) * addPrice.AddPriceTimes).ParseToInt();
else
skuParam.productSkuInfo.salePrice = (skuInfo.multi_price * addPrice.AddPriceTimes + addPrice.AddMorePrice * 100).ParseToInt();
break;
}
}
}
// sku图
skuParam.productSkuInfo.thumbImg = upProdParam.product.info.productSaleAttrs[0].items.FirstOrDefault(a => a.value == skuInfo.spec[0].spec_name)?.imgUrl;
// 库存
skuParam.productSkuInfo.stockInfo = new stockInfoParam() { stockNum = defaultAddPriceRule.StockNum };
skuParam.productSkuInfo.saleParam = new List<saleParamParam>();
foreach (var specInfo in skuInfo.spec)
{
saleParamParam saleParam = new saleParamParam();
skuParam.productSkuInfo.saleParam.Add(saleParam);
saleParam.categorys = new List<object>();
// specKey
categoryKeyParam skuCateKeyParam = new categoryKeyParam();
saleParam.categorys.Add(skuCateKeyParam);
skuCateKeyParam.isCustomize = true;
skuCateKeyParam.isMainSale = true;
skuCateKeyParam.name = specInfo.parent_name;
skuCateKeyParam.id = dicSpecParentNameId[specInfo.parent_name].ParseToInt(); // 3;
skuCateKeyParam.catId = dicSpecParentNameCatId[specInfo.parent_name];
skuCateKeyParam.label = "自定义规格";
skuCateKeyParam.catInfo = new skuCatInfoParam() { isCustomize = 1 };
skuCateKeyParam.catType = 8;
// specValue
categoryValueParam skuCateValueParam = new categoryValueParam();
saleParam.categorys.Add(skuCateValueParam);
skuCateValueParam.fCatId = dicSpecNamefCatId[specInfo.spec_name];
skuCateValueParam.catId = dicSpecNameCatId[specInfo.spec_name];
skuCateValueParam.name = specInfo.spec_name;
skuCateValueParam.skuNameValue = specInfo.spec_name;
skuCateValueParam.desc = "";
skuCateValueParam.catInfo = new categoryValueCatInfo() { editByUser = 1 };
skuCateValueParam.thumbImg = "";
var specIndex = skuInfo.spec.IndexOf(specInfo);
skuCateValueParam.priority = prodInfo.detail.sku.Select(s => s.spec[specIndex].spec_name).Distinct().ToList().IndexOf(specInfo.spec_name);
skuCateValueParam.selected = false;
}
skuParam.productSkuInfo.skuDeliverInfo = new skuDeliverInfoParam();
skuParam.productSkuInfo.stockDiff = new stockDiffParam() { diffType = 1, num = defaultAddPriceRule.StockNum };
skuParam.status = 5;
}
#endregion
if (cell != null)
{
Invoke(new Action(() =>
{
cell.Value = "正在提交商品";
}));
}
Thread.Sleep(Randomx.GetId(1000, 2000));
var uploadDraftRst = WXUpload.uploadProductDraft(shop, upProdParam);
if (!uploadDraftRst.Contains("\"code\":0") && !uploadDraftRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref uploadDraftRst, "msg");
if (string.IsNullOrEmpty(error))
error = uploadDraftRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"草稿保存失败 " + error + "\"}";
}
if (cell != null)
{
Invoke(new Action(() =>
{
var timeSpan = DateTime.Now - startTime;
var duration = timeSpan.TotalSeconds;
cell.Value = "商品已保存草稿,正在提交上架" + " " + duration.ParseToInt() + "秒";
}));
}
upProdParam.product.productKey.productId = BaseRegex.GetLongJson(ref uploadDraftRst, "productId").ParseToString();
upload_draft_products.Add(upProdParam);
if (chkUpDraft.Checked)
return "{\"success\":true,\"draftId\":" + upProdParam.product.productKey.productId + ",\"status\":\"草稿箱\",\"errMsg\":\"上架到草稿箱\"}";
// 提交商品上架
var uploadProdRst = WXUpload.upProductV2(shop, upProdParam);
if (!uploadProdRst.Contains("\"code\":0") && !uploadProdRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref uploadProdRst, "msg");
if (string.IsNullOrEmpty(error))
error = uploadProdRst;
return "{\"success\":false,\"draftId\":" + upProdParam.product.productKey.productId + ",\"status\":\"草稿箱\",\"errMsg\":\"上架失败 " + error + "\"}";
}
if (cell != null)
{
Invoke(new Action(() =>
{
var timeSpan = DateTime.Now - startTime;
var duration = timeSpan.TotalSeconds;
cell.Value = "商品已上传" + " " + duration.ParseToInt() + "秒";
}));
}
// 已传的商品保存为安全商品
if (dbProd.wx_safe_status == "未校验")
{
var url = BaseClass.BuildObjString("product/mdy_pdd_product");
var data = "";
Invoke(new Action(() =>
{
data = UserLogin.GetSignaturex();
data += "&spu_id=" + dbProd.spu_id;
data += "&wx_safe_status=安全商品";
}));
var html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
html = GetHtml.PostUtf8(url, data);
}
//colUploadCount
var dgvShopRow = dgvShop.Rows.Cast<DataGridViewRow>().FirstOrDefault(row => row.Cells["colShopId"]?.Value.ParseToString() == shop.ShopId);
if (dgvShopRow != null)
{
Invoke(new Action(() =>
{
dgvShopRow.Cells["colUploadCount"].Value = dgvShopRow.Cells["colUploadCount"].Value.ParseToInt() + 1;
}));
}
return "{\"success\":true,\"draftId\":" + upProdParam.product.productKey.productId + ",\"status\":\"已上传\",\"msg\":\"上传成功\"}";
}
public string UploadImg(ShopLoginInfo shop, string img_url, DataGridViewCell cell = null)
{
var upImgAuthRst = WXUpload.getUploadTempImgAuth(shop);
for (int i = 0; i < 10 && upImgAuthRst.Contains("LogicError"); i++)
{
if (cell != null)
{
Invoke(new Action(() =>
{
cell.Value = "图片提报失败,正在重试。";
}));
}
Thread.Sleep(Randomx.GetId(3000, 6000));
upImgAuthRst = WXUpload.getUploadTempImgAuth(shop);
}
if (!upImgAuthRst.Contains("\"code\":0"))
{
var error = BaseRegex.GetStringJson(ref upImgAuthRst, "msg");
if (string.IsNullOrEmpty(error))
error = upImgAuthRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"申请上传图片失败 " + error + "\"}";
}
string disK = BaseRegex.GetStringJson(ref upImgAuthRst, "disK");
long disT = BaseRegex.GetLongJson(ref upImgAuthRst, "disT");
string ext = BaseRegex.GetStringJson(ref upImgAuthRst, "ext");
string imgBase64 = "";
//-------------------------------------------------------------------------------------------------------------------------------------
//生成详情图base64字符串
string getImgError;
var image = GetHtml.GetUrlImg(img_url.Replace("https://", "http://"), out getImgError);
var imageBg = new Bitmap(image.Width, image.Height);
if (!string.IsNullOrEmpty(getImgError) || image == null)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"初始化图片上传失败\"}";
}
try
{
using (Graphics g = Graphics.FromImage(imageBg))
{
g.DrawImage(image, new Rectangle(0, 0, imageBg.Width, imageBg.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
}
using (MemoryStream memoryStream = new MemoryStream())
{
imageBg.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] imageBytes = memoryStream.ToArray();
imgBase64 = Convert.ToBase64String(imageBytes);
}
}
catch (Exception ex)
{
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"" + "修改图片失败 " + ex.Message + "\"}";
}
//-------------------------------------------------------------------------------------------------------------------------------------
//上传详情图,获取图片路径
var upImgRst = WXUpload.adtimageupload(shop, imgBase64, disK, disT, ext).ParseToString();
var location = BaseRegex.GetStringJson(ref upImgRst, "Location");
if (string.IsNullOrEmpty(location))
{
var error = BaseRegex.GetStringJson(ref upImgAuthRst, "msg");
if (string.IsNullOrEmpty(error))
error = upImgAuthRst;
return "{\"success\":false,\"draftId\":0,\"status\":\"未上传\",\"errMsg\":\"图片上传失败 " + error + "\"}";
}
return "{\"success\":true,\"location\":\"" + location + "\"}";
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
}
private void btnStop_Click(object sender, EventArgs e)
{
if (this.cancellationTokenSource != null)
this.cancellationTokenSource.Cancel();
}
private void btnRandomAdd_Click(object sender, EventArgs e)
{
int addCount = txtAddCount.Text.Trim().ParseToInt();
Task.Run(() =>
{
List<KJDDBProduct> prodLst = new List<KJDDBProduct>();
while (addCount > 0)
{
int prodCount = 0;
// 如果产品数量在0到50之间,说明数据库商品数量不足,无需再重复筛选,直接随机打乱
if (prodLst.Count == 0 || prodLst.Count == Math.Min(50, addCount))
{
prodLst = GetRandomProductList(out prodCount, 1, Math.Min(50, addCount));
Thread.Sleep(Randomx.GetId(50, 100));
}
else
{
prodLst = prodLst.OrderBy(x => Guid.NewGuid()).ToList();
Thread.Sleep(Randomx.GetId(10, 30));
}
Invoke(new Action(() =>
{
lblGoodsCount.Text = "产品库 " + prodCount + " 件";
}));
if (prodLst.Count == 0) // 等于0要么库里没数据要么出错了,跳出
break;
foreach (var prod in prodLst)
{
var selectProd = JsonHelper.DeserializeJsonToObject<TemuDBProductSelect>(JsonHelper.SerializeObject(prod));
selectProd.out_product_Id = prod.id.ToString();
selectProd.id = 1;
if(lstTemuDBProductSelect.Count > 0)
selectProd.id = lstTemuDBProductSelect.Max(p => p.id) + 1;
this.lstTemuDBProductSelect.Add(selectProd);
Invoke(new Action(() =>
{
lblWaitToUp.Text = "待上传 " + lstTemuDBProductSelect.Count + " 件";
}));
addCount--;
if (addCount <= 0)
break;
}
NaiBa.Util.Helper.ConfigHelper.SaveConfig("wx_db_prod_upload_list", this.lstTemuDBProductSelect);
}
});
}
public List<KJDDBProduct> GetRandomProductList(out int totalCount, int page = 1, int pageSize = 50)
{
var lstShopId = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colSelect"]?.Value.ParseToBool() == true).Select(r => r.Cells["colShopId"]?.Value.ToString()).ToList();
List<KJDDBProduct> list = new List<KJDDBProduct>();
int pageCount = 1;
totalCount = 0;
var url = BaseClass.BuildObjString("product/get_pdd_product_list_random");
var data = "";
Invoke(new Action(() =>
{
data = UserLogin.GetSignaturex() +
"&page=" + 1 +
"&page_size=" + pageSize;
data += "&in_ext_codes=" + txtExtCodeFilter.Text;
data += "&in_skc_ids=" + txtIdFilter.Text;
data += "&in_groups=" + cmbGroupFilter.Text;
data += "&in_cates=" + cmbCateFilter.Text;
data += "&product_get_type=" + cmbSourceType.Text.Trim();
data += "&wx_safe_status=" + cmbWxSafe.Text.Trim();
}));
var html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
html = GetHtml.PostUtf8(url, data);
if (string.IsNullOrEmpty(html) || !html.Contains("\"code\":200"))
{
Invoke(new Action(() =>
{
BaseMsgForm.ShowError("获取商品失败,请重试!" + BaseRegex.GetStringJson(ref html, "msg"));
}));
return new List<KJDDBProduct>();
}
int count = BaseRegex.GetIntJson(ref html, "count");
totalCount = count;
pageCount = Math.Ceiling(1.0 * count / pageSize).ParseToInt();
pageCount = Math.Max(pageCount, 1);
var jArr = JObject.Parse(html)["data"];
if (jArr.Count() == 0)
return list;
var sProd = JsonHelper.SerializeObject(jArr);
try
{
list = JsonHelper.DeserializeJsonToList<KJDDBProduct>(sProd);
return list;
}
catch (Exception ex)
{
return new List<KJDDBProduct>();
}
}
private void btnClearUpload_Click(object sender, EventArgs e)
{
if (BaseMsgForm.ShowConfirm("确定清空待上传商品吗?清空后不可恢复!").DialogResult == DialogResult.Cancel)
return;
this.lstTemuDBProductSelect.Clear();
NaiBa.Util.Helper.ConfigHelper.SaveConfig("wx_db_prod_upload_list", this.lstTemuDBProductSelect);
lblWaitToUp.Text = "待上传 " + lstTemuDBProductSelect.Count + " 件";
}
private void lblNewAddPrice_Click(object sender, EventArgs e)
{
var ucPrice = new UcAddPrice();
if (IsSetFontScaleNone)
{
Font of = ucPrice.Font;
Font nf = new Font(of.FontFamily, (of.Size * 96.0 / FormDpi).ParseToFloat(), of.Style, of.Unit, of.GdiCharSet, of.Bold);
ucPrice.Font = nf;
}
ucPrice.PriceChange += ucAddPrice_PriceChange;
this.fPnlPriceRule.Controls.Add(ucPrice);
}
private void ucAddPrice_PriceChange(object obj)
{
List<AddPriceRule> priceRuleLst = new List<AddPriceRule>();
foreach (var ucItem in fPnlPriceRule.Controls)
{
var ucPrice = ucItem as UcAddPrice;
if (ucPrice != null)
{
priceRuleLst.Add(new AddPriceRule()
{
AddMorePrice = ucPrice.PriceAddMore,
AddPriceTimes = ucPrice.PriceAddTimes,
LessThanPrice = ucPrice.PriceEnd,
MoreThanPrice = ucPrice.PriceStart,
SinglePriceAdd = ucPrice.SinglePriceAdd,
});
}
}
this.lstAddPriceRule.Clear();
this.lstAddPriceRule.AddRange(priceRuleLst);
NaiBa.Util.Helper.ConfigHelper.SaveConfig("wx_add_price_rules", lstAddPriceRule);
}
private void txtAddPrice_TextChanged(object sender, EventArgs e)
{
if (IsLoadComplate)
{
defaultAddPriceRule.AddPriceTimes = txtAddTimes.Text.Trim().ParseToDecimal();
defaultAddPriceRule.AddMorePrice = txtAddMorePrice.Text.Trim().ParseToDecimal();
defaultAddPriceRule.SinglePriceAdd = txtSinglePriceAdd.Text.Trim().ParseToDecimal();
defaultAddPriceRule.StockNum = txtStockNum.Text.Trim().ParseToInt();
NaiBa.Util.Helper.ConfigHelper.SaveConfig<AddPriceRule>("wx_default_add_price_rule", defaultAddPriceRule);
}
}
private void chkStepAddPrice_CheckedChanged(object sender, EventArgs e)
{
isStepAddPrice = this.chkStepAddPrice.Checked;
}
private void btnClearDgv_Click(object sender, EventArgs e)
{
//this.dgvSelectProduct.Rows.Clear();
var rows = this.dgvSelectProduct.Rows.Cast<DataGridViewRow>().ToList(); //Cast后Rows做foreach循环时仍会夹花跳过,所以要ToList转一个新的数组。
foreach (var row in rows)
{
if (row.Cells["colCheck"].Value.ParseToBool() == true)
this.dgvSelectProduct.Rows.Remove(row);
}
}
private void chkAddMorePriceFirst_CheckedChanged(object sender, EventArgs e)
{
if (IsLoadComplate)
{
defaultAddPriceRule.AddMorePriceFirst = chkAddMorePriceFirst.Checked;
NaiBa.Util.Helper.ConfigHelper.SaveConfig("wx_default_add_price_rule", defaultAddPriceRule);
}
}
private void lblGoodsCount_Click(object sender, EventArgs e)
{
//PDDDBProdListForm f = new PDDDBProdListForm();
//f.Width = 1366;
//f.Height = 768;
//f.ShowMaximizeBox = true;
//f.ShowDialog();
}
private void lblWaitToUp_Click(object sender, EventArgs e)
{
PDDDBProdUserSelectCacheForm selectCacheForm = new PDDDBProdUserSelectCacheForm(lstTemuDBProductSelect);
selectCacheForm.ShowDialog();
lblWaitToUp.Text = "待上传 " + lstTemuDBProductSelect.Count + " 件";
}
private void btnClearFilter_Click(object sender, EventArgs e)
{
txtIdFilter.Text = "";
txtExtCodeFilter.Text = "";
cmbGroupFilter.Text = "";
cmbCateFilter.Text = "";
cmbWxSafe.SelectedIndex = 0;
int prodCount;
GetRandomProductList(out prodCount, 1, 1);
lblGoodsCount.Text = "产品库 " + prodCount + " 件";
}
private void 并发上传_Click(object sender, EventArgs e)
{
var draftIdLst = dgvSelectProduct.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colCheck"]?.Value.ParseToBool() == true).Select(r => r.Cells["colDraftId"]?.Value.ToString()).ToList();
// var lst = NaiBa.Util.Helper.ConfigHelper.LoadConfig<NaiBa.Util.ConcurrentList<WXUploadProductParam>>("wx_upload_draft_products");
// if (lst == null)
// lst = new ConcurrentList<WXUploadProductParam>();
var lst = upload_draft_products;
var upLst = lst.Where(l => draftIdLst.Contains(l.product.productKey.productId)).ToList();
DateTime startTime = DateTime.Now;
Task.Run(() =>
{
List<Task> tLst = new List<Task>();
foreach (var prodParam in upLst)
{
var row = this.dgvSelectProduct.Rows.Cast<DataGridViewRow>().FirstOrDefault(r => r.Cells["colDraftId"].Value.ParseToString() == prodParam.product.productKey.productId);
if (row == null)
continue;
var shop = GlobalConfig.ShopLoginList.FirstOrDefault(s => s.ShopId == row.Cells["colSupplierId"].Value.ParseToString());
if (shop == null)
continue;
var t =Task.Run(() =>
{
UploadSameTime(shop, prodParam, row.Cells["colOpResult"]);
});
tLst.Add(t);
}
Task.WaitAll(tLst.ToArray());
var duration = DateTime.Now - startTime;
Invoke(new Action(() => { BaseMsgForm.ShowInfo("并发上传完成,耗时:" + duration.TotalSeconds + " 秒"); }));
});
}
public ConcurrentList<WXUploadProductParam> upload_draft_products = new ConcurrentList<WXUploadProductParam>();
void UploadSameTime(ShopLoginInfo shop, WXUploadProductParam upProdParam, DataGridViewCell cell)
{
var uploadProdRst = WXUpload.upProductV2(shop, upProdParam);
int retryTimes = 0;
while (!uploadProdRst.Contains("\"code\":0") && !uploadProdRst.Contains("\"success\":true"))
{
retryTimes++;
uploadProdRst = WXUpload.upProductV2(shop, upProdParam);
if (retryTimes >= 5)
break;
}
if (!uploadProdRst.Contains("\"code\":0") && !uploadProdRst.Contains("\"success\":true"))
{
var error = BaseRegex.GetStringJson(ref uploadProdRst, "msg");
if (string.IsNullOrEmpty(error))
error = uploadProdRst;
if (cell != null)
{
Invoke(new Action(() =>
{
cell.Value = "商品上传失败 " + error;
}));
}
}
else
{
if (cell != null)
{
upload_draft_products.Remove(upProdParam);
Invoke(new Action(() =>
{
cell.Value = "商品已上传,重试次数 " + retryTimes;
}));
}
var dgvShopRow = dgvShop.Rows.Cast<DataGridViewRow>().FirstOrDefault(row => row.Cells["colShopId"]?.Value.ParseToString() == shop.ShopId);
if (dgvShopRow != null)
{
Invoke(new Action(() =>
{
dgvShopRow.Cells["colUploadCount"].Value = dgvShopRow.Cells["colUploadCount"].Value.ParseToInt() + 1;
}));
}
}
}
}
public class WXUpload
{
public static string searchProduct(ShopLoginInfo shop, string extCode)
{
string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/searchProduct?" +
"token=&lang=zh_CN&pageSize=20&productStatus[]=-1&productSource=[1,16,32]&searchSource=1&useNew=true&pageNum=1&status[]=5&spuCode=" + extCode;
string refere = "https://store.weixin.qq.com/shop/goods/list?currentTab=PRODUCT_STATUS_ON";
var result = WXHttpResponseBLL.WeiXinGetResponse(shop, url, refere);
return result;
}
public static string getUploadTempImgAuth(ShopLoginInfo shop, int uploadScene = 3)
{
string url = "https://store.weixin.qq.com/shop-faas/mmecchannelspicture/cgi/getUploadTempImgAuth?token=&lang=zh_CN&uploadScene=" + uploadScene;
string refere = "https://store.weixin.qq.com/shop/goods/entry";
//{"code":0,"disK":"538c14e950da7b678ce9f5a12658c8acddd09e4b","disT":1767870926,"ext":"23aa0ecfb792a","url":"https://westore.video.qq.com/adtimageupload"}
var result = WXHttpResponseBLL.WeiXinGetResponse(shop, url, refere);
return result;
}
public static string adtimageupload(ShopLoginInfo shop, string imgBase64, string dis_k, long dis_t, string ext)
{
string url = "https://westorealpha.video.qq.com/adtimageupload";
string referer = "https://store.weixin.qq.com/";
string body = imgBase64;
var result = WXHttpResponseBLL.WeiXinImgPostResponse(shop, url, body, dis_k, dis_t, ext, referer);
return result;
}
public static string getProductClassify(ShopLoginInfo shop, string goodsName, List<string> goodImgUrlsLst)
{
string boundaryLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
string boundaryStr = "----WebKitFormBoundary";
for (int i = 0; i < 16; i++)
{
boundaryStr += boundaryLetters[Randomx.GetId(boundaryLetters.Length)];
}
string url = "https://store.weixin.qq.com/shop-faas/cgi/common/productClassify?from=B&title=" + GetHtml.UrlEncodeUtf8(goodsName) + "&token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
string body = @"--" + boundaryStr + @"
";
foreach (var imgFullPath in goodImgUrlsLst)
{
string fileName = imgFullPath.Split('\\').LastOrDefault();
body += @"Content-Disposition: form-data; name=""file""; filename=""" + fileName + @"""
Content-Type: image/jpeg
<!>" + imgFullPath + @"<!>
--" + boundaryStr;
}
body += @"--
";
var result = WXHttpResponseBLL.WeiXinUploadResponse(shop, url, body, boundaryStr, referer);
return result;
}
public static string getCategoryOnShelf(ShopLoginInfo shop, List<long> catIdLst)
{
string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/product/getCategoryOnShelfV2?token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
string body = @"{""catIdList"":[" + string.Join(",", catIdLst) + @"],""brandId"":2100000000}";
var result = WXHttpResponseBLL.WeiXinPostResponse(shop, url, body, referer);
return result;
}
public static string batchCheckCategoryRelation(ShopLoginInfo shop, long catId)
{
string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/product/batchCheckCategoryRelation?token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
string body = @"{""categoryIdList"":[" + catId + "]}";
var result = WXHttpResponseBLL.WeiXinPostResponse(shop, url, body, referer);
return result;
}
public static string addFinderCategoryV2(ShopLoginInfo shop, long catId)
{
string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradecategory/cgi/addFinderCategoryV2?token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
string body = @"{""categoryInfo"":{""categories"":[{""id"":""" + catId + @"""}]},""brandIdList"":[],""leafCategoryId"":""" + catId + @""",""reuse"":0,""applyType"":1}";
var result = WXHttpResponseBLL.WeiXinPostResponse(shop, url, body, referer);
return result;
}
public static string genProductShortTitle(ShopLoginInfo shop, WXGetShortTitleParam getShortTitleParam)
{
string url = "https://store.weixin.qq.com/shop-faas/mmecnodeproductupload/common/cgi/goods/genProductShortTitle?token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
string body = JsonHelper.SerializeObject(getShortTitleParam);
//{"productTitle":"妈妈老年中年阔脚裤冬季秋季时尚牛仔裤","headImgUrls":["https://wst.wxapp.tc.qq.com/160/20304/snscosdownload/SH/reserved/6xykWLEnztKEVU0iahAM7HQ28puCia87zPkvSbFT8Fcia99g2ZNWRdy8licxD6qwsqV4bCicoxwQF9e6jh3qwibgzxuA?token=x5Y29zUxcibCe0pFyoSA8zb1aYVKnIBLkQ8ZUXMcwEq3qYHsko3TDzv2rsL2AfJPd&idx=1&expire=1768211170","https://wst.wxapp.tc.qq.com/160/20304/snscosdownload/SH/reserved/6xykWLEnztKEVU0iahAM7Hbwaw1AboTKxjGsLhJgVreuYNxwyQxrk9RtvCv3XsXSnic9WfBFMAIZYpNgYkWd7VDQ?token=x5Y29zUxcibCe0pFyoSA8zb1aYVKnIBLk4qWUsS2WZiaCjXhZLj0D6PYyddX71qNiat&idx=1&expire=1768211170","https://wst.wxapp.tc.qq.com/160/20304/snscosdownload/SH/reserved/6xykWLEnztKEVU0iahAM7HTa1Ej2xJpy6Ej84arVO7A3vxIDD1XP6ZRVw43OficKLXPcXPUvDNmc8A4lMHCgbic3A?token=x5Y29zUxcibCe0pFyoSA8zb1aYVKnIBLkhejArCiaiaLIEKtvOicA5chibIj1tfELV0Mm&idx=1&expire=1768211170"],"categories":[{"catId":"10000111","catName":"服饰内衣"},{"catId":"10000113","catName":"女装"},{"catId":"10000672","catName":"裤子"},{"catId":"547705","catName":"牛仔裤"}]}
var result = WXHttpResponseBLL.WeiXinPostResponse(shop, url, body, referer);
return result;
}
public static string getFreightTemplate(ShopLoginInfo shop)
{
string url = "https://store.weixin.qq.com/shop-faas/mmecnodeproductupload/express/cgi/goods/getFreightTemplate?token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
var result = WXHttpResponseBLL.WeiXinGetResponse(shop, url, referer);
return result;
}
/// <summary>
/// 取售后地址
/// </summary>
/// <param name="shop"></param>
/// <returns></returns>
public static string getAddress(ShopLoginInfo shop)
{
string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeexpress/cgi/getAddress?token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
var result = WXHttpResponseBLL.WeiXinGetResponse(shop, url, referer);
return result;
}
public static string uploadProductDraft(ShopLoginInfo shop, WXUploadProductParam prodParam)
{
string url = "https://store.weixin.qq.com/shop-faas/mmecnodeproductupload/common/cgi/goods/uploadProductDraft?token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
JsonSerializerSettings jsonSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
var prodStr = JsonConvert.SerializeObject(prodParam, jsonSetting);
JObject jObj = new JObject();
jObj.Add("data", prodStr);
string body = JsonHelper.SerializeObject(jObj);
var result = WXHttpResponseBLL.WeiXinPostResponse(shop, url, body, referer);
return result;
}
public static string upProductV2(ShopLoginInfo shop, WXUploadProductParam prodParam)
{
string url = "https://store.weixin.qq.com/shop-faas/mmchannelstradeproductcore/cgi/goods/upProductV2?token=&lang=zh_CN";
string referer = "https://store.weixin.qq.com/shop/goods/entry";
JsonSerializerSettings jsonSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
var prodStr = JsonConvert.SerializeObject(prodParam, jsonSetting);
JObject jObj = new JObject();
jObj.Add("data", prodStr);
string body = JsonHelper.SerializeObject(jObj);
var result = WXHttpResponseBLL.WeiXinPostResponse(shop, url, body, referer);
return result;
}
}
public class AddPriceRule
{
/// <summary>
/// 加价金额区间大于 不包含
/// </summary>
public decimal MoreThanPrice { get; set; }
/// <summary>
/// 加价金额区间小于 包含
/// </summary>
public decimal LessThanPrice { get; set; }
/// <summary>
/// 加价倍数
/// </summary>
public decimal AddPriceTimes { get; set; }
/// <summary>
/// 额外加价金额
/// </summary>
public decimal AddMorePrice { get; set; }
/// <summary>
/// 单买加价
/// </summary>
public decimal SinglePriceAdd { get; set; }
/// <summary>
/// 先加后乘
/// </summary>
public bool AddMorePriceFirst { get; set; } = false;
/// <summary>
/// 上货库存量设置
/// </summary>
public int StockNum { get; set; } = 0;
}
public class WXUploadRule
{
public bool IsUseUpperSizeSpec { get; set; } = true;
public bool IsKeepChanceGoodImg { get; set; } = true;
/// <summary>
/// 是否报名活动(提交一个虚拟高倍率加价再通过活动价格实现商品原价)
/// </summary>
public bool IsSignActivity { get; set; } = true;
/// <summary>
/// 准备报名活动的商品原价加价倍率
/// </summary>
public decimal ActivityAddPriceTimes { get; set; } = 3m;
public bool IsLowPriceSku { get; set; } = true;
public string LowPriceSkuName { get; set; } = "福利款";
public decimal LowPriceSkuLowestPrice { get; set; } = 5m;
/// <summary>
/// 升级版
/// </summary>
public bool IsUpgradeVersion { get; set; } = false;
public string UpgradeVersionName { get; set; } = "升级版";
/// <summary>
/// 升级版额外加价
/// </summary>
public decimal UpgradeVersionAddPrice { get; set; } = 1m;
public bool IsUseExtCodePrice { get; set; }
public bool sign20981 { get; set; }
public bool sign22347 { get; set; }
public bool sign15996 { get; set; }
public bool sign21365 { get; set; }
}
}