using Azure.Cosmos; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Threading.Tasks; using TEAMModelBI.Tool; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK.Models; using TEAMModelOS.SDK.Models.Table; namespace TEAMModelBI.Controllers.BIHome { [Route("online")] [ApiController] public class OnLineController : ControllerBase { private readonly AzureCosmosFactory _azureCosmos; private readonly AzureStorageFactory _azureStorage; private readonly AzureRedisFactory _azureRedis; public OnLineController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis) { _azureCosmos = azureCosmos; _azureStorage = azureStorage; _azureRedis = azureRedis; } /// /// 总数统计 /// /// [HttpPost("get-count")] public async Task GetCount() { var cosmosClient = _azureCosmos.GetCosmosClient(); var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin"); DateTimeOffset dateTime = DateTimeOffset.UtcNow; var (daySt, dayEt) = TimeHelper.GetStartOrEnd(dateTime); //今天开始时间 13位 var (daySf, dayEf) = TimeHelper.GetStartOrEnd(dateTime, dateLenth: false); //今天开始时间 10位 var (lastDayS, lastdayE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year}-{dateTime.Month}-{dateTime.Day - 1}")); //昨天开始时间 var near7S = dateTime.AddDays(-7).ToUnixTimeMilliseconds(); //前七天的开始时间 var near7E = dateTime.ToUnixTimeMilliseconds(); //当前结束时间 long hour1 = dateTime.AddHours(-1).ToUnixTimeMilliseconds(); //一小时前时间戳 int areaCnt = 0; //学区总数 int scCnt = 0; //学校总数 int tchCnt = 0; //教师总数 int stuCnt = 0; //学生总数 int onStuCnt = 0; //学生在线人数 int onTchCnt = 0; //教师在线人数 int todayScCnt = 0; //今日新增学校数 int todayTchCnt = 0; //今日新增教师 int todayStuCnt = 0; //今日新增学生数 string currentSql = "select value(count(c.id)) from c"; areaCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Normal", currentSql, "Base-Area"); scCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", currentSql, "Base"); tchCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", currentSql, "Base"); stuCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Student", "select value(count(c.id)) from c where c.pk='Base'"); string addSql = $"select value(count(c.id)) from c where c.pk='Base' and c.createTime >={daySf} and c.createTime <= {dayEf}"; todayScCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", addSql, "Base"); todayTchCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", addSql, "Base"); todayStuCnt = await CommonFind.GetSqlValueCount(cosmosClient, "Student", addSql, "Base"); List recStuOnLines = new(); await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Student").GetItemQueryIterator(queryText: "select c.id,c.name,c.code,c.loginInfos from c where c.pk='Base' and array_length(c.loginInfos) > 0 ", requestOptions:new QueryRequestOptions() { })) { recStuOnLines.Add(item); } List recTecOnLines = new(); await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator(queryText: "select c.id,c.name,c.code,c.loginInfos from c where array_length(c.loginInfos) > 0 ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") })) { recTecOnLines.Add(item); } //onStuCnt = (from rs in recStuOnLines from l in rs.loginInfos where l.expire >= hour1 select rs).ToList().Count(); //linq查询 学生在线人数 onStuCnt = recStuOnLines.Select(rss => new RecOnLine { id = rss.id,code=rss.code, name =rss.name,loginInfos = new List { rss.loginInfos.Find(f => f.expire >= hour1) } }).Where(w => w.loginInfos.FirstOrDefault() != null).ToList().Count(); //lambda 表达式查询 教师查询人数 //onTchCnt = (from rs in recTecOnLines from l in rs.loginInfos where l.expire >= hour1 select rs).ToList().Count(); //linq查询 教师查询人数 onTchCnt = recTecOnLines.Select(rss => new RecOnLine { id = rss.id,code=rss.code, name =rss.name,loginInfos = new List { rss.loginInfos.Find(f => f.expire >= hour1) } }).Where(w => w.loginInfos.FirstOrDefault() != null).ToList().Count(); //lambda 表达式查询 教师查询人数 return Ok(new { state = 200, areaCnt, scCnt, tchCnt, stuCnt, todayScCnt, todayTchCnt, todayStuCnt, onStuCnt, onTchCnt}); } /// /// 在线人数趋势图 /// /// [HttpPost("get-trend")] public async Task GetTrend() { var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin"); DateTimeOffset dateTime = DateTimeOffset.UtcNow; var (daySt, dayEt) = TimeHelper.GetStartOrEnd(dateTime); //今天开始时间 13位 var (strDaySt, strDayEt) = TimeHelper.GetUnixToDate(daySt, dayEt, "yyyyMMddHH"); var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期 daySt.ToString("yyyyMMddHH"); Dictionary allDays = new(); //所有在线人数 Dictionary tchDays = new(); //教师在线人数 Dictionary stuDays = new(); //学生在线人数 Dictionary tmdDays = new(); //醍摩豆账户学生 SortedSetEntry[] tchDay = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:teacher:{dateDay}"); if (tchDay.Length > 0) { foreach (var item in tchDay) { int val = ((int)item.Score); int key = ((int)item.Element); var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH")); tchDays.Add(hour, val); if (allDays.ContainsKey(hour)) allDays[hour] = (allDays[hour] + val); else allDays.Add(hour, val); } } else { string tableSqlTch = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'"; List hourLoginsTch = await table.QueryWhereString(tableSqlTch); if (hourLoginsTch.Count > 0) { foreach (var item in hourLoginsTch) { await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:teacher:{dateDay}", $"{item.Hour}", item.Teacher);//存一天24小时 var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH")); tchDays.Add(hour, item.Teacher); if (allDays.ContainsKey(hour)) allDays[hour] = (allDays[hour] + item.Teacher); else allDays.Add(hour, item.Teacher); } } } SortedSetEntry[] stuDay = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:student:{dateDay}"); if (stuDay.Length > 0) { foreach (var item in stuDay) { int val = (int)item.Score; int key = (int)item.Element; var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH")); stuDays.Add(hour, val); if (allDays.ContainsKey(hour)) allDays[hour] = (allDays[hour] + val); else allDays.Add(hour, val); } } else { string tableSqlStu = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'"; List hourLoginsStu = await table.QueryWhereString(tableSqlStu); //var hourStuCnt = hourLoginsStu.GroupBy(x => x.Hour).Select(k => new { key = int.Parse(k.Key.ToString().Substring(8, 2)), value = k.Count() }).ToList(); if (hourLoginsStu.Count > 0) { foreach (var item in hourLoginsStu) { await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:student:{dateDay}", $"{item.Hour}", item.Student);//存一天24小时 var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH")); stuDays.Add(hour, item.Student); if (allDays.ContainsKey(hour)) allDays[hour] = (allDays[hour] + item.Student); else allDays.Add(hour, item.Student); } } } SortedSetEntry[] tmdDay = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:tmduser:{dateDay}"); if (tmdDay.Length > 0) { foreach (var item in stuDay) { int val = (int)item.Score; int key = (int)item.Element; var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {key}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH")); tmdDays.Add(hour, val); if (allDays.ContainsKey(hour)) allDays[hour] = (allDays[hour] + val); else allDays.Add(hour, val); } } else { string tableSqlTmd = $"PartitionKey eq 'HourLogin' and RowKey ge '{strDaySt}' and RowKey le '{strDayEt}'"; List hourLoginsTmd = await table.QueryWhereString(tableSqlTmd); //var hourTmdCnt = hourLoginsTmd.GroupBy(x => x.Hour).Select(k => new { key = int.Parse(k.Key.ToString().Substring(8, 2)), value = k.Count() }).ToList(); if (hourLoginsTmd.Count > 0) { foreach (var item in hourLoginsTmd) { await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:tmduser:{dateDay}", $"{item.Hour}", item.TmdUser);//存一天24小时 var hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {item.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH")); tmdDays.Add(hour, item.TmdUser); if (allDays.ContainsKey(hour)) allDays[hour] = (allDays[hour] + item.TmdUser); else allDays.Add(hour, item.TmdUser); } } } 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() }); } /// /// 课例趋势图 /// /// [HttpPost("get-lessontrend")] public async Task GetLessonTrend() { DateTimeOffset dateTime = DateTimeOffset.UtcNow; var cosmosClient = _azureCosmos.GetCosmosClient(); int year = dateTime.Year; //当前年 int month = dateTime.Month; //当前月 int day = dateTime.Day; //当天 int hour = int.Parse(DateTime.SpecifyKind(Convert.ToDateTime($"{dateTime.Year}/{dateTime.Month}/{ dateTime.Day} {dateTime.Hour}:00:00"), DateTimeKind.Utc).ToLocalTime().ToString("HH")); //当前小时 Dictionary scLessCnt = new(); //学校课例 Dictionary tchLessCnt = new(); //教师课例 Dictionary yesterdayCnt = new(); //昨天24小时课例 var (daySt, dayEt) = TimeHelper.GetStartOrEnd(dateTime); //今天开始时间 13位 var (lastDayS, lastdayE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year}-{dateTime.Month}-{dateTime.Day - 1}")); //昨天开始时间 List scRecLesn = new(); //学校课例 List tchRecLesn = new(); //个人课例 List allRecLesn = new(); //昨天所有课例 string lesnSql = $"select c.id,c.name,c.code,c.school,c.scope,c.startTime from c where c.pk='LessonRecord' and c.startTime >={daySt} and c.startTime <= {dayEt}"; await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator(queryText: lesnSql, requestOptions: new QueryRequestOptions() { })) { scRecLesn.Add(item); } await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator(queryText: lesnSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("LessonRecord") })) { tchRecLesn.Add(item); } string allLesnSql = $"select c.id,c.name,c.code,c.school,c.scope,c.startTime from c where c.pk='LessonRecord' and c.startTime >={lastDayS} and c.startTime <= {lastdayE}"; await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator(queryText: allLesnSql, requestOptions: new QueryRequestOptions() { })) { allRecLesn.Add(item); } await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator(queryText: allLesnSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("LessonRecord") })) { allRecLesn.Add(item); } for (int i = 0; i < 24; i++) { if (hour >= i) { DateTimeOffset timeHour = new DateTime(year, month, day, i, 0, 0); var (hourS, hourE) = TimeHelper.GetStartOrEnd(timeHour, type: "hour"); var scLesn = scRecLesn.Where(item => item.startTime >= hourS && item.startTime <= hourE).ToList(); scLessCnt.Add(i, scLesn.Count()); var tchLesn = scRecLesn.Where(item => item.startTime >= hourS && item.startTime <= hourE).ToList(); tchLessCnt.Add(i, tchLesn.Count()); } DateTimeOffset yesterday = new DateTime(year, month, day - 1, i, 0, 0); var (yHourS, yHourE) = TimeHelper.GetStartOrEnd(yesterday, type: "hour"); var allLesn = allRecLesn.Where(item => item.startTime >= yHourS && item.startTime <= yHourE).ToList(); yesterdayCnt.Add(i, allLesn.Count()); } ////通过循环实时查询课例统计 //for (int i = 0; i < 24; i++) //{ // if (hour >= i) // { // DateTimeOffset timeHour = new DateTime(year, month, day, i, 0, 0); // var (hourS, hourE) = TimeHelper.GetStartOrEnd(timeHour, type: "hour"); // await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator(queryText: $"select value(count(c.id)) from c where c.pk='LessonRecord' and c.startTime >={hourS} and c.startTime <= {hourE}", requestOptions: new QueryRequestOptions() { })) // { // scLessCnt.Add(i, item); // } // await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator(queryText: $"select value(count(c.id)) from c where c.startTime >={hourS} and c.startTime <= {hourE}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("LessonRecord") })) // { // tchLessCnt.Add(i, item); // } // } // DateTimeOffset yesterday = new DateTime(year, month, day - 1, i, 0, 0); // var (yHourS, yHourE) = TimeHelper.GetStartOrEnd(yesterday, type: "hour"); // string sql = $"select value(count(c.id)) from c where c.pk='LessonRecord' and c.startTime >= {yHourS} and c.startTime <= {yHourE}"; // int hourLessCnt = await CommonFind.GetSqlValueCount(cosmosClient, new List { "School", "Teacher" }, sql); // yesterdayCnt.Add(i, hourLessCnt); //} return Ok(new { state = 200, scLessCnt = scLessCnt.ToList(), tchLessCnt = tchLessCnt.ToList(), yesterdayCnt = yesterdayCnt.ToList() }); } /// /// 版本数量占比 /// /// [HttpPost("get-edition")] public async Task GetEdition() { var cosmosClient = _azureCosmos.GetCosmosClient(); List scEdCnt = new(); var ScSql = $"select c.id,c.name,c.size,c.scale from c"; await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator(queryText: ScSql, requestOptions:new QueryRequestOptions() { PartitionKey= new PartitionKey("Base")})) { scEdCnt.Add(item); } scEdCnt.ForEach(async scProductCnt => { var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(scProductCnt.id, new PartitionKey("ProductSum")); if (response.Status == 200) { using var json = await JsonDocument.ParseAsync(response.ContentStream); SchoolProductSum ScProductSum = json.ToObject(); scProductCnt.serial = ScProductSum.serial.Count(); scProductCnt.service = ScProductSum.service.Count(); scProductCnt.hard = ScProductSum.hard.Count(); } }); return Ok(new { state = 200, scEdCnt }); } /// /// 记录在线人数 /// public record RecOnLine { public string id { get; set; } public string name { get; set; } public string code { get; set; } public List loginInfos { get; set; } } /// /// 记录学校版本信息 /// public record RecScEd { public string id { get; set; } public string name { get; set; } public int size { get; set; } public int scale { get; set; } public int serial { get; set; } = 0;//软体 public int service { get; set; } = 0; //服务 public int hard { get; set; } = 0; //硬体 } /// /// 记录课例 /// public record RecLesn { public string id { get; set; } public string name { get; set; } public string code { get; set; } public string school { get; set; } public string scope{get;set;} public long startTime { get; set; } } } }