Sfoglia il codice sorgente

Merge branch 'test' of http://110.188.24.182:10023/Fengwo/hotline into test

田爽 4 giorni fa
parent
commit
1dbc4da215

+ 11 - 0
src/Hotline.Api/Controllers/Exam/TrainRecordController.cs

@@ -58,6 +58,17 @@ namespace Hotline.Api.Controllers.Exam
             return await _trainRecordService.GetTrainPracticeAsync(trainPracticeRequest);
         }
 
+        /// <summary>
+        /// 获取培训习题
+        /// </summary>
+        /// <param name="trainPracticeRequest"></param>
+        /// <returns></returns>
+        [HttpGet(TrainRecordApiRoute.GetSimpleTrainPractice)]
+        public async Task<SimpleTrainPracticeDto> GetSimpleTrainPractice([FromQuery] TrainPracticeRequest trainPracticeRequest)
+        {
+            return await _trainRecordService.GetSimpleTrainPracticeAsync(trainPracticeRequest);
+        }
+
         /// <summary>
         /// 完成培训课件学习
         /// </summary>

+ 2 - 0
src/Hotline.Application/Exam/Constants/ApiRoutes/TrainRecordApiRoute.cs

@@ -11,6 +11,8 @@ namespace Hotline.Application.Exam.Constants.ApiRoutes
 
         public const string GetTrainPractice = "GetTrainPractice";
 
+        public const string GetSimpleTrainPractice = "GetSimpleTrainPractice";
+
         public const string CompleteTrainKnowladge = "CompleteTrainKnowladge";
 
         public const string CompleteTrainRecord = "CompleteTrainRecord";

+ 7 - 0
src/Hotline.Application/Exam/Interface/Train/ITrainRecordService.cs

@@ -32,6 +32,13 @@ namespace Hotline.Application.Exam.Interface.Train
         /// <returns></returns>
         Task<TrainPracticeDto> GetTrainPracticeAsync(TrainPracticeRequest trainPracticeRequest);
 
+        /// <summary>
+        /// 获取培训习题
+        /// </summary>
+        /// <param name="trainPracticeRequest"></param>
+        /// <returns></returns>
+        Task<SimpleTrainPracticeDto> GetSimpleTrainPracticeAsync(TrainPracticeRequest trainPracticeRequest);
+
         /// <summary>
         /// 完成培训课件学习
         /// </summary>

+ 11 - 0
src/Hotline.Application/Exam/QueryExtensions/Trains/TrainRecordQueryExtensions.cs

@@ -26,6 +26,17 @@ namespace Hotline.Application.Exam.QueryExtensions.Trains
             return expression;
         }
 
+        public static Expression<Func<ExamTrainRecord, bool>> GetTrainRecordExpression(this TrainRecordPagedRequest trainRecordPagedRequest)
+        {
+            Expression<Func<ExamTrainRecord, bool>> expression = m => m.Id != null;
+
+            expression = ExpressionableUtility.CreateExpression<ExamTrainRecord>()
+                .AndIF(trainRecordPagedRequest.UserId.IsNotNull(), x => x.UserId == trainRecordPagedRequest.UserId)
+                .ToExpression();
+
+            return expression;
+        }
+
         public static Expression<Func<ExamTrainPractice, bool>> GetExpression(this TrainQuestionRequest trainQuestionRequest)
         {
             Expression<Func<ExamTrainPractice, bool>> expression = m => m.Id != null;

+ 4 - 2
src/Hotline.Application/Exam/Service/ExamManages/UserExamService.cs

@@ -678,7 +678,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             userExamItem.UserExamItemOptionses = await AddUserExamItemOptions(addUserExamItemDto, cancellationToken);
 
-            userExamItem.ExamAnswers = await AddExamAnswer(addUserExamItemDto, cancellationToken);
+            userExamItem.ExamAnswers = await AddExamAnswer(addUserExamItemDto, userExamItem.Id, cancellationToken);
+            
 
             await userExamItemRepository.AddNav(userExamItem)
                 .Include(x => x.UserExamItemOptionses)
@@ -733,7 +734,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
             return null;
         }
 
-        private async Task<List<ExamAnswer>> AddExamAnswer(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
+        private async Task<List<ExamAnswer>> AddExamAnswer(AddUserExamItemDto addUserExamItemDto,string id, CancellationToken cancellationToken)
         {
             if (addUserExamItemDto.QuestionType.CheckSelectType()) return null;
 
@@ -742,6 +743,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
             var examAnswer = new ExamAnswer
             {
                 UserId = _sessionContext.UserId,
+                UserExamItemId = id,
                 Answer = addUserExamItemDto.Answer
             };
 

+ 4 - 4
src/Hotline.Application/Exam/Service/Practices/PracticeService.cs

@@ -353,7 +353,7 @@ namespace Hotline.Application.Exam.Service.Practices
                                       .Where((p, r, i) => r.PracticeQuestionId == practiceQuestionRequest.PracticeQuestionId)
                                       .Select((p, r, i) => i);
 
-            return await practiceResultItems.ToListAsync();
+            return await practiceResultItems.Distinct().ToListAsync();
         }
 
         private async Task<List<PracticeQuestionKnowladgeDto>> GetPracticeQuestionKnowladge(PracticeQuestionRequest practiceQuestionRequest)
@@ -374,7 +374,7 @@ namespace Hotline.Application.Exam.Service.Practices
                 });
 
 
-            return await queryResult.ToListAsync();
+            return await queryResult.Distinct().ToListAsync();
         }
 
         private async Task<List<PracticeQuestionSourcewareDto>> GetPracticeQuestionSourceware(PracticeQuestionRequest practiceQuestionRequest)
@@ -397,7 +397,7 @@ namespace Hotline.Application.Exam.Service.Practices
                 });
 
 
-            return await queryResult.ToListAsync();
+            return await queryResult.Distinct().ToListAsync();
         }
 
         private async Task<List<PracticeQuestionOptionsDto>> GetPracticeQuestionOptions(PracticeQuestionRequest practiceQuestionRequest)
@@ -415,7 +415,7 @@ namespace Hotline.Application.Exam.Service.Practices
                     QuestionOptionId = o.QuestionOptionId
                 });
 
-            return await queryResult.ToListAsync();
+            return await queryResult.Distinct().ToListAsync();
         }
         private SqlSugar.ISugarQueryable<PracticeViewResponse> QueryResult(PracticePagedRequest queryRequest)
         {

+ 54 - 5
src/Hotline.Application/Exam/Service/Trains/TrainRecordService.cs

@@ -28,6 +28,10 @@ using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using Hotline.Share.Exams.Extensions;
 using NPOI.SS.Formula.Functions;
+using Hotline.Repository.SqlSugar.Exam.Repositories.Trains;
+using static NPOI.HSSF.Util.HSSFColor;
+using DocumentFormat.OpenXml.Drawing.Charts;
+using JiebaNet.Segmenter.Common;
 
 namespace Hotline.Application.Exam.Service.Trains
 {
@@ -131,14 +135,16 @@ namespace Hotline.Application.Exam.Service.Trains
 
         public async Task<TrainPracticeDto> GetTrainPracticeAsync(TrainPracticeRequest trainPracticeRequest)
         {
-            var trainPracticeRepostitory = new TrainPracticeRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            SqlSugar.ISugarQueryable<ExamTrainPractice> trainPractices = GetTrainPractices(trainPracticeRequest);
 
-            var trainPractice = await trainPracticeRepostitory.GetAsync(trainPracticeRequest.TrainPracticeId);
+            var trainPractice = await trainPractices.FirstAsync();
 
             if (trainPractice == null) return null;
 
             var trainPracticeDto = _mapper.Map<TrainPracticeDto>(trainPractice);
 
+            trainPracticeRequest.TrainPracticeId = trainPractice.Id;
+
             trainPracticeDto.TrainPracticeOptionsDtos = await GetTrainQuestionOptions(trainPracticeRequest);
 
             trainPracticeDto.TrainPracticeSourcewareDtos = await GetTrainPracticeSourcewares(trainPracticeRequest);
@@ -148,6 +154,23 @@ namespace Hotline.Application.Exam.Service.Trains
             return trainPracticeDto;
         }
 
+        public async Task<SimpleTrainPracticeDto> GetSimpleTrainPracticeAsync(TrainPracticeRequest trainPracticeRequest)
+        {
+            SqlSugar.ISugarQueryable<ExamTrainPractice> trainPractices = GetTrainPractices(trainPracticeRequest);
+
+            var trainPractice = await trainPractices.FirstAsync();
+
+            if (trainPractice == null) return null;
+
+            var trainPracticeDto = _mapper.Map<TrainPracticeDto>(trainPractice);
+
+            trainPracticeRequest.TrainPracticeId = trainPractice.Id;
+
+            trainPracticeDto.TrainPracticeOptionsDtos = await GetTrainQuestionOptions(trainPracticeRequest);
+
+            return trainPracticeDto;
+        }
+
         public async Task<TrainResultPagedViewResponse> AnalysisTrainResult(TrainResultReportPagedRequest trainResultReportPagedRequest)
         {
             trainResultReportPagedRequest.ResoleEndTime();
@@ -244,9 +267,11 @@ namespace Hotline.Application.Exam.Service.Trains
         private SqlSugar.ISugarQueryable<TrainRecordViewResponse> QueryResult(TrainRecordPagedRequest queryRequest)
         {
             var trainPlanRepository = new TrainPlanRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            queryRequest.UserId = _sessionContext.UserId;
             var expression = queryRequest.GetExpression();
             var trainPlanTable = trainPlanRepository.Queryable().Where(expression);
-            var trainRecordTable = _repository.Queryable();
+            var traiRecordExpression = queryRequest.GetTrainRecordExpression();
+            var trainRecordTable = _repository.Queryable().Where(traiRecordExpression);
 
             var queryResult = trainPlanTable.InnerJoin(trainRecordTable, (p, r) => p.Id == r.TrainPlanId)
                             .Select((p, r) => new TrainRecordViewResponse
@@ -358,12 +383,36 @@ namespace Hotline.Application.Exam.Service.Trains
             return trainPracticeDto;
         }
 
+        private SqlSugar.ISugarQueryable<ExamTrainPractice> GetTrainPractices(TrainPracticeRequest trainPracticeRequest)
+        {
+            var trainPracticeRepostitory = new TrainPracticeRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            var trainPlanRepository = new TrainPlanRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            var trainPlanTemplateRepository = new TrainPlanTemplateRepository(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+
+            var trainRecordTable = _repository.Queryable().Where(x => x.Id == trainPracticeRequest.Id);
+            var trainPlanTable = trainPlanRepository.Queryable();
+            var trainPracticeTable = trainPracticeRepostitory.Queryable().WhereIF(!string.IsNullOrEmpty(trainPracticeRequest.TrainPracticeId),x=>x.Id == trainPracticeRequest.TrainPracticeId);
+            var tranPlanTemplateTable = trainPlanTemplateRepository.Queryable();
+
+            var trainPractices = trainPracticeTable.InnerJoin(tranPlanTemplateTable, (tp, tpt) => tp.TrainTemplateId == tpt.TrainTemplateId)
+                .InnerJoin(trainPlanTable, (tp, tpt, tpn) => tpt.TrainPlanId == tpn.Id)
+                .InnerJoin(trainRecordTable, (tp, tpt, tpn, tr) => tpn.Id == tr.TrainPlanId)
+                .Select((tp, tpt, tpn, tr) => tp)
+                .OrderBy(tp => tp.CreationTime);
+            return trainPractices;
+        }
+
         private async Task<List<SimpleTrainPracticeOptionsDto>> GetTrainQuestionOptions(TrainPracticeRequest trainPracticeRequest)
         {
-            var trainPracticeRepository = new ExamRepository<ExamTrainPracticeOptions>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            var trainPracticeOptionsRepository = new ExamRepository<ExamTrainPracticeOptions>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
             var trainRecordAnswerRepository = new ExamRepository<ExamTrainRecordAnswer>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
             // TODO: 获取未阅卷的第一道题
-            var trainPracticeOptions = trainPracticeRepository.Queryable().Where(x => x.TrainPracticeId == trainPracticeRequest.TrainPracticeId);
+            var trainPractices = GetTrainPractices(trainPracticeRequest);
+
+            var trainPracticeOptions = await trainPracticeOptionsRepository.Queryable()
+                .InnerJoin(trainPractices, (tpo, tp) => tpo.TrainPracticeId == tp.Id)
+                .Where((tpo, tp)=> tp.Id == trainPracticeRequest.TrainPracticeId)
+                .Select((tpo, tp) => tpo).ToListAsync();
 
             var trainRecordOptions = await trainRecordAnswerRepository.Queryable()
                 .InnerJoin<ExamTrainRecord>((t,x)=>t.TrainRecordId == x.Id)

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

@@ -35,7 +35,7 @@ namespace Hotline.Repository.SqlSugar.Exam.Validators.ExamManages
         {
             base.BaseValidateRule();
             RuleFor(m=>m.UserId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamAnswer.UserId))));
-            RuleFor(m=>m.UserExamItemId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamAnswer.UserId))));
+            RuleFor(m=>m.UserExamItemId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamAnswer.UserExamItemId))));
         }
 
         protected override void ValidateRuleWithAdd()

+ 0 - 1
src/Hotline.Repository.SqlSugar/Exam/Validators/Sourcewares/SourcewareCategoryValidator.cs

@@ -47,7 +47,6 @@ namespace Exam.Repository.Sqlsugar.Validators.Sourcewares
         {
             base.BaseValidateRule();
             RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamSourcewareCategory.Name))));
-            RuleFor(m => m.ParentId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamSourcewareCategory.ParentId))));
             RuleFor(m => m.SortIndex).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamSourcewareCategory.SortIndex))));
         }
 

+ 1 - 1
src/Hotline.Share/Dtos/ExamManages/ExamTagDto.cs

@@ -29,7 +29,7 @@ namespace Hotline.Share.Dtos.ExamManages
         /// 父级ID
         /// </summary>
         [Description("父级ID")]
-        public string ParentId { get; set; }
+        public string? ParentId { get; set; }
     }
 
     /// <summary>

+ 17 - 6
src/Hotline.Share/Dtos/Trains/TrainPracticeDto.cs

@@ -14,7 +14,7 @@ namespace Hotline.Share.Dtos.Trains
     /// 培训习题
     /// </summary>
     [Description("培训习题")]
-    public class TrainPracticeDto : UpdateTrainPracticeDto
+    public class TrainPracticeDto : SimpleTrainPracticeDto
     {
         // <summary>
         /// 关联课件
@@ -28,12 +28,16 @@ namespace Hotline.Share.Dtos.Trains
         [Description("关联知识")]
         public new List<TrainPracticeKnowladgeDto> TrainPracticeKnowladgeDtos { get; set; }
 
-        /// <summary>
-        /// 培训习题选项
-        /// </summary>
-        [Description("培训习题选项")]
-        public List<SimpleTrainPracticeOptionsDto> TrainPracticeOptionsDtos { get; set; }
 
+        
+    }
+
+    /// <summary>
+    /// 培训习题
+    /// </summary>
+    [Description("培训习题")]
+    public class SimpleTrainPracticeDto : UpdateTrainPracticeDto
+    {
         /// <summary>
         /// 题型
         /// </summary>
@@ -57,6 +61,13 @@ namespace Hotline.Share.Dtos.Trains
                 return DifficultyLevel.GetDescription();
             }
         }
+
+
+        /// <summary>
+        /// 培训习题选项
+        /// </summary>
+        [Description("培训习题选项")]
+        public List<SimpleTrainPracticeOptionsDto> TrainPracticeOptionsDtos { get; set; }
     }
 
     public class AddTrainPracticeDto : IAddRequest, IOperationStatus

+ 9 - 0
src/Hotline.Share/Requests/Train/TrainPracticeRequest.cs

@@ -1,10 +1,19 @@
 using Exam.Infrastructure.Data.Interface;
+using Newtonsoft.Json;
 using System.ComponentModel;
 
 namespace Hotline.Share.Requests.Train
 {
     public class TrainPracticeRequest:IQueryRequest
     {
+
+        /// <summary>
+        /// 培训记录Id
+        /// </summary>
+        [Description("培训记录Id")]
+        public string Id { get; set; }
+
+
         /// <summary>
         /// 培训习题Id
         /// </summary>

+ 9 - 0
src/Hotline.Share/Requests/Train/TrainRecordPagedRequest.cs

@@ -1,5 +1,6 @@
 using Exam.Infrastructure.Data.Interface;
 using System.ComponentModel;
+using System.Text.Json.Serialization;
 
 namespace Hotline.Share.Requests.Train
 {
@@ -40,5 +41,13 @@ namespace Hotline.Share.Requests.Train
         /// </summary>
         [Description("最大结束时间")]
         public DateTime? MaxEndTime { get; set; }
+
+        /// <summary>
+        /// 用户Id
+        /// </summary>
+        [Description("用户Id")]
+        [JsonIgnore]
+        public string UserId { get; set; }
+
     }
 }

+ 0 - 1
src/Hotline/Validators/Exams/ExamManages/AddExamTagDtoValidator.cs

@@ -11,7 +11,6 @@ namespace Hotline.Validators.Exams
         public AddExamTagDtoValidator()
         {
             RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.Name))));
-            RuleFor(m => m.ParentId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.ParentId))));
         }
     }
 }

+ 0 - 1
src/Hotline/Validators/Exams/ExamManages/UpdateExamTagDtoValidator.cs

@@ -18,7 +18,6 @@ namespace Hotline.Validators.Exams
         {
             RuleFor(m => m.Id).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.Id))));
             RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.Name))));
-            RuleFor(m => m.ParentId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamTag.ParentId))));
 
         }
     }

+ 0 - 1
src/Hotline/Validators/Exams/Sourcewares/AddSourcewareCategoryDtoValidator.cs

@@ -16,7 +16,6 @@ namespace Hotline.Validators.Exams
         public AddSourcewareCategoryDtoValidator()
         {
             RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamSourcewareCategory.Name))));
-            RuleFor(m => m.ParentId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamSourcewareCategory.ParentId))));
 
         }
     }

+ 0 - 1
src/Hotline/Validators/Exams/Sourcewares/UpdateSourceCategoryDtoValidator.cs

@@ -17,7 +17,6 @@ namespace Hotline.Validators.Exams
         {
             RuleFor(m => m.Id).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamSourcewareCategory.Id))));
             RuleFor(m => m.Name).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamSourcewareCategory.Name))));
-            RuleFor(m => m.ParentId).NotEmpty().WithMessage(x => string.Format(ExamErrorMessage.IsRequired, x.GetType().GetDescription(nameof(ExamSourcewareCategory.ParentId))));
         }
     }
 }