HiScanController.cs 30 KB

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