待上传商品筛选配置保存

This commit is contained in:
chfei committed 2026-09-17 18:02:37 +08:00
1 parent ab4f94e320
commit 1b9d2244c8
2 files changed
+444 -4

No files matched your search

+150
View File
@@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TemuKJD.Extension;
public class DataContext<TSource> : BindingSource
{
public DataContext() { }
public DataContext(TSource dataSource) : base(dataSource, null) { }
// 强类型的 DataSource,避免调用方还要自己转型
public new TSource DataSource
{
get => (TSource)base.DataSource;
set => base.DataSource = value;
}
}
public static class BindingExtensions
{
/// <summary>
/// TSource 必须显式指定(因为无法从参数推断),TControl 自动从调用方控件推断
/// </summary>
public static Binding Bind<TSource, TControl>(
this TControl ctrl,
DataContext<TSource> dataSource,
Expression<Func<TControl, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
where TControl : Control
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), dataSource, dataPropertyExpr, mode, format, parseHandler);
public static Binding Bind<TControl>(
this TControl ctrl,
BindingSource dataSource,
Expression<Func<TControl, object>> controlPropertyExpr,
string dataPropertyName,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null) where TControl : Control
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), dataSource, dataPropertyName, mode, format, parseHandler);
// ---------- 共享的核心实现,不对外暴露 ----------
private static Binding BindCore<TSource>(
Control ctrl,
string controlPropertyName,
BindingSource bs,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode,
string format,
ConvertEventHandler parseHandler) => BindCore(ctrl, controlPropertyName, bs, dataPropertyExpr.GetPropertyName(), mode, format, parseHandler);
private static Binding BindCore(
Control ctrl,
string controlPropertyName,
BindingSource bs,
string dataPropertyName,
DataSourceUpdateMode mode,
string format,
ConvertEventHandler parseHandler)
{
var binding = new Binding(controlPropertyName, bs, dataPropertyName, true, mode);
if (!string.IsNullOrEmpty(format))
binding.Format += (s, e) => e.Value = string.Format($"{{0:{format}}}", e.Value);
if (parseHandler != null)
binding.Parse += parseHandler;
ctrl.DataBindings.Add(binding);
return binding;
}
// ---------- TextBox ----------
public static Binding Bind<TSource>(
this TextBox ctrl,
BindingSource bs,
Expression<Func<TextBox, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
// ---------- CheckBox ----------
public static Binding Bind<TSource>(
this CheckBox ctrl,
BindingSource bs,
Expression<Func<CheckBox, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
// ---------- DateTimePicker ----------
public static Binding Bind<TSource>(
this DateTimePicker ctrl,
BindingSource bs,
Expression<Func<DateTimePicker, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
// ---------- ComboBox ----------
public static Binding Bind<TSource>(
this ComboBox ctrl,
BindingSource bs,
Expression<Func<ComboBox, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
// ---------- NumericUpDown ----------
public static Binding Bind<TSource>(
this NumericUpDown ctrl,
BindingSource bs,
Expression<Func<NumericUpDown, object>> controlPropertyExpr,
Expression<Func<TSource, object>> dataPropertyExpr,
DataSourceUpdateMode mode = DataSourceUpdateMode.OnPropertyChanged,
string format = null,
ConvertEventHandler parseHandler = null)
=> BindCore(ctrl, controlPropertyExpr.GetPropertyName(), bs, dataPropertyExpr, mode, format, parseHandler);
public static string GetPropertyName<TSource, TProperty>(
this Expression<Func<TSource, TProperty>> propertyExpr)
{
if (propertyExpr.Body is MemberExpression member)
return member.Member.Name;
// 处理值类型属性被隐式转换为 object 的情况(如 decimal -> object)
if (propertyExpr.Body is UnaryExpression unary &&
unary.Operand is MemberExpression unaryMember)
return unaryMember.Member.Name;
throw new ArgumentException("表达式必须是形如 x => x.PropertyName 的属性访问", nameof(propertyExpr));
}
}
@@ -1,4 +1,4 @@
using AllBase;
using AllBase;
using AllBase.Extension;
using AllBase.Helper;
using AllBase.Model.Config;
@@ -38,6 +38,7 @@ using Work;
using Work.BLL.Tools;
using Work.Services;
using static System.Net.Mime.MediaTypeNames;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Rebar;
namespace TemuKJD.WXForms.ProductForms
{
@@ -79,7 +80,50 @@ namespace TemuKJD.WXForms.ProductForms
{
InitializeComponent();
}
DataContext<WaitingProductConfig> _bs;
WaitingProductConfig waiting_product_config = new WaitingProductConfig();
void InitWaitingProductConfigBinding()
{
Debug.WriteLine($"初始化配置");
Invoke(new Action(() =>
{
waiting_product_config = NaiBa.Util.Helper.ConfigHelper.LoadConfig<WaitingProductConfig>(nameof(waiting_product_config));
if (waiting_product_config == null)
{
waiting_product_config = new WaitingProductConfig();
}
_bs = new DataContext<WaitingProductConfig>(waiting_product_config);
//NaiBa.Util.Helper.ConfigHelper.SaveConfig<AddPriceRule>("wx_default_add_price_rule", defaultAddPriceRule);
////txtIdFilter.Bind<wx_qualification_image_info>(_bs,a=>a.)
txtIdFilter.Bind(_bs, a => a.Text, a => a.IdFilter);
txtSearchGoodsName.Bind(_bs, a => a.Text, a => a.SearchGoodsName);
cmbSourceType.Bind(_bs, a => a.Text, a => a.SourceType);
cmbGroupFilter.Bind(_bs, a => a.Text, a => a.GroupFilter);
cmbHot.Bind(_bs, a => a.Text, a => a.Hot);
cmbWxSafe.Bind(_bs, a => a.Text, a => a.WxSafe);
cmbCateFilter1.Bind(_bs, a => a.Text, a => a.CateFilter1);
cmbCateFilter2.Bind(_bs, a => a.Text, a => a.CateFilter2);
cmbCateFilter3.Bind(_bs, a => a.Text, a => a.CateFilter3);
cmbNotes.Bind(_bs, a => a.Text, a => a.Notes);
cmbJstInitSet.Bind(_bs, a => a.Text, a => a.JstInitSet);
txtAddCount.Bind(_bs, a => a.Text, a => a.AddCount);
chkSkipQualification.Bind(_bs, a => a.Checked, a => a.SkipQualification);
chkRandomFissionProduct.Bind(_bs, a => a.Checked, a => a.RandomFissionProduct);
txtRandomFissionProductCount.Bind(_bs, a => a.Text, a => a.RandomFissionProductCount);
chkWXComplateProd.Bind(_bs, a => a.Checked, a => a.WXComplateProd);
chkUpdateInDays.Bind(_bs, a => a.Checked, a => a.UpdateInDaysChecked);
txtUpdateInDays.Bind(_bs, a => a.Text, a => a.UpdateInDays);
cmbUpdateInDays.Bind(_bs, a => a.Text, a => a.UpdateInDaysType);
chkFilterViewUv.Bind(_bs, a => a.Checked, a => a.FilterViewUvChecked);
numFilterViewUv.Bind(_bs, a => a.Value, a => a.FilterViewUv);
chkFilterSaleCountNum.Bind(_bs, a => a.Checked, a => a.FilterSaleCountNumChecked);
numFilterSaleCountNum.Bind(_bs, a => a.Value, a => a.FilterSaleCountNum);
}));
Debug.WriteLine($"初始化配置END");
}
private void UserSelectDbProductForm_Load(object sender, EventArgs e)
{
Instance = this;
@@ -167,6 +211,8 @@ namespace TemuKJD.WXForms.ProductForms
}
catch { }
txtAddTimes.TextChanged -= txtAddPrice_TextChanged;
txtAddMorePrice.TextChanged -= txtAddPrice_TextChanged;
txtSinglePriceAdd.TextChanged -= txtAddPrice_TextChanged;
@@ -611,7 +657,7 @@ namespace TemuKJD.WXForms.ProductForms
{
RefreshShopLogin();
updateAuthor();
RefreshDbProdGroupAndCate();
RefreshDbProdGroupAndCate(InitWaitingProductConfigBinding);
lblWaitToUp.Text = "待上传 " + lstTemuDBProductSelect.Count + " 件";
if (!isInit)
@@ -637,7 +683,7 @@ namespace TemuKJD.WXForms.ProductForms
}
}
private void RefreshDbProdGroupAndCate()
private void RefreshDbProdGroupAndCate(Action call = null)
{
Task.Run(() =>
{
@@ -664,7 +710,10 @@ namespace TemuKJD.WXForms.ProductForms
this.btnSwitchCatType.Text = "P";
btnSwitchCatType_Click(null, null);
pbLoadingShop.Visible = false;
}));
call?.Invoke();
});
}
@@ -989,6 +1038,8 @@ namespace TemuKJD.WXForms.ProductForms
private void btnUpload_Click(object sender, EventArgs e)
{
NaiBa.Util.Helper.ConfigHelper.SaveConfig<WaitingProductConfig>(nameof(waiting_product_config), waiting_product_config);
var shopIdLst = dgvShop.Rows.Cast<DataGridViewRow>().Where(row
=> row.Cells["colSelect"]?.Value.ParseToBool() == true).Select(r => r.Cells["colShopId"]?.Value.ToString()).ToList();
if (shopIdLst.Count <= 0)
@@ -2095,7 +2146,7 @@ namespace TemuKJD.WXForms.ProductForms
// 同颜色规格向下浮动同价格
if (chkSameSpecPriceDown.Checked)
{
var priceTextLst = dbProd.price_text.ParseToString().Split('-');
var priceTextLst = dbProd.price_text.ParseToString().Split('-');
if (priceTextLst.Length != 2 || priceTextLst[0] != priceTextLst[1])
{
Dictionary<string, int> specPriceDic = new Dictionary<string, int>();
@@ -7030,6 +7081,7 @@ namespace TemuKJD.WXForms.ProductForms
private void cmbCateFilter1_TextChanged(object sender, EventArgs e)
{
Debug.WriteLine($"Filter1 修改:{cmbCateFilter1.Text}");
//if (cmbSourceType.Text != "厂商直采" && cmbSourceType.Text != "1688厂家" && cmbSourceType.Text != "微信店采" && cmbSourceType.Text != "微信小店")
if (btnSwitchCatType.Text != "W")
return;
@@ -7051,6 +7103,7 @@ namespace TemuKJD.WXForms.ProductForms
private void cmbCateFilter2_TextChanged(object sender, EventArgs e)
{
Debug.WriteLine($"Filter1 修改:{cmbCateFilter2.Text}");
//if (cmbSourceType.Text != "厂商直采" && cmbSourceType.Text != "1688厂家" && cmbSourceType.Text != "微信店采" && cmbSourceType.Text != "微信小店")
if (btnSwitchCatType.Text != "W")
return;
@@ -7998,4 +8051,241 @@ Content-Type: application/octet-stream
public string PlatformUrl { get; set; }
public bool IsCache { get; set; }
}
class WaitingProductConfig : BindableBase
{
public WaitingProductConfig()
{
IdFilter = "";
SearchGoodsName = "";
SourceType = "厂商直采";
GroupFilter = "";
Hot = "普通商品";
WxSafe = "安全+未校验";
CateFilter1 = "全部";
CateFilter2 = "全部";
CateFilter3 = "全部";
Notes = "";
JstInitSet = "是";
AddCount = "500";
SkipQualification = false;
RandomFissionProduct = false;
RandomFissionProductCount = "100";
WXComplateProd = false;
UpdateInDaysChecked = false;
UpdateInDays = "30";
UpdateInDaysType = "新增";
FilterViewUvChecked = false;
FilterViewUv = 200m;
FilterSaleCountNumChecked = false;
FilterSaleCountNum = 1m;
}
/// <summary>
/// txtIdFilter
/// </summary>
public string IdFilter
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// txtSearchGoodsName
/// </summary>
public string SearchGoodsName
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbSourceType
/// </summary>
public string SourceType
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbGroupFilter
/// </summary>
public string GroupFilter
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbHot
/// </summary>
public string Hot
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbWxSafe
/// </summary>
public string WxSafe
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbCateFilter1
/// </summary>
public string CateFilter1
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbCateFilter2
/// </summary>
public string CateFilter2
{
get => GetValue<string>();
set => base.SetValue(value);
}
/// <summary>
/// cmbCateFilter3
/// </summary>
public string CateFilter3
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbNotes
/// </summary>
public string Notes
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbJstInitSet
/// </summary>
public string JstInitSet
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// txtAddCount
/// </summary>
public string AddCount
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// chkSkipQualification
/// </summary>
public bool SkipQualification
{
get => GetValue<bool>();
set => SetValue(value);
}
/// <summary>
/// chkRandomFissionProduct
/// </summary>
public bool RandomFissionProduct
{
get => GetValue<bool>();
set => SetValue(value);
}
/// <summary>
/// txtRandomFissionProductCount
/// </summary>
public string RandomFissionProductCount
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// chkWXComplateProd
/// </summary>
public bool WXComplateProd
{
get => GetValue<bool>();
set => SetValue(value);
}
/// <summary>
/// chkUpdateInDays
/// </summary>
public bool UpdateInDaysChecked
{
get => GetValue<bool>();
set => SetValue(value);
}
/// <summary>
/// txtUpdateInDays
/// </summary>
public string UpdateInDays
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// cmbUpdateInDays
/// </summary>
public string UpdateInDaysType
{
get => GetValue<string>();
set => SetValue(value);
}
/// <summary>
/// chkFilterViewUv
/// </summary>
public bool FilterViewUvChecked
{
get => GetValue<bool>();
set => SetValue(value);
}
/// <summary>
/// numFilterViewUv
/// </summary>
public decimal FilterViewUv
{
get => GetValue<decimal>();
set => SetValue(value);
}
/// <summary>
/// chkFilterSaleCountNum
/// </summary>
public bool FilterSaleCountNumChecked
{
get => GetValue<bool>();
set => SetValue(value);
}
/// <summary>
/// numFilterSaleCountNum
/// </summary>
public decimal FilterSaleCountNum
{
get => GetValue<decimal>();
set => SetValue(value);
}
}
}