签到与活动配置:后台配置接口、用户签到流程、UserEntity 扩展
This commit is contained in:
@@ -44,11 +44,11 @@ namespace UserApi.GameConfigs
|
||||
return this.ToListResult(config?.GoldShopConfigs ?? new List<GoldShopConfig>());
|
||||
}
|
||||
|
||||
[HttpGet("signConfigs")]
|
||||
public async Task<ListResponse<SignConfig>> GetSignConfigs()
|
||||
[HttpGet("signConfig")]
|
||||
public async Task<BaseResponse<SignActivityConfig>> GetSignConfig()
|
||||
{
|
||||
var config = await _activityConfigService.Get();
|
||||
return this.ToListResult(config?.SignConfigs ?? new List<SignConfig>());
|
||||
return this.ToResult(config?.SignActivityConfig ?? new SignActivityConfig());
|
||||
}
|
||||
|
||||
[HttpGet("reliefConfig")]
|
||||
|
||||
@@ -145,13 +145,20 @@ namespace UserApi.Hall
|
||||
}
|
||||
|
||||
[HttpGet("SignIn")]
|
||||
public async Task<BaseResponse<long>> SignIn()
|
||||
public async Task<BaseResponse<SignRewardResult>> SignIn()
|
||||
{
|
||||
var res = await _userService.Sign(loginUser);
|
||||
if (res.isok)
|
||||
return this.ToResult<long>(res.gold);
|
||||
return this.ToResult(res.result);
|
||||
else
|
||||
return this.ToFailResult<long>(res.msg);
|
||||
return this.ToFailResult<SignRewardResult>(res.msg);
|
||||
}
|
||||
|
||||
[HttpGet("GetSignStatus")]
|
||||
public async Task<BaseResponse<SignStatusResult>> GetSignStatus()
|
||||
{
|
||||
var res = await _userService.GetSignStatus(loginUser);
|
||||
return this.ToResult(res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Common.Utils;
|
||||
using CommonDomain;
|
||||
using CommonDomain.BaseModel;
|
||||
@@ -201,6 +201,9 @@ namespace UserDomain.Entity
|
||||
{
|
||||
public bool IsSign { get; set; } = false;
|
||||
public long SignTime { get; set; } = 0;
|
||||
|
||||
/// <summary>当前已签到的周期天数(0=未开始,1~7)</summary>
|
||||
public int SignDay { get; set; } = 0;
|
||||
}
|
||||
[BsonIgnoreExtraElements]
|
||||
public class PlayerFactor
|
||||
|
||||
@@ -92,7 +92,9 @@ namespace UserService.User
|
||||
|
||||
Task<(bool isok, string msg)> BuyDiamondPayCallBack(string orderId);
|
||||
|
||||
Task<(bool isok, string msg, long gold)> Sign(LoginUser loginUser);
|
||||
Task<(bool isok, string msg, SignRewardResult result)> Sign(LoginUser loginUser);
|
||||
|
||||
Task<SignStatusResult> GetSignStatus(LoginUser loginUser);
|
||||
|
||||
|
||||
Task<(bool isok, string msg)> ChangeCannon(string number, LoginUser loginUser);
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using CommonDomain.BaseModel;
|
||||
|
||||
namespace UserService.Param
|
||||
{
|
||||
/// <summary>签到奖励返回</summary>
|
||||
public class SignRewardResult
|
||||
{
|
||||
/// <summary>本次签到对应第几天(1~7)</summary>
|
||||
public int Day { get; set; } = 0;
|
||||
|
||||
public long Gold { get; set; } = 0;
|
||||
|
||||
public int Diamond { get; set; } = 0;
|
||||
|
||||
public List<BaseProductCount> Product { get; set; } = new List<BaseProductCount>();
|
||||
}
|
||||
|
||||
/// <summary>签到状态返回</summary>
|
||||
public class SignStatusResult
|
||||
{
|
||||
public bool IsOpen { get; set; } = false;
|
||||
|
||||
/// <summary>勾选=不可中断(漏签不回退);未勾选=可中断(漏签重置)</summary>
|
||||
public bool CannotInterrupt { get; set; } = false;
|
||||
|
||||
/// <summary>当前周期已完成到第几天(0~7)</summary>
|
||||
public int SignDay { get; set; } = 0;
|
||||
|
||||
/// <summary>今天签到对应的天数(已签则为其已签天数;未签则为下一次目标天数)</summary>
|
||||
public int TodayDay { get; set; } = 0;
|
||||
|
||||
/// <summary>今天是否已签到</summary>
|
||||
public bool IsTodaySigned { get; set; } = false;
|
||||
|
||||
/// <summary>7 天奖励配置</summary>
|
||||
public List<SignConfig> Days { get; set; } = new List<SignConfig>();
|
||||
}
|
||||
}
|
||||
@@ -1364,36 +1364,107 @@ namespace UserService.User
|
||||
}
|
||||
|
||||
|
||||
public async Task<(bool isok, string msg, long gold)> Sign(LoginUser loginUser)
|
||||
public async Task<(bool isok, string msg, SignRewardResult result)> Sign(LoginUser loginUser)
|
||||
{
|
||||
var user = await GetUser(loginUser.UserId);
|
||||
if (user == null)
|
||||
throw new BusinessException("用户不存在");
|
||||
|
||||
// if (user.Assets.VipLevel == 0)
|
||||
|
||||
// if (user.Sign.IsSign)
|
||||
var activityConfig = await _activityConfigService.Get();
|
||||
|
||||
var signList = activityConfig.SignConfigs;
|
||||
if (signList.Count == 0)
|
||||
var signConfig = activityConfig?.SignActivityConfig;
|
||||
if (signConfig == null || !signConfig.IsOpen)
|
||||
throw new BusinessException("签到活动未开启");
|
||||
if (signConfig.Days == null || signConfig.Days.Count == 0)
|
||||
throw new BusinessException("签到配置不存在");
|
||||
|
||||
var sign = GetRandomSignConfig(activityConfig);
|
||||
if (user.Sign == null)
|
||||
user.Sign = new SignInfo();
|
||||
|
||||
var gold = Convert.ToInt64(sign.Gold * (1 + user.Assets.VipSignInAdd));
|
||||
var now = DateTime.Now;
|
||||
var today = now.Date;
|
||||
DateTime? lastSignDate = user.Sign.SignTime > 0 ? user.Sign.SignTime.ToDateTime().Date : (DateTime?)null;
|
||||
if (lastSignDate.HasValue && lastSignDate.Value == today)
|
||||
throw new BusinessException("今日已签到");
|
||||
|
||||
user.Sign.IsSign = true;
|
||||
user.Sign.SignTime = DateTime.Now.ToTimeStamp();
|
||||
var day = CalcSignDay(user.Sign.SignDay, lastSignDate, today, signConfig.CannotInterrupt);
|
||||
var dayConfig = signConfig.Days.FirstOrDefault(c => c.Day == day) ?? signConfig.Days.OrderBy(c => c.Day).First();
|
||||
if (dayConfig == null || dayConfig.GiftList == null || dayConfig.GiftList.Count == 0)
|
||||
throw new BusinessException($"第{day}天签到奖励未配置");
|
||||
|
||||
var gift = GetGift(dayConfig.GiftList);
|
||||
var gold = Convert.ToInt64(gift.Gold * (1 + user.Assets.VipSignInAdd));
|
||||
|
||||
var res = await UpdateAssets(new UserAssetParam
|
||||
{
|
||||
UserId = user.Id,
|
||||
ChangeType = UserAssetChangeTypeEnum.增加,
|
||||
Source = RewardSource.签到,
|
||||
Remark = $"第{day}天签到奖励",
|
||||
Gold = gold,
|
||||
Diamond = gift.Diamond,
|
||||
RewardItems = gift.Product
|
||||
});
|
||||
if (!res.isok)
|
||||
return (false, res.msg, null);
|
||||
|
||||
var signUpdate = Builders<UserEntity>.Update
|
||||
.Set(p => p.Sign.IsSign, true)
|
||||
.Set(p => p.Sign.SignTime, now.ToTimeStamp())
|
||||
.Set(p => p.Sign.SignDay, day);
|
||||
await _userMongo.UpdateByIdAsync(user.Id, signUpdate);
|
||||
|
||||
return (true, "签到成功", new SignRewardResult
|
||||
{
|
||||
Day = day,
|
||||
Gold = gold,
|
||||
Diamond = gift.Diamond,
|
||||
Product = gift.Product ?? new List<BaseProductCount>()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
UserReward userReward = new UserReward() { UserId = user.Id, ChangeCount = gold, CurrencyType = 1, Remark = "签到获取金币", Source = RewardSource.签到, Type = 1, BeforeCount = user.Assets.Gold };
|
||||
user.Assets.Gold += gold;
|
||||
userReward.AfterCount = user.Assets.Gold;
|
||||
await _rewardMongo.InsertOneAsync(userReward);
|
||||
public async Task<SignStatusResult> GetSignStatus(LoginUser loginUser)
|
||||
{
|
||||
var user = await GetUser(loginUser.UserId);
|
||||
var activityConfig = await _activityConfigService.Get();
|
||||
var signConfig = activityConfig?.SignActivityConfig;
|
||||
|
||||
await _userMongo.ReplaceOneAsync(user);
|
||||
var result = new SignStatusResult
|
||||
{
|
||||
IsOpen = signConfig?.IsOpen ?? false,
|
||||
CannotInterrupt = signConfig?.CannotInterrupt ?? false,
|
||||
Days = signConfig?.Days?.OrderBy(c => c.Day).ToList() ?? new List<SignConfig>()
|
||||
};
|
||||
|
||||
return (true, "签到成功", gold);
|
||||
var today = DateTime.Now.Date;
|
||||
DateTime? lastSignDate = user?.Sign != null && user.Sign.SignTime > 0
|
||||
? user.Sign.SignTime.ToDateTime().Date
|
||||
: (DateTime?)null;
|
||||
|
||||
result.SignDay = user?.Sign?.SignDay ?? 0;
|
||||
result.IsTodaySigned = lastSignDate.HasValue && lastSignDate.Value == today;
|
||||
result.TodayDay = result.IsTodaySigned
|
||||
? result.SignDay
|
||||
: CalcSignDay(result.SignDay, lastSignDate, today, result.CannotInterrupt);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private const int SignCycleDays = 7;
|
||||
|
||||
/// <summary>计算本次签到对应的天数(1~7)</summary>
|
||||
private static int CalcSignDay(int currentDay, DateTime? lastSignDate, DateTime today, bool cannotInterrupt)
|
||||
{
|
||||
// 上次签到为昨天:连续签到,天数顺延
|
||||
if (lastSignDate.HasValue && lastSignDate.Value.Date == today.AddDays(-1))
|
||||
return currentDay > 0 ? currentDay % SignCycleDays + 1 : 1;
|
||||
|
||||
// 漏签:不可中断则继续顺延(累计循环);可中断则重置回第1天
|
||||
if (currentDay > 0 && cannotInterrupt)
|
||||
return currentDay % SignCycleDays + 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2328,40 +2399,6 @@ namespace UserService.User
|
||||
}
|
||||
|
||||
|
||||
public SignConfig GetRandomSignConfig(ActivityConfig activityConfig)
|
||||
{
|
||||
|
||||
if (activityConfig?.SignConfigs == null || !activityConfig.SignConfigs.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var configs = activityConfig.SignConfigs;
|
||||
var totalProbability = configs.Sum(c => Math.Max(0, c.Probability));
|
||||
|
||||
if (totalProbability <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var randomValue = System.Random.Shared.NextDouble() * totalProbability;
|
||||
|
||||
double cumulativeProbability = 0;
|
||||
foreach (var config in configs)
|
||||
{
|
||||
var currentProbability = Math.Max(0, config.Probability);
|
||||
cumulativeProbability += currentProbability;
|
||||
|
||||
if (randomValue <= cumulativeProbability)
|
||||
{
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
return configs.LastOrDefault();
|
||||
}
|
||||
|
||||
|
||||
public GiftResponse GetGift(List<GiftConfig> giftConfigs)
|
||||
{
|
||||
GiftResponse response = new GiftResponse();
|
||||
|
||||
Reference in New Issue
Block a user