ItemController.cs 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786
  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;
  8. using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
  9. using TEAMModelOS.SDK.DI;
  10. using System.Text.Json;
  11. using TEAMModelOS.SDK.Helper.Common.StringHelper;
  12. using TEAMModelOS.SDK.Models;
  13. using Microsoft.AspNetCore.Http;
  14. using TEAMModelOS.SDK.Extension;
  15. using Azure.Cosmos;
  16. using Microsoft.AspNetCore.Authentication;
  17. using System.Text;
  18. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  19. using Microsoft.Extensions.Options;
  20. using Azure.Messaging.ServiceBus;
  21. using Microsoft.Extensions.Configuration;
  22. using TEAMModelOS.Services.Common;
  23. namespace TEAMModelOS.Controllers
  24. {
  25. [ProducesResponseType(StatusCodes.Status200OK)]
  26. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  27. //[Authorize(Roles = "IES5")]
  28. [Route("item")]
  29. //[Route("api/[controller]")]
  30. [ApiController]
  31. public class ItemController : ControllerBase
  32. {
  33. private readonly SnowflakeId _snowflakeId;
  34. private readonly AzureCosmosFactory _azureCosmos;
  35. private readonly DingDing _dingDing;
  36. private readonly Option _option;
  37. private readonly AzureStorageFactory _azureStorage;
  38. private readonly AzureServiceBusFactory _serviceBus;
  39. public IConfiguration _configuration { get; set; }
  40. public ItemController(AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage, 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. }
  50. [ProducesDefaultResponseType]
  51. [HttpPost("upsert")]
  52. public async Task<IActionResult> Upsert(JsonElement request)
  53. {
  54. /* if (string.IsNullOrEmpty(request.id))
  55. {
  56. request.id = _snowflakeId.NextId() + "";
  57. request.code = typeof(ItemInfo).Name + "-" + request.code;
  58. };
  59. request.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  60. return Ok(await _azureCosmos.SaveOrUpdate(request));*/
  61. var client = _azureCosmos.GetCosmosClient();
  62. if (!request.TryGetProperty("itemInfo", out JsonElement item)) return BadRequest();
  63. if (!request.TryGetProperty("option", out JsonElement option)) return BadRequest();
  64. try
  65. {
  66. ItemInfo itemInfo;
  67. itemInfo = item.ToObject<ItemInfo>();
  68. itemInfo.size = await _azureStorage.GetBlobContainerClient(itemInfo.code).GetBlobsSize($"item/{itemInfo.id}");
  69. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"item/{itemInfo.id}", name = $"{itemInfo.code}" }.ToJsonString());
  70. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  71. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  72. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  73. if (option.ToString().Equals("insert"))
  74. {
  75. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  76. //DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  77. if (!itemInfo.code.Contains("Item"))
  78. {
  79. itemInfo.code = "Item-" + itemInfo.code;
  80. // itemInfo = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  81. }
  82. var response = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  83. if (response.Status == 200)
  84. {
  85. return Ok();
  86. }
  87. else
  88. {
  89. if (itemInfo.scope.Equals("private"))
  90. {
  91. itemInfo = await client.GetContainer("TEAMModelOS", "Teacher").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  92. }
  93. else
  94. {
  95. // itemInfo.periodId
  96. itemInfo = await client.GetContainer("TEAMModelOS", "School").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  97. }
  98. }
  99. }
  100. else
  101. {
  102. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  103. if (itemInfo.scope.Equals("private"))
  104. {
  105. if (!itemInfo.code.Contains("Item"))
  106. {
  107. itemInfo.code = "Item-" + itemInfo.code;
  108. // itemInfo = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  109. }
  110. itemInfo = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  111. }
  112. else
  113. {
  114. if (!itemInfo.code.Contains("Item"))
  115. {
  116. itemInfo.code = "Item-" + itemInfo.code;
  117. //itemInfo = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  118. }
  119. itemInfo = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  120. }
  121. }
  122. return Ok(new { itemInfo });
  123. }
  124. catch (Exception ex)
  125. {
  126. await _dingDing.SendBotMsg($"OS,{_option.Location},item/upsert()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  127. return BadRequest();
  128. }
  129. }
  130. /// <summary>
  131. //获取题目摘要信息
  132. /// </summary>
  133. /// <param name="request"></param>
  134. /// <returns></returns>
  135. [ProducesDefaultResponseType]
  136. //[AuthToken(Roles = "teacher")]
  137. [HttpPost("find-summary")]
  138. public async Task<IActionResult> FindSummary(JsonElement requert)
  139. {
  140. try
  141. {
  142. var client = _azureCosmos.GetCosmosClient();
  143. StringBuilder sql = new StringBuilder();
  144. sql.Append("select c.id, c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime from c ");
  145. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  146. /* if (!requert.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest();
  147. if (!requert.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();*/
  148. if (!requert.TryGetProperty("@DESC", out JsonElement desc)) return BadRequest();
  149. if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  150. List<object> summary = new List<object>();
  151. Dictionary<string, object> dict = new Dictionary<string, object>();
  152. /* dict.Add("@CURRPAGE", page.GetInt32());
  153. dict.Add("@PAGESIZE", size.GetInt32());*/
  154. dict.Add("@DESC", desc.ToString());
  155. if (requert.TryGetProperty("periodId", out JsonElement periodId))
  156. {
  157. dict.Add("periodId", periodId);
  158. }
  159. if (requert.TryGetProperty("subjectId", out JsonElement subjectId))
  160. {
  161. dict.Add("subjectId", subjectId);
  162. }
  163. if (requert.TryGetProperty("level", out JsonElement level))
  164. {
  165. dict.Add("level", level);
  166. }
  167. if (requert.TryGetProperty("type", out JsonElement type))
  168. {
  169. dict.Add("type", type);
  170. }
  171. if (requert.TryGetProperty("field", out JsonElement field))
  172. {
  173. dict.Add("field", field);
  174. }
  175. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  176. //List<object> items = new List<object>();
  177. if (scope.ToString().Equals("private"))
  178. {
  179. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  180. {
  181. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  182. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  183. {
  184. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  185. {
  186. summary.Add(obj.ToObject<object>());
  187. }
  188. }
  189. }
  190. }
  191. if (scope.ToString().Equals("school"))
  192. {
  193. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  194. {
  195. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  196. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  197. {
  198. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  199. {
  200. summary.Add(obj.ToObject<object>());
  201. }
  202. }
  203. }
  204. }
  205. return Ok(new { summary });
  206. }
  207. catch (Exception ex)
  208. {
  209. await _dingDing.SendBotMsg($"OS,{_option.Location},item/FindSummary()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  210. return BadRequest();
  211. }
  212. }
  213. /// <summary>
  214. /// 删除
  215. /// </summary>
  216. /// <param name="request"></param>
  217. /// <returns></returns>
  218. [ProducesDefaultResponseType]
  219. //[AuthToken(Roles = "teacher")]
  220. [HttpPost("delete")]
  221. public async Task<IActionResult> Delete(JsonElement request)
  222. {
  223. try
  224. {
  225. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  226. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  227. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  228. var client = _azureCosmos.GetCosmosClient();
  229. //删除blob 相关资料
  230. await _azureStorage.GetBlobServiceClient().DelectBlobs(code.ToString().Replace("Item-",""), $"item/{id}");
  231. //通知删除信息
  232. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "delete", root = $"item/{id}", name = code.ToString().Replace("Item-", "") }.ToJsonString());
  233. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  234. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  235. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  236. if (scope.ToString().Equals("school"))
  237. {
  238. var response = await client.GetContainer("TEAMModelOS", "School").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
  239. return Ok(new { code = response.Status });
  240. }
  241. else
  242. {
  243. var response = await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
  244. return Ok(new { code = response.Status });
  245. }
  246. }
  247. catch (Exception e)
  248. {
  249. await _dingDing.SendBotMsg($"OS,{_option.Location},item/FindSummary()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  250. return BadRequest();
  251. }
  252. /* ResponseBuilder builder = ResponseBuilder.custom();
  253. IdPk idPk = await _azureCosmos.DeleteAsync<ItemInfo>( request );
  254. return Ok(idPk);*/
  255. }
  256. /// <summary>
  257. /// 手动挑题
  258. /// </summary>
  259. /// <param name="request"></param>
  260. /// <returns></returns>
  261. [ProducesDefaultResponseType]
  262. //[AuthToken(Roles = "teacher")]
  263. [HttpPost("find")]
  264. public async Task<IActionResult> Find(JsonElement requert)
  265. {
  266. try
  267. {
  268. var client = _azureCosmos.GetCosmosClient();
  269. StringBuilder sql = new StringBuilder();
  270. 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 ");
  271. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  272. /* if (!requert.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest();
  273. if (!requert.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();*/
  274. if (!requert.TryGetProperty("@DESC", out JsonElement desc)) return BadRequest();
  275. if (!requert.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  276. Dictionary<string, object> dict = new Dictionary<string, object>();
  277. /*var emobj = requert.EnumerateObject();
  278. while (emobj.MoveNext())
  279. {
  280. dict[emobj.Current.Name] = emobj.Current.Value;
  281. }
  282. //处理code
  283. if (dict.TryGetValue("code", out object _))
  284. {
  285. dict.Remove("code");
  286. }*/
  287. /* dict.Add("@CURRPAGE", page.GetInt32());
  288. dict.Add("@PAGESIZE", size.GetInt32());*/
  289. dict.Add("@DESC", desc.ToString());
  290. if (requert.TryGetProperty("periodId", out JsonElement periodId))
  291. {
  292. dict.Add("periodId", periodId);
  293. }
  294. if (requert.TryGetProperty("subjectId", out JsonElement subjectId))
  295. {
  296. dict.Add("subjectId", subjectId);
  297. }
  298. if (requert.TryGetProperty("level", out JsonElement level))
  299. {
  300. dict.Add("level", level);
  301. }
  302. if (requert.TryGetProperty("type", out JsonElement type))
  303. {
  304. dict.Add("type", type);
  305. }
  306. if (requert.TryGetProperty("field", out JsonElement field))
  307. {
  308. dict.Add("field", field);
  309. }
  310. if (requert.TryGetProperty("gradeIds[*]", out JsonElement gradeIds))
  311. {
  312. dict.Add("gradeIds[*]", gradeIds);
  313. }
  314. if (requert.TryGetProperty("pid", out JsonElement pd))
  315. {
  316. if (pd.ValueKind != JsonValueKind.Null)
  317. {
  318. dict.Add("pid", pd.ToString());
  319. }
  320. else
  321. {
  322. dict.Add("pid", null);
  323. }
  324. }
  325. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  326. List<object> items = new List<object>();
  327. if (scope.ToString().Equals("private"))
  328. {
  329. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  330. {
  331. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  332. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  333. {
  334. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  335. {
  336. items.Add(obj.ToObject<object>());
  337. }
  338. }
  339. }
  340. }
  341. if (scope.ToString().Equals("school"))
  342. {
  343. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  344. {
  345. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  346. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  347. {
  348. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  349. {
  350. items.Add(obj.ToObject<object>());
  351. }
  352. }
  353. }
  354. }
  355. //ResponseBuilder builder = ResponseBuilder.custom();
  356. /* List<ItemInfo> items = new List<ItemInfo>();
  357. if (StringHelper.getKeyCount(requert) > 0)
  358. {
  359. items = await _azureCosmos.FindByDict<ItemInfo>(requert);
  360. }*/
  361. return Ok(new { items });
  362. //return builder.Data(items).build();
  363. }
  364. catch (Exception e)
  365. {
  366. await _dingDing.SendBotMsg($"OS,{_option.Location},item/Find()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  367. return BadRequest(e.StackTrace);
  368. }
  369. }
  370. /// <summary>
  371. /// 手动挑题
  372. /// </summary>
  373. /// <param name="request"></param>
  374. /// <returns></returns>
  375. [ProducesDefaultResponseType]
  376. //[AuthToken(Roles = "teacher")]
  377. [HttpPost("Find-cache-shell")]
  378. public async Task<IActionResult> FindCacheShell(JsonElement requert)
  379. {
  380. var client = _azureCosmos.GetCosmosClient();
  381. if (!requert.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
  382. if (!requert.TryGetProperty("ids", out JsonElement id)) return BadRequest();
  383. //List<string> ids = new List<string>();
  384. string info = "";
  385. for (int i = 0; i < id.GetArrayLength(); i++)
  386. {
  387. //ids.Add(id[i].ToJsonString());
  388. info += id[i].ToJsonString() + ",";
  389. }
  390. List<object> items = new List<object>();
  391. 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]})";
  392. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{school_code}") }))
  393. {
  394. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  395. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  396. {
  397. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  398. {
  399. items.Add(obj.ToObject<object>());
  400. }
  401. }
  402. }
  403. return Ok(new { items });
  404. }
  405. /// <summary>
  406. /// 自动组题
  407. /// </summary>
  408. /// <param name="request"></param>
  409. /// <returns></returns>
  410. [HttpPost("Automatic")]
  411. public async Task<IActionResult> Automatic(List<Compose> request)
  412. {
  413. try
  414. {
  415. //ResponseBuilder builder = ResponseBuilder.custom();
  416. List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
  417. var client = _azureCosmos.GetCosmosClient();
  418. for (int i = 0; i < request.Count; i++)
  419. {
  420. ///处理知识点均分问题
  421. int avg = 0;
  422. Dictionary<string, int> point = new Dictionary<string, int>();
  423. if (request[i].points.IsNotEmpty())
  424. {
  425. avg = (int)Math.Ceiling(request[i].count * 1.0 / request[i].points.Count);
  426. foreach (string p in request[i].points)
  427. {
  428. point.TryAdd(p, avg);
  429. }
  430. }
  431. List<ItemInfo> retnInfos = new List<ItemInfo>();
  432. List<ItemInfo> itemInfos = new List<ItemInfo>();
  433. List<TempItem> tempItems = new List<TempItem>();
  434. if (request[i].quInfos.IsNotEmpty())
  435. {
  436. List<string> types = new List<string>();
  437. List<int> levels = new List<int>();
  438. foreach (QuInfo quInfo in request[i].quInfos)
  439. {
  440. StringBuilder sql = new StringBuilder();
  441. 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 ");
  442. // 自定义
  443. if (quInfo.custom.IsNotEmpty() && quInfo.policy.Equals("custom"))
  444. {
  445. foreach (Custom custom in quInfo.custom)
  446. {
  447. for (int j = 0; j < custom.count; j++)
  448. {
  449. tempItems.Add(new TempItem { level = custom.level, type = quInfo.type });
  450. }
  451. Dictionary<string, object> dict = new Dictionary<string, object>();
  452. if (!string.IsNullOrEmpty(request[i].code))
  453. {
  454. dict.Add("code", request[i].code);
  455. }
  456. if (!string.IsNullOrEmpty(request[i].period))
  457. {
  458. dict.Add("periodId", request[i].period);
  459. }
  460. if (request[i].points.IsNotEmpty())
  461. {
  462. dict.Add("knowledge[*]", request[i].points.ToArray());
  463. }
  464. //dict.Add("lite", false);
  465. dict.Add("pid", null);
  466. ///
  467. dict.Add("type", quInfo.type);
  468. dict.Add("level", custom.level);
  469. List<ItemInfo> items = new List<ItemInfo>();
  470. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  471. if (request[i].scope.Equals("school"))
  472. {
  473. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  474. {
  475. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  476. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  477. {
  478. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  479. {
  480. items.Add(obj.ToObject<ItemInfo>());
  481. }
  482. }
  483. }
  484. }
  485. else
  486. {
  487. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  488. {
  489. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  490. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  491. {
  492. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  493. {
  494. items.Add(obj.ToObject<ItemInfo>());
  495. }
  496. }
  497. }
  498. }
  499. //List<ItemInfo> items = await _azureCosmos.FindByDict<ItemInfo>(dict);
  500. //id去重
  501. items = items.Where((x, i) => items.FindIndex(z => z.id == x.id) == i).ToList();
  502. ////均分知识点题目
  503. itemInfos.AddRange(items);
  504. }
  505. }
  506. else
  507. {
  508. Dictionary<string, object> dict = new Dictionary<string, object>();
  509. if (!string.IsNullOrEmpty(request[i].code))
  510. {
  511. dict.Add("code", request[i].code);
  512. }
  513. if (!string.IsNullOrEmpty(request[i].period))
  514. {
  515. dict.Add("periodId", request[i].period);
  516. }
  517. if (request[i].points.IsNotEmpty())
  518. {
  519. dict.Add("knowledge[*]", request[i].points.ToArray());
  520. }
  521. if (!string.IsNullOrEmpty(request[i].subject))
  522. {
  523. dict.Add("subjectId", request[i].subject);
  524. }
  525. //dict.Add("lite", false);
  526. dict.Add("pid", null);
  527. dict.Add("type", quInfo.type);
  528. List<ItemInfo> items = new List<ItemInfo>();
  529. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  530. if (request[i].scope.Equals("school"))
  531. {
  532. await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  533. {
  534. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  535. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  536. {
  537. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  538. {
  539. items.Add(obj.ToObject<ItemInfo>());
  540. }
  541. }
  542. }
  543. }
  544. else
  545. {
  546. await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  547. {
  548. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  549. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  550. {
  551. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  552. {
  553. items.Add(obj.ToObject<ItemInfo>());
  554. }
  555. }
  556. }
  557. }
  558. //List<ItemInfo> items = await _azureCosmos.FindByDict<ItemInfo>(dict);
  559. //id去重
  560. items = items.Where((x, i) => items.FindIndex(z => z.id == x.id) == i).ToList();
  561. itemInfos.AddRange(items);
  562. //均分
  563. if (quInfo.policy.Equals("average"))
  564. {
  565. //按等级去重 获取所有等级
  566. List<int> lvls = items.Where((x, i) => items.FindIndex(z => z.level == x.level) == i).Select(x => x.level).ToList();
  567. foreach (int k in lvls)
  568. {
  569. int count = quInfo.count / lvls.Count;
  570. for (int j = 0; j < count; j++)
  571. {
  572. tempItems.Add(new TempItem { level = k, type = quInfo.type });
  573. }
  574. }
  575. // 余数 取模 随机处理
  576. if (lvls.Count != 0)
  577. {
  578. int mod = quInfo.count % lvls.Count;
  579. for (int m = 0; m < mod; m++)
  580. {
  581. int lv = lvls.OrderBy(x => Guid.NewGuid()).Take(1).FirstOrDefault();
  582. tempItems.Add(new TempItem { level = lv, type = quInfo.type });
  583. lvls.Remove(lv);
  584. }
  585. }
  586. }
  587. //随机
  588. if (quInfo.policy.Equals("random"))
  589. {
  590. List<int> lvls = items.Where((x, i) => items.FindIndex(z => z.level == x.level) == i).Select(x => x.level).ToList();
  591. for (int n = 0; n < quInfo.count; n++)
  592. {
  593. int lv = lvls.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  594. tempItems.Add(new TempItem { level = lv, type = quInfo.type, policy = "random" });
  595. }
  596. }
  597. }
  598. }
  599. }
  600. itemInfos = itemInfos.OrderBy(x => Guid.NewGuid()).ToList();
  601. tempItems = tempItems.OrderBy(x => Guid.NewGuid()).ToList();
  602. foreach (TempItem temp in tempItems)
  603. {
  604. ItemInfo itemInfo = new ItemInfo();
  605. if (temp.policy != null && temp.policy.Equals("random"))
  606. {
  607. itemInfo = itemInfos.Where(x => x.type == temp.type).OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  608. }
  609. else
  610. {
  611. itemInfo = itemInfos.Where(x => x.level == temp.level && x.type == temp.type).OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  612. }
  613. if (itemInfo != null)
  614. {
  615. retnInfos.Add(itemInfo);
  616. itemInfos.Remove(itemInfo);
  617. }
  618. }
  619. List<ItemInfo> restItem = new List<ItemInfo>();
  620. //处理综合题问题
  621. foreach (var item in retnInfos)
  622. {
  623. if (!string.IsNullOrWhiteSpace(item.pid))
  624. {
  625. if (item.scope == "school")
  626. {
  627. var iteme = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<ItemInfo>(item.id, new PartitionKey(item.code));
  628. if (iteme != null)
  629. {
  630. restItem.Add(iteme.Value);
  631. }
  632. }
  633. else if (item.scope == "private")
  634. {
  635. var iteme = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<ItemInfo>(item.id, new PartitionKey(item.code));
  636. if (iteme != null)
  637. {
  638. restItem.Add(iteme.Value);
  639. }
  640. }
  641. }
  642. else
  643. {
  644. restItem.Add(item);
  645. }
  646. }
  647. List<List<ItemInfo>> listInfo = new List<List<ItemInfo>>();
  648. //处理综合题id重复
  649. restItem = restItem.Where((x, i) => restItem.FindIndex(z => z.id == x.id) == i).ToList();
  650. foreach (IGrouping<string, ItemInfo> group in restItem.GroupBy(c => c.type))
  651. {
  652. Dictionary<string, object> dictInfo = new Dictionary<string, object>();
  653. listInfo.Add(group.ToList());
  654. }
  655. foreach (List<ItemInfo> infos in listInfo)
  656. {
  657. List<Dictionary<string, object>> dict = new List<Dictionary<string, object>>();
  658. foreach (IGrouping<int, ItemInfo> group in infos.GroupBy(c => c.level))
  659. {
  660. Dictionary<string, object> dictInfo = new Dictionary<string, object>();
  661. dictInfo.Add("level", group.Key);
  662. dictInfo.Add("count", group.Count());
  663. dict.Add(dictInfo);
  664. }
  665. Dictionary<string, object> typeDict = new Dictionary<string, object>();
  666. typeDict.Add("info", dict);
  667. typeDict.Add("item", infos);
  668. typeDict.Add("count", infos.Count);
  669. typeDict.Add("type", infos.FirstOrDefault().type);
  670. list.Add(typeDict);
  671. }
  672. }
  673. //return builder.Data(list).build();
  674. return Ok(list);
  675. }
  676. catch (Exception e)
  677. {
  678. await _dingDing.SendBotMsg($"OS,{_option.Location},item/Automatic()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  679. return BadRequest();
  680. }
  681. }
  682. }
  683. public class TempItem
  684. {
  685. public string type { get; set; }
  686. public int level { get; set; }
  687. public ItemInfo itemInfo { get; set; }
  688. public string policy { get; set; }
  689. }
  690. public class Compose
  691. {
  692. /// <summary>
  693. /// 科目
  694. /// </summary>
  695. public string subject { get; set; }
  696. /// <summary>
  697. /// 来源,个人题库,校本题库
  698. /// </summary>
  699. public string code { get; set; }
  700. /// <summary>
  701. /// 适用学段,小学,初中,高中
  702. /// </summary>
  703. public string period { get; set; }
  704. /// <summary>
  705. /// 关联知识点
  706. /// </summary>
  707. public List<string> points { get; set; }
  708. /// <summary>
  709. /// 题目组合
  710. /// </summary>
  711. public List<QuInfo> quInfos { get; set; }
  712. /// <summary>
  713. /// 题目总数
  714. /// </summary>
  715. public int count { get; set; }
  716. public string scope { get; set; }
  717. }
  718. public class QuInfo
  719. {
  720. /// <summary>
  721. /// 题目类型,单选,多选,判断,填空,问答,综合 Single单选,Multiple多选,Judge判断,Complete填空,Subjective问答,Compose综合
  722. /// </summary>
  723. public string type { get; set; }
  724. /// <summary>
  725. /// 随机 random 平均的 average ,自定义 custom
  726. /// </summary>
  727. public string policy { get; set; }
  728. /// <summary>
  729. /// 自定义题目类型
  730. /// </summary>
  731. public List<Custom> custom { get; set; }
  732. /// <summary>
  733. /// 总题
  734. /// </summary>
  735. public int count { get; set; }
  736. }
  737. public class Custom
  738. {
  739. /// <summary>
  740. /// 难易程度
  741. /// </summary>
  742. public int level { get; set; }
  743. /// <summary>
  744. /// 数量
  745. /// </summary>
  746. public int count { get; set; }
  747. }
  748. }