/// <summary> /// 删除回答 /// </summary> /// <remarks> /// 1.管理员删除被采纳的回答时,需要将问题状态变更为“待解决” /// 2.注意维护相关问题的回答数,调用UpdateAskQuestion,AnswerCount-- /// 3.注意需要删除动态,通过EventModule处理; /// 4.注意需要扣除增加的积分,通过EventModule处理; /// 5.注意需要删除回答者对问题的关注,通过EventModule处理; /// 6.需要触发的事件:1)Delete的OnBefore、OnAfter;2)审核状态变更 /// </remarks> /// <param name="answer">回答实体</param> public void DeleteAnswer(AskAnswer answer) { EventBus <AskAnswer> .Instance().OnBefore(answer, new CommonEventArgs(EventOperationType.Instance().Delete())); askAnswerRepository.Delete(answer); //更新相关问题的内容 AskQuestion question = askQuestionRepository.Get(answer.QuestionId); question.AnswerCount--; if (answer.IsBest) { question.Status = QuestionStatus.Unresolved; } //调用Service中的Update方法,以触发相应的事件,但是不更新审核状态 this.UpdateQuestion(question, false); //用户计数 OwnerDataService ownerDataService = new OwnerDataService(TenantTypeIds.Instance().User()); ownerDataService.Change(answer.UserId, OwnerDataKeys.Instance().AnswerCount(), -1); EventBus <AskAnswer> .Instance().OnAfter(answer, new CommonEventArgs(EventOperationType.Instance().Delete())); EventBus <AskAnswer, AuditEventArgs> .Instance().OnAfter(answer, new AuditEventArgs(answer.AuditStatus, null)); }
/// <summary> /// 发布问题 /// </summary> /// <remarks> /// 1.用户提问时,悬赏的积分会被冻结,需要先扣除相应的用户积分;同时发布问题会产生新积分 /// 2.注意在EventModule中处理动态、积分、通知、自动关注(提问者自动关注该问题); /// 3.使用AuditService.ChangeAuditStatusForCreate设置审核状态; /// 4.注意调用AttachmentService转换临时附件; /// 5.需要触发的事件:1)Create的OnBefore、OnAfter;2)审核状态变更; /// </remarks> /// <param name="question">问题实体</param> /// <returns>是否创建成功</returns> public bool CreateQuestion(AskQuestion question) { EventBus <AskQuestion> .Instance().OnBefore(question, new CommonEventArgs(EventOperationType.Instance().Create())); //设置审核状态 new AuditService().ChangeAuditStatusForCreate(question.UserId, question); askQuestionRepository.Insert(question); if (question.QuestionId > 0) { //将临时附件转换为正式附件 AttachmentService attachmentService = new AttachmentService(TenantTypeIds.Instance().AskQuestion()); attachmentService.ToggleTemporaryAttachments(question.UserId, TenantTypeIds.Instance().AskQuestion(), question.QuestionId); //用户计数 OwnerDataService ownerDataService = new OwnerDataService(TenantTypeIds.Instance().User()); ownerDataService.Change(question.UserId, OwnerDataKeys.Instance().QuestionCount(), 1); AtUserService atUserService = new AtUserService(TenantTypeIds.Instance().AskQuestion()); atUserService.ResolveBodyForEdit(question.Body, question.UserId, question.QuestionId); EventBus <AskQuestion> .Instance().OnAfter(question, new CommonEventArgs(EventOperationType.Instance().Create())); EventBus <AskQuestion, AuditEventArgs> .Instance().OnAfter(question, new AuditEventArgs(null, question.AuditStatus)); } return(question.QuestionId > 0); }
/// <summary> /// 编辑回答 /// </summary> /// <remarks> /// 1.使用AuditService.ChangeAuditStatusForUpdate设置审核状态; /// 2.需要触发的事件:Update的OnBefore、OnAfter; /// </remarks> /// <param name="answer">回答实体</param> /// <param name="changeAuditStatusForUpdate">是否更新审核状态</param> public void UpdateAnswer(AskAnswer answer, bool changeAuditStatusForUpdate = true) { EventBus <AskAnswer> .Instance().OnBefore(answer, new CommonEventArgs(EventOperationType.Instance().Update())); AuditStatus prevAuditStatus = answer.AuditStatus; //设置审核状态 if (changeAuditStatusForUpdate) { new AuditService().ChangeAuditStatusForUpdate(answer.UserId, answer); } askAnswerRepository.Update(answer); //更新相关问题的内容 AskQuestion question = askQuestionRepository.Get(answer.QuestionId); question.LastAnswerUserId = answer.UserId; question.LastAnswerAuthor = answer.Author; question.LastAnswerDate = answer.DateCreated; if (answer.IsBest) { question.Status = QuestionStatus.Resolved; } //将临时附件转换为正式附件 AttachmentService attachmentService = new AttachmentService(TenantTypeIds.Instance().AskAnswer()); attachmentService.ToggleTemporaryAttachments(answer.UserId, TenantTypeIds.Instance().AskAnswer(), answer.AnswerId); this.UpdateQuestion(question, false); //调用Service中的Update方法,以触发相应的事件,但是不更新审核状态 EventBus <AskAnswer> .Instance().OnAfter(answer, new CommonEventArgs(EventOperationType.Instance().Update())); EventBus <AskAnswer, AuditEventArgs> .Instance().OnAfter(answer, new AuditEventArgs(prevAuditStatus, answer.AuditStatus)); }
/// <summary> /// 创建回答 /// </summary> /// <remarks> /// 1.登录用户可以回答问题 /// 2.问题提问者不得回答自己的问题 /// 3.每个回答者针对每个问题只能回答一次 /// </remarks> public static bool Answer_Create(this Authorizer authorizer, AskQuestion question, out string errorMessage) { errorMessage = string.Empty; IUser currentUser = UserContext.CurrentUser; if (currentUser == null) { errorMessage = "您需要先登录,才能回答"; return(false); } if (question.UserId == currentUser.UserId) { errorMessage = "提问者不可以回答自己的问题"; return(false); } if (question.Status != QuestionStatus.Unresolved) { errorMessage = "只有未解决状态的问题,才能回答"; return(false); } AskAnswer answer = new AskService().GetUserAnswerByQuestionId(currentUser.UserId, question.QuestionId); if (answer != null) { errorMessage = "您已经回答过一次,不可重复回答"; return(false); } bool result = authorizer.AuthorizationService.Check(currentUser, PermissionItemKeys.Instance().Ask_CreateAnswer()); if (!result && currentUser.IsModerated) { errorMessage = Resources.Resource.Description_ModeratedUser_CreateAnswerDenied; } return(result); }
/// <summary> /// 编辑问题 /// </summary> /// <remarks> /// 1.使用AuditService.ChangeAuditStatusForUpdate设置审核状态; /// 2.Repository更新时不处理:IsEssential /// 3.需要触发的事件:Update的OnBefore、OnAfter; /// </remarks> /// <param name="question">问题实体</param> /// <param name="changeAuditStatusForUpdate">是否更新审核状态</param> public void UpdateQuestion(AskQuestion question, bool changeAuditStatusForUpdate = true) { AskQuestion question_beforeUpDate = GetQuestion(question.QuestionId); if (question.Reward != question_beforeUpDate.Reward && question.Reward < (question.User.TradePoints + question_beforeUpDate.Reward)) { question.AddedReward = question.Reward - question_beforeUpDate.Reward; } else { question.AddedReward = 0; } EventBus <AskQuestion> .Instance().OnBefore(question, new CommonEventArgs(EventOperationType.Instance().Update())); AuditStatus prevAuditStatus = question.AuditStatus; //设置审核状态 if (changeAuditStatusForUpdate) { new AuditService().ChangeAuditStatusForUpdate(question.UserId, question); } askQuestionRepository.Update(question); AtUserService atUserService = new AtUserService(TenantTypeIds.Instance().AskQuestion()); atUserService.ResolveBodyForEdit(question.Body, question.UserId, question.QuestionId); EventBus <AskQuestion> .Instance().OnAfter(question, new CommonEventArgs(EventOperationType.Instance().Update())); EventBus <AskQuestion, AuditEventArgs> .Instance().OnAfter(question, new AuditEventArgs(prevAuditStatus, question.AuditStatus)); }
/// <summary> /// 取消问题 /// </summary> /// <param name="question">问题实体</param> public void CancelQuestion(AskQuestion question) { question.Status = QuestionStatus.Canceled; //调用Service中的Update方法,以触发相应的事件,但是不更新审核状态 this.UpdateQuestion(question, false); }
/// <summary> /// 编辑问题/取消问题 /// </summary> /// <remarks> /// 1.如果问题未解决(答案被采纳前),提问者及管理员都可以对问题进行编辑,如果修改悬赏分值仅允许追加悬赏分值 /// 2.如果问题已解决(答案被采纳后),则仅允许管理员对问题进行编辑,不允许修改悬赏分值 /// </remarks> public static bool Question_Edit(this Authorizer authorizer, AskQuestion question) { IUser currentUser = UserContext.CurrentUser; if (currentUser == null) { return(false); } //如果问题未解决 if (question.Status == QuestionStatus.Unresolved) { if (question.UserId == currentUser.UserId || authorizer.IsAdministrator(AskConfig.Instance().ApplicationId)) { return(true); } } //如果问题已解决 if (question.Status == QuestionStatus.Resolved) { if (authorizer.IsAdministrator(AskConfig.Instance().ApplicationId)) { return(true); } } return(false); }
/// <summary> /// 采纳满意回答 /// </summary> /// <remarks> /// 1.如果问题有悬赏则悬赏分值转移到回答者的帐户(如有交易税,需要扣除),通过EventModule实现 /// 2.除了悬赏分的交易,回答被采纳,回答者还会获得新产生的积分,通过EventModule实现 /// 3.注意需要发送通知给问题的关注者,通过EventModule实现 /// 4.需要触发的事件:SetBestAnswer的OnAfter /// </remarks> /// <param name="question">问题实体</param> /// <param name="answer">回答实体</param> public void SetBestAnswer(AskQuestion question, AskAnswer answer) { if (!answer.IsBest) { answer.IsBest = true; //调用Service中的Update方法,以触发相应的事件,但是不更新审核状态 this.UpdateAnswer(answer, false); //todo:jiangshl,改为EventModule处理 //处理威望 OwnerDataService ownerDataService = new OwnerDataService(TenantTypeIds.Instance().User()); //用户获得威望值 PointService pointService = new PointService(); //提问者获取威望值 PointItem questionPointItem = pointService.GetPointItem(PointItemKeys.Instance().Ask_AcceptedAnswer()); ownerDataService.Change(question.UserId, OwnerDataKeys.Instance().UserAskReputation(), questionPointItem.ReputationPoints); //回答者获得威望 PointItem AnswerPointItem = pointService.GetPointItem(PointItemKeys.Instance().Ask_AnswerWereAccepted()); ownerDataService.Change(answer.UserId, OwnerDataKeys.Instance().UserAskReputation(), AnswerPointItem.ReputationPoints); //用户计数 ownerDataService.Change(answer.UserId, OwnerDataKeys.Instance().AnswerAcceptCount(), 1); } }
/// <summary> /// 删除问题 /// </summary> /// <remarks> /// 管理员可以删除问题 /// </remarks> public static bool Question_Delete(this Authorizer authorizer, AskQuestion question) { if (authorizer.IsAdministrator(AskConfig.Instance().ApplicationId)) { return(true); } return(false); }
/// <summary> /// 设置/取消精华问题(管理员操作) /// </summary> /// <remarks> /// 1.精华状态未变化不用进行任何操作 /// 2.在EventModule里处理积分 /// 3.需要触发的事件:加精或取消精华SetEssential的OnAfter /// </remarks> /// <param name="question">问题实体</param> /// <param name="isEssential">是否精华</param> public void SetEssential(AskQuestion question, bool isEssential) { if (question.IsEssential != isEssential) { askQuestionRepository.SetEssential(question, isEssential); string eventOperationType = isEssential ? EventOperationType.Instance().SetEssential() : EventOperationType.Instance().CancelEssential(); EventBus <AskQuestion> .Instance().OnAfter(question, new CommonEventArgs(eventOperationType)); } }
/// <summary> /// 将数据库中的信息转换成EditModel实体 /// </summary> /// <param name="askQuestion">问题实体</param> /// <returns>编辑问题的EditModel</returns> public static AskQuestionEditModel AsEditModel(this AskQuestion askQuestion) { return(new AskQuestionEditModel { QuestionId = askQuestion.QuestionId, Subject = askQuestion.Subject, Body = askQuestion.Body, Reward = askQuestion.Reward, UserId = askQuestion.UserId, QuestionStatus = askQuestion.Status }); }
/// <summary> /// 新建实体时使用 /// </summary> public static AskQuestion New() { AskQuestion question = new AskQuestion() { IsEssential = false, IP = WebUtility.GetIP(), DateCreated = DateTime.UtcNow, LastModified = DateTime.UtcNow }; return(question); }
/// <summary> /// 编辑回答 /// </summary> /// <remarks> /// 1.如果问题已解决(答案被采纳后),不允许回答者编辑,其余情况允许回答者编辑 /// 2.管理员可以编辑所有的回答 /// </remarks> public static bool Answer_Edit(this Authorizer authorizer, AskQuestion question, AskAnswer answer) { if (question.Status == QuestionStatus.Unresolved) { if (UserContext.CurrentUser != null && UserContext.CurrentUser.UserId == answer.UserId) { return(true); } } if (authorizer.IsAdministrator(AskConfig.Instance().ApplicationId)) { return(true); } return(false); }
/// <summary> /// 转换成AskQuestion类型 /// </summary> /// <returns>问题实体</returns> public AskQuestion AsAskQuestion() { AskQuestion askQuestion = null; //发布问题 if (this.QuestionId == 0) { askQuestion = AskQuestion.New(); askQuestion.UserId = UserContext.CurrentUser.UserId; askQuestion.Author = UserContext.CurrentUser.DisplayName; askQuestion.Status = QuestionStatus.Unresolved; if (this.AskUserId > 0) { askQuestion.AskUserId = this.AskUserId; } if (this.OwnerId.HasValue) { askQuestion.OwnerId = this.OwnerId.Value; askQuestion.TenantTypeId = TenantTypeIds.Instance().Group(); } else { askQuestion.OwnerId = 0; askQuestion.TenantTypeId = TenantTypeIds.Instance().User(); } } //编辑问题 else { AskService askService = new AskService(); askQuestion = askService.GetQuestion(this.QuestionId); askQuestion.LastModified = DateTime.UtcNow; } askQuestion.Subject = this.Subject; askQuestion.Body = this.Body; askQuestion.LastModifiedUserId = UserContext.CurrentUser.UserId; askQuestion.LastModifier = UserContext.CurrentUser.DisplayName; if (this.Reward > askQuestion.Reward && this.Reward <= askQuestion.User.TradePoints) { askQuestion.AddedReward = this.Reward - askQuestion.Reward; askQuestion.Reward = this.Reward; } return(askQuestion); }
/// <summary> /// 发布回答 /// </summary> /// <remarks> /// 1.每个回答者针对每个问题只能回答一次,创建回答前需做重复检查 /// 2.注意维护相关问题的回答数,AnswerCount++ /// 3.注意需要在EventModule中处理动态、积分、通知、自动关注(回答者自动关注该问题) /// 4.注意使用AuditService.ChangeAuditStatusForCreate设置审核状态; /// 5.注意调用AttachmentService转换临时附件; /// 6.需要触发的事件:1)Create的OnBefore、OnAfter;2)审核状态变更; /// </remarks> /// <param name="answer">回答实体</param> /// <returns>是否创建成功</returns> public bool CreateAnswer(AskAnswer answer) { //先查询当前用户是否已经回答了指定问题 if (GetUserAnswerByQuestionId(answer.UserId, answer.QuestionId) == null) { EventBus <AskAnswer> .Instance().OnBefore(answer, new CommonEventArgs(EventOperationType.Instance().Create())); //设置审核状态 new AuditService().ChangeAuditStatusForCreate(answer.UserId, answer); askAnswerRepository.Insert(answer); if (answer.AnswerId > 0) { //维护相关问题的内容 AskQuestion question = askQuestionRepository.Get(answer.QuestionId); question.LastAnswerUserId = answer.UserId; question.LastAnswerAuthor = answer.Author; question.LastAnswerDate = answer.DateCreated; question.AnswerCount++; //调用Service中的Update方法,以触发相应的事件,但是不更新审核状态 this.UpdateQuestion(question, false); //将临时附件转换为正式附件 AttachmentService attachmentService = new AttachmentService(TenantTypeIds.Instance().AskAnswer()); attachmentService.ToggleTemporaryAttachments(answer.UserId, TenantTypeIds.Instance().AskAnswer(), answer.AnswerId); //用户回答数计数 OwnerDataService ownerDataService = new OwnerDataService(TenantTypeIds.Instance().User()); ownerDataService.Change(answer.UserId, OwnerDataKeys.Instance().AnswerCount(), 1); EventBus <AskAnswer> .Instance().OnAfter(answer, new CommonEventArgs(EventOperationType.Instance().Create())); EventBus <AskAnswer, AuditEventArgs> .Instance().OnAfter(answer, new AuditEventArgs(null, answer.AuditStatus)); } } return(answer.AnswerId > 0); }
/// <summary> /// 管理员审核问题 /// </summary> /// <remarks> /// 1.审核状态未变化不用进行任何操作; /// 2.审核状态的变化影响动态的生成与删除、积分的变化 /// 3.需要触发的事件:1) 批准或不批准;2) 审核状态变更; /// </remarks> /// <param name="questiongId">问题id</param> /// <param name="isApproved">是否通过审核</param> public void ApproveQuestion(long questiongId, bool isApproved) { AskQuestion question = askQuestionRepository.Get(questiongId); AuditStatus prevAuditStatus = question.AuditStatus; AuditStatus auditStatus = AuditStatus.Fail; if (isApproved) { auditStatus = AuditStatus.Success; } if (question.AuditStatus != auditStatus) { question.AuditStatus = auditStatus; this.UpdateQuestion(question, false); string eventOperationType = isApproved ? EventOperationType.Instance().Approved() : EventOperationType.Instance().Disapproved(); EventBus <AskQuestion> .Instance().OnAfter(question, new CommonEventArgs(eventOperationType)); EventBus <AskQuestion, AuditEventArgs> .Instance().OnAfter(question, new AuditEventArgs(prevAuditStatus, question.AuditStatus)); } }
/// <summary> /// 删除问题 /// </summary> /// <remarks> /// 1.只有管理员可删除问题,已解决问题的积分不返还,未解决的问题应该解除冻结积分,通过EventModule处理; /// 2.注意需要删除动态,通过EventModule处理; /// 3.注意需要扣除发布问题时增加的积分,通过EventModule处理; /// 4.注意需要删除所有用户对该问题的关注,通过EventModule处理; /// 5.注意删除与标签的关联,其它数据的删除由各模块自动处理 /// 6.需要触发的事件:1)Delete的OnBefore、OnAfter;2)审核状态变更 /// </remarks> /// <param name="question">问题实体</param> public void DeleteQuestion(AskQuestion question) { EventBus <AskQuestion> .Instance().OnBefore(question, new CommonEventArgs(EventOperationType.Instance().Delete())); //删除与标签的关联 TagService tagService = new TagService(TenantTypeIds.Instance().AskQuestion()); tagService.ClearTagsFromItem(question.QuestionId, question.UserId); //删除问题的所有回答 int pageSize = 100; int pageIndex = 1; int pageCount = 1; do { PagingDataSet <AskAnswer> answers = this.GetAnswersByQuestionId(question.QuestionId, SortBy_AskAnswer.DateCreated_Desc, pageSize, pageIndex); foreach (AskAnswer answer in answers) { this.DeleteAnswer(answer); } pageCount = answers.PageCount; pageIndex++; } while (pageIndex <= pageCount); //删除问题 askQuestionRepository.Delete(question); OwnerDataService ownerDataService = new OwnerDataService(TenantTypeIds.Instance().User()); ownerDataService.Change(question.UserId, OwnerDataKeys.Instance().QuestionCount(), -1); EventBus <AskQuestion> .Instance().OnAfter(question, new CommonEventArgs(EventOperationType.Instance().Delete())); EventBus <AskQuestion, AuditEventArgs> .Instance().OnAfter(question, new AuditEventArgs(question.AuditStatus, null)); }
/// <summary> /// AskQuestion转换成Document /// </summary> /// <param name="question">问题对象</param> /// <returns>问题对应的document对象</returns> public static Document Convert(AskQuestion question) { //文档初始权重 Document doc = new Document(); //不索引问题审核状态为不通过的、已取消的 if (question.AuditStatus != Tunynet.Common.AuditStatus.Fail && question.Status != QuestionStatus.Canceled) { //索引基本信息 doc.Add(new Field(AskIndexDocument.QuestionId, question.QuestionId.ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field(AskIndexDocument.Author, question.Author.ToLower(), Field.Store.YES, Field.Index.ANALYZED)); doc.Add(new Field(AskIndexDocument.Subject, question.Subject.ToLower(), Field.Store.YES, Field.Index.ANALYZED)); if (!string.IsNullOrWhiteSpace(question.Body)) { doc.Add(new Field(AskIndexDocument.Body, HtmlUtility.StripHtml(question.Body, true, false).ToLower(), Field.Store.NO, Field.Index.ANALYZED)); } doc.Add(new Field(AskIndexDocument.AuditStatus, ((int)question.AuditStatus).ToString(), Field.Store.YES, Field.Index.NOT_ANALYZED)); doc.Add(new Field(AskIndexDocument.DateCreated, DateTools.DateToString(question.DateCreated, DateTools.Resolution.MILLISECOND), Field.Store.YES, Field.Index.NOT_ANALYZED)); //索引问题标签 foreach (var tag in question.Tags) { doc.Add(new Field(AskIndexDocument.Tag, tag.TagName.ToLower(), Field.Store.YES, Field.Index.ANALYZED)); } //循环加入问题的回答 int pageSize = 100; int pageIndex = 1; int pageCount = 1; do { PagingDataSet <AskAnswer> answers = askService.GetAnswersByQuestionId(question.QuestionId, SortBy_AskAnswer.DateCreated_Desc, pageSize, pageIndex); foreach (AskAnswer answer in answers) { Field field = new Field(AskIndexDocument.Answer, HtmlUtility.TrimHtml(answer.Body, 0).ToLower(), Field.Store.NO, Field.Index.ANALYZED); if (answer.IsBest) { field.SetBoost((float)BoostLevel.Hight); } doc.Add(field); } pageCount = answers.PageCount; pageIndex++; } while (pageIndex <= pageCount); } //回答数和悬赏值给文档加权重 float boost = question.AnswerCount + question.Reward + (float)BoostLevel.Low; //已解决问题给文档加权重 if (question.Status == QuestionStatus.Resolved) { boost += (float)BoostLevel.Medium; } //精华问题给文档加权重 if (question.IsEssential) { boost += (float)BoostLevel.Hight; } doc.SetBoost(boost); return(doc); }
/// <summary> /// 创建问题 /// </summary> public static bool Answer_Create(this Authorizer authorizer, AskQuestion question) { string errorMessage = string.Empty; return(authorizer.Answer_Create(question, out errorMessage)); }
/// <summary> /// 更新索引 /// </summary> /// <param name="question">待更新的问答</param> public void Update(AskQuestion question) { Update(new AskQuestion[] { question }); }
/// <summary> /// 添加索引 /// </summary> /// <param name="question">待添加的问答</param> public void Insert(AskQuestion question) { Insert(new AskQuestion[] { question }); }
public void SetTradeStatus(AskQuestion question, bool tradeStatus) { question.IsTrated = tradeStatus; askQuestionRepository.Update(question); }