Procházet zdrojové kódy

Merge branch 'feature/exam' into dev
合并冲突

guqiang před 2 dny
rodič
revize
cec2e103b6

+ 5 - 1
src/Hotline.Application/Exam/Interface/Strategy/IExamStrategy.cs

@@ -16,6 +16,10 @@ namespace Hotline.Application.Exam.Interface.Strategy
 
         public string ErroMessage { get; }
 
-        public Action CallBack { get; set; }
+        public Func<object> CallBack { get; set; }
+
+        public object GetResult();
+
+
     }
 }

+ 49 - 12
src/Hotline.Application/Exam/Service/ExamManages/UserExamService.cs

@@ -183,9 +183,9 @@ namespace Hotline.Application.Exam.Service.ExamManages
             var result = queryable.GroupBy(x => x.QuestionType).Select(m => new ExamQuestionViewResponse
             {
                 QuestionType = m.Key,
-                Questions = m.Select(n => new SimpleViewResponse
+                Questions = m.GroupBy(g=>g.QuestionId).Select(n => new SimpleViewResponse
                 {
-                    Id = n.QuestionId
+                    Id = n.Key
                 }).ToList()
             }).ToList();
 
@@ -304,6 +304,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             if (!startExamViewResponse.CheckValidate())
             {
+                await SetExamStatus(userExam, startExamViewResponse, cancellationToken);
+
                 return startExamViewResponse;
             }
 
@@ -322,6 +324,16 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             return startExamViewResponse;
         }
+
+        private async Task SetExamStatus(ExamUserExam userExam, StartExamViewResponse startExamViewResponse, CancellationToken cancellationToken)
+        {
+            userExam.ExamStatus = startExamViewResponse.IsCompleted ? EExamStatus.Complete : EExamStatus.NoStart;
+
+            userExam.ToUpdate(_sessionContext);
+
+            await _repository.UpdateWithValidateAsync(userExam, cancellationToken);
+        }
+
         public async Task<StartExamViewResponse> StartUserExamAsync(StartUserExamDto startUserExamDto, CancellationToken cancellationToken)
         {
             var userExam = await _repository.GetAsync(x => x.Id == startUserExamDto.Id);
@@ -338,6 +350,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             if (!startExamViewResponse.CheckValidate())
             {
+                await SetExamStatus(userExam, startExamViewResponse, cancellationToken);
+
                 return startExamViewResponse;
             }
 
@@ -382,8 +396,11 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 startExamViewResponse = AddCheckValidateTimeStrategy(examUserExam, examManage, startExamViewResponse, examStrategys);
                 startExamViewResponse = AddCheckValidateCountStrategy(examUserExam, examManage, startExamViewResponse, examStrategys);
 
+                examStrategyProxy.Initial(examStrategys);
+
                 if (!examStrategyProxy.Validate())
                 {
+                    startExamViewResponse = (StartExamViewResponse)examStrategyProxy.GetResult();
                     return startExamViewResponse;
                 }
             }
@@ -417,12 +434,16 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 {
                     CallBack = () =>
                     {
-                        startExamViewResponse = new StartExamViewResponse
+                       var  response = new StartExamViewResponse
                         {
                             IsJoin = false,
                             IsStart = false,
-                            IsCompleted = true
+                            IsCompleted = true,
+                            StartTime = examUserExam.StartTime,
+                            TimeSpan = examManage.TimeSpan
                         };
+
+                        return response;
                     }
                 };
                 examStrategys.Add(checkStartTime);
@@ -436,12 +457,16 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 {
                     CallBack = () =>
                     {
-                        startExamViewResponse = new StartExamViewResponse
+                       var response = new StartExamViewResponse
                         {
                             IsJoin = false,
                             IsStart = false,
-                            IsCompleted = true
+                            IsCompleted = true,
+                            StartTime = examUserExam.StartTime,
+                            TimeSpan = examManage.TimeSpan
                         };
+
+                        return response;
                     }
                 };
                 examStrategys.Add(checkStartTime);
@@ -458,12 +483,16 @@ namespace Hotline.Application.Exam.Service.ExamManages
             {
                 CallBack = () =>
                 {
-                    startExamViewResponse = new StartExamViewResponse
+                    var response = new StartExamViewResponse
                     {
                         IsJoin = false,
                         IsStart = false,
-                        IsCompleted = true
+                        IsCompleted = true,
+                        StartTime = examUserExam.StartTime,
+                        TimeSpan = examManage.TimeSpan
                     };
+
+                    return response;
                 }
             };
             examStrategys.Add(checkStartTime);
@@ -478,12 +507,16 @@ namespace Hotline.Application.Exam.Service.ExamManages
             {
                 CallBack = () =>
                 {
-                    startExamViewResponse = new StartExamViewResponse
+                    var response = new StartExamViewResponse
                     {
                         IsJoin = false,
                         IsStart = false,
-                        IsCompleted = true
+                        IsCompleted = true,
+                        StartTime = examUserExam.StartTime,
+                        TimeSpan = examManage.TimeSpan
                     };
+
+                    return response;
                 }
             };
             examStrategys.Add(checkStartTime);
@@ -498,12 +531,16 @@ namespace Hotline.Application.Exam.Service.ExamManages
             {
                 CallBack = () =>
                 {
-                    startExamViewResponse = new StartExamViewResponse
+                    var response = new StartExamViewResponse
                     {
                         IsJoin = false,
                         IsStart = false,
-                        IsCompleted = false
+                        IsCompleted = false,
+                        StartTime = examUserExam.StartTime,
+                        TimeSpan = examManage.TimeSpan
                     };
+
+                    return response;
                 }
             };
             examStrategys.Add(checkStartTime);

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

@@ -39,6 +39,7 @@ using XF.Domain.Dependency;
 using Hotline.Repository.SqlSugar.Exam.Service;
 using Hotline.Repository.SqlSugar.Exam.Extensions;
 using Exam.Infrastructure.Extensions;
+using Consul;
 
 namespace Hotline.Application.Exam.Service.Practices
 {
@@ -593,44 +594,44 @@ namespace Hotline.Application.Exam.Service.Practices
             var tagIds = actionRequest.PracticeTagDtos.Select(x => x.TagId).ToList();
 
             var questionTagRepostiory = new ExamRepository<ExamQuestionTag>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+
             var questionRepository = new ExamRepository<ExamQuestion>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
 
-            var questionTagTable = questionTagRepostiory.Queryable();
-            var questionTable = questionRepository.Queryable().Where(x=>!(x.QuestionType == Share.Enums.Exams.EQuestionType.Single && x.QuestionType == Share.Enums.Exams.EQuestionType.Multi || x.QuestionType == Share.Enums.Exams.EQuestionType.Judge));
+            ISugarQueryable<ExamQuestionTag, ExamQuestion> questionTable = GetCheckQuestions(questionTagRepostiory);
 
             // 按照标签获取试题,至少取一道
             if (actionRequest.Count < actionRequest.PracticeTagDtos.Count)
             {
-                questionTagTable = questionTagTable.Where(x => tagIds.Contains(x.TagId)).Take(actionRequest.Count);
+                var queryResult = questionTable.Where((qt, q) => tagIds.Contains(qt.TagId)).Take(actionRequest.Count).Select((qt, q) => q);
+
+                return await queryResult.ToListAsync();
             }
             else
             {
-                var unionQuestions = new List<ISugarQueryable<ExamQuestionTag>>();
+                var unionQuestions = new List<ISugarQueryable<ExamQuestion>>();
                 var ids = new List<string>();
                 // 保证每个标签至少获取一道题
                 tagIds.ForEach(v =>
                 {
-                    var unionQuestion = questionTagTable;
-                    unionQuestion= unionQuestion.Where(x => x.TagId == v).Take(1);
-                    ids.Add(questionTagRepostiory.Queryable().Where(x => x.TagId == v).Select(x => x.Id).First());
+                    var unionQuestion = GetCheckQuestions(questionTagRepostiory).Where((qt, q) => qt.TagId == v).Take(1).Select((qt, q) => q);
+                    ids.Add(GetCheckQuestions(questionTagRepostiory).Where((qt, q) => qt.TagId == v).Select(qt => qt.Id).First());
                     unionQuestions.Add(unionQuestion);
-                    questionTagTable = questionTagRepostiory.Queryable();
                 });
 
-                var mainQuesiton = questionTagTable;
-                mainQuesiton = mainQuesiton.Where(x => tagIds.Contains(x.TagId) && !ids.Contains(x.Id)).Take(actionRequest.Count - tagIds.Count);
+                var mainQuesiton = GetCheckQuestions(questionTagRepostiory).Where((qt, q) => tagIds.Contains(qt.TagId) && !ids.Contains(qt.Id)).Take(actionRequest.Count - tagIds.Count).Select((qt, q) => q);
 
                 unionQuestions.Add(mainQuesiton);
 
-                questionTagTable = questionTagRepostiory.Queryable();
-                questionTagTable = questionTagRepostiory.UnionAll(unionQuestions.ToArray());
-            }
+                var queryResult = questionRepository.UnionAll(unionQuestions.ToArray());
 
-            var queryResult = questionTagTable.InnerJoin(questionTable, (t, q) => t.QuestionId == q.Id)
-                              .Select((t, q) => q);
+                return await queryResult.ToListAsync();
+            }
 
-            return await queryResult.ToListAsync();
+        }
 
+        private static ISugarQueryable<ExamQuestionTag, ExamQuestion> GetCheckQuestions(ExamRepository<ExamQuestionTag> questionTagRepostiory)
+        {
+            return questionTagRepostiory.Queryable().InnerJoin<ExamQuestion>((qt, q) => qt.QuestionId == q.Id).Where((qt, q) => q.QuestionType == Share.Enums.Exams.EQuestionType.Single || q.QuestionType == Share.Enums.Exams.EQuestionType.Multi || q.QuestionType == Share.Enums.Exams.EQuestionType.Judge);
         }
 
         private async Task<string> GenerateCode(string codePrefix, int length)

+ 20 - 0
src/Hotline.Application/Exam/Service/Trains/TrainRecordService.cs

@@ -166,9 +166,29 @@ namespace Hotline.Application.Exam.Service.Trains
 
             trainPracticeDto.TrainPracticeKnowladgeDtos = await GetTrainPracticeKnowladges(trainPracticeRequest);
 
+            trainPracticeDto.AddTrainRecordAnswerDto = await GetTrainRecordAnswer(trainPracticeRequest);
+
             return trainPracticeDto;
         }
 
+        private async Task<AddTrainRecordAnswerDto?> GetTrainRecordAnswer(TrainPracticeRequest trainPracticeRequest)
+        {
+            var trainRecordAnswerRepository = new ExamRepository<ExamTrainRecordAnswer>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            var queryable = trainRecordAnswerRepository.Queryable()
+               .InnerJoin<ExamTrainRecord>((t, x) => t.TrainRecordId == x.Id)
+               .InnerJoin<ExamTrainPlanTemplate>((t, x, p) => x.TrainPlanId == p.TrainPlanId)
+               .InnerJoin<ExamTrainPractice>((t, x, p, tp) => p.TrainTemplateId == tp.TrainTemplateId)
+               .Where((t, x, p, tp) => tp.Id == trainPracticeRequest.TrainPracticeId)
+               .Select((t, x, p, tp) => t);
+
+            var examTrainRecordAnswer = await queryable
+                .FirstAsync();
+
+            var addTrainRecordAnswerDto = _mapper.Map<ExamTrainRecordAnswer, AddTrainRecordAnswerDto>(examTrainRecordAnswer);
+
+            return addTrainRecordAnswerDto;
+        }
+
         public async Task<SimpleTrainPracticeDto> GetSimpleTrainPracticeAsync(TrainPracticeRequest trainPracticeRequest)
         {
             SqlSugar.ISugarQueryable<ExamTrainPractice> trainPractices = GetTrainPractices(trainPracticeRequest);

+ 13 - 3
src/Hotline.Application/Exam/Strategy/CheckEndTimeStrategy.cs

@@ -11,7 +11,7 @@ namespace Hotline.Application.Exam.Strategy
     {
         public string ErroMessage { get; private set; }
 
-        public Action CallBack { get; set; }
+        public Func<object> CallBack { get; set; }
 
         private IExamStrategy _next;
 
@@ -19,6 +19,9 @@ namespace Hotline.Application.Exam.Strategy
 
         private DateTime? _startTime;
 
+        private IExamStrategy _current;
+
+
         public CheckEndTimeStrategy(DateTime examEndTime, DateTime? startTime)
         {
             _examEndTime = examEndTime;
@@ -35,12 +38,19 @@ namespace Hotline.Application.Exam.Strategy
         {
             if (_examEndTime < _startTime)
             {
-                if (CallBack != null)
-                    CallBack();
                 ErroMessage = "考试结束";
                 return false;
             }
+            _current = _next;
             return _next.Validate();
         }
+
+        public object GetResult()
+        {
+            if (_current.CallBack != null)
+                return _current.CallBack();
+
+            return null;
+        }
     }
 }

+ 13 - 3
src/Hotline.Application/Exam/Strategy/CheckStartTimeStrategy.cs

@@ -6,7 +6,7 @@ namespace Hotline.Application.Exam.Strategy
     {
         public string ErroMessage { get; private set; }
 
-        public Action CallBack { get; set; }
+        public Func<object> CallBack { get; set; }
 
         private IExamStrategy _next;
 
@@ -14,6 +14,9 @@ namespace Hotline.Application.Exam.Strategy
 
         private DateTime? _startTime;
 
+        private IExamStrategy _current;
+
+
         public CheckStartTimeStrategy(DateTime examStartTime,DateTime? startTime)
         {
             _examStartTime = examStartTime;
@@ -30,12 +33,19 @@ namespace Hotline.Application.Exam.Strategy
         {
             if (_examStartTime > _startTime)
             {
-                if (CallBack != null)
-                    CallBack();
                 ErroMessage = "考试未开始";
                 return false;
             }
+            _current = _next;
             return _next.Validate();
         }
+
+        public object GetResult()
+        {
+            if (_current.CallBack != null)
+                return _current.CallBack();
+
+            return null;
+        }
     }
 }

+ 10 - 3
src/Hotline.Application/Exam/Strategy/CheckValidateCountStrategy.cs

@@ -11,7 +11,7 @@ namespace Hotline.Application.Exam.Strategy
     {
         public string ErroMessage { get; private set; }
 
-        public Action CallBack { get; set; }
+        public Func<object> CallBack { get; set; }
 
         private IExamStrategy _next;
 
@@ -19,6 +19,8 @@ namespace Hotline.Application.Exam.Strategy
 
         private int _count;
 
+        private IExamStrategy _current;
+
         public CheckValidateCountStrategy(int validateCount, int count)
         {
             _validateCount = validateCount;
@@ -35,12 +37,17 @@ namespace Hotline.Application.Exam.Strategy
         {
             if (_count>=_validateCount)
             {
-                if (CallBack != null)
-                    CallBack();
                 ErroMessage = "已超过可考次数,考试结束";
                 return false;
             }
             return _next.Validate();
         }
+        public object GetResult()
+        {
+            if (_current.CallBack != null)
+                return _current.CallBack();
+
+            return null;
+        }
     }
 }

+ 15 - 3
src/Hotline.Application/Exam/Strategy/CheckValidateTimeStrategy.cs

@@ -11,7 +11,7 @@ namespace Hotline.Application.Exam.Strategy
     {
         public string ErroMessage { get; private set; }
 
-        public Action CallBack { get; set; }
+        public Func<object> CallBack { get; set; }
 
         private IExamStrategy _next;
 
@@ -19,6 +19,9 @@ namespace Hotline.Application.Exam.Strategy
 
         private int _timeSpan;
 
+        private IExamStrategy _current;
+
+
         public CheckValidateTimeStrategy(int timeSpan, DateTime? startTime)
         {
             _startTime = startTime;
@@ -35,12 +38,21 @@ namespace Hotline.Application.Exam.Strategy
         {
             if (_startTime.Value.AddMinutes(_timeSpan) < DateTime.Now)
             {
-                if (CallBack != null)
-                    CallBack();
                 ErroMessage = "考试已超时,考试结束";
                 return false;
             }
+            _current = _next;
             return _next.Validate();
         }
+
+
+
+        public object GetResult()
+        {
+            if (_current.CallBack != null)
+                return _current.CallBack();
+
+            return null;
+        }
     }
 }

+ 12 - 8
src/Hotline.Application/Exam/Strategy/ExamStrategyProxy.cs

@@ -14,6 +14,10 @@ namespace Hotline.Application.Exam.Strategy
         /// </summary>
         public string ErrorMessage { get; private set; }
 
+        public ExamStrategyProxy()
+        {
+        }
+
 
         public bool Validate()
         {
@@ -26,19 +30,19 @@ namespace Hotline.Application.Exam.Strategy
                 }
                 else
                 {
-                    ErrorMessage = _current.ErroMessage;
-                    if (_current.CallBack != null)
-                    {
-                        _current.CallBack();
-                    }
-                    return false;
-                }
+                    ErrorMessage = _current.ErroMessage;                  
 
-                
+                    return false;
+                }                
             }
             return true;
         }
 
+        public object GetResult()
+        {
+            return _current.GetResult();
+        }
+
         public void Initial(List<IExamStrategy> examStrategys)
         {
             if (examStrategys == null || examStrategys.Count <= 0) return;

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

@@ -27,9 +27,6 @@ namespace Hotline.Share.Dtos.Trains
         /// </summary>
         [Description("关联知识")]
         public new List<TrainPracticeKnowladgeDto> TrainPracticeKnowladgeDtos { get; set; }
-
-
-        
     }
 
     /// <summary>
@@ -68,6 +65,12 @@ namespace Hotline.Share.Dtos.Trains
         /// </summary>
         [Description("培训习题选项")]
         public List<SimpleTrainPracticeOptionsDto> TrainPracticeOptionsDtos { get; set; }
+
+
+        /// <summary>
+        /// 答案
+        /// </summary>
+        public AddTrainRecordAnswerDto? AddTrainRecordAnswerDto { get; set; }
     }
 
     public class AddTrainPracticeDto : IAddRequest, IOperationStatus