feat: 完成激活码功能

This commit is contained in:
chenchun
2025-12-19 14:16:59 +08:00
parent 75c208dafc
commit 7f0d57b311
7 changed files with 91 additions and 53 deletions

View File

@@ -16,19 +16,15 @@ public class ActivationCodeCreateInput
/// 数量 /// 数量
/// </summary> /// </summary>
public int Count { get; set; } = 1; public int Count { get; set; } = 1;
}
/// <summary>
/// 是否允许多人各使用一次 /// <summary>
/// </summary> /// 批量生成激活码列表输入
public bool IsReusable { get; set; } /// </summary>
public class ActivationCodeCreateListInput
/// <summary> {
/// 是否限制同类型只能兑换一次 /// <summary>
/// </summary> /// 生成项列表
public bool IsSameTypeOnce { get; set; } /// </summary>
public List<ActivationCodeCreateInput> Items { get; set; } = new();
/// <summary>
/// 备注
/// </summary>
public string? Remark { get; set; }
} }

View File

@@ -22,3 +22,14 @@ public class ActivationCodeCreateOutput
/// </summary> /// </summary>
public List<string> Codes { get; set; } = new(); public List<string> Codes { get; set; } = new();
} }
/// <summary>
/// 批量生成激活码列表输出
/// </summary>
public class ActivationCodeCreateListOutput
{
/// <summary>
/// 分组输出
/// </summary>
public List<ActivationCodeCreateOutput> Items { get; set; } = new();
}

View File

@@ -11,7 +11,7 @@ public interface IActivationCodeService : IApplicationService
/// <summary> /// <summary>
/// 批量生成激活码 /// 批量生成激活码
/// </summary> /// </summary>
Task<ActivationCodeCreateOutput> CreateBatchAsync(ActivationCodeCreateInput input); Task<ActivationCodeCreateListOutput> CreateBatchAsync(ActivationCodeCreateListInput input);
/// <summary> /// <summary>
/// 兑换激活码 /// 兑换激活码

View File

@@ -35,20 +35,29 @@ public class ActivationCodeService : ApplicationService, IActivationCodeService
/// </summary> /// </summary>
[Authorize] [Authorize]
[HttpPost("activationCode/Batch")] [HttpPost("activationCode/Batch")]
public async Task<ActivationCodeCreateOutput> CreateBatchAsync(ActivationCodeCreateInput input) public async Task<ActivationCodeCreateListOutput> CreateBatchAsync(ActivationCodeCreateListInput input)
{ {
var entities = await _activationCodeManager.CreateBatchAsync( if (input.Items == null || input.Items.Count == 0)
input.GoodsType,
input.Count,
input.IsReusable,
input.IsSameTypeOnce,
input.Remark);
return new ActivationCodeCreateOutput
{ {
GoodsType = input.GoodsType, throw new UserFriendlyException("生成列表不能为空");
Count = input.Count, }
Codes = entities.Select(x => x.Code).ToList()
var entities = await _activationCodeManager.CreateBatchAsync(
input.Items.Select(x => (x.GoodsType, x.Count)).ToList());
var outputs = entities
.GroupBy(x => x.GoodsType)
.Select(group => new ActivationCodeCreateOutput
{
GoodsType = group.Key,
Count = group.Count(),
Codes = group.Select(x => x.Code).ToList()
})
.ToList();
return new ActivationCodeCreateListOutput
{
Items = outputs
}; };
} }

View File

@@ -13,6 +13,8 @@ public class ActivationCodeGoodsAttribute : Attribute
public long TokenAmount { get; } public long TokenAmount { get; }
public int VipMonths { get; } public int VipMonths { get; }
public bool IsCombo { get; } public bool IsCombo { get; }
public bool IsReusable { get; }
public bool IsSameTypeOnce { get; }
public string DisplayName { get; } public string DisplayName { get; }
public string Content { get; } public string Content { get; }
@@ -21,6 +23,8 @@ public class ActivationCodeGoodsAttribute : Attribute
long tokenAmount, long tokenAmount,
int vipMonths, int vipMonths,
bool isCombo, bool isCombo,
bool isReusable,
bool isSameTypeOnce,
string displayName, string displayName,
string content) string content)
{ {
@@ -28,6 +32,8 @@ public class ActivationCodeGoodsAttribute : Attribute
TokenAmount = tokenAmount; TokenAmount = tokenAmount;
VipMonths = vipMonths; VipMonths = vipMonths;
IsCombo = isCombo; IsCombo = isCombo;
IsReusable = isReusable;
IsSameTypeOnce = isSameTypeOnce;
DisplayName = displayName; DisplayName = displayName;
Content = content; Content = content;
} }
@@ -41,37 +47,43 @@ public enum ActivationCodeGoodsTypeEnum
/// <summary> /// <summary>
/// 48.90【意心Ai会员1月+2000w 尊享Token】新人首单组合包推荐 /// 48.90【意心Ai会员1月+2000w 尊享Token】新人首单组合包推荐
/// </summary> /// </summary>
[ActivationCodeGoods(48.90, 20000000, 1, true, "意心Ai会员1月+2000w 尊享Token", "新人首单组合包(推荐)")] [ActivationCodeGoods(price: 48.90, tokenAmount: 20000000, vipMonths: 1, isCombo: true, isReusable: false,
isSameTypeOnce: true, displayName: "意心Ai会员1月+2000w 尊享Token", content: "新人首单组合包(推荐)")]
Vip1MonthPlus2000W = 1, Vip1MonthPlus2000W = 1,
/// <summary> /// <summary>
/// 1.00【10w 尊享Token】测试体验包 /// 1.00【10w 尊享Token】测试体验包
/// </summary> /// </summary>
[ActivationCodeGoods(1.00, 100000, 0, false, "10w 尊享Token", "测试体验包")] [ActivationCodeGoods(price: 1.00, tokenAmount: 100000, vipMonths: 0, isCombo: false, isReusable: false,
isSameTypeOnce: false, displayName: "10w 尊享Token", content: "测试体验包")]
Premium10W = 2, Premium10W = 2,
/// <summary> /// <summary>
/// 9.90【1000w 尊享Token】意心会员首单回馈包 /// 9.90【1000w 尊享Token】意心会员首单回馈包
/// </summary> /// </summary>
[ActivationCodeGoods(9.90, 10000000, 0, false, "1000w 尊享Token", "意心会员首单回馈包")] [ActivationCodeGoods(price: 9.90, tokenAmount: 10000000, vipMonths: 0, isCombo: false, isReusable: false,
isSameTypeOnce: true, displayName: "1000w 尊享Token", content: "意心会员首单回馈包")]
Premium1000W = 3, Premium1000W = 3,
/// <summary> /// <summary>
/// 22.90【意心Ai会员1月】特价包 /// 22.90【意心Ai会员1月】特价包
/// </summary> /// </summary>
[ActivationCodeGoods(22.90, 0, 1, false, "意心Ai会员1月", "特价包")] [ActivationCodeGoods(price: 22.90, tokenAmount: 0, vipMonths: 1, isCombo: false, isReusable: false,
isSameTypeOnce: false, displayName: "意心Ai会员1月", content: "特价包")]
Vip1Month = 4, Vip1Month = 4,
/// <summary> /// <summary>
/// 138.90【5000w 尊享Token】特价包 /// 138.90【5000w 尊享Token】特价包
/// </summary> /// </summary>
[ActivationCodeGoods(138.90, 50000000, 0, false, "5000w 尊享Token", "特价包")] [ActivationCodeGoods(price: 138.90, tokenAmount: 50000000, vipMonths: 0, isCombo: false, isReusable: false,
isSameTypeOnce: false, displayName: "5000w 尊享Token", content: "特价包")]
Premium5000W = 5, Premium5000W = 5,
/// <summary> /// <summary>
/// 198.90【1亿 尊享Token】特价包 /// 198.90【1亿 尊享Token】特价包
/// </summary> /// </summary>
[ActivationCodeGoods(198.90, 100000000, 0, false, "1亿 尊享Token", "特价包")] [ActivationCodeGoods(price: 198.90, tokenAmount: 100000000, vipMonths: 0, isCombo: false, isReusable: false,
isSameTypeOnce: false, displayName: "1亿 尊享Token", content: "特价包")]
Premium1Yi = 6 Premium1Yi = 6
} }

View File

@@ -34,27 +34,36 @@ public class ActivationCodeManager : DomainService
_logger = logger; _logger = logger;
} }
public async Task<List<ActivationCodeAggregateRoot>> CreateBatchAsync(ActivationCodeGoodsTypeEnum goodsType, public async Task<List<ActivationCodeAggregateRoot>> CreateBatchAsync(
int count, bool isReusable, bool isSameTypeOnce, string? remark) List<(ActivationCodeGoodsTypeEnum GoodsType, int Count)> items)
{ {
if (count <= 0)
{
throw new UserFriendlyException("生成数量必须大于0");
}
var entities = new List<ActivationCodeAggregateRoot>(); var entities = new List<ActivationCodeAggregateRoot>();
for (var i = 0; i < count; i++) foreach (var item in items)
{ {
var code = await GenerateUniqueActivationCodeAsync(); if (item.Count <= 0)
entities.Add(new ActivationCodeAggregateRoot
{ {
Code = code, throw new UserFriendlyException("生成数量必须大于0");
GoodsType = goodsType, }
IsReusable = isReusable,
IsSameTypeOnce = isSameTypeOnce, var goods = item.GoodsType.GetGoods();
UsedCount = 0, if (goods == null)
Remark = remark {
}); throw new UserFriendlyException("激活码商品类型无效");
}
for (var i = 0; i < item.Count; i++)
{
var code = await GenerateUniqueActivationCodeAsync();
entities.Add(new ActivationCodeAggregateRoot
{
Code = code,
GoodsType = item.GoodsType,
IsReusable = goods.IsReusable,
IsSameTypeOnce = goods.IsSameTypeOnce,
UsedCount = 0,
Remark = null
});
}
} }
await _activationCodeRepository.InsertRangeAsync(entities); await _activationCodeRepository.InsertRangeAsync(entities);
@@ -161,4 +170,5 @@ public class ActivationCodeManager : DomainService
return builder.ToString(); return builder.ToString();
} }
} }

View File

@@ -358,8 +358,8 @@ namespace Yi.Abp.Web
var app = context.GetApplicationBuilder(); var app = context.GetApplicationBuilder();
app.UseRouting(); app.UseRouting();
// app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<AiModelEntity>(); // app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<ActivationCodeAggregateRoot>();
// app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<TokenAggregateRoot>(); // app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<ActivationCodeRecordAggregateRoot>();
// app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<UsageStatisticsAggregateRoot>(); // app.ApplicationServices.GetRequiredService<ISqlSugarDbContext>().SqlSugarClient.CodeFirst.InitTables<UsageStatisticsAggregateRoot>();
//跨域 //跨域