203 lines
6.2 KiB
C#
203 lines
6.2 KiB
C#
using System.Data.Common;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Logging;
|
|
using StopShopping.EF;
|
|
using StopShopping.Services.Models;
|
|
using StopShopping.Services.Models.Req;
|
|
using StopShopping.Services.Models.Resp;
|
|
|
|
namespace StopShopping.Services.Implementions;
|
|
|
|
public class CategoryService : ICategoryService
|
|
{
|
|
public CategoryService(
|
|
IFileService fileService,
|
|
StopShoppingContext dbContext,
|
|
ILogger<CategoryService> logger
|
|
)
|
|
{
|
|
_fileService = fileService;
|
|
_dbContext = dbContext;
|
|
_logger = logger;
|
|
}
|
|
|
|
private readonly IFileService _fileService;
|
|
private readonly StopShoppingContext _dbContext;
|
|
private readonly ILogger<CategoryService> _logger;
|
|
|
|
public async Task<ApiResponse> DeleteCategoryAsync(CategoryIdParams model)
|
|
{
|
|
var category = await _dbContext.Categories
|
|
.AsNoTracking()
|
|
.FirstOrDefaultAsync(c => c.Id == model.CategoryId && !c.Deleted);
|
|
if (null == category)
|
|
return ApiResponse.Failed("此分类已不存在,请刷新重试");
|
|
|
|
var anyProduct = await _dbContext.Products
|
|
.AsNoTracking()
|
|
.AnyAsync(p =>
|
|
_dbContext.Categories
|
|
.AsNoTracking()
|
|
.Where(c => c.Path.StartsWith(category.Path) && !c.Deleted)
|
|
.Select(c => c.Id)
|
|
.Contains(p.CategoryId));
|
|
if (anyProduct)
|
|
return ApiResponse.Failed("分类下已有商品,不允许删除");
|
|
|
|
await _dbContext.Categories
|
|
.Where(c => c.Path.StartsWith(category.Path) && !c.Deleted)
|
|
.ExecuteDeleteAsync();
|
|
|
|
return ApiResponse.Succed();
|
|
}
|
|
|
|
public async Task<ApiResponse<Category>> EditCategoryAsync(EditCategoryParams model)
|
|
{
|
|
EF.Models.Category category;
|
|
|
|
using var trans = await _dbContext.Database.BeginTransactionAsync();
|
|
try
|
|
{
|
|
short level = 1, order = 1;
|
|
string path = string.Empty;
|
|
|
|
var parent = await _dbContext.Categories
|
|
.FirstOrDefaultAsync(c => c.Id == model.ParentId);
|
|
if (null != parent)
|
|
level = (short)(parent.Level + 1);
|
|
|
|
if (model.Id > 0)
|
|
{
|
|
category = await _dbContext.Categories
|
|
.FirstAsync(c => c.Id == model.Id && !c.Deleted);
|
|
if (null == category)
|
|
return new ApiResponse<Category>().Failed("此分类已不存在");
|
|
|
|
path = category.Path;
|
|
order = category.Order;
|
|
}
|
|
else
|
|
{
|
|
category = new EF.Models.Category();
|
|
await _dbContext.Categories.AddAsync(category);
|
|
|
|
order = await _dbContext.Categories
|
|
.Where(c => c.ParentId == model.ParentId)
|
|
.Select(c => c.Order)
|
|
.DefaultIfEmpty()
|
|
.MaxAsync();
|
|
}
|
|
|
|
category.Level = level;
|
|
if (!string.IsNullOrWhiteSpace(model.Logo))
|
|
category.Logo = model.Logo;
|
|
category.Name = model.Name;
|
|
category.Order = order;
|
|
category.ParentId = model.ParentId;
|
|
category.Path = path;
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
if (!(model.Id > 0))
|
|
{
|
|
category.Path = BuildPath(parent?.Path ?? "", category.Id);
|
|
await _dbContext.SaveChangesAsync();
|
|
}
|
|
|
|
await trans.CommitAsync();
|
|
|
|
var categoryResult = Cast(category);
|
|
|
|
return new ApiResponse<Category>(categoryResult);
|
|
}
|
|
catch (DbException e)
|
|
{
|
|
await trans.RollbackAsync();
|
|
_logger.LogError(e, "新增/修改分类失败");
|
|
return new ApiResponse<Category>().Failed("数据库操作失败,请刷新重试");
|
|
}
|
|
}
|
|
|
|
public ApiResponse<List<Category>> GetCategoriesTree()
|
|
{
|
|
var qry = _dbContext.Categories
|
|
.AsNoTracking()
|
|
.Where(c => !c.Deleted)
|
|
.OrderBy(c => c.ParentId)
|
|
.ThenBy(c => c.Order)
|
|
.AsEnumerable();
|
|
|
|
var result = new ApiResponse<List<Category>>(ToTree(qry));
|
|
|
|
return result;
|
|
}
|
|
|
|
public async Task<ApiResponse> ResortCategoryAsync(ResortCategoryParams model)
|
|
{
|
|
var curr = await _dbContext.Categories
|
|
.FirstOrDefaultAsync(c => c.Id == model.Id && !c.Deleted);
|
|
if (null == curr)
|
|
return ApiResponse.Failed("此分类已不存在,请刷新重试");
|
|
|
|
var target = await _dbContext.Categories
|
|
.FirstOrDefaultAsync(c => c.Order == model.TargetOrder && !c.Deleted);
|
|
if (null == target)
|
|
return ApiResponse.Failed("目标位置分类已不存在,请刷新重试");
|
|
|
|
target.Order = curr.Order;
|
|
curr.Order = model.TargetOrder;
|
|
|
|
await _dbContext.SaveChangesAsync();
|
|
|
|
return ApiResponse.Succed();
|
|
}
|
|
|
|
#region private methods
|
|
|
|
private List<Category> ToTree(IEnumerable<EF.Models.Category> models)
|
|
{
|
|
Dictionary<int, Category> idDicts = [];
|
|
List<Category> categories = [];
|
|
|
|
foreach (var model in models)
|
|
{
|
|
Category node = Cast(model);
|
|
node.Children = [];
|
|
idDicts.Add(node.Id, node);
|
|
}
|
|
|
|
foreach (var d in idDicts)
|
|
{
|
|
if (d.Value.ParentId > 0)
|
|
idDicts[d.Value.ParentId].Children.Add(d.Value);
|
|
else
|
|
categories.Add(d.Value);
|
|
}
|
|
|
|
return categories;
|
|
}
|
|
|
|
private Category Cast(EF.Models.Category model)
|
|
{
|
|
return new()
|
|
{
|
|
Id = model.Id,
|
|
LogoUrl = string.IsNullOrWhiteSpace(model.Logo)
|
|
? ""
|
|
: _fileService.GetFileUrl(UploadScences.Category, model.Logo),
|
|
Name = model.Name,
|
|
Order = model.Order,
|
|
ParentId = model.ParentId,
|
|
Children = []
|
|
};
|
|
}
|
|
|
|
private string BuildPath(string prefix, params int[] ids)
|
|
{
|
|
return string.Format("{0}/{1}/",
|
|
prefix.TrimEnd('/')
|
|
, string.Join('/', ids));
|
|
}
|
|
|
|
#endregion
|
|
} |