/// <summary> /// 添加一条评论 /// </summary> /// <param name="personId">评论者ID</param> /// <param name="blogId">评论的BlogID</param> /// <param name="content">评论内容</param> /// <param name="photoContentIds">评论的附件ID(仅限图片)</param> /// <param name="baseCommentId">被评论的CommentID</param> /// <returns></returns> public async Task<Comment> AddCommentAsync(long personId, long blogId, string content, List<long> photoContentIds = null, long? baseCommentId = null) { BlogHandler blogHandler = new BlogHandler(_dbContext); GroupHandler groupHandler = new GroupHandler(_dbContext); PersonHandler perHandler = new PersonHandler(_dbContext); //1. 检查要评论的Blog是否存在。 Blog beCommentBlog = await blogHandler.GetByIdAsync(blogId); //2. 如果为空或者被逻辑删除,则Exception。 if (beCommentBlog == null || beCommentBlog.IsDeleted) { throw new DisplayableException("要评论的Blog不存在或者已经被删除"); } //2.1 自己评论自己的Blog永远可以,所以只需要判断不同的PersonID。 if(beCommentBlog.PersonID != personId) { //3. 检查当前用户是否被该评论Blog的用户加入了黑名单,如果是则不能进行评论。 Group beCommentBlogPersonBlackList = await groupHandler.Include(x => x.GroupMembers).SingleOrDefaultAsync(x => x.PersonID == beCommentBlog.PersonID && x.Type == GroupType.BlackList); if (beCommentBlogPersonBlackList != null && beCommentBlogPersonBlackList.GroupMembers.Count > 0) { bool isBlocked = beCommentBlogPersonBlackList.GroupMembers.Select(x => x.PersonID).Contains(personId); if (isBlocked) { throw new DisplayableException("由于用户设置,你无法回复评论。"); } } //4. 检查评论Blog的用户消息设置,是否允许评论。 Person beCommentBlogPerson = await perHandler.GetByIdAsync(beCommentBlog.PersonID); if (beCommentBlogPerson != null) { //4.1 如果评论只允许关注的人评论,则判断Blog的用户的是否关注了当前用户。 if (beCommentBlogPerson.AllowablePersonForComment == AllowablePersonForComment.FollowerOnly) { //4.2 判断关注的人集合是否已经加载。 if (!_dbContext.Entry(beCommentBlogPerson).Collection(x => x.MyFollowingPersons).IsLoaded) { _dbContext.Entry(beCommentBlogPerson).Collection(x => x.MyFollowingPersons).Load(); } bool isFollow = beCommentBlogPerson.MyFollowingPersons.Select(x => x.FollowingID).Contains(personId); if (!isFollow) { throw new DisplayableException("由于用户设置,你无法回复评论。"); } } //4.3 如果评论只允许粉丝评论,则判断当前用户是否关注了该Blog用户。 else if (beCommentBlogPerson.AllowablePersonForComment == AllowablePersonForComment.FansOnly) { //4.4 判断粉丝集合是否已经加载。 if (!_dbContext.Entry(beCommentBlogPerson).Collection(x => x.MyFans).IsLoaded) { _dbContext.Entry(beCommentBlogPerson).Collection(x => x.MyFans).Load(); } bool isFans = beCommentBlogPerson.MyFans.Select(x => x.FollowerID).Contains(personId); if (!isFans) { throw new DisplayableException("由于用户设置,你无法回复评论。"); } } } //5. 检查评论Blog的用户消息设置,是否允许评论附带图片。 if(photoContentIds != null && photoContentIds.Count > 0) { if(!beCommentBlogPerson.AllowCommentAttachContent) { throw new DisplayableException("由于用户设置,你回复评论无法添加图片。"); } } } using(var dbTransaction = _dbContext.Database.BeginTransaction()) { try { //6. 建立Comment对象并保存。 Comment comment = new Comment() { PersonID = personId, BlogID = blogId, Content = content }; this.Add(comment); await SaveChangesAsync(); //7. 判断是否有图片,有则建立与Comment的关联。 if (photoContentIds != null && photoContentIds.Count > 0) { if(photoContentIds.Count > 6) { throw new DisplayableException("评论最多附件6张图片"); } ContentHandler contentHandler = new ContentHandler(_dbContext); //7.1 判断附件是否为图片。 List<Content> photoContents = await contentHandler.Fetch(x => photoContentIds.Contains(x.ID)).ToListAsync(); if(!photoContents.Any(x => x.Type == ContentType.Photo)) { throw new DisplayableException("评论只能附件图片"); } //7.2 建立Comment与Content的关联。 CommentXContentHandler cxcHandler = new CommentXContentHandler(_dbContext); foreach (var photoContentId in photoContentIds) { CommentXContent cxc = new CommentXContent() { CommentID = comment.ID, ContentID = photoContentId }; cxcHandler.Add(cxc); } await SaveChangesAsync(); } //8. 判断当前评论是否评论Blog里的其他评论,如果是则建立关联。 if(baseCommentId != null) { //8.1 判断被评论ID是否存在。 Comment baseComment = await GetByIdAsync(baseCommentId); if(baseComment == null) { throw new DisplayableException("此评论不存在或者已经被删除"); } //8.2 判断被评论的BlogID是否与当前评论的BlogID一致。 if(baseComment.BlogID != blogId) { throw new DisplayableException("此评论的BlogID与被评论的BlogID不一致"); } //8.3 建立关联。 CommentXCommentHandler cxcHandler = new CommentXCommentHandler(_dbContext); CommentXComment cxc = new CommentXComment() { BaseCommentID = (long)baseCommentId, NewCommentID = comment.ID }; cxcHandler.Add(cxc); await SaveChangesAsync(); } dbTransaction.Commit(); return comment; } catch (Exception) { dbTransaction.Rollback(); throw; } } }
/// <summary> /// 关注 /// </summary> /// <param name="followerId">关注者ID</param> /// <param name="followingId">被关注者ID</param> /// <returns></returns> public async Task<bool> FollowAsync(long followerId, long followingId) { GroupHandler groupHandler = new GroupHandler(_dbContext); PersonXPersonHandler pxpHandler = new PersonXPersonHandler(_dbContext); //1. 检查被关注人黑名单是否存在关注人,若已拉黑,则无法关注。 Group blackGroup = await groupHandler.Include(x => x.GroupMembers).SingleOrDefaultAsync(x => x.PersonID == followingId && x.Type == GroupType.BlackList); if(blackGroup != null && blackGroup.GroupMembers.Count > 0) { bool isInGroupMember = blackGroup.GroupMembers.Select(x => x.PersonID).Contains(followerId); if(isInGroupMember) { throw new DisplayableException("由于用户设置,你无法关注。"); } } //2. 检查关注人的关注名单是否已经关注了。 bool isFollow = await pxpHandler.Fetch(x => x.FollowerID == followerId && x.FollowingID == followingId).SingleOrDefaultAsync() != null; //3. 如果未关注则添加纪录。 if(!isFollow) { PersonXPerson pxp = new PersonXPerson() { FollowerID = followerId, FollowingID = followingId }; pxpHandler.Add(pxp); return await SaveChangesAsync() > 0; } return true; }
/// <summary> /// 获取当前用户关注的人Blog /// </summary> /// <param name="personId">用户ID</param> /// <param name="groupId">组ID</param> /// <returns></returns> public async Task<List<Blog>> GetBlogsAsync(long personId, long? groupId = null, int pageIndex = 1, int pageSize = int.MaxValue) { PersonHandler perHandler = new PersonHandler(_dbContext); GroupHandler groupHandler = new GroupHandler(_dbContext); BlogAccessControlHandler acHandler = new BlogAccessControlHandler(_dbContext); //1. 获取当前用户Person实体,并加载正在关注列表。 Person per = await perHandler.Include(x => x.MyFollowingPersons).SingleOrDefaultAsync(x => x.ID == personId); if(per == null) { throw new DisplayableException("该用户不存在"); } //2. 获取组成员或者已关注的用户ID集合,若指定了GroupID,则获取组里成员ID集合,反则获取已关注的人ID集合。 List<long> perIds = new List<long>(); if(groupId.HasValue) { Group normalGroup = await groupHandler.Include(x => x.GroupMembers).SingleOrDefaultAsync(x => x.ID == groupId); if(normalGroup != null) { if(normalGroup.PersonID != personId) { throw new DisplayableException("该组不属于此用户"); } //2.1 获取指定Group的用户ID集合。 if(normalGroup.GroupMembers.Count > 0) { perIds = normalGroup.GroupMembers.Select(x => x.PersonID).ToList(); } } } else { //2.2 获取当前用户已关注的用户ID集合。 perIds = per.MyFollowingPersons.Select(x => x.FollowingID).ToList(); } //2.3 加上当前用户的ID,提供查询当前用户的Blog。 perIds.Add(personId); //3. 获取当前用户屏蔽名单Group。 Group shieldGroup = await groupHandler.Include(x => x.GroupMembers).SingleOrDefaultAsync(x => x.PersonID == personId && x.Type == GroupType.ShieldList); if (shieldGroup != null && shieldGroup.GroupMembers.Count > 0) { List<long> shieldListIds = shieldGroup.GroupMembers.Select(x => x.PersonID).ToList(); //3.1 过滤屏蔽名单上的用户,不加载屏蔽名单上用户的Blog。 perIds = perIds.Except(shieldListIds).ToList(); } //4. 获取过滤后的用户ID集合的Blog列表,以创建时间降序排序。 List<Blog> blogs = await Fetch(x => perIds.Contains(x.PersonID) && !x.IsDeleted).OrderByDescending(x => x.CreatedDate).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync(); if(blogs.Count > 0) { //5.1 获取排除当前用户ID的BlogIDs集合。 List<long> blogListIds = blogs.Where(x => x.PersonID != personId).Select(x => x.ID).ToList(); //5.2 获取Blog列表的AccessControl(权限控制)列表,排除公开的权限控制。 List<BlogAccessControl> blogAccessControls = await acHandler.Fetch(x => blogListIds.Contains(x.BlogID) && x.AccessLevel != BlogInfoAccessInfo.All).ToListAsync(); foreach (var blogAccessControl in blogAccessControls) { Blog acBlog = blogs.Single(x => x.ID == blogAccessControl.BlogID); //5.3 如果权限控制为仅自己可见,且发表Blog的用户ID不等于当前用户ID,则过滤掉此Blog。 if (blogAccessControl.AccessLevel == BlogInfoAccessInfo.MyselfOnly) { blogs.Remove(acBlog); } //5.4 如果权限控制为群可见,判断此群的人员名单是否包含当前用户,没有则过滤此Blog。 else if (blogAccessControl.AccessLevel == BlogInfoAccessInfo.GroupOnly) { BlogAccessControlXGroupHandler acxgHandler = new BlogAccessControlXGroupHandler(_dbContext); BlogAccessControlXGroup acxGroup = await acxgHandler.Include(x => x.Group, x => x.Group.GroupMembers).SingleOrDefaultAsync(x => x.BlogAccessControlID == blogAccessControl.ID); if (acxGroup != null) { bool isInGroupMember = false; if (acxGroup.Group != null && acxGroup.Group.GroupMembers.Count > 0) { isInGroupMember = acxGroup.Group.GroupMembers.Select(x => x.PersonID).Any(x => x == personId); } if (!isInGroupMember) { blogs.Remove(acBlog); } } } //5.5 如果权限控制为朋友圈可见,判断当前用户是否与互相关注(Friends),如果不是则过滤此Blog。 else if (blogAccessControl.AccessLevel == BlogInfoAccessInfo.FriendOnly) { PersonXPersonHandler pxpHandler = new PersonXPersonHandler(_dbContext); bool isFriend = await pxpHandler.IsFriendAsync(personId, acBlog.PersonID); if (!isFriend) { blogs.Remove(acBlog); } } } } return blogs; }