UserExamService.cs 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278
  1. using Exam.Application.Interface.Exam;
  2. using Exam.Infrastructure.Data.Entity;
  3. using Exam.Infrastructure.Enums;
  4. using Exam.Infrastructure.Extensions;
  5. using Exam.Share;
  6. using Exam.Share.Dtos.ExamManage;
  7. using Exam.Share.ViewResponses.Exam;
  8. using Hotline.Application.Exam.Core.Extensions;
  9. using Hotline.Application.Exam.Extensions;
  10. using Hotline.Application.Exam.Interface.Strategy;
  11. using Hotline.Application.Exam.QueryExtensions.ExamManages;
  12. using Hotline.Application.Exam.Strategy;
  13. using Hotline.Exams.ExamManages;
  14. using Hotline.Repository.SqlSugar;
  15. using Hotline.Repository.SqlSugar.DataPermissions;
  16. using Hotline.Repository.SqlSugar.Exam.Interfaces.ExamManages;
  17. using Hotline.Share.Dtos.ExamManages;
  18. using Hotline.Share.Exams.Extensions;
  19. using Hotline.Share.Requests.Exam;
  20. using Hotline.Share.ViewResponses;
  21. using Hotline.Share.ViewResponses.Exam;
  22. using Hotline.Users;
  23. using JiebaNet.Segmenter.Common;
  24. using MapsterMapper;
  25. using Hotline.Application.Exam.Core.Utilities;
  26. using Hotline.Application.Exam.Interface.ExamManages;
  27. using Hotline.Exams.Validate;
  28. using Hotline.Repository.SqlSugar.Exam.Repositories;
  29. using XF.Domain.Authentications;
  30. using XF.Domain.Dependency;
  31. using XF.Domain.Exceptions;
  32. using XF.Domain.Repository;
  33. using ExamQuestion = Hotline.Exams.Questions.ExamQuestion;
  34. using Hotline.Repository.SqlSugar.Exam.Service;
  35. using Hotline.Repository.SqlSugar.Exam.Extensions;
  36. using Exam.Infrastructure.Data.Interface;
  37. using Hotline.Repository.SqlSugar.Exam.Interface;
  38. using DocumentFormat.OpenXml.Drawing.Charts;
  39. using SqlSugar;
  40. using System.Threading;
  41. using DocumentFormat.OpenXml.Office2013.Excel;
  42. using Hotline.Share.Enums.Exams;
  43. using DocumentFormat.OpenXml.Wordprocessing;
  44. using Hotline.Repository.SqlSugar.Exam.Repositories.ExamManages;
  45. namespace Hotline.Application.Exam.Service.ExamManages
  46. {
  47. public class UserExamService : ApiService<ExamUserExam, AddUserExamDto, UpdateUserExamDto, HotlineDbContext>, IUserExamService, IScopeDependency
  48. {
  49. private readonly IUserExamRepository _repository;
  50. private readonly IUserExamItemRepository _userExamItemRepository;
  51. private readonly IUserExamItemOptionRepository _userExamItemOptionRepository;
  52. private readonly IExamAnswerRepository _examAnswerRepository;
  53. private readonly IExamManageRepository _examManageRepository;
  54. private readonly IDataPermissionFilterBuilder _dataPermissionFilterBuilder;
  55. private readonly IServiceProvider _serviceProvider;
  56. private readonly IMapper _mapper;
  57. private readonly ISessionContext _sessionContext
  58. ;
  59. public UserExamService(IUserExamRepository repository,
  60. IUserExamItemRepository userExamItemRepository,
  61. IUserExamItemOptionRepository userExamItemOptionRepository,
  62. IExamAnswerRepository examAnswerRepository,
  63. IExamManageRepository examManageRepository,
  64. IDataPermissionFilterBuilder dataPermissionFilterBuilder, IServiceProvider serviceProvider,
  65. IMapper mapper, ISessionContext sessionContext) : base(repository, mapper, sessionContext)
  66. {
  67. this._repository = repository;
  68. this._userExamItemRepository = userExamItemRepository;
  69. this._userExamItemOptionRepository = userExamItemOptionRepository;
  70. this._examAnswerRepository = examAnswerRepository;
  71. this._examManageRepository = examManageRepository;
  72. this._dataPermissionFilterBuilder = dataPermissionFilterBuilder;
  73. this._serviceProvider = serviceProvider;
  74. this._mapper = mapper;
  75. this._sessionContext = sessionContext;
  76. }
  77. #region public method
  78. public Task<UserExamDto> GetAsync(EntityQueryRequest entityQueryRequest)
  79. {
  80. throw new NotImplementedException();
  81. }
  82. public Task<(int, List<UserExamResultViewResponse>)> GetListAsync(UserExamPagedRequest queryRequest)
  83. {
  84. throw new NotImplementedException();
  85. }
  86. public async Task<ExamQuestionDto> GetExamQuestionDto(ExamQuestionRequest examQuestionRequest)
  87. {
  88. var expression = examQuestionRequest.GetExpression();
  89. var quesetion = await new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(expression).FirstAsync();
  90. if (quesetion != null)
  91. {
  92. var examQuestionDto = _mapper.Map<ExamQuestionDto>(quesetion);
  93. if (examQuestionDto.QuestionType.CheckSelectType())
  94. {
  95. var questionOptions = await new ExamRepository<ExamQuestionOptionsBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.ExamQuestionId == quesetion.Id).ToListAsync();
  96. List<ExamUserExamItemOptions> userItemItemOptions = await GetUserExteamItemOptios(quesetion);
  97. if (questionOptions != null)
  98. {
  99. examQuestionDto.QuestionOptions = new List<ExamQuestionOptionsDto>();
  100. questionOptions.ForEach(item =>
  101. {
  102. var examQuestionOptionsDto = _mapper.Map<ExamQuestionOptionsDto>(item);
  103. if (userItemItemOptions != null)
  104. {
  105. examQuestionOptionsDto.IsSelected = userItemItemOptions.Any(m => m.QuestionOptionId == item.Id);
  106. }
  107. examQuestionDto.QuestionOptions.Add(examQuestionOptionsDto);
  108. });
  109. }
  110. }
  111. else
  112. {
  113. List<ExamAnswer> examAnswers = await GetExamAnswers(examQuestionRequest);
  114. examQuestionDto.Answer = examAnswers != null ? examAnswers.FirstOrDefault()?.Answer : null;
  115. }
  116. return examQuestionDto;
  117. }
  118. else
  119. {
  120. throw new UserFriendlyException(ExamErrorMessage.ServiceError, string.Format(ExamErrorMessage.IsNotExists, string.Concat(typeof(ExamQuestion).GetDescription(), ":", examQuestionRequest.QuestionId)));
  121. }
  122. }
  123. private async Task<List<ExamAnswer>> GetExamAnswers(ExamQuestionRequest examQuestionRequest)
  124. {
  125. var examAnswerRepository = new ExamRepository<ExamAnswer>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  126. var userExamItemRepository = new ExamRepository<ExamUserExamItem>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  127. var userExamItemTable = userExamItemRepository.Queryable().Where(i => i.QuestionId == examQuestionRequest.QuestionId);
  128. var userExamTable = _repository.Queryable().Where(u => u.UserId == _sessionContext.UserId && u.ExamId == examQuestionRequest.ExamId);
  129. var examAnswerTable = examAnswerRepository.Queryable();
  130. var examAnswers = await examAnswerTable.InnerJoin(userExamItemTable, (e, i) => e.UserExamItemId == i.Id)
  131. .InnerJoin(userExamTable, (e, i, u) => i.UserExamId == u.Id)
  132. .Select((e, i, u) => e).ToListAsync();
  133. return examAnswers;
  134. }
  135. private async Task<List<ExamUserExamItemOptions>> GetUserExteamItemOptios(Exams.ExamManages.ExamQuestionBak quesetion)
  136. {
  137. var userExamItemOptionsRepository = new ExamRepository<ExamUserExamItemOptions>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  138. var userExamItemOptionsTable = userExamItemOptionsRepository.Queryable();
  139. var userExamItemTable = _userExamItemRepository.Queryable();
  140. var userExamTable = _repository.Queryable();
  141. var userItemItemOptions = await userExamItemOptionsTable
  142. .InnerJoin(userExamItemTable, (o, u) => o.UserExamItemId == u.Id)
  143. .InnerJoin(userExamTable, (o, u, e) => u.UserExamId == e.Id)
  144. .Where((o, u, e) => u.QuestionId == quesetion.QuestionId && e.UserId == _sessionContext.UserId).
  145. Select((o, u, e) => o).ToListAsync();
  146. return userItemItemOptions;
  147. }
  148. public async Task<List<ExamQuestionViewResponse>> GetExamQuestionViewResponses(ExamQuestionGroupRequest examQuestionGroupRequest)
  149. {
  150. if (examQuestionGroupRequest.ExamId.IsNull() && examQuestionGroupRequest.UserId.IsNull())
  151. throw UserFriendlyException.SameMessage("查询参数不能为空");
  152. var expression = examQuestionGroupRequest.GetExpression();
  153. var examManageTable = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(expression);
  154. var testPaperItemTable = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
  155. var queryable = await examManageTable.InnerJoin(testPaperItemTable, (e, i) => e.Id == i.ExamId)
  156. .Select((e, i) => i).ToListAsync();
  157. var result = queryable.GroupBy(x => x.QuestionType).Select(m => new ExamQuestionViewResponse
  158. {
  159. QuestionType = m.Key,
  160. Questions = m.GroupBy(g => g.QuestionId).Select(n => new SimpleViewResponse
  161. {
  162. Id = n.Key
  163. }).ToList()
  164. }).ToList();
  165. return result;
  166. }
  167. public async Task<List<GradingQuestionViewResponce>> GetGradingQuestionViewResponces(ExamQuestionGroupRequest examQuestionGroupRequest)
  168. {
  169. var expression = examQuestionGroupRequest.GetExpression();
  170. var examManageTable = _examManageRepository.Queryable().Where(expression);
  171. var testPaperItemTable = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
  172. var queryable = await examManageTable.InnerJoin(testPaperItemTable, (e, i) => e.Id == i.ExamId)
  173. .Select((e, i) => i).ToListAsync();
  174. var examQuestionScores = await new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.ExamManageId == examQuestionGroupRequest.ExamId).ToListAsync();
  175. var userExamItemTable = _userExamItemRepository.Queryable();
  176. var userExamTable = _repository.Queryable().Where(x => x.ExamId == examQuestionGroupRequest.ExamId && x.UserId == examQuestionGroupRequest.UserId);
  177. var userExamItems = await userExamItemTable.InnerJoin(userExamTable, (i, u) => i.UserExamId == u.Id)
  178. .Select((i, u) => i).ToListAsync();
  179. var result = queryable.GroupBy(x => x.QuestionType).Select(m => new GradingQuestionViewResponce
  180. {
  181. QuestionType = m.Key,
  182. Questions = m.Select(n => new GradingExamViewResponse
  183. {
  184. IsCorrect = CheckCorrect(n, examQuestionScores, userExamItems),
  185. Id = userExamItems.FirstOrDefault(x => x.QuestionId == n.QuestionId)?.Id ?? n.Id
  186. }).ToList()
  187. }).ToList();
  188. return result;
  189. }
  190. private bool CheckCorrect(Exams.ExamManages.ExamQuestionBak n, List<ExamQuestionScoreBak> examQuestionScores, List<ExamUserExamItem> userExamItems)
  191. {
  192. var examQuestionScore = examQuestionScores.FirstOrDefault(x => x.QuestionType == n.QuestionType);
  193. var userItem = userExamItems.FirstOrDefault(x => x.QuestionId == n.QuestionId);
  194. if (userItem != null && examQuestionScore != null)
  195. {
  196. return userItem.Score == examQuestionScore.Score;
  197. }
  198. return false;
  199. }
  200. public async Task<PageViewResponse<UserExamResultViewResponse>> GetPagedListAsync(UserExamPagedRequest queryRequest)
  201. {
  202. SqlSugar.ISugarQueryable<UserExamResultViewResponse> queryable = GetQueryable(queryRequest);
  203. var list = await queryable.ToPageListAsync(queryRequest.PageIndex, queryRequest.PageSize);
  204. var total = await queryable.CountAsync();
  205. var result = new UserExamResultPageViewResponse
  206. {
  207. Items = list,
  208. Pagination = new Pagination(queryRequest.PageIndex, queryRequest.PageSize, total)
  209. };
  210. return result;
  211. }
  212. public async Task<GradingExamQuestionDto> GradingAsync(GradingExamItemDto gradingExtamItemDto, CancellationToken cancellationToken)
  213. {
  214. var userExamItem = await _userExamItemRepository.GetAsync(m => m.Id == gradingExtamItemDto.UserExamItemId);
  215. if (userExamItem != null)
  216. {
  217. userExamItem = _mapper.Map<GradingExamItemDto, ExamUserExamItem>(gradingExtamItemDto, userExamItem);
  218. await _userExamItemRepository.UpdateWithValidateAsync(userExamItem, cancellationToken);
  219. }
  220. return await GetNextExamQuestion(gradingExtamItemDto);
  221. }
  222. public async Task SubmitAsync(SubmitExamDto submitExamDto, CancellationToken cancellationToken)
  223. {
  224. var userExam = await _repository.GetAsync(x => x.Id == submitExamDto.Id);
  225. if (userExam != null)
  226. {
  227. userExam = _mapper.Map<SubmitExamDto, ExamUserExam>(submitExamDto, userExam);
  228. userExam.ExamStatus = EExamStatus.Complete;
  229. await _repository.UpdateWithValidateAsync(userExam, cancellationToken);
  230. await CompleteExamManage(userExam.ExamId, cancellationToken);
  231. }
  232. }
  233. private async Task CompleteExamManage(string examId, CancellationToken cancellationToken)
  234. {
  235. var userExams = await _repository.Queryable().Where(x => x.ExamId == examId).ToListAsync();
  236. if (userExams.All(x => x.IsSubmit))
  237. {
  238. var examManage = await _examManageRepository.GetAsync(x => x.Id == examId);
  239. examManage.ExamStatus = EExamStatus.Complete;
  240. await _examManageRepository.UpdateWithValidateAsync(examManage, cancellationToken);
  241. }
  242. }
  243. public async Task<StartExamViewResponse> ExamAsync(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
  244. {
  245. var userExam = await new ExamRepository<ExamUserExam>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.Id == updateUserExamItemDto.UserExamId).FirstAsync();
  246. var startExamViewResponse = await CheckExamValid(userExam, cancellationToken);
  247. if (!startExamViewResponse.CheckValidate())
  248. {
  249. await SetExamStatus(userExam, startExamViewResponse, cancellationToken);
  250. return startExamViewResponse;
  251. }
  252. var hasUserExamItem = _userExamItemRepository.Queryable().Where(x => x.UserExamId == updateUserExamItemDto.UserExamId && x.QuestionId == updateUserExamItemDto.QuestionId).Any();
  253. if (!hasUserExamItem)
  254. {
  255. var addUserExamItemDto = _mapper.Map<UpdateUserExamItemDto, AddUserExamItemDto>(updateUserExamItemDto);
  256. await AddExamAsync(_userExamItemRepository, addUserExamItemDto, cancellationToken);
  257. }
  258. else
  259. {
  260. await UpdateExamAsync(_userExamItemRepository, updateUserExamItemDto, cancellationToken);
  261. }
  262. await CalcuteExamItemScore(_userExamItemRepository, updateUserExamItemDto, cancellationToken);
  263. return startExamViewResponse;
  264. }
  265. private async Task SetExamStatus(ExamUserExam userExam, StartExamViewResponse startExamViewResponse, CancellationToken cancellationToken)
  266. {
  267. userExam.ExamStatus = startExamViewResponse.IsCompleted ? EExamStatus.Complete : EExamStatus.NoStart;
  268. userExam.ToUpdate(_sessionContext);
  269. await _repository.UpdateWithValidateAsync(userExam, cancellationToken);
  270. }
  271. public async Task<StartExamViewResponse> StartUserExamAsync(StartUserExamDto startUserExamDto, CancellationToken cancellationToken)
  272. {
  273. var userExam = await _repository.GetAsync(x => x.Id == startUserExamDto.Id);
  274. if (userExam == null) return new StartExamViewResponse
  275. {
  276. IsJoin = false
  277. };
  278. if (userExam.StartTime == null)
  279. userExam.StartTime = DateTime.Now;
  280. var startExamViewResponse = await CheckExamValid(userExam, cancellationToken);
  281. if (!startExamViewResponse.CheckValidate())
  282. {
  283. await SetExamStatus(userExam, startExamViewResponse, cancellationToken);
  284. return startExamViewResponse;
  285. }
  286. if (userExam.ExamStatus == EExamStatus.NoStart)
  287. {
  288. userExam.ExamStatus = Share.Enums.Exams.EExamStatus.Executing;
  289. userExam.ToUpdate(_sessionContext);
  290. await _repository.UpdateWithValidateAsync(userExam, cancellationToken);
  291. }
  292. var examManage = await _examManageRepository.GetAsync(x => x.Id == userExam.ExamId);
  293. return new StartExamViewResponse
  294. {
  295. StartTime = userExam.StartTime,
  296. TimeSpan = examManage?.TimeSpan,
  297. IsCompleted = false
  298. };
  299. }
  300. private async Task<StartExamViewResponse> CheckExamValid(ExamUserExam examUserExam, CancellationToken cancellationToken)
  301. {
  302. var examManage = await _examManageRepository.Queryable().Where(x => x.Id == examUserExam.ExamId).FirstAsync();
  303. var startExamViewResponse = new StartExamViewResponse
  304. {
  305. IsJoin = true,
  306. IsCompleted = false
  307. };
  308. if (examManage != null)
  309. {
  310. var examStrategyProxy = new ExamStrategyProxy();
  311. var examStrategys = new List<IExamStrategy>();
  312. startExamViewResponse = AddCheckStartTimeStrategy(examUserExam, examManage, startExamViewResponse, examStrategys);
  313. startExamViewResponse = AddCheckEndTimeStrategy(examUserExam, examManage, startExamViewResponse, examStrategys);
  314. startExamViewResponse = AddCheckValidateTimeStrategy(examUserExam, examManage, startExamViewResponse, examStrategys);
  315. startExamViewResponse = AddCheckValidateCountStrategy(examUserExam, examManage, startExamViewResponse, examStrategys);
  316. examStrategyProxy.Initial(examStrategys);
  317. if (!examStrategyProxy.Validate())
  318. {
  319. startExamViewResponse = (StartExamViewResponse)examStrategyProxy.GetResult();
  320. return startExamViewResponse;
  321. }
  322. }
  323. startExamViewResponse.IsStart = true;
  324. if (examManage.ExamStatus == EExamStatus.NoStart)
  325. {
  326. await UpdateExamStatus(examManage, cancellationToken);
  327. }
  328. startExamViewResponse.TimeSpan = examManage?.TimeSpan ?? 0;
  329. startExamViewResponse.StartTime = examUserExam?.StartTime;
  330. return startExamViewResponse;
  331. }
  332. private async Task UpdateExamStatus(ExamManage? examManage, CancellationToken cancellationToken)
  333. {
  334. examManage.ExamStatus = EExamStatus.Executing;
  335. examManage.ToUpdate(_sessionContext);
  336. await _examManageRepository.UpdateWithValidateAsync(examManage, cancellationToken);
  337. }
  338. private StartExamViewResponse AddCheckValidateCountStrategy(ExamUserExam examUserExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List<IExamStrategy> examStrategys)
  339. {
  340. if (examManage.ExamType == Share.Enums.Exams.EExamType.Simulate)
  341. {
  342. var checkStartTime = new CheckValidateCountStrategy(1, 1)
  343. {
  344. CallBack = () =>
  345. {
  346. var response = new StartExamViewResponse
  347. {
  348. IsJoin = false,
  349. IsStart = false,
  350. IsCompleted = true,
  351. StartTime = examUserExam.StartTime,
  352. TimeSpan = examManage.TimeSpan
  353. };
  354. return response;
  355. }
  356. };
  357. examStrategys.Add(checkStartTime);
  358. return startExamViewResponse;
  359. }
  360. else
  361. {
  362. var count = new ExamRepository<ExamUserExam>(_uow, _dataPermissionFilterBuilder, _serviceProvider).CountAsync(x => x.ExamId == examManage.Id && x.UserId == examUserExam.UserId).Result;
  363. var checkStartTime = new CheckValidateCountStrategy(examManage.Count, count)
  364. {
  365. CallBack = () =>
  366. {
  367. var response = new StartExamViewResponse
  368. {
  369. IsJoin = false,
  370. IsStart = false,
  371. IsCompleted = true,
  372. StartTime = examUserExam.StartTime,
  373. TimeSpan = examManage.TimeSpan
  374. };
  375. return response;
  376. }
  377. };
  378. examStrategys.Add(checkStartTime);
  379. return startExamViewResponse;
  380. }
  381. }
  382. private StartExamViewResponse AddCheckValidateTimeStrategy(ExamUserExam examUserExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List<IExamStrategy> examStrategys)
  383. {
  384. if (examManage.ExamType == Share.Enums.Exams.EExamType.Simulate) return startExamViewResponse;
  385. var checkStartTime = new CheckValidateTimeStrategy(examManage.TimeSpan, examUserExam.StartTime)
  386. {
  387. CallBack = () =>
  388. {
  389. var response = new StartExamViewResponse
  390. {
  391. IsJoin = false,
  392. IsStart = false,
  393. IsCompleted = true,
  394. StartTime = examUserExam.StartTime,
  395. TimeSpan = examManage.TimeSpan
  396. };
  397. return response;
  398. }
  399. };
  400. examStrategys.Add(checkStartTime);
  401. return startExamViewResponse;
  402. }
  403. private StartExamViewResponse AddCheckEndTimeStrategy(ExamUserExam examUserExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List<IExamStrategy> examStrategys)
  404. {
  405. if (examManage.ExamType == Share.Enums.Exams.EExamType.Simulate) return startExamViewResponse;
  406. var checkStartTime = new CheckEndTimeStrategy(examManage.EndTime, DateTime.Now)
  407. {
  408. CallBack = () =>
  409. {
  410. var response = new StartExamViewResponse
  411. {
  412. IsJoin = false,
  413. IsStart = false,
  414. IsCompleted = true,
  415. StartTime = examUserExam.StartTime,
  416. TimeSpan = examManage.TimeSpan
  417. };
  418. return response;
  419. }
  420. };
  421. examStrategys.Add(checkStartTime);
  422. return startExamViewResponse;
  423. }
  424. private static StartExamViewResponse AddCheckStartTimeStrategy(ExamUserExam examUserExam, ExamManage examManage, StartExamViewResponse startExamViewResponse, List<IExamStrategy> examStrategys)
  425. {
  426. if (examManage.ExamType == Share.Enums.Exams.EExamType.Simulate) return startExamViewResponse;
  427. var checkStartTime = new CheckStartTimeStrategy(examManage.StartTime, examUserExam.StartTime)
  428. {
  429. CallBack = () =>
  430. {
  431. var response = new StartExamViewResponse
  432. {
  433. IsJoin = false,
  434. IsStart = false,
  435. IsCompleted = false,
  436. StartTime = examUserExam.StartTime,
  437. TimeSpan = examManage.TimeSpan
  438. };
  439. return response;
  440. }
  441. };
  442. examStrategys.Add(checkStartTime);
  443. return startExamViewResponse;
  444. }
  445. public async Task CompleteGradingAsync(GradingExamDto gradingExtamDto, CancellationToken cancellationToken)
  446. {
  447. var userExam = await _repository.GetAsync(x => x.Id == gradingExtamDto.Id);
  448. if (userExam == null) return;
  449. var userExamItems = await _userExamItemRepository.Queryable().Where(x => x.UserExamId == gradingExtamDto.Id).ToListAsync();
  450. if (userExamItems != null)
  451. {
  452. var totalScore = userExamItems.Sum(x => x.Score);
  453. userExam.Score = totalScore;
  454. var examManage = await new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider).GetAsync(x => x.Id == userExam.ExamId);
  455. userExam.IsSuccess = totalScore >= examManage.CutoffScore;
  456. userExam.ExamStatus = Share.Enums.Exams.EExamStatus.Complete;
  457. userExam.ToUpdate(_sessionContext);
  458. await _repository.UpdateWithValidateAsync(userExam, cancellationToken);
  459. }
  460. }
  461. public async Task<List<GradingExamQuestionDto>> GetGradingExamQuestion(GradingExamRequest gradingExamRequest)
  462. {
  463. var expression = gradingExamRequest.GetExpression();
  464. var userExamTable = _repository.Queryable().Where(expression);
  465. var questionScoreRepository = new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  466. var userExamItemTable = _userExamItemRepository.Queryable();
  467. var userExamItemOptionTable = _userExamItemOptionRepository.Queryable();
  468. var examAnswerTable = new ExamRepository<ExamAnswer>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
  469. var questionTable = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
  470. var quesitonOptionTable = new ExamRepository<ExamQuestionOptionsBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
  471. var testPaperItemAnswerTable = new ExamRepository<ExamQuestionAnswerBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
  472. var questionScoreTable = questionScoreRepository.Queryable();
  473. var queryable = userExamTable.InnerJoin(userExamItemTable, (e, i) => e.Id == i.UserExamId)
  474. .InnerJoin(questionTable, (e, i, q) => i.QuestionId == q.QuestionId)
  475. .LeftJoin(userExamItemOptionTable, (e, i, q, o) => i.Id == o.UserExamItemId)
  476. .LeftJoin(quesitonOptionTable, (e, i, q, o, qo) => o.QuestionOptionId == qo.Id)
  477. .LeftJoin(examAnswerTable, (e, i, q, o, qo, a) => i.Id == a.UserExamItemId)
  478. .LeftJoin(testPaperItemAnswerTable, (e, i, q, o, qo, a, ta) => ta.QuestionId == q.QuestionId)
  479. .InnerJoin(questionScoreTable, (e, i, q, o, qo, a, ta, s) => q.QuestionType == s.QuestionType && e.ExamId == s.ExamManageId)
  480. .Where((e, i, q, o, qo, a, ta, s) => !(q.QuestionType == EQuestionType.Single || q.QuestionType == EQuestionType.Multi || q.QuestionType == EQuestionType.Judge))
  481. .Select(
  482. (e, i, q, o, qo, a, ta, s) => new GradingExamQuestionTempDto
  483. {
  484. Id = i.Id,
  485. QuestionType = q.QuestionType,
  486. CorrectAnswer = ta.Id != null ? ta.Answer : string.Empty,
  487. Answer = a.Id != null ? a.Answer : string.Empty,
  488. Title = q.Title,
  489. QuestionOptionId = o.Id,
  490. UserExamItemId = i.Id,
  491. Content = qo.Content,
  492. Label = qo.Label,
  493. IsAnswer = qo.IsAnswer,
  494. IsSelected = o.Id != null,
  495. QuestionScore = s.Score,
  496. Score = i.Score
  497. }
  498. );
  499. var queryResult = await queryable.ToListAsync();
  500. var gradingExamQuestionDtos = queryResult.GroupBy(x => new
  501. {
  502. Id = x.Id,
  503. QuestionType = x.QuestionType
  504. }).Select(g => new GradingExamQuestionDto
  505. {
  506. Answer = g.FirstOrDefault().Answer,
  507. QuestionType = g.Key.QuestionType,
  508. Id = g.Key.Id,
  509. QuestionScore = g.FirstOrDefault().QuestionScore,
  510. Score = g.FirstOrDefault().Score,
  511. Title = g.FirstOrDefault().Title,
  512. CorrectAnswer = g.Key.QuestionType.CheckSelectType() ? string.Join(",", g.Where(i => i.IsAnswer).Select(n => n.Label).Distinct()) : g.FirstOrDefault()?.CorrectAnswer
  513. }).ToList();
  514. return gradingExamQuestionDtos;
  515. }
  516. public async Task<GradingExamQuestionDto> ViewGradingExamQuestion(ViewGradingExamRequest viewGradingExamRequest)
  517. {
  518. var gradingExtamItemDto = _mapper.Map<ViewGradingExamRequest, GradingExamItemDto>(viewGradingExamRequest);
  519. return await GetNextExamQuestion(gradingExtamItemDto);
  520. }
  521. public async Task<UnExamUserPageViewResponse> GetUnExamUsers(UnExamUserReportPagedRequest unExamUserReportPagedRequest)
  522. {
  523. unExamUserReportPagedRequest.ResolveEndTime();
  524. var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  525. var userRepository = new ExamRepository<User>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  526. var expression = unExamUserReportPagedRequest.GetExpression();
  527. var userExamExpression = unExamUserReportPagedRequest.GetUserExamExpression();
  528. var examManageTable = examManageRepository.Queryable().Where(expression);
  529. var userTable = userRepository.Queryable();
  530. var userExamTable = _repository.Queryable().Where(userExamExpression);
  531. var queryResult = userExamTable.InnerJoin(examManageTable, (ue, e) => ue.ExamId == e.Id)
  532. .InnerJoin(userTable, (ue, e, u) => ue.UserId == u.Id)
  533. .Select((ue, e, u) => new UnExamUserViewResponse
  534. {
  535. ExamName = e.Name,
  536. OrgName = u.Organization.Name,
  537. UserName = u.Name
  538. });
  539. var total = await queryResult.CountAsync();
  540. var items = await queryResult.ToPageListAsync(unExamUserReportPagedRequest.PageIndex, unExamUserReportPagedRequest.PageSize);
  541. return new UnExamUserPageViewResponse
  542. {
  543. Items = items,
  544. Pagination = new Pagination(unExamUserReportPagedRequest.PageIndex, unExamUserReportPagedRequest.PageSize, total)
  545. };
  546. }
  547. public async Task<UserExamResultPageViewResponse> GetUserExamResults(UserExamResultReportPagedRequest userExamResultReportPagedRequest)
  548. {
  549. userExamResultReportPagedRequest.ResolveEndTime();
  550. var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  551. var userRepository = new ExamRepository<User>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  552. var expression = userExamResultReportPagedRequest.GetExpression();
  553. var userExamExpression = userExamResultReportPagedRequest.GetUserExamExpression();
  554. var examManageTable = examManageRepository.Queryable().Where(expression);
  555. var userTable = userRepository.Queryable();
  556. var userExamTable = _repository.Queryable().Where(userExamExpression);
  557. var queryResult = userExamTable.InnerJoin(examManageTable, (ue, e) => ue.ExamId == e.Id)
  558. .InnerJoin(userTable, (ue, e, u) => ue.UserId == u.Id)
  559. .Select((ue, e, u) => new UserExamResultViewResponse
  560. {
  561. ExamName = e.Name,
  562. OrgName = u.Organization.Name,
  563. UserName = u.Name,
  564. TotalScore = e.TotalScore,
  565. CutoffScore = e.CutoffScore,
  566. Score = ue.Score ?? 0,
  567. })
  568. .MergeTable()
  569. .OrderByDescending(x => x.Score);
  570. var total = await queryResult.CountAsync();
  571. var items = await queryResult.ToPageListAsync(userExamResultReportPagedRequest.PageIndex, userExamResultReportPagedRequest.PageSize);
  572. return new UserExamResultPageViewResponse
  573. {
  574. Items = items,
  575. Pagination = new Pagination(userExamResultReportPagedRequest.PageIndex, userExamResultReportPagedRequest.PageSize, total)
  576. };
  577. }
  578. public async Task<GradingResultPageViewResponse> GetGradingResultPagedList(GradingPagedRequest gradingPagedRequest)
  579. {
  580. // 只要有阅卷记录就在已阅卷列表中,已阅卷和未阅卷会有重复数据,只有所有记录都已阅卷才会从未阅卷列表中排除
  581. var userExamTable = _repository.Queryable().WhereIF(gradingPagedRequest.IsCheck != null, x => x.IsCheck == gradingPagedRequest.IsCheck).Where(x=>x.IsSubmit);
  582. var examManageTable = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
  583. var queryable = userExamTable.InnerJoin(examManageTable, (u, e) => u.ExamId == e.Id).GroupBy((u, e) => new
  584. {
  585. ExamName = e.Name,
  586. ExamCode = e.Code,
  587. CutoffScore = e.CutoffScore,
  588. TotalScore = e.TotalScore,
  589. Id = e.Id,
  590. Status = e.Status,
  591. Remark = e.Remark
  592. }).Select((u, e) => new GradingResultViewResponse
  593. {
  594. CutoffScore = e.CutoffScore,
  595. TotalScore = e.TotalScore,
  596. ExamName = e.Name,
  597. ExamCode = e.Code,
  598. IsCheck = SqlFunc.Subqueryable<ExamUserExam>().Where(x => x.ExamId == e.Id && x.IsCheck).Any(),
  599. Id = e.Id,
  600. Remark = e.Remark
  601. });
  602. var list = await queryable.ToPageListAsync(gradingPagedRequest.PageIndex, gradingPagedRequest.PageSize);
  603. var total = await queryable.CountAsync();
  604. var result = new GradingResultPageViewResponse
  605. {
  606. Items = list,
  607. Pagination = new Pagination(gradingPagedRequest.PageIndex, gradingPagedRequest.PageSize, total)
  608. };
  609. return result;
  610. }
  611. public async Task BatchGradingAsync(BatchGradingExamItemDto batchGradingExamItemDto, CancellationToken cancellationToken)
  612. {
  613. var userExamItemIds = batchGradingExamItemDto.Items.Select(x => x.UserExamItemId);
  614. var userExamItems = await _userExamItemRepository.Queryable().Where(m => userExamItemIds.Contains(m.Id)).ToListAsync();
  615. if (userExamItems != null && userExamItemIds.Any())
  616. {
  617. var updateUserExamItems = new List<ExamUserExamItem>();
  618. userExamItems.ForEach(x =>
  619. {
  620. var gradingExamItemDto = batchGradingExamItemDto.Items.Find(m => m.UserExamItemId == x.Id);
  621. var updateUserExamItem = _mapper.Map<GradingExamItemDto, ExamUserExamItem>(gradingExamItemDto, x);
  622. updateUserExamItem.IsCheck = true;
  623. updateUserExamItems.Add(updateUserExamItem);
  624. });
  625. updateUserExamItems.ToUpdate(_sessionContext);
  626. await _userExamItemRepository.UpdateWithValidateAsync(updateUserExamItems, cancellationToken);
  627. var userExamId = userExamItems.FirstOrDefault()?.UserExamId;
  628. // 计算本次考试得分
  629. var userExamItemsInCheck = await _userExamItemRepository.Queryable()
  630. .InnerJoin<ExamQuestionBak>((u, q) => u.QuestionId == q.QuestionId)
  631. .Where((u, q) => u.UserExamId == userExamId && (q.QuestionType == EQuestionType.Single || q.QuestionType == EQuestionType.Multi || q.QuestionType == EQuestionType.Judge)).Select((u, q) => new UpdateUserExamItemDto
  632. {
  633. QuestionId = u.QuestionId,
  634. QuestionType = q.QuestionType,
  635. UserExamId = u.UserExamId,
  636. }).Distinct().ToListAsync();
  637. await CalcuteExamItemScore(_userExamItemRepository, userExamItemsInCheck, cancellationToken);
  638. await CalcuteTotalScore(_userExamItemRepository, userExamId, cancellationToken);
  639. }
  640. }
  641. public async Task<List<ExamUserViewResponse>> GetUserListAsync(ExamUserQueryRequest examUserQueryRequest)
  642. {
  643. var userExamTable = _repository.Queryable().Where(x => x.ExamId == examUserQueryRequest.ExamId);
  644. var queryable = await userExamTable.InnerJoin<User>((ux, u) => ux.UserId == u.Id).Select((ux, u) => new ExamUserViewResponse
  645. {
  646. ExamId = ux.ExamId,
  647. UserId = ux.UserId,
  648. UserName = u.Name,
  649. Id = ux.Id
  650. }).ToListAsync();
  651. return queryable;
  652. }
  653. #endregion
  654. #region private method
  655. private async Task CalcuteExamItemScore(IUserExamItemRepository userExamRepository, UpdateUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
  656. {
  657. if (!addUserExamItemDto.QuestionType.CheckSelectType()) return;
  658. var testPaperItemOptionsRepository = new ExamRepository<ExamQuestionOptionsBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  659. var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  660. var testPaperItemRepository = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  661. var examQuestionScoreRepository = new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  662. var testPaperOptionsTable = testPaperItemOptionsRepository.Queryable().Where(x => x.QuestionId == addUserExamItemDto.QuestionId && x.IsAnswer);
  663. var testPaperItemTable = testPaperItemRepository.Queryable();
  664. var userExamTable = _repository.Queryable().Where(x => x.Id == addUserExamItemDto.UserExamId);
  665. var examManageTable = examManageRepository.Queryable();
  666. var testPaperOptionIds = await testPaperOptionsTable.InnerJoin(testPaperItemTable, (t, i) => t.ExamQuestionId == i.Id)
  667. .InnerJoin(examManageTable, (t, i, e) => i.ExamId == e.Id)
  668. .InnerJoin(userExamTable, (t, i, e, u) => e.Id == u.ExamId)
  669. .Select((t, i, e, u) => t.Id).ToListAsync();
  670. var isCorrect = addUserExamItemDto.UserExamItemOptionDtos.Select(x => x.QuestionOptionId).OrderBy(x => x).SequenceEqual(testPaperOptionIds.OrderBy(x => x));
  671. var userExamItem = await userExamRepository.GetAsync(x => x.UserExamId == addUserExamItemDto.UserExamId && x.QuestionId == addUserExamItemDto.QuestionId);
  672. var examQuesiontScores = await examQuestionScoreRepository.Queryable().Where(x => x.QuestionType == addUserExamItemDto.QuestionType)
  673. .InnerJoin(userExamTable, (e, u) => e.Id == u.ExamId)
  674. .Select((e, u) => e).ToListAsync();
  675. userExamItem.IsCheck = true;
  676. userExamItem.Score = isCorrect ? examQuesiontScores.FirstOrDefault()?.Score : 0;
  677. userExamItem.ToUpdate(_sessionContext);
  678. await userExamRepository.UpdateWithValidateAsync(userExamItem, cancellationToken);
  679. }
  680. private async Task CalcuteExamItemScore(IUserExamItemRepository userExamItemRepository, List<UpdateUserExamItemDto> addUserExamItemDtos, CancellationToken cancellationToken)
  681. {
  682. var questionIds = addUserExamItemDtos.Select(x => x.QuestionId).ToList();
  683. var userExamIds = addUserExamItemDtos.Select(x => x.UserExamId).ToList();
  684. var questionTypes = addUserExamItemDtos.Select(x => x.QuestionType).ToList();
  685. var testPaperItemOptionsRepository = new ExamRepository<ExamQuestionOptionsBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  686. var userExamItemOptionRepository = new ExamRepository<ExamUserExamItemOptions>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  687. var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  688. var testPaperItemRepository = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  689. var examQuestionScoreRepository = new ExamRepository<ExamQuestionScoreBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  690. var testPaperOptionsTable = testPaperItemOptionsRepository.Queryable().Where(x => questionIds.Contains(x.QuestionId) && x.IsAnswer);
  691. var testPaperItemTable = testPaperItemRepository.Queryable().Where(x => x.QuestionType == EQuestionType.Single || x.QuestionType == EQuestionType.Multi || x.QuestionType == EQuestionType.Judge);
  692. var userExamTable = _repository.Queryable().Where(x => userExamIds.Contains(x.Id));
  693. var examManageTable = examManageRepository.Queryable();
  694. var testPaperOptionIds = await testPaperOptionsTable.InnerJoin(testPaperItemTable, (t, i) => t.ExamQuestionId == i.Id)
  695. .InnerJoin(examManageTable, (t, i, e) => i.ExamId == e.Id)
  696. .InnerJoin(userExamTable, (t, i, e, u) => e.Id == u.ExamId)
  697. .Select((t, i, e, u) => t.Id).ToListAsync();
  698. var userExamItems = await userExamItemRepository.Queryable().Where(x => userExamIds.Contains(x.UserExamId)).ToListAsync();
  699. var userExamItemIds = userExamItems.Select(x => x.Id).ToList();
  700. var userExamItemOptions = await userExamItemOptionRepository.Queryable().Where(x => userExamItemIds.Contains(x.UserExamItemId)).ToListAsync();
  701. var examQuesiontScores = await examQuestionScoreRepository.Queryable().Where(x => questionTypes.Contains(x.QuestionType))
  702. .InnerJoin(userExamTable, (e, u) => e.Id == u.ExamId)
  703. .Select((e, u) => e).ToListAsync();
  704. foreach (var addUserExamItemDto in addUserExamItemDtos)
  705. {
  706. var isCorrect = userExamItemOptions.Select(x => x.QuestionOptionId).OrderBy(x => x).SequenceEqual(testPaperOptionIds.OrderBy(x => x));
  707. var userExamItem = userExamItems.FirstOrDefault(x => x.QuestionId == addUserExamItemDto.QuestionId);
  708. if (userExamItem != null)
  709. {
  710. userExamItem.IsCheck = true;
  711. userExamItem.Score = isCorrect ? examQuesiontScores.FirstOrDefault(x => x.QuestionType == addUserExamItemDto.QuestionType)?.Score : 0;
  712. userExamItem.ToUpdate(_sessionContext);
  713. }
  714. }
  715. await userExamItemRepository.UpdateWithValidateAsync(userExamItems, cancellationToken);
  716. }
  717. private async Task CalcuteTotalScore(IUserExamItemRepository userExamItemRepository, string userExamId, CancellationToken cancellationToken)
  718. {
  719. var userExam = await _repository.GetAsync(x => x.Id == userExamId);
  720. if (userExam != null)
  721. {
  722. var userExamItems = await userExamItemRepository.Queryable().Where(x => x.UserExamId == userExamId).ToListAsync();
  723. var examManageRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  724. var examManage = await examManageRepository.GetAsync(x => x.Id == userExam.ExamId);
  725. var totalScore = userExamItems.Sum(x => x.Score);
  726. userExam.Score = totalScore;
  727. userExam.IsCheck = true;
  728. userExam.ExamStatus = EExamStatus.Complete;
  729. if (examManage != null)
  730. {
  731. userExam.IsSuccess = userExam.Score > examManage.CutoffScore;
  732. }
  733. userExam.ToUpdate(_sessionContext);
  734. await _repository.UpdateWithValidateAsync(userExam, cancellationToken);
  735. }
  736. }
  737. private async Task AddExamAsync(IRepository<ExamUserExamItem> userExamItemRepository, AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
  738. {
  739. var userExamItem = await AddUserExamItem(addUserExamItemDto, cancellationToken);
  740. userExamItem.UserExamItemOptionses = await AddUserExamItemOptions(addUserExamItemDto, cancellationToken);
  741. userExamItem.ExamAnswers = await AddExamAnswer(addUserExamItemDto, userExamItem.Id, cancellationToken);
  742. await userExamItemRepository.AddNav(userExamItem)
  743. .Include(x => x.UserExamItemOptionses)
  744. .Include(x => x.ExamAnswers)
  745. .ExecuteCommandAsync();
  746. }
  747. private async Task UpdateExamAsync(IRepository<ExamUserExamItem> userExamItemRepository, UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
  748. {
  749. var userExamItem = await UpdateUserExamItem(updateUserExamItemDto, cancellationToken);
  750. userExamItem.UserExamItemOptionses = await ModifyUserItemOptions(updateUserExamItemDto, cancellationToken);
  751. userExamItem.ExamAnswers = await UpdateExamAnswer(updateUserExamItemDto, cancellationToken);
  752. await userExamItemRepository.UpdateNav(userExamItem)
  753. .Include(x => x.UserExamItemOptionses)
  754. .Include(x => x.ExamAnswers)
  755. .ExecuteCommandAsync();
  756. }
  757. private async Task<GradingExamQuestionDto> GetNextExamQuestion(GradingExamItemDto gradingExtamItemDto)
  758. {
  759. // TODO: 获取未阅卷的第一道题
  760. var current = _userExamItemRepository.Queryable().Where(x => x.Id == gradingExtamItemDto.UserExamItemId);
  761. var userExamItemTable = _userExamItemRepository.Queryable().Where(x => !x.IsCheck);
  762. var userExamItem = current.InnerJoin(userExamItemTable, (c, u) => c.UserExamId == u.UserExamId).OrderBy((c, u) => c.SortIndex).First();
  763. if (userExamItem != null)
  764. {
  765. var testPaperItem = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.Id == userExamItem.Id && !x.QuestionType.CheckSelectType()).First();
  766. if (testPaperItem == null) return null;
  767. var gradingExamQuestionDto = new GradingExamQuestionDto();
  768. gradingExamQuestionDto = _mapper.Map<Exams.ExamManages.ExamQuestionBak, GradingExamQuestionDto>(testPaperItem, gradingExamQuestionDto);
  769. var examAnswer = new ExamRepository<ExamAnswer>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.UserExamItemId == userExamItem.Id).First();
  770. var testPaperItemAnswer = await new ExamRepository<ExamQuestionAnswerBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().FirstAsync(x => x.QuestionId == testPaperItem.QuestionId && x.ExamQuestionId == testPaperItem.Id);
  771. gradingExamQuestionDto.Answer = examAnswer.Answer ?? string.Empty;
  772. gradingExamQuestionDto.CorrectAnswer = testPaperItemAnswer != null ? testPaperItemAnswer.Answer ?? string.Empty : string.Empty;
  773. return gradingExamQuestionDto;
  774. }
  775. return null;
  776. }
  777. private async Task<List<ExamAnswer>> AddExamAnswer(AddUserExamItemDto addUserExamItemDto, string id, CancellationToken cancellationToken)
  778. {
  779. if (addUserExamItemDto.QuestionType.CheckSelectType()) return null;
  780. var examAnswers = new List<ExamAnswer>();
  781. var examAnswer = new ExamAnswer
  782. {
  783. UserId = _sessionContext.UserId,
  784. UserExamItemId = id,
  785. Answer = addUserExamItemDto.Answer
  786. };
  787. examAnswer.ToInsert(_sessionContext);
  788. await _examAnswerRepository.ValidateAddAsync(examAnswer, cancellationToken);
  789. examAnswers.Add(examAnswer);
  790. return examAnswers;
  791. }
  792. private async Task<UserExamQuestionDto> GetNextExamQuestion(AddUserExamItemDto addUserExamItemDto)
  793. {
  794. // TODO: 获取未阅卷的第一道题
  795. var testPaperItemRepository = new ExamRepository<Exams.ExamManages.ExamQuestionBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  796. var examRepository = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider);
  797. var userExamTable = _repository.Queryable().Where(x => x.Id == addUserExamItemDto.UserExamId);
  798. var userExamItemTable = _userExamItemRepository.Queryable().WhereIF(addUserExamItemDto.QuestionId.IsNotNullOrEmpty(), x => x.QuestionId == addUserExamItemDto.QuestionId);
  799. var examTable = examRepository.Queryable();
  800. var testPaperItemTable = testPaperItemRepository.Queryable();
  801. var current = examTable.InnerJoin(testPaperItemTable, (e, t) => e.Id == t.ExamId)
  802. .InnerJoin(userExamTable, (e, t, u) => e.Id == u.ExamId)
  803. .InnerJoin(userExamItemTable, (e, t, u, i) => t.QuestionId == i.QuestionId).Select((e, t, u, i) => t);
  804. var nextTable = testPaperItemTable.InnerJoin(current, (t, c) => t.SortIndex > c.SortIndex).OrderBy((t, c) => t.SortIndex).Select((t, c) => t);
  805. var userExamItem = userExamItemTable.InnerJoin(nextTable, (u, n) => u.QuestionId == n.QuestionId).OrderBy((u, n) => u.SortIndex).Select((u, n) => u).First();
  806. if (userExamItem != null)
  807. {
  808. var question = testPaperItemRepository.Queryable().Where(x => x.Id == userExamItem.Id).First();
  809. if (question == null) return null;
  810. var userExamQuestionDto = new UserExamQuestionDto();
  811. userExamQuestionDto = _mapper.Map<Exams.ExamManages.ExamQuestionBak, UserExamQuestionDto>(question, userExamQuestionDto);
  812. if (question.QuestionType.CheckSelectType())
  813. {
  814. var userExamItemOptionTable = _userExamItemOptionRepository.Queryable().Where(x => x.UserExamItemId == userExamItem.Id);
  815. var quesitonOptionTable = new ExamRepository<ExamQuestionOptionsBak>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable();
  816. var queryResult = userExamItemOptionTable.InnerJoin(quesitonOptionTable, (u, q) => u.QuestionOptionId == q.Id)
  817. .Select((u, q) => new UserExamItemOptionDto
  818. {
  819. Content = q.Content,
  820. QuestionOptionId = u.QuestionOptionId,
  821. UserExamItemId = u.UserExamItemId
  822. });
  823. userExamQuestionDto.UserExamItemOptionDtos = queryResult.ToList();
  824. }
  825. else
  826. {
  827. var examAnswer = new ExamRepository<ExamAnswer>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(x => x.UserExamItemId == userExamItem.Id).First();
  828. userExamQuestionDto.Answer = examAnswer.Answer ?? string.Empty;
  829. }
  830. return userExamQuestionDto;
  831. }
  832. else
  833. {
  834. return null;
  835. }
  836. }
  837. private async Task<List<ExamAnswer>> UpdateExamAnswer(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
  838. {
  839. var examAnswerTable = _examAnswerRepository.Queryable();
  840. var userExamItemTable = _userExamItemRepository.Queryable().Where(x => x.Id == updateUserExamItemDto.Id);
  841. var examAnswer = await examAnswerTable.InnerJoin(userExamItemTable, (e, u) => e.UserExamItemId == u.Id).Select((e, u) => e).FirstAsync();
  842. if (!updateUserExamItemDto.QuestionType.CheckSelectType())
  843. {
  844. var examAnswers = new List<ExamAnswer>();
  845. if (examAnswer != null)
  846. {
  847. examAnswer.Answer = updateUserExamItemDto.Answer;
  848. examAnswer.UserId = _sessionContext.UserId;
  849. examAnswer.UserExamItemId = updateUserExamItemDto.Id;
  850. examAnswer.ToUpdate(_sessionContext);
  851. await _examAnswerRepository.UpdateWithValidateAsync(examAnswer, cancellationToken);
  852. examAnswers.Add(examAnswer);
  853. }
  854. else
  855. {
  856. examAnswer = new ExamAnswer
  857. {
  858. Answer = updateUserExamItemDto.Answer,
  859. UserId = _sessionContext.UserId,
  860. UserExamItemId = updateUserExamItemDto.Id
  861. };
  862. examAnswer.ToInsert(_sessionContext);
  863. await _examAnswerRepository.ValidateAddAsync(examAnswer, cancellationToken);
  864. examAnswers.Add(examAnswer);
  865. }
  866. return examAnswers;
  867. }
  868. return null;
  869. }
  870. private async Task<List<ExamUserExamItemOptions>> ModifyUserItemOptions(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
  871. {
  872. if (updateUserExamItemDto.QuestionType.CheckSelectType())
  873. {
  874. var entityQuestionRequest = new EntityQueryRequest
  875. {
  876. Expression = ExpressionableUtility.CreateExpression<ExamUserExamItemOptions>()
  877. .AndIF(updateUserExamItemDto.Id.IsNotEmpty(), x => x.UserExamItemId == updateUserExamItemDto.Id).ToExpression()
  878. };
  879. await DeleteUserExamItemOptions(entityQuestionRequest, cancellationToken);
  880. //await UpdateUserItemOptions(updateUserExamItemDto, cancellationToken);
  881. var addUserExamItemDto = _mapper.Map<AddUserExamItemDto>(updateUserExamItemDto);
  882. addUserExamItemDto.UserExamItemOptionDtos = new List<AddUserExamItemOptionDto>();
  883. updateUserExamItemDto.UserExamItemOptionDtos.ForEach(item =>
  884. {
  885. addUserExamItemDto.UserExamItemOptionDtos.Add(_mapper.Map<AddUserExamItemOptionDto>(item));
  886. });
  887. return await AddUserExamItemOptions(addUserExamItemDto, cancellationToken);
  888. }
  889. return null;
  890. }
  891. private async Task UpdateUserItemOptions(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
  892. {
  893. if (updateUserExamItemDto.QuestionType.CheckSelectType())
  894. {
  895. var userExamItemOptions = await _userExamItemOptionRepository.Queryable().Where(x => x.UserExamItemId == updateUserExamItemDto.Id).ToListAsync();
  896. var entities = new List<ExamUserExamItemOptions>();
  897. if (updateUserExamItemDto.UserExamItemOptionDtos != null)
  898. {
  899. updateUserExamItemDto.UserExamItemOptionDtos.Where(m => m.OperationStatus == EEOperationStatus.Update).ToList().ForEach(x =>
  900. {
  901. var entity = userExamItemOptions.FirstOrDefault(m => m.Id == x.Id);
  902. if (entity != null)
  903. {
  904. entities.Add(_mapper.Map<UpdateUserExamItemOptionDto, ExamUserExamItemOptions>(x, entity));
  905. }
  906. });
  907. }
  908. entities.ToUpdate(_sessionContext);
  909. await _userExamItemOptionRepository.UpdateWithValidateAsync(entities, cancellationToken);
  910. }
  911. }
  912. private async Task<ExamUserExamItem> UpdateUserExamItem(UpdateUserExamItemDto updateUserExamItemDto, CancellationToken cancellationToken)
  913. {
  914. var userExamItem = await _userExamItemRepository.GetAsync(x => x.UserExamId == updateUserExamItemDto.UserExamId && x.QuestionId == updateUserExamItemDto.QuestionId);
  915. userExamItem = _mapper.Map<UpdateUserExamItemDto, ExamUserExamItem>(updateUserExamItemDto, userExamItem);
  916. updateUserExamItemDto.Id = userExamItem.Id;
  917. userExamItem.ToUpdate(_sessionContext);
  918. await _userExamItemRepository.UpdateWithValidateAsync(userExamItem, cancellationToken);
  919. if (updateUserExamItemDto.QuestionType.CheckSelectType())
  920. {
  921. if (updateUserExamItemDto.UserExamItemOptionDtos != null)
  922. {
  923. updateUserExamItemDto.UserExamItemOptionDtos.ForEach(x => x.UserExamItemId = updateUserExamItemDto.Id);
  924. }
  925. }
  926. return userExamItem;
  927. }
  928. private async Task<List<ExamUserExamItemOptions>> AddUserExamItemOptions(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
  929. {
  930. var userExamItemOptions = new List<ExamUserExamItemOptions>();
  931. if (addUserExamItemDto.QuestionType.CheckSelectType())
  932. {
  933. if (addUserExamItemDto.UserExamItemOptionDtos != null)
  934. {
  935. addUserExamItemDto.UserExamItemOptionDtos.ToList().ForEach(x =>
  936. {
  937. userExamItemOptions.Add(_mapper.Map<ExamUserExamItemOptions>(x));
  938. });
  939. }
  940. }
  941. userExamItemOptions.ToInsert(_sessionContext);
  942. await _userExamItemOptionRepository.ValidateAddAsync(userExamItemOptions, cancellationToken);
  943. return userExamItemOptions;
  944. }
  945. private async Task<ExamUserExamItem> AddUserExamItem(AddUserExamItemDto addUserExamItemDto, CancellationToken cancellationToken)
  946. {
  947. var userExamItem = _mapper.Map<ExamUserExamItem>(addUserExamItemDto);
  948. userExamItem.ToInsert(_sessionContext);
  949. await _userExamItemRepository.ValidateAddAsync(userExamItem, cancellationToken);
  950. if (addUserExamItemDto.QuestionType.CheckSelectType())
  951. {
  952. if (addUserExamItemDto.UserExamItemOptionDtos != null)
  953. {
  954. addUserExamItemDto.UserExamItemOptionDtos.ForEach(x => x.UserExamItemId = userExamItem.Id);
  955. }
  956. }
  957. return userExamItem;
  958. }
  959. private async Task DeleteUserExamItemOptions(EntityQueryRequest entityQueryRequest, CancellationToken cancellationToken)
  960. {
  961. await _userExamItemOptionRepository.DeleteWithValidateAsync(entityQueryRequest, cancellationToken);
  962. }
  963. private SqlSugar.ISugarQueryable<UserExamResultViewResponse> GetQueryable(UserExamPagedRequest queryRequest)
  964. {
  965. if (_sessionContext.UserId != null)
  966. {
  967. queryRequest.UserId = _sessionContext.UserId;
  968. }
  969. var expression = queryRequest.GetExpression();
  970. var userExamTable = _repository.Queryable().Where(expression);
  971. var examManageExpression = queryRequest.GetExamManageExpression();
  972. var examManageTable = new ExamRepository<ExamManage>(_uow, _dataPermissionFilterBuilder, _serviceProvider).Queryable().Where(examManageExpression);
  973. var queryable = userExamTable.InnerJoin(examManageTable, (u, e) => u.ExamId == e.Id).Select((u, e) => new UserExamResultViewResponse
  974. {
  975. Id = u.Id,
  976. CutoffScore = e.CutoffScore,
  977. TotalScore = e.TotalScore,
  978. ExamName = e.Name,
  979. Score = u.Score ?? 0,
  980. Status = u.Status,
  981. SortIndex = u.SortIndex,
  982. ExamStatus = u.ExamStatus,
  983. IsSuccess = u.IsCheck? u.IsSuccess:null,
  984. EndTime = e.EndTime,
  985. StartTime = e.StartTime,
  986. TimeSpan = e.TimeSpan,
  987. ExamType = e.ExamType,
  988. ExamId = e.Id,
  989. IsCheck = u.IsCheck
  990. });
  991. return queryable;
  992. }
  993. #endregion
  994. }
  995. }