BILeesonService.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. using Microsoft.Azure.Cosmos;
  2. using StackExchange.Redis;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Text.Json;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using TEAMModelOS.SDK.DI;
  11. using TEAMModelOS.SDK.Extension;
  12. using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
  13. using TEAMModelOS.SDK.Models.Cosmos.BI.BITable;
  14. namespace TEAMModelOS.SDK.Models.Service.BI
  15. {
  16. public class BILeesonService
  17. {
  18. /// <summary>
  19. /// 通过时间戳保存开课记录和课例记录统计
  20. /// 统计数据存储在CosmosDB表中
  21. /// </summary>
  22. /// <param name="cosmosClient">cosmosDB连接</param>
  23. /// <param name="_azureRedis">redis</param>
  24. /// <param name="_dingDing">错误消息发送</param>
  25. /// <param name="unix">13位时间戳</param>
  26. /// <param name="num">数量</param>
  27. /// <param name="type">类型:0 开课记录 1 课例记录</param>
  28. /// <param name="schoolId">学校编码</param>
  29. /// <returns></returns>
  30. public static async Task SetCosmosDBStats(CosmosClient cosmosClient, AzureRedisFactory _azureRedis, DingDing _dingDing, long unix, int num = 1, int type = 0, string schoolId = null)
  31. {
  32. try
  33. {
  34. DateTimeOffset dateTime = DateTimeOffset.FromUnixTimeMilliseconds(unix);
  35. int year, month, day, hour, days;
  36. year = dateTime.Year;
  37. month = dateTime.Month;
  38. day = dateTime.Day;
  39. hour = dateTime.Hour;
  40. days = dateTime.DayOfYear;
  41. var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
  42. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  43. DateTime expireDay = DateTime.UtcNow.AddDays(8); //8天后到期
  44. DateTime expireYear = DateTime.UtcNow.AddDays(396); //一年后到期
  45. var redisClient = _azureRedis.GetRedisClient(8);
  46. string LessType = "Open";
  47. if (type == 1)
  48. LessType = "Lesson";
  49. await redisClient.SortedSetIncrementAsync($"BIStats:Less:All:{LessType}:{dateDay}", $"{hour}", num);//一天24小时课例数 有上传 base.josn 小时为单位
  50. await redisClient.SortedSetIncrementAsync($"BIStats:Less:All:{LessType}:{year}", $"{days}", num);//一年的课例数量 有上传 base.josn 小时为单位
  51. var expDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:All:{LessType}:{dateDay}");
  52. if (expDay == null)
  53. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:All:{LessType}:{dateDay}", expireDay); //设置八天后到期
  54. var expYear = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:All:{LessType}:{year}");
  55. if (expYear == null)
  56. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:All:{LessType}:{year}", expireYear); //设置一年后到期
  57. //保存当天的统计 小时
  58. var dayCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:All:{LessType}:{dateDay}");
  59. if (dayCnt != null && dayCnt.Length > 0)
  60. {
  61. double[] daHour = new double[23];
  62. foreach (var item in dayCnt)
  63. {
  64. double val = ((double)item.Score);
  65. int key = ((int)item.Element);
  66. daHour[key] = val;
  67. }
  68. List<double> lessHours = new(daHour);
  69. var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{dateDay}", new PartitionKey("LessonHour"));
  70. if (lessRes.StatusCode == System.Net.HttpStatusCode.OK)
  71. {
  72. using var json = await JsonDocument.ParseAsync(lessRes.Content);
  73. LessonStats lessonStats = json.ToObject<LessonStats>();
  74. lessonStats.code = "LessonHour";
  75. lessonStats.pk = "LessonHour";
  76. if (type == 1)
  77. lessonStats.lesson = lessHours;
  78. else
  79. lessonStats.open = lessHours;
  80. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonStats, lessonStats.id, new PartitionKey("LessonHour"));
  81. }
  82. else
  83. {
  84. LessonStats lessonStats = new();
  85. lessonStats.id = $"{dateDay}";
  86. lessonStats.code = "LessonHour";
  87. lessonStats.pk = "LessonHour";
  88. if (type == 1)
  89. lessonStats.lesson = lessHours;
  90. else
  91. lessonStats.open = lessHours;
  92. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(lessonStats, new PartitionKey("LessonHour"));
  93. }
  94. }
  95. //保一年的统计 天
  96. var yearCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:All:{LessType}:{year}");
  97. if (yearCnt != null && yearCnt.Length > 0)
  98. {
  99. double[] daYear = new double[yearDays];
  100. foreach (var item in yearCnt)
  101. {
  102. double val = ((double)item.Score);
  103. int key = ((int)item.Element);
  104. daYear[key] = val;
  105. }
  106. List<double> lessYear = new(daYear);
  107. var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{year}", new PartitionKey("LessonYear"));
  108. if (lessRes.StatusCode == System.Net.HttpStatusCode.OK)
  109. {
  110. using var json = await JsonDocument.ParseAsync(lessRes.Content);
  111. LessonStats lessonYear = json.ToObject<LessonStats>();
  112. lessonYear.code = "LessonYear";
  113. lessonYear.pk = "LessonYear";
  114. if (type == 1)
  115. lessonYear.lesson = lessYear;
  116. else
  117. lessonYear.open = lessYear;
  118. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonYear, lessonYear.id, new PartitionKey("LessonYear"));
  119. }
  120. else
  121. {
  122. LessonStats lessonYear = new();
  123. lessonYear.id = $"{year}";
  124. lessonYear.code = "LessonYear";
  125. lessonYear.pk = "LessonYear";
  126. if (type == 1)
  127. lessonYear.lesson = lessYear;
  128. else
  129. lessonYear.open = lessYear;
  130. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(lessonYear, new PartitionKey("LessonYear"));
  131. }
  132. }
  133. if (!string.IsNullOrEmpty(schoolId))
  134. {
  135. await redisClient.SortedSetIncrementAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}", $"{hour}", num);//一天24小时课例数 有上传 base.josn 小时为单位
  136. await redisClient.SortedSetIncrementAsync($"BIStats:Less:{schoolId}:{LessType}:{year}", $"{days}", num);//一年的课例数量 有上传 base.josn 小时为单位
  137. var scExpDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}");
  138. if (scExpDay == null)
  139. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}", expireDay); //设置八天后到期
  140. var scExpYear = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:{schoolId}:{LessType}:{year}");
  141. if (scExpYear == null)
  142. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:{schoolId}:{LessType}:{year}", expireYear); //设置一年后到期
  143. //保存当天的统计 小时
  144. var dayScCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:{schoolId}:{LessType}:{dateDay}");
  145. if (dayScCnt != null && dayScCnt.Length > 0)
  146. {
  147. double[] daHour = new double[23];
  148. foreach (var item in dayScCnt)
  149. {
  150. double val = ((double)item.Score);
  151. int key = ((int)item.Element);
  152. daHour[key] = val;
  153. }
  154. List<double> lessHours = new(daHour);
  155. var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{dateDay}", new PartitionKey($"LessonHour-{schoolId}"));
  156. if (lessRes.StatusCode == System.Net.HttpStatusCode.OK)
  157. {
  158. using var json = await JsonDocument.ParseAsync(lessRes.Content);
  159. LessonStats lessonStats = json.ToObject<LessonStats>();
  160. lessonStats.code = $"LessonHour-{schoolId}";
  161. lessonStats.pk = "LessonHour";
  162. if (type == 1)
  163. lessonStats.lesson = lessHours;
  164. else
  165. lessonStats.open = lessHours;
  166. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonStats, lessonStats.id, new PartitionKey($"LessonHour-{schoolId}"));
  167. }
  168. else
  169. {
  170. LessonStats lessonStats = new();
  171. lessonStats.id = $"{dateDay}";
  172. lessonStats.code = $"LessonHour-{schoolId}";
  173. lessonStats.pk = "LessonHour";
  174. if (type == 1)
  175. lessonStats.lesson = lessHours;
  176. else
  177. lessonStats.open = lessHours;
  178. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(lessonStats, new PartitionKey($"LessonHour-{schoolId}"));
  179. }
  180. }
  181. //保一年的统计 天
  182. var scYearCnt = redisClient.SortedSetRangeByScoreWithScores($"BILesson:{schoolId}:{LessType}:{year}");
  183. if (scYearCnt != null && scYearCnt.Length > 0)
  184. {
  185. double[] daYear = new double[yearDays];
  186. foreach (var item in scYearCnt)
  187. {
  188. double val = ((double)item.Score);
  189. int key = ((int)item.Element);
  190. daYear[key] = val;
  191. }
  192. List<double> lessYear = new(daYear);
  193. var lessRes = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync($"{year}", new PartitionKey($"LessonYear-{schoolId}"));
  194. if (lessRes.StatusCode == System.Net.HttpStatusCode.OK)
  195. {
  196. using var json = await JsonDocument.ParseAsync(lessRes.Content);
  197. LessonStats lessonYear = json.ToObject<LessonStats>();
  198. lessonYear.code = $"LessonYear-{schoolId}";
  199. lessonYear.pk = "LessonYear";
  200. if (type == 1)
  201. lessonYear.lesson = lessYear;
  202. else
  203. lessonYear.open = lessYear;
  204. await cosmosClient.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<LessonStats>(lessonYear, lessonYear.id, new PartitionKey($"LessonYear-{schoolId}"));
  205. }
  206. else
  207. {
  208. LessonStats lessonYear = new();
  209. lessonYear.id = $"{year}";
  210. lessonYear.code = $"LessonYear-{schoolId}";
  211. lessonYear.pk = "LessonYear";
  212. if (type == 1)
  213. lessonYear.lesson = lessYear;
  214. else
  215. lessonYear.open = lessYear;
  216. await cosmosClient.GetContainer("TEAMModelOS", "School").CreateItemAsync<LessonStats>(lessonYear, new PartitionKey($"LessonYear-{schoolId}"));
  217. }
  218. }
  219. }
  220. }
  221. catch (Exception ex)
  222. {
  223. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-SetBICosmosDBStats 课例统计异常 {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  224. }
  225. }
  226. /// <summary>
  227. /// 通过时间戳保存开课记录和课例记录统计
  228. /// 统计数据存储在table表中
  229. /// </summary>
  230. /// <param name="_azureStorage">table连接池</param>
  231. /// <param name="_azureRedis">redis连接池</param>
  232. /// <param name="_dingDing">错误消息发送</param>
  233. /// <param name="unix">13位时间戳</param>
  234. /// <param name="num">数量</param>
  235. /// <param name="type">类型:0 开课记录 1 课例记录</param>
  236. /// <param name="scope">范围(默认学校范围):学校 school 个人 private</param>
  237. /// <param name="schoolId">学校编码</param>
  238. /// <returns></returns>
  239. public static async Task SetTableStats(AzureStorageFactory _azureStorage, AzureRedisFactory _azureRedis, DingDing _dingDing, long unix, int num = 1, int type = 0,string scope = "private", string schoolId = null)
  240. {
  241. try
  242. {
  243. //SemaphoreSlim slimlock = new(1, 1); //对可同时访问资源或资源池的线程数加以限制 结束
  244. //await slimlock.WaitAsync();
  245. Monitor.TryEnter(unix); //锁对象
  246. DateTimeOffset dateTime = DateTimeOffset.FromUnixTimeMilliseconds(unix);
  247. int year, month, day, hour, days;
  248. year = dateTime.Year;
  249. month = dateTime.Month;
  250. day = dateTime.Day;
  251. hour = dateTime.Hour;
  252. days = dateTime.DayOfYear;
  253. var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
  254. var yearDays = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? 366 : 365;
  255. var table = _azureStorage.GetCloudTableClient().GetTableReference("BIStats");
  256. var redisClient = _azureRedis.GetRedisClient(8);
  257. DateTime expireDay = DateTime.UtcNow.AddDays(8); //8天后到期
  258. DateTime expireYear = DateTime.UtcNow.AddDays(396); //一年后到期
  259. ////保存当天的统计 小时
  260. //SortedSetEntry[] dayCnt = null;
  261. ////保一年的统计 天
  262. //SortedSetEntry[] yearCnt = null;
  263. string LessType = "Open";
  264. if (type == 1)
  265. LessType = "Lesson";
  266. try
  267. {
  268. await redisClient.SortedSetIncrementAsync($"BIStats:Less:All:{LessType}:{dateDay}", $"{hour}", num);//一天24小时课例数 有上传 base.josn 小时为单位
  269. await redisClient.SortedSetIncrementAsync($"BIStats:Less:All:{LessType}:{year}", $"{days}", num);//一年的课例数量 有上传 base.josn 小时为单位
  270. var expDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:All:{LessType}:{dateDay}");
  271. if (expDay == null)
  272. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:All:{LessType}:{dateDay}", expireDay); //设置八天后到期
  273. var expYear = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:All:{LessType}:{year}");
  274. if (expYear == null)
  275. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:All:{LessType}:{year}", expireYear); //设置一年后到期
  276. ////保存当天的统计 小时
  277. //dayCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:All:{LessType}:{dateDay}");
  278. ////保一年的统计 天
  279. //yearCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:All:{LessType}:{year}");
  280. }
  281. catch { }
  282. double[] daHour = new double[23];
  283. daHour[hour] = num;
  284. string hourStats = string.Join(',', daHour);
  285. double[] daYear = new double[yearDays];
  286. daYear[hour] = num;
  287. string yearStats = string.Join(',', daYear);
  288. LessStats lessHour = table.Get<LessStats>("LessonHour", $"{dateDay}");
  289. if (lessHour != null)
  290. {
  291. if (type == 1)
  292. {
  293. if (lessHour.lesson != null)
  294. {
  295. double[] tempLess = Array.ConvertAll<string, double>(lessHour.lesson.Split(','), s => double.Parse(s));
  296. tempLess[hour] = tempLess[hour] + num;
  297. string strLess = string.Join(',', tempLess);
  298. lessHour.lesson = strLess;
  299. }
  300. else
  301. lessHour.lesson = hourStats;
  302. }
  303. else
  304. {
  305. if (lessHour.open != null)
  306. {
  307. double[] tempOpen = Array.ConvertAll<string, double>(lessHour.open.Split(','), s => double.Parse(s));
  308. tempOpen[hour] = tempOpen[hour] + num;
  309. string sOpen = string.Join(',', tempOpen);
  310. lessHour.open = sOpen;
  311. }
  312. else
  313. lessHour.open = hourStats;
  314. }
  315. }
  316. else
  317. {
  318. lessHour = new() { PartitionKey = "LessonHour", RowKey = $"{dateDay}" };
  319. if (type == 1)
  320. lessHour.lesson = hourStats;
  321. else
  322. lessHour.open = hourStats;
  323. }
  324. await table.SaveOrUpdate<LessStats>(lessHour);
  325. LessStats lessYear = table.Get<LessStats>("LessonYear", $"{year}");
  326. if (lessYear != null)
  327. {
  328. if (type == 1)
  329. {
  330. if (lessYear.lesson != null)
  331. {
  332. double[] tempLess = Array.ConvertAll<string, double>(lessYear.lesson.Split(','), s => double.Parse(s));
  333. tempLess[days] = tempLess[days] + num;
  334. string sLess = string.Join(',', tempLess);
  335. lessYear.lesson = sLess;
  336. }
  337. else
  338. lessYear.lesson = yearStats;
  339. }
  340. else
  341. {
  342. if (lessYear.open != null)
  343. {
  344. double[] tempOpen = Array.ConvertAll<string, double>(lessYear.open.Split(','), s => double.Parse(s));
  345. tempOpen[days] = tempOpen[days] + num;
  346. string sOpen = string.Join(',', tempOpen);
  347. lessYear.open = sOpen;
  348. }
  349. else
  350. lessYear.open = yearStats;
  351. }
  352. }
  353. else
  354. {
  355. lessYear = new() { PartitionKey = "LessonYear", RowKey = $"{year}" };
  356. if (type == 1)
  357. lessYear.lesson = yearStats;
  358. else
  359. lessYear.open = yearStats;
  360. }
  361. try
  362. {
  363. await table.SaveOrUpdate<LessStats>(lessYear);
  364. }
  365. catch { }
  366. //保存学校课例数据
  367. if (!string.IsNullOrEmpty(schoolId) && scope.Equals("school"))
  368. {
  369. ////保存学校当天的统计 小时
  370. //SortedSetEntry[] dayScCnt = null;
  371. ////保学校一年的统计 天
  372. //SortedSetEntry[] scYearCnt = null;
  373. try
  374. {
  375. await redisClient.SortedSetIncrementAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}", $"{hour}", num);//一天24小时课例数 有上传 base.josn 小时为单位
  376. await redisClient.SortedSetIncrementAsync($"BIStats:Less:{schoolId}:{LessType}:{year}", $"{days}", num);//一年的课例数量 有上传 base.josn 小时为单位
  377. var scExpDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}");
  378. if (scExpDay == null)
  379. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:{schoolId}:{LessType}:{dateDay}", expireDay); //设置八天后到期
  380. var scExpYear = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"BIStats:Less:{schoolId}:{LessType}:{year}");
  381. if (scExpYear == null)
  382. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"BIStats:Less:{schoolId}:{LessType}:{year}", expireYear); //设置一年后到期
  383. ////保存学校当天的统计 小时
  384. //dayScCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:{schoolId}:{LessType}:{dateDay}");
  385. ////保学校一年的统计 天
  386. //scYearCnt = redisClient.SortedSetRangeByScoreWithScores($"BIStats:Less:{schoolId}:{LessType}:{year}");
  387. }catch { }
  388. double[] daScHour = new double[23];
  389. daScHour[hour] = num;
  390. string hourScStats = string.Join(',', daScHour);
  391. double[] daScYear = new double[yearDays];
  392. daScYear[hour] = num;
  393. string strYearSc = string.Join(',', daScYear);
  394. LessStats lessScHour = table.Get<LessStats>("LessonHour", $"{dateDay}-{schoolId}");
  395. if (lessScHour != null)
  396. {
  397. if (type == 1)
  398. {
  399. if (lessScHour.lesson != null)
  400. {
  401. double[] tempLess = Array.ConvertAll<string, double>(lessScHour.lesson.Split(','), s => double.Parse(s));
  402. tempLess[hour] = tempLess[hour] + num;
  403. string strLess = string.Join(',', tempLess);
  404. lessScHour.lesson = strLess;
  405. }
  406. else
  407. lessScHour.lesson = hourScStats;
  408. }
  409. else
  410. {
  411. if (lessScHour.open != null)
  412. {
  413. double[] tempOpen = Array.ConvertAll<string, double>(lessScHour.open.Split(','), s => double.Parse(s));
  414. tempOpen[hour] = tempOpen[hour] + num;
  415. string sOpen = string.Join(',', tempOpen);
  416. lessScHour.open = sOpen;
  417. }
  418. else
  419. lessScHour.open = hourScStats;
  420. }
  421. }
  422. else
  423. {
  424. lessScHour = new() { PartitionKey = "LessonHour", RowKey = $"{dateDay}-{schoolId}" };
  425. if (type == 1)
  426. lessScHour.lesson = hourScStats;
  427. else
  428. lessScHour.open = hourScStats;
  429. }
  430. try
  431. {
  432. await table.SaveOrUpdate<LessStats>(lessScHour);
  433. }
  434. catch { }
  435. LessStats lessScYear = table.Get<LessStats>("LessonYear", $"{year}-{schoolId}");
  436. if (lessScYear != null)
  437. {
  438. if (type == 1)
  439. {
  440. if (lessScYear.lesson != null)
  441. {
  442. double[] tempLess = Array.ConvertAll<string, double>(lessScYear.lesson.Split(','), s => double.Parse(s));
  443. tempLess[days] = tempLess[days] + num;
  444. string sLess = string.Join(',', tempLess);
  445. lessScYear.lesson = sLess;
  446. }
  447. else
  448. lessScYear.lesson = strYearSc;
  449. }
  450. else
  451. {
  452. if (lessScYear.open != null)
  453. {
  454. double[] tempOpen = Array.ConvertAll<string, double>(lessScYear.open.Split(','), s => double.Parse(s));
  455. tempOpen[days] = tempOpen[days] + num;
  456. string sOpen = string.Join(',', tempOpen);
  457. lessScYear.open = sOpen;
  458. }
  459. else
  460. lessScYear.open = strYearSc;
  461. }
  462. }
  463. else
  464. {
  465. lessScYear = new() { PartitionKey = "LessonYear", RowKey = $"{year}" };
  466. if (type == 1)
  467. lessScYear.lesson = strYearSc;
  468. else
  469. lessScYear.open = strYearSc;
  470. }
  471. try
  472. {
  473. await table.SaveOrUpdate<LessStats>(lessScYear);
  474. }
  475. catch { }
  476. //if (dayScCnt != null && dayScCnt.Length > 0)
  477. //{
  478. // double[] daHourSc = new double[23];
  479. // foreach (var item in dayScCnt)
  480. // {
  481. // double val = ((double)item.Score);
  482. // int key = ((int)item.Element);
  483. // daHourSc[key] = val;
  484. // }
  485. // string hoursStatsSc = string.Join(",", daHourSc);
  486. // LessStats lessStatsSc = table.Get<LessStats>("LessonHour", $"{dateDay}-{schoolId}");
  487. // if (lessStatsSc != null)
  488. // {
  489. // if (type == 1)
  490. // lessStatsSc.lesson = hoursStatsSc;
  491. // else
  492. // lessStatsSc.open = hoursStatsSc;
  493. // }
  494. // else
  495. // {
  496. // lessStatsSc = new() { PartitionKey = "LessonHour", RowKey = $"{dateDay}-{schoolId}" };
  497. // if (type == 1)
  498. // lessStatsSc.lesson = hoursStatsSc;
  499. // else
  500. // lessStatsSc.open = hoursStatsSc;
  501. // lessStatsSc.time = dateDay;
  502. // lessStatsSc.school = schoolId;
  503. // }
  504. // try
  505. // {
  506. // await table.SaveOrUpdate<LessStats>(lessStatsSc);
  507. // }
  508. // catch { }
  509. //}
  510. //if (scYearCnt != null && scYearCnt.Length > 0)
  511. //{
  512. // double[] daYearSc = new double[yearDays];
  513. // foreach (var item in scYearCnt)
  514. // {
  515. // double val = ((double)item.Score);
  516. // int key = ((int)item.Element);
  517. // daYearSc[key] = val;
  518. // }
  519. // string tempStatsSc = string.Join(",", daYearSc);
  520. // LessStats lessStatsSc = table.Get<LessStats>("LessonYear", $"{year}-{schoolId}");
  521. // if (lessStatsSc != null)
  522. // {
  523. // if (type == 1)
  524. // lessStatsSc.lesson = tempStatsSc;
  525. // else
  526. // lessStatsSc.open = tempStatsSc;
  527. // }
  528. // else
  529. // {
  530. // lessStatsSc = new() { PartitionKey = "LessonYear", RowKey = $"{year}-{schoolId}" };
  531. // if (type == 1)
  532. // lessStatsSc.lesson = tempStatsSc;
  533. // else
  534. // lessStatsSc.open = tempStatsSc;
  535. // lessStatsSc.time = $"{year}";
  536. // lessStatsSc.school = schoolId;
  537. // }
  538. // try
  539. // {
  540. // await table.SaveOrUpdate<LessStats>(lessStatsSc);
  541. // }
  542. // catch { }
  543. //}
  544. }
  545. Monitor.Enter(unix); //锁对象 结束
  546. //slimlock.Release(); // 对可同时访问资源或资源池的线程数加以限制 结束
  547. }
  548. catch (Exception ex)
  549. {
  550. await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-SetBITableStats BI记录课例统计数据异常!参数:{unix}|{num}|{type}|{scope}|{schoolId} ;错误信息:{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  551. }
  552. }
  553. }
  554. }