HiScanController.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IdentityModel.Tokens.Jwt;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Text.Json;
  10. using System.Threading.Tasks;
  11. using TEAMModelOS.Models.Dto;
  12. using TEAMModelOS.SDK.Models;
  13. using TEAMModelOS.SDK;
  14. using TEAMModelOS.SDK.DI;
  15. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  16. using TEAMModelOS.SDK.Extension;
  17. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  18. using TEAMModelOS.Models;
  19. using Microsoft.Extensions.Options;
  20. using TEAMModelOS.SDK.Models.Cosmos;
  21. using Microsoft.AspNetCore.Authorization;
  22. using TEAMModelOS.Filter;
  23. using StackExchange.Redis;
  24. using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
  25. using System.IO;
  26. using System.Dynamic;
  27. using Azure.Storage.Blobs.Models;
  28. using Azure.Storage.Sas;
  29. using Lib.AspNetCore.ServerSentEvents;
  30. using TEAMModelOS.SDK.Models.Cosmos.Common;
  31. using HTEXLib.COMM.Helpers;
  32. namespace TEAMModelOS.Controllers.Core
  33. {
  34. [ProducesResponseType(StatusCodes.Status200OK)]
  35. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  36. //[Authorize(Roles = "HiTool")]
  37. [Route("hiscan")]
  38. [ApiController]
  39. public class HiScanController : ControllerBase
  40. {
  41. private readonly AzureRedisFactory _azureRedis;
  42. private readonly AzureCosmosFactory _azureCosmos;
  43. private readonly SnowflakeId _snowflakeId;
  44. private readonly AzureServiceBusFactory _serviceBus;
  45. private readonly DingDing _dingDing;
  46. private readonly Option _option;
  47. private readonly AzureStorageFactory _azureStorage;
  48. // private readonly ServerSentEventsService _sse;
  49. private readonly CoreAPIHttpService _coreAPIHttpService;
  50. public HiScanController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option,
  51. AzureRedisFactory azureRedis, AzureStorageFactory azureStorage//, ServerSentEventsService sse
  52. )
  53. {
  54. _azureCosmos = azureCosmos;
  55. _serviceBus = serviceBus;
  56. _snowflakeId = snowflakeId;
  57. _dingDing = dingDing;
  58. _option = option?.Value;
  59. _azureRedis = azureRedis;
  60. _coreAPIHttpService = coreAPIHttpService;
  61. _azureStorage = azureStorage;
  62. //_sse = sse;
  63. }
  64. ///<summary>
  65. ///查询教师的阅卷任务列表
  66. /// </summary>
  67. /// <data>
  68. /// ! "code":"tmdid"
  69. /// </data>
  70. /// <param name="request"></param>
  71. /// <returns></returns>
  72. [ProducesDefaultResponseType]
  73. [HttpPost("get-schoolinfo")]
  74. // [AuthToken(Roles = "teacher,admin")]
  75. public async Task<IActionResult> GetSchoolinfo(JsonElement request)
  76. {
  77. List<dynamic> schools = new List<dynamic>();
  78. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  79. var client = _azureCosmos.GetCosmosClient();
  80. try
  81. {
  82. Teacher response = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>($"{id}", new PartitionKey("Base"));
  83. string name = response.name;
  84. string picture = response.picture;
  85. foreach (var obj in response.schools)
  86. {
  87. string statusNow = obj.status;
  88. //正式加入才会有
  89. if (statusNow.Equals("join"))
  90. {
  91. try
  92. {
  93. //dynamic schoolExtobj = new ExpandoObject();
  94. School schoolJson = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{obj.schoolId}", new PartitionKey("Base"));
  95. var schoolId = obj.schoolId;
  96. var schoolName = schoolJson.name;
  97. var schoolPicture = schoolJson.picture;
  98. //检查学校购买的模组是否包含阅卷模组,暂不检查
  99. //int count = 0;
  100. //string sql = $" SELECT value(count(product)) FROM c join product in c.service.product where c.id ='{schoolId}' and c.pk='Product' and product.prodCode='YMPCVCIM' ";
  101. //await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<int>(sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Product") }))
  102. //{
  103. // count = item;
  104. //}
  105. //if (count > 0)
  106. //{
  107. // schools.Add(new { name = $"{schoolName}", picture = $"{schoolPicture}", id = $"{schoolId}" });
  108. //}
  109. schools.Add(new { name = $"{schoolName}", picture = $"{schoolPicture}", id = $"{schoolId}" });
  110. }
  111. catch { continue; }
  112. }
  113. }
  114. var (tblob_uri, tblob_sas) = _azureStorage.GetBlobContainerSAS($"{id}", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);
  115. return Ok(new { schools, teacher = new { name, picture, id, bloburl = tblob_uri, blobsas = tblob_sas } });
  116. }
  117. catch (CosmosException ex) when (ex.Status == 404)
  118. {
  119. return Ok(new {error= 1,msg="账号未再IES5使用"});
  120. }
  121. catch (Exception ex) {
  122. return BadRequest();
  123. }
  124. }
  125. ///<summary>
  126. ///查询教师的阅卷任务列表
  127. /// </summary>
  128. /// <data>
  129. /// ! "code":"tmdid"
  130. /// </data>
  131. /// <param name="request"></param>
  132. /// <returns></returns>
  133. [ProducesDefaultResponseType]
  134. [HttpPost("get-examinfo")]
  135. // [AuthToken(Roles = "teacher,admin")]
  136. public async Task<IActionResult> GetExaminfo(JsonElement request)
  137. {
  138. try
  139. {
  140. List<SheetConfig> configs = new List<SheetConfig>();
  141. HashSet<string> classesSet = new HashSet<string>();
  142. List<ExamRcd> sexamRcds = new List<ExamRcd>();
  143. List<ExamRcd> psexamRcds = new List<ExamRcd>();
  144. List<ExamRcd> ppexamRcds = new List<ExamRcd>();
  145. List<ExamRcd> pexamRcds = new List<ExamRcd>();
  146. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  147. if (!request.TryGetProperty("schoolId", out JsonElement _schoolId)) return BadRequest();
  148. var client = _azureCosmos.GetCosmosClient();
  149. School school = null;
  150. try
  151. {
  152. school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{_schoolId}", new PartitionKey("Base"));
  153. }
  154. catch (CosmosException ex)
  155. {
  156. if (ex.Status == 404)
  157. {
  158. school = null;
  159. }
  160. }
  161. var response = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync($"{id}", new PartitionKey("Base"));
  162. if (school != null)
  163. {
  164. //检查学校购买的模组是否包含阅卷模组
  165. int count = 0;
  166. string sql = $" SELECT value(count(product)) FROM c join product in c.service.product where c.id ='{_schoolId}' and c.pk='Product' and product.prodCode='YMPCVCIM' ";
  167. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<int>(sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Product") }))
  168. {
  169. count = item;
  170. }
  171. if (count > 0)
  172. {
  173. //获取学校线下阅卷评测
  174. sexamRcds = await GetExam("school", $"{_schoolId}", $"{_schoolId}", client, configs, classesSet);
  175. }
  176. if (response.Status == 200)
  177. {
  178. //获取scope=school
  179. psexamRcds = await GetExam("school", $"{_schoolId}", $"{id}", client, configs, classesSet);
  180. if (psexamRcds.IsNotEmpty())
  181. {
  182. pexamRcds.AddRange(psexamRcds);
  183. }
  184. }
  185. }
  186. if (response.Status == 200)
  187. {
  188. //获取scope=private
  189. ppexamRcds = await GetExam("private", null, $"{id}", client, configs, classesSet);
  190. if (ppexamRcds.IsNotEmpty())
  191. {
  192. pexamRcds.AddRange(ppexamRcds);
  193. }
  194. }
  195. (List<RMember> tmdIds, List<RGroupList> classInfo) = await GroupListService.GetStutmdidListids(_coreAPIHttpService, client, _dingDing, classesSet.ToList(), $"{_schoolId}");
  196. /*var addStudentsCls = tmdIds.FindAll(x => x.type == 2);
  197. var addTmdidsCls = tmdIds.FindAll(x => x.type == 1);*/
  198. List<SheetConfig> configsN = new List<SheetConfig>();
  199. foreach (var config in configs)
  200. {
  201. if (config.scope.Equals("school"))
  202. {
  203. try
  204. {
  205. SheetConfig con = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SheetConfig>(config.id, new PartitionKey(config.code));
  206. configsN.Add(con);
  207. }
  208. catch (CosmosException ex) { }
  209. }
  210. else
  211. {
  212. try
  213. {
  214. SheetConfig con = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<SheetConfig>(config.id, new PartitionKey(config.code));
  215. configsN.Add(con);
  216. }
  217. catch (CosmosException ex) { }
  218. }
  219. }
  220. //处理学校发布的评测
  221. if (sexamRcds.IsNotEmpty())
  222. {
  223. sexamRcds.SelectMany(y => y.classes).ToList().ForEach(z => {
  224. var a = classInfo.Where(m => m.id.Equals(z.id)).FirstOrDefault();
  225. if (a != null)
  226. {
  227. z.name = a.name;
  228. z.members = a.members;
  229. //z.tmdInfos = a.members.FindAll(x => x.type == 1);
  230. }
  231. });
  232. sexamRcds.SelectMany(y => y.papers).ToList().ForEach(z => {
  233. if (z.sheet != null)
  234. {
  235. var a = configsN.Where(m => m.id == z.sheet.id).FirstOrDefault();
  236. if (a != null)
  237. {
  238. z.sheet = a;
  239. }
  240. }
  241. });
  242. }
  243. //处理教师发布的个人班级评测和学校班级评测
  244. if (pexamRcds.IsNotEmpty())
  245. {
  246. pexamRcds.SelectMany(y => y.classes).ToList().ForEach(z => {
  247. var a = classInfo.Where(m => m.id == z.id).FirstOrDefault();
  248. if (a != null)
  249. {
  250. z.name = a.name;
  251. z.members = a.members;
  252. // z.members = a.tmdInfos;
  253. }
  254. });
  255. pexamRcds.SelectMany(y => y.papers).ToList().ForEach(z => {
  256. if (z.sheet != null)
  257. {
  258. var a = configsN.Where(m => m.id == z.sheet.id).FirstOrDefault();
  259. if (a != null)
  260. {
  261. z.sheet = a;
  262. }
  263. }
  264. });
  265. }
  266. string teacherBlobSas = null;
  267. string teacherBlobUrl = null;
  268. string schoolBlobSas = null;
  269. string schoolBlobUrl = null;
  270. if (ppexamRcds.IsNotEmpty())
  271. {
  272. var (tblob_uri, tblob_sas) = _azureStorage.GetBlobContainerSAS($"{id}", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
  273. teacherBlobUrl = tblob_uri;
  274. teacherBlobSas = tblob_sas;
  275. }
  276. if (psexamRcds.IsNotEmpty() || sexamRcds.IsNotEmpty())
  277. {
  278. var (sblob_uri, sblob_sas) = _azureStorage.GetBlobContainerSAS(school.id, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Write);
  279. schoolBlobUrl = sblob_uri;
  280. schoolBlobSas = sblob_sas;
  281. }
  282. return Ok(new { teacherBlobSas, teacherBlobUrl, schoolBlobSas, schoolBlobUrl, school = sexamRcds.IsNotEmpty() ? sexamRcds : null, teacher = pexamRcds.IsNotEmpty() ? pexamRcds : null });
  283. }
  284. catch (Exception ex)
  285. {
  286. await _dingDing.SendBotMsg($"IES5,{_option.Location},hiscan/verify-qrcode()\n{ex.Message}{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  287. return BadRequest();
  288. }
  289. }
  290. private async Task<List<ExamRcd>> GetExam(string scope, string school, string code, CosmosClient client, List<SheetConfig> sheet, HashSet<string> classesSet)
  291. {
  292. List<ExamRcd> examRcds = new List<ExamRcd>();
  293. int i = 1;
  294. StringBuilder sql = new StringBuilder($"SELECT * FROM c where (c.status<>404 or IS_DEFINED(c.status) = false ) and (c.progress='going' or c.progress='finish') and c.scope='{scope}' ");
  295. if (!string.IsNullOrEmpty(school))
  296. {
  297. sql.Append($" and c.school='{school}' ");
  298. }
  299. //await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<Correct>(queryText: "SELECT * FROM c where c.source='2' and c.progress='going' order by c.createTime ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Correct-{code}") }))
  300. await foreach (var exam in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamInfo>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{code}") }))
  301. {
  302. List<RGroupList> classes = new List<RGroupList>();
  303. if (exam.classes.IsNotEmpty())
  304. {
  305. exam.classes.ForEach(x => { classes.Add(new RGroupList { id = x }); classesSet.Add(x); });
  306. }
  307. if (exam.stuLists.IsNotEmpty())
  308. {
  309. exam.stuLists.ForEach(x => { classes.Add(new RGroupList { id = x }); classesSet.Add(x); });
  310. }
  311. List<PaperRcd> dys = new List<PaperRcd>();
  312. foreach (var pap in exam.papers)
  313. {
  314. if (!string.IsNullOrEmpty(pap.sheet))
  315. {
  316. if (exam.scope.Equals("school"))
  317. {
  318. SheetConfig config = new SheetConfig { id = pap.sheet, no = pap.sheetNo, scope = exam.scope, mode = pap.mode, code = $"SheetConfig-{exam.school}" };
  319. dys.Add(new PaperRcd { name = pap.name, answers = pap.answers, point = pap.point, sheet = config });
  320. sheet.Add(config);
  321. }
  322. else
  323. {
  324. SheetConfig config = new SheetConfig { id = pap.sheet, no = pap.sheetNo, scope = exam.scope,mode=pap.mode , code = $"SheetConfig-{code}" };
  325. dys.Add(new PaperRcd { name = pap.name, answers = pap.answers, point = pap.point, sheet = config });
  326. sheet.Add(config);
  327. }
  328. }
  329. else
  330. {
  331. dys.Add(new PaperRcd { name = pap.name, answers = pap.answers, point = pap.point, sheet = null });
  332. }
  333. }
  334. examRcds.Add(new ExamRcd
  335. {
  336. id = exam.id,
  337. name = exam.name,
  338. startTime = exam.startTime,
  339. endTime = exam.endTime,
  340. period = exam.period,
  341. grades = exam.grades,
  342. subjects = exam.subjects,
  343. papers = dys,
  344. classes = classes,
  345. scope = exam.scope
  346. });
  347. }
  348. return examRcds;
  349. }
  350. ///<summary>
  351. ///查询教师的阅卷任务列表
  352. /// </summary>
  353. /// <data>
  354. /// ! "code":"tmdid"
  355. /// </data>
  356. /// <param name="request"></param>
  357. /// <returns></returns>
  358. [ProducesDefaultResponseType]
  359. [HttpPost("get-exam-by-sheet")]
  360. // [AuthToken(Roles = "teacher,admin")]
  361. public async Task<IActionResult> GetExamBySheet(JsonElement request)
  362. {
  363. try
  364. {
  365. HashSet<string> classesSet = new HashSet<string>();
  366. ExamData examData = null;
  367. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  368. if (!request.TryGetProperty("schoolId", out JsonElement _schoolId)) return BadRequest();
  369. if (!request.TryGetProperty("sheetNo", out JsonElement _sheetNo)) return BadRequest();
  370. if (!request.TryGetProperty("owner", out JsonElement _owner)) return BadRequest();
  371. var client = _azureCosmos.GetCosmosClient();
  372. School school = null;
  373. school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{_schoolId}", new PartitionKey("Base"));
  374. if (school == null) return BadRequest();
  375. if ($"{_owner}".Equals("school", StringComparison.OrdinalIgnoreCase))
  376. {
  377. examData = await GetExamBySheet($"{_owner}", $"{_schoolId}", $"{_schoolId}", client, classesSet, $"{_sheetNo}");
  378. }
  379. else {
  380. var response = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync($"{id}", new PartitionKey("Base"));
  381. examData = await GetExamBySheet($"{_owner}", null, $"{id}", client, classesSet, $"{_sheetNo}");
  382. if (examData == null && string.IsNullOrEmpty($"{_schoolId}")) {
  383. examData = await GetExamBySheet($"{_owner}", $"{_schoolId}", $"{id}", client, classesSet, $"{_sheetNo}");
  384. }
  385. }
  386. (List<RMember> tmdIds, List<RGroupList> classInfo) = await GroupListService.GetStutmdidListids(_coreAPIHttpService, client, _dingDing, classesSet.ToList(), $"{_schoolId}");
  387. List<SheetConfig> configsN = new List<SheetConfig>();
  388. if (examData.sheet != null) {
  389. if (examData.sheet.scope.Equals("school"))
  390. {
  391. Azure.Response azure = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(examData.sheet.id, new PartitionKey(examData.sheet.code));
  392. if (azure.Status == 200 && azure.Content!=null )
  393. {
  394. SheetConfig config = JsonDocument.Parse(azure.Content).RootElement.Deserialize<SheetConfig>();
  395. if (config != null)
  396. {
  397. configsN.Add(config);
  398. }
  399. }
  400. }
  401. else
  402. {
  403. Azure.Response azure = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync(examData.sheet.id, new PartitionKey(examData.sheet.code));
  404. if (azure.Status == 200 && azure.Content != null)
  405. {
  406. SheetConfig config = JsonDocument.Parse(azure.Content).RootElement.Deserialize<SheetConfig>();
  407. if (config != null)
  408. {
  409. configsN.Add(config);
  410. }
  411. }
  412. }
  413. }
  414. if (examData != null)
  415. {
  416. examData.classes.ForEach(z => {
  417. var a = classInfo.Where(m => m.id.Equals(z.id)).FirstOrDefault();
  418. if (a != null)
  419. {
  420. z.no=a.no;
  421. z.creatorId=a.creatorId;
  422. z.year=a.year;
  423. z.tcount=a.tcount;
  424. z.scount=a.scount;
  425. z.periodId = a.periodId;
  426. z.scope = a.scope;
  427. z.school = a.school;
  428. z.code = a.code;
  429. z.name = a.name;
  430. z.members = a.members;
  431. //z.tmdInfos = a.tmdInfos;
  432. }
  433. });
  434. if (examData.sheet!=null) {
  435. var a = configsN.Where(m => m.id == examData.sheet.id && m.scope.Equals(examData.sheet.scope)).FirstOrDefault();
  436. if (a != null)
  437. {
  438. examData.sheet = a;
  439. }
  440. }
  441. }
  442. string blobSas = null;
  443. string blobUrl = null;
  444. ExamData exam = null;
  445. if (examData.sheet.scope.Equals("school", StringComparison.OrdinalIgnoreCase))
  446. {
  447. if (examData != null)
  448. {
  449. var (sblob_uri, sblob_sas) = _azureStorage.GetBlobContainerSAS(school.id, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Write);
  450. blobUrl = sblob_uri;
  451. blobSas = sblob_sas;
  452. exam = examData;
  453. }
  454. }
  455. else {
  456. if (examData != null)
  457. {
  458. var (tblob_uri, tblob_sas) = _azureStorage.GetBlobContainerSAS($"{id}", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
  459. blobUrl = tblob_uri;
  460. blobSas = tblob_sas;
  461. exam = examData;
  462. }
  463. }
  464. return Ok(new { blobUrl, blobSas, exam});
  465. }
  466. catch (Exception ex)
  467. {
  468. await _dingDing.SendBotMsg($"IES5,{_option.Location},get-exam-by-sheet\n{ex.Message}{ex.StackTrace}{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  469. return BadRequest();
  470. }
  471. }
  472. private async Task<ExamData> GetExamBySheet(string owner, string school, string code, CosmosClient client,HashSet<string> classesSet, string sheetNo)
  473. {
  474. ExamData examRcds = null;
  475. StringBuilder sql = new StringBuilder($"SELECT value(c) FROM c join papers in c.papers where (c.status<>404 or IS_DEFINED(c.status) = false ) and c.owner='{owner}' and papers.sheetNo='{sheetNo}' ");
  476. if (!string.IsNullOrEmpty(school))
  477. {
  478. sql.Append($" and c.school='{school}' ");
  479. }
  480. //await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<Correct>(queryText: "SELECT * FROM c where c.source='2' and c.progress='going' order by c.createTime ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Correct-{code}") }))
  481. await foreach (var exam in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamInfo>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{code}") }))
  482. {
  483. List<RGroupList> classes = new List<RGroupList>();
  484. if (exam.classes.IsNotEmpty())
  485. {
  486. exam.classes.ForEach(x => { classes.Add(new RGroupList { id = x }); classesSet.Add(x); });
  487. }
  488. if (exam.stuLists.IsNotEmpty())
  489. {
  490. exam.stuLists.ForEach(x => { classes.Add(new RGroupList { id = x }); classesSet.Add(x); });
  491. }
  492. PaperRcdData paper = null;
  493. ExamSubjectData subjectData = null;
  494. PaperSimple pap = exam.papers.Find(x => x.sheetNo == sheetNo);
  495. if (pap != null) {
  496. int index = exam.papers.FindIndex(x => x.sheetNo == sheetNo);
  497. ExamSubject subject = exam.subjects[index];
  498. subjectData = new ExamSubjectData { id = subject.id, name = subject.name };
  499. }
  500. SheetConfig config = null;
  501. if (!string.IsNullOrEmpty(pap.sheet))
  502. {
  503. if (exam.scope.Equals("school"))
  504. {
  505. config = new SheetConfig { id = pap.sheet, scope = exam.scope, mode = pap.mode, no = pap.sheetNo, code = $"SheetConfig-{exam.school}" };
  506. paper = new PaperRcdData { name = pap.name, answers = pap.answers, point = pap.point };
  507. }
  508. else
  509. {
  510. config = new SheetConfig { id = pap.sheet, scope = exam.scope, mode = pap.mode,no=pap.sheetNo, code = $"SheetConfig-{code}" };
  511. paper = new PaperRcdData { name = pap.name, answers = pap.answers, point = pap.point };
  512. }
  513. }
  514. else
  515. {
  516. paper = new PaperRcdData { name = pap.name, answers = pap.answers, point = pap.point, };
  517. }
  518. examRcds = new ExamData
  519. {
  520. code = exam.code.Replace("Exam-", ""),
  521. id = exam.id,
  522. name = exam.name,
  523. startTime = exam.startTime,
  524. endTime = exam.endTime,
  525. period = exam.period,
  526. grades = exam.grades,
  527. subject = subjectData,
  528. paper = paper,
  529. classes = classes,
  530. scope = exam.scope,
  531. sheet = config
  532. };
  533. }
  534. return examRcds;
  535. }
  536. }
  537. public record PaperRcdData
  538. {
  539. public string name { get; set; }
  540. public List<List<string>> answers { get; set; } = new List<List<string>>();
  541. public List<double> point { get; set; } = new List<double>();
  542. }
  543. public record PaperRcd
  544. {
  545. public string name { get; set; }
  546. public List<List<string>> answers { get; set; } = new List<List<string>>();
  547. public List<double> point { get; set; } = new List<double>();
  548. public SheetConfig sheet { get; set; }
  549. }
  550. public class ExamSubjectData
  551. {
  552. public string id { get; set; }
  553. public string name { get; set; }
  554. }
  555. public record ExamData
  556. {
  557. public string code { get; set; }
  558. public SheetConfig sheet { get; set; }
  559. public string id { get; set; }
  560. public string name { get; set; }
  561. public long startTime { get; set; }
  562. public long endTime { get; set; }
  563. public PeriodSimple period { get; set; }
  564. public List<Grade> grades { get; set; }
  565. public ExamSubjectData subject { get; set; }
  566. public PaperRcdData paper { get; set; }
  567. public List<RGroupList> classes { get; set; }
  568. public string scope { get; set; }
  569. }
  570. public record ExamRcd
  571. {
  572. public string id { get; set; }
  573. public string name { get; set; }
  574. public long startTime { get; set; }
  575. public long endTime { get; set; }
  576. public PeriodSimple period { get; set; }
  577. public List<Grade> grades { get; set; }
  578. public List<ExamSubject> subjects { get; set; }
  579. public List<PaperRcd> papers { get; set; }
  580. public List<RGroupList> classes { get; set; }
  581. public string scope { get; set; }
  582. }
  583. }