ManageController.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. using IES.ExamLib.Models;
  2. using IES.ExamServer.DI;
  3. using IES.ExamServer.DI.SignalRHost;
  4. using IES.ExamServer.Filters;
  5. using IES.ExamServer.Helper;
  6. using IES.ExamServer.Helpers;
  7. using IES.ExamServer.Models;
  8. using Microsoft.AspNetCore.Mvc;
  9. using Microsoft.AspNetCore.SignalR;
  10. using Microsoft.Extensions.Caching.Memory;
  11. using Microsoft.Extensions.Configuration;
  12. using System.Linq.Expressions;
  13. using System.Net.Http;
  14. using System.Net.Http.Json;
  15. using System.Text.Json;
  16. using System.Text.Json.Nodes;
  17. namespace IES.ExamServer.Controllers
  18. {
  19. [ApiController]
  20. [Route("manage")]
  21. public class ManageController:BaseController
  22. {
  23. private readonly IConfiguration _configuration;
  24. private readonly IHttpClientFactory _httpClientFactory;
  25. private readonly IMemoryCache _memoryCache;
  26. private readonly ILogger<ManageController> _logger;
  27. private readonly LiteDBFactory _liteDBFactory;
  28. private readonly DataCenterConnectionService _connectionService;
  29. private readonly int DelayMicro = 10;//微观数据延迟
  30. private readonly int DelayMacro = 100;//宏观数据延迟
  31. private readonly IHubContext<SignalRExamServerHub> _signalRExamServerHub;
  32. public ManageController(LiteDBFactory liteDBFactory,ILogger<ManageController> logger, IConfiguration configuration,
  33. IHttpClientFactory httpClientFactory, IMemoryCache memoryCache, DataCenterConnectionService connectionService, IHubContext<SignalRExamServerHub> signalRExamServerHub)
  34. {
  35. _logger = logger;
  36. _configuration=configuration;
  37. _httpClientFactory=httpClientFactory;
  38. _memoryCache=memoryCache;
  39. _liteDBFactory=liteDBFactory;
  40. _connectionService=connectionService;
  41. _signalRExamServerHub=signalRExamServerHub;
  42. }
  43. [HttpPost("download-package")]
  44. [AuthToken("admin","teacher")]
  45. public async Task<IActionResult> DownloadPackage(JsonNode json)
  46. {
  47. //C#.NET 6 后端与前端流式通信
  48. //https://www.doubao.com/chat/collection/687687510791426?type=Thread
  49. //下载日志记录:1.步骤,检查,2.获取描述信息,3.分类型,4下载文件,5.前端处理,6.返回结果 , 正在下载...==> [INFO]https://www.doubao.com/chat/collection/687687510791426?type=Thread [Size=180kb] Ok...
  50. //进度条 展示下载文件总大小和已下载,末尾展示 文件总个数和已下载个数
  51. //https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.7/signalr.min.js
  52. /* int data = 0,blob=0,webview=0, groupList=0
  53. {
  54. "evaluationId":"idssss",
  55. "shortCode":"1234567890",
  56. "ownerId":"hbcn/tmdid",
  57. "data":1,
  58. "blob":1,
  59. "webview":1,
  60. "groupList":1
  61. }
  62. */
  63. //如果要访问中心,则需要教师登录联网。
  64. var token = GetAuthTokenInfo();
  65. if (token.scope.Equals(ExamConstant.ScopeTeacher))
  66. {
  67. if (_connectionService.dataCenterIsConnected)
  68. {
  69. Teacher? teacher = _liteDBFactory.GetLiteDatabase().GetCollection<Teacher>().FindOne(x => x.id!.Equals(token.id));
  70. if (teacher != null)
  71. {
  72. string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
  73. var client = _httpClientFactory.CreateClient();
  74. if (client.DefaultRequestHeaders.Contains(Constant._X_Auth_AuthToken))
  75. {
  76. client.DefaultRequestHeaders.Remove(Constant._X_Auth_AuthToken);
  77. }
  78. client.DefaultRequestHeaders.Add(Constant._X_Auth_AuthToken, teacher.x_auth_token);
  79. HttpResponseMessage message = await client.PostAsJsonAsync($"{CenterUrl}/blob/sas-read", new { containerName = $"{json["ownerId"]}" });
  80. string sas = string.Empty;
  81. string url = string.Empty;
  82. string cnt = string.Empty;
  83. if (message.IsSuccessStatusCode)
  84. {
  85. //url sas timeout name
  86. string content = await message.Content.ReadAsStringAsync();
  87. JsonNode? jsonNode = content.ToObject<JsonNode>();
  88. if (jsonNode != null)
  89. {
  90. sas = $"{jsonNode["sas"]}";
  91. cnt = $"{jsonNode["name"]}";
  92. }
  93. }
  94. var httpClient= _httpClientFactory.CreateClient();
  95. if ($"{json["data"]}".Equals("1"))
  96. {
  97. await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/package/evaluation.json");
  98. }
  99. if ($"{json["groupList"]}".Equals("1"))
  100. {
  101. await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/package/grouplist.json");
  102. }
  103. if ($"{json["blob"]}".Equals("1"))
  104. {
  105. await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/paper");
  106. }
  107. if ($"{json["webview"]}".Equals("1"))
  108. {
  109. //await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/evaluation.json");
  110. }
  111. }
  112. }
  113. }
  114. return Ok();
  115. }
  116. [HttpPost("check-short-code")]
  117. [AuthToken("admin", "teacher", "visitor")]
  118. public async Task<IActionResult> CheckShortCode(JsonNode json)
  119. {
  120. string shortCode = $"{json["shortCode"]}";
  121. string evaluationId = $"{json["evaluationId"]}";
  122. string deviceId = $"{json["deviceId"]}";
  123. string centerCode= string.Empty, centerMsg= string.Empty;
  124. Expression<Func<EvaluationClient, bool>> predicate = x => true;
  125. int checkTotal = 0, checkSuccess = 0, checkError = 0, checkWarning = 0;
  126. int msg_status = Constant._Message_status_info;
  127. if (!string.IsNullOrEmpty(shortCode))
  128. {
  129. var codePredicate = ExpressionHelper.Or<EvaluationClient>(
  130. x => !string.IsNullOrWhiteSpace(x.shortCode) && x.shortCode == shortCode,
  131. x => !string.IsNullOrWhiteSpace(x.password) && x.password == shortCode
  132. );
  133. predicate= predicate.And(codePredicate);
  134. }
  135. else {
  136. return Ok(new { code = 400,msg="必须输入开卷码" });
  137. }
  138. if (!string.IsNullOrWhiteSpace(evaluationId))
  139. {
  140. predicate= predicate.And(x => x.id!.Equals(evaluationId));
  141. }
  142. IEnumerable<EvaluationClient>? evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Find(predicate);
  143. EvaluationClient? evaluationLocal = null;
  144. EvaluationClient? evaluationCloud = null;
  145. if (evaluationClients!=null && evaluationClients.Count()>0)
  146. {
  147. evaluationLocal= evaluationClients.First();
  148. }
  149. //如果要访问中心,则需要教师登录联网。
  150. var token = GetAuthTokenInfo();
  151. if (token.scope.Equals(ExamConstant.ScopeTeacher))
  152. {
  153. if (_connectionService.dataCenterIsConnected)
  154. {
  155. Teacher? teacher = _liteDBFactory.GetLiteDatabase().GetCollection<Teacher>().FindOne(x => x.id!.Equals(token.id));
  156. if (teacher != null)
  157. {
  158. string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
  159. var client = _httpClientFactory.CreateClient();
  160. if (client.DefaultRequestHeaders.Contains(Constant._X_Auth_AuthToken))
  161. {
  162. client.DefaultRequestHeaders.Remove(Constant._X_Auth_AuthToken);
  163. }
  164. client.DefaultRequestHeaders.Add(Constant._X_Auth_AuthToken, teacher.x_auth_token);
  165. HttpResponseMessage message = await client.PostAsJsonAsync($"{CenterUrl}/evaluation-sync/find-sync-info", new { shortCode, evaluationId });
  166. if (message.IsSuccessStatusCode)
  167. {
  168. string content = await message.Content.ReadAsStringAsync();
  169. JsonNode? jsonNode = content.ToObject<JsonNode>();
  170. if (jsonNode != null)
  171. {
  172. centerCode = $"{jsonNode["code"]}";
  173. centerMsg = $"{jsonNode["msg"]}";
  174. if ($"{jsonNode["code"]}".Equals("200"))
  175. {
  176. evaluationCloud = jsonNode["evaluation"]?.ToObject<EvaluationClient>();
  177. }
  178. }
  179. else
  180. {
  181. centerCode = "500";
  182. centerMsg = "数据转换异常";
  183. }
  184. }
  185. else
  186. {
  187. centerCode = $"{message.StatusCode}";
  188. centerMsg = "数据中心访问异常";
  189. }
  190. }
  191. else
  192. {
  193. centerCode = $"401";
  194. centerMsg = "当前登录账号未找到";
  195. }
  196. }
  197. else
  198. {
  199. centerCode = $"404";
  200. centerMsg = "云端数据中心未连接";
  201. }
  202. if (centerCode.Equals("200"))
  203. {
  204. msg_status=Constant._Message_status_success;
  205. checkTotal++;
  206. checkSuccess++;
  207. }
  208. else
  209. {
  210. msg_status=Constant._Message_status_warning;
  211. checkTotal++;
  212. checkWarning++;
  213. }
  214. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  215. new MessageContent { dataId=evaluationCloud?.id, dataName=evaluationCloud?.name, messageType=Constant._Message_type_message, status=msg_status, content=$"云端数据检测结果:{centerMsg},状态:{centerCode}" });
  216. }
  217. //数据,文件,页面 0 没有更新,1 有更新
  218. int data = 0,blob=0,webview=0, groupList=0, status=0;
  219. long dataSize = 0, blobSize=0 , webviewSize=0, studentCount=0;
  220. if (evaluationLocal== null && evaluationCloud==null)
  221. {
  222. //线上线下没有数据
  223. status=1;
  224. }
  225. else if (evaluationLocal!=null && evaluationCloud!=null)
  226. {
  227. //线上线下有数据
  228. status = 2;
  229. if ((!string.IsNullOrWhiteSpace(evaluationLocal.blobHash) && !evaluationLocal.blobHash.Equals(evaluationCloud.blobHash))
  230. ||(evaluationLocal.blobTime<evaluationCloud.blobTime)
  231. ||(evaluationLocal.blobCount!= evaluationCloud.blobCount)
  232. ||(evaluationLocal.blobSize!= evaluationCloud.blobSize))
  233. {
  234. blob=1;
  235. blobSize=evaluationCloud.blobSize;
  236. }
  237. if ((evaluationLocal.dataTime<evaluationCloud.dataTime)
  238. ||(evaluationLocal.dataSize!=evaluationCloud.dataSize)
  239. ||(evaluationLocal.paperCount!= evaluationCloud.paperCount)
  240. )
  241. {
  242. data=1;
  243. dataSize=evaluationCloud.dataSize;
  244. }
  245. if ((evaluationLocal.webviewCount!=evaluationCloud.webviewCount)
  246. ||(evaluationLocal.webviewSize!= evaluationCloud.webviewSize)
  247. ||(evaluationLocal.webviewTime!= evaluationCloud.webviewTime)
  248. ||(!string.IsNullOrWhiteSpace(evaluationLocal.webviewPath)&& !evaluationLocal.webviewPath.Equals(evaluationCloud.webviewPath)))
  249. {
  250. webview=1;
  251. webviewSize=evaluationCloud.webviewSize;
  252. }
  253. if ((evaluationLocal.studentCount!= evaluationCloud.studentCount)||(!$"{evaluationLocal.grouplistHash}".Equals(evaluationCloud.grouplistHash)))
  254. {
  255. groupList=1;
  256. studentCount=evaluationCloud.studentCount;
  257. }
  258. }
  259. else if (evaluationLocal!=null && evaluationCloud==null)
  260. {
  261. //线下有数据,线上没有数据,可能没联网。
  262. status = 3;
  263. }
  264. else if (evaluationLocal==null && evaluationCloud!=null)
  265. {
  266. //线下没有数据,线上有数据
  267. evaluationLocal= evaluationCloud;
  268. blob=1;
  269. data=1;
  270. webview=1;
  271. groupList=1;
  272. blobSize=evaluationCloud.blobSize;
  273. dataSize=evaluationCloud.dataSize;
  274. webviewSize=evaluationCloud.webviewSize;
  275. studentCount=evaluationCloud.studentCount;
  276. status = 4;
  277. _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Insert(evaluationLocal);
  278. }
  279. List<string> file_error = new List<string>();
  280. if (evaluationLocal!=null)
  281. {
  282. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  283. new MessageContent {dataId=evaluationLocal.id,dataName=evaluationLocal.name,messageType=Constant._Message_type_message, status=0, content="开始检查评测信息文件.." });
  284. //校验本地文件数据
  285. string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
  286. if (!Directory.Exists(packagePath))
  287. Directory.CreateDirectory(packagePath);
  288. string evaluationPath = Path.Combine(packagePath, evaluationLocal.id!);
  289. // await Task.Delay(DelayMacro);
  290. string path_evaluation = Path.Combine(evaluationPath, "evaluation.json");
  291. if (!System.IO.File.Exists(path_evaluation))
  292. {
  293. file_error.Add("evaluation");
  294. msg_status=Constant._Message_status_error;
  295. checkTotal++;
  296. checkError++;
  297. }
  298. else
  299. {
  300. msg_status=Constant._Message_status_success;
  301. checkTotal++;
  302. checkSuccess++;
  303. }
  304. //数据格式: [消息][信息/错误/警告][15:43]=>[开始检查评测信息文件...]
  305. //数据格式: [检查][成功/失败][15:43]=>[评测数据文件:/wwwroot/package/623a9fe6-5445-0938-ff77-aeb80066ef27/evaluation.json]
  306. //数据格式: [下载][成功/失败][15:43]=>[评测数据文件:/wwwroot/package/623a9fe6-5445-0938-ff77-aeb80066ef27/evaluation.json][1024kb][15ms]
  307. await _signalRExamServerHub.SendMessage(_memoryCache,_logger,deviceId, Constant._Message_grant_type_check_file,
  308. new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status,content=$"评测数据文件:{path_evaluation}" });
  309. //await Task.Delay(DelayMacro);
  310. string path_groupList = Path.Combine(evaluationPath, "groupList.json");
  311. msg_status =Constant._Message_status_info;
  312. if (!System.IO.File.Exists(path_groupList))
  313. {
  314. file_error.Add("groupList");
  315. msg_status=Constant._Message_status_error;
  316. checkTotal++;
  317. checkError++;
  318. }
  319. else
  320. {
  321. msg_status=Constant._Message_status_success;
  322. checkTotal++;
  323. checkSuccess++;
  324. }
  325. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  326. new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content=$"评测名单文件:{path_groupList}" });
  327. //await Task.Delay(DelayMacro);
  328. string path_source = Path.Combine(evaluationPath, "source.json");
  329. msg_status = Constant._Message_status_info;
  330. if (!System.IO.File.Exists(path_source))
  331. {
  332. file_error.Add("source");
  333. msg_status=Constant._Message_status_error;
  334. checkTotal++;
  335. checkError++;
  336. }
  337. else
  338. {
  339. msg_status=Constant._Message_status_success;
  340. checkTotal++;
  341. checkSuccess++;
  342. }
  343. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  344. new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content=$"评测原始数据:{path_source}" });
  345. // await Task.Delay(DelayMacro);
  346. msg_status =Constant._Message_status_info;
  347. try {
  348. string evaluation_str = await System.IO.File.ReadAllTextAsync(path_evaluation);
  349. JsonNode? evaluation_data = evaluation_str.ToObject<JsonNode>();
  350. if (evaluation_data!=null)
  351. {
  352. EvaluationClient? evaluationClient = evaluation_data["evaluationClient"]?.ToObject<EvaluationClient>();
  353. if (evaluationClient!=null)
  354. {
  355. if ((!string.IsNullOrWhiteSpace(evaluationLocal.blobHash) && evaluationLocal.blobHash.Equals(evaluationClient.blobHash))
  356. &&(evaluationLocal.blobTime==evaluationClient.blobTime)
  357. &&(evaluationLocal.blobCount== evaluationClient.blobCount)
  358. &&(evaluationLocal.blobSize== evaluationClient.blobSize)&& (evaluationLocal.dataTime==evaluationClient.dataTime)
  359. &&(evaluationLocal.dataSize==evaluationClient.dataSize)&&(evaluationLocal.webviewCount==evaluationClient.webviewCount)
  360. &&(evaluationLocal.webviewSize== evaluationClient.webviewSize)
  361. &&(evaluationLocal.webviewTime== evaluationClient.webviewTime)
  362. &&(!string.IsNullOrWhiteSpace(evaluationLocal.webviewPath)&& evaluationLocal.webviewPath.Equals(evaluationClient.webviewPath)))
  363. {
  364. msg_status=Constant._Message_status_info;
  365. }
  366. else
  367. {
  368. msg_status=Constant._Message_status_error;
  369. }
  370. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  371. new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="校验本地试卷文件..." });
  372. }
  373. List<EvaluationExam>? evaluationExams = evaluation_data["evaluationExams"]?.ToObject<List<EvaluationExam>>();
  374. if (evaluationExams.IsNotEmpty())
  375. {
  376. string path_papers = Path.Combine(evaluationPath, "papers");
  377. var papers_files = FileHelper.ListAllFiles(path_papers);
  378. foreach (var evaluationExam in evaluationExams!)
  379. {
  380. int paperIndex = 0;
  381. foreach (var paper in evaluationExam.papers)
  382. {
  383. paperIndex++;
  384. List<MessageContent> contents = new List<MessageContent>();
  385. int paper_error_count = 0;
  386. foreach (var blobInfo in paper.blobs)
  387. {
  388. msg_status=Constant._Message_status_info;
  389. if (!string.IsNullOrWhiteSpace(blobInfo.path))
  390. {
  391. var file = papers_files.Find(x => x.Contains(blobInfo.path));
  392. if (file!=null)
  393. {
  394. msg_status=1;
  395. msg_status=Constant._Message_status_success;
  396. }
  397. else {
  398. msg_status=Constant._Message_status_error;
  399. paper_error_count++;
  400. }
  401. }
  402. else {
  403. msg_status=Constant._Message_status_warning; ;
  404. paper_error_count++;
  405. }
  406. contents.Add(new MessageContent {
  407. dataId=evaluationLocal.id,
  408. dataName=evaluationLocal.name,
  409. messageType=Constant._Message_type_check, status=msg_status, content=$"试卷文件信息:{paper.paperName}" });
  410. }
  411. int paper_msg_status = Constant. _Message_status_info;
  412. if (paper_error_count>0)
  413. {
  414. paper_msg_status=Constant._Message_status_error;
  415. }
  416. else {
  417. paper_msg_status=Constant._Message_status_success;
  418. }
  419. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  420. new MessageContent {
  421. dataId=evaluationLocal.id,
  422. dataName=evaluationLocal.name,
  423. messageType=Constant._Message_type_message,
  424. status=paper_msg_status,
  425. content=$"试卷名称:[{paperIndex}]{evaluationExam.examName}-{evaluationExam.subjectName}-{paper.paperName}\r\n文件数量:{paper.blobs.Count()},检测成功数量:{contents.Count(x => x.status==Constant._Message_status_success)},检测异常数量{contents.Count(x => x.status==Constant._Message_status_error)}",
  426. contents=contents
  427. });
  428. }
  429. }
  430. }
  431. }
  432. }
  433. catch (Exception e) {
  434. }
  435. //检查需要更新的项目:
  436. if (data==1)
  437. {
  438. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  439. new MessageContent
  440. {
  441. dataId=evaluationLocal.id,
  442. dataName=evaluationLocal.name,
  443. messageType=Constant._Message_type_message,
  444. status=Constant._Message_status_warning,
  445. content=$"检查到评测数据需要更新。[{dataSize}]"
  446. });
  447. }
  448. if (blob==1)
  449. {
  450. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  451. new MessageContent
  452. {
  453. dataId=evaluationLocal.id,
  454. dataName=evaluationLocal.name,
  455. messageType=Constant._Message_type_message,
  456. status=Constant._Message_status_warning,
  457. content=$"检查到评测试卷需要更新。[{blobSize}]"
  458. });
  459. }
  460. if (webview==1)
  461. {
  462. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  463. new MessageContent
  464. {
  465. dataId=evaluationLocal.id,
  466. dataName=evaluationLocal.name,
  467. messageType=Constant._Message_type_message,
  468. status=Constant._Message_status_warning,
  469. content=$"检查到评测作答页面需要更新。[{webviewSize}]"
  470. });
  471. }
  472. if (groupList==1)
  473. {
  474. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  475. new MessageContent
  476. {
  477. dataId=evaluationLocal.id,
  478. dataName=evaluationLocal.name,
  479. messageType=Constant._Message_type_message,
  480. status=Constant._Message_status_warning,
  481. content=$"检查到评测名单需要更新。[{studentCount}]"
  482. });
  483. }
  484. }
  485. int finalStatus = Constant._Message_status_success;
  486. if (checkWarning>0)
  487. {
  488. finalStatus = Constant._Message_status_warning;
  489. }
  490. if (checkError>0)
  491. {
  492. finalStatus = Constant._Message_status_error;
  493. }
  494. await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
  495. new MessageContent {
  496. dataId=evaluationLocal?.id,
  497. dataName=evaluationLocal?.name,
  498. messageType=Constant._Message_type_message,
  499. status=Constant._Message_status_warning,
  500. content=$"最终检测结果:总数({checkTotal}),成功({checkSuccess}),警告({checkWarning}),异常({checkError})。"
  501. });
  502. return Ok(new {
  503. code = 200,
  504. evaluation = evaluationLocal,
  505. data,
  506. blob,
  507. webview,
  508. dataSize,
  509. blobSize,
  510. webviewSize,
  511. status,
  512. groupList,
  513. studentCount,
  514. checkTotal,
  515. checkSuccess,
  516. checkError,
  517. checkWarning
  518. });
  519. }
  520. /// <summary>
  521. /// 激活考试
  522. /// </summary>
  523. /// <param name="json"></param>
  524. /// <returns></returns>
  525. [HttpPost("activate-evaluation")]
  526. [AuthToken("admin", "teacher", "visitor")]
  527. public IActionResult ActivateEvaluation(JsonNode json)
  528. {
  529. string id = $"{json["id"]}";
  530. string shortCode = $"{json["shortCode"]}";
  531. if (!string.IsNullOrWhiteSpace(id) && !string.IsNullOrWhiteSpace(shortCode))
  532. {
  533. EvaluationClient? evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindOne(x => x.id!.Equals(id) && !string.IsNullOrWhiteSpace(x.shortCode) && x.shortCode.Equals(shortCode));
  534. if (evaluationClient != null)
  535. {
  536. }
  537. }
  538. return Ok();
  539. }
  540. /// <summary>
  541. /// 加载本地的活动列表
  542. /// </summary>
  543. /// <param name="json"></param>
  544. /// <returns></returns>
  545. [HttpPost("list-local-evaluation")]
  546. [AuthToken("admin", "teacher", "visitor")]
  547. public IActionResult ListLocalEvaluation(JsonNode json)
  548. {
  549. IEnumerable<EvaluationClient>? evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindAll().OrderByDescending(x=>x.activate).ThenByDescending(x=>x.stime);
  550. if (evaluationClients != null)
  551. {
  552. var result = evaluationClients.Select(client =>
  553. {
  554. var properties = client.GetType().GetProperties();
  555. var anonymousObject = new Dictionary<string, object?>();
  556. foreach (var property in properties)
  557. {
  558. if (!property.Name.Equals("password") && !property.Name.Equals("shortCode"))
  559. {
  560. anonymousObject[property.Name] = property.GetValue(client);
  561. }
  562. }
  563. return anonymousObject;
  564. });
  565. return Ok(new { code = 200, evaluation = result });
  566. }
  567. else {
  568. return Ok(new { code = 200, evaluation = new Dictionary<string, object?>() });
  569. }
  570. }
  571. }
  572. }