AbilityTaskController.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. using Azure;
  2. using Microsoft.Azure.Cosmos;
  3. using Microsoft.AspNetCore.Http;
  4. using Microsoft.AspNetCore.Mvc;
  5. using Microsoft.Extensions.Options;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text;
  10. using System.Text.Json;
  11. using System.Threading.Tasks;
  12. using TEAMModelOS.Models;
  13. using TEAMModelOS.SDK.DI;
  14. using TEAMModelOS.SDK.Extension;
  15. using TEAMModelOS.SDK;
  16. using TEAMModelOS.SDK.Models;
  17. using TEAMModelOS.SDK.Models.Cosmos;
  18. using TEAMModelOS.SDK.Models.Cosmos;
  19. using TEAMModelOS.SDK.Models.Cosmos.Inner;
  20. using TEAMModelOS.Filter;
  21. using System.ComponentModel.DataAnnotations;
  22. using Microsoft.AspNetCore.Authorization;
  23. using TEAMModelOS.SDK.Services;
  24. namespace TEAMModelOS.Controllers
  25. {
  26. [ProducesResponseType(StatusCodes.Status200OK)]
  27. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  28. [Route("research/ability-task")]
  29. [ApiController]
  30. //[Authorize]
  31. public class AbilityTaskController: ControllerBase
  32. {
  33. private readonly AzureCosmosFactory _azureCosmos;
  34. private readonly Option _option;
  35. private readonly DingDing _dingDing;
  36. public AbilityTaskController(AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option)
  37. {
  38. _azureCosmos = azureCosmos;
  39. _dingDing = dingDing;
  40. _option = option?.Value;
  41. }
  42. /// <summary>
  43. /// 批量保存或更新课纲
  44. ///
  45. /// </summary>
  46. /// <param name="request"></param>
  47. /// <returns></returns>
  48. [ProducesDefaultResponseType]
  49. [HttpPost("upsert-tree")]
  50. [Authorize(Roles = "IES")]
  51. [AuthToken(Roles = "area")]
  52. public async Task<IActionResult> SaveOrUpdateAsTree(UpdateAsTree request)
  53. {
  54. //if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  55. //if (!request.TryGetProperty("standard", out JsonElement standard)) return BadRequest();
  56. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  57. foreach (AbilityTaskTreeNode abilityTaskTree in request.taskTrees)
  58. {
  59. if (!string.IsNullOrEmpty(abilityTaskTree.id))
  60. {
  61. AbilityTask abilityTask = null;
  62. try
  63. {
  64. abilityTask = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReadItemAsync<AbilityTask>(abilityTaskTree.id, new PartitionKey($"AbilityTask-{request.standard}"));
  65. }
  66. catch
  67. {
  68. }
  69. if (abilityTask == null)
  70. {
  71. if (abilityTaskTree.trees.IsNotEmpty())
  72. {
  73. abilityTaskTree.trees.ForEach(x => x.id = abilityTaskTree.id);
  74. }
  75. List<Tnode> nodes = new List<Tnode>();
  76. AbilityService.TreeToList(abilityTaskTree.trees, nodes, now);
  77. abilityTask = new AbilityTask();
  78. abilityTask.id = abilityTaskTree.id;
  79. abilityTask.children = nodes;
  80. abilityTask.code = $"AbilityTask-{request.standard}";
  81. abilityTask.pk = "AbilityTask";
  82. abilityTask.ttl = -1;
  83. abilityTask.abilityId = abilityTaskTree.abilityId;
  84. abilityTask.scope = abilityTaskTree.scope;
  85. abilityTask.codeval = $"{request.standard}";
  86. abilityTask.standard = $"{request.standard}";
  87. await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").CreateItemAsync<AbilityTask>(abilityTask, new PartitionKey($"AbilityTask-{request.standard}"));
  88. }
  89. else
  90. {
  91. if (abilityTaskTree.trees.IsNotEmpty())
  92. {
  93. abilityTaskTree.trees.ForEach(x => x.id = abilityTaskTree.id);
  94. }
  95. List<Tnode> nodes = new List<Tnode>();
  96. AbilityService.TreeToList(abilityTaskTree.trees, nodes, now);
  97. abilityTask.children = nodes;
  98. abilityTaskTree.auth = abilityTask.auth;
  99. await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<AbilityTask>(abilityTask, abilityTask.id, new PartitionKey($"AbilityTask-{request.standard}"));
  100. }
  101. }
  102. else
  103. {
  104. string id = Guid.NewGuid().ToString();
  105. abilityTaskTree.id = id;
  106. if (abilityTaskTree.trees.IsNotEmpty())
  107. {
  108. abilityTaskTree.trees.ForEach(x => x.id = abilityTaskTree.id);
  109. }
  110. List<Tnode> nodes = new List<Tnode>();
  111. AbilityService.TreeToList(abilityTaskTree.trees, nodes, now);
  112. AbilityTask abilityTask = new AbilityTask
  113. {
  114. id = id,
  115. code = $"AbilityTask-{request.standard}",
  116. pk = "AbilityTask",
  117. ttl = -1,
  118. abilityId = abilityTaskTree.abilityId,
  119. children = nodes,
  120. scope = abilityTaskTree.scope,
  121. codeval = $"{request.standard}",
  122. standard = $"{request.standard}"
  123. };
  124. await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").CreateItemAsync<AbilityTask>(abilityTask, new PartitionKey($"AbilityTask-{request.standard}"));
  125. }
  126. }
  127. return Ok(request);
  128. }
  129. /// <summary>
  130. /// 检查资源链接是否被其他结构关联
  131. ///
  132. /// </summary>
  133. /// <param name="request"></param>
  134. /// <returns></returns>
  135. [ProducesDefaultResponseType]
  136. [HttpPost("check-link")]
  137. [AuthToken(Roles = "area")]
  138. [Authorize(Roles = "IES")]
  139. public async Task<IActionResult> CheckLink(JsonElement request)
  140. {
  141. //if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  142. if (!request.TryGetProperty("standard", out JsonElement standard)) return BadRequest();
  143. if (!request.TryGetProperty("links", out JsonElement _links)) return BadRequest();
  144. //if (!request.TryGetProperty("code", out JsonElement _code)) return BadRequest();
  145. //if (!request.TryGetProperty("scope", out JsonElement _scope)) return BadRequest();
  146. if (_links.ValueKind.Equals(JsonValueKind.Array))
  147. {
  148. List<AbilityLinkDto> links = new List<AbilityLinkDto>();
  149. List<string> list = _links.ToObject<List<string>>();
  150. var client = _azureCosmos.GetCosmosClient();
  151. list = list.Select(x => $"'{x}'").ToList();
  152. string lks = string.Join(",", list);
  153. StringBuilder queryText = new StringBuilder($"SELECT c.id as abilityTaskId,c.abilityId,rnodes.link ,children.id as treeid FROM c join children in c.children join rnodes in children.rnodes where rnodes.link in ({lks}) ");
  154. await foreach (var item in client.GetContainer("TEAMModelOS", "Normal").GetItemQueryIteratorSql<AbilityLinkDto>(queryText: queryText.ToString(),
  155. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{standard}") }))
  156. {
  157. links.Add(item);
  158. }
  159. var count = links.GroupBy(x => x.link).Select(y => new { key = y.Key, count = y.ToList().Count });
  160. return Ok(new { count, links });
  161. }
  162. else
  163. {
  164. return BadRequest();
  165. }
  166. }
  167. public class AbilityLinkDto
  168. {
  169. /// <summary>
  170. /// 原来为 abilityTaskId
  171. /// </summary>
  172. public string abilityTaskId { get; set; }
  173. /// <summary>
  174. /// 原来为 abilityId
  175. /// </summary>
  176. public string abilityId { get; set; }
  177. public string link { get; set; }
  178. public string treeid { get; set; }
  179. }
  180. /*
  181. [
  182. {
  183. "id": "章节id",
  184. "abilityId": "册别id",
  185. "scope": "school",
  186. "trees": [
  187. {
  188. "id": "b2b15c99-83cc-eca7-5b4b-e58d2a457c8e",
  189. "pid": "0baf00db-0768-4b62-a8f7-280f6bcebf71",
  190. "title": "第一单元",
  191. "type": 1,
  192. "children": []
  193. }
  194. ]
  195. }
  196. ]
  197. */
  198. public class UpdateAsTree {
  199. public List<AbilityTaskTreeNode> taskTrees { get; set; }
  200. [Required(ErrorMessage = "standard 必须设置")]
  201. public string standard { get; set; }
  202. }
  203. /*
  204. {"abilityId":"册别id:0baf00db-0768-4b62-a8f7-280f6bcebf71","scope":"school","abilityCode":"册别分区键"}
  205. */
  206. /// <summary>
  207. /// 查找课纲
  208. /// </summary>
  209. /// <param name="request"></param>
  210. /// <returns></returns>
  211. [ProducesDefaultResponseType]
  212. [HttpPost("find-id")]
  213. [AuthToken(Roles = "teacher,student,admin,area")]
  214. [Authorize(Roles = "IES")]
  215. public async Task<IActionResult> Find(JsonElement request)
  216. {
  217. //if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  218. if (!request.TryGetProperty("standard", out JsonElement standard)) return BadRequest();
  219. var client = _azureCosmos.GetCosmosClient();
  220. if (!request.TryGetProperty("abilityId", out JsonElement abilityId)) return BadRequest();
  221. // if (!request.TryGetProperty("abilityCode", out JsonElement abilityCode)) return BadRequest();
  222. //if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
  223. Ability ability = null;
  224. List<AbilityTaskTreeNode> treeNodes = new List<AbilityTaskTreeNode>();
  225. List<AbilityTaskTreeNode> redt = new List<AbilityTaskTreeNode>();
  226. try
  227. {
  228. int rnodeCount=0;
  229. ability = await client.GetContainer("TEAMModelOS", "Normal").ReadItemAsync<Ability>($"{abilityId}", new PartitionKey($"Ability-{standard}"));
  230. await foreach (var item in client.GetContainer("TEAMModelOS", "Normal").GetItemQueryIteratorSql<AbilityTask>(queryText: $"select value(c) from c where c.abilityId='{abilityId}'",
  231. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{standard}") }))
  232. {
  233. var rns = item.children.Select(x => x.rnodes);
  234. if (rns != null)
  235. {
  236. var list = rns.ToList();
  237. list.ForEach(x => {
  238. if (x.IsNotEmpty())
  239. {
  240. rnodeCount += 1;
  241. }
  242. });
  243. }
  244. List<AbilityTaskTree> trees = AbilityService.ListToTree(item.children);
  245. AbilityTaskTreeNode tree = new AbilityTaskTreeNode() { id = item.id, scope = item.scope, trees = trees, abilityId = item.abilityId, auth = item.auth, codeval = ability.school };
  246. treeNodes.Add(tree);
  247. }
  248. //对课纲树形结构排序
  249. if (ability.abilityTaskIds.IsNotEmpty())
  250. {
  251. ability.abilityTaskIds.ForEach(x =>
  252. {
  253. for (int index = 0; index < treeNodes.Count; index++)
  254. {
  255. if (treeNodes[index].id .Equals(x))
  256. {
  257. redt.Add(treeNodes[index]);
  258. treeNodes.RemoveAt(index);
  259. }
  260. }
  261. });
  262. redt.AddRange(treeNodes);
  263. return Ok(new { tree = redt });
  264. }
  265. else
  266. {
  267. return Ok(new { tree = treeNodes, rnodeCount });
  268. }
  269. }
  270. catch (Exception ex)
  271. {
  272. await _dingDing.SendBotMsg($"OS,{_option.Location},common/syllabus/find-id\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  273. return Ok(new { tree = treeNodes });
  274. }
  275. }
  276. /*
  277. {"id":"章节id","code":"学校编码/醍摩豆id","scope":"school/private"}
  278. */
  279. /// <summary>
  280. /// 删除章节
  281. /// </summary>
  282. /// <param name="request"></param>
  283. /// <returns></returns>
  284. [ProducesDefaultResponseType]
  285. [HttpPost("delete")]
  286. [Authorize(Roles = "IES")]
  287. [AuthToken(Roles = "area")]
  288. public async Task<IActionResult> Delete(JsonElement request)
  289. {
  290. try
  291. {
  292. //if (!HttpContext.Items.TryGetValue("Standard", out object standard)) return BadRequest();
  293. if (!request.TryGetProperty("standard", out JsonElement standard)) return BadRequest();
  294. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  295. //if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  296. var client = _azureCosmos.GetCosmosClient();
  297. var response = await client.GetContainer("TEAMModelOS", "Normal").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"AbilityTask-{standard}"));
  298. return Ok(new { code = response.StatusCode });
  299. }
  300. catch
  301. {
  302. return Ok(new { code = 404 });
  303. }
  304. }
  305. }
  306. }