feat: 激活码与VIP充值支持按天计费
- 新增 VIP 天数概念,支持月数与天数组合计算过期时间 - 激活码商品新增 VipDays 配置,并新增 1 天会员试用组合包 - VIP 充值统一按天数计算(1 个月 = 31 天),兼容原有逻辑 - 激活码兑换时支持仅天数或天月组合的 VIP 充值
This commit is contained in:
@@ -25,11 +25,17 @@ public class RechargeCreateInput
|
|||||||
public string Content { get; set; } = string.Empty;
|
public string Content { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// VIP月数(为空或0表示永久VIP)
|
/// VIP月数(为空或0表示永久VIP,1个月按31天计算)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Range(0, int.MaxValue, ErrorMessage = "月数必须大于等于0")]
|
[Range(0, int.MaxValue, ErrorMessage = "月数必须大于等于0")]
|
||||||
public int? Months { get; set; }
|
public int? Months { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// VIP天数(为空或0表示不使用天数充值)
|
||||||
|
/// </summary>
|
||||||
|
[Range(0, int.MaxValue, ErrorMessage = "天数必须大于等于0")]
|
||||||
|
public int? Days { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 备注
|
/// 备注
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public class ActivationCodeService : ApplicationService, IActivationCodeService
|
|||||||
isCreateRechargeRecord: !goods.IsCombo);
|
isCreateRechargeRecord: !goods.IsCombo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (goods.VipMonths > 0)
|
if (goods.VipMonths > 0 || goods.VipDays > 0)
|
||||||
{
|
{
|
||||||
await _rechargeService.RechargeVipAsync(new RechargeCreateInput
|
await _rechargeService.RechargeVipAsync(new RechargeCreateInput
|
||||||
{
|
{
|
||||||
@@ -100,6 +100,7 @@ public class ActivationCodeService : ApplicationService, IActivationCodeService
|
|||||||
RechargeAmount = totalAmount,
|
RechargeAmount = totalAmount,
|
||||||
Content = packageName,
|
Content = packageName,
|
||||||
Months = goods.VipMonths,
|
Months = goods.VipMonths,
|
||||||
|
Days = goods.VipDays,
|
||||||
Remark = "激活码兑换",
|
Remark = "激活码兑换",
|
||||||
ContactInfo = null
|
ContactInfo = null
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -55,13 +55,24 @@ namespace Yi.Framework.AiHub.Application.Services
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="input">充值输入参数</param>
|
/// <param name="input">充值输入参数</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
[HttpPost("recharge/vip")]
|
[RemoteService(isEnabled:false)]
|
||||||
public async Task RechargeVipAsync(RechargeCreateInput input)
|
public async Task RechargeVipAsync(RechargeCreateInput input)
|
||||||
{
|
{
|
||||||
DateTime? expireDateTime = null;
|
DateTime? expireDateTime = null;
|
||||||
|
|
||||||
// 如果传入了月数,计算过期时间
|
// 计算总天数(1个月 = 31天)
|
||||||
|
int totalDays = 0;
|
||||||
if (input.Months.HasValue && input.Months.Value > 0)
|
if (input.Months.HasValue && input.Months.Value > 0)
|
||||||
|
{
|
||||||
|
totalDays += input.Months.Value * 31;
|
||||||
|
}
|
||||||
|
if (input.Days.HasValue && input.Days.Value > 0)
|
||||||
|
{
|
||||||
|
totalDays += input.Days.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有天数,计算过期时间
|
||||||
|
if (totalDays > 0)
|
||||||
{
|
{
|
||||||
// 直接查询该用户最大的过期时间
|
// 直接查询该用户最大的过期时间
|
||||||
var maxExpireTime = await _repository._DbQueryable
|
var maxExpireTime = await _repository._DbQueryable
|
||||||
@@ -75,9 +86,9 @@ namespace Yi.Framework.AiHub.Application.Services
|
|||||||
? maxExpireTime.Value
|
? maxExpireTime.Value
|
||||||
: DateTime.Now;
|
: DateTime.Now;
|
||||||
// 计算新的过期时间
|
// 计算新的过期时间
|
||||||
expireDateTime = baseDateTime.AddMonths(input.Months.Value);
|
expireDateTime = baseDateTime.AddDays(totalDays);
|
||||||
}
|
}
|
||||||
// 如果月数为空或0,表示永久VIP,ExpireDateTime保持为null
|
// 如果总天数为0,表示永久VIP,ExpireDateTime保持为null
|
||||||
|
|
||||||
// 创建充值记录
|
// 创建充值记录
|
||||||
var rechargeRecord = new AiRechargeAggregateRoot
|
var rechargeRecord = new AiRechargeAggregateRoot
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ public class ActivationCodeGoodsAttribute : Attribute
|
|||||||
public decimal Price { get; }
|
public decimal Price { get; }
|
||||||
public long TokenAmount { get; }
|
public long TokenAmount { get; }
|
||||||
public int VipMonths { get; }
|
public int VipMonths { get; }
|
||||||
|
public int VipDays { get; }
|
||||||
public bool IsCombo { get; }
|
public bool IsCombo { get; }
|
||||||
public bool IsReusable { get; }
|
public bool IsReusable { get; }
|
||||||
public bool IsSameTypeOnce { get; }
|
public bool IsSameTypeOnce { get; }
|
||||||
@@ -26,11 +27,13 @@ public class ActivationCodeGoodsAttribute : Attribute
|
|||||||
bool isReusable,
|
bool isReusable,
|
||||||
bool isSameTypeOnce,
|
bool isSameTypeOnce,
|
||||||
string displayName,
|
string displayName,
|
||||||
string content)
|
string content,
|
||||||
|
int vipDays = 0)
|
||||||
{
|
{
|
||||||
Price = (decimal)price;
|
Price = (decimal)price;
|
||||||
TokenAmount = tokenAmount;
|
TokenAmount = tokenAmount;
|
||||||
VipMonths = vipMonths;
|
VipMonths = vipMonths;
|
||||||
|
VipDays = vipDays;
|
||||||
IsCombo = isCombo;
|
IsCombo = isCombo;
|
||||||
IsReusable = isReusable;
|
IsReusable = isReusable;
|
||||||
IsSameTypeOnce = isSameTypeOnce;
|
IsSameTypeOnce = isSameTypeOnce;
|
||||||
@@ -86,7 +89,12 @@ public enum ActivationCodeGoodsTypeEnum
|
|||||||
isSameTypeOnce: false, displayName: "1亿 尊享Token", content: "特价包")]
|
isSameTypeOnce: false, displayName: "1亿 尊享Token", content: "特价包")]
|
||||||
Premium1Yi = 6,
|
Premium1Yi = 6,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 1【意心Ai会员1天+50w 尊享Token】新人试用首单组合包
|
||||||
|
/// </summary>
|
||||||
|
[ActivationCodeGoods(price: 1, tokenAmount: 500000, vipMonths: 0, vipDays: 1, isCombo: true, isReusable: false,
|
||||||
|
isSameTypeOnce: true, displayName: "意心Ai会员1天+50w 尊享Token", content: "新人首单组合包")]
|
||||||
|
Vip1DayTest = 7,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 0【10w 尊享Token】免费包
|
/// 0【10w 尊享Token】免费包
|
||||||
|
|||||||
Reference in New Issue
Block a user