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; }
+ }