MonitorServicesBus.cs 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Text.Json;
  5. using System.Threading.Tasks;
  6. using Azure.Cosmos;
  7. using Azure.Messaging.ServiceBus;
  8. using Microsoft.Azure.WebJobs;
  9. using Microsoft.Azure.WebJobs.Host;
  10. using Microsoft.Extensions.Logging;
  11. using StackExchange.Redis;
  12. using TEAMModelOS.SDK.DI;
  13. using TEAMModelOS.SDK.Extension;
  14. using TEAMModelOS.SDK;
  15. using TEAMModelOS.SDK.Models;
  16. using TEAMModelOS.SDK.Models.Cosmos;
  17. using TEAMModelOS.SDK.Models.Cosmos.Common;
  18. using TEAMModelOS.Services.Common;
  19. using System.Linq;
  20. using TEAMModelOS.SDK.Models.Service;
  21. using TEAMModelOS.SDK.Models.Cosmos.BI;
  22. using TEAMModelOS.Models;
  23. using Microsoft.Extensions.Options;
  24. using Microsoft.Extensions.Configuration;
  25. using HTEXLib.COMM.Helpers;
  26. namespace TEAMModelFunction
  27. {
  28. public class MonitorServicesBus
  29. {
  30. private readonly AzureCosmosFactory _azureCosmos;
  31. private readonly DingDing _dingDing;
  32. private readonly AzureStorageFactory _azureStorage;
  33. private readonly AzureRedisFactory _azureRedis;
  34. private readonly AzureServiceBusFactory _serviceBus;
  35. private readonly Option _option;
  36. private readonly NotificationService _notificationService;
  37. private readonly IConfiguration _configuration;
  38. public MonitorServicesBus(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IOptionsSnapshot<Option> option, NotificationService notificationService, IConfiguration configuration)
  39. {
  40. _azureCosmos = azureCosmos;
  41. _dingDing = dingDing;
  42. _azureStorage = azureStorage;
  43. _azureRedis = azureRedis;
  44. _serviceBus = serviceBus;
  45. _option = option?.Value;
  46. _notificationService = notificationService;
  47. _configuration = configuration;
  48. }
  49. [FunctionName("Exam")]
  50. public async Task ExamFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "exam", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  51. {
  52. try
  53. {
  54. var json = JsonDocument.Parse(msg);
  55. json.RootElement.TryGetProperty("id", out JsonElement id);
  56. json.RootElement.TryGetProperty("progress", out JsonElement progress);
  57. json.RootElement.TryGetProperty("code", out JsonElement code);
  58. //Dictionary<string, object> keyValuePairs = mySbMsg.ToObject<Dictionary<string, object>>();
  59. var client = _azureCosmos.GetCosmosClient();
  60. ExamInfo exam = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"{code}"));
  61. exam.progress = progress.ToString();
  62. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(exam, id.ToString(), new PartitionKey($"{code}"));
  63. }
  64. catch (CosmosException e)
  65. {
  66. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,ExamBus()-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組);
  67. }
  68. catch (Exception ex)
  69. {
  70. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,ExamBus()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  71. }
  72. }
  73. [FunctionName("Vote")]
  74. public async Task VoteFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "vote", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  75. {
  76. try
  77. {
  78. var jsonMsg = JsonDocument.Parse(msg);
  79. jsonMsg.RootElement.TryGetProperty("id", out JsonElement id);
  80. jsonMsg.RootElement.TryGetProperty("progress", out JsonElement progress);
  81. jsonMsg.RootElement.TryGetProperty("code", out JsonElement code);
  82. var client = _azureCosmos.GetCosmosClient();
  83. Vote vote = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Vote>(id.ToString(), new PartitionKey($"{code}"));
  84. vote.progress = progress.ToString();
  85. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(vote, id.ToString(), new PartitionKey($"{code}"));
  86. }
  87. catch (CosmosException e)
  88. {
  89. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,VoteBus()-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組);
  90. }
  91. catch (Exception ex)
  92. {
  93. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,VoteBus()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  94. }
  95. }
  96. [FunctionName("Correct")]
  97. public async Task CorrectFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "correct", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  98. {
  99. try
  100. {
  101. var jsonMsg = JsonDocument.Parse(msg);
  102. jsonMsg.RootElement.TryGetProperty("id", out JsonElement id);
  103. jsonMsg.RootElement.TryGetProperty("progress", out JsonElement progress);
  104. jsonMsg.RootElement.TryGetProperty("code", out JsonElement code);
  105. var client = _azureCosmos.GetCosmosClient();
  106. Correct correct = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Correct>(id.ToString(), new PartitionKey($"{code}"));
  107. correct.progress = progress.ToString();
  108. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(correct, id.ToString(), new PartitionKey($"{code}"));
  109. }
  110. catch (CosmosException e)
  111. {
  112. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Correct()-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組);
  113. }
  114. catch (Exception ex)
  115. {
  116. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Correct()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  117. }
  118. }
  119. [FunctionName("Survey")]
  120. public async Task SurveyFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "survey", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  121. {
  122. try
  123. {
  124. var jsonMsg = JsonDocument.Parse(msg);
  125. jsonMsg.RootElement.TryGetProperty("id", out JsonElement id);
  126. jsonMsg.RootElement.TryGetProperty("progress", out JsonElement progress);
  127. jsonMsg.RootElement.TryGetProperty("code", out JsonElement code);
  128. //Dictionary<string, object> keyValuePairs = mySbMsg.ToObject<Dictionary<string, object>>();
  129. var client = _azureCosmos.GetCosmosClient();
  130. Survey survey = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Survey>(id.ToString(), new PartitionKey($"{code}"));
  131. survey.progress = progress.ToString();
  132. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(survey, id.ToString(), new PartitionKey($"{code}"));
  133. }
  134. catch (CosmosException e)
  135. {
  136. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,SurveyBus()-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組);
  137. }
  138. catch (Exception ex)
  139. {
  140. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,SurveyBus()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  141. }
  142. }
  143. [FunctionName("Homework")]
  144. public async Task HomeworkFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "homework", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  145. {
  146. try
  147. {
  148. var jsonMsg = JsonDocument.Parse(msg);
  149. jsonMsg.RootElement.TryGetProperty("id", out JsonElement id);
  150. jsonMsg.RootElement.TryGetProperty("progress", out JsonElement progress);
  151. jsonMsg.RootElement.TryGetProperty("code", out JsonElement code);
  152. var client = _azureCosmos.GetCosmosClient();
  153. Homework homework = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Homework>(id.ToString(), new PartitionKey($"{code}"));
  154. homework.progress = progress.ToString();
  155. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(homework, id.ToString(), new PartitionKey($"{code}"));
  156. }
  157. catch (CosmosException e)
  158. {
  159. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Homework()-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組);
  160. }
  161. catch (Exception ex)
  162. {
  163. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Homework()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  164. }
  165. }
  166. [FunctionName("Study")]
  167. public async Task StudyFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "study", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  168. {
  169. try
  170. {
  171. var jsonMsg = JsonDocument.Parse(msg);
  172. jsonMsg.RootElement.TryGetProperty("id", out JsonElement id);
  173. jsonMsg.RootElement.TryGetProperty("progress", out JsonElement progress);
  174. jsonMsg.RootElement.TryGetProperty("code", out JsonElement code);
  175. var client = _azureCosmos.GetCosmosClient();
  176. Study study = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Study>(id.ToString(), new PartitionKey($"{code}"));
  177. study.progress = progress.ToString();
  178. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(study, id.ToString(), new PartitionKey($"{code}"));
  179. }
  180. catch (CosmosException e)
  181. {
  182. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Study()-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組);
  183. }
  184. catch (Exception ex)
  185. {
  186. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Study()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  187. }
  188. }
  189. [FunctionName("ExamLite")]
  190. public async Task ExamLiteFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "examlite", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  191. {
  192. try
  193. {
  194. var jsonMsg = JsonDocument.Parse(msg);
  195. jsonMsg.RootElement.TryGetProperty("id", out JsonElement id);
  196. jsonMsg.RootElement.TryGetProperty("progress", out JsonElement progress);
  197. jsonMsg.RootElement.TryGetProperty("code", out JsonElement code);
  198. var client = _azureCosmos.GetCosmosClient();
  199. ExamLite lite = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamLite>(id.ToString(), new PartitionKey($"{code}"));
  200. lite.progress = progress.ToString();
  201. await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(lite, id.ToString(), new PartitionKey($"{code}"));
  202. }
  203. catch (CosmosException e)
  204. {
  205. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,ExamLite()-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組);
  206. }
  207. catch (Exception ex)
  208. {
  209. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,ExamLite()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  210. }
  211. }
  212. /// <summary>
  213. /// 根据容器的根目录刷新redis并获取redis的最新使用情况
  214. /// </summary>
  215. /// <param name="msg"></param>
  216. /// <returns></returns>
  217. [FunctionName("BlobRoot")]
  218. public async Task BlobRootFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "blobroot", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  219. {
  220. try
  221. {
  222. var jsonMsg = JsonDocument.Parse(msg);
  223. if (jsonMsg.RootElement.TryGetProperty("name", out JsonElement _name) && _name.ValueKind == JsonValueKind.String
  224. && jsonMsg.RootElement.TryGetProperty("root", out JsonElement root) && root.ValueKind == JsonValueKind.String)
  225. {
  226. //await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Blob() 容器:触发变更,{jsonMsg.ToJsonString()}",
  227. // GroupNames.成都开发測試群組);
  228. List<Dictionary<string, double?>> list = new List<Dictionary<string, double?>>();
  229. string[] uls = System.Web.HttpUtility.UrlDecode($"{root}", Encoding.UTF8).Split("/");
  230. string u = !string.IsNullOrEmpty(uls[0]) ? uls[0] : uls[1];
  231. string name = $"{_name}";
  232. string lockKey = $"Blob:Lock:{name}:{u}";
  233. bool exist = await _azureRedis.GetRedisClient(8).KeyExistsAsync(lockKey);
  234. if (!exist)
  235. { ///key不存在则正常进行计算
  236. bool condition = false;
  237. TimeSpan timeSpan = new TimeSpan(DateTimeOffset.UtcNow.AddMinutes(5).Ticks);
  238. timeSpan = timeSpan - new TimeSpan(DateTimeOffset.UtcNow.Ticks);
  239. //准备处理Blob刷新时间
  240. long action = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  241. await _azureRedis.GetRedisClient(8).StringSetAsync(lockKey, action, expiry: timeSpan);
  242. await RefreshBlob(name, u);
  243. //将action 与Redis最新的时间进行比较,如果
  244. var rds = await CheckLockKey(lockKey, action);
  245. condition = rds.condition;
  246. exist = rds.exist;
  247. if (condition || !exist)
  248. {
  249. await RefreshBlob(name, u);
  250. }
  251. //使用 CancellationToken
  252. //while (condition || !exist)
  253. //{
  254. //}
  255. }
  256. else
  257. {
  258. ///key存在则,则刷新key对应的值
  259. TimeSpan timeSpan = new TimeSpan(DateTimeOffset.UtcNow.AddMinutes(5).Ticks);
  260. timeSpan = timeSpan - new TimeSpan(DateTimeOffset.UtcNow.Ticks);
  261. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  262. await _azureRedis.GetRedisClient(8).StringSetAsync(lockKey, now, expiry: timeSpan);
  263. }
  264. //await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Blob() 容器:{name}使用:{u},文件分类:{list.ToJsonString()}",
  265. // GroupNames.成都开发測試群組);
  266. }
  267. }
  268. catch (Exception ex)
  269. {
  270. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Blob()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  271. }
  272. }
  273. private async Task<(bool condition, bool exist)> CheckLockKey(string lockKey, long nowTime)
  274. {
  275. //Redis的最新时间
  276. long newestTime = 0;
  277. RedisValue value = await _azureRedis.GetRedisClient(8).StringGetAsync(lockKey);
  278. if (value != default && !value.IsNullOrEmpty)
  279. {
  280. JsonElement record = value.ToString().ToObject<JsonElement>();
  281. if (record.TryGetInt64(out newestTime))
  282. {
  283. }
  284. }
  285. //说明key已经不存在
  286. if (newestTime == 0)
  287. {
  288. return (false, true);
  289. }
  290. //说明key存在
  291. else
  292. {
  293. //说明Redis记录了最新的时间戳
  294. if (nowTime != newestTime)
  295. {
  296. return (true, false);
  297. }
  298. //时间相同,没有被再次记录最新的时间戳
  299. else
  300. {
  301. await _azureRedis.GetRedisClient(8).KeyDeleteAsync(lockKey);
  302. return (false, true);
  303. }
  304. }
  305. }
  306. private async Task RefreshBlob(string name, string u)
  307. {
  308. long statr = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  309. var client = _azureStorage.GetBlobContainerClient(name);
  310. var size = await client.GetBlobsSize(u);
  311. await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{name}", u);
  312. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Blob:Catalog:{name}", u, size.HasValue ? size.Value : 0);
  313. var scores = await _azureRedis.GetRedisClient(8).SortedSetRangeByRankWithScoresAsync($"Blob:Catalog:{name}");
  314. double blobsize = 0;
  315. if (scores != default && scores != null)
  316. {
  317. foreach (var score in scores)
  318. {
  319. blobsize = blobsize + score.Score;
  320. }
  321. }
  322. await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", new RedisValue(name), new RedisValue($"{blobsize}"));
  323. long end = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  324. long dis = (end - statr) / 1000;
  325. long timeout = 10;
  326. if (dis > timeout)
  327. {
  328. await _dingDing.SendBotMsg($"ServiceBus,RefreshBlob:空间计算已经超过{timeout}秒\n容器名:{name}\n文件夹:{u}\n计算时长:{dis}", GroupNames.醍摩豆服務運維群組);
  329. }
  330. }
  331. /// <summary>
  332. /// 完善课程变更,StuListChange, originCode是学校编码 则表示名单是学校自定义名单,如果是tmdid则表示醍摩豆的私有名单,scope=school,private。
  333. /// </summary>
  334. /// <data msg>
  335. /// CourseChange
  336. ///// </data>
  337. /// <param name="msg"></param>
  338. /// <returns></returns>
  339. [FunctionName("TeacherTrainChange")]
  340. public async Task TeacherTrainChangeFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "teacher-train-change", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  341. {
  342. try
  343. {
  344. // await _dingDing.SendBotMsg($"teacher-train-change\n{msg}",GroupNames.成都开发測試群組);
  345. TeacherTrainChange change = msg.ToObject<TeacherTrainChange>();
  346. if (change.update == null || change.update.Count <= 0 || change.tmdids.IsEmpty())
  347. {
  348. return;
  349. }
  350. var client = _azureCosmos.GetCosmosClient();
  351. string insql = $"where c.id in ({string.Join(",", change.tmdids.Select(x => $"'{x}'"))})";
  352. string selsql = $"select value(c) from c {insql} ";
  353. List<TeacherTrain> teacherTrains = new List<TeacherTrain>();
  354. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<TeacherTrain>(queryText: selsql,
  355. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{change.school}") }))
  356. {
  357. teacherTrains.Add(item);
  358. }
  359. if (change.statistics != 1)
  360. {
  361. List<Task<ItemResponse<TeacherTrain>>> task = new List<Task<ItemResponse<TeacherTrain>>>();
  362. teacherTrains.ForEach(x =>
  363. {
  364. x.update.UnionWith(change.update);
  365. task.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<TeacherTrain>(x, x.id, new PartitionKey($"TeacherTrain-{change.school}")));
  366. });
  367. await task.TaskPage(5);
  368. var unchange = change.tmdids.Except(teacherTrains.Select(x => x.id));
  369. if (unchange != null)
  370. {
  371. task.Clear();
  372. unchange.ToList().ForEach(x =>
  373. {
  374. TeacherTrain teacherTrain = new TeacherTrain
  375. {
  376. pk = "TeacherTrain",
  377. id = x,
  378. code = $"TeacherTrain-{change.school}",
  379. tmdid = x,
  380. school = change.school,
  381. update = new HashSet<string> { StatisticsService.TeacherAbility,
  382. StatisticsService.TeacherClass, StatisticsService.OfflineRecord }
  383. };
  384. teacherTrain.update.UnionWith(change.update);
  385. task.Add(client.GetContainer(Constant.TEAMModelOS, "Teacher").UpsertItemAsync<TeacherTrain>(teacherTrain, new PartitionKey($"TeacherTrain-{change.school}")));
  386. });
  387. await task.TaskPage(1);
  388. }
  389. }
  390. else
  391. {
  392. Area area = null;
  393. string sql = $"select value(c) from c where c.standard='{change.standard}'";
  394. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql,
  395. requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
  396. {
  397. area = item;
  398. }
  399. AreaSetting setting = null;
  400. if (area != null)
  401. {
  402. try
  403. {
  404. //优先找校级
  405. setting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<AreaSetting>(change.school, new PartitionKey("AreaSetting"));
  406. }
  407. catch (CosmosException)
  408. {
  409. try
  410. {
  411. setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(area.id, new PartitionKey("AreaSetting"));
  412. }
  413. catch (CosmosException)
  414. {
  415. setting = null;
  416. }
  417. }
  418. }
  419. if (setting == null)
  420. {
  421. setting = new AreaSetting
  422. {
  423. allTime = 50,
  424. classTime = 5,
  425. submitTime = 15,
  426. onlineTime = 20,
  427. offlineTime = 10,
  428. lessonMinutes = 45,
  429. };
  430. }
  431. List<Task<TeacherTrain>> task = new List<Task<TeacherTrain>>();
  432. teacherTrains.ForEach(x =>
  433. {
  434. x.update.UnionWith(change.update);
  435. task.Add(StatisticsService.StatisticsTeacher(x, setting, area, client, null));
  436. });
  437. await task.TaskPage(1);
  438. var unchange = change.tmdids.Except(teacherTrains.Select(x => x.id));
  439. if (unchange != null)
  440. {
  441. task.Clear();
  442. unchange.ToList().ForEach(x =>
  443. {
  444. task.Add(StatisticsService.StatisticsTeacher(new TeacherTrain
  445. {
  446. pk = "TeacherTrain",
  447. id = x,
  448. code = $"TeacherTrain-{change.school}",
  449. tmdid = x,
  450. school = change.school,
  451. update = new HashSet<string> { StatisticsService.TeacherAbility,
  452. StatisticsService.TeacherClass, StatisticsService.OfflineRecord }
  453. }, setting, area, client, null));
  454. });
  455. await task.TaskPage(1);
  456. }
  457. }
  458. }
  459. catch (CosmosException ex)
  460. {
  461. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-研修数据变更,重新统计-TeacherTrainChange\n{msg}\n{ex.Message}\n{ex.StackTrace}CosmosException{ex.Status}", GroupNames.成都开发測試群組);
  462. }
  463. catch (Exception ex)
  464. {
  465. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-研修数据变更,重新统计-TeacherTrainChange\n{msg}\n{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  466. }
  467. }
  468. /// <summary>
  469. /// 完善课程变更,StuListChange, originCode是学校编码 则表示名单是学校自定义名单,如果是tmdid则表示醍摩豆的私有名单,scope=school,private。
  470. /// </summary>
  471. /// <data msg>
  472. /// CourseChange
  473. ///// </data>
  474. /// <param name="msg"></param>
  475. /// <returns></returns>
  476. [FunctionName("GroupChange")]
  477. public async Task GroupChangeFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "group-change", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  478. {
  479. var client = _azureCosmos.GetCosmosClient();
  480. try
  481. {
  482. //await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-名单成员变更-GroupChange\n{msg}", GroupNames.成都开发測試群組);
  483. var jsonMsg = JsonDocument.Parse(msg);
  484. GroupChange groupChange = msg.ToObject<GroupChange>();
  485. //名单变动修改学生课程关联信息
  486. //await StuListService.FixStuCourse(client, stuListChange);
  487. //Vote投票 Survey问卷 Exam评测 Learn学习活动 Homework作业活动
  488. //名单变动修改学生问卷关联信息
  489. await ActivityService.FixActivity(client, _dingDing, groupChange, "Survey");
  490. //名单变动修改学生投票关联信息
  491. await ActivityService.FixActivity(client, _dingDing, groupChange, "Vote");
  492. //名单变动修改学生评测关联信息
  493. await ActivityService.FixActivity(client, _dingDing, groupChange, "Exam");
  494. //名单变动修改学生研修关联信息
  495. await ActivityService.FixActivity(client, _dingDing, groupChange, "Study");
  496. //名单变动修改学生简易评测关联信息
  497. await ActivityService.FixActivity(client, _dingDing, groupChange, "ExamLite");
  498. //TODO学习活动
  499. //await FixActivity(client, stuListChange, "Learn");
  500. //名单变动修改学生作业活动信息
  501. await ActivityService.FixActivity(client, _dingDing, groupChange, "Homework");
  502. if (groupChange.type == null || !groupChange.type.Equals("research") || !groupChange.type.Equals("yxtrain") || !groupChange.type.Equals("activity"))
  503. {
  504. //课程名单变动修改学生课程关联信息
  505. await ActivityService.FixStuCourse(client, _dingDing, groupChange);
  506. }
  507. }
  508. catch (Exception ex)
  509. {
  510. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-GroupChange-GroupChange\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.成都开发測試群組);
  511. }
  512. }
  513. [FunctionName("ItemCond")]
  514. public async Task ItemCondFunc([ServiceBusTrigger("%Azure:ServiceBus:ItemCondQueue%", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  515. {
  516. try
  517. {
  518. var client = _azureCosmos.GetCosmosClient();
  519. var jsonMsg = JsonDocument.Parse(msg);
  520. List<ItemCondDto> itemCondDtos = msg.ToObject<List<ItemCondDto>>();
  521. foreach (var itemCondDto in itemCondDtos)
  522. {
  523. if (itemCondDto.scope.Equals("school"))
  524. {
  525. ItemCond itemCond = null;
  526. List<ItemInfo> items = new List<ItemInfo>();
  527. var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field ,c.scope FROM c where c.periodId='{itemCondDto.filed}' and c.pid= null ";
  528. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{itemCondDto.key}") }))
  529. {
  530. items.Add(item);
  531. }
  532. itemCond = new ItemCond()
  533. {
  534. id = $"{itemCondDto.filed}",
  535. code = $"ItemCond-{itemCondDto.key}",
  536. pk = "ItemCond",
  537. ttl = -1,
  538. count = items.Count,
  539. grades = new List<GradeCount>(),
  540. subjects = new List<SubjectCount>()
  541. };
  542. items.ForEach(z =>
  543. {
  544. if (!string.IsNullOrEmpty(z.type))
  545. {
  546. ItemService.CountItemCond(z, null, itemCond);
  547. }
  548. });
  549. await _azureRedis.GetRedisClient(8).HashSetAsync($"ItemCond:{itemCondDto.key}", $"{itemCondDto.filed}", itemCond.ToJsonString());
  550. }
  551. else
  552. {
  553. ItemCond itemCond = null;
  554. List<ItemInfo> items = new List<ItemInfo>();
  555. var queryslt = $"SELECT c.gradeIds,c.subjectId,c.periodId,c.type,c.level,c.field ,c.scope FROM c where c.pid= null ";
  556. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<ItemInfo>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{itemCondDto.filed}") }))
  557. {
  558. items.Add(item);
  559. }
  560. itemCond = new ItemCond() { id = $"{itemCondDto.filed}", code = $"ItemCond", pk = "ItemCond", ttl = -1, count = items.Count };
  561. items.ForEach(z =>
  562. {
  563. if (!string.IsNullOrEmpty(z.type))
  564. {
  565. ItemService.CountItemCond(z, null, itemCond);
  566. }
  567. });
  568. await _azureRedis.GetRedisClient(8).HashSetAsync($"ItemCond:ItemCond", $"{itemCondDto.filed}", itemCond.ToJsonString());
  569. }
  570. }
  571. }
  572. catch (CosmosException ex)
  573. {
  574. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,ItemCond()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  575. }
  576. catch (Exception ex)
  577. {
  578. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,ItemCond()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  579. }
  580. }
  581. //更新產品一覽表
  582. [FunctionName("Product")]
  583. public async Task ProductFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "product", Connection = "Azure:ServiceBus:ConnectionString")] string msg, ILogger log)
  584. {
  585. try
  586. {
  587. var jsonMsg = JsonDocument.Parse(msg);
  588. jsonMsg.RootElement.TryGetProperty("method", out JsonElement method);
  589. jsonMsg.RootElement.TryGetProperty("schoolId", out JsonElement schoolId);
  590. jsonMsg.RootElement.TryGetProperty("prodCode", out JsonElement prodCode);
  591. jsonMsg.RootElement.TryGetProperty("prodId", out JsonElement prodId);
  592. var client = _azureCosmos.GetCosmosClient();
  593. string strQuery = string.Empty;
  594. //取得所有學校產品
  595. ////序號
  596. List<SchoolProductSumData> serialsProductSumOrg = new List<SchoolProductSumData>();
  597. strQuery = $"SELECT * FROM c WHERE c.dataType = 'serial'";
  598. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: strQuery, requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Product-{schoolId}") }))
  599. {
  600. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  601. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  602. {
  603. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  604. {
  605. SchoolProductSerial serialInfo = obj.ToObject<SchoolProductSerial>();
  606. SchoolProductSumData serialProd = serialsProductSumOrg.Where(sp => sp.prodCode == serialInfo.prodCode).FirstOrDefault();
  607. if (serialProd == null)
  608. {
  609. SchoolProductSumData serialProdAdd = new SchoolProductSumData();
  610. serialProdAdd.prodCode = serialInfo.prodCode;
  611. serialProdAdd.ids.Add(serialInfo.id);
  612. serialProdAdd.avaliable = serialProdAdd.ids.Count;
  613. serialsProductSumOrg.Add(serialProdAdd);
  614. }
  615. else
  616. {
  617. if (!serialProd.ids.Contains(serialInfo.id))
  618. {
  619. serialProd.ids.Add(serialInfo.id);
  620. }
  621. serialProd.avaliable = serialProd.ids.Count;
  622. }
  623. }
  624. }
  625. }
  626. ////服務
  627. List<SchoolProductSumData> servicesProductSumOrg = new List<SchoolProductSumData>();
  628. long timestampToday = DateTimeOffset.UtcNow.AddSeconds(1).ToUnixTimeSeconds(); //比現實時間延遲1秒
  629. strQuery = $"SELECT * FROM c WHERE c.dataType = 'service' AND c.startDate <= {timestampToday} AND {timestampToday} <= c.endDate AND c.ttl < 0"; //在授權期間、ttl < 0 才取
  630. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: strQuery, requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Product-{schoolId}") }))
  631. {
  632. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  633. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  634. {
  635. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  636. {
  637. SchoolProductService serviceInfo = obj.ToObject<SchoolProductService>();
  638. SchoolProductSumData serviceProd = servicesProductSumOrg.Where(sp => sp.prodCode == serviceInfo.prodCode).FirstOrDefault();
  639. if (serviceProd == null)
  640. {
  641. SchoolProductSumData serviceProdAdd = new SchoolProductSumData();
  642. serviceProdAdd.prodCode = serviceInfo.prodCode;
  643. serviceProdAdd.avaliable = 0;
  644. serviceProdAdd.ids.Add(serviceInfo.id);
  645. serviceProdAdd.avaliable += serviceInfo.number;
  646. servicesProductSumOrg.Add(serviceProdAdd);
  647. }
  648. else
  649. {
  650. if (!serviceProd.ids.Contains(serviceInfo.id))
  651. {
  652. serviceProd.ids.Add(serviceInfo.id);
  653. serviceProd.avaliable += serviceInfo.number;
  654. }
  655. }
  656. }
  657. }
  658. }
  659. ////服務產品特別對應項
  660. if (servicesProductSumOrg.Count > 0)
  661. {
  662. foreach (SchoolProductSumData servicesProductSumOrgRow in servicesProductSumOrg)
  663. {
  664. //更新學校空間
  665. if (servicesProductSumOrgRow.prodCode.Equals("IPALJ6NY"))
  666. {
  667. School school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{schoolId}", new PartitionKey("Base"));
  668. school.size = (servicesProductSumOrgRow.avaliable < 1) ? 1 : servicesProductSumOrgRow.avaliable;
  669. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(school, $"{schoolId}", new PartitionKey("Base"));
  670. }
  671. }
  672. }
  673. ////硬體
  674. List<SchoolProductSumDataHard> hardsProductSumOrg = new List<SchoolProductSumDataHard>();
  675. strQuery = $"SELECT * FROM c WHERE c.dataType = 'hard'";
  676. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryText: strQuery, requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Product-{schoolId}") }))
  677. {
  678. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  679. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  680. {
  681. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  682. {
  683. SchoolProductHard hardInfo = obj.ToObject<SchoolProductHard>();
  684. SchoolProductSumData hardProd = hardsProductSumOrg.Where(sp => sp.prodCode == hardInfo.prodCode).FirstOrDefault();
  685. if (hardProd == null)
  686. {
  687. SchoolProductSumDataHard hardProdAdd = new SchoolProductSumDataHard();
  688. hardProdAdd.prodCode = hardInfo.prodCode;
  689. hardProdAdd.model = hardInfo.model;
  690. hardProdAdd.ids.Add(hardInfo.id);
  691. hardProdAdd.avaliable = hardProdAdd.ids.Count;
  692. hardsProductSumOrg.Add(hardProdAdd);
  693. }
  694. else
  695. {
  696. if (!hardProd.ids.Contains(hardInfo.id))
  697. {
  698. hardProd.ids.Add(hardInfo.id);
  699. }
  700. hardProd.avaliable = hardProd.ids.Count;
  701. }
  702. }
  703. }
  704. }
  705. //更新學校產品一覽表
  706. SchoolProductSum prodSum = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolProductSum>(schoolId.ToString(), new PartitionKey($"ProductSum"));
  707. prodSum.serial = serialsProductSumOrg;
  708. prodSum.service = servicesProductSumOrg;
  709. prodSum.hard = hardsProductSumOrg;
  710. await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolProductSum>(prodSum, prodSum.id, new PartitionKey($"{prodSum.code}"));
  711. }
  712. catch (CosmosException ex)
  713. {
  714. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Product()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  715. }
  716. catch (Exception ex)
  717. {
  718. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,Product()\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.醍摩豆服務運維群組);
  719. }
  720. }
  721. /// <summary>
  722. /// 批量复制文件
  723. /// </summary>
  724. /// <param name="msg"></param>
  725. /// <returns></returns>
  726. [FunctionName("CopyStandardFile")]
  727. public async Task BatchCopyBlobFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "copy-standard-file", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  728. {
  729. try
  730. {
  731. //await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-Blob复制文件-CopyStandardFile\n{msg}", GroupNames.成都开发測試群組);
  732. var jsonMsg = JsonDocument.Parse(msg);
  733. BatchCopyFile bIBatchCopyFile = msg.ToObject<BatchCopyFile>();
  734. //批量复制文件
  735. var result = await BatchCopyFileService.CopyFile(_dingDing, _azureStorage, bIBatchCopyFile);
  736. if (result == 200)
  737. {
  738. //发送消息实体
  739. Notification notification = new Notification
  740. {
  741. hubName = "hita",
  742. type = "msg",
  743. from = $"BI:{_option.Location}:private",
  744. to = bIBatchCopyFile.tmdIds,
  745. label = $"{bIBatchCopyFile.codeKey}_finish",
  746. body = new { location = _option.Location, biz = $"{bIBatchCopyFile.codeKey}", tmdid = $"{bIBatchCopyFile.tmdid}", tmdname = $"{bIBatchCopyFile.tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
  747. expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
  748. };
  749. var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
  750. var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
  751. var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
  752. var location = _option.Location;
  753. await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //站内发送消息
  754. }
  755. }
  756. catch (Exception ex)
  757. {
  758. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-Blob复制文件-CopyStandardFile\n{ex.Message}\n{ex.StackTrace}\n{msg}", GroupNames.成都开发測試群組);
  759. }
  760. }
  761. /// <summary>
  762. /// 更新开课数据事件
  763. /// </summary>
  764. /// <param name="msg"></param>
  765. /// <returns></returns>
  766. [FunctionName("LessonRecordEvent")]
  767. public async Task LessonRecordFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "lesson-record-event", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
  768. {
  769. JsonElement data = msg.ToObject<JsonElement>();
  770. string scope = "";
  771. string tmdid = "";
  772. string lessonId;
  773. string school;
  774. string tbname;
  775. string code;
  776. string blobname;
  777. List<LessonUpdate> updates = new List<LessonUpdate>();
  778. //更新课堂记录
  779. if (data.TryGetProperty("lesson_id", out JsonElement _lessonId) && !string.IsNullOrEmpty($"{_lessonId}"))
  780. {
  781. if (!data.TryGetProperty("tmdid", out JsonElement _tmdid)) return;
  782. if (!data.TryGetProperty("scope", out JsonElement _scope)) return;
  783. if (!data.TryGetProperty("grant_types", out JsonElement _grant_types)) return;
  784. data.TryGetProperty("school", out JsonElement _school);
  785. school = $"{_school}";
  786. scope = $"{_scope}";
  787. tmdid = $"{_tmdid}";
  788. lessonId = $"{_lessonId}";
  789. updates = _grant_types.ToObject<List<LessonUpdate>>();
  790. }//创建课堂记录
  791. else if (data.TryGetProperty("id", out JsonElement _id) && !string.IsNullOrEmpty($"{_id}")
  792. && data.TryGetProperty("tmdid", out JsonElement _tmdid) && !string.IsNullOrEmpty($"{_tmdid}")
  793. && data.TryGetProperty("scope", out JsonElement _scope) && !string.IsNullOrEmpty($"{_scope}"))
  794. {
  795. data.TryGetProperty("school", out JsonElement _school);
  796. school = $"{_school}";
  797. scope = $"{_scope}";
  798. tmdid = $"{_tmdid}";
  799. lessonId = $"{_id}";
  800. updates.Add(new LessonUpdate { grant_type = "create" });
  801. }//删除课堂记录
  802. else if (data.TryGetProperty("delete_id", out JsonElement _delete_id) && !string.IsNullOrEmpty($"{_delete_id}")
  803. && data.TryGetProperty("tmdid", out JsonElement _dtmdid) && !string.IsNullOrEmpty($"{_dtmdid}")
  804. && data.TryGetProperty("scope", out JsonElement _dscope) && !string.IsNullOrEmpty($"{_dscope}")
  805. && data.TryGetProperty("opt", out JsonElement _opt) && !string.IsNullOrEmpty($"{_opt}"))
  806. {
  807. data.TryGetProperty("school", out JsonElement _dschool);
  808. school = $"{_dschool}";
  809. if ($"{_opt}".Equals("delete"))
  810. {
  811. scope = $"{_dscope}";
  812. tmdid = $"{_dtmdid}";
  813. lessonId = $"{_delete_id}";
  814. updates.Add(new LessonUpdate { grant_type = "delete" });
  815. }
  816. else { return; }
  817. }
  818. else
  819. {
  820. return;
  821. }
  822. var client = _azureCosmos.GetCosmosClient();
  823. if ($"{scope}".Equals("school") && !string.IsNullOrEmpty($"{school}"))
  824. {
  825. blobname = $"{school}";
  826. code = $"LessonRecord-{school}";
  827. tbname = "School";
  828. }
  829. else if ($"{scope}".Equals("private"))
  830. {
  831. blobname = $"{tmdid}";
  832. code = $"LessonRecord-{tmdid}";
  833. tbname = "Teacher";
  834. }
  835. else
  836. {
  837. return;
  838. }
  839. LessonDis lessonDis = new LessonDis();
  840. List<LessonUpdate> msgs = new List<LessonUpdate>();
  841. try
  842. {
  843. LessonRecord oldlessonRecord = null;
  844. LessonRecord lessonRecord = null;
  845. Azure.Response response = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemStreamAsync(lessonId, new PartitionKey(code));
  846. if (response.Status == 200)
  847. {
  848. var doc = JsonDocument.Parse(response.ContentStream);
  849. lessonRecord = doc.RootElement.ToObject<LessonRecord>();
  850. oldlessonRecord = doc.RootElement.ToObject<LessonRecord>();
  851. }
  852. else
  853. {
  854. lessonRecord = null;
  855. }
  856. if (updates.IsNotEmpty())
  857. {
  858. foreach (LessonUpdate update in updates)
  859. {
  860. switch (update.grant_type)
  861. {
  862. //更新课堂时长
  863. case "up-duration":
  864. var duration = double.Parse($"{update.data}");
  865. lessonRecord.duration = duration;
  866. msgs.Add(update);
  867. break;
  868. //更新T分
  869. case "up-tScore":
  870. var tScore = int.Parse($"{update.data}");
  871. lessonRecord.tScore = tScore;
  872. msgs.Add(update);
  873. break;
  874. //更新课P分
  875. case "up-pScore":
  876. var pScore = int.Parse($"{update.data}");
  877. lessonRecord.pScore = pScore;
  878. msgs.Add(update);
  879. break;
  880. //更新 学生人数
  881. case "up-mCount":
  882. var mCount = int.Parse($"{update.data}");
  883. lessonRecord.mCount = mCount;
  884. msgs.Add(update);
  885. break;
  886. //更新 议课次数
  887. case "up-techCount":
  888. var techCount = int.Parse($"{update.data}");
  889. lessonRecord.mCount = techCount;
  890. msgs.Add(update);
  891. break;
  892. //更新 时间线
  893. case "up-TimeLine":
  894. //BlobDownloadResult TimeLineblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/{_lessonId}/IES/TimeLine.json").DownloadContentAsync();
  895. //var timeline = TimeLineblobDownload.Content.ToObjectFromJson<List<LessonTimeLine>>();
  896. msgs.Add(update);
  897. break;
  898. //更新 课堂总览信息
  899. case "up-ActivityInfo":
  900. //BlobDownloadResult ActivityInfoblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/{_lessonId}/IES/ActivityInfo.json").DownloadContentAsync();
  901. //var activityInfos = ActivityInfoblobDownload.Content.ToObjectFromJson<List<LessonActivityInfo>>();
  902. msgs.Add(update);
  903. break;
  904. case "delete":
  905. try
  906. {
  907. await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemAsync<LessonRecord>(lessonId, new PartitionKey(code));
  908. msgs.Add(update);
  909. }
  910. catch (CosmosException ex)
  911. {
  912. msgs.Add(update);
  913. }
  914. lessonRecord = null;
  915. break;
  916. case "create":
  917. oldlessonRecord = null;
  918. //处理课堂选用的课程信息
  919. if (!string.IsNullOrEmpty(lessonRecord.courseId))
  920. {
  921. Course course = null;
  922. try
  923. {
  924. course = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Course>(lessonRecord.courseId, new PartitionKey($"Course-{lessonRecord.school}"));
  925. }
  926. catch (CosmosException ex) when (ex.Status != 404)
  927. {
  928. try
  929. {
  930. course = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Course>(lessonRecord.courseId, new PartitionKey($"Course-{lessonRecord.tmdid}"));
  931. }
  932. catch (CosmosException e) when (e.Status != 404)
  933. {
  934. course = null;
  935. }
  936. }
  937. if (course != null)
  938. {
  939. lessonRecord.periodId = course.period?.id;
  940. lessonRecord.subjectId = course.subject?.id;
  941. }
  942. }
  943. //处理课堂选用的名单
  944. if (lessonRecord.groupIds.IsNotEmpty())
  945. {
  946. HashSet<string> grades = new HashSet<string>();
  947. List<GroupListDto> groups = await GroupListService.GetGroupListListids(client, _dingDing, lessonRecord.groupIds, lessonRecord.school);
  948. List<GroupListDto> groupLists = groups.FindAll(x => !string.IsNullOrEmpty(x.periodId) && x.year > 0 && !string.IsNullOrEmpty(x.school));
  949. if (groupLists.IsNotEmpty() && !string.IsNullOrEmpty(lessonRecord.periodId))
  950. {
  951. School schoolObj = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(lessonRecord.school, new PartitionKey("Base"));
  952. //年级算法
  953. int? Count = schoolObj.period.Find(x => x.id.Equals(lessonRecord.periodId)).grades?.Count;
  954. if (Count.HasValue)
  955. {
  956. int Month = DateTimeOffset.UtcNow.Month;
  957. int Year = DateTimeOffset.UtcNow.Year;
  958. foreach (int year in groupLists.Select(x => x.year))
  959. {
  960. int grade;
  961. if (Month >= 1 && Month <= 6)
  962. {
  963. grade = (Year - year + 1) / Count.Value;
  964. }
  965. else
  966. {
  967. grade = (Year - year) / Count.Value;
  968. }
  969. grades.Add($"{grade}");
  970. }
  971. }
  972. }
  973. lessonRecord.grade.AddRange(grades);
  974. }
  975. msgs.Add(update);
  976. break;
  977. default:
  978. break;
  979. }
  980. }
  981. //
  982. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<LessonRecord>(lessonRecord, lessonId, new PartitionKey(code));
  983. //计算课堂更新前后的差值
  984. lessonDis = LessonService.DisLessonCount(oldlessonRecord, lessonRecord, lessonDis);
  985. await LessonService.FixLessonCount(client, _dingDing, lessonRecord, oldlessonRecord, lessonDis);
  986. }
  987. } catch (CosmosException e) {
  988. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-更新课堂记录出错-CosmosDB异常{e.Message}\n{e.Status}", GroupNames.成都开发測試群組);
  989. }
  990. catch (Exception ex)
  991. {
  992. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-更新课堂记录出错\n{ex.Message}\n{ex.StackTrace}\n{data}\n{code}\n", GroupNames.成都开发測試群組);
  993. }
  994. }
  995. }
  996. }