增加 AI识图检测,个人收藏产品检测

This commit is contained in:
chfei committed 2026-11-09 14:38:03 +08:00
commit 09098efd34
45 files changed
+2932 -631

No files matched your search

+4
View File
@@ -117,6 +117,10 @@ namespace AllBase
public static decimal PostagePerOrder { get; set; } = 2.2m;
public static decimal RefundPostagePerOrder { get; set; } = 2.5m;
public static decimal GiftOemAmountPerOrder { get; set; } = 0m;
/// <summary>
/// 图片检测配额
/// </summary>
public static int ImageAnalysisQuota { get; set; }
/// <summary>
/// 采集最低销量
/// </summary>
+10
View File
@@ -127,8 +127,18 @@ namespace AllBase.Helper
Alibaba = 6,
}
public sealed class ComplianceOptions
{
public int? MainCount { get; set; }
public int? DetailCount { get; set; } = 0;
public bool IncludeSku { get; set; }
public string Keywords { get; set; }
}
public class GlobalSettings
{
public ComplianceOptions GoodsCompliance { get; set; } = new ComplianceOptions();
/// <summary>
/// 微信使用软件设置的默认上货地址
/// </summary>
+146 -130
View File
@@ -8,6 +8,7 @@ using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace CsharpHttpHelper
@@ -52,6 +53,16 @@ namespace CsharpHttpHelper
});
}
public static Task<HttpResult> GetAsync(string Url)
{
return RequestAsync(new HttpItem { URL = Url, Method = MethodType.Get });
}
public static Task<HttpResult> PostAsync(string Url, string PostData)
{
return RequestAsync(new HttpItem { URL = Url, Method = MethodType.Post, Postdata = PostData });
}
/// <summary>
/// 下载文件
/// </summary>
@@ -77,17 +88,13 @@ namespace CsharpHttpHelper
public static HttpResult Request(HttpItem item)
{
HttpResult result = new HttpHelper().GetHtml(item);
if (!string.IsNullOrEmpty(result.Html))
{
if (result.Html[0] == 65279)
{
result.Html = result.Html.Remove(0, 1);
}
}
return result;
return new HttpHelper().GetHtml(item);
}
public static Task<HttpResult> RequestAsync(HttpItem item)
{
return new HttpHelper().GetHtmlCoreAsync(item);
}
#region Cookie
/// <summary>
@@ -137,8 +144,6 @@ namespace CsharpHttpHelper
private Encoding postencoding = Encoding.Default;
//HttpWebRequest对象用来发起请求
private HttpWebRequest request = null;
//获取影响流的数据对象
private HttpWebResponse response = null;
/// <summary>
/// 根据相传入的数据,得到相应页面数据
/// </summary>
@@ -146,61 +151,150 @@ namespace CsharpHttpHelper
/// <returns>返回HttpResult类型</returns>
public HttpResult GetHtml(HttpItem item)
{
//返回参数
HttpResult result = new HttpResult();
result.item = item;
try
{
//准备参数
SetRequest(item);
if (item.Method == MethodType.Post || item.Method == MethodType.Put)
{
byte[] body;
if (item.PostDataType == PostDataType.FilePath && !string.IsNullOrEmpty(item.Postdata))
{
using var reader = new StreamReader(item.Postdata, postencoding);
body = postencoding.GetBytes(reader.ReadToEnd());
}
else body = GetPostBytes(item);
if (body != null)
{
request.ContentLength = body.Length;
using var stream = request.GetRequestStream();
stream.Write(body, 0, body.Length);
}
}
}
catch (Exception ex)
{
result = new HttpResult();
result.Cookie = string.Empty;
result.Header = null;
result.Html = ex.Message;
result.StatusDescription = "配置参数时出错:" + ex.Message;
return result;
return ConfigurationError(ex);
}
var result = new HttpResult { item = item };
try
{
#region 得到请求的response
using (response = (HttpWebResponse)request.GetResponse())
using var response = (HttpWebResponse)request.GetResponse();
SetResponseHeaders(result, response);
if (response.Cookies != null) result.CookieCollection = response.Cookies;
result.Cookie = response.Headers["set-cookie"];
using var source = OpenResponseStream(response);
using var buffer = new MemoryStream();
source.CopyTo(buffer);
DecodeBody(item, result, response, buffer.ToArray());
}
catch (WebException ex) when (ex.Response is HttpWebResponse)
{
using var response = (HttpWebResponse)ex.Response;
SetResponseHeaders(result, response);
using var reader = new StreamReader(OpenResponseStream(response), item.Encoding ?? Encoding.UTF8);
result.Html = reader.ReadToEnd();
}
catch (Exception ex)
{
result.Html = ex.Message;
}
if (item.IsToLower) result.Html = result.Html.ToLower();
return result;
}
public Task<HttpResult> GetHtmlAsync(HttpItem item)
{
// 每次异步调用独立保存请求和编码,允许同一实例并发使用。
return new HttpHelper().GetHtmlCoreAsync(item);
}
private async Task<HttpResult> GetHtmlCoreAsync(HttpItem item)
{
using var timeout = new CancellationTokenSource();
using var abort = timeout.Token.Register(() => request.Abort());
try
{
SetRequest(item);
timeout.CancelAfter(request.Timeout);
if (item.Method == MethodType.Post || item.Method == MethodType.Put)
{
byte[] body;
if (item.PostDataType == PostDataType.FilePath && !string.IsNullOrEmpty(item.Postdata))
{
using var reader = new StreamReader(item.Postdata, postencoding);
body = postencoding.GetBytes(await reader.ReadToEndAsync().ConfigureAwait(false));
}
else body = GetPostBytes(item);
if (body != null)
{
request.ContentLength = body.Length;
using var stream = await request.GetRequestStreamAsync().ConfigureAwait(false);
await stream.WriteAsync(body, 0, body.Length).ConfigureAwait(false);
}
}
}
catch (Exception ex)
{
return ConfigurationError(ex);
}
var result = new HttpResult { item = item };
try
{
using var response = (HttpWebResponse)await request.GetResponseAsync().ConfigureAwait(false);
SetResponseHeaders(result, response);
if (response.Cookies != null) result.CookieCollection = response.Cookies;
result.Cookie = response.Headers["set-cookie"];
using var source = OpenResponseStream(response);
using var buffer = new MemoryStream();
await source.CopyToAsync(buffer).ConfigureAwait(false);
DecodeBody(item, result, response, buffer.ToArray());
}
catch (WebException ex) when (ex.Response is HttpWebResponse)
{
using var response = (HttpWebResponse)ex.Response;
SetResponseHeaders(result, response);
using var reader = new StreamReader(OpenResponseStream(response), item.Encoding ?? Encoding.UTF8);
result.Html = await reader.ReadToEndAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
result.Html = ex.Message;
}
if (item.IsToLower) result.Html = result.Html.ToLower();
return result;
}
private static HttpResult ConfigurationError(Exception ex)
{
return new HttpResult { Cookie = string.Empty, Html = ex.Message, StatusDescription = "配置参数时出错:" + ex.Message };
}
private static void SetResponseHeaders(HttpResult result, HttpWebResponse response)
{
result.StatusCode = response.StatusCode;
result.StatusDescription = response.StatusDescription;
result.Header = response.Headers;
if (response.Cookies != null) result.CookieCollection = response.Cookies;
if (response.Headers["set-cookie"] != null) result.Cookie = response.Headers["set-cookie"];
MemoryStream _stream = new MemoryStream();
//GZIIP处理
if (response.ContentEncoding != null && response.ContentEncoding.Equals("gzip", StringComparison.InvariantCultureIgnoreCase))
{
//开始读取流并设置编码方式
//new GZipStream(response.GetResponseStream(), CompressionMode.Decompress).CopyTo(_stream, 10240);
//.net4.0以下写法
_stream = GetMemoryStream(new GZipStream(response.GetResponseStream(), CompressionMode.Decompress));
}
}
else
private static Stream OpenResponseStream(HttpWebResponse response)
{
//开始读取流并设置编码方式
//response.GetResponseStream().CopyTo(_stream, 10240);
//.net4.0以下写法
_stream = GetMemoryStream(response.GetResponseStream());
var stream = response.GetResponseStream();
return string.Equals(response.ContentEncoding, "gzip", StringComparison.OrdinalIgnoreCase)
? new GZipStream(stream, CompressionMode.Decompress) : stream;
}
//获取Byte
byte[] ResponseByte = _stream.ToArray();
_stream.Close();
if (ResponseByte != null & ResponseByte.Length > 0)
private void DecodeBody(HttpItem item, HttpResult result, HttpWebResponse response, byte[] bytes)
{
if (bytes.Length > 0)
{
//是否返回Byte类型数据
if (item.ResultType == ResultType.Byte) result.ResultByte = ResponseByte;
if (item.ResultType == ResultType.Byte) result.ResultByte = bytes;
//从这里开始我们要无视编码了
if (encoding == null)
{
Match meta = Regex.Match(Encoding.Default.GetString(ResponseByte), "<meta([^<]*)charset=([^<]*)[\"']", RegexOptions.IgnoreCase);
Match meta = Regex.Match(Encoding.Default.GetString(bytes), "<meta([^<]*)charset=([^<]*)[\"']", RegexOptions.IgnoreCase);
string c = (meta.Groups.Count > 1) ? meta.Groups[2].Value.ToLower().Trim() : string.Empty;
if (c.Length > 2)
{
@@ -222,7 +316,7 @@ namespace CsharpHttpHelper
}
}
//得到返回的HTML
result.Html = encoding.GetString(ResponseByte);
result.Html = encoding.GetString(bytes);
}
else
{
@@ -230,53 +324,6 @@ namespace CsharpHttpHelper
result.Html = "本次请求并未返回任何数据";
}
}
#endregion
}
catch (WebException ex)
{
//这里是在发生异常时返回的错误信息
response = (HttpWebResponse)ex.Response;
result.Html = ex.Message;
if (response != null)
{
using (response)
{
result.StatusCode = response.StatusCode;
result.StatusDescription = response.StatusDescription;
result.Header = response.Headers;
// 保留错误响应正文,供微信调用方识别业务错误和登录失效。
using (var source = response.GetResponseStream())
using (var decoded = string.Equals(response.ContentEncoding, "gzip", StringComparison.OrdinalIgnoreCase)
? (Stream)new GZipStream(source, CompressionMode.Decompress) : source)
using (var reader = new StreamReader(decoded, item.Encoding ?? Encoding.UTF8))
result.Html = reader.ReadToEnd();
}
}
}
catch (Exception ex)
{
result.Html = ex.Message;
}
if (item.IsToLower) result.Html = result.Html.ToLower();
return result;
}
/// <summary>
/// 4.0以下.net版本取数据使用
/// </summary>
/// <param name="streamResponse">流</param>
private MemoryStream GetMemoryStream(Stream streamResponse)
{
MemoryStream _stream = new MemoryStream();
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = streamResponse.Read(buffer, 0, Length);
while (bytesRead > 0)
{
_stream.Write(buffer, 0, bytesRead);
bytesRead = streamResponse.Read(buffer, 0, Length);
}
return _stream;
}
/// <summary>
/// 为请求准备参数
/// </summary>
@@ -308,6 +355,7 @@ namespace CsharpHttpHelper
request.UserAgent = item.UserAgent;
// 编码
encoding = item.Encoding;
if (item.Method != MethodType.Get && item.PostEncoding != null) postencoding = item.PostEncoding;
//设置安全凭证
request.Credentials = item.ICredentials;
//设置Cookie
@@ -316,8 +364,6 @@ namespace CsharpHttpHelper
request.Referer = item.Referer;
//是否执行跳转功能
request.AllowAutoRedirect = item.Allowautoredirect;
//设置Post数据
SetPostData(item);
//设置最大连接
if (item.Connectionlimit > 0) request.ServicePoint.ConnectionLimit = item.Connectionlimit;
}
@@ -373,43 +419,13 @@ namespace CsharpHttpHelper
request.CookieContainer.Add(item.CookieCollection);
}
}
/// <summary>
/// 设置Post数据
/// </summary>
/// <param name="item">Http参数</param>
private void SetPostData(HttpItem item)
private byte[] GetPostBytes(HttpItem item)
{
//验证在得到结果时是否有传入数据
if (request.Method.Trim().ToLower().Contains("post") || request.Method.Trim().ToLower().Contains("put"))
{
if (item.PostEncoding != null)
{
postencoding = item.PostEncoding;
}
byte[] buffer = null;
//写入Byte类型
if (item.PostDataType == PostDataType.Byte && item.PostdataByte != null && item.PostdataByte.Length > 0)
{
//验证在得到结果时是否有传入数据
buffer = item.PostdataByte;
}//写入文件
else if (item.PostDataType == PostDataType.FilePath && !string.IsNullOrEmpty(item.Postdata))
{
StreamReader r = new StreamReader(item.Postdata, postencoding);
buffer = postencoding.GetBytes(r.ReadToEnd());
r.Close();
} //写入字符串
else if (!string.IsNullOrEmpty(item.Postdata))
{
buffer = postencoding.GetBytes(item.Postdata);
}
if (buffer != null)
{
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
}
}
if (item.PostDataType == PostDataType.Byte && item.PostdataByte?.Length > 0)
return item.PostdataByte;
return string.IsNullOrEmpty(item.Postdata) ? null : postencoding.GetBytes(item.Postdata);
}
/// <summary>
/// 设置代理
/// </summary>
+2
View File
@@ -118,5 +118,7 @@ namespace AllBase.Model.Result
public string has_wx_format { get; set; }
public string add_user_name { get; set; }
public int? is_del { get; set; }
public bool? is_safe { get; set; }
}
}
+3 -3
View File
@@ -8,8 +8,8 @@ namespace AllBase.Model.Result
{
public enum PlatformType
{
None,
PDD,
WX,
None = 0,
PDD = 1,
WX = 2,
}
}
+2
View File
@@ -20,6 +20,8 @@ namespace AllBase.Model.Result
public int Code { get; set; }
public string Msg { get; set; }
public bool? Success { get; set; }
public string TraceId { get; set; }
}
public class Result<TData> : Result
{
@@ -12,7 +12,7 @@ namespace TemuKJD.BLL.ImportConverts
{
public class ConverterToPddFactory
{
private static List<IGoodsConverter> _converters = new List<IGoodsConverter>
private static List<IGoodsConverter> CreateConverters() => new List<IGoodsConverter>
{
new ConverterToPddV5(),
new ConverterWXToPddV1(),
@@ -24,7 +24,7 @@ namespace TemuKJD.BLL.ImportConverts
public static PDDFrontProductInfo5 Convert(string filePath)
{
foreach (IGoodsConverter item in _converters)
foreach (IGoodsConverter item in CreateConverters())
{
try
{
@@ -47,7 +47,7 @@ namespace TemuKJD.BLL.ImportConverts
public static PDDFrontProductInfo5 SetContentConvert(string content)
{
foreach (IGoodsConverter item in _converters)
foreach (IGoodsConverter item in CreateConverters())
{
try
{
@@ -8,7 +8,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
namespace TemuKJD.BLL.ImportConverters
{
+5 -2
View File
@@ -68,10 +68,10 @@
<ProjectReference Include="..\Work\Work.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="PDDForms\ProductSelectForms\CloudGoodsFavoriteForm.cs">
<Compile Update="WXForms\ProductForms\CloudGoodsFavoriteForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="PDDForms\ProductSelectForms\CloudGoodsForm.cs">
<Compile Update="WXForms\ProductForms\CloudGoodsForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="Properties\Resources.Designer.cs">
@@ -86,4 +86,7 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Remove="BLL\PDDProdFormConverter.cs;BLL\ImportConverters\*.cs" />
</ItemGroup>
</Project>
+7 -1
View File
@@ -10,7 +10,7 @@
<ErrorReportUrlHistory />
<FallbackCulture>zh-CN</FallbackCulture>
<VerifyUploadedFiles>false</VerifyUploadedFiles>
<ActiveDebugProfile>Production</ActiveDebugProfile>
<ActiveDebugProfile>Development</ActiveDebugProfile>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
@@ -47,6 +47,9 @@
<Compile Update="KJDForms\SystemForms\SystemUploadConfigForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="KJDForms\SystemForms\SystemGoodsComplianceForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="KJDForms\SystemForms\SystemViolationDetectionForm.cs">
<SubType>Form</SubType>
</Compile>
@@ -68,6 +71,9 @@
<Compile Update="PDDForms\ProductSelectForms\PDDDBProdGroupManageFrom.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="UserComponent\UcNumericRange.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Update="WXForms\AdminForms\WXAdminOemWithdrawal.cs">
<SubType>Form</SubType>
</Compile>
+3 -1
View File
@@ -31,8 +31,9 @@
System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("解除限制");
System.Windows.Forms.TreeNode violationNode = new System.Windows.Forms.TreeNode("违规检测");
System.Windows.Forms.TreeNode uploadConfigNode = new System.Windows.Forms.TreeNode("上货配置");
System.Windows.Forms.TreeNode complianceNode = new System.Windows.Forms.TreeNode("商品 AI 检测");
System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("系统设置", new System.Windows.Forms.TreeNode[] {
treeNode1, violationNode, uploadConfigNode});
treeNode1, violationNode,complianceNode, uploadConfigNode});
this.panel1 = new System.Windows.Forms.Panel();
this.panel3 = new System.Windows.Forms.Panel();
this.panel2 = new System.Windows.Forms.Panel();
@@ -105,6 +106,7 @@
this.tv.Name = "tv";
treeNode1.Name = "解除限制";
treeNode1.Text = "解除限制";
complianceNode.Name = "商品 AI 检测";
violationNode.Name = "违规检测";
violationNode.Text = "违规检测";
uploadConfigNode.Name = "上货配置";
@@ -17,6 +17,8 @@ namespace TemuKJD.KJDForms.SystemForms
public Lazy<SystemRemoveRestrictionsForm> systemRemoveRestrictionsForm = new Lazy<SystemRemoveRestrictionsForm>();
public Lazy<SystemViolationDetectionForm> systemViolationDetectionForm = new Lazy<SystemViolationDetectionForm>();
public Lazy<SystemUploadConfigForm> systemUploadConfigForm = new Lazy<SystemUploadConfigForm>();
private readonly Lazy<SystemGoodsComplianceForm> goodsComplianceForm = new Lazy<SystemGoodsComplianceForm>();
public SystemForm()
{
InitializeComponent();
@@ -48,6 +50,9 @@ namespace TemuKJD.KJDForms.SystemForms
case "解除限制":
SetForm(systemRemoveRestrictionsForm.Value);
break;
case "商品 AI 检测":
SetForm(goodsComplianceForm.Value);
break;
case "违规检测":
SetForm(systemViolationDetectionForm.Value);
break;
@@ -0,0 +1,367 @@
using System.Drawing;
using System.Windows.Forms;
namespace TemuKJD.KJDForms.SystemForms
{
partial class SystemGoodsComplianceForm
{
private GroupBox imagesGroup;
private Label mainLabel;
private ComboBox main;
private NumericUpDown mainCount;
private Label mainUnit;
private Label detailLabel;
private ComboBox detail;
private NumericUpDown detailCount;
private Label detailUnit;
private CheckBox sku;
private GroupBox keywordsGroup;
private TextBox keywords;
private Label keywordsHint;
private Button btnSaveDetection;
private void InitializeComponent()
{
this.imagesGroup = new System.Windows.Forms.GroupBox();
this.mainLabel = new System.Windows.Forms.Label();
this.main = new System.Windows.Forms.ComboBox();
this.mainCount = new System.Windows.Forms.NumericUpDown();
this.mainUnit = new System.Windows.Forms.Label();
this.detailLabel = new System.Windows.Forms.Label();
this.detail = new System.Windows.Forms.ComboBox();
this.detailCount = new System.Windows.Forms.NumericUpDown();
this.detailUnit = new System.Windows.Forms.Label();
this.sku = new System.Windows.Forms.CheckBox();
this.keywordsGroup = new System.Windows.Forms.GroupBox();
this.keywords = new System.Windows.Forms.TextBox();
this.keywordsHint = new System.Windows.Forms.Label();
this.btnSaveDetection = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.num_points = new System.Windows.Forms.NumericUpDown();
this.lb_imagequtoa = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.btn_Exchange = new System.Windows.Forms.Button();
this.label4 = new System.Windows.Forms.Label();
this.imagesGroup.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.mainCount)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.detailCount)).BeginInit();
this.keywordsGroup.SuspendLayout();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.num_points)).BeginInit();
this.SuspendLayout();
//
// imagesGroup
//
this.imagesGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.imagesGroup.Controls.Add(this.mainLabel);
this.imagesGroup.Controls.Add(this.main);
this.imagesGroup.Controls.Add(this.mainCount);
this.imagesGroup.Controls.Add(this.mainUnit);
this.imagesGroup.Controls.Add(this.detailLabel);
this.imagesGroup.Controls.Add(this.detail);
this.imagesGroup.Controls.Add(this.detailCount);
this.imagesGroup.Controls.Add(this.detailUnit);
this.imagesGroup.Controls.Add(this.sku);
this.imagesGroup.Location = new System.Drawing.Point(20, 71);
this.imagesGroup.Name = "imagesGroup";
this.imagesGroup.Size = new System.Drawing.Size(760, 153);
this.imagesGroup.TabIndex = 0;
this.imagesGroup.TabStop = false;
this.imagesGroup.Text = "检测图片";
//
// mainLabel
//
this.mainLabel.AutoSize = true;
this.mainLabel.Location = new System.Drawing.Point(16, 34);
this.mainLabel.Name = "mainLabel";
this.mainLabel.Size = new System.Drawing.Size(56, 17);
this.mainLabel.TabIndex = 0;
this.mainLabel.Text = "商品主图";
//
// main
//
this.main.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.main.Items.AddRange(new object[] {
"全部",
"前几张"});
this.main.Location = new System.Drawing.Point(106, 30);
this.main.Name = "main";
this.main.Size = new System.Drawing.Size(110, 25);
this.main.TabIndex = 1;
this.main.SelectedIndexChanged += new System.EventHandler(this.ImageRangeChanged);
//
// mainCount
//
this.mainCount.AccessibleName = "商品主图检测张数";
this.mainCount.Enabled = false;
this.mainCount.Location = new System.Drawing.Point(228, 30);
this.mainCount.Maximum = new decimal(new int[] {
999,
0,
0,
0});
this.mainCount.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.mainCount.Name = "mainCount";
this.mainCount.Size = new System.Drawing.Size(60, 23);
this.mainCount.TabIndex = 2;
this.mainCount.Value = new decimal(new int[] {
1,
0,
0,
0});
//
// mainUnit
//
this.mainUnit.AutoSize = true;
this.mainUnit.Location = new System.Drawing.Point(294, 34);
this.mainUnit.Name = "mainUnit";
this.mainUnit.Size = new System.Drawing.Size(20, 17);
this.mainUnit.TabIndex = 3;
this.mainUnit.Text = "张";
//
// detailLabel
//
this.detailLabel.AutoSize = true;
this.detailLabel.Location = new System.Drawing.Point(16, 72);
this.detailLabel.Name = "detailLabel";
this.detailLabel.Size = new System.Drawing.Size(44, 17);
this.detailLabel.TabIndex = 4;
this.detailLabel.Text = "详情图";
//
// detail
//
this.detail.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.detail.Items.AddRange(new object[] {
"不检测",
"前几张",
"全部"});
this.detail.Location = new System.Drawing.Point(106, 68);
this.detail.Name = "detail";
this.detail.Size = new System.Drawing.Size(110, 25);
this.detail.TabIndex = 5;
this.detail.SelectedIndexChanged += new System.EventHandler(this.ImageRangeChanged);
//
// detailCount
//
this.detailCount.AccessibleName = "详情图检测张数";
this.detailCount.Enabled = false;
this.detailCount.Location = new System.Drawing.Point(228, 68);
this.detailCount.Maximum = new decimal(new int[] {
999,
0,
0,
0});
this.detailCount.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.detailCount.Name = "detailCount";
this.detailCount.Size = new System.Drawing.Size(60, 23);
this.detailCount.TabIndex = 6;
this.detailCount.Value = new decimal(new int[] {
1,
0,
0,
0});
//
// detailUnit
//
this.detailUnit.AutoSize = true;
this.detailUnit.Location = new System.Drawing.Point(294, 72);
this.detailUnit.Name = "detailUnit";
this.detailUnit.Size = new System.Drawing.Size(20, 17);
this.detailUnit.TabIndex = 7;
this.detailUnit.Text = "张";
//
// sku
//
this.sku.AutoSize = true;
this.sku.Location = new System.Drawing.Point(106, 112);
this.sku.Name = "sku";
this.sku.Size = new System.Drawing.Size(107, 21);
this.sku.TabIndex = 8;
this.sku.Text = "检测 SKU 图片";
//
// keywordsGroup
//
this.keywordsGroup.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.keywordsGroup.Controls.Add(this.keywords);
this.keywordsGroup.Controls.Add(this.keywordsHint);
this.keywordsGroup.Location = new System.Drawing.Point(20, 238);
this.keywordsGroup.Name = "keywordsGroup";
this.keywordsGroup.Size = new System.Drawing.Size(760, 143);
this.keywordsGroup.TabIndex = 1;
this.keywordsGroup.TabStop = false;
this.keywordsGroup.Text = "检测关键词";
//
// keywords
//
this.keywords.AcceptsReturn = true;
this.keywords.AccessibleName = "检测关键词";
this.keywords.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.keywords.Location = new System.Drawing.Point(16, 27);
this.keywords.Multiline = true;
this.keywords.Name = "keywords";
this.keywords.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
this.keywords.Size = new System.Drawing.Size(728, 68);
this.keywords.TabIndex = 0;
//
// keywordsHint
//
this.keywordsHint.AutoSize = true;
this.keywordsHint.ForeColor = System.Drawing.SystemColors.GrayText;
this.keywordsHint.Location = new System.Drawing.Point(16, 105);
this.keywordsHint.Name = "keywordsHint";
this.keywordsHint.Size = new System.Drawing.Size(260, 17);
this.keywordsHint.TabIndex = 1;
this.keywordsHint.Text = "多个关键词可用逗号、分号、空格或换行分隔。";
//
// btnSaveDetection
//
this.btnSaveDetection.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(126)))), ((int)(((byte)(255)))));
this.btnSaveDetection.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnSaveDetection.FlatAppearance.BorderSize = 0;
this.btnSaveDetection.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnSaveDetection.ForeColor = System.Drawing.Color.White;
this.btnSaveDetection.Location = new System.Drawing.Point(20, 396);
this.btnSaveDetection.Name = "btnSaveDetection";
this.btnSaveDetection.Size = new System.Drawing.Size(96, 32);
this.btnSaveDetection.TabIndex = 2;
this.btnSaveDetection.Text = "保存条件";
this.btnSaveDetection.UseVisualStyleBackColor = false;
this.btnSaveDetection.Click += new System.EventHandler(this.SaveDetectionClick);
//
// groupBox1
//
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.btn_Exchange);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.num_points);
this.groupBox1.Controls.Add(this.lb_imagequtoa);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Location = new System.Drawing.Point(20, 12);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(760, 53);
this.groupBox1.TabIndex = 3;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "积分兑换";
//
// num_points
//
this.num_points.Location = new System.Drawing.Point(269, 20);
this.num_points.Maximum = new decimal(new int[] {
1000,
0,
0,
0});
this.num_points.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.num_points.Name = "num_points";
this.num_points.Size = new System.Drawing.Size(120, 23);
this.num_points.TabIndex = 2;
this.num_points.Value = new decimal(new int[] {
1,
0,
0,
0});
//
// lb_imagequtoa
//
this.lb_imagequtoa.AutoSize = true;
this.lb_imagequtoa.Location = new System.Drawing.Point(130, 23);
this.lb_imagequtoa.Name = "lb_imagequtoa";
this.lb_imagequtoa.Size = new System.Drawing.Size(50, 17);
this.lb_imagequtoa.TabIndex = 1;
this.lb_imagequtoa.Text = "999999";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(65, 23);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(68, 17);
this.label1.TabIndex = 0;
this.label1.Text = "检测图片:";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(195, 23);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(56, 17);
this.label3.TabIndex = 3;
this.label3.Text = "积分兑换";
//
// btn_Exchange
//
this.btn_Exchange.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(126)))), ((int)(((byte)(255)))));
this.btn_Exchange.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_Exchange.FlatAppearance.BorderSize = 0;
this.btn_Exchange.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btn_Exchange.ForeColor = System.Drawing.Color.White;
this.btn_Exchange.Location = new System.Drawing.Point(395, 19);
this.btn_Exchange.Name = "btn_Exchange";
this.btn_Exchange.Size = new System.Drawing.Size(68, 24);
this.btn_Exchange.TabIndex = 4;
this.btn_Exchange.Text = "兑换";
this.btn_Exchange.UseVisualStyleBackColor = false;
this.btn_Exchange.Click += new System.EventHandler(this.btn_Exchange_Click);
//
// label4
//
this.label4.AutoSize = true;
this.label4.ForeColor = System.Drawing.SystemColors.ControlDark;
this.label4.Location = new System.Drawing.Point(478, 23);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(165, 17);
this.label4.TabIndex = 5;
this.label4.Text = "兑换比例:1积分=100张图片";
//
// SystemGoodsComplianceForm
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.AutoScroll = true;
this.AutoScrollMinSize = new System.Drawing.Size(365, 390);
this.BackColor = System.Drawing.Color.White;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.imagesGroup);
this.Controls.Add(this.keywordsGroup);
this.Controls.Add(this.btnSaveDetection);
this.Font = new System.Drawing.Font("微软雅黑", 9F);
this.Name = "SystemGoodsComplianceForm";
this.Text = "商品 AI 检测";
this.imagesGroup.ResumeLayout(false);
this.imagesGroup.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.mainCount)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.detailCount)).EndInit();
this.keywordsGroup.ResumeLayout(false);
this.keywordsGroup.PerformLayout();
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.num_points)).EndInit();
this.ResumeLayout(false);
}
private GroupBox groupBox1;
private NumericUpDown num_points;
private Label lb_imagequtoa;
private Label label1;
private Label label4;
private Button btn_Exchange;
private Label label3;
}
}
@@ -0,0 +1,109 @@
using AllBase;
using AllBase.Helper;
using AllBase.Model.Result;
using Newtonsoft.Json;
using System;
using System.Runtime.Remoting.Metadata.W3cXsd2001;
using System.Threading.Tasks;
using System.Windows.Forms;
using TemuKJD.BaseForms;
using Work;
using Work.Services;
namespace TemuKJD.KJDForms.SystemForms
{
public partial class SystemGoodsComplianceForm : BaseForm
{
public SystemGoodsComplianceForm()
{
InitializeComponent();
VisibleChanged += (sender, e) => { if (Visible) LoadSettings(); };
LoadSettings();
}
private void LoadSettings()
{
lb_imagequtoa.Text = BaseClass.ImageAnalysisQuota.ToString();
var options = GlobalConfig.GlobalSettings.GoodsCompliance ?? new ComplianceOptions();
main.SelectedIndex = options.MainCount.HasValue ? 1 : 0;
detail.SelectedIndex = options.DetailCount == null ? 2 : options.DetailCount == 0 ? 0 : 1;
mainCount.Value = Math.Min(mainCount.Maximum, Math.Max(1, options.MainCount ?? 1));
detailCount.Value = Math.Min(detailCount.Maximum, Math.Max(1, options.DetailCount ?? 1));
sku.Checked = options.IncludeSku;
keywords.Text = options.Keywords;
}
private void ImageRangeChanged(object sender, EventArgs e)
{
mainCount.Enabled = main.SelectedIndex == 1;
detailCount.Enabled = detail.SelectedIndex == 1;
}
private void SaveDetectionClick(object sender, EventArgs e)
{
if (GoodsComplianceService.Keywords(keywords.Text).Length == 0)
{
MessageBox.Show(this, "请输入检测关键词。");
keywords.Focus();
return;
}
var settings = GlobalConfig.GlobalSettings;
var previous = settings.GoodsCompliance;
settings.GoodsCompliance = new ComplianceOptions
{
MainCount = main.SelectedIndex == 0 ? (int?)null : (int)mainCount.Value,
DetailCount = detail.SelectedIndex == 2 ? (int?)null : detail.SelectedIndex == 0 ? 0 : (int)detailCount.Value,
IncludeSku = sku.Checked,
Keywords = keywords.Text.Trim()
};
try { StartUp.SaveGlobalSettings(); }
catch (Exception ex)
{
settings.GoodsCompliance = previous;
MessageBox.Show(this, "保存检测条件失败:" + ex.Message);
return;
}
MessageBox.Show(this, "已保存 AI 检测条件。");
}
private async void btn_Exchange_Click(object sender, EventArgs e)
{
try
{
btn_Exchange.Enabled = false;
int points = (int)num_points.Value;
if (BaseMsgForm.ShowConfirm($"是否要兑换 {points} 积分,共:{points * 100}张图片检测?", "提示").DialogResult != DialogResult.OK)
{
return;
}
var url = BaseClass.BuildObjString("user/BuyImageAnalysisQuota");
var data = UserLogin.GetSignPostData(new
{
Amount = points,
});
string html = await GetHtml.PostJsonAsync(url, data);
var ret = JsonConvert.DeserializeObject<Result<int>>(html);
if (ret.Code == 200)
{
BaseClass.ImageAnalysisQuota += ret.Data;
lb_imagequtoa.Text = BaseClass.ImageAnalysisQuota.ToString();
BaseMsgForm.ShowInfo("兑换成功");
}
}
catch (Exception ex)
{
BaseMsgForm.ShowInfo("兑换失败:" + ex.Message);
}
finally
{
btn_Exchange.Enabled = true;
}
}
}
}
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -9,6 +9,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TemuKJD.BaseForms;
using TemuKJD.WXForms.ProductForms;
using AllBase;
using TemuKJD.PDDForms.ProductSelectForms;
using TemuKJD.PDDForms.ProductForms.CouponForms;
+159
View File
@@ -0,0 +1,159 @@
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace TemuKJD.UserComponent
{
[DefaultEvent(nameof(ValueChanged))]
public class UcNumericRange : UserControl
{
private const decimal DefaultMaximum = 1000000m;
private const int NormalWidth = 220;
private const int CompactWidth = 112;
private readonly Label separator = new Label { Text = "至", AutoSize = true, Anchor = AnchorStyles.None };
private readonly NumericUpDown lower = CreateEditor("起始值");
private readonly NumericUpDown upper = CreateEditor("结束值");
private bool updating;
public UcNumericRange()
{
upper.Value = DefaultMaximum;
var layout = new TableLayoutPanel { Dock = DockStyle.Fill, ColumnCount = 3, RowCount = 1 };
layout.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
layout.Controls.Add(CreateCell(lower), 0, 0);
layout.Controls.Add(separator, 1, 0);
layout.Controls.Add(CreateCell(upper), 2, 0);
Controls.Add(layout);
Size = new Size(NormalWidth, lower.PreferredHeight + 2);
lower.ValueChanged += (s, e) => UpdateRange(lower, upper);
upper.ValueChanged += (s, e) => UpdateRange(upper, lower);
}
[Description("两个数值之间显示的文字。"), DefaultValue("至")]
public string SeparatorText
{
get => separator.Text;
set => separator.Text = value;
}
[Description("使用窄布局并隐藏微调按钮,仍可用方向键调整数值。"), DefaultValue(false)]
public bool Compact
{
get => separator.Margin == Padding.Empty;
set
{
if (value == Compact) return;
separator.Margin = value ? Padding.Empty : new Padding(3, 0, 3, 0);
SetCompactBorder(lower, value);
SetCompactBorder(upper, value);
if (Dock == DockStyle.None && Width == (value ? NormalWidth : CompactWidth))
Width = value ? CompactWidth : NormalWidth;
}
}
private static void SetCompactBorder(NumericUpDown editor, bool compact)
{
var cell = (Panel)editor.Parent;
editor.BorderStyle = compact ? BorderStyle.None : BorderStyle.Fixed3D;
cell.BorderStyle = compact ? BorderStyle.FixedSingle : BorderStyle.None;
cell.BackColor = compact ? editor.BackColor : Color.Empty;
cell.PerformLayout();
}
private Panel CreateCell(NumericUpDown editor)
{
var cell = new Panel { Dock = DockStyle.Fill, Margin = Padding.Empty };
cell.Controls.Add(editor);
var buttons = editor.Controls[0] is TextBox ? editor.Controls[1] : editor.Controls[0];
// 紧凑模式将右侧按钮移出可见区域,保留原生数字输入和键盘操作。
cell.Layout += (s, e) =>
{
int clippedWidth = Compact ? editor.Width - buttons.Left : 0;
editor.Width = cell.ClientSize.Width + clippedWidth;
editor.Top = Compact ? Math.Max(0, (cell.ClientSize.Height - editor.Height) / 2) : 0;
};
return cell;
}
private static NumericUpDown CreateEditor(string name)
{
return new NumericUpDown { AccessibleName = name, Margin = Padding.Empty, Maximum = DefaultMaximum };
}
[Description("允许输入的最小值。"), DefaultValue(typeof(decimal), "0")]
public decimal Minimum
{
get => lower.Minimum;
set => SetLimits(value, Math.Max(value, Maximum));
}
[Description("允许输入的最大值。"), DefaultValue(typeof(decimal), "1000000")]
public decimal Maximum
{
get => lower.Maximum;
set => SetLimits(Math.Min(value, Minimum), value);
}
[Description("选中范围的起始值。"), DefaultValue(typeof(decimal), "0")]
public decimal LowerValue
{
get => lower.Value;
set => lower.Value = value;
}
[Description("选中范围的结束值。"), DefaultValue(typeof(decimal), "1000000")]
public decimal UpperValue
{
get => upper.Value;
set => upper.Value = value;
}
[Description("数字输入框显示的小数位数。"), DefaultValue(0)]
public int DecimalPlaces
{
get => lower.DecimalPlaces;
set
{
if (value < 0 || value > 28) throw new ArgumentOutOfRangeException(nameof(value));
lower.DecimalPlaces = upper.DecimalPlaces = value;
decimal increment = 1m;
for (int i = 0; i < value; i++)
increment /= 10m;
lower.Increment = upper.Increment = increment;
}
}
public event EventHandler ValueChanged;
private void SetLimits(decimal minimum, decimal maximum)
{
decimal oldLower = LowerValue, oldUpper = UpperValue;
updating = true;
try
{
lower.Minimum = upper.Minimum = minimum;
lower.Maximum = upper.Maximum = maximum;
}
finally { updating = false; }
if (LowerValue != oldLower || UpperValue != oldUpper)
ValueChanged?.Invoke(this, EventArgs.Empty);
}
private void UpdateRange(NumericUpDown edited, NumericUpDown other)
{
if (updating) return;
updating = true;
try
{
if (LowerValue > UpperValue)
other.Value = edited.Value;
}
finally { updating = false; }
ValueChanged?.Invoke(this, EventArgs.Empty);
}
}
}
+26
View File
@@ -14,6 +14,7 @@ using System.Threading.Tasks;
using System.Windows.Forms;
using TemuKJD.BaseForms;
using Work;
using Work.Store.Api;
namespace TemuKJD.UserForm
{
@@ -285,6 +286,31 @@ namespace TemuKJD.UserForm
// return;
//}
//_ = Task.Run(() =>
//{
// try
// {
// StoreApiClient.Instance.Auth.Login(new LoginRequest
// {
// UserName = BaseClass.UserName,
// Password = BaseClass.PassWord
// });
// }
// catch (Exception ex)
// {
// try
// {
// LogSave.AddFile("Store API 登录失败:" + ex.Message);
// }
// catch
// {
// // 日志失败也不能影响主程序。
// }
// }
//});
Hide();
mf.Hide();
@@ -1,5 +1,5 @@
namespace TemuKJD.PDDForms.ProductSelectForms
namespace TemuKJD.WXForms.ProductForms
{
partial class CloudGoodsFavoriteForm
{
@@ -29,25 +29,25 @@ namespace TemuKJD.PDDForms.ProductSelectForms
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle9 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.cb_safe = new System.Windows.Forms.ComboBox();
this.label4 = new System.Windows.Forms.Label();
this.num_price = new TemuKJD.UserComponent.UcNumericRange();
this.num_sold = new TemuKJD.UserComponent.UcNumericRange();
this.panel1 = new System.Windows.Forms.Panel();
this.btnSafeDetection = new DevComponents.DotNetBar.PanelEx();
this.btn_removefavorite = new DevComponents.DotNetBar.PanelEx();
this.bt_importUploadList = new DevComponents.DotNetBar.PanelEx();
this.label5r = new System.Windows.Forms.Label();
this.cb_Platform = new System.Windows.Forms.ComboBox();
this.cb_Platformr = new System.Windows.Forms.ComboBox();
this.cmbCatSelect2 = new System.Windows.Forms.ComboBox();
this.cmbCatSelect1 = new System.Windows.Forms.ComboBox();
this.cmbCatSelect4 = new System.Windows.Forms.ComboBox();
this.cmbCatSelect3 = new System.Windows.Forms.ComboBox();
this.label4 = new System.Windows.Forms.Label();
this.num_maxprice = new System.Windows.Forms.NumericUpDown();
this.num_minprice = new System.Windows.Forms.NumericUpDown();
this.label7 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.num_maxsold = new System.Windows.Forms.NumericUpDown();
this.num_minsold = new System.Windows.Forms.NumericUpDown();
this.txt_title = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.label6 = new System.Windows.Forms.Label();
@@ -64,23 +64,22 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.Column2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column3 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.Column4 = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colDetectionResult = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.ucSplitPage1 = new TemuKJD.UserControls.UcSplitPage();
this.statusBar = new TemuKJD.UserControls.StatusBarUserControl();
this.numericUpDown1 = new System.Windows.Forms.NumericUpDown();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
this.splitContainer1.SuspendLayout();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.num_maxprice)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.num_minprice)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.num_maxsold)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.num_minsold)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit();
this.splitContainer2.Panel1.SuspendLayout();
this.splitContainer2.Panel2.SuspendLayout();
this.splitContainer2.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pbLoading)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.dgvData)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).BeginInit();
this.SuspendLayout();
//
// splitContainer1
@@ -94,20 +93,19 @@ namespace TemuKJD.PDDForms.ProductSelectForms
//
// splitContainer1.Panel1
//
this.splitContainer1.Panel1.Controls.Add(this.cb_safe);
this.splitContainer1.Panel1.Controls.Add(this.label4);
this.splitContainer1.Panel1.Controls.Add(this.num_price);
this.splitContainer1.Panel1.Controls.Add(this.num_sold);
this.splitContainer1.Panel1.Controls.Add(this.panel1);
this.splitContainer1.Panel1.Controls.Add(this.label5r);
this.splitContainer1.Panel1.Controls.Add(this.cb_Platform);
this.splitContainer1.Panel1.Controls.Add(this.cb_Platformr);
this.splitContainer1.Panel1.Controls.Add(this.cmbCatSelect2);
this.splitContainer1.Panel1.Controls.Add(this.cmbCatSelect1);
this.splitContainer1.Panel1.Controls.Add(this.cmbCatSelect4);
this.splitContainer1.Panel1.Controls.Add(this.cmbCatSelect3);
this.splitContainer1.Panel1.Controls.Add(this.label4);
this.splitContainer1.Panel1.Controls.Add(this.num_maxprice);
this.splitContainer1.Panel1.Controls.Add(this.num_minprice);
this.splitContainer1.Panel1.Controls.Add(this.label7);
this.splitContainer1.Panel1.Controls.Add(this.label3);
this.splitContainer1.Panel1.Controls.Add(this.num_maxsold);
this.splitContainer1.Panel1.Controls.Add(this.num_minsold);
this.splitContainer1.Panel1.Controls.Add(this.txt_title);
this.splitContainer1.Panel1.Controls.Add(this.label1);
this.splitContainer1.Panel1.Controls.Add(this.label6);
@@ -119,26 +117,133 @@ namespace TemuKJD.PDDForms.ProductSelectForms
//
this.splitContainer1.Panel2.Controls.Add(this.splitContainer2);
this.splitContainer1.Panel2.Margin = new System.Windows.Forms.Padding(4);
this.splitContainer1.Size = new System.Drawing.Size(1643, 530);
this.splitContainer1.Size = new System.Drawing.Size(1719, 530);
this.splitContainer1.TabIndex = 35;
//
// cb_safe
//
this.cb_safe.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cb_safe.DropDownWidth = 150;
this.cb_safe.FormattingEnabled = true;
this.cb_safe.Items.AddRange(new object[] {
"全部",
"安全",
"违规",
"未检测"});
this.cb_safe.Location = new System.Drawing.Point(1141, 13);
this.cb_safe.Name = "cb_safe";
this.cb_safe.Size = new System.Drawing.Size(97, 25);
this.cb_safe.TabIndex = 930;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(1104, 17);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(44, 17);
this.label4.TabIndex = 929;
this.label4.Text = "检测:";
//
// num_price
//
this.num_price.Compact = true;
this.num_price.Location = new System.Drawing.Point(391, 15);
this.num_price.LowerValue = new decimal(new int[] {
1,
0,
0,
0});
this.num_price.Maximum = new decimal(new int[] {
9999999,
0,
0,
0});
this.num_price.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.num_price.Name = "num_price";
this.num_price.SeparatorText = "";
this.num_price.Size = new System.Drawing.Size(108, 23);
this.num_price.TabIndex = 922;
this.num_price.UpperValue = new decimal(new int[] {
9999999,
0,
0,
0});
//
// num_sold
//
this.num_sold.Compact = true;
this.num_sold.Location = new System.Drawing.Point(218, 15);
this.num_sold.LowerValue = new decimal(new int[] {
1,
0,
0,
0});
this.num_sold.Maximum = new decimal(new int[] {
9999999,
0,
0,
0});
this.num_sold.Minimum = new decimal(new int[] {
1,
0,
0,
0});
this.num_sold.Name = "num_sold";
this.num_sold.SeparatorText = "";
this.num_sold.Size = new System.Drawing.Size(108, 23);
this.num_sold.TabIndex = 921;
this.num_sold.UpperValue = new decimal(new int[] {
9999999,
0,
0,
0});
//
// panel1
//
this.panel1.Controls.Add(this.btnSafeDetection);
this.panel1.Controls.Add(this.btn_removefavorite);
this.panel1.Controls.Add(this.bt_importUploadList);
this.panel1.Dock = System.Windows.Forms.DockStyle.Right;
this.panel1.Location = new System.Drawing.Point(1507, 0);
this.panel1.Location = new System.Drawing.Point(1509, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(136, 50);
this.panel1.Size = new System.Drawing.Size(210, 50);
this.panel1.TabIndex = 914;
//
// btnSafeDetection
//
this.btnSafeDetection.ColorSchemeStyle = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
this.btnSafeDetection.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnSafeDetection.DisabledBackColor = System.Drawing.Color.Empty;
this.btnSafeDetection.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSafeDetection.Location = new System.Drawing.Point(132, 14);
this.btnSafeDetection.Name = "btnSafeDetection";
this.btnSafeDetection.Size = new System.Drawing.Size(58, 23);
this.btnSafeDetection.Style.Alignment = System.Drawing.StringAlignment.Center;
this.btnSafeDetection.Style.BackColor1.Color = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0)))));
this.btnSafeDetection.Style.BackColor2.Color = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(128)))), ((int)(((byte)(0)))));
this.btnSafeDetection.Style.BorderColor.ColorSchemePart = DevComponents.DotNetBar.eColorSchemePart.PanelBorder;
this.btnSafeDetection.Style.BorderDashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
this.btnSafeDetection.Style.BorderSide = DevComponents.DotNetBar.eBorderSide.None;
this.btnSafeDetection.Style.ForeColor.Color = System.Drawing.Color.White;
this.btnSafeDetection.Style.GradientAngle = 90;
this.btnSafeDetection.StyleMouseOver.Alignment = System.Drawing.StringAlignment.Center;
this.btnSafeDetection.StyleMouseOver.BackColor1.Color = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(102)))), ((int)(((byte)(255)))));
this.btnSafeDetection.StyleMouseOver.BackColor2.Color = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(102)))), ((int)(((byte)(255)))));
this.btnSafeDetection.TabIndex = 451;
this.btnSafeDetection.Text = "AI检测";
this.btnSafeDetection.Click += new System.EventHandler(this.btnSafeDetection_Click);
//
// btn_removefavorite
//
this.btn_removefavorite.ColorSchemeStyle = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
this.btn_removefavorite.Cursor = System.Windows.Forms.Cursors.Hand;
this.btn_removefavorite.DisabledBackColor = System.Drawing.Color.Empty;
this.btn_removefavorite.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btn_removefavorite.Location = new System.Drawing.Point(67, 14);
this.btn_removefavorite.Location = new System.Drawing.Point(68, 14);
this.btn_removefavorite.Name = "btn_removefavorite";
this.btn_removefavorite.Size = new System.Drawing.Size(58, 23);
this.btn_removefavorite.Style.Alignment = System.Drawing.StringAlignment.Center;
@@ -183,31 +288,31 @@ namespace TemuKJD.PDDForms.ProductSelectForms
// label5r
//
this.label5r.AutoSize = true;
this.label5r.Location = new System.Drawing.Point(1048, 16);
this.label5r.Location = new System.Drawing.Point(942, 16);
this.label5r.Name = "label5r";
this.label5r.Size = new System.Drawing.Size(44, 17);
this.label5r.TabIndex = 907;
this.label5r.Text = "来源:";
//
// cb_Platform
// cb_Platformr
//
this.cb_Platform.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cb_Platform.DropDownWidth = 150;
this.cb_Platform.FormattingEnabled = true;
this.cb_Platform.Items.AddRange(new object[] {
this.cb_Platformr.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cb_Platformr.DropDownWidth = 150;
this.cb_Platformr.FormattingEnabled = true;
this.cb_Platformr.Items.AddRange(new object[] {
"全部",
"多多",
"微信"});
this.cb_Platform.Location = new System.Drawing.Point(1098, 13);
this.cb_Platform.Name = "cb_Platform";
this.cb_Platform.Size = new System.Drawing.Size(97, 25);
this.cb_Platform.TabIndex = 906;
this.cb_Platformr.Location = new System.Drawing.Point(992, 13);
this.cb_Platformr.Name = "cb_Platformr";
this.cb_Platformr.Size = new System.Drawing.Size(97, 25);
this.cb_Platformr.TabIndex = 906;
//
// cmbCatSelect2
//
this.cmbCatSelect2.DropDownWidth = 150;
this.cmbCatSelect2.FormattingEnabled = true;
this.cmbCatSelect2.Location = new System.Drawing.Point(745, 12);
this.cmbCatSelect2.Location = new System.Drawing.Point(639, 12);
this.cmbCatSelect2.Name = "cmbCatSelect2";
this.cmbCatSelect2.Size = new System.Drawing.Size(97, 25);
this.cmbCatSelect2.TabIndex = 897;
@@ -216,7 +321,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
//
this.cmbCatSelect1.DropDownWidth = 150;
this.cmbCatSelect1.FormattingEnabled = true;
this.cmbCatSelect1.Location = new System.Drawing.Point(648, 12);
this.cmbCatSelect1.Location = new System.Drawing.Point(542, 12);
this.cmbCatSelect1.Name = "cmbCatSelect1";
this.cmbCatSelect1.Size = new System.Drawing.Size(97, 25);
this.cmbCatSelect1.TabIndex = 896;
@@ -225,7 +330,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
//
this.cmbCatSelect4.DropDownWidth = 150;
this.cmbCatSelect4.FormattingEnabled = true;
this.cmbCatSelect4.Location = new System.Drawing.Point(939, 12);
this.cmbCatSelect4.Location = new System.Drawing.Point(833, 12);
this.cmbCatSelect4.Name = "cmbCatSelect4";
this.cmbCatSelect4.Size = new System.Drawing.Size(97, 25);
this.cmbCatSelect4.TabIndex = 899;
@@ -234,50 +339,15 @@ namespace TemuKJD.PDDForms.ProductSelectForms
//
this.cmbCatSelect3.DropDownWidth = 150;
this.cmbCatSelect3.FormattingEnabled = true;
this.cmbCatSelect3.Location = new System.Drawing.Point(842, 12);
this.cmbCatSelect3.Location = new System.Drawing.Point(736, 12);
this.cmbCatSelect3.Name = "cmbCatSelect3";
this.cmbCatSelect3.Size = new System.Drawing.Size(97, 25);
this.cmbCatSelect3.TabIndex = 898;
//
// label4
//
this.label4.AutoSize = true;
this.label4.ForeColor = System.Drawing.Color.Gray;
this.label4.Location = new System.Drawing.Point(518, 17);
this.label4.Margin = new System.Windows.Forms.Padding(0);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(13, 17);
this.label4.TabIndex = 488;
this.label4.Text = "-";
//
// num_maxprice
//
this.num_maxprice.Location = new System.Drawing.Point(534, 14);
this.num_maxprice.Maximum = new decimal(new int[] {
99999,
0,
0,
0});
this.num_maxprice.Name = "num_maxprice";
this.num_maxprice.Size = new System.Drawing.Size(70, 23);
this.num_maxprice.TabIndex = 487;
//
// num_minprice
//
this.num_minprice.Location = new System.Drawing.Point(447, 14);
this.num_minprice.Maximum = new decimal(new int[] {
99999,
0,
0,
0});
this.num_minprice.Name = "num_minprice";
this.num_minprice.Size = new System.Drawing.Size(70, 23);
this.num_minprice.TabIndex = 486;
//
// label7
//
this.label7.AutoSize = true;
this.label7.Location = new System.Drawing.Point(388, 17);
this.label7.Location = new System.Drawing.Point(332, 17);
this.label7.Name = "label7";
this.label7.Size = new System.Drawing.Size(64, 17);
this.label7.TabIndex = 485;
@@ -294,30 +364,6 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.label3.TabIndex = 484;
this.label3.Text = "-";
//
// num_maxsold
//
this.num_maxsold.Location = new System.Drawing.Point(310, 14);
this.num_maxsold.Maximum = new decimal(new int[] {
9999999,
0,
0,
0});
this.num_maxsold.Name = "num_maxsold";
this.num_maxsold.Size = new System.Drawing.Size(70, 23);
this.num_maxsold.TabIndex = 483;
//
// num_minsold
//
this.num_minsold.Location = new System.Drawing.Point(223, 14);
this.num_minsold.Maximum = new decimal(new int[] {
9999999,
0,
0,
0});
this.num_minsold.Name = "num_minsold";
this.num_minsold.Size = new System.Drawing.Size(70, 23);
this.num_minsold.TabIndex = 482;
//
// txt_title
//
this.txt_title.Location = new System.Drawing.Point(60, 14);
@@ -337,7 +383,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
// label6
//
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(610, 17);
this.label6.Location = new System.Drawing.Point(504, 17);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(44, 17);
this.label6.TabIndex = 440;
@@ -349,7 +395,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.btnSearch.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnSearch.DisabledBackColor = System.Drawing.Color.Empty;
this.btnSearch.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSearch.Location = new System.Drawing.Point(1208, 14);
this.btnSearch.Location = new System.Drawing.Point(1257, 14);
this.btnSearch.Name = "btnSearch";
this.btnSearch.Size = new System.Drawing.Size(58, 23);
this.btnSearch.Style.Alignment = System.Drawing.StringAlignment.Center;
@@ -372,7 +418,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.pnlEmpty.CanvasColor = System.Drawing.SystemColors.Control;
this.pnlEmpty.ColorSchemeStyle = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
this.pnlEmpty.DisabledBackColor = System.Drawing.Color.Empty;
this.pnlEmpty.Location = new System.Drawing.Point(1272, 14);
this.pnlEmpty.Location = new System.Drawing.Point(1321, 15);
this.pnlEmpty.Name = "pnlEmpty";
this.pnlEmpty.Size = new System.Drawing.Size(58, 23);
this.pnlEmpty.Style.Alignment = System.Drawing.StringAlignment.Center;
@@ -420,7 +466,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
//
this.splitContainer2.Panel2.Controls.Add(this.ucSplitPage1);
this.splitContainer2.Panel2.Controls.Add(this.statusBar);
this.splitContainer2.Size = new System.Drawing.Size(1643, 476);
this.splitContainer2.Size = new System.Drawing.Size(1719, 476);
this.splitContainer2.SplitterDistance = 447;
this.splitContainer2.TabIndex = 0;
//
@@ -428,7 +474,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
//
this.pbLoading.Anchor = System.Windows.Forms.AnchorStyles.None;
this.pbLoading.Image = global::TemuKJD.Properties.Resources.loading_blue;
this.pbLoading.Location = new System.Drawing.Point(796, 198);
this.pbLoading.Location = new System.Drawing.Point(834, 198);
this.pbLoading.Name = "pbLoading";
this.pbLoading.Size = new System.Drawing.Size(50, 50);
this.pbLoading.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
@@ -439,20 +485,20 @@ namespace TemuKJD.PDDForms.ProductSelectForms
//
this.dgvData.AllowUserToAddRows = false;
this.dgvData.AllowUserToDeleteRows = false;
dataGridViewCellStyle9.BackColor = System.Drawing.Color.WhiteSmoke;
this.dgvData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle9;
dataGridViewCellStyle1.BackColor = System.Drawing.Color.WhiteSmoke;
this.dgvData.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
this.dgvData.AutoRowNumber = true;
this.dgvData.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgvData.BackgroundColor = System.Drawing.Color.White;
this.dgvData.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(126)))), ((int)(((byte)(255)))));
dataGridViewCellStyle10.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle10.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle10.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
dataGridViewCellStyle10.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle10.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle10.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle10.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.dgvData.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle10;
dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle2.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.dgvData.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle2;
this.dgvData.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgvData.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.colSelect,
@@ -461,7 +507,8 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.c_goodsid,
this.Column2,
this.Column3,
this.Column4});
this.Column4,
this.colDetectionResult});
this.dgvData.Dock = System.Windows.Forms.DockStyle.Fill;
this.dgvData.Location = new System.Drawing.Point(4, 0);
this.dgvData.MultiSelectCheckBox = true;
@@ -469,7 +516,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.dgvData.ReadOnly = true;
this.dgvData.RowTemplate.Height = 60;
this.dgvData.ShowCellErrors = false;
this.dgvData.Size = new System.Drawing.Size(1635, 447);
this.dgvData.Size = new System.Drawing.Size(1711, 447);
this.dgvData.TabIndex = 5;
//
// colSelect
@@ -537,13 +584,23 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.Column4.ReadOnly = true;
this.Column4.Width = 120;
//
// colDetectionResult
//
this.colDetectionResult.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None;
this.colDetectionResult.HeaderText = "AI检测结果";
this.colDetectionResult.MinimumWidth = 50;
this.colDetectionResult.Name = "colDetectionResult";
this.colDetectionResult.ReadOnly = true;
this.colDetectionResult.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.colDetectionResult.Width = 160;
//
// ucSplitPage1
//
this.ucSplitPage1.CurrentPage = 1;
this.ucSplitPage1.Dock = System.Windows.Forms.DockStyle.Right;
this.ucSplitPage1.IsShowPageSize = true;
this.ucSplitPage1.IsShowTotalCount = true;
this.ucSplitPage1.Location = new System.Drawing.Point(1181, 0);
this.ucSplitPage1.Location = new System.Drawing.Point(1257, 0);
this.ucSplitPage1.Margin = new System.Windows.Forms.Padding(0);
this.ucSplitPage1.MaxPageSizeValue = 2000;
this.ucSplitPage1.Name = "ucSplitPage1";
@@ -561,14 +618,21 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.statusBar.Location = new System.Drawing.Point(0, 0);
this.statusBar.Margin = new System.Windows.Forms.Padding(0);
this.statusBar.Name = "statusBar";
this.statusBar.Size = new System.Drawing.Size(1643, 25);
this.statusBar.Size = new System.Drawing.Size(1719, 25);
this.statusBar.TabIndex = 1;
this.statusBar.Visible = false;
//
// numericUpDown1
//
this.numericUpDown1.Location = new System.Drawing.Point(918, 274);
this.numericUpDown1.Name = "numericUpDown1";
this.numericUpDown1.Size = new System.Drawing.Size(120, 21);
this.numericUpDown1.TabIndex = 7;
//
// CloudGoodsFavoriteForm
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.ClientSize = new System.Drawing.Size(1643, 530);
this.ClientSize = new System.Drawing.Size(1719, 530);
this.Controls.Add(this.splitContainer1);
this.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.KeyPreview = true;
@@ -581,16 +645,13 @@ namespace TemuKJD.PDDForms.ProductSelectForms
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit();
this.splitContainer1.ResumeLayout(false);
this.panel1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.num_maxprice)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.num_minprice)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.num_maxsold)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.num_minsold)).EndInit();
this.splitContainer2.Panel1.ResumeLayout(false);
this.splitContainer2.Panel2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit();
this.splitContainer2.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.pbLoading)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.dgvData)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.numericUpDown1)).EndInit();
this.ResumeLayout(false);
}
@@ -609,11 +670,6 @@ namespace TemuKJD.PDDForms.ProductSelectForms
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox txt_title;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.NumericUpDown num_maxsold;
private System.Windows.Forms.NumericUpDown num_minsold;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.NumericUpDown num_maxprice;
private System.Windows.Forms.NumericUpDown num_minprice;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.ComboBox cmbCatSelect2;
@@ -621,7 +677,16 @@ namespace TemuKJD.PDDForms.ProductSelectForms
private System.Windows.Forms.ComboBox cmbCatSelect4;
private System.Windows.Forms.ComboBox cmbCatSelect3;
private System.Windows.Forms.Label label5r;
private System.Windows.Forms.ComboBox cb_Platform;
private System.Windows.Forms.ComboBox cb_Platformr;
private System.Windows.Forms.Panel panel1;
private DevComponents.DotNetBar.PanelEx btn_removefavorite;
private DevComponents.DotNetBar.PanelEx bt_importUploadList;
private DevComponents.DotNetBar.PanelEx btnSafeDetection;
private System.Windows.Forms.NumericUpDown numericUpDown1;
private UserComponent.UcNumericRange num_sold;
private UserComponent.UcNumericRange num_price;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.ComboBox cb_safe;
private System.Windows.Forms.DataGridViewCheckBoxColumn colSelect;
private System.Windows.Forms.DataGridViewTextBoxColumn c_Platform;
private System.Windows.Forms.DataGridViewImageColumn Column1;
@@ -629,8 +694,6 @@ namespace TemuKJD.PDDForms.ProductSelectForms
private System.Windows.Forms.DataGridViewTextBoxColumn Column2;
private System.Windows.Forms.DataGridViewTextBoxColumn Column3;
private System.Windows.Forms.DataGridViewTextBoxColumn Column4;
private System.Windows.Forms.Panel panel1;
private DevComponents.DotNetBar.PanelEx btn_removefavorite;
private DevComponents.DotNetBar.PanelEx bt_importUploadList;
private System.Windows.Forms.DataGridViewTextBoxColumn colDetectionResult;
}
}
@@ -1,3 +1,4 @@
using TemuKJD.BLL;
using AllBase;
using AllBase.Helper;
using AllBase.Model.Result;
@@ -19,28 +20,30 @@ using System.Net;
using System.Net.Http;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using TemuKJD.BaseForms;
using TemuKJD.Extension;
using TemuKJD.ToolForms;
using TemuKJD.UserControls;
using TemuKJD.WXForms.ProductForms;
using Work;
using Work.GoodDetail;
using Work.Services;
namespace TemuKJD.PDDForms.ProductSelectForms
namespace TemuKJD.WXForms.ProductForms
{
public partial class CloudGoodsFavoriteForm : BaseForm
{
private GoodsSearchRequest search = new GoodsSearchRequest();
private List<ComboBox> catBoxList = new List<ComboBox>();
private BindingList<CloudGoods> dataList = new BindingList<CloudGoods>();
private CancellationTokenSource detection;
CheckBox chkSelectAll = null;
public CloudGoodsFavoriteForm()
{
InitializeComponent();
Disposed += (sender, e) => detection?.Cancel();
}
private void AdminCardCodeForm_Load(object sender, EventArgs e)
@@ -50,13 +53,14 @@ namespace TemuKJD.PDDForms.ProductSelectForms
InitCategory();
InitBindingDataGridView();
num_sold.LowerValue = 1;
num_sold.UpperValue = 9999999;
num_price.LowerValue = 1;
num_price.UpperValue = 9999999;
num_minsold.Value = 0;
num_maxsold.Value = 9999999;
num_minprice.Value = 0;
num_maxprice.Value = 999;
cb_Platformr.SelectedIndex = 0;
cb_safe.SelectedIndex = 0;
cb_Platform.SelectedIndex = 0;
ucSplitPage1.TotalCount = 0;
@@ -79,6 +83,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
this.Column3.DataPropertyName = nameof(CloudGoods.Price);
this.Column4.DataPropertyName = nameof(CloudGoods.SoldQuantity);
this.c_goodsid.DataPropertyName = nameof(CloudGoods.GoodsId);
this.colDetectionResult.DataPropertyName = nameof(CloudGoods.DetectionResult);
this.c_Platform.DataPropertyName = nameof(CloudGoods.Platform);
// 2. 设置列样式
// 时间列格式化
@@ -311,6 +316,8 @@ namespace TemuKJD.PDDForms.ProductSelectForms
}
private async void btnSearch_Click(object sender, EventArgs e)
{
if (detection != null) return;
activeSearches++;
try
{
this.pbLoading.Visible = true;
@@ -318,12 +325,13 @@ namespace TemuKJD.PDDForms.ProductSelectForms
UserFavoritesGoodsSearchRequest search = new UserFavoritesGoodsSearchRequest();
search.Platform = cb_Platform.SelectedIndex == 1 ? PlatformType.PDD : cb_Platform.SelectedIndex == 2 ? PlatformType.WX : PlatformType.None;
search.Platform = cb_Platformr.SelectedIndex == 1 ? PlatformType.PDD : cb_Platformr.SelectedIndex == 2 ? PlatformType.WX : PlatformType.None;
search.SafeStatus = cb_safe.SelectedIndex;
search.Title = txt_title.Text;
search.MinSoldQuantity = (int)num_minsold.Value;
search.MaxSoldQuantity = (int)num_maxsold.Value;
search.MinPrice = (long)num_minprice.Value * 100;
search.MaxPrice = (long)num_maxprice.Value * 100;
search.MinSoldQuantity = (int)num_sold.LowerValue;
search.MaxSoldQuantity = (int)num_sold.UpperValue;
search.MinPrice = (long)(num_price.LowerValue * 100);
search.MaxPrice = (long)(num_price.UpperValue * 100);
if (cmbCatSelect1.SelectedItem is PddCatInfo cat1)
{
search.CatId1 = (int)(cat1.cat_id);
@@ -349,7 +357,7 @@ namespace TemuKJD.PDDForms.ProductSelectForms
finally
{
this.pbLoading.Visible = false;
btnSearch.Enabled = true;
btnSearch.Enabled = --activeSearches == 0;
}
@@ -357,26 +365,36 @@ namespace TemuKJD.PDDForms.ProductSelectForms
private void pnlEmpty_Click(object sender, EventArgs e)
{
txt_title.Text = "";
num_minsold.Value = 0;
num_maxsold.Value = 99999;
num_minprice.Value = 0;
num_maxprice.Value = 999;
num_sold.LowerValue = 1;
num_sold.UpperValue = 9999999;
num_price.LowerValue = 1;
num_price.UpperValue = 9999999;
cmbCatSelect1.SelectedIndex = 0;
cb_Platform.SelectedIndex = 0;
cb_Platformr.SelectedIndex = 0;
cb_safe.SelectedIndex = 0;
ucSplitPage1.PageChange -= UcSplitPage1_PageChange;
ucSplitPage1.CurrentPage = 1;
ucSplitPage1.PageChange += UcSplitPage1_PageChange;
}
private int latestGoodsQuery;
private int activeSearches;
public async Task GetGoods(UserFavoritesGoodsSearchRequest request)
{
dataList.Clear();
var query = ++latestGoodsQuery;
PageData<CloudGoods> ret = await CloudGoodsService.SearchFavorites(request);
Invoke(new Action(() =>
{
ret.List.ForEach(a => dataList.Add(a));
if (query != latestGoodsQuery) return;
dataList.Clear();
foreach (var goods in ret.List)
{
dataList.Add(goods);
}
ucSplitPage1.TotalPage = Math.Max(1, ret.TotalPages);
ucSplitPage1.TotalCount = ret.Total;
this.pbLoading.Visible = false;
@@ -473,6 +491,71 @@ namespace TemuKJD.PDDForms.ProductSelectForms
btn_removefavorite.Enabled = true;
}
}
/// <summary>
/// 批量AI检测
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void btnSafeDetection_Click(object sender, EventArgs e)
{
BaseMsgForm.ShowInfo($"当前AI检测剩余:{BaseClass.ImageAnalysisQuota}张");
if (detection != null)
{
detection.Cancel();
btnSafeDetection.Text = "正在停止";
btnSafeDetection.Enabled = false;
return;
}
if (!btnSearch.Enabled || !btn_removefavorite.Enabled)
{
BaseMsgForm.ShowInfo("请等待当前操作完成后再检测。");
return;
}
var selected = dataList.Where(x => x.IsSelected)
.Select(x => new ComplianceGoods
{
id = x.GoodsId.ToString(),
name = x.Title,
image = x.ThumbUrl,
type = ComplianceGoods.Cloud,
platform = x.Platform
}).ToList();
var locked = splitContainer1.Panel1.Controls.Cast<Control>().Where(c => c != panel1)
.Concat(panel1.Controls.Cast<Control>().Where(c => c != btnSafeDetection))
.Concat(new Control[] { splitContainer2 }).Where(c => c.Enabled).ToList();
var originalText = btnSafeDetection.Text;
detection = new CancellationTokenSource();
try
{
foreach (var control in locked) control.Enabled = false;
btnSafeDetection.Text = "停止检测";
var result = await GoodsComplianceService.DetectSelectedAsync(selected, ComplianceProductReader.Read, (id, status) =>
{
if (IsDisposed) return;
foreach (var goods in dataList.Where(x => x.GoodsId.ToString() == id))
goods.DetectionResult = status;
}, detection.Token);
if (!IsDisposed)
{
var title = result.Unfinished > 0 ? "AI 检测已停止" : "AI 检测完成";
BaseMsgForm.ShowInfo($"{title}:安全 {result.Safe},有风险 {result.Risk},失败 {result.Failed},未完成 {result.Unfinished}。");
}
}
catch (Exception ex) { if (!IsDisposed) MessageBox.Show(this, ex.Message); }
finally
{
detection.Dispose();
detection = null;
if (!IsDisposed)
{
foreach (var control in locked) control.Enabled = true;
btnSafeDetection.Text = originalText;
btnSafeDetection.Enabled = true;
}
}
}
}
@@ -1,5 +1,5 @@
namespace TemuKJD.PDDForms.ProductSelectForms
namespace TemuKJD.WXForms.ProductForms
{
partial class CloudGoodsForm
{
@@ -25,12 +25,11 @@ using TemuKJD.BaseForms;
using TemuKJD.Extension;
using TemuKJD.ToolForms;
using TemuKJD.UserControls;
using TemuKJD.WXForms.ProductForms;
using Work;
using Work.GoodDetail;
using Work.Services;
namespace TemuKJD.PDDForms.ProductSelectForms
namespace TemuKJD.WXForms.ProductForms
{
public partial class CloudGoodsForm : BaseForm
{
@@ -1586,54 +1586,7 @@ namespace TemuKJD.WXForms.ProductForms
/// <param name="noBanWx">校验微信禁售商品</param>
/// <returns></returns>
public static KJDDBProduct GetProductDetail(string prodDbId, out string errMsg, bool noViolationProduct = false, bool noBanWx = false)
{
errMsg = "";
if (string.IsNullOrEmpty(prodDbId))
{
errMsg = "产品编号为空";
return new KJDDBProduct();
}
List<KJDDBProduct> list = new List<KJDDBProduct>();
var url = BaseClass.BuildObjString("product/get_pdd_product_detail_list");
var data = UserLogin.GetSignaturex() + "&search_db_ids=" + prodDbId;
if (noViolationProduct)
data += "&wx_safe_status=安全商品,未校验";
if (noBanWx)
data += "&ban_wx=0";
if (BaseClass.SaLevel > 0 || BaseClass.UserAuthority.Contains("爆款数据") || BaseClass.UserAuthority.Contains("学员数据") || BaseClass.ParentAuthority.Contains("学员数据"))
data += "&special_prod_type=普通商品,爆款数据";
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"))
{
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;
}
}
=> ComplianceProductReader.GetProductDetail(prodDbId, out errMsg, noViolationProduct, noBanWx);
public static KJDDBProduct GetCloudProductDetail(TemuDBProductSelect selectProd, out string errMsg, bool noViolationProduct = false, bool noBanWx = false)
{
@@ -30,23 +30,23 @@ namespace TemuKJD.WXForms.ProductForms
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle5 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle6 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle7 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle8 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle9 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle10 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle11 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle12 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle13 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle14 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle15 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle16 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle17 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle18 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle19 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle20 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle21 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle22 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle23 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle24 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle25 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle26 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle27 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle28 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle29 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle30 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle31 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle32 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle33 = new System.Windows.Forms.DataGridViewCellStyle();
System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle34 = new System.Windows.Forms.DataGridViewCellStyle();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WXUserCollectAuthProdListForm));
this.splitContainer1 = new System.Windows.Forms.SplitContainer();
this.btn_import_wx = new DevComponents.DotNetBar.PanelEx();
@@ -66,6 +66,8 @@ namespace TemuKJD.WXForms.ProductForms
this.btnGetProdWxCate = new DevComponents.DotNetBar.PanelEx();
this.btnDel = new DevComponents.DotNetBar.PanelEx();
this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
this.cb_safe = new System.Windows.Forms.ComboBox();
this.label11 = new System.Windows.Forms.Label();
this.cmbNotes = new System.Windows.Forms.ComboBox();
this.label9 = new System.Windows.Forms.Label();
this.cmbHasFission = new System.Windows.Forms.ComboBox();
@@ -94,6 +96,8 @@ namespace TemuKJD.WXForms.ProductForms
this.chkTime = new TemuKJD.UserComponent.UcCheckBox(this.components);
this.dtpStart = new System.Windows.Forms.DateTimePicker();
this.dtpEnd = new System.Windows.Forms.DateTimePicker();
this.btnSafeDetection = new DevComponents.DotNetBar.PanelEx();
this.txt_listing_time = new System.Windows.Forms.TextBox();
this.label10 = new System.Windows.Forms.Label();
this.label7 = new System.Windows.Forms.Label();
this.splitContainer2 = new System.Windows.Forms.SplitContainer();
@@ -147,6 +151,7 @@ namespace TemuKJD.WXForms.ProductForms
this.colGetType = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colSpProdType = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colWxSafe = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colDetectionResult = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colAddTime = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.colMdyTime = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.col_edit = new System.Windows.Forms.DataGridViewLinkColumn();
@@ -155,7 +160,6 @@ namespace TemuKJD.WXForms.ProductForms
this.ucSplitPage1 = new TemuKJD.UserControls.UcSplitPage();
this.statusBar = new TemuKJD.UserControls.StatusBarUserControl();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.txt_listing_time = new System.Windows.Forms.TextBox();
((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit();
this.splitContainer1.Panel1.SuspendLayout();
this.splitContainer1.Panel2.SuspendLayout();
@@ -581,6 +585,8 @@ namespace TemuKJD.WXForms.ProductForms
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 16.66667F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 20F));
this.tableLayoutPanel1.Controls.Add(this.cb_safe, 5, 2);
this.tableLayoutPanel1.Controls.Add(this.label11, 4, 2);
this.tableLayoutPanel1.Controls.Add(this.cmbNotes, 7, 0);
this.tableLayoutPanel1.Controls.Add(this.label9, 2, 2);
this.tableLayoutPanel1.Controls.Add(this.cmbHasFission, 11, 1);
@@ -609,8 +615,9 @@ namespace TemuKJD.WXForms.ProductForms
this.tableLayoutPanel1.Controls.Add(this.chkTime, 0, 2);
this.tableLayoutPanel1.Controls.Add(this.dtpStart, 1, 2);
this.tableLayoutPanel1.Controls.Add(this.dtpEnd, 3, 2);
this.tableLayoutPanel1.Controls.Add(this.label10, 10, 2);
this.tableLayoutPanel1.Controls.Add(this.txt_listing_time, 11, 2);
this.tableLayoutPanel1.Controls.Add(this.btnSafeDetection, 11, 2);
this.tableLayoutPanel1.Controls.Add(this.txt_listing_time, 7, 2);
this.tableLayoutPanel1.Controls.Add(this.label10, 6, 2);
this.tableLayoutPanel1.Location = new System.Drawing.Point(4, 6);
this.tableLayoutPanel1.Name = "tableLayoutPanel1";
this.tableLayoutPanel1.RowCount = 3;
@@ -620,12 +627,40 @@ namespace TemuKJD.WXForms.ProductForms
this.tableLayoutPanel1.Size = new System.Drawing.Size(992, 105);
this.tableLayoutPanel1.TabIndex = 679;
//
// cb_safe
//
this.cb_safe.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cb_safe.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cb_safe.FormattingEnabled = true;
this.cb_safe.Items.AddRange(new object[] {
"全部",
"安全",
"违规",
"未检测"});
this.cb_safe.Location = new System.Drawing.Point(386, 73);
this.cb_safe.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cb_safe.Name = "cb_safe";
this.cb_safe.Size = new System.Drawing.Size(99, 25);
this.cb_safe.TabIndex = 1201;
//
// label11
//
this.label11.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label11.AutoSize = true;
this.label11.Location = new System.Drawing.Point(342, 77);
this.label11.Margin = new System.Windows.Forms.Padding(3, 7, 0, 0);
this.label11.Name = "label11";
this.label11.Size = new System.Drawing.Size(44, 17);
this.label11.TabIndex = 1199;
this.label11.Text = "AI检测";
//
// cmbNotes
//
this.cmbNotes.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cmbNotes.FormattingEnabled = true;
this.cmbNotes.Location = new System.Drawing.Point(554, 3);
this.cmbNotes.Location = new System.Drawing.Point(555, 3);
this.cmbNotes.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbNotes.Name = "cmbNotes";
this.cmbNotes.Size = new System.Drawing.Size(99, 25);
@@ -651,17 +686,17 @@ namespace TemuKJD.WXForms.ProductForms
"",
"是",
"否"});
this.cmbHasFission.Location = new System.Drawing.Point(888, 38);
this.cmbHasFission.Location = new System.Drawing.Point(889, 38);
this.cmbHasFission.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbHasFission.Name = "cmbHasFission";
this.cmbHasFission.Size = new System.Drawing.Size(101, 25);
this.cmbHasFission.Size = new System.Drawing.Size(100, 25);
this.cmbHasFission.TabIndex = 982;
//
// label8
//
this.label8.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label8.AutoSize = true;
this.label8.Location = new System.Drawing.Point(832, 42);
this.label8.Location = new System.Drawing.Point(833, 42);
this.label8.Margin = new System.Windows.Forms.Padding(3, 7, 0, 0);
this.label8.Name = "label8";
this.label8.Size = new System.Drawing.Size(56, 17);
@@ -674,7 +709,7 @@ namespace TemuKJD.WXForms.ProductForms
| System.Windows.Forms.AnchorStyles.Right)));
this.txtCatBoundLessThan.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txtCatBoundLessThan.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txtCatBoundLessThan.Location = new System.Drawing.Point(723, 38);
this.txtCatBoundLessThan.Location = new System.Drawing.Point(724, 38);
this.txtCatBoundLessThan.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtCatBoundLessThan.Name = "txtCatBoundLessThan";
this.txtCatBoundLessThan.Size = new System.Drawing.Size(99, 25);
@@ -684,7 +719,7 @@ namespace TemuKJD.WXForms.ProductForms
// chkCatBoundLessThan
//
this.chkCatBoundLessThan.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.chkCatBoundLessThan.Location = new System.Drawing.Point(659, 40);
this.chkCatBoundLessThan.Location = new System.Drawing.Point(660, 40);
this.chkCatBoundLessThan.Margin = new System.Windows.Forms.Padding(3, 5, 0, 0);
this.chkCatBoundLessThan.Name = "chkCatBoundLessThan";
this.chkCatBoundLessThan.Size = new System.Drawing.Size(64, 21);
@@ -774,7 +809,7 @@ namespace TemuKJD.WXForms.ProductForms
| System.Windows.Forms.AnchorStyles.Right)));
this.txtCatBoundMoreThan.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txtCatBoundMoreThan.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txtCatBoundMoreThan.Location = new System.Drawing.Point(554, 38);
this.txtCatBoundMoreThan.Location = new System.Drawing.Point(555, 38);
this.txtCatBoundMoreThan.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtCatBoundMoreThan.Name = "txtCatBoundMoreThan";
this.txtCatBoundMoreThan.Size = new System.Drawing.Size(99, 25);
@@ -784,7 +819,7 @@ namespace TemuKJD.WXForms.ProductForms
// chkCatBoundMoreThan
//
this.chkCatBoundMoreThan.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.chkCatBoundMoreThan.Location = new System.Drawing.Point(490, 40);
this.chkCatBoundMoreThan.Location = new System.Drawing.Point(491, 40);
this.chkCatBoundMoreThan.Margin = new System.Windows.Forms.Padding(3, 5, 0, 0);
this.chkCatBoundMoreThan.Name = "chkCatBoundMoreThan";
this.chkCatBoundMoreThan.Size = new System.Drawing.Size(64, 21);
@@ -826,7 +861,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.label17.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label17.AutoSize = true;
this.label17.Location = new System.Drawing.Point(342, 42);
this.label17.Location = new System.Drawing.Point(343, 42);
this.label17.Margin = new System.Windows.Forms.Padding(3, 7, 0, 0);
this.label17.Name = "label17";
this.label17.Size = new System.Drawing.Size(43, 17);
@@ -842,7 +877,7 @@ namespace TemuKJD.WXForms.ProductForms
this.cmbCat3.DropDownWidth = 1;
this.cmbCat3.FormattingEnabled = true;
this.cmbCat3.IntegralHeight = false;
this.cmbCat3.Location = new System.Drawing.Point(385, 38);
this.cmbCat3.Location = new System.Drawing.Point(386, 38);
this.cmbCat3.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbCat3.Name = "cmbCat3";
this.cmbCat3.Size = new System.Drawing.Size(99, 25);
@@ -855,7 +890,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.lblSourceType.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.lblSourceType.AutoSize = true;
this.lblSourceType.Location = new System.Drawing.Point(353, 7);
this.lblSourceType.Location = new System.Drawing.Point(354, 7);
this.lblSourceType.Margin = new System.Windows.Forms.Padding(3, 7, 0, 0);
this.lblSourceType.Name = "lblSourceType";
this.lblSourceType.Size = new System.Drawing.Size(32, 17);
@@ -872,7 +907,7 @@ namespace TemuKJD.WXForms.ProductForms
"多多商品",
"1688商品",
"微信商品"});
this.cmbSourceType.Location = new System.Drawing.Point(385, 3);
this.cmbSourceType.Location = new System.Drawing.Point(386, 3);
this.cmbSourceType.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbSourceType.Name = "cmbSourceType";
this.cmbSourceType.Size = new System.Drawing.Size(99, 25);
@@ -884,7 +919,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.lblNotes.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.lblNotes.AutoSize = true;
this.lblNotes.Location = new System.Drawing.Point(518, 7);
this.lblNotes.Location = new System.Drawing.Point(519, 7);
this.lblNotes.Margin = new System.Windows.Forms.Padding(3, 7, 0, 0);
this.lblNotes.Name = "lblNotes";
this.lblNotes.Size = new System.Drawing.Size(36, 17);
@@ -895,7 +930,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.label12.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label12.AutoSize = true;
this.label12.Location = new System.Drawing.Point(663, 7);
this.label12.Location = new System.Drawing.Point(664, 7);
this.label12.Margin = new System.Windows.Forms.Padding(3, 7, 0, 0);
this.label12.Name = "label12";
this.label12.Size = new System.Drawing.Size(60, 17);
@@ -911,7 +946,7 @@ namespace TemuKJD.WXForms.ProductForms
"",
"是",
"否"});
this.cmbWxCat.Location = new System.Drawing.Point(723, 3);
this.cmbWxCat.Location = new System.Drawing.Point(724, 3);
this.cmbWxCat.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbWxCat.Name = "cmbWxCat";
this.cmbWxCat.Size = new System.Drawing.Size(99, 25);
@@ -921,7 +956,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.lblWxSafe.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.lblWxSafe.AutoSize = true;
this.lblWxSafe.Location = new System.Drawing.Point(828, 7);
this.lblWxSafe.Location = new System.Drawing.Point(829, 7);
this.lblWxSafe.Margin = new System.Windows.Forms.Padding(3, 7, 0, 0);
this.lblWxSafe.Name = "lblWxSafe";
this.lblWxSafe.Size = new System.Drawing.Size(60, 17);
@@ -938,10 +973,10 @@ namespace TemuKJD.WXForms.ProductForms
"安全+未校验",
"安全商品",
"未校验"});
this.cmbWxSafe.Location = new System.Drawing.Point(888, 3);
this.cmbWxSafe.Location = new System.Drawing.Point(889, 3);
this.cmbWxSafe.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbWxSafe.Name = "cmbWxSafe";
this.cmbWxSafe.Size = new System.Drawing.Size(101, 25);
this.cmbWxSafe.Size = new System.Drawing.Size(100, 25);
this.cmbWxSafe.TabIndex = 676;
this.cmbWxSafe.Text = "安全+未校验";
//
@@ -977,17 +1012,54 @@ namespace TemuKJD.WXForms.ProductForms
this.dtpEnd.Size = new System.Drawing.Size(99, 23);
this.dtpEnd.TabIndex = 982;
//
// btnSafeDetection
//
this.btnSafeDetection.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnSafeDetection.ColorSchemeStyle = DevComponents.DotNetBar.eDotNetBarStyle.StyleManagerControlled;
this.btnSafeDetection.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnSafeDetection.DisabledBackColor = System.Drawing.Color.Empty;
this.btnSafeDetection.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
this.btnSafeDetection.Location = new System.Drawing.Point(893, 73);
this.btnSafeDetection.Name = "btnSafeDetection";
this.btnSafeDetection.Size = new System.Drawing.Size(96, 25);
this.btnSafeDetection.Style.Alignment = System.Drawing.StringAlignment.Center;
this.btnSafeDetection.Style.BackColor1.Color = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(126)))), ((int)(((byte)(255)))));
this.btnSafeDetection.Style.BackColor2.Color = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(126)))), ((int)(((byte)(255)))));
this.btnSafeDetection.Style.BorderColor.ColorSchemePart = DevComponents.DotNetBar.eColorSchemePart.PanelBorder;
this.btnSafeDetection.Style.BorderDashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
this.btnSafeDetection.Style.BorderSide = DevComponents.DotNetBar.eBorderSide.None;
this.btnSafeDetection.Style.ForeColor.Color = System.Drawing.Color.White;
this.btnSafeDetection.Style.GradientAngle = 90;
this.btnSafeDetection.StyleMouseOver.Alignment = System.Drawing.StringAlignment.Center;
this.btnSafeDetection.StyleMouseOver.BackColor1.Color = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(102)))), ((int)(((byte)(255)))));
this.btnSafeDetection.StyleMouseOver.BackColor2.Color = System.Drawing.Color.FromArgb(((int)(((byte)(25)))), ((int)(((byte)(102)))), ((int)(((byte)(255)))));
this.btnSafeDetection.TabIndex = 1202;
this.btnSafeDetection.Text = "AI检测";
this.btnSafeDetection.Click += new System.EventHandler(this.btnSafeDetection_Click);
//
// txt_listing_time
//
this.txt_listing_time.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txt_listing_time.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_listing_time.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_listing_time.Location = new System.Drawing.Point(555, 73);
this.txt_listing_time.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txt_listing_time.Name = "txt_listing_time";
this.txt_listing_time.Size = new System.Drawing.Size(99, 25);
this.txt_listing_time.TabIndex = 984;
this.txt_listing_time.Text = "365";
//
// label10
//
this.label10.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.label10.AutoSize = true;
this.label10.Location = new System.Drawing.Point(832, 77);
this.label10.Location = new System.Drawing.Point(499, 77);
this.label10.Margin = new System.Windows.Forms.Padding(3, 7, 0, 0);
this.label10.Name = "label10";
this.label10.Size = new System.Drawing.Size(56, 17);
this.label10.TabIndex = 983;
this.label10.Text = "上架日期";
this.toolTip1.SetToolTip(this.label10, "导入数据时超出时间(天)范围的不导入");
//
// label7
//
@@ -1036,14 +1108,14 @@ namespace TemuKJD.WXForms.ProductForms
this.splitContainer2.Panel2.Controls.Add(this.ucSplitPage1);
this.splitContainer2.Panel2.Controls.Add(this.statusBar);
this.splitContainer2.Size = new System.Drawing.Size(1438, 567);
this.splitContainer2.SplitterDistance = 538;
this.splitContainer2.SplitterDistance = 537;
this.splitContainer2.TabIndex = 0;
//
// lblRelation
//
this.lblRelation.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.lblRelation.AutoSize = true;
this.lblRelation.Location = new System.Drawing.Point(246, 69);
this.lblRelation.Location = new System.Drawing.Point(246, 68);
this.lblRelation.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.lblRelation.Name = "lblRelation";
this.lblRelation.Size = new System.Drawing.Size(68, 17);
@@ -1055,7 +1127,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.pbLoading.Anchor = System.Windows.Forms.AnchorStyles.None;
this.pbLoading.Image = global::TemuKJD.Properties.Resources.loading_blue;
this.pbLoading.Location = new System.Drawing.Point(694, 244);
this.pbLoading.Location = new System.Drawing.Point(694, 243);
this.pbLoading.Name = "pbLoading";
this.pbLoading.Size = new System.Drawing.Size(50, 50);
this.pbLoading.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
@@ -1066,7 +1138,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.label16.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label16.AutoSize = true;
this.label16.Location = new System.Drawing.Point(22, 197);
this.label16.Location = new System.Drawing.Point(22, 196);
this.label16.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label16.Name = "label16";
this.label16.Size = new System.Drawing.Size(69, 17);
@@ -1077,7 +1149,7 @@ namespace TemuKJD.WXForms.ProductForms
// txtRealCoid
//
this.txtRealCoid.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.txtRealCoid.Location = new System.Drawing.Point(91, 129);
this.txtRealCoid.Location = new System.Drawing.Point(91, 128);
this.txtRealCoid.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtRealCoid.Name = "txtRealCoid";
this.txtRealCoid.Size = new System.Drawing.Size(133, 23);
@@ -1087,7 +1159,7 @@ namespace TemuKJD.WXForms.ProductForms
// txtSKC
//
this.txtSKC.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.txtSKC.Location = new System.Drawing.Point(91, 194);
this.txtSKC.Location = new System.Drawing.Point(91, 193);
this.txtSKC.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtSKC.Name = "txtSKC";
this.txtSKC.Size = new System.Drawing.Size(133, 23);
@@ -1098,7 +1170,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.label13.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label13.AutoSize = true;
this.label13.Location = new System.Drawing.Point(23, 163);
this.label13.Location = new System.Drawing.Point(23, 162);
this.label13.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(68, 17);
@@ -1109,7 +1181,7 @@ namespace TemuKJD.WXForms.ProductForms
// txtSecretStyleCode
//
this.txtSecretStyleCode.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.txtSecretStyleCode.Location = new System.Drawing.Point(91, 37);
this.txtSecretStyleCode.Location = new System.Drawing.Point(91, 36);
this.txtSecretStyleCode.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtSecretStyleCode.Name = "txtSecretStyleCode";
this.txtSecretStyleCode.Size = new System.Drawing.Size(133, 23);
@@ -1120,7 +1192,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.label1.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(22, 133);
this.label1.Location = new System.Drawing.Point(22, 132);
this.label1.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(69, 17);
@@ -1131,7 +1203,7 @@ namespace TemuKJD.WXForms.ProductForms
// chkWXComplateProd
//
this.chkWXComplateProd.Anchor = System.Windows.Forms.AnchorStyles.Left;
this.chkWXComplateProd.Location = new System.Drawing.Point(25, 233);
this.chkWXComplateProd.Location = new System.Drawing.Point(25, 232);
this.chkWXComplateProd.Margin = new System.Windows.Forms.Padding(6, 3, 3, 3);
this.chkWXComplateProd.Name = "chkWXComplateProd";
this.chkWXComplateProd.Size = new System.Drawing.Size(87, 21);
@@ -1144,7 +1216,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.lblGroup.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.lblGroup.AutoSize = true;
this.lblGroup.Location = new System.Drawing.Point(270, 37);
this.lblGroup.Location = new System.Drawing.Point(270, 36);
this.lblGroup.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.lblGroup.Name = "lblGroup";
this.lblGroup.Size = new System.Drawing.Size(44, 17);
@@ -1156,7 +1228,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.cmbGroupFilter.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.cmbGroupFilter.FormattingEnabled = true;
this.cmbGroupFilter.Location = new System.Drawing.Point(314, 34);
this.cmbGroupFilter.Location = new System.Drawing.Point(314, 33);
this.cmbGroupFilter.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbGroupFilter.Name = "cmbGroupFilter";
this.cmbGroupFilter.Size = new System.Drawing.Size(146, 25);
@@ -1167,7 +1239,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.label15.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label15.AutoSize = true;
this.label15.Location = new System.Drawing.Point(47, 40);
this.label15.Location = new System.Drawing.Point(47, 39);
this.label15.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label15.Name = "label15";
this.label15.Size = new System.Drawing.Size(44, 17);
@@ -1178,7 +1250,7 @@ namespace TemuKJD.WXForms.ProductForms
// txtExtCode
//
this.txtExtCode.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Left | System.Windows.Forms.AnchorStyles.Right)));
this.txtExtCode.Location = new System.Drawing.Point(91, 67);
this.txtExtCode.Location = new System.Drawing.Point(91, 66);
this.txtExtCode.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txtExtCode.Name = "txtExtCode";
this.txtExtCode.Size = new System.Drawing.Size(133, 23);
@@ -1189,7 +1261,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.label4.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(47, 70);
this.label4.Location = new System.Drawing.Point(47, 69);
this.label4.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(44, 17);
@@ -1206,7 +1278,7 @@ namespace TemuKJD.WXForms.ProductForms
"是",
"否",
"导出未拉回"});
this.cmbExportToOutServer.Location = new System.Drawing.Point(91, 159);
this.cmbExportToOutServer.Location = new System.Drawing.Point(91, 158);
this.cmbExportToOutServer.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbExportToOutServer.Name = "cmbExportToOutServer";
this.cmbExportToOutServer.Size = new System.Drawing.Size(133, 25);
@@ -1221,7 +1293,7 @@ namespace TemuKJD.WXForms.ProductForms
"",
"是",
"否"});
this.cmbRelation.Location = new System.Drawing.Point(314, 69);
this.cmbRelation.Location = new System.Drawing.Point(314, 68);
this.cmbRelation.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbRelation.Name = "cmbRelation";
this.cmbRelation.Size = new System.Drawing.Size(146, 25);
@@ -1235,7 +1307,7 @@ namespace TemuKJD.WXForms.ProductForms
this.cmbSort.Items.AddRange(new object[] {
"入库时间",
"认领总数"});
this.cmbSort.Location = new System.Drawing.Point(91, 96);
this.cmbSort.Location = new System.Drawing.Point(91, 95);
this.cmbSort.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.cmbSort.Name = "cmbSort";
this.cmbSort.Size = new System.Drawing.Size(133, 25);
@@ -1247,7 +1319,7 @@ namespace TemuKJD.WXForms.ProductForms
//
this.label6.Anchor = System.Windows.Forms.AnchorStyles.Right;
this.label6.AutoSize = true;
this.label6.Location = new System.Drawing.Point(47, 100);
this.label6.Location = new System.Drawing.Point(47, 99);
this.label6.Margin = new System.Windows.Forms.Padding(3, 0, 0, 0);
this.label6.Name = "label6";
this.label6.Size = new System.Drawing.Size(44, 17);
@@ -1259,20 +1331,20 @@ namespace TemuKJD.WXForms.ProductForms
//
this.dgvDbProduct.AllowUserToAddRows = false;
this.dgvDbProduct.AllowUserToDeleteRows = false;
dataGridViewCellStyle1.BackColor = System.Drawing.Color.WhiteSmoke;
this.dgvDbProduct.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle1;
dataGridViewCellStyle18.BackColor = System.Drawing.Color.WhiteSmoke;
this.dgvDbProduct.AlternatingRowsDefaultCellStyle = dataGridViewCellStyle18;
this.dgvDbProduct.AutoRowNumber = true;
this.dgvDbProduct.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
this.dgvDbProduct.BackgroundColor = System.Drawing.Color.White;
this.dgvDbProduct.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(126)))), ((int)(((byte)(255)))));
dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle2.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.dgvDbProduct.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle2;
dataGridViewCellStyle19.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
dataGridViewCellStyle19.BackColor = System.Drawing.SystemColors.Control;
dataGridViewCellStyle19.Font = new System.Drawing.Font("微软雅黑", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
dataGridViewCellStyle19.ForeColor = System.Drawing.SystemColors.WindowText;
dataGridViewCellStyle19.SelectionBackColor = System.Drawing.SystemColors.Highlight;
dataGridViewCellStyle19.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
dataGridViewCellStyle19.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
this.dgvDbProduct.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle19;
this.dgvDbProduct.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.dgvDbProduct.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.colSelect,
@@ -1306,6 +1378,7 @@ namespace TemuKJD.WXForms.ProductForms
this.colGetType,
this.colSpProdType,
this.colWxSafe,
this.colDetectionResult,
this.colAddTime,
this.colMdyTime,
this.col_edit,
@@ -1317,7 +1390,7 @@ namespace TemuKJD.WXForms.ProductForms
this.dgvDbProduct.Name = "dgvDbProduct";
this.dgvDbProduct.ReadOnly = true;
this.dgvDbProduct.RowTemplate.Height = 23;
this.dgvDbProduct.Size = new System.Drawing.Size(1430, 538);
this.dgvDbProduct.Size = new System.Drawing.Size(1430, 537);
this.dgvDbProduct.TabIndex = 6;
this.dgvDbProduct.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this.dgvDbProduct_CellContentClick);
this.dgvDbProduct.Scroll += new System.Windows.Forms.ScrollEventHandler(this.dgvDbProduct_Scroll);
@@ -1355,8 +1428,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// col_product_name
//
dataGridViewCellStyle3.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_product_name.DefaultCellStyle = dataGridViewCellStyle3;
dataGridViewCellStyle20.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_product_name.DefaultCellStyle = dataGridViewCellStyle20;
this.col_product_name.FillWeight = 140F;
this.col_product_name.HeaderText = "标题";
this.col_product_name.Name = "col_product_name";
@@ -1399,8 +1472,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// col_spu_id
//
dataGridViewCellStyle4.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_spu_id.DefaultCellStyle = dataGridViewCellStyle4;
dataGridViewCellStyle21.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_spu_id.DefaultCellStyle = dataGridViewCellStyle21;
this.col_spu_id.HeaderText = "真实商品Id";
this.col_spu_id.Name = "col_spu_id";
this.col_spu_id.ReadOnly = true;
@@ -1422,8 +1495,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// colMainCate
//
dataGridViewCellStyle5.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colMainCate.DefaultCellStyle = dataGridViewCellStyle5;
dataGridViewCellStyle22.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colMainCate.DefaultCellStyle = dataGridViewCellStyle22;
this.colMainCate.FillWeight = 50F;
this.colMainCate.HeaderText = "主类目";
this.colMainCate.Name = "colMainCate";
@@ -1431,8 +1504,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// col_cat_name
//
dataGridViewCellStyle6.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_cat_name.DefaultCellStyle = dataGridViewCellStyle6;
dataGridViewCellStyle23.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_cat_name.DefaultCellStyle = dataGridViewCellStyle23;
this.col_cat_name.FillWeight = 60F;
this.col_cat_name.HeaderText = "类目";
this.col_cat_name.Name = "col_cat_name";
@@ -1447,8 +1520,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// col_ext_code
//
dataGridViewCellStyle7.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_ext_code.DefaultCellStyle = dataGridViewCellStyle7;
dataGridViewCellStyle24.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_ext_code.DefaultCellStyle = dataGridViewCellStyle24;
this.col_ext_code.HeaderText = "货号";
this.col_ext_code.Name = "col_ext_code";
this.col_ext_code.ReadOnly = true;
@@ -1456,8 +1529,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// colStyleCode
//
dataGridViewCellStyle8.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colStyleCode.DefaultCellStyle = dataGridViewCellStyle8;
dataGridViewCellStyle25.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colStyleCode.DefaultCellStyle = dataGridViewCellStyle25;
this.colStyleCode.HeaderText = "资料编码/真实上家";
this.colStyleCode.Name = "colStyleCode";
this.colStyleCode.ReadOnly = true;
@@ -1465,8 +1538,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// colGroup
//
dataGridViewCellStyle9.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colGroup.DefaultCellStyle = dataGridViewCellStyle9;
dataGridViewCellStyle26.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colGroup.DefaultCellStyle = dataGridViewCellStyle26;
this.colGroup.HeaderText = "分组";
this.colGroup.Name = "colGroup";
this.colGroup.ReadOnly = true;
@@ -1474,8 +1547,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// colPriceText
//
dataGridViewCellStyle10.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colPriceText.DefaultCellStyle = dataGridViewCellStyle10;
dataGridViewCellStyle27.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colPriceText.DefaultCellStyle = dataGridViewCellStyle27;
this.colPriceText.FillWeight = 60F;
this.colPriceText.HeaderText = "母店价格";
this.colPriceText.Name = "colPriceText";
@@ -1525,8 +1598,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// col_notes
//
dataGridViewCellStyle11.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_notes.DefaultCellStyle = dataGridViewCellStyle11;
dataGridViewCellStyle28.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.col_notes.DefaultCellStyle = dataGridViewCellStyle28;
this.col_notes.FillWeight = 70F;
this.col_notes.HeaderText = "备注";
this.col_notes.Name = "col_notes";
@@ -1534,8 +1607,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// colHeadWords
//
dataGridViewCellStyle12.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colHeadWords.DefaultCellStyle = dataGridViewCellStyle12;
dataGridViewCellStyle29.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colHeadWords.DefaultCellStyle = dataGridViewCellStyle29;
this.colHeadWords.HeaderText = "标题前缀";
this.colHeadWords.Name = "colHeadWords";
this.colHeadWords.ReadOnly = true;
@@ -1543,8 +1616,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// colEndWords
//
dataGridViewCellStyle13.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colEndWords.DefaultCellStyle = dataGridViewCellStyle13;
dataGridViewCellStyle30.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colEndWords.DefaultCellStyle = dataGridViewCellStyle30;
this.colEndWords.HeaderText = "标题后缀";
this.colEndWords.Name = "colEndWords";
this.colEndWords.ReadOnly = true;
@@ -1552,16 +1625,16 @@ namespace TemuKJD.WXForms.ProductForms
//
// colFissionWords
//
dataGridViewCellStyle14.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colFissionWords.DefaultCellStyle = dataGridViewCellStyle14;
dataGridViewCellStyle31.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colFissionWords.DefaultCellStyle = dataGridViewCellStyle31;
this.colFissionWords.HeaderText = "裂变标题";
this.colFissionWords.Name = "colFissionWords";
this.colFissionWords.ReadOnly = true;
//
// colGetType
//
dataGridViewCellStyle15.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colGetType.DefaultCellStyle = dataGridViewCellStyle15;
dataGridViewCellStyle32.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colGetType.DefaultCellStyle = dataGridViewCellStyle32;
this.colGetType.FillWeight = 70F;
this.colGetType.HeaderText = "采集来源";
this.colGetType.Name = "colGetType";
@@ -1582,10 +1655,20 @@ namespace TemuKJD.WXForms.ProductForms
this.colWxSafe.Name = "colWxSafe";
this.colWxSafe.ReadOnly = true;
//
// colDetectionResult
//
this.colDetectionResult.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.None;
this.colDetectionResult.HeaderText = "AI检测结果";
this.colDetectionResult.MinimumWidth = 50;
this.colDetectionResult.Name = "colDetectionResult";
this.colDetectionResult.ReadOnly = true;
this.colDetectionResult.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
this.colDetectionResult.Width = 160;
//
// colAddTime
//
dataGridViewCellStyle16.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colAddTime.DefaultCellStyle = dataGridViewCellStyle16;
dataGridViewCellStyle33.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colAddTime.DefaultCellStyle = dataGridViewCellStyle33;
this.colAddTime.FillWeight = 70F;
this.colAddTime.HeaderText = "入库时间";
this.colAddTime.Name = "colAddTime";
@@ -1593,8 +1676,8 @@ namespace TemuKJD.WXForms.ProductForms
//
// colMdyTime
//
dataGridViewCellStyle17.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colMdyTime.DefaultCellStyle = dataGridViewCellStyle17;
dataGridViewCellStyle34.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
this.colMdyTime.DefaultCellStyle = dataGridViewCellStyle34;
this.colMdyTime.FillWeight = 70F;
this.colMdyTime.HeaderText = "更新时间";
this.colMdyTime.Name = "colMdyTime";
@@ -1639,7 +1722,7 @@ namespace TemuKJD.WXForms.ProductForms
this.ucSplitPage1.Name = "ucSplitPage1";
this.ucSplitPage1.Padding = new System.Windows.Forms.Padding(0, 0, 1, 0);
this.ucSplitPage1.PageSize = 100;
this.ucSplitPage1.Size = new System.Drawing.Size(453, 25);
this.ucSplitPage1.Size = new System.Drawing.Size(453, 26);
this.ucSplitPage1.TabIndex = 6;
this.ucSplitPage1.TotalCount = ((long)(0));
this.ucSplitPage1.TotalPage = 1;
@@ -1652,22 +1735,9 @@ namespace TemuKJD.WXForms.ProductForms
this.statusBar.Location = new System.Drawing.Point(0, 0);
this.statusBar.Margin = new System.Windows.Forms.Padding(0);
this.statusBar.Name = "statusBar";
this.statusBar.Size = new System.Drawing.Size(1438, 25);
this.statusBar.Size = new System.Drawing.Size(1438, 26);
this.statusBar.TabIndex = 5;
//
// txt_listing_time
//
this.txt_listing_time.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txt_listing_time.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.txt_listing_time.Font = new System.Drawing.Font("微软雅黑", 10F);
this.txt_listing_time.Location = new System.Drawing.Point(888, 73);
this.txt_listing_time.Margin = new System.Windows.Forms.Padding(0, 3, 3, 3);
this.txt_listing_time.Name = "txt_listing_time";
this.txt_listing_time.Size = new System.Drawing.Size(101, 25);
this.txt_listing_time.TabIndex = 984;
this.txt_listing_time.Text = "365";
//
// WXUserCollectAuthProdListForm
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
@@ -1764,6 +1834,21 @@ namespace TemuKJD.WXForms.ProductForms
private System.Windows.Forms.Label label8;
private System.Windows.Forms.ComboBox cmbHasFission;
private DevComponents.DotNetBar.PanelEx btnAITitleFission;
private DevComponents.DotNetBar.PanelEx btnBatchEditNotes;
private DevComponents.DotNetBar.PanelEx btnEditNotes;
public System.Windows.Forms.ComboBox cmbNotes;
public System.Windows.Forms.ComboBox cmbBatchEditNotes;
private DevComponents.DotNetBar.PanelEx btnBatchEditCate;
private DevComponents.DotNetBar.PanelEx btn_import_wx;
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.Label label9;
private UserComponent.UcCheckBox chkTime;
private System.Windows.Forms.DateTimePicker dtpStart;
private System.Windows.Forms.DateTimePicker dtpEnd;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.TextBox txt_listing_time;
private System.Windows.Forms.Label label11;
public System.Windows.Forms.ComboBox cb_safe;
private System.Windows.Forms.DataGridViewCheckBoxColumn colSelect;
private System.Windows.Forms.DataGridViewTextBoxColumn col_db_id;
private System.Windows.Forms.DataGridViewTextBoxColumn colFromShopId;
@@ -1795,23 +1880,12 @@ namespace TemuKJD.WXForms.ProductForms
private System.Windows.Forms.DataGridViewTextBoxColumn colGetType;
private System.Windows.Forms.DataGridViewTextBoxColumn colSpProdType;
private System.Windows.Forms.DataGridViewTextBoxColumn colWxSafe;
private System.Windows.Forms.DataGridViewTextBoxColumn colDetectionResult;
private System.Windows.Forms.DataGridViewTextBoxColumn colAddTime;
private System.Windows.Forms.DataGridViewTextBoxColumn colMdyTime;
private System.Windows.Forms.DataGridViewLinkColumn col_edit;
private System.Windows.Forms.DataGridViewLinkColumn col_delete;
private System.Windows.Forms.DataGridViewLinkColumn col_select_product;
private DevComponents.DotNetBar.PanelEx btnBatchEditNotes;
private System.Windows.Forms.DateTimePicker dtpStart;
private System.Windows.Forms.DateTimePicker dtpEnd;
private UserComponent.UcCheckBox chkTime;
private System.Windows.Forms.Label label9;
private DevComponents.DotNetBar.PanelEx btnEditNotes;
public System.Windows.Forms.ComboBox cmbNotes;
public System.Windows.Forms.ComboBox cmbBatchEditNotes;
private DevComponents.DotNetBar.PanelEx btnBatchEditCate;
private DevComponents.DotNetBar.PanelEx btn_import_wx;
private System.Windows.Forms.Label label10;
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.TextBox txt_listing_time;
private DevComponents.DotNetBar.PanelEx btnSafeDetection;
}
}
@@ -28,12 +28,14 @@ using TemuKJD.Extension;
using TemuKJD.PDDForms.ProductSelectForms;
using TemuKJD.ToolForms;
using Work;
using Work.Services;
namespace TemuKJD.WXForms.ProductForms
{
public partial class WXUserCollectAuthProdListForm : BaseGeneralForm
{
ShopLoginInfo shop = null;
private CancellationTokenSource detection;
public CancellationTokenSource cancellationTokenSource { get; set; } = new CancellationTokenSource();
ConcurrentList<KJDDBProduct> lstTemuDbProduct = new ConcurrentList<KJDDBProduct>();
@@ -42,11 +44,13 @@ namespace TemuKJD.WXForms.ProductForms
public WXUserCollectAuthProdListForm()
{
InitializeComponent();
Disposed += (sender, e) => detection?.Cancel();
}
public WXUserCollectAuthProdListForm(ShopLoginInfo _shop)
{
InitializeComponent();
Disposed += (sender, e) => detection?.Cancel();
shop = _shop;
}
@@ -61,7 +65,7 @@ namespace TemuKJD.WXForms.ProductForms
PDDDBProdListForm.GetPDDProductNotes(new List<ComboBox> { cmbNotes }, addUserName);
PDDDBProdListForm.GetPDDProductNotes(new List<ComboBox> { cmbBatchEditNotes }, addUserName);
});
cb_safe.SelectedIndex = 0;
//chkCatBoundLessThan.Visible = false;
//chkCatBoundMoreThan.Visible = false;
//tableLayoutPanel1.SetColumn(lblSourceType, 2);
@@ -271,11 +275,13 @@ namespace TemuKJD.WXForms.ProductForms
.Replace("已采集数据", "1688商品").Replace("机会商品", "多多商品").Replace("多多外部数据", "多多商品").Replace("微信店采", "微信商品"),
prod.special_prod_type,
prod.wx_safe_status,
prod.is_safe == null ? "未检测" : prod.is_safe.Value ==true ? "安全" : "违规",
prod.add_time.ToString("yy-MM-dd HH:mm"),
prod.mdy_time.ToString("yy-MM-dd HH:mm"),
"编辑",
"删除",
"认领"
"认领",
"未检测"
);
dgvDbProduct.Rows[rowIndex].Height = dgvDbProduct.Columns["colMainImg"].Width;
@@ -523,7 +529,7 @@ namespace TemuKJD.WXForms.ProductForms
{
data += "&no_fission_words=true";
}
data += "&safe_status=" + cb_safe.SelectedIndex;
if (isNotCount)
data += "&is_not_count=true";
}));
@@ -981,6 +987,7 @@ namespace TemuKJD.WXForms.ProductForms
private void WXUserProdListForm_FormClosing(object sender, FormClosingEventArgs e)
{
detection?.Cancel();
this.Hide();
e.Cancel = true;
}
@@ -1275,6 +1282,89 @@ namespace TemuKJD.WXForms.ProductForms
SearchDbProd(1);
}
private async void btnSafeDetection_Click(object sender, EventArgs e)
{
if (detection != null)
{
detection.Cancel();
btnSafeDetection.Text = "正在停止";
return;
}
if (pbLoading.Visible || !btnSelect.Enabled || !btn_import_wx.Enabled)
{
BaseMsgForm.ShowInfo("请等待当前操作完成后再检测。");
return;
}
var rows = dgvDbProduct.Rows.Cast<DataGridViewRow>()
.Where(row => row.Cells["colSelect"].Value.ParseToBool()).ToList();
var ids = rows.Select(row => row.Cells["col_db_id"].Value.ParseToInt()).ToList();
var productDict = lstTemuDbProduct
.Where(p => ids.Contains(p.id))
.ToDictionary(p => p.id);
var selected = ids
.Where(id => productDict.ContainsKey(id))
.Select(id =>
{
var prod = productDict[id];
return new ComplianceGoods
{
id = prod.id.ToString(),
name = prod.product_name,
image = prod.main_img,
type = ComplianceGoods.Library
};
})
.ToList();
if (selected.Count == 0)
{
BaseMsgForm.ShowInfo("请选择商品");
return;
}
if (BaseClass.ImageAnalysisQuota > 0)
{
BaseMsgForm.ShowInfo($"当前AI检测剩余:{BaseClass.ImageAnalysisQuota}张");
}
else
{
BaseMsgForm.ShowInfo($"当前AI检测剩余:{BaseClass.ImageAnalysisQuota}张,请兑换");
return;
}
var originalText = btnSafeDetection.Text;
detection = new CancellationTokenSource();
try
{
btnSafeDetection.Text = "停止检测";
var result = await GoodsComplianceService.DetectSelectedAsync(selected, ComplianceProductReader.Read, (id, status) =>
{
if (IsDisposed) return;
foreach (var row in rows.Where(r => r.Cells["col_db_id"].Value.ParseToString() == id))
row.Cells["colDetectionResult"].Value = status;
}, detection.Token);
if (!IsDisposed)
{
var title = result.Unfinished > 0 ? "AI 检测已停止" : "AI 检测完成";
BaseMsgForm.ShowInfo($"{title}:安全 {result.Safe},有风险 {result.Risk},失败 {result.Failed},未完成 {result.Unfinished}。");
}
}
catch (Exception ex) { if (!IsDisposed) MessageBox.Show(this, ex.Message); }
finally
{
detection.Dispose();
detection = null;
if (!IsDisposed)
{
btnSafeDetection.Text = originalText;
}
}
}
private void btnAITitleFission_Click(object sender, EventArgs e)
{
var lstProdId = dgvDbProduct.Rows.Cast<DataGridViewRow>().Where(row
@@ -1375,6 +1465,5 @@ namespace TemuKJD.WXForms.ProductForms
SearchDbProd(this.ucSplitPage1.CurrentPage);
}
}
}
@@ -117,9 +117,6 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="colSelect.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
@@ -228,6 +225,9 @@
<metadata name="col_select_product.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
+31 -95
View File
@@ -6,7 +6,7 @@ using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Work.Store.Api;
using System.Threading.Tasks;
using Work.Api.Wx;
@@ -17,35 +17,13 @@ namespace Work.Services
/// </summary>
public class CloudGoodsService
{
private static string ServerUrl = "http://103.90.155.78:9001";
static CloudGoodsService()
{
if (EnvironmentHelper.IsDevelopment)
{
ServerUrl = "http://localhost:14312";
}
}
public static async Task<PageData<CloudGoods>> GetGoods(GoodsSearchRequest request)
{
var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/SearchGoods", request);
var ret = JsonConvert.DeserializeObject<Result<PageData<CloudGoods>>>(html);
if (ret.Code != 200)
{
throw new Exception(ret.Msg);
}
return ret.Data;
return await StoreApiClient.Instance.CloudGoods.GetGoods(request);
}
public static string GetGoodsDetail(long goodsId)
{
var html = GetHtml.PostJson(ServerUrl + $"/api/CloudGoods/GetGoodsRawData?goodsId={goodsId}", "");
var ret = JsonConvert.DeserializeObject<Result<string>>(html);
if (ret.Code != 200)
{
throw new Exception(ret.Msg);
}
return ret.Data;
return StoreApiClient.Instance.CloudGoods.GetGoodsDetail(goodsId);
}
/// <summary>
@@ -338,17 +316,7 @@ namespace Work.Services
throw new ArgumentException("违规商品列表不能包含空项。", nameof(items));
}
var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/ReportViolations", items, timeOut: 5);
var ret = JsonConvert.DeserializeObject<Result<List<ReportGoodsViolationResult>>>(html);
if (ret == null)
{
throw new Exception("批量上报违规商品返回为空。");
}
if (ret.Code != 200)
{
throw new Exception(ret.Msg);
}
return ret.Data ?? throw new Exception("批量上报违规商品返回数据为空。");
return await StoreApiClient.Instance.CloudGoods.ReportViolations(items);
}
/// <summary>
@@ -361,17 +329,7 @@ namespace Work.Services
throw new ArgumentNullException(nameof(goodsIds));
}
var html = GetHtml.PostJson(ServerUrl + "/api/CloudGoods/GetViolationStatus", goodsIds, timeOut: 5);
var ret = JsonConvert.DeserializeObject<Result<List<GoodsViolationStatus>>>(html);
if (ret == null)
{
throw new Exception("批量查询商品违规状态返回为空。");
}
if (ret.Code != 200)
{
throw new Exception(ret.Msg);
}
return ret.Data ?? throw new Exception("批量查询商品违规状态返回数据为空。");
return StoreApiClient.Instance.CloudGoods.GetViolationStatus(goodsIds);
}
/// <summary>逐原因记录店铺动作。日志请求失败不能改变剔除决定或中断后续下架。</summary>
@@ -424,23 +382,13 @@ namespace Work.Services
{
if (requests == null || requests.Count == 0 || requests.Any(item => item == null))
throw new ArgumentException("请提供有效的违规日志。", nameof(requests));
var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/RecordViolationLog", requests, timeOut: 5);
var ret = JsonConvert.DeserializeObject<Result>(html) ?? throw new Exception("记录违规日志返回为空。");
if (ret.Code != 200)
throw new Exception(ret.Msg);
await StoreApiClient.Instance.CloudGoods.RecordViolationLogs(requests);
}
/// <summary>读取日志筛选和显示使用的违规原因字典。</summary>
public static async Task<List<ViolationReason>> GetViolationReasons()
{
using (var web = new System.Net.WebClient { Encoding = Encoding.UTF8 })
{
var html = await web.DownloadStringTaskAsync(ServerUrl + "/api/CloudGoods/GetViolationReasons");
var ret = JsonConvert.DeserializeObject<Result<List<ViolationReason>>>(html);
if (ret?.Code != 200 || ret.Data == null)
throw new Exception(ret?.Msg ?? "查询违规类型返回为空。");
return ret.Data;
}
return await StoreApiClient.Instance.CloudGoods.GetViolationReasons();
}
public class ViolationReason
@@ -457,12 +405,7 @@ namespace Work.Services
if (shopIds == null || shopIds.Length == 0 || shopIds.Any(string.IsNullOrWhiteSpace))
throw new ArgumentException("请提供有效的店铺编号。", nameof(shopIds));
var request = new GetViolationLogsRequest { ShopIds = shopIds, GoodsId = goodsId, BeforeId = beforeId, Size = size };
var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/GetViolationLogs", request, timeOut: 5);
var ret = JsonConvert.DeserializeObject<Result<List<GoodsViolationLogEntity>>>(html)
?? throw new Exception("查询违规日志返回为空。");
if (ret.Code != 200)
throw new Exception(ret.Msg);
return ret.Data ?? throw new Exception("查询违规日志返回数据为空。");
return await StoreApiClient.Instance.CloudGoods.GetViolationLogs(request);
}
#region user
@@ -475,14 +418,13 @@ namespace Work.Services
public static async Task<PageData<CloudGoods>> SearchFavorites(UserFavoritesGoodsSearchRequest request)
{
request.UserName = GetUserName();
var html = await GetHtml.PostJsonAsync(ServerUrl + "/api/CloudGoods/SearchFavorites", request);
var ret = JsonConvert.DeserializeObject<Result<PageData<CloudGoods>>>(html);
if (ret.Code != 200)
var page = await StoreApiClient.Instance.CloudGoods.SearchFavorites(request);
foreach (var item in page.List)
{
throw new Exception(ret.Msg);
item.DetectionResult = item.IsSafe == null ? "未检测" : item.IsSafe.Value ? "安全" : "违规";
}
return ret.Data;
return page;
}
/// <summary>
@@ -494,18 +436,7 @@ namespace Work.Services
public static async Task<int> Favorite(List<long> goodsIds)
{
var html = await GetHtml.PostJsonAsync(ServerUrl + $"/api/CloudGoods/AddFavorite", new
{
UserName = GetUserName(),
GoodsIds = goodsIds,
});
var ret = JsonConvert.DeserializeObject<Result<int>>(html);
if (ret.Code != 200)
{
throw new Exception(ret.Msg);
}
return ret.Data;
return await StoreApiClient.Instance.CloudGoods.Favorite(GetUserName(), goodsIds);
}
/// <summary>
/// 取消收藏
@@ -516,18 +447,7 @@ namespace Work.Services
public static async Task<int> RemoveFavorites(List<long> goodsIds)
{
var html = await GetHtml.PostJsonAsync(ServerUrl + $"/api/CloudGoods/RemoveFavorites", new
{
UserName = GetUserName(),
GoodsIds = goodsIds,
});
var ret = JsonConvert.DeserializeObject<Result<int>>(html);
if (ret.Code != 200)
{
throw new Exception(ret.Msg);
}
return ret.Data;
return await StoreApiClient.Instance.CloudGoods.RemoveFavorites(GetUserName(), goodsIds);
}
#endregion
@@ -662,6 +582,8 @@ namespace Work.Services
/// 平台类型
/// </summary>
public PlatformType Platform { get; set; }
/// <summary>安全状态:0 全部(默认),1 安全,2 违规,3 未检测。</summary>
public int SafeStatus { get; set; }
/// <summary>
/// 页码(默认1)
@@ -715,6 +637,7 @@ namespace Work.Services
}
public class CloudGoods : BindableBase
{
public bool IsSelected
{
get => GetValue<bool>();
@@ -805,5 +728,18 @@ namespace Work.Services
/// 索引同步状态:0未同步 1已同步
/// </summary>
public byte IndexStatus { get; set; }
/// <summary>
/// 安全检测
/// </summary>
public bool? IsSafe { get; set; }
[JsonIgnore]
public string? DetectionResult
{
get => GetValue<string>();
set => SetValue(value);
}
}
}
+143
View File
@@ -0,0 +1,143 @@
using AllBase.Model;
using AllBase.Model.Result;
using AllBase.Model.Result.PDDResult;
using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Linq;
using TemuKJD.BLL.ImportConverts;
using AllBase;
using System.Collections.Generic;
using TemuKJD.BLL;
namespace Work.Services;
public static class ComplianceProductReader
{
public static Product Read(ComplianceGoods item)
{
KJDDBProduct db;
if (item.type == ComplianceGoods.Cloud)
db = new KJDDBProduct { product_json = CloudGoodsService.GetGoodsDetail(long.Parse(item.id)) };
else if (item.type == ComplianceGoods.Library)
{
db = GetProductDetail(item.id, out var message);
if (!string.IsNullOrEmpty(message)) throw new InvalidDataException(message);
}
else throw new InvalidDataException("未知商品来源:" + item.type);
if (string.IsNullOrWhiteSpace(db?.product_json)) throw new InvalidDataException("未取得商品详情。");
var raw = db.product_json;
var root = JObject.Parse(raw);
PDDProductInfo info;
string error = null;
var converter = new PDDProdFormConverter();
if (root.SelectToken("detail.galleries") is JArray)
info = root.ToObject<PDDProductInfo>();
else if (db.product_get_type_text == "厂商直采") info = converter.JstPddProdToPddConvert(out error, db);
else if (db.product_get_type_text == "微信店采") info = converter.WXProdToPddConvert(out error, db);
else if (db.product_get_type_text == "微信小店") info = converter.WXClientToPddConvert(out error, db);
else if (db.product_get_type_text == "1688厂家") info = converter._1688ClientToPddConvert(out error, db);
else if (db.product_get_type_text == "1688外部数据") info = converter._1688OutToPddConvert(out error, db);
else
{
var front = ConverterToPddFactory.SetContentConvert(raw);
if (front != null)
{
var originalId = front.GoodsId > 0 ? front.GoodsId.ToString() : db.spu_id;
return new Product
{
ProductId = item.type == ComplianceGoods.Cloud ? item.id : originalId,
Platform = item.platform.HasValue ? (PlatformType)item.platform.Value : front.Platform,
Title = front.Title ?? item.name, Description = front.Description,
MainImages = front.MainImages, DetailImages = front.DetailImages,
Skus = front.Skus?.Select(x => new ProductSku { SkuId = x.SkuId, ImageUrl = x.SpecImage }).ToList()
};
}
string converted;
if (raw.Contains("\"spec_keys\"") && raw.Contains("\"spec_values\""))
converted = converter.PddFrontToPddBackConvert(raw, isSaveDb: false);
else if (raw.Contains("\"goods_id\"") && raw.Contains("\"gallery\""))
converted = converter.PddFrontToPddBackConvert2(raw, isSaveDb: false);
else if (raw.Contains("\"topGallery\"") && raw.Contains("\"detailGallery\""))
converted = converter.PddFrontToPddBackConvert3(raw, isSaveDb: false);
else if (raw.Contains("\"商品编号\"") && raw.Contains("\"商品链接\""))
converted = converter.PddFrontToPddBackConvertV4(raw, isSaveDb: false);
else throw new InvalidDataException("不支持的商品详情格式。");
if (converted == null || !converted.StartsWith("success", StringComparison.Ordinal))
throw new InvalidDataException(converted ?? "商品详情转换失败。");
info = JObject.Parse(converted.Substring(7)).ToObject<PDDProductInfo>();
}
if (!string.IsNullOrEmpty(error) || info?.detail == null)
throw new InvalidDataException(error ?? "商品详情转换失败。");
var detail = info.detail;
var platform = db.product_get_type_text switch
{
"微信店采" or "微信小店" or "微信外部数据" or "微信" => PlatformType.WX,
"厂商直采" or "1688厂家" or "1688外部数据" => PlatformType.None,
_ => PlatformType.PDD
};
var productId = db.product_get_type_text == "厂商直采"
? (string)root.SelectToken("pddData.itemSpuId") ?? db.spu_id
: detail.goods_id > 0 ? detail.goods_id.ToString() : db.spu_id;
return new Product
{
Platform = item.platform.HasValue ? (PlatformType)item.platform.Value : platform,
ProductId = item.type == ComplianceGoods.Cloud ? item.id : productId,
Title = detail.goods_name ?? item.name, Description = detail.goods_desc,
MainImages = detail.galleries?.Where(x => x.type == 1).Select(x => x.url).ToList(),
DetailImages = detail.galleries?.Where(x => x.type == 2).Select(x => x.url).ToList(),
Skus = detail.sku?.Select(x => new ProductSku { SkuId = x.sku_id.ToString(), ImageUrl = x.thumb_url }).ToList()
};
}
public static KJDDBProduct GetProductDetail(string prodDbId, out string errMsg, bool noViolationProduct = false, bool noBanWx = false)
{
errMsg = "";
if (string.IsNullOrEmpty(prodDbId))
{
errMsg = "产品编号为空";
return new KJDDBProduct();
}
List<KJDDBProduct> list = new List<KJDDBProduct>();
var url = BaseClass.BuildObjString("product/get_pdd_product_detail_list");
var data = UserLogin.GetSignaturex() + "&search_db_ids=" + prodDbId;
if (noViolationProduct)
data += "&wx_safe_status=安全商品,未校验";
if (noBanWx)
data += "&ban_wx=0";
if (BaseClass.SaLevel > 0 || BaseClass.UserAuthority.Contains("爆款数据") || BaseClass.UserAuthority.Contains("学员数据") || BaseClass.ParentAuthority.Contains("学员数据"))
data += "&special_prod_type=普通商品,爆款数据";
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"))
{
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;
}
}
}
+310
View File
@@ -0,0 +1,310 @@
using AllBase.Helper;
using AllBase;
using AllBase.Model;
using Work.Store.Api;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Net.Http;
using System.Linq;
using System.Text;
namespace Work.Services;
public sealed class ComplianceGoods
{
public const string Cloud = "云端收藏";
public const string Library = "我的商品库";
public string id { get; set; }
public string name { get; set; }
public string image { get; set; }
public string type { get; set; }
public byte? platform { get; set; }
}
public sealed class ComplianceResult
{
public string Text { get; internal set; }
public string[] Hits { get; internal set; } = Array.Empty<string>();
public int HitImageNumber { get; internal set; }
public string Error { get; internal set; }
public string Status => Error != null ? "失败,可重试" : Hits.Length == 0 ? "安全" : "有风险";
public string Summary => Error != null ? "失败:" + Error :
Hits.Length == 0 ? Status : $"有风险:{HitSource}命中关键词:{string.Join(",", Hits)}";
private string HitSource => HitImageNumber == 0 ? "标题" : $"第 {HitImageNumber} 张图片";
}
public sealed class ComplianceBatchResult
{
public int Safe { get; internal set; }
public int Risk { get; internal set; }
public int Failed { get; internal set; }
public int Unfinished { get; internal set; }
}
public static class GoodsComplianceService
{
private static readonly HttpClient ImageClient = new HttpClient(new HttpClientHandler { UseCookies = false })
{
Timeout = TimeSpan.FromSeconds(30),
MaxResponseContentBufferSize = 32 * 1024 * 1024
};
private static readonly SemaphoreSlim BatchGate = new SemaphoreSlim(1, 1);
public static async Task<ComplianceBatchResult> DetectSelectedAsync(IReadOnlyList<ComplianceGoods> items,
Func<ComplianceGoods, Product> readProduct, Action<string, string> update, CancellationToken cancellationToken = default)
{
if (items == null || items.Count == 0) throw new ArgumentException("请选择商品。", nameof(items));
if (readProduct == null) throw new ArgumentNullException(nameof(readProduct));
if (update == null) throw new ArgumentNullException(nameof(update));
if (!BatchGate.Wait(0)) throw new InvalidOperationException("已有商品正在检测。");
try
{
var options = GlobalConfig.GlobalSettings.GoodsCompliance;
var words = ValidateOptions(options);
var path = QueuePath();
var pending = ReadPending(path);
if (items.Any(InvalidItem)) throw new ArgumentException("缺少商品 ID 或来源。", nameof(items));
var selected = items.GroupBy(x => Tuple.Create(x.type, x.id)).Select(g => g.First()).ToList();
var existing = new HashSet<Tuple<string, string>>(pending.Select(x => Tuple.Create(x.type, x.id)));
pending.AddRange(selected.Where(x => existing.Add(Tuple.Create(x.type, x.id))));
SavePending(path, pending);
var batch = new ComplianceBatchResult { Unfinished = selected.Count };
foreach (ComplianceGoods item in selected)
{
if (cancellationToken.IsCancellationRequested) break;
update(item.id, "读取详情中");
ComplianceResult result;
try
{
//item.type
var product = await Task.Run(() => readProduct(item), cancellationToken);
result = await DetectProductAsync(product, options, words,
number => update(item.id, $"正在检测第 {number} 张图片"), cancellationToken);
if (result.Error == null)
{
try
{
if (item.type == ComplianceGoods.Library)
{
var url = BaseClass.BuildPDDObjString("product/SaveProductSafety");
var data = UserLogin.GetSignature();
data += "&user_name=" + BaseClass.UserName;
data += "&id=" + item.id;
string html = await GetHtml.PostJsonAsync(url, data);
}
else
{
await StoreApiClient.Instance.CloudGoods.SaveProductSafety(new SaveProductSafetyRequest
{
UserName = GetUserName(),
ProductId = product.ProductId,
IsSafe = result.Hits.Length == 0
});
}
}
catch (Exception ex)
{
result.Error = $"检测结果为{result.Status},上报失败:{ex.Message}";
}
}
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
update(item.id, "已停止");
break;
}
catch (Exception ex) { result = new ComplianceResult { Error = ex.Message }; }
if (result.Error == null)
{
var remaining = pending.Where(x => x.type != item.type || x.id != item.id).ToList();
try { SavePending(path, remaining); pending = remaining; }
catch (Exception ex) { result.Error = ex.Message; }
}
if (result.Error != null) batch.Failed++;
else if (result.Hits.Length > 0) batch.Risk++;
else batch.Safe++;
batch.Unfinished--;
update(item.id, result.Summary);
}
return batch;
}
finally { BatchGate.Release(); }
}
private static string QueuePath()
{
var username = BaseClass.UserName;
if (string.IsNullOrWhiteSpace(username)) throw new InvalidOperationException("请先登录。");
var user = Convert.ToBase64String(Encoding.UTF8.GetBytes(username)).Replace('/', '_').Replace('+', '-');
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "data", "config", "goods_compliance_" + user + ".json");
}
private static bool InvalidItem(ComplianceGoods item) =>
item == null || string.IsNullOrWhiteSpace(item.id) || string.IsNullOrWhiteSpace(item.type);
private static List<ComplianceGoods> ReadPending(string path)
{
if (!File.Exists(path)) return new List<ComplianceGoods>();
var items = JsonConvert.DeserializeObject<List<ComplianceGoods>>(File.ReadAllText(path));
if (items == null || items.Any(InvalidItem))
throw new InvalidDataException("待检测配置无效,请检查 " + path);
return items;
}
private static void SavePending(string path, List<ComplianceGoods> items)
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
var temp = path + ".tmp";
File.WriteAllText(temp, JsonConvert.SerializeObject(items));
if (File.Exists(path)) File.Replace(temp, path, null);
else File.Move(temp, path);
}
public static async Task DetectAsync(IReadOnlyList<Product> products, ComplianceOptions options,
Action<Product, ComplianceResult> completed, Action<Product> started = null)
{
if (products == null) throw new ArgumentNullException(nameof(products));
if (completed == null) throw new ArgumentNullException(nameof(completed));
var words = ValidateOptions(options);
foreach (var product in products)
{
started?.Invoke(product);
var result = await DetectProductAsync(product, options, words);
if (result.Error == null)
{
try
{
await StoreApiClient.Instance.CloudGoods.SaveProductSafety(new SaveProductSafetyRequest
{
UserName = GetUserName(),
ProductId = product.ProductId,
IsSafe = result.Hits.Length == 0
});
}
catch (Exception ex)
{
result.Error = $"检测结果为{result.Status},上报失败:{ex.Message}";
}
}
completed(product, result);
}
}
private static string[] ValidateOptions(ComplianceOptions options)
{
var words = Keywords(options?.Keywords);
if (words.Length == 0) throw new ArgumentException("请先在系统设置的「商品 AI 检测」中保存 AI 检测关键词。");
if (options.MainCount <= 0 || options.DetailCount < 0)
throw new ArgumentException("请检查检测关键词和图片数量。");
return words;
}
private static async Task<ComplianceResult> DetectProductAsync(Product product, ComplianceOptions options,
string[] words, Action<int> imageStarted = null, CancellationToken cancellationToken = default)
{
var result = new ComplianceResult();
try
{
cancellationToken.ThrowIfCancellationRequested();
if (string.IsNullOrWhiteSpace(product?.ProductId)) throw new InvalidDataException("缺少商品 ID。");
result.Hits = Matches(product.Title ?? string.Empty, words);
if (result.Hits.Length > 0)
{
result.Text = product.Title;
return result;
}
var urls = SelectImages(product.MainImages, options.MainCount)
.Concat(SelectImages(product.DetailImages, options.DetailCount));
if (options.IncludeSku) urls = urls.Concat(SelectImages(product.Skus?.Select(s => s?.ImageUrl), null));
var texts = new List<string>();
int imageNumber = 0;
foreach (var url in urls.Distinct(StringComparer.Ordinal))
{
cancellationToken.ThrowIfCancellationRequested();
imageNumber++;
imageStarted?.Invoke(imageNumber);
try
{
var jpeg = await DownloadInspectionImageAsync(url);
cancellationToken.ThrowIfCancellationRequested();
var lines = await StoreApiClient.Instance.CloudGoods.RecognizeAsync(BaseClass.GetMd5(url), jpeg);
BaseClass.ImageAnalysisQuota -= 1;
var imageText = string.Join(Environment.NewLine, lines);
texts.AddRange(lines);
result.Hits = Matches(imageText, words);
if (result.Hits.Length > 0)
{
result.HitImageNumber = imageNumber;
break;
}
}
catch (Exception ex) when (!cancellationToken.IsCancellationRequested)
{
throw new InvalidDataException($"第 {imageNumber} 张图片检测失败:{ex.Message}", ex);
}
}
cancellationToken.ThrowIfCancellationRequested();
if (imageNumber == 0) throw new InvalidDataException("所选检测范围内没有图片。");
result.Text = string.Join(Environment.NewLine, texts);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) { throw; }
catch (Exception ex) { result.Error = ex.Message; }
return result;
}
private static IEnumerable<string> SelectImages(IEnumerable<string> urls, int? count) =>
(urls ?? Enumerable.Empty<string>()).Where(url => !string.IsNullOrWhiteSpace(url)).Select(url => url.Trim())
.Distinct(StringComparer.Ordinal).Take(count ?? int.MaxValue);
private static async Task<byte[]> DownloadInspectionImageAsync(string url)
{
if (!Uri.TryCreate(url, UriKind.Absolute, out var uri) ||
(uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps))
throw new InvalidDataException("图片链接必须为 HTTP 或 HTTPS 地址。");
var bytes = await ImageClient.GetByteArrayAsync(uri).ConfigureAwait(false);
const int maxSide = 600;
using (var input = new MemoryStream(bytes))
using (var source = Image.FromStream(input))
{
var scale = Math.Min(1d, (double)maxSide / Math.Max(source.Width, source.Height));
int width = Math.Max(1, (int)Math.Round(source.Width * scale));
int height = Math.Max(1, (int)Math.Round(source.Height * scale));
using var canvas = new Bitmap(width, height, PixelFormat.Format24bppRgb);
using var output = new MemoryStream();
using (var g = Graphics.FromImage(canvas))
{
g.Clear(Color.White);
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.DrawImage(source, new Rectangle(0, 0, width, height),
0, 0, source.Width, source.Height, GraphicsUnit.Pixel);
}
canvas.Save(output, ImageFormat.Jpeg);
return output.ToArray();
}
}
public static string[] Keywords(string value) =>
System.Text.RegularExpressions.Regex.Split(value ?? "", @"[,,;;|\s]+")
.Where(x => x.Length > 0).Distinct(StringComparer.OrdinalIgnoreCase).ToArray();
public static string[] Matches(string recognized, string[] keywords) =>
keywords.Where(x => recognized.IndexOf(x, StringComparison.OrdinalIgnoreCase) >= 0).ToArray();
public static string GetUserName()
{
return string.IsNullOrEmpty(BaseClass.ParentUserName) ? BaseClass.UserName : BaseClass.ParentUserName;
}
}
+7 -59
View File
@@ -1,14 +1,11 @@
using AllBase;
using AllBase.Helper;
using AllBase.Model.Result;
using AllBase.Model.Result.PDDResult;
using AllBase.Model.Result;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Work.Store.Api;
namespace Work.Services;
@@ -17,17 +14,6 @@ namespace Work.Services;
/// </summary>
public class ImageCacheService
{
private static string ServerUrl = "http://103.90.155.78:9001";
static ImageCacheService()
{
if (EnvironmentHelper.IsDevelopment)
{
ServerUrl = "http://localhost:14312";
}
}
/// <summary>
/// 获取图片缓存
/// </summary>
@@ -37,10 +23,6 @@ public class ImageCacheService
Dictionary<string, ImageCache> wxImgMapDic = new Dictionary<string, ImageCache>(StringComparer.OrdinalIgnoreCase);
try
{
//if (EnvironmentHelper.IsProduction)
//{
// return wxImgMapDic;
//}
List<string> imageUrls = new List<string>();
imageUrls.AddRange(product.detail.galleries.Where(g => g.type == 1).Take(9).Select(a => a.url));
var temp_detailGalleries = product.detail.galleries.Where(g => g.type == 2).ToList();
@@ -58,18 +40,13 @@ public class ImageCacheService
List<string> imageUrlMd5s = imageUrls.Select(a => BaseClass.GetMd5(a)).ToList();
var url = ServerUrl + "/api/ImageCache/GetImageCache";//获取缓存
var html = GetHtml.PostJson(url, new { md5s = imageUrlMd5s });
var ret = JsonConvert.DeserializeObject<Result<List<ImageCache>>>(html);
if (ret.Code == 200)
{
foreach (var item in ret.Data)
var caches = StoreApiClient.Instance.ImageCache.GetImageCaches(imageUrlMd5s);
foreach (var item in caches)
{
item.IsCache = true;
wxImgMapDic[item.Md5] = item;
}
}
}
catch(Exception ex)
{
@@ -86,38 +63,9 @@ public class ImageCacheService
{
try
{
//if (EnvironmentHelper.IsProduction)
//{
// return;
//}
var data = "";
data = JsonHelper.SerializeObject(images.Where(a => a.IsCache == false).Select(a =>
new
{
md5 = a.Md5,
Platform = platform,
PlatformUrl = a.PlatformUrl
}
));
var url = ServerUrl + "/api/ImageCache/AddOrUpdate";
var html = GetHtml.PostJson(url, data);
var ret = JsonConvert.DeserializeObject<Result<JToken>>(html);
List<string> failed = new List<string>();
if (ret.Code == 500)
{
if (ret.Data is JArray jArray)
{
failed = jArray.ToObject<List<string>>() ?? new List<string>();
}
else if (ret.Data is JValue jValue && jValue.Value is string str)
{
failed.Add(str);
}
}
foreach (ImageCache item in images)
var pending = images.Where(image => !image.IsCache).ToList();
var failed = StoreApiClient.Instance.ImageCache.SaveImageCaches((int)platform, pending);
foreach (var item in pending)
{
item.IsCache = !failed.Contains(item.Md5, StringComparer.OrdinalIgnoreCase);
}
+19
View File
@@ -0,0 +1,19 @@
using CsharpHttpHelper;
using Newtonsoft.Json.Linq;
namespace Work.Store.Api;
/// <summary>保留业务错误数据,供批量接口识别部分失败项。</summary>
public sealed class ApiException : HttpException
{
public int? Code { get; }
public JToken ResponseData { get; }
public string TraceId { get; }
public ApiException(string message, int? code, JToken responseData, string traceId = null) : base(message)
{
Code = code;
ResponseData = responseData;
TraceId = traceId;
}
}
+203
View File
@@ -0,0 +1,203 @@
using CsharpHttpHelper;
using AllBase.Model.Result;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace Work.Store.Api;
/// <summary>管理 API 的统一 HTTP 出口,负责 JSON、Bearer 认证和错误处理。</summary>
public sealed class ApiTransport
{
private readonly string _baseUrl;
private string _token;
private LoginRequest _credentials;
internal SemaphoreSlim SessionGate { get; } = new SemaphoreSlim(1, 1);
// 调用方持有 SessionGate。
internal void SetSession(string token, LoginRequest credentials)
{
_token = token;
_credentials = credentials;
}
public ApiTransport(string baseUrl)
{
if (!Uri.TryCreate(baseUrl, UriKind.Absolute, out var uri) ||
(uri.Scheme != "http" && uri.Scheme != "https") ||
uri.UserInfo.Length != 0 || uri.Query.Length != 0 || uri.Fragment.Length != 0)
throw new ArgumentException("必须提供无凭据、查询参数和片段的 HTTP(S) 根地址。", nameof(baseUrl));
_baseUrl = uri.AbsoluteUri.TrimEnd('/') + "/";
}
/// <summary>仅存于内存;手动赋值会清除自动登录凭据,设为 null 退出本地会话。</summary>
public string Token
{
get
{
SessionGate.Wait();
try { return _token; }
finally { SessionGate.Release(); }
}
set
{
if (value != null && (string.IsNullOrWhiteSpace(value) || value.IndexOfAny(new[] { '\r', '\n' }) >= 0))
throw new ArgumentException("Token 不能为空白或包含换行。", nameof(value));
SessionGate.Wait();
try { SetSession(value, null); }
finally { SessionGate.Release(); }
}
}
public T Send<T>(string route, MethodType method, object body = null,
IDictionary<string, string> query = null, bool authenticated = true,
int timeoutMilliseconds = 30000)
{
var item = CreateRequest(route, method, body, query, timeoutMilliseconds);
string token = null;
if (authenticated)
{
//SessionGate.Wait();
//try { token = _token ?? throw new HttpException("请先登录。") { IsOnline = false }; }
//finally { SessionGate.Release(); }
}
for (int attempt = 0; ; attempt++)
{
if (token != null) item.Header["Authorization"] = "Bearer " + token;
var response = HttpHelper.Request(item);
try { return ReadResult<T>(response); }
catch (HttpException ex) when (authenticated && !ex.IsOnline)
{
SessionGate.Wait();
try
{
if (_token == token)
{
_token = null;
if (attempt == 0 && _credentials != null)
_token = AuthApi.LoginCore(this, _credentials).Token;
}
if (attempt != 0 || _token == null) throw;
token = _token;
}
finally { SessionGate.Release(); }
}
}
}
public async Task<T> SendAsync<T>(string route, MethodType method, object body = null,
IDictionary<string, string> query = null, bool authenticated = true,
int timeoutMilliseconds = 30000)
{
var item = CreateRequest(route, method, body, query, timeoutMilliseconds);
string token = null;
if (authenticated)
{
//await SessionGate.WaitAsync().ConfigureAwait(false);
//try { token = _token ?? throw new HttpException("请先登录。") { IsOnline = false }; }
//finally { SessionGate.Release(); }
}
for (int attempt = 0; ; attempt++)
{
if (token != null) item.Header["Authorization"] = "Bearer " + token;
var response = await HttpHelper.RequestAsync(item).ConfigureAwait(false);
try { return ReadResult<T>(response); }
catch (HttpException ex) when (authenticated && !ex.IsOnline)
{
await SessionGate.WaitAsync().ConfigureAwait(false);
try
{
if (_token == token)
{
_token = null;
if (attempt == 0 && _credentials != null)
_token = (await AuthApi.LoginCoreAsync(this, _credentials).ConfigureAwait(false)).Token;
}
if (attempt != 0 || _token == null) throw;
token = _token;
}
finally { SessionGate.Release(); }
}
}
}
private HttpItem CreateRequest(string route, MethodType method, object body,
IDictionary<string, string> query, int timeoutMilliseconds)
{
if (string.IsNullOrWhiteSpace(route) ||
!Regex.IsMatch(route, @"\A[A-Za-z0-9_-]+(/[A-Za-z0-9_-]+)*\z"))
throw new ArgumentException("接口必须使用相对路由,例如 Auth/Login。", nameof(route));
if (body != null) Validator.ValidateObject(body, new ValidationContext(body), true);
if (timeoutMilliseconds <= 0) throw new ArgumentOutOfRangeException(nameof(timeoutMilliseconds));
var url = new StringBuilder(_baseUrl).Append(route);
if (query != null)
{
bool first = true;
foreach (var pair in query)
{
if (pair.Value == null) continue;
url.Append(first ? '?' : '&').Append(Uri.EscapeDataString(pair.Key))
.Append('=').Append(Uri.EscapeDataString(pair.Value));
first = false;
}
}
return new HttpItem
{
URL = url.ToString(),
Method = method,
ContentType = "application/json; charset=utf-8",
Accept = "application/json",
PostDataType = PostDataType.Byte,
PostdataByte = body == null ? null : Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(body)),
Encoding = Encoding.UTF8,
Timeout = timeoutMilliseconds,
ReadWriteTimeout = timeoutMilliseconds,
Allowautoredirect = false
};
}
private static T ReadResult<T>(HttpResult response)
{
int status = (int)response.StatusCode;
if (status == 0) throw new HttpException("无法连接服务器或请求超时。");
Result<JToken> result = null;
JsonException parseError = null;
try { result = JsonConvert.DeserializeObject<Result<JToken>>(response.Html ?? ""); }
catch (JsonException ex) { parseError = ex; }
if (status == 401 || (result?.Success == false && result.Code == 401))
throw new HttpException(result?.Msg ?? "登录已失效,请重新登录。") { IsOnline = false };
// 统一错误响应即使使用 HTTP 4xx/5xx,也保留业务码、数据和追踪 ID。
if (result?.Success == false)
throw new ApiException("请求失败:" + (result.Msg ?? $"业务码 {result.Code}。"),
result.Code, result.Data, result.TraceId);
if (status < 200 || status >= 300)
throw new HttpException($"请求失败(HTTP {status}):{result?.Msg}");
if (result?.Success == null)
throw new HttpException("服务器响应不是有效的 Result 格式。", parseError);
if (result.Data == null || result.Data.Type == JTokenType.Null) return default;
try { return result.Data.ToObject<T>(); }
catch (JsonException ex) { throw new HttpException("服务器响应 data 格式无效。", ex); }
}
public T GetRequired<T>(string route, MethodType method, object body = null,
IDictionary<string, string> query = null, bool authenticated = true,
int timeoutMilliseconds = 30000) where T : class
=> Send<T>(route, method, body, query, authenticated, timeoutMilliseconds)
?? throw new HttpException("服务器响应缺少 data。");
public async Task<T> GetRequiredAsync<T>(string route, MethodType method, object body = null,
IDictionary<string, string> query = null, bool authenticated = true,
int timeoutMilliseconds = 30000) where T : class
=> await SendAsync<T>(route, method, body, query, authenticated, timeoutMilliseconds).ConfigureAwait(false)
?? throw new HttpException("服务器响应缺少 data。");
}
+89
View File
@@ -0,0 +1,89 @@
using CsharpHttpHelper;
using System;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
namespace Work.Store.Api;
public sealed class LoginRequest
{
[Required]
public string UserName { get; set; }
/// <summary>UTF-8 密码的 32 位大写 MD5,由调用方计算。</summary>
[Required]
public string Password { get; set; }
[StringLength(100)]
public string DeviceId { get; set; }
[StringLength(100)]
public string DeviceName { get; set; }
}
public sealed class LoginResult
{
public string TokenType { get; set; } = "Bearer";
public string Token { get; set; }
public uint ExpiresInMinutes { get; set; }
}
public sealed class AuthApi
{
private readonly ApiTransport _transport;
private readonly string _deviceId;
public AuthApi(string baseUrl) : this(new ApiTransport(baseUrl)) { }
public AuthApi(ApiTransport transport, string deviceId = null)
{
_transport = transport ?? throw new ArgumentNullException(nameof(transport));
_deviceId = deviceId;
}
/// <summary>同步登录,凭据快照仅存内存,供 401 时自动重登;界面调用需放在后台线程。</summary>
public LoginResult Login(LoginRequest request)
{
if (request == null) throw new ArgumentNullException(nameof(request));
var credentials = new LoginRequest
{
UserName = request.UserName,
Password = request.Password,
DeviceId = _deviceId ?? request.DeviceId,
DeviceName = request.DeviceName
};
_transport.SessionGate.Wait();
try
{
var result = LoginCore(_transport, credentials);
_transport.SetSession(result.Token, credentials);
return result;
}
finally { _transport.SessionGate.Release(); }
}
internal static LoginResult LoginCore(ApiTransport transport, LoginRequest request)
{
var result = transport.GetRequired<LoginResult>("Auth/Login", MethodType.Post, request, authenticated: false);
return ValidateToken(result);
}
internal static async Task<LoginResult> LoginCoreAsync(ApiTransport transport, LoginRequest request)
{
var result = await transport.GetRequiredAsync<LoginResult>("Auth/Login", MethodType.Post, request, authenticated: false).ConfigureAwait(false);
return ValidateToken(result);
}
private static LoginResult ValidateToken(LoginResult result)
{
if (result == null || string.IsNullOrWhiteSpace(result.Token) ||
result.Token.IndexOfAny(new[] { '\r', '\n' }) >= 0 ||
!string.Equals(result.TokenType, "Bearer", StringComparison.OrdinalIgnoreCase))
throw new HttpException("登录响应缺少有效的 Bearer Token。");
return result;
}
}
+86
View File
@@ -0,0 +1,86 @@
using AllBase;
using AllBase.Helper;
using AllBase.Model.Result;
using CsharpHttpHelper;
using NaiBa.Util.Helper;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Work.Services;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.StartPanel;
namespace Work.Store.Api;
/// <summary>云商品接口,沿用服务端不带版本号的路由。</summary>
public sealed class CloudGoodsApi
{
private readonly ApiTransport _transport;
public CloudGoodsApi(ApiTransport transport)
=> _transport = transport ?? throw new ArgumentNullException(nameof(transport));
public Task<PageData<CloudGoods>> GetGoods(GoodsSearchRequest request)
=> _transport.GetRequiredAsync<PageData<CloudGoods>>("CloudGoods/SearchGoods", MethodType.Post, request);
public string GetGoodsDetail(long goodsId)
=> _transport.GetRequired<string>("CloudGoods/GetGoodsRawData", MethodType.Post,
query: new Dictionary<string, string> { ["goodsId"] = goodsId.ToString(CultureInfo.InvariantCulture) });
public Task<List<ReportGoodsViolationResult>> ReportViolations(List<ReportGoodsViolationItem> items)
=> _transport.GetRequiredAsync<List<ReportGoodsViolationResult>>("CloudGoods/ReportViolations", MethodType.Post, items,
timeoutMilliseconds: 5000);
public List<GoodsViolationStatus> GetViolationStatus(List<long> goodsIds)
=> _transport.GetRequired<List<GoodsViolationStatus>>("CloudGoods/GetViolationStatus", MethodType.Post, goodsIds,
timeoutMilliseconds: 5000);
public Task RecordViolationLogs(IReadOnlyList<RecordViolationLogRequest> requests)
=> _transport.SendAsync<object>("CloudGoods/RecordViolationLog", MethodType.Post, requests,
timeoutMilliseconds: 5000);
public Task<List<CloudGoodsService.ViolationReason>> GetViolationReasons()
=> _transport.GetRequiredAsync<List<CloudGoodsService.ViolationReason>>("CloudGoods/GetViolationReasons", MethodType.Get);
public Task<List<GoodsViolationLogEntity>> GetViolationLogs(GetViolationLogsRequest request)
=> _transport.GetRequiredAsync<List<GoodsViolationLogEntity>>("CloudGoods/GetViolationLogs", MethodType.Post, request,
timeoutMilliseconds: 5000);
public Task<PageData<CloudGoods>> SearchFavorites(UserFavoritesGoodsSearchRequest request)
=> _transport.GetRequiredAsync<PageData<CloudGoods>>("CloudGoods/SearchFavorites", MethodType.Post, request);
public Task<int> Favorite(string userName, List<long> goodsIds)
=> _transport.SendAsync<int>("CloudGoods/AddFavorite", MethodType.Post,
new { UserName = userName, GoodsIds = goodsIds });
public Task<int> RemoveFavorites(string userName, List<long> goodsIds)
=> _transport.SendAsync<int>("CloudGoods/RemoveFavorites", MethodType.Post,
new { UserName = userName, GoodsIds = goodsIds });
/// <summary>识别上传图片中的文字和品牌 Logo。</summary>
public async Task<List<string>> RecognizeAsync(string urlMd5, byte[] jpeg)
{
int sleep = 0;
if (EnvironmentHelper.IsProduction)
{
sleep = RandomHelper.GetRandom(600, 1200);
}
var minimumDuration = Task.Delay(TimeSpan.FromMilliseconds(sleep));
var request = new { UserName = BaseClass.UserName, Md5 = urlMd5, Image = Convert.ToBase64String(jpeg) };
var recognitionTask = _transport.GetRequiredAsync<List<string>>("CloudGoods/InspectImage", MethodType.Post, request);
await Task.WhenAll(minimumDuration, recognitionTask).ConfigureAwait(false);
return await recognitionTask.ConfigureAwait(false);
}
public async Task SaveProductSafety(SaveProductSafetyRequest request)
{
var ret = await _transport.SendAsync<int>("CloudGoods/SaveProductSafety", MethodType.Post, new
{
UserName = request.UserName,
ProductId = request.ProductId,
IsSafe = request.IsSafe
});
}
}
+70
View File
@@ -0,0 +1,70 @@
using AllBase;
using AllBase.Helper;
using CsharpHttpHelper;
using NaiBa.Util.Helper;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Threading.Tasks;
namespace Work.Store.Api;
public sealed class GoodsComplianceApi
{
private readonly ApiTransport transport;
internal GoodsComplianceApi(ApiTransport transport) => this.transport = transport;
///// <summary>上报平台商品的安全检测记录。</summary>
//public Task SaveProductSafety(SaveProductSafetyRequest request)
//{
// request.UserName = BaseClass.UserName;
// return transport.SendAsync<object>("ProductInspection/SaveProductSafety", MethodType.Post,
// request ?? throw new ArgumentNullException(nameof(request)));
//}
/// <summary>按平台和商品 ID 批量查询安全记录。</summary>
public Task<List<ProductSafetyDto>> QueryProductSafety(QueryProductSafetyRequest request)
{
request.UserName = BaseClass.UserName;
return transport.GetRequiredAsync<List<ProductSafetyDto>>("ProductInspection/QueryProductSafety", MethodType.Post,
request ?? throw new ArgumentNullException(nameof(request)));
}
/// <summary>识别上传图片中的文字和品牌 Logo。</summary>
public async Task<List<string>> RecognizeAsync(string urlMd5, byte[] jpeg)
{
int sleep = 0;
if (EnvironmentHelper.IsProduction)
{
sleep = RandomHelper.GetRandom(600, 1200);
}
var minimumDuration = Task.Delay(TimeSpan.FromMilliseconds(sleep));
var request = new { UserName = BaseClass.UserName, Md5 = urlMd5, Image = Convert.ToBase64String(jpeg) };
var recognitionTask = transport.GetRequiredAsync<List<string>>("ProductInspection/InspectImage", MethodType.Post, request);
await Task.WhenAll(minimumDuration, recognitionTask).ConfigureAwait(false);
return await recognitionTask.ConfigureAwait(false);
}
}
public sealed class SaveProductSafetyRequest
{
[Required] public string UserName { get; set; } = "";
[Required] public string ProductId { get; set; } = "";
[Required] public bool? IsSafe { get; set; }
}
public sealed class QueryProductSafetyRequest
{
[Required] public string UserName { get; set; } = "";
[Required] public string PlatformId { get; set; } = "";
[Required] public string[] ProductIds { get; set; } = [];
}
public sealed record ProductSafetyDto(string ProductId, bool IsSafe)
{
[Required] public string UserName { get; set; } = "";
public string ProductId { get; } = ProductId;
public bool IsSafe { get; } = IsSafe;
}
+41
View File
@@ -0,0 +1,41 @@
using CsharpHttpHelper;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using Work.Services;
namespace Work.Store.Api;
/// <summary>图片缓存接口,返回批量保存失败的 MD5 列表。</summary>
public sealed class ImageCacheApi
{
private readonly ApiTransport _transport;
public ImageCacheApi(ApiTransport transport)
=> _transport = transport ?? throw new ArgumentNullException(nameof(transport));
public List<ImageCache> GetImageCaches(List<string> md5s)
=> _transport.GetRequired<List<ImageCache>>("ImageCache/GetImageCache", MethodType.Post, new { md5s });
public List<string> SaveImageCaches(int platform, IReadOnlyList<ImageCache> images)
{
if (images == null) throw new ArgumentNullException(nameof(images));
if (images.Count == 0) return new List<string>();
try
{
_transport.Send<object>("ImageCache/AddOrUpdate", MethodType.Post,
images.Select(image => new { md5 = image.Md5, Platform = platform, PlatformUrl = image.PlatformUrl }).ToArray());
return new List<string>();
}
catch (ApiException ex) when (ex.Code == 500)
{
// 兼容旧服务的部分失败响应;没有明确失败项时保持整体失败。
if (ex.ResponseData is JArray array && array.Count > 0 && array.All(item => item.Type == JTokenType.String))
return array.ToObject<List<string>>();
if (ex.ResponseData?.Type == JTokenType.String && !string.IsNullOrWhiteSpace((string)ex.ResponseData))
return new List<string> { (string)ex.ResponseData };
throw;
}
}
}
+52
View File
@@ -0,0 +1,52 @@
using Microsoft.Win32;
using AllBase.Helper;
using System;
using System.Security.Cryptography;
using System.Text;
namespace Work.Store.Api;
/// <summary>全局共用一个用户会话与请求出口,窗体通过 Instance 访问。</summary>
public sealed class StoreApiClient
{
private static readonly string BaseUrl = EnvironmentHelper.IsProduction
? "http://103.90.155.78:9001/api/"
: "http://localhost:14312/api/";
public static StoreApiClient Instance { get; } = new StoreApiClient();
public ApiTransport Transport { get; }
public AuthApi Auth { get; }
public CloudGoodsApi CloudGoods { get; }
//public GoodsComplianceApi GoodsCompliance { get; }
public ImageCacheApi ImageCache { get; }
/// <summary>当前 Windows 安装的 SHA-256 设备指纹,登录时作为 DeviceId 发送。</summary>
public string DeviceId { get; }
private StoreApiClient()
{
DeviceId = CreateDeviceId();
Transport = new ApiTransport(BaseUrl);
Auth = new AuthApi(Transport, DeviceId);
CloudGoods = new CloudGoodsApi(Transport);
//GoodsCompliance = new GoodsComplianceApi(Transport);
ImageCache = new ImageCacheApi(Transport);
}
private static string CreateDeviceId()
{
using (var machine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
using (var key = machine.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography"))
{
if (!Guid.TryParse(key?.GetValue("MachineGuid") as string, out var machineGuid) || machineGuid == Guid.Empty)
throw new InvalidOperationException("无法读取有效的 Windows MachineGuid,不能生成设备指纹。");
using (var sha256 = SHA256.Create())
return BitConverter.ToString(sha256.ComputeHash(
Encoding.UTF8.GetBytes("Store.Api:" + machineGuid.ToString("D")))).Replace("-", "");
}
}
/// <summary>清除内存中的 Token 和自动登录凭据,不调用服务端退出接口。</summary>
public void ClearSession() => Transport.Token = null;
}
+2
View File
@@ -101,6 +101,8 @@ namespace Work
BaseClass.OemId = BaseRegex.GetStringJson(ref html, "oem_id");
BaseClass.OemName = BaseRegex.GetStringJson(ref html, "oem_name");
BaseClass.IsOemOwner = BaseRegex.GetBoolJson(ref html, "is_oem_owner");
BaseClass.ImageAnalysisQuota = Math.Max(0, BaseRegex.GetIntJson(ref html, "image_analysis_quota"));
#if DEBUG
if (!string.IsNullOrEmpty(BaseRegex.GetStringJson(ref html, "prod_api_url")) && !BaseClass.LoginApiUrl.Contains("localhost") && !BaseClass.LoginApiUrl.Contains("127.0.0.1"))
{
+5
View File
@@ -51,6 +51,7 @@
<Reference Include="NaiBa.Util.Winform">
<HintPath>..\DllReference\NaiBa.Util.Winform.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Data.SQLite">
<HintPath>..\DllReference\System.Data.SQLite.DLL</HintPath>
<SpecificVersion>False</SpecificVersion>
@@ -77,4 +78,8 @@
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\TEMUKJD\BLL\PDDProdFormConverter.cs" Link="ImportConverters\PDDProdFormConverter.cs" />
<Compile Include="..\TEMUKJD\BLL\ImportConverters\*.cs" Link="ImportConverters\%(Filename)%(Extension)" />
</ItemGroup>
</Project>
+112
View File
@@ -0,0 +1,112 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using CsharpHttpHelper;
using Work.Store.Api;
// Compile against Work.dll, AllBase.dll and Newtonsoft.Json.dll; run beside these assemblies.
internal static class ApiTransportSmoke
{
private static void Check(bool passed)
{
if (!passed) throw new Exception("ApiTransport assertion failed.");
}
private static async Task<T> Respond<T>(int status, string json, Func<ApiTransport, Task<T>> request)
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
var server = Task.Run(() =>
{
using (var client = listener.AcceptTcpClient())
using (var stream = client.GetStream())
using (var reader = new StreamReader(stream, Encoding.ASCII, false, 1024, true))
{
while (!string.IsNullOrEmpty(reader.ReadLine())) { }
var body = Encoding.UTF8.GetBytes(json);
var header = Encoding.ASCII.GetBytes("HTTP/1.1 " + status + " Response\r\nContent-Type: application/json\r\nContent-Length: " + body.Length + "\r\nConnection: close\r\n\r\n");
stream.Write(header, 0, header.Length);
stream.Write(body, 0, body.Length);
}
});
try
{
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
return await request(new ApiTransport("http://127.0.0.1:" + port));
}
finally
{
listener.Stop();
await server;
}
}
private static Task<string> Send(ApiTransport transport)
{
return transport.SendAsync<string>("Test", MethodType.Get, authenticated: false, timeoutMilliseconds: 5000);
}
public static async Task Main()
{
Check(await Respond(200, "{\"code\":0,\"success\":true,\"data\":\"ok\"}", Send) == "ok");
Check(await Respond(200, "{\"code\":0,\"success\":true,\"data\":null}", Send) == null);
Check(await Respond(200, "{\"success\":true,\"data\":null}", transport =>
transport.SendAsync<int>("Test", MethodType.Get, authenticated: false)) == 0);
Check((await Respond(200, "{\"success\":true,\"data\":[1,2]}", transport =>
transport.SendAsync<int[]>("Test", MethodType.Get, authenticated: false)))[1] == 2);
foreach (var status in new[] { 200, 500 })
{
await Respond(status, "{\"data\":null,\"code\":5000,\"msg\":\"semaphore limit\",\"traceId\":\"trace-1\",\"success\":false}", async transport =>
{
try { await Send(transport); throw new Exception("Expected ApiException."); }
catch (ApiException ex)
{
Check(ex.Code == 5000 && ex.TraceId == "trace-1" && ex.Message.Contains("semaphore limit"));
}
return true;
});
}
await Respond(200, "{\"code\":200,\"success\":false,\"data\":{}}", async transport =>
{
try { await Send(transport); throw new Exception("Expected ApiException."); }
catch (ApiException ex) { Check(ex.Code == 200 && ex.ResponseData is Newtonsoft.Json.Linq.JObject); }
return true;
});
foreach (var json in new[] { "not json", "[]", "null", "{\"code\":\"invalid\",\"success\":true}",
"{\"code\":200,\"data\":\"legacy\"}", "{\"code\":200,\"success\":null}", "{}" })
{
await Respond(200, json, async transport =>
{
try { await Send(transport); throw new Exception("Expected response format error."); }
catch (HttpException ex) { Check(ex.Message.Contains("Result")); }
return true;
});
}
await Respond(401, "{\"code\":401,\"success\":false,\"msg\":\"expired\"}", async transport =>
{
try { await Send(transport); throw new Exception("Expected authentication error."); }
catch (HttpException ex) { Check(!ex.IsOnline && ex.Message == "expired"); }
return true;
});
Check(await Respond(200, "{\"success\":true,\"data\":\"ok\"}", transport =>
Task.Run(() => transport.GetRequired<string>("Test", MethodType.Get, authenticated: false))) == "ok");
var stalled = new TcpListener(IPAddress.Loopback, 0);
stalled.Start();
try
{
var transport = new ApiTransport("http://" + stalled.LocalEndpoint);
try
{
await transport.SendAsync<string>("Test", MethodType.Get, authenticated: false, timeoutMilliseconds: 250);
throw new Exception("Expected timeout.");
}
catch (HttpException ex) { Check(ex.Message.Contains("超时")); }
}
finally { stalled.Stop(); }
Console.WriteLine("ApiTransport smoke checks passed.");
}
}
+79
View File
@@ -0,0 +1,79 @@
using AllBase.Helper;
using AllBase;
using AllBase.Model;
using System.Collections.Generic;
using System;
using System.Linq;
using Work.Services;
// Compile against the built Work.dll, AllBase.dll and Newtonsoft.Json.dll and run in an isolated directory.
internal static class GoodsComplianceSmoke
{
private static void Check(bool passed)
{
if (!passed) throw new Exception("商品合规自测失败");
}
public static void Main()
{
var user = Guid.NewGuid().ToString();
BaseClass.UserName = user;
GlobalConfig.GlobalSettings.GoodsCompliance = new ComplianceOptions { Keywords = "测试" };
var cloud = new ComplianceGoods { id = "123", type = ComplianceGoods.Cloud };
var library = new ComplianceGoods { id = "123", type = ComplianceGoods.Library };
var attempted = new List<ComplianceGoods>();
var failures = new List<string>();
var batch = GoodsComplianceService.DetectSelectedAsync(new[] { cloud, cloud, library }, item =>
{
attempted.Add(item);
throw new InvalidOperationException("读取失败");
}, (id, status) => { if (status == "失败:读取失败") failures.Add(id); }).GetAwaiter().GetResult();
Check(attempted.SequenceEqual(new[] { cloud, library }) && failures.Count == 2);
var file = System.IO.Directory.GetFiles(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
"data", "config"), "goods_compliance_" + Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(user)) + ".json").Single();
Check(Newtonsoft.Json.JsonConvert.DeserializeObject<List<ComplianceGoods>>(System.IO.File.ReadAllText(file))
.Select(x => x.type).SequenceEqual(new[] { cloud.type, library.type }));
Check(batch.Safe == 0 && batch.Risk == 0 && batch.Failed == 2 && batch.Unfinished == 0);
using (var stop = new System.Threading.CancellationTokenSource())
{
attempted.Clear();
var stopped = GoodsComplianceService.DetectSelectedAsync(new[] { cloud, library }, item =>
{
attempted.Add(item);
stop.Cancel();
return new Product { ProductId = item.id };
}, (id, status) => { }, stop.Token).GetAwaiter().GetResult();
Check(attempted.SequenceEqual(new[] { cloud }) && stopped.Unfinished == 2 && stopped.Failed == 0);
Check(Newtonsoft.Json.JsonConvert.DeserializeObject<List<ComplianceGoods>>(System.IO.File.ReadAllText(file)).Count == 2);
}
var words = GoodsComplianceService.Keywords("广告,测试,abc 促销;ABC|示例");
Check(words.Length == 5);
Check(GoodsComplianceService.Matches("ABC广告", words).SequenceEqual(new[] { "广告", "abc" }));
Check(GoodsComplianceService.Matches("普通商品", words).Length == 0);
// Exercise detection without calling the reporting API.
var detect = typeof(GoodsComplianceService).GetMethod("DetectProductAsync",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
var titleHit = ((System.Threading.Tasks.Task<ComplianceResult>)detect.Invoke(null, new object[]
{
new Product { ProductId = "title", Title = "ABC广告" }, new ComplianceOptions(), words, null,
System.Threading.CancellationToken.None
})).GetAwaiter().GetResult();
Check(titleHit.Status == "有风险" && titleHit.Summary == "有风险:标题命中关键词:广告,abc");
var invalidImage = new Product { ProductId = "bad-image", MainImages = new List<string> { "file:///image.jpg" } };
var statuses = new List<string>();
GoodsComplianceService.DetectSelectedAsync(new[] { cloud }, item => invalidImage,
(id, status) => statuses.Add(status)).GetAwaiter().GetResult();
Check(statuses.SequenceEqual(new[] { "读取详情中", "正在检测第 1 张图片", "失败:第 1 张图片检测失败:图片链接必须为 HTTP 或 HTTPS 地址。" }));
var products = new[] { new Product(), new Product { ProductId = "empty" }, invalidImage };
var callbacks = new List<Product>();
GoodsComplianceService.DetectAsync(products, new ComplianceOptions { Keywords = "测试" }, (product, result) =>
{
Check(result.Error != null);
if (product == invalidImage) Check(result.Error.Contains("第 1 张图片") && result.Error.Contains("HTTP"));
callbacks.Add(product);
}).GetAwaiter().GetResult();
Check(callbacks.SequenceEqual(products));
System.IO.File.Delete(file);
Console.WriteLine("商品合规队列与匹配自测通过");
}
}
+68
View File
@@ -0,0 +1,68 @@
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using CsharpHttpHelper;
internal static class HttpHelperAsyncSmoke
{
public static async Task Main()
{
await CheckRequests(false);
await CheckRequests(true);
}
private static async Task CheckRequests(bool asynchronous)
{
var listener = new TcpListener(IPAddress.Loopback, 0);
listener.Start();
try
{
string url = "http://" + listener.LocalEndpoint + "/";
var pending = asynchronous ? HttpHelper.PostAsync(url, "hello") : Task.Run(() => HttpHelper.Post(url, "hello"));
using (var client = await listener.AcceptTcpClientAsync())
using (var stream = client.GetStream())
using (var reader = new StreamReader(stream, Encoding.ASCII, false, 1024, true))
{
if (!reader.ReadLine().StartsWith("POST ", StringComparison.OrdinalIgnoreCase))
throw new Exception("Expected POST");
while (!string.IsNullOrEmpty(reader.ReadLine())) { }
var reply = Encoding.ASCII.GetBytes("HTTP/1.1 100 Continue\r\n\r\n");
stream.Write(reply, 0, reply.Length);
var body = new char[5];
if (reader.ReadBlock(body, 0, body.Length) != 5 || new string(body) != "hello")
throw new Exception("POST body mismatch");
reply = Encoding.ASCII.GetBytes("HTTP/1.1 400 Bad Request\r\nContent-Length: 7\r\nConnection: close\r\n\r\ninvalid");
stream.Write(reply, 0, reply.Length);
}
var result = await pending;
if (result.StatusCode != HttpStatusCode.BadRequest || result.Html != "invalid")
throw new Exception("Missing error response");
var get = asynchronous ? HttpHelper.GetAsync(url) : Task.Run(() => HttpHelper.Get(url));
using (var client = await listener.AcceptTcpClientAsync())
using (var stream = client.GetStream())
using (var reader = new StreamReader(stream, Encoding.ASCII, false, 1024, true))
{
if (!reader.ReadLine().StartsWith("GET ", StringComparison.OrdinalIgnoreCase))
throw new Exception("Expected GET");
while (!string.IsNullOrEmpty(reader.ReadLine())) { }
var reply = Encoding.UTF8.GetBytes("HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: 5\r\nConnection: close\r\n\r\n\uFEFFok");
stream.Write(reply, 0, reply.Length);
}
if ((await get).Html != "\uFEFFok") throw new Exception("Expected GET response to retain its BOM");
var item = new HttpItem { URL = url, Timeout = 250 };
var stalled = asynchronous ? HttpHelper.RequestAsync(item) : Task.Run(() => HttpHelper.Request(item));
if (await Task.WhenAny(stalled, Task.Delay(5000)) != stalled || string.IsNullOrEmpty((await stalled).Html))
throw new Exception("Expected a timeout result");
}
finally
{
listener.Stop();
}
}
}
+45
View File
@@ -0,0 +1,45 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using TemuKJD.UserComponent;
internal static class NumericRangeSmoke
{
[STAThread]
public static void Main()
{
using (var range = new UcNumericRange())
{
int width = range.Width;
var layout = (TableLayoutPanel)range.Controls[0];
var separator = (Label)layout.GetControlFromPosition(1, 0);
var margin = separator.Margin;
var cell = layout.GetControlFromPosition(0, 0);
var editor = (NumericUpDown)cell.Controls[0];
var text = (TextBox)(editor.Controls[0] is TextBox ? editor.Controls[0] : editor.Controls[1]);
var buttons = editor.Controls[0] == text ? editor.Controls[1] : editor.Controls[0];
range.SeparatorText = "~";
range.Compact = true;
var rightCell = layout.GetControlFromPosition(2, 0);
using (var bitmap = new Bitmap(range.Width, range.Height))
{
range.DrawToBitmap(bitmap, range.ClientRectangle);
int y = rightCell.Top + rightCell.Height / 2;
int border = bitmap.GetPixel(rightCell.Right - 1, y).ToArgb();
if (border == editor.BackColor.ToArgb() || border != bitmap.GetPixel(rightCell.Left, y).ToArgb())
throw new Exception("结束值输入框右边框未绘制");
}
if (range.Width != 112 || buttons.Left < cell.Width - 2 || text.Right < cell.Width - 4)
throw new Exception("紧凑模式未充分利用输入区域");
if (separator.Text != "~" || range.Width >= width || separator.Margin != Padding.Empty)
throw new Exception("紧凑布局或分隔文字错误");
range.Compact = false;
if (buttons.Right > cell.Width || text.Right > buttons.Left) throw new Exception("微调按钮未恢复");
if (range.Width != width || separator.Margin != margin)
throw new Exception("普通布局未恢复");
range.Width = 190;
range.Compact = true;
if (range.Width != 190) throw new Exception("自定义宽度被覆盖");
}
}
}