ArtController.cs 48 KB

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