SchoolController.cs 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. using Azure.Cosmos;
  2. using HTEXLib.COMM.Helpers;
  3. using Microsoft.AspNetCore.Http;
  4. using Microsoft.AspNetCore.Mvc;
  5. using Microsoft.Extensions.Configuration;
  6. using Microsoft.Extensions.Options;
  7. using StackExchange.Redis;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Linq;
  11. using System.Text;
  12. using System.Text.Json;
  13. using System.Threading.Tasks;
  14. using TEAMModelBI.Filter;
  15. using TEAMModelBI.Tool;
  16. using TEAMModelBI.Tool.CosmosBank;
  17. using TEAMModelBI.Tool.Extension;
  18. using TEAMModelOS.Models;
  19. using TEAMModelOS.SDK.DI;
  20. using TEAMModelOS.SDK.Extension;
  21. using TEAMModelOS.SDK.Models;
  22. using TEAMModelOS.SDK.Models.Cosmos.BI;
  23. using TEAMModelOS.SDK.Models.Service;
  24. namespace TEAMModelBI.Controllers.BISchool
  25. {
  26. [Route("schoolcheck")]
  27. [ApiController]
  28. public class SchoolController : ControllerBase
  29. {
  30. private readonly AzureCosmosFactory _azureCosmos;
  31. private readonly DingDing _dingDing;
  32. private readonly Option _option;
  33. private readonly AzureStorageFactory _azureStorage;
  34. private readonly AzureRedisFactory _azureRedis;
  35. private readonly IConfiguration _configuration;
  36. private readonly NotificationService _notificationService;
  37. public SchoolController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, AzureRedisFactory azureRedis, IConfiguration configuration, NotificationService notificationService)
  38. {
  39. _azureCosmos = azureCosmos;
  40. _dingDing = dingDing;
  41. _azureStorage = azureStorage;
  42. _option = option?.Value;
  43. _azureRedis = azureRedis;
  44. _configuration = configuration;
  45. _notificationService = notificationService;
  46. }
  47. /// <summary>
  48. /// 查询未加入区域的学校
  49. /// </summary>
  50. /// <returns></returns>
  51. [ProducesDefaultResponseType]
  52. [HttpPost("get-notarea")]
  53. public async Task<IActionResult> GetNotAreaSchool()
  54. {
  55. try
  56. {
  57. var cosmosClient = _azureCosmos.GetCosmosClient();
  58. 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";
  59. List<NotAreaSchool> notAreaSchools = new List<NotAreaSchool>();
  60. await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: sqltxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  61. {
  62. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  63. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  64. {
  65. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  66. {
  67. //List<string> temp0 = obj.GetProperty("period").ToObject<List<Period>>().Select(x=>x.name).ToList();
  68. NotAreaSchool notAreaSchool = new NotAreaSchool()
  69. {
  70. id = obj.GetProperty("id").GetString(),
  71. name = obj.GetProperty("name").GetString(),
  72. schoolCode = obj.GetProperty("schoolCode").GetString(),
  73. picture = obj.GetProperty("picture").GetString(),
  74. period = obj.GetProperty("period").ToObject<List<Period>>().Select(x => x.name).ToList(),
  75. province = obj.GetProperty("province").GetString(),
  76. city = obj.GetProperty("city").GetString(),
  77. dist = obj.GetProperty("dist").GetString(),
  78. };
  79. notAreaSchools.Add(notAreaSchool);
  80. }
  81. }
  82. }
  83. return Ok(new { state = 200, notAreaSchools });
  84. }
  85. catch (Exception ex)
  86. {
  87. await _dingDing.SendBotMsg($"BI,{_option.Location} /schoolcheck/get-notarea \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  88. return BadRequest();
  89. }
  90. }
  91. /// <summary>
  92. /// 学校加入区
  93. /// </summary>
  94. /// <param name="jsonElement"></param>
  95. /// <returns></returns>
  96. [ProducesDefaultResponseType]
  97. [AuthToken(Roles = "assist")]
  98. [HttpPost("set-schooljoinarea")]
  99. public async Task<IActionResult> SetSchoolJoinArea(JsonElement jsonElement)
  100. {
  101. try
  102. {
  103. if (!jsonElement.TryGetProperty("standard", out JsonElement standard)) return BadRequest();
  104. if (!jsonElement.TryGetProperty("schoolCode", out JsonElement _schoolCode)) return BadRequest();
  105. if (!jsonElement.TryGetProperty("areaId", out JsonElement _areaId)) return BadRequest();
  106. var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
  107. List<string> schoolCodes = _schoolCode.ToObject<List<string>>();
  108. var cosmosCliet = _azureCosmos.GetCosmosClient();
  109. if (schoolCodes.Count > 0)
  110. {
  111. foreach (var tempCode in schoolCodes)
  112. {
  113. School school = await cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(tempCode, new PartitionKey("Base"));
  114. if (school != null)
  115. {
  116. school.standard = $"{standard}";
  117. school.areaId = $"{_areaId}";
  118. await cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey(school.code));
  119. }
  120. }
  121. }
  122. //保存操作记录
  123. await _azureStorage.SaveBILog("school-update", $"{_tmdName}【{_tmdId}】操作学校加入区域功能,加入的区域:{standard},学校ID:{string.Join("|", schoolCodes.ToArray())}", _dingDing, httpContext: HttpContext);
  124. return Ok(new { state = 200 });
  125. }
  126. catch (Exception ex)
  127. {
  128. await _dingDing.SendBotMsg($"BI,{_option.Location} /schoolcheck/set-schooljoinarea \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  129. return BadRequest();
  130. }
  131. }
  132. /// <summary>
  133. /// 依据醍摩豆账户查询顾问管理学校的基础信息
  134. /// </summary>
  135. /// <param name="jsonElement"></param>
  136. /// <returns></returns>
  137. [HttpPost("get-assistschool")]
  138. public async Task<IActionResult> GetAssistSchool(JsonElement jsonElement)
  139. {
  140. try
  141. {
  142. if (!jsonElement.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
  143. List<object> schools = new List<object>();
  144. var cosmosClient = _azureCosmos.GetCosmosClient();
  145. //List<string> schoolIds = new List<string>();
  146. //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}' ";
  147. //await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { }))
  148. //{
  149. // using var json = await JsonDocument.ParseAsync(item.ContentStream);
  150. // foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  151. // {
  152. // schoolIds.Add(obj.GetProperty("schoolId").GetString());
  153. // }
  154. //}
  155. List<string> schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
  156. foreach (var item in schoolIds)
  157. {
  158. 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") }))
  159. {
  160. var json = await JsonDocument.ParseAsync(itemBase.ContentStream);
  161. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  162. {
  163. schools.Add(obj.ToObject<object>());
  164. }
  165. }
  166. }
  167. return Ok(new { state = 200, schools });
  168. }
  169. catch (Exception ex)
  170. {
  171. await _dingDing.SendBotMsg($"BI,{_option.Location} /schoolcheck/get-assustschool \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  172. return BadRequest();
  173. }
  174. }
  175. /// <summary>
  176. /// 依据学校编号查询学校信息
  177. /// </summary>
  178. /// <param name="jsonElement"></param>
  179. /// <returns></returns>
  180. [HttpPost("get-schoolid")]
  181. public async Task<IActionResult> GetSchoolId(JsonElement jsonElement)
  182. {
  183. try
  184. {
  185. if (!jsonElement.TryGetProperty("schoolId", out JsonElement schoolId)) return BadRequest();
  186. var cosmosClient = _azureCosmos.GetCosmosClient();
  187. var rsponse = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{schoolId}", new PartitionKey("Base"));
  188. if (rsponse.Status == 200)
  189. {
  190. using var json = await JsonDocument.ParseAsync(rsponse.ContentStream);
  191. School school = json.ToObject<School>();
  192. return Ok(new { state = 200, school });
  193. }
  194. else
  195. return Ok(new { state = 404, msg = $"未找到ID是({schoolId})的学校" });
  196. }
  197. catch (Exception ex)
  198. {
  199. await _dingDing.SendBotMsg($"BI,{_option.Location} /schoolcheck/get-schoolid \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  200. return BadRequest();
  201. }
  202. }
  203. /// <summary>
  204. /// 修改学校信息
  205. /// </summary>
  206. /// <param name="school"></param>
  207. /// <returns></returns>
  208. [ProducesDefaultResponseType]
  209. [AuthToken(Roles = "assist")]
  210. [HttpPost("upd-school")]
  211. public async Task<IActionResult> UpdSchool(School school)
  212. {
  213. try
  214. {
  215. School schoolInfo = new School();
  216. var cosmosClient = _azureCosmos.GetCosmosClient();
  217. string _auth = HttpContext.GetXAuth("AuthToken");
  218. //var (tmdId, tmdName) = HttpJwtAnalysis.JwtXAuth(_auth, _option);
  219. var (tmdId, tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(_auth, _option);
  220. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(school.id, new PartitionKey($"Base"));
  221. if (response.Status == 200)
  222. {
  223. string sql = $"SELECT distinct value(c) FROM c join A1 in c.schools where A1.schoolId='{school.id}'";
  224. List<Teacher> teachers = new List<Teacher>();
  225. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Teacher>(sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
  226. {
  227. teachers.Add(item);
  228. }
  229. foreach (var item in teachers)
  230. {
  231. Teacher.TeacherSchool teacherSchool = item.schools.Find(x => x.schoolId.Equals(school.id));
  232. if (teacherSchool != null)
  233. {
  234. teacherSchool.name = school.name;
  235. teacherSchool.picture = school.picture;
  236. teacherSchool.areaId = school.areaId;
  237. }
  238. await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync(item, item.id, new PartitionKey($"Base"));
  239. }
  240. schoolInfo = await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<School>(school, school.id, new PartitionKey($"Base"));
  241. //保存操作记录
  242. await _azureStorage.SaveBILog("school-update", $"{tmdName}【{tmdId}】修改学校信息,学校和ID:{school.name}【{school.id}】", _dingDing, httpContext: HttpContext);
  243. }
  244. else return Ok(new { state = 400, message = "请求错误!" });
  245. return Ok(new { state = 200, schoolInfo });
  246. //School tempShool = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(replaceSchool.school.id, new PartitionKey("Base"));
  247. //if (tempShool != null)
  248. //{
  249. // List<Teacher> teachers = new List<Teacher>();
  250. // string sqltxt = $"select distinct value(c) from c join a1 in c.schools where a1.schoolId='{replaceSchool.school.id}'";
  251. // await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Teacher>(queryText: sqltxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  252. // {
  253. // teachers.Add(item);
  254. // }
  255. // foreach (var item in teachers)
  256. // {
  257. // Teacher.TeacherSchool teacherSchool = item.schools.Find(x => x.schoolId.Equals(replaceSchool.school.id));
  258. // if (teacherSchool != null)
  259. // {
  260. // teacherSchool.name = replaceSchool.school.name;
  261. // teacherSchool.picture = replaceSchool.school.picture;
  262. // teacherSchool.areaId = replaceSchool.school.areaId;
  263. // }
  264. // await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(item, item.id, new PartitionKey("Base"));
  265. // }
  266. // schoolInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(replaceSchool.school, replaceSchool.school.id, new PartitionKey("Base"));
  267. // //保存操作记录
  268. // await _azureStorage.SaveBILog("school-update", $"{replaceSchool.tmdName}【{replaceSchool.tmdId}】修改学校信息,学校和ID:{replaceSchool.school.name}【{replaceSchool.school.id}】", _dingDing, httpContext: HttpContext);
  269. // return Ok(new { state = 200, schoolInfo });
  270. //}
  271. //else return Ok(new { state = 400, message = "请求错误!" });
  272. }
  273. catch (Exception ex)
  274. {
  275. await _dingDing.SendBotMsg($"BI,{_option.Location} /batchschool/upd-school \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  276. return BadRequest();
  277. }
  278. }
  279. /// <summary>
  280. /// 顾问学校空间使用情况
  281. /// </summary>
  282. /// <param name="jsonElement"></param>
  283. /// <returns></returns>
  284. [HttpPost("get-assistspace")]
  285. public async Task<IActionResult> GetAssistSchoolSpace(JsonElement jsonElement)
  286. {
  287. if (!jsonElement.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
  288. var cosmosClient = _azureCosmos.GetCosmosClient();
  289. List<string> schools = await CommonFind.FindSchoolIds(cosmosClient, $"{tmdId}");
  290. List<SchoolSpace> schoolSpaces = new();
  291. foreach (var sid in schools)
  292. {
  293. School school = new();
  294. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(sid, new PartitionKey("Base"));
  295. if (response.Status == 200)
  296. {
  297. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  298. school = json.ToObject<School>();
  299. }
  300. long teach = 0;
  301. 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}") }))
  302. {
  303. var json = await JsonDocument.ParseAsync(item.ContentStream);
  304. foreach (var elmt in json.RootElement.GetProperty("Documents").EnumerateArray())
  305. {
  306. if (elmt.TryGetProperty("size", out JsonElement _size) && _size.ValueKind.Equals(JsonValueKind.Number))
  307. {
  308. teach = _size.GetInt32();
  309. break;
  310. }
  311. }
  312. }
  313. SchoolSpace schoolSpace = new() { id = sid, name = school != null ? school.name : sid };
  314. Space space = new Space();
  315. long blobsize = 0; //使用大小
  316. RedisValue value = default;
  317. value = _azureRedis.GetRedisClient(8).HashGet($"Blob:Record", sid);
  318. if (value != default && !value.IsNullOrEmpty)
  319. {
  320. JsonElement record = value.ToString().ToObject<JsonElement>();
  321. if (record.TryGetInt64(out blobsize))
  322. {
  323. }
  324. }
  325. else
  326. {
  327. var client = _azureStorage.GetBlobContainerClient(sid);
  328. var size = await client.GetBlobsCatalogSize();
  329. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", sid, size.Item1);
  330. foreach (var key in size.Item2.Keys)
  331. {
  332. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{sid}", key);
  333. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{sid}", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
  334. }
  335. space.useSize = (long)size.Item1; space.tSize = teach; space.catalogSize = size.Item2;
  336. schoolSpace.space = space;
  337. schoolSpaces.Add(schoolSpace);
  338. continue;
  339. }
  340. Dictionary<string, double?> catalog = new Dictionary<string, double?>();
  341. SortedSetEntry[] Scores = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Blob:Catalog:{sid}");
  342. if (Scores != null)
  343. {
  344. foreach (var score in Scores)
  345. {
  346. double val = score.Score;
  347. string key = score.Element.ToString();
  348. catalog.Add(key, val);
  349. }
  350. space.useSize = blobsize; space.tSize = teach; space.catalogSize = catalog;
  351. schoolSpace.space = space;
  352. schoolSpaces.Add(schoolSpace);
  353. continue;
  354. }
  355. else
  356. {
  357. var client = _azureStorage.GetBlobContainerClient(sid);
  358. var size = await client.GetBlobsCatalogSize();
  359. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", sid, size.Item1);
  360. foreach (var key in size.Item2.Keys)
  361. {
  362. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{sid}", key);
  363. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{sid}", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
  364. }
  365. space.useSize = (long)size.Item1;
  366. space.tSize = teach;
  367. space.catalogSize = size.Item2;
  368. schoolSpace.space = space;
  369. schoolSpaces.Add(schoolSpace);
  370. continue;
  371. }
  372. }
  373. return Ok(new { state = 200, schoolSpaces });
  374. }
  375. /// <summary>
  376. /// 移交学校顾问
  377. /// </summary>
  378. /// <param name="jsonElement"></param>
  379. /// <returns></returns>
  380. [HttpPost("get-shift")]
  381. public async Task<IActionResult> GetShift(JsonElement jsonElement)
  382. {
  383. var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
  384. if (!jsonElement.TryGetProperty("school", out JsonElement _school)) return BadRequest();
  385. //if (!jsonElement.TryGetProperty("teacher", out JsonElement _teacher)) return BadRequest();
  386. if (!jsonElement.TryGetProperty("shiftTeacher", out JsonElement _shiftTeacher)) return BadRequest();
  387. var cosmosClient = _azureCosmos.GetCosmosClient();
  388. SchoolTeacher schoolTeacher = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<SchoolTeacher>($"{_tmdId}", new PartitionKey($"Teacher-{_school}"));
  389. if (schoolTeacher.roles.IsNotEmpty() && schoolTeacher.roles.Contains("assist"))
  390. {
  391. schoolTeacher.roles.Remove("assist");
  392. SchoolTeacher newSchoolTeacher = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<SchoolTeacher>($"{_shiftTeacher}", new PartitionKey($"Teacher-{_school}"));
  393. if (!newSchoolTeacher.roles.Contains("assist"))
  394. {
  395. newSchoolTeacher.roles.Add("assist");
  396. newSchoolTeacher = await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(newSchoolTeacher, $"{_shiftTeacher}", new PartitionKey($"Teacher-{_school}"));
  397. }
  398. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, $"{_tmdId}", new PartitionKey($"Teacher-{_school}"));
  399. School schoolBase = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>($"{_school}", new PartitionKey($"Base"));
  400. //发送消息实体
  401. string shiftCode = "shift-assist";
  402. Notification notification = new Notification
  403. {
  404. hubName = "hita",
  405. type = "msg",
  406. from = $"BI:{_option.Location}:{_school}",
  407. to = new List<string> { $"{_shiftTeacher}" },
  408. label = $"{shiftCode}_school",
  409. body = new { location = _option.Location, biz = shiftCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
  410. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  411. };
  412. if (notification != null)
  413. {
  414. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  415. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  416. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  417. var location = _option.Location;
  418. await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);//站内发送消息
  419. }
  420. //保存操作记录
  421. await _azureStorage.SaveBILog("schoolTeacher-add", $"{_tmdName}【{_tmdId}】移交顾问给{newSchoolTeacher.name}【{newSchoolTeacher.id}】", _dingDing, httpContext: HttpContext);
  422. return Ok(new { state = 200 });
  423. }
  424. else { return Ok(new { status = 201, msg = $"{_tmdName}【{_tmdId}】账号不是顾问" }); }
  425. }
  426. /// <summary>
  427. /// 修改顾问学校
  428. /// </summary>
  429. /// <param name="jsonElement"></param>
  430. /// <returns></returns>
  431. [ProducesDefaultResponseType]
  432. [AuthToken(Roles = "admin")]
  433. [HttpPost("set-aistschool")]
  434. public async Task<IActionResult> SetAssistSchool(JsonElement jsonElement)
  435. {
  436. try
  437. {
  438. if (!jsonElement.TryGetProperty("partitionKey", out JsonElement parKey)) return BadRequest();
  439. jsonElement.TryGetProperty("userId", out JsonElement userId);
  440. if (!jsonElement.TryGetProperty("tmdId", out JsonElement tmdId)) return BadRequest();
  441. if (!jsonElement.TryGetProperty("schoolIds", out JsonElement jsSchoolIds)) return BadRequest();
  442. if (!jsonElement.TryGetProperty("busy", out JsonElement busy)) return BadRequest();
  443. List<string> schoolIds = jsSchoolIds.ToObject<List<string>>();
  444. var table = _azureStorage.GetCloudTableClient().GetTableReference("BIDDUserInfo");
  445. var cosmosClient = _azureCosmos.GetCosmosClient();
  446. string divide = _option.Location;
  447. Dictionary<string, object> dic = new() { { "PartitionKey", $"{parKey}" },{ "tmdId", $"{tmdId}" } };
  448. if (!string.IsNullOrEmpty($"{userId}"))
  449. {
  450. dic.Add("userId", $"{userId}");
  451. }
  452. Dictionary<string, List<string>> noSchools = new();
  453. List<DingDingUserInfo> ddUserInfoList = await table.FindListByDict<DingDingUserInfo>(dic);
  454. List<DingDingUserInfo> updUsers = new();
  455. if (ddUserInfoList.Count > 0)
  456. {
  457. foreach (var ddInfo in ddUserInfoList)
  458. {
  459. if (schoolIds.Count > 0)
  460. {
  461. List<string> noSchool = await SchoolWay.SchoolAdviser(cosmosClient, ddInfo, schoolIds, $"{busy}");
  462. if (noSchool.Count > 0)
  463. {
  464. noSchools.Add(ddInfo.tmdId, noSchool);
  465. }
  466. }
  467. List<string> userSchoolAdv = new(ddInfo.schoolIds.Split("|", StringSplitOptions.RemoveEmptyEntries));
  468. if ($"{busy}".Equals("add"))
  469. {
  470. userSchoolAdv.AddRange(schoolIds);
  471. ddInfo.schoolIds = userSchoolAdv.Count > 0 ? string.Join("|", userSchoolAdv) : "";
  472. }
  473. if ($"{busy}".Equals("del"))
  474. {
  475. var temp = userSchoolAdv.Where(p => !schoolIds.Any(x => x == p)).ToList();
  476. ddInfo.schoolIds = temp.Count > 0 ? string.Join("|", temp) : "";
  477. }
  478. updUsers.Add(ddInfo);
  479. }
  480. }
  481. updUsers = await table.SaveOrUpdateAll(updUsers);
  482. if (noSchools.Count > 0)
  483. return Ok(new { state = 201, recUsers = updUsers, noSchools });
  484. else
  485. return Ok(new { state = 200, recUsers = updUsers });
  486. }
  487. catch (Exception ex)
  488. {
  489. await _dingDing.SendBotMsg($"BI,{_option.Location} /batchschool/set-aistschool \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  490. return BadRequest();
  491. }
  492. }
  493. /// <summary>
  494. /// 依据学校ID查学校管理员信息
  495. /// </summary>
  496. /// <param name="jsonElement"></param>
  497. /// <returns></returns>
  498. [HttpPost("get-schoolmanage")]
  499. public async Task<IActionResult> GetSchoolManage(JsonElement jsonElement)
  500. {
  501. if (!jsonElement.TryGetProperty("schoolCode", out JsonElement schoolCode)) return BadRequest();
  502. if (!jsonElement.TryGetProperty("isAdmin", out JsonElement isAdmin)) return BadRequest();
  503. var cosmosClient = _azureCosmos.GetCosmosClient();
  504. List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
  505. //string sqlTxt = "select value(c) from c where array_contains(c.roles,'admin')";
  506. string sqlTxt = "select value(c) from c";
  507. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{schoolCode}") }))
  508. {
  509. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  510. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt16() > 0)
  511. {
  512. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  513. {
  514. SchoolTeacher schoolTeacher = obj.ToObject<SchoolTeacher>();
  515. //schoolTeachers.Add(schoolTeacher);
  516. if (bool.Parse($"{isAdmin}") == true)
  517. {
  518. if (schoolTeacher.roles.Contains("admin"))
  519. {
  520. schoolTeachers.Add(schoolTeacher);
  521. }
  522. }
  523. else
  524. {
  525. if (!schoolTeacher.roles.Contains("admin"))
  526. {
  527. schoolTeachers.Add(schoolTeacher);
  528. }
  529. }
  530. }
  531. }
  532. }
  533. return Ok(new { state = 200, schoolTeachers });
  534. }
  535. /// <summary>
  536. /// 设置学校管理员
  537. /// </summary>
  538. /// <param name="jsonElement"></param>
  539. /// <returns></returns>
  540. [HttpPost("set-schoolme")]
  541. public async Task<IActionResult> SetSchoolManage(JsonElement jsonElement)
  542. {
  543. try
  544. {
  545. var (_tmdId, _tmdName, _, _, _, _) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
  546. if (!jsonElement.TryGetProperty("manageId", out JsonElement _adminTmdId)) return BadRequest();
  547. if (!jsonElement.TryGetProperty("manageName", out JsonElement _adminTmdName)) return BadRequest();
  548. if (!jsonElement.TryGetProperty("schoolId", out JsonElement _schoolId)) return BadRequest();
  549. var cosmosClient = _azureCosmos.GetCosmosClient();
  550. var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{_adminTmdId}", new PartitionKey($"Teacher-{_schoolId}"));
  551. if (response.Status == 200)
  552. {
  553. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  554. SchoolTeacher schoolTeacher = json.ToObject<SchoolTeacher>();
  555. if (!schoolTeacher.roles.Contains("admin"))
  556. {
  557. schoolTeacher.roles.Add("admin");
  558. SchoolTeacher st = await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(schoolTeacher, schoolTeacher.id, new PartitionKey(schoolTeacher.code));
  559. //保存操作记录
  560. await _azureStorage.SaveBILog("schoolTeacher-update", $"{_tmdName}【{_tmdId}】账户把{_adminTmdName}【{_adminTmdId}】设置学校id为{_schoolId}管理员。", _dingDing, httpContext: HttpContext);
  561. return Ok(new { state = 200, schoolTeacher = st });
  562. }
  563. else
  564. return Ok(new { state = 201, schoolTeacher = "已经是管理人员" });
  565. }
  566. else
  567. {
  568. SchoolTeacher schoolTeacher = new SchoolTeacher
  569. {
  570. id = $"{_adminTmdId}",
  571. code = $"Teacher-{_schoolId}",
  572. roles = new List<string> { "admin" },
  573. job = "管理员",
  574. name = $"{_adminTmdName}",
  575. picture = "",
  576. status = "join",
  577. createTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
  578. pk = "Teacher",
  579. ttl = -1
  580. };
  581. schoolTeacher = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<SchoolTeacher>(schoolTeacher, new PartitionKey(schoolTeacher.code));
  582. //保存操作记录
  583. await _azureStorage.SaveBILog("schoolTeacher-add", $"{_tmdName}【{_tmdId}】账户创建{_adminTmdName}【{_adminTmdId}】账户,并设学校管理员。学校ID:{_schoolId}。", _dingDing, httpContext: HttpContext);
  584. return Ok(new { status = 200, schoolTeacher });
  585. }
  586. }
  587. catch (Exception ex)
  588. {
  589. await _dingDing.SendBotMsg($"BI,{_option.Location} /batchschool/set-schoolme \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
  590. return BadRequest();
  591. }
  592. }
  593. /// <summary>
  594. /// 通过学校Id查询详情 数据管理工具——查询工具
  595. /// </summary>
  596. /// <returns></returns>
  597. [HttpPost("get-info")]
  598. public async Task<IActionResult> GetSchool(JsonElement jsonElement)
  599. {
  600. jsonElement.TryGetProperty("schoolId", out JsonElement schoolId);
  601. var clientCosmosDB = _azureCosmos.GetCosmosClient();
  602. StringBuilder sqlTxt = new StringBuilder("select * from c");
  603. if (!string.IsNullOrEmpty($"{schoolId}"))
  604. {
  605. sqlTxt.Append($" where c.id='{schoolId}'");
  606. }
  607. List<School> schools = new();
  608. await foreach (var item in clientCosmosDB.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
  609. {
  610. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  611. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  612. {
  613. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  614. {
  615. schools.Add(obj.ToObject<School>());
  616. }
  617. }
  618. }
  619. return Ok(new { state = 200, schools });
  620. }
  621. /// <summary>
  622. /// 依据区域Id查询区域空间统计
  623. /// </summary>
  624. /// <param name="jsonElement"></param>
  625. /// <returns></returns>
  626. [ProducesDefaultResponseType]
  627. [HttpPost("get-spance")]
  628. public async Task<IActionResult> GetAreaSpace(JsonElement jsonElement)
  629. {
  630. jsonElement.TryGetProperty("areaId", out JsonElement areaId);
  631. jsonElement.TryGetProperty("schoolId", out JsonElement schoolId);
  632. var cosmosClient = _azureCosmos.GetCosmosClient();
  633. long allSize = 0; //全部大小
  634. int teacherSpace = 0; //学校分配给教师的空间
  635. long useSize = 0; //已使用大小
  636. Dictionary<string, double?> useSpaceInfo = new(); //学校使用详情
  637. //查询区域所有学校
  638. if (!string.IsNullOrEmpty($"{areaId}"))
  639. {
  640. List<string> schools = new();
  641. schools = await CommonFind.FindSchoolIds(cosmosClient, $"select c.id from c where c.areaId='{areaId}'", "Base");
  642. allSize = await CommonFind.FindTotals(cosmosClient, $"select sum(c.size) as totals from c where c.areaId='{areaId}'", new List<string> { "School" }); //区域所有学校空间
  643. foreach (var school in schools)
  644. {
  645. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: $"SELECT sum(c.size) as size FROM c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Teacher-{school}") }))
  646. {
  647. var json = await JsonDocument.ParseAsync(item.ContentStream);
  648. foreach (var elmt in json.RootElement.GetProperty("Documents").EnumerateArray())
  649. {
  650. if (elmt.TryGetProperty("size", out JsonElement _size) && _size.ValueKind.Equals(JsonValueKind.Number))
  651. {
  652. teacherSpace += _size.GetInt32();
  653. break;
  654. }
  655. }
  656. }
  657. long blobsize = 0;
  658. RedisValue value = _azureRedis.GetRedisClient(8).HashGet($"Blob:Record", $"{school}");
  659. if (!value.IsNullOrEmpty)
  660. {
  661. JsonElement record = value.ToString().ToObject<JsonElement>();
  662. if (record.TryGetInt64(out blobsize))
  663. {
  664. }
  665. }
  666. else
  667. {
  668. var storageClient = _azureStorage.GetBlobContainerClient("school");
  669. var size = await storageClient.GetBlobsCatalogSize();
  670. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", $"{school}", size.Item1);
  671. foreach (var key in size.Item2.Keys)
  672. {
  673. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Bolb:Catalog:{school}", key);
  674. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Bolb:Catalog:school", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
  675. }
  676. useSize += size.Item1.Value;
  677. useSpaceInfo = useSpaceInfo.Concat(size.Item2).GroupBy(g => g.Key).ToDictionary(k => k.Key, k => k.Sum(kvp => kvp.Value)); //lamebda表达式
  678. //useSpaceInfo = (from e in useSpaceInfo.Concat(size.Item2) group e by e.Key into g select new { Name = g.Key, value = g.Sum(kvp => kvp.Value) }).ToDictionary(item => item.Name, item => item.value); //linq 方式合并
  679. }
  680. SortedSetEntry[] Scores = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Blob:Catalog:{school}");
  681. if (Scores != null)
  682. {
  683. Dictionary<string, double?> catalog = new();
  684. foreach (var score in Scores)
  685. {
  686. double val = score.Score;
  687. string key = score.Element.ToString();
  688. catalog.Add(key, val);
  689. }
  690. useSpaceInfo = useSpaceInfo.Concat(catalog).GroupBy(g => g.Key).ToDictionary(k => k.Key, k => k.Sum(kvp => kvp.Value)); //lamebda表达式
  691. //useSpaceInfo = (from e in useSpaceInfo.Concat(catalog) group e by e.Key into g select new { Name = g.Key, value = g.Sum(kvp => kvp.Value) }).ToDictionary(item => item.Name, item => item.value); //linq 方式合并
  692. }
  693. else
  694. {
  695. var client = _azureStorage.GetBlobContainerClient("school");
  696. var size = await client.GetBlobsCatalogSize();
  697. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", $"{school}", size.Item1);
  698. foreach (var key in size.Item2.Keys)
  699. {
  700. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{school}", key);
  701. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{school}", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
  702. }
  703. useSize += size.Item1.Value;
  704. useSpaceInfo = useSpaceInfo.Concat(size.Item2).GroupBy(g => g.Key).ToDictionary(k => k.Key, k => k.Sum(kvp => kvp.Value)); //lamebda表达式
  705. //useSpaceInfo = (from e in useSpaceInfo.Concat(size.Item2) group e by e.Key into g select new { Name = g.Key, value = g.Sum(kvp => kvp.Value) }).ToDictionary(item => item.Name, item => item.value); //linq 方式合并
  706. }
  707. }
  708. }
  709. //查询学校
  710. if (!string.IsNullOrEmpty($"{schoolId}"))
  711. {
  712. allSize = await CommonFind.FindTotals(cosmosClient, $"SELECT c.size as totals FROM c where c.id='{schoolId}'", "School", "Base");
  713. teacherSpace = await CommonFind.FindTotals(cosmosClient, $"SELECT sum(c.size) as totals FROM c", "School", $"Teacher-{schoolId}");
  714. long blobsize = 0;
  715. RedisValue value = _azureRedis.GetRedisClient(8).HashGet($"Blob:Record", $"{schoolId}");
  716. if (!value.IsNullOrEmpty)
  717. {
  718. JsonElement record = value.ToString().ToObject<JsonElement>();
  719. if (record.TryGetInt64(out blobsize))
  720. {
  721. useSize = blobsize;
  722. }
  723. }
  724. else
  725. {
  726. var storageClient = _azureStorage.GetBlobContainerClient("school");
  727. var size = await storageClient.GetBlobsCatalogSize();
  728. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", $"{schoolId}", size.Item1);
  729. foreach (var key in size.Item2.Keys)
  730. {
  731. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Bolb:Catalog:{schoolId}", key);
  732. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Bolb:Catalog:school", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
  733. }
  734. useSpaceInfo = size.Item2;
  735. }
  736. Dictionary<string, double?> catalog = new();
  737. SortedSetEntry[] Scores = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Blob:Catalog:{schoolId}");
  738. if (Scores != null)
  739. {
  740. foreach (var score in Scores)
  741. {
  742. double val = score.Score;
  743. string key = score.Element.ToString();
  744. catalog.Add(key, val);
  745. }
  746. useSpaceInfo = catalog;
  747. }
  748. else
  749. {
  750. var client = _azureStorage.GetBlobContainerClient("school");
  751. var size = await client.GetBlobsCatalogSize();
  752. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", $"{schoolId}", size.Item1);
  753. foreach (var key in size.Item2.Keys)
  754. {
  755. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{schoolId}", key);
  756. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{schoolId}", key, size.Item2[key].HasValue ? size.Item2[key].Value : 0);
  757. }
  758. useSize = size.Item1.Value;
  759. useSpaceInfo = size.Item2;
  760. }
  761. }
  762. return Ok(new { state = 200, allSize, useSize, teacherSpace, useSpaceInfo });
  763. }
  764. /// <summary>
  765. /// 未加入区域的学校
  766. /// </summary>
  767. public record NotAreaSchool
  768. {
  769. public string id { get; set; }
  770. public string name { get; set; }
  771. public string schoolCode { get; set; }
  772. public string picture { get; set; }
  773. public List<string> period { get; set; }
  774. public string province { get; set; }
  775. public string city { get; set; }
  776. public string dist { get; set; }
  777. }
  778. /// <summary>
  779. /// 学校空间使用情况
  780. /// </summary>
  781. public record SchoolSpace
  782. {
  783. public string id { get; set; }
  784. public string name { get; set; }
  785. public Space space { get; set; }
  786. }
  787. /// <summary>
  788. /// 空间
  789. /// </summary>
  790. public record Space
  791. {
  792. /// <summary>
  793. /// 已使用空间
  794. /// </summary>
  795. public long useSize { get; set; }
  796. /// <summary>
  797. /// 分配教师空间
  798. /// </summary>
  799. public long tSize { get; set; }
  800. /// <summary>
  801. /// 空间类型
  802. /// </summary>
  803. public Dictionary<string, double?> catalogSize { get; set; }
  804. }
  805. }
  806. }