OnLineController.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  1. using Microsoft.Azure.Cosmos;
  2. using Azure.Storage.Blobs;
  3. using Azure.Storage.Blobs.Models;
  4. using Microsoft.AspNetCore.Http;
  5. using Microsoft.AspNetCore.Mvc;
  6. using StackExchange.Redis;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.Data.SqlTypes;
  10. using System.IO;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Text.Json;
  14. using System.Threading.Tasks;
  15. using TEAMModelBI.Tool;
  16. using TEAMModelOS.SDK.Context.BI;
  17. using TEAMModelOS.SDK.Context.Constant;
  18. using TEAMModelOS.SDK.DI;
  19. using TEAMModelOS.SDK.Extension;
  20. using TEAMModelOS.SDK.Models;
  21. using TEAMModelOS.SDK.Models.Cosmos.BI;
  22. using TEAMModelOS.SDK.Models.Service.BI;
  23. using TEAMModelOS.SDK.Models.Table;
  24. namespace TEAMModelBI.Controllers.BIHome
  25. {
  26. [Route("online")]
  27. [ApiController]
  28. public class OnLineController : ControllerBase
  29. {
  30. private readonly AzureCosmosFactory _azureCosmos;
  31. private readonly AzureStorageFactory _azureStorage;
  32. private readonly AzureRedisFactory _azureRedis;
  33. public OnLineController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis)
  34. {
  35. _azureCosmos = azureCosmos;
  36. _azureStorage = azureStorage;
  37. _azureRedis = azureRedis;
  38. }
  39. /// <summary>
  40. /// 总数统计 //已对接
  41. /// </summary>
  42. /// <returns></returns>
  43. [ProducesDefaultResponseType]
  44. [HttpPost("get-count")]
  45. public async Task<IActionResult> GetCount(JsonElement jsonElement)
  46. {
  47. var cosmosClient = _azureCosmos.GetCosmosClient();
  48. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin");
  49. var blobClient = _azureStorage.GetBlobContainerClient($"0-public");
  50. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  51. //if ($"{site}".Equals(BIConst.Global))
  52. //{
  53. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  54. // table = _azureStorage.GetCloudTableClient(BIConst.Global).GetTableReference("IESLogin");
  55. // blobClient = _azureStorage.GetBlobContainerClient($"0-public", BIConst.Global);
  56. //}
  57. DateTimeOffset dateTime = DateTimeOffset.UtcNow;
  58. string cDay = dateTime.ToString("yyyyMMdd");
  59. var (daySt, dayEt) = TimeHelper.GetStartOrEnd(dateTime); //今天开始时间 13位
  60. var (daySf, dayEf) = TimeHelper.GetStartOrEnd(dateTime, dateLenth: false); //今天开始时间 10位
  61. var (lastDayS, lastdayE) = TimeHelper.GetStartOrEnd(dateTime.AddDays(-1)); //昨天开始时间
  62. var near7S = dateTime.AddDays(-7).ToUnixTimeMilliseconds(); //前七天的开始时间
  63. var near7E = dateTime.ToUnixTimeMilliseconds(); //当前结束时间
  64. long hour1 = dateTime.AddHours(-1).ToUnixTimeMilliseconds(); //一小时前时间戳
  65. int areaCnt = 0; //学区总数
  66. int scCnt = 0; //学校总数
  67. int tchCnt = 0; //教师总数
  68. int stuCnt = 0; //学生总数
  69. int apiCnt = 0; //当天接口访问总量
  70. int onStuCnt = 0; //学生在线人数
  71. int onTchCnt = 0; //教师在线人数
  72. int todayScCnt = 0; //今日新增学校数
  73. int todayTchCnt = 0; //今日新增教师
  74. int todayStuCnt = 0; //今日新增学生数
  75. long datetime = dateTime.ToUnixTimeMilliseconds();
  76. string currentSql = "select value(count(c.id)) from c";
  77. areaCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Normal", currentSql, "Base-Area");
  78. scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", currentSql, "Base");
  79. tchCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", currentSql, "Base");
  80. stuCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Student", "select value(count(c.id)) from c where c.pk='Base'");
  81. string addSql = $"select value(count(c.id)) from c where c.createTime >={daySt} and c.createTime <= {dayEt}";
  82. todayScCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", addSql, "Base");
  83. todayTchCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", addSql, "Base");
  84. todayStuCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Student", addSql, "Base");
  85. //string onStuSql = $"select value(count(c.id)) from c join t in c.loginInfos where array_length(c.loginInfos) > 0 and t.expire > {hour1} and c.pk='Base'";
  86. //onTchCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", onStuSql);
  87. //onStuCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Student", onStuSql);
  88. #region 取得在線人數
  89. var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
  90. var redisClinet = _azureRedis.GetRedisClient(8);
  91. var (strDaySt, strDayEt) = TimeHelper.GetUnixToDate(daySt, dayEt, "yyyyMMddHH");
  92. Dictionary<long, int> allDays = new(); //所有在线人数
  93. Dictionary<long, int> tchDays = new(); //教师在线人数
  94. Dictionary<long, int> stuDays = new(); //学生在线人数
  95. Dictionary<long, int> tmdDays = new(); //醍摩豆账户学生
  96. int tchkey = 0;// 最近時間的key
  97. // 撈redis記錄的教師在線人數
  98. SortedSetEntry[] tchDay = redisClinet.SortedSetRangeByScoreWithScores($"Login:IES:teacher:{dateDay}");
  99. if (tchDay.Length > 0)// 如果redis有資料就直接使用
  100. {
  101. foreach (var item in tchDay)
  102. {
  103. int val = ((int)item.Score);
  104. int key = ((int)item.Element);
  105. tchDays.Add(key, val);
  106. }
  107. var tchDaysOrderBy = tchDays.OrderBy(o => o.Key).ToList();
  108. tchkey = (int)tchDaysOrderBy[tchDaysOrderBy.Count - 1].Key;
  109. onTchCnt = (int)tchDaysOrderBy[tchDaysOrderBy.Count - 1].Value;
  110. }
  111. else
  112. {// 如果redis沒資料去Azure Storage取
  113. string tableSqlTch = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'";
  114. List<HourLogin> hourLoginsTch = await table.QueryWhereString<HourLogin>(tableSqlTch);
  115. if (hourLoginsTch.Count > 0)
  116. {
  117. foreach (var item in hourLoginsTch)
  118. {
  119. tchDays.Add(item.Hour, item.Teacher);
  120. }
  121. var tchDaysOrderBy = tchDays.OrderBy(o => o.Key).ToList();
  122. tchkey = (int)tchDaysOrderBy[tchDaysOrderBy.Count - 1].Key;
  123. onTchCnt = (int)tchDaysOrderBy[tchDaysOrderBy.Count - 1].Value;
  124. }
  125. }
  126. // 撈redis記錄的學生在線人數
  127. SortedSetEntry[] stuDay = redisClinet.SortedSetRangeByScoreWithScores($"Login:IES:student:{dateDay}");
  128. if (stuDay.Length > 0)// 如果redis有資料就直接使用
  129. {
  130. foreach (var item in stuDay)
  131. {
  132. int val = ((int)item.Score);
  133. int key = ((int)item.Element);
  134. stuDays.Add(key, val);
  135. }
  136. var stuDaysOrderBy = stuDays.OrderBy(o => o.Key).ToList();
  137. onStuCnt = (int)stuDaysOrderBy[stuDaysOrderBy.Count - 1].Value;
  138. }
  139. else
  140. {// 如果redis沒資料去Azure Storage取
  141. string tableSqlStu = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'";
  142. List<HourLogin> hourLoginsStu = await table.QueryWhereString<HourLogin>(tableSqlStu);
  143. if (hourLoginsStu.Count > 0)
  144. {
  145. foreach (var item in hourLoginsStu)
  146. {
  147. stuDays.Add(item.Hour, item.Student);
  148. }
  149. var stuDaysOrderBy = stuDays.OrderBy(o => o.Key).ToList();
  150. onStuCnt = (int)stuDaysOrderBy[stuDaysOrderBy.Count - 1].Value;
  151. }
  152. }
  153. SortedSetEntry[] tmdDay = redisClinet.SortedSetRangeByScoreWithScores($"Login:IES:tmduser:{dateDay}");
  154. if (tmdDay.Length > 0)
  155. {
  156. foreach (var item in tmdDay)
  157. {
  158. int val = (int)item.Score;
  159. int key = (int)item.Element;
  160. tmdDays.Add(key, val);
  161. }
  162. int iValue = 0;
  163. if (tmdDays.TryGetValue(tchkey, out iValue))
  164. {
  165. onStuCnt = onStuCnt + tmdDays[tchkey]; // 用最近時間的key取在線醍摩豆账户学生數
  166. }
  167. }
  168. else
  169. {
  170. string tableSqlTmd = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'";
  171. List<HourLogin> hourLoginsTmd = await table.QueryWhereString<HourLogin>(tableSqlTmd);
  172. if (hourLoginsTmd.Count > 0)
  173. {
  174. foreach (var item in hourLoginsTmd)
  175. {
  176. var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, item.Hour, 00, 00)).Hour;
  177. tmdDays.Add(utcTo, item.TmdUser);
  178. }
  179. int iValue = 0;
  180. if (tmdDays.TryGetValue(tchkey, out iValue))
  181. {
  182. onStuCnt = onStuCnt + tmdDays[tchkey]; // 用最近時間的key取在線醍摩豆账户学生數
  183. }
  184. }
  185. }
  186. #endregion
  187. //接口访问量
  188. List<RecCnt> recCnts = new();
  189. await foreach (BlobItem blobItem in blobClient.GetBlobsAsync(BlobTraits.None, BlobStates.None, $"visitCnt/{cDay}"))
  190. {
  191. if (blobItem.Name.EndsWith(".json") && !blobItem.Name.EndsWith("/days.json"))
  192. {
  193. BlobClient tempBlobClient = blobClient.GetBlobClient(blobItem.Name);
  194. if (await tempBlobClient.ExistsAsync())
  195. {
  196. using (var meomoryStream = new MemoryStream())
  197. {
  198. var response = blobClient.GetBlobClient($"{blobItem.Name}").DownloadTo(meomoryStream);
  199. RecCnt recCnt = Encoding.UTF8.GetString(meomoryStream.ToArray()).ToString().ToObject<RecCnt>();
  200. recCnts.Add(recCnt);
  201. }
  202. }
  203. }
  204. }
  205. apiCnt = recCnts.Select(x => x.apiCnt.Select(s => s.count).Sum()).Sum();
  206. string yymmss = TimeHelper.GetDateTime(datetime).ToString();
  207. return Ok(new { state = 200, yymmss, datetime, areaCnt, scCnt, tchCnt, stuCnt, todayScCnt, todayTchCnt, todayStuCnt, onStuCnt, onTchCnt, apiCnt });
  208. }
  209. /// <summary>
  210. /// 在线人数趋势图 //已对接
  211. /// </summary>
  212. /// <returns></returns>
  213. [ProducesDefaultResponseType]
  214. [HttpPost("get-trend")]
  215. public async Task<IActionResult> GetTrend(JsonElement jsonElement)
  216. {
  217. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin");
  218. var redisClinet = _azureRedis.GetRedisClient(8);
  219. //jsonElement.TryGetProperty("site", out JsonElement site); //分开部署,就不需要,一站多用时,取消注释
  220. //if ($"{site}".Equals(BIConst.Global))
  221. //{
  222. // table = _azureStorage.GetCloudTableClient(BIConst.Global).GetTableReference("IESLogin");
  223. // redisClinet = _azureRedis.GetRedisClient(dbnum: 8, name: BIConst.Global);
  224. //}
  225. DateTimeOffset dateTime = DateTimeOffset.UtcNow;
  226. var (daySt, dayEt) = TimeHelper.GetStartOrEnd(dateTime); //今天开始时间 13位
  227. var (strDaySt, strDayEt) = TimeHelper.GetUnixToDate(daySt, dayEt, "yyyyMMddHH");
  228. var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
  229. //daySt.ToString("yyyyMMddHH");
  230. Dictionary<long, int> allDays = new(); //所有在线人数
  231. Dictionary<long, int> tchDays = new(); //教师在线人数
  232. Dictionary<long, int> stuDays = new(); //学生在线人数
  233. Dictionary<long, int> tmdDays = new(); //醍摩豆账户学生
  234. SortedSetEntry[] tchDay = redisClinet.SortedSetRangeByScoreWithScores($"Login:IES:teacher:{dateDay}");
  235. if (tchDay.Length > 0)
  236. {
  237. foreach (var item in tchDay)
  238. {
  239. int val = ((int)item.Score);
  240. int key = ((int)item.Element);
  241. //var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, key, 0, 0)).Hour;
  242. //var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH"));
  243. tchDays.Add(key, val);
  244. if (allDays.ContainsKey(key))
  245. allDays[key] = (allDays[key] + val);
  246. else
  247. allDays.Add(key, val);
  248. }
  249. }
  250. else
  251. {
  252. string tableSqlTch = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'";
  253. List<HourLogin> hourLoginsTch = await table.QueryWhereString<HourLogin>(tableSqlTch);
  254. if (hourLoginsTch.Count > 0)
  255. {
  256. foreach (var item in hourLoginsTch)
  257. {
  258. await redisClinet.SortedSetIncrementAsync($"Login:IES:teacher:{dateDay}", $"{item.Hour}", item.Teacher);//存一天24小时
  259. tchDays.Add(item.Hour, item.Teacher);
  260. if (allDays.ContainsKey(item.Hour))
  261. allDays[item.Hour] = (allDays[item.Hour] + item.Teacher);
  262. else
  263. allDays.Add(item.Hour, item.Teacher);
  264. }
  265. }
  266. }
  267. SortedSetEntry[] stuDay = redisClinet.SortedSetRangeByScoreWithScores($"Login:IES:student:{dateDay}");
  268. if (stuDay.Length > 0)
  269. {
  270. foreach (var item in stuDay)
  271. {
  272. int val = (int)item.Score;
  273. int key = (int)item.Element;
  274. stuDays.Add(key, val);
  275. if (allDays.ContainsKey(key))
  276. allDays[key] = (allDays[key] + val);
  277. else
  278. allDays.Add(key, val);
  279. }
  280. }
  281. else
  282. {
  283. string tableSqlStu = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'";
  284. List<HourLogin> hourLoginsStu = await table.QueryWhereString<HourLogin>(tableSqlStu);
  285. //var hourStuCnt = hourLoginsStu.GroupBy(x => x.Hour).Select(k => new { key = int.Parse(k.Key.ToString().Substring(8, 2)), value = k.Count() }).ToList();
  286. if (hourLoginsStu.Count > 0)
  287. {
  288. foreach (var item in hourLoginsStu)
  289. {
  290. await redisClinet.SortedSetIncrementAsync($"Login:IES:student:{dateDay}", $"{item.Hour}", item.Student);//存一天24小时
  291. stuDays.Add(item.Hour, item.Student);
  292. if (allDays.ContainsKey(item.Hour))
  293. allDays[item.Hour] = (allDays[item.Hour] + item.Student);
  294. else
  295. allDays.Add(item.Hour, item.Student);
  296. }
  297. }
  298. }
  299. SortedSetEntry[] tmdDay = redisClinet.SortedSetRangeByScoreWithScores($"Login:IES:tmduser:{dateDay}");
  300. if (tmdDay.Length > 0)
  301. {
  302. foreach (var item in tmdDay)
  303. {
  304. int val = (int)item.Score;
  305. int key = (int)item.Element;
  306. tmdDays.Add(key, val);
  307. if (allDays.ContainsKey(key))
  308. allDays[key] = (allDays[key] + val);
  309. else
  310. allDays.Add(key, val);
  311. }
  312. }
  313. else
  314. {
  315. string tableSqlTmd = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'";
  316. List<HourLogin> hourLoginsTmd = await table.QueryWhereString<HourLogin>(tableSqlTmd);
  317. //var hourTmdCnt = hourLoginsTmd.GroupBy(x => x.Hour).Select(k => new { key = int.Parse(k.Key.ToString().Substring(8, 2)), value = k.Count() }).ToList();
  318. if (hourLoginsTmd.Count > 0)
  319. {
  320. foreach (var item in hourLoginsTmd)
  321. {
  322. await redisClinet.SortedSetIncrementAsync($"Login:IES:tmduser:{dateDay}", $"{item.Hour}", item.TmdUser);//存一天24小时
  323. var utcTo = new DateTimeOffset(new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, item.Hour, 00, 00)).Hour;
  324. tmdDays.Add(utcTo, item.TmdUser);
  325. if (allDays.ContainsKey(utcTo))
  326. allDays[utcTo] = (allDays[utcTo] + item.TmdUser);
  327. else
  328. allDays.Add(utcTo, item.TmdUser);
  329. }
  330. }
  331. }
  332. return Ok(new { state = 200,allDays = allDays.OrderBy(o=>o.Key).ToList(), tchDays=tchDays.OrderBy(o => o.Key).ToList(), stuDays= stuDays.OrderBy(o => o.Key).ToList(), tmdDays= tmdDays.OrderBy(o => o.Key).ToList() });
  333. }
  334. /// <summary>
  335. /// 课例趋势图 //已对接
  336. /// </summary>
  337. /// <returns></returns>
  338. [ProducesDefaultResponseType]
  339. [HttpPost("get-lessontrend")]
  340. public async Task<IActionResult> GetLessonTrend(JsonElement jsonElement)
  341. {
  342. DateTimeOffset dateTime = DateTimeOffset.UtcNow;
  343. var cosmosClient = _azureCosmos.GetCosmosClient();
  344. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  345. //if ($"{site}".Equals(BIConst.Global))
  346. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  347. int year = dateTime.Year; //当前年
  348. int month = dateTime.Month; //当前月
  349. int day = dateTime.Day; //当天
  350. var lestDate = dateTime.AddDays(-1); //昨天
  351. int hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {dateTime.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH")); //当前小时
  352. var (daySt, dayEt) = TimeHelper.GetStartOrEnd(dateTime); //今天开始时间 13位
  353. var (lastDayS, lastdayE) = TimeHelper.GetStartOrEnd(lestDate); //昨天开始时间
  354. var (monthDayS, monthDayE) = TimeHelper.GetStartOrEnd(lestDate, "monthDay"); //本月开始/结束时间
  355. var (yearS, yearE) = TimeHelper.GetStartOrEnd(lestDate, "yearMonth"); //本月开始/结束时间
  356. Dictionary<int, int> sdOpenLesn = new(); //今日开课
  357. Dictionary<int, int> sdUpdLesn = new(); //今日上传课例
  358. Dictionary<int, int> ydOpenLesn = new(); //昨日开课
  359. Dictionary<int, int> ydUpdLesn = new(); //昨日上传课例
  360. Dictionary<int, int> mthOpenLesn = new(); //本月开课
  361. Dictionary<int, int> mthUpdLesn = new(); //本月上传课例
  362. Dictionary<int, int> yrOpenLesn = new(); //本年开课
  363. Dictionary<int, int> yrUpdLesn = new(); //本年上传课例
  364. Dictionary<int, int> allOpenLesn = new(); //所有年开课
  365. Dictionary<int, int> allUpdLesn = new(); //所有年上传课例
  366. List<RecLesn> yearLeson = new();
  367. List<RecLesn> allLess = new();
  368. string allSql = "select c.id,c.name,c.code,c.school,c.scope,c.startTime from c where c.pk='LessonRecord'";
  369. //所有的课例
  370. allLess = await CommonFind.GetObject<RecLesn>(cosmosClient, new List<string>() { "School", "Teacher" }, allSql);
  371. if (allLess.Count > 0)
  372. {
  373. for (int i = 0; i < 24; i++)
  374. {
  375. if (hour >= i)
  376. {
  377. DateTimeOffset timeHour = new DateTime(year, month, day, i, 0, 0);
  378. var (hourS, hourE) = TimeHelper.GetStartOrEnd(timeHour, type: "hour");
  379. var openLesn1 = allLess.Where(item => item.startTime >= hourS && item.startTime <= hourE && item.upload == 0).Count();
  380. var openLesn = allLess.Where(item => item.startTime >= hourS && item.startTime <= hourE && item.upload == 0).ToList();
  381. sdOpenLesn.Add(i, openLesn.Count());
  382. var UpdLesn = allLess.Where(item => item.startTime >= hourS && item.startTime <= hourE && item.upload == 1).ToList();
  383. sdUpdLesn.Add(i, UpdLesn.Count());
  384. }
  385. DateTimeOffset yesterday = new DateTime(lestDate.Year, lestDate.Month, lestDate.Day, i, 0, 0);
  386. var (yHourS, yHourE) = TimeHelper.GetStartOrEnd(yesterday, type: "hour");
  387. var yOpenLesn = allLess.Where(item => item.startTime >= yHourS && item.startTime <= yHourE && item.upload == 0).ToList();
  388. ydOpenLesn.Add(i, yOpenLesn.Count);
  389. var yUpdLesn = allLess.Where(item => item.startTime >= yHourS && item.startTime <= yHourE && item.upload == 1).ToList();
  390. ydUpdLesn.Add(i, yUpdLesn.Count);
  391. }
  392. for (int i = 1; i <= day; i++)
  393. {
  394. DateTimeOffset timeDay = new DateTime(year, month, i, 0, 0, 0);
  395. var (dayS, dayE) = TimeHelper.GetStartOrEnd(timeDay); //本月开始/结束时间
  396. var openLesn = allLess.Where(item => item.startTime >= dayS && item.startTime <= dayE && item.upload == 0).ToList();
  397. mthOpenLesn.Add(i, openLesn.Count());
  398. var UpdLesn = allLess.Where(item => item.startTime >= dayS && item.startTime <= dayE && item.upload == 1).ToList();
  399. mthUpdLesn.Add(i, UpdLesn.Count());
  400. }
  401. for (int i = 1; i <= month; i++)
  402. {
  403. DateTimeOffset timeDay = DateTimeOffset.UtcNow;
  404. if (i == 2)
  405. {
  406. int tempDay = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? tempDay = 29 : tempDay = 28;
  407. timeDay = new DateTime(year, i, tempDay, 0, 0, 0);
  408. }
  409. else
  410. {
  411. timeDay = new DateTime(year, i, 1, 0, 0, 0);
  412. }
  413. var (monthS, monthE) = TimeHelper.GetStartOrEnd(timeDay, "month"); //本月开始/结束时间
  414. var openLesn = allLess.Where(item => item.startTime >= monthS && item.startTime <= monthE && item.upload == 0).ToList();
  415. yrOpenLesn.Add(i, openLesn.Count());
  416. var UpdLesn = allLess.Where(item => item.startTime >= monthS && item.startTime <= monthE && item.upload == 1).ToList();
  417. yrUpdLesn.Add(i, UpdLesn.Count());
  418. }
  419. yearLeson = allLess.Select(item => { item.startTime = TimeHelper.GetDateTime(item.startTime).Year; return item; }).ToList();
  420. List<RecLesn> oRecLess = yearLeson.Where(o => o.upload == 0).ToList();
  421. var allo = oRecLess.GroupBy(g => g.startTime).Select(s => new { key = s.Key, value = s.Count() }).ToList();
  422. if (allo.Count > 0)
  423. allo.ForEach(a => { allOpenLesn.Add((int)a.key, a.value); });
  424. List<RecLesn> uRecLesns = yearLeson.Where(o => o.upload == 1).ToList();
  425. var allu = uRecLesns.GroupBy(g => g.startTime).Select(s => new { key = s.Key, value = s.Count() }).ToList();
  426. if (allu.Count > 0)
  427. allu.ForEach(a => { allUpdLesn.Add((int)a.key, a.value); });
  428. }
  429. return Ok(new
  430. {
  431. state = RespondCode.Ok,
  432. hours = new { sdOpenLesn = sdOpenLesn.ToList(), sdUpdLesn = sdUpdLesn.ToList(), ydOpenLesn = ydOpenLesn.ToList(), ydUpdLesn = ydUpdLesn.ToList() },
  433. days = new { sdOpenLesn = mthOpenLesn.ToList(), sdUpdLesn = mthUpdLesn.ToList() },
  434. months = new { sdOpenLesn = yrOpenLesn.ToList(), sdUpdLesn = yrUpdLesn.ToList() },
  435. years = new { sdOpenLesn = allOpenLesn.ToList(), sdUpdLesn = allUpdLesn.ToList() }
  436. }) ;
  437. }
  438. /// <summary>
  439. /// 版本数量占比 //已对接
  440. /// </summary>
  441. /// <returns></returns>
  442. [ProducesDefaultResponseType]
  443. [HttpPost("get-edition")]
  444. public async Task<IActionResult> GetEdition(JsonElement jsonElement)
  445. {
  446. var cosmosClient = _azureCosmos.GetCosmosClient();
  447. //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
  448. //if ($"{site}".Equals(BIConst.Global))
  449. // cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
  450. int beCnt = 0; //基础班
  451. int seCnt = 0; //标准版
  452. int peCnt = 0; //专业版
  453. int cuCnt = 0; //自訂版
  454. List<RecScEd> scEdCnt = new();
  455. var ScSql = $"select c.id,c.name,c.size,c.scale, c.edition, c.service from c";
  456. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIteratorSql<RecScEd>(queryText: ScSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("BIRel") }))
  457. {
  458. scEdCnt.Add(item);
  459. }
  460. await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIteratorSql<RecScEd>(queryText: ScSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("VirtualBase") }))
  461. {
  462. scEdCnt.Add(item);
  463. }
  464. foreach (var item in scEdCnt)
  465. {
  466. bool isHaveScaleVersion = false;
  467. if (item.edition != null)
  468. {
  469. if (!string.IsNullOrWhiteSpace(item.edition.scaleVersion))
  470. {
  471. isHaveScaleVersion = true;
  472. }
  473. }
  474. // ※版本判定:1.學校管理(IPDYZYLC) + 學情分析(YMPCVCIM)=「標準版」
  475. // 2.學校管理(IPDYZYLC) + 學情分析(YMPCVCIM) + 五育看板(YPXSJ6NJ) =「專業版」
  476. bool isIP = item.service.Exists(t => t == "IPDYZYLC");
  477. bool isYM = item.service.Exists(t => t == "YMPCVCIM");
  478. bool isYP = item.service.Exists(t => t == "YPXSJ6NJ");
  479. if (isHaveScaleVersion)
  480. { // 自訂版
  481. cuCnt += 1;
  482. }
  483. else if (isIP && isYM && isYP)
  484. { // 專業版
  485. peCnt += 1;
  486. }
  487. else if (isIP && isYM && !isYP)
  488. { // 標準版
  489. seCnt += 1;
  490. }
  491. else
  492. { // 基礎版
  493. beCnt += 1;
  494. }
  495. }
  496. return Ok(new { state = 200, beCnt, seCnt, peCnt, cuCnt, scEdCnt });
  497. }
  498. /// <summary>
  499. /// 记录学校版本信息
  500. /// </summary>
  501. public record RecScEd
  502. {
  503. public string id { get; set; }
  504. public string name { get; set; }
  505. public int size { get; set; }
  506. public int scale { get; set; }
  507. public List<string> serial { get; set; } = new List<string>();//软体
  508. public List<string> service { get; set; } = new List<string>(); //服务
  509. public List<string> hard { get; set; } = new List<string>(); //硬体
  510. public Edition edition { get; set; }
  511. }
  512. /// <summary>
  513. /// 记录课例
  514. /// </summary>
  515. public record RecLesn
  516. {
  517. public string id { get; set; }
  518. public string name { get; set; }
  519. public string code { get; set; }
  520. public string school { get; set; }
  521. public string scope{get;set;}
  522. public long startTime { get; set; }
  523. public int upload { get; set; }
  524. }
  525. }
  526. }