云商品 增加分组

This commit is contained in:
chfei committed 2026-11-10 15:10:20 +08:00
1 parent f4913b4fc2
commit b18aad1f85
5 files changed
+200 -24

No files matched your search

@@ -96,7 +96,7 @@ namespace Store.Modules.CloudProduct.Controllers
/// 创建收藏分组:创建成功返回 true,同名分组已存在返回 false。
/// </summary>
[HttpPost]
public async Task<bool> CreateGroup(CreateUserFavoriteGroupRequest request)
public async Task<bool> CreateGroup(UserFavoriteGroupRequest request)
{
if (request == null)
{
@@ -121,7 +121,7 @@ namespace Store.Modules.CloudProduct.Controllers
/// <summary>
/// 查询用户的收藏分组(含默认分组)及分组下收藏数量。
/// </summary>
[HttpGet]
[HttpPost]
public async Task<List<UserFavoriteGroupDto>> GetGroups(string? userName = null)
{
var resolved = ResolveUserName(userName);
@@ -153,6 +153,41 @@ namespace Store.Modules.CloudProduct.Controllers
return await _favoritesService.GetFavoriteStatusAsync(request);
}
/// <summary>
/// 删除分组
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
[HttpPost]
public async Task<bool> DelGroup(UserFavoriteGroupRequest request)
{
if (request == null)
{
throw new AppException("请求参数不能为空", ResultCode.ValidationError);
}
request.UserName = ResolveUserName(request.UserName);
if (string.IsNullOrWhiteSpace(request.UserName))
{
throw new AppException("用户名不能为空", ResultCode.ValidationError);
}
return await _favoritesService.DelGroupAsync(request);
}
/// <summary>将已收藏商品移动到指定分组。</summary>
[HttpPost]
public async Task<bool> SetFavoriteGroup(SetUserFavoriteGroupRequest request)
{
if (request == null)
{
throw new AppException("请求参数不能为空", ResultCode.ValidationError);
}
request.UserName = ResolveUserName(request.UserName);
return await _favoritesService.SetFavoriteGroupAsync(request);
}
/// <summary>
/// 检索用户收藏的商品(标题、销量、价格、类目、分组)。
@@ -274,4 +309,4 @@ namespace Store.Modules.CloudProduct.Controllers
: userName.Trim();
}
}
}
}
@@ -3,7 +3,7 @@ namespace Store.Modules.CloudProduct.Dtos
/// <summary>
/// 创建收藏分组请求
/// </summary>
public class CreateUserFavoriteGroupRequest
public class UserFavoriteGroupRequest
{
/// <summary>
/// 用户名(为空时取当前登录用户)
@@ -0,0 +1,15 @@
namespace Store.Modules.CloudProduct.Dtos
{
/// <summary>将用户已收藏的商品移动到指定分组。</summary>
public class SetUserFavoriteGroupRequest
{
/// <summary>用户名称,为空时由 API 使用当前登录用户。</summary>
public string UserName { get; set; } = string.Empty;
/// <summary>商品编号集合。</summary>
public List<long> GoodsIds { get; set; } = new();
/// <summary>目标分组 ID。</summary>
public int GroupId { get; set; }
}
}
@@ -15,6 +15,6 @@ namespace Store.Modules.CloudProduct.Dtos
public string GroupName { get; set; } = string.Empty;
/// <summary>该分组下的收藏数量</summary>
public long FavoriteCount { get; set; }
//public long FavoriteCount { get; set; }
}
}
@@ -27,7 +27,7 @@ namespace Store.Modules.CloudProduct.Services
Task<int> RemoveFavoritesAsync(RemoveUserFavoritesRequest request);
/// <summary>创建收藏分组:创建成功返回 true,同名分组已存在返回 false</summary>
Task<bool> CreateGroupAsync(CreateUserFavoriteGroupRequest request);
Task<bool> CreateGroupAsync(UserFavoriteGroupRequest request);
/// <summary>查询用户的收藏分组(含默认分组)及分组下收藏数量</summary>
Task<List<UserFavoriteGroupDto>> GetGroupsAsync(string userName);
@@ -40,6 +40,8 @@ namespace Store.Modules.CloudProduct.Services
/// <summary>移除所有用户收藏索引并按数据库数据全量重建,返回重建的文档数</summary>
Task<long> RebuildSearchIndexAsync();
Task<bool> DelGroupAsync(UserFavoriteGroupRequest request);
Task<bool> SetFavoriteGroupAsync(SetUserFavoriteGroupRequest request);
}
internal class UserFavoritesService : IUserFavoritesService
@@ -298,7 +300,7 @@ namespace Store.Modules.CloudProduct.Services
/// <summary>
/// 创建收藏分组:创建成功返回 true,同一用户同名分组已存在返回 false。
/// </summary>
public async Task<bool> CreateGroupAsync(CreateUserFavoriteGroupRequest request)
public async Task<bool> CreateGroupAsync(UserFavoriteGroupRequest request)
{
if (request == null)
{
@@ -356,36 +358,160 @@ namespace Store.Modules.CloudProduct.Services
.OrderBy(x => x.Id)
.ToListAsync();
var countList = await _favoriteRepository.Select
.Where(x => x.UserName == userName)
.GroupBy(x => x.GroupId)
.ToListAsync(x => new { GroupId = x.Key, Count = x.Count() });
//var countList = await _favoriteRepository.Select
// .Where(x => x.UserName == userName)
// .GroupBy(x => x.GroupId)
// .ToListAsync(x => new { GroupId = x.Key, Count = x.Count() });
var countMap = countList.ToDictionary(x => x.GroupId, x => (long)x.Count);
//var countMap = countList.ToDictionary(x => x.GroupId, x => (long)x.Count);
var result = new List<UserFavoriteGroupDto>();
if (countMap.TryGetValue(0, out var defaultCount) && defaultCount > 0)
{
result.Add(new UserFavoriteGroupDto
{
Id = 0,
UserName = userName,
GroupName = DefaultGroupName,
FavoriteCount = defaultCount,
});
}
//if (countMap.TryGetValue(0, out var defaultCount) && defaultCount > 0)
//{
// result.Add(new UserFavoriteGroupDto
// {
// Id = 0,
// UserName = userName,
// GroupName = DefaultGroupName,
// FavoriteCount = defaultCount,
// });
//}
result.AddRange(groups.Select(x => new UserFavoriteGroupDto
{
Id = x.Id,
UserName = x.UserName,
GroupName = x.GroupName,
FavoriteCount = countMap.TryGetValue((int)x.Id, out var count) ? count : 0,
//FavoriteCount = countMap.TryGetValue((int)x.Id, out var count) ? count : 0,
}));
return result;
}
/// <summary>
/// 删除用户分组
/// </summary>
/// <param name="request"></param>
/// <returns></returns>
/// <exception cref="AppException"></exception>
public async Task<bool> DelGroupAsync(UserFavoriteGroupRequest request)
{
if (request == null)
{
throw new AppException("请求参数不能为空", ResultCode.ValidationError);
}
var userName = request.UserName?.Trim() ?? string.Empty;
if (string.IsNullOrWhiteSpace(userName))
{
throw new AppException("用户名不能为空", ResultCode.ValidationError);
}
var groupName = request.GroupName?.Trim() ?? string.Empty;
if (string.IsNullOrWhiteSpace(groupName))
{
throw new AppException("分组名不能为空", ResultCode.ValidationError);
}
if (groupName.Length > 255)
{
throw new AppException("分组名长度不能超过255个字符", ResultCode.ValidationError);
}
//_favoriteRepository.Select.Where(a=>a.Id)
var existing = await _groupRepository.Select
.Where(x => x.UserName == userName && x.GroupName == groupName)
.FirstAsync();
if (existing != null)
{
var favorites = await _favoriteRepository.Select
.Where(x => x.UserName == userName && x.GroupId == existing.Id)
.ToListAsync();
var goodsIds = favorites.Select(x => x.GoodsId).ToList();
var goodsMap = goodsIds.Count == 0
? new Dictionary<long, GoodsEntity>()
: (await _goodsRepository.Select.Where(x => goodsIds.Contains(x.GoodsId)).ToListAsync())
.ToDictionary(x => x.GoodsId);
await _favoriteRepository.Orm.Update<UserGoodsFavoriteEntity>()
.Set(a => a.GroupId, 0)
.Where(a => a.UserName == userName && a.GroupId == existing.Id)
.ExecuteAffrowsAsync();
foreach (var favorite in favorites)
{
favorite.GroupId = 0;
}
await _indexService.IndexDocumentsAsync(favorites
.Where(x => goodsMap.ContainsKey(x.GoodsId))
.Select(x => BuildDocument(x, goodsMap[x.GoodsId], DefaultGroupName)));
}
var rows = await _groupRepository.DeleteAsync(a => a.UserName == userName && a.GroupName == groupName);
if (rows != 1)
{
return false;
}
return true;
}
/// <summary>将用户已收藏的商品移动到其指定分组,并同步收藏索引。</summary>
public async Task<bool> SetFavoriteGroupAsync(SetUserFavoriteGroupRequest request)
{
if (request == null)
{
throw new AppException("请求参数不能为空", ResultCode.ValidationError);
}
var userName = request.UserName?.Trim() ?? string.Empty;
var goodsIds = request.GoodsIds?.Where(x => x > 0).Distinct().ToList() ?? new List<long>();
if (string.IsNullOrWhiteSpace(userName) || goodsIds.Count == 0 || request.GroupId < 0)
{
throw new AppException("用户、商品或分组参数无效", ResultCode.ValidationError);
}
var mainUser = await _queryService.GetMainUser(userName);
userName = mainUser.UserName;
await using var lease = await _indexLock.AcquireFavoritesAsync();
var favorites = await _favoriteRepository.Select
.Where(x => x.UserName == userName && goodsIds.Contains(x.GoodsId))
.ToListAsync();
if (request.GroupId > 0 && await _groupRepository.Select
.Where(x => x.Id == request.GroupId && x.UserName == userName)
.FirstAsync() == null)
{
throw new AppException("收藏分组不存在或不属于该用户", ResultCode.ValidationError);
}
var goodsList = await _goodsRepository.Select.Where(x => goodsIds.Contains(x.GoodsId)).ToListAsync();
if (goodsList.Count != goodsIds.Count)
{
throw new AppException("部分商品不存在", ResultCode.ValidationError);
}
var changedFavorites = favorites.Where(x => x.GroupId != request.GroupId).ToList();
if (changedFavorites.Count == 0)
{
return true;
}
await _favoriteRepository.Orm.Update<UserGoodsFavoriteEntity>()
.Set(x => x.GroupId, request.GroupId)
.Where(x => x.UserName == userName && goodsIds.Contains(x.GoodsId))
.ExecuteAffrowsAsync();
foreach (var favorite in changedFavorites)
{
favorite.GroupId = request.GroupId;
}
var goodsMap = goodsList.ToDictionary(x => x.GoodsId);
var groupName = await ResolveGroupNameAsync(userName, request.GroupId);
await _indexService.IndexDocumentsAsync(changedFavorites.Select(x => BuildDocument(x, goodsMap[x.GoodsId], groupName)));
return true;
}
/// <summary>
/// 按 GoodsIds 顺序返回每个商品是否已被该用户收藏(商品编号无效的返回 false)。
@@ -640,4 +766,4 @@ namespace Store.Modules.CloudProduct.Services
: UserFavoritesSortBy.CreatedTimeDesc;
}
}
}
}