diff --git a/src/CloudGaming/Api/CloudGaming.Api/.versionDescribe b/src/CloudGaming/Api/CloudGaming.Api/.versionDescribe new file mode 100644 index 0000000..930e866 --- /dev/null +++ b/src/CloudGaming/Api/CloudGaming.Api/.versionDescribe @@ -0,0 +1,5 @@ +### 20241119 +1. 增加兑换码接口 +2. 增加首页排行榜接口 +3. 增加游玩历史接口 +4. 增加游戏时长接 diff --git a/src/CloudGaming/Api/CloudGaming.Api/CloudGaming.Api.csproj b/src/CloudGaming/Api/CloudGaming.Api/CloudGaming.Api.csproj index 687f39b..1f6d4e5 100644 --- a/src/CloudGaming/Api/CloudGaming.Api/CloudGaming.Api.csproj +++ b/src/CloudGaming/Api/CloudGaming.Api/CloudGaming.Api.csproj @@ -40,4 +40,10 @@ + + + Always + + + diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/GameController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/GameController.cs index b1743b0..c319b0b 100644 --- a/src/CloudGaming/Api/CloudGaming.Api/Controllers/GameController.cs +++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/GameController.cs @@ -121,5 +121,30 @@ namespace CloudGaming.Api.Controllers } + /// + /// 游玩历史 + /// + /// + [HttpGet] + [Authorize] + public async Task> GetGameHistory() + { + GameBLL gamebll = new GameBLL(this.ServiceProvider); + return await gamebll.GetGameHistory(); + } + + /// + /// 游戏时长排行榜,十分钟更新一次 + /// + /// + [HttpGet] + [RedisCache(10, 0)] + public async Task GamePlayTimeList([FromQuery] string gameId) + { + GameBLL gamebll = new GameBLL(this.ServiceProvider); + return await gamebll.GamePlayTimeList(gameId); + } + + } } diff --git a/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs b/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs index d158d86..c22d5b8 100644 --- a/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs +++ b/src/CloudGaming/Api/CloudGaming.Api/Controllers/HomeController.cs @@ -1,7 +1,9 @@ using CloudGaming.Api.Base; using CloudGaming.Code.Epg; +using CloudGaming.Code.Game; using CloudGaming.Code.MiddlewareExtend; using CloudGaming.DtoModel.Epg; +using CloudGaming.DtoModel.Game; using Microsoft.AspNetCore.JsonPatch.Internal; using Microsoft.AspNetCore.Mvc; @@ -29,4 +31,15 @@ public class HomeController : CloudGamingControllerBase return await epgBLL.GetHomeInfo(); } + /// + /// 首页排行榜 + /// + /// + [HttpGet] + [RedisCache(10, 0)] + public async Task> GetGameRankingList([FromQuery] string gameId) + { + GameBLL gamebll = new GameBLL(this.ServiceProvider); + return await gamebll.GetGameRankingList(); + } } diff --git a/src/CloudGaming/Api/CloudGaming.Api/Program.cs b/src/CloudGaming/Api/CloudGaming.Api/Program.cs index f87a23a..56d215c 100644 --- a/src/CloudGaming/Api/CloudGaming.Api/Program.cs +++ b/src/CloudGaming/Api/CloudGaming.Api/Program.cs @@ -99,8 +99,28 @@ builder.Services.AddSwaggerGen(c => { {securityScheme, Array.Empty()} }); + string description = ""; + //.versionDescribe + var filePath = Path.GetFullPath(".versionDescribe"); + if (File.Exists(filePath)) + { + description= File.ReadAllText(filePath); + //string[] lines = File.ReadAllLines(filePath); + //foreach (string line in lines) + //{ + // if (line.Contains("##")) + // { + // description += $"**{line}**"; // 使用Markdown的加粗 - c.SwaggerDoc("v1", new OpenApiInfo { Title = "蒸汽云游戏", Version = "0.1.7", Description = "" }); + // } + // else + // { + // description += line + "
"; + // } + //} + //description = $"{description}"; + } + c.SwaggerDoc("v1", new OpenApiInfo { Title = "蒸汽云游戏", Version = "0.1.7", Description = description }); foreach (var assemblies in AppDomain.CurrentDomain.GetAssemblies()) { // 添加 XML 注释文件路径 @@ -162,6 +182,8 @@ app.UseSwaggerUI(c => c.EnableFilter("true"); //c.RoutePrefix = string.Empty; c.SwaggerEndpoint("/swagger/v1/swagger.json", "蒸汽云游戏 API V1"); + // 使用自定义CSS + c.InjectStylesheet("/custom.css"); }); app.UseHttpsRedirection(); diff --git a/src/CloudGaming/Api/CloudGaming.Api/wwwroot/custom.css b/src/CloudGaming/Api/CloudGaming.Api/wwwroot/custom.css new file mode 100644 index 0000000..1f6b4fe --- /dev/null +++ b/src/CloudGaming/Api/CloudGaming.Api/wwwroot/custom.css @@ -0,0 +1,5 @@ + +.renderedMarkdown { + max-height: 300px; + overflow: auto; +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/Aliyun/AlipayPayment.cs b/src/CloudGaming/Code/CloudGaming.Code/Aliyun/AlipayPayment.cs index 8436707..db56ac1 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Aliyun/AlipayPayment.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Aliyun/AlipayPayment.cs @@ -16,6 +16,11 @@ using System.Threading.Tasks; namespace CloudGaming.Code.Aliyun; +/// +/// 支付宝支付 +/// +/// +/// public class AlipayPayment(AppConfig appConfig, int userId) : IPayment { public Task<(string orderId, string order)> CreateOrder(int productId, string productName, decimal price, params object[] args) diff --git a/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs b/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs index ea1de40..966fdef 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Cache/CloudGamingCache.cs @@ -3,6 +3,7 @@ using AutoMapper; using CloudGaming.Code.Cache.Special; using CloudGaming.DtoModel.Game; using CloudGaming.DtoModel.Mall; +using CloudGaming.DtoModel.RedemptionCode; using CloudGaming.DtoModel.SevenSign; using HuanMeng.DotNetCore.CacheHelper; @@ -123,6 +124,7 @@ namespace CloudGaming.Code.Cache } } #endregion + /// /// /// @@ -187,6 +189,41 @@ namespace CloudGaming.Code.Cache } #endregion + #region 兑换码 + /// + /// + /// + private RedemptionCodeEntityCache redemptionCodeEntityCache; + + /// + /// 兑换码缓存 + /// + public RedemptionCodeEntityCache RedemptionCodeEntityCache + { + get + { + if (redemptionCodeEntityCache == null) + { + redemptionCodeEntityCache = new RedemptionCodeEntityCache(_gamingBase.Dao, _gamingBase.RedisCache, _gamingBase.Mapper); + } + return redemptionCodeEntityCache; + } + } + + /// + /// 兑换码列表 + /// + public List RedemptionCodeList + { + get + { + return RedemptionCodeEntityCache.DataList ?? new List(); + } + } + #endregion + + + #region 首页缓存表 diff --git a/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/RedemptionCodeEntityCache.cs b/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/RedemptionCodeEntityCache.cs new file mode 100644 index 0000000..6561337 --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/Cache/Special/RedemptionCodeEntityCache.cs @@ -0,0 +1,51 @@ +using AutoMapper; + +using CloudGaming.Code.DataAccess; +using CloudGaming.DtoModel.RedemptionCode; +using CloudGaming.DtoModel.SevenSign; + +using HuanMeng.DotNetCore.CacheHelper; + +using StackExchange.Redis; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.Cache.Special; + +/// +/// 兑换码 +/// +/// +/// +/// +public class RedemptionCodeEntityCache(DAO dao, IDatabase database, IMapper mapper) : RedisDataEntityCache(database, GameEntityCache.GameEntityCacheLock, 60 * 60 * 1) +{ + public override List GetDataList() + { + var list = dao.DaoPhone.Context.T_RedemptionCode.AsNoTracking().Where(it => it.IsActive).ToList(); + if (list == null) + { + return new List(); + } + + var sevenDayCache = mapper.Map>(list); + var rewards = dao.DaoPhone.Context.T_RewardConfig.Where(it => it.ParentNodeType == (int)RewardConfigType.兑换码).AsNoTracking().ToList(); + sevenDayCache.ForEach(item => + { + //获取所有奖励 + var _rewards = rewards.Where(it => it.ParentNodeId == item.Id).ToList(); + item.RewardConfigs = _rewards; + if (item.RewardConfigs == null) + { + item.RewardConfigs = new List(); + } + }); + return sevenDayCache; + } + + public override string key => "App:RedemptionCode"; +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/Game/GameBLL.cs b/src/CloudGaming/Code/CloudGaming.Code/Game/GameBLL.cs index 0808612..d77fc2f 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Game/GameBLL.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Game/GameBLL.cs @@ -2,6 +2,8 @@ using CloudGaming.Code.Account; using CloudGaming.Code.Cache; using CloudGaming.DtoModel.Game; +using Microsoft.IdentityModel.Tokens; + using System; using System.Collections.Generic; using System.Linq; @@ -10,6 +12,7 @@ using System.Text; using System.Threading.Tasks; using static CloudGaming.DtoModel.Epg.EpgEnum; +using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.CreateMarketingMemberCardActivityRequest.Types.AwardSendPeriod.Types.AwardSendDayTime.Types; namespace CloudGaming.Code.Game { @@ -198,7 +201,7 @@ namespace CloudGaming.Code.Game } /// - /// + /// 游戏收藏 /// /// /// @@ -234,5 +237,146 @@ namespace CloudGaming.Code.Game await this.SaveUserInfoCacheChangesAsync(); return new BaseResponse(ResonseCode.Success, "收藏成功"); } + + /// + /// 游玩历史 + /// + /// + public async Task> GetGameHistory() + { + if (_UserId == 0) + { + return new List(); + } + List gameHistoryListDtos = new List(); + var list = await Dao.DaoPhone.Context.T_User_GameList.Where(it => it.UserId == _UserId).OrderByDescending(it => it.UpdateTime).ToListAsync(); + var gameList = Cache.GameEntityCache; + list?.ForEach(it => + { + if (string.IsNullOrEmpty(it.GameId)) + { + return; + } + var gameinfo = gameList[it.GameId]; + if (gameinfo != null) + { + gameHistoryListDtos.Add(new GameHistoryListDto(gameinfo, it.PlayTime)); + } + }); + return gameHistoryListDtos; + } + + /// + /// 游戏时长排行榜 + /// + /// + /// + public async Task GamePlayTimeList(string gameId) + { + GamePlayTimeInfoDto gamePlayTimeInfoDto = new GamePlayTimeInfoDto(); + List gamePlayTimeDtos = new List(); + //游玩记录 + var list = await Dao.DaoPhone.Context.T_User_GameList.Where(it => it.GameId == gameId).OrderByDescending(it => it.PlayTime).Take(50).ToListAsync(); + #region 排行榜数据 + var topList = list.Take(10).ToList(); + var userIds = topList.Select(it => it.UserId).ToList(); + var userInfo = await Dao.DaoUser.Context.T_User.Where(it => userIds.Contains(it.Id)).Select(it => new { it.UserName, it.Id, it.UserIconUrl }).ToListAsync(); + var index = 1; + topList.ForEach(it => + { + var user = userInfo.FirstOrDefault(item => item.Id == it.UserId); + GamePlayTimeDto gamePlayTimeDto = new GamePlayTimeDto() + { + PlayTime = $"{(it.PlayTime / 60).ToString("0.##")}小时", + UserIcon = user?.UserIconUrl ?? AppConfig.UserConfig.UserIconUrl, + UserName = user?.UserName ?? AppConfig.UserConfig.NickName, + UserId = it.UserId, + Ranking = index, + }; + gamePlayTimeDtos.Add(gamePlayTimeDto); + index++; + }); + #endregion + #region 用户数据 + GamePlayTimeDto userGamePlayTimeDto = new GamePlayTimeDto() + { + PlayTime = $"0小时", + Ranking = 0, + UserIcon = AppConfig.UserConfig.NickName, + UserId = 0, + UserName = "" + }; + if (_UserId > 0) + { + //查找当前用户游玩记录 + var userGame = await Dao.DaoPhone.Context.T_User_GameList.Where(it => it.GameId == gameId && it.UserId == _UserId).FirstOrDefaultAsync(); + if (userGame != null) + { + //计算用户排名,看看是否进入前50名 + var userIndex = list.FindIndex(it => it.UserId == _UserId); + userGamePlayTimeDto.PlayTime = $"{(userGame.PlayTime / 60).ToString("0.##")}小时"; + if (userIndex > -1) + { + userGamePlayTimeDto.Ranking = userIndex + 1; + } + } + userGamePlayTimeDto.UserName = UserInfo.UserName; + userGamePlayTimeDto.UserId = _UserId; + + } + #endregion + gamePlayTimeInfoDto.UserGamePlayTime = userGamePlayTimeDto; + gamePlayTimeInfoDto.GamePlayTimes = gamePlayTimeDtos; + return gamePlayTimeInfoDto; + } + + /// + /// 获取首页排行榜 + /// + /// + public async Task> GetGameRankingList() + { + //后期需要把这个做出一个服务,每隔几分钟去查询一次 + var now = DateTime.Now; + //从凌晨4点开始统计数据,如果当前时间小于凌晨4点,则将时间改成上一天 + if (now < new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day, 4, 0, 0)) + { + now = now.AddDays(-1); + } + var startDate = new DateTime(now.Year, now.Month, now.Day, 4, 0, 0); + //如果开始游玩时间大于凌晨4点,则直接计算时间 + var list = await Dao.DaoPhone.Context.T_User_GameList.Where(it => it.CreateTime > startDate) + .GroupBy(it => it.GameId).Select(it => new { it.Key, PlayTime = it.Sum(it => it.PlayTime) }).OrderByDescending(it => it.PlayTime).Take(20).ToDictionaryAsync(it => it.Key, it => it.PlayTime); + //如果开始时间小于凌晨4点,并且结束时间大于凌晨4点,则用结束时间减去凌晨4点,计算得到的游玩总时间 + var list1 = await Dao.DaoPhone.Context.T_User_GameList.Where(it => it.CreateTime < startDate && it.UpdateTime > startDate) + .Select(it => + new + { + it.GameId, + PlayTime = it.UpdateTime.Subtract(startDate).TotalMinutes + }).GroupBy(it => it.GameId).Select(it => new { it.Key, PlayTime = it.Sum(it => it.PlayTime) }).OrderByDescending(it => it.PlayTime).Take(20).ToListAsync(); + //将结果二查出来合并到结果1中 + list1.ForEach(item => + { + if (list.ContainsKey(item.Key)) + { + list[item.Key] += (int)item.PlayTime; + } + else + { + list.TryAdd(item.Key, (int)item.PlayTime); + } + }); + var gameCache = Cache.GameEntityCache; + List gameListDtos = new List(); + list = list.OrderByDescending(it => it.Value).Take(20).ToDictionary(); + + foreach (var gameId in list.Keys) + { + var gameInfo = gameCache[gameId]; + gameListDtos.Add(new GameListDto(gameInfo, ImageResStyle.小LOGO)); + } + return gameListDtos; + } } } diff --git a/src/CloudGaming/Code/CloudGaming.Code/Other/RedemptionBLL.cs b/src/CloudGaming/Code/CloudGaming.Code/Other/RedemptionBLL.cs new file mode 100644 index 0000000..9ab0ce0 --- /dev/null +++ b/src/CloudGaming/Code/CloudGaming.Code/Other/RedemptionBLL.cs @@ -0,0 +1,109 @@ +using CloudGaming.Code.Account; +using CloudGaming.Code.DataAccess; +using CloudGaming.DtoModel.Account.User; +using CloudGaming.DtoModel.RedemptionCode; +using CloudGaming.DtoModel.SevenSign; + +using HuanMeng.DotNetCore.Redis; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.Code.Other +{ + /// + /// 兑换码 + /// + public class RedemptionBLL : CloudGamingBase + { + public RedemptionBLL(IServiceProvider serviceProvider) : base(serviceProvider) + { + } + + public async Task> UseRedemptionCode(string code) + { + if (string.IsNullOrEmpty(code)) + { + throw new ArgumentNullException("兑换码不能为空"); + } + var list = Cache.RedemptionCodeList; + var red = list.Where(it => it.Code == code).FirstOrDefault(); + if (red == null) + { + throw new ArgumentNullException("兑换码不存在"); + } + if (!red.IsActive) + { + throw new ArgumentNullException("兑换码已失效"); + } + if (red.ExpirationDate < DateTime.Now) + { + throw new ArgumentNullException("兑换码已过期"); + } + start: + if (red.UsageLimit > 0) + { + var redemptionUsageCount = Dao.DaoPhone.Context.T_User_RedemptionUsage.Where(it => it.Code == code && it.Status == (int)RedemptionUsageStatus.领取成功).Count(); + if (redemptionUsageCount >= red.UsageLimit) + { + throw new ArgumentNullException("兑换码已使用"); + } + if (red.UsageLimit == 1) + { + var lockStr = $"lock:RedemptionCode:{code}"; + //加锁 + if (!RedisCache.StringSetLock(lockStr, "", 2)) + { + await Task.Delay(200); + goto start; + } + string msg = await SendReward(code, red); + await RedisCache.KeyDeleteAsync(lockStr); + return new BaseResponse(ResonseCode.Success, msg, true) { }; + } + } + string m = await SendReward(code, red); + return new BaseResponse(ResonseCode.Success, m, true) { }; + } + + private async Task SendReward(string code, RedemptionCodeCache? red) + { + T_User_RedemptionUsage t_User_RedemptionUsage = new T_User_RedemptionUsage() + { + Code = code, + RedemptionCodeId = red.Id, + Status = (int)RedemptionUsageStatus.领取成功, + UsedDate = DateTime.Now, + UserId = _UserId, + }; + await Dao.DaoPhone.Context.T_User_RedemptionUsage.AddAsync(t_User_RedemptionUsage); + await Dao.DaoPhone.Context.SaveChangesAsync(); + var msg = "领取成功!"; + //发放奖励 + if (red.RewardConfigs != null && red.RewardConfigs.Count > 0) + { + foreach (var raw in red.RewardConfigs) + { + var isSuccess = await this.UserConsumeDiamondMoneyAsync(raw.AwardNum, $"兑换码礼包"); + if (!isSuccess) + { + t_User_RedemptionUsage.Status = (int)RedemptionUsageStatus.领取失败; + t_User_RedemptionUsage.Remarks = msg; + if (t_User_RedemptionUsage.Remarks.Length > 250) + { + t_User_RedemptionUsage.Remarks = t_User_RedemptionUsage.Remarks[^250..]; + } + await Dao.DaoPhone.Context.SaveChangesAsync(); + throw MessageBox.Show(ResonseCode.Error, "奖励发放失败"); + } + msg += $"获得{(UserCurrencyType)raw.CurrencyType}*{raw.AwardNum}"; + } + } + + return msg; + } + } +} diff --git a/src/CloudGaming/Code/CloudGaming.Code/Other/SevenSignBLL.cs b/src/CloudGaming/Code/CloudGaming.Code/Other/SevenSignBLL.cs index 9f684d4..9a0b624 100644 --- a/src/CloudGaming/Code/CloudGaming.Code/Other/SevenSignBLL.cs +++ b/src/CloudGaming/Code/CloudGaming.Code/Other/SevenSignBLL.cs @@ -107,9 +107,10 @@ public class SevenSignBLL : CloudGamingBase var isSuccess = await this.UserConsumeDiamondMoneyAsync(raw.AwardNum, $"七天签到-第{userSevenInfo.ConsecutiveSignDays + 1}天礼包"); if (!isSuccess) { - msg += $"获得{(UserCurrencyType)raw.CurrencyType}*{raw.AwardNum}"; + throw MessageBox.Show(ResonseCode.Error, "奖励发放失败"); } + msg += $"获得{(UserCurrencyType)raw.CurrencyType}*{raw.AwardNum}"; } } diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/Epg/EpgEnum.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/Epg/EpgEnum.cs index 1b09bfe..864a1c2 100644 --- a/src/CloudGaming/Model/CloudGaming.DtoModel/Epg/EpgEnum.cs +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/Epg/EpgEnum.cs @@ -68,6 +68,9 @@ namespace CloudGaming.DtoModel.Epg /// 游戏库 = 5, + /// + /// 主页使用 + /// 系类 = 6, } diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameHistoryListDto.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameHistoryListDto.cs new file mode 100644 index 0000000..b78e929 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameHistoryListDto.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.Game; + +/// +/// 游玩历史 +/// +public class GameHistoryListDto : GameListDto +{ + public GameHistoryListDto() { } + + /// + /// + /// + /// + public GameHistoryListDto(GameInfo gameInfo) : base(gameInfo, Epg.EpgEnum.ImageResStyle.小LOGO) + { } + + /// + /// + /// + /// 游戏 + /// 游玩时间 + public GameHistoryListDto(GameInfo gameInfo, int playtime) : base(gameInfo, Epg.EpgEnum.ImageResStyle.小LOGO) + { + this.Playtime = $"{(playtime / 60).ToString("0.##")}小时"; + } + + /// + /// 游玩时间 + /// + public string Playtime { get; set; } +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameListDto.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameListDto.cs index e83a1d7..50d21a3 100644 --- a/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameListDto.cs +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GameListDto.cs @@ -13,7 +13,7 @@ using static CloudGaming.DtoModel.Epg.EpgEnum; namespace CloudGaming.DtoModel.Game; /// -/// 游戏列表数据 +/// 游戏列表数据 /// public class GameListDto { @@ -30,9 +30,6 @@ public class GameListDto this.GameName = gameInfo.GameName; this.GameId = gameInfo.GameId; this.GameIconImage = imageResStyle.GetImageResStyle(gameInfo); - - - } } /// diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GamePlayTimeDto.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GamePlayTimeDto.cs new file mode 100644 index 0000000..6305f4e --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/Game/GamePlayTimeDto.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.Game; + +/// +/// 游戏时长排行榜 +/// +public class GamePlayTimeDto +{ + + /// + /// 排名 + /// + public int Ranking { get; set; } + + /// + /// 用户Id + /// + public int UserId { get; set; } + /// + /// 用户昵称 + /// + public string UserName { get; set; } + /// + /// 用户头像 + /// + public string UserIcon { get; set; } + /// + /// 游戏时长 + /// + public string PlayTime { get; set; } +} + +/// +/// +/// +public class GamePlayTimeInfoDto +{ + /// + /// 排行榜数据 + /// + public List GamePlayTimes { get; set; } + + /// + /// 用户数据 + /// + public GamePlayTimeDto UserGamePlayTime { get; set; } + +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RedemptionCodeCache.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RedemptionCodeCache.cs new file mode 100644 index 0000000..8326851 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RedemptionCodeCache.cs @@ -0,0 +1,22 @@ +using AutoMapper; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.RedemptionCode +{ + /// + /// 兑换码缓存 + /// + [AutoMap(typeof(T_RedemptionCode))] + public class RedemptionCodeCache : T_RedemptionCode + { + /// + /// 奖励配置表 + /// + public List RewardConfigs { get; set; } + } +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RedemptionUsageStatus.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RedemptionUsageStatus.cs new file mode 100644 index 0000000..18a5ec7 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RedemptionUsageStatus.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.RedemptionCode +{ + /// + /// + /// + public enum RedemptionUsageStatus + { + /// + /// 领取成功 + /// + 领取成功 = 1, + /// + /// 领取失败 + /// + 领取失败 = 2, + /// + /// 已过期 + /// + 已过期 = 3 + } +} diff --git a/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RewardConfigType.cs b/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RewardConfigType.cs new file mode 100644 index 0000000..21886dc --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.DtoModel/RedemptionCode/RewardConfigType.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace CloudGaming.DtoModel.RedemptionCode; + +/// +/// 通用奖励配置类型 +/// +public enum RewardConfigType +{ + /// + /// 兑换码 + /// + 兑换码 = 1 +} diff --git a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/CloudGamingPhoneContext.cs b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/CloudGamingPhoneContext.cs index 11bdf45..73938bd 100644 --- a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/CloudGamingPhoneContext.cs +++ b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/CloudGamingPhoneContext.cs @@ -123,6 +123,16 @@ public partial class CloudGamingPhoneContext : MultiTenantDbContext//DbContext /// public virtual DbSet T_Products_Reward { get; set; } + /// + /// 兑换码表 + /// + public virtual DbSet T_RedemptionCode { get; set; } + + /// + /// 通用奖励配置表 + /// + public virtual DbSet T_RewardConfig { get; set; } + /// /// 七日签到配置表 /// @@ -148,6 +158,21 @@ public partial class CloudGamingPhoneContext : MultiTenantDbContext//DbContext /// public virtual DbSet T_UIs { get; set; } + /// + /// 用户游玩记录表。玩一次游戏记录一条数据 + /// + public virtual DbSet T_User_GameList { get; set; } + + /// + /// 用户游玩时间表,总表,一个游戏一条数据 + /// + public virtual DbSet T_User_PlayGameTime { get; set; } + + /// + /// 兑换码使用表 + /// + public virtual DbSet T_User_RedemptionUsage { get; set; } + /// /// 用户签到表 /// @@ -837,6 +862,55 @@ public partial class CloudGamingPhoneContext : MultiTenantDbContext//DbContext } }); + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__T_Redemp__3214EC07017D7B4F"); + + entity.ToTable(tb => tb.HasComment("兑换码表")); + + entity.Property(e => e.Id).HasComment("主键"); + entity.Property(e => e.Code) + .HasMaxLength(64) + .HasComment("兑换码(唯一)"); + entity.Property(e => e.CreatedDate) + .HasComment("兑换码生成时间") + .HasColumnType("datetime"); + entity.Property(e => e.ExpirationDate) + .HasComment("兑换码有效期截止时间") + .HasColumnType("datetime"); + entity.Property(e => e.IsActive).HasComment("是否启用(1为启用,0为禁用)"); + entity.Property(e => e.Remarks) + .HasMaxLength(255) + .HasComment("备注信息(可选"); + entity.Property(e => e.TenantId).HasComment("租户"); + entity.Property(e => e.Type).HasComment("兑换码类型(如优惠券、礼品卡等)"); + entity.Property(e => e.UsageLimit).HasComment("最大使用次数,0表示无限次使用"); + //添加全局筛选器 + if (this.TenantInfo != null) + { + entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId); + } + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__T_Reward__3214EC0757C4F706"); + + entity.ToTable(tb => tb.HasComment("通用奖励配置表")); + + entity.Property(e => e.Id).HasComment("主键"); + entity.Property(e => e.AwardNum).HasComment("奖励数量"); + entity.Property(e => e.CurrencyType).HasComment("奖励类型"); + entity.Property(e => e.ParentNodeId).HasComment("对应主键的id"); + entity.Property(e => e.ParentNodeType).HasComment("奖励类型,1兑换码奖励"); + entity.Property(e => e.TenantId).HasComment("租户"); + //添加全局筛选器 + if (this.TenantInfo != null) + { + entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId); + } + }); + modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("PK_T_SEVENDAYSIGNIN_CBT"); @@ -964,6 +1038,97 @@ public partial class CloudGamingPhoneContext : MultiTenantDbContext//DbContext } }); + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__T_User_G__3214EC072692200E"); + + entity.ToTable(tb => tb.HasComment("用户游玩记录表。玩一次游戏记录一条数据")); + + entity.Property(e => e.Channel) + .HasMaxLength(10) + .HasComment("渠道号"); + entity.Property(e => e.CreateTime) + .HasComment("创建时间,游戏开始时间") + .HasColumnType("datetime"); + entity.Property(e => e.GameId) + .HasMaxLength(20) + .HasComment("游戏Id"); + entity.Property(e => e.PlaySeconds).HasComment("游玩时间,秒"); + entity.Property(e => e.PlayTime).HasComment("游玩时间,分组数"); + entity.Property(e => e.Status).HasComment("状态"); + entity.Property(e => e.TenantId).HasComment("租户"); + entity.Property(e => e.UpdateTime) + .HasComment("修改时间,游戏结束时间") + .HasColumnType("datetime"); + entity.Property(e => e.UserId).HasComment("用户Id"); + //添加全局筛选器 + if (this.TenantInfo != null) + { + entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId); + } + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__T_User_P__3214EC07D35C08FA"); + + entity.ToTable(tb => tb.HasComment("用户游玩时间表,总表,一个游戏一条数据")); + + entity.HasIndex(e => new { e.UserId, e.GameId }, "T_UserId_GameId"); + + entity.Property(e => e.Createtime) + .HasComment("修改时间") + .HasColumnType("datetime"); + entity.Property(e => e.DiamondPlayTime).HasComment("钻石游玩时间"); + entity.Property(e => e.FreePlayTime).HasComment("免费时间"); + entity.Property(e => e.GameId) + .HasMaxLength(100) + .HasComment("游戏Id"); + entity.Property(e => e.NightCardPlayTime).HasComment("包夜卡游玩时间"); + entity.Property(e => e.PlayTime).HasComment("游玩总时间"); + entity.Property(e => e.TenantId).HasComment("租户"); + entity.Property(e => e.UpdateTime) + .HasComment("创建时间") + .HasColumnType("datetime"); + entity.Property(e => e.UserId).HasComment("用户id"); + //添加全局筛选器 + if (this.TenantInfo != null) + { + entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId); + } + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__T_User_R__3214EC07BEE9D60C"); + + entity.ToTable(tb => tb.HasComment("兑换码使用表")); + + entity.Property(e => e.Id).HasComment("主键"); + entity.Property(e => e.Code) + .HasMaxLength(255) + .IsUnicode(false) + .HasComment("兑换码"); + entity.Property(e => e.OrderId) + .HasMaxLength(64) + .HasComment("使用兑换码关联的订单ID(可选)"); + entity.Property(e => e.RedemptionCodeId).HasComment("兑换码主键表"); + entity.Property(e => e.Remarks) + .HasMaxLength(255) + .HasComment("备注"); + entity.Property(e => e.Status).HasComment("使用状态(如成功、失败、已过期等)"); + entity.Property(e => e.TenantId).HasComment("租户"); + entity.Property(e => e.UsedDate) + .HasComment("兑换码使用时间") + .HasColumnType("datetime"); + entity.Property(e => e.UserId).HasComment("用户Id"); + //添加全局筛选器 + if (this.TenantInfo != null) + { + entity.HasQueryFilter(it => it.TenantId == this.TenantInfo.TenantId); + } + }); + modelBuilder.Entity(entity => { entity.HasKey(e => e.Id).HasName("PK_T_USER_SIGNDAYS"); diff --git a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_GameCBT.cs b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_GameCBT.cs index 4521537..1d3c9e3 100644 --- a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_GameCBT.cs +++ b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_GameCBT.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace CloudGaming.Model.DbSqlServer.Db_Phone; diff --git a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_RedemptionCode.cs b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_RedemptionCode.cs new file mode 100644 index 0000000..1798574 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_RedemptionCode.cs @@ -0,0 +1,56 @@ +using System; + +namespace CloudGaming.Model.DbSqlServer.Db_Phone; + +/// +/// 兑换码表 +/// +public partial class T_RedemptionCode: MultiTenantEntity +{ + public T_RedemptionCode() { } + + /// + /// 主键 + /// + public virtual int Id { get; set; } + + /// + /// 兑换码(唯一) + /// + public virtual string Code { get; set; } = null!; + + /// + /// 兑换码类型(如优惠券、礼品卡等) + /// + public virtual int Type { get; set; } + + /// + /// 最大使用次数,0表示无限次使用 + /// + public virtual int UsageLimit { get; set; } + + /// + /// 兑换码有效期截止时间 + /// + public virtual DateTime ExpirationDate { get; set; } + + /// + /// 是否启用(1为启用,0为禁用) + /// + public virtual bool IsActive { get; set; } + + /// + /// 兑换码生成时间 + /// + public virtual DateTime CreatedDate { get; set; } + + /// + /// 备注信息(可选 + /// + public virtual string? Remarks { get; set; } + + /// + /// 所属租户 + /// + public override Guid TenantId { get; set; } + } diff --git a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_RewardConfig.cs b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_RewardConfig.cs new file mode 100644 index 0000000..969d797 --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_RewardConfig.cs @@ -0,0 +1,40 @@ + +namespace CloudGaming.Model.DbSqlServer.Db_Phone; + +/// +/// 通用奖励配置表 +/// +public partial class T_RewardConfig: MultiTenantEntity +{ + public T_RewardConfig() { } + + /// + /// 主键 + /// + public virtual int Id { get; set; } + + /// + /// 奖励类型 + /// + public virtual int CurrencyType { get; set; } + + /// + /// 奖励数量 + /// + public virtual int AwardNum { get; set; } + + /// + /// 奖励类型,1兑换码奖励 + /// + public virtual int ParentNodeType { get; set; } + + /// + /// 对应主键的id + /// + public virtual int ParentNodeId { get; set; } + + /// + /// 所属租户 + /// + public override Guid TenantId { get; set; } + } diff --git a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_GameList.cs b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_GameList.cs new file mode 100644 index 0000000..b86315d --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_GameList.cs @@ -0,0 +1,58 @@ +using System; + +namespace CloudGaming.Model.DbSqlServer.Db_Phone; + +/// +/// 用户游玩记录表。玩一次游戏记录一条数据 +/// +public partial class T_User_GameList: MultiTenantEntity +{ + public T_User_GameList() { } + + public virtual int Id { get; set; } + + /// + /// 用户Id + /// + public virtual int UserId { get; set; } + + /// + /// 游戏Id + /// + public virtual string GameId { get; set; } = null!; + + /// + /// 游玩时间,秒 + /// + public virtual int PlaySeconds { get; set; } + + /// + /// 游玩时间,分组数 + /// + public virtual int PlayTime { get; set; } + + /// + /// 渠道号 + /// + public virtual string? Channel { get; set; } + + /// + /// 状态 + /// + public virtual int Status { get; set; } + + /// + /// 修改时间,游戏结束时间 + /// + public virtual DateTime UpdateTime { get; set; } + + /// + /// 创建时间,游戏开始时间 + /// + public virtual DateTime CreateTime { get; set; } + + /// + /// 所属租户 + /// + public override Guid TenantId { get; set; } + } diff --git a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_PlayGameTime.cs b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_PlayGameTime.cs new file mode 100644 index 0000000..22e937c --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_PlayGameTime.cs @@ -0,0 +1,58 @@ +using System; + +namespace CloudGaming.Model.DbSqlServer.Db_Phone; + +/// +/// 用户游玩时间表,总表,一个游戏一条数据 +/// +public partial class T_User_PlayGameTime: MultiTenantEntity +{ + public T_User_PlayGameTime() { } + + public virtual int Id { get; set; } + + /// + /// 用户id + /// + public virtual int UserId { get; set; } + + /// + /// 游戏Id + /// + public virtual string GameId { get; set; } = null!; + + /// + /// 游玩总时间 + /// + public virtual int PlayTime { get; set; } + + /// + /// 免费时间 + /// + public virtual int FreePlayTime { get; set; } + + /// + /// 钻石游玩时间 + /// + public virtual int DiamondPlayTime { get; set; } + + /// + /// 包夜卡游玩时间 + /// + public virtual int NightCardPlayTime { get; set; } + + /// + /// 创建时间 + /// + public virtual DateTime UpdateTime { get; set; } + + /// + /// 修改时间 + /// + public virtual DateTime Createtime { get; set; } + + /// + /// 所属租户 + /// + public override Guid TenantId { get; set; } + } diff --git a/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_RedemptionUsage.cs b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_RedemptionUsage.cs new file mode 100644 index 0000000..e57fe3d --- /dev/null +++ b/src/CloudGaming/Model/CloudGaming.Model/DbSqlServer/Db_Phone/T_User_RedemptionUsage.cs @@ -0,0 +1,56 @@ +using System; + +namespace CloudGaming.Model.DbSqlServer.Db_Phone; + +/// +/// 兑换码使用表 +/// +public partial class T_User_RedemptionUsage: MultiTenantEntity +{ + public T_User_RedemptionUsage() { } + + /// + /// 主键 + /// + public virtual int Id { get; set; } + + /// + /// 兑换码 + /// + public virtual string Code { get; set; } = null!; + + /// + /// 兑换码主键表 + /// + public virtual int RedemptionCodeId { get; set; } + + /// + /// 用户Id + /// + public virtual int UserId { get; set; } + + /// + /// 兑换码使用时间 + /// + public virtual DateTime UsedDate { get; set; } + + /// + /// 使用兑换码关联的订单ID(可选) + /// + public virtual string? OrderId { get; set; } + + /// + /// 使用状态(如成功、失败、已过期等) + /// + public virtual int Status { get; set; } + + /// + /// 备注 + /// + public virtual string? Remarks { get; set; } + + /// + /// 所属租户 + /// + public override Guid TenantId { get; set; } + }