BIHttpTrigger.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Dynamic;
  4. using System.IO;
  5. using System.Net;
  6. using System.Net.Http;
  7. using System.Text.Json;
  8. using System.Threading.Tasks;
  9. using Azure.Cosmos;
  10. using Azure.Storage.Blobs;
  11. using DocumentFormat.OpenXml.Bibliography;
  12. using Microsoft.AspNetCore.Http;
  13. using Microsoft.Azure.Functions.Worker;
  14. using Microsoft.Azure.Functions.Worker.Http;
  15. using NUnit.Framework.Constraints;
  16. using StackExchange.Redis;
  17. using TEAMModelOS.SDK.DI;
  18. using TEAMModelOS.SDK.Extension;
  19. using TEAMModelOS.SDK.Models;
  20. using TEAMModelOS.SDK.Models.Cosmos.BI;
  21. using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
  22. using TEAMModelOS.SDK.Models.Service.BI;
  23. using TEAMModelOS.SDK.Models.Service.BIStatsWay;
  24. namespace TEAMModelOS.FunctionV4.HttpTrigger
  25. {
  26. public class BIHttpTrigger
  27. {
  28. private readonly AzureCosmosFactory _azureCosmos;
  29. private readonly DingDing _dingDing;
  30. private readonly AzureStorageFactory _azureStorage;
  31. private readonly AzureRedisFactory _azureRedis;
  32. public BIHttpTrigger(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis)
  33. {
  34. _azureCosmos = azureCosmos;
  35. _dingDing = dingDing;
  36. _azureStorage = azureStorage;
  37. _azureRedis = azureRedis;
  38. }
  39. /// <summary>
  40. /// 学校信息BI中间件更新
  41. /// </summary>
  42. /// <param name="req"></param>
  43. /// <returns></returns>
  44. [Function("set-sc-birelation")]
  45. public async Task<HttpResponseData> upSchoolBIRelation([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req)
  46. {
  47. var response = req.CreateResponse(HttpStatusCode.OK);
  48. dynamic jsondata = new ExpandoObject();
  49. try
  50. {
  51. var cosmosClient = _azureCosmos.GetCosmosClient();
  52. var tableClient = _azureStorage.GetCloudTableClient();
  53. var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
  54. string data = await new StreamReader(req.Body).ReadToEndAsync();
  55. var json = JsonDocument.Parse(data).RootElement;
  56. School school = new();
  57. jsondata = json;
  58. if (json.TryGetProperty("school", out JsonElement _school))
  59. {
  60. school = _school.ToObject<School>();
  61. }
  62. string type = "";
  63. BIRelation bIRelation = new();
  64. var resBiRel = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(school.id, new PartitionKey("BIRel"));
  65. if (resBiRel.Status == 200)
  66. {
  67. using var fileJson = await JsonDocument.ParseAsync(resBiRel.ContentStream);
  68. bIRelation = fileJson.ToObject<BIRelation>();
  69. }
  70. else
  71. bIRelation.id = school.id;
  72. string aName = null;
  73. if (!string.IsNullOrEmpty($"{school.areaId}"))
  74. aName = await CosmosQueryHelper.GetStr(cosmosClient, "Normal", $"select value(c.name) from c where c.id='{school.areaId}'", "Base-Area");
  75. bIRelation.name = school.name;
  76. bIRelation.picture = school.picture;
  77. bIRelation.region = school.region;
  78. bIRelation.province = school.province;
  79. bIRelation.city = school.city;
  80. bIRelation.dist = school.dist;
  81. bIRelation.address = school.address;
  82. bIRelation.areaId = school.areaId;
  83. bIRelation.size = school.size;
  84. bIRelation.scale = school.scale;
  85. bIRelation.upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  86. bIRelation.areaName = aName;
  87. if (resBiRel.Status == 200)
  88. {
  89. await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<BIRelation>(bIRelation, bIRelation.id, new PartitionKey("BIRel"));
  90. type = "update";
  91. }
  92. else
  93. {
  94. await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<BIRelation>(bIRelation, new PartitionKey("BIRel"));
  95. type = "add";
  96. }
  97. //保存操作记录
  98. await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, $"birelation-{type}", $"触发更新学校信息表中间件", _dingDing);
  99. }
  100. catch (Exception ex)
  101. {
  102. await _dingDing.SendBotMsg($"stats-sc-info,{ex.Message}\n{ex.StackTrace}\n{jsondata.ToJsonString()}", GroupNames.成都开发測試群組);
  103. }
  104. return response;
  105. }
  106. /// <summary>
  107. /// 统计学校的信息
  108. /// </summary>
  109. /// <param name="req"></param>
  110. /// <returns></returns>
  111. [Function("stats-sc-info")]
  112. public async Task<HttpResponseData> StatsSchoolInfo([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req)
  113. {
  114. var response = req.CreateResponse(HttpStatusCode.OK);
  115. dynamic jsondata = new ExpandoObject();
  116. try
  117. {
  118. string scId = null;
  119. var cosmosClient = _azureCosmos.GetCosmosClient();
  120. var tableClient = _azureStorage.GetCloudTableClient();
  121. var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
  122. string data = await new StreamReader(req.Body).ReadToEndAsync();
  123. var json = JsonDocument.Parse(data).RootElement;
  124. jsondata = json;
  125. if (json.TryGetProperty("schoolId", out JsonElement _schoolId))
  126. {
  127. scId = $"{_schoolId}";
  128. }
  129. if (string.IsNullOrEmpty(scId))
  130. {
  131. return response;
  132. }
  133. bool locKey = await _azureRedis.GetRedisClient(8).KeyExistsAsync($"Train:Statistics:Lock:{scId}");
  134. if (!locKey)
  135. {
  136. await _azureRedis.GetRedisClient(8).SetAddAsync($"Train:Statistics:Lock:{scId}", new RedisValue(scId));
  137. DateTime minutes = DateTime.UtcNow.AddMinutes(15); //15分钟
  138. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Train:Statistics:Lock:{scId}", minutes);
  139. bool isExist = true;
  140. StatsInfo statsInfo = new();
  141. var scDataStats = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey("Stats"));
  142. if (scDataStats.Status == 200)
  143. {
  144. using var fileJson = await JsonDocument.ParseAsync(scDataStats.ContentStream);
  145. statsInfo = fileJson.ToObject<StatsInfo>();
  146. }
  147. else
  148. isExist = false;
  149. statsInfo = await SchoolStatsWay.GetSingleSc(cosmosClient, scId);
  150. statsInfo.upTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  151. if (isExist)
  152. statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<StatsInfo>(statsInfo, statsInfo.id, new PartitionKey("Stats"));
  153. else
  154. statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<StatsInfo>(statsInfo, new PartitionKey("Stats"));
  155. }
  156. //保存操作记录
  157. await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "trigger-schoolStats", $"触发更新统计数据库", _dingDing);
  158. }
  159. catch (Exception ex)
  160. {
  161. await _dingDing.SendBotMsg($"stats-sc-info,{ex.Message}\n{ex.StackTrace}\n{jsondata.ToJsonString()}", GroupNames.成都开发測試群組);
  162. }
  163. return response;
  164. }
  165. /// <summary>
  166. /// 处理传过来的信息加入到统计信息中
  167. /// </summary>
  168. /// <param name="req"></param>
  169. /// <returns></returns>
  170. [Function("set-scstats-type")]
  171. public async Task<HttpResponseData> SetSchoolStatsType([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req)
  172. {
  173. var response = req.CreateResponse(HttpStatusCode.OK);
  174. dynamic jsondata = new ExpandoObject();
  175. try
  176. {
  177. string scId = null,type = null;
  178. var cosmosClient = _azureCosmos.GetCosmosClient();
  179. var tableClient = _azureStorage.GetCloudTableClient();
  180. var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
  181. string data = await new StreamReader(req.Body).ReadToEndAsync();
  182. var json = JsonDocument.Parse(data).RootElement;
  183. jsondata = json;
  184. long careDate = 0;
  185. int cnt = 0;
  186. DateTimeOffset dateOff = DateTimeOffset.UtcNow;
  187. if (!json.TryGetProperty("scId", out JsonElement _schoolId))
  188. {
  189. scId = $"{_schoolId}";
  190. }
  191. if (!json.TryGetProperty("type", out JsonElement _type))
  192. {
  193. type = $"{_type}";
  194. }
  195. if (string.IsNullOrEmpty(scId) && string.IsNullOrEmpty(type))
  196. {
  197. await _dingDing.SendBotMsg($"set-scstats-type, {req.Body};转换后:{json}", GroupNames.成都开发測試群組);
  198. return response;
  199. }
  200. if (!json.TryGetProperty("cnt", out JsonElement _cnt))
  201. {
  202. cnt = int.Parse($"{_cnt}");
  203. }
  204. if (!json.TryGetProperty("date", out JsonElement _date))
  205. {
  206. careDate = long.Parse($"{_date}");
  207. }
  208. else
  209. {
  210. careDate = dateOff.ToUnixTimeMilliseconds();
  211. }
  212. long currDay = dateOff.ToUnixTimeMilliseconds();
  213. var (lastDays, lastDaye) = TimeHelper.GetStartOrEnd(dateOff.AddDays(-1));//昨天开始/结束时间
  214. var (DayS, DayE) = TimeHelper.GetStartOrEnd(dateOff); //今天开始时间结束时间
  215. var (lastWeekS, lastWeekE) = TimeHelper.GetStartOrEnd(dateOff, "lastweek"); //计算上周开始/结束时间
  216. var (weekS, weekE) = TimeHelper.GetStartOrEnd(dateOff, "week"); //计算本周开始/结束时间
  217. var (lastTermS, lastTermE) = TimeHelper.GetStartOrEnd(dateOff, "lastterm"); //计算上学期开始/结束时间
  218. var (termS, termE) = TimeHelper.GetStartOrEnd(dateOff, "term"); //计算本学期开始/结束时间
  219. var (lastYearS, lastYearE) = TimeHelper.GetStartOrEnd(dateOff, "lastYear"); //计算去年开始/结束时间
  220. var (yearS, yearE) = TimeHelper.GetStartOrEnd(dateOff, "year"); //计算今年开始/结束时间
  221. StatsInfo statsInfo = new();
  222. var resStsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(scId, new PartitionKey("BIRel"));
  223. if (resStsInfo.Status == 200)
  224. {
  225. using var fileJson = await JsonDocument.ParseAsync(resStsInfo.ContentStream);
  226. statsInfo = fileJson.ToObject<StatsInfo>();
  227. }
  228. else
  229. {
  230. ScBase scBase = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<ScBase>(scId, new PartitionKey("Base"));
  231. statsInfo.id = scBase.id;
  232. statsInfo.name = scBase.name;
  233. statsInfo.picture = scBase.picture;
  234. statsInfo.size = scBase.size;
  235. statsInfo.scCreateTime = scBase.createTime;
  236. statsInfo.areaId = scBase.areaId;
  237. statsInfo.upTime = currDay;
  238. }
  239. switch ($"{type}")
  240. {
  241. case "Exam":
  242. if (statsInfo.upTime < DayS && statsInfo.upTime >= lastDays)
  243. {
  244. statsInfo.activity.lastDay = statsInfo.activity.dayCnt;
  245. statsInfo.activity.year[dateOff.DayOfYear-1] += statsInfo.activity.dayCnt;
  246. }
  247. if (DayS <= statsInfo.upTime && statsInfo.upTime <= DayE)
  248. {
  249. statsInfo.activity.dayCnt += cnt;
  250. statsInfo.activity.exam += cnt;
  251. statsInfo.activity.year[dateOff.DayOfYear] += cnt;
  252. }
  253. statsInfo.activity.cnt += cnt;
  254. break;
  255. case "Survey":
  256. break;
  257. case "Vote":
  258. break;
  259. case "Homework":
  260. break;
  261. case "Less":
  262. break;
  263. case "stu":
  264. break;
  265. case "tch":
  266. break;
  267. }
  268. }
  269. catch (Exception ex)
  270. {
  271. await _dingDing.SendBotMsg($"set-scstats-type,{ex.Message}\n{ex.StackTrace}\n{jsondata.ToJsonString()}", GroupNames.成都开发測試群組);
  272. }
  273. return response;
  274. }
  275. }
  276. }