ItemController.cs 61 KB

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