using System.Data.Common; using System.Drawing.Imaging; using System.Xml.Linq; using AntDesign; using AntDesign.TableModels; using EasyTemplate.Tool; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Web; using Microsoft.JSInterop; using Org.BouncyCastle.Crypto; using SqlSugar; namespace EasyTemplate.Page.Pages; public partial class Product { protected override async Task OnInitializedAsync() { } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { await NavigationManager.RedirectLogin(IJSRuntime); tProperties = _TProperty.AsQueryable().ToTree(it => it.Children, it => it.ParentId, 0); } } #region 表格 /// /// 查 /// /// private async Task Query() { Loading = true; RefAsync total = 0; var products = await _Repository.AsQueryable() .Where(x => !x.IsDelete) .WhereIF(!string.IsNullOrWhiteSpace(Q_Name), x => x.Name.Contains(Q_Name)) .WhereIF(!string.IsNullOrWhiteSpace(Q_Code), x => x.Code.Contains(Q_Code)) .ToPageListAsync(Pi, Ps, total); products?.ForEach(item => { item.Skus = _Sku.AsQueryable().Where(x => x.ProductId == item.Id).ToList(); }); DataSource = products; Total = total.Value; Loading = false; } /// /// 增/改 /// /// /// private bool InsertOrUpdate(TProduct data) { try { _Repository.Context.Ado.BeginTran(); tProduct.Preview = string.Join(",", FileList.Select(x => x.Url).ToList()); tProduct.TotalStock = tProduct.Skus.Sum(x => x.Stock); if (data.Id == 0) { if (_Repository.AsQueryable().Any(x => x.Name.ToLower() == data.Name.ToLower() || x.Code.ToLower() == data.Code.ToLower())) { throw new Exception("该商品已存在"); } if (string.IsNullOrWhiteSpace(data.Code)) { data.Code = $"TP{DateTime.Now.ToString("yyyyMMddHHmmssfff")}{new Random().Next(1000, 9999)}"; } //新增商品 var id = _Repository.AsInsertable(data).ExecuteReturnBigIdentity(); //新增规格 _Sku.AsDeleteable().Where(x => x.ProductId == id).ExecuteCommand(); data.Skus.ForEach(item => { item.ProductId = id; }); _Sku.AsInsertable(data.Skus).ExecuteCommand(); } else { if (_Repository.AsQueryable().Any(x => x.Name.ToLower() == data.Name.ToLower() && x.Id != data.Id)) { throw new Exception("该商品已存在"); } //更新商品 _Repository.AsUpdateable() .SetColumns(x => x.Name == data.Name) .SetColumns(x => x.Description == data.Description) .SetColumns(x => x.Preview == data.Preview) .SetColumns(x => x.Content == data.Content) .Where(x => x.Id == data.Id) .ExecuteCommand(); //新增规格 _Sku.AsDeleteable().Where(x => x.ProductId == data.Id).ExecuteCommand(); data.Skus.ForEach(item => { item.ProductId = data.Id; }); _Sku.AsInsertable(data.Skus).ExecuteCommand(); } _Repository.Context.Ado.CommitTran(); return true; } catch (Exception ex) { Log.Error($"商品增改失败:{ex}"); _Repository.Context.Ado.RollbackTran(); return false; } } /// /// 重置查询 /// private async Task ResetQuery() { Q_Name = Q_Code = string.Empty; Pi = 1; await Query(); } /// /// 表格使用它来初始化,不要在页面初始化时调用,否则会导致重复加载 /// /// /// private async Task OnChange(QueryModel query) => await Query(); private async Task Search() { Pi = 1; await Query(); } private void CheckedChanged(TProduct row) { _Repository.AsUpdateable() .SetColumns(x => x.Available == row.Available) .Where(x => x.Id == row.Id) .ExecuteCommand(); } /// /// 名称 /// private string Q_Name { get; set; } /// /// 编码 /// private string Q_Code { get; set; } private TProduct tProduct = new(); /// /// /// private ITable _Table; /// /// /// private IEnumerable SelectedRows = []; /// /// /// private List DataSource; /// /// /// private int Pi = 1; /// /// /// private int Ps = 20; /// /// /// private int Total; /// /// /// private bool Loading = false; /// /// /// private string imgUrl = string.Empty; /// /// /// private bool previewVisible = false; #endregion #region 表单方法 /// /// 初始化表单 /// /// private void InitFormData(TProduct row) { IsControlByUser = false; UsingTPropertyItems.Clear(); TPropertyItems.Clear(); if (row != null) { //获取规格id并去重 var ids = row.Skus .SelectMany(x => x.PropertyIds.Split(',', StringSplitOptions.RemoveEmptyEntries)) .Select(idStr => long.TryParse(idStr, out var id) ? id : (long?)null) .Where(id => id.HasValue) .Select(id => id!.Value) .Distinct() .ToList(); var Main = tProperties.Where(x => x.Children is null ? false : x.Children.Any(y => ids.Contains(y.Id))).ToList(); for (int index = 0; index < Main.Count; index++) { var arr = Main[index].Children.Where(x => ids.Contains(x.Id)).Select(x => x.Id).ToArray(); var newlist = tProperties.Except(Main).ToList(); newlist.Add(Main[index]); TPropertyItems.Add(new SkuSet() { Index = (index + 1), MainProperties = newlist.OrderBy(x=>x.Id).ToList(), MainSelectedValue = Main[index].Id, ChildProperties = Main[index].Children, ChildSelectedValues = arr?.OfType() ?? Enumerable.Empty() }); UsingTPropertyItems.Add(Main[index]); } } else { TPropertyItems.Add(new SkuSet() { Index = 1, MainProperties = tProperties }); } IsDisabled = TPropertyItems.Count >= tProperties.Count; FileList.Clear(); if (!string.IsNullOrWhiteSpace(tProduct.Preview)) { var imgs = tProduct.Preview.Split(",").ToList(); for (int index = 0; index < imgs.Count; index++) { FileList.Add(new UploadFileItem { Id = (index + 1).ToString(), State = UploadState.Success, Url = imgs[index], FileName = Path.GetFileName(imgs[index]) }); } } } /// /// 更新规格表 /// private void GenerateSkuTable() { if (TPropertyItems?.Count > 0) { tProduct.Skus = new(); var selectedValuesLists = TPropertyItems .Where(item => item.ChildSelectedValues != null && item.ChildSelectedValues.Any()) .Select(item => item.ChildSelectedValues.ToList()) .ToList(); var res = GenerateCartesianProduct(selectedValuesLists) .Select(combination => string.Join(",", combination)) .ToList(); var skus = new List(); for (int index = 0; index < res.Count; index++) { var names = _TProperty.AsQueryable() .Where(x => SqlFunc.SplitIn(res[index], x.Id.ToString())) .Select(x => x.Name) .ToList(); skus.Add(new TProductSku() { PropertyIds = res[index], PropertyName = string.Join(",", names), Code = $"S{DateTime.Now.ToString("yyyyMMddHHmmssfff")}-{(index + 1)}", }); } tProduct.Skus = skus; } IsDisabled = TPropertyItems?.Count >= tProperties.Count; modalRef.UpdateConfigAsync(); } private static IEnumerable> GenerateCartesianProduct(IEnumerable> sequences) { IEnumerable> emptyProduct = new[] { Enumerable.Empty() }; return sequences.Aggregate( emptyProduct, (accumulator, sequence) => from acc in accumulator from item in sequence select acc.Concat(new[] { item })); } /// /// 新增规格选择框 /// private void AddProperty() { if (TPropertyItems[TPropertyItems.Count - 1].MainSelect?.Value == null) { MessageService.Warning("还未选择规格"); return; } if (TPropertyItems[TPropertyItems.Count - 1].ChildSelectedValues?.Count() == 0) { MessageService.Warning("还未选择规格"); return; } var prop = tProperties.Except(UsingTPropertyItems).ToList(); TPropertyItems.Add(new SkuSet() { Index = TPropertyItems.Count + 1, MainProperties = prop }); if (prop.Count == 1) { IsDisabled = true; } modalRef.UpdateConfigAsync(); } /// /// 删除规格选择框 /// /// /// private void DeleteProperty(SkuSet? selectedValue, MouseEventArgs args) { TPropertyItems.Remove(selectedValue); var current = selectedValue.MainProperties.Where(x => x.Id == selectedValue.MainSelectedValue).FirstOrDefault(); UsingTPropertyItems.Remove(current); UpdatePropertyItems(); GenerateSkuTable(); } /// /// 触发点击说明用户开始操作 /// private void OnClick() { IsControlByUser = true; } /// /// 主规格被选 /// /// private void OnMainSelectedItemChanged(SkuSet? selectedValue, TProductProperty value) { if (!IsControlByUser) return; TProductProperty old = null; if (UsingTPropertyItems.Count >= selectedValue.Index && UsingTPropertyItems[selectedValue.Index - 1].Id != value.Id) { old = UsingTPropertyItems[selectedValue.Index - 1]; UsingTPropertyItems[selectedValue.Index - 1] = value; } if (!UsingTPropertyItems.Any(x => x.Id == value.Id)) { UsingTPropertyItems.Add(value); } UpdatePropertyItems(old, value); modalRef.UpdateConfigAsync(); } private void UpdatePropertyItems(TProductProperty oldValue = null, TProductProperty newValue = null) { foreach (var TPropertyItem in TPropertyItems) { var newlist = tProperties.Except(UsingTPropertyItems).ToList() ?? new(); var current = tProperties.Where(x => x.Id == TPropertyItem.MainSelectedValue).FirstOrDefault(); newlist.Add(current); TPropertyItem.MainProperties = newlist.OrderBy(x => x.Id).ToList(); TPropertyItem.ChildProperties = _TProperty.AsQueryable().Where(x => x.ParentId == TPropertyItem.MainSelectedValue).ToList(); if (oldValue != null && newValue != null && oldValue.Id != TPropertyItem.MainSelectedValue && newValue.Id == TPropertyItem.MainSelectedValue) { TPropertyItem.ChildSelectedValues = default; } } } /// /// 子规格被选 /// /// private void OnChildSelectedItemsChanged(IEnumerable value) { if (!IsControlByUser) return; GenerateSkuTable(); } /// /// 新增规格 /// /// private void AddNewMainProperty(MouseEventArgs args) { if (!string.IsNullOrWhiteSpace(_name)) { if (!_TProperty.IsAny(x => x.Name == _name)) { _TProperty.AsInsertable(new TProductProperty() { Name = _name }).ExecuteCommand(); var MainProperties = _TProperty.AsQueryable().Where(x => x.ParentId == 0).ToList(); foreach (var item in TPropertyItems) { item.MainProperties = MainProperties; } _name = string.Empty; modalRef.UpdateConfigAsync(); } else { MessageService.Warning("已存在该规格"); } } } /// /// 新增子规格 /// /// /// private async Task AddNewChildProperty(SkuSet? selectedValue, MouseEventArgs args) { var MainSelectedValue = selectedValue.MainSelect?.Value; if (!string.IsNullOrWhiteSpace(_name) && MainSelectedValue.HasValue && MainSelectedValue.Value > 0) { if (!_TProperty.IsAny(x => x.ParentId == MainSelectedValue && x.Name == _name)) { await _TProperty.AsInsertable(new TProductProperty() { Name = _name, ParentId = MainSelectedValue.Value }).ExecuteCommandAsync(); var child = TPropertyItems.Where(x => x.MainSelect?.Value == MainSelectedValue).First(); child.ChildProperties = _TProperty.AsQueryable().Where(x => x.ParentId == MainSelectedValue).ToList(); _name = string.Empty; modalRef?.UpdateConfigAsync(); } else { MessageService.Warning("已存在该属性"); } } } /// /// /// /// /// private bool BeforeUpload(UploadFileItem file) { var isLt2M = file.Size / 1024 / 1024 <= 4; if (!isLt2M) { MessageService.Error("图片必须小于4M"); return false; } return true; } /// /// Sku属性设置 /// internal class SkuSet { /// /// 索引 /// public int Index { get; set; } /// /// 主要属性列表 /// public List MainProperties { get; set; } /// /// 被选主要属性 /// public Select MainSelect { get; set; } /// /// 被选中的主要值 /// public long? MainSelectedValue { get; set; } /// /// 子属性列表 /// public Select ChildSelect { get; set; } /// /// 子属性值 /// public List ChildProperties { get; set; } /// /// 子属性值 /// public IEnumerable ChildSelectedValues { get; set; } } /// /// 是否初始化表单 /// private bool IsControlByUser { get; set; } = false; /// /// /// private bool ImageLoading { get; set; } = false; /// /// /// private bool IsDisabled { get; set; } = false; /// /// /// private List TPropertyItems = new(); /// /// 正在被使用的属性 /// private List UsingTPropertyItems { get; set; } = new(); /// /// /// private List FileList { get; set; } = new(); /// /// /// private ModalRef modalRef = default; /// /// /// private string _name = string.Empty; /// /// /// private ITable SkuTable; #endregion /// /// 注入实例 /// [Inject] private SqlSugarRepository _Repository { get; set; } /// /// /// [Inject] private SqlSugarRepository _Sku { get; set; } /// /// /// [Inject] private SqlSugarRepository _TProperty { get; set; } /// /// /// private List tProperties { get; set; } /// /// /// [Inject] NavigationManager NavigationManager { get; set; } /// /// /// [Inject] IJSRuntime IJSRuntime { get; set; } }