From 7f0d57b311f06d39ec236a960f5a94090be89229 Mon Sep 17 00:00:00 2001 From: chenchun Date: Fri, 19 Dec 2025 14:16:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E6=BF=80=E6=B4=BB?= =?UTF-8?q?=E7=A0=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ActivationCodeCreateInput.cs | 26 +++++------ .../ActivationCodeCreateOutput.cs | 11 +++++ .../IServices/IActivationCodeService.cs | 2 +- .../Services/ActivationCodeService.cs | 33 +++++++++----- .../Enums/ActivationCodeGoodsTypeEnum.cs | 24 +++++++--- .../Managers/ActivationCodeManager.cs | 44 ++++++++++++------- Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs | 4 +- 7 files changed, 91 insertions(+), 53 deletions(-) diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/ActivationCode/ActivationCodeCreateInput.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/ActivationCode/ActivationCodeCreateInput.cs index dc9a4070..debb79ae 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/ActivationCode/ActivationCodeCreateInput.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/ActivationCode/ActivationCodeCreateInput.cs @@ -16,19 +16,15 @@ public class ActivationCodeCreateInput /// 数量 /// public int Count { get; set; } = 1; - - /// - /// 是否允许多人各使用一次 - /// - public bool IsReusable { get; set; } - - /// - /// 是否限制同类型只能兑换一次 - /// - public bool IsSameTypeOnce { get; set; } - - /// - /// 备注 - /// - public string? Remark { get; set; } +} + +/// +/// 批量生成激活码列表输入 +/// +public class ActivationCodeCreateListInput +{ + /// + /// 生成项列表 + /// + public List Items { get; set; } = new(); } diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/ActivationCode/ActivationCodeCreateOutput.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/ActivationCode/ActivationCodeCreateOutput.cs index 4f734b0a..82944399 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/ActivationCode/ActivationCodeCreateOutput.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/Dtos/ActivationCode/ActivationCodeCreateOutput.cs @@ -22,3 +22,14 @@ public class ActivationCodeCreateOutput /// public List Codes { get; set; } = new(); } + +/// +/// 批量生成激活码列表输出 +/// +public class ActivationCodeCreateListOutput +{ + /// + /// 分组输出 + /// + public List Items { get; set; } = new(); +} diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/IServices/IActivationCodeService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/IServices/IActivationCodeService.cs index 9f887a0d..7fb1f99b 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/IServices/IActivationCodeService.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application.Contracts/IServices/IActivationCodeService.cs @@ -11,7 +11,7 @@ public interface IActivationCodeService : IApplicationService /// /// 批量生成激活码 /// - Task CreateBatchAsync(ActivationCodeCreateInput input); + Task CreateBatchAsync(ActivationCodeCreateListInput input); /// /// 兑换激活码 diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/ActivationCodeService.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/ActivationCodeService.cs index 2ca825f5..009af46e 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/ActivationCodeService.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Application/Services/ActivationCodeService.cs @@ -35,20 +35,29 @@ public class ActivationCodeService : ApplicationService, IActivationCodeService /// [Authorize] [HttpPost("activationCode/Batch")] - public async Task CreateBatchAsync(ActivationCodeCreateInput input) + public async Task CreateBatchAsync(ActivationCodeCreateListInput input) { - var entities = await _activationCodeManager.CreateBatchAsync( - input.GoodsType, - input.Count, - input.IsReusable, - input.IsSameTypeOnce, - input.Remark); - - return new ActivationCodeCreateOutput + if (input.Items == null || input.Items.Count == 0) { - GoodsType = input.GoodsType, - Count = input.Count, - Codes = entities.Select(x => x.Code).ToList() + throw new UserFriendlyException("生成列表不能为空"); + } + + 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 }; } diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Enums/ActivationCodeGoodsTypeEnum.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Enums/ActivationCodeGoodsTypeEnum.cs index 7a07b11f..f0482223 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Enums/ActivationCodeGoodsTypeEnum.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain.Shared/Enums/ActivationCodeGoodsTypeEnum.cs @@ -13,6 +13,8 @@ public class ActivationCodeGoodsAttribute : Attribute public long TokenAmount { get; } public int VipMonths { get; } public bool IsCombo { get; } + public bool IsReusable { get; } + public bool IsSameTypeOnce { get; } public string DisplayName { get; } public string Content { get; } @@ -21,6 +23,8 @@ public class ActivationCodeGoodsAttribute : Attribute long tokenAmount, int vipMonths, bool isCombo, + bool isReusable, + bool isSameTypeOnce, string displayName, string content) { @@ -28,6 +32,8 @@ public class ActivationCodeGoodsAttribute : Attribute TokenAmount = tokenAmount; VipMonths = vipMonths; IsCombo = isCombo; + IsReusable = isReusable; + IsSameTypeOnce = isSameTypeOnce; DisplayName = displayName; Content = content; } @@ -41,37 +47,43 @@ public enum ActivationCodeGoodsTypeEnum /// /// 48.90【意心Ai会员1月+2000w 尊享Token】新人首单组合包(推荐) /// - [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, /// /// 1.00【10w 尊享Token】测试体验包 /// - [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, /// /// 9.90【1000w 尊享Token】意心会员首单回馈包 /// - [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, /// /// 22.90【意心Ai会员1月】特价包 /// - [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, /// /// 138.90【5000w 尊享Token】特价包 /// - [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, /// /// 198.90【1亿 尊享Token】特价包 /// - [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 } diff --git a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/ActivationCodeManager.cs b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/ActivationCodeManager.cs index 9b6cf322..4430b85e 100644 --- a/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/ActivationCodeManager.cs +++ b/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/ActivationCodeManager.cs @@ -34,27 +34,36 @@ public class ActivationCodeManager : DomainService _logger = logger; } - public async Task> CreateBatchAsync(ActivationCodeGoodsTypeEnum goodsType, - int count, bool isReusable, bool isSameTypeOnce, string? remark) + public async Task> CreateBatchAsync( + List<(ActivationCodeGoodsTypeEnum GoodsType, int Count)> items) { - if (count <= 0) - { - throw new UserFriendlyException("生成数量必须大于0"); - } - var entities = new List(); - for (var i = 0; i < count; i++) + foreach (var item in items) { - var code = await GenerateUniqueActivationCodeAsync(); - entities.Add(new ActivationCodeAggregateRoot + if (item.Count <= 0) { - Code = code, - GoodsType = goodsType, - IsReusable = isReusable, - IsSameTypeOnce = isSameTypeOnce, - UsedCount = 0, - Remark = remark - }); + throw new UserFriendlyException("生成数量必须大于0"); + } + + var goods = item.GoodsType.GetGoods(); + if (goods == null) + { + 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); @@ -161,4 +170,5 @@ public class ActivationCodeManager : DomainService return builder.ToString(); } + } diff --git a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs index 8d00c304..8de0dab9 100644 --- a/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs +++ b/Yi.Abp.Net8/src/Yi.Abp.Web/YiAbpWebModule.cs @@ -358,8 +358,8 @@ namespace Yi.Abp.Web var app = context.GetApplicationBuilder(); app.UseRouting(); - // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables(); - // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables(); + // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables(); + // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables(); // app.ApplicationServices.GetRequiredService().SqlSugarClient.CodeFirst.InitTables(); //跨域