KnowledgeController.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567
  1. using Microsoft.AspNetCore.Authorization;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Options;
  5. using System.Collections.Generic;
  6. using System.Text.Json;
  7. using System.Threading.Tasks;
  8. using TEAMModelOS.Filter;
  9. using TEAMModelOS.Models;
  10. using TEAMModelOS.SDK;
  11. using TEAMModelOS.SDK.DI;
  12. using TEAMModelOS.SDK.Models;
  13. using TEAMModelOS.SDK.Extension;
  14. using System.Text;
  15. using System;
  16. using Azure.Cosmos;
  17. using TEAMModelOS.SDK.Models.Service;
  18. using System.Linq;
  19. using OfficeOpenXml;
  20. namespace TEAMModelOS.Controllers.Both
  21. {
  22. [ProducesResponseType(StatusCodes.Status200OK)]
  23. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  24. [Route("knowledge")]
  25. [ApiController]
  26. public class KnowledgeController : ControllerBase
  27. {
  28. private readonly SnowflakeId _snowflakeId;
  29. private readonly AzureCosmosFactory _azureCosmos;
  30. private readonly DingDing _dingDing;
  31. private readonly Option _option;
  32. private readonly AzureRedisFactory _azureRedis;
  33. private readonly HttpTrigger _httpTrigger;
  34. public KnowledgeController(HttpTrigger httpTrigger, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureRedisFactory azureRedis)
  35. {
  36. _azureCosmos = azureCosmos;
  37. _snowflakeId = snowflakeId;
  38. _dingDing = dingDing;
  39. _option = option?.Value;
  40. _azureRedis = azureRedis;
  41. _httpTrigger = httpTrigger;
  42. }
  43. [ProducesDefaultResponseType]
  44. [HttpPost("import")]
  45. #if !DEBUG
  46. [Authorize(Roles = "IES")]
  47. #endif
  48. [AuthToken(Roles = "admin", Permissions = "knowledge-upd")]
  49. public IActionResult ItemImport([FromForm] IFormFile file)
  50. {
  51. var tokenAuth = HttpContext.GetAuthTokenInfo();
  52. ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
  53. List<dynamic> period_subject = new List<dynamic>();
  54. List<MoofenKnowledgePointDto> pointDtos = new List<MoofenKnowledgePointDto>();
  55. List<string> titles = new List<string>();
  56. List<List<string>> datas = new List<List<string>>();
  57. using (ExcelPackage package = new ExcelPackage(file.OpenReadStream()))
  58. {
  59. ExcelWorksheets sheets = package.Workbook.Worksheets;
  60. var sheet = sheets.FirstOrDefault();
  61. if (sheet!= null)
  62. {
  63. var rows = sheet.Dimension.Rows;
  64. var columns = sheet.Dimension.Columns;
  65. for (int r = 1; r <= rows; r++)
  66. {
  67. List<string> data = new List<string>();
  68. for (int c = 1; c <= columns; c++)
  69. {
  70. var value = sheet.GetValue(r, c);
  71. if (r == 1)
  72. {
  73. if (!string.IsNullOrWhiteSpace($"{value}"))
  74. {
  75. titles.Add($"{value}");
  76. }
  77. else
  78. {
  79. break;
  80. }
  81. }
  82. else
  83. {
  84. if (c > titles.Count)
  85. {
  86. break;
  87. }
  88. else
  89. {
  90. data.Add($"{value}");
  91. }
  92. }
  93. }
  94. if (data.Any())
  95. {
  96. datas.Add(data);
  97. }
  98. }
  99. }
  100. }
  101. int index = 1;
  102. foreach (var data in datas)
  103. {
  104. MoofenKnowledgePointDto knowledgePointDto = new MoofenKnowledgePointDto { kp1 = data[0], kp2= data[1], kp3 = data[2], kp4= data[3], id=$"{index}" };
  105. if (!string.IsNullOrWhiteSpace(knowledgePointDto.kp1))
  106. {
  107. knowledgePointDto.level=1;
  108. knowledgePointDto.name=knowledgePointDto.kp1;
  109. }
  110. if (!string.IsNullOrWhiteSpace(knowledgePointDto.kp2))
  111. {
  112. knowledgePointDto.level=2;
  113. knowledgePointDto.name=knowledgePointDto.kp2;
  114. }
  115. if (!string.IsNullOrWhiteSpace(knowledgePointDto.kp3))
  116. {
  117. knowledgePointDto.level=3;
  118. knowledgePointDto.name=knowledgePointDto.kp3;
  119. }
  120. if (!string.IsNullOrWhiteSpace(knowledgePointDto.kp4))
  121. {
  122. knowledgePointDto.level=4;
  123. knowledgePointDto.name=knowledgePointDto.kp4;
  124. }
  125. pointDtos.Add(knowledgePointDto);
  126. index++;
  127. } // 构建树形结构
  128. var tree = KnowledgeService.BuildTree(pointDtos);
  129. tree.name=$"{file.FileName}";
  130. KnowledgeTreeDto knowledge = new KnowledgeTreeDto()
  131. {
  132. name=tree.name,
  133. tree= tree.children,
  134. };
  135. return Ok(new { knowledgeTree =knowledge});
  136. }
  137. [ProducesDefaultResponseType]
  138. [HttpPost("read")]
  139. #if !DEBUG
  140. [Authorize(Roles = "IES")]
  141. [AuthToken(Roles = "teacher,admin,student", Permissions = "knowledge-read,knowledge-upd")]
  142. #endif
  143. public async Task<IActionResult> ReadKnowledge(JsonElement json)
  144. {
  145. var client = _azureCosmos.GetCosmosClient();
  146. var tokenAuth = HttpContext.GetAuthTokenInfo();
  147. string scope = "school";
  148. if (json.TryGetProperty("scope", out JsonElement _scope))
  149. {
  150. scope=$"{scope}";
  151. }
  152. List<Knowledge> knowledges = new List<Knowledge>();
  153. string code = string.Empty;
  154. List<string> keywords = new List<string>();
  155. if (scope.Equals("school"))
  156. {
  157. json.TryGetProperty("periodId", out JsonElement periodId);
  158. if (!json.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
  159. string school=string.Empty;
  160. if (string.IsNullOrWhiteSpace(tokenAuth.school))
  161. {
  162. if (json.TryGetProperty("school_code", out JsonElement school_code))
  163. {
  164. school=$"{school_code}";
  165. }
  166. }
  167. else {
  168. school=tokenAuth.school;
  169. }
  170. code = $"Knowledge-{school}-{subjectId}";
  171. StringBuilder sql = new StringBuilder($"select value(c) from c");
  172. if (periodId.ValueKind.Equals(JsonValueKind.String))
  173. {
  174. sql.Append($" where c.periodId = '{periodId}'");
  175. }
  176. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<Knowledge>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
  177. {
  178. item.blocks.ForEach(x =>
  179. {
  180. if (x.points == null)
  181. {
  182. x.points = keywords;
  183. }
  184. });
  185. knowledges.Add(item);
  186. }
  187. }
  188. else {
  189. code=$"Knowledge-{tokenAuth.id}";
  190. StringBuilder sql = new StringBuilder($"select value(c) from c");
  191. await foreach (var item in client.GetContainer(Constant.TEAMModelOS,Constant.Teacher).GetItemQueryIterator<Knowledge>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
  192. {
  193. item.blocks.ForEach(x =>
  194. {
  195. if (x.points == null)
  196. {
  197. x.points = keywords;
  198. }
  199. });
  200. knowledges.Add(item);
  201. }
  202. }
  203. return Ok(new { knowledgeTrees = KnowledgeService. KnowledgeTranslate(knowledges) });
  204. }
  205. [ProducesDefaultResponseType]
  206. [HttpPost("modify")]
  207. #if !DEBUG
  208. [Authorize(Roles = "IES")]
  209. [AuthToken(Roles = "admin", Permissions = "knowledge-upd")]
  210. #endif
  211. public async Task<IActionResult> ModifyKnowledgeNode(JsonElement json)
  212. {
  213. List<TagOldNew> old_new = null;
  214. if (json.TryGetProperty("old_new", out JsonElement _old_new))
  215. {
  216. old_new = _old_new.ToObject<List<TagOldNew>>();
  217. }
  218. string id = json.GetProperty("id").GetString();
  219. string scope = json.GetProperty("scope").GetString();
  220. string owner = json.GetProperty("owner").GetString();
  221. string code =string.Empty;
  222. string tbname = string.Empty;
  223. string subjectId=string.Empty;
  224. int updateRel = json.GetProperty("updateRel").GetInt32();
  225. List<TagOldNew> updateData = new List<TagOldNew>();
  226. if ($"{scope}".Equals("school"))
  227. {
  228. subjectId = json.GetProperty("subjectId").GetString();
  229. code = $"Knowledge-{owner}-{subjectId}";
  230. tbname= Constant.School;
  231. }
  232. else {
  233. code=$"Knowledge-{owner}";
  234. tbname= Constant.Teacher;
  235. }
  236. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(id, new PartitionKey(code));
  237. if (response.Status==200)
  238. {
  239. bool change = false;
  240. Knowledge knowledge = JsonDocument.Parse(response.Content).RootElement.ToObject<Knowledge>();
  241. foreach(TagOldNew tagOldNew in old_new)
  242. {
  243. if(!string.IsNullOrWhiteSpace(tagOldNew._id) && !string.IsNullOrEmpty(tagOldNew._old) &&! string.IsNullOrWhiteSpace(tagOldNew._new) && !tagOldNew._old.Equals(tagOldNew._new))
  244. {
  245. var node = knowledge.nodes.Find(x =>!string.IsNullOrWhiteSpace(x.name) && x.id.Equals(tagOldNew._id) && tagOldNew._old.Equals(x.name));
  246. node.name= tagOldNew._new;
  247. updateData.Add(tagOldNew);
  248. change = true;
  249. }
  250. if ( !string.IsNullOrEmpty(tagOldNew._old) &&!string.IsNullOrWhiteSpace(tagOldNew._new) && !tagOldNew._old.Equals(tagOldNew._new))
  251. {
  252. var rsp= knowledge.points.Remove(tagOldNew._old);
  253. if (rsp) {
  254. change=true;
  255. knowledge.points.Add(tagOldNew._new);
  256. }
  257. foreach (var block in knowledge.blocks) {
  258. if (block.source!=1)
  259. {
  260. var rsb= block.points.Remove(tagOldNew._old);
  261. if (rsb) {
  262. block.points.Add(tagOldNew._new);
  263. change=true;
  264. }
  265. }
  266. }
  267. }
  268. }
  269. if (change) {
  270. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).UpsertItemAsync(knowledge, new PartitionKey(code));
  271. }
  272. if (updateData.IsNotEmpty() &&updateRel==1)
  273. {
  274. try
  275. {
  276. _ = _httpTrigger.RequestHttpTrigger(new { old_new = old_new, owner = $"{owner}", scope = $"{scope}", subjectId = $"{subjectId}" }, _option.Location, "knowledge-change");
  277. }
  278. catch (Exception ex)
  279. {
  280. //暂不处理
  281. }
  282. }
  283. var dto = KnowledgeService.KnowledgeTranslate(knowledge);
  284. return Ok(new { knowledgeTree = dto});
  285. }
  286. return Ok(new {code =404});
  287. }
  288. [ProducesDefaultResponseType]
  289. [HttpPost("upsert")]
  290. #if !DEBUG
  291. [Authorize(Roles = "IES")]
  292. [AuthToken(Roles = "admin", Permissions = "knowledge-upd")]
  293. #endif
  294. public async Task<IActionResult> UpsertKnowledge(JsonElement json)
  295. {
  296. KnowledgeTreeDto knowledge = json.GetProperty("knowledge").ToObject<KnowledgeTreeDto>();
  297. ValidResult validResult = knowledge.Valid();
  298. if (!validResult.isVaild)
  299. {
  300. return BadRequest(validResult);
  301. }
  302. var client = _azureCosmos.GetCosmosClient();
  303. string code = string.Empty;
  304. Knowledge old = null;
  305. Knowledge knowledgeDb=null;
  306. var blocks = new List<Block>();
  307. var points = new HashSet<string>();
  308. var nodes = new List<PointNode>();
  309. KnowledgeService.TreeToList(knowledge.tree, nodes, blocks, points);
  310. if (knowledge.scope.Equals("school"))
  311. {
  312. if (!string.IsNullOrWhiteSpace(knowledge.subjectId) && !string.IsNullOrWhiteSpace(knowledge.periodId))
  313. {
  314. code = $"Knowledge-{knowledge.owner}-{knowledge.subjectId}";
  315. StringBuilder sql = new StringBuilder($"select value c from c where c.periodId = '{knowledge.periodId}'");
  316. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Knowledge>
  317. (queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
  318. {
  319. old = item;
  320. break;
  321. }
  322. if (old!=null)
  323. {
  324. knowledge.id = old.id;
  325. knowledge.points=old.points;
  326. knowledge.blocks=old.blocks;
  327. foreach (var p in old.points)
  328. {
  329. points.Add(p);
  330. }
  331. foreach (var b in old.blocks)
  332. {
  333. var bks = blocks.FindAll(x => x.name.Equals(b.name));
  334. if (bks.IsNotEmpty())
  335. {
  336. foreach (var bk in bks)
  337. {
  338. bk.points.AddRange(b.points);
  339. bk.points= bk.points.Distinct().ToList();
  340. }
  341. }
  342. else
  343. {
  344. blocks.Add(b);
  345. }
  346. }
  347. }
  348. else
  349. {
  350. knowledge.id = Guid.NewGuid().ToString();
  351. }
  352. knowledgeDb = new Knowledge
  353. {
  354. id=knowledge.id,
  355. code=code,
  356. name=knowledge.name,
  357. periodId=knowledge.periodId,
  358. subjectId =knowledge.subjectId,
  359. scope=knowledge.scope,
  360. blocks=knowledge.blocks,
  361. pk="Knowledge",
  362. points=knowledge.points.ToList(),
  363. nodes=nodes,
  364. owner=knowledge.owner,
  365. };
  366. var count = new { pcount = points.Count, bcount = blocks.Count,name =knowledge.name };
  367. //处理知识点,知识块计数问题
  368. string key = $"KnowledgeNew:Count:{knowledge.owner}-{knowledge.periodId}";
  369. string filed = knowledge.subjectId;
  370. await _azureRedis.GetRedisClient(8).HashSetAsync(key, filed, count.ToJsonString());
  371. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).UpsertItemAsync(knowledgeDb, new PartitionKey(code));
  372. }
  373. else {
  374. return BadRequest();
  375. }
  376. }
  377. else
  378. {
  379. code=$"Knowledge-{knowledge.owner}";
  380. if (!string.IsNullOrWhiteSpace(knowledge.id))
  381. {
  382. Azure.Response response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(knowledge.id, new PartitionKey(code));
  383. if (response.Status!=200)
  384. {
  385. knowledge.id = Guid.NewGuid().ToString();
  386. }
  387. }
  388. knowledgeDb = new Knowledge
  389. {
  390. id=knowledge.id,
  391. code=code,
  392. name=knowledge.name,
  393. periodId=knowledge.periodId,
  394. subjectId =knowledge.subjectId,
  395. scope=knowledge.scope,
  396. //blocks=blocks,
  397. pk="Knowledge",
  398. // points=points.ToList(),
  399. nodes=nodes,
  400. owner=knowledge.owner,
  401. };
  402. //处理知识点,知识块计数问题
  403. string key = $"KnowledgeNew:Count:{knowledge.owner}";
  404. string filed = knowledge.id;
  405. var count = new { pcount = points.Count, bcount = blocks.Count, name = knowledge.name };
  406. await _azureRedis.GetRedisClient(8).HashSetAsync(key, filed, count.ToJsonString());
  407. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(knowledgeDb, new PartitionKey(code));
  408. }
  409. if (knowledgeDb!=null)
  410. {
  411. var dto = KnowledgeService.KnowledgeTranslate(knowledgeDb);
  412. return Ok(new { knowledgeTree = dto });
  413. }
  414. else {
  415. return BadRequest();
  416. }
  417. }
  418. [ProducesDefaultResponseType]
  419. [HttpPost("list")]
  420. #if !DEBUG
  421. [Authorize(Roles = "IES")]
  422. #endif
  423. [AuthToken(Roles = "teacher,admin,student", Permissions = "knowledge-read,knowledge-upd")]
  424. public async Task<IActionResult> FindCount(JsonElement json)
  425. {
  426. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  427. if (!json.TryGetProperty("scope", out var _scope)) {
  428. return BadRequest();
  429. }
  430. List<KnowledgeCount> datas = new List<KnowledgeCount>();
  431. if ($"{_scope}".Equals("school", StringComparison.OrdinalIgnoreCase))
  432. {
  433. if (!json.TryGetProperty("periodId", out var periodId))
  434. {
  435. return BadRequest();
  436. }
  437. School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
  438. var period = schoolBase.period.Find(x => x.id.Equals($"{periodId}", StringComparison.OrdinalIgnoreCase));
  439. var values = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"KnowledgeNew:Count:{period.id}");
  440. if (values!=null && values!=default && values.Length>0)
  441. {
  442. foreach (var value in values)
  443. {
  444. KnowledgeCount record = value.Value.ToString().ToObject<KnowledgeCount>();
  445. record.periodId=period.id;
  446. record.subjectId=value.Name;
  447. record.owner=school;
  448. record.scope="school";
  449. datas.Add(record);
  450. }
  451. }
  452. foreach (var subject in period.subjects)
  453. {
  454. var record = datas.Find(x => x.subjectId.Equals(subject.id));
  455. if (record!=null)
  456. {
  457. record.name= subject.name;
  458. }
  459. else {
  460. string sql= $" select value c from c where c.subjectId='{subject.id}' and c.periodId='{period.id}' ";
  461. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Knowledge>(sql, $"Knowledge-{school}-{subject.id}");
  462. if (result.list.IsNotEmpty())
  463. {
  464. foreach (var item in result.list) {
  465. var dto = KnowledgeService.KnowledgeTranslate(item);
  466. var count = new { pcount = dto.points.Count(), bcount = dto.blocks.Count(), name = subject.name };
  467. //处理知识点,知识块计数问题
  468. string key = $"KnowledgeNew:Count:{item.owner}-{item.periodId}";
  469. string filed = item.subjectId;
  470. await _azureRedis.GetRedisClient(8).HashSetAsync(key, filed, count.ToJsonString());
  471. record = new KnowledgeCount
  472. {
  473. id= item.id,
  474. periodId=period.id,
  475. subjectId=subject.id,
  476. name=subject.name,
  477. owner=school,
  478. scope="school",
  479. pcount=dto.points.Count(),
  480. bcount=dto.blocks.Count(),
  481. };
  482. datas.Add(record);
  483. break;
  484. }
  485. }
  486. else {
  487. record = new KnowledgeCount
  488. {
  489. periodId=period.id,
  490. subjectId=subject.id,
  491. name=subject.name,
  492. owner=school,
  493. scope="school",
  494. pcount=0,
  495. bcount=0,
  496. };
  497. datas.Add(record);
  498. }
  499. }
  500. }
  501. }
  502. else {
  503. var values = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"KnowledgeNew:Count:{userid}");
  504. if (values!=null && values!=default && values.Length>0)
  505. {
  506. foreach (var value in values)
  507. {
  508. KnowledgeCount record = value.Value.ToString().ToObject<KnowledgeCount>();
  509. record.id=value.Name;
  510. record.owner=userid;
  511. record.scope="private";
  512. datas.Add(record);
  513. }
  514. }
  515. string sql = string.Empty;
  516. if (datas.IsNotEmpty())
  517. {
  518. sql= $" select value c from c where c.id not in ({string.Join(",", datas.Select(x => $"'{x.id}'"))}) ";
  519. }
  520. else {
  521. sql= $" select value c from c ";
  522. }
  523. var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<Knowledge>(sql, $"Knowledge-{userid}");
  524. if (result.list.IsNotEmpty())
  525. {
  526. foreach (var item in result.list)
  527. {
  528. var dto= KnowledgeService.KnowledgeTranslate(item);
  529. //处理知识点,知识块计数问题
  530. string key = $"KnowledgeNew:Count:{item.owner}";
  531. string filed = item.id;
  532. var count = new { pcount = dto. points.Count(), bcount = dto.blocks.Count(), name = item.name };
  533. await _azureRedis.GetRedisClient(8).HashSetAsync(key, filed, count.ToJsonString());
  534. KnowledgeCount record = new KnowledgeCount
  535. {
  536. id=item.id,
  537. name=item.name,
  538. owner=userid,
  539. scope="private",
  540. pcount=dto.points.Count(),
  541. bcount=dto.blocks.Count(),
  542. };
  543. datas.Add(record);
  544. }
  545. }
  546. }
  547. return Ok(new { datas });
  548. }
  549. }
  550. }