Browse Source

增加试题管理

guqiang 1 tháng trước cách đây
mục cha
commit
65b529e554
22 tập tin đã thay đổi với 516 bổ sung46 xóa
  1. 9 0
      src/Exam.Infrastructure.Data/Entity/EntityQueryRequest.cs
  2. 6 0
      src/Exam.Infrastructure.Validation/Validation/ErrorMessage.cs
  3. 68 4
      src/Hotline.Api/Controllers/Exam/QuestionController.cs
  4. 8 0
      src/Hotline.Application/Exam/Constants/ApiRoutes/QuestionApiRoute.cs
  5. 276 6
      src/Hotline.Application/Exam/Service/Questions/QuestionService.cs
  6. 1 1
      src/Hotline.Repository.SqlSugar/Exam/Repositories/ExamManages/ExamTagRepository.cs
  7. 23 4
      src/Hotline.Repository.SqlSugar/Exam/Repositories/ExamRepository.cs
  8. 1 1
      src/Hotline.Repository.SqlSugar/Exam/Repositories/Questions/QuestionRepository.cs
  9. 1 1
      src/Hotline.Repository.SqlSugar/Exam/Repositories/Sourcewares/SourcewareCategoryRepository.cs
  10. 1 1
      src/Hotline.Repository.SqlSugar/Exam/Repositories/Sourcewares/SourcewareRepository.cs
  11. 33 1
      src/Hotline.Repository.SqlSugar/Exam/Validators/ExamManages/ExamTagValidator.cs
  12. 3 0
      src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionAnswerValidator.cs
  13. 4 0
      src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionKnowladgeValidator.cs
  14. 3 0
      src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionOptionsValidator.cs
  15. 4 0
      src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionSourcewareValidator.cs
  16. 3 0
      src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionTagValidator.cs
  17. 17 3
      src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionValidator.cs
  18. 4 0
      src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/TagQuestionValidator.cs
  19. 33 3
      src/Hotline.Repository.SqlSugar/Exam/Validators/Sourcewares/SourcewareCategoryValidator.cs
  20. 12 2
      src/Hotline.Repository.SqlSugar/Exam/Validators/Sourcewares/SourcewareValidator.cs
  21. 0 19
      src/Hotline.Repository.SqlSugar/Interfaces/IExamTagRepository.cs
  22. 6 0
      src/Hotline.Share/Dtos/Questions/QuestionSourcewareDto.cs

+ 9 - 0
src/Exam.Infrastructure.Data/Entity/EntityQueryRequest.cs

@@ -1,4 +1,6 @@
 using System.ComponentModel;
+using System.Linq.Expressions;
+using System.Text.Json.Serialization;
 
 namespace Exam.Infrastructure.Data.Entity
 {
@@ -15,5 +17,12 @@ namespace Exam.Infrastructure.Data.Entity
         /// </summary>
         [Description("主键集合")]
         public List<string> Ids { get; set; }
+
+        /// <summary>
+        /// 查询表达式
+        /// </summary>
+        [Description("查询表达式")]
+        [JsonIgnore]
+        public LambdaExpression Expression { get; set; }
     }
 }

+ 6 - 0
src/Exam.Infrastructure.Validation/Validation/ErrorMessage.cs

@@ -95,6 +95,12 @@
         public const string EmptyUploadFile = "上传文件件为空";
 
         public const string ServiceError = "服务错误";
+
+        public const string IsRefrence = "{0}({1})正在被使用,不可以删除";
+
+        public const string IsSimpleRefrence = "{0}正在被使用,不可以删除";
+
+        public const string RequestFail = "请求失败!";
     }
 
     public static class RegexConstant

+ 68 - 4
src/Hotline.Api/Controllers/Exam/QuestionController.cs

@@ -1,23 +1,87 @@
 using Exam.Application.Interface.Questions;
+using Exam.Infrastructure.Data.Entity;
+using Exam.Infrastructure.Data.Extensions;
+using Exam.Share.ViewResponses.Question;
+using Hotline.Application.Exam.Constants.ApiRoutes;
 using Hotline.Share.Dtos.Questions;
-using Microsoft.AspNetCore.Authorization;
+using Hotline.Share.Requests.Question;
 using Microsoft.AspNetCore.Mvc;
+using XF.Domain.Authentications;
 
 namespace Hotline.Api.Controllers.Exam
 {
     public class QuestionController : BaseController
     {
         private readonly IQuestionService _questionService;
-        public QuestionController(IQuestionService questionService)
+        private readonly ISessionContext _sessionContext;
+        public QuestionController(IQuestionService questionService,ISessionContext sessionContext)
         {
             _questionService = questionService;
+            _sessionContext = sessionContext;
         }
 
-        [HttpPost]
-        [AllowAnonymous]
+        /// <summary>
+        /// 新增题库
+        /// </summary>
+        /// <param name="questionDto"></param>
+        /// <returns></returns>
+        [HttpPost(QuestionApiRoute.Add)]
         public async Task Add([FromBody] QuestionDto questionDto)
         {
+            questionDto.InitRequest(_sessionContext);
             await _questionService.AddAsync(questionDto, HttpContext.RequestAborted);
         }
+
+        /// <summary>
+        /// 修改题库
+        /// </summary>
+        /// <param name="questionDto"></param>
+        /// <returns></returns>
+        [HttpPut(QuestionApiRoute.Update)]
+        public async Task Update([FromBody] QuestionDto questionDto)
+        {
+            questionDto.InitRequest(_sessionContext);
+            await _questionService.UpdateAsync(questionDto, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 删除题库
+        /// </summary>
+        /// <param name="entityQueryRequest"></param>
+        /// <returns></returns>
+        [HttpDelete(QuestionApiRoute.Delete)]
+        public async Task Delete([FromBody] EntityQueryRequest entityQueryRequest)
+        {
+            await _questionService.DeleteAsync(entityQueryRequest, HttpContext.RequestAborted);
+        }
+
+        /// <summary>
+        /// 获取题库分页列表
+        /// </summary>
+        /// <param name="questionPagedRequest"></param>
+        /// <returns></returns>
+        [HttpPost(QuestionApiRoute.GetPagedList)]
+        public async Task<QuestionPageViewResponse> GetPagedList([FromBody] QuestionPagedRequest questionPagedRequest)
+        {
+            var questionPageViewResponse = await _questionService.GetPagedListAsync(questionPagedRequest);
+
+            return questionPageViewResponse as QuestionPageViewResponse;
+        }
+
+        /// <summary>
+        /// 获取题库
+        /// </summary>
+        /// <param name="id"></param>
+        /// <returns></returns>
+        [HttpGet(QuestionApiRoute.Get)]
+        public async Task<QuestionDto> Get(string id)
+        {
+            var questionDto = await _questionService.GetAsync(new EntityQueryRequest
+            {
+                Id = id
+            });
+
+            return questionDto;
+        }
     }
 }

+ 8 - 0
src/Hotline.Application/Exam/Constants/ApiRoutes/QuestionApiRoute.cs

@@ -0,0 +1,8 @@
+using Exam.Infrastructure.Web.Constants;
+
+namespace Hotline.Application.Exam.Constants.ApiRoutes
+{
+    public class QuestionApiRoute:ApiRoute
+    {
+    }
+}

+ 276 - 6
src/Hotline.Application/Exam/Service/Questions/QuestionService.cs

@@ -9,6 +9,7 @@ using Exam.Repository.Sqlsugar;
 using Exam.Repository.Sqlsugar.Repositories;
 using Exam.Share.ViewResponses.Question;
 using Hotline.Application.Exam.QueryExtensions.Questions;
+using Hotline.Exams.Sourcewares;
 using Hotline.Repository.SqlSugar;
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Repository.SqlSugar.Exam.Interfaces.Questions;
@@ -16,6 +17,7 @@ using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Share.Dtos.Questions;
 using Hotline.Share.Requests.Question;
 using Mapster;
+using SqlSugar;
 using XF.Domain.Dependency;
 
 namespace Hotline.Application.Exam.Service.Questions
@@ -58,6 +60,16 @@ namespace Hotline.Application.Exam.Service.Questions
 
             var questionDto = entity.Adapt<QuestionDto>();
 
+            questionDto.QuestionTagDtos = await GetQuestionTags(entityQueryRequest);
+
+            questionDto.QuestionAnswerDto = await GetQuestionAnswer(entityQueryRequest);
+
+            questionDto.QuestionKnowladgeDtos = await GetKnowladges(entityQueryRequest);
+
+            questionDto.QuestionOptionsDtos = await GetQuestionOptions(entityQueryRequest);
+
+            questionDto.QuestionSourcewareDtos = await GetQuestionSourcewares(entityQueryRequest);
+
             return questionDto;
         }
 
@@ -67,7 +79,7 @@ namespace Hotline.Application.Exam.Service.Questions
             var questionTable = _repository.Queryable().Where(expression);
 
             var questionTagExpression = queryRequest.GetQuestionTagExpression();
-            var questionTagTable = new ExamRepository<QuestionTag>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(questionTagExpression);
+            var questionTagTable = _questionTagRepository.Queryable().Where(questionTagExpression);
 
             var examTagExpression = queryRequest.GetExamTagExpression();
             var examTagTable = new ExamRepository<ExamTag>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(examTagExpression);
@@ -138,6 +150,36 @@ namespace Hotline.Application.Exam.Service.Questions
 
             await AddSourcewares(actionRequest, cancellationToken);
         }
+
+        public override async Task UpdateAsync(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            await base.UpdateAsync(actionRequest, cancellationToken);
+
+            await ModifyQuestionTags(actionRequest, cancellationToken);
+
+            await ModifyQuestionOptions(actionRequest, cancellationToken);
+
+            await ModifyQuestionAnswer(actionRequest, cancellationToken);
+
+            await ModifyKnowladges(actionRequest, cancellationToken);
+
+            await ModifySourcewares(actionRequest, cancellationToken);
+        }
+
+        public override async Task DeleteAsync(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
+        {
+            await base.DeleteAsync(entityQueryRequest, cancellationToken);
+
+            await DeleteQuestionTags(entityQueryRequest, cancellationToken);
+
+            await DeleteQuestionOptions(entityQueryRequest, cancellationToken);
+
+            await DeleteQuestionAnswer(entityQueryRequest, cancellationToken);
+
+            await DeleteKnowladges(entityQueryRequest, cancellationToken);
+
+            await DeleteSourcewares(entityQueryRequest, cancellationToken);
+        }
         #endregion
 
         #region private method
@@ -151,7 +193,6 @@ namespace Hotline.Application.Exam.Service.Questions
 
             await _questionTagRepository.AddWithValidateAsync(questionTags, cancellationToken);
         }
-
         private async Task AddQuestionOptions(QuestionDto actionRequest, CancellationToken cancellationToken)
         {
             if (actionRequest.QuestionOptionsDtos == null) return;
@@ -166,7 +207,6 @@ namespace Hotline.Application.Exam.Service.Questions
 
             await _questionOptionRepository.AddWithValidateAsync(questionOptionses, cancellationToken);
         }
-
         private async Task AddQuestionAnswer(QuestionDto actionRequest, CancellationToken cancellationToken)
         {
             if (actionRequest.QuestionAnswerDto == null) return;
@@ -187,13 +227,12 @@ namespace Hotline.Application.Exam.Service.Questions
         {
             if (actionRequest.QuestionSourcewareDtos == null) return;
 
-            var questionSourcewares = actionRequest.QuestionSourcewareDtos.Where(x=>x.OperationStatus == OperationStatus.Add).Adapt<QuestionSourceware>();
+            var questionSourcewares = actionRequest.QuestionSourcewareDtos.Where(x => x.OperationStatus == OperationStatus.Add).Adapt<QuestionSourceware>();
 
             questionSourcewares.ToInsert(actionRequest);
 
-            await _questionSourcewareRepository.AddWithValidateAsync(questionSourcewares,cancellationToken);
+            await _questionSourcewareRepository.AddWithValidateAsync(questionSourcewares, cancellationToken);
         }
-
         private async Task AddKnowladges(QuestionDto actionRequest, CancellationToken cancellationToken)
         {
             if (actionRequest.QuestionKnowladgeDtos == null) return;
@@ -204,6 +243,237 @@ namespace Hotline.Application.Exam.Service.Questions
 
             await _questionKnowladgeRepository.AddWithValidateAsync(questionKnowladges, cancellationToken);
         }
+        private async Task UpdateSourcewares(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            if (actionRequest.QuestionSourcewareDtos == null) return;
+
+            var questionSourcewares = actionRequest.QuestionSourcewareDtos.Where(x => x.OperationStatus == OperationStatus.Add).Adapt<QuestionSourceware>();
+
+            questionSourcewares.ToUpdate(actionRequest);
+
+            await _questionSourcewareRepository.UpdateWithValidateAsync(questionSourcewares, cancellationToken);
+        }
+        private async Task UpdateKnowladges(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            if (actionRequest.QuestionKnowladgeDtos == null) return;
+
+            var questionKnowladges = actionRequest.QuestionKnowladgeDtos.Where(x => x.OperationStatus == OperationStatus.Add).Adapt<QuestionKnowladge>();
+
+            questionKnowladges.ToUpdate(actionRequest);
+
+            await _questionKnowladgeRepository.UpdateWithValidateAsync(questionKnowladges, cancellationToken);
+        }
+        private async Task UpdateQuestionAnswer(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            if (actionRequest.QuestionAnswerDto == null) return;
+
+            // 简单和填空没有选项
+            if (actionRequest.QuestionType == Share.Enums.Exams.EQuestionType.Multi
+                || actionRequest.QuestionType == Share.Enums.Exams.EQuestionType.Single
+                || actionRequest.QuestionType == Share.Enums.Exams.EQuestionType.Judge) return;
+
+            var questionAnswer = actionRequest.QuestionAnswerDto.Adapt<QuestionAnswer>();
+
+            questionAnswer.ToUpdate(actionRequest);
+
+            await _questionAnswerRepository.UpdateWithValidateAsync(questionAnswer, cancellationToken);
+        }
+        private async Task UpdateQuestionOptions(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            if (actionRequest.QuestionOptionsDtos == null) return;
+
+            // 简单和填空没有选项
+            if (actionRequest.QuestionType == Share.Enums.Exams.EQuestionType.Essay || actionRequest.QuestionType == Share.Enums.Exams.EQuestionType.Blank)
+                return;
+
+            var questionOptionses = actionRequest.QuestionOptionsDtos.Where(x => x.OperationStatus == OperationStatus.Add).Adapt<QuestionOptions>();
+
+            questionOptionses.ToUpdate(actionRequest);
+
+            await _questionOptionRepository.UpdateWithValidateAsync(questionOptionses, cancellationToken);
+        }
+        private async Task UpdateQuestionTags(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            if (actionRequest.QuestionTagDtos == null) return;
+
+            var questionTags = actionRequest.QuestionTagDtos.Where(x => x.OperationStatus == OperationStatus.Update).Adapt<QuestionTag>();
+
+            questionTags.ToUpdate(actionRequest);
+
+            await _questionTagRepository.UpdateWithValidateAsync(questionTags, cancellationToken);
+        }
+        private async Task DeleteSourcewares(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
+        {
+            await _questionSourcewareRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
+        }
+        private async Task DeleteKnowladges(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
+        {
+            await _questionKnowladgeRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
+        }
+        private async Task DeleteQuestionAnswer(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
+        {
+            await _questionAnswerRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
+        }
+        private async Task DeleteQuestionOptions(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
+        {
+            await _questionOptionRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
+        }
+        private async Task DeleteQuestionTags(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
+        {
+            await _questionTagRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
+        }
+        private async Task ModifySourcewares(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            await AddSourcewares(actionRequest, cancellationToken);
+
+            await UpdateSourcewares(actionRequest, cancellationToken);
+
+            Expressionable<QuestionSourceware> expressionable = new Expressionable<QuestionSourceware>();
+            var questionSourcewareDtos = actionRequest.QuestionSourcewareDtos.Where(x => x.OperationStatus == OperationStatus.Delete);
+            expressionable.AndIF(questionSourcewareDtos.Any(), x => questionSourcewareDtos.Select(m => m.Id).Contains(x.Id));
+
+            var entityQueryRequest = new EntityQueryRequest
+            {
+                Expression = expressionable.ToExpression()
+            };
+
+            await DeleteSourcewares(entityQueryRequest, cancellationToken);
+        }
+
+        private async Task ModifyKnowladges(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            await AddKnowladges(actionRequest, cancellationToken);
+
+            await UpdateKnowladges(actionRequest, cancellationToken);
+
+            Expressionable<QuestionKnowladge> expressionable = new Expressionable<QuestionKnowladge>();
+            var questionKnowladgeDtos = actionRequest.QuestionKnowladgeDtos.Where(x => x.OperationStatus == OperationStatus.Delete);
+            expressionable.AndIF(questionKnowladgeDtos.Any(), x => questionKnowladgeDtos.Select(m => m.Id).Contains(x.Id));
+
+            var entityQueryRequest = new EntityQueryRequest
+            {
+                Expression = expressionable.ToExpression()
+            };
+
+            await DeleteKnowladges(entityQueryRequest, cancellationToken);
+        }
+
+        private async Task ModifyQuestionAnswer(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            await AddQuestionAnswer(actionRequest, cancellationToken);
+
+            await UpdateQuestionAnswer(actionRequest, cancellationToken);
+
+            if (actionRequest.QuestionAnswerDto != null && actionRequest.QuestionAnswerDto.OperationStatus == OperationStatus.Delete)
+            {
+                var entityQueryRequest = new EntityQueryRequest
+                {
+                    Id = actionRequest.QuestionAnswerDto?.Id
+                };
+
+                await DeleteQuestionAnswer(entityQueryRequest, cancellationToken);
+            }
+
+        }
+
+        private async Task ModifyQuestionOptions(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            await AddQuestionOptions(actionRequest, cancellationToken);
+
+            await UpdateQuestionOptions(actionRequest, cancellationToken);
+
+            Expressionable<QuestionOptions> expressionable = new Expressionable<QuestionOptions>();
+            var questionSourcewareDtos = actionRequest.QuestionOptionsDtos.Where(x => x.OperationStatus == OperationStatus.Delete);
+            expressionable.AndIF(questionSourcewareDtos.Any(), x => questionSourcewareDtos.Select(m => m.Id).Contains(x.Id));
+
+            var entityQueryRequest = new EntityQueryRequest
+            {
+                Expression = expressionable.ToExpression()
+            };
+
+            await DeleteQuestionOptions(entityQueryRequest, cancellationToken);
+        }
+
+        private async Task ModifyQuestionTags(QuestionDto actionRequest, CancellationToken cancellationToken)
+        {
+            await AddQuestionTags(actionRequest, cancellationToken);
+
+            await UpdateQuestionTags(actionRequest, cancellationToken);
+
+            Expressionable<QuestionTag> expressionable = new Expressionable<QuestionTag>();
+            var questionSourcewareDtos = actionRequest.QuestionTagDtos.Where(x => x.OperationStatus == OperationStatus.Delete);
+            expressionable.AndIF(questionSourcewareDtos.Any(), x => questionSourcewareDtos.Select(m => m.Id).Contains(x.Id));
+
+            var entityQueryRequest = new EntityQueryRequest
+            {
+                Expression = expressionable.ToExpression()
+            };
+
+            await DeleteQuestionTags(entityQueryRequest, cancellationToken);
+        }
+
+
+
+        private async Task<List<QuestionSourcewareDto>> GetQuestionSourcewares(EntityQueryRequest entityQueryRequest)
+        {
+            var questionSourcewareTable = _questionSourcewareRepository.Queryable().Where(x => x.QuestionId == entityQueryRequest.Id);
+
+            var sourcewareTable = new ExamRepository<Sourceware>(_questionSourcewareRepository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
+
+            var questionSourcewares = questionSourcewareTable.InnerJoin(sourcewareTable, (q, s) =>
+              q.SourcewareId == s.Id).Select((q, s) => new QuestionSourcewareDto
+              {
+                  Id = q.Id,
+                  SourcewareId = q.SourcewareId,
+                  Sourceware = s.Name
+              });
+
+            return await questionSourcewares.ToListAsync();
+        }
+
+        private async Task<List<QuestionOptionsDto>> GetQuestionOptions(EntityQueryRequest entityQueryRequest)
+        {
+            var questionOptionTable = await _questionOptionRepository.Queryable().Where(x => x.QuestionId == entityQueryRequest.Id).ToListAsync();
+
+            var questionOptions = questionOptionTable.Adapt<List<QuestionOptionsDto>>();
+
+            return questionOptions;
+        }
+
+        private async Task<List<QuestionKnowladgeDto>> GetKnowladges(EntityQueryRequest entityQueryRequest)
+        {
+            var questionKnowladgeTable = await _questionKnowladgeRepository.Queryable().Where(x => x.QuestionId == entityQueryRequest.Id).ToListAsync();
+
+            var questionKnowladges = questionKnowladgeTable.Adapt<List<QuestionKnowladgeDto>>();
+
+            return questionKnowladges;
+        }
+
+        private async Task<QuestionAnswerDto> GetQuestionAnswer(EntityQueryRequest entityQueryRequest)
+        {
+            var questionAnswer = await _questionAnswerRepository.GetAsync(entityQueryRequest.Id);
+
+            var questionAnswerDto = questionAnswer.Adapt<QuestionAnswerDto>();
+
+            return questionAnswerDto;
+        }
+
+        private async Task<List<QuestionTagDto>> GetQuestionTags(EntityQueryRequest entityQueryRequest)
+        {
+            var questionTags = _questionTagRepository.Queryable().Where(x => x.QuestionId == entityQueryRequest.Id);
+
+            var examTags = new ExamRepository<ExamTag>(_questionTagRepository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
+
+            var questionTagDtos = questionTags.InnerJoin(examTags, (q, t) => q.TagId == t.Id).Select((q, t) => new QuestionTagDto
+            {
+                Id = q.Id,
+                TagId = q.TagId,
+                Tag = t.Name,
+                QuestionId = q.QuestionId
+            });
+
+            return await questionTagDtos.ToListAsync();
+        }
         #endregion
     }
 }

+ 1 - 1
src/Hotline.Repository.SqlSugar/Exam/Repositories/ExamManages/ExamTagRepository.cs

@@ -20,7 +20,7 @@ namespace Exam.Repository.Sqlsugar
     {
         public ExamTagRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
         {
-            Validator = new ExamTagValidator();
+            Validator = new ExamTagValidator(this,dataPermissionFilterBuilder, serviceProvider);
         }
 
         public async Task<List<ExamTag>> GetTreeAsync(Expression<Func<ExamTag, bool>> expression)

+ 23 - 4
src/Hotline.Repository.SqlSugar/Exam/Repositories/ExamRepository.cs

@@ -1,4 +1,5 @@
 using Exam.Infrastructure.Data.Entity;
+using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Exceptions;
 using Exam.Infrastructure.Validation.Extensions;
 using Exam.Infrastructure.Validation.Validation;
@@ -7,8 +8,10 @@ using Hotline.Repository.SqlSugar;
 using Hotline.Repository.SqlSugar.DataPermissions;
 using Hotline.Repository.SqlSugar.Interface;
 using SqlSugar;
+using System.Linq.Expressions;
 using XF.Domain.Entities;
 using XF.Domain.Exceptions;
+using XF.Domain.Repository;
 
 namespace Exam.Repository.Sqlsugar.Repositories
 {
@@ -46,17 +49,33 @@ namespace Exam.Repository.Sqlsugar.Repositories
         }
 
         public async Task DeleteWithValidateAsync(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
-        {
+        {          
+
             if (entityQueryRequest.Ids != null && entityQueryRequest.Ids.Any())
             {
                 var entities = await base.QueryAsync(x => entityQueryRequest.Ids.Contains(x.Id));
 
+                await DoValidationAsync(entities, ValidatorTypeConstants.Remove);
+
                 await base.RemoveRangeAsync(entities, cancellationToken);
             }
-            else
+            else if(entityQueryRequest.Id.IsNotNullOrEmpty())
             {
+                var entity = new TEntity();
+                entity.Id = entityQueryRequest.Id;
+
+                await DoValidationAsync(entity, ValidatorTypeConstants.Remove);
+
                 await base.RemoveAsync(entityQueryRequest.Id);
             }
+            else
+            {
+                var entities = await base.QueryAsync((Expression<Func<TEntity, bool>>)entityQueryRequest.Expression);
+
+                await DoValidationAsync(entities, ValidatorTypeConstants.Remove);
+
+                await base.RemoveAsync((Expression<Func<TEntity, bool>>)entityQueryRequest.Expression, false, cancellationToken);
+            }
         }
 
         public async Task UpdateWithValidateAsync(TEntity entity, CancellationToken cancellationToken)
@@ -89,7 +108,7 @@ namespace Exam.Repository.Sqlsugar.Repositories
             if (!validatorResult.IsValid)
             {
                 var errorMessages = validatorResult.ErrorItems.Select(x => x.ErrorMessage);
-                throw new UserFriendlyException(string.Join(";", errorMessages));
+                throw new UserFriendlyException(ErrorMessage.RequestFail,string.Join(";", errorMessages));
             }
         }
 
@@ -115,7 +134,7 @@ namespace Exam.Repository.Sqlsugar.Repositories
             if (domainException.ValidationErrors.ErrorItems.Any())
             {
                 var errorMessages = domainException.ValidationErrors.ErrorItems.Select(x => x.ErrorMessage);
-                throw new UserFriendlyException(string.Join(";", errorMessages));
+                throw new UserFriendlyException(ErrorMessage.RequestFail, string.Join(";", errorMessages));
             }
         }
         #endregion

+ 1 - 1
src/Hotline.Repository.SqlSugar/Exam/Repositories/Questions/QuestionRepository.cs

@@ -18,7 +18,7 @@ namespace Exam.Repository.Sqlsugar
     {
         public QuestionRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
         {
-            Validator = new QuestionValidator();
+            Validator = new QuestionValidator(this);
         }
     }
 }

+ 1 - 1
src/Hotline.Repository.SqlSugar/Exam/Repositories/Sourcewares/SourcewareCategoryRepository.cs

@@ -20,7 +20,7 @@ namespace Exam.Repository.Sqlsugar.Repositories.Sourcewares
     {
         public SourcewareCategoryRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
         {
-            Validator = new SourcewareCategoryValidator();
+            Validator = new SourcewareCategoryValidator(this,dataPermissionFilterBuilder,serviceProvider);
         }
 
         /// <summary>

+ 1 - 1
src/Hotline.Repository.SqlSugar/Exam/Repositories/Sourcewares/SourcewareRepository.cs

@@ -17,7 +17,7 @@ namespace Exam.Repository.Sqlsugar.Repositories.Sourcewares
     {
         public SourcewareRepository(ISugarUnitOfWork<HotlineDbContext> uow, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider) : base(uow, dataPermissionFilterBuilder, serviceProvider)
         {
-            Validator = new SourcewareValidator();
+            Validator = new SourcewareValidator(this);
         }
     }
 }

+ 33 - 1
src/Hotline.Repository.SqlSugar/Exam/Validators/ExamManages/ExamTagValidator.cs

@@ -1,15 +1,29 @@
 using Exam.ExamManages;
 using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
+using Exam.Practices;
+using Exam.Questions;
+using Exam.Repository.Sqlsugar.Repositories;
+using Exam.TestPapers;
 using FluentValidation;
+using Hotline.Exams.Sourcewares;
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages;
 using Hotline.Repository.SqlSugar.Validate;
 
 namespace Exam.Repository.Sqlsugar.Validators.ExamManages
 {
     public class ExamTagValidator:BaseValidator<ExamTag>
     {
-        public ExamTagValidator()
+        private readonly IExamTagRepository _examTagRepository;
+        private readonly IDataPermissionFilterBuilder _dataPermissionFilterBuilder;
+        private readonly IServiceProvider _serviceProvider;
+        public ExamTagValidator(IExamTagRepository examTagRepository, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider)
         {
+            _examTagRepository = examTagRepository;
+            _dataPermissionFilterBuilder = dataPermissionFilterBuilder;
+            _serviceProvider = serviceProvider;
+
             RuleSet(ValidatorTypeConstants.Create, () =>
             {
                 BaseValidateRule();
@@ -23,6 +37,11 @@ namespace Exam.Repository.Sqlsugar.Validators.ExamManages
 
                 ValidateRuleWithModify();
             });
+
+            RuleSet(ValidatorTypeConstants.Remove, () =>
+            {
+                ValidateRuleWithRemove();
+            });
         }
 
         protected override void BaseValidateRule()
@@ -34,13 +53,26 @@ namespace Exam.Repository.Sqlsugar.Validators.ExamManages
         {
             base.ValidateRuleWithAdd();
             RuleFor(m => m.CreationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.CreationTime))));
+            RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.Name))));
+            RuleFor(m => m.ParentId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.ParentId))));
+            RuleFor(m => m.Name).Must(v => !_examTagRepository.Queryable().Any(x => x.Name == v)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamTag.Name))));
         }
 
         protected override void ValidateRuleWithModify()
         {
             base.ValidateRuleWithModify();
             RuleFor(m => m.LastModificationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.LastModificationTime))));
+            RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.Name))));
+            RuleFor(m => m.ParentId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.ParentId))));
+            RuleFor(m => m.Name).Must((t, v) => !_examTagRepository.Queryable().Any(x => x.Name == v && x.Id != t.Id)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamTag.Name))));
+        }
 
+        private void ValidateRuleWithRemove()
+        {
+            RuleFor(m => m.Id).Must(v => !new ExamRepository<QuestionTag>(_examTagRepository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Any(x => x.TagId == v)).WithMessage(x => string.Format(ErrorMessage.IsRefrence, typeof(ExamTag).GetDescription(),x.Name));
+            RuleFor(m => m.Id).Must(v => !new ExamRepository<PracticeTag>(_examTagRepository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Any(x => x.TagId == v)).WithMessage(x => string.Format(ErrorMessage.IsRefrence, typeof(ExamTag).GetDescription(), x.Name));
+            RuleFor(m => m.Id).Must(v => !new ExamRepository<RuleTag>(_examTagRepository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Any(x => x.TagId == v)).WithMessage(x => string.Format(ErrorMessage.IsRefrence, typeof(ExamTag).GetDescription(), x.Name));
+            RuleFor(m => m.Id).Must(v => !new ExamRepository<TestPaperRuleTag>(_examTagRepository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Any(x => x.TagId == v)).WithMessage(x => string.Format(ErrorMessage.IsRefrence, typeof(ExamTag).GetDescription(), x.Name));
         }
 
     }

+ 3 - 0
src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionAnswerValidator.cs

@@ -2,6 +2,7 @@ using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
 using Exam.Questions;
 using FluentValidation;
+using Hotline.Exams.Sourcewares;
 using Hotline.Repository.SqlSugar.Validate;
 
 namespace Exam.Repository.Sqlsugar.Validators.Questions
@@ -28,6 +29,8 @@ namespace Exam.Repository.Sqlsugar.Validators.Questions
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+            RuleFor(m => m.Answer).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(QuestionAnswer))));
+            RuleFor(m => m.QuestionId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(Question).GetDescription()));
         }
 
         protected override void ValidateRuleWithAdd()

+ 4 - 0
src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionKnowladgeValidator.cs

@@ -2,6 +2,8 @@ using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
 using Exam.Questions;
 using FluentValidation;
+using Hotline.Exams.Sourcewares;
+using Hotline.KnowledgeBase;
 using Hotline.Repository.SqlSugar.Validate;
 
 namespace Exam.Repository.Sqlsugar.Validators.Questions
@@ -28,6 +30,8 @@ namespace Exam.Repository.Sqlsugar.Validators.Questions
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+            RuleFor(m => m.KnowladgeId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(Knowledge).GetDescription()));
+            RuleFor(m => m.QuestionId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(Question).GetDescription()));
         }
 
         protected override void ValidateRuleWithAdd()

+ 3 - 0
src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionOptionsValidator.cs

@@ -1,3 +1,4 @@
+using Exam.ExamManages;
 using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
 using Exam.Questions;
@@ -28,6 +29,8 @@ namespace Exam.Repository.Sqlsugar.Validators.Questions
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+            RuleFor(m => m.Content).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired,x.GetType().GetDescription(nameof(QuestionOptions))));
+            RuleFor(m => m.QuestionId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(Question).GetDescription()));
         }
 
         protected override void ValidateRuleWithAdd()

+ 4 - 0
src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionSourcewareValidator.cs

@@ -1,7 +1,9 @@
+using Exam.ExamManages;
 using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
 using Exam.Questions;
 using FluentValidation;
+using Hotline.Exams.Sourcewares;
 using Hotline.Repository.SqlSugar.Validate;
 
 namespace Exam.Repository.Sqlsugar.Validators.Questions
@@ -28,6 +30,8 @@ namespace Exam.Repository.Sqlsugar.Validators.Questions
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+            RuleFor(m => m.SourcewareId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(Sourceware).GetDescription()));
+            RuleFor(m => m.QuestionId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(Question).GetDescription()));
         }
 
         protected override void ValidateRuleWithAdd()

+ 3 - 0
src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionTagValidator.cs

@@ -1,3 +1,4 @@
+using Exam.ExamManages;
 using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
 using Exam.Questions;
@@ -28,6 +29,8 @@ namespace Exam.Repository.Sqlsugar.Validators.Questions
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+            RuleFor(m => m.TagId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(ExamTag).GetDescription()));
+            RuleFor(m => m.QuestionId).NotEmpty().WithMessage(x=>string.Format(ErrorMessage.IsRequired,typeof(Question).GetDescription()));
         }
 
         protected override void ValidateRuleWithAdd()

+ 17 - 3
src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/QuestionValidator.cs

@@ -2,14 +2,20 @@ using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
 using Exam.Questions;
 using FluentValidation;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.Questions;
 using Hotline.Repository.SqlSugar.Validate;
+using Newtonsoft.Json.Linq;
+using System.ComponentModel.DataAnnotations;
 
 namespace Exam.Repository.Sqlsugar.Validators.Questions
 {
-    public class QuestionValidator:BaseValidator<Question>
+    public class QuestionValidator : BaseValidator<Question>
     {
-        public QuestionValidator()
+        private readonly IQuestionRepository _questionRepository;
+        public QuestionValidator(IQuestionRepository questionRepository)
         {
+            _questionRepository = questionRepository;
+
             RuleSet(ValidatorTypeConstants.Create, () =>
             {
                 BaseValidateRule();
@@ -28,20 +34,28 @@ namespace Exam.Repository.Sqlsugar.Validators.Questions
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+            RuleFor(m => m.Title).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Question.Title))));
+            RuleFor(m => m.DifficultyLevel).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Question.DifficultyLevel))));
+            RuleFor(m => m.FormalEnable).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Question.FormalEnable))));
+            RuleFor(m => m.SimulateEnable).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Question.SimulateEnable))));
+
         }
 
         protected override void ValidateRuleWithAdd()
         {
             base.ValidateRuleWithAdd();
             RuleFor(m => m.CreationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Question.CreationTime))));
+
+            RuleFor(m => m.Title).Must(v => !_questionRepository.Queryable().Any(x => x.Title == v)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(Question.Title))));
         }
 
         protected override void ValidateRuleWithModify()
         {
             base.ValidateRuleWithModify();
             RuleFor(m => m.LastModificationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Question.LastModificationTime))));
+            RuleFor(m => m.Title).Must((q, v, ctx) => _questionRepository.Queryable().Where(x => x.Title ==v  && x.Id  != q.Id).Any()).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(Question.Title))));        }
 
-        }
+       
 
     }
 }

+ 4 - 0
src/Hotline.Repository.SqlSugar/Exam/Validators/Questions/TagQuestionValidator.cs

@@ -1,7 +1,9 @@
 using Exam.ExamManages;
 using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
+using Exam.Questions;
 using FluentValidation;
+using Hotline.Exams.Sourcewares;
 using Hotline.Repository.SqlSugar.Validate;
 
 namespace Exam.Repository.Sqlsugar.Validators.Questions
@@ -28,6 +30,8 @@ namespace Exam.Repository.Sqlsugar.Validators.Questions
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+            RuleFor(m => m.TagId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(ExamTag).GetDescription()));
+            RuleFor(m => m.RuleId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(ExtractRule).GetDescription()));
         }
 
         protected override void ValidateRuleWithAdd()

+ 33 - 3
src/Hotline.Repository.SqlSugar/Exam/Validators/Sourcewares/SourcewareCategoryValidator.cs

@@ -1,15 +1,31 @@
+using Exam.ExamManages;
 using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
+using Exam.Practices;
+using Exam.Questions;
+using Exam.Repository.Sqlsugar.Repositories;
+using Exam.Repository.Sqlsugar.Repositories.Sourcewares;
+using Exam.TestPapers;
 using FluentValidation;
 using Hotline.Exams.Sourcewares;
+using Hotline.Repository.SqlSugar.DataPermissions;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.Sourcewares;
 using Hotline.Repository.SqlSugar.Validate;
 
 namespace Exam.Repository.Sqlsugar.Validators.Sourcewares
 {
-    public class SourcewareCategoryValidator:BaseValidator<SourcewareCategory>
+    public class SourcewareCategoryValidator : BaseValidator<SourcewareCategory>
     {
-        public SourcewareCategoryValidator()
+        private readonly ISourcewareCategoryRepository _sourcewareCategoryRepository;
+        private readonly IDataPermissionFilterBuilder _dataPermissionFilterBuilder;
+        private readonly IServiceProvider _serviceProvider;
+        public SourcewareCategoryValidator(ISourcewareCategoryRepository sourcewareCategoryRepository, IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider)
         {
+            _sourcewareCategoryRepository = sourcewareCategoryRepository;
+            _dataPermissionFilterBuilder = dataPermissionFilterBuilder;
+            _serviceProvider = serviceProvider;
+
             RuleSet(ValidatorTypeConstants.Create, () =>
             {
                 BaseValidateRule();
@@ -23,25 +39,39 @@ namespace Exam.Repository.Sqlsugar.Validators.Sourcewares
 
                 ValidateRuleWithModify();
             });
+
+            RuleSet(ValidatorTypeConstants.Remove, () =>
+            {
+                ValidateRuleWithRemove();
+            });
         }
 
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+            RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(SourcewareCategory.Name))));
+            RuleFor(m => m.ParentId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(SourcewareCategory.ParentId))));
+            RuleFor(m => m.SortIndex).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(SourcewareCategory.SortIndex))));
         }
 
         protected override void ValidateRuleWithAdd()
         {
             base.ValidateRuleWithAdd();
             RuleFor(m => m.CreationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(SourcewareCategory.CreationTime))));
+            RuleFor(m => m.Name).Must(v => !_sourcewareCategoryRepository.Queryable().Any(x => x.Name == v)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(SourcewareCategory.Name))));
+
         }
 
         protected override void ValidateRuleWithModify()
         {
             base.ValidateRuleWithModify();
             RuleFor(m => m.LastModificationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(SourcewareCategory.LastModificationTime))));
-
+              RuleFor(m => m.Name).Must((t, v) => !_sourcewareCategoryRepository.Queryable().Any(x => x.Name == v && t.Id != x.Id)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(SourcewareCategory.Name))));
         }
 
+        private void ValidateRuleWithRemove()
+        {
+            RuleFor(m => m.Id).Must(v => !new ExamRepository<Sourceware>(_sourcewareCategoryRepository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Any(x => x.CategoryId == v)).WithMessage(x => x.Name.IsNullOrEmpty()? string.Format(ErrorMessage.IsSimpleRefrence, typeof(SourcewareCategory).GetDescription()): string.Format(ErrorMessage.IsRefrence, typeof(SourcewareCategory).GetDescription(), x.Name));
+        }
     }
 }

+ 12 - 2
src/Hotline.Repository.SqlSugar/Exam/Validators/Sourcewares/SourcewareValidator.cs

@@ -1,15 +1,20 @@
 using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
+using Exam.Repository.Sqlsugar.Repositories.Sourcewares;
 using FluentValidation;
 using Hotline.Exams.Sourcewares;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.Sourcewares;
 using Hotline.Repository.SqlSugar.Validate;
 
 namespace Exam.Repository.Sqlsugar.Validators.Sourcewares
 {
     public class SourcewareValidator:BaseValidator<Sourceware>
     {
-        public SourcewareValidator()
+        private readonly ISourcewareRepository _sourcewareRepository;
+        public SourcewareValidator(ISourcewareRepository sourcewareRepository)
         {
+            _sourcewareRepository = sourcewareRepository;
+
             RuleSet(ValidatorTypeConstants.Create, () =>
             {
                 BaseValidateRule();
@@ -34,13 +39,18 @@ namespace Exam.Repository.Sqlsugar.Validators.Sourcewares
         {
             base.ValidateRuleWithAdd();
             RuleFor(m => m.CreationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Sourceware.CreationTime))));
+            RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Sourceware.Name))));
+            RuleFor(m => m.CategoryId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(SourcewareCategory).GetDescription()));
+            RuleFor(m => m.Name).Must(v => !_sourcewareRepository.Queryable().Any(x => x.Name == v)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(Sourceware.Name))));
         }
 
         protected override void ValidateRuleWithModify()
         {
             base.ValidateRuleWithModify();
             RuleFor(m => m.LastModificationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Sourceware.LastModificationTime))));
-
+            RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(Sourceware.Name))));
+            RuleFor(m => m.CategoryId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(SourcewareCategory).GetDescription()));
+            RuleFor(m => m.Name).Must((t,v) => !_sourcewareRepository.Queryable().Any(x => x.Name == v && t.Id != x.Id)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(Sourceware.Name))));
         }
 
     }

+ 0 - 19
src/Hotline.Repository.SqlSugar/Interfaces/IExamTagRepository.cs

@@ -1,19 +0,0 @@
-using Exam.ExamManages;
-using Hotline.Repository.SqlSugar;
-using Hotline.Repository.SqlSugar.Interface;
-using System.ComponentModel;
-using XF.Domain.Repository;
-
-namespace Hotline.Repository.Sqlsugar
-{
-    /// <summary>
-    /// 考试标签仓储接口
-    /// </summary>
-    [Description("考试标签仓储接口")]
-    public interface IExamTagRepository:IRepository<ExamTag>,IExamRepository<ExamTag,HotlineDbContext>
-    {
-       
-    }
-}
-
-

+ 6 - 0
src/Hotline.Share/Dtos/Questions/QuestionSourcewareDto.cs

@@ -20,5 +20,11 @@ namespace Hotline.Share.Dtos.Questions
         /// </summary>
         [Description("课件Id")]
         public string SourcewareId { get; set; }
+
+        /// <summary>
+        /// 课件
+        /// </summary>
+        [Description("课件")]
+        public string Sourceware { get; set; }
     }
 }