SchoolController.cs 22 KB

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