ItemController.cs 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565
  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 Microsoft.Azure.Cosmos;
  13. using System.Text;
  14. using Microsoft.Extensions.Options;
  15. using Azure.Messaging.ServiceBus;
  16. using Microsoft.Extensions.Configuration;
  17. using Microsoft.AspNetCore.Authorization;
  18. using TEAMModelOS.SDK.Services;
  19. using System.Text.RegularExpressions;
  20. using TEAMModelOS.Filter;
  21. using TEAMModelOS.SDK;
  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. [AuthToken(Roles = "teacher,admin,student")]
  58. #if !DEBUG
  59. [Authorize(Roles = "IES")]
  60. #endif
  61. public async Task<IActionResult> CondCount(JsonElement request)
  62. {
  63. try
  64. {
  65. var client = _azureCosmos.GetCosmosClient();
  66. request.TryGetProperty("periodId", out JsonElement periodId);
  67. request.TryGetProperty("schoolCode", out JsonElement schoolCode);
  68. request.TryGetProperty("tmdid", out JsonElement tmdid);
  69. if (!string.IsNullOrEmpty($"{periodId}") && !string.IsNullOrEmpty($"{schoolCode}"))
  70. {
  71. var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ItemCond:{schoolCode}", $"{periodId}");
  72. ItemCond itemCond = null;
  73. if (value != default && !value.IsNullOrEmpty)
  74. {
  75. itemCond = value.ToString().ToObject<ItemCond>();
  76. }
  77. else
  78. {
  79. List<ItemInfo> items = new List<ItemInfo>();
  80. 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 ";
  81. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIteratorSql<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{schoolCode}") }))
  82. {
  83. items.Add(item);
  84. }
  85. itemCond = new ItemCond()
  86. {
  87. id = $"{periodId}",
  88. code = $"ItemCond-{schoolCode}",
  89. pk = "ItemCond",
  90. ttl = -1,
  91. count = items.Count,
  92. grades = new List<GradeCount>(),
  93. subjects = new List<SubjectItemCount>()
  94. };
  95. items.ForEach(z =>
  96. {
  97. if (!string.IsNullOrEmpty(z.type))
  98. {
  99. ItemService.CountItemCond(z, null, itemCond);
  100. }
  101. });
  102. await _azureRedis.GetRedisClient(8).HashSetAsync($"ItemCond:{schoolCode}", $"{periodId}", itemCond.ToJsonString());
  103. }
  104. return Ok(new { itemConds = new List<ItemCond>() { itemCond } });
  105. }
  106. else if (!string.IsNullOrEmpty($"{schoolCode}"))
  107. {
  108. List<ItemCond> itemConds = new List<ItemCond>();
  109. School school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{schoolCode}", new PartitionKey("Base"));
  110. List<string> nocachePeriods = new List<string>();
  111. foreach (var period in school.period)
  112. {
  113. var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ItemCond:{schoolCode}", $"{period.id}");
  114. ItemCond itemCond = null;
  115. if (value != default && !value.IsNullOrEmpty)
  116. {
  117. itemCond = value.ToString().ToObject<ItemCond>();
  118. itemConds.Add(itemCond);
  119. }
  120. else
  121. {
  122. nocachePeriods.Add(period.id);
  123. }
  124. }
  125. string nocachePeriodsql = "";
  126. if (nocachePeriods.IsNotEmpty())
  127. {
  128. string sql = string.Join(',', nocachePeriods.Select(x => $"'{x}'"));
  129. nocachePeriodsql = $" and c.periodId in ({sql})";
  130. List<ItemInfo> items = new List<ItemInfo>();
  131. var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field,c.scope FROM c where c.pid= null {nocachePeriodsql}";
  132. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIteratorSql<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{schoolCode}") }))
  133. {
  134. items.Add(item);
  135. }
  136. var list = items.GroupBy(x => x.periodId).Select(y => new { key = y.Key, list = y.ToList() }).ToList();
  137. foreach (var z in list)
  138. {
  139. 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<SubjectItemCount>() };
  140. z.list.ForEach(y =>
  141. {
  142. if (!string.IsNullOrEmpty(y.type))
  143. {
  144. ItemService.CountItemCond(y, null, cond);
  145. }
  146. });
  147. await _azureRedis.GetRedisClient(8).HashSetAsync($"ItemCond:{schoolCode}", $"{z.key}", cond.ToJsonString());
  148. itemConds.Add(cond);
  149. }
  150. if (school != null)
  151. {
  152. foreach (var period in school.period)
  153. {
  154. var cond = itemConds.Find(x => x.id.Equals(period.id));
  155. if (cond == null)
  156. {
  157. ItemCond condn = new ItemCond() { id = period.id, code = $"ItemCond-{school.id}", pk = "ItemCond", ttl = -1, count = 0, grades = new List<GradeCount>(), subjects = new List<SubjectItemCount>() };
  158. itemConds.Add(condn);
  159. }
  160. }
  161. }
  162. }
  163. return Ok(new { itemConds = itemConds });
  164. }
  165. else if (!string.IsNullOrEmpty($"{tmdid}"))
  166. {
  167. var value = await _azureRedis.GetRedisClient(8).HashGetAsync($"ItemCond:ItemCond", $"{tmdid}");
  168. ItemCond itemCond = null;
  169. if (value != default && !value.IsNullOrEmpty)
  170. {
  171. itemCond = value.ToString().ToObject<ItemCond>();
  172. }
  173. else
  174. {
  175. List<ItemInfo> items = new List<ItemInfo>();
  176. var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field ,c.scope FROM c where c.pid= null ";
  177. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIteratorSql<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{tmdid}") }))
  178. {
  179. items.Add(item);
  180. }
  181. itemCond = new ItemCond() { id = $"{tmdid}", code = $"ItemCond", pk = "ItemCond", ttl = -1, count = items.Count };
  182. items.ForEach(z =>
  183. {
  184. if (!string.IsNullOrEmpty(z.type))
  185. {
  186. ItemService.CountItemCond(z, null, itemCond);
  187. }
  188. });
  189. await _azureRedis.GetRedisClient(8).HashSetAsync($"ItemCond:ItemCond", $"{tmdid}", itemCond.ToJsonString());
  190. }
  191. return Ok(new { itemConds = new List<ItemCond>() { itemCond } });
  192. }
  193. else
  194. {
  195. return Ok(new { itemConds = new List<ItemCond>() { } });
  196. }
  197. }
  198. catch (CosmosException ex)
  199. {
  200. return Ok(new { itemConds = new List<ItemCond>() { } });
  201. }
  202. catch (Exception ex)
  203. {
  204. return Ok(new { itemConds = new List<ItemCond>() { } });
  205. }
  206. }
  207. [ProducesDefaultResponseType]
  208. [HttpPost("upsert-all")]
  209. [AuthToken(Roles = "teacher,admin")]
  210. #if !DEBUG
  211. [Authorize(Roles = "IES")]
  212. #endif
  213. public async Task<IActionResult> UpsertAll(JsonElement request)
  214. {
  215. var ItemCondQueue = _configuration.GetValue<string>("Azure:ServiceBus:ItemCondQueue");
  216. var client = _azureCosmos.GetCosmosClient();
  217. List<ItemInfo> itemInfos = null;
  218. if (!request.TryGetProperty("itemInfos", out JsonElement items)) return BadRequest();
  219. if (!request.TryGetProperty("option", out JsonElement option)) return BadRequest();
  220. try
  221. {
  222. Dictionary<string, ItemCondDto> dict = new Dictionary<string, ItemCondDto>();
  223. itemInfos = items.ToObject<List<ItemInfo>>();
  224. if (itemInfos.IsNotEmpty())
  225. {
  226. IEnumerable<string> ids = itemInfos.Where(x => !string.IsNullOrWhiteSpace(x.id)).Select(x => x.id);
  227. List<ItemInfo> dbIDs = new List<ItemInfo>();
  228. if (ids!=null && ids.Count()>0)
  229. {
  230. string scope = itemInfos[0].scope.Equals("school") ? Constant.School : Constant.Teacher;
  231. string code = !itemInfos[0].code.Contains("Item") ? $"Item-" + itemInfos[0].code : itemInfos[0].code;
  232. string sql = $"select value c from c where c.id in ({string.Join(",", ids.Select(x => $"'{x}'"))} )";
  233. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, scope).GetList<ItemInfo>(sql, code);
  234. if (result.list.IsNotEmpty())
  235. {
  236. dbIDs= result.list;
  237. }
  238. }
  239. {
  240. //处理数据库没有的数据
  241. var notinDB = itemInfos.ExceptBy(dbIDs.Select(x=>x.id),x=>x.id);
  242. if (notinDB!=null && notinDB.Count()>0)
  243. {
  244. foreach (var itemInfo in notinDB)
  245. {
  246. try {
  247. itemInfo.ttl = -1;
  248. itemInfo.size = await _azureStorage.GetBlobContainerClient(itemInfo.code).GetBlobsSize($"item/{itemInfo.id}");
  249. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = $"item", name = $"{itemInfo.code}".Replace("Item-", "") }, _serviceBus, _configuration, _azureRedis);
  250. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  251. if (!itemInfo.code.Contains("Item"))
  252. {
  253. itemInfo.code = "Item-" + itemInfo.code;
  254. }
  255. if (itemInfo.scope.Equals("private"))
  256. {
  257. if (string.IsNullOrEmpty(itemInfo.pid))
  258. {
  259. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  260. {
  261. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed= $"{itemInfo.code.Replace("Item-", "")}", scope= "private" });
  262. }
  263. }
  264. await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  265. }
  266. else
  267. {
  268. if (string.IsNullOrEmpty(itemInfo.pid))
  269. {
  270. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  271. {
  272. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed=$"{itemInfo.periodId}", scope = "school" });
  273. }
  274. }
  275. await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  276. }
  277. } catch (Exception ex)
  278. {
  279. await _dingDing.SendBotMsg($"{_option.Location},题目批量保存报错:,{ex.Message}\n{ex.StackTrace}\n{itemInfo.ToJsonString()}", GroupNames.成都开发測試群組);
  280. }
  281. }
  282. }
  283. }
  284. {
  285. //处理更新的
  286. var dbs = dbIDs.Select(x => x.id);
  287. var inDB = itemInfos.Where(x => dbs.Contains(x.id));
  288. foreach (var itemInfo in inDB) {
  289. itemInfo.ttl = -1;
  290. itemInfo.size = await _azureStorage.GetBlobContainerClient(itemInfo.code).GetBlobsSize($"item/{itemInfo.id}");
  291. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = $"item", name = $"{itemInfo.code}".Replace("Item-", "") }, _serviceBus, _configuration, _azureRedis);
  292. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  293. if (itemInfo.scope.Equals("private"))
  294. {
  295. if (!itemInfo.code.Contains("Item"))
  296. {
  297. itemInfo.code = "Item-" + itemInfo.code;
  298. }
  299. if (string.IsNullOrEmpty(itemInfo.pid))
  300. {
  301. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  302. {
  303. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.code.Replace("Item-", "")}", scope = "private" });
  304. }
  305. //ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  306. ItemInfo olditemInfo = dbIDs.Find(x => x.id.Equals(itemInfo.id) && x.code.Equals(itemInfo.code));
  307. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}"))
  308. {
  309. dict.Add($"{olditemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.code.Replace("Item-", "")}", scope = "private" });
  310. }
  311. }
  312. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  313. }
  314. else
  315. {
  316. if (!itemInfo.code.Contains("Item"))
  317. {
  318. itemInfo.code = "Item-" + itemInfo.code;
  319. }
  320. if (string.IsNullOrEmpty(itemInfo.pid))
  321. {
  322. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  323. {
  324. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.periodId}", scope = "school" });
  325. }
  326. // ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  327. ItemInfo olditemInfo = dbIDs.Find(x=>x.id.Equals(itemInfo.id) && x.code.Equals(itemInfo.code));
  328. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}"))
  329. {
  330. dict.Add($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.periodId}", scope = "school" });
  331. }
  332. }
  333. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  334. }
  335. }
  336. }
  337. /*
  338. foreach (var itemInfo in itemInfos)
  339. {
  340. itemInfo.ttl = -1;
  341. itemInfo.size = await _azureStorage.GetBlobContainerClient(itemInfo.code).GetBlobsSize($"item/{itemInfo.id}");
  342. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = $"item", name = $"{itemInfo.code}".Replace("Item-", "") }, _serviceBus, _configuration, _azureRedis);
  343. if (option.ToString().Equals("insert"))
  344. {
  345. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  346. if (!itemInfo.code.Contains("Item"))
  347. {
  348. itemInfo.code = "Item-" + itemInfo.code;
  349. }
  350. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  351. if (response.StatusCode==System.Net.HttpStatusCode.OK)
  352. {
  353. return Ok();
  354. }
  355. else
  356. {
  357. if (itemInfo.scope.Equals("private"))
  358. {
  359. if (string.IsNullOrEmpty(itemInfo.pid))
  360. {
  361. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  362. {
  363. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed= $"{itemInfo.code.Replace("Item-", "")}", scope= "private" });
  364. }
  365. }
  366. await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  367. }
  368. else
  369. {
  370. if (string.IsNullOrEmpty(itemInfo.pid))
  371. {
  372. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  373. {
  374. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed=$"{itemInfo.periodId}", scope = "school" });
  375. }
  376. }
  377. await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  378. }
  379. }
  380. }
  381. else
  382. {
  383. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  384. if (itemInfo.scope.Equals("private"))
  385. {
  386. if (!itemInfo.code.Contains("Item"))
  387. {
  388. itemInfo.code = "Item-" + itemInfo.code;
  389. }
  390. if (string.IsNullOrEmpty(itemInfo.pid))
  391. {
  392. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  393. {
  394. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.code.Replace("Item-", "")}", scope = "private" });
  395. }
  396. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  397. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}"))
  398. {
  399. dict.Add($"{olditemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.code.Replace("Item-", "")}", scope = "private" });
  400. }
  401. }
  402. await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  403. }
  404. else
  405. {
  406. if (!itemInfo.code.Contains("Item"))
  407. {
  408. itemInfo.code = "Item-" + itemInfo.code;
  409. }
  410. if (string.IsNullOrEmpty(itemInfo.pid))
  411. {
  412. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  413. {
  414. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.periodId}", scope = "school" });
  415. }
  416. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  417. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}"))
  418. {
  419. dict.Add($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.periodId}", scope = "school" });
  420. }
  421. }
  422. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  423. }
  424. }
  425. }
  426. */
  427. var itemCondDtos = dict.Select(x => x.Value).ToList();
  428. var str = itemCondDtos.ToJsonString();
  429. var messageBlobItemCond = new ServiceBusMessage(str);
  430. await _serviceBus.GetServiceBusClient().SendMessageAsync(ItemCondQueue, messageBlobItemCond);
  431. return Ok(new { itemInfos });
  432. }
  433. else {
  434. return BadRequest();
  435. }
  436. }
  437. catch (Exception ex)
  438. {
  439. await _dingDing.SendBotMsg($"OS,{_option.Location},item/upsert()\n{ex.Message}\n{ex.StackTrace}\n{request}", GroupNames.醍摩豆服務運維群組);
  440. return BadRequest();
  441. }
  442. }
  443. [ProducesDefaultResponseType]
  444. [HttpPost("upsert")]
  445. [AuthToken(Roles = "teacher,admin,student")]
  446. #if !DEBUG
  447. [Authorize(Roles = "IES")]
  448. #endif
  449. public async Task<IActionResult> Upsert(JsonElement request)
  450. {
  451. var client = _azureCosmos.GetCosmosClient();
  452. if (!request.TryGetProperty("itemInfo", out JsonElement item)) return BadRequest();
  453. if (!request.TryGetProperty("option", out JsonElement option)) return BadRequest();
  454. try
  455. {
  456. Dictionary<string, ItemCondDto> dict = new Dictionary<string, ItemCondDto>();
  457. var ItemCondQueue = _configuration.GetValue<string>("Azure:ServiceBus:ItemCondQueue");
  458. ItemInfo itemInfo;
  459. itemInfo = item.ToObject<ItemInfo>();
  460. itemInfo.size = await _azureStorage.GetBlobContainerClient(itemInfo.code).GetBlobsSize($"item/{itemInfo.id}");
  461. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = $"item", name = $"{itemInfo.code}".Replace("Item-", "") }, _serviceBus, _configuration, _azureRedis);
  462. if (option.ToString().Equals("insert"))
  463. {
  464. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  465. if (!itemInfo.code.Contains("Item"))
  466. {
  467. itemInfo.code = "Item-" + itemInfo.code;
  468. }
  469. var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  470. if (response.StatusCode==System.Net.HttpStatusCode.OK)
  471. {
  472. return Ok(new { code = 409, msg = "题目已经存在" });
  473. }
  474. else
  475. {
  476. if (itemInfo.scope.Equals("private"))
  477. {
  478. if (string.IsNullOrEmpty(itemInfo.pid))
  479. {
  480. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  481. {
  482. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.code.Replace("Item-", "")}", scope = "private" });
  483. }
  484. }
  485. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  486. }
  487. else
  488. {
  489. if (string.IsNullOrEmpty(itemInfo.pid))
  490. {
  491. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  492. {
  493. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.periodId}", scope = "school" });
  494. }
  495. }
  496. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync(itemInfo, new PartitionKey($"{itemInfo.code}"));
  497. }
  498. }
  499. }
  500. else
  501. {
  502. itemInfo.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  503. if (itemInfo.scope.Equals("private"))
  504. {
  505. if (!itemInfo.code.Contains("Item"))
  506. {
  507. itemInfo.code = "Item-" + itemInfo.code;
  508. }
  509. if (string.IsNullOrEmpty(itemInfo.pid))
  510. {
  511. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}"))
  512. {
  513. dict.Add($"{itemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.code.Replace("Item-", "")}", scope = "private" });
  514. }
  515. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  516. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}"))
  517. {
  518. dict.Add($"{olditemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.code.Replace("Item-", "")}", scope = "private" });
  519. }
  520. }
  521. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  522. }
  523. else
  524. {
  525. if (!itemInfo.code.Contains("Item"))
  526. {
  527. itemInfo.code = "Item-" + itemInfo.code;
  528. }
  529. if (string.IsNullOrEmpty(itemInfo.pid))
  530. {
  531. if (!dict.ContainsKey($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}"))
  532. {
  533. dict.Add($"{itemInfo.code.Replace("Item-", "")}-{itemInfo.periodId}", new ItemCondDto { key = $"{itemInfo.code.Replace("Item-", "")}", filed = $"{itemInfo.periodId}", scope = "school" });
  534. }
  535. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>(itemInfo.id, new PartitionKey($"{itemInfo.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. }
  541. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(itemInfo, itemInfo.id, new PartitionKey($"{itemInfo.code}"));
  542. }
  543. }
  544. var itemCondDtos = dict.Select(x => x.Value).ToList();
  545. var str = itemCondDtos.ToJsonString();
  546. var messageBlobItemCond = new ServiceBusMessage(str);
  547. await _serviceBus.GetServiceBusClient().SendMessageAsync(ItemCondQueue, messageBlobItemCond);
  548. return Ok(new { itemInfo });
  549. }
  550. catch (Exception ex)
  551. {
  552. await _dingDing.SendBotMsg($"OS,{_option.Location},item/upsert()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  553. return BadRequest();
  554. }
  555. }
  556. /// <summary>
  557. //获取题目摘要信息
  558. /// </summary>
  559. /// <param name="request"></param>
  560. /// <returns></returns>
  561. [ProducesDefaultResponseType]
  562. //[AuthToken(Roles = "teacher")]
  563. [HttpPost("find-summary")]
  564. [AuthToken(Roles = "teacher,admin,student")]
  565. #if !DEBUG
  566. [Authorize(Roles = "IES")]
  567. #endif
  568. public async Task<IActionResult> FindSummary(JsonElement request)
  569. {
  570. try
  571. {
  572. var client = _azureCosmos.GetCosmosClient();
  573. StringBuilder sql = new StringBuilder();
  574. sql.Append("select c.id, c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime from c ");
  575. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  576. /* if (!request.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest();
  577. if (!request.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();*/
  578. if (!request.TryGetProperty("@DESC", out JsonElement desc)) return BadRequest();
  579. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  580. List<object> summary = new List<object>();
  581. Dictionary<string, object> dict = new Dictionary<string, object>();
  582. /* dict.Add("@CURRPAGE", page.GetInt32());
  583. dict.Add("@PAGESIZE", size.GetInt32());*/
  584. dict.Add("@DESC", desc.ToString());
  585. if (request.TryGetProperty("periodId", out JsonElement periodId))
  586. {
  587. dict.Add("periodId", periodId);
  588. }
  589. if (request.TryGetProperty("subjectId", out JsonElement subjectId))
  590. {
  591. dict.Add("subjectId", subjectId);
  592. }
  593. if (request.TryGetProperty("level", out JsonElement level))
  594. {
  595. dict.Add("level", level);
  596. }
  597. if (request.TryGetProperty("type", out JsonElement type))
  598. {
  599. dict.Add("type", type);
  600. }
  601. if (request.TryGetProperty("field", out JsonElement field))
  602. {
  603. dict.Add("field", field);
  604. }
  605. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  606. //List<object> items = new List<object>();
  607. if (scope.ToString().Equals("private"))
  608. {
  609. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIteratorQuery(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  610. {
  611. using var json = await JsonDocument.ParseAsync(item.Content);
  612. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  613. {
  614. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  615. {
  616. summary.Add(obj.ToObject<object>());
  617. }
  618. }
  619. }
  620. }
  621. if (scope.ToString().Equals("school"))
  622. {
  623. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIteratorQuery(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  624. {
  625. using var json = await JsonDocument.ParseAsync(item.Content);
  626. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  627. {
  628. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  629. {
  630. summary.Add(obj.ToObject<object>());
  631. }
  632. }
  633. }
  634. }
  635. return Ok(new { summary });
  636. }
  637. catch (Exception ex)
  638. {
  639. await _dingDing.SendBotMsg($"OS,{_option.Location},item/FindSummary()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  640. return BadRequest();
  641. }
  642. }
  643. /// <summary>
  644. /// 删除
  645. /// </summary>
  646. /// <param name="request"></param>
  647. /// <returns></returns>
  648. [ProducesDefaultResponseType]
  649. //[AuthToken(Roles = "teacher")]
  650. [HttpPost("delete")]
  651. [AuthToken(Roles = "teacher,admin")]
  652. #if !DEBUG
  653. [Authorize(Roles = "IES")]
  654. #endif
  655. public async Task<IActionResult> Delete(JsonElement request)
  656. {
  657. try
  658. {
  659. Dictionary<string, ItemCondDto> dict = new Dictionary<string, ItemCondDto>();
  660. var ItemCondQueue = _configuration.GetValue<string>("Azure:ServiceBus:ItemCondQueue");
  661. List<string> ids = new List<string>();
  662. request.TryGetProperty("id", out JsonElement _id);
  663. if (_id.ValueKind.Equals(JsonValueKind.String) && !string.IsNullOrWhiteSpace(_id.GetString()))
  664. {
  665. ids.Add(_id.GetString());
  666. }
  667. request.TryGetProperty("ids", out JsonElement _ids);
  668. if (_ids.ValueKind.Equals(JsonValueKind.Array))
  669. {
  670. var __ids = _ids.ToObject<List<string>>();
  671. var ds = __ids.Where(z => !string.IsNullOrWhiteSpace(z));
  672. if (ds.Any())
  673. {
  674. ids.AddRange(ds);
  675. }
  676. }
  677. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  678. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  679. var client = _azureCosmos.GetCosmosClient();
  680. //删除blob 相关资料
  681. List<dynamic> codes = new List<dynamic>();
  682. foreach (var id in ids)
  683. {
  684. await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, code.ToString().Replace("Item-", ""), new List<string> { $"item/{id}" });
  685. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "delete", root = $"item", name = code.ToString().Replace("Item-", "") }, _serviceBus, _configuration, _azureRedis);
  686. if (scope.ToString().Equals("school"))
  687. {
  688. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>($"{id}", new PartitionKey($"{code}"));
  689. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}"))
  690. {
  691. dict.Add($"{olditemInfo.code.Replace("Item-", "")}-{olditemInfo.periodId}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.periodId}", scope = "school" });
  692. }
  693. var itemCondDtos = dict.Select(x => x.Value).ToList();
  694. var str = itemCondDtos.ToJsonString();
  695. var messageBlobItemCond = new ServiceBusMessage(str);
  696. await _serviceBus.GetServiceBusClient().SendMessageAsync(ItemCondQueue, messageBlobItemCond);
  697. var response = await client.GetContainer(Constant.TEAMModelOS, "School").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
  698. codes.Add(new { id, code = response.StatusCode });
  699. }
  700. else
  701. {
  702. ItemInfo olditemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>($"{id}", new PartitionKey($"{code}"));
  703. if (!dict.ContainsKey($"{olditemInfo.code.Replace("Item-", "")}"))
  704. {
  705. dict.Add($"{olditemInfo.code.Replace("Item-", "")}", new ItemCondDto { key = $"{olditemInfo.code.Replace("Item-", "")}", filed = $"{olditemInfo.code.Replace("Item-", "")}", scope = "private" });
  706. }
  707. var itemCondDtos = dict.Select(x => x.Value).ToList();
  708. var str = itemCondDtos.ToJsonString();
  709. var messageBlobItemCond = new ServiceBusMessage(str);
  710. await _serviceBus.GetServiceBusClient().SendMessageAsync(ItemCondQueue, messageBlobItemCond);
  711. var response = await client.GetContainer(Constant.TEAMModelOS, "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
  712. codes.Add(new { id, code = response.StatusCode });
  713. }
  714. }
  715. return Ok(new { code = 200, codes });
  716. }
  717. catch (Exception e)
  718. {
  719. await _dingDing.SendBotMsg($"OS,{_option.Location},item/delete()\n{e.Message}\n{e.StackTrace},", GroupNames.醍摩豆服務運維群組);
  720. return BadRequest();
  721. }
  722. /* ResponseBuilder builder = ResponseBuilder.custom();
  723. IdPk idPk = await _azureCosmos.DeleteAsync<ItemInfo>( request );
  724. return Ok(idPk);*/
  725. }
  726. /// <summary>
  727. /// 关键字搜索
  728. /// </summary>
  729. /// <param name="request"></param>
  730. /// <returns></returns>
  731. [ProducesDefaultResponseType]
  732. //[AuthToken(Roles = "teacher")]
  733. [HttpPost("research")]
  734. [AuthToken(Roles = "teacher,admin")]
  735. #if !DEBUG
  736. [Authorize(Roles = "IES")]
  737. #endif
  738. public async Task<IActionResult> Research(JsonElement request)
  739. {
  740. var client = _azureCosmos.GetCosmosClient();
  741. StringBuilder sql = new StringBuilder();
  742. sql.Append("select distinct c.id,c.code,c.repairResource, c.periodId,c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime," +
  743. "c.answer,c.explain,c.children,c.score,c.gradeIds,c.subjectId,c.blob,c.scope from c where 1=1 and c.pid=null ");
  744. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  745. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  746. if (!request.TryGetProperty("researchKey", out JsonElement researchKey)) return BadRequest();
  747. request.TryGetProperty("orOpt", out JsonElement _orOpt);
  748. string _researchKey = Regex.Replace($"{researchKey}", "[ \\[ \\] \\^ \\-|()【】/' {}_*×――(^)$%~!@#$…&%¥—+=<>《》!!???::•`·、。,;,.;\"‘’“”-]", " ");
  749. var keys = Regex.Split(_researchKey, "\\s+", RegexOptions.IgnoreCase).Where(y => !string.IsNullOrWhiteSpace(y));
  750. if (keys.Count() ==0)
  751. {
  752. return BadRequest();
  753. }
  754. else if (keys.Count() == 1)
  755. {
  756. sql.Append($" and contains(c.question,'{keys.First()}')");
  757. }
  758. else
  759. {
  760. string join = " and ";
  761. if (_orOpt.ValueKind.Equals(JsonValueKind.True))
  762. {
  763. join = " or ";
  764. }
  765. sql.Append($" and ( {string.Join(join, keys.Select(x => $" contains(c.question,'{x}') "))})");
  766. }
  767. request.TryGetProperty("type", out JsonElement type);
  768. if (!string.IsNullOrWhiteSpace($"{type}"))
  769. {
  770. sql.Append($" and c.type='{type}' ");
  771. }
  772. request.TryGetProperty("level", out JsonElement level);
  773. if (!string.IsNullOrWhiteSpace($"{level}"))
  774. {
  775. sql.Append($" and c.level={level} ");
  776. }
  777. request.TryGetProperty("field", out JsonElement field);
  778. if (!string.IsNullOrWhiteSpace($"{field}"))
  779. {
  780. sql.Append($" and c.level={field} ");
  781. }
  782. request.TryGetProperty("continuationToken", out JsonElement _continuationToken);
  783. string continuationToken = null;
  784. if (!string.IsNullOrWhiteSpace($"{_continuationToken}"))
  785. {
  786. continuationToken = $"{_continuationToken}";
  787. }
  788. int pageCount = 10;
  789. if (request.TryGetProperty("pageCount", out JsonElement _pageCount))
  790. {
  791. int.TryParse($"{_pageCount}", out int pcount);
  792. if (pcount > 0)
  793. {
  794. pageCount = pcount;
  795. }
  796. }
  797. List<object> items = new List<object>();
  798. if (scope.ToString().Equals("private"))
  799. {
  800. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIteratorSql(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  801. {
  802. using var json = await JsonDocument.ParseAsync(item.Content);
  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<object>());
  808. }
  809. //continuationToken=item.ContinuationToken;
  810. //break;
  811. }
  812. }
  813. }
  814. if (scope.ToString().Equals("school"))
  815. {
  816. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIteratorSql(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  817. {
  818. using var json = await JsonDocument.ParseAsync(item.Content);
  819. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  820. {
  821. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  822. {
  823. items.Add(obj.ToObject<object>());
  824. }
  825. //continuationToken = item.ContinuationToken;
  826. //break;
  827. }
  828. }
  829. }
  830. //需要处理 图片中的 base64
  831. return Ok(new { items, continuationToken });
  832. }
  833. /// <summary>
  834. /// 根据条件随机挑选一个题目
  835. /// </summary>
  836. /// <param name="request"></param>
  837. /// <returns></returns>
  838. [ProducesDefaultResponseType]
  839. //[AuthToken(Roles = "teacher")]
  840. [HttpPost("find-random-one")]
  841. [AuthToken(Roles = "teacher,admin,student")]
  842. #if !DEBUG
  843. [Authorize(Roles = "IES")]
  844. #endif
  845. public async Task<IActionResult> FindRandomOne(JsonElement request)
  846. {
  847. try
  848. {
  849. ItemInfo itemInfo = null;
  850. var client = _azureCosmos.GetCosmosClient();
  851. string sql = $"select value(c.id) from c joingradeIds joinknowledge where 1=1";
  852. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  853. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  854. Dictionary<string, object> dict = new Dictionary<string, object>();
  855. if (request.TryGetProperty("periodId", out JsonElement periodId))
  856. {
  857. sql=$"{sql} and c.periodId='{periodId}'";
  858. }
  859. if (request.TryGetProperty("subjectId", out JsonElement subjectId))
  860. {
  861. sql = $"{sql} and c.subjectId='{subjectId}'";
  862. }
  863. if (request.TryGetProperty("level", out JsonElement level))
  864. {
  865. sql = $"{sql} and c.level={level}";
  866. }
  867. if (request.TryGetProperty("type", out JsonElement type))
  868. {
  869. sql = $"{sql} and c.type='{type}'";
  870. }
  871. if (request.TryGetProperty("field", out JsonElement field))
  872. {
  873. sql = $"{sql} and c.field={field}";
  874. }
  875. if (request.TryGetProperty("gradeIds", out JsonElement _gradeIds) && _gradeIds.ValueKind.Equals(JsonValueKind.Array))
  876. {
  877. List<string> gradeIds = _gradeIds.ToObject<List<string>>();
  878. if (gradeIds.IsNotEmpty())
  879. {
  880. sql = $"{sql} and g in ({string.Join(",", gradeIds.Select(x => $"'{x}'"))})";
  881. sql= sql.Replace("joingradeIds", " join g in c.gradeIds");
  882. }
  883. }
  884. if (request.TryGetProperty("knowledge", out JsonElement _knowledge) && _knowledge.ValueKind.Equals(JsonValueKind.Array))
  885. {
  886. List<string> knowledge = _knowledge.ToObject<List<string>>();
  887. if (knowledge.IsNotEmpty())
  888. {
  889. sql = $"{sql} and k in ({string.Join(",", knowledge.Select(x => $"'{x}'"))})";
  890. sql= sql.Replace("joinknowledge", " join k in c.knowledge");
  891. }
  892. }
  893. if (request.TryGetProperty("pid", out JsonElement pd))
  894. {
  895. if (pd.ValueKind != JsonValueKind.Null)
  896. {
  897. sql = $"{sql} and c.pid='{pd}'";
  898. }
  899. else
  900. {
  901. sql = $"{sql} and c.pid= null ";
  902. }
  903. }
  904. List<string> notinIds = null;
  905. if (request.TryGetProperty("notinIds", out JsonElement _notinIds) && _notinIds.ValueKind.Equals(JsonValueKind.Array))
  906. {
  907. notinIds = _notinIds.ToObject<List<string>>();
  908. if (notinIds.IsNotEmpty())
  909. {
  910. sql = $"{sql} and c.id not in ({string.Join(",", notinIds.Select(x => $"'{x}'"))})";
  911. }
  912. }
  913. string sqlstr = sql.ToString().Replace("joingradeIds", " ").Replace("joinknowledge", " ");
  914. if (sqlstr.EndsWith("1=1") || !sqlstr.Contains("and"))
  915. {
  916. return Ok(new { itemInfo = itemInfo });
  917. }
  918. if (scope.ToString().Equals("private"))
  919. {
  920. List<string> items = new List<string>();
  921. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIteratorSql<string>(queryText: sqlstr, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  922. {
  923. items.Add(item);
  924. }
  925. if (notinIds.IsNotEmpty())
  926. {
  927. items = items.Except(notinIds).ToList();
  928. }
  929. string id = items.OrderBy(x => Guid.NewGuid().ToString()).Take(1).FirstOrDefault();
  930. if (!string.IsNullOrWhiteSpace(id))
  931. {
  932. try
  933. {
  934. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>(id, new PartitionKey($"Item-{code}"));
  935. }
  936. catch (Exception ex)
  937. {
  938. itemInfo = null;
  939. }
  940. }
  941. }
  942. if (scope.ToString().Equals("school"))
  943. {
  944. List<string> items = new List<string>();
  945. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIteratorSql<string>(queryText: sqlstr, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  946. {
  947. items.Add(item);
  948. }
  949. if (notinIds.IsNotEmpty())
  950. {
  951. items = items.Except(notinIds).ToList();
  952. }
  953. string id = items.OrderBy(x => Guid.NewGuid().ToString()).Take(1).FirstOrDefault();
  954. if (!string.IsNullOrWhiteSpace(id))
  955. {
  956. try
  957. {
  958. itemInfo = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>(id, new PartitionKey($"Item-{code}"));
  959. }
  960. catch (Exception ex)
  961. {
  962. itemInfo = null;
  963. }
  964. }
  965. }
  966. return Ok(new { itemInfo = itemInfo });
  967. }
  968. catch (Exception e)
  969. {
  970. await _dingDing.SendBotMsg($"OS,{_option.Location},item/Find()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  971. return BadRequest();
  972. }
  973. }
  974. /// <summary>
  975. /// 查找题目
  976. /// </summary>
  977. /// <param name="request"></param>
  978. /// <returns></returns>
  979. [ProducesDefaultResponseType]
  980. //[AuthToken(Roles = "teacher")]
  981. [HttpPost("find-ids")]
  982. [AuthToken(Roles = "teacher,admin,student")]
  983. #if !DEBUG
  984. [Authorize(Roles = "IES")]
  985. #endif
  986. public async Task<IActionResult> FindIds(JsonElement request)
  987. {
  988. var client = _azureCosmos.GetCosmosClient();
  989. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  990. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  991. if (!request.TryGetProperty("ids", out JsonElement _ids)) return BadRequest();
  992. string tbname = $"{scope}".Equals("school") ? Constant.School : Constant.Teacher;
  993. List<ItemInfo> items = new List<ItemInfo>();
  994. List<string> ids = _ids.ToObject<List<string>>();
  995. if (ids.IsNotEmpty())
  996. {
  997. string sql = $"select value c from c where c.id in ({string.Join(",", ids.Select(z => $"'{z}'"))})";
  998. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, tbname).GetItemQueryIteratorSql<ItemInfo>(sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Item-{code}") }))
  999. {
  1000. items.Add(item);
  1001. }
  1002. return Ok(new { items });
  1003. }
  1004. else
  1005. {
  1006. return Ok(new { items });
  1007. }
  1008. }
  1009. /// <summary>
  1010. /// 手动挑题
  1011. /// </summary>
  1012. /// <param name="request"></param>
  1013. /// <returns></returns>
  1014. [ProducesDefaultResponseType]
  1015. //[AuthToken(Roles = "teacher")]
  1016. [HttpPost("find")]
  1017. [Authorize(Roles = "IES")]
  1018. public async Task<IActionResult> Find(JsonElement request)
  1019. {
  1020. try
  1021. {
  1022. var client = _azureCosmos.GetCosmosClient();
  1023. StringBuilder sql = new StringBuilder();
  1024. 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 ");
  1025. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  1026. /* if (!request.TryGetProperty("@CURRPAGE", out JsonElement page)) return BadRequest();
  1027. if (!request.TryGetProperty("@PAGESIZE", out JsonElement size)) return BadRequest();*/
  1028. if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  1029. Dictionary<string, object> dict = new Dictionary<string, object>();
  1030. /*var emobj = request.EnumerateObject();
  1031. while (emobj.MoveNext())
  1032. {
  1033. dict[emobj.Current.Name] = emobj.Current.Value;
  1034. }
  1035. //处理code
  1036. if (dict.TryGetValue("code", out object _))
  1037. {
  1038. dict.Remove("code");
  1039. }*/
  1040. /* dict.Add("@CURRPAGE", page.GetInt32());
  1041. dict.Add("@PAGESIZE", size.GetInt32());*/
  1042. if (request.TryGetProperty("@DESC", out JsonElement desc))
  1043. {
  1044. dict.Add("@DESC", desc.ToString());
  1045. }
  1046. if (request.TryGetProperty("@ASC", out JsonElement asc))
  1047. {
  1048. dict.Add("@ASC", asc.ToString());
  1049. }
  1050. if (request.TryGetProperty("periodId", out JsonElement periodId))
  1051. {
  1052. dict.Add("periodId", periodId);
  1053. }
  1054. if (request.TryGetProperty("subjectId", out JsonElement subjectId))
  1055. {
  1056. dict.Add("subjectId", subjectId);
  1057. }
  1058. if (request.TryGetProperty("level", out JsonElement level))
  1059. {
  1060. dict.Add("level", level);
  1061. }
  1062. if (request.TryGetProperty("type", out JsonElement type))
  1063. {
  1064. dict.Add("type", type);
  1065. }
  1066. if (request.TryGetProperty("field", out JsonElement field))
  1067. {
  1068. dict.Add("field", field);
  1069. }
  1070. if (request.TryGetProperty("gradeIds[*]", out JsonElement gradeIds))
  1071. {
  1072. dict.Add("gradeIds[*]", gradeIds);
  1073. }
  1074. if (request.TryGetProperty("knowledge[*]", out JsonElement knowledge))
  1075. {
  1076. dict.Add("knowledge[*]", knowledge);
  1077. }
  1078. if (request.TryGetProperty("pid", out JsonElement pd))
  1079. {
  1080. if (pd.ValueKind != JsonValueKind.Null)
  1081. {
  1082. dict.Add("pid", pd.ToString());
  1083. }
  1084. else
  1085. {
  1086. dict.Add("pid", null);
  1087. }
  1088. }
  1089. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  1090. List<object> items = new List<object>();
  1091. if (scope.ToString().Equals("private"))
  1092. {
  1093. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIteratorQuery(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  1094. {
  1095. using var json = await JsonDocument.ParseAsync(item.Content);
  1096. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1097. {
  1098. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1099. {
  1100. items.Add(obj.ToObject<object>());
  1101. }
  1102. }
  1103. }
  1104. }
  1105. if (scope.ToString().Equals("school"))
  1106. {
  1107. // var s = client.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryStreamIterator(queryText: "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 where 1=1 and c.pid = null and c.subjectId in ( '8b94c6b6-2572-41e5-89b9-a82fcf13891e' ) Order By c.createTime DESC ",
  1108. var s = client.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryStreamIterator(queryDefinition:cosmosDbQuery.CosmosQueryDefinition ,
  1109. requestOptions: new QueryRequestOptions() { PartitionKey= new PartitionKey("Item-hbcn") });
  1110. while (s.HasMoreResults) {
  1111. var response = await s.ReadNextAsync();
  1112. if (response.Content!=null)
  1113. {
  1114. using var json = await JsonDocument.ParseAsync(response.Content);
  1115. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1116. {
  1117. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1118. {
  1119. items.Add(obj.ToObject<object>());
  1120. }
  1121. }
  1122. }
  1123. }
  1124. //await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIteratorQuery(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
  1125. //{
  1126. // using var json = await JsonDocument.ParseAsync(item.Content);
  1127. // if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1128. // {
  1129. // foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1130. // {
  1131. // items.Add(obj.ToObject<object>());
  1132. // }
  1133. // }
  1134. //}
  1135. }
  1136. //ResponseBuilder builder = ResponseBuilder.custom();
  1137. /* List<ItemInfo> items = new List<ItemInfo>();
  1138. if (StringHelper.getKeyCount(request) > 0)
  1139. {
  1140. items = await _azureCosmos.FindByDict<ItemInfo>(request);
  1141. }*/
  1142. return Ok(new { items });
  1143. //return builder.Data(items).build();
  1144. }
  1145. catch (Exception e)
  1146. {
  1147. await _dingDing.SendBotMsg($"OS,{_option.Location},item/Find()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  1148. return BadRequest();
  1149. }
  1150. }
  1151. /// <summary>
  1152. /// 自动组题
  1153. /// </summary>
  1154. /// <param name="request"></param>
  1155. /// <returns></returns>
  1156. [HttpPost("automatic")]
  1157. [AuthToken(Roles = "teacher,admin,student")]
  1158. #if !DEBUG
  1159. [Authorize(Roles = "IES")]
  1160. #endif
  1161. public async Task<IActionResult> Automatic(List<Compose> request)
  1162. {
  1163. try
  1164. {
  1165. //ResponseBuilder builder = ResponseBuilder.custom();
  1166. List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
  1167. var client = _azureCosmos.GetCosmosClient();
  1168. for (int i = 0; i < request.Count; i++)
  1169. {
  1170. ///处理知识点均分问题
  1171. int avg = 0;
  1172. Dictionary<string, int> point = new Dictionary<string, int>();
  1173. if (request[i].points.IsNotEmpty())
  1174. {
  1175. avg = (int)Math.Ceiling(request[i].count * 1.0 / request[i].points.Count);
  1176. foreach (string p in request[i].points)
  1177. {
  1178. point.TryAdd(p, avg);
  1179. }
  1180. }
  1181. List<ItemInfo> retnInfos = new List<ItemInfo>();
  1182. List<ItemInfo> itemInfos = new List<ItemInfo>();
  1183. List<TempItem> tempItems = new List<TempItem>();
  1184. if (request[i].quInfos.IsNotEmpty())
  1185. {
  1186. List<string> types = new List<string>();
  1187. List<int> levels = new List<int>();
  1188. foreach (QuInfo quInfo in request[i].quInfos)
  1189. {
  1190. StringBuilder sql = new StringBuilder();
  1191. 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 ");
  1192. // 自定义
  1193. if (quInfo.custom.IsNotEmpty() && quInfo.policy.Equals("custom"))
  1194. {
  1195. foreach (Custom custom in quInfo.custom)
  1196. {
  1197. for (int j = 0; j < custom.count; j++)
  1198. {
  1199. tempItems.Add(new TempItem { level = custom.level, type = quInfo.type });
  1200. }
  1201. Dictionary<string, object> dict = new Dictionary<string, object>();
  1202. if (!string.IsNullOrEmpty(request[i].code))
  1203. {
  1204. dict.Add("code", request[i].code);
  1205. }
  1206. if (!string.IsNullOrEmpty(request[i].period))
  1207. {
  1208. dict.Add("periodId", request[i].period);
  1209. }
  1210. if (request[i].points.IsNotEmpty())
  1211. {
  1212. dict.Add("knowledge[*]", request[i].points.ToArray());
  1213. }
  1214. //dict.Add("lite", false);
  1215. dict.Add("pid", null);
  1216. ///
  1217. dict.Add("type", quInfo.type);
  1218. dict.Add("level", custom.level);
  1219. List<ItemInfo> items = new List<ItemInfo>();
  1220. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  1221. if (request[i].scope.Equals("school"))
  1222. {
  1223. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIteratorQuery(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  1224. {
  1225. using var json = await JsonDocument.ParseAsync(item.Content);
  1226. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1227. {
  1228. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1229. {
  1230. items.Add(obj.ToObject<ItemInfo>());
  1231. }
  1232. }
  1233. }
  1234. }
  1235. else
  1236. {
  1237. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIteratorQuery(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  1238. {
  1239. using var json = await JsonDocument.ParseAsync(item.Content);
  1240. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1241. {
  1242. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1243. {
  1244. items.Add(obj.ToObject<ItemInfo>());
  1245. }
  1246. }
  1247. }
  1248. }
  1249. //List<ItemInfo> items = await _azureCosmos.FindByDict<ItemInfo>(dict);
  1250. //id去重
  1251. items = items.Where((x, i) => items.FindIndex(z => z.id == x.id) == i).ToList();
  1252. ////均分知识点题目
  1253. itemInfos.AddRange(items);
  1254. }
  1255. }
  1256. else
  1257. {
  1258. Dictionary<string, object> dict = new Dictionary<string, object>();
  1259. if (!string.IsNullOrEmpty(request[i].code))
  1260. {
  1261. dict.Add("code", request[i].code);
  1262. }
  1263. if (!string.IsNullOrEmpty(request[i].period))
  1264. {
  1265. dict.Add("periodId", request[i].period);
  1266. }
  1267. if (request[i].points.IsNotEmpty())
  1268. {
  1269. dict.Add("knowledge[*]", request[i].points.ToArray());
  1270. }
  1271. if (!string.IsNullOrEmpty(request[i].subject))
  1272. {
  1273. dict.Add("subjectId", request[i].subject);
  1274. }
  1275. //dict.Add("lite", false);
  1276. dict.Add("pid", null);
  1277. dict.Add("type", quInfo.type);
  1278. List<ItemInfo> items = new List<ItemInfo>();
  1279. AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
  1280. if (request[i].scope.Equals("school"))
  1281. {
  1282. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIteratorQuery(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  1283. {
  1284. using var json = await JsonDocument.ParseAsync(item.Content);
  1285. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1286. {
  1287. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1288. {
  1289. items.Add(obj.ToObject<ItemInfo>());
  1290. }
  1291. }
  1292. }
  1293. }
  1294. else
  1295. {
  1296. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIteratorQuery(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{request[i].code}") }))
  1297. {
  1298. using var json = await JsonDocument.ParseAsync(item.Content);
  1299. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  1300. {
  1301. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  1302. {
  1303. items.Add(obj.ToObject<ItemInfo>());
  1304. }
  1305. }
  1306. }
  1307. }
  1308. //List<ItemInfo> items = await _azureCosmos.FindByDict<ItemInfo>(dict);
  1309. //id去重
  1310. Console.WriteLine(items.Count);
  1311. items = items.Where((x, i) => items.FindIndex(z => z.id == x.id) == i).ToList();
  1312. itemInfos.AddRange(items);
  1313. //均分
  1314. if (quInfo.policy.Equals("average"))
  1315. {
  1316. //按等级去重 获取所有等级
  1317. List<int> lvls = items.Where((x, i) => items.FindIndex(z => z.level == x.level) == i).Select(x => x.level).ToList();
  1318. foreach (int k in lvls)
  1319. {
  1320. int count = quInfo.count / lvls.Count;
  1321. for (int j = 0; j < count; j++)
  1322. {
  1323. tempItems.Add(new TempItem { level = k, type = quInfo.type });
  1324. }
  1325. }
  1326. // 余数 取模 随机处理
  1327. if (lvls.Count != 0)
  1328. {
  1329. int mod = quInfo.count % lvls.Count;
  1330. for (int m = 0; m < mod; m++)
  1331. {
  1332. int lv = lvls.OrderBy(x => Guid.NewGuid()).Take(1).FirstOrDefault();
  1333. tempItems.Add(new TempItem { level = lv, type = quInfo.type });
  1334. lvls.Remove(lv);
  1335. }
  1336. }
  1337. }
  1338. //随机
  1339. if (quInfo.policy.Equals("random"))
  1340. {
  1341. List<int> lvls = items.Where((x, i) => items.FindIndex(z => z.level == x.level) == i).Select(x => x.level).ToList();
  1342. for (int n = 0; n < quInfo.count; n++)
  1343. {
  1344. int lv = lvls.OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  1345. tempItems.Add(new TempItem { level = lv, type = quInfo.type, policy = "random" });
  1346. }
  1347. }
  1348. }
  1349. }
  1350. }
  1351. itemInfos = itemInfos.OrderBy(x => Guid.NewGuid()).ToList();
  1352. tempItems = tempItems.OrderBy(x => Guid.NewGuid()).ToList();
  1353. foreach (TempItem temp in tempItems)
  1354. {
  1355. ItemInfo itemInfo = new ItemInfo();
  1356. if (temp.policy != null && temp.policy.Equals("random"))
  1357. {
  1358. itemInfo = itemInfos.Where(x => x.type == temp.type).OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  1359. }
  1360. else
  1361. {
  1362. itemInfo = itemInfos.Where(x => x.level == temp.level && x.type == temp.type).OrderBy(x => Guid.NewGuid()).FirstOrDefault();
  1363. }
  1364. if (itemInfo != null)
  1365. {
  1366. retnInfos.Add(itemInfo);
  1367. itemInfos.Remove(itemInfo);
  1368. }
  1369. }
  1370. List<ItemInfo> restItem = new List<ItemInfo>();
  1371. //处理综合题问题
  1372. foreach (var item in retnInfos)
  1373. {
  1374. if (!string.IsNullOrWhiteSpace(item.pid))
  1375. {
  1376. if (item.scope.Equals("school"))
  1377. {
  1378. ItemInfo iteme = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<ItemInfo>(item.id, new PartitionKey(item.code));
  1379. if (iteme != null)
  1380. {
  1381. restItem.Add(iteme);
  1382. }
  1383. }
  1384. else if (item.scope.Equals("private"))
  1385. {
  1386. ItemInfo iteme = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<ItemInfo>(item.id, new PartitionKey(item.code));
  1387. if (iteme != null)
  1388. {
  1389. restItem.Add(iteme);
  1390. }
  1391. }
  1392. }
  1393. else
  1394. {
  1395. restItem.Add(item);
  1396. }
  1397. }
  1398. List<List<ItemInfo>> listInfo = new List<List<ItemInfo>>();
  1399. //处理综合题id重复
  1400. restItem = restItem.Where((x, i) => restItem.FindIndex(z => z.id == x.id) == i).ToList();
  1401. foreach (IGrouping<string, ItemInfo> group in restItem.GroupBy(c => c.type))
  1402. {
  1403. Dictionary<string, object> dictInfo = new Dictionary<string, object>();
  1404. listInfo.Add(group.ToList());
  1405. }
  1406. foreach (List<ItemInfo> infos in listInfo)
  1407. {
  1408. List<Dictionary<string, object>> dict = new List<Dictionary<string, object>>();
  1409. foreach (IGrouping<int, ItemInfo> group in infos.GroupBy(c => c.level))
  1410. {
  1411. Dictionary<string, object> dictInfo = new Dictionary<string, object>();
  1412. dictInfo.Add("level", group.Key);
  1413. dictInfo.Add("count", group.Count());
  1414. dict.Add(dictInfo);
  1415. }
  1416. Dictionary<string, object> typeDict = new Dictionary<string, object>();
  1417. typeDict.Add("info", dict);
  1418. typeDict.Add("item", infos);
  1419. typeDict.Add("count", infos.Count);
  1420. typeDict.Add("type", infos.FirstOrDefault().type);
  1421. list.Add(typeDict);
  1422. }
  1423. }
  1424. //return builder.Data(list).build();
  1425. return Ok(list);
  1426. }
  1427. catch (Exception e)
  1428. {
  1429. await _dingDing.SendBotMsg($"OS,{_option.Location},item/Automatic()\n{e.Message}\n{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
  1430. return BadRequest();
  1431. }
  1432. }
  1433. }
  1434. public class TempItem
  1435. {
  1436. public string type { get; set; }
  1437. public int level { get; set; }
  1438. public ItemInfo itemInfo { get; set; }
  1439. public string policy { get; set; }
  1440. }
  1441. public class Compose
  1442. {
  1443. /// <summary>
  1444. /// 科目
  1445. /// </summary>
  1446. public string subject { get; set; }
  1447. /// <summary>
  1448. /// 来源,个人题库,校本题库
  1449. /// </summary>
  1450. public string code { get; set; }
  1451. /// <summary>
  1452. /// 适用学段,小学,初中,高中
  1453. /// </summary>
  1454. public string period { get; set; }
  1455. /// <summary>
  1456. /// 关联知识点
  1457. /// </summary>
  1458. public List<string> points { get; set; }
  1459. /// <summary>
  1460. /// 题目组合
  1461. /// </summary>
  1462. public List<QuInfo> quInfos { get; set; }
  1463. /// <summary>
  1464. /// 题目总数
  1465. /// </summary>
  1466. public int count { get; set; }
  1467. public string scope { get; set; }
  1468. }
  1469. public class QuInfo
  1470. {
  1471. /// <summary>
  1472. /// 题目类型,单选,多选,判断,填空,问答,综合 Single单选,Multiple多选,Judge判断,Complete填空,Subjective问答,Compose综合
  1473. /// </summary>
  1474. public string type { get; set; }
  1475. /// <summary>
  1476. /// 随机 random 平均的 average ,自定义 custom
  1477. /// </summary>
  1478. public string policy { get; set; }
  1479. /// <summary>
  1480. /// 自定义题目类型
  1481. /// </summary>
  1482. public List<Custom> custom { get; set; }
  1483. /// <summary>
  1484. /// 总题
  1485. /// </summary>
  1486. public int count { get; set; }
  1487. }
  1488. public class Custom
  1489. {
  1490. /// <summary>
  1491. /// 难易程度
  1492. /// </summary>
  1493. public int level { get; set; }
  1494. /// <summary>
  1495. /// 数量
  1496. /// </summary>
  1497. public int count { get; set; }
  1498. }
  1499. }