云商品 增加分组
This commit is contained in:
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。
|
/// 创建收藏分组:创建成功返回 true,同名分组已存在返回 false。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<bool> CreateGroup(CreateUserFavoriteGroupRequest request)
|
public async Task<bool> CreateGroup(UserFavoriteGroupRequest request)
|
||||||
{
|
{
|
||||||
if (request == null)
|
if (request == null)
|
||||||
{
|
{
|
||||||
@@ -121,7 +121,7 @@ namespace Store.Modules.CloudProduct.Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 查询用户的收藏分组(含默认分组)及分组下收藏数量。
|
/// 查询用户的收藏分组(含默认分组)及分组下收藏数量。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpGet]
|
[HttpPost]
|
||||||
public async Task<List<UserFavoriteGroupDto>> GetGroups(string? userName = null)
|
public async Task<List<UserFavoriteGroupDto>> GetGroups(string? userName = null)
|
||||||
{
|
{
|
||||||
var resolved = ResolveUserName(userName);
|
var resolved = ResolveUserName(userName);
|
||||||
@@ -153,6 +153,41 @@ namespace Store.Modules.CloudProduct.Controllers
|
|||||||
|
|
||||||
return await _favoritesService.GetFavoriteStatusAsync(request);
|
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>
|
/// <summary>
|
||||||
/// 检索用户收藏的商品(标题、销量、价格、类目、分组)。
|
/// 检索用户收藏的商品(标题、销量、价格、类目、分组)。
|
||||||
@@ -274,4 +309,4 @@ namespace Store.Modules.CloudProduct.Controllers
|
|||||||
: userName.Trim();
|
: userName.Trim();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,7 +3,7 @@ namespace Store.Modules.CloudProduct.Dtos
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建收藏分组请求
|
/// 创建收藏分组请求
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class CreateUserFavoriteGroupRequest
|
public class UserFavoriteGroupRequest
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <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;
|
public string GroupName { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>该分组下的收藏数量</summary>
|
/// <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);
|
Task<int> RemoveFavoritesAsync(RemoveUserFavoritesRequest request);
|
||||||
|
|
||||||
/// <summary>创建收藏分组:创建成功返回 true,同名分组已存在返回 false</summary>
|
/// <summary>创建收藏分组:创建成功返回 true,同名分组已存在返回 false</summary>
|
||||||
Task<bool> CreateGroupAsync(CreateUserFavoriteGroupRequest request);
|
Task<bool> CreateGroupAsync(UserFavoriteGroupRequest request);
|
||||||
|
|
||||||
/// <summary>查询用户的收藏分组(含默认分组)及分组下收藏数量</summary>
|
/// <summary>查询用户的收藏分组(含默认分组)及分组下收藏数量</summary>
|
||||||
Task<List<UserFavoriteGroupDto>> GetGroupsAsync(string userName);
|
Task<List<UserFavoriteGroupDto>> GetGroupsAsync(string userName);
|
||||||
@@ -40,6 +40,8 @@ namespace Store.Modules.CloudProduct.Services
|
|||||||
|
|
||||||
/// <summary>移除所有用户收藏索引并按数据库数据全量重建,返回重建的文档数</summary>
|
/// <summary>移除所有用户收藏索引并按数据库数据全量重建,返回重建的文档数</summary>
|
||||||
Task<long> RebuildSearchIndexAsync();
|
Task<long> RebuildSearchIndexAsync();
|
||||||
|
Task<bool> DelGroupAsync(UserFavoriteGroupRequest request);
|
||||||
|
Task<bool> SetFavoriteGroupAsync(SetUserFavoriteGroupRequest request);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class UserFavoritesService : IUserFavoritesService
|
internal class UserFavoritesService : IUserFavoritesService
|
||||||
@@ -298,7 +300,7 @@ namespace Store.Modules.CloudProduct.Services
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建收藏分组:创建成功返回 true,同一用户同名分组已存在返回 false。
|
/// 创建收藏分组:创建成功返回 true,同一用户同名分组已存在返回 false。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<bool> CreateGroupAsync(CreateUserFavoriteGroupRequest request)
|
public async Task<bool> CreateGroupAsync(UserFavoriteGroupRequest request)
|
||||||
{
|
{
|
||||||
if (request == null)
|
if (request == null)
|
||||||
{
|
{
|
||||||
@@ -356,36 +358,160 @@ namespace Store.Modules.CloudProduct.Services
|
|||||||
.OrderBy(x => x.Id)
|
.OrderBy(x => x.Id)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var countList = await _favoriteRepository.Select
|
//var countList = await _favoriteRepository.Select
|
||||||
.Where(x => x.UserName == userName)
|
// .Where(x => x.UserName == userName)
|
||||||
.GroupBy(x => x.GroupId)
|
// .GroupBy(x => x.GroupId)
|
||||||
.ToListAsync(x => new { GroupId = x.Key, Count = x.Count() });
|
// .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>();
|
var result = new List<UserFavoriteGroupDto>();
|
||||||
|
|
||||||
if (countMap.TryGetValue(0, out var defaultCount) && defaultCount > 0)
|
//if (countMap.TryGetValue(0, out var defaultCount) && defaultCount > 0)
|
||||||
{
|
//{
|
||||||
result.Add(new UserFavoriteGroupDto
|
// result.Add(new UserFavoriteGroupDto
|
||||||
{
|
// {
|
||||||
Id = 0,
|
// Id = 0,
|
||||||
UserName = userName,
|
// UserName = userName,
|
||||||
GroupName = DefaultGroupName,
|
// GroupName = DefaultGroupName,
|
||||||
FavoriteCount = defaultCount,
|
// FavoriteCount = defaultCount,
|
||||||
});
|
// });
|
||||||
}
|
//}
|
||||||
|
|
||||||
result.AddRange(groups.Select(x => new UserFavoriteGroupDto
|
result.AddRange(groups.Select(x => new UserFavoriteGroupDto
|
||||||
{
|
{
|
||||||
Id = x.Id,
|
Id = x.Id,
|
||||||
UserName = x.UserName,
|
UserName = x.UserName,
|
||||||
GroupName = x.GroupName,
|
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;
|
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>
|
/// <summary>
|
||||||
/// 按 GoodsIds 顺序返回每个商品是否已被该用户收藏(商品编号无效的返回 false)。
|
/// 按 GoodsIds 顺序返回每个商品是否已被该用户收藏(商品编号无效的返回 false)。
|
||||||
@@ -640,4 +766,4 @@ namespace Store.Modules.CloudProduct.Services
|
|||||||
: UserFavoritesSortBy.CreatedTimeDesc;
|
: UserFavoritesSortBy.CreatedTimeDesc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user