Преглед изворни кода

优化IES5登录无须等待.

Li пре 3 година
родитељ
комит
eb463ecc97

+ 25 - 13
TEAMModelBI/Controllers/BITest/Ies5TestController.cs

@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Hosting;
+using Azure.Messaging.ServiceBus;
+using Microsoft.AspNetCore.Hosting;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Configuration;
@@ -13,7 +14,9 @@ using TEAMModelBI.Tool;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.Teacher;
 using TEAMModelOS.SDK.Models.Service;
 using static TEAMModelOS.SDK.Models.Teacher;
 
@@ -26,6 +29,7 @@ namespace TEAMModelBI.Controllers.BITest
 
         private readonly AzureCosmosFactory _azureCosmos;
         private readonly AzureRedisFactory _azureRedis;
+        private readonly AzureServiceBusFactory _serviceBus;
         private readonly DingDing _dingDing;
         private readonly Option _option;
         private readonly AzureStorageFactory _azureStorage;
@@ -49,21 +53,29 @@ namespace TEAMModelBI.Controllers.BITest
         }
 
         [HttpPost("get-datetime")]
-        public async Task<IActionResult> GetDateTime() 
+        public async Task<IActionResult> GetDateTime()
         {
-           var dateHours =  DateTimeOffset.UtcNow.Hour;
-           var dateHours1 = DateTime.Now.Hour;
-           var dateHours2 = DateTimeOffset.Now.Hour;
-           var dateDays = DateTimeOffset.UtcNow.Month;
+            var dateHours = DateTimeOffset.UtcNow.Hour;
+            var dateHours1 = DateTime.Now.Hour;
+            var dateHours2 = DateTimeOffset.Now.Hour;
+            var dateDays = DateTimeOffset.UtcNow.Month;
 
-           var dateDay = DateTimeOffset.UtcNow.ToString("yyyyMMdd");
-           var dateMonth = DateTimeOffset.UtcNow.ToString("yyyyMM");
-           long expire = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds();
-           long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
+            var dateDay = DateTimeOffset.UtcNow.ToString("yyyyMMdd");
+            var dateMonth = DateTimeOffset.UtcNow.ToString("yyyyMM");
+            long expire = DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds();
+            long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
             var cosmosClient = _azureCosmos.GetCosmosClient();
-           List<LoginInfo> loginInfos = new() { new LoginInfo (){ time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),ip="172.54.81.101",expire = expire } };
-            var tets = await LoginService.DoLoginInfo(loginInfos: loginInfos, school: "hbcn", scope: "teacher", id: "1636016499", ip: "172.168.52.102", _azureRedis, _azureStorage, expire: 1);
-           return Ok(new { state = 200, dateHours, dateHours1, dateHours2, dateDay,dateDays, dateMonth, });
+
+            //在线记录
+            List<LoginInfo> loginInfos = new() { new LoginInfo() { time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), ip = "172.54.81.101", expire = expire } };
+            //var tets = await LoginService.DoLoginInfo(loginInfos: loginInfos, school: "hbcn", scope: "teacher", id: "1636016499", ip: "172.168.52.102", _azureRedis, _azureStorage, expire: 1);
+
+            OnLinRec olrec = new() { id = "1636016499", scope = Constant.ScopeTeacher, ip = "172.168.52.102", school = "hbcn", expire = 1 };
+            var messageBatchCopyFile = new ServiceBusMessage(olrec.ToJsonString());
+            messageBatchCopyFile.ApplicationProperties.Add("name", "OnLinRecord");   //Function名称
+            var onlinRecTask = _configuration.GetValue<string>("Azue:ServiceBus:OnlinRecord");
+            await _serviceBus.GetServiceBusClient().SendMessageAsync(onlinRecTask, messageBatchCopyFile);
+            return Ok(new { state = 200, dateHours, dateHours1, dateHours2, dateDay, dateDays, dateMonth, });
         }
 
         public async Task<IActionResult> GetRedisToTable(JsonElement jsonElement)

+ 383 - 5
TEAMModelOS.FunctionV4/HttpTrigger/IESHttpTrigger.cs

@@ -12,9 +12,13 @@ using System.Reflection;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
+using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.Teacher;
+using TEAMModelOS.SDK.Models.Table;
+using static TEAMModelOS.SDK.Models.Teacher;
 
 namespace TEAMModelOS.FunctionV4.HttpTrigger
 {
@@ -39,7 +43,8 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
         /// <param name="log"></param>
         /// <returns></returns>
         [Function("system-info-function")]
-        public async Task<HttpResponseData> SystemInfo([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequestData req) {
+        public async Task<HttpResponseData> SystemInfo([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequestData req)
+        {
             var response = req.CreateResponse(HttpStatusCode.OK);
             Type attr = this.GetType();
             string currentDirectory = Path.GetDirectoryName(attr.Assembly.Location);
@@ -63,7 +68,7 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
             await response.WriteAsJsonAsync(new { version, description, nowtime });
             return response;
 
-           
+
         }
         /// <summary>
         /// 数据推送接口
@@ -99,7 +104,8 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
                         items.Add(item);
                     }
 
-                    items.ForEach(item => {
+                    items.ForEach(item =>
+                    {
                         //修改知识点
                         if (!string.IsNullOrEmpty(on._new))
                         {
@@ -127,8 +133,8 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
                             {
                                 var blob = JsonDocument.Parse(blobDownloadResult.Content);
                                 itemBlob = blob.RootElement.ToObject<ItemBlob>();
-                                itemBlob.exercise.knowledge=item.knowledge;
-                                await _azureStorage.UploadFileByContainer($"{school}", itemBlob.ToJsonString(), "item", $"{item.id}/{item.id}.json", true) ;
+                                itemBlob.exercise.knowledge = item.knowledge;
+                                await _azureStorage.UploadFileByContainer($"{school}", itemBlob.ToJsonString(), "item", $"{item.id}/{item.id}.json", true);
                             }
                         }
                         catch (Exception ex)
@@ -142,5 +148,377 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
             await response.WriteAsJsonAsync(new { data = json });
             return response;
         }
+
+        /// <summary>
+        /// 在线人数记录
+        /// </summary>
+        /// <param name="msg"></param>
+        /// <returns></returns>
+        [Function("onlin-record")]
+        public async Task OnlinRecord([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req)
+        {
+            try
+            {
+                var response = req.CreateResponse(HttpStatusCode.OK);
+                string data = await new StreamReader(req.Body).ReadToEndAsync();
+                var json = JsonDocument.Parse(data).RootElement;
+
+                string school = null;
+                string scope = null;
+                string id = null;
+                string ip = null;
+                int expire = 1;
+                if (json.TryGetProperty("school", out JsonElement _school))
+                {
+                    school = _school.GetString();
+                }
+
+                if (json.TryGetProperty("scope", out JsonElement _scope))
+                {
+                    scope = _scope.GetString();
+                }
+
+                if (json.TryGetProperty("id", out JsonElement _id))
+                {
+                    id = _id.GetString();
+                }
+
+                if (json.TryGetProperty("ip", out JsonElement _ip))
+                {
+                    ip = _ip.GetString();
+                }
+
+                if (json.TryGetProperty("expire", out JsonElement _expire))
+                {
+                    expire = _expire.GetInt32();
+                }
+
+                var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin");
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+
+                DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+                var dateHour = dateTime.ToString("yyyyMMddHH"); //获取当天的小时
+                var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
+                var dateMonth = dateTime.ToString("yyyyMM");//获取当月的日期
+                var currentHour = dateTime.Hour;
+                var currentDay = dateTime.Day;
+                long Expire = dateTime.AddHours(expire).ToUnixTimeMilliseconds();  //token到期时间
+                long now = dateTime.ToUnixTimeMilliseconds();   //时间戳
+
+                DateTime hour = DateTime.UtcNow.AddHours(25);   //25小时到期
+                DateTime month = DateTime.UtcNow.AddDays(32);   //一个月到期
+
+                switch (scope)
+                {
+                    case "teacher":
+                        try
+                        {
+                            Teacher teacher = await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
+                            teacher.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
+                            await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacher, teacher.id, new PartitionKey("Base"));
+                        }
+                        catch { }
+                        break;
+                    case "student":
+                        try
+                        {
+                            Student student = await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Student>(id, new PartitionKey($"Base-{school}"));
+                            student.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
+                            await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Student>(student, student.id, new PartitionKey("Base"));
+                        }
+                        catch { }
+                        break;
+                    case "tmduser":
+                        try
+                        {
+                            TmdUser tmdUser = await cosmosClient.GetContainer("TEAMModelOS", "Student").ReadItemAsync<TmdUser>(id, new PartitionKey("Base"));
+                            tmdUser.loginInfos = new List<LoginInfo>() { new LoginInfo { expire = Expire, ip = ip, time = now } };
+                            await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<TmdUser>(tmdUser, tmdUser.id, new PartitionKey("Base"));
+                        }
+                        catch { }
+                        break;
+                }
+
+                await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateDay}", $"{currentHour}", 1);//一天24小时
+                await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateMonth}", $"{currentDay}", 1); //当天的累计
+
+                var resDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateDay}");
+                if (resDay == null)
+                {
+                    await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateDay}", hour);  //设置到期时间
+                }
+
+                var rspMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateMonth}");
+                if (rspMonth == null)
+                {
+                    await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateMonth}", month);  //设置到期时间
+                }
+
+                ////查询Redis是否有值
+                //var dayCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateDay}");
+                //List<dynamic> dayCounts = new();
+                //if (dayCnt != null && dayCnt.Length > 0)
+                //{
+                //    foreach (var hourCnt in dayCnt)
+                //    {
+                //        dayCounts.Add(new { code = hourCnt.Element.ToString(), count = (int)hourCnt.Score });
+                //    }
+                //}
+
+                //var monthCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateMonth}");
+                //List<dynamic> monthCounts = new();
+                //if (monthCnt != null && monthCnt.Length > 0)
+                //{
+                //    foreach (var mCnt in monthCnt)
+                //    {
+                //        monthCounts.Add(new { code = mCnt.Element.ToString(), count = (int)mCnt.Score });
+                //    }
+                //}
+
+                //保存当天每小时的峰值
+                List<HourLogin> hourLogins = await table.QueryWhereString<HourLogin>($"PartitionKey eq 'HourLogin' and RowKey eq '{dateHour}'");
+                if (hourLogins.Count > 0)
+                {
+                    foreach (var hourLogin in hourLogins)
+                    {
+                        //hourLogin.Hour = currentHour;
+                        if (scope.Equals("teacher"))
+                            hourLogin.Teacher += 1;
+                        else if (scope.Equals("student"))
+                            hourLogin.Student += 1;
+                        else
+                            hourLogin.TmdUser += 1;
+                    }
+
+                    try
+                    {
+                        await table.SaveOrUpdateAll(hourLogins);
+                    }
+                    catch { }
+                }
+                else
+                {
+                    HourLogin hourLogin = new() { PartitionKey = $"HourLogin", RowKey = dateHour, Hour = currentHour };
+                    if (scope.Equals("teacher"))
+                    {
+                        hourLogin.Teacher = 1;
+                        hourLogin.Student = 0;
+                        hourLogin.TmdUser = 0;
+                    }
+                    else if (scope.Equals("student"))
+                    {
+                        hourLogin.Teacher = 0;
+                        hourLogin.Student = 1;
+                        hourLogin.TmdUser = 0;
+                    }
+                    else
+                    {
+                        hourLogin.Teacher = 0;
+                        hourLogin.Student = 0;
+                        hourLogin.TmdUser = 1;
+                    }
+                    try
+                    {
+                        await table.SaveOrUpdate<HourLogin>(hourLogin);//保存在线数据
+                    }
+                    catch { }
+                }
+
+                //保存当天的峰值
+                List<DayLogin> dayLogins = await table.QueryWhereString<DayLogin>($"PartitionKey eq 'DayLogin' and RowKey eq '{dateDay}'");
+                if (dayLogins.Count > 0)
+                {
+                    foreach (var dayLogin in dayLogins)
+                    {
+                        //dayLogin.Day = currentDay;
+                        if (scope.Equals("teacher"))
+                            dayLogin.Teacher += 1;
+                        else if (scope.Equals("student"))
+                            dayLogin.Student += 1;
+                        else
+                            dayLogin.TmdUser += 1;
+                    }
+
+                    try
+                    {
+                        await table.SaveOrUpdateAll(dayLogins);
+                    }
+                    catch { }
+                }
+                else
+                {
+                    //保存当月每天的峰值
+                    DayLogin dayLogin = new() { PartitionKey = $"DayLogin", RowKey = dateDay, Day = currentDay };
+                    if (scope.Equals("teacher"))
+                    {
+                        dayLogin.Teacher = 1;
+                        dayLogin.Student = 0;
+                        dayLogin.TmdUser = 0;
+                    }
+                    else if (scope.Equals("student"))
+                    {
+                        dayLogin.Teacher = 0;
+                        dayLogin.Student = 1;
+                        dayLogin.TmdUser = 0;
+                    }
+                    else
+                    {
+                        dayLogin.Teacher = 0;
+                        dayLogin.Student = 0;
+                        dayLogin.TmdUser = 1;
+                    }
+                    try
+                    {
+                        await table.SaveOrUpdate<DayLogin>(dayLogin);//保存当月每天在线数据
+                    }
+                    catch { }
+                }
+
+                if (!string.IsNullOrWhiteSpace(school))
+                {
+                    await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateDay}", $"{currentHour}", 1);//当天当前小时在线人加1
+                    await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateMonth}", $"{currentDay}", 1); //当天的在线加1
+
+                    var reScDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateDay}");
+                    if (reScDay == null)
+                    {
+                        await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateDay}", hour);  //设置到期时间
+                    }
+
+                    var reScMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateMonth}");
+                    if (reScMonth == null)
+                    {
+                        await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateMonth}", month);  //设置到期时间
+                    }
+
+                    ////查询Redis是否有值
+                    //var scDayCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateDay}");
+                    //List<dynamic> scDayCounts = new();
+                    //if (scDayCnt != null && scDayCnt.Length > 0)
+                    //{
+                    //    foreach (var itemHour in scDayCnt)
+                    //    {
+                    //        scDayCounts.Add(new { code = itemHour.Element.ToString(), count = (int)itemHour.Score });
+                    //    }
+                    //}
+                    //var ScMonth = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateMonth}");
+                    //List<dynamic> scMonthCount = new();
+                    //if (ScMonth != null && ScMonth.Length > 0)
+                    //{
+                    //    foreach (var count in ScMonth)
+                    //    {
+                    //        scMonthCount.Add(new { code = count.Element.ToString(), count = (int)count.Score });
+                    //    }
+                    //}
+
+                    //保存学校当天每小时的
+                    List<HourLoginSchool> hourLoginSchools = await table.QueryWhereString<HourLoginSchool>($"PartitionKey eq 'HourLogin-{school}' and RowKey eq '{dateHour}'");
+                    if (hourLoginSchools.Count > 0)
+                    {
+                        foreach (var hLoginSc in hourLoginSchools)
+                        {
+                            //hLoginSc.Hour = currentHour;
+                            if (scope.Equals("teacher"))
+                                hLoginSc.Teacher += 1;
+                            else if (scope.Equals("student"))
+                                hLoginSc.Student += 1;
+                            else
+                                hLoginSc.TmdUser += 1;
+                        }
+
+                        try
+                        {
+                            await table.SaveOrUpdateAll(hourLoginSchools);
+                        }
+                        catch { }
+                    }
+                    else
+                    {
+                        //学校小时峰值
+                        HourLoginSchool hourLoginSc = new() { PartitionKey = $"HourLogin-{school}", RowKey = dateHour, Hour = currentHour, School = school };
+                        if (scope.Equals("teacher"))
+                        {
+                            hourLoginSc.Teacher = 1;
+                            hourLoginSc.Student = 0;
+                            hourLoginSc.TmdUser = 0;
+                        }
+                        else if (scope.Equals("student"))
+                        {
+                            hourLoginSc.Teacher = 0;
+                            hourLoginSc.Student = 1;
+                            hourLoginSc.TmdUser = 0;
+                        }
+                        else
+                        {
+                            hourLoginSc.Teacher = 0;
+                            hourLoginSc.Student = 0;
+                            hourLoginSc.TmdUser = 1;
+                        }
+
+                        try
+                        {
+                            await table.SaveOrUpdate<HourLoginSchool>(hourLoginSc);//保存在线数据
+                        }
+                        catch { }
+                    }
+
+                    //学校天峰值
+                    List<DayLoginSchool> DayLoginSchools = await table.QueryWhereString<DayLoginSchool>($"PartitionKey eq 'DayLogin-{school}' and RowKey eq '{dateDay}'");
+                    if (DayLoginSchools.Count > 0)
+                    {
+                        foreach (var dLoginSc in DayLoginSchools)
+                        {
+                            //dLoginSc.Day = currentDay;
+                            if (scope.Equals("teacher"))
+                                dLoginSc.Teacher += 1;
+                            else if (scope.Equals("student"))
+                                dLoginSc.Student += 1;
+                            else
+                                dLoginSc.TmdUser += 1;
+                        }
+
+                        try
+                        {
+                            await table.SaveOrUpdateAll(DayLoginSchools);
+                        }
+                        catch { }
+                    }
+                    else
+                    {
+                        //学校天峰值
+                        DayLoginSchool dayLoginSc = new() { PartitionKey = $"DayLogin-{school}", RowKey = dateDay, Day = currentDay, School = school };
+                        if (scope.Equals("teacher"))
+                        {
+                            dayLoginSc.Teacher = 1;
+                            dayLoginSc.Student = 0;
+                            dayLoginSc.TmdUser = 0;
+                        }
+                        else if (scope.Equals("student"))
+                        {
+                            dayLoginSc.Teacher = 0;
+                            dayLoginSc.Student = 1;
+                            dayLoginSc.TmdUser = 0;
+                        }
+                        else
+                        {
+                            dayLoginSc.Teacher = 0;
+                            dayLoginSc.Student = 0;
+                            dayLoginSc.TmdUser = 1;
+                        }
+
+                        try
+                        {
+                            await table.SaveOrUpdate<DayLoginSchool>(dayLoginSc);//保存在线数据
+                        }
+                        catch { }
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"OS:在线记录{Environment.GetEnvironmentVariable("Option:Location")}  onlin-record \n{ex.Message}\n{ex.StackTrace}\n\n{req}", GroupNames.成都开发測試群組);
+            }
+
+        }
     }
 }

+ 44 - 0
TEAMModelOS.SDK/Models/Cosmos/Teacher/OnLinRec.cs

@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using static TEAMModelOS.SDK.Models.Teacher;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Teacher
+{
+    /// <summary>
+    /// 存储登录记录试题存储中间实体
+    /// </summary>
+    public class OnLinRec
+    {
+        /// <summary>
+        /// 登录者的ID
+        /// </summary>
+        public string id { get; set; }
+        /// <summary>
+        /// 登录类型Teacher Student  TmdUser
+        /// </summary>
+        public string scope { get; set; }
+        /// <summary>
+        /// 登陆者的IP地址
+        /// </summary>
+        public string ip { get; set; }
+        /// <summary>
+        /// 学校ID
+        /// </summary>
+        public string school { get; set; }
+        /// <summary>
+        /// 到期时间 小时
+        /// </summary>
+        public int expire { get; set; } = 1;
+        /// <summary>
+        /// 上次登录地址
+        /// </summary>
+        public string region { get; set; } = null;
+        ///// <summary>
+        ///// 保留一条登录信息
+        ///// </summary>
+        //public List<LoginInfo> loginInfos { get; set; }
+    }
+}

+ 6 - 2
TEAMModelOS.SDK/Models/Service/Common/TeacherService.cs

@@ -29,7 +29,7 @@ namespace TEAMModelOS.Services
 {
     public static class TeacherService
     {
-        public static async Task<TeacherInfo> TeacherInfo(AzureCosmosFactory _azureCosmos, Teacher teacher, string name, string picture, string id, AzureStorageFactory _azureStorage, Option _option,AzureRedisFactory _azureRedis,string ip)
+        public static async Task<TeacherInfo> TeacherInfo(AzureCosmosFactory _azureCosmos, Teacher teacher, string name, string picture, string id, AzureStorageFactory _azureStorage, Option _option,AzureRedisFactory _azureRedis,string ip, HttpTrigger _httpTrigger)
         {
             List<object> schools = new List<object>();
             List<AreaDto> areas = new List<AreaDto>();
@@ -278,7 +278,11 @@ namespace TEAMModelOS.Services
             var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, standard: areaa != null ? areaa.standard : "", roles: roles.ToArray(), expire: 1);
 
             //用户在线记录
-            teacher.loginInfos = await LoginService.DoLoginInfo(teacher.loginInfos, defaultschool, Constant.ScopeTeacher, id, ip, _azureRedis, _azureStorage, expire: 1);
+            try
+            {
+                _ = _httpTrigger.RequestHttpTrigger(new { school = defaultschool, scope = $"{Constant.ScopeTeacher}", id=$"{id}", ip=$"{ip}", expire=1 }, _option.Location, "onlin-record");
+            }
+            catch { }
 
             await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
             //取得Teacher Blob 容器位置及SAS 

+ 8 - 7
TEAMModelOS/Controllers/Client/HiScanController.cs

@@ -51,9 +51,10 @@ namespace TEAMModelOS.Controllers.Core
         // private readonly ServerSentEventsService _sse;
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IPSearcher _searcher;
+        private readonly HttpTrigger _httpTrigger;
 
         public HiScanController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option,
-           AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, IPSearcher searcher//, ServerSentEventsService sse
+           AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, IPSearcher searcher, HttpTrigger httpTrigger//, ServerSentEventsService sse
                                                                          )
         {
             _azureCosmos = azureCosmos;
@@ -65,6 +66,7 @@ namespace TEAMModelOS.Controllers.Core
             _coreAPIHttpService = coreAPIHttpService;
             _azureStorage = azureStorage;
             _searcher = searcher;
+            _httpTrigger = httpTrigger;
             //_sse = sse;
         }
 
@@ -119,15 +121,14 @@ namespace TEAMModelOS.Controllers.Core
                         catch { continue; }
                     }
                 }
-                
-                response.loginInfos = await LoginService.DoLoginInfo(response.loginInfos, response?.defaultSchool, Constant.ScopeTeacher, $"{id}", ip, _azureRedis, _azureStorage, expire: 1);
+
+                //用户在线记录
                 try
                 {
-                    await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(response, $"{id}", new PartitionKey("Base"));
-                }
-                catch
-                {
+                    _ = _httpTrigger.RequestHttpTrigger(new { school = response.defaultSchool, scope = Constant.ScopeTeacher, id = $"{id}", ip = ip, expire = 1 }, _option.Location, "onlin-record");
                 }
+                catch { }
+
                 var (tblob_uri, tblob_sas) = _azureStorage.GetBlobContainerSAS($"{id}", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete);
                 return Ok(new { schools, teacher = new { name, picture, id, bloburl = tblob_uri, blobsas = tblob_sas } });
             }

+ 6 - 7
TEAMModelOS/Controllers/Client/HiTAControlller.cs

@@ -38,13 +38,14 @@ namespace TEAMModelOS.Controllers.Client
         private readonly IConfiguration _configuration;
         private readonly NotificationService _notificationService;
         private readonly IPSearcher _searcher;
+        private readonly HttpTrigger _httpTrigger;
         public HiTAControlller(
             AzureStorageFactory azureStorage,
             AzureRedisFactory azureRedis,
             AzureCosmosFactory azureCosmos,
             DingDing dingDing,
             SnowflakeId snowflakeId,
-            IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService, IPSearcher searcher)
+            IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService, IPSearcher searcher, HttpTrigger httpTrigger)
         {
             _azureStorage = azureStorage;
             _azureRedis = azureRedis;
@@ -55,6 +56,7 @@ namespace TEAMModelOS.Controllers.Client
             _configuration = configuration;
             _notificationService = notificationService;
             _searcher = searcher;
+            _httpTrigger = httpTrigger;
         }
 
         public class HiTAJoinSchool
@@ -466,15 +468,12 @@ namespace TEAMModelOS.Controllers.Client
                     //    }
                     //}
 
-                    Teacher teacher = jsonsc.ToObject<Teacher>();
-                    teacher.loginInfos = await LoginService.DoLoginInfo(teacher.loginInfos, defaultschool, Constant.ScopeTeacher, id, ip, _azureRedis, _azureStorage, expire: 1);
+                    //用户在线记录
                     try
                     {
-                        await clientc.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
-                    }
-                    catch
-                    {
+                        _ = _httpTrigger.RequestHttpTrigger(new { school = defaultschool, scope = $"{Constant.ScopeTeacher}", id = $"{id}", ip = $"{ip}", expire = 1 }, _option.Location, "onlin-record");
                     }
+                    catch { }
 
                     return Ok(new { schools, defaultschool, courses, size, resCount, itemCount, paperCount, activityCount });
                 }

+ 12 - 19
TEAMModelOS/Controllers/Client/HiTeachController.cs

@@ -23,7 +23,6 @@ using System.Dynamic;
 using HTEXLib.COMM.Helpers;
 using StackExchange.Redis;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
-
 using TEAMModelOS.SDK;
 using Microsoft.Extensions.Configuration;
 using Azure.Messaging.ServiceBus;
@@ -50,6 +49,7 @@ namespace TEAMModelOS.Controllers.Client
         private readonly IConfiguration _configuration;
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IPSearcher _searcher;
+        private readonly HttpTrigger _httpTrigger;
 
         public HiTeachController(
             AzureStorageFactory azureStorage,
@@ -60,7 +60,7 @@ namespace TEAMModelOS.Controllers.Client
             IOptionsSnapshot<Option> option,
             AzureServiceBusFactory serviceBus,
             IConfiguration configuration,
-            CoreAPIHttpService coreAPIHttpService, IPSearcher searcher)
+            CoreAPIHttpService coreAPIHttpService, IPSearcher searcher, HttpTrigger httpTrigger)
         {
             _azureStorage = azureStorage;
             _azureRedis = azureRedis;
@@ -72,6 +72,7 @@ namespace TEAMModelOS.Controllers.Client
             _configuration = configuration;
             _coreAPIHttpService = coreAPIHttpService;
             _searcher = searcher;
+            _httpTrigger = httpTrigger;
         }
         /// <summary>
         /// 更新课堂记录
@@ -247,16 +248,6 @@ namespace TEAMModelOS.Controllers.Client
                     {
                         defaultschool = valueD.ToString();
                     }
-
-                    Teacher teacher = jsonsc.ToObject<Teacher>();
-                    teacher.loginInfos = await LoginService.DoLoginInfo(teacher.loginInfos, defaultschool, Constant.ScopeTeacher, id, ip, _azureRedis, _azureStorage, expire: 1);
-                    try
-                    {
-                        await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
-                    }
-                    catch
-                    {
-                    }
                 }
                 else
                 {
@@ -274,7 +265,6 @@ namespace TEAMModelOS.Controllers.Client
                         defaultSchool = null,
                         schools = new List<Teacher.TeacherSchool>(),
                     };
-                    teacher.loginInfos = await LoginService.DoLoginInfo(teacher.loginInfos, "", Constant.ScopeTeacher, id, ip, _azureRedis, _azureStorage, expire: 1);
                     teacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").CreateItemAsync<Teacher>(teacher, new PartitionKey("Base"));
                 }
 
@@ -416,6 +406,12 @@ namespace TEAMModelOS.Controllers.Client
                         }
                     }
                 }
+                //用户在线记录
+                try
+                {
+                    _ = _httpTrigger.RequestHttpTrigger(new { school = defaultschool, scope = $"{Constant.ScopeTeacher}", id = $"{id}", ip = $"{ip}", expire = 1 }, _option.Location, "onlin-record");
+                }
+                catch { }
 
                 //取得Teacher Blob 容器位置及SAS 
                 var container = _azureStorage.GetBlobContainerClient(id);
@@ -736,15 +732,12 @@ namespace TEAMModelOS.Controllers.Client
                     }
                 }
 
+                //用户在线记录
                 try
                 {
-                    Teacher teacher = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Teacher>($"{id}", new PartitionKey("Base"));
-                    teacher.loginInfos = await LoginService.DoLoginInfo(teacher.loginInfos, school_code.GetString(), Constant.ScopeTeacher, id, ip, _azureRedis, _azureStorage, expire: 1);
-                    await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
-                }
-                catch
-                {
+                    _ = _httpTrigger.RequestHttpTrigger(new { school = school_code.GetString(), scope = $"{Constant.ScopeTeacher}", id = $"{id}", ip = $"{ip}", expire = 1 }, _option.Location, "onlin-record");
                 }
+                catch { }
 
                 //取得School Blob 容器位置及SAS
                 string school_code_blob = school_code.GetString().ToLower();

+ 17 - 4
TEAMModelOS/Controllers/Student/StudentController.cs

@@ -43,9 +43,10 @@ namespace TEAMModelOS.Controllers
         private readonly DingDing _dingDing;
         private readonly Option _option;
         private readonly IPSearcher _searcher;
+        private readonly HttpTrigger _httpTrigger;
         public IConfiguration _configuration { get; set; }
         private readonly AzureServiceBusFactory _serviceBus;
-        public StudentController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IPSearcher searcher, IOptionsSnapshot<Option> option,IConfiguration configuration, AzureServiceBusFactory serviceBus
+        public StudentController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IPSearcher searcher, IOptionsSnapshot<Option> option,IConfiguration configuration, AzureServiceBusFactory serviceBus, HttpTrigger httpTrigger
             )
         {
             _searcher = searcher;
@@ -56,6 +57,7 @@ namespace TEAMModelOS.Controllers
             _option = option?.Value;
             _configuration = configuration;
             _serviceBus = serviceBus;
+            _httpTrigger = httpTrigger;
         }
 
         /// <summary>
@@ -552,7 +554,11 @@ namespace TEAMModelOS.Controllers
             var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name, picture, _option.JwtSecretKey, scope: Constant.ScopeStudent, Website: "IES", areaId: areaId, schoolID: school_code, roles: new[] { "student" }, expire: 1);
 
             //用户在线记录
-            student.loginInfos = await LoginService.DoLoginInfo(student.loginInfos, school_code, Constant.ScopeStudent, id, ip, _azureRedis, _azureStorage, expire: 1);
+            try
+            {
+                _ = _httpTrigger.RequestHttpTrigger(new { school = school_code, scope = $"{Constant.ScopeStudent}", id = $"{id}", ip = $"{ip}", expire = 1 }, _option.Location, "onlin-record");
+            }
+            catch {}
 
             await cosmosClient.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync<Student>(student, id, new PartitionKey($"Base-{school_code}"));
 
@@ -683,8 +689,15 @@ namespace TEAMModelOS.Controllers
                         }
                         //換取AuthToken,提供給前端
                         var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id.GetString(), name.GetString(), picture.GetString(), _option.JwtSecretKey, Website: "IES", areaId: schoolInfo.areaId, scope: Constant.ScopeStudent, schoolID: school_code.GetString(), roles: new[] { "student" }, expire: 1);
-                        //在线人数记录
-                        student.loginInfos = await LoginService.DoLoginInfo(student.loginInfos, school_code.GetString(), Constant.ScopeStudent, id.GetString(), ip, _azureRedis, _azureStorage, expire: 1);
+                        
+                        //用户在线记录
+                        try
+                        {
+                            _ = _httpTrigger.RequestHttpTrigger(new { school = school_code.GetString(), scope = $"{Constant.ScopeStudent}", id = $"{id}", ip = $"{ip}", expire = 1 }, _option.Location, "onlin-record");
+                        }
+                        catch { }
+
+
                         //保存学生登录信息
                         await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync<Student>(student, student.id, new PartitionKey($"{student.code}"));
 

+ 10 - 6
TEAMModelOS/Controllers/Student/TmdUserController.cs

@@ -44,8 +44,9 @@ namespace TEAMModelOS.Controllers
         private readonly IConfiguration _configuration;
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IPSearcher _searcher;
+        private readonly HttpTrigger _httpTrigger;
 
-        public TmdUserController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, IPSearcher searcher, AzureRedisFactory azureRedis)
+        public TmdUserController(CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, IPSearcher searcher, AzureRedisFactory azureRedis, HttpTrigger httpTrigger)
         {
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
@@ -55,6 +56,7 @@ namespace TEAMModelOS.Controllers
             _coreAPIHttpService = coreAPIHttpService;
             _searcher = searcher;
             _azureRedis = azureRedis;
+            _httpTrigger = httpTrigger;
         }
         [ProducesDefaultResponseType]
         [HttpPost("get-school-info")]
@@ -126,9 +128,6 @@ namespace TEAMModelOS.Controllers
                     }
                     loginInfos = tmdUser.loginInfos;
 
-                    //在线人数记录
-                    tmdUser.loginInfos = await LoginService.DoLoginInfo(tmdUser.loginInfos, Schoolid?.ToString(), Constant.ScopeTmdUser, id, ip, _azureRedis, _azureStorage, expire: 1);
-
                    await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync<TmdUser>(tmdUser, id, new PartitionKey("Base"));
                     //預設學校ID
                     defaultschool = tmdUser.defaultSchool;
@@ -151,14 +150,19 @@ namespace TEAMModelOS.Controllers
                         };
                         var container = _azureStorage.GetBlobContainerClient(id);
                         await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建Teacher私有容器,如存在則不做任何事,保障容器一定存在
-                        //在线人数记录
-                        teacher.loginInfos = await LoginService.DoLoginInfo(teacher.loginInfos, "", Constant.ScopeTmdUser, id, ip, _azureRedis, _azureStorage, expire: 1);
                         teacher = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Student").CreateItemAsync<TmdUser>(teacher, new PartitionKey("Base"));
                     }
                 }
                 //換取AuthToken,提供給前端
                 var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTmdUser, roles: new[] { "student" }, expire: 1);
 
+                //用户在线记录
+                try
+                {
+                    _ = _httpTrigger.RequestHttpTrigger(new { school = defaultschool, scope = $"{Constant.ScopeTmdUser}", id = $"{id}", ip = $"{ip}", expire = 1 }, _option.Location, "onlin-record");
+                }
+                catch { }
+
                 if (!string.IsNullOrEmpty(defaultschool))
                 {
 

+ 12 - 4
TEAMModelOS/Controllers/Teacher/InitController.cs

@@ -50,8 +50,9 @@ namespace TEAMModelOS.Controllers
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IPSearcher _searcher;
         private readonly ILogger<InitController> _logger;
+        private readonly HttpTrigger _httpTrigger;
 
-        public InitController(ILogger<InitController> logger, IPSearcher searcher, CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
+        public InitController(ILogger<InitController> logger, IPSearcher searcher, CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService, HttpTrigger httpTrigger)
         {
             _searcher = searcher;
             _azureCosmos = azureCosmos;
@@ -63,6 +64,7 @@ namespace TEAMModelOS.Controllers
             _notificationService = notificationService;
             _coreAPIHttpService = coreAPIHttpService;
             _logger = logger;
+            _httpTrigger = httpTrigger;
         }
         /// <summary>
         /// 修改教师信息
@@ -277,7 +279,7 @@ namespace TEAMModelOS.Controllers
             try
             {
                 Teacher teacher = null;
-                TeacherInfo teacherInfo = await TeacherService.TeacherInfo(_azureCosmos, teacher, $"{name}", $"{picture}", id, _azureStorage, _option,_azureRedis,ip);
+                TeacherInfo teacherInfo = await TeacherService.TeacherInfo(_azureCosmos, teacher, $"{name}", $"{picture}", id, _azureStorage, _option, _azureRedis, ip, _httpTrigger);
                 teacherInfo.areas.ForEach(x => { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } });
                 LoginService.LoginLog(HttpContext, _option, _logger, _dingDing, ip, region, id, $"{name}", 200);
                 int lessonLimit = teacherInfo.teacher.lessonLimit;
@@ -422,8 +424,6 @@ namespace TEAMModelOS.Controllers
                 {
                     school_code = teacher.schools[0].schoolId;
                     teacher.defaultSchool = school_code;
-                    //在线人数记录
-                    teacher.loginInfos = await LoginService.DoLoginInfo(teacher.loginInfos, school_code, Constant.ScopeTeacher, id, ip, _azureRedis, _azureStorage, expire: 1);
                     teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, id, new PartitionKey("Base"));
                 }
                 var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{school_code}"));
@@ -537,6 +537,14 @@ namespace TEAMModelOS.Controllers
                 //TODO JJ,更新Token时,在取得学校资讯时,没有传入schoolId
                 var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName, id, name?.ToString(), picture?.ToString(), _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, schoolID: school_code.ToString(), areaId: currAreaId, standard: school_base.standard, roles: roles.ToArray(), permissions: permissions.ToArray(), expire: 1);
 
+                //用户在线记录
+                try
+                {
+                    _ = _httpTrigger.RequestHttpTrigger(new { school = school_code.ToString(), scope = $"{Constant.ScopeTeacher}", id = $"{id}", ip = $"{ip}", expire = 1 }, _option.Location, "onlin-record");
+                }
+                catch { }
+
+
                 //取得班级
                 List<object> school_classes = new List<object>();
                 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator