AreaController.cs 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204
  1. using Azure.Cosmos;
  2. using Azure.Storage.Sas;
  3. using Microsoft.AspNetCore.Http;
  4. using Microsoft.AspNetCore.Mvc;
  5. using Microsoft.Extensions.Configuration;
  6. using Microsoft.Extensions.Options;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Linq;
  10. using System.Net;
  11. using System.Text;
  12. using System.Text.Json;
  13. using System.Threading.Tasks;
  14. using TEAMModelOS.Filter;
  15. using TEAMModelOS.Models;
  16. using TEAMModelOS.SDK;
  17. using TEAMModelOS.SDK.DI;
  18. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  19. using TEAMModelOS.SDK.Extension;
  20. using TEAMModelOS.SDK.Models;
  21. using TEAMModelOS.SDK.Models.Cosmos.Common;
  22. using TEAMModelOS.SDK.Models.Cosmos.School;
  23. using TEAMModelOS.SDK.Models.Service;
  24. namespace TEAMModelOS.Controllers
  25. {
  26. [ProducesResponseType(StatusCodes.Status200OK)]
  27. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  28. [Route("school/area")]
  29. [ApiController]
  30. public class AreaController : ControllerBase
  31. {
  32. private readonly AzureCosmosFactory _azureCosmos;
  33. private readonly SnowflakeId _snowflakeId;
  34. private readonly AzureServiceBusFactory _serviceBus;
  35. private readonly DingDing _dingDing;
  36. private readonly Option _option;
  37. private readonly AzureStorageFactory _azureStorage;
  38. private readonly AzureRedisFactory _azureRedis;
  39. public IConfiguration _configuration { get; set; }
  40. public AreaController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing,
  41. IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, IConfiguration configuration)
  42. {
  43. _azureCosmos = azureCosmos;
  44. _serviceBus = serviceBus;
  45. _snowflakeId = snowflakeId;
  46. _dingDing = dingDing;
  47. _option = option?.Value;
  48. _azureStorage = azureStorage;
  49. _azureRedis = azureRedis;
  50. _configuration = configuration;
  51. }
  52. /// <param name="request"></param>
  53. /// <returns></returns>
  54. [ProducesDefaultResponseType]
  55. //[AuthToken(Roles = "Teacher")]
  56. [HttpPost("find-group")]
  57. public async Task<IActionResult> Find(JsonElement requert)
  58. {
  59. try
  60. {
  61. //区级Id
  62. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  63. var client = _azureCosmos.GetCosmosClient();
  64. //获取区级以下所有学校编码和基础信息
  65. List<string> baseIds = new();
  66. List<(string id, string name, string picture)> scInfos = new List<(string id, string name, string picture)>();
  67. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"select c.id,c.name,c.picture from c where c.areaId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  68. {
  69. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  70. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  71. {
  72. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  73. while (accounts.MoveNext())
  74. {
  75. JsonElement account = accounts.Current;
  76. baseIds.Add(account.GetProperty("id").GetString());
  77. scInfos.Add((account.GetProperty("id").GetString(), account.GetProperty("name").GetString(), account.GetProperty("picture").GetString()));
  78. }
  79. }
  80. }
  81. List<(string id, List<string> gId, List<string> name)> groups = new List<(string id, List<string> gId, List<string> name)>();
  82. foreach (string sId in baseIds)
  83. {
  84. List<(string id, string name)> group = new();
  85. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"SELECT c.id, c.name FROM c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TchList-{sId}") }))
  86. {
  87. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  88. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  89. {
  90. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  91. while (accounts.MoveNext())
  92. {
  93. JsonElement account = accounts.Current;
  94. group.Add((account.GetProperty("id").GetString(), account.GetProperty("name").GetString()));
  95. //group.Add();
  96. }
  97. }
  98. }
  99. group = group.Where(g => !string.IsNullOrEmpty(g.id)).ToList();
  100. groups.Add((sId, group.Select(s=>s.id).ToList(), group.Select(s => s.name).ToList()));
  101. }
  102. //var (blob_uri, blob_sas) = _azureStorage.GetBlobContainerSAS("hbcn", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
  103. var gr = groups.Select(o => new
  104. {
  105. o.id,
  106. o.gId,
  107. uri = _azureStorage.GetBlobContainerSAS(o.id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List).uri,
  108. sas = _azureStorage.GetBlobContainerSAS(o.id, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List).sas,
  109. sname = scInfos.FirstOrDefault(c => c.id == o.id).name,
  110. o.name
  111. });
  112. return Ok(new { gr });
  113. }
  114. catch (Exception e)
  115. {
  116. await _dingDing.SendBotMsg($"OS,{_option.Location},school/area/find-group()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  117. return BadRequest();
  118. }
  119. }
  120. [ProducesDefaultResponseType]
  121. //[AuthToken(Roles = "Teacher")]
  122. [HttpPost("find")]
  123. public async Task<IActionResult> FindGroup(JsonElement requert)
  124. {
  125. try
  126. {
  127. //区级Id
  128. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  129. var client = _azureCosmos.GetCosmosClient();
  130. //获取区级以下所有学校编码和基础信息
  131. List<string> baseIds = new();
  132. List<(string id, string name, string picture)> scInfos = new List<(string id, string name, string picture)>();
  133. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"select c.id,c.name,c.picture from c where c.areaId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  134. {
  135. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  136. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  137. {
  138. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  139. while (accounts.MoveNext())
  140. {
  141. JsonElement account = accounts.Current;
  142. baseIds.Add(account.GetProperty("id").GetString());
  143. scInfos.Add((account.GetProperty("id").GetString(), account.GetProperty("name").GetString(), account.GetProperty("picture").GetString()));
  144. }
  145. }
  146. }
  147. //获取所有学校人数
  148. List<(string id, int count)> scCount = new List<(string id, int count)>();
  149. foreach (string sId in baseIds)
  150. {
  151. List<string> tIds = new();
  152. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: $"select c.id from c join A0 in c.schools where A0.schoolId = '{sId}' ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  153. {
  154. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  155. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  156. {
  157. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  158. while (accounts.MoveNext())
  159. {
  160. JsonElement account = accounts.Current;
  161. tIds.Add(account.GetProperty("id").GetString());
  162. }
  163. }
  164. }
  165. scCount.Add((sId, tIds.Count));
  166. }
  167. var info = scInfos.Select(o =>
  168. new
  169. {
  170. o.id,
  171. o.name,
  172. o.picture,
  173. areaId = id,
  174. count = scCount.FirstOrDefault(c => c.id == o.id).count,
  175. }
  176. );
  177. return Ok(new { info });
  178. }
  179. catch (Exception e)
  180. {
  181. await _dingDing.SendBotMsg($"OS,{_option.Location},school/area/find()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  182. return BadRequest();
  183. }
  184. }
  185. /// <summary>
  186. /// 保存研修信息
  187. /// </summary>
  188. /// <param name="request"></param>
  189. /// <returns></returns>
  190. [ProducesDefaultResponseType]
  191. //[AuthToken(Roles = "teacher,admin")]
  192. [HttpPost("save-study")]
  193. public async Task<IActionResult> SaveStudy(JsonElement request)
  194. {
  195. try
  196. {
  197. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  198. if (!request.TryGetProperty("para", out JsonElement para)) return BadRequest();
  199. if (!request.TryGetProperty("study", out JsonElement stu)) return BadRequest();
  200. List<parameter> parameters = para.ToObject<List<parameter>>();
  201. var client = _azureCosmos.GetCosmosClient();
  202. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  203. List<Study> studies = new();
  204. Study areaStudy = stu.ToObject<Study>();
  205. areaStudy.owner = "area";
  206. areaStudy.ttl = -1;
  207. areaStudy.code = "Study-" + id.GetString();
  208. areaStudy.createTime = now;
  209. if (string.IsNullOrEmpty(areaStudy.id))
  210. {
  211. areaStudy.id = Guid.NewGuid().ToString();
  212. }
  213. List<string> allName = new();
  214. foreach (parameter pa in parameters)
  215. {
  216. Study study = stu.ToObject<Study>();
  217. //string code = pa.sId;
  218. study.areaId = id.GetString();
  219. study.school = pa.sId;
  220. study.owner = "area";
  221. study.ttl = -1;
  222. study.code = "Study-" + pa.sId;
  223. study.createTime = now;
  224. study.tchLists = pa.gId;
  225. study.pId = areaStudy.id;
  226. study.targetType = "research";
  227. if (pa.gName.Count == 0)
  228. {
  229. string sName = pa.sName + "-" + "所有老师(未分组)";
  230. allName.Add(sName);
  231. string json = "所有老师(未分组)";
  232. study.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  233. //study.targets.Add("所有老师(未分组)");
  234. }
  235. else
  236. {
  237. //study.targets = pa.gName;
  238. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  239. study.targets = tn;
  240. foreach (string name in pa.gName)
  241. {
  242. //处理区级target
  243. string sName = pa.sName + "-" + name;
  244. allName.Add(sName);
  245. }
  246. }
  247. foreach (string setting in study.settings)
  248. {
  249. if (setting.Equals("exam"))
  250. {
  251. if (!request.TryGetProperty("exam", out JsonElement exam)) return BadRequest();
  252. ExamLite trExam = exam.ToObject<ExamLite>();
  253. trExam.owner = "area";
  254. trExam.school = pa.sId;
  255. trExam.areaId = id.GetString();
  256. trExam.tchLists = pa.gId;
  257. trExam.targetType = "research";
  258. trExam.blob = $"/{trExam.areaId}/exam/{study.pId}/index.json";
  259. //处理发布对象
  260. await getMoreExam(pa, trExam);
  261. //保存更多得评测信息
  262. string eId = await ExamService.saveMoreAsync(client, _dingDing, trExam);
  263. if (string.IsNullOrEmpty(eId))
  264. {
  265. return Ok(new { code = (int)HttpStatusCode.BadRequest, msg = "评测信息异常" });
  266. }
  267. else
  268. {
  269. study.examId = eId;
  270. }
  271. }
  272. if (setting.Equals("survey"))
  273. {
  274. if (!request.TryGetProperty("survey", out JsonElement survey)) return BadRequest();
  275. Survey trSurvey = survey.ToObject<Survey>();
  276. trSurvey.owner = "area";
  277. trSurvey.school = pa.sId;
  278. trSurvey.areaId = id.GetString();
  279. trSurvey.tchLists = pa.gId;
  280. trSurvey.targetType = "research";
  281. trSurvey.blob = $"/{trSurvey.areaId}/survey/{study.pId}/index.json";
  282. await getMoreSurvey(pa, trSurvey);
  283. string surveyId = await SurveyService.saveMoreAsync(client, _dingDing, trSurvey);
  284. if (string.IsNullOrEmpty(surveyId))
  285. {
  286. return Ok(new { code = (int)HttpStatusCode.BadRequest, msg = "问卷信息异常" });
  287. }
  288. else
  289. {
  290. study.surveyId = surveyId;
  291. }
  292. }
  293. }
  294. if (string.IsNullOrEmpty(study.id))
  295. {
  296. study.id = Guid.NewGuid().ToString();
  297. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(study, new PartitionKey($"{study.code}"));
  298. }
  299. else
  300. {
  301. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(study, new PartitionKey($"{study.code}"));
  302. }
  303. studies.Add(study);
  304. }
  305. //areaStudy.targets = allName;
  306. var atn = allName.ToJsonString().ToObject<List<JsonElement>>();
  307. areaStudy.targets = atn;
  308. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(areaStudy, new PartitionKey($"{areaStudy.code}"));
  309. var ids = studies.Select(s => new { s.id, s.school, s.examId, s.surveyId });
  310. return Ok(new { id, ids, code = (int)HttpStatusCode.OK, acId = areaStudy.id });
  311. }
  312. catch (Exception ex)
  313. {
  314. await _dingDing.SendBotMsg($"OS,{_option.Location},area/save-study()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  315. return BadRequest();
  316. }
  317. }
  318. /// <param name="request"></param>
  319. /// <returns></returns>
  320. [ProducesDefaultResponseType]
  321. //[AuthToken(Roles = "Teacher")]
  322. [HttpPost("find-all-study")]
  323. public async Task<IActionResult> FindAllStudy(JsonElement requert)
  324. {
  325. try
  326. {
  327. //区级Id
  328. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  329. var client = _azureCosmos.GetCosmosClient();
  330. // List<string> baseIds = await getId(client, id.GetString());
  331. List<object> studies = new();
  332. var query = $"select c.id,c.img,c.name,c.type,c.startTime,c.endTime,c.presenter,c.topic,c.address,c.owner,c.school from c ";
  333. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{id}") }))
  334. {
  335. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  336. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  337. {
  338. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  339. {
  340. studies.Add(obj.ToObject<object>());
  341. }
  342. }
  343. }
  344. return Ok(new { studies });
  345. }
  346. catch (Exception e)
  347. {
  348. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-study()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  349. return BadRequest();
  350. }
  351. }
  352. [ProducesDefaultResponseType]
  353. //[AuthToken(Roles = "Teacher")]
  354. [HttpPost("find-all-study-teachers")]
  355. public async Task<IActionResult> FindAllStudyTeacher(JsonElement requert)
  356. {
  357. try
  358. {
  359. //区级活动Id
  360. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  361. if (!requert.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
  362. var client = _azureCosmos.GetCosmosClient();
  363. List<string> baseIds = await getId(client, areaId.GetString());
  364. List<Study> studies = new();
  365. List<(string id, string name)> ps = await getInfo(client, areaId.GetString());
  366. //List<string> aName = new();
  367. var query = $"select value(c) from c where c.pId = '{id}'";
  368. foreach (string code in baseIds)
  369. {
  370. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<Study>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{code}") }))
  371. {
  372. studies.Add(item);
  373. }
  374. }
  375. List<Survey> trSurveys = new List<Survey>();
  376. List<ExamLite> trExams = new List<ExamLite>();
  377. List<(List<TmdInfo> teac, Study stu)> moreInfo = new List<(List<TmdInfo> teac, Study stu)>();
  378. foreach (Study study in studies) {
  379. (List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, study.tchLists, study.school);
  380. if (!string.IsNullOrEmpty(study.surveyId))
  381. {
  382. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<Survey>(queryText: $"select value(c) from c where c.id = '{study.surveyId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{study.school}") }))
  383. {
  384. trSurveys.Add(item);
  385. }
  386. }
  387. if (!string.IsNullOrEmpty(study.examId)) {
  388. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamLite>(queryText: $"select value(c) from c where c.id = '{study.examId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamLite-{study.school}") }))
  389. {
  390. trExams.Add(item);
  391. }
  392. }
  393. moreInfo.Add((tchList,study));
  394. } ;
  395. var survey = trSurveys.Select(s => new {
  396. count = s.answers.Count,
  397. ansCount = s.answers.Count,
  398. });
  399. var exam = trExams.Select(s => new {
  400. count = s.teachers.Count,
  401. ansCount = s.teachers.Where(h => h.answer.Count > 0).ToList().Count,
  402. });
  403. var info = studies.Select(s => new {
  404. s.id,
  405. name = ps.FirstOrDefault(c => c.id == s.id).name,
  406. count = s.teachers.Count,
  407. //hwCount = s.teachers.Where(h => h.hwTime > 0).ToList().Count,
  408. signCount = s.teachers.Where(h => h.signTime > 0).ToList().Count,
  409. lateCount = s.teachers.Where(h =>!string.IsNullOrEmpty(h.sign) && h.sign.Equals("1")).ToList().Count,
  410. acount = s.teachers.Where(h => h.aTime > 0).ToList().Count
  411. });
  412. return Ok(new { survey,exam, info, studies = moreInfo.Select(m => new { m.teac,m.stu}) });
  413. }
  414. catch (Exception e)
  415. {
  416. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-study-teachers()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  417. return BadRequest();
  418. }
  419. }
  420. [ProducesDefaultResponseType]
  421. //[AuthToken(Roles = "Teacher")]
  422. [HttpPost("find-all-vote")]
  423. public async Task<IActionResult> FindAllVote(JsonElement requert)
  424. {
  425. try
  426. {
  427. //区级Id
  428. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  429. var client = _azureCosmos.GetCosmosClient();
  430. //List<string> baseIds = await getId(client, id.GetString());
  431. List<object> votes = new();
  432. //List<string> aName = new();
  433. var query = $"select c.id,c.name,c.startTime,c.progress,c.owner,c.school from c ";
  434. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{id}") }))
  435. {
  436. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  437. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  438. {
  439. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  440. {
  441. votes.Add(obj.ToObject<object>());
  442. }
  443. }
  444. }
  445. return Ok(new { votes });
  446. }
  447. catch (Exception e)
  448. {
  449. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-vote()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  450. return BadRequest();
  451. }
  452. }
  453. [ProducesDefaultResponseType]
  454. //[AuthToken(Roles = "Teacher")]
  455. [HttpPost("find-vote-id")]
  456. public async Task<IActionResult> FindAllVoteTeacher(JsonElement requert)
  457. {
  458. try
  459. {
  460. //区级活动Id
  461. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  462. if (!requert.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
  463. var client = _azureCosmos.GetCosmosClient();
  464. List<string> baseIds = await getId(client, areaId.GetString());
  465. //List<object> votes = new();
  466. List<(string id, string name)> ps = await getInfo(client, areaId.GetString()) ;
  467. //List<string> aName = new();
  468. List<Vote> votes = new List<Vote>();
  469. Vote vote = null;
  470. List<(string code,string url, int count)> recordUrl = new List<(string code, string url, int count)>();
  471. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.GetString(), new PartitionKey($"Vote-{areaId}"));
  472. if (response.Status == 200)
  473. {
  474. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  475. vote = json.ToObject<Vote>();
  476. var query = $"select c.tchLists,c.recordUrl from c where c.pId = '{id}'";
  477. foreach (string code in baseIds)
  478. {
  479. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{code}") }))
  480. {
  481. using var sjson = await JsonDocument.ParseAsync(item.ContentStream);
  482. if (sjson.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  483. {
  484. var accounts = sjson.RootElement.GetProperty("Documents").EnumerateArray();
  485. while (accounts.MoveNext())
  486. {
  487. JsonElement account = accounts.Current;
  488. List<string> tcs = account.GetProperty("tchLists").ToObject<List<string>>();
  489. (List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, tcs, code);
  490. recordUrl.Add((code,account.GetProperty("recordUrl").GetString(),tchList.Count));
  491. }
  492. }
  493. }
  494. }
  495. }
  496. //var info = ps.Select(p => new { p.id, p.name });
  497. return Ok(new { vote , code = recordUrl.Select(r => new { r.code, r.url,r.count }) });
  498. }
  499. catch (Exception e)
  500. {
  501. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-vote-teachers()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  502. return BadRequest();
  503. }
  504. }
  505. [ProducesDefaultResponseType]
  506. //[AuthToken(Roles = "Teacher")]
  507. [HttpPost("find-all-survey")]
  508. public async Task<IActionResult> FindAllSurvey(JsonElement requert)
  509. {
  510. try
  511. {
  512. //区级Id
  513. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  514. var client = _azureCosmos.GetCosmosClient();
  515. //List<string> baseIds = await getId(client, id.GetString());
  516. List<object> surveys = new();
  517. // List<string> aName = new();
  518. var query = $"select c.id,c.name,c.startTime,c.progress,c.sType,c.owner,c.school from c ";
  519. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{id}") }))
  520. {
  521. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  522. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  523. {
  524. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  525. {
  526. surveys.Add(obj.ToObject<object>());
  527. }
  528. }
  529. }
  530. return Ok(new { surveys });
  531. }
  532. catch (Exception e)
  533. {
  534. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-survey()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  535. return BadRequest();
  536. }
  537. }
  538. [ProducesDefaultResponseType]
  539. //[AuthToken(Roles = "Teacher")]
  540. [HttpPost("find-survey-id")]
  541. public async Task<IActionResult> FindAllSurveyTeacher(JsonElement requert)
  542. {
  543. try
  544. {
  545. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  546. if (!requert.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
  547. var client = _azureCosmos.GetCosmosClient();
  548. List<string> baseIds = await getId(client, areaId.GetString());
  549. List<object> surveys = new();
  550. Survey survey = null;
  551. List<(string code, string url, int count)> recordUrl = new List<(string code, string url, int count)>();
  552. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.GetString(), new PartitionKey($"Survey-{areaId}"));
  553. if (response.Status == 200)
  554. {
  555. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  556. survey = json.ToObject<Survey>();
  557. var query = $"select c.tchLists,c.recordUrl from c where c.pId = '{id}'";
  558. foreach (string code in baseIds)
  559. {
  560. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{code}") }))
  561. {
  562. using var sjson = await JsonDocument.ParseAsync(item.ContentStream);
  563. if (sjson.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  564. {
  565. var accounts = sjson.RootElement.GetProperty("Documents").EnumerateArray();
  566. while (accounts.MoveNext())
  567. {
  568. JsonElement account = accounts.Current;
  569. List<string> tcs = account.GetProperty("tchLists").ToObject<List<string>>();
  570. (List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, tcs, code);
  571. recordUrl.Add((code,account.GetProperty("recordUrl").GetString(),tchList.Count));
  572. }
  573. }
  574. }
  575. }
  576. }
  577. //var info = ps.Select(p => new { p.id, p.name });
  578. return Ok(new { survey, code = recordUrl.Select(r => new { r.code,r.url,r.count }) });
  579. }
  580. catch (Exception e)
  581. {
  582. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-survey-teachers()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  583. return BadRequest();
  584. }
  585. }
  586. [ProducesDefaultResponseType]
  587. //[AuthToken(Roles = "Teacher")]
  588. [HttpPost("find-all-Exam")]
  589. public async Task<IActionResult> FindAllExam(JsonElement requert)
  590. {
  591. try
  592. {
  593. //区级Id
  594. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  595. var client = _azureCosmos.GetCosmosClient();
  596. //List<string> baseIds = await getId(client, id.GetString());
  597. List<object> exams = new();
  598. // List<string> aName = new();
  599. var query = $"select c.id,c.name,c.createTime,c.sType,c.owner,c.school from c ";
  600. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamLite-{id}") }))
  601. {
  602. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  603. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  604. {
  605. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  606. {
  607. exams.Add(obj.ToObject<object>());
  608. }
  609. }
  610. }
  611. return Ok(new { exams });
  612. }
  613. catch (Exception e)
  614. {
  615. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-exam()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  616. return BadRequest();
  617. }
  618. }
  619. [ProducesDefaultResponseType]
  620. //[AuthToken(Roles = "Teacher")]
  621. [HttpPost("find-all-exam-teachers")]
  622. public async Task<IActionResult> FindAllExamTeacher(JsonElement requert)
  623. {
  624. try
  625. {
  626. //区级活动Id
  627. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  628. if (!requert.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
  629. var client = _azureCosmos.GetCosmosClient();
  630. List<string> baseIds = await getId(client, areaId.GetString());
  631. List<object> exams = new();
  632. List<(string id, string name)> ps = await getInfo(client, areaId.GetString());
  633. //List<string> aName = new();
  634. var query = $"select c.school,c.teachers from c where c.acId = '{id}'";
  635. foreach (string code in baseIds)
  636. {
  637. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TrExam-{code}") }))
  638. {
  639. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  640. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  641. {
  642. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  643. {
  644. exams.Add(obj.ToObject<object>());
  645. }
  646. }
  647. }
  648. }
  649. var info = ps.Select(p => new { p.id, p.name });
  650. return Ok(new {info,exams });
  651. }
  652. catch (Exception e)
  653. {
  654. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-exam-teachers()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  655. return BadRequest();
  656. }
  657. }
  658. /// <summary>
  659. /// 保存投票信息
  660. /// </summary>
  661. /// <param name="request"></param>
  662. /// <returns></returns>
  663. [ProducesDefaultResponseType]
  664. //[AuthToken(Roles = "teacher,admin")]
  665. [HttpPost("save-vote")]
  666. public async Task<IActionResult> SaveVote(JsonElement request)
  667. {
  668. try
  669. {
  670. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  671. if (!request.TryGetProperty("para", out JsonElement para)) return BadRequest();
  672. if (!request.TryGetProperty("vote", out JsonElement vote)) return BadRequest();
  673. List<parameter> parameters = para.ToObject<List<parameter>>();
  674. List<Vote> votes = new();
  675. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  676. var client = _azureCosmos.GetCosmosClient();
  677. Vote areaVote = vote.ToObject<Vote>();
  678. areaVote.owner = "area";
  679. areaVote.ttl = -1;
  680. areaVote.code = "Vote-" + id.GetString();
  681. areaVote.createTime = now;
  682. if (areaVote.startTime <= 0)
  683. {
  684. areaVote.startTime = now;
  685. }
  686. if (areaVote.startTime > now)
  687. {
  688. areaVote.progress = "pending";
  689. }
  690. else
  691. {
  692. areaVote.progress = "going";
  693. }
  694. if (string.IsNullOrEmpty(areaVote.id))
  695. {
  696. areaVote.id = Guid.NewGuid().ToString();
  697. }
  698. List<string> allName = new();
  699. foreach (parameter pa in parameters)
  700. {
  701. Vote trVote = vote.ToObject<Vote>();
  702. string code = pa.sId;
  703. trVote.school = code;
  704. trVote.ttl = -1;
  705. trVote.code = "Vote-" + code;
  706. trVote.createTime = now;
  707. trVote.areaId = id.GetString();
  708. trVote.owner = "area";
  709. trVote.pId = areaVote.id;
  710. trVote.tchLists = pa.gId;
  711. trVote.targetType = "research";
  712. if (trVote.startTime <= 0)
  713. {
  714. trVote.startTime = now;
  715. }
  716. if (trVote.startTime > now)
  717. {
  718. trVote.progress = "pending";
  719. }
  720. else
  721. {
  722. trVote.progress = "going";
  723. }
  724. if (pa.gName.Count == 0)
  725. {
  726. string sName = pa.sName + "-" + "所有老师(未分组)";
  727. allName.Add(sName);
  728. string json = "所有老师(未分组)";
  729. //var json = new { name = "所有老师(未分组)" };
  730. trVote.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  731. }
  732. else
  733. {
  734. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  735. trVote.targets = tn;
  736. foreach (string name in pa.gName)
  737. {
  738. //处理区级target
  739. string sName = pa.sName + "-" + name;
  740. allName.Add(sName);
  741. }
  742. }
  743. if (string.IsNullOrEmpty(trVote.id))
  744. {
  745. trVote.id = Guid.NewGuid().ToString();
  746. string url = $"/vote/{trVote.id}/record.json";
  747. trVote.recordUrl = url;
  748. await _azureStorage.UploadFileByContainer(code, new { options = new List<string>(), records = new List<VoteRecord>() }.ToJsonString(), "vote", $"{trVote.id}/record.json");
  749. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(trVote, new PartitionKey($"{trVote.code}"));
  750. }
  751. else
  752. {
  753. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(trVote, trVote.id, new PartitionKey($"{trVote.code}"));
  754. }
  755. votes.Add(trVote);
  756. }
  757. var atn = allName.ToJsonString().ToObject<List<JsonElement>>();
  758. /*List<JsonElement> atn = new List<JsonElement>();
  759. foreach (string agn in allName)
  760. {
  761. atn.Add(agn.ToObject<JsonElement>());
  762. }*/
  763. areaVote.targets =atn;
  764. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(areaVote, new PartitionKey($"{areaVote.code}"));
  765. var ids = votes.Select(s => new { s.id, s.school });
  766. return Ok(new { id, ids, code = (int)HttpStatusCode.OK });
  767. }
  768. catch (Exception ex)
  769. {
  770. await _dingDing.SendBotMsg($"OS,{_option.Location},area/save-vote()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  771. return BadRequest();
  772. }
  773. }
  774. [ProducesDefaultResponseType]
  775. //[AuthToken(Roles = "Teacher")]
  776. [HttpPost("delete")]
  777. public async Task<IActionResult> Delete(JsonElement request)
  778. {
  779. try
  780. {
  781. //区级活动Id
  782. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  783. //区级id
  784. if (!request.TryGetProperty("areaId", out JsonElement code)) return BadRequest();
  785. if (!request.TryGetProperty("pk", out JsonElement pk)) return BadRequest();
  786. var client = _azureCosmos.GetCosmosClient();
  787. var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{pk}-{code}"));
  788. List<string> bascId = await getId(client,code.GetString());
  789. List<(string id, string name)> ids = new();
  790. foreach (string sId in bascId) {
  791. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select c.id,c.code from c where c.pId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{pk}-{sId}") }))
  792. {
  793. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  794. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  795. {
  796. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  797. while (accounts.MoveNext())
  798. {
  799. JsonElement account = accounts.Current;
  800. ids.Add((account.GetProperty("id").GetString(), account.GetProperty("code").GetString()));
  801. }
  802. }
  803. }
  804. }
  805. if (ids.Count > 0)
  806. {
  807. foreach ((string s, string c) in ids)
  808. {
  809. if (c.Contains("Study")) {
  810. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(s.ToString(), new PartitionKey($"{c}"));
  811. if (sresponse.Status == 200)
  812. {
  813. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  814. Study study = json.ToObject<Study>();
  815. if (!string.IsNullOrEmpty(study.examId))
  816. {
  817. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(study.examId, new PartitionKey($"ExamLite-{study.school}"));
  818. }
  819. if (!string.IsNullOrEmpty(study.surveyId))
  820. {
  821. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(study.surveyId, new PartitionKey($"Survey-{study.school}"));
  822. }
  823. }
  824. }
  825. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(s.ToString(), new PartitionKey($"{c}"));
  826. }
  827. }
  828. return Ok(new { id, code = response.Status });
  829. }
  830. catch (Exception e)
  831. {
  832. await _dingDing.SendBotMsg($"OS,{_option.Location},area/delete()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  833. return BadRequest();
  834. }
  835. }
  836. /// <summary>
  837. /// 保存问卷信息
  838. /// </summary>
  839. /// <param name="request"></param>
  840. /// <returns></returns>
  841. [ProducesDefaultResponseType]
  842. //[AuthToken(Roles = "teacher,admin")]
  843. [HttpPost("save-survey")]
  844. public async Task<IActionResult> SaveSurvey(JsonElement request)
  845. {
  846. try
  847. {
  848. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  849. if (!request.TryGetProperty("para", out JsonElement para)) return BadRequest();
  850. if (!request.TryGetProperty("survey", out JsonElement survey)) return BadRequest();
  851. List<parameter> parameters = para.ToObject<List<parameter>>();
  852. List<Survey> surveys = new();
  853. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  854. var client = _azureCosmos.GetCosmosClient();
  855. Survey areaSurvey = survey.ToObject<Survey>();
  856. areaSurvey.owner = "area";
  857. areaSurvey.ttl = -1;
  858. areaSurvey.code = "Survey-" + id.GetString();
  859. areaSurvey.createTime = now;
  860. if (areaSurvey.startTime <= 0)
  861. {
  862. areaSurvey.startTime = now;
  863. }
  864. if (areaSurvey.startTime > now)
  865. {
  866. areaSurvey.progress = "pending";
  867. }
  868. else
  869. {
  870. areaSurvey.progress = "going";
  871. }
  872. if (string.IsNullOrEmpty(areaSurvey.id))
  873. {
  874. areaSurvey.id = Guid.NewGuid().ToString();
  875. }
  876. List<string> allName = new();
  877. foreach (parameter pa in parameters)
  878. {
  879. Survey trSurvey = survey.ToObject<Survey>();
  880. string code = pa.sId;
  881. trSurvey.ttl = -1;
  882. trSurvey.school = code;
  883. trSurvey.code = "Survey-" + code;
  884. trSurvey.createTime = now;
  885. trSurvey.areaId = id.GetString();
  886. trSurvey.owner = "area";
  887. trSurvey.tchLists = pa.gId;
  888. trSurvey.pId = areaSurvey.id;
  889. trSurvey.targetType = "research";
  890. if (areaSurvey.startTime <= 0)
  891. {
  892. areaSurvey.startTime = now;
  893. }
  894. if (trSurvey.startTime > now)
  895. {
  896. trSurvey.progress = "pending";
  897. }
  898. else
  899. {
  900. trSurvey.progress = "going";
  901. }
  902. if (pa.gName.Count == 0)
  903. {
  904. string sName = pa.sName + "-" + "所有老师(未分组)";
  905. allName.Add(sName);
  906. string json = "所有老师(未分组)";
  907. trSurvey.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  908. }
  909. else
  910. {
  911. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  912. trSurvey.targets = tn;
  913. foreach (string name in pa.gName)
  914. {
  915. //处理区级target
  916. string sName = pa.sName + "-" + name;
  917. allName.Add(sName);
  918. }
  919. }
  920. await getMoreSurvey(pa, trSurvey);
  921. if (string.IsNullOrEmpty(trSurvey.id))
  922. {
  923. trSurvey.id = Guid.NewGuid().ToString();
  924. trSurvey.recordUrl = $"/survey/{trSurvey.id}/record.json";
  925. var cods = new { records = new List<string>(), userids = new List<string>(), question = new List<QuestionRecord>() };
  926. await _azureStorage.UploadFileByContainer(code, cods.ToJsonString(), "survey", $"{trSurvey.id}/record.json");
  927. // trSurvey.blob = SurveyService.getBlob(trSurvey.id);
  928. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(trSurvey, new PartitionKey($"{trSurvey.code}"));
  929. }
  930. else
  931. {
  932. // trSurvey.blob = SurveyService.getBlob(trSurvey.id);
  933. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(trSurvey, new PartitionKey($"{trSurvey.code}"));
  934. }
  935. surveys.Add(trSurvey);
  936. }
  937. //areaSurvey.targets = allName;
  938. var atn = allName.ToJsonString().ToObject<List<JsonElement>>();
  939. areaSurvey.targets = atn;
  940. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(areaSurvey, new PartitionKey($"{areaSurvey.code}"));
  941. var ids = surveys.Select(s => new { s.id, s.school });
  942. return Ok(new { id, ids, code = (int)HttpStatusCode.OK });
  943. }
  944. catch (Exception ex)
  945. {
  946. await _dingDing.SendBotMsg($"OS,{_option.Location},area/save-survey()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  947. return BadRequest();
  948. }
  949. }
  950. /// <summary>
  951. /// 保存评测信息
  952. /// </summary>
  953. /// <param name="request"></param>
  954. /// <returns></returns>
  955. [ProducesDefaultResponseType]
  956. //[AuthToken(Roles = "teacher,admin")]
  957. [HttpPost("save-exam")]
  958. public async Task<IActionResult> SaveExam(JsonElement request)
  959. {
  960. try
  961. {
  962. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  963. if (!request.TryGetProperty("para", out JsonElement para)) return BadRequest();
  964. if (!request.TryGetProperty("exam", out JsonElement exam)) return BadRequest();
  965. List<parameter> parameters = para.ToObject<List<parameter>>();
  966. List<ExamLite> exams = new();
  967. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  968. var client = _azureCosmos.GetCosmosClient();
  969. ExamLite areaExam = exam.ToObject<ExamLite>();
  970. areaExam.owner = "area";
  971. areaExam.ttl = -1;
  972. areaExam.code = "TrExam-" + id.GetString();
  973. areaExam.createTime = now;
  974. if (string.IsNullOrEmpty(areaExam.id))
  975. {
  976. areaExam.id = Guid.NewGuid().ToString();
  977. }
  978. List<string> allName = new();
  979. foreach (parameter pa in parameters)
  980. {
  981. ExamLite trExam = exam.ToObject<ExamLite>();
  982. string code = pa.sId;
  983. trExam.ttl = -1;
  984. trExam.school = code;
  985. trExam.code = "TrExam-" + code;
  986. trExam.createTime = now;
  987. trExam.areaId = id.GetString();
  988. trExam.owner = "area";
  989. trExam.pId = areaExam.id;
  990. trExam.targetType = "research";
  991. if (pa.gName.Count == 0)
  992. {
  993. string sName = pa.sName + "-" + "所有老师(未分组)";
  994. allName.Add(sName);
  995. }
  996. else
  997. {
  998. foreach (string name in pa.gName)
  999. {
  1000. //处理区级target
  1001. string sName = pa.sName + "-" + name;
  1002. allName.Add(sName);
  1003. }
  1004. }
  1005. await getMoreExam(pa, trExam);
  1006. if (string.IsNullOrEmpty(trExam.id))
  1007. {
  1008. trExam.id = Guid.NewGuid().ToString();
  1009. // trExam.blob = ExamService.getBlob(trExam.id);
  1010. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(trExam, new PartitionKey($"{trExam.code}"));
  1011. }
  1012. else
  1013. {
  1014. //trExam.blob = ExamService.getBlob(trExam.id);
  1015. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(trExam, trExam.id, new PartitionKey($"{trExam.code}"));
  1016. }
  1017. exams.Add(trExam);
  1018. }
  1019. //areaExam.targets = allName;
  1020. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(areaExam, new PartitionKey($"{areaExam.code}"));
  1021. var ids = exams.Select(s => new { s.id, s.school });
  1022. return Ok(new { id, ids, code = (int)HttpStatusCode.OK });
  1023. }
  1024. catch (Exception ex)
  1025. {
  1026. await _dingDing.SendBotMsg($"OS,{_option.Location},area/save-exam()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1027. return BadRequest();
  1028. }
  1029. }
  1030. private async Task<List<string>> getId(CosmosClient client, string id)
  1031. {
  1032. //获取区级以下所有学校编码和基础信息
  1033. List<string> baseIds = new();
  1034. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"select c.id from c where c.areaId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  1035. {
  1036. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1037. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1038. {
  1039. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1040. while (accounts.MoveNext())
  1041. {
  1042. JsonElement account = accounts.Current;
  1043. baseIds.Add(account.GetProperty("id").GetString());
  1044. }
  1045. }
  1046. }
  1047. return baseIds;
  1048. }
  1049. private async Task<List<teacherInfo>> GetTeacherAll(string name, string code)
  1050. {
  1051. var client = _azureCosmos.GetCosmosClient();
  1052. string query = string.Empty;
  1053. List<teacherInfo> teachers = new List<teacherInfo>();
  1054. if (string.IsNullOrEmpty(name))
  1055. {
  1056. query = $"SELECT c.id, c.name, c.groupName FROM c ";
  1057. }
  1058. else
  1059. {
  1060. query = $"SELECT c.id, c.name, c.groupName FROM c where c.groupName = '{name}'";
  1061. }
  1062. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<teacherInfo>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{code}") }))
  1063. {
  1064. teachers.Add(item);
  1065. }
  1066. return teachers;
  1067. }
  1068. private Task<ExamLite> getMoreExam(parameter pa, ExamLite trExam)
  1069. {
  1070. if (pa.gName.Count == 0)
  1071. {
  1072. string json = "所有老师(未分组)";
  1073. trExam.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  1074. }
  1075. else
  1076. {
  1077. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  1078. trExam.targets = tn;
  1079. }
  1080. return Task.FromResult(trExam);
  1081. }
  1082. private Task<Survey> getMoreSurvey(parameter pa, Survey trSurvey)
  1083. {
  1084. if (pa.gName.Count == 0)
  1085. {
  1086. //trSurvey.targets.Add("所有老师(未分组)");
  1087. string json = "所有老师(未分组)";
  1088. trSurvey.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  1089. }
  1090. else
  1091. {
  1092. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  1093. trSurvey.targets = tn;
  1094. }
  1095. return Task.FromResult(trSurvey);
  1096. }
  1097. private async Task<List<(string id, string name)>> getInfo(CosmosClient client, string id) {
  1098. List<(string id, string name)> scInfos = new List<(string id, string name)>();
  1099. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"select c.id,c.name from c where c.areaId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
  1100. {
  1101. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1102. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1103. {
  1104. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1105. while (accounts.MoveNext())
  1106. {
  1107. JsonElement account = accounts.Current;
  1108. scInfos.Add((account.GetProperty("id").GetString(), account.GetProperty("name").GetString()));
  1109. }
  1110. }
  1111. }
  1112. return scInfos;
  1113. }
  1114. public class parameter
  1115. {
  1116. public string sId { get; set; }
  1117. public string sName { get; set; }
  1118. public List<string> gName { get; set; }
  1119. public List<string> gId { get; set; }
  1120. }
  1121. public class teacherInfo
  1122. {
  1123. public string id { get; set; }
  1124. public string name { get; set; }
  1125. public string groupName { get; set; }
  1126. }
  1127. }
  1128. }