浏览代码

调整考试验证

guqiang 1 月之前
父节点
当前提交
40d63f1667
共有 23 个文件被更改,包括 695 次插入169 次删除
  1. 2 13
      src/Hotline.Api/Controllers/Exam/UserExamController.cs
  2. 15 0
      src/Hotline.Application/Exam/Extensions/StartExamViewResponseExtensions.cs
  3. 2 10
      src/Hotline.Application/Exam/Interface/ExamManages/IUserExamService.cs
  4. 21 0
      src/Hotline.Application/Exam/Interface/Strategy/IExamStrategy.cs
  5. 1 1
      src/Hotline.Application/Exam/QueryExtensions/ExamManages/ExamManageQueryExtensions.cs
  6. 29 43
      src/Hotline.Application/Exam/Service/ExamManages/ExamManageService.cs
  7. 277 69
      src/Hotline.Application/Exam/Service/ExamManages/UserExamService.cs
  8. 46 0
      src/Hotline.Application/Exam/Strategy/CheckEndTimeStrategy.cs
  9. 41 0
      src/Hotline.Application/Exam/Strategy/CheckStartTimeStrategy.cs
  10. 46 0
      src/Hotline.Application/Exam/Strategy/CheckValidateCountStrategy.cs
  11. 46 0
      src/Hotline.Application/Exam/Strategy/CheckValidateTimeStrategy.cs
  12. 58 0
      src/Hotline.Application/Exam/Strategy/ExamStrategyProxy.cs
  13. 1 1
      src/Hotline.Repository.SqlSugar/Exam/Validators/ExamManages/ExamManageValidator.cs
  14. 6 0
      src/Hotline.Share/Dtos/ExamManages/ExamQuestionDto.cs
  15. 21 0
      src/Hotline.Share/Dtos/ExamManages/ExamQuestionOptionsDto.cs
  16. 12 12
      src/Hotline.Share/Dtos/ExamManages/GradingExamQuestionDto.cs
  17. 1 1
      src/Hotline.Share/Enums/Exams/EExamMode.cs
  18. 1 1
      src/Hotline.Share/Requests/Exam/ExamManagePagedRequest.cs
  19. 1 18
      src/Hotline.Share/ViewResponses/Exam/ExamManageViewResponse.cs
  20. 41 0
      src/Hotline.Share/ViewResponses/Exam/StartExamViewResponse.cs
  21. 6 0
      src/Hotline.Share/ViewResponses/Exam/UserExamResultViewResponse.cs
  22. 14 0
      src/Hotline/Exams/ExamManages/UserExam.cs
  23. 7 0
      src/Hotline/Exams/ExamManages/UserExamItem.cs

+ 2 - 13
src/Hotline.Api/Controllers/Exam/UserExamController.cs

@@ -71,20 +71,9 @@ namespace Hotline.Api.Controllers.Exam
         /// <param name="addUserExamItemDto"></param>
         /// <returns></returns>
         [HttpPost(UserExamApiRoute.Exam)]
-        public async Task<UserExamQuestionDto> Exam([FromBody] AddUserExamItemDto addUserExamItemDto)
+        public async Task<StartExamViewResponse> Exam([FromBody] UpdateUserExamItemDto updateUserExamItemDto)
         {
-            return await _userExamService.ExamAsync(addUserExamItemDto, HttpContext.RequestAborted);
-        }
-
-        /// <summary>
-        /// 更新考试
-        /// </summary>
-        /// <param name="updateUserExamItemDto"></param>
-        /// <returns></returns>
-        [HttpPut(UserExamApiRoute.UpdateExam)]
-        public async Task<UserExamQuestionDto> UpdateExam([FromBody]UpdateUserExamItemDto updateUserExamItemDto)
-        {
-           return await _userExamService.UpdateExamAsync(updateUserExamItemDto,HttpContext.RequestAborted);
+            return await _userExamService.ExamAsync(updateUserExamItemDto, HttpContext.RequestAborted);
         }
 
         /// <summary>

+ 15 - 0
src/Hotline.Application/Exam/Extensions/StartExamViewResponseExtensions.cs

@@ -0,0 +1,15 @@
+using Hotline.Share.ViewResponses.Exam;
+
+namespace Hotline.Application.Exam.Extensions
+{
+    public static class StartExamViewResponseExtensions
+    {
+        public static bool CheckValidate(this StartExamViewResponse startExamViewResponse)
+        {
+            if (startExamViewResponse.IsCompleted || !startExamViewResponse.IsJoin || !startExamViewResponse.IsStart)
+                return false;
+
+            return true;
+        }
+    }
+}

+ 2 - 10
src/Hotline.Application/Exam/Interface/ExamManages/IUserExamService.cs

@@ -55,15 +55,7 @@ namespace Exam.Application.Interface.Exam
         /// </summary>
         /// <param name="addUserExamItemDto"></param>
         /// <returns></returns>
-        Task<UserExamQuestionDto> ExamAsync(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken);
-
-        /// <summary>
-        /// 修改考试选项
-        /// </summary>
-        /// <param name="addUserExamItemDto"></param>
-        /// <param name="cancellationToken"></param>
-        /// <returns></returns>
-        Task<UserExamQuestionDto> UpdateExamAsync(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken);
+        Task<StartExamViewResponse> ExamAsync(UpdateUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken);
 
         /// <summary>
         /// 开始考试
@@ -71,7 +63,7 @@ namespace Exam.Application.Interface.Exam
         /// <param name="startUserExamDto"></param>
         /// <param name="CancellationToken"></param>
         /// <returns></returns>
-        Task StartUserExamAsync(StartUserExamDto startUserExamDto,CancellationToken cancellationToken);
+        Task<StartExamViewResponse> StartUserExamAsync(StartUserExamDto startUserExamDto,CancellationToken cancellationToken);
 
         /// <summary>
         /// 完成阅卷

+ 21 - 0
src/Hotline.Application/Exam/Interface/Strategy/IExamStrategy.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Exam.Interface.Strategy
+{
+    public interface IExamStrategy
+    {
+
+        public bool Validate();
+
+        public void SetNext(IExamStrategy examStrategy);
+
+
+        public string ErroMessage { get; }
+
+        public Action CallBack { get; set; }
+    }
+}

+ 1 - 1
src/Hotline.Application/Exam/QueryExtensions/ExamManages/ExamManageQueryExtensions.cs

@@ -17,7 +17,7 @@ namespace Hotline.Application.Exam.QueryExtensions.ExamManages
                          .AndIF(examManagePagedRequest.Code.IsNotNullOrEmpty(), x => x.Code.Contains(examManagePagedRequest.Code))
                          .AndIF(examManagePagedRequest.Name.IsNotNullOrEmpty(), x => x.Name.Contains(examManagePagedRequest.Name))
                          .AndIF(examManagePagedRequest.ExamType.IsNotNull(), x => x.ExamType == examManagePagedRequest.ExamType)
-                         .AndIF(examManagePagedRequest.Method.IsNotNull(), x => x.Method == examManagePagedRequest.Method).ToExpression();
+                         .AndIF(examManagePagedRequest.Mode.IsNotNull(), x => x.Mode == examManagePagedRequest.Mode).ToExpression();
 
             return expression;
         }

+ 29 - 43
src/Hotline.Application/Exam/Service/ExamManages/ExamManageService.cs

@@ -106,28 +106,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
         public async Task<(int, List<ExamManageViewResponse>)> GetListAsync(ExamManagePagedRequest queryRequest)
         {
-            var expression = queryRequest.GetExpression();
-            var questionTable = _repository.Queryable().Where(expression);
-
-            var queryable = questionTable.Select(e => new ExamManageViewResponse
-            {
-                Id = e.Id,
-                Code = e.Code,
-                Count = e.Count,
-                CutoffScore = e.CutoffScore,
-                EndTime = e.EndTime,
-                ExamStatus = e.ExamStatus,
-                ExamType = e.ExamType,
-                Mehtod = e.Method,
-                Mode = e.Mode,
-                Name = e.Name,
-                Remark = e.Name,
-                SortIndex = e.SortIndex,
-                StartTime = e.StartTime,
-                TimeSpan = e.TimeSpan,
-                TotalScore = e.TotalScore,
-            });
-
+            ISugarQueryable<ExamManageViewResponse> queryable = Queryable(queryRequest);
 
             var result = await queryable.ToListAsync();
 
@@ -138,27 +117,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
         public async Task<PageViewResponse<ExamManageViewResponse>> GetPagedListAsync(ExamManagePagedRequest queryRequest)
         {
-            var expression = queryRequest.GetExpression();
-            var questionTable = _repository.Queryable().Where(expression);
-
-            var queryable = questionTable.Select(e => new ExamManageViewResponse
-            {
-                Id = e.Id,
-                Code = e.Code,
-                Count = e.Count,
-                CutoffScore = e.CutoffScore,
-                EndTime = e.EndTime,
-                ExamStatus = e.ExamStatus,
-                ExamType = e.ExamType,
-                Mehtod = e.Method,
-                Mode = e.Mode,
-                Name = e.Name,
-                Remark = e.Name,
-                SortIndex = e.SortIndex,
-                StartTime = e.StartTime,
-                TimeSpan = e.TimeSpan,
-                TotalScore = e.TotalScore,
-            });
+            ISugarQueryable<ExamManageViewResponse> queryable = Queryable(queryRequest);
 
             var list = await queryable.ToPageListAsync(queryRequest.PageIndex, queryRequest.PageSize);
             var total = await queryable.CountAsync();
@@ -518,6 +477,33 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 throw new UserFriendlyException(ErrorMessage.ServiceError, string.Format(ErrorMessage.IsNotEqual, "试题分数总和", typeof(AddExamManageDto).GetDescription(nameof(AddExamManageDto.TotalScore))));
             }
         }
+
+
+
+        private ISugarQueryable<ExamManageViewResponse> Queryable(ExamManagePagedRequest queryRequest)
+        {
+            var expression = queryRequest.GetExpression();
+            var questionTable = _repository.Queryable().Where(expression);
+
+            var queryable = questionTable.Select(e => new ExamManageViewResponse
+            {
+                Id = e.Id,
+                Code = e.Code,
+                Count = e.Count,
+                CutoffScore = e.CutoffScore,
+                EndTime = e.EndTime,
+                ExamStatus = e.ExamStatus,
+                ExamType = e.ExamType,
+                Mode = e.Mode,
+                Name = e.Name,
+                Remark = e.Name,
+                SortIndex = e.SortIndex,
+                StartTime = e.StartTime,
+                TimeSpan = e.TimeSpan,
+                TotalScore = e.TotalScore,
+            });
+            return queryable;
+        }
         #endregion
     }
 }

+ 277 - 69
src/Hotline.Application/Exam/Service/ExamManages/UserExamService.cs

@@ -17,7 +17,10 @@ using Exam.Share.Dtos.ExamManage;
 using Exam.Share.ViewResponses.Exam;
 using Exam.TestPapers;
 using Hotline.Application.Exam.Core.Extensions;
+using Hotline.Application.Exam.Extensions;
+using Hotline.Application.Exam.Interface.Strategy;
 using Hotline.Application.Exam.QueryExtensions.ExamManages;
+using Hotline.Application.Exam.Strategy;
 using Hotline.Exams.ExamManages;
 using Hotline.Exams.TestPapers;
 using Hotline.Repository.SqlSugar;
@@ -38,9 +41,11 @@ using MapsterMapper;
 using NPOI.SS.Formula.Functions;
 using SqlSugar;
 using System.Linq;
+using System.Threading.Tasks;
 using XF.Domain.Authentications;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
+using XF.Domain.Repository;
 
 namespace Hotline.Application.Exam.Service.ExamManages
 {
@@ -110,7 +115,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
             }
             else
             {
-                throw new UserFriendlyException(ErrorMessage.ServiceError, string.Format(ErrorMessage.IsNotExists, nameof(Question)));
+                throw new UserFriendlyException(ErrorMessage.ServiceError, string.Format(ErrorMessage.IsNotExists, string.Concat(typeof(Question).GetDescription(),":", examQuestionRequest.QuestionId)));
             }
 
         }
@@ -129,7 +134,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 QuestionType = m.Key,
                 Questions = m.Select(n => new SimpleViewResponse
                 {
-                    Id = n.Id
+                    Id = n.QuestionId
                 }).ToList()
             }).ToList();
 
@@ -222,43 +227,190 @@ namespace Hotline.Application.Exam.Service.ExamManages
             }
         }
 
-        public async Task<UserExamQuestionDto> ExamAsync(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
+        public async Task<StartExamViewResponse> ExamAsync(UpdateUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
         {
-            await AddUserExamItem(addUserExamItemDto, cancellationToken);
+            var userExam = await new ExamRepository<UserExam>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.Id == addUserExamItemDto.UserExamId).FirstAsync();
 
-            await AddUserExamItemOptions(addUserExamItemDto, cancellationToken);
+            var startExamViewResponse = await CheckExamValid(userExam);
 
-            await AddExamAnswer(addUserExamItemDto, cancellationToken);
+            if (!startExamViewResponse.CheckValidate())
+            {
+                return startExamViewResponse;
+            }
+
+            var userExamRepository = new ExamRepository<UserExamItem>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider);
+
+            var hasUserExamItem = userExamRepository.Queryable().Where(x => x.UserExamId == addUserExamItemDto.UserExamId && x.QuestionId == addUserExamItemDto.QuestionId).Any();
+
+            if (!hasUserExamItem)
+            {
+                await AddExamAsync(userExamRepository,addUserExamItemDto, cancellationToken);
+            }
+            else
+            {
+               await  UpdateExamAsync(userExamRepository,addUserExamItemDto, cancellationToken);
+            }
 
-            var gradingExamQuestionDto = await GetNextExamQuestion(addUserExamItemDto);
+            await CalcuteExamItemScore(userExamRepository, addUserExamItemDto, cancellationToken);
 
-            return gradingExamQuestionDto;
+            return startExamViewResponse;
         }
+        public async Task<StartExamViewResponse> StartUserExamAsync(StartUserExamDto startUserExamDto, CancellationToken cancellationToken)
+        {
+            var userExam = await _repository.GetAsync(x => x.Id == startUserExamDto.Id);
+
+            if (userExam == null) return new StartExamViewResponse
+            {
+                IsJoin = false
+            };
+
+            if (userExam.StartTime == null)
+                userExam.StartTime = DateTime.Now;
 
+            var startExamViewResponse = await CheckExamValid(userExam);
 
-        public async Task<UserExamQuestionDto> UpdateExamAsync(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
+            if (!startExamViewResponse.CheckValidate())
+            {
+                return startExamViewResponse;
+            }
+
+            userExam.ExamStatus = Share.Enums.Exams.EExamStatus.Executing;          
+
+            userExam.ToUpdate(_sessionContext);
+
+            await _repository.UpdateWithValidateAsync(userExam, cancellationToken);
+
+            return new StartExamViewResponse
+            {
+                StartTime = userExam.StartTime,
+                IsCompleted = false
+            };
+        }
+
+        private async Task<StartExamViewResponse> CheckExamValid(UserExam userExam)
         {
-            await UpdateUserExamItem(updateUserExamItemDto, cancellationToken);
+            var examManageRepository = new ExamRepository<ExamManage>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider);
 
-            await ModifyUserItemOptions(updateUserExamItemDto, cancellationToken);
+            var examManage = await examManageRepository.Queryable().Where(x => x.Id == userExam.ExamId).FirstAsync();
 
-            await UpdateExamAnswer(updateUserExamItemDto, cancellationToken);
+            var startExamViewResponse = new StartExamViewResponse
+            {
+                IsJoin = false,
+                IsCompleted = true
+            };
+
+            if (examManage != null)
+            {
+                var examStrategyProxy = new ExamStrategyProxy();
 
-            var gradingExamQuestionDto = await GetNextExamQuestion(updateUserExamItemDto);
+                var examStrategys = new List<IExamStrategy>();
+                startExamViewResponse = AddCheckStartTimeStrategy(userExam, examManage, startExamViewResponse, examStrategys);
+                startExamViewResponse = AddCheckEndTimeStrategy(userExam, examManage, startExamViewResponse, examStrategys);
+                startExamViewResponse = AddCheckValidateTimeStrategy(userExam, examManage, startExamViewResponse, examStrategys);
+                startExamViewResponse = AddCheckValidateCountStrategy(userExam, examManage, startExamViewResponse, examStrategys);
 
-            return gradingExamQuestionDto;
+                if (!examStrategyProxy.Validate())
+                {
+                    return startExamViewResponse;
+                }
+            }
+
+            return startExamViewResponse;
         }
-        public async Task StartUserExamAsync(StartUserExamDto startUserExamDto, CancellationToken cancellationToken)
+
+        private StartExamViewResponse AddCheckValidateCountStrategy(UserExam userExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List<IExamStrategy> examStrategys)
         {
-            var userExam = await _repository.GetAsync(x => x.Id == startUserExamDto.Id);
+            if(examManage.ExamType == Share.Enums.Exams.EExamType.Simulate)
+            {
+                var checkStartTime = new CheckValidateCountStrategy(1, 1)
+                {
+                    CallBack = () =>
+                    {
+                        startExamViewResponse = new StartExamViewResponse
+                        {
+                            IsJoin = false,
+                            IsStart = false,
+                            IsCompleted = true
+                        };
+                    }
+                };
+                examStrategys.Add(checkStartTime);
+                return startExamViewResponse;
+            }
+            else
+            {
+                var count = new ExamRepository<UserExam>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).CountAsync(x => x.ExamId == examManage.Id && x.UserId == userExam.UserId).Result;
 
-            if (userExam == null) return;
+                var checkStartTime = new CheckValidateCountStrategy(examManage.Count, count)
+                {
+                    CallBack = () =>
+                    {
+                        startExamViewResponse = new StartExamViewResponse
+                        {
+                            IsJoin = false,
+                            IsStart = false,
+                            IsCompleted = true
+                        };
+                    }
+                };
+                examStrategys.Add(checkStartTime);
+                return startExamViewResponse;
+            }
+            
+        }
 
-            userExam.ExamStatus = Share.Enums.Exams.EExamStatus.Executing;
+        private StartExamViewResponse AddCheckValidateTimeStrategy(UserExam userExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List<IExamStrategy> examStrategys)
+        {
+            var checkStartTime = new CheckValidateTimeStrategy(examManage.TimeSpan, userExam.StartTime)
+            {
+                CallBack = () =>
+                {
+                    startExamViewResponse = new StartExamViewResponse
+                    {
+                        IsJoin = false,
+                        IsStart = false,
+                        IsCompleted = true
+                    };
+                }
+            };
+            examStrategys.Add(checkStartTime);
+            return startExamViewResponse;
+        }
 
-            userExam.ToUpdate(_sessionContext);
+        private StartExamViewResponse AddCheckEndTimeStrategy(UserExam userExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List<IExamStrategy> examStrategys)
+        {
+            var checkStartTime = new CheckEndTimeStrategy(examManage.EndTime, DateTime.Now)
+            {
+                CallBack = () =>
+                {
+                    startExamViewResponse = new StartExamViewResponse
+                    {
+                        IsJoin = false,
+                        IsStart = false,
+                        IsCompleted = true
+                    };
+                }
+            };
+            examStrategys.Add(checkStartTime);
+            return startExamViewResponse;
+        }
 
-            await _repository.ValidateUpdateAsync(userExam, cancellationToken);
+        private static StartExamViewResponse AddCheckStartTimeStrategy(UserExam userExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List<IExamStrategy> examStrategys)
+        {
+            var checkStartTime = new CheckStartTimeStrategy(examManage.StartTime, userExam.StartTime)
+            {
+                CallBack = () =>
+                {
+                    startExamViewResponse = new StartExamViewResponse
+                    {
+                        IsJoin = false,
+                        IsStart = false,
+                        IsCompleted = false
+                    };
+                }
+            };
+            examStrategys.Add(checkStartTime);
+            return startExamViewResponse;
         }
 
         public async Task CompleteGradingAsync(GradingExamDto gradingExtamDto, CancellationToken cancellationToken)
@@ -290,12 +442,15 @@ namespace Hotline.Application.Exam.Service.ExamManages
             var expression = gradingExamRequest.GetExpression();
             var userExamTable = _repository.Queryable().Where(expression);
 
+            var questionScoreRepository = new ExamRepository<ExamQuestionScore>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider);
+
             var userExamItemTable = _userExamItemRepository.Queryable();
             var userExamItemOptionTable = _userExamItemOptionRepository.Queryable();
             var examAnswerTable = new ExamRepository<ExamAnswer>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
             var questionTable = new ExamRepository<TestPaperItem>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
             var quesitonOptionTable = new ExamRepository<TestPaperItemOptions>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
             var testPaperItemAnswerTable = new ExamRepository<TestPaperItemAnswer>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
+            var questionScoreTable = questionScoreRepository.Queryable();
 
             var queryResult = await userExamTable.InnerJoin(userExamItemTable, (e, i) => e.Id == i.UserExamId)
                 .InnerJoin(questionTable, (e, i, q) => i.QuestionId == q.Id)
@@ -303,8 +458,10 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 .LeftJoin(quesitonOptionTable, (e, i, q, o, qo) => o.QuestionOptionId == qo.Id)
                 .LeftJoin(examAnswerTable, (e, i, q, o, qo, a) => i.Id == a.UserExamItemId)
                 .LeftJoin(testPaperItemAnswerTable, (e, i, q, o, qo, a, ta) => ta.QuestionId == qo.QuestionId)
+                .InnerJoin(questionScoreTable, (e, i, q, o, qo, a, ta, s) => q.QuestionType == s.QuestionType && e.ExamId == s.ExamManageId)
+                .Where((e, i, q, o, qo, a, ta, s) => !q.QuestionType.CheckSelectType())
                 .Select(
-                (e, i, q, o, qo, a, ta) => new GradingExamQuestionTempDto
+                (e, i, q, o, qo, a, ta, s) => new GradingExamQuestionTempDto
                 {
                     Id = i.Id,
                     QuestionType = q.QuestionType,
@@ -316,7 +473,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
                     Content = qo.Content,
                     Label = qo.Label,
                     IsAnswer = qo.IsAnswer,
-                    IsSelected = o != null
+                    IsSelected = o != null,
+                    Score = s.Score
                 }
                 ).ToListAsync();
 
@@ -329,16 +487,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 Answer = g.FirstOrDefault().Answer,
                 QuestionType = g.Key.QuestionType,
                 Id = g.Key.Id,
+                Score = g.FirstOrDefault().Score,
                 Title = g.FirstOrDefault().Title,
-                UserExamItemOptionDtos = g.Select(i => new GradingUserExamItemOptionDto
-                {
-                    QuestionOptionId = i.QuestionOptionId,
-                    UserExamItemId = i.UserExamItemId,
-                    Content = i.Content,
-                    IsAnswer = i.IsAnswer,
-                    IsSelected = i.IsSelected,
-                    Label = i.Label
-                }).ToList(),
                 CorrectAnswer = g.Key.QuestionType.CheckSelectType() ? string.Join(",", g.Where(i => i.IsAnswer).Select(n => n.Label)) : g.FirstOrDefault()?.CorrectAnswer
             }).ToList();
 
@@ -427,17 +577,74 @@ namespace Hotline.Application.Exam.Service.ExamManages
         #region private method
 
 
+
+        private async Task CalcuteExamItemScore(ExamRepository<UserExamItem> userExamRepository, UpdateUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
+        {
+            if (!addUserExamItemDto.QuestionType.CheckSelectType()) return;
+
+            var testPaperItemOptionsRepository = new ExamRepository<TestPaperItemOptions>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider);
+            var examManageRepository = new ExamRepository<ExamManage>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider);
+            var testPaperItemRepository = new ExamRepository<TestPaperItem>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider);
+            var examQuestionScoreRepository = new ExamRepository<ExamQuestionScore>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider);
+            var testPaperOptionsTable = testPaperItemOptionsRepository.Queryable().Where(x => x.QuestionId == addUserExamItemDto.QuestionId && x.IsAnswer);
+            var testPaperItemTable = testPaperItemRepository.Queryable();
+            var userExamTable = _repository.Queryable().Where(x => x.Id == addUserExamItemDto.UserExamId);
+            var examManageTable = examManageRepository.Queryable();
+            var testPaperOptionIds = await testPaperOptionsTable.InnerJoin(testPaperItemTable, (t, i) => t.TestPaperItemId == i.Id)
+                .InnerJoin(examManageTable, (t, i, e) => i.TestPaperId == e.TestPaperId)
+                .InnerJoin(userExamTable, (t, i, e, u) => e.Id == u.ExamId)
+                .Select((t, i, e, u) => t.Id).ToListAsync();
+
+            var isCorrect = addUserExamItemDto.UserExamItemOptionDtos.Select(x => x.QuestionOptionId).OrderBy(x => x).SequenceEqual(testPaperOptionIds.OrderBy(x => x));
+
+            var userExamItem = await userExamRepository.GetAsync(x => x.UserExamId == addUserExamItemDto.UserExamId && x.QuestionId == addUserExamItemDto.QuestionId);
+            var examQuesiontScores = await examQuestionScoreRepository.Queryable().Where(x => x.QuestionType == addUserExamItemDto.QuestionType)
+                .InnerJoin(userExamTable, (e, u) => e.Id == u.ExamId)
+                .Select((e, u) => e).ToListAsync();
+            userExamItem.IsCheck = true;
+            userExamItem.Score = isCorrect ? examQuesiontScores.FirstOrDefault()?.Score : 0;
+            userExamItem.ToUpdate(_sessionContext);
+            await userExamRepository.UpdateWithValidateAsync(userExamItem, cancellationToken);
+        }
+
+        private async Task AddExamAsync(IRepository<UserExamItem> userExamItemRepository, AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
+        {
+            var userExamItem = await AddUserExamItem(addUserExamItemDto, cancellationToken);
+
+            userExamItem.UserExamItemOptionses = await AddUserExamItemOptions(addUserExamItemDto, cancellationToken);
+
+            userExamItem.ExamAnswers = await AddExamAnswer(addUserExamItemDto, cancellationToken);
+
+            await userExamItemRepository.AddNav(userExamItem)
+                .Include(x => x.UserExamItemOptionses)
+                .Include(x => x.ExamAnswers)
+                .ExecuteCommandAsync();
+        }
+
+        private async Task UpdateExamAsync(IRepository<UserExamItem> userExamItemRepository, UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
+        {
+            var userExamItem = await UpdateUserExamItem(updateUserExamItemDto, cancellationToken);
+
+            userExamItem.UserExamItemOptionses = await ModifyUserItemOptions(updateUserExamItemDto, cancellationToken);
+
+            userExamItem.ExamAnswers = await UpdateExamAnswer(updateUserExamItemDto, cancellationToken);
+
+            await userExamItemRepository.UpdateNav(userExamItem)
+              .Include(x => x.UserExamItemOptionses)
+              .Include(x => x.ExamAnswers)
+              .ExecuteCommandAsync();
+        }
         private async Task<GradingExamQuestionDto> GetNextExamQuestion(GradingExtamItemDto gradingExtamItemDto)
         {
             // TODO: 获取未阅卷的第一道题
             var current = _userExamItemRepository.Queryable().Where(x => x.Id == gradingExtamItemDto.UserExamItemId);
             var userExamItemTable = _userExamItemRepository.Queryable().Where(x => !x.IsCheck);
 
-            var userExamItem = current.InnerJoin(userExamItemTable, (c, u) => c.UserExamId == u.UserExamId).OrderBy(x => x.SortIndex).First();
+            var userExamItem = current.InnerJoin(userExamItemTable, (c, u) => c.UserExamId == u.UserExamId).OrderBy((c, u) => c.SortIndex).First();
 
             if (userExamItem != null)
             {
-                var testPaperItem = new ExamRepository<TestPaperItem>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.Id == userExamItem.Id).First();
+                var testPaperItem = new ExamRepository<TestPaperItem>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.Id == userExamItem.Id && !x.QuestionType.CheckSelectType()).First();
 
                 if (testPaperItem == null) return null;
 
@@ -445,36 +652,14 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
                 gradingExamQuestionDto = _mapper.Map<TestPaperItem, GradingExamQuestionDto>(testPaperItem, gradingExamQuestionDto);
 
-                if (testPaperItem.QuestionType.CheckSelectType())
-                {
-                    var userExamItemOptionTable = _userExamItemOptionRepository.Queryable().Where(x => x.UserExamItemId == userExamItem.Id);
-                    var quesitonOptionTable = new ExamRepository<TestPaperItemOptions>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
-
-                    var queryResult = quesitonOptionTable.LeftJoin(userExamItemOptionTable, (q, u) => u.QuestionOptionId == q.Id)
-                        .Select((q, u) => new GradingUserExamItemOptionDto
-                        {
-                            Content = q.Content,
-                            QuestionOptionId = u.QuestionOptionId,
-                            UserExamItemId = u != null ? u.UserExamItemId : string.Empty,
-                            IsAnswer = q.IsAnswer,
-                            Label = q.Label,
-                            IsSelected = u != null
-                        });
+                var examAnswer = new ExamRepository<ExamAnswer>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.UserExamItemId == userExamItem.Id).First();
 
-                    gradingExamQuestionDto.UserExamItemOptionDtos = queryResult.ToList();
+                var testPaperItemAnswer = await new ExamRepository<TestPaperItemAnswer>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().FirstAsync(x => x.QuestionId == testPaperItem.QuestionId && x.TestPaperItemId == testPaperItem.Id);
 
-                    gradingExamQuestionDto.CorrectAnswer = string.Join(",", gradingExamQuestionDto.UserExamItemOptionDtos.Where(x => x.IsAnswer).Select(m => m.Label));
-                }
-                else
-                {
-                    var examAnswer = new ExamRepository<ExamAnswer>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.UserExamItemId == userExamItem.Id).First();
+                gradingExamQuestionDto.Answer = examAnswer.Answer ?? string.Empty;
 
-                    var testPaperItemAnswer = await new ExamRepository<TestPaperItemAnswer>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).Queryable().FirstAsync(x => x.QuestionId == testPaperItem.QuestionId && x.TestPaperItemId == testPaperItem.Id);
+                gradingExamQuestionDto.CorrectAnswer = testPaperItemAnswer != null ? testPaperItemAnswer.Answer ?? string.Empty : string.Empty;
 
-                    gradingExamQuestionDto.Answer = examAnswer.Answer ?? string.Empty;
-
-                    gradingExamQuestionDto.CorrectAnswer = testPaperItemAnswer != null ? testPaperItemAnswer.Answer ?? string.Empty : string.Empty;
-                }
 
                 return gradingExamQuestionDto;
 
@@ -483,9 +668,11 @@ namespace Hotline.Application.Exam.Service.ExamManages
             return null;
         }
 
-        private async Task AddExamAnswer(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
+        private async Task<List<ExamAnswer>> AddExamAnswer(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
         {
-            if (addUserExamItemDto.QuestionType.CheckSelectType()) return;
+            if (addUserExamItemDto.QuestionType.CheckSelectType()) return null;
+
+            var examAnswers = new List<ExamAnswer>();
 
             var examAnswer = new ExamAnswer
             {
@@ -496,6 +683,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
             examAnswer.ToInsert(_sessionContext);
 
             await new ExamRepository<ExamAnswer>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider).ValidateAddAsync(examAnswer, cancellationToken);
+
+            return examAnswers;
         }
 
 
@@ -557,7 +746,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
         }
 
-        private async Task UpdateExamAnswer(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
+        private async Task<List<ExamAnswer>> UpdateExamAnswer(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
         {
             var repository = new ExamRepository<ExamAnswer>(_repository.UOW, _dataPermissionFilterBuilder, _serviceProvider);
 
@@ -574,11 +763,19 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 examAnswer.ToUpdate(_sessionContext);
 
                 await repository.ValidateAddAsync(examAnswer, cancellationToken);
+
+                var examAnswers = new List<ExamAnswer>();
+
+                examAnswers.Add(examAnswer);
+
+                return examAnswers;
             }
+
+            return null;
         }
 
 
-        private async Task ModifyUserItemOptions(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
+        private async Task<List<UserExamItemOptions>> ModifyUserItemOptions(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
         {
             if (updateUserExamItemDto.QuestionType.CheckSelectType())
             {
@@ -602,8 +799,10 @@ namespace Hotline.Application.Exam.Service.ExamManages
                     addUserExamItemDto.UserExamItemOptionDtos.Add(_mapper.Map<AddUserExamItemOptionDto>(item));
                 });
 
-                await AddUserExamItemOptions(addUserExamItemDto, cancellationToken);
+                return await AddUserExamItemOptions(addUserExamItemDto, cancellationToken);
             }
+
+            return null;
         }
 
         private async Task UpdateUserItemOptions(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
@@ -637,12 +836,14 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
         }
 
-        private async Task UpdateUserExamItem(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
+        private async Task<UserExamItem> UpdateUserExamItem(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
         {
-            var userExamItem = await _userExamItemRepository.GetAsync(x => x.Id == updateUserExamItemDto.Id);
+            var userExamItem = await _userExamItemRepository.GetAsync(x => x.UserExamId == updateUserExamItemDto.UserExamId && x.QuestionId == updateUserExamItemDto.QuestionId);
 
             userExamItem = _mapper.Map<UpdateUserExamItemDto, UserExamItem>(updateUserExamItemDto, userExamItem);
 
+            updateUserExamItemDto.Id = userExamItem.Id;
+
             userExamItem.ToUpdate(_sessionContext);
 
             await _userExamItemRepository.ValidateUpdateAsync(userExamItem, cancellationToken);
@@ -654,10 +855,12 @@ namespace Hotline.Application.Exam.Service.ExamManages
                     updateUserExamItemDto.UserExamItemOptionDtos.ForEach(x => x.UserExamItemId = updateUserExamItemDto.Id);
                 }
             }
+
+            return userExamItem;
         }
 
 
-        private async Task AddUserExamItemOptions(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
+        private async Task<List<UserExamItemOptions>> AddUserExamItemOptions(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
         {
             var userExamItemOptions = new List<UserExamItemOptions>();
 
@@ -675,9 +878,11 @@ namespace Hotline.Application.Exam.Service.ExamManages
             userExamItemOptions.ToInsert(_sessionContext);
 
             await _userExamItemOptionRepository.ValidateAddAsync(userExamItemOptions, cancellationToken);
+
+            return userExamItemOptions;
         }
 
-        private async Task AddUserExamItem(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
+        private async Task<UserExamItem> AddUserExamItem(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
         {
             var userExamItem = _mapper.Map<UserExamItem>(addUserExamItemDto);
 
@@ -692,6 +897,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
                     addUserExamItemDto.UserExamItemOptionDtos.ForEach(x => x.UserExamItemId = userExamItem.Id);
                 }
             }
+
+            return userExamItem;
         }
 
         private async Task DeleteUserExamItemOptions(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
@@ -725,7 +932,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 EndTime = e.EndTime,
                 StartTime = e.StartTime,
                 TimeSpan = e.TimeSpan,
-                ExamType = e.ExamType
+                ExamType = e.ExamType,
+                ExamId = e.Id
             });
             return queryable;
         }

+ 46 - 0
src/Hotline.Application/Exam/Strategy/CheckEndTimeStrategy.cs

@@ -0,0 +1,46 @@
+using Hotline.Application.Exam.Interface.Strategy;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Exam.Strategy
+{
+    public class CheckEndTimeStrategy : IExamStrategy
+    {
+        public string ErroMessage { get; private set; }
+
+        public Action CallBack { get; set; }
+
+        private IExamStrategy _next;
+
+        private DateTime _examEndTime;
+
+        private DateTime? _startTime;
+
+        public CheckEndTimeStrategy(DateTime examEndTime, DateTime? startTime)
+        {
+            _examEndTime = examEndTime;
+            _startTime = startTime;
+        }
+
+
+        public void SetNext(IExamStrategy examStrategy)
+        {
+            _next = examStrategy;
+        }
+
+        public bool Validate()
+        {
+            if (_examEndTime < _startTime)
+            {
+                if (CallBack != null)
+                    CallBack();
+                ErroMessage = "考试结束";
+                return false;
+            }
+            return _next.Validate();
+        }
+    }
+}

+ 41 - 0
src/Hotline.Application/Exam/Strategy/CheckStartTimeStrategy.cs

@@ -0,0 +1,41 @@
+using Hotline.Application.Exam.Interface.Strategy;
+
+namespace Hotline.Application.Exam.Strategy
+{
+    public class CheckStartTimeStrategy : IExamStrategy
+    {
+        public string ErroMessage { get; private set; }
+
+        public Action CallBack { get; set; }
+
+        private IExamStrategy _next;
+
+        private DateTime _examStartTime;
+
+        private DateTime? _startTime;
+
+        public CheckStartTimeStrategy(DateTime examStartTime,DateTime? startTime)
+        {
+            _examStartTime = examStartTime;
+            _startTime = startTime;
+        }
+
+
+        public void SetNext(IExamStrategy examStrategy)
+        {
+            _next = examStrategy;
+        }
+
+        public bool Validate()
+        {
+            if (_examStartTime > _startTime)
+            {
+                if (CallBack != null)
+                    CallBack();
+                ErroMessage = "考试未开始";
+                return false;
+            }
+            return _next.Validate();
+        }
+    }
+}

+ 46 - 0
src/Hotline.Application/Exam/Strategy/CheckValidateCountStrategy.cs

@@ -0,0 +1,46 @@
+using Hotline.Application.Exam.Interface.Strategy;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Exam.Strategy
+{
+    public class CheckValidateCountStrategy : IExamStrategy
+    {
+        public string ErroMessage { get; private set; }
+
+        public Action CallBack { get; set; }
+
+        private IExamStrategy _next;
+
+        private int _validateCount;
+
+        private int _count;
+
+        public CheckValidateCountStrategy(int validateCount, int count)
+        {
+            _validateCount = validateCount;
+            _count = count;
+        }
+
+
+        public void SetNext(IExamStrategy examStrategy)
+        {
+            _next = examStrategy;
+        }
+
+        public bool Validate()
+        {
+            if (_count>=_validateCount)
+            {
+                if (CallBack != null)
+                    CallBack();
+                ErroMessage = "已超过可考次数,考试结束";
+                return false;
+            }
+            return _next.Validate();
+        }
+    }
+}

+ 46 - 0
src/Hotline.Application/Exam/Strategy/CheckValidateTimeStrategy.cs

@@ -0,0 +1,46 @@
+using Hotline.Application.Exam.Interface.Strategy;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Exam.Strategy
+{
+    public class CheckValidateTimeStrategy : IExamStrategy
+    {
+        public string ErroMessage { get; private set; }
+
+        public Action CallBack { get; set; }
+
+        private IExamStrategy _next;
+
+        private DateTime? _startTime;
+
+        private int _timeSpan;
+
+        public CheckValidateTimeStrategy(int timeSpan, DateTime? startTime)
+        {
+            _startTime = startTime;
+            _timeSpan = timeSpan;
+        }
+
+
+        public void SetNext(IExamStrategy examStrategy)
+        {
+            _next = examStrategy;
+        }
+
+        public bool Validate()
+        {
+            if (_startTime.Value.AddMinutes(_timeSpan) < DateTime.Now)
+            {
+                if (CallBack != null)
+                    CallBack();
+                ErroMessage = "考试已超时,考试结束";
+                return false;
+            }
+            return _next.Validate();
+        }
+    }
+}

+ 58 - 0
src/Hotline.Application/Exam/Strategy/ExamStrategyProxy.cs

@@ -0,0 +1,58 @@
+using Hotline.Application.Exam.Interface.Strategy;
+
+namespace Hotline.Application.Exam.Strategy
+{
+    public class ExamStrategyProxy
+    {
+        /// <summary>
+        /// 当前策略
+        /// </summary>
+        private IExamStrategy _current;
+
+        /// <summary>
+        /// 错误消息
+        /// </summary>
+        public string ErrorMessage { get; private set; }
+
+
+        public bool Validate()
+        {
+            if(_current!=null)
+            {
+
+                if (_current.Validate())
+                {
+                    return true;
+                }
+                else
+                {
+                    ErrorMessage = _current.ErroMessage;
+                    if (_current.CallBack != null)
+                    {
+                        _current.CallBack();
+                    }
+                    return false;
+                }
+
+                
+            }
+            return true;
+        }
+
+        public void Initial(List<IExamStrategy> examStrategys)
+        {
+            if (examStrategys == null || examStrategys.Count <= 0) return;
+
+            var current = examStrategys.FirstOrDefault();
+            if (current != null)
+            {
+                for (var i = 1; i < examStrategys.Count - 1; i++)
+                {
+                    current.SetNext(examStrategys[i]);
+                    current = examStrategys[i];
+                }
+            }
+            _current = examStrategys.FirstOrDefault();
+        }
+    }
+}

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

@@ -53,7 +53,7 @@ namespace Exam.Application
             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.ExamType == EExamType.Formal && e.StartTime < v).WithMessage(x => string.Format(ErrorMessage.Greater, x.GetType().GetDescription(nameof(ExamManage.EndTime)), x.GetType().GetDescription(nameof(ExamManage.StartTime))));
+            RuleFor(m => m.EndTime).Must((e, v) => e.ExamType == EExamType.Simulate || 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))));
         }
 

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

@@ -22,6 +22,12 @@ namespace Hotline.Share.Dtos.ExamManages
         [Description("题型")]
         public EQuestionType QuestionType { get; set; }
 
+        /// <summary>
+        /// 分数
+        /// </summary>
+        [Description("分数")]
+        public int Score { get; set; }
+
         /// <summary>
         /// 考试选项
         /// </summary>

+ 21 - 0
src/Hotline.Share/Dtos/ExamManages/ExamQuestionOptionsDto.cs

@@ -16,5 +16,26 @@ namespace Hotline.Share.Dtos.ExamManages
         /// </summary>
         [Description("试题")]
         public string QuestionId { get; set; }
+
+        /// <summary>
+        /// 选项标签
+        /// </summary>
+        [Description("选项标签")]
+        public string Label { get; set; }
+    }
+
+    public class GradingQuestionOptions: ExamQuestionOptionsDto
+    {
+        /// <summary>
+        /// 是否选中
+        /// </summary>
+        [Description("是否选中")]
+        public bool IsSelected { get; set; }
+
+        /// <summary>
+        /// 是否答案
+        /// </summary>
+        [Description("是否答案")]
+        public bool IsAnswer { get; set; }
     }
 }

+ 12 - 12
src/Hotline.Share/Dtos/ExamManages/GradingExamQuestionDto.cs

@@ -21,18 +21,6 @@ namespace Exam.Application.Interface.Exam
 
         public string CorrectAnswer { get; set; }
 
-        /// <summary>
-        /// 得分
-        /// </summary>
-        [Description("得分")]
-        public int? Score { get; set; }
-
-        /// <summary>
-        /// 考试明细选项
-        /// </summary>
-        [Description("考试明细选项")]
-        public List<GradingUserExamItemOptionDto> UserExamItemOptionDtos { get; set; }
-
     }
 
     public class GradingExamQuestionTempDto
@@ -102,6 +90,12 @@ namespace Exam.Application.Interface.Exam
         /// </summary>
         [Description("是否选中")]
         public bool IsSelected { get; set; }
+
+        /// <summary>
+        /// 分数
+        /// </summary>
+        [Description("分数")]
+        public int Score { get; set; }
     }
 
     public class UserExamQuestionDto:IActionRequest
@@ -135,5 +129,11 @@ namespace Exam.Application.Interface.Exam
         /// </summary>
         [Description("考试明细选项")]
         public List<UserExamItemOptionDto> UserExamItemOptionDtos { get; set; }
+
+        /// <summary>
+        /// 考试是否结束
+        /// </summary>
+        [Description("考试是否结束")]
+        public bool IsCompleted { get; set; }
     }
 }

+ 1 - 1
src/Hotline.Share/Enums/Exams/EExamMode.cs

@@ -12,7 +12,7 @@ namespace Hotline.Share.Enums.Exams
         /// <summary>
         /// 自选试题
         /// </summary>
-        [Description("自选试题")]
+        [Description("统一试卷")]
         Manual = 1,
         /// <summary>
         /// 导入

+ 1 - 1
src/Hotline.Share/Requests/Exam/ExamManagePagedRequest.cs

@@ -16,7 +16,7 @@ namespace Hotline.Share.Requests.Exam
         /// 考核方式
         /// </summary>
         [Description("考核方式")]
-        public EMethod? Method { get; set; }
+        public EExamMode? Mode { get; set; }
 
         /// <summary>
         /// 考试编号

+ 1 - 18
src/Hotline.Share/ViewResponses/Exam/ExamManageViewResponse.cs

@@ -48,24 +48,7 @@ namespace Exam.Share.ViewResponses.Exam
                 return Mode.GetDescription();
             }
         }
-
-        /// <summary>
-        /// 考核方式
-        /// </summary>
-        [Description("考核方式")]
-        public EMethod Mehtod { get; set; }
-
-        /// <summary>
-        /// 组卷方式
-        /// </summary>
-        [Description("组卷方式")]
-        public string MehtodDes
-        {
-            get
-            {
-                return Mehtod.GetDescription();
-            }
-        }
+       
 
         /// <summary>
         /// 组卷方式

+ 41 - 0
src/Hotline.Share/ViewResponses/Exam/StartExamViewResponse.cs

@@ -0,0 +1,41 @@
+using Exam.Infrastructure.Data.Interface;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Share.ViewResponses.Exam
+{
+    /// <summary>
+    /// 开始考试结果
+    /// </summary>
+    [Description("开始考试结果")]
+    public class StartExamViewResponse
+    {
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        [Description("开始时间")]
+        public DateTime? StartTime { get; set; }
+
+        /// <summary>
+        /// 是否结束
+        /// </summary>
+        [Description("是否结束")]
+        public bool IsCompleted { get; set; }
+
+        /// <summary>
+        /// 是否开始
+        /// </summary>
+        [Description("是否开始")]
+        public bool IsStart { get; set; } = true;
+
+        /// <summary>
+        /// 是否参与考试
+        /// </summary>
+        [Description("是否参与考试")]
+        public bool IsJoin { get; set; } = true;
+    }
+}

+ 6 - 0
src/Hotline.Share/ViewResponses/Exam/UserExamResultViewResponse.cs

@@ -109,5 +109,11 @@ namespace Exam.Share.ViewResponses.Exam
         /// </summary>
         [Description("考试类型")]
         public EExamType ExamType { get; set; }
+
+        /// <summary>
+        /// 考试ID
+        /// </summary>
+        [Description("考试ID")]
+        public string ExamId { get; set; }
     }
 }

+ 14 - 0
src/Hotline/Exams/ExamManages/UserExam.cs

@@ -59,5 +59,19 @@ namespace Exam.ExamManages
         [SugarColumn(ColumnDescription = "是否交卷")]
         [Description("是否交卷")]
         public bool IsSubmit { get; set; }
+
+        /// <summary>
+        /// 开始考试时间
+        /// </summary>
+        [SugarColumn(ColumnDescription = "开始考试时间")]
+        [Description("开始考试时间")]
+        public DateTime? StartTime { get; set; }
+
+        /// <summary>
+        /// 是否补考
+        /// </summary>
+        [SugarColumn(ColumnDescription = "是否补考")]
+        [Description("是否补考")]
+        public bool IsReExam { get; set; }
     }
 }

+ 7 - 0
src/Hotline/Exams/ExamManages/UserExamItem.cs

@@ -1,5 +1,6 @@
 using System.ComponentModel;
 using Hotline.Exams.Base;
+using Hotline.Exams.ExamManages;
 using SqlSugar;
 
 namespace Exam.ExamManages
@@ -37,5 +38,11 @@ namespace Exam.ExamManages
         [SugarColumn(ColumnDescription ="是否已阅卷")]
         [Description("是否已阅卷")]
         public bool IsCheck { get; set; }
+
+        [Navigate(NavigateType.OneToMany,nameof(UserExamItemOptions.UserExamItemId))]
+        public List<UserExamItemOptions> UserExamItemOptionses { get; set; }
+
+        [Navigate(NavigateType.OneToMany, nameof(ExamAnswer.UserExamItemId))]
+        public List<ExamAnswer> ExamAnswers { get; set; }
     }
 }