ArtController.cs 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. using Azure.Core;
  2. using Azure.Cosmos;
  3. using DinkToPdf.Contracts;
  4. using DocumentFormat.OpenXml.Office2010.Excel;
  5. using DocumentFormat.OpenXml.Office2013.Excel;
  6. using DocumentFormat.OpenXml.Office2016.Excel;
  7. using DocumentFormat.OpenXml.Spreadsheet;
  8. using DocumentFormat.OpenXml.Wordprocessing;
  9. using MathNet.Numerics.RootFinding;
  10. using Microsoft.AspNetCore.Authorization;
  11. using Microsoft.AspNetCore.Http;
  12. using Microsoft.AspNetCore.Mvc;
  13. using Microsoft.Extensions.Configuration;
  14. using Microsoft.Extensions.Options;
  15. using NUnit.Framework;
  16. using OpenXmlPowerTools;
  17. using System;
  18. using System.Collections.Generic;
  19. using System.Linq;
  20. using System.Net;
  21. using System.Reflection;
  22. using System.Text;
  23. using System.Text.Json;
  24. using System.Threading.Tasks;
  25. using System.Xml.Linq;
  26. using TEAMModelOS.Filter;
  27. using TEAMModelOS.Models;
  28. using TEAMModelOS.SDK;
  29. using TEAMModelOS.SDK.DI;
  30. using TEAMModelOS.SDK.Extension;
  31. using TEAMModelOS.SDK.Models;
  32. using TEAMModelOS.SDK.Models.Cosmos.Common;
  33. using Survey = TEAMModelOS.SDK.Models.Survey;
  34. namespace TEAMModelOS.Controllers.Common
  35. {
  36. [ProducesResponseType(StatusCodes.Status200OK)]
  37. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  38. [Route("common/art")]
  39. [ApiController]
  40. public class ArtController : ControllerBase
  41. {
  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 AzureRedisFactory _azureRedis;
  49. private readonly IConverter _converter;
  50. public IConfiguration _configuration { get; set; }
  51. private readonly CoreAPIHttpService _coreAPIHttpService;
  52. public ArtController(IConverter converter, CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
  53. IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, IConfiguration configuration)
  54. {
  55. _coreAPIHttpService = coreAPIHttpService;
  56. _azureCosmos = azureCosmos;
  57. _serviceBus = serviceBus;
  58. _snowflakeId = snowflakeId;
  59. _dingDing = dingDing;
  60. _option = option?.Value;
  61. _azureStorage = azureStorage;
  62. _azureRedis = azureRedis;
  63. _configuration = configuration;
  64. _converter = converter;
  65. }
  66. /// <summary>
  67. /// 保存艺术评价信息
  68. /// </summary>
  69. /// <param name="request"></param>
  70. /// <returns></returns>
  71. [ProducesDefaultResponseType]
  72. [AuthToken(Roles = "teacher,admin")]
  73. [HttpPost("save")]
  74. [Authorize(Roles = "IES")]
  75. public async Task<IActionResult> Save(JsonElement request)
  76. {
  77. try
  78. {
  79. if (!request.TryGetProperty("art", out JsonElement art)) return BadRequest();
  80. var client = _azureCosmos.GetCosmosClient();
  81. ArtEvaluation ae = art.ToObject<ArtEvaluation>();
  82. bool flag = false;
  83. ArtMusic music = new();
  84. if (request.TryGetProperty("ArtMusic", out JsonElement am))
  85. {
  86. music = am.ToObject<ArtMusic>();
  87. music.ttl = -1;
  88. music.code = "ArtMusic";
  89. flag = true;
  90. };
  91. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  92. string code = ae.school;
  93. ae.ttl = -1;
  94. ae.progress = "going";
  95. ae.creatorId = userid;
  96. if (!ae.owner.Equals("area"))
  97. {
  98. ae.owner = "school";
  99. ae.code = "Art-" + code;
  100. ae.scope = "school";
  101. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  102. ae.createTime = now;
  103. ae.publish = 0;
  104. }
  105. if (string.IsNullOrEmpty(ae.id))
  106. {
  107. ae.id = Guid.NewGuid().ToString();
  108. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(ae, new PartitionKey($"{ae.code}"));
  109. if (flag)
  110. {
  111. music.id = ae.id;
  112. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(music, new PartitionKey("ArtMusic"));
  113. }
  114. }
  115. else
  116. {
  117. if (flag)
  118. {
  119. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(music, music.id, new PartitionKey("ArtMusic"));
  120. }
  121. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(ae, ae.id, new PartitionKey($"{ae.code}"));
  122. }
  123. return Ok(new { ae });
  124. }
  125. catch (Exception ex)
  126. {
  127. await _dingDing.SendBotMsg($"OS,{_option.Location},art/save()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  128. return Ok(new { code = 500, msg = ex.Message });
  129. }
  130. }
  131. [ProducesDefaultResponseType]
  132. [AuthToken(Roles = "teacher,admin,student")]
  133. [HttpPost("update-state")]
  134. [Authorize(Roles = "IES")]
  135. public async Task<IActionResult> UpdateState(JsonElement request)
  136. {
  137. if (!request.TryGetProperty("isAnswer", out JsonElement isAnswer)) return BadRequest();
  138. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  139. var client = _azureCosmos.GetCosmosClient();
  140. try
  141. {
  142. ArtMusic music = new();
  143. var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.GetString(), new PartitionKey("ArtMusic"));
  144. if (response.Status == 200)
  145. {
  146. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  147. music = json.ToObject<ArtMusic>();
  148. music.isAnswer = isAnswer.GetInt32();
  149. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(music, music.id, new PartitionKey($"{music.code}"));
  150. }
  151. return Ok(music);
  152. }
  153. catch (Exception e)
  154. {
  155. return BadRequest(new { msg = e.Message });
  156. }
  157. }
  158. [ProducesDefaultResponseType]
  159. [AuthToken(Roles = "teacher,admin,student")]
  160. [HttpPost("upload")]
  161. [Authorize(Roles = "IES")]
  162. public async Task<IActionResult> Upload(ArtRecord request)
  163. {
  164. try
  165. {
  166. var client = _azureCosmos.GetCosmosClient();
  167. var (userid, name, picture, school) = HttpContext.GetAuthTokenInfo();
  168. HttpContext.Items.TryGetValue("Scope", out object scope);
  169. int userType = $"{scope}".Equals(Constant.ScopeStudent) ? 2 : 1;
  170. request.school = school;
  171. request.stuId = userid;
  172. request.code = "ArtRecord";
  173. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  174. request.createTime = now;
  175. ArtRecord record;
  176. StudentArtResult artResult;
  177. ArtEvaluation art;
  178. List<string> classIds = new();
  179. List<GroupListGrp> groups = await GroupListService.GetMemberInGroupList(_coreAPIHttpService, client, _dingDing, userid, userType, school, new List<string> { "class", "teach" });
  180. foreach (var grp in groups)
  181. {
  182. classIds.Add(grp.id);
  183. }
  184. if (string.IsNullOrEmpty(request.id))
  185. {
  186. request.id = Guid.NewGuid().ToString();
  187. record = await client.GetContainer("TEAMModelOS", "Student").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  188. }
  189. else
  190. {
  191. record = await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync(request, request.id, new PartitionKey($"{request.code}"));
  192. }
  193. string rId = string.Format("{0}{1}{2}", request.school, "-", userid);
  194. //首先根据大ID获取整个活动得内容
  195. var aresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(request.artId, new PartitionKey($"Art-{school}"));
  196. if (aresponse.Status == 200)
  197. {
  198. using var json = await JsonDocument.ParseAsync(aresponse.ContentStream);
  199. art = json.ToObject<ArtEvaluation>();
  200. var response = await client.GetContainer("TEAMModelOS", "Student").ReadItemStreamAsync(rId, new PartitionKey($"ArtResult-{request.artId}"));
  201. if (response.Status == 200)
  202. {
  203. using var json_1 = await JsonDocument.ParseAsync(response.ContentStream);
  204. artResult = json_1.ToObject<StudentArtResult>();
  205. List<Attachment> files = new();
  206. files = request.attachments;
  207. //bool flage = artResult.results.Exists(a => a.taskId == request.acId);
  208. artResult.results.ForEach(a =>
  209. {
  210. if (a.taskId == request.acId)
  211. {
  212. a.files = files;
  213. }
  214. });
  215. await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync(artResult, artResult.id, new PartitionKey($"{artResult.code}"));
  216. }
  217. else
  218. {
  219. artResult = new StudentArtResult
  220. {
  221. id = rId,
  222. pk = "ArtResult",
  223. code = $"ArtResult-{request.artId}",
  224. studentId = userid,
  225. picture = picture,
  226. studentName = name,
  227. school = school,
  228. userType = userType,
  229. artId = request.artId,
  230. classIds = classIds,
  231. };
  232. foreach (var qIds in art.settings)
  233. {
  234. foreach (var task in qIds.task)
  235. {
  236. ArtQuotaResult quotaResult = new()
  237. {
  238. quotaId = qIds.id,
  239. quotaName = qIds.quotaname,
  240. quotaType = (int)task.type,
  241. subjectId = task.subject,
  242. taskId = task.acId
  243. };
  244. if (!string.IsNullOrEmpty(quotaResult.taskId))
  245. {
  246. if (quotaResult.taskId.Equals(request.acId))
  247. {
  248. quotaResult.files = request.attachments;
  249. }
  250. }
  251. artResult.results.Add(quotaResult);
  252. }
  253. }
  254. await client.GetContainer("TEAMModelOS", "Student").CreateItemAsync(artResult, new PartitionKey($"{artResult.code}"));
  255. }
  256. }
  257. return Ok(new { record, code = 200 });
  258. }
  259. catch (Exception ex)
  260. {
  261. await _dingDing.SendBotMsg($"OS,{_option.Location},art/upload()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  262. return Ok(new { code = 500, msg = ex.Message });
  263. }
  264. }
  265. [ProducesDefaultResponseType]
  266. [AuthToken(Roles = "teacher,admin,student")]
  267. [HttpPost("upload-all")]
  268. [Authorize(Roles = "IES")]
  269. public async Task<IActionResult> UploadAll(JsonElement element)
  270. {
  271. try
  272. {
  273. var client = _azureCosmos.GetCosmosClient();
  274. var (_, _, _, school) = HttpContext.GetAuthTokenInfo();
  275. if (!element.TryGetProperty("artId", out JsonElement artId)) return BadRequest();
  276. if (!element.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  277. if (!element.TryGetProperty("quotaId", out JsonElement quotaId)) return BadRequest();
  278. if (!element.TryGetProperty("acId", out JsonElement acId)) return BadRequest();
  279. if (!element.TryGetProperty("subject", out JsonElement subject)) return BadRequest();
  280. if (!element.TryGetProperty("stus", out JsonElement stus)) return BadRequest();
  281. //HttpContext.Items.TryGetValue("Scope", out object scope);
  282. //int userType = $"{scope}".Equals(Constant.ScopeStudent) ? 2 : 1;
  283. List<stuFiles> stuFiles = stus.ToObject<List<stuFiles>>();
  284. List<string> value = new List<string>();
  285. await foreach (var s in stuTask(stuFiles, client, school, artId.GetString(), classId.GetString(), quotaId.GetString(), acId.GetString(), subject.GetString()))
  286. {
  287. if (s.code == 1)
  288. {
  289. value.Add(s.value);
  290. }
  291. }
  292. if (value.Count > 0)
  293. {
  294. return Ok(new { code = 1, msg = "学生ID导入异常", value = value });
  295. }
  296. else
  297. {
  298. return Ok(new { code = 0 });
  299. }
  300. }
  301. catch (Exception ex)
  302. {
  303. await _dingDing.SendBotMsg($"OS,{_option.Location},art/uploadAll()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  304. return Ok(new { code = 500, msg = ex.Message });
  305. }
  306. }
  307. private async IAsyncEnumerable<(int code, string value)> stuTask(List<stuFiles> stuFiles, CosmosClient client, string school, string artId, string classId, string quotaId, string acId, string subject)
  308. {
  309. string queryScore = $" select c.id from c where c.artId ='{artId}' and c.quotaId = '{quotaId}' and c.acId = '{acId}' and c.subject = '{subject}'";
  310. List<string> ids = new();
  311. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryStreamIterator
  312. (queryText: queryScore, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("ArtRecord") }))
  313. {
  314. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  315. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  316. {
  317. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  318. {
  319. if (obj.TryGetProperty("id", out JsonElement subScore))
  320. {
  321. string sId = obj.GetProperty("id").GetString();
  322. ids.Add(sId);
  323. }
  324. }
  325. }
  326. }
  327. await client.GetContainer(Constant.TEAMModelOS, "Student").DeleteItemsAsync<ArtRecord>(ids, "ArtRecord");
  328. // await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, school, new List<string> { $"art/{artId}" });
  329. foreach (var request in stuFiles)
  330. {
  331. string value = "";
  332. int code = 0;
  333. try
  334. {
  335. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  336. ArtRecord record = new()
  337. {
  338. school = school,
  339. stuId = request.stuId,
  340. artId = artId,
  341. classId = classId,
  342. quotaId = quotaId,
  343. acId = acId,
  344. subject = subject,
  345. createTime = now,
  346. code = "ArtRecord",
  347. attachments = request.attachments
  348. };
  349. StudentArtResult artResult;
  350. ArtEvaluation art;
  351. List<string> classIds = new();
  352. List<GroupListGrp> groups = await GroupListService.GetMemberInGroupList(_coreAPIHttpService, client, _dingDing, request.stuId, request.userType, school, new List<string> { "class", "teach" });
  353. foreach (var grp in groups)
  354. {
  355. classIds.Add(grp.id);
  356. }
  357. if (string.IsNullOrEmpty(record.id))
  358. {
  359. record.id = Guid.NewGuid().ToString();
  360. record = await client.GetContainer("TEAMModelOS", "Student").CreateItemAsync(record, new PartitionKey($"{record.code}"));
  361. }
  362. else
  363. {
  364. record = await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync(record, record.id, new PartitionKey($"{record.code}"));
  365. }
  366. string rId = string.Format("{0}{1}{2}", record.school, "-", record.stuId);
  367. //首先根据大ID获取整个活动得内容
  368. var aresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(artId, new PartitionKey($"Art-{school}"));
  369. if (aresponse.Status == 200)
  370. {
  371. using var json = await JsonDocument.ParseAsync(aresponse.ContentStream);
  372. art = json.ToObject<ArtEvaluation>();
  373. var response = await client.GetContainer("TEAMModelOS", "Student").ReadItemStreamAsync(rId, new PartitionKey($"ArtResult-{artId}"));
  374. if (response.Status == 200)
  375. {
  376. using var json_1 = await JsonDocument.ParseAsync(response.ContentStream);
  377. artResult = json_1.ToObject<StudentArtResult>();
  378. List<Attachment> files = new();
  379. files = request.attachments;
  380. //bool flage = artResult.results.Exists(a => a.taskId == request.acId);
  381. artResult.results.ForEach(a =>
  382. {
  383. if (a.taskId == acId)
  384. {
  385. a.files = files;
  386. }
  387. });
  388. await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync(artResult, artResult.id, new PartitionKey($"{artResult.code}"));
  389. }
  390. else
  391. {
  392. artResult = new StudentArtResult
  393. {
  394. id = rId,
  395. pk = "ArtResult",
  396. code = $"ArtResult-{artId}",
  397. studentId = request.stuId,
  398. //picture = picture,
  399. studentName = request.name,
  400. school = school,
  401. userType = request.userType,
  402. artId = artId,
  403. classIds = classIds,
  404. };
  405. foreach (var qIds in art.settings)
  406. {
  407. foreach (var task in qIds.task)
  408. {
  409. ArtQuotaResult quotaResult = new()
  410. {
  411. quotaId = qIds.id,
  412. quotaName = qIds.quotaname,
  413. quotaType = (int)task.type,
  414. subjectId = task.subject,
  415. taskId = task.acId
  416. };
  417. if (!string.IsNullOrEmpty(quotaResult.taskId))
  418. {
  419. if (quotaResult.taskId.Equals(acId))
  420. {
  421. quotaResult.files = request.attachments;
  422. }
  423. }
  424. artResult.results.Add(quotaResult);
  425. }
  426. }
  427. await client.GetContainer("TEAMModelOS", "Student").CreateItemAsync(artResult, new PartitionKey($"{artResult.code}"));
  428. }
  429. }
  430. }
  431. catch (Exception e)
  432. {
  433. value = request.stuId;
  434. code = 1;
  435. }
  436. yield return (code, value);
  437. }
  438. }
  439. [ProducesDefaultResponseType]
  440. [AuthToken(Roles = "teacher,admin")]
  441. [HttpPost("delete")]
  442. [Authorize(Roles = "IES")]
  443. public async Task<IActionResult> Delete(JsonElement request)
  444. {
  445. try
  446. {
  447. //object userScope = null;
  448. //object _standard = null;
  449. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  450. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  451. /* string standard = null;
  452. HttpContext?.Items?.TryGetValue("Scope", out userScope);
  453. if (userScope != null && $"{userScope}".Equals(Constant.ScopeTeacher))
  454. {
  455. HttpContext?.Items?.TryGetValue("Standard", out _standard);
  456. standard = _standard != null && string.IsNullOrEmpty($"{userScope}") ? _standard.ToString() : null;
  457. }*/
  458. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  459. var client = _azureCosmos.GetCosmosClient();
  460. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Art-{code}"));
  461. if (sresponse.Status == 200)
  462. {
  463. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  464. ArtEvaluation art = json.ToObject<ArtEvaluation>();
  465. //必须是本人或者这个学校的管理者才能删除
  466. bool flag = false;
  467. if (art.creatorId == userid)
  468. {
  469. flag = true;
  470. }
  471. else
  472. {
  473. if (art.scope == "school" && art.school.Equals(school))
  474. {
  475. flag = true;
  476. }
  477. }
  478. /*try
  479. {
  480. (List<RMember> members, List<RGroupList> groups) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, null, art.school, null);
  481. await StatisticsService.DoChange(new TeacherTrainChange
  482. { standard = standard, tmdids = members.Select(x => x.id)?.ToList(), school = art.school, update = new HashSet<string> { StatisticsService.OfflineRecord }, statistics = 0 }, _azureCosmos);
  483. }
  484. catch (Exception ex)
  485. {
  486. await _dingDing.SendBotMsg($"OS,{_option.Location},art/delete()ex\n{ex.Message}\n{ex.StackTrace},\n", GroupNames.醍摩豆服務運維群組);
  487. }*/
  488. if (flag)
  489. {
  490. art.status = 404;
  491. foreach (var info in art.settings)
  492. {
  493. /* if (info.TryGetProperty("examId", out JsonElement eId)) {
  494. }*/
  495. foreach (var acs in info.task)
  496. {
  497. if (!string.IsNullOrEmpty(acs.acId))
  498. {
  499. if (acs.type == 1)
  500. {
  501. Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(acs.acId, new PartitionKey($"Exam-{code}"));
  502. if (response.Status == 200)
  503. {
  504. ExamInfo data = JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamInfo>();
  505. data.status = 404;
  506. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Exam-{code}"));
  507. }
  508. }
  509. }
  510. }
  511. }
  512. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(art, art.id, new PartitionKey($"{art.code}"));
  513. }
  514. }
  515. return Ok(new { id });
  516. }
  517. catch (Exception e)
  518. {
  519. await _dingDing.SendBotMsg($"OS,{_option.Location},art/delete()\n{e.Message}\n{e.StackTrace},\n", GroupNames.醍摩豆服務運維群組);
  520. return Ok(new { code = 500 });
  521. }
  522. }
  523. /// <param name="request"></param>
  524. /// <returns></returns>
  525. [ProducesDefaultResponseType]
  526. [Authorize(Roles = "IES")]
  527. [AuthToken(Roles = "teacher,admin")]
  528. [HttpPost("find")]
  529. public async Task<IActionResult> Find(JsonElement request)
  530. {
  531. try
  532. {
  533. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  534. request.TryGetProperty("periodId", out JsonElement period);
  535. request.TryGetProperty("periodType", out JsonElement periodType);
  536. if (string.IsNullOrWhiteSpace($"{period}") && string.IsNullOrWhiteSpace($"{periodType}"))
  537. {
  538. return BadRequest();
  539. }
  540. var client = _azureCosmos.GetCosmosClient();
  541. StringBuilder stringBuilder = new($"select c.id,c.img,c.name,c.classes,c.code,c.type,c.startTime,c.endTime,c.presenter,c.topic,c.address,c.owner,c.progress from c where (c.status<>404 or IS_DEFINED(c.status) = false )");
  542. string continuationToken = string.Empty;
  543. string token = default;
  544. if (!string.IsNullOrWhiteSpace($"{period}") && !string.IsNullOrWhiteSpace($"{periodType}"))
  545. {
  546. stringBuilder.Append($" and (c.period.id = '{period}' or c.periodType = '{periodType}')");
  547. }
  548. if (string.IsNullOrWhiteSpace($"{period}") && !string.IsNullOrWhiteSpace($"{periodType}"))
  549. {
  550. stringBuilder.Append($" and c.periodType = '{periodType}' ");
  551. }
  552. if (!string.IsNullOrWhiteSpace($"{period}") && string.IsNullOrWhiteSpace($"{periodType}"))
  553. {
  554. stringBuilder.Append($" and c.period.id = '{period}' ");
  555. }
  556. stringBuilder.Append("order by c.createTime desc");
  557. //是否需要进行分页查询,默认不分页
  558. bool iscontinuation = false;
  559. if (request.TryGetProperty("token", out JsonElement token_1))
  560. {
  561. token = token_1.GetString();
  562. iscontinuation = true;
  563. };
  564. //默认不指定返回大小
  565. int? topcout = null;
  566. if (request.TryGetProperty("count", out JsonElement jcount))
  567. {
  568. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
  569. {
  570. topcout = data;
  571. }
  572. }
  573. List<ArtEvaluation> arts = new();
  574. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Art-{code}") }))
  575. {
  576. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  577. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  578. {
  579. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  580. {
  581. arts.Add(obj.ToObject<ArtEvaluation>());
  582. }
  583. }
  584. if (iscontinuation)
  585. {
  586. continuationToken = item.GetContinuationToken();
  587. break;
  588. }
  589. }
  590. arts = arts.Where((x, i) => arts.FindIndex(z => z.id == x.id) == i).ToList();
  591. return Ok(new { arts });
  592. }
  593. catch (Exception e)
  594. {
  595. await _dingDing.SendBotMsg($"OS,{_option.Location},art/find()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  596. return Ok(new { code = 500 });
  597. }
  598. }
  599. [ProducesDefaultResponseType]
  600. [Authorize(Roles = "IES")]
  601. [AuthToken(Roles = "teacher,admin,student")]
  602. [HttpPost("find-summary")]
  603. public async Task<IActionResult> FindSummary(JsonElement request)
  604. {
  605. try
  606. {
  607. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  608. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  609. var client = _azureCosmos.GetCosmosClient();
  610. ArtEvaluation art = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ArtEvaluation>(id.GetString(), new PartitionKey($"Art-{code}"));
  611. ArtMusic music = new();
  612. ArtExam ae = new();
  613. if (art != null)
  614. {
  615. string queryArtExam = $" select value(c) from c where c.activityId = '{art.pId}' ";
  616. //List<ArtExam> aes = new List<ArtExam>();
  617. /* await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetItemQueryIterator<ArtExam>
  618. (queryText: queryArtExam, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtExam") }))
  619. {
  620. aes.Add(item);
  621. }*/
  622. if (!string.IsNullOrWhiteSpace(art.pId))
  623. {
  624. var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.pId, new PartitionKey("ArtMusic"));
  625. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.pId, new PartitionKey("ArtExam"));
  626. if (sresponse.Status == 200)
  627. {
  628. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  629. ae = json.ToObject<ArtExam>();
  630. }
  631. if (response.Status == 200)
  632. {
  633. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  634. music = json.ToObject<ArtMusic>();
  635. }
  636. }
  637. else
  638. {
  639. var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.id, new PartitionKey("ArtMusic"));
  640. if (response.Status == 200)
  641. {
  642. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  643. music = json.ToObject<ArtMusic>();
  644. }
  645. }
  646. (List<RMember> rmembers, List<RGroupList> groups) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, art.classes, art.school);
  647. var classes = art.classes.Select(c => new
  648. {
  649. id = c,
  650. groups.Where(g => g.id.Equals(c)).FirstOrDefault().name
  651. });
  652. rmembers.ForEach(x =>
  653. {
  654. groups.ForEach(z =>
  655. {
  656. if (z.members.Exists(y => y.id.Equals(x.id) && y.type == x.type))
  657. {
  658. x.groupListIds.Add(z.id);
  659. }
  660. });
  661. });
  662. List<ArtSubjectScore> subjectScores = new List<ArtSubjectScore>();
  663. art.subjects.ForEach(z => { subjectScores.Add(new ArtSubjectScore { subjectId = z.id, score = 0 }); });
  664. var students = rmembers.Select(z => new StudentArtResult
  665. {
  666. studentId = z.id,
  667. studentName = z.name,
  668. userType = z.type,
  669. classIds = z.groupListIds,
  670. school = z.schoolId,
  671. picture = z.picture,
  672. artId = $"{id}",
  673. id = $"{z.schoolId}-{z.id}",
  674. code = $"ArtResult-{id}",
  675. pk = "ArtResult",
  676. ttl = -1,
  677. subjectScores = subjectScores,
  678. }).ToList();
  679. //TODO 缺考人数的结算(多科评量检测,作业的提交)
  680. if (students.Any())
  681. {
  682. string query = $" select value c.id from c where c.id in({string.Join(",", students.Select(x => $"'{x.id}'"))}) ";
  683. List<string> list = new List<string>();
  684. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<string>
  685. (queryText: query, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtResult-{id}") }))
  686. {
  687. list.Add(item);
  688. }
  689. students.RemoveAll(x => list.Contains(x.id));
  690. students.ForEach(x =>
  691. {
  692. art.settings.ForEach(a =>
  693. {
  694. a.task.ForEach(z =>
  695. {
  696. ArtQuotaResult quotaResult = new ArtQuotaResult
  697. {
  698. taskId = z.acId,
  699. subjectId = z.subject,
  700. quotaId = a.id,
  701. quotaType = z.type.Value,
  702. quotaName = a.quotaname
  703. };
  704. x.results.Add(quotaResult);
  705. });
  706. });
  707. });
  708. List<Task<ItemResponse<StudentArtResult>>> responses = new();
  709. students.ForEach(z =>
  710. {
  711. responses.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).CreateItemAsync(z, new PartitionKey(z.code)));
  712. });
  713. if (responses.Count > 0)
  714. {
  715. await responses.TaskPage(10);
  716. }
  717. }
  718. if (!string.IsNullOrWhiteSpace(ae.id))
  719. {
  720. return Ok(new { art, classes, ae, music, code = 200 });
  721. }
  722. else
  723. {
  724. return Ok(new { art, classes, music, code = 200 });
  725. }
  726. }
  727. else
  728. {
  729. return Ok(new { art, code = 404 });
  730. }
  731. }
  732. catch (CosmosException ex) when (ex.Status == 404)
  733. {
  734. return Ok(new { code = 404 });
  735. }
  736. catch (Exception e)
  737. {
  738. await _dingDing.SendBotMsg($"OS,{_option.Location},art/FindSummary()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  739. return Ok(new { code = 500 });
  740. }
  741. }
  742. [ProducesDefaultResponseType]
  743. [Authorize(Roles = "IES")]
  744. [AuthToken(Roles = "teacher,admin,student")]
  745. [HttpPost("find-summary-by-student")]
  746. public async Task<IActionResult> findByStudent(JsonElement request)
  747. {
  748. try
  749. {
  750. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  751. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  752. var client = _azureCosmos.GetCosmosClient();
  753. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  754. ArtEvaluation art = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ArtEvaluation>(id.GetString(), new PartitionKey($"Art-{code}"));
  755. ArtMusic music = new();
  756. if (art != null)
  757. {
  758. List<StuActivity> stus = new();
  759. List<string> wIds = new();
  760. List<ArtRecord> works = new();
  761. if (!string.IsNullOrWhiteSpace(art.pId))
  762. {
  763. var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.pId, new PartitionKey("ArtMusic"));
  764. if (response.Status == 200)
  765. {
  766. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  767. music = json.ToObject<ArtMusic>();
  768. }
  769. }
  770. else
  771. {
  772. var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.id, new PartitionKey("ArtMusic"));
  773. if (response.Status == 200)
  774. {
  775. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  776. music = json.ToObject<ArtMusic>();
  777. }
  778. }
  779. foreach (var tt in art.settings)
  780. {
  781. foreach (var acs in tt.task)
  782. {
  783. if (acs.type == 1)
  784. {
  785. var response = await client.GetContainer("TEAMModelOS", "Student").ReadItemStreamAsync(acs.acId, new PartitionKey($"Activity-{school}-{userid}"));
  786. if (response.Status == 200)
  787. {
  788. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  789. StuActivity info = json.ToObject<StuActivity>();
  790. stus.Add(info);
  791. }
  792. }
  793. if (acs.type == 2)
  794. {
  795. wIds.Add(acs.acId);
  796. }
  797. }
  798. }
  799. if (wIds.Count > 0)
  800. {
  801. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator<ArtRecord>(
  802. queryText: $"select value(c) from c where c.stuId = '{userid}' and c.acId in ({string.Join(",", wIds.Select(o => $"'{o}'"))})",
  803. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ArtRecord") }))
  804. {
  805. works.Add(item);
  806. }
  807. }
  808. return Ok(new { art, stus, works, music, code = 200 });
  809. }
  810. else
  811. {
  812. return Ok(new { art, code = 404 });
  813. }
  814. }
  815. catch (CosmosException ex) when (ex.Status == 404)
  816. {
  817. return Ok(new { code = 404 });
  818. }
  819. catch (Exception e)
  820. {
  821. await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-summary-by-student()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  822. return Ok(new { code = 500 });
  823. }
  824. }
  825. [ProducesDefaultResponseType]
  826. [Authorize(Roles = "IES")]
  827. [AuthToken(Roles = "teacher,admin")]
  828. [HttpPost("find-summary-by-work")]
  829. public async Task<IActionResult> findBywork(JsonElement request)
  830. {
  831. try
  832. {
  833. if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
  834. if (!request.TryGetProperty("subject", out JsonElement subject)) return BadRequest();
  835. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  836. var client = _azureCosmos.GetCosmosClient();
  837. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  838. List<object> works = new();
  839. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryStreamIterator(
  840. queryText: $"select c.stuId,c.attachments from c where c.classId = '{classId}' and c.acId = '{id}' and c.subject = '{subject}'",
  841. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ArtRecord") }))
  842. {
  843. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  844. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  845. {
  846. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  847. {
  848. works.Add(obj.ToObject<object>());
  849. }
  850. }
  851. }
  852. return Ok(new { works, code = 200 });
  853. }
  854. catch (CosmosException ex) when (ex.Status == 404)
  855. {
  856. return Ok(new { code = 404 });
  857. }
  858. catch (Exception e)
  859. {
  860. await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-summary-by-work()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  861. return Ok(new { code = 500 });
  862. }
  863. }
  864. /// <param name="request"></param>
  865. /// <returns></returns>
  866. [ProducesDefaultResponseType]
  867. [Authorize(Roles = "IES")]
  868. [AuthToken(Roles = "teacher,admin")]
  869. [HttpPost("find-by-teacher")]
  870. public async Task<IActionResult> FindByTeacher(JsonElement request)
  871. {
  872. try
  873. {
  874. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  875. if (!request.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  876. var client = _azureCosmos.GetCosmosClient();
  877. var query = $"select c.id,c.img,c.name,c.startTime,c.type,c.endTime,c.presenter,c.topic,c.address,c.owner from c join A0 in c.teachers where A0.id = '{tId}'";
  878. List<object> arts = new();
  879. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Art-{code}") }))
  880. {
  881. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  882. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  883. {
  884. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  885. {
  886. arts.Add(obj.ToObject<object>());
  887. }
  888. }
  889. }
  890. return Ok(new { arts });
  891. }
  892. catch (Exception e)
  893. {
  894. await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-by-teacher()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  895. return Ok(new { code = 500 });
  896. }
  897. }
  898. [ProducesDefaultResponseType]
  899. [Authorize(Roles = "IES")]
  900. [AuthToken(Roles = "teacher,admin")]
  901. [HttpPost("find-summary-by-teacher")]
  902. public async Task<IActionResult> FindSummaryByTeacher(JsonElement request)
  903. {
  904. try
  905. {
  906. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  907. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  908. if (!request.TryGetProperty("tId", out JsonElement tId)) return BadRequest();
  909. var client = _azureCosmos.GetCosmosClient();
  910. List<object> arts = new();
  911. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select value(c) from c join A0 in c.teachers where A0.id = '{tId}' and c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Art-{code}") }))
  912. {
  913. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  914. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  915. {
  916. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  917. {
  918. arts.Add(obj.ToObject<object>());
  919. }
  920. }
  921. }
  922. return Ok(new { arts });
  923. }
  924. catch (Exception e)
  925. {
  926. await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-summary-by-teacher()\n{e.Message}\n{e.StackTrace}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  927. return Ok(new { code = 500 });
  928. }
  929. }
  930. private class stuFiles
  931. {
  932. public string stuId { get; set; }
  933. public int userType { get; set; }
  934. public string name { get; set; }
  935. public List<Attachment> attachments { get; set; } = new List<Attachment>();
  936. }
  937. }
  938. }