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

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

1.功能需求

大致罗列下需求:

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

2.表(实体)结构设计

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

1.题目表

public class Question : Entity
{
///


/// 标题
///

public string Title { get; set; }
///
/// 类型
///

public QuestionTypeEnum QuestionType { get; set; }
///
/// 提交人id
///

public long UserId { get; set; }
///
/// 提交人
///

public User User { get; set; }
///
/// 题目分类id
///

public long? QuestionCategoryId { get; set; }
///
/// 题目标签
///

public string QuestionTag { get; set; }
///
/// 浏览数
///

public int BrowserCount { get; set; }
///
/// 评论数
///

public int CommentCount { get; set; }
///
/// 收藏数
///

public int CollectCount { get; set; }
///
/// 奖励金币
///

public int RewardCoin { get; set; }
///
/// 是否发布
///

public bool IsPublish { get; set; }
///
/// 审核状态
///

public ApproveStatus ApproveStatus { get; set; }
}

2.题目解析表

public class QuestionAnalysis : Entity
{
///


/// 题目id
///

public long InterviewQuestionId { get; set; }
///
/// 解析简要
///

public string AnalysisContentDescription { get; set; }
///
/// 题目解析
///

public string AnalysisContent { get; set; }
///
/// 提交人id
///

public long UserId { get; set; }
///
/// 提交人
///

public User User { get; set; }
///
/// 评论数
///

public int CommentCount { get; set; }
///
/// 赞同数
///

public int AgreeCount { get; set; }
///
/// 反对数
///

public int AgainstCount { get; set; }
///
/// 是否最佳解析
///

public bool? Best { get; set; }
///
/// 是否默认
///

public bool? IsDefault { get; set; }
///
/// 收货金币
///

public int? GetCoin { get; set; }
///
/// 审核状态
///

public ApproveStatus ApproveStatus { get; set; }
}

3.题目分类表

public class InterviewQuestionCategory: Entity
{
///


/// 分类名称
///

public string Name { get; set; }
///
/// 图标
///

public string Icon { get; set; }
///
/// 父分类id
///

public long? ParentCategoryId { get; set; }
///
/// 是否启用
///

public bool IsEnable { get; set; }
///
/// 排序
///

public int SortNo { get; set; }
///
/// 描述
///

public string Description { get; set; }
}

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

4、业务逻辑实现

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

递归获取分类树

public async Task<List> GetCategoryTreesAsync()
{
List categorys = await GetCategorys();
return BuildTrees(categorys);
}

private List BuildTrees(List interviewQuestionCategories)
{
List list = new List();
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 GetChildrens(InterviewQuestionCategory root, List interviewQuestionCategories, TreeVM interviewCategoryTreeVM = null)
{
var childrens = interviewQuestionCategories.Where(s => s.ParentCategoryId == root.Id).OrderBy(s => s.SortNo);
List list = new List();
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 SaveQuestion(SaveInterviewQuestionVM saveInterviewQuestion)
{
if (saveInterviewQuestion.IsPublish && string.IsNullOrEmpty(saveInterviewQuestion.AnalysisContent))
throw new ValidationException("题目解析内容为空");
var questionRepository = unitOfWork.GetRepository();
var questionAnalysisRepository = unitOfWork.GetRepository();
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 AgreeFunc(InterviewQuestionAnalysisAgreeVM agreeVM)
{
var cache = CacheClient.CreateClient();
string cacheKey = $"{CacheKey.InterviewQuestionAnalysisAgreeKey}{agreeVM.InterviewQuestionAnalysisId}";
string cacheValue = $"{agreeVM.AgreeType}
{LoginUserId.Value}";
if (agreeVM.AgreeType == 1)
{
string oldCacheValue = $"2
{LoginUserId.Value}";
cache.SetRemove(cacheKey, oldCacheValue);
}
else
{
string oldCacheValue = $"1
_{LoginUserId.Value}";
cache.SetRemove(cacheKey, oldCacheValue);
}
bool result = cache.AddSet(cacheKey, cacheValue);
if (result)
{
List 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;

}

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

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

image

详细的面试列表界面

image

查看页面

image

提交参考解析的页面

image

作者:程序员奶牛

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

posted @ 2024-11-14 20:46  灬丶  阅读(188)  评论(2)    收藏  举报