ItemController.cs 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122
  1. using Microsoft.AspNetCore.Mvc;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using TEAMModelOS.Models;
  7. using TEAMModelOS.SDK.DI;
  8. using System.Text.Json;
  9. using TEAMModelOS.SDK.Models;
  10. using Microsoft.AspNetCore.Http;
  11. using TEAMModelOS.SDK.Extension;
  12. using Azure.Cosmos;
  13. using System.Text;
  14. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  15. using Microsoft.Extensions.Options;
  16. using Azure.Messaging.ServiceBus;
  17. using Microsoft.Extensions.Configuration;
  18. using HTEXLib.COMM.Helpers;
  19. using StackExchange.Redis;
  20. using Microsoft.AspNetCore.Authorization;
  21. using TEAMModelOS.SDK.Services;
  22. namespace TEAMModelOS.Controllers
  23. {
  24. [ProducesResponseType(StatusCodes.Status200OK)]
  25. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  26. [Route("item")]
  27. [ApiController]
  28. public class ItemController : ControllerBase
  29. {
  30. private readonly SnowflakeId _snowflakeId;
  31. private readonly AzureCosmosFactory _azureCosmos;
  32. private readonly DingDing _dingDing;
  33. private readonly Option _option;
  34. private readonly AzureStorageFactory _azureStorage;
  35. private readonly AzureServiceBusFactory _serviceBus;
  36. private readonly AzureRedisFactory _azureRedis;
  37. public IConfiguration _configuration { get; set; }
  38. public ItemController(AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage,
  39. AzureRedisFactory azureRedis,AzureServiceBusFactory serviceBus, IConfiguration configuration)
  40. {
  41. _azureCosmos = azureCosmos;
  42. _snowflakeId = snowflakeId;
  43. _dingDing = dingDing;
  44. _option = option?.Value;
  45. _azureStorage = azureStorage;
  46. _serviceBus = serviceBus;
  47. _configuration = configuration;
  48. _azureRedis = azureRedis;
  49. }
  50. /// <summary>
  51. /// 参数{"periodId":"学段id","schoolCode":"学校编码"} 其中periodId 不填则是全部学段的。
  52. /// </summary>
  53. /// <param name="request"></param>
  54. /// <returns></returns>
  55. [ProducesDefaultResponseType]
  56. [HttpPost("cond-count")]
  57. public async Task<IActionResult> CondCount(JsonElement request) {
  58. try
  59. {
  60. var client = _azureCosmos.GetCosmosClient();
  61. request.TryGetProperty("periodId", out JsonElement periodId);
  62. request.TryGetProperty("schoolCode", out JsonElement schoolCode);
  63. request.TryGetProperty("tmdid", out JsonElement tmdid);
  64. if (!string.IsNullOrEmpty($"{periodId}") && !string.IsNullOrEmpty($"{schoolCode}"))
  65. {
  66. var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ItemCond:{schoolCode}", $"{periodId}");
  67. ItemCond itemCond = null;
  68. if (value != default && !value.IsNullOrEmpty)
  69. {
  70. itemCond = value.ToString().ToObject<ItemCond>();
  71. }
  72. else {
  73. List<ItemInfo> items = new List<ItemInfo>();
  74. var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field ,c.scope FROM c where c.periodId='{periodId}' and c.pid= null ";
  75. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{schoolCode}") }))
  76. {
  77. items.Add(item);
  78. }
  79. itemCond = new ItemCond()
  80. {
  81. id = $"{periodId}",
  82. code = $"ItemCond-{schoolCode}",
  83. pk = "ItemCond",
  84. ttl = -1,
  85. count = items.Count,
  86. grades = new List<GradeCount>(),
  87. subjects = new List<SubjectCount>()
  88. };
  89. items.ForEach(z =>
  90. {
  91. if (!string.IsNullOrEmpty(z.type))
  92. {
  93. ItemService.CountItemCond(z, null, itemCond);
  94. }
  95. });
  96. await _azureRedis.GetRedisClient(8).HashSetAsync($"ItemCond:{schoolCode}", $"{periodId}", itemCond.ToJsonString());
  97. }
  98. return Ok(new { itemConds = new List<ItemCond>() { itemCond } });
  99. }
  100. else if (!string.IsNullOrEmpty($"{schoolCode}"))
  101. {
  102. List<ItemCond> itemConds = new List<ItemCond>();
  103. School school =await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{schoolCode}", new PartitionKey("Base"));
  104. List<string> nocachePeriods = new List<string>();
  105. foreach (var period in school.period) {
  106. var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ItemCond:{schoolCode}", $"{period.id}");
  107. ItemCond itemCond = null;
  108. if (value != default && !value.IsNullOrEmpty)
  109. {
  110. itemCond = value.ToString().ToObject<ItemCond>();
  111. itemConds.Add(itemCond);
  112. }
  113. else {
  114. nocachePeriods.Add(period.id);
  115. }
  116. }
  117. string nocachePeriodsql = "";
  118. if (nocachePeriods.IsNotEmpty())
  119. {
  120. string sql = string.Join(',', nocachePeriods.Select(x => $"'{x}'"));
  121. nocachePeriodsql = $" and c.periodId in ({sql})";
  122. List<ItemInfo> items = new List<ItemInfo>();
  123. var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field,c.scope FROM c where c.pid= null {nocachePeriodsql}";
  124. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{schoolCode}") }))
  125. {
  126. items.Add(item);
  127. }
  128. var list = items.GroupBy(x => x.periodId).Select(y => new { key = y.Key, list = y.ToList() }).ToList();
  129. foreach (var z in list)
  130. {
  131. ItemCond cond = new ItemCond() { id = z.key, code = $"ItemCond-{school.id}", pk = "ItemCond", ttl = -1, count = z.list.Count, grades = new List<GradeCount>(), subjects = new List<SubjectCount>() };
  132. z.list.ForEach(y =>
  133. {
  134. if (!string.IsNullOrEmpty(y.type))
  135. {
  136. ItemService.CountItemCond(y, null, cond);
  137. }
  138. });
  139. await _azureRedis.GetRedisClient(8).HashSetAsync($"ItemCond:{schoolCode}", $"{z.key}", cond.ToJsonString());
  140. itemConds.Add(cond);
  141. }
  142. if (school != null)
  143. {
  144. foreach (var period in school.period)
  145. {
  146. var cond = itemConds.Find(x => x.id.Equals(period.id));
  147. if (cond == null)
  148. {
  149. ItemCond condn = new ItemCond() { id = period.id, code = $"ItemCond-{school.id}", pk = "ItemCond", ttl = -1, count = 0, grades = new List<GradeCount>(), subjects = new List<SubjectCount>() };
  150. itemConds.Add(condn);
  151. }
  152. }
  153. }
  154. }
  155. return Ok(new { itemConds = itemConds });
  156. }
  157. else if (!string.IsNullOrEmpty($"{tmdid}"))
  158. {
  159. var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ItemCond:ItemCond", $"{tmdid}");
  160. ItemCond itemCond = null;
  161. if (value != default && !value.IsNullOrEmpty)
  162. {
  163. itemCond = value.ToString().ToObject<ItemCond>();
  164. }
  165. else {
  166. List<ItemInfo> items = new List<ItemInfo>();
  167. var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field ,c.scope FROM c where c.pid= null ";
  168. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{tmdid}") }))
  169. {
  170. items.Add(item);
  171. }
  172. itemCond = new ItemCond() { id = $"{tmdid}", code = $"ItemCond", pk = "ItemCond", ttl = -1, count = items.Count };
  173. items.ForEach(z =>
  174. {
  175. if (!string.IsNullOrEmpty(z.type)) {
  176. ItemService.CountItemCond(z, null, itemCond);
  177. }
  178. });
  179. await _azureRedis.GetRedisClient(8).HashSetAsync($"ItemCond:ItemCond", $"{tmdid}", itemCond.ToJsonString());
  180. }
  181. return Ok(new { itemConds = new List<ItemCond>() { itemCond } });
  182. }
  183. else
  184. {
  185. return Ok(new { itemConds = new List<ItemCond>() { } });
  186. }
  187. }
  188. catch (CosmosException ex)
  189. {
  190. return Ok(new { itemConds = new List<ItemCond>() { } });
  191. }
  192. catch (Exception ex)
  193. {
  194. return Ok(new { itemConds = new List<ItemCond>() { } });
  195. }
  196. }
  197. [ProducesDefaultResponseType]
  198. [HttpPost("upsert-all")]
  199. [Authorize(Roles = "IES")]
  200. public async Task<IActionResult> UpsertAll(JsonElement request)
  201. {
  202. var ItemCondQueue = _configuration.GetValue<string>("Azure:ServiceBus:ItemCondQueue");
  203. var client = _azureCosmos.GetCosmosClient();
  204. List<ItemInfo> itemInfos = null;
  205. if (!request.TryGetProperty("itemInfos", out JsonElement items)) return BadRequest();
  206. if (!request.TryGetProperty("option", out JsonElement option)) return BadRequest();
  207. try
  208. {
  209. Dictionary<string, ItemCondDto> dict = new Dictionary<string, ItemCondDto>();
  210. itemInfos = items.ToObject<List<ItemInfo>>();
  211. foreach (var itemInfo in itemInfos) {
  212. itemInfo.ttl = -1;
  213. itemInfo.size = await _azureStorage.GetBlobContainerClient(itemInfo.code).GetBlobsSize($"item/{itemInfo.id}");
  214. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"item/{itemInfo.id}", name = $"{itemInfo.code}" }.ToJsonString());
  215. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  216. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  217. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  218. if (option.ToString().Equals("insert"))
  219. {
  220. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  221. if (!itemInfo.code.Contains("Item"))
  222. {
  223. itemInfo.code = "Item-" + itemInfo.code;
  224. }
  225. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  226. if (response.Status == 200)
  227. {
  228. return Ok();
  229. }
  230. else
  231. {
  232. if (itemInfo.scope.Equals("private"))
  233. {
  234. if (string.IsNullOrEmpty(itemInfo.pid))
  235. {
  236. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  237. {
  238. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}",filed= $"{itemInfo.code.Replace("Item-", "")}", scope= "private" });
  239. }
  240. }
  241. await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  242. }
  243. else
  244. {
  245. if (string.IsNullOrEmpty(itemInfo.pid))
  246. {
  247. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  248. {
  249. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}",filed=$"{itemInfo.periodId}", scope = "school" });
  250. }
  251. }
  252. await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  253. }
  254. }
  255. }
  256. else
  257. {
  258. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  259. if (itemInfo.scope.Equals("private"))
  260. {
  261. if (!itemInfo.code.Contains("Item"))
  262. {
  263. itemInfo.code = "Item-" + itemInfo.code;
  264. }
  265. if (string.IsNullOrEmpty(itemInfo.pid))
  266. {
  267. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  268. {
  269. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.code.Replace("Item-", "")}", scope = "private" });
  270. }
  271. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  272. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}"))
  273. {
  274. dict.Add($"{olditemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.code.Replace("Item-", "")}", scope = "private" });
  275. }
  276. }
  277. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  278. }
  279. else
  280. {
  281. if (!itemInfo.code.Contains("Item"))
  282. {
  283. itemInfo.code = "Item-" + itemInfo.code;
  284. }
  285. if (string.IsNullOrEmpty(itemInfo.pid))
  286. {
  287. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  288. {
  289. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.periodId}", scope = "school" });
  290. }
  291. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  292. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}"))
  293. {
  294. dict.Add($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.periodId}", scope = "school" });
  295. }
  296. }
  297. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  298. }
  299. }
  300. }
  301. var itemCondDtos= dict.Select(x => x.Value).ToList();
  302. var str = itemCondDtos.ToJsonString();
  303. var messageBlobItemCond = new ServiceBusMessage(str);
  304. await _serviceBus.GetServiceBusClient().SendMessageAsync(ItemCondQueue, messageBlobItemCond);
  305. return Ok(new { itemInfos });
  306. }
  307. catch (Exception ex)
  308. {
  309. await _dingDing.SendBotMsg($"OS,{_option.Location},item/upsert()\n{ex.Message}{ex.StackTrace}\n{request}", GroupNames.醍摩豆服務運維群組);
  310. return BadRequest();
  311. }
  312. }
  313. [ProducesDefaultResponseType]
  314. [HttpPost("upsert")]
  315. [Authorize(Roles = "IES")]
  316. public async Task<IActionResult> Upsert(JsonElement request)
  317. {
  318. var client = _azureCosmos.GetCosmosClient();
  319. if (!request.TryGetProperty("itemInfo", out JsonElement item)) return BadRequest();
  320. if (!request.TryGetProperty("option", out JsonElement option)) return BadRequest();
  321. try
  322. {
  323. Dictionary<string, ItemCondDto> dict = new Dictionary<string, ItemCondDto>();
  324. var ItemCondQueue = _configuration.GetValue<string>("Azure:ServiceBus:ItemCondQueue");
  325. ItemInfo itemInfo;
  326. itemInfo = item.ToObject<ItemInfo>();
  327. itemInfo.size = await _azureStorage.GetBlobContainerClient(itemInfo.code).GetBlobsSize($"item/{itemInfo.id}");
  328. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"item/{itemInfo.id}", name = $"{itemInfo.code}" }.ToJsonString());
  329. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  330. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  331. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  332. if (option.ToString().Equals("insert"))
  333. {
  334. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  335. if (!itemInfo.code.Contains("Item"))
  336. {
  337. itemInfo.code = "Item-" + itemInfo.code;
  338. }
  339. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  340. if (response.Status == 200)
  341. {
  342. return Ok();
  343. }
  344. else
  345. {
  346. if (itemInfo.scope.Equals("private"))
  347. {
  348. if (string.IsNullOrEmpty(itemInfo.pid))
  349. {
  350. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  351. {
  352. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.code.Replace("Item-", "")}", scope = "private" });
  353. }
  354. }
  355. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  356. }
  357. else
  358. {
  359. if (string.IsNullOrEmpty(itemInfo.pid))
  360. {
  361. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  362. {
  363. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.periodId}", scope = "school" });
  364. }
  365. }
  366. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  367. }
  368. }
  369. }
  370. else
  371. {
  372. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  373. if (itemInfo.scope.Equals("private"))
  374. {
  375. if (!itemInfo.code.Contains("Item"))
  376. {
  377. itemInfo.code = "Item-" + itemInfo.code;
  378. }
  379. if (string.IsNullOrEmpty(itemInfo.pid))
  380. {
  381. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  382. {
  383. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.code.Replace("Item-", "")}", scope = "private" });
  384. }
  385. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  386. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}"))
  387. {
  388. dict.Add($"{olditemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.code.Replace("Item-", "")}", scope = "private" });
  389. }
  390. }
  391. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  392. }
  393. else
  394. {
  395. if (!itemInfo.code.Contains("Item"))
  396. {
  397. itemInfo.code = "Item-" + itemInfo.code;
  398. }
  399. if (string.IsNullOrEmpty(itemInfo.pid))
  400. {
  401. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  402. {
  403. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.periodId}", scope = "school" });
  404. }
  405. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  406. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}"))
  407. {
  408. dict.Add($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.periodId}", scope = "school" });
  409. }
  410. }
  411. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  412. }
  413. }
  414. var itemCondDtos = dict.Select(x => x.Value).ToList();
  415. var str = itemCondDtos.ToJsonString();
  416. var messageBlobItemCond = new ServiceBusMessage(str);
  417. await _serviceBus.GetServiceBusClient().SendMessageAsync(ItemCondQueue, messageBlobItemCond);
  418. return Ok(new { itemInfo });
  419. }
  420. catch (Exception ex)
  421. {
  422. await _dingDing.SendBotMsg($"OS,{_option.Location},item/upsert()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  423. return BadRequest();
  424. }
  425. }
  426. /// <summary>
  427. //获取题目摘要信息
  428. /// </summary>
  429. /// <param name="request"></param>
  430. /// <returns></returns>
  431. [ProducesDefaultResponseType]
  432. //[AuthToken(Roles = "teacher")]
  433. [HttpPost("find-summary")]
  434. public async Task<IActionResult> FindSummary(JsonElement requert)
  435. {
  436. try
  437. {
  438. var client = _azureCosmos.GetCosmosClient();
  439. StringBuilder sql = new StringBuilder();
  440. sql.Append("select c.id, c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime from c ");
  441. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  442. /* if (!requert.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest();
  443. if (!requert.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();*/
  444. if (!requert.TryGetProperty("@DESC", out JsonElement desc)) return BadRequest();
  445. if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  446. List<object> summary = new List<object>();
  447. Dictionary<string, object> dict = new Dictionary<string, object>();
  448. /* dict.Add("@CURRPAGE", page.GetInt32());
  449. dict.Add("@PAGESIZE", size.GetInt32());*/
  450. dict.Add("@DESC", desc.ToString());
  451. if (requert.TryGetProperty("periodId", out JsonElement periodId))
  452. {
  453. dict.Add("periodId", periodId);
  454. }
  455. if (requert.TryGetProperty("subjectId", out JsonElement subjectId))
  456. {
  457. dict.Add("subjectId", subjectId);
  458. }
  459. if (requert.TryGetProperty("level", out JsonElement level))
  460. {
  461. dict.Add("level", level);
  462. }
  463. if (requert.TryGetProperty("type", out JsonElement type))
  464. {
  465. dict.Add("type", type);
  466. }
  467. if (requert.TryGetProperty("field", out JsonElement field))
  468. {
  469. dict.Add("field", field);
  470. }
  471. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  472. //List<object> items = new List<object>();
  473. if (scope.ToString().Equals("private"))
  474. {
  475. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  476. {
  477. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  478. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  479. {
  480. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  481. {
  482. summary.Add(obj.ToObject<object>());
  483. }
  484. }
  485. }
  486. }
  487. if (scope.ToString().Equals("school"))
  488. {
  489. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  490. {
  491. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  492. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  493. {
  494. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  495. {
  496. summary.Add(obj.ToObject<object>());
  497. }
  498. }
  499. }
  500. }
  501. return Ok(new { summary });
  502. }
  503. catch (Exception ex)
  504. {
  505. await _dingDing.SendBotMsg($"OS,{_option.Location},item/FindSummary()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  506. return BadRequest();
  507. }
  508. }
  509. /// <summary>
  510. /// 删除
  511. /// </summary>
  512. /// <param name="request"></param>
  513. /// <returns></returns>
  514. [ProducesDefaultResponseType]
  515. //[AuthToken(Roles = "teacher")]
  516. [HttpPost("delete")]
  517. [Authorize(Roles = "IES")]
  518. public async Task<IActionResult> Delete(JsonElement request)
  519. {
  520. try
  521. {
  522. Dictionary<string, ItemCondDto> dict = new Dictionary<string, ItemCondDto>();
  523. var ItemCondQueue = _configuration.GetValue<string>("Azure:ServiceBus:ItemCondQueue");
  524. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  525. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  526. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  527. var client = _azureCosmos.GetCosmosClient();
  528. //删除blob 相关资料
  529. await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, code.ToString().Replace("Item-",""),new List<string> { $"item/{id}" });
  530. //通知删除信息
  531. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "delete", root = $"item/{id}", name = code.ToString().Replace("Item-", "") }.ToJsonString());
  532. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  533. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  534. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  535. if (scope.ToString().Equals("school"))
  536. {
  537. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>($"{id}", new PartitionKey($"{code}"));
  538. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}"))
  539. {
  540. dict.Add($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.periodId}", scope = "school" });
  541. }
  542. var itemCondDtos = dict.Select(x => x.Value).ToList();
  543. var str = itemCondDtos.ToJsonString();
  544. var messageBlobItemCond = new ServiceBusMessage(str);
  545. await _serviceBus.GetServiceBusClient().SendMessageAsync(ItemCondQueue, messageBlobItemCond);
  546. var response = await client.GetContainer(Constant.TEAMModelOS, "School").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
  547. return Ok(new { code = response.Status });
  548. }
  549. else
  550. {
  551. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>($"{id}", new PartitionKey($"{code}"));
  552. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}"))
  553. {
  554. dict.Add($"{olditemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.code.Replace("Item-", "")}", scope = "private" });
  555. }
  556. var itemCondDtos = dict.Select(x => x.Value).ToList();
  557. var str = itemCondDtos.ToJsonString();
  558. var messageBlobItemCond = new ServiceBusMessage(str);
  559. await _serviceBus.GetServiceBusClient().SendMessageAsync(ItemCondQueue, messageBlobItemCond);
  560. var response = await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
  561. return Ok(new { code = response.Status });
  562. }
  563. }
  564. catch (Exception e)
  565. {
  566. await _dingDing.SendBotMsg($"OS,{_option.Location},item/delete()\n{e.Message},{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  567. return BadRequest();
  568. }
  569. /* ResponseBuilder builder = ResponseBuilder.custom();
  570. IdPk idPk = await _azureCosmos.DeleteAsync<ItemInfo>( request );
  571. return Ok(idPk);*/
  572. }
  573. /// <summary>
  574. /// 手动挑题
  575. /// </summary>
  576. /// <param name="request"></param>
  577. /// <returns></returns>
  578. [ProducesDefaultResponseType]
  579. //[AuthToken(Roles = "teacher")]
  580. [HttpPost("find")]
  581. public async Task<IActionResult> Find(JsonElement requert)
  582. {
  583. try
  584. {
  585. var client = _azureCosmos.GetCosmosClient();
  586. StringBuilder sql = new StringBuilder();
  587. sql.Append("select c.id,c.code,c.repairResource, c.periodId,c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime,c.answer,c.explain,c.children,c.score,c.gradeIds,c.subjectId,c.blob,c.scope from c ");
  588. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  589. /* if (!requert.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest();
  590. if (!requert.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();*/
  591. if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  592. Dictionary<string, object> dict = new Dictionary<string, object>();
  593. /*var emobj = requert.EnumerateObject();
  594. while (emobj.MoveNext())
  595. {
  596. dict[emobj.Current.Name] = emobj.Current.Value;
  597. }
  598. //处理code
  599. if (dict.TryGetValue("code", out object _))
  600. {
  601. dict.Remove("code");
  602. }*/
  603. /* dict.Add("@CURRPAGE", page.GetInt32());
  604. dict.Add("@PAGESIZE", size.GetInt32());*/
  605. if (requert.TryGetProperty("@DESC", out JsonElement desc)) {
  606. dict.Add("@DESC", desc.ToString());
  607. }
  608. if (requert.TryGetProperty("@ASC", out JsonElement asc))
  609. {
  610. dict.Add("@ASC", asc.ToString());
  611. }
  612. if (requert.TryGetProperty("periodId", out JsonElement periodId))
  613. {
  614. dict.Add("periodId", periodId);
  615. }
  616. if (requert.TryGetProperty("subjectId", out JsonElement subjectId))
  617. {
  618. dict.Add("subjectId", subjectId);
  619. }
  620. if (requert.TryGetProperty("level", out JsonElement level))
  621. {
  622. dict.Add("level", level);
  623. }
  624. if (requert.TryGetProperty("type", out JsonElement type))
  625. {
  626. dict.Add("type", type);
  627. }
  628. if (requert.TryGetProperty("field", out JsonElement field))
  629. {
  630. dict.Add("field", field);
  631. }
  632. if (requert.TryGetProperty("gradeIds[*]", out JsonElement gradeIds))
  633. {
  634. dict.Add("gradeIds[*]", gradeIds);
  635. }
  636. if (requert.TryGetProperty("knowledge[*]", out JsonElement knowledge))
  637. {
  638. dict.Add("knowledge[*]", knowledge);
  639. }
  640. if (requert.TryGetProperty("pid", out JsonElement pd))
  641. {
  642. if (pd.ValueKind != JsonValueKind.Null)
  643. {
  644. dict.Add("pid", pd.ToString());
  645. }
  646. else
  647. {
  648. dict.Add("pid", null);
  649. }
  650. }
  651. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  652. List<object> items = new List<object>();
  653. if (scope.ToString().Equals("private"))
  654. {
  655. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  656. {
  657. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  658. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  659. {
  660. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  661. {
  662. items.Add(obj.ToObject<object>());
  663. }
  664. }
  665. }
  666. }
  667. if (scope.ToString().Equals("school"))
  668. {
  669. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  670. {
  671. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  672. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  673. {
  674. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  675. {
  676. items.Add(obj.ToObject<object>());
  677. }
  678. }
  679. }
  680. }
  681. //ResponseBuilder builder = ResponseBuilder.custom();
  682. /* List<ItemInfo> items = new List<ItemInfo>();
  683. if (StringHelper.getKeyCount(requert) > 0)
  684. {
  685. items = await _azureCosmos.FindByDict<ItemInfo>(requert);
  686. }*/
  687. return Ok(new { items });
  688. //return builder.Data(items).build();
  689. }
  690. catch (Exception e)
  691. {
  692. await _dingDing.SendBotMsg($"OS,{_option.Location},item/Find()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  693. return BadRequest();
  694. }
  695. }
  696. /// <summary>
  697. /// 手动挑题
  698. /// </summary>
  699. /// <param name="request"></param>
  700. /// <returns></returns>
  701. [ProducesDefaultResponseType]
  702. //[AuthToken(Roles = "teacher")]
  703. [HttpPost("Find-cache-shell")]
  704. public async Task<IActionResult> FindCacheShell(JsonElement requert)
  705. {
  706. var client = _azureCosmos.GetCosmosClient();
  707. if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
  708. if (!requert.TryGetProperty("ids", out JsonElement id)) return BadRequest();
  709. //List<string> ids = new List<string>();
  710. string info = "";
  711. for (int i = 0; i < id.GetArrayLength(); i++)
  712. {
  713. //ids.Add(id[i].ToJsonString());
  714. info += id[i].ToJsonString() + ",";
  715. }
  716. List<object> items = new List<object>();
  717. var query = $"select c.id, c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime from c where c.id in ({info[0..^1]})";
  718. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{school_code}") }))
  719. {
  720. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  721. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  722. {
  723. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  724. {
  725. items.Add(obj.ToObject<object>());
  726. }
  727. }
  728. }
  729. return Ok(new { items });
  730. }
  731. /// <summary>
  732. /// 自动组题
  733. /// </summary>
  734. /// <param name="request"></param>
  735. /// <returns></returns>
  736. [HttpPost("Automatic")]
  737. [Authorize(Roles = "IES")]
  738. public async Task<IActionResult> Automatic(List<Compose> request)
  739. {
  740. try
  741. {
  742. //ResponseBuilder builder = ResponseBuilder.custom();
  743. List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
  744. var client = _azureCosmos.GetCosmosClient();
  745. for (int i = 0; i < request.Count; i++)
  746. {
  747. ///处理知识点均分问题
  748. int avg = 0;
  749. Dictionary<string, int> point = new Dictionary<string, int>();
  750. if (request[i].points.IsNotEmpty())
  751. {
  752. avg = (int)Math.Ceiling(request[i].count * 1.0 / request[i].points.Count);
  753. foreach (string p in request[i].points)
  754. {
  755. point.TryAdd(p, avg);
  756. }
  757. }
  758. List<ItemInfo> retnInfos = new List<ItemInfo>();
  759. List<ItemInfo> itemInfos = new List<ItemInfo>();
  760. List<TempItem> tempItems = new List<TempItem>();
  761. if (request[i].quInfos.IsNotEmpty())
  762. {
  763. List<string> types = new List<string>();
  764. List<int> levels = new List<int>();
  765. foreach (QuInfo quInfo in request[i].quInfos)
  766. {
  767. StringBuilder sql = new StringBuilder();
  768. sql.Append("select c.id,c.code,c.repairResource, c.periodId,c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime,c.answer,c.explain,c.children,c.score,c.gradeIds,c.subjectId,c.blob,c.scope from c ");
  769. // 自定义
  770. if (quInfo.custom.IsNotEmpty() && quInfo.policy.Equals("custom"))
  771. {
  772. foreach (Custom custom in quInfo.custom)
  773. {
  774. for (int j = 0; j < custom.count; j++)
  775. {
  776. tempItems.Add(new TempItem { level = custom.level, type = quInfo.type });
  777. }
  778. Dictionary<string, object> dict = new Dictionary<string, object>();
  779. if (!string.IsNullOrEmpty(request[i].code))
  780. {
  781. dict.Add("code", request[i].code);
  782. }
  783. if (!string.IsNullOrEmpty(request[i].period))
  784. {
  785. dict.Add("periodId", request[i].period);
  786. }
  787. if (request[i].points.IsNotEmpty())
  788. {
  789. dict.Add("knowledge[*]", request[i].points.ToArray());
  790. }
  791. //dict.Add("lite", false);
  792. dict.Add("pid", null);
  793. ///
  794. dict.Add("type", quInfo.type);
  795. dict.Add("level", custom.level);
  796. List<ItemInfo> items = new List<ItemInfo>();
  797. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  798. if (request[i].scope.Equals("school"))
  799. {
  800. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  801. {
  802. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  803. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  804. {
  805. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  806. {
  807. items.Add(obj.ToObject<ItemInfo>());
  808. }
  809. }
  810. }
  811. }
  812. else
  813. {
  814. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  815. {
  816. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  817. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  818. {
  819. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  820. {
  821. items.Add(obj.ToObject<ItemInfo>());
  822. }
  823. }
  824. }
  825. }
  826. //List<ItemInfo> items = await _azureCosmos.FindByDict<ItemInfo>(dict);
  827. //id去重
  828. items = items.Where((x, i) => items.FindIndex(z => z.id == x.id) == i).ToList();
  829. ////均分知识点题目
  830. itemInfos.AddRange(items);
  831. }
  832. }
  833. else
  834. {
  835. Dictionary<string, object> dict = new Dictionary<string, object>();
  836. if (!string.IsNullOrEmpty(request[i].code))
  837. {
  838. dict.Add("code", request[i].code);
  839. }
  840. if (!string.IsNullOrEmpty(request[i].period))
  841. {
  842. dict.Add("periodId", request[i].period);
  843. }
  844. if (request[i].points.IsNotEmpty())
  845. {
  846. dict.Add("knowledge[*]", request[i].points.ToArray());
  847. }
  848. if (!string.IsNullOrEmpty(request[i].subject))
  849. {
  850. dict.Add("subjectId", request[i].subject);
  851. }
  852. //dict.Add("lite", false);
  853. dict.Add("pid", null);
  854. dict.Add("type", quInfo.type);
  855. List<ItemInfo> items = new List<ItemInfo>();
  856. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  857. if (request[i].scope.Equals("school"))
  858. {
  859. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  860. {
  861. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  862. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  863. {
  864. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  865. {
  866. items.Add(obj.ToObject<ItemInfo>());
  867. }
  868. }
  869. }
  870. }
  871. else
  872. {
  873. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  874. {
  875. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  876. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  877. {
  878. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  879. {
  880. items.Add(obj.ToObject<ItemInfo>());
  881. }
  882. }
  883. }
  884. }
  885. //List<ItemInfo> items = await _azureCosmos.FindByDict<ItemInfo>(dict);
  886. //id去重
  887. items = items.Where((x, i) => items.FindIndex(z => z.id == x.id) == i).ToList();
  888. itemInfos.AddRange(items);
  889. //均分
  890. if (quInfo.policy.Equals("average"))
  891. {
  892. //按等级去重 获取所有等级
  893. List<int> lvls = items.Where((x, i) => items.FindIndex(z => z.level == x.level) == i).Select(x => x.level).ToList();
  894. foreach (int k in lvls)
  895. {
  896. int count = quInfo.count / lvls.Count;
  897. for (int j = 0; j < count; j++)
  898. {
  899. tempItems.Add(new TempItem { level = k, type = quInfo.type });
  900. }
  901. }
  902. // 余数 取模 随机处理
  903. if (lvls.Count != 0)
  904. {
  905. int mod = quInfo.count % lvls.Count;
  906. for (int m = 0; m < mod; m++)
  907. {
  908. int lv = lvls.OrderBy(x => Guid.NewGuid()).Take(1).FirstOrDefault();
  909. tempItems.Add(new TempItem { level = lv, type = quInfo.type });
  910. lvls.Remove(lv);
  911. }
  912. }
  913. }
  914. //随机
  915. if (quInfo.policy.Equals("random"))
  916. {
  917. List<int> lvls = items.Where((x, i) => items.FindIndex(z => z.level == x.level) == i).Select(x => x.level).ToList();
  918. for (int n = 0; n < quInfo.count; n++)
  919. {
  920. int lv = lvls.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  921. tempItems.Add(new TempItem { level = lv, type = quInfo.type, policy = "random" });
  922. }
  923. }
  924. }
  925. }
  926. }
  927. itemInfos = itemInfos.OrderBy(x => Guid.NewGuid()).ToList();
  928. tempItems = tempItems.OrderBy(x => Guid.NewGuid()).ToList();
  929. foreach (TempItem temp in tempItems)
  930. {
  931. ItemInfo itemInfo = new ItemInfo();
  932. if (temp.policy != null && temp.policy.Equals("random"))
  933. {
  934. itemInfo = itemInfos.Where(x => x.type == temp.type).OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  935. }
  936. else
  937. {
  938. itemInfo = itemInfos.Where(x => x.level == temp.level && x.type == temp.type).OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  939. }
  940. if (itemInfo != null)
  941. {
  942. retnInfos.Add(itemInfo);
  943. itemInfos.Remove(itemInfo);
  944. }
  945. }
  946. List<ItemInfo> restItem = new List<ItemInfo>();
  947. //处理综合题问题
  948. foreach (var item in retnInfos)
  949. {
  950. if (!string.IsNullOrWhiteSpace(item.pid))
  951. {
  952. if (item.scope .Equals("school"))
  953. {
  954. var iteme = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>(item.id, new PartitionKey(item.code));
  955. if (iteme != null)
  956. {
  957. restItem.Add(iteme.Value);
  958. }
  959. }
  960. else if (item.scope .Equals("private"))
  961. {
  962. var iteme = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>(item.id, new PartitionKey(item.code));
  963. if (iteme != null)
  964. {
  965. restItem.Add(iteme.Value);
  966. }
  967. }
  968. }
  969. else
  970. {
  971. restItem.Add(item);
  972. }
  973. }
  974. List<List<ItemInfo>> listInfo = new List<List<ItemInfo>>();
  975. //处理综合题id重复
  976. restItem = restItem.Where((x, i) => restItem.FindIndex(z => z.id == x.id) == i).ToList();
  977. foreach (IGrouping<string, ItemInfo> group in restItem.GroupBy(c => c.type))
  978. {
  979. Dictionary<string, object> dictInfo = new Dictionary<string, object>();
  980. listInfo.Add(group.ToList());
  981. }
  982. foreach (List<ItemInfo> infos in listInfo)
  983. {
  984. List<Dictionary<string, object>> dict = new List<Dictionary<string, object>>();
  985. foreach (IGrouping<int, ItemInfo> group in infos.GroupBy(c => c.level))
  986. {
  987. Dictionary<string, object> dictInfo = new Dictionary<string, object>();
  988. dictInfo.Add("level", group.Key);
  989. dictInfo.Add("count", group.Count());
  990. dict.Add(dictInfo);
  991. }
  992. Dictionary<string, object> typeDict = new Dictionary<string, object>();
  993. typeDict.Add("info", dict);
  994. typeDict.Add("item", infos);
  995. typeDict.Add("count", infos.Count);
  996. typeDict.Add("type", infos.FirstOrDefault().type);
  997. list.Add(typeDict);
  998. }
  999. }
  1000. //return builder.Data(list).build();
  1001. return Ok(list);
  1002. }
  1003. catch (Exception e)
  1004. {
  1005. await _dingDing.SendBotMsg($"OS,{_option.Location},item/Automatic()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  1006. return BadRequest();
  1007. }
  1008. }
  1009. }
  1010. public class TempItem
  1011. {
  1012. public string type { get; set; }
  1013. public int level { get; set; }
  1014. public ItemInfo itemInfo { get; set; }
  1015. public string policy { get; set; }
  1016. }
  1017. public class Compose
  1018. {
  1019. /// <summary>
  1020. /// 科目
  1021. /// </summary>
  1022. public string subject { get; set; }
  1023. /// <summary>
  1024. /// 来源,个人题库,校本题库
  1025. /// </summary>
  1026. public string code { get; set; }
  1027. /// <summary>
  1028. /// 适用学段,小学,初中,高中
  1029. /// </summary>
  1030. public string period { get; set; }
  1031. /// <summary>
  1032. /// 关联知识点
  1033. /// </summary>
  1034. public List<string> points { get; set; }
  1035. /// <summary>
  1036. /// 题目组合
  1037. /// </summary>
  1038. public List<QuInfo> quInfos { get; set; }
  1039. /// <summary>
  1040. /// 题目总数
  1041. /// </summary>
  1042. public int count { get; set; }
  1043. public string scope { get; set; }
  1044. }
  1045. public class QuInfo
  1046. {
  1047. /// <summary>
  1048. /// 题目类型,单选,多选,判断,填空,问答,综合 Single单选,Multiple多选,Judge判断,Complete填空,Subjective问答,Compose综合
  1049. /// </summary>
  1050. public string type { get; set; }
  1051. /// <summary>
  1052. /// 随机 random 平均的 average ,自定义 custom
  1053. /// </summary>
  1054. public string policy { get; set; }
  1055. /// <summary>
  1056. /// 自定义题目类型
  1057. /// </summary>
  1058. public List<Custom> custom { get; set; }
  1059. /// <summary>
  1060. /// 总题
  1061. /// </summary>
  1062. public int count { get; set; }
  1063. }
  1064. public class Custom
  1065. {
  1066. /// <summary>
  1067. /// 难易程度
  1068. /// </summary>
  1069. public int level { get; set; }
  1070. /// <summary>
  1071. /// 数量
  1072. /// </summary>
  1073. public int count { get; set; }
  1074. }
  1075. }