个人网站建站日记-面试宝典功能

  • 个人网站建站日记-面试宝典功能已关闭评论
  • 17 次浏览
  • A+
所属分类:.NET技术
摘要

目前,关于java的面试相关的,网上可以说是多的数不胜数,但是关于.net的,找来找去却发现很少,并且大部分相似,所以,我这里便想做个关于.net面试相关的功能,所以就我花了好几个周末的时间,毛毛糙糙的算是把这个功能赶了出来,当然也有很多不完善的地方。欢迎大家赏脸哈!现在我把我的实现步骤贴出来分享一下。
因为一个人开发,个人精力以及能力有限,很多地方也会有不好的地方,所以希望大家多多包涵,如果感兴趣的话,可以点进去瞧瞧 https://www.xiandanplay.com/interview-manual

目前,关于java的面试相关的,网上可以说是多的数不胜数,但是关于.net的,找来找去却发现很少,并且大部分相似,所以,我这里便想做个关于.net面试相关的功能,所以就我花了好几个周末的时间,毛毛糙糙的算是把这个功能赶了出来,当然也有很多不完善的地方。欢迎大家赏脸哈!现在我把我的实现步骤贴出来分享一下。
因为一个人开发,个人精力以及能力有限,很多地方也会有不好的地方,所以希望大家多多包涵,如果感兴趣的话,可以点进去瞧瞧 https://www.xiandanplay.com/interview-manual

1.功能需求

大致罗列下需求:

  • 题目分类管理
  • 题目的发布,只要谁登录了网站都可以发布,默认是待审核的,网页只显示 已审核、待审核的功能
  • 题目解析,发布者必须填写自己的对题目的解析,其他人也可以提交参考解析,并且展现出来
  • 对题目解析的查看,如果第一次查看这个题目,需要点击“查看解析”的按钮,如果已登录并且查看过,则第二次就不需要点“查看解析”的按钮了。
  • 支持对题目的标题、难度、标签的查询

2.表(实体)结构设计

这里我就用实体来表示了,因为我是用的ef,基本上用CodeFirst就是表结构了

1.题目表

public class Question : Entity<long>     {         /// <summary>         /// 标题         /// </summary>         public string Title { get; set; }         /// <summary>         /// 类型         /// </summary>         public QuestionTypeEnum QuestionType { get; set; }         /// <summary>         /// 提交人id         /// </summary>         public long UserId { get; set; }         /// <summary>         /// 提交人         /// </summary>         public User User { get; set; }         /// <summary>         /// 题目分类id         /// </summary>         public long? QuestionCategoryId { get; set; }         /// <summary>         /// 题目标签         /// </summary>         public string QuestionTag { get; set; }         /// <summary>         /// 浏览数         /// </summary>         public int BrowserCount { get; set; }         /// <summary>         /// 评论数         /// </summary>         public int CommentCount { get; set; }         /// <summary>         /// 收藏数         /// </summary>         public int CollectCount { get; set; }         /// <summary>         /// 奖励金币         /// </summary>         public int RewardCoin { get; set; }         /// <summary>         /// 是否发布         /// </summary>         public bool IsPublish { get; set; }         /// <summary>         /// 审核状态         /// </summary>         public ApproveStatus ApproveStatus { get; set; }     } 

2.题目解析表

 public class QuestionAnalysis : Entity<long>     {         /// <summary>         /// 题目id         /// </summary>         public long InterviewQuestionId { get; set; }         /// <summary>         /// 解析简要         /// </summary>         public string AnalysisContentDescription { get; set; }         /// <summary>         /// 题目解析         /// </summary>         public string AnalysisContent { get; set; }         /// <summary>         /// 提交人id         /// </summary>         public long UserId { get; set; }         /// <summary>         /// 提交人         /// </summary>         public User User { get; set; }         /// <summary>         /// 评论数         /// </summary>         public int CommentCount { get; set; }         /// <summary>         /// 赞同数         /// </summary>         public int AgreeCount { get; set; }         /// <summary>         /// 反对数         /// </summary>         public int AgainstCount { get; set; }         /// <summary>         /// 是否最佳解析         /// </summary>         public bool? Best { get; set; }         /// <summary>         /// 是否默认         /// </summary>         public bool? IsDefault { get; set; }         /// <summary>         /// 收货金币         /// </summary>         public int? GetCoin { get; set; }         /// <summary>         /// 审核状态         /// </summary>         public ApproveStatus ApproveStatus { get; set; }     } 

3.题目分类表

public class InterviewQuestionCategory: Entity<long>     {         /// <summary>         /// 分类名称         /// </summary>         public string Name { get; set; }         /// <summary>         /// 图标         /// </summary>         public string Icon { get; set; }         /// <summary>         /// 父分类id         /// </summary>         public long? ParentCategoryId { get; set; }         /// <summary>         /// 是否启用         /// </summary>         public bool IsEnable { get; set; }         /// <summary>         ///  排序         /// </summary>         public int SortNo { get; set; }         /// <summary>         /// 描述         /// </summary>         public string Description { get; set; }     } 

大致就罗列这几个主要的吧。

4、业务逻辑实现

业务代码逻辑倒是没有特别复杂,都是写CRUD,一看就会,这里举例部分代码。

递归获取分类树

  public async Task<List<TreeVM>> GetCategoryTreesAsync()         {             List<InterviewQuestionCategory> categorys = await GetCategorys();             return BuildTrees(categorys);         }   private List<TreeVM> BuildTrees(List<InterviewQuestionCategory> interviewQuestionCategories)         {             List<TreeVM> list = new List<TreeVM>();             var roots = interviewQuestionCategories.Where(s => !s.ParentCategoryId.HasValue).OrderBy(s => s.SortNo);             foreach (var root in roots)             {                 TreeVM interviewCategoryTreeVM = new TreeVM();                 interviewCategoryTreeVM.Id = root.Id;                 interviewCategoryTreeVM.Label = root.Name;                 interviewCategoryTreeVM.Icon = root.Icon;                 GetChildrens(root, interviewQuestionCategories, interviewCategoryTreeVM);                 list.Add(interviewCategoryTreeVM);             }             return list;         }          private List<TreeVM> GetChildrens(InterviewQuestionCategory root, List<InterviewQuestionCategory> interviewQuestionCategories, TreeVM interviewCategoryTreeVM = null)         {             var childrens = interviewQuestionCategories.Where(s => s.ParentCategoryId == root.Id).OrderBy(s => s.SortNo);             List<TreeVM> list = new List<TreeVM>();             foreach (var item in childrens)             {                 TreeVM treeVM = new TreeVM();                 treeVM.Id = item.Id;                 treeVM.Label = item.Name;                 treeVM.Icon = item.Icon;                 list.Add(treeVM);                 if (interviewQuestionCategories.Any(s => s.ParentCategoryId == item.Id))                     GetChildrens(item, interviewQuestionCategories, treeVM);             }             interviewCategoryTreeVM.Children = list;             return list;         } 

创建题目

 public async Task<long> SaveQuestion(SaveInterviewQuestionVM saveInterviewQuestion)         {             if (saveInterviewQuestion.IsPublish && string.IsNullOrEmpty(saveInterviewQuestion.AnalysisContent))                 throw new ValidationException("题目解析内容为空");             var questionRepository = unitOfWork.GetRepository<Question>();             var questionAnalysisRepository = unitOfWork.GetRepository<QuestionAnalysis>();             Question question = null;             QuestionAnalysis questionAnalysis = null;             bool isAddQuestion = true;             bool isAddAnalysis = true;             if (saveInterviewQuestion.Id.HasValue)             {                 question = await questionRepository.SelectByIdAsync(saveInterviewQuestion.Id.Value);                 if (question.Id != CurrentLoginUser.UserId)                     throw new ValidationException("无权修改");                 questionAnalysis = await questionAnalysisRepository.Select(s => s.InterviewQuestionId == saveInterviewQuestion.Id.Value && s.IsDefault == true).FirstOrDefaultAsync();                 isAddQuestion = false;             }             else             {                 question = new Question()                 {                     Id = CreateEntityId()                 };             }             question.Title = saveInterviewQuestion.Title;             question.QuestionDifficulty = saveInterviewQuestion.Difficultion;             question.QuestionCategoryId = saveInterviewQuestion.CategoryId;             question.UserId = LoginUserId.Value;             question.ApproveStatus = ApproveStatus.ToPass;             question.IsPublish = saveInterviewQuestion.IsPublish;             question.QuestionType = QuestionTypeEnum.面试题;             if (saveInterviewQuestion.QuestionTags != null && saveInterviewQuestion.QuestionTags.Length > 0)                 question.QuestionTag = string.Join(',', saveInterviewQuestion.QuestionTags);             if (questionAnalysis == null)             {                 questionAnalysis = new QuestionAnalysis();                 questionAnalysis.Id = CreateEntityId();                 questionAnalysis.IsDefault = true;                 questionAnalysis.InterviewQuestionId = question.Id;                 questionAnalysis.UserId = LoginUserId.Value;                 questionAnalysis.ApproveStatus = ApproveStatus.ToPass;                 questionAnalysis.AnalysisContent = saveInterviewQuestion.AnalysisContent;             }             else             {                 questionAnalysis.AnalysisContent = saveInterviewQuestion.AnalysisContent;                 isAddAnalysis = false;             }             if (isAddQuestion)                 await questionRepository.InsertAsync(question);             else                 await questionRepository.UpdateAsync(question);             if (isAddAnalysis)                 await questionAnalysisRepository.InsertAsync(questionAnalysis);             else                 await questionAnalysisRepository.UpdateAsync(questionAnalysis);             await unitOfWork.CommitAsync();             return question.Id;         } 

使用Redis的Set类型处理赞成与反对操作

 public async Task<bool> AgreeFunc(InterviewQuestionAnalysisAgreeVM agreeVM)         {             var cache = CacheClient.CreateClient();             string cacheKey = $"{CacheKey.InterviewQuestionAnalysisAgreeKey}_{agreeVM.InterviewQuestionAnalysisId}";             string cacheValue = $"{agreeVM.AgreeType}_{agreeVM.InterviewQuestionAnalysisId}_{LoginUserId.Value}";             if (agreeVM.AgreeType == 1)             {                 string oldCacheValue = $"2_{agreeVM.InterviewQuestionAnalysisId}_{LoginUserId.Value}";                 cache.SetRemove(cacheKey, oldCacheValue);             }             else             {                 string oldCacheValue = $"1_{agreeVM.InterviewQuestionAnalysisId}_{LoginUserId.Value}";                 cache.SetRemove(cacheKey, oldCacheValue);             }             bool result = cache.AddSet(cacheKey, cacheValue);             if (result)             {                 List<string> setMembers= cache.GetMembersBySetKey(cacheKey);                 int agreeCount = 0;                 int againstCount = 0;                 foreach (var item in setMembers)                 {                     if (item.StartsWith('1'))                         agreeCount += 1;                     else                         againstCount += 1;                 }                 await qaRepository.UpdateAgree(agreeVM.InterviewQuestionAnalysisId, agreeCount, againstCount);                 await unitOfWork.CommitAsync();                 return true;             }             return false;          } 

以上只是部分代码,仅供一下参考,但是也花费了我好多个周末的时间,其它的就不说了,放几个截图看看吧,部分的功能还没完善,这个只是初版。

面试宝典首页图(每日推荐那里还没完成)

个人网站建站日记-面试宝典功能

详细的面试列表界面

个人网站建站日记-面试宝典功能

查看页面

个人网站建站日记-面试宝典功能

提交参考解析的页面

个人网站建站日记-面试宝典功能

作者:程序员奶牛

个人主页:https://www.xiandanplay.com/user/user-home?id=16782377660907520