IESHttpTrigger.cs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. using Azure.Cosmos;
  2. using Azure.Storage.Blobs.Models;
  3. using HTEXLib.COMM.Helpers;
  4. using Microsoft.Azure.Cosmos.Table;
  5. using Microsoft.Azure.Functions.Worker;
  6. using Microsoft.Azure.Functions.Worker.Http;
  7. using OpenXmlPowerTools;
  8. using StackExchange.Redis;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Dynamic;
  12. using System.IO;
  13. using System.Linq;
  14. using System.Net;
  15. using System.Reflection;
  16. using System.Text;
  17. using System.Text.Json;
  18. using System.Threading.Tasks;
  19. using TEAMModelOS.SDK;
  20. using TEAMModelOS.SDK.DI;
  21. using TEAMModelOS.SDK.Extension;
  22. using TEAMModelOS.SDK.Models;
  23. using TEAMModelOS.SDK.Models.Cosmos.Teacher;
  24. using TEAMModelOS.SDK.Models.Table;
  25. using static TEAMModelOS.SDK.Models.Teacher;
  26. namespace TEAMModelOS.FunctionV4.HttpTrigger
  27. {
  28. public class IESHttpTrigger
  29. {
  30. private readonly AzureCosmosFactory _azureCosmos;
  31. private readonly DingDing _dingDing;
  32. private readonly AzureStorageFactory _azureStorage;
  33. private readonly AzureRedisFactory _azureRedis;
  34. public IESHttpTrigger(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage
  35. , AzureRedisFactory azureRedis)
  36. {
  37. _azureCosmos = azureCosmos;
  38. _dingDing = dingDing;
  39. _azureStorage = azureStorage;
  40. _azureRedis = azureRedis;
  41. }
  42. /// <summary>
  43. /// </summary>
  44. /// <param name="req"></param>
  45. /// <param name="log"></param>
  46. /// <returns></returns>
  47. [Function("system-info-function")]
  48. public async Task<HttpResponseData> SystemInfo([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequestData req)
  49. {
  50. var response = req.CreateResponse(HttpStatusCode.OK);
  51. Type attr = this.GetType();
  52. string currentDirectory = Path.GetDirectoryName(attr.Assembly.Location);
  53. Assembly assembly = Assembly.LoadFrom($"{currentDirectory}\\TEAMModelOS.FunctionV4.dll");
  54. var description = assembly.GetCustomAttribute<AssemblyDescriptionAttribute>().Description;
  55. //var v1 = Assembly.GetEntryAssembly().GetName().Version;
  56. //var v2 = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
  57. // var description = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyDescriptionAttribute>().Description;
  58. var version = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version;
  59. long nowtime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  60. //Console.WriteLine($"Assembly.GetEntryAssembly().GetName().Version: " +
  61. // $"{Assembly.GetEntryAssembly().GetName().Version}");5.2107.12.1
  62. //Console.WriteLine($"Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version:" +
  63. // $"{Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>().Version}");5.2107.12.1
  64. //Console.WriteLine($"Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion:" +
  65. // $"{Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion}");5.2107.12
  66. await response.WriteAsJsonAsync(new { version, description, nowtime });
  67. return response;
  68. }
  69. /// <summary>
  70. /// 区级艺术评价变更,异步同步已开启数据同步的学校。
  71. /// </summary>
  72. /// <param name="req"></param>
  73. /// <param name="log"></param>
  74. /// <returns></returns>
  75. [Function("area-artsetting-change")]
  76. public async Task<HttpResponseData> AreaArtSettingChange([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req) {
  77. var response = req.CreateResponse(HttpStatusCode.OK);
  78. string data = await new StreamReader(req.Body).ReadToEndAsync();
  79. var json = JsonDocument.Parse(data).RootElement;
  80. json.TryGetProperty("areaId", out JsonElement _areaId);
  81. string schoolSQL = $"select c.id ,c.name ,c.period from c where c.areaId='{_areaId}'";
  82. List<School> schools = new List<School>();
  83. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School)
  84. .GetItemQueryIterator<School>(queryText: schoolSQL, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base") }))
  85. {
  86. schools.Add(item);
  87. }
  88. ArtSetting artSetting= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<ArtSetting>($"{_areaId}", new PartitionKey());
  89. foreach (var school in schools) {
  90. var periods = school.period.Where(p => p.type.IsNotEmpty());
  91. foreach (var period in periods)
  92. {
  93. var dimension = artSetting.dimensions.FindAll(x => x.type.Intersect(period.type).Any());
  94. var bindIds = period.subjects.Where(s => !string.IsNullOrWhiteSpace(s.bindId)).Select(x => x.bindId);
  95. //该学段未同步学科的。
  96. var unBindIds = dimension.Where(z => !string.IsNullOrWhiteSpace(z.subjectBind)).Select(x => x.subjectBind).ToHashSet().Except(bindIds);
  97. if (unBindIds.Any())
  98. {
  99. //尝试寻找同名学科且没有设置bindId的
  100. foreach (var unBindId in unBindIds)
  101. {
  102. var subjects = artSetting.dimensions.FindAll(d => !string.IsNullOrWhiteSpace(d.subjectBind) && !string.IsNullOrWhiteSpace(d.subject) && d.subjectBind.Equals(unBindId))?.Select(m => m.subject);
  103. if (subjects != null)
  104. {
  105. foreach (var subject in subjects)
  106. {
  107. //获取同名学科,且没绑定的
  108. var sub = period.subjects.FindAll(sub => sub.name.Equals(subject) && string.IsNullOrWhiteSpace(sub.bindId));
  109. if (sub.IsNotEmpty())
  110. {
  111. sub[0].bindId = unBindId;
  112. }
  113. else
  114. {
  115. period.subjects.Add(new Subject { id = Guid.NewGuid().ToString(), name = subject, bindId = unBindId, type = 1 });
  116. }
  117. break;
  118. }
  119. }
  120. }
  121. }
  122. var period_subjects = period.subjects.Where(s => !string.IsNullOrWhiteSpace(s.bindId));
  123. foreach (var subject in period_subjects)
  124. {
  125. var dim= dimension.Where(x => x.subjectBind.Equals(subject.bindId));
  126. if (dim.Any()) {
  127. Knowledge old = null;
  128. string sql = $"select value(c) from c where c.periodId = '{period.id}'";
  129. string pk = $"Knowledge-{school.id}-{subject.id}";
  130. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").
  131. GetItemQueryIterator<Knowledge>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(pk) }))
  132. {
  133. old = item;
  134. break;
  135. }
  136. //同步知识块。
  137. if (old != null)
  138. {
  139. bool change = false;
  140. //如果之前的是1 来源于区级,后面因区级删除,应该还原为0。
  141. var oldBlocks = old.blocks.Select(x => x.name).ToHashSet() ;
  142. var dimBlocks = dim.SelectMany(d => d.blocks);
  143. //增加的
  144. var addBlocks = dimBlocks.Except(oldBlocks);
  145. //减少的
  146. var cutBlocks = oldBlocks.Except(dimBlocks);
  147. foreach (var add in addBlocks) {
  148. old.blocks.Add(new Block { name = add,source = 1 });
  149. change = true;
  150. }
  151. //减少的还原为0
  152. if (cutBlocks.Any()) {
  153. old.blocks.ForEach(ob => {
  154. if (cutBlocks.Contains(ob.name))
  155. {
  156. ob.source = 0;
  157. change=true;
  158. }
  159. });
  160. }
  161. if (change) {
  162. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(old, old.id, new PartitionKey(old.code));
  163. }
  164. }
  165. else
  166. {
  167. var blocks = dim.SelectMany(x => x.blocks).Select(bs=> new Block { name=bs,source=-1 });
  168. if (blocks.Any()) {
  169. var _new = new Knowledge
  170. {
  171. id = Guid.NewGuid().ToString(),
  172. pk = "Knowledge",
  173. code = pk,
  174. owner = school.id,
  175. periodId = period.id,
  176. subjectId = subject.id,
  177. blocks = blocks.ToList()
  178. };
  179. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).CreateItemAsync(_new, new PartitionKey(_new.code));
  180. }
  181. }
  182. }
  183. }
  184. }
  185. }
  186. return response;
  187. }
  188. /// <summary>
  189. /// 行政班,学生毕业状态变更。
  190. /// </summary>
  191. /// <param name="req"></param>
  192. /// <param name="log"></param>
  193. /// <returns></returns>
  194. [Function("graduate-change")]
  195. public async Task<HttpResponseData> GraduateChange([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req) {
  196. var response = req.CreateResponse(HttpStatusCode.OK);
  197. dynamic jsondata =new ExpandoObject() ;
  198. try {
  199. string data = await new StreamReader(req.Body).ReadToEndAsync();
  200. var json = JsonDocument.Parse(data).RootElement;
  201. jsondata = json;
  202. //await _dingDing.SendBotMsg( "毕业状态变更:"+json.ToJsonString(), GroupNames.成都开发測試群組);
  203. string schoolId = null;
  204. if (json.TryGetProperty("schoolId", out JsonElement _schoolId))
  205. {
  206. schoolId = $"{_schoolId}";
  207. }
  208. if (string.IsNullOrEmpty(schoolId))
  209. {
  210. return response;
  211. }
  212. //计算毕业的
  213. if (json.TryGetProperty("graduate_classes", out JsonElement _graduate_classes))
  214. {
  215. List<Class> graduate_classes = _graduate_classes.ToObject<List<Class>>();
  216. if (graduate_classes.IsNotEmpty())
  217. {
  218. var ids = graduate_classes.Where(x => !string.IsNullOrWhiteSpace(x.id)).Select(x => $"'{x.id}'");
  219. List<Student> students = new List<Student>();
  220. string sql = $"select value c from c where (c.graduate = 0 or IS_DEFINED(c.graduate) = false) and c.classId in ({string.Join(",", ids)})";
  221. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student)
  222. .GetItemQueryIterator<Student>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base-{schoolId}") }))
  223. {
  224. item.graduate = 1;
  225. students.Add(item);
  226. }
  227. foreach (var item in students)
  228. {
  229. item.graduate = 1;
  230. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync<Student>(item, item.id, new PartitionKey($"Base-{schoolId}"));
  231. }
  232. foreach (var item in graduate_classes)
  233. {
  234. item.graduate = 1;
  235. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync<Class>(item, item.id, new PartitionKey($"Class-{schoolId}"));
  236. }
  237. }
  238. }
  239. //未毕业的
  240. if (json.TryGetProperty("cancel_graduate_classes", out JsonElement _cancel_graduate_classes))
  241. {
  242. List<Class> cancel_graduate_classes = _cancel_graduate_classes.ToObject<List<Class>>();
  243. if (cancel_graduate_classes.IsNotEmpty())
  244. {
  245. var ids = cancel_graduate_classes.Where(x => !string.IsNullOrWhiteSpace(x.id)).Select(x => $"'{x.id}'");
  246. List<Student> students = new List<Student>();
  247. string sql = $"select value c from c where c.graduate =1 and c.classId in ({string.Join(",", ids)})";
  248. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student)
  249. .GetItemQueryIterator<Student>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Base-{schoolId}") }))
  250. {
  251. item.graduate = 0;
  252. students.Add(item);
  253. }
  254. foreach (var item in students)
  255. {
  256. item.graduate = 0;
  257. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync<Student>(item, item.id, new PartitionKey($"Base-{schoolId}"));
  258. }
  259. foreach (var item in cancel_graduate_classes)
  260. {
  261. item.graduate = 0;
  262. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync<Class>(item, item.id, new PartitionKey($"Class-{schoolId}"));
  263. }
  264. }
  265. }
  266. } catch (Exception ex) {
  267. await _dingDing.SendBotMsg($"graduate-change,{ex.Message}\n{ex.StackTrace}\n{jsondata.ToJsonString()}",GroupNames.醍摩豆服務運維群組);
  268. }
  269. return response;
  270. }
  271. /// <summary>
  272. /// 数据推送接口
  273. /// </summary>
  274. /// <param name="req"></param>
  275. /// <param name="log"></param>
  276. /// <returns></returns>
  277. [Function("lesson-tag-change")]
  278. public async Task<HttpResponseData> LessonTagChange([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req) {
  279. var response = req.CreateResponse(HttpStatusCode.OK);
  280. string data = await new StreamReader(req.Body).ReadToEndAsync();
  281. var json = JsonDocument.Parse(data).RootElement;
  282. List<TagOldNew> old_new = null;
  283. string school = null;
  284. if (json.TryGetProperty("school", out JsonElement _school))
  285. {
  286. school = _school.GetString();
  287. }
  288. if (json.TryGetProperty("old_new", out JsonElement _old_new))
  289. {
  290. old_new = _old_new.ToObject<List<TagOldNew>>();
  291. }
  292. if (old_new.IsNotEmpty() && !string.IsNullOrWhiteSpace(school))
  293. {
  294. foreach (var on in old_new)
  295. {
  296. List<LessonRecord> lessonRecords = new List<LessonRecord>();
  297. string sql = $"select value(c) from c where array_contains(c.category,'{on._old}') ";
  298. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonRecord>
  299. (queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonRecord-{_school}") }))
  300. {
  301. lessonRecords.Add(item);
  302. }
  303. lessonRecords.ForEach(item =>
  304. {
  305. //修改标签
  306. if (!string.IsNullOrWhiteSpace(on._new))
  307. {
  308. for (int i = 0; i < item.category.Count; i++)
  309. {
  310. if (item.category[i].Equals(on._old))
  311. {
  312. item.category[i] = on._new;
  313. }
  314. }
  315. }
  316. else
  317. {
  318. //表示删除标签
  319. item.category.RemoveAll(x => x.Equals(on._old));
  320. }
  321. });
  322. foreach (var item in lessonRecords)
  323. {
  324. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
  325. }
  326. }
  327. }
  328. await response.WriteAsJsonAsync(new { data = json });
  329. return response;
  330. }
  331. /// <summary>
  332. /// 数据推送接口
  333. /// </summary>
  334. /// <param name="req"></param>
  335. /// <param name="log"></param>
  336. /// <returns></returns>
  337. [Function("knowledge-change")]
  338. public async Task<HttpResponseData> KnowledgeChange([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req)
  339. {
  340. var response = req.CreateResponse(HttpStatusCode.OK);
  341. string data = await new StreamReader(req.Body).ReadToEndAsync();
  342. var json = JsonDocument.Parse(data).RootElement;
  343. List<TagOldNew> old_new = null;
  344. string school = null;
  345. if (json.TryGetProperty("school", out JsonElement _school))
  346. {
  347. school = _school.GetString();
  348. }
  349. if (json.TryGetProperty("old_new", out JsonElement _old_new))
  350. {
  351. old_new = _old_new.ToObject<List<TagOldNew>>();
  352. }
  353. if (old_new.IsNotEmpty() && !string.IsNullOrWhiteSpace(school))
  354. {
  355. foreach (var on in old_new)
  356. {
  357. List<ItemInfo> items = new List<ItemInfo>();
  358. string sql = $"select value(c) from c where array_contains(c.knowledge,'{on._old}') ";
  359. await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<ItemInfo>
  360. (queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{_school}") }))
  361. {
  362. items.Add(item);
  363. }
  364. items.ForEach(item =>
  365. {
  366. //修改知识点
  367. if (!string.IsNullOrEmpty(on._new))
  368. {
  369. for (int i = 0; i < item.knowledge.Count; i++)
  370. {
  371. if (item.knowledge[i].Equals(on._old))
  372. {
  373. item.knowledge[i] = on._new;
  374. }
  375. }
  376. }
  377. else
  378. {
  379. //表示删除知识点
  380. item.knowledge.RemoveAll(x => x.Equals(on._old));
  381. }
  382. });
  383. foreach (var item in items)
  384. {
  385. ItemBlob itemBlob = null;
  386. try
  387. {
  388. BlobDownloadInfo blobDownloadResult = await _azureStorage.GetBlobContainerClient($"{school}").GetBlobClient($"/item/{item.id}/{item.id}.json").DownloadAsync();
  389. if (blobDownloadResult != null)
  390. {
  391. var blob = JsonDocument.Parse(blobDownloadResult.Content);
  392. itemBlob = blob.RootElement.ToObject<ItemBlob>();
  393. itemBlob.exercise.knowledge = item.knowledge;
  394. await _azureStorage.GetBlobContainerClient($"{school}").UploadFileByContainer(itemBlob.ToJsonString(), "item", $"{item.id}/{item.id}.json", true);
  395. }
  396. }
  397. catch (Exception ex)
  398. {
  399. itemBlob = null;
  400. }
  401. await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
  402. }
  403. }
  404. }
  405. await response.WriteAsJsonAsync(new { data = json });
  406. return response;
  407. }
  408. /// <summary>
  409. /// 在线人数记录
  410. /// </summary>
  411. /// <param name="msg"></param>
  412. /// <returns></returns>
  413. [Function("online-record")]
  414. public async Task<HttpResponseData> OnlineRecord([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req)
  415. {
  416. var response = req.CreateResponse(HttpStatusCode.OK);
  417. string data = await new StreamReader(req.Body).ReadToEndAsync();
  418. var json = JsonDocument.Parse(data).RootElement;
  419. try
  420. {
  421. string school = null;
  422. string scope = null;
  423. string id = null;
  424. string ip = null;
  425. int expire = 1;
  426. if (json.TryGetProperty("school", out JsonElement _school))
  427. school = _school.GetString();
  428. if (json.TryGetProperty("scope", out JsonElement _scope))
  429. scope = _scope.GetString();
  430. if (json.TryGetProperty("id", out JsonElement _id))
  431. id = _id.GetString();
  432. if (json.TryGetProperty("ip", out JsonElement _ip))
  433. ip = _ip.GetString();
  434. if (json.TryGetProperty("expire", out JsonElement _expire))
  435. expire = _expire.GetInt32();
  436. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin");
  437. var cosmosClient = _azureCosmos.GetCosmosClient();
  438. DateTimeOffset dateTime = DateTimeOffset.UtcNow;
  439. var dateHour = dateTime.ToString("yyyyMMddHH"); //获取当天的小时
  440. var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
  441. var dateMonth = dateTime.ToString("yyyyMM");//获取当月的日期
  442. var currentHour = dateTime.Hour; //当前小时
  443. var currentDay = dateTime.Day; //当前天
  444. long Expire = dateTime.AddHours(expire).ToUnixTimeMilliseconds(); //token到期时间
  445. long now = dateTime.ToUnixTimeMilliseconds(); //当前时间戳
  446. DateTime hour = DateTime.UtcNow.AddHours(25); //25小时到期
  447. DateTime month = DateTime.UtcNow.AddDays(32); //一个月到期
  448. var delTbHour = dateTime.AddHours(-168).ToString("yyyyMMddHH"); //168小时前
  449. var delTbDay = dateTime.AddDays(-180).ToString("yyyyMMdd"); //180天前
  450. switch (scope)
  451. {
  452. case "teacher":
  453. try
  454. {
  455. Teacher teacher = await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
  456. teacher.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
  457. await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey("Base"));
  458. }
  459. catch { }
  460. break;
  461. case "student":
  462. try
  463. {
  464. Student student = await cosmosClient.GetContainer("TEAMModelOS", Constant.Student).ReadItemAsync<Student>(id, new PartitionKey($"Base-{school}"));
  465. student.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
  466. await cosmosClient.GetContainer("TEAMModelOS", Constant.Student).ReplaceItemAsync<Student>(student, student.id, new PartitionKey($"Base-{school}"));
  467. }
  468. catch { }
  469. break;
  470. case "tmduser":
  471. try
  472. {
  473. TmdUser tmdUser = await cosmosClient.GetContainer("TEAMModelOS", Constant.Student).ReadItemAsync<TmdUser>(id, new PartitionKey("Base"));
  474. tmdUser.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
  475. await cosmosClient.GetContainer("TEAMModelOS", Constant.Student).ReplaceItemAsync<TmdUser>(tmdUser, tmdUser.id, new PartitionKey("Base"));
  476. }
  477. catch { }
  478. break;
  479. }
  480. //天
  481. SortedSetEntry[] dayCnt = null;
  482. //月
  483. SortedSetEntry[] monthCnt = null;
  484. try
  485. {
  486. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateDay}", $"{currentHour}", 1);//一天24小时 小时为单位
  487. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateMonth}", $"{currentDay}", 1); //一天的累计 天为单位
  488. var resDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateDay}");
  489. if (resDay == null)
  490. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateDay}", hour); //设置到期时间
  491. var rspMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateMonth}");
  492. if (rspMonth == null)
  493. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateMonth}", month); //设置到期时间
  494. //保存当前小时统计
  495. dayCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateDay}");
  496. //保存当前的统计数据
  497. monthCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateMonth}");
  498. }
  499. catch { }
  500. if (dayCnt != null && dayCnt.Length > 0)
  501. {
  502. List<HourLogin> hourLogins = new();
  503. foreach (var dCnt in dayCnt)
  504. {
  505. if (((int)dCnt.Element) == currentHour)
  506. {
  507. var tphourLogins = await table.QueryWhereString<HourLogin>($"PartitionKey eq 'HourLogin' and RowKey eq '{dateHour}'");
  508. if (tphourLogins.Count > 0)
  509. {
  510. foreach (var hourLogin in tphourLogins)
  511. {
  512. if (scope.Equals("teacher"))
  513. hourLogin.Teacher = (int)dCnt.Score;
  514. else if (scope.Equals("student"))
  515. hourLogin.Student = (int)dCnt.Score;
  516. else
  517. hourLogin.TmdUser = (int)dCnt.Score;
  518. hourLogins.Add(hourLogin);
  519. }
  520. }
  521. else
  522. {
  523. HourLogin hourLogin = new() { PartitionKey = $"HourLogin", RowKey = dateHour, Hour = currentHour };
  524. if (scope.Equals("teacher"))
  525. {
  526. hourLogin.Teacher = 1;
  527. hourLogin.Student = 0;
  528. hourLogin.TmdUser = 0;
  529. }
  530. else if (scope.Equals("student"))
  531. {
  532. hourLogin.Teacher = 0;
  533. hourLogin.Student = 1;
  534. hourLogin.TmdUser = 0;
  535. }
  536. else
  537. {
  538. hourLogin.Teacher = 0;
  539. hourLogin.Student = 0;
  540. hourLogin.TmdUser = 1;
  541. }
  542. hourLogins.Add(hourLogin);
  543. }
  544. }
  545. }
  546. await table.SaveOrUpdateAll(hourLogins); //保存和更新保存当前小时登录次数
  547. }
  548. if (monthCnt != null && monthCnt.Length > 0)
  549. {
  550. List<DayLogin> dayLogins = new();
  551. foreach (var mCnt in monthCnt)
  552. {
  553. if (((int)mCnt.Element) == currentDay)
  554. {
  555. //保存当天的峰值
  556. var tbDays = await table.QueryWhereString<DayLogin>($"PartitionKey eq 'DayLogin' and RowKey eq '{dateDay}'");
  557. if (tbDays.Count > 0)
  558. {
  559. foreach (var dayLogin in tbDays)
  560. {
  561. if (scope.Equals("teacher"))
  562. dayLogin.Teacher = (int)mCnt.Score;
  563. else if (scope.Equals("student"))
  564. dayLogin.Student = (int)mCnt.Score;
  565. else
  566. dayLogin.TmdUser = (int)mCnt.Score;
  567. dayLogins.Add(dayLogin);
  568. }
  569. }
  570. else
  571. {
  572. //保存当月每天的峰值
  573. DayLogin dayLogin = new() { PartitionKey = $"DayLogin", RowKey = dateDay, Day = currentDay };
  574. if (scope.Equals("teacher"))
  575. {
  576. dayLogin.Teacher = 1;
  577. dayLogin.Student = 0;
  578. dayLogin.TmdUser = 0;
  579. }
  580. else if (scope.Equals("student"))
  581. {
  582. dayLogin.Teacher = 0;
  583. dayLogin.Student = 1;
  584. dayLogin.TmdUser = 0;
  585. }
  586. else
  587. {
  588. dayLogin.Teacher = 0;
  589. dayLogin.Student = 0;
  590. dayLogin.TmdUser = 1;
  591. }
  592. dayLogins.Add(dayLogin);
  593. }
  594. }
  595. }
  596. await table.SaveOrUpdateAll(dayLogins);// 保存当月每天在线数据
  597. }
  598. string tbHourSql = $"PartitionKey eq 'HourLogin' and RowKey le '{delTbHour}'";
  599. string tbDaySql = $"PartitionKey eq 'DayLogin' and RowKey le '{delTbDay}'";
  600. try
  601. {
  602. await table.DeleteStringWhere<HourLogin>(rowKey: tbHourSql); //删除168小时前的数据
  603. await table.DeleteStringWhere<DayLogin>(rowKey: tbDaySql); //删除180天前的数据
  604. }
  605. catch { }
  606. if (!string.IsNullOrWhiteSpace(school))
  607. {
  608. //天
  609. SortedSetEntry[] scDayCnt = null;
  610. //月
  611. SortedSetEntry[] scMonthCnt = null;
  612. try
  613. {
  614. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateDay}", $"{currentHour}", 1);//当天当前小时在线人加1
  615. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateMonth}", $"{currentDay}", 1); //当天的在线加1
  616. var reScDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateDay}");
  617. if (reScDay == null)
  618. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateDay}", hour); //设置到期时间
  619. var reScMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateMonth}");
  620. if (reScMonth == null)
  621. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateMonth}", month); //设置到期时间
  622. //保存学校当天每小时的
  623. scDayCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateDay}");
  624. //学校天峰值
  625. scMonthCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateMonth}");
  626. }
  627. catch { }
  628. if (scDayCnt != null && scDayCnt.Length > 0)
  629. {
  630. List<HourLoginSchool> hourLoginSchools = new();
  631. foreach (var scDCnt in scDayCnt)
  632. {
  633. if (((int)scDCnt.Element) == currentHour)
  634. {
  635. var tmpHour = await table.QueryWhereString<HourLoginSchool>($"PartitionKey eq 'HourLogin-{school}' and RowKey eq '{dateHour}'");
  636. if (tmpHour.Count > 0)
  637. {
  638. foreach (var hLoginSc in tmpHour)
  639. {
  640. if (scope.Equals("teacher"))
  641. hLoginSc.Teacher = (int)scDCnt.Score;
  642. else if (scope.Equals("student"))
  643. hLoginSc.Student = (int)scDCnt.Score;
  644. else
  645. hLoginSc.TmdUser = (int)scDCnt.Score;
  646. hourLoginSchools.Add(hLoginSc);
  647. }
  648. }
  649. else
  650. {
  651. //学校小时峰值
  652. HourLoginSchool hourLoginSc = new() { PartitionKey = $"HourLogin-{school}", RowKey = dateHour, Hour = currentHour, School = school };
  653. if (scope.Equals("teacher"))
  654. {
  655. hourLoginSc.Teacher = 1;
  656. hourLoginSc.Student = 0;
  657. hourLoginSc.TmdUser = 0;
  658. }
  659. else if (scope.Equals("student"))
  660. {
  661. hourLoginSc.Teacher = 0;
  662. hourLoginSc.Student = 1;
  663. hourLoginSc.TmdUser = 0;
  664. }
  665. else
  666. {
  667. hourLoginSc.Teacher = 0;
  668. hourLoginSc.Student = 0;
  669. hourLoginSc.TmdUser = 1;
  670. }
  671. hourLoginSchools.Add(hourLoginSc);
  672. }
  673. }
  674. }
  675. await table.SaveOrUpdateAll(hourLoginSchools);
  676. }
  677. if (scMonthCnt != null && scMonthCnt.Length > 0)
  678. {
  679. List<DayLoginSchool> DayLoginSchools = new();
  680. foreach (var scMCnt in scMonthCnt)
  681. {
  682. if (((int)scMCnt.Element) == currentDay)
  683. {
  684. var tempDays = await table.QueryWhereString<DayLoginSchool>($"PartitionKey eq 'DayLogin-{school}' and RowKey eq '{dateDay}'");
  685. if (tempDays.Count > 0)
  686. {
  687. foreach (var dLoginSc in tempDays)
  688. {
  689. if (scope.Equals("teacher"))
  690. dLoginSc.Teacher = (int)scMCnt.Score;
  691. else if (scope.Equals("student"))
  692. dLoginSc.Student = (int)scMCnt.Score;
  693. else
  694. dLoginSc.TmdUser = (int)scMCnt.Score;
  695. DayLoginSchools.Add(dLoginSc);
  696. }
  697. }
  698. else
  699. {
  700. //学校天峰值
  701. DayLoginSchool dayLoginSc = new() { PartitionKey = $"DayLogin-{school}", RowKey = dateDay, Day = currentDay, School = school };
  702. if (scope.Equals("teacher"))
  703. {
  704. dayLoginSc.Teacher = 1;
  705. dayLoginSc.Student = 0;
  706. dayLoginSc.TmdUser = 0;
  707. }
  708. else if (scope.Equals("student"))
  709. {
  710. dayLoginSc.Teacher = 0;
  711. dayLoginSc.Student = 1;
  712. dayLoginSc.TmdUser = 0;
  713. }
  714. else
  715. {
  716. dayLoginSc.Teacher = 0;
  717. dayLoginSc.Student = 0;
  718. dayLoginSc.TmdUser = 1;
  719. }
  720. DayLoginSchools.Add(dayLoginSc);
  721. }
  722. }
  723. }
  724. await table.SaveOrUpdateAll(DayLoginSchools);//保存学校当月在线数据
  725. }
  726. string tbScHourSql = $"PartitionKey eq 'HourLogin-{school}' and RowKey le '{delTbHour}'";
  727. List<HourLogin> scHourLog = await table.QueryWhereString<HourLogin>(tbScHourSql);
  728. if (scHourLog.Count > 0)
  729. try
  730. {
  731. //await table.DeleteStringWhere<HourLogin>(tbScHourSql); //删除学校168小时前的数据
  732. await table.DeleteAll(scHourLog);
  733. }
  734. catch { }
  735. string tbScDaySql = $"PartitionKey eq 'DayLogin-{school}' and RowKey le '{delTbDay}'";
  736. List<DayLogin> scDayLog = await table.QueryWhereString<DayLogin>(tbScDaySql);
  737. if (scDayLog.Count > 0)
  738. try
  739. {
  740. //await table.DeleteStringWhere<DayLogin>(tbScDaySql); //删除学校180天前的数据
  741. await table.DeleteAll(scDayLog);
  742. }
  743. catch { }
  744. }
  745. await response.WriteAsJsonAsync(new { data = json });
  746. return response;
  747. }
  748. catch (Exception ex)
  749. {
  750. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-online-record 人数记录异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  751. await response.WriteAsJsonAsync(new { data = json });
  752. return response;
  753. }
  754. }
  755. }
  756. }