using JiaZhiQuan.Common.Messaging; using JiaZhiQuan.Common.Messaging.Models; using JiaZhiQuan.Common.Models.CacheModel; using JiaZhiQuan.Common.Models.PO; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading.Tasks; using Wicture.DbRESTFul; using Wicture.DbRESTFul.Cache; using Wicture.DbRESTFul.Infrastructure.Repository; using static JiaZhiQuan.Common.UserGrow; namespace JiaZhiQuan.Common { public static partial class RepositoryExtension { /// /// 完成任务 /// /// /// /// /// /// /// /// /// public static async Task TaskCompleteAsync(this DbRESTFulRepository repository, long userId, TaskEvent taskEvent, Dictionary data, RedisCacheProvider redis, Producer producer) { string key = CacheKeys.DailyUserTaskCompletion(); // 获取用户当天的行为 UserGrowBehavior userBehavior = await GetDailyUserBehavior(userId, redis); // 查询任务详情 var task = await repository.GetTaskInfo(taskEvent); if (task is null) return new TaskCompleteResult { isComplete = false }; // 根据任务类型判断任务是否完成 bool isOk = taskEvent switch { TaskEvent.Collect => TaskCollectAsync(task, userBehavior), TaskEvent.Share => TaskShareAsync(task, userBehavior), TaskEvent.PublishCommentOrReply => TaskCommentOrReplyAsync(task, userBehavior), TaskEvent.FocusUser => TaskFocusUserAsync(task, userBehavior), TaskEvent.PublishPost => TaskPublishPostAsync(task, userBehavior), TaskEvent.CheckPost => TaskCheckPostAsync(task, userBehavior), TaskEvent.DayRead => TaskReadAsync(task, userBehavior), TaskEvent.DayThumbsup => TaskThumbsupAsync(task, userBehavior), _ => throw new NotImplementedException() }; bool experienceAddSuccess = false; // 说明用户完成任务,添加经验值 if (isOk) { experienceAddSuccess = await UserAddExperience(repository, userId, task, producer); if (experienceAddSuccess) { switch (taskEvent) { case TaskEvent.Collect: case TaskEvent.Share: case TaskEvent.PublishCommentOrReply: case TaskEvent.FocusUser: case TaskEvent.PublishPost: case TaskEvent.CheckPost: case TaskEvent.DayRead: case TaskEvent.DayThumbsup: await redis.CSRedisClient.HSetAsync(key, userId.ToString(), userBehavior); break; } } } else { switch (taskEvent) { case TaskEvent.Collect: case TaskEvent.Share: case TaskEvent.PublishCommentOrReply: case TaskEvent.FocusUser: case TaskEvent.PublishPost: case TaskEvent.CheckPost: case TaskEvent.DayRead: case TaskEvent.DayThumbsup: await redis.CSRedisClient.HSetAsync(key, userId.ToString(), userBehavior); break; } } return new TaskCompleteResult { isComplete = experienceAddSuccess, taskMessage = $"{task.taskName}完成,+{task.experience}成长值", taskImage = task.taskImage }; } /// /// 阅读数 /// /// /// /// private static bool TaskReadAsync(TaskInfo task, UserGrowBehavior userBehavior) { ++userBehavior.read; if (userBehavior.read >= task.taskCompleteNeedCount && userBehavior.hasRead == false) { userBehavior.hasRead = true; return true; } else { return false; } } /// /// 点赞数 /// /// /// /// private static bool TaskThumbsupAsync(TaskInfo task, UserGrowBehavior userBehavior) { ++userBehavior.thumbsup; if (userBehavior.thumbsup >= task.taskCompleteNeedCount && userBehavior.hasThumb == false) { userBehavior.hasThumb = true; return true; } else { return false; } } /// /// 收藏 /// /// /// /// private static bool TaskCollectAsync(TaskInfo task, UserGrowBehavior userBehavior) { // 收藏次数+1 userBehavior.collection = userBehavior.collection + 1; // 如果收藏次数大于等于任务需要的分享次数,且当前还没有完成过收藏任务 if (userBehavior.collection >= task.taskCompleteNeedCount && userBehavior.hasCollection == false) { // 标记已完成任务 userBehavior.hasCollection = true; return true; } else { return false; } } /// /// 分享 /// /// /// /// private static bool TaskShareAsync(TaskInfo task, UserGrowBehavior userBehavior) { // 分享次数+1 userBehavior.share = userBehavior.share + 1; // 如果分享次数大于等于任务需要的分享次数,且当前还没有完成过分享任务 if (userBehavior.share >= task.taskCompleteNeedCount && userBehavior.hasShare == false) { // 标记已完成任务 userBehavior.hasShare = true; return true; } else { return false; } } /// /// 评论/回复 /// /// /// /// private static bool TaskCommentOrReplyAsync(TaskInfo task, UserGrowBehavior userBehavior) { // 评论/回复次数+1 userBehavior.comment = userBehavior.comment + 1; // 如果评论/回复次数大于等于任务需要的次数,且当前还没有完成过任务 if (userBehavior.comment >= task.taskCompleteNeedCount && userBehavior.hasComment == false) { // 标记已完成任务 userBehavior.hasComment = true; return true; } else { return false; } } /// /// 关注用户 /// /// /// /// private static bool TaskFocusUserAsync(TaskInfo task, UserGrowBehavior userBehavior) { // 关注次数+1 userBehavior.focus = userBehavior.focus + 1; // 如果关注次数大于等于任务需要的次数,且当前还没有完成过任务 if (userBehavior.focus >= task.taskCompleteNeedCount && userBehavior.hasFocus == false) { // 标记已完成任务 userBehavior.hasFocus = true; return true; } else { return false; } } /// /// 发布笔记 /// /// /// /// private static bool TaskPublishPostAsync(TaskInfo task, UserGrowBehavior userBehavior) { // 发布笔记次数+1 userBehavior.publish = userBehavior.publish + 1; // 如果发布笔记次数大于等于任务需要的次数,且当前还没有完成过任务 if (userBehavior.publish >= task.taskCompleteNeedCount && userBehavior.hasPublish == false) { // 标记已完成任务 userBehavior.hasPublish = true; return true; } else { return false; } } /// /// 审核笔记通过 /// /// /// /// private static bool TaskCheckPostAsync(TaskInfo task, UserGrowBehavior userBehavior) { // 审核笔记通过次数+1 userBehavior.approved = userBehavior.approved + 1; // 如果审核笔记次数大于等于任务需要的次数,且当前还没有完成过任务 if (userBehavior.approved >= task.taskCompleteNeedCount && userBehavior.hasApproved == false) { // 标记已完成任务 userBehavior.hasApproved = true; return true; } else { return false; } } #region Utils /// /// 获取当前用户当天的任务完成情况 /// /// /// /// public static async Task GetDailyUserBehavior(long userId, RedisCacheProvider redis) { string key = CacheKeys.DailyUserTaskCompletion(); UserGrowBehavior userGrow = await redis.CSRedisClient.HGetAsync(key, userId.ToString()); if (userGrow is null) { userGrow = new UserGrowBehavior(); await redis.CSRedisClient.HSetAsync(key, userId.ToString(), userGrow); await redis.CSRedisClient.ExpireAtAsync(key, DateTime.Now.AddDays(1).Date); } return userGrow; } /// /// 用户增加成长经验 /// /// /// /// /// /// /// /// public static async Task UserAddExperience(DbRESTFulRepository repository, long userId, TaskInfo task, Producer producer) { // 获取用户相关经验信息 var user = await repository.QuerySingleOrDefaultAsync($@"select id as userId, growLevel, growNowExperience, growSumExperience from n_user where id = @userId", new { userId }); if (user is null) { LoggerManager.Logger.Error($"未找到用户,用户id:{userId},任务类型:{TaskEvent.CheckPost}"); return false; } user.versionId = task.versionId; using var conn = repository.ConnectionManager.GetConnection(false); conn.Open(); var trans = conn.BeginTransaction(); try { // 用户增加经验 user.growNowExperience = user.growNowExperience + task.experience; user.growSumExperience = user.growSumExperience + task.experience; // 保存用户成长经验记录 await repository.QuerySingleOrDefaultAsync($@"INSERT INTO n_user_grow_experience_log (versionId, userId, source, taskId, experience, nowSumExperience, createAt) VALUES (@versionId, @userId, @source, @taskId, @experience, @nowSumExperience, now());", new { task.versionId, userId, source = (int)UserGrow.ExperienceSource.任务, taskId = task.id, task.experience, nowSumExperience = user.growSumExperience }, conn, trans); await repository.QuerySingleOrDefaultAsync($@"update n_user set growNowExperience = @growNowExperience, growSumExperience = @growSumExperience where id = @userId", user, conn, trans); // 用户升级 await UserLevelUp(user, repository, conn, trans, producer); trans.Commit(); return true; } catch (Exception ex) { LoggerManager.Logger.Error(ex, $"用户获取经验报错,错误信息:" + ex.Message); trans.Rollback(); return false; } } /// /// 用户升级 /// /// /// /// /// /// public static async Task UserLevelUp(UserExperience user, DbRESTFulRepository repository, IDbConnection conn, IDbTransaction trans, Producer producer) { var level = await repository.QuerySingleOrDefaultAsync($@"select id, `code`, experience from grow_level where versionId = @versionId and level = @level and @experience >= experience ", new { user.versionId, level = user.growLevel + 1, experience = user.growNowExperience }, conn); // 说明用户暂时不满足升级条件 if (level is null) return; user.growLevel = user.growLevel + 1; user.growNowExperience = user.growNowExperience - level.experience; string code = Guid.NewGuid().ToString("N"); // 保存用户升级记录 await repository.QuerySingleOrDefaultAsync($@"insert into n_user_grow_level_log (code, versionId, userId, levelId, level, levelUpNeedExperience, nowLevelSumExperience, nowExperience, createAt) values (@code, @versionId, @userId, @levelId, @level, @levelUpNeedExperience, @nowLevelSumExperience, @nowExperience, now())", new { code, user.versionId, user.userId, levelId = level.id, level = user.growLevel, levelUpNeedExperience = level.experience, nowLevelSumExperience = user.growSumExperience - user.growNowExperience, nowExperience = user.growNowExperience }, conn, trans); // 等级对应的奖励 var prizes = await repository.QueryAsync($@"select * from grow_level_prize where versionId = @versionId and levelCode = @code", new { user.versionId, code = level.code }); // 保存用户升级待领取奖励记录 await repository.QuerySingleOrDefaultAsync($@"insert into n_user_grow_prize_order (versionId, userId, levelId, levelPrizeId, levelLogCode, level, status, expireTime, points, displayOrder, type, name, thumbnails, prizeId, createAt) values (@versionId, @userId, @levelId, @levelPrizeId, @levelLogCode, @level, @status, @expireTime, @points, @displayOrder, @type, @name, @thumbnails, @prizeId, now())", prizes.Select(e => new { user.versionId, user.userId, levelId = level.id, levelPrizeId = e.id, levelLogCode = code, level = user.growLevel, status = 0, expireTime = DateTime.Now.AddDays(e.expirationDays), e.points, e.displayOrder, e.type, e.name, thumbnails = e.image, e.prizeId }), conn, trans); // 更新用户等级 await repository.QuerySingleOrDefaultAsync($@"update n_user set growLevel = @growLevel, growNowExperience = @growNowExperience, growSumExperience = @growSumExperience where id = @userId", user, conn, trans); // 给用户发送升级通知 _ = producer.ProduceAsync(NotificationModel.GetMsgKey(), new NotificationModel { Type = NotificationType.Common, Content = JsonConvert.SerializeObject(new CommonSubModel { UserId = user.userId, Title = $"等级升至Lv{user.growLevel}", Message = $"Lv{user.growLevel}等级权益已解锁,立即领取 >>>", ActionLink = "app://mine/grow" }) }); // 递归调用,判断是否连续升级 await UserLevelUp(user, repository, conn, trans, producer); return; } #endregion /// /// 获取任务详情 /// /// /// /// public static async Task GetTaskInfo(this DbRESTFulRepository repository, TaskEvent taskEvent) { // 获取版本详情 var version = await repository.QuerySingleOrDefaultAsync("select * from grow_version where enabled = 1 order by enabledAt desc limit 1"); if (version is null) { // 当前没有启用的版本,无需处理 // LoggerManager.Logger.Error($"当前无启用的用户成长体系版本"); return null; } // 获取任务详情 var task = await repository.QuerySingleOrDefaultAsync($@"SELECT t1.id, t1.versionId, t1.experience, t1.taskCompleteNeedCount, t1.`name` as taskName, t1.image as taskImage, t1.taskEventId FROM grow_task AS t1 LEFT JOIN grow_task_event AS t2 ON t1.taskEventId = t2.id WHERE t1.enabled = 1 AND t1.versionId = @versionId AND t2.`code` = '{taskEvent}'", new { versionId = version.id }); if (task is null) { // 该版本没有此任务,无需处理 // LoggerManager.Logger.Error($"当前启用版本没有此任务类型,任务类型:{taskEvent}"); return null; } return task; } } public class UserExperience { public int versionId { get; set; } public long userId { get; set; } public int growLevel { get; set; } public int growNowExperience { get; set; } public int growSumExperience { get; set; } } public class TaskInfo { public int versionId { get; set; } public int id { get; set; } public int experience { get; set; } public int taskCompleteNeedCount { get; set; } public string taskName { get; set; } public string taskImage { get; set; } public int taskEventId { get; set; } } public class TaskCompleteResult { /// /// 是否完成任务 /// public bool isComplete { get; set; } /// /// 任务描述 /// public string taskMessage { get; set; } /// /// 任务图标 /// public string taskImage { get; set; } } }