guqiang 1 сар өмнө
parent
commit
cda292b4e8

+ 12 - 0
src/Hotline.Api/Controllers/Exam/TestPaperController.cs

@@ -82,5 +82,17 @@ namespace Hotline.Api.Controllers.Exam
 
             return extractRuleDto;
         }
+
+        /// <summary>
+        /// 获取课件分页列表
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet(TestPaperApiRoute.Count)]
+        public async Task<List<TestPaperQuestionCountViewResponse>> GetPagedList([FromQuery] TestPaperQuestionCountRequest testPaperQuestionCountRequest)
+        {
+            var testPaperQuestionCountViewResponses = await _testPaperService.GetTestPaperQuestionCount(testPaperQuestionCountRequest);
+
+            return testPaperQuestionCountViewResponses;
+        }
     }
 }

+ 1 - 0
src/Hotline.Application/Exam/Constants/ApiRoutes/TestPaperApiRoute.cs

@@ -4,5 +4,6 @@ namespace Hotline.Application.Exam.Constants.ApiRoutes
 {
     public class TestPaperApiRoute:ApiRoute
     {
+        public const string Count = "GetTestPaperQuestionCount";
     }
 }

+ 2 - 0
src/Hotline.Application/Exam/Interface/TestPapers/ITestPaperService.cs

@@ -4,10 +4,12 @@ using Exam.TestPapers;
 using Hotline.Repository.SqlSugar.Interface;
 using Hotline.Share.Dtos.TestPapers;
 using Hotline.Share.Requests.Exam;
+using Hotline.Share.ViewResponses.Exam;
 
 namespace Exam.Application.Interface.TestPapers
 {
     public interface ITestPaperService:IQueryService<TestPaperViewResponse,TestPaperDto,TestPaperPagedRequest>,IApiService<AddTestPaperDto,UpdateTestPaperDto,TestPaper>
     {
+        public Task<List<TestPaperQuestionCountViewResponse>> GetTestPaperQuestionCount(TestPaperQuestionCountRequest testPaperQuestionCountRequest);
     }
 }

+ 33 - 0
src/Hotline.Application/Exam/QueryExtensions/TestPapers/TestPaperQueryExtensions.cs

@@ -36,5 +36,38 @@ namespace Hotline.Application.Exam.QueryExtensions.TestPapers
 
             return expression;
         }
+
+        public static Expression<Func<TestPaper,bool>> GetTestPaperCountExpression(this TestPaperQuestionCountRequest testPaperQuestionCountRequest)
+        {
+            Expression<Func<TestPaper, bool>> expression = m => m.Id != null;
+
+            expression = ExpressionableUtility.CreateExpression<TestPaper>()
+               .AndIF(testPaperQuestionCountRequest.TestPaperId.IsNotNullOrEmpty(), x => x.Id == testPaperQuestionCountRequest.TestPaperId)
+               .ToExpression();
+
+            return expression;
+        }
+
+        public static Expression<Func<TestPaperRule,bool>> GetTestPaperRuleExpression(this TestPaperQuestionCountRequest testPaperQuestionCountRequest)
+        {
+            Expression<Func<TestPaperRule, bool>> expression = m => m.Id != null;
+
+            expression = ExpressionableUtility.CreateExpression<TestPaperRule>()
+               .AndIF(testPaperQuestionCountRequest.TestPaperId.IsNotNullOrEmpty(), x => x.TestPaperId == testPaperQuestionCountRequest.TestPaperId)
+               .ToExpression();
+
+            return expression;
+        }
+
+        public static Expression<Func<TestPaperItem,bool>> GetTestPaperItemsExpression(this TestPaperQuestionCountRequest testPaperQuestionCountRequest)
+        {
+            Expression<Func<TestPaperItem, bool>> expression = m => m.Id != null;
+
+            expression = ExpressionableUtility.CreateExpression<TestPaperItem>()
+               .AndIF(testPaperQuestionCountRequest.TestPaperId.IsNotNullOrEmpty(), x => x.TestPaperId == testPaperQuestionCountRequest.TestPaperId)
+               .ToExpression();
+
+            return expression;
+        }
     }
 }

+ 18 - 2
src/Hotline.Application/Exam/Service/ExamManages/ExamManageService.cs

@@ -137,9 +137,11 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
         public override async Task<string> AddAsync(AddExamManageDto actionRequest, CancellationToken cancellationToken)
         {
+            CalcuteTotalScore(actionRequest);
+
             var id = await base.AddAsync(actionRequest, cancellationToken);
 
-            ResolveQuestionId(actionRequest, id);
+            ResolveQuestionId(actionRequest, id);            
 
             await AddExamQuestionScores(actionRequest, cancellationToken);
 
@@ -150,6 +152,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
         public override async Task UpdateAsync(UpdateExamManageDto actionRequest, CancellationToken cancellationToken)
         {
+            CalcuteTotalScore(actionRequest);
+
             await base.UpdateAsync(actionRequest, cancellationToken);
 
             ResolveQuestionId(actionRequest, actionRequest.Id);
@@ -209,7 +213,13 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             var userExamDtos = actionRequest.UserExamDtos.Where(x => x.OperationStatus == EEOperationStatus.Add).ToList();
 
-            var userExams = _mapper.Map<List<UserExam>>(userExamDtos);
+            var userExams = new List<UserExam>();
+            //_mapper.Map<List<UserExam>>(userExamDtos);
+
+            userExamDtos.ForEach(x =>
+            {
+                userExams.Add(_mapper.Map<UserExam>(x));
+            });
 
             await _userExamRepository.AddWithValidateAsync(userExams, cancellationToken);
 
@@ -323,6 +333,12 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             return await examQuestionScoreDtos.ToListAsync();
         }
+        private void CalcuteTotalScore(AddExamManageDto actionRequest)
+        {
+            var examQuestionScoreDtos = actionRequest.ExamQuestionScoreDtos.Where(x => x.OperationStatus != EEOperationStatus.Delete);
+
+            actionRequest.TotalScore = examQuestionScoreDtos.Sum(x => x.Count * x.Score);
+        }
         #endregion
     }
 }

+ 79 - 7
src/Hotline.Application/Exam/Service/TestPapers/TestPaperService.cs

@@ -18,6 +18,7 @@ using Hotline.Repository.SqlSugar.Extensions;
 using Hotline.Share.Dtos.TestPapers;
 using Hotline.Share.Requests.Exam;
 using Hotline.Share.Tools;
+using Hotline.Share.ViewResponses.Exam;
 using JiebaNet.Segmenter.Common;
 using MapsterMapper;
 using SqlSugar;
@@ -113,6 +114,12 @@ namespace Hotline.Application.Exam.Service.TestPapers
             return id;
         }
 
+        /// <summary>
+        /// 修改试卷
+        /// </summary>
+        /// <param name="actionRequest"></param>
+        /// <param name="cancellationToken"></param>
+        /// <returns></returns>
         public override async Task UpdateAsync(UpdateTestPaperDto actionRequest, CancellationToken cancellationToken)
         {
             await base.UpdateAsync(actionRequest, cancellationToken);
@@ -159,15 +166,29 @@ namespace Hotline.Application.Exam.Service.TestPapers
             await DeleteTestPaperRuleTags(tempEntityQueryRequest, cancellationToken);
         }
 
-        private async Task<List<TestPaperRuleTag>> GetTestPaperRuleTags(EntityQueryRequest entityQueryRequest)
+        /// <summary>
+        /// 获取试卷试题数量
+        /// </summary>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        public async Task<List<TestPaperQuestionCountViewResponse>> GetTestPaperQuestionCount(TestPaperQuestionCountRequest testPaperQuestionCountRequest)
         {
-            var expression = entityQueryRequest.GetTestPaperRuleExpression();
-            var testPageRuleTable = _testPaperRuleRepository.Queryable().Where(expression);
-            var testPageRuleTagTable = _testPaperRuleTagRepository.Queryable();
+            var expression = testPaperQuestionCountRequest.GetTestPaperCountExpression();
+            var testPaper = await _repository.Queryable().Where(expression).FirstAsync();
 
-            var query = testPageRuleTagTable.InnerJoin(testPageRuleTable, (t, r) => t.TestPaperRuleId == r.Id).Select((t,r) => t);
-
-            return await query.ToListAsync();
+            var testPaperQuestionCountViewResponses = new List<TestPaperQuestionCountViewResponse>();
+            if (testPaper != null)
+            {
+                if(testPaper.Mode == Share.Enums.Exams.EExamMode.Random)
+                {
+                    testPaperQuestionCountViewResponses = await CalcuteRandomQuestionCount(testPaperQuestionCountRequest);
+                }
+                else if(testPaper.Mode == Share.Enums.Exams.EExamMode.Manual)
+                {
+                    testPaperQuestionCountViewResponses = await CalcuteManualQuestionCount(testPaperQuestionCountRequest);
+                }
+            }
+            return testPaperQuestionCountViewResponses;
         }
         #endregion
 
@@ -442,6 +463,57 @@ namespace Hotline.Application.Exam.Service.TestPapers
 
             actionRequest.TestPaperItemDtos.ForEach(x => x.TestPaperId = id);
         }
+
+        private async Task<List<TestPaperRuleTag>> GetTestPaperRuleTags(EntityQueryRequest entityQueryRequest)
+        {
+            var expression = entityQueryRequest.GetTestPaperRuleExpression();
+            var testPageRuleTable = _testPaperRuleRepository.Queryable().Where(expression);
+            var testPageRuleTagTable = _testPaperRuleTagRepository.Queryable();
+
+            var query = testPageRuleTagTable.InnerJoin(testPageRuleTable, (t, r) => t.TestPaperRuleId == r.Id).Select((t, r) => t);
+
+            return await query.ToListAsync();
+        }
+
+        private async Task<List<TestPaperQuestionCountViewResponse>> CalcuteRandomQuestionCount(TestPaperQuestionCountRequest testPaperQuestionCountRequest)
+        {
+            var testPaperQuestionCountViewResponses = new List<TestPaperQuestionCountViewResponse>();
+
+            var expression = testPaperQuestionCountRequest.GetTestPaperRuleExpression();
+
+            var testPaperRules = await _testPaperRuleRepository.Queryable().Where(expression).ToListAsync();
+
+            if (testPaperRules != null)
+            {
+                testPaperRules.ForEach(x => testPaperQuestionCountViewResponses.Add(new TestPaperQuestionCountViewResponse
+                {
+                    QuestionType = x.QuestionType,
+                    Count = x.Count
+                }));
+            }
+
+            return testPaperQuestionCountViewResponses;
+        }
+
+        private async Task<List<TestPaperQuestionCountViewResponse>> CalcuteManualQuestionCount(TestPaperQuestionCountRequest testPaperQuestionCountRequest)
+        {
+            var testPaperQuestionCountViewResponses = new List<TestPaperQuestionCountViewResponse>();
+
+            var expression = testPaperQuestionCountRequest.GetTestPaperItemsExpression();
+
+            var testPaperItemTable =  _testPaperItemRepository.Queryable().Where(expression);
+            var questionTable = new ExamRepository<Question>(_testPaperItemRepository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
+
+            testPaperQuestionCountViewResponses = await testPaperItemTable.InnerJoin(questionTable, (t, q) => t.QuestionId == q.Id)
+                .GroupBy((t, q) => q.QuestionType).Select((t, q) => new TestPaperQuestionCountViewResponse
+                {
+                    QuestionType = q.QuestionType,
+                    Count = SqlFunc.AggregateCount(t.Id)
+                }).ToListAsync();           
+
+
+            return testPaperQuestionCountViewResponses;
+        }
         #endregion
     }
 }

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

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

+ 25 - 1
src/Hotline.Repository.SqlSugar/Exam/Validators/ExamManages/ExamManageValidator.cs

@@ -2,14 +2,18 @@
 using Exam.ExamManages;
 using Exam.Infrastructure.Extensions;
 using Exam.Infrastructure.Validation.Validation;
+using Exam.TestPapers;
 using FluentValidation;
+using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages;
 using Hotline.Repository.SqlSugar.Validate;
 
 namespace Exam.Application
 {
     public class ExamManageValidator:BaseValidator<ExamManage>
     {
-        public ExamManageValidator()
+        private readonly IExamManageRepository _examManageRepository;
+
+        public ExamManageValidator(IExamManageRepository examManageRepository)
         {
             RuleSet(ValidatorTypeConstants.Create, () =>
             {
@@ -24,17 +28,34 @@ namespace Exam.Application
 
                 ValidateRuleWithModify();
             });
+            this._examManageRepository = examManageRepository;
         }
 
         protected override void BaseValidateRule()
         {
             base.BaseValidateRule();
+
+            RuleFor(m => m.Name).NotEmpty().WithMessage(x=>string.Format(ErrorMessage.IsRequired,x.GetType().GetDescription(nameof(ExamManage.Name))));
+            RuleFor(m => m.Code).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.Code))));
+            RuleFor(m => m.CutoffScore).NotNull().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.CutoffScore))));
+            RuleFor(m => m.ExamType).NotNull().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.ExamType))));
+            RuleFor(m => m.Method).NotNull().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.Method))));
+            RuleFor(m => m.TestPaperId).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, typeof(TestPaper).GetDescription()));
+            RuleFor(m => m.Count).NotNull().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.Count))));
+            RuleFor(m => m.TimeSpan).NotNull().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.TimeSpan))));
+            RuleFor(m => m.StartTime).NotNull().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.StartTime))));
+            RuleFor(m => m.EndTime).NotNull().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.EndTime))));
+            RuleFor(m => m.EndTime).Must((e, v) => e.StartTime < v).WithMessage(x => string.Format(ErrorMessage.Greater, x.GetType().GetDescription(nameof(ExamManage.EndTime)), x.GetType().GetDescription(nameof(ExamManage.StartTime))));
+            RuleFor(m => m.TotalScore).NotNull().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.TotalScore))));
         }
 
         protected override void ValidateRuleWithAdd()
         {
             base.ValidateRuleWithAdd();
             RuleFor(m => m.CreationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.CreationTime))));
+
+            RuleFor(m => m.Name).Must(v => _examManageRepository.Queryable().Any(x => x.Name == v)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamManage.Name))));
+            RuleFor(m => m.Code).Must(v => _examManageRepository.Queryable().Any(x => x.Code == v)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamManage.Code))));
         }
 
         protected override void ValidateRuleWithModify()
@@ -42,6 +63,9 @@ namespace Exam.Application
             base.ValidateRuleWithModify();
             RuleFor(m => m.LastModificationTime).NotEmpty().WithMessage(x => string.Format(ErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamManage.LastModificationTime))));
 
+            RuleFor(m => m.Name).Must((e,v) => _examManageRepository.Queryable().Any(x => x.Name == v && x.Id!=e.Id)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamManage.Name))));
+            RuleFor(m => m.Code).Must((e,v) => _examManageRepository.Queryable().Any(x => x.Code == v && x.Id != e.Id)).WithMessage(x => string.Format(ErrorMessage.IsRepeat, x.GetType().GetDescription(nameof(ExamManage.Code))));
+
         }
 
     }

+ 6 - 0
src/Hotline.Share/Dtos/ExamManages/ExamQuestionScoreDto.cs

@@ -33,6 +33,12 @@ namespace Exam.Share
         [Description("试题分数")]
         public int Score { get; set; }
 
+        /// <summary>
+        /// 试题数
+        /// </summary>
+        [Description("试题数")]
+        public int Count { get; set; }
+
         /// <summary>
         /// 考试管理Id
         /// </summary>

+ 15 - 15
src/Hotline.Share/Dtos/ExamManages/UserExamDto.cs

@@ -13,11 +13,11 @@ namespace Exam.Share
     [Description("用户考试")]
     public class UserExamDto:UpdateUserExamDto
     {       
-        /// <summary>
-        /// 用户考试明细
-        /// </summary>
-        [Description("用户考试明细")]
-        public new List<UserExamItemDto> UserExamItems { get; set; }
+        ///// <summary>
+        ///// 用户考试明细
+        ///// </summary>
+        //[Description("用户考试明细")]
+        //public new List<UserExamItemDto> UserExamItems { get; set; }
     }
 
     /// <summary>
@@ -62,11 +62,11 @@ namespace Exam.Share
         [Description("是否已阅卷")]
         public ECheck IsCheck { get; set; }
 
-        /// <summary>
-        /// 用户考试明细
-        /// </summary>
-        [Description("用户考试明细")]
-        public List<AddUserExamItemDto> UserExamItems { get; set; }
+        ///// <summary>
+        ///// 用户考试明细
+        ///// </summary>
+        //[Description("用户考试明细")]
+        //public List<AddUserExamItemDto> UserExamItems { get; set; }
 
         /// <summary>
         /// 操作状态        
@@ -87,10 +87,10 @@ namespace Exam.Share
         [Description("主键")]
         public string Id { get; set; }
 
-        /// <summary>
-        /// 用户考试明细
-        /// </summary>
-        [Description("用户考试明细")]
-        public new List<UpdateUserExamItemDto> UserExamItems { get; set; }
+        ///// <summary>
+        ///// 用户考试明细
+        ///// </summary>
+        //[Description("用户考试明细")]
+        //public new List<UpdateUserExamItemDto> UserExamItems { get; set; }
     }
 }

+ 14 - 0
src/Hotline.Share/Requests/Exam/TestPaperQuestionCountRequest.cs

@@ -0,0 +1,14 @@
+using Exam.Infrastructure.Data.Interface;
+using System.ComponentModel;
+
+namespace Hotline.Share.Requests.Exam
+{
+    public class TestPaperQuestionCountRequest: IQueryRequest
+    {
+        /// <summary>
+        /// 试卷Id
+        /// </summary>
+        [Description("试卷Id")]
+        public string TestPaperId { get; set; }
+    }
+}

+ 39 - 0
src/Hotline.Share/ViewResponses/Exam/TestPaperQuestionCountViewResponse.cs

@@ -0,0 +1,39 @@
+using Exam.Infrastructure.Data.Interface;
+using Exam.Infrastructure.Extensions;
+using Hotline.Share.Enums.Exams;
+using System.ComponentModel;
+
+namespace Hotline.Share.ViewResponses.Exam
+{
+    public class TestPaperQuestionCountViewResponse : IViewResponse
+    {
+        /// <summary>
+        /// 主键
+        /// </summary>
+        [Description("主键")]
+        public string Id { get; set; }
+
+        /// <summary>
+        /// 试题类型
+        /// </summary>
+        [Description("试题类型")]
+        public EQuestionType QuestionType { get; set; }
+
+        /// <summary>
+        /// 试题类型
+        /// </summary>
+        [Description("试题类型")]
+        public string QuestionTypeDesc {
+            get
+            {
+                return QuestionType.GetDescription();
+            }
+        }
+
+        /// <summary>
+        /// 试题数
+        /// </summary>
+        [Description("试题数")]
+        public int Count { get; set; }
+    }
+}

+ 2 - 1
src/Hotline/Exams/ExamManages/UserExam.cs

@@ -1,5 +1,6 @@
 using System.ComponentModel;
 using Hotline.Exams.Base;
+using Hotline.Share.Enums.Exams;
 using SqlSugar;
 
 namespace Exam.ExamManages
@@ -43,7 +44,7 @@ namespace Exam.ExamManages
         /// </summary>
         [SugarColumn(ColumnDescription ="考试状态")]
         [Description("考试状态")]
-        public int ExamStatus { get; set; }
+        public EExamStatus ExamStatus { get; set; }
 
         /// <summary>
         /// 是否已阅卷

+ 2 - 0
src/Hotline/Exams/Validate/ErrorMessage.cs

@@ -101,6 +101,8 @@
         public const string IsSimpleRefrence = "{0}正在被使用,不可以删除";
 
         public const string RequestFail = "请求失败!";
+
+        public const string Greater = "{0}不能大于{1}";
     }
 
     public static class RegexConstant