HaniBlindBox/server/HoneyBox/src/HoneyBox.Core/Services/VipService.cs
2026-01-04 01:47:02 +08:00

193 lines
5.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using HoneyBox.Core.Interfaces;
using HoneyBox.Model.Data;
using HoneyBox.Model.Entities;
using HoneyBox.Model.Models.Vip;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
namespace HoneyBox.Core.Services;
/// <summary>
/// VIP服务实现
/// </summary>
public class VipService : IVipService
{
private readonly HoneyBoxDbContext _dbContext;
private readonly ILogger<VipService> _logger;
public VipService(HoneyBoxDbContext dbContext, ILogger<VipService> logger)
{
_dbContext = dbContext;
_logger = logger;
}
/// <inheritdoc />
public async Task<VipInfoResponse> GetVipInfoAsync(int userId)
{
// 获取用户信息
var user = await _dbContext.Users
.Where(u => u.Id == userId)
.Select(u => new { u.Id, u.Nickname, u.HeadImg, u.Vip })
.FirstOrDefaultAsync();
if (user == null)
{
throw new InvalidOperationException("用户不存在");
}
// 计算并更新VIP等级
var currentVip = await CalculateVipLevelAsync(userId, user.Vip);
// 获取所有VIP等级列表
var vipLevels = await _dbContext.VipLevels
.Where(v => v.DeletedAt == null)
.OrderBy(v => v.Level)
.ToListAsync();
// 获取最大VIP等级
var maxVipLevel = vipLevels.Any() ? vipLevels.Max(v => v.Level) : 0;
// 构建用户VIP信息
var userInfo = new VipUserInfoDto
{
Nickname = user.Nickname,
Headimg = user.HeadImg,
Vip = currentVip,
UpgradeMoney = "0",
LastVip = 0,
JinDu = 0,
Notice = string.Empty
};
// 如果未达到最高等级,计算升级进度
if (currentVip < maxVipLevel)
{
// 计算累计消费
var totalOrder = await GetTotalOrderConsumptionAsync(userId);
// 获取下一个VIP等级的条件
var nextLevel = vipLevels
.Where(v => v.Level > currentVip)
.OrderBy(v => v.Level)
.FirstOrDefault();
if (nextLevel != null)
{
var upgradeMoney = nextLevel.Number - totalOrder;
userInfo.UpgradeMoney = upgradeMoney > 0 ? upgradeMoney.ToString("F2") : "0";
userInfo.LastVip = nextLevel.Level;
// 计算进度百分比
if (totalOrder >= nextLevel.Number)
{
userInfo.JinDu = 100;
}
else if (nextLevel.Number > 0)
{
userInfo.JinDu = Math.Round((decimal)totalOrder / nextLevel.Number * 100, 2);
}
}
}
else
{
userInfo.UpgradeMoney = "0";
userInfo.LastVip = 0;
userInfo.JinDu = 100;
}
// 获取当前等级的提示信息
var currentLevelInfo = vipLevels.FirstOrDefault(v => v.Level == currentVip);
if (currentLevelInfo != null)
{
userInfo.Notice = currentLevelInfo.Title; // 使用标题作为提示信息
}
// 构建VIP等级列表DTO
var vipLevelDtos = vipLevels.Select(v => new VipLevelDto
{
Id = v.Id,
Level = v.Level,
Title = v.Title,
Imgurl = string.Empty, // SQL Server表中没有imgurl字段
Condition = v.Number,
Discount = 0, // SQL Server表中没有discount字段
Notice = v.Title
}).ToList();
return new VipInfoResponse
{
Userinfo = userInfo,
Data = vipLevelDtos
};
}
/// <inheritdoc />
public async Task<int> CalculateVipLevelAsync(int userId, int currentVip)
{
// 计算累计消费
var totalOrder = await GetTotalOrderConsumptionAsync(userId);
// 查找符合升级条件的最高等级
// 条件:等级 > 当前等级 且 升级条件 <= 累计消费
var newVipLevel = await _dbContext.VipLevels
.Where(v => v.DeletedAt == null)
.Where(v => v.Level > currentVip)
.Where(v => v.Number <= totalOrder)
.OrderByDescending(v => v.Level)
.FirstOrDefaultAsync();
if (newVipLevel != null)
{
// 更新用户VIP等级
var user = await _dbContext.Users.FindAsync(userId);
if (user != null)
{
user.Vip = (byte)newVipLevel.Level;
await _dbContext.SaveChangesAsync();
_logger.LogInformation("用户 {UserId} VIP等级从 {OldVip} 升级到 {NewVip}",
userId, currentVip, newVipLevel.Level);
}
return newVipLevel.Level;
}
return currentVip;
}
/// <inheritdoc />
public async Task<List<VipLevelDto>> GetVipLevelsAsync()
{
var vipLevels = await _dbContext.VipLevels
.Where(v => v.DeletedAt == null)
.OrderBy(v => v.Level)
.ToListAsync();
return vipLevels.Select(v => new VipLevelDto
{
Id = v.Id,
Level = v.Level,
Title = v.Title,
Imgurl = string.Empty,
Condition = v.Number,
Discount = 0,
Notice = v.Title
}).ToList();
}
/// <summary>
/// 获取用户累计订单消费金额
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>累计消费金额</returns>
private async Task<decimal> GetTotalOrderConsumptionAsync(int userId)
{
// 计算累计消费status=1已支付且 order_type<5
var totalOrder = await _dbContext.Orders
.Where(o => o.UserId == userId)
.Where(o => o.Status == 1)
.Where(o => o.OrderType < 5)
.SumAsync(o => o.OrderTotal);
return totalOrder;
}
}