Browse Source

Merge branch 'feature/exam' into release

xf 2 weeks ago
parent
commit
b245ae34ed

+ 2 - 0
src/Hotline.Api/Controllers/Exam/ExamManageController.cs

@@ -59,6 +59,8 @@ namespace Hotline.Api.Controllers.Exam
         [HttpPost(ExamManageApiRoute.GetPagedList)]
         public async Task<ExamManagePageViewResponse> GetPagedList([FromBody] ExamManagePagedRequest questionPagedRequest)
         {
+            await _examManageService.UpdateExamStatus(new EntityQueryRequest(), HttpContext.RequestAborted);
+
             var questionPageViewResponse = await _examManageService.GetPagedListAsync(questionPagedRequest);
 
             return questionPageViewResponse as ExamManagePageViewResponse;

+ 37 - 1
src/Hotline.Api/Controllers/Exam/TrainRecordController.cs

@@ -1,13 +1,17 @@
 using DocumentFormat.OpenXml.Office2010.ExcelAc;
 using Exam.Infrastructure.Data.Entity;
 using Exam.Share.Dtos.Trains;
+using Exam.Share.ViewResponses.Exam;
 using Exam.Share.ViewResponses.Train;
 using Hotline.Application.Exam.Constants.ApiRoutes;
 using Hotline.Application.Exam.Interface.Train;
+using Hotline.Share.Dtos.Order;
 using Hotline.Share.Dtos.Trains;
 using Hotline.Share.Requests.Exam;
 using Hotline.Share.Requests.Train;
 using Hotline.Share.ViewResponses.Trains;
+using Hotline.Tools;
+using MapsterMapper;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Train.Application.Interface.Train;
@@ -17,10 +21,12 @@ namespace Hotline.Api.Controllers.Exam
     public class TrainRecordController : BaseController
     {
         private readonly ITrainRecordService _trainRecordService;
+        private readonly IMapper _mapper;
 
-        public TrainRecordController(ITrainRecordService trainRecordService)
+        public TrainRecordController(ITrainRecordService trainRecordService,IMapper mapper)
         {
             this._trainRecordService = trainRecordService;
+            this._mapper = mapper;
         }
 
         /// <summary>
@@ -102,6 +108,36 @@ namespace Hotline.Api.Controllers.Exam
             return await _trainRecordService.AnalysisTrainResult(trainResultReportPagedRequest);
         }
 
+        /// <summary>
+        /// 导出培训结果统计
+        /// </summary>
+        /// <param name="exportExcelDto"></param>
+        /// <returns></returns>
+        [HttpPost(TrainRecordApiRoute.ExportTrainResult)]
+        public async Task<FileStreamResult> ExportTrainResult([FromBody] ExportExcelDto<TrainResultReportPagedRequest> exportExcelDto)
+        {
+            if (exportExcelDto.IsExportAll)
+            {
+                exportExcelDto.QueryDto.IsPaged = false;
+            }
+
+            var result = await _trainRecordService.AnalysisTrainResult(exportExcelDto.QueryDto);
+
+            var items = result.Items;
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<TrainResultViewResponse>(exportExcelDto.ColumnInfos ?? new List<ColumnInfo>());
+
+            var dtos = items
+                .Select(stu => _mapper.Map(stu, typeof(TrainResultViewResponse), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "导出培训结果统计");
+
+        }
+
         /// <summary>
         /// 计算培训结果比例
         /// </summary>

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

@@ -10,16 +10,24 @@ using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using System.ComponentModel;
 using Hotline.Application.Exam.Interface.ExamManages;
+using Exam.Infrastructure.Data.Entity;
+using Hotline.Share.Dtos.Order;
+using Hotline.Tools;
+using MapsterMapper;
 
 namespace Hotline.Api.Controllers.Exam
 {
     public class UserExamController : BaseController
     {
         private readonly IUserExamService _userExamService;
+        private readonly IExamManageService _examManageService;
+        private readonly IMapper _mapper;
 
-        public UserExamController(IUserExamService userExamService)
+        public UserExamController(IUserExamService userExamService,IExamManageService examManageService,IMapper mapper)
         {
             this._userExamService = userExamService;
+            this._examManageService = examManageService;
+            this._mapper = mapper;
         }
 
         /// <summary>
@@ -30,6 +38,8 @@ namespace Hotline.Api.Controllers.Exam
         [HttpPost(UserExamApiRoute.GetPagedList)]
         public async Task<UserExamResultPageViewResponse> GetPagedList([FromBody] UserExamPagedRequest userExamPagedRequest)
         {
+            await _examManageService.UpdateExamStatus(new EntityQueryRequest(), HttpContext.RequestAborted);
+
             return await _userExamService.GetPagedListAsync(userExamPagedRequest) as UserExamResultPageViewResponse;
         }
 
@@ -185,7 +195,38 @@ namespace Hotline.Api.Controllers.Exam
         [HttpPost(UserExamApiRoute.GetUnExamUsers)]
         public async Task<UnExamUserPageViewResponse> GetUnExamUsers([FromBody] UnExamUserReportPagedRequest unExamUserReportPagedRequest)
         {
-            return await _userExamService.GetUnExamUsers(unExamUserReportPagedRequest);
+            return await _userExamService.GetUnExamUsersPaged(unExamUserReportPagedRequest);
+        }
+
+        /// <summary>
+        /// 导出未考试的考生信息
+        /// </summary>
+        /// <param name="exportExcelDto"></param>
+        /// <returns></returns>
+        [HttpPost(UserExamApiRoute.ExportUnExamUsers)]
+        public async Task<FileStreamResult> ExportUnExamUsers([FromBody] ExportExcelDto<UnExamUserReportPagedRequest> exportExcelDto)
+        {
+            if (exportExcelDto.IsExportAll)
+            {
+                exportExcelDto.QueryDto.IsPaged = false;
+            }
+            var result = await _userExamService.GetUnExamUsersPaged(exportExcelDto.QueryDto);
+
+            var items = result.Items;
+
+            var viewResponses = _mapper.Map<ICollection<UnExamUserViewResponse>>(items);
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<UnExamUserViewResponse>(exportExcelDto.ColumnInfos??new List<ColumnInfo>());
+
+            var dtos = viewResponses
+                .Select(stu => _mapper.Map(stu, typeof(UnExamUserViewResponse), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "未考试的考生信息");
+
         }
 
         /// <summary>
@@ -200,6 +241,39 @@ namespace Hotline.Api.Controllers.Exam
             return await _userExamService.GetUserExamResults(userExamResultReportPagedRequest); 
         }
 
+
+        /// <summary>
+        /// 导出成绩统计分析
+        /// </summary>
+        /// <param name="exportExcelDto"></param>
+        /// <returns></returns>
+
+        [HttpPost(UserExamApiRoute.ExportUserExamResults)]
+        public async Task<FileStreamResult> ExportUserExamResults([FromBody] ExportExcelDto<UserExamResultReportPagedRequest> exportExcelDto)
+        {
+            if (exportExcelDto.IsExportAll)
+            {
+                exportExcelDto.QueryDto.IsPaged = false;
+            }
+
+            var result = await _userExamService.GetUserExamResults(exportExcelDto.QueryDto);
+
+            var items = result.Items;
+
+            dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass<UserExamResultViewResponse>(exportExcelDto.ColumnInfos ?? new List<ColumnInfo>());
+
+            var dtos = items
+                .Select(stu => _mapper.Map(stu, typeof(UserExamResultViewResponse), dynamicClass))
+                .Cast<object>()
+                .ToList();
+
+            var stream = ExcelHelper.CreateStream(dtos);
+
+            return ExcelStreamResult(stream, "成绩统计分析");
+        }
+
+
+
         /// <summary>
         /// 查看考试试题
         /// </summary>

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

@@ -20,5 +20,7 @@ namespace Hotline.Application.Exam.Constants.ApiRoutes
         public const string AnalysisTrainResult = "AnalysisTrainResult";
 
         public const string CalcuteAnalysisRate = "CalcuteAnalysisRate";
+
+        public const string ExportTrainResult = "ExportTrainResult";
     }
 }

+ 4 - 0
src/Hotline.Application/Exam/Constants/ApiRoutes/UserExamApiRoute.cs

@@ -42,5 +42,9 @@ namespace Hotline.Application.Exam.Constants.ApiRoutes
         public const string GetGradingPagedList = "GetGradingPagedList";
 
         public const string GetUserList = "GetUserList";
+
+        public const string ExportUnExamUsers = "ExportUnExamUsers";
+
+        public const string ExportUserExamResults = "ExportUserExamResults";
     }
 }

+ 8 - 1
src/Hotline.Application/Exam/Interface/ExamManages/IUserExamService.cs

@@ -92,7 +92,14 @@ namespace Hotline.Application.Exam.Interface.ExamManages
         /// </summary>
         /// <param name="unExamUserReportPagedRequest"></param>
         /// <returns></returns>
-        Task<UnExamUserPageViewResponse> GetUnExamUsers(UnExamUserReportPagedRequest unExamUserReportPagedRequest);
+        Task<UnExamUserPageViewResponse> GetUnExamUsersPaged(UnExamUserReportPagedRequest unExamUserReportPagedRequest);
+
+        /// <summary>
+        /// 获取缺考考生名单(不分页)
+        /// </summary>
+        /// <param name="unExamUserReportPagedRequest"></param>
+        /// <returns></returns>
+        Task<List<UnExamUserViewResponse>> GetUnExamUsers(UnExamUserReportPagedRequest unExamUserReportPagedRequest);
 
         /// <summary>
         /// 获取用户考试成绩

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

@@ -78,7 +78,7 @@ namespace Hotline.Application.Exam.QueryExtensions.ExamManages
             Expression<Func<ExamUserExam, bool>> expression = m => m.Id != null;
 
             expression = ExpressionableUtility.CreateExpression<ExamUserExam>()
-                .And(x=>x.ExamStatus == Share.Enums.Exams.EExamStatus.NoStart)
+                .And(x=>x.ExamStatus == Share.Enums.Exams.EExamStatus.Absent)
             .ToExpression();
 
             return expression;

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

@@ -332,7 +332,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
         {
             List<ExamManage> examManages = await UpdateExamManageStatus(entityQueryRequest, requestAborted);
 
-            //await UdpateUserExam(examManages, requestAborted);
+            await UdpateUserExam(examManages, requestAborted);
 
         }
         #endregion
@@ -604,7 +604,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
             var expression = queryRequest.GetExpression();
             var questionTable = _repository.Queryable().Where(expression);
 
-            var queryable = questionTable.Select(e => new ExamManageViewResponse
+            var queryable = questionTable.OrderBy(e => e.CreationTime).Select(e => new ExamManageViewResponse
             {
                 Id = e.Id,
                 Code = e.Code,
@@ -696,7 +696,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             userExams.ForEach(item =>
             {
-                item.ExamStatus = Share.Enums.Exams.EExamStatus.Complete;
+                item.ExamStatus = item.ExamStatus== Share.Enums.Exams.EExamStatus.NoStart? Share.Enums.Exams.EExamStatus.Absent: item.ExamStatus;
             });
 
             userExams.ToUpdate(_sessionContext);
@@ -708,7 +708,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
         {
             var queryable = _repository.Queryable()
                 .WhereIF(entityQueryRequest != null && entityQueryRequest.Ids != null, x => entityQueryRequest.Ids.Contains(x.Id))
-                .Where(x => x.EndTime < DateTime.Now);
+                .Where(x => x.EndTime < DateTime.Now && x.ExamStatus != Share.Enums.Exams.EExamStatus.Complete);
             var examManages = await queryable.ToListAsync();
 
             examManages.ForEach(item =>

+ 207 - 155
src/Hotline.Application/Exam/Service/ExamManages/UserExamService.cs

@@ -46,6 +46,8 @@ using Hotline.Exams.Questions;
 using Hotline.Exams.Sourcewares;
 using Hotline.Share.Dtos.Questions;
 using DocumentFormat.OpenXml.Office2010.Excel;
+using System.Linq.Expressions;
+using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
 
 namespace Hotline.Application.Exam.Service.ExamManages
 {
@@ -104,12 +106,12 @@ namespace Hotline.Application.Exam.Service.ExamManages
             {
                 var examQuestionDto = _mapper.Map<ExamQuestionDto>(question);
 
-                var questionScore = await new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).GetAsync(x=>x.QuestionType == question.QuestionType && x.ExamManageId == question.ExamId);
+                var questionScore = await new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).GetAsync(x => x.QuestionType == question.QuestionType && x.ExamManageId == question.ExamId);
 
                 if (questionScore != null)
                 {
                     examQuestionDto.Score = questionScore.Score;
-                }               
+                }
 
                 if (examQuestionDto.QuestionType.CheckSelectType())
                 {
@@ -359,7 +361,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 IsJoin = false
             };
 
-            if (userExam.StartTime == null || userExam.ExamStatus == EExamStatus.Complete)
+            if (userExam.ExamStatus == EExamStatus.NoStart || userExam.ExamStatus == EExamStatus.Complete)
                 userExam.StartTime = DateTime.Now;
 
             var startExamViewResponse = await CheckExamValid(userExam, cancellationToken);
@@ -381,7 +383,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             }
             // TODO: 删除之前选项和答案
-            else if(userExam.ExamStatus == EExamStatus.Complete)
+            else if (userExam.ExamStatus == EExamStatus.Complete)
             {
                 await ReExam(userExam, cancellationToken);
             }
@@ -618,6 +620,35 @@ namespace Hotline.Application.Exam.Service.ExamManages
         public async Task<List<GradingExamQuestionDto>> GetGradingExamQuestion(GradingExamRequest gradingExamRequest)
         {
             var expression = gradingExamRequest.GetExpression();
+
+            ISugarQueryable<GradingExamQuestionTempDto> queryable = GetViewExamQuestionTempDtos(expression);
+
+            queryable =
+            queryable.MergeTable().Where((q) => !(q.QuestionType == EQuestionType.Single || q.QuestionType == EQuestionType.Multi || q.QuestionType == EQuestionType.Judge));
+
+            var queryResult = await queryable.ToListAsync();
+
+            var gradingExamQuestionDtos = queryResult.GroupBy(x => new
+            {
+                Id = x.Id,
+                QuestionType = x.QuestionType
+            }).Select(g => new GradingExamQuestionDto
+            {
+                Answer = g.FirstOrDefault().Answer,
+                QuestionType = g.Key.QuestionType,
+                Id = g.Key.Id,
+                QuestionScore = g.FirstOrDefault().QuestionScore,
+                Score = g.FirstOrDefault().Score,
+                Title = g.FirstOrDefault().Title,
+                CorrectAnswer = g.Key.QuestionType.CheckSelectType() ? string.Join(",", g.Where(i => i.IsAnswer).Select(n => n.Label).Distinct()) : g.FirstOrDefault()?.CorrectAnswer
+            }).ToList();
+
+            return gradingExamQuestionDtos;
+        }
+
+        private ISugarQueryable<GradingExamQuestionTempDto> GetViewExamQuestionTempDtos(Expression<Func<ExamUserExam, bool>> expression)
+        {
+
             var userExamTable = _repository.Queryable().Where(expression);
 
             var questionScoreRepository = new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
@@ -630,14 +661,13 @@ namespace Hotline.Application.Exam.Service.ExamManages
             var testPaperItemAnswerTable = new ExamRepository<ExamQuestionAnswerBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
             var questionScoreTable = questionScoreRepository.Queryable();
 
-            var queryable = userExamTable.InnerJoin(userExamItemTable, (e, i) => e.Id == i.UserExamId)
-                .InnerJoin(questionTable, (e, i, q) => i.QuestionId == q.QuestionId)
+            return userExamTable.InnerJoin(userExamItemTable, (e, i) => e.Id == i.UserExamId)
+                .InnerJoin(questionTable, (e, i, q) => i.QuestionId == q.QuestionId && q.ExamId == e.ExamId)
                 .LeftJoin(userExamItemOptionTable, (e, i, q, o) => i.Id == o.UserExamItemId)
                 .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 == q.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 == EQuestionType.Single || q.QuestionType == EQuestionType.Multi || q.QuestionType == EQuestionType.Judge))
             .Select(
             (e, i, q, o, qo, a, ta, s) => new GradingExamQuestionTempDto
             {
@@ -647,6 +677,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 Answer = a.Id != null ? a.Answer : string.Empty,
                 Title = q.Title,
                 QuestionOptionId = o.Id,
+                QuestionId = q.QuestionId,
+                ExamQuestionId = q.Id,
                 UserExamItemId = i.Id,
                 Content = qo.Content,
                 Label = qo.Label,
@@ -656,28 +688,8 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 Score = i.Score
             }
                 );
-
-            var queryResult = await queryable.ToListAsync();
-
-            var gradingExamQuestionDtos = queryResult.GroupBy(x => new
-            {
-                Id = x.Id,
-                QuestionType = x.QuestionType
-            }).Select(g => new GradingExamQuestionDto
-            {
-                Answer = g.FirstOrDefault().Answer,
-                QuestionType = g.Key.QuestionType,
-                Id = g.Key.Id,
-                QuestionScore = g.FirstOrDefault().QuestionScore,
-                Score = g.FirstOrDefault().Score,
-                Title = g.FirstOrDefault().Title,
-                CorrectAnswer = g.Key.QuestionType.CheckSelectType() ? string.Join(",", g.Where(i => i.IsAnswer).Select(n => n.Label).Distinct()) : g.FirstOrDefault()?.CorrectAnswer
-            }).ToList();
-
-            return gradingExamQuestionDtos;
         }
 
-
         public async Task<GradingExamQuestionDto> ViewGradingExamQuestion(ViewGradingExamRequest viewGradingExamRequest)
         {
             var gradingExtamItemDto = _mapper.Map<ViewGradingExamRequest, GradingExamItemDto>(viewGradingExamRequest);
@@ -686,10 +698,37 @@ namespace Hotline.Application.Exam.Service.ExamManages
         }
 
 
-        public async Task<UnExamUserPageViewResponse> GetUnExamUsers(UnExamUserReportPagedRequest unExamUserReportPagedRequest)
+        public async Task<UnExamUserPageViewResponse> GetUnExamUsersPaged(UnExamUserReportPagedRequest unExamUserReportPagedRequest)
         {
-            if(unExamUserReportPagedRequest.EndTime == null)
-            unExamUserReportPagedRequest.ResolveEndTime();
+            ISugarQueryable<UnExamUserViewResponse> queryResult = GEtUnExamUserQueryable(unExamUserReportPagedRequest);
+
+            var total = await queryResult.CountAsync();
+
+            var items = unExamUserReportPagedRequest.IsPaged ?
+                await queryResult.ToPageListAsync(unExamUserReportPagedRequest.PageIndex, unExamUserReportPagedRequest.PageSize)
+                : await queryResult.ToListAsync();
+
+            return new UnExamUserPageViewResponse
+            {
+                Items = items,
+                Pagination = new Pagination(unExamUserReportPagedRequest.PageIndex, unExamUserReportPagedRequest.PageSize, total)
+            };
+
+        }
+
+        public async Task<List<UnExamUserViewResponse>> GetUnExamUsers(UnExamUserReportPagedRequest unExamUserReportPagedRequest)
+        {
+            ISugarQueryable<UnExamUserViewResponse> queryResult = GEtUnExamUserQueryable(unExamUserReportPagedRequest);
+
+            var items = await queryResult.ToListAsync();
+
+            return items;
+        }
+
+        private ISugarQueryable<UnExamUserViewResponse> GEtUnExamUserQueryable(UnExamUserReportPagedRequest unExamUserReportPagedRequest)
+        {
+            if (unExamUserReportPagedRequest.EndTime == null)
+                unExamUserReportPagedRequest.ResolveEndTime();
 
             var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
             var userRepository = new ExamRepository<User>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
@@ -707,23 +746,15 @@ namespace Hotline.Application.Exam.Service.ExamManages
                     ExamName = e.Name,
                     OrgName = u.Organization.Name,
                     UserName = u.Name
-                });
-
-            var total = await queryResult.CountAsync();
-            var items = await queryResult.ToPageListAsync(unExamUserReportPagedRequest.PageIndex, unExamUserReportPagedRequest.PageSize);
-
-            return new UnExamUserPageViewResponse
-            {
-                Items = items,
-                Pagination = new Pagination(unExamUserReportPagedRequest.PageIndex, unExamUserReportPagedRequest.PageSize, total)
-            };
-
+                })
+                .MergeTable()
+                .OrderByPropertyNameIF(!string.IsNullOrEmpty(unExamUserReportPagedRequest.SortField), unExamUserReportPagedRequest.SortField, (OrderByType)(unExamUserReportPagedRequest.SortRule ?? 0));
+            return queryResult;
         }
-
         public async Task<UserExamResultPageViewResponse> GetUserExamResults(UserExamResultReportPagedRequest userExamResultReportPagedRequest)
         {
-            if(userExamResultReportPagedRequest.EndTime == null)
-            userExamResultReportPagedRequest.ResolveEndTime();
+            if (userExamResultReportPagedRequest.EndTime == null)
+                userExamResultReportPagedRequest.ResolveEndTime();
 
             var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
             var userRepository = new ExamRepository<User>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
@@ -736,21 +767,26 @@ namespace Hotline.Application.Exam.Service.ExamManages
 
             var queryResult = userExamTable.InnerJoin(examManageTable, (ue, e) => ue.ExamId == e.Id)
                 .InnerJoin(userTable, (ue, e, u) => ue.UserId == u.Id)
-                .Select((ue, e, u) => new UserExamResultViewResponse
-                {
-                    ExamName = e.Name,
-                    OrgName = u.Organization.Name,
-                    UserName = u.Name,
-                    TotalScore = e.TotalScore,
-                    CutoffScore = e.CutoffScore,
-                    Score = ue.Score ?? 0,
-
-                })
+               .Select((ue, e, u) => new UserExamResultViewResponse
+               {
+                   ExamName = e.Name,
+                   OrgName = u.Organization.Name,
+                   UserName = u.Name,
+                   TotalScore = e.TotalScore,
+                   CutoffScore = e.CutoffScore,
+                   Score = ue.Score ?? 0,
+
+               })
                 .MergeTable()
-                .OrderByDescending(x => x.Score);
-
+               .OrderByPropertyNameIF(!string.IsNullOrEmpty(userExamResultReportPagedRequest.SortField), userExamResultReportPagedRequest.SortField, (OrderByType)(userExamResultReportPagedRequest.SortRule ?? 0))
+                .OrderByDescending(x => x.Score)
+      ;
+            
             var total = await queryResult.CountAsync();
-            var items = await queryResult.ToPageListAsync(userExamResultReportPagedRequest.PageIndex, userExamResultReportPagedRequest.PageSize);
+            var items = userExamResultReportPagedRequest.IsPaged ?
+                await queryResult.ToPageListAsync(userExamResultReportPagedRequest.PageIndex, userExamResultReportPagedRequest.PageSize)
+                : await queryResult.ToListAsync();
+                ;
 
             return new UserExamResultPageViewResponse
             {
@@ -835,6 +871,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
                         QuestionId = u.QuestionId,
                         QuestionType = q.QuestionType,
                         UserExamId = u.UserExamId,
+                        Id = u.Id
                     }).Distinct().ToListAsync();
                 await CalcuteExamItemScore(_userExamItemRepository, userExamItemsInCheck, cancellationToken);
 
@@ -899,31 +936,24 @@ namespace Hotline.Application.Exam.Service.ExamManages
             var userExamIds = addUserExamItemDtos.Select(x => x.UserExamId).ToList();
             var questionTypes = addUserExamItemDtos.Select(x => x.QuestionType).ToList();
 
-            var testPaperItemOptionsRepository = new ExamRepository<ExamQuestionOptionsBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            List<ExamQuestionOptionsBak> examQuestionOptions = await GetQuestionOptionBaks(questionIds, userExamIds, true).ToListAsync();
+
             var userExamItemOptionRepository = new ExamRepository<ExamUserExamItemOptions>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
-            var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
-            var testPaperItemRepository = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
             var examQuestionScoreRepository = new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
-            var testPaperOptionsTable = testPaperItemOptionsRepository.Queryable().Where(x => questionIds.Contains(x.QuestionId) && x.IsAnswer);
-            var testPaperItemTable = testPaperItemRepository.Queryable().Where(x => x.QuestionType == EQuestionType.Single || x.QuestionType == EQuestionType.Multi || x.QuestionType == EQuestionType.Judge);
             var userExamTable = _repository.Queryable().Where(x => userExamIds.Contains(x.Id));
-            var examManageTable = examManageRepository.Queryable();
-            var testPaperOptionIds = await testPaperOptionsTable.InnerJoin(testPaperItemTable, (t, i) => t.ExamQuestionId == i.Id)
-                .InnerJoin(examManageTable, (t, i, e) => i.ExamId == e.Id)
-                .InnerJoin(userExamTable, (t, i, e, u) => e.Id == u.ExamId)
-                .Select((t, i, e, u) => t.Id).ToListAsync();
 
             var userExamItems = await userExamItemRepository.Queryable().Where(x => userExamIds.Contains(x.UserExamId)).ToListAsync();
             var userExamItemIds = userExamItems.Select(x => x.Id).ToList();
             var userExamItemOptions = await userExamItemOptionRepository.Queryable().Where(x => userExamItemIds.Contains(x.UserExamItemId)).ToListAsync();
             var examQuesiontScores = await examQuestionScoreRepository.Queryable().Where(x => questionTypes.Contains(x.QuestionType))
-                .InnerJoin(userExamTable, (e, u) => e.Id == u.ExamId)
+                .InnerJoin(userExamTable, (e, u) => e.ExamManageId == u.ExamId)
                 .Select((e, u) => e).ToListAsync();
 
 
             foreach (var addUserExamItemDto in addUserExamItemDtos)
             {
-                var isCorrect = userExamItemOptions.Select(x => x.QuestionOptionId).OrderBy(x => x).SequenceEqual(testPaperOptionIds.OrderBy(x => x));
+                var examQuestionOptionIds = examQuestionOptions.Where(x => x.QuestionId == addUserExamItemDto.QuestionId).Select(x => x.Id).ToList();
+                var isCorrect = userExamItemOptions.Where(x => x.UserExamItemId == addUserExamItemDto.Id).Select(x => x.QuestionOptionId).OrderBy(x => x).SequenceEqual(examQuestionOptionIds.OrderBy(x => x));
                 var userExamItem = userExamItems.FirstOrDefault(x => x.QuestionId == addUserExamItemDto.QuestionId);
                 if (userExamItem != null)
                 {
@@ -937,6 +967,32 @@ namespace Hotline.Application.Exam.Service.ExamManages
             await userExamItemRepository.UpdateWithValidateAsync(userExamItems, cancellationToken);
         }
 
+        private ISugarQueryable<ExamQuestionOptionsBak> GetQuestionOptionBaks(List<string> questionIds, List<string> userExamIds, bool isFilterAnswer)
+        {
+            var questionRepository = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            var questionTable = questionRepository.Queryable().Where(x => x.QuestionType == EQuestionType.Single || x.QuestionType == EQuestionType.Multi || x.QuestionType == EQuestionType.Judge);
+            var userExamTable = _repository.Queryable().Where(x => userExamIds.Contains(x.Id));
+            var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            var examManageTable = examManageRepository.Queryable();
+            var examQuestionOptionsRepository = new ExamRepository<ExamQuestionOptionsBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
+            var examQuestionOptionsTable = examQuestionOptionsRepository.Queryable()
+                .Where(x => questionIds.Contains(x.QuestionId))
+                .WhereIF(isFilterAnswer, x => x.IsAnswer);
+            var examQuestionOptions = examQuestionOptionsTable.InnerJoin(questionTable, (t, i) => t.ExamQuestionId == i.Id)
+                .InnerJoin(examManageTable, (t, i, e) => i.ExamId == e.Id)
+                .InnerJoin(userExamTable, (t, i, e, u) => e.Id == u.ExamId)
+                .Select((t, i, e, u) => new ExamQuestionOptionsBak
+                {
+                    Id = t.Id,
+                    Content = t.Content,
+                    IsAnswer = t.IsAnswer,
+                    Label = t.Label,
+                    ExamQuestionId = t.ExamQuestionId,
+                    QuestionId = t.QuestionId
+                });
+            return examQuestionOptions;
+        }
+
         private async Task CalcuteTotalScore(IUserExamItemRepository userExamItemRepository, string userExamId, CancellationToken cancellationToken)
         {
             var userExam = await _repository.GetAsync(x => x.Id == userExamId);
@@ -1308,7 +1364,7 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 Score = u.Score ?? 0,
                 Status = u.Status,
                 SortIndex = u.SortIndex,
-                ExamStatus = u.ExamStatus,
+                ExamStatus = u.ExamStatus == EExamStatus.Absent? EExamStatus.Complete: u.ExamStatus,
                 IsSuccess = u.IsCheck ? u.IsSuccess : null,
                 EndTime = e.EndTime,
                 StartTime = e.StartTime,
@@ -1317,41 +1373,28 @@ namespace Hotline.Application.Exam.Service.ExamManages
                 ExamId = e.Id,
                 IsCheck = u.IsCheck,
                 IsReExam = u.IsReExam,
-                CanReExam = SqlFunc.Subqueryable<ExamUserExamItem>().Where(x=>x.UserExamId == u.Id).Count()< e.Count
+                CanReExam = SqlFunc.Subqueryable<ExamUserExamItem>().Where(x => x.UserExamId == u.Id).Count() < e.Count
             });
             return queryable;
         }
 
         public async Task<List<ViewExamQuestionDto>> View(string id)
         {
-           
-            List<ViewExamQuestionDto> viewExamQuestionDtos = await GetViewExamQuestion(id,null);
 
-            var questionIds = viewExamQuestionDtos.Select(x => x.QuestionId).ToList();
-
-            List<ViewQuestionAnswerDto> questionAnswers = await GetQuestionAnswers(id, questionIds);
-            List<ViewQuestionOptionDto> questionOptions = await GetQuestionOptions( questionIds);
-            List<QuestionKnowladgeDto> questionKnowladges = await GetQuestionKnowladges( questionIds);
-            List<QuestionSourcewareDto> sourcewares = await GetSourcewares(questionIds);
+            List<ViewExamQuestionDto> viewExamQuestionDtos = await GetViewExamQuestion(id, null);
 
-            viewExamQuestionDtos.ForEach(item =>
+            var examQuestionIds = viewExamQuestionDtos.Select(x => x.ExamQuestionId).ToList();
+            var questionIds = viewExamQuestionDtos.Select(x => x.QuestionId).ToList();
+            var userExamIds = new List<string>
             {
-                item.QuestionKnowladgeDtos = questionKnowladges.Where(x => x.QuestionId == item.QuestionId).ToList();
-                item.QuestionSourcewareDtos = sourcewares.Where(x => x.QuestionId == item.QuestionId).ToList();
-                if (!item.QuestionType.CheckSelectType())
-                {
-                    var questionAnswer = questionAnswers.FirstOrDefault(x => x.QuestionId == item.QuestionId);
-                    item.Answer = questionAnswer?.Answer ?? string.Empty;
-                    item.CorrectAnswer = questionAnswer?.CorrectAnswer ?? string.Empty;
-                }
-                else
-                {
-                    item.QuestionOptions = questionOptions.Where(x => x.QuestionId == item.QuestionId).ToList();
-                    item.CorrectAnswer = string.Join(",", item.QuestionOptions.Where(x => x.IsAnswer).Select(x => x.Label));
-                }
-                
-            });
+                id
+            };
+            //List<ViewQuestionAnswerDto> questionAnswers = await GetQuestionAnswers(id, questionIds);
+            List<ViewQuestionOptionDto> questionOptions = await GetQuestionOptions(questionIds, userExamIds);
+            List<QuestionKnowladgeDto> questionKnowladges = await GetQuestionKnowladges(examQuestionIds);
+            List<QuestionSourcewareDto> sourcewares = await GetSourcewares(examQuestionIds);
 
+            ResolveExamQuestions(viewExamQuestionDtos, questionOptions, questionKnowladges, sourcewares);
 
             return viewExamQuestionDtos;
 
@@ -1363,41 +1406,44 @@ namespace Hotline.Application.Exam.Service.ExamManages
         {
             List<ViewExamQuestionDto> viewExamQuestionDtos = await GetViewExamQuestion(id, questionId);
 
+            var examQuestionIds = viewExamQuestionDtos.Select(x => x.ExamQuestionId).ToList();
             var questionIds = viewExamQuestionDtos.Select(x => x.QuestionId).ToList();
+            var userExamIds = new List<string>
+            {
+                id
+            };
+            //List<ViewQuestionAnswerDto> questionAnswers = await GetQuestionAnswers(id, questionIds);
+            List<ViewQuestionOptionDto> questionOptions = await GetQuestionOptions(questionIds, userExamIds);
+            List<QuestionKnowladgeDto> questionKnowladges = await GetQuestionKnowladges(examQuestionIds);
+            List<QuestionSourcewareDto> sourcewares = await GetSourcewares(examQuestionIds);
+
+            ResolveExamQuestions(viewExamQuestionDtos, questionOptions, questionKnowladges, sourcewares);
 
-            List<ViewQuestionAnswerDto> questionAnswers = await GetQuestionAnswers(id, questionIds);
-            List<ViewQuestionOptionDto> questionOptions = await GetQuestionOptions(questionIds);
-            List<QuestionKnowladgeDto> questionKnowladges = await GetQuestionKnowladges(questionIds);
-            List<QuestionSourcewareDto> sourcewares = await GetSourcewares(questionIds);
+            return viewExamQuestionDtos.FirstOrDefault();
+        }
 
+        private static void ResolveExamQuestions(List<ViewExamQuestionDto> viewExamQuestionDtos, List<ViewQuestionOptionDto> questionOptions, List<QuestionKnowladgeDto> questionKnowladges, List<QuestionSourcewareDto> sourcewares)
+        {
             viewExamQuestionDtos.ForEach(item =>
             {
-                item.QuestionKnowladgeDtos = questionKnowladges.Where(x => x.QuestionId == item.QuestionId).ToList();
-                item.QuestionSourcewareDtos = sourcewares.Where(x => x.QuestionId == item.QuestionId).ToList();
-                if (!item.QuestionType.CheckSelectType())
+                item.QuestionKnowladgeDtos = questionKnowladges.Where(x => x.QuestionId == item.ExamQuestionId).ToList();
+                item.QuestionSourcewareDtos = sourcewares.Where(x => x.QuestionId == item.ExamQuestionId).ToList();
+                if (item.QuestionType.CheckSelectType())
                 {
-                    var questionAnswer = questionAnswers.FirstOrDefault(x => x.QuestionId == item.QuestionId);
-                    item.Answer = questionAnswer?.Answer ?? string.Empty;
-                    item.CorrectAnswer = questionAnswer?.CorrectAnswer ?? string.Empty;
-                }
-                else
-                {
-                    item.QuestionOptions = questionOptions.Where(x => x.QuestionId == item.QuestionId).ToList();
-                    item.CorrectAnswer = string.Join(",", item.QuestionOptions.Where(x => x.IsAnswer).Select(x => x.Label));
+                    item.QuestionOptions = questionOptions.Where(x => x.QuestionId == item.ExamQuestionId).ToList();
+
+                    item.CorrectAnswer = string.Join(",", item.QuestionOptions.Where(m => m.IsAnswer).Select(m => m.Label).ToArray());
                 }
 
             });
-
-
-            return viewExamQuestionDtos.FirstOrDefault();
         }
 
-        private  async Task<List<QuestionSourcewareDto>> GetSourcewares(List<string> questionIds)
+        private async Task<List<QuestionSourcewareDto>> GetSourcewares(List<string> questionIds)
         {
             var questionSourcewareTable = new ExamRepository<ExamQuestionSourcewareBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
             var sourcewareTable = new ExamRepository<ExamSourceware>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
 
-            var querable = questionSourcewareTable.InnerJoin<ExamQuestionSourceware>((qsb,qs)=>qsb.SourcewareId == qs.Id).InnerJoin(sourcewareTable, (qsb,qs, s) => qs.SourcewareId == s.Id).Select((qsb, qs, s) => new QuestionSourcewareDto
+            var querable = questionSourcewareTable.InnerJoin<ExamQuestionSourceware>((qsb, qs) => qsb.SourcewareId == qs.Id).InnerJoin(sourcewareTable, (qsb, qs, s) => qs.SourcewareId == s.Id).Select((qsb, qs, s) => new QuestionSourcewareDto
             {
                 Id = qs.Id,
                 Name = s.Name,
@@ -1409,27 +1455,28 @@ namespace Hotline.Application.Exam.Service.ExamManages
             return await querable.ToListAsync();
         }
 
-        private  async Task<List<QuestionKnowladgeDto>> GetQuestionKnowladges(List<string> questionIds)
+        private async Task<List<QuestionKnowladgeDto>> GetQuestionKnowladges(List<string> questionIds)
         {
             var questionKnowladgeTable = new ExamRepository<ExamQuestionKnowladgeBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
-            
+
 
             return await questionKnowladgeTable.Where(x => questionIds.Contains(x.ExamQuestionId))
-                .InnerJoin<ExamQuestionKnowladge>((kb,k)=>kb.KnowladgeId == k.Id).Select((kb, k) => new QuestionKnowladgeDto
-            {
-                Id = kb.Id,
-                QuestionId = kb.ExamQuestionId,
-                KnowladgeId = k.KnowladgeId,
-                Title = kb.Title
-            }).ToListAsync();
+                .InnerJoin<ExamQuestionKnowladge>((kb, k) => kb.KnowladgeId == k.Id).Select((kb, k) => new QuestionKnowladgeDto
+                {
+                    Id = kb.Id,
+                    QuestionId = kb.ExamQuestionId,
+                    KnowladgeId = k.KnowladgeId,
+                    Title = kb.Title
+                }).ToListAsync();
         }
 
-        private  async Task<List<ViewQuestionOptionDto>> GetQuestionOptions(List<string> questionIds)
+        private async Task<List<ViewQuestionOptionDto>> GetQuestionOptions(List<string> questionIds, List<string> userExamIds)
         {
+            var selectQuestionOptions = GetQuestionOptionBaks(questionIds, userExamIds, false).MergeTable();
+
             var userExamItemOptionTable = _userExamItemOptionRepository.Queryable();
-            var questionOptionTable = new ExamRepository<ExamQuestionOptionsBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
 
-            var querable = questionOptionTable.Where(x => questionIds.Contains(x.ExamQuestionId))
+            var querable = selectQuestionOptions
                 .LeftJoin(userExamItemOptionTable, (op, uio) => op.Id == uio.QuestionOptionId)
                 .Select((op, uio) => new ViewQuestionOptionDto
                 {
@@ -1439,13 +1486,13 @@ namespace Hotline.Application.Exam.Service.ExamManages
                     Label = op.Label,
                     QuestionId = op.ExamQuestionId,
                     IsSelected = uio.Id != null
-                }).MergeTable().OrderBy(x=>x.Label);
+                }).MergeTable().OrderBy(x => x.Label);
 
             return await querable.Distinct()
                 .ToListAsync();
         }
 
-        private  async Task<List<ViewQuestionAnswerDto>> GetQuestionAnswers(string id, List<string> questionIds)
+        private async Task<List<ViewQuestionAnswerDto>> GetQuestionAnswers(string id, List<string> questionIds)
         {
             var userExamTable = _repository.Queryable().Where(x => x.Id == id);
             var userExamItemTable = _userExamItemRepository.Queryable();
@@ -1454,11 +1501,11 @@ namespace Hotline.Application.Exam.Service.ExamManages
             var questionAnswerTable = new ExamRepository<ExamQuestionAnswerBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
 
             var querable = examAnswerTable
-                .InnerJoin(userExamItemTable, (a, ui) => ui.Id == a.UserExamItemId &&  ui.UserExamId == id)
-                .LeftJoin(questionAnswerTable, (a, ui, qab) => qab.QuestionId == ui.QuestionId  )
-                .LeftJoin<ExamQuestionAnswer>((a, ui, qab ,qa) => qab.QuestionAnswerId == qa.Id )
-                .LeftJoin(questionTable, (a, ui, qab, qa,q)=>qab.QuestionId == q.QuestionId && questionIds.Contains(q.Id))
-                .Select((a, ui, qab, qa,q) => new ViewQuestionAnswerDto
+                .InnerJoin(userExamItemTable, (a, ui) => ui.Id == a.UserExamItemId && ui.UserExamId == id)
+                .LeftJoin(questionAnswerTable, (a, ui, qab) => qab.QuestionId == ui.QuestionId)
+                .LeftJoin<ExamQuestionAnswer>((a, ui, qab, qa) => qab.QuestionAnswerId == qa.Id)
+                .LeftJoin(questionTable, (a, ui, qab, qa, q) => qab.QuestionId == q.QuestionId && questionIds.Contains(q.Id))
+                .Select((a, ui, qab, qa, q) => new ViewQuestionAnswerDto
                 {
                     Answer = a.Answer,
                     CorrectAnswer = qa.Answer != null ? qa.Answer : string.Empty,
@@ -1468,30 +1515,35 @@ namespace Hotline.Application.Exam.Service.ExamManages
             return await querable.ToListAsync();
         }
 
-        private  async Task<List<ViewExamQuestionDto>> GetViewExamQuestion(string id,string questionId)
+        private async Task<List<ViewExamQuestionDto>> GetViewExamQuestion(string id, string questionId)
         {
-            var userExamTable = _repository.Queryable().Where(x => x.Id == id);
-            var userExamItemTable = _userExamItemRepository.Queryable();
-            var examManageTable = _examManageRepository.Queryable();
-            var questionTable = new ExamRepository<ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().WhereIF(!string.IsNullOrEmpty(questionId), x => x.QuestionId == questionId);
-            var questionScoreTable = new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
+            var expression = ExpressionableUtility.CreateExpression<ExamUserExam>()
+                .And(x => x.Id == id).ToExpression();
 
+            ISugarQueryable<GradingExamQuestionTempDto> queryable = GetViewExamQuestionTempDtos(expression);
 
-            var querable = userExamItemTable.InnerJoin(userExamTable, (ui, u) => ui.UserExamId == u.Id)
-                            .InnerJoin(questionTable, (ui, u, q) => ui.QuestionId == q.QuestionId && u.ExamId == q.ExamId)
-                            .InnerJoin(examManageTable, (ui, u, q, e) => u.ExamId == e.Id)
-                            .InnerJoin(questionScoreTable, (ui, u, q, e, s) => q.QuestionType == s.QuestionType && s.ExamManageId == e.Id)
-                            .Select((ui, u, q, e, s) => new ViewExamQuestionDto
-                            {
-                                Id = ui.Id,
-                                Score = s.Score,
-                                RealScore = ui.Score,
-                                Title = q.Title,
-                                QuestionType = q.QuestionType,
-                                QuestionId = q.Id,
-                            }).MergeTable().OrderBy(x=>x.QuestionType).OrderBy(x=>x.Id);
-
-            return await querable.Distinct().ToListAsync();
+            queryable = queryable.MergeTable().WhereIF(!string.IsNullOrEmpty(questionId), x => x.QuestionId == questionId);
+
+            var queryResult = await queryable.ToListAsync();
+
+            var viewExamQuestion = queryResult.GroupBy(x => new
+            {
+                Id = x.Id,
+                QuestionType = x.QuestionType
+            }).Select(g => new ViewExamQuestionDto
+            {
+                Answer = g.FirstOrDefault().Answer,
+                QuestionType = g.Key.QuestionType,
+                QuestionId = g.FirstOrDefault().QuestionId,
+                ExamQuestionId = g.FirstOrDefault().ExamQuestionId,
+                Id = g.Key.Id,
+                Score = g.FirstOrDefault().QuestionScore,
+                RealScore = g.FirstOrDefault().Score,
+                Title = g.FirstOrDefault().Title,
+                CorrectAnswer = g.Key.QuestionType.CheckSelectType() ? string.Empty : g.FirstOrDefault()?.CorrectAnswer
+            }).ToList();
+
+            return viewExamQuestion;
         }
         #endregion
 

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

@@ -670,11 +670,13 @@ namespace Hotline.Application.Exam.Service.Practices
             var tagQuestionTable = tagQuestionRepository.Queryable().Where(expression);
             var questionTable = quesitonRepository.Queryable().Where(questionExpression);
 
-            var taqQuestions = await tagQuestionTable.LeftJoin(questionTable, (t, q) => t.QuestionId == q.Id)
+            var queryable = tagQuestionTable.InnerJoin(questionTable, (t, q) => t.QuestionId == q.Id)
                 .Select((t, q) => new TagQuestionCountViewResponse
                 {
                     TotalCount = SqlFunc.AggregateCount(t.Id)
-                })
+                });
+
+            var taqQuestions = await queryable
                 .ToListAsync();
 
             return taqQuestions.Count() > 0 ? taqQuestions.FirstOrDefault() : new TagQuestionCountViewResponse

+ 8 - 2
src/Hotline.Application/Exam/Service/Trains/TrainRecordService.cs

@@ -32,6 +32,7 @@ using JiebaNet.Segmenter.Common;
 using Hotline.Repository.SqlSugar.Exam.Service;
 using Hotline.Repository.SqlSugar.Exam.Extensions;
 using DocumentFormat.OpenXml.Office2010.Excel;
+using SqlSugar;
 
 namespace Hotline.Application.Exam.Service.Trains
 {
@@ -236,11 +237,16 @@ namespace Hotline.Application.Exam.Service.Trains
                     IsComplete = r.IsComplete,
                     SortIndex = r.SortIndex,
                     Status = r.Status
-                });
+                })
+                .MergeTable()
+               .OrderByPropertyNameIF(!string.IsNullOrEmpty(trainResultReportPagedRequest.SortField), trainResultReportPagedRequest.SortField, (OrderByType)(trainResultReportPagedRequest.SortRule ?? 0));
 
             var total = await queryResult.CountAsync();
 
-            var items = await queryResult.ToPageListAsync(trainResultReportPagedRequest.PageIndex, trainResultReportPagedRequest.PageSize);
+            var items = trainResultReportPagedRequest.IsPaged ?
+                await queryResult.ToPageListAsync(trainResultReportPagedRequest.PageIndex, trainResultReportPagedRequest.PageSize)
+                : await queryResult.ToListAsync();
+                ;
 
             return new TrainResultPagedViewResponse
             {

+ 13 - 0
src/Hotline.Application/Mappers/ExamMapperConfigs.cs

@@ -0,0 +1,13 @@
+using Mapster;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Hotline.Application.Mappers
+{
+    public partial class MapperConfigs : IRegister
+    {
+    }
+}

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

@@ -61,6 +61,12 @@ namespace Hotline.Share.Dtos.ExamManages
         [Description("试题Id")]
         public string QuestionId { get; set; }
 
+        /// <summary>
+        /// 考试试题Id
+        /// </summary>
+        [Description("考试试题Id")]
+        public string ExamQuestionId { get; set; }
+
         /// <summary>
         /// 试题关联知识
         /// </summary>

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

@@ -109,6 +109,18 @@ namespace Exam.Application.Interface.Exam
         /// </summary>
         [Description("实际分数")]
         public int? Score { get; set; }
+
+        /// <summary>
+        /// 试题Id
+        /// </summary>
+        [Description("试题Id")]
+        public string QuestionId { get; set; }
+
+        /// <summary>
+        /// 考试试题Id
+        /// </summary>
+        [Description("考试试题Id")]
+        public string ExamQuestionId { get; set; }
     }
 
     public class UserExamQuestionDto : IActionRequest

+ 6 - 1
src/Hotline.Share/Enums/Exams/EExamStatus.cs

@@ -18,6 +18,11 @@ namespace Hotline.Share.Enums.Exams
         /// 开始结束
         /// </summary>
         [Description("考试结束")]
-        Complete=2
+        Complete=2,
+        /// <summary>
+        /// 缺考
+        /// </summary>
+        [Description("缺考")]
+        Absent = 3
     }
 }

+ 2 - 0
src/Hotline.Share/Requests/Exam/AnalysisReportRequest.cs

@@ -6,5 +6,7 @@ namespace Hotline.Share.Requests.Exam
     public record AnalysisReportRequest : ReportPagedRequest,IQueryRequest
     {
         public EAnlysisType AnlysisType { get; set; }
+
+        public bool IsPaged { get; set; } = true;
     }
 }