/// <summary> /// 创建 <see cref="ArticlePage"/> /// </summary> /// <param name="authorIdCode">作者识别码</param> /// <param name="sidForAuthor">文章在作者名下的序号</param> /// <param name="currentUserId">当前登录用户 ID</param> /// <param name="isOperator">当前登录用户是否为运维职员</param> /// <param name="dbContext"><see cref="KeylolDbContext"/></param> /// <param name="cachedData"><see cref="CachedDataProvider"/></param> /// <param name="userManager"><see cref="KeylolUserManager"/></param> /// <returns><see cref="ArticlePage"/></returns> public static async Task <ArticlePage> CreateAsync(string authorIdCode, int sidForAuthor, string currentUserId, bool isOperator, KeylolDbContext dbContext, CachedDataProvider cachedData, KeylolUserManager userManager) { var articlePage = new ArticlePage(); var article = await dbContext.Articles .Include(a => a.Author) .Include(a => a.TargetPoint) .Where(a => a.Author.IdCode == authorIdCode && a.SidForAuthor == sidForAuthor) .SingleOrDefaultAsync(); if (article == null) { return(articlePage); } articlePage.Archived = article.Archived != ArchivedState.None; if (articlePage.Archived.Value && currentUserId != article.AuthorId && !isOperator) { return(articlePage); } articlePage.PointBasicInfo = await PointBasicInfo.CreateAsync(currentUserId, article.TargetPoint, dbContext, cachedData); articlePage.AuthorBasicInfo = new UserBasicInfo { Id = article.Author.Id, IdCode = article.Author.IdCode, AvatarImage = article.Author.AvatarImage, UserName = article.Author.UserName, FriendCount = await cachedData.Subscriptions.GetFriendCountAsync(article.AuthorId), SubscribedUserCount = await cachedData.Subscriptions .GetSubscribedUserCountAsync(article.AuthorId), SubscriberCount = await cachedData.Subscriptions .GetSubscriberCountAsync(article.AuthorId, SubscriptionTargetType.User), IsFriend = string.IsNullOrWhiteSpace(currentUserId) ? (bool?)null : await cachedData.Users.IsFriendAsync(currentUserId, article.AuthorId), Subscribed = string.IsNullOrWhiteSpace(currentUserId) ? (bool?)null : await cachedData.Subscriptions.IsSubscribedAsync(currentUserId, article.AuthorId, SubscriptionTargetType.User), SteamId = await userManager.GetSteamIdAsync(article.AuthorId) }; if (!string.IsNullOrWhiteSpace(articlePage.AuthorBasicInfo.SteamId)) { articlePage.AuthorBasicInfo.SteamProfileName = article.Author.SteamProfileName; } articlePage.AuthorPlayedTime = article.TargetPoint.SteamAppId == null ? null : (await dbContext.UserSteamGameRecords .Where(r => r.UserId == article.AuthorId && r.SteamAppId == article.TargetPoint.SteamAppId) .SingleOrDefaultAsync())?.TotalPlayedTime; articlePage.Id = article.Id; articlePage.Title = article.Title; articlePage.Subtitle = article.Subtitle; var attachedPointIds = Helpers.SafeDeserialize <List <string> >(article.AttachedPoints) ?? new List <string>(); articlePage.AttachedPoints = (from id in attachedPointIds join point in await(from point in dbContext.Points where attachedPointIds.Contains(point.Id) select new { point.Type, point.Id, point.IdCode, point.AvatarImage, point.ChineseName, point.EnglishName }).ToListAsync() on id equals point.Id select new PointBasicInfo { Type = point.Type, Id = point.Id, IdCode = point.IdCode, AvatarImage = point.AvatarImage, ChineseName = point.ChineseName, EnglishName = point.EnglishName }).ToList(); articlePage.PublishTime = article.PublishTime; articlePage.Rejected = article.Rejected; articlePage.Spotlighted = article.Spotlighted; articlePage.Warned = article.Warned; articlePage.Content = article.Content; articlePage.ReproductionRequirement = Helpers.SafeDeserialize <ReproductionRequirement>(article.ReproductionRequirement); articlePage.LikeCount = await cachedData.Likes.GetTargetLikeCountAsync(article.Id, LikeTargetType.Article); articlePage.Liked = string.IsNullOrWhiteSpace(currentUserId) ? (bool?)null : await cachedData.Likes.IsLikedAsync(currentUserId, article.Id, LikeTargetType.Article); articlePage.Rating = article.Rating; articlePage.CoverImage = article.CoverImage; articlePage.Pros = Helpers.SafeDeserialize <List <string> >(article.Pros); articlePage.Cons = Helpers.SafeDeserialize <List <string> >(article.Cons); articlePage.RecommendedArticles = await RecommendedArticleList.CreateAsync(article.Id, article.AuthorId, article.TargetPointId, dbContext); var comments = await ArticleCommentList.CreateAsync(article, 1, currentUserId, isOperator, true, dbContext, cachedData); articlePage.CommentCount = comments.Item2; articlePage.LatestCommentTime = comments.Item3; articlePage.CommentPageCount = comments.Item4; articlePage.Comments = comments.Item1; return(articlePage); }
/// <summary> /// 创建 <see cref="RecommendedArticleList"/> /// </summary> /// <param name="currentArticleId">当前文章 ID</param> /// <param name="authorId">文章作者 ID</param> /// <param name="pointId">据点 ID</param> /// <param name="dbContext"><see cref="KeylolDbContext"/></param> /// <returns><see cref="RecommendedArticleList"/></returns> public static async Task <RecommendedArticleList> CreateAsync(string currentArticleId, string authorId, string pointId, KeylolDbContext dbContext) { var result = new RecommendedArticleList(3); // 作者的其他文章中,认可最多的文章 var a = await(from article in dbContext.Articles where article.AuthorId == authorId && article.Archived == ArchivedState.None && article.Rejected == false && article.Id != currentArticleId orderby dbContext.Likes .Count(l => l.TargetId == article.Id && l.TargetType == LikeTargetType.Article) descending select new { AuthorIdCode = article.Author.IdCode, article.SidForAuthor, article.CoverImage, article.Title, article.Subtitle }).FirstOrDefaultAsync(); if (a != null) { result.Add(new RecommendedArticle { AuthorIdCode = a.AuthorIdCode, SidForAuthor = a.SidForAuthor, CoverImage = a.CoverImage, Title = a.Title, Subtitle = a.Subtitle }); } // 据点的其他文章中,认可最多的文章 a = await(from article in dbContext.Articles where article.TargetPointId == pointId && article.Archived == ArchivedState.None && article.Rejected == false && article.Id != currentArticleId orderby dbContext.Likes .Count(l => l.TargetId == article.Id && l.TargetType == LikeTargetType.Article) descending select new { AuthorIdCode = article.Author.IdCode, article.SidForAuthor, article.CoverImage, article.Title, article.Subtitle }).FirstOrDefaultAsync(); if (a != null) { result.Add(new RecommendedArticle { AuthorIdCode = a.AuthorIdCode, SidForAuthor = a.SidForAuthor, CoverImage = a.CoverImage, Title = a.Title, Subtitle = a.Subtitle }); } // 作者最近认可过的文章 a = await(from like in dbContext.Likes where like.OperatorId == authorId && like.TargetType == LikeTargetType.Article join article in dbContext.Articles on like.TargetId equals article.Id where article.Archived == ArchivedState.None && article.Rejected == false orderby like.Sid descending select new { AuthorIdCode = article.Author.IdCode, article.SidForAuthor, article.CoverImage, article.Title, article.Subtitle }).FirstOrDefaultAsync(); if (a != null) { result.Add(new RecommendedArticle { AuthorIdCode = a.AuthorIdCode, SidForAuthor = a.SidForAuthor, CoverImage = a.CoverImage, Title = a.Title, Subtitle = a.Subtitle }); } result = new RecommendedArticleList(result.DistinctBy(aa => new { aa.AuthorIdCode, aa.SidForAuthor })); // 广场收稿箱中最近的文章 if (result.Count < 3) { var remaining = 3 - result.Count; var supplies = await(from article in dbContext.Articles where article.Rejected == false && article.Archived == ArchivedState.None && article.Id != currentArticleId orderby article.Sid descending select new { AuthorIdCode = article.Author.IdCode, article.SidForAuthor, article.CoverImage, article.Title, article.Subtitle }).Take(() => remaining).ToListAsync(); result.AddRange(supplies.Select(s => new RecommendedArticle { AuthorIdCode = s.AuthorIdCode, SidForAuthor = s.SidForAuthor, CoverImage = s.CoverImage, Title = s.Title, Subtitle = s.Subtitle })); } return(result); }