AreaController.cs 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277
  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.scope = "school";
  227. study.targetType = "research";
  228. if (pa.gName.Count == 0)
  229. {
  230. string sName = pa.sName + "-" + "所有老师(未分组)";
  231. allName.Add(sName);
  232. string json = "所有老师(未分组)";
  233. study.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  234. //study.targets.Add("所有老师(未分组)");
  235. }
  236. else
  237. {
  238. //study.targets = pa.gName;
  239. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  240. study.targets = tn;
  241. foreach (string name in pa.gName)
  242. {
  243. //处理区级target
  244. string sName = pa.sName + "-" + name;
  245. allName.Add(sName);
  246. }
  247. }
  248. foreach (string setting in study.settings)
  249. {
  250. if (setting.Equals("exam"))
  251. {
  252. if (!request.TryGetProperty("exam", out JsonElement exam)) return BadRequest();
  253. ExamLite trExam = exam.ToObject<ExamLite>();
  254. trExam.owner = "area";
  255. trExam.school = pa.sId;
  256. trExam.areaId = id.GetString();
  257. trExam.tchLists = pa.gId;
  258. trExam.scope = "school";
  259. trExam.targetType = "research";
  260. trExam.blob = $"/{trExam.areaId}/exam/{study.pId}/index.json";
  261. //处理发布对象
  262. await getMoreExam(pa, trExam);
  263. //保存更多得评测信息
  264. string eId = await ExamService.saveMoreAsync(client, _dingDing, trExam);
  265. if (string.IsNullOrEmpty(eId))
  266. {
  267. return Ok(new { code = (int)HttpStatusCode.BadRequest, msg = "评测信息异常" });
  268. }
  269. else
  270. {
  271. study.examId = eId;
  272. }
  273. }
  274. if (setting.Equals("survey"))
  275. {
  276. if (!request.TryGetProperty("survey", out JsonElement survey)) return BadRequest();
  277. Survey trSurvey = survey.ToObject<Survey>();
  278. trSurvey.owner = "area";
  279. trSurvey.school = pa.sId;
  280. trSurvey.areaId = id.GetString();
  281. trSurvey.tchLists = pa.gId;
  282. trSurvey.scope = "school";
  283. trSurvey.targetType = "research";
  284. trSurvey.blob = $"/{trSurvey.areaId}/survey/{study.pId}/index.json";
  285. await getMoreSurvey(pa, trSurvey);
  286. string surveyId = await SurveyService.saveMoreAsync(client, _dingDing, trSurvey);
  287. if (string.IsNullOrEmpty(surveyId))
  288. {
  289. return Ok(new { code = (int)HttpStatusCode.BadRequest, msg = "问卷信息异常" });
  290. }
  291. else
  292. {
  293. study.surveyId = surveyId;
  294. }
  295. }
  296. if (setting.Equals("work"))
  297. {
  298. if (!request.TryGetProperty("work", out JsonElement work)) return BadRequest();
  299. TeacherWork teacherWork = work.ToObject<TeacherWork>();
  300. teacherWork.owner = "area";
  301. teacherWork.school = pa.sId;
  302. teacherWork.areaId = id.GetString();
  303. teacherWork.tchLists = pa.gId;
  304. teacherWork.scope = "school";
  305. teacherWork.targetType = "research";
  306. teacherWork.blob = $"/{teacherWork.areaId}/survey/{study.pId}/index.json";
  307. await getMoreWork(pa, teacherWork);
  308. string workId = await TeacherWorkService.saveMoreAsync(client, _dingDing, teacherWork);
  309. if (string.IsNullOrEmpty(workId))
  310. {
  311. return Ok(new { code = (int)HttpStatusCode.BadRequest, msg = "作业活动异常" });
  312. }
  313. else
  314. {
  315. study.workId = workId;
  316. }
  317. }
  318. }
  319. if (string.IsNullOrEmpty(study.id))
  320. {
  321. study.id = Guid.NewGuid().ToString();
  322. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(study, new PartitionKey($"{study.code}"));
  323. }
  324. else
  325. {
  326. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(study, new PartitionKey($"{study.code}"));
  327. }
  328. studies.Add(study);
  329. }
  330. //areaStudy.targets = allName;
  331. var atn = allName.ToJsonString().ToObject<List<JsonElement>>();
  332. areaStudy.targets = atn;
  333. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(areaStudy, new PartitionKey($"{areaStudy.code}"));
  334. var ids = studies.Select(s => new { s.id, s.school, s.examId, s.surveyId });
  335. return Ok(new { id, ids, code = (int)HttpStatusCode.OK, acId = areaStudy.id });
  336. }
  337. catch (Exception ex)
  338. {
  339. await _dingDing.SendBotMsg($"OS,{_option.Location},area/save-study()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  340. return BadRequest();
  341. }
  342. }
  343. /// <param name="request"></param>
  344. /// <returns></returns>
  345. [ProducesDefaultResponseType]
  346. //[AuthToken(Roles = "Teacher")]
  347. [HttpPost("find-all-study")]
  348. public async Task<IActionResult> FindAllStudy(JsonElement requert)
  349. {
  350. try
  351. {
  352. //区级Id
  353. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  354. var client = _azureCosmos.GetCosmosClient();
  355. // List<string> baseIds = await getId(client, id.GetString());
  356. List<object> studies = new();
  357. 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 ";
  358. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{id}") }))
  359. {
  360. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  361. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  362. {
  363. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  364. {
  365. studies.Add(obj.ToObject<object>());
  366. }
  367. }
  368. }
  369. return Ok(new { studies });
  370. }
  371. catch (Exception e)
  372. {
  373. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-study()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  374. return BadRequest();
  375. }
  376. }
  377. [ProducesDefaultResponseType]
  378. //[AuthToken(Roles = "Teacher")]
  379. [HttpPost("find-all-study-teachers")]
  380. public async Task<IActionResult> FindAllStudyTeacher(JsonElement requert)
  381. {
  382. try
  383. {
  384. //区级活动Id
  385. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  386. if (!requert.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
  387. var client = _azureCosmos.GetCosmosClient();
  388. List<(string id, string name)> baseIds = await getId(client, areaId.GetString());
  389. List<Study> studies = new();
  390. List<(string id, string name)> ps = await getInfo(client, areaId.GetString());
  391. //List<string> aName = new();
  392. var query = $"select value(c) from c where c.pId = '{id}'";
  393. foreach ((string code,string name) in baseIds)
  394. {
  395. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<Study>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{code}") }))
  396. {
  397. studies.Add(item);
  398. }
  399. }
  400. List<(List<TmdInfo> teac, Survey sur)> trSurveys = new List<(List<TmdInfo> teac, Survey sur)>();
  401. List<(List<TmdInfo> teac, ExamLite examLite)> trExams = new List<(List<TmdInfo> teac, ExamLite examLite)>();
  402. List<(List<TmdInfo> teac, Study stu)> moreInfo = new List<(List<TmdInfo> teac, Study stu)>();
  403. List<(List<TmdInfo> teac, TeacherWork tw)> works = new List<(List<TmdInfo> teac, TeacherWork tw)>();
  404. foreach (Study study in studies)
  405. {
  406. (List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, study.tchLists, study.school);
  407. if (!string.IsNullOrEmpty(study.surveyId))
  408. {
  409. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(study.surveyId, new PartitionKey($"Survey-{study.school}"));
  410. if (sresponse.Status == 200)
  411. {
  412. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  413. Survey surs = json.ToObject<Survey>();
  414. trSurveys.Add((tchList, surs));
  415. }
  416. }
  417. if (!string.IsNullOrEmpty(study.examId))
  418. {
  419. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(study.examId, new PartitionKey($"ExamLite-{study.school}"));
  420. if (sresponse.Status == 200)
  421. {
  422. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  423. ExamLite lite = json.ToObject<ExamLite>();
  424. trExams.Add((tchList, lite));
  425. }
  426. }
  427. if (!string.IsNullOrEmpty(study.workId))
  428. {
  429. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(study.examId, new PartitionKey($"TeacherWork-{study.school}"));
  430. if (sresponse.Status == 200)
  431. {
  432. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  433. TeacherWork work = json.ToObject<TeacherWork>();
  434. works.Add((tchList, work));
  435. }
  436. }
  437. moreInfo.Add((tchList, study));
  438. };
  439. var survey = trSurveys.Select(s => new
  440. {
  441. count = s.teac.Count,
  442. ansCount = s.sur.answers.Count,
  443. });
  444. var twork = works.Select(s => new
  445. {
  446. count = s.teac.Count,
  447. ansCount = s.tw.teachers.Where(h => !string.IsNullOrEmpty(h.hw)).ToList().Count,
  448. });
  449. var exam = trExams.Select(s => new
  450. {
  451. count = s.teac.Count,
  452. ansCount = s.examLite.teachers.Where(h => h.answer.Count > 0).ToList().Count,
  453. });
  454. var info = moreInfo.Select(s => new
  455. {
  456. s.stu.id,
  457. name = ps.FirstOrDefault(c => c.id == s.stu.id).name,
  458. count = s.teac.Count,
  459. //hwCount = s.teachers.Where(h => h.hwTime > 0).ToList().Count,
  460. signCount = s.stu.teachers.Where(h => h.signTime > 0).ToList().Count,
  461. lateCount = s.stu.teachers.Where(h => !string.IsNullOrEmpty(h.sign) && h.sign.Equals("1")).ToList().Count,
  462. acount = s.stu.teachers.Where(h => h.aTime > 0).ToList().Count
  463. });
  464. return Ok(new { survey, exam, info, studies = moreInfo.Select(m => new { m.teac, m.stu }) });
  465. }
  466. catch (Exception e)
  467. {
  468. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-study-teachers()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  469. return BadRequest();
  470. }
  471. }
  472. [ProducesDefaultResponseType]
  473. //[AuthToken(Roles = "Teacher")]
  474. [HttpPost("find-all-vote")]
  475. public async Task<IActionResult> FindAllVote(JsonElement requert)
  476. {
  477. try
  478. {
  479. //区级Id
  480. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  481. var client = _azureCosmos.GetCosmosClient();
  482. //List<string> baseIds = await getId(client, id.GetString());
  483. List<object> votes = new();
  484. //List<string> aName = new();
  485. var query = $"select c.id,c.name,c.startTime,c.progress,c.owner,c.school from c ";
  486. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{id}") }))
  487. {
  488. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  489. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  490. {
  491. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  492. {
  493. votes.Add(obj.ToObject<object>());
  494. }
  495. }
  496. }
  497. return Ok(new { votes });
  498. }
  499. catch (Exception e)
  500. {
  501. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-vote()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  502. return BadRequest();
  503. }
  504. }
  505. [ProducesDefaultResponseType]
  506. //[AuthToken(Roles = "Teacher")]
  507. [HttpPost("find-vote-id")]
  508. public async Task<IActionResult> FindAllVoteTeacher(JsonElement requert)
  509. {
  510. try
  511. {
  512. //区级活动Id
  513. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  514. if (!requert.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
  515. var client = _azureCosmos.GetCosmosClient();
  516. List<(string id, string name)> baseIds = await getId(client, areaId.GetString());
  517. //List<object> votes = new();
  518. List<(string id, string name)> ps = await getInfo(client, areaId.GetString());
  519. //List<string> aName = new();
  520. List<Vote> votes = new List<Vote>();
  521. Vote vote = null;
  522. List<(string code,string name, string url, int count)> recordUrl = new List<(string code, string name, string url, int count)>();
  523. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.GetString(), new PartitionKey($"Vote-{areaId}"));
  524. if (response.Status == 200)
  525. {
  526. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  527. vote = json.ToObject<Vote>();
  528. var query = $"select c.tchLists,c.recordUrl from c where c.pId = '{id}'";
  529. foreach ((string code, string name) in baseIds)
  530. {
  531. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Vote-{code}") }))
  532. {
  533. using var sjson = await JsonDocument.ParseAsync(item.ContentStream);
  534. if (sjson.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  535. {
  536. var accounts = sjson.RootElement.GetProperty("Documents").EnumerateArray();
  537. while (accounts.MoveNext())
  538. {
  539. JsonElement account = accounts.Current;
  540. List<string> tcs = account.GetProperty("tchLists").ToObject<List<string>>();
  541. (List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, tcs, code);
  542. recordUrl.Add((code,name, account.GetProperty("recordUrl").GetString(), tchList.Count));
  543. }
  544. }
  545. }
  546. }
  547. }
  548. //var info = ps.Select(p => new { p.id, p.name });
  549. return Ok(new { vote, code = recordUrl.Select(r => new { r.code,r.name, r.url, r.count }) });
  550. }
  551. catch (Exception e)
  552. {
  553. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-vote-teachers()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  554. return BadRequest();
  555. }
  556. }
  557. [ProducesDefaultResponseType]
  558. //[AuthToken(Roles = "Teacher")]
  559. [HttpPost("find-all-survey")]
  560. public async Task<IActionResult> FindAllSurvey(JsonElement requert)
  561. {
  562. try
  563. {
  564. //区级Id
  565. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  566. var client = _azureCosmos.GetCosmosClient();
  567. //List<string> baseIds = await getId(client, id.GetString());
  568. List<object> surveys = new();
  569. // List<string> aName = new();
  570. var query = $"select c.id,c.name,c.startTime,c.progress,c.sType,c.owner,c.school from c ";
  571. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{id}") }))
  572. {
  573. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  574. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  575. {
  576. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  577. {
  578. surveys.Add(obj.ToObject<object>());
  579. }
  580. }
  581. }
  582. return Ok(new { surveys });
  583. }
  584. catch (Exception e)
  585. {
  586. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-survey()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  587. return BadRequest();
  588. }
  589. }
  590. [ProducesDefaultResponseType]
  591. //[AuthToken(Roles = "Teacher")]
  592. [HttpPost("find-survey-id")]
  593. public async Task<IActionResult> FindAllSurveyTeacher(JsonElement requert)
  594. {
  595. try
  596. {
  597. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  598. if (!requert.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
  599. var client = _azureCosmos.GetCosmosClient();
  600. List<(string id, string name)> baseIds = await getId(client, areaId.GetString());
  601. List<object> surveys = new();
  602. Survey survey = null;
  603. List<(string code, string name,string url, int count)> recordUrl = new List<(string code, string name,string url, int count)>();
  604. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.GetString(), new PartitionKey($"Survey-{areaId}"));
  605. if (response.Status == 200)
  606. {
  607. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  608. survey = json.ToObject<Survey>();
  609. var query = $"select c.tchLists,c.recordUrl from c where c.pId = '{id}'";
  610. foreach ((string code, string name) in baseIds)
  611. {
  612. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Survey-{code}") }))
  613. {
  614. using var sjson = await JsonDocument.ParseAsync(item.ContentStream);
  615. if (sjson.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  616. {
  617. var accounts = sjson.RootElement.GetProperty("Documents").EnumerateArray();
  618. while (accounts.MoveNext())
  619. {
  620. JsonElement account = accounts.Current;
  621. List<string> tcs = account.GetProperty("tchLists").ToObject<List<string>>();
  622. (List<TmdInfo> tchList, _) = await TriggerStuActivity.GetTchList(client, _dingDing, tcs, code);
  623. recordUrl.Add((code, name,account.GetProperty("recordUrl").GetString(), tchList.Count));
  624. }
  625. }
  626. }
  627. }
  628. }
  629. //var info = ps.Select(p => new { p.id, p.name });
  630. return Ok(new { survey, code = recordUrl.Select(r => new { r.code,r.name, r.url, r.count }) });
  631. }
  632. catch (Exception e)
  633. {
  634. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-survey-teachers()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  635. return BadRequest();
  636. }
  637. }
  638. [ProducesDefaultResponseType]
  639. //[AuthToken(Roles = "Teacher")]
  640. [HttpPost("find-all-Exam")]
  641. public async Task<IActionResult> FindAllExam(JsonElement requert)
  642. {
  643. try
  644. {
  645. //区级Id
  646. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  647. var client = _azureCosmos.GetCosmosClient();
  648. //List<string> baseIds = await getId(client, id.GetString());
  649. List<object> exams = new();
  650. // List<string> aName = new();
  651. var query = $"select c.id,c.name,c.createTime,c.sType,c.owner,c.school from c ";
  652. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamLite-{id}") }))
  653. {
  654. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  655. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  656. {
  657. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  658. {
  659. exams.Add(obj.ToObject<object>());
  660. }
  661. }
  662. }
  663. return Ok(new { exams });
  664. }
  665. catch (Exception e)
  666. {
  667. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-exam()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  668. return BadRequest();
  669. }
  670. }
  671. [ProducesDefaultResponseType]
  672. //[AuthToken(Roles = "Teacher")]
  673. [HttpPost("find-all-exam-teachers")]
  674. public async Task<IActionResult> FindAllExamTeacher(JsonElement requert)
  675. {
  676. try
  677. {
  678. //区级活动Id
  679. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  680. if (!requert.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
  681. var client = _azureCosmos.GetCosmosClient();
  682. List<(string id, string name)> baseIds = await getId(client, areaId.GetString());
  683. List<object> exams = new();
  684. List<(string id, string name)> ps = await getInfo(client, areaId.GetString());
  685. //List<string> aName = new();
  686. var query = $"select c.school,c.teachers from c where c.acId = '{id}'";
  687. foreach ((string code, string name) in baseIds)
  688. {
  689. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TrExam-{code}") }))
  690. {
  691. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  692. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  693. {
  694. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  695. {
  696. exams.Add(obj.ToObject<object>());
  697. }
  698. }
  699. }
  700. }
  701. var info = ps.Select(p => new { p.id, p.name });
  702. return Ok(new { info, exams });
  703. }
  704. catch (Exception e)
  705. {
  706. await _dingDing.SendBotMsg($"OS,{_option.Location},area/find-all-exam-teachers()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  707. return BadRequest();
  708. }
  709. }
  710. /// <summary>
  711. /// 保存投票信息
  712. /// </summary>
  713. /// <param name="request"></param>
  714. /// <returns></returns>
  715. [ProducesDefaultResponseType]
  716. //[AuthToken(Roles = "teacher,admin")]
  717. [HttpPost("save-vote")]
  718. public async Task<IActionResult> SaveVote(JsonElement request)
  719. {
  720. try
  721. {
  722. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  723. if (!request.TryGetProperty("para", out JsonElement para)) return BadRequest();
  724. if (!request.TryGetProperty("vote", out JsonElement vote)) return BadRequest();
  725. List<parameter> parameters = para.ToObject<List<parameter>>();
  726. List<Vote> votes = new();
  727. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  728. var client = _azureCosmos.GetCosmosClient();
  729. Vote areaVote = vote.ToObject<Vote>();
  730. areaVote.owner = "area";
  731. areaVote.ttl = -1;
  732. areaVote.code = "Vote-" + id.GetString();
  733. areaVote.createTime = now;
  734. if (areaVote.startTime <= 0)
  735. {
  736. areaVote.startTime = now;
  737. }
  738. if (areaVote.startTime > now)
  739. {
  740. areaVote.progress = "pending";
  741. }
  742. else
  743. {
  744. areaVote.progress = "going";
  745. }
  746. if (string.IsNullOrEmpty(areaVote.id))
  747. {
  748. areaVote.id = Guid.NewGuid().ToString();
  749. }
  750. List<string> allName = new();
  751. foreach (parameter pa in parameters)
  752. {
  753. Vote trVote = vote.ToObject<Vote>();
  754. string code = pa.sId;
  755. trVote.school = code;
  756. trVote.ttl = -1;
  757. trVote.code = "Vote-" + code;
  758. trVote.createTime = now;
  759. trVote.areaId = id.GetString();
  760. trVote.owner = "area";
  761. trVote.pId = areaVote.id;
  762. trVote.tchLists = pa.gId;
  763. trVote.targetType = "research";
  764. if (trVote.startTime <= 0)
  765. {
  766. trVote.startTime = now;
  767. }
  768. if (trVote.startTime > now)
  769. {
  770. trVote.progress = "pending";
  771. }
  772. else
  773. {
  774. trVote.progress = "going";
  775. }
  776. if (pa.gName.Count == 0)
  777. {
  778. string sName = pa.sName + "-" + "所有老师(未分组)";
  779. allName.Add(sName);
  780. string json = "所有老师(未分组)";
  781. //var json = new { name = "所有老师(未分组)" };
  782. trVote.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  783. }
  784. else
  785. {
  786. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  787. trVote.targets = tn;
  788. foreach (string name in pa.gName)
  789. {
  790. //处理区级target
  791. string sName = pa.sName + "-" + name;
  792. allName.Add(sName);
  793. }
  794. }
  795. if (string.IsNullOrEmpty(trVote.id))
  796. {
  797. trVote.id = Guid.NewGuid().ToString();
  798. string url = $"/vote/{trVote.id}/record.json";
  799. trVote.recordUrl = url;
  800. await _azureStorage.UploadFileByContainer(code, new { options = new List<string>(), records = new List<VoteRecord>() }.ToJsonString(), "vote", $"{trVote.id}/record.json");
  801. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(trVote, new PartitionKey($"{trVote.code}"));
  802. }
  803. else
  804. {
  805. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(trVote, trVote.id, new PartitionKey($"{trVote.code}"));
  806. }
  807. votes.Add(trVote);
  808. }
  809. var atn = allName.ToJsonString().ToObject<List<JsonElement>>();
  810. /*List<JsonElement> atn = new List<JsonElement>();
  811. foreach (string agn in allName)
  812. {
  813. atn.Add(agn.ToObject<JsonElement>());
  814. }*/
  815. areaVote.targets = atn;
  816. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(areaVote, new PartitionKey($"{areaVote.code}"));
  817. var ids = votes.Select(s => new { s.id, s.school });
  818. return Ok(new { id, ids, code = (int)HttpStatusCode.OK });
  819. }
  820. catch (Exception ex)
  821. {
  822. await _dingDing.SendBotMsg($"OS,{_option.Location},area/save-vote()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  823. return BadRequest();
  824. }
  825. }
  826. [ProducesDefaultResponseType]
  827. //[AuthToken(Roles = "Teacher")]
  828. [HttpPost("delete")]
  829. public async Task<IActionResult> Delete(JsonElement request)
  830. {
  831. try
  832. {
  833. //区级活动Id
  834. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  835. //区级id
  836. if (!request.TryGetProperty("areaId", out JsonElement code)) return BadRequest();
  837. if (!request.TryGetProperty("pk", out JsonElement pk)) return BadRequest();
  838. var client = _azureCosmos.GetCosmosClient();
  839. var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{pk}-{code}"));
  840. List<(string id, string name)> bascId = await getId(client, code.GetString());
  841. List<(string id, string name)> ids = new();
  842. foreach ((string sId, string name) in bascId)
  843. {
  844. 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}") }))
  845. {
  846. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  847. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  848. {
  849. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  850. while (accounts.MoveNext())
  851. {
  852. JsonElement account = accounts.Current;
  853. ids.Add((account.GetProperty("id").GetString(), account.GetProperty("code").GetString()));
  854. }
  855. }
  856. }
  857. }
  858. if (ids.Count > 0)
  859. {
  860. foreach ((string s, string c) in ids)
  861. {
  862. if (c.Contains("Study"))
  863. {
  864. var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(s.ToString(), new PartitionKey($"{c}"));
  865. if (sresponse.Status == 200)
  866. {
  867. using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
  868. Study study = json.ToObject<Study>();
  869. if (!string.IsNullOrEmpty(study.examId))
  870. {
  871. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(study.examId, new PartitionKey($"ExamLite-{study.school}"));
  872. }
  873. if (!string.IsNullOrEmpty(study.surveyId))
  874. {
  875. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(study.surveyId, new PartitionKey($"Survey-{study.school}"));
  876. }
  877. }
  878. }
  879. await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(s.ToString(), new PartitionKey($"{c}"));
  880. }
  881. }
  882. return Ok(new { id, code = response.Status });
  883. }
  884. catch (Exception e)
  885. {
  886. await _dingDing.SendBotMsg($"OS,{_option.Location},area/delete()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  887. return BadRequest();
  888. }
  889. }
  890. /// <summary>
  891. /// 保存问卷信息
  892. /// </summary>
  893. /// <param name="request"></param>
  894. /// <returns></returns>
  895. [ProducesDefaultResponseType]
  896. //[AuthToken(Roles = "teacher,admin")]
  897. [HttpPost("save-survey")]
  898. public async Task<IActionResult> SaveSurvey(JsonElement request)
  899. {
  900. try
  901. {
  902. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  903. if (!request.TryGetProperty("para", out JsonElement para)) return BadRequest();
  904. if (!request.TryGetProperty("survey", out JsonElement survey)) return BadRequest();
  905. List<parameter> parameters = para.ToObject<List<parameter>>();
  906. List<Survey> surveys = new();
  907. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  908. var client = _azureCosmos.GetCosmosClient();
  909. Survey areaSurvey = survey.ToObject<Survey>();
  910. areaSurvey.owner = "area";
  911. areaSurvey.ttl = -1;
  912. areaSurvey.code = "Survey-" + id.GetString();
  913. areaSurvey.createTime = now;
  914. if (areaSurvey.startTime <= 0)
  915. {
  916. areaSurvey.startTime = now;
  917. }
  918. if (areaSurvey.startTime > now)
  919. {
  920. areaSurvey.progress = "pending";
  921. }
  922. else
  923. {
  924. areaSurvey.progress = "going";
  925. }
  926. if (string.IsNullOrEmpty(areaSurvey.id))
  927. {
  928. areaSurvey.id = Guid.NewGuid().ToString();
  929. }
  930. List<string> allName = new();
  931. foreach (parameter pa in parameters)
  932. {
  933. Survey trSurvey = survey.ToObject<Survey>();
  934. string code = pa.sId;
  935. trSurvey.ttl = -1;
  936. trSurvey.school = code;
  937. trSurvey.code = "Survey-" + code;
  938. trSurvey.createTime = now;
  939. trSurvey.areaId = id.GetString();
  940. trSurvey.owner = "area";
  941. trSurvey.tchLists = pa.gId;
  942. trSurvey.pId = areaSurvey.id;
  943. trSurvey.targetType = "research";
  944. if (areaSurvey.startTime <= 0)
  945. {
  946. areaSurvey.startTime = now;
  947. }
  948. if (trSurvey.startTime > now)
  949. {
  950. trSurvey.progress = "pending";
  951. }
  952. else
  953. {
  954. trSurvey.progress = "going";
  955. }
  956. if (pa.gName.Count == 0)
  957. {
  958. string sName = pa.sName + "-" + "所有老师(未分组)";
  959. allName.Add(sName);
  960. string json = "所有老师(未分组)";
  961. trSurvey.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  962. }
  963. else
  964. {
  965. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  966. trSurvey.targets = tn;
  967. foreach (string name in pa.gName)
  968. {
  969. //处理区级target
  970. string sName = pa.sName + "-" + name;
  971. allName.Add(sName);
  972. }
  973. }
  974. await getMoreSurvey(pa, trSurvey);
  975. if (string.IsNullOrEmpty(trSurvey.id))
  976. {
  977. trSurvey.id = Guid.NewGuid().ToString();
  978. trSurvey.recordUrl = $"/survey/{trSurvey.id}/record.json";
  979. var cods = new { records = new List<string>(), userids = new List<string>(), question = new List<QuestionRecord>() };
  980. await _azureStorage.UploadFileByContainer(code, cods.ToJsonString(), "survey", $"{trSurvey.id}/record.json");
  981. // trSurvey.blob = SurveyService.getBlob(trSurvey.id);
  982. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(trSurvey, new PartitionKey($"{trSurvey.code}"));
  983. }
  984. else
  985. {
  986. // trSurvey.blob = SurveyService.getBlob(trSurvey.id);
  987. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(trSurvey, new PartitionKey($"{trSurvey.code}"));
  988. }
  989. surveys.Add(trSurvey);
  990. }
  991. //areaSurvey.targets = allName;
  992. var atn = allName.ToJsonString().ToObject<List<JsonElement>>();
  993. areaSurvey.targets = atn;
  994. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(areaSurvey, new PartitionKey($"{areaSurvey.code}"));
  995. var ids = surveys.Select(s => new { s.id, s.school });
  996. return Ok(new { id, ids, code = (int)HttpStatusCode.OK });
  997. }
  998. catch (Exception ex)
  999. {
  1000. await _dingDing.SendBotMsg($"OS,{_option.Location},area/save-survey()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1001. return BadRequest();
  1002. }
  1003. }
  1004. /// <summary>
  1005. /// 保存评测信息
  1006. /// </summary>
  1007. /// <param name="request"></param>
  1008. /// <returns></returns>
  1009. [ProducesDefaultResponseType]
  1010. //[AuthToken(Roles = "teacher,admin")]
  1011. [HttpPost("save-exam")]
  1012. public async Task<IActionResult> SaveExam(JsonElement request)
  1013. {
  1014. try
  1015. {
  1016. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  1017. if (!request.TryGetProperty("para", out JsonElement para)) return BadRequest();
  1018. if (!request.TryGetProperty("exam", out JsonElement exam)) return BadRequest();
  1019. List<parameter> parameters = para.ToObject<List<parameter>>();
  1020. List<ExamLite> exams = new();
  1021. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  1022. var client = _azureCosmos.GetCosmosClient();
  1023. ExamLite areaExam = exam.ToObject<ExamLite>();
  1024. areaExam.owner = "area";
  1025. areaExam.ttl = -1;
  1026. areaExam.code = "TrExam-" + id.GetString();
  1027. areaExam.createTime = now;
  1028. if (string.IsNullOrEmpty(areaExam.id))
  1029. {
  1030. areaExam.id = Guid.NewGuid().ToString();
  1031. }
  1032. List<string> allName = new();
  1033. foreach (parameter pa in parameters)
  1034. {
  1035. ExamLite trExam = exam.ToObject<ExamLite>();
  1036. string code = pa.sId;
  1037. trExam.ttl = -1;
  1038. trExam.school = code;
  1039. trExam.code = "TrExam-" + code;
  1040. trExam.createTime = now;
  1041. trExam.areaId = id.GetString();
  1042. trExam.owner = "area";
  1043. trExam.pId = areaExam.id;
  1044. trExam.targetType = "research";
  1045. if (pa.gName.Count == 0)
  1046. {
  1047. string sName = pa.sName + "-" + "所有老师(未分组)";
  1048. allName.Add(sName);
  1049. }
  1050. else
  1051. {
  1052. foreach (string name in pa.gName)
  1053. {
  1054. //处理区级target
  1055. string sName = pa.sName + "-" + name;
  1056. allName.Add(sName);
  1057. }
  1058. }
  1059. await getMoreExam(pa, trExam);
  1060. if (string.IsNullOrEmpty(trExam.id))
  1061. {
  1062. trExam.id = Guid.NewGuid().ToString();
  1063. // trExam.blob = ExamService.getBlob(trExam.id);
  1064. await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(trExam, new PartitionKey($"{trExam.code}"));
  1065. }
  1066. else
  1067. {
  1068. //trExam.blob = ExamService.getBlob(trExam.id);
  1069. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(trExam, trExam.id, new PartitionKey($"{trExam.code}"));
  1070. }
  1071. exams.Add(trExam);
  1072. }
  1073. //areaExam.targets = allName;
  1074. await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(areaExam, new PartitionKey($"{areaExam.code}"));
  1075. var ids = exams.Select(s => new { s.id, s.school });
  1076. return Ok(new { id, ids, code = (int)HttpStatusCode.OK });
  1077. }
  1078. catch (Exception ex)
  1079. {
  1080. await _dingDing.SendBotMsg($"OS,{_option.Location},area/save-exam()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  1081. return BadRequest();
  1082. }
  1083. }
  1084. private async Task<List<(string id, string name)>> getId(CosmosClient client, string id)
  1085. {
  1086. //获取区级以下所有学校编码和基础信息
  1087. List<(string id,string name)> baseIds = new();
  1088. 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") }))
  1089. {
  1090. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1091. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1092. {
  1093. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1094. while (accounts.MoveNext())
  1095. {
  1096. JsonElement account = accounts.Current;
  1097. baseIds.Add((account.GetProperty("id").GetString(), account.GetProperty("name").GetString()));
  1098. }
  1099. }
  1100. }
  1101. return baseIds;
  1102. }
  1103. private async Task<List<teacherInfo>> GetTeacherAll(string name, string code)
  1104. {
  1105. var client = _azureCosmos.GetCosmosClient();
  1106. string query = string.Empty;
  1107. List<teacherInfo> teachers = new List<teacherInfo>();
  1108. if (string.IsNullOrEmpty(name))
  1109. {
  1110. query = $"SELECT c.id, c.name, c.groupName FROM c ";
  1111. }
  1112. else
  1113. {
  1114. query = $"SELECT c.id, c.name, c.groupName FROM c where c.groupName = '{name}'";
  1115. }
  1116. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<teacherInfo>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{code}") }))
  1117. {
  1118. teachers.Add(item);
  1119. }
  1120. return teachers;
  1121. }
  1122. private Task<ExamLite> getMoreExam(parameter pa, ExamLite trExam)
  1123. {
  1124. if (pa.gName.Count == 0)
  1125. {
  1126. string json = "所有老师(未分组)";
  1127. trExam.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  1128. }
  1129. else
  1130. {
  1131. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  1132. trExam.targets = tn;
  1133. }
  1134. return Task.FromResult(trExam);
  1135. }
  1136. private Task<Survey> getMoreSurvey(parameter pa, Survey trSurvey)
  1137. {
  1138. if (pa.gName.Count == 0)
  1139. {
  1140. //trSurvey.targets.Add("所有老师(未分组)");
  1141. string json = "所有老师(未分组)";
  1142. trSurvey.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  1143. }
  1144. else
  1145. {
  1146. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  1147. trSurvey.targets = tn;
  1148. }
  1149. return Task.FromResult(trSurvey);
  1150. }
  1151. private Task<TeacherWork> getMoreWork(parameter pa, TeacherWork work)
  1152. {
  1153. if (pa.gName.Count == 0)
  1154. {
  1155. //trSurvey.targets.Add("所有老师(未分组)");
  1156. string json = "所有老师(未分组)";
  1157. work.targets.Add(json.ToJsonString().ToObject<JsonElement>());
  1158. }
  1159. else
  1160. {
  1161. var tn = pa.gName.ToJsonString().ToObject<List<JsonElement>>();
  1162. work.targets = tn;
  1163. }
  1164. return Task.FromResult(work);
  1165. }
  1166. private async Task<List<(string id, string name)>> getInfo(CosmosClient client, string id)
  1167. {
  1168. List<(string id, string name)> scInfos = new List<(string id, string name)>();
  1169. 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") }))
  1170. {
  1171. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  1172. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1173. {
  1174. var accounts = json.RootElement.GetProperty("Documents").EnumerateArray();
  1175. while (accounts.MoveNext())
  1176. {
  1177. JsonElement account = accounts.Current;
  1178. scInfos.Add((account.GetProperty("id").GetString(), account.GetProperty("name").GetString()));
  1179. }
  1180. }
  1181. }
  1182. return scInfos;
  1183. }
  1184. public class parameter
  1185. {
  1186. public string sId { get; set; }
  1187. public string sName { get; set; }
  1188. public List<string> gName { get; set; }
  1189. public List<string> gId { get; set; }
  1190. }
  1191. public class teacherInfo
  1192. {
  1193. public string id { get; set; }
  1194. public string name { get; set; }
  1195. public string groupName { get; set; }
  1196. }
  1197. }
  1198. }