using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models;
using HoneyBox.Model.Models.Goods;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace HoneyBox.Core.Services;
///
/// 收藏服务实现
///
public class CollectionService : ICollectionService
{
private readonly HoneyBoxDbContext _dbContext;
private readonly ILogger _logger;
private readonly IRedisService _redisService;
// 奖品统计ID范围 (与PHP保持一致)
private static readonly int[] ShangPrizeIdRange = { 10, 33 };
public CollectionService(
HoneyBoxDbContext dbContext,
ILogger logger,
IRedisService redisService)
{
_dbContext = dbContext;
_logger = logger;
_redisService = redisService;
}
///
public async Task ToggleCollectionAsync(int userId, int goodsId, int goodsNum)
{
// 1. 验证商品是否存在
var goods = await _dbContext.Goods
.Where(g => g.Id == goodsId)
.Select(g => new { g.Id, g.Stock, g.Status, g.Type })
.FirstOrDefaultAsync();
if (goods == null)
{
throw new InvalidOperationException("盒子不存在");
}
if (goods.Status != 1 && goods.Status != 3)
{
throw new InvalidOperationException("盒子已下架");
}
// 2. 检查是否已收藏
var existingCollection = await _dbContext.GoodsCollections
.Where(c => c.UserId == userId && c.GoodsId == goodsId && c.Num == goodsNum)
.FirstOrDefaultAsync();
bool result;
if (existingCollection != null)
{
// 已收藏,则取消收藏
_dbContext.GoodsCollections.Remove(existingCollection);
result = await _dbContext.SaveChangesAsync() > 0;
}
else
{
// 未收藏,则添加收藏
var collection = new GoodsCollection
{
UserId = userId,
GoodsId = goodsId,
Num = goodsNum,
Type = goods.Type,
CreatedAt = DateTime.Now
};
_dbContext.GoodsCollections.Add(collection);
result = await _dbContext.SaveChangesAsync() > 0;
}
// 3. 清除相关缓存
if (result)
{
try
{
await _redisService.DeleteAsync($"goods_detail_{goodsId}_{userId}");
await _redisService.DeleteAsync($"infinite_goodsdetail_{goodsId}_{userId}");
}
catch (Exception ex)
{
_logger.LogWarning(ex, "清除收藏相关缓存失败");
}
}
return result;
}
///
public async Task GetCollectionListAsync(int userId, int type, int page, int pageSize)
{
// 1. 构建查询
var query = _dbContext.GoodsCollections
.Where(c => c.UserId == userId);
// 按类型过滤
if (type > 0)
{
query = query.Where(c => c.Type == type);
}
// 2. 获取总数和分页数据
var totalCount = await query.CountAsync();
var lastPage = pageSize > 0 ? (int)Math.Ceiling((double)totalCount / pageSize) : 1;
var collections = await query
.OrderByDescending(c => c.Id)
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
if (!collections.Any())
{
return new CollectionListResponse
{
Data = new List(),
LastPage = lastPage
};
}
// 3. 获取商品信息
var goodsIds = collections.Select(c => c.GoodsId).Distinct().ToList();
var goodsDict = await _dbContext.Goods
.Where(g => goodsIds.Contains(g.Id))
.Select(g => new { g.Id, g.Title, g.Price, g.ImgUrl })
.ToDictionaryAsync(g => g.Id);
// 4. 获取库存信息 (仅对特定类型的商品)
// 类型 1, 3, 5, 6, 10, 11 需要查询库存
var stockTypes = new byte[] { 1, 3, 5, 6, 10, 11 };
var stockCollections = collections
.Where(c => stockTypes.Contains(c.Type))
.Select(c => new { c.GoodsId, c.Num })
.Distinct()
.ToList();
var stockDict = new Dictionary();
if (stockCollections.Any())
{
foreach (var sc in stockCollections)
{
var stockInfo = await _dbContext.GoodsItems
.Where(gi => gi.GoodsId == sc.GoodsId
&& gi.Num == sc.Num
&& gi.ShangId >= ShangPrizeIdRange[0]
&& gi.ShangId <= ShangPrizeIdRange[1])
.GroupBy(gi => 1)
.Select(g => new
{
Stock = g.Sum(x => x.Stock),
SurplusStock = g.Sum(x => x.SurplusStock)
})
.FirstOrDefaultAsync();
var key = $"{sc.GoodsId}_{sc.Num}";
stockDict[key] = stockInfo != null
? (stockInfo.Stock, stockInfo.SurplusStock)
: (0, 0);
}
}
// 5. 构建响应
var result = new List();
foreach (var collection in collections)
{
var dto = new CollectionDto
{
Id = collection.Id,
GoodsId = collection.GoodsId,
Type = collection.Type,
Num = collection.Num
};
// 填充商品信息
if (goodsDict.TryGetValue(collection.GoodsId, out var goodsInfo))
{
dto.GoodsTitle = goodsInfo.Title;
dto.GoodsPrice = goodsInfo.Price.ToString("0.##");
dto.ImgUrl = FormatImageUrl(goodsInfo.ImgUrl);
}
// 填充库存信息
if (stockTypes.Contains(collection.Type))
{
var stockKey = $"{collection.GoodsId}_{collection.Num}";
if (stockDict.TryGetValue(stockKey, out var stock))
{
dto.Stock = stock.Stock;
dto.SurplusStock = stock.SurplusStock;
}
}
result.Add(dto);
}
return new CollectionListResponse
{
Data = result,
LastPage = lastPage
};
}
///
public async Task DeleteCollectionAsync(int userId, int collectionId)
{
var collection = await _dbContext.GoodsCollections
.Where(c => c.UserId == userId && c.Id == collectionId)
.FirstOrDefaultAsync();
if (collection == null)
{
throw new InvalidOperationException("请求重复操作");
}
_dbContext.GoodsCollections.Remove(collection);
return await _dbContext.SaveChangesAsync() > 0;
}
///
public async Task IsCollectedAsync(int userId, int goodsId, int goodsNum)
{
if (userId <= 0)
{
return false;
}
return await _dbContext.GoodsCollections
.AnyAsync(c => c.UserId == userId && c.GoodsId == goodsId && c.Num == goodsNum);
}
///
public async Task CancelCollectionByGoodsIdAsync(int userId, int goodsId)
{
// 查找该用户对该商品的所有收藏记录
var collections = await _dbContext.GoodsCollections
.Where(c => c.UserId == userId && c.GoodsId == goodsId)
.ToListAsync();
if (!collections.Any())
{
throw new InvalidOperationException("未找到收藏记录");
}
_dbContext.GoodsCollections.RemoveRange(collections);
var result = await _dbContext.SaveChangesAsync() > 0;
// 清除相关缓存
if (result)
{
try
{
await _redisService.DeleteAsync($"goods_detail_{goodsId}_{userId}");
await _redisService.DeleteAsync($"infinite_goodsdetail_{goodsId}_{userId}");
}
catch (Exception ex)
{
_logger.LogWarning(ex, "清除收藏相关缓存失败");
}
}
return result;
}
///
/// 格式化图片URL
///
private static string FormatImageUrl(string? imgUrl)
{
if (string.IsNullOrEmpty(imgUrl))
{
return string.Empty;
}
// 如果已经是完整URL,直接返回
if (imgUrl.StartsWith("http://") || imgUrl.StartsWith("https://"))
{
return imgUrl;
}
// 否则直接返回 (可以从配置读取基础URL)
return imgUrl;
}
}