SchoolController.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using Microsoft.Extensions.Options;
  5. using StackExchange.Redis;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using System.Text.Json;
  10. using System.Threading.Tasks;
  11. using TEAMModelBI.Filter;
  12. using TEAMModelBI.Tool;
  13. using TEAMModelBI.Tool.Extension;
  14. using TEAMModelOS.Models;
  15. using TEAMModelOS.SDK.DI;
  16. using TEAMModelOS.SDK.Extension;
  17. using TEAMModelOS.SDK.Models;
  18. using TEAMModelOS.SDK.Models.Cosmos.BI;
  19. namespace TEAMModelBI.Controllers.BISchool
  20. {
  21. [Route("schoolcheck")]
  22. [ApiController]
  23. public class SchoolController : ControllerBase
  24. {
  25. private readonly AzureCosmosFactory _azureCosmos;
  26. private readonly DingDing _dingDing;
  27. private readonly Option _option;
  28. private readonly AzureStorageFactory _azureStorage;
  29. private readonly AzureRedisFactory _azureRedis;
  30. public SchoolController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, AzureRedisFactory azureRedis)
  31. {
  32. _azureCosmos = azureCosmos;
  33. _dingDing = dingDing;
  34. _azureStorage = azureStorage;
  35. _option = option?.Value;
  36. _azureRedis = azureRedis;
  37. }
  38. /// <summary>
  39. /// 查询未加入区域的学校
  40. /// </summary>
  41. /// <returns></returns>
  42. [ProducesDefaultResponseType]
  43. [HttpPost("get-notarea")]
  44. public async Task<IActionResult> GetNotAreaSchool()
  45. {
  46. try
  47. {
  48. var cosmosClient = _azureCosmos.GetCosmosClient();
  49. string sqltxt = $"SELECT c.id,c.name,c.schoolCode,c.province,c.city,c.dist,c.picture,c.period FROM c WHERE c.standard=null";
  50. List<NotAreaSchool> notAreaSchools = new List<NotAreaSchool>();
  51. await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: sqltxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  52. {
  53. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  54. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  55. {
  56. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  57. {
  58. //List<string> temp0 = obj.GetProperty("period").ToObject<List<Period>>().Select(x=>x.name).ToList();
  59. NotAreaSchool notAreaSchool = new NotAreaSchool()
  60. {
  61. id = obj.GetProperty("id").GetString(),
  62. name = obj.GetProperty("name").GetString(),
  63. schoolCode = obj.GetProperty("schoolCode").GetString(),
  64. picture = obj.GetProperty("picture").GetString(),
  65. period = obj.GetProperty("period").ToObject<List<Period>>().Select(x => x.name).ToList(),
  66. province = obj.GetProperty("province").GetString(),
  67. city = obj.GetProperty("city").GetString(),
  68. dist = obj.GetProperty("dist").GetString(),
  69. };
  70. notAreaSchools.Add(notAreaSchool);
  71. }
  72. }
  73. }
  74. return Ok(new { state = 200, notAreaSchools });
  75. }
  76. catch (Exception ex)
  77. {
  78. await _dingDing.SendBotMsg($"BI,{_option.Location} /schoolcheck/get-notarea \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  79. return BadRequest();
  80. }
  81. }
  82. /// <summary>
  83. /// 学校加入区
  84. /// </summary>
  85. /// <param name="jsonElement"></param>
  86. /// <returns></returns>
  87. [ProducesDefaultResponseType]
  88. [AuthToken(Roles = "assist")]
  89. [HttpPost("set-schooljoinarea")]
  90. public async Task<IActionResult> SetSchoolJoinArea(JsonElement jsonElement)
  91. {
  92. try
  93. {
  94. if (!jsonElement.TryGetProperty("tmdId", out JsonElement _tmdId)) return BadRequest(); //醍摩豆账户
  95. if (!jsonElement.TryGetProperty("tmdName", out JsonElement _tmdName)) return BadRequest(); //醍摩豆账号名称
  96. if (!jsonElement.TryGetProperty("standard", out JsonElement standard)) return BadRequest();
  97. if (!jsonElement.TryGetProperty("schoolCode", out JsonElement _schoolCode)) return BadRequest();
  98. if (!jsonElement.TryGetProperty("areaId", out JsonElement _areaId)) return BadRequest();
  99. List<string> schoolCodes = _schoolCode.ToObject<List<string>>();
  100. var cosmosCliet = _azureCosmos.GetCosmosClient();
  101. if (schoolCodes.Count > 0)
  102. {
  103. foreach (var tempCode in schoolCodes)
  104. {
  105. School school = await cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(tempCode,new PartitionKey("Base"));
  106. if (school != null)
  107. {
  108. school.standard = $"{standard}";
  109. school.areaId = $"{_areaId}";
  110. await cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey(school.code));
  111. }
  112. }
  113. }
  114. //保存操作记录
  115. await _azureStorage.SaveLog("school-join", $"{_tmdName}【{_tmdId}】操作学校加入区域功能,加入的区域:{standard},学校ID:{string.Join("|", schoolCodes.ToArray())}", _dingDing, httpContext: HttpContext);
  116. return Ok(new { state = 200 });
  117. }
  118. catch (Exception ex)
  119. {
  120. await _dingDing.SendBotMsg($"BI,{_option.Location} /schoolcheck/set-schooljoinarea \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  121. return BadRequest();
  122. }
  123. }
  124. /// <summary>
  125. /// 依据醍摩豆账户查询顾问管理学校的基础信息
  126. /// </summary>
  127. /// <param name="jsonElement"></param>
  128. /// <returns></returns>
  129. [HttpPost("get-assustschool")]
  130. public async Task<IActionResult> GetAssistSchool(JsonElement jsonElement)
  131. {
  132. try
  133. {
  134. if (!jsonElement.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
  135. List<string> schoolIds = new List<string>();
  136. List<object> schools = new List<object>();
  137. var cosmosClient = _azureCosmos.GetCosmosClient();
  138. string sqlTxt = $"SELECT DISTINCT REPLACE(c.code, 'Teacher-', '') AS schoolId FROM c WHERE c.pk = 'Teacher' AND c.status = 'join' AND ARRAY_CONTAINS(c.roles, 'assist', true) AND c.id='{tmdId}' ";
  139. await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { }))
  140. {
  141. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  142. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  143. {
  144. schoolIds.Add(obj.GetProperty("schoolId").GetString());
  145. }
  146. }
  147. foreach (var item in schoolIds)
  148. {
  149. await foreach (var itemBase in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"select c.id,c.code,c.name,c.picture,c.region,c.province,c.city,c.dist from c where c.id='{item}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  150. {
  151. var json = await JsonDocument.ParseAsync(itemBase.ContentStream);
  152. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  153. {
  154. schools.Add(obj.ToObject<object>());
  155. }
  156. }
  157. }
  158. return Ok(new { state = 200, schools });
  159. }
  160. catch (Exception ex)
  161. {
  162. await _dingDing.SendBotMsg($"BI,{_option.Location} /schoolcheck/get-assustschool {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  163. return BadRequest();
  164. }
  165. }
  166. /// <summary>
  167. /// 依据学校编号查询学校信息
  168. /// </summary>
  169. /// <param name="jsonElement"></param>
  170. /// <returns></returns>
  171. [HttpPost("get-schoolid")]
  172. public async Task<IActionResult> GetSchoolId(JsonElement jsonElement)
  173. {
  174. try
  175. {
  176. if (!jsonElement.TryGetProperty("schoolId", out JsonElement schoolId)) return BadRequest();
  177. var cosmosClient = _azureCosmos.GetCosmosClient();
  178. var rsponse = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{schoolId}", new PartitionKey("Base"));
  179. if (rsponse.Status == 200)
  180. {
  181. using var json = await JsonDocument.ParseAsync(rsponse.ContentStream);
  182. School school = json.ToObject<School>();
  183. return Ok(new { state = 200, school });
  184. }
  185. else
  186. return Ok(new { state = 404, msg = $"未找到ID是({schoolId})的学校" });
  187. }
  188. catch (Exception ex)
  189. {
  190. await _dingDing.SendBotMsg($"BI,{_option.Location} /schoolcheck/get-schoolid {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  191. return BadRequest();
  192. }
  193. }
  194. /// <summary>
  195. /// 修改学校信息
  196. /// </summary>
  197. /// <param name="school"></param>
  198. /// <returns></returns>
  199. [ProducesDefaultResponseType]
  200. [AuthToken(Roles = "assist")]
  201. [HttpPost("upd-school")]
  202. public async Task<IActionResult> UpdSchool(School school)
  203. {
  204. try
  205. {
  206. School schoolInfo = new School();
  207. var cosmosClient = _azureCosmos.GetCosmosClient();
  208. string _auth = HttpContext.GetXAuth("AuthToken");
  209. //var (tmdId, tmdName) = HttpJwtAnalysis.JwtXAuth(_auth, _option);
  210. var (tmdId, tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(_auth, _option);
  211. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(school.id, new PartitionKey($"Base"));
  212. if (response.Status == 200)
  213. {
  214. string sql = $"SELECT distinct value(c) FROM c join A1 in c.schools where A1.schoolId='{school.id}'";
  215. List<Teacher> teachers = new List<Teacher>();
  216. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Teacher>(sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  217. {
  218. teachers.Add(item);
  219. }
  220. foreach (var item in teachers)
  221. {
  222. Teacher.TeacherSchool teacherSchool = item.schools.Find(x => x.schoolId.Equals(school.id));
  223. if (teacherSchool != null)
  224. {
  225. teacherSchool.name = school.name;
  226. teacherSchool.picture = school.picture;
  227. teacherSchool.areaId = school.areaId;
  228. }
  229. await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(item, item.id, new PartitionKey($"Base"));
  230. }
  231. schoolInfo = await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<School>(school,school.id, new PartitionKey($"Base"));
  232. //保存操作记录
  233. await _azureStorage.SaveLog("school-update", $"{tmdName}【{tmdId}】修改学校信息,学校和ID:{school.name}【{school.id}】", _dingDing, httpContext: HttpContext);
  234. }
  235. else return Ok(new { state = 400, message = "请求错误!" });
  236. return Ok(new { state = 200, schoolInfo });
  237. //School tempShool = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(replaceSchool.school.id, new PartitionKey("Base"));
  238. //if (tempShool != null)
  239. //{
  240. // List<Teacher> teachers = new List<Teacher>();
  241. // string sqltxt = $"select distinct value(c) from c join a1 in c.schools where a1.schoolId='{replaceSchool.school.id}'";
  242. // await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Teacher>(queryText: sqltxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  243. // {
  244. // teachers.Add(item);
  245. // }
  246. // foreach (var item in teachers)
  247. // {
  248. // Teacher.TeacherSchool teacherSchool = item.schools.Find(x => x.schoolId.Equals(replaceSchool.school.id));
  249. // if (teacherSchool != null)
  250. // {
  251. // teacherSchool.name = replaceSchool.school.name;
  252. // teacherSchool.picture = replaceSchool.school.picture;
  253. // teacherSchool.areaId = replaceSchool.school.areaId;
  254. // }
  255. // await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(item, item.id, new PartitionKey("Base"));
  256. // }
  257. // schoolInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(replaceSchool.school, replaceSchool.school.id, new PartitionKey("Base"));
  258. // //保存操作记录
  259. // await _azureStorage.SaveLog("school-update", $"{replaceSchool.tmdName}【{replaceSchool.tmdId}】修改学校信息,学校和ID:{replaceSchool.school.name}【{replaceSchool.school.id}】", _dingDing, httpContext: HttpContext);
  260. // return Ok(new { state = 200, schoolInfo });
  261. //}
  262. //else return Ok(new { state = 400, message = "请求错误!" });
  263. }
  264. catch (Exception ex)
  265. {
  266. await _dingDing.SendBotMsg($"BI,{_option.Location} /batchschool/upd-school \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  267. return BadRequest();
  268. }
  269. }
  270. /// <summary>
  271. /// 顾问学校空间使用情况
  272. /// </summary>
  273. /// <param name="jsonElement"></param>
  274. /// <returns></returns>
  275. [HttpPost("get-space")]
  276. public async Task<IActionResult> GetAssistSchoolSpace(JsonElement jsonElement)
  277. {
  278. if (!jsonElement.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
  279. var cosmosClient = _azureCosmos.GetCosmosClient();
  280. List<string> schools = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
  281. List<SchoolSpace> schoolSpaces = new List<SchoolSpace>();
  282. foreach (var sid in schools)
  283. {
  284. School school = new();
  285. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(sid, new PartitionKey("Base"));
  286. if (response.Status == 200)
  287. {
  288. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  289. school = json.ToObject<School>();
  290. }
  291. long teach = 0;
  292. await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: $"SELECT sum(c.size) as size FROM c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{sid}") }))
  293. {
  294. var json = await JsonDocument.ParseAsync(item.ContentStream);
  295. foreach (var elmt in json.RootElement.GetProperty("Documents").EnumerateArray())
  296. {
  297. if (elmt.TryGetProperty("size", out JsonElement _size) && _size.ValueKind.Equals(JsonValueKind.Number))
  298. {
  299. teach = _size.GetInt32();
  300. break;
  301. }
  302. }
  303. }
  304. SchoolSpace schoolSpace = new SchoolSpace() { id = sid, name = school != null ? school.name : sid };
  305. Space space = new Space();
  306. long blobsize = 0; //使用大小
  307. RedisValue value = default;
  308. value = _azureRedis.GetRedisClient(8).HashGet($"Blob:Record", sid);
  309. if (value != default && !value.IsNullOrEmpty)
  310. {
  311. JsonElement record = value.ToString().ToObject<JsonElement>();
  312. if (record.TryGetInt64(out blobsize))
  313. {
  314. }
  315. }
  316. else
  317. {
  318. var client = _azureStorage.GetBlobContainerClient(sid);
  319. var size = await client.GetBlobsCatalogSize();
  320. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", sid, size.Item1);
  321. foreach (var key in size.Item2.Keys)
  322. {
  323. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{sid}", key);
  324. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{sid}", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
  325. }
  326. space.useSize = (long)size.Item1; space.tSize = teach; space.catalogSize = size.Item2;
  327. schoolSpace.space = space;
  328. schoolSpaces.Add(schoolSpace);
  329. continue;
  330. }
  331. Dictionary<string, double?> catalog = new Dictionary<string, double?>();
  332. SortedSetEntry[] Scores = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Blob:Catalog:{sid}");
  333. if (Scores != null)
  334. {
  335. foreach (var score in Scores)
  336. {
  337. double val = score.Score;
  338. string key = score.Element.ToString();
  339. catalog.Add(key, val);
  340. }
  341. space.useSize = blobsize; space.tSize = teach; space.catalogSize = catalog;
  342. schoolSpace.space = space;
  343. schoolSpaces.Add(schoolSpace);
  344. continue;
  345. }
  346. else
  347. {
  348. var client = _azureStorage.GetBlobContainerClient(sid);
  349. var size = await client.GetBlobsCatalogSize();
  350. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", sid, size.Item1);
  351. foreach (var key in size.Item2.Keys)
  352. {
  353. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{sid}", key);
  354. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{sid}", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
  355. }
  356. space.useSize = (long)size.Item1;
  357. space.tSize = teach;
  358. space.catalogSize = size.Item2;
  359. schoolSpace.space = space;
  360. schoolSpaces.Add(schoolSpace);
  361. continue;
  362. }
  363. }
  364. return Ok(new { state = 200, schoolSpaces });
  365. }
  366. /// <summary>
  367. /// 修改学校的结构
  368. /// </summary>
  369. public record ReplaceSchool()
  370. {
  371. /// <summary>
  372. /// 醍摩豆账户ID
  373. /// </summary>
  374. public string tmdId { get; set; }
  375. /// <summary>
  376. /// 醍摩豆账户名称
  377. /// </summary>
  378. public string tmdName { get; set; }
  379. /// <summary>
  380. /// 学校
  381. /// </summary>
  382. public School school { get; set; }
  383. }
  384. /// <summary>
  385. /// 未加入区域的学校
  386. /// </summary>
  387. public record NotAreaSchool
  388. {
  389. public string id { get; set; }
  390. public string name { get; set; }
  391. public string schoolCode { get; set; }
  392. public string picture { get; set; }
  393. public List<string> period { get; set; }
  394. public string province { get; set; }
  395. public string city { get; set; }
  396. public string dist { get; set; }
  397. }
  398. /// <summary>
  399. /// 学校空间使用情况
  400. /// </summary>
  401. public record SchoolSpace
  402. {
  403. public string id { get; set; }
  404. public string name { get; set; }
  405. public Space space { get; set; }
  406. }
  407. /// <summary>
  408. /// 空间
  409. /// </summary>
  410. public record Space
  411. {
  412. /// <summary>
  413. /// 已使用空间
  414. /// </summary>
  415. public long useSize { get; set; }
  416. /// <summary>
  417. /// 分配教师空间
  418. /// </summary>
  419. public long tSize { get; set; }
  420. /// <summary>
  421. /// 空间类型
  422. /// </summary>
  423. public Dictionary<string, double?> catalogSize { get; set; }
  424. }
  425. }
  426. }