소스 검색

Merge branch 'PL/develop-BI' into develop

Li 2 년 전
부모
커밋
a47d237256
34개의 변경된 파일1338개의 추가작업 그리고 317개의 파일을 삭제
  1. 1 0
      TEAMModelBI/Controllers/BIBlob/AnalyseFileController.cs
  2. 6 6
      TEAMModelBI/Controllers/BIHome/HomeStatisController.cs
  3. 1 0
      TEAMModelBI/Controllers/BIHome/OnLineController.cs
  4. 0 14
      TEAMModelBI/Controllers/BINormal/AreaRelevantController.cs
  5. 1 1
      TEAMModelBI/Controllers/BINormal/BatchAreaController.cs
  6. 22 3
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  7. 8 2
      TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs
  8. 5 2
      TEAMModelBI/Controllers/BITest/TestController.cs
  9. 4 2
      TEAMModelBI/Controllers/Census/ActivitySticsController.cs
  10. 1 1
      TEAMModelBI/Controllers/Census/BlobLogController.cs
  11. 1 0
      TEAMModelBI/Controllers/Census/ItemSticsController.cs
  12. 1 1
      TEAMModelBI/Controllers/Census/LessonSticsController.cs
  13. 4 3
      TEAMModelBI/Controllers/Census/PaperController.cs
  14. 1 0
      TEAMModelBI/Controllers/Census/ProductStatisController.cs
  15. 101 27
      TEAMModelBI/Controllers/Census/SchoolController.cs
  16. 97 0
      TEAMModelBI/Controllers/RepairApi/NormalController.cs
  17. 33 0
      TEAMModelBI/Models/ForeEndModel.cs
  18. 1 0
      TEAMModelBI/Startup.cs
  19. 0 74
      TEAMModelBI/Tool/BIStatsWay/SchoolStatsWay.cs
  20. 0 77
      TEAMModelBI/Tool/BIStatsWay/StudyStatsWay.cs
  21. 11 7
      TEAMModelBI/Tool/CommonFind.cs
  22. 82 0
      TEAMModelBI/Tool/CosmosBank/JointlySingleQuery1.cs
  23. 1 0
      TEAMModelBI/Tool/CosmosBank/StatsWay.cs
  24. 456 0
      TEAMModelBI/Tool/TimeHelper1.cs
  25. 66 2
      TEAMModelOS.FunctionV4/HttpTrigger/BIHttpTrigger.cs
  26. 2 2
      TEAMModelOS.SDK/Models/Cosmos/BI/BICommon/MonthStartEnd.cs
  27. 19 17
      TEAMModelBI/Models/FrontModel.cs
  28. 12 12
      TEAMModelOS.SDK/Models/Cosmos/BI/StatsInfo.cs
  29. 9 6
      TEAMModelBI/Tool/CosmosBank/JointlySingleQuery.cs
  30. 95 47
      TEAMModelBI/Tool/TimeHelper.cs
  31. 8 5
      TEAMModelBI/Tool/BIStatsWay/ActivityStatsWay.cs
  32. 9 6
      TEAMModelBI/Tool/BIStatsWay/LessonRecordStatsWay.cs
  33. 199 0
      TEAMModelOS.SDK/Models/Service/BIStatsWay/SchoolStatsWay.cs
  34. 81 0
      TEAMModelOS.SDK/Models/Service/BIStatsWay/StudyStatsWay.cs

+ 1 - 0
TEAMModelBI/Controllers/BIBlob/AnalyseFileController.cs

@@ -18,6 +18,7 @@ using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.BIBlob
 {

+ 6 - 6
TEAMModelBI/Controllers/BIHome/HomeStatisController.cs

@@ -116,7 +116,7 @@ namespace TEAMModelBI.Controllers.BIHome
                     var tempCode = provinceStics.Find(x => x.provCode == itemStandard.provCode);
                     if (tempCode != null)
                     {
-                        string sqlSc = $"select c.id from c where c.standard='{itemStandard.standard}'";
+                        string sqlSc = $"select value(c.id) from c where c.standard='{itemStandard.standard}'";
                         List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, sqlSc, "Base");
                         tempCode.schoolCount += schoolIds.Count;
 
@@ -149,7 +149,7 @@ namespace TEAMModelBI.Controllers.BIHome
                         tempProvinceStics.provName = itemStandard.provName;
                         tempProvinceStics.standardCount += 1;
 
-                        string sqlSc = $"select c.id from c where c.standard='{itemStandard.standard}'";
+                        string sqlSc = $"select value(c.id) from c where c.standard='{itemStandard.standard}'";
                         List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, sqlSc, "Base");
                         tempProvinceStics.schoolCount += schoolIds.Count;
                         
@@ -292,7 +292,7 @@ namespace TEAMModelBI.Controllers.BIHome
                     };
 
                     //string sqlTxt = $"select c.id from c where c.standard='{itemStandrd.standard}'";
-                    string sqlTxt = $"select c.id from c where c.areaId='{itemStandrd.id}' and c.standard='{itemStandrd.standard}'";
+                    string sqlTxt = $"select value(c.id) from c where c.areaId='{itemStandrd.id}' and c.standard='{itemStandrd.standard}'";
                     List<string> schoolIds = await CommonFind.FindScIds(cosmosClient,sqlTxt, "Base");
                     districtStics.schoolCount += schoolIds.Count;
 
@@ -361,7 +361,7 @@ namespace TEAMModelBI.Controllers.BIHome
                     if (tempCode != null)
                     {
                         //List<string> schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"select c.id from c where c.standard='{itemStandrd.standard}'", "Base");
-                        List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.areaId='{itemStandrd.id}' and c.standard='{itemStandrd.standard}'", "Base");
+                        List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.areaId='{itemStandrd.id}' and c.standard='{itemStandrd.standard}'", "Base");
                         tempCode.schoolCount += schoolIds.Count;
 
                         var tempModel = sticsCitys.Where(x => x.cityCode == tempCode.cityCode).FirstOrDefault();
@@ -400,7 +400,7 @@ namespace TEAMModelBI.Controllers.BIHome
                         citySchool.cityCode = itemStandrd.cityCode;
                         citySchool.cityName = itemStandrd.cityName;
 
-                        List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.standard='{itemStandrd.standard}'","Base");
+                        List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.standard='{itemStandrd.standard}'","Base");
                         citySchool.schoolCount += schoolIds.Count;
 
                         List<DistrictStics> tempDistrictStics = new();
@@ -468,7 +468,7 @@ namespace TEAMModelBI.Controllers.BIHome
 
                 //查询学校空间和学校Id
                 totalSize = await CommonFind.GetSqlValueCount(cosmosClient, "School", "select value(sum(c.size)) from c", "Base");
-                schoolId = await CommonFind.FindScIds(cosmosClient, "select c.id,c.size from c", "Base");
+                schoolId = await CommonFind.FindScIds(cosmosClient, "select value(c.id) from c", "Base");
 
                 //查询学校已使用空间大小
                 foreach (var itemId in schoolId)

+ 1 - 0
TEAMModelBI/Controllers/BIHome/OnLineController.cs

@@ -19,6 +19,7 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.SDK.Models.Table;
 
 namespace TEAMModelBI.Controllers.BIHome

+ 0 - 14
TEAMModelBI/Controllers/BINormal/AreaRelevantController.cs

@@ -561,20 +561,6 @@ namespace TEAMModelBI.Controllers.BINormal
 
         }
 
-        public record AreaAssist
-        {
-            public string userId { get; set; }
-            public string unionId { get; set; }
-            public string name { get; set; }
-            public string mobile { get; set; }
-            public string avatar { get; set; }
-            public string tmdId { get; set; }
-            public string tmdName { get; set; }
-            public string tmdMobile { get; set; }
-            public string picture { get; set; }
-            public string roles { get; set; }
-            public string schoolIds { get; set; }
-        }
 
         /// <summary>
         /// 通过区域ID查询学校前端暂时

+ 1 - 1
TEAMModelBI/Controllers/BINormal/BatchAreaController.cs

@@ -956,7 +956,7 @@ namespace TEAMModelBI.Controllers.BINormal
                         await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(item, item.id, new PartitionKey("Base"));
                     }
 
-                    List<string> scIds = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.areaId='{area.id}' and c.standard ='{area.standard}'", "Base");
+                    List<string> scIds = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.areaId='{area.id}' and c.standard ='{area.standard}'", "Base");
 
                     foreach (var item in scIds)
                     {

+ 22 - 3
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -1622,12 +1622,12 @@ namespace TEAMModelBI.Controllers.BISchool
 
             //if ((string.IsNullOrEmpty($"{tmdId}") && string.IsNullOrEmpty($"{schooId}")) || (!string.IsNullOrEmpty($"{tmdId}") && !string.IsNullOrEmpty($"{schooId}")))
                 
-            List<MonthStartEnd> mthStartEnds = await TimeHelper.GetYearSataMthCtMth(DateTimeOffset.UtcNow);
+            List<StartEndTime> mthStartEnds = await TimeHelper.GetYearSataMthCtMth(DateTimeOffset.UtcNow);
             if (mthStartEnds.Count > 0)
             {
                 foreach (var item in mthStartEnds)
                 {
-                    YearCnt yearCnt = new() { name = item.yearMonth };
+                    YearCnt yearCnt = new() { name = item.date };
                     string selessSql = $"{strSql} and {scSql.ToString()} and c.startTime >= {item.start} and c.startTime <= {item.end}";
                     yearCnt.lessCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", selessSql);
 
@@ -1818,6 +1818,25 @@ namespace TEAMModelBI.Controllers.BISchool
             return Ok(new { state = RespondCode.Ok, school, gradeCnt, subCnt });
         }
 
+        /// <summary>
+        /// 学校简要信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-schools")]
+        public async Task<IActionResult> GetSchools (JsonElement jsonElement)
+        {
+            List<ScBriefInfo> scBriefs = new();
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS,"School").GetItemQueryIterator<ScBriefInfo>(queryText:"select value(c) from c" ,requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")}))
+            {
+                scBriefs.Add(item);
+            }
+
+            return Ok(new { state = RespondCode.Ok, scBriefs });
+        }
+
         /// <summary>
         /// 通过tmdID 账户查询学校专业和模组   //已对接
         /// </summary>
@@ -1991,7 +2010,7 @@ namespace TEAMModelBI.Controllers.BISchool
             if (!string.IsNullOrEmpty($"{areaId}"))
             {
                 List<string> schools = new();
-                schools = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.areaId='{areaId}'", "Base");
+                schools = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.areaId='{areaId}'", "Base");
 
                 allSize = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"select value(sum(c.size)) from c where c.areaId='{areaId}'", "Base"); //区域所有学校空间
 

+ 8 - 2
TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs

@@ -418,7 +418,13 @@ namespace TEAMModelBI.Controllers.BITable
                             {
                                 if (scTch.roles.Contains("sales"))
                                 {
-                                    int index = scTch.roles.FindIndex(fi => fi.Contains("sales"));
+
+                                    //int index = scTch.roles.FindIndex(fi => fi.Equals("sales"));
+                                    //scTch.roles[index]= "assist";
+                                    //scTch.job = "顾问";
+                                    //upScTch.Add(cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scTch, scTch.id, new PartitionKey($"{scTch.code}")));
+
+                                    int index = scTch.roles.FindIndex(fi => fi.Equals("sales"));
                                     if (index >= 0)
                                     {
                                         scTch.roles[index] = "assist";
@@ -436,7 +442,7 @@ namespace TEAMModelBI.Controllers.BITable
                             {
                                 if (scTch.roles.Contains("assist"))
                                 {
-                                    int index = scTch.roles.FindIndex(fi => fi.Contains("assist"));
+                                    int index = scTch.roles.FindIndex(fi => fi.Equals("assist"));
                                     if (index >= 0) 
                                     {
                                         scTch.roles[index] = "sales";

+ 5 - 2
TEAMModelBI/Controllers/BITest/TestController.cs

@@ -680,6 +680,10 @@ namespace TEAMModelBI.Controllers.BITest
         [HttpPost("get-date")]
         public async Task<IActionResult> GetDate()
         {
+            ////计算一年每天的开始/结束时间
+            //List<StartEndTime> everyDay = TimeHelper.GetYearEveryDay(DateTimeOffset.UtcNow, isCurrDay: true);
+            //return Ok(new { state = RespondCode.Ok, dayCnt = everyDay.Count, everyDay });
+
             List<string> day7 = TimeHelper.GetNearDay(DateTimeOffset.UtcNow, 7);
             List<string> day30 = TimeHelper.GetNearDay(DateTimeOffset.UtcNow, 30);
 
@@ -714,7 +718,7 @@ namespace TEAMModelBI.Controllers.BITest
             var start = GetMonthStart(ere);
             var end = GetMonthEnd(ere);
 
-            List<MonthStartEnd> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
+            List<StartEndTime> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
             //return Ok(new { strList, dateTime, year, start, end, endList, endList1, endList2 });
 
 
@@ -1346,7 +1350,6 @@ namespace TEAMModelBI.Controllers.BITest
             //        }
             //    }
             //}
-
             var (an, saveUrl) = await BILogAnalyseService.GetPathAnalyse(_azureStorage, _ipSearcher, _dingDing, $"{path}", BIConst.LogChina, timeType: $"{jTimeType}");
 
             return Ok(new { state = RespondCode.Ok, cnt = filename.Count, filename, an, saveUrl });

+ 4 - 2
TEAMModelBI/Controllers/Census/ActivitySticsController.cs

@@ -239,7 +239,7 @@ namespace TEAMModelBI.Controllers.Census
                 monthLess = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"{oftenSql} where c.pk='LessonRecord' and {comSql} and c.startTime >= {monthS} and c.startTime <= {monthE}");
 
                 //学时
-                totalTime = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", $"select value(sum(c.totalTime)) from c where c.pk='TeacherTrain' and {comSql}");
+                //totalTime = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", $"select value(sum(c.totalTime)) from c where c.pk='TeacherTrain' and {comSql}");
 
                 //活动
                 string actSpl = BICommonWay.ManyScSql(" and c.school", scIds);
@@ -260,7 +260,7 @@ namespace TEAMModelBI.Controllers.Census
                 //string stSql = $"{oftenSql} join s in c.currency where c.TeacherTrain and {comSql} and s.submitTime = 0 or s.submitTime >= {setting.submitTime}";
                 //submitCount = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", ctSql);
 
-                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: $"select c.id,c.code,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and {comSql}", requestOptions: new QueryRequestOptions() { })) 
+                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: $"select c.id,c.code,c.totalTime,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and {comSql}", requestOptions: new QueryRequestOptions() { })) 
                 {
                     using var json = await JsonDocument.ParseAsync(item.ContentStream);
                     if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
@@ -272,6 +272,8 @@ namespace TEAMModelBI.Controllers.Census
                     }
                 }
 
+                //学时
+                totalTime = trains.Select(s => s.totalTime).Sum();
                 trains.ForEach(x =>
                 {
                     //线上研修

+ 1 - 1
TEAMModelBI/Controllers/Census/BlobLogController.cs

@@ -62,7 +62,7 @@ namespace TEAMModelBI.Controllers.Census
             List<string> schoolIds = new();
             if (!string.IsNullOrEmpty($"{areaId}"))
             {
-                string sqlTxt = $"select c.id from c where c.areaId='{areaId}'";
+                string sqlTxt = $"select value(c.id) from c where c.areaId='{areaId}'";
                 sqlSize.Append($" where c.areaId = '{areaId}'");
                 schoolIds = await CommonFind.FindScIds(cosmosClient, sqlTxt.ToString(), "Base");
                 foreach (var item in StaticValue.fileType)

+ 1 - 0
TEAMModelBI/Controllers/Census/ItemSticsController.cs

@@ -17,6 +17,7 @@ using Azure.Core;
 using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
 using TEAMModelOS.SDK.Context.Constant;
 using DocumentFormat.OpenXml.Wordprocessing;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.Census
 {

+ 1 - 1
TEAMModelBI/Controllers/Census/LessonSticsController.cs

@@ -558,7 +558,7 @@ namespace TEAMModelBI.Controllers.Census
             //if ($"{site}".Equals(BIConst.Global))
             //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
 
-            StringBuilder scSqlTxt = new("select c.id from c");
+            StringBuilder scSqlTxt = new("select value(c.id) from c");
             if (!string.IsNullOrEmpty($"{areaId}"))
             {
                 scSqlTxt.Append($" where c.areaId='{areaId}'");

+ 4 - 3
TEAMModelBI/Controllers/Census/PaperController.cs

@@ -25,6 +25,7 @@ using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.Census
 {
@@ -361,7 +362,7 @@ namespace TEAMModelBI.Controllers.Census
             ////分开部署,就不需要,一站多用时,取消注释
             //if ($"{site}".Equals(BIConst.Global))
             //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
-            List<MonthStartEnd> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
+            List<StartEndTime> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
             if (string.IsNullOrEmpty($"{tmdId}"))
             {
                 Dictionary<string, long> schoolYears = new Dictionary<string, long>();
@@ -370,7 +371,7 @@ namespace TEAMModelBI.Controllers.Census
                     string sqlText = $"SELECT value(COUNT(c.id)) FROM c WHERE c.createTime >= {temp.start} and c.createTime <= {temp.end} and c.pk='Paper'";
 
                     long total = await CommonFind.GetSqlValueCount(cosmosClient, new List<string>() { "School", "Teacher" }, sqlText);
-                    schoolYears.Add(temp.yearMonth, total);
+                    schoolYears.Add(temp.date, total);
                 }
 
                 return Ok(new { state = 200, schoolYears });
@@ -398,7 +399,7 @@ namespace TEAMModelBI.Controllers.Census
                     {                        
                         string sqlTxt = $"SELECT value(COUNT(c.id)) FROM c WHERE c.code='Paper-{schoolId}' and c.createTime >= {temp.start} and c.createTime <= {temp.end} and c.pk='Paper'";
                         long totals = await CommonFind.GetSqlValueCount(cosmosClient, new List<string>() { "School", "Teacher" }, sqlTxt);
-                        yearCount.Add(temp.yearMonth, totals);
+                        yearCount.Add(temp.date, totals);
                     }
                     schoolYear.yearPaper = yearCount;
                     schoolYears.Add(schoolYear);

+ 1 - 0
TEAMModelBI/Controllers/Census/ProductStatisController.cs

@@ -13,6 +13,7 @@ using TEAMModelOS.SDK.Context.BI;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.Census
 {

+ 101 - 27
TEAMModelBI/Controllers/Census/SchoolController.cs

@@ -1,4 +1,5 @@
 using Azure.Cosmos;
+using DocumentFormat.OpenXml.Bibliography;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
@@ -13,7 +14,6 @@ using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelBI.Models;
 using TEAMModelBI.Tool;
-using TEAMModelBI.Tool.BIStatsWay;
 using TEAMModelBI.Tool.CosmosBank;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.BI;
@@ -23,8 +23,7 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using TEAMModelOS.SDK.Models.Service.BI;
-using static TEAMModelBI.Controllers.BINormal.AreaRelevantController;
-using static TEAMModelBI.Controllers.Census.LessonSticsController;
+using TEAMModelOS.SDK.Models.Service.BIStatsWay;
 
 namespace TEAMModelBI.Controllers.Census
 {
@@ -36,13 +35,15 @@ namespace TEAMModelBI.Controllers.Census
         private readonly AzureStorageFactory _azureStorage;
         private readonly DingDing _dingDing;
         private readonly Option _option;
+        private readonly HttpTrigger _httpTrigger;
 
-        public SchoolController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option)
+        public SchoolController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, HttpTrigger httpTrigger)
         {
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
             _dingDing = dingDing;
             _option = option?.Value;
+            _httpTrigger = httpTrigger;
         }
 
         /// <summary>
@@ -489,7 +490,8 @@ namespace TEAMModelBI.Controllers.Census
         }
 
         /// <summary>
-        /// 学校统计
+        /// 学校统计     
+        /// 新的数据结构
         /// </summary>
         /// <param name="jsonElement"></param>
         /// <returns></returns>
@@ -498,12 +500,12 @@ namespace TEAMModelBI.Controllers.Census
         public async Task<IActionResult> GetSchoolStats(JsonElement jsonElement) 
         {
             if (!jsonElement.TryGetProperty("scId", out JsonElement scId)) return BadRequest();
-            var cosmosClinet = _azureCosmos.GetCosmosClient();
+            var cosmosClient = _azureCosmos.GetCosmosClient();
 
             School school = new();
             ScStats scStats = new();
 
-            var respSc = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey($"Base"));
+            var respSc = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey($"Base"));
             if (respSc.Status == 200)
             {
                 using var fileJson = await JsonDocument.ParseAsync(respSc.ContentStream);
@@ -514,15 +516,19 @@ namespace TEAMModelBI.Controllers.Census
 
             try
             {
+                bool isExist = true;
                 StatsInfo statsInfo = new();
-                var scDataStats = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey("Stats"));
+                var scDataStats = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey("Stats"));
                 if (scDataStats.Status == 200)
                 {
                     using var fileJson = await JsonDocument.ParseAsync(scDataStats.ContentStream);
                     statsInfo = fileJson.ToObject<StatsInfo>();
                 }
                 else
+                {
                     scStats.id = school.id;
+                    isExist = false;
+                }
 
                 bool isnew = false;
                 DateTimeOffset dateTime = DateTimeOffset.UtcNow;
@@ -574,18 +580,21 @@ namespace TEAMModelBI.Controllers.Census
                     scStats.actStats.term = statsInfo.activity.term;
                     scStats.actStats.LastYear = TimeHelper.GetYearMonth(statsInfo.activity.LastYear ,dateTime.Year,dateTime.Month);
                     scStats.actStats.year = TimeHelper.GetYearMonth(statsInfo.activity.year, dateTime.Year, dateTime.Month);
-                    scStats.srStats.learnTime = statsInfo.study.learnTime;
-                    scStats.srStats.onlineTime = statsInfo.study.onlineTime;
-                    scStats.srStats.offlineTime = statsInfo.study.offlineTime;
-                    scStats.srStats.classTime = statsInfo.study.classTime;
-                    scStats.srStats.currency = statsInfo.study.currency;
-                    scStats.srStats.notStarted = statsInfo.study.notStarted;
-                    scStats.srStats.ongoing = statsInfo.study.ongoing;
-                    scStats.srStats.finish = statsInfo.study.finish;
+                    if (statsInfo.study != null)
+                    {
+                        scStats.srStats.learnTime = statsInfo.study.learnTime;
+                        scStats.srStats.online = statsInfo.study.online;
+                        scStats.srStats.offline = statsInfo.study.offline;
+                        scStats.srStats.classRoom = statsInfo.study.classRoom;
+                        scStats.srStats.submit = statsInfo.study.submit;
+                        scStats.srStats.notStarted = statsInfo.study.notStarted;
+                        scStats.srStats.ongoing = statsInfo.study.ongoing;
+                        scStats.srStats.finish = statsInfo.study.finish;
+                    }
                 }
 
                 if(statsInfo.upTime > 0 && !isnew) {
-                    long timedis = 15 * 60 * 1000;//15分钟
+                    long timedis = 20 * 60 * 1000;//20分钟
                     if (now - statsInfo.upTime < timedis)
                         isnew = true;
                 }
@@ -593,11 +602,20 @@ namespace TEAMModelBI.Controllers.Census
                     statsInfo.upTime = now;
                 if (statsInfo.upTime == 0 && isnew)
                     statsInfo.upTime = DateTimeOffset.UtcNow.Add(new TimeSpan(-1, 0, 0, 0)).ToUnixTimeMilliseconds();
+                if (!isnew)
+                {
+                    //Function 处理Function 更新或者新增
+                    //_ = _httpTrigger.RequestHttpTrigger(new { schoolId = $"{school.id}"}, _option.Location, "stats-sc-info");
 
-                statsInfo = await SchoolStatsWay.upSingleSc(cosmosClinet, school.id);
-
-
+                    //异步方法处理 同步更新
+                    statsInfo = await SchoolStatsWay.GetSingleSc(cosmosClient, school.id);
 
+                    statsInfo.upTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    if (isExist)
+                        statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<StatsInfo>(statsInfo, statsInfo.id, new PartitionKey("Stats"));
+                    else
+                        statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<StatsInfo>(statsInfo, new PartitionKey("Stats"));
+                }
 
                 return Ok(new { state = RespondCode.Ok, statsInfo });
             }
@@ -608,6 +626,62 @@ namespace TEAMModelBI.Controllers.Census
             }
         }
 
+        /// <summary>
+        /// 区域统计
+        /// 新的数据结构
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-areastats")]
+        public async Task<IActionResult> GetAreaStats(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+
+            Area area = new();
+            ScStats areaScStats = new();
+
+            var respSc = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{areaId}", new PartitionKey($"Base-Area"));
+            if (respSc.Status == 200)
+            {
+                using var fileJson = await JsonDocument.ParseAsync(respSc.ContentStream);
+                area = fileJson.ToObject<Area>();
+            }
+            else
+                return Ok(new { state = RespondCode.NotFound, msg = $"未找到id:{areaId};相关的学区,请检查!" });
+
+            List<string> scIds = new();
+            //scIds.Contains
+            string scSql = $"select value(c.id) from c where c.areaId='{areaId}'";
+
+            scIds = await CommonFind.FindScIds(cosmosClient, scSql, "Base");
+
+            //await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<string>(queryText: scSql,requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")} ))
+            //{
+            //    scIds.Add(item);
+            //}
+
+            StringBuilder statsSql = new("select value(c) from c");
+            if (scIds.Count > 0) 
+            {
+                statsSql.Append($" where {BICommonWay.ManyScSql("c.id", scIds)}");
+            }
+
+            List<ScStats> scStats = new();
+            List<StatsInfo> statsInfos = new();
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS,"School").GetItemQueryIterator<StatsInfo>(queryText:statsSql.ToString(),requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Stats") }))
+            {
+                statsInfos.Add(item);
+            }
+
+            StatsInfo statsInfo = new();
+            statsInfo = await SchoolStatsWay.GetAreaStats(cosmosClient, _httpTrigger, _option, statsInfos, scIds);
+
+            return Ok(new { state = RespondCode.Ok ,area, statsInfo, scIds });
+        }
+
 
         /// <summary>
         /// 依据Id查询School容器  数据管理工具——查询工具
@@ -666,10 +740,10 @@ namespace TEAMModelBI.Controllers.Census
             public int size { get; set; }
             public long scCreateTime { get; set; }
             public long upTime { get; set; }
-            public ScLessStats lessStats { get; set; }
-            public ScActStats actStats { get; set; }
+            public ScLessStats lessStats { get; set; } = new ScLessStats();
+            public ScActStats actStats { get; set; } = new ScActStats();
 
-            public ScSRStats srStats { get; set; }
+            public ScSRStats srStats { get; set; } = new ScSRStats();
         }
 
         /// <summary>
@@ -722,10 +796,10 @@ namespace TEAMModelBI.Controllers.Census
         public record ScSRStats 
         { 
             public int learnTime { get; set; }
-            public int onlineTime { get; set; }
-            public int offlineTime { get; set; }
-            public int classTime { get; set; }
-            public int currency { get; set; }
+            public int online { get; set; }
+            public int offline { get; set; }
+            public int classRoom { get; set; }
+            public int submit { get; set; }
             public int notStarted { get; set; }
             public int ongoing { get; set; }
             public int finish { get; set; }

+ 97 - 0
TEAMModelBI/Controllers/RepairApi/NormalController.cs

@@ -0,0 +1,97 @@
+using Azure.Cosmos;
+using DinkToPdf;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK;
+using TEAMModelOS.SDK.Context.Constant;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.DI.CoreAPI;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelBI.Controllers.RepairApi
+{
+    [Route("normal")]
+    [ApiController]
+    public class NormalController : ControllerBase
+    {
+
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly IConfiguration _configuration;
+        private readonly NotificationService _notificationService;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly IHttpClientFactory _http;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly IWebHostEnvironment _environment; //读取文件
+
+        public NormalController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment)
+        {
+            _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _azureStorage = azureStorage;
+            _option = option?.Value;
+            _configuration = configuration;
+            _notificationService = notificationService;
+            _serviceBus = serviceBus;
+            _http = http;
+            _coreAPIHttpService = coreAPIHttpService;
+            _environment = hostingEnvironment;
+        }
+
+        /// <summary>
+        /// 修改学区名称、标准名称、单位
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-areabase")]
+        public async Task<IActionResult> SetAreaBase(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("oldName", out JsonElement oldName)) return BadRequest();
+            if (!jsonElement.TryGetProperty("name", out JsonElement name)) return BadRequest();
+            if(!jsonElement.TryGetProperty("type", out JsonElement type)) return BadRequest();
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            string sql = $"select value(c) from c where c.name = '{oldName}'";
+
+            Area area = new();
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base-Area") }))
+            {
+                area = item;
+            };
+
+            if (!string.IsNullOrEmpty(area.id)) 
+            {
+                area.name = $"{name}";
+                switch ($"{type}")
+                {
+                    case "all":
+                        area.institution = $"{name}";
+                        area.standardName = $"{name}";
+                        break;
+                    case "unit":
+                        area.institution = $"{name}";
+                        break;
+                    case "standard":
+                        area.standardName = $"{name}";
+                        break;
+                }
+
+                area = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<Area>(area, area.id, new PartitionKey("Base-Area"));
+            }
+            return Ok(new { state = RespondCode.Ok, area });
+        }
+
+
+
+    }
+}

+ 33 - 0
TEAMModelBI/Models/ForeEndModel.cs

@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelBI.Models
+{
+    public class ForeEndModel
+    {
+    }
+
+    public record AreaAssist
+    {
+        public string userId { get; set; }
+        public string unionId { get; set; }
+        public string name { get; set; }
+        public string mobile { get; set; }
+        public string avatar { get; set; }
+        public string tmdId { get; set; }
+        public string tmdName { get; set; }
+        public string tmdMobile { get; set; }
+        public string picture { get; set; }
+        public string roles { get; set; }
+        public string schoolIds { get; set; }
+    }
+
+    public record ScBriefInfo
+    {
+        public string id { get; set; }
+        public string name { get; set; }
+        public string picture { get; set; }
+        public int size { get; set; }
+        public List<Period> period { get; set; }
+    }
+}

+ 1 - 0
TEAMModelBI/Startup.cs

@@ -130,6 +130,7 @@ namespace TEAMModelBI
             services.AddHttpClient<NotificationService>();
             services.AddCoreAPIHttpService(Configuration);
             services.AddHttpClient<CoreAPIHttpService>();
+            services.AddHttpClient<HttpTrigger>();
             services.AddMemoryCache();
             services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = false; });
             services.Configure<SysConfig>(Configuration.GetSection("sysConfig"));  //注册连接

+ 0 - 74
TEAMModelBI/Tool/BIStatsWay/SchoolStatsWay.cs

@@ -1,74 +0,0 @@
-using System.Threading.Tasks;
-using System;
-using TEAMModelBI.Models;
-using TEAMModelBI.Tool.CosmosBank;
-using TEAMModelOS.SDK.Models.Cosmos.BI;
-using Azure.Cosmos;
-
-namespace TEAMModelBI.Tool.BIStatsWay
-{
-    public static class SchoolStatsWay
-    {
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="cosmosClient"></param>
-        /// <param name="scId"></param>
-        /// <returns></returns>
-        public static async Task<StatsInfo> upSingleSc(CosmosClient cosmosClient, string scId)
-        {
-
-            StatsInfo statsInfo = new() { id = $"{scId}" };
-
-            DateTimeOffset dateTime = DateTimeOffset.UtcNow;
-            var (dayS, dayE) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间    13位
-            var (lastWeekS, lastWeekE) = TimeHelper.GetStartOrEnd(dateTime, "lastweek");   //计算上周开始/结束时间
-            var (weekS, weekE) = TimeHelper.GetStartOrEnd(dateTime, "week");             //计算本周开始/结束时间
-
-            var (lastTermS, lastTermE) = TimeHelper.GetStartOrEnd(dateTime, "lastterm");   //计算上学期开始/结束时间
-            var (termS, termE) = TimeHelper.GetStartOrEnd(dateTime, "term");   //计算本学期开始/结束时间
-
-            var (lastMthS, LastmthE) = TimeHelper.GetStartOrEnd(dateTime, "lastMonth");  //上月开始/结束时间
-            var (mthS, mthE) = TimeHelper.GetStartOrEnd(dateTime, "month");  //本月开始/结束时间
-
-            var (lastYearS, lastYearE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year - 1}-1-1"), "year"); //计算去年开始/结束时间
-            var (yearS, yearE) = TimeHelper.GetStartOrEnd(dateTime, "year");         //计算今年开始/结束时间
-
-            string currSql = "select value(count(c.id)) from c";
-            string dayWhereSql = $"c.createTime >= {dayS} and c.createTime <= {dayE}";
-            string weekWhereSql = $"c.createTime >= {weekS} and c.createTime <= {weekE}";
-            string monthWhereSql = $"c.createTime >= {mthS} and c.createTime <= {mthE}";
-
-            ScBase scBase = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<ScBase>(statsInfo.id, new PartitionKey("Base"));
-            statsInfo.name = scBase.name;
-            statsInfo.picture = scBase.picture;
-            statsInfo.size = scBase.size;
-            statsInfo.scCreateTime = scBase.createTime;
-
-            string tchSql = $"{currSql} where ARRAY_CONTAINS(c.roles, 'teacher', true) AND c.status = 'join'";
-            statsInfo.tch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", tchSql, code: $"Teacher-{scBase.id}");
-            statsInfo.dayTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and {dayWhereSql} ", code: $"Teacher-{scBase.id}");
-            statsInfo.weekTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {weekWhereSql}", code: $"Teacher-{scBase.id}");
-            statsInfo.monthTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {monthWhereSql}", code: $"Teacher-{scBase.id}");
-
-            statsInfo.stu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", currSql, code: $"Base-{scBase.id}");
-            statsInfo.dayStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {dayWhereSql}", code: $"Base-{scBase.id}");
-            statsInfo.weekStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {weekWhereSql}", code: $"Base-{scBase.id}");
-            statsInfo.monthStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {monthWhereSql}", code: $"Base-{scBase.id}");
-
-            statsInfo.room = await JointlySingleQuery.GetValueInt(cosmosClient, "School", currSql, code: $"Room-{scBase.id}");
-            statsInfo.witRoom = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{currSql} where (c.serial != null or c.serial != '' or IS_DEFINED(c.serial) = true)", code: $"Room-{scBase.id}");
-
-
-            statsInfo.lesson = await LessonRecordStatsWay.GetLessStats(cosmosClient, statsInfo.id);
-            statsInfo.activity = await ActivityStatsWay.GetActStats(cosmosClient, statsInfo.id);
-
-
-
-
-            return statsInfo;
-        }
-
-    }
-}

+ 0 - 77
TEAMModelBI/Tool/BIStatsWay/StudyStatsWay.cs

@@ -1,77 +0,0 @@
-using Azure.Cosmos;
-using System.Collections.Generic;
-using System.Text.Json;
-using System.Threading.Tasks;
-using TEAMModelBI.Models;
-using TEAMModelOS.SDK.Models;
-using TEAMModelOS.SDK.Models.Cosmos.BI;
-
-namespace TEAMModelBI.Tool.BIStatsWay
-{
-    public static class StudyStatsWay
-    {
-        /// <summary>
-        /// 学校研修统计
-        /// </summary>
-        /// <param name="cosmosClient"></param>
-        /// <param name="scId"></param>
-        /// <returns></returns>
-        public static async Task<StudyStats> GetStudyStats(CosmosClient cosmosClient, string scId)
-        {
-            StudyStats studyStats = new();
-            List<AreaStudy> trains = new();
-
-            School rschool = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemAsync<School>($"{scId}", new PartitionKey("AreaSetting"));
-
-            AreaSetting setting = null;
-
-            var responSett = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"123", new PartitionKey("AreaSetting"));
-            if (responSett.Status == 200) 
-            {
-                
-            }
-            if (setting == null)
-            {
-                setting = new AreaSetting
-                {
-                    allTime = 50,
-                    classTime = 5,
-                    submitTime = 15,
-                    onlineTime = 20,
-                    offlineTime = 10,
-                    lessonMinutes = 45,
-                };
-            }
-
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<AreaStudy>(queryText: $"select c.id,c.code,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and c.school='{scId}'", requestOptions: new QueryRequestOptions() { }))
-            {
-                trains.Add(item);
-            }
-
-
-
-            //trains.ForEach(x =>
-            //{
-            //    //线上研修
-            //    if (x.onlineTime == 0) studyStats++; else if (x.onlineTime >= setting.onlineTime) onLineCount++; else onLineCount++;
-
-            //    //线下研修
-            //    if (x.offlineTime == 0) offlineCount++; else if (x.onlineTime >= setting.offlineTime) offlineCount++; else offlineCount++;
-
-            //    //课堂实录
-            //    if (x.classTime == 0) classRoomCount++; else if (x.classTime >= setting.classTime) classRoomCount++; else classRoomCount++;
-
-            //    //认证材料
-            //    if (x.currency.submitTime == 0) submitCount++; else if (x.currency.submitTime >= setting.submitTime) submitCount++; else submitCount++;
-
-            //    if (x.currency.submitTime == 0 && x.classTime == 0 && x.offlineTime == 0 && x.onlineTime == 0) noCount++;
-            //    else if (x.currency.submitTime >= setting.submitTime && x.classTime >= setting.classTime && x.onlineTime >= setting.offlineTime && x.onlineTime >= setting.onlineTime) fulfilCount++;
-            //    else carryOnCount++;
-            //});
-
-
-
-            return studyStats;
-        }
-    }
-}

+ 11 - 7
TEAMModelBI/Tool/CommonFind.cs

@@ -134,16 +134,20 @@ namespace TEAMModelBI.Tool
         public static async Task<List<string>> FindScIds(CosmosClient cosmosClient, string sqlTxt, string code)
         {
             List<string> schoolIds = new();
-
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
             {
-                using var json = await JsonDocument.ParseAsync(item.ContentStream);
-                foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
-                {
-                    schoolIds.Add(obj.GetProperty("id").GetString());
-                }
+                schoolIds.Add(item);
             }
 
+            //await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
+            //{
+            //    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+            //    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+            //    {
+            //        schoolIds.Add(obj.GetProperty("id").GetString());
+            //    }
+            //}
+
             return schoolIds;
         }
 

+ 82 - 0
TEAMModelBI/Tool/CosmosBank/JointlySingleQuery1.cs

@@ -0,0 +1,82 @@
+using Azure.Cosmos;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace TEAMModelBI.Tool.CosmosBank
+{
+    public class JointlySingleQuery1
+    {
+        /// <summary>
+        /// 多个容器返回整数 使用
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="containerId"></param>
+        /// <param name="sqlTxt"></param>
+        /// <param name="code"></param>
+        /// <returns></returns>
+        public static async Task<int> GetValueInt(CosmosClient cosmosClient, List<string> containerId, string sqlTxt = null, string code = null) 
+        {
+            int totals = 0;
+            string sql = $"select value(count(c.id)) from c";
+            if (!string.IsNullOrEmpty(sqlTxt)) 
+            {
+                sql = sqlTxt;
+            }
+
+            foreach (string conId in containerId) 
+            {
+                await foreach (var itemInt in cosmosClient.GetContainer("TEAMModelOS", conId).GetItemQueryIterator<int>(queryText: sql, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+                {
+                    totals += itemInt;
+                }
+            }
+
+            return totals;            
+        }
+
+        /// <summary>
+        /// 单个容器返回整数 统计使用
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="container"></param>
+        /// <param name="sqlTxt"></param>
+        /// <param name="code"></param>
+        /// <returns></returns>
+        public static async Task<int> GetValueInt(CosmosClient cosmosClient, string container, string sqlTxt = null, string code = null)
+        {
+            int totals = 0;
+            string sql = $"select value(count(c.id)) from c";
+            if (!string.IsNullOrEmpty(sqlTxt))
+            {
+                sql = sqlTxt;
+            }
+
+            await foreach (var itemInt in cosmosClient.GetContainer("TEAMModelOS", container).GetItemQueryIterator<int>(queryText: sql, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+            {
+                totals += itemInt;
+            }
+
+            return totals;
+        }
+
+        /// <summary>   
+        /// 返回字符集合
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="containerId"></param>
+        /// <param name="sqlTxt"></param>
+        /// <param name="code"></param>
+        /// <returns></returns>
+        public static async Task<List<string>> GetListString(CosmosClient cosmosClient, string containerId, string sqlTxt, string code = null) 
+        {
+            List<string> strList = new();
+
+            await foreach (var itemInt in cosmosClient.GetContainer("TEAMModelOS", containerId).GetItemQueryIterator<string>(queryText: sqlTxt, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+            {
+                strList.Add(itemInt);
+            }
+
+            return strList;
+        }
+    }
+}

+ 1 - 0
TEAMModelBI/Tool/CosmosBank/StatsWay.cs

@@ -8,6 +8,7 @@ using System.Threading.Tasks;
 using TEAMModelBI.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BITable;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Tool.CosmosBank
 {

+ 456 - 0
TEAMModelBI/Tool/TimeHelper1.cs

@@ -0,0 +1,456 @@
+using DocumentFormat.OpenXml.Bibliography;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelBI.Models;
+using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+
+namespace TEAMModelBI.Tool
+{
+    public static class TimeHelper1
+    {
+        /// <summary>
+        /// 平年
+        /// </summary>
+        public static List<int> flatY = new() { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+        /// <summary>
+        /// 闰年
+        /// </summary>
+        public static List<int> leapY = new() { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+        /// <summary>
+        /// 通过时间戳转换为时间
+        /// </summary>
+        /// <param name="timeStamp"></param>
+        /// <returns></returns>
+        public static DateTimeOffset GetDateTime(long timeStamp)
+        {
+            long begtime = timeStamp * 10000;
+            DateTimeOffset dt_1970 = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
+            long tricks_1970 = dt_1970.Ticks;//1970年1月1日刻度
+            long time_tricks = tricks_1970 + begtime;//日志日期刻度
+            DateTimeOffset dt = new DateTime(time_tricks);//转化为DateTime
+            return dt;
+        }
+
+        /// <summary>
+        ///  通过string装换为时间并获取时间的年、月、日、一年第几天、小时
+        /// </summary>
+        /// <param name="time">时间,例如:2022060706</param>
+        /// <param name="timeStrType">时间类型: 例如:yyyyMMddHH </param>
+        /// <returns></returns>
+        public static (int year,int month,int day, int days, int hour) GetDateTime(string time, string timeStrType = null)  
+        {
+            string type = "yyyyMMddHH";
+            if (!string.IsNullOrEmpty(timeStrType)) 
+            {
+                type = timeStrType;
+            }
+
+            int year = 0, month = 0, day = 0, days = 0, hour = 0;
+            DateTimeOffset dateTime = new();
+            dateTime = DateTime.ParseExact(time, type, System.Globalization.CultureInfo.CurrentCulture);
+            year = dateTime.Year;
+            month = dateTime.Month;
+            day = dateTime.Day;
+            DateTimeOffset dt1 = new DateTime(year, 1, 1);
+
+            days = (dateTime.Date - dt1.Date).Days + 1;
+            hour = dateTime.Hour;
+
+            return (year, month, day, days, hour);
+        }
+
+        /// <summary>
+        /// 获取月份的开始和结束时间戳   13位
+        /// </summary>
+        /// <param name="year"></param>
+        /// <param name="month"></param>
+        /// <returns></returns>
+        public static (long start, long end) GetMonthStartEnd(int year, int month, bool dateLenth = true)
+        {
+            DateTimeOffset dtNew = new(year, month, 1, 0, 0, 0, TimeSpan.Zero);
+            long start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeMilliseconds();
+            if (dateLenth == false) start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeSeconds();
+            var ste = dtNew.AddMonths(1).AddDays(-1).Day;
+            long end = new DateTimeOffset(dtNew.Year, dtNew.Month, ste, 23, 59, 59,TimeSpan.Zero).ToUnixTimeMilliseconds();
+            // DateTimeOffset.Parse($"{dt.Year}-{dt.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
+            if (dateLenth == false) end = new DateTimeOffset(dtNew.Year, dtNew.Month, dtNew.Day, 23, 59, 59, TimeSpan.Zero).ToUnixTimeSeconds();
+            //DateTimeOffset.Parse($"{dt.Year}-{dt.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
+
+            return (start, end);
+        }
+
+        /// <summary>
+        /// 通过时间获取当前年开始月份到现在月的开始时间到结束时间  现在月是当前天的结束时间
+        /// </summary>
+        /// <param name="date"></param>
+        /// <param name="dateLenth"></param>
+        /// <returns></returns>
+        public static async Task<List<StartEndTime>> GetYearSataMthCtMth(DateTimeOffset date,bool dateLenth = true) 
+        {
+            int year = date.Year;
+            int mth = date.Month;
+            int day = date.Day;
+
+            List<StartEndTime> monthStartEnds = new();
+            for (int i = 1; i <= mth; i++)
+            {
+                StartEndTime monthStartEnd = new() { date = $"{year}-{i}" };
+                //DateTime dt = DateTime.Parse($"{year}-{i}");
+                DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
+                long start = dtNew.ToUnixTimeMilliseconds();
+                if (dateLenth == false)
+                    start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeSeconds();
+                monthStartEnd.start = start;
+                long end = 0;
+                if (i == mth)
+                {
+                    end = DateTimeOffset.Parse($"{year}-{mth}-{day} 23:59:59").ToUnixTimeMilliseconds();
+                    if (dateLenth == false)
+                        end = DateTimeOffset.Parse($"{year}-{mth}-{day} 23:59:59").ToUnixTimeSeconds();
+                }
+                else
+                {
+                    var ste = dtNew.AddMonths(1).AddDays(-1).Day;
+                    end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
+                    if (dateLenth == false)
+                        end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
+                }
+                monthStartEnd.end = end;
+                monthStartEnds.Add(monthStartEnd);
+            }
+
+            return monthStartEnds;
+        }
+
+        /// <summary>
+        /// 获取今年12个月的月份开始和结束时间戳 13位 10位  
+        /// </summary>
+        /// <param name="year">年份</param>
+        /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
+        /// <returns></returns>
+        public static List<StartEndTime> GetYearMonthlyStartEnd(int year, bool dateLenth = true)
+        {
+            List<StartEndTime> monthStartEnds = new();
+            for (int i = 1; i <= 12; i++)
+            {
+                StartEndTime monthStartEnd = new StartEndTime() { date = $"{year}-{i}" };
+                //DateTime dt = DateTime.Parse($"{year}-{i}");
+                DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
+                long start = dtNew.ToUnixTimeMilliseconds();
+                if (dateLenth == false) 
+                    start = dtNew.ToUnixTimeSeconds();
+                monthStartEnd.start = start;
+                var ste = dtNew.AddMonths(1).AddDays(-1).Day;
+                long end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
+                if (dateLenth == false) 
+                    end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
+                monthStartEnd.end = end;
+                monthStartEnds.Add(monthStartEnd);
+            }
+
+            return monthStartEnds;
+        }
+
+        /// <summary>
+        /// 获取过去12个月的每月开始和结束的时间戳
+        /// </summary>
+        /// <param name="yearMonth">日期</param>
+        /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
+        /// <returns></returns>
+        public static List<StartEndTime> monthsOfYear(string yearMonth, bool dateLenth = true)
+        {
+            List<StartEndTime> monthStartEnds = new();
+            DateTime dateTime = DateTime.Parse(yearMonth);
+
+            int year = dateTime.Year;
+            int month = dateTime.Month;
+            List<string> months = new();
+            while (year > dateTime.Year - 1 || month > dateTime.Month)
+            {
+                StartEndTime monthStartEnd = new() { date = $"{year}-{month}" };
+
+                DateTimeOffset dtNew = new(year, month, 1, 0, 0, 0, TimeSpan.Zero);
+                long start = dateLenth ? dtNew.ToUnixTimeMilliseconds() : dtNew.ToUnixTimeSeconds();
+                monthStartEnd.start = start;
+                var ste = dtNew.AddMonths(1).AddDays(-1).Day;
+                long end = dateLenth ? DateTimeOffset.Parse($"{dateTime.Year}-{dateTime.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{dateTime.Year}-{dateTime.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
+                monthStartEnd.end = end;
+
+                monthStartEnds.Add(monthStartEnd);
+                
+                months.Add($"{year}-{(month < 10 ? "0" : "") + month}");
+                month -= 1;
+                if (month <= 0)
+                {
+                    year -= 1;
+                    month = 12;
+                }
+            }
+
+            return monthStartEnds;
+        }
+
+        /// <summary>
+        /// 获取传过来的时间学期的开始时间戳和结束时间  
+        /// </summary>
+        /// <param name="dateTime">日期</param>
+        /// <param name="dateLenth">true :13位时间戳  false:10位时间戳 </param>
+        /// <returns></returns>
+        public static (long start, long end) GetTermStartOrEnd(DateTimeOffset dateTime, bool dateLenth = true)
+        {
+            long start = 0; 
+            long end = 0;
+            //DateTime dateTime = tempDateTime;
+            int year = dateTime.Year;
+            int month = dateTime.Month;
+            if (month <= 8 && month >= 3)
+            {
+                DateTimeOffset newStart = new(year, 3, 1, 0, 0, 0, TimeSpan.Zero);
+                start = dateLenth ? DateTimeOffset.Parse($"{newStart}").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{newStart}").ToUnixTimeSeconds();
+
+                DateTimeOffset newEnd = new(year, 8, 31, 23, 59, 59, TimeSpan.Zero);
+                end = dateLenth ? DateTimeOffset.Parse($"{newEnd}").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{newEnd}").ToUnixTimeSeconds();
+            }
+            else
+            {
+                //计算当前月份
+                int days = 0;
+                if (month >= 9)
+                {
+                    DateTimeOffset newStart = new(dateTime.Year, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                    start = dateLenth ? newStart.ToUnixTimeMilliseconds() : newStart.ToUnixTimeSeconds();
+
+                    DateTimeOffset newEnd = new(dateTime.Year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                    end = dateLenth ? newEnd.ToUnixTimeMilliseconds() : newEnd.ToUnixTimeSeconds();
+                }
+                else
+                {
+                    DateTimeOffset newStart = new(dateTime.Year - 1, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                    start = dateLenth ? newStart.ToUnixTimeMilliseconds() : newStart.ToUnixTimeSeconds();
+
+                    DateTimeOffset newEnd = new(dateTime.Year, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                    end = dateLenth ? newEnd.ToUnixTimeMilliseconds() : newEnd.ToUnixTimeSeconds();
+                }
+            }
+
+            return (start, end);
+        }
+
+        /// <summary>
+        /// 开始时间和结束时间戳
+        /// </summary>
+        /// <param name="dateTime"></param>
+        /// <param name="type"></param>
+        /// <param name="dateLenth"></param>
+        /// <returns></returns>
+        public static (long start, long end) GetStartOrEnd(DateTimeOffset dateTime, string type = "", bool dateLenth = true)
+        {
+            try
+            {
+                long start = 0;
+                long end = 0;
+                int year = dateTime.Year;
+                int month = dateTime.Month;
+                int day = dateTime.Day;
+                int hour = dateTime.Hour;
+                DateTimeOffset tempStrart = new();
+                DateTimeOffset tempEnd = new();
+                switch (type)
+                {
+                    //今年开始、结束
+                    case "yearMonth":
+                        tempStrart = new DateTimeOffset(year, 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, DateTime.DaysInMonth(year, month), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //今年开始、结束
+                    case "year":
+                        tempStrart = new DateTimeOffset(year, 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, 12, DateTime.DaysInMonth(year, 12), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //去年开始、结束
+                    case "lastYear":
+                        tempStrart = new DateTimeOffset(year - 1, 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year - 1, 12, DateTime.DaysInMonth(year, 12), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //本学期
+                    case "term":
+                        if (month <= 8 && month >= 3)
+                        {
+                            tempStrart = new DateTimeOffset(year, 3, 1, 0, 0, 0, TimeSpan.Zero);
+                            tempEnd = new DateTimeOffset(year, 8, 31, 23, 59, 59, TimeSpan.Zero);
+                        }
+                        else
+                        {
+                            //计算当前月份
+                            int days = 0;
+                            if (month >= 9)
+                            {
+                                tempStrart = new DateTimeOffset(year, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                                tempEnd = new DateTimeOffset(year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                            }
+                            else
+                            {
+                                tempStrart = new DateTimeOffset(year - 1, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                                tempEnd = new DateTimeOffset(year, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                            }
+                        }
+                        break;
+                    //上学期
+                    case "lastterm":
+                        DateTimeOffset tempDate = new();
+                        if (dateTime.Month > 9)
+                            tempDate = new DateTimeOffset(year, dateTime.Month - 4, 1, 0, 0, 0, TimeSpan.Zero);
+                        else tempDate = new DateTimeOffset(year - 1, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                        if (!string.IsNullOrEmpty($"{tempDate}"))
+                        {
+                            year = tempDate.Year;
+                            month = tempDate.Month;
+                            if (month <= 8 && month >= 3)
+                            {
+                                tempStrart = new DateTimeOffset(year, 3, 1, 0, 0, 0, TimeSpan.Zero);
+                                tempEnd = new DateTimeOffset(year, 8, 31, 23, 59, 59,TimeSpan.Zero);
+                            }
+                            else
+                            {
+                                //计算当前月份
+                                int days = 0;
+                                if (month >= 9)
+                                {
+                                    tempStrart = new DateTimeOffset(year, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                                    tempEnd = new DateTimeOffset(year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59,TimeSpan.Zero);
+                                }
+                                else
+                                {
+                                    tempStrart = new DateTimeOffset(year - 1, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                                    tempEnd = new DateTimeOffset(year, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                                }
+                            }
+                        }
+                        break;
+                    //上个月
+                    case "lastMonth":
+                        tempStrart = new DateTimeOffset(year, month - 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month - 1, DateTime.DaysInMonth(year, month - 1), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //本月1号至当天
+                    case "monthDay":
+                        tempStrart = new DateTimeOffset(year, month, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, day, 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //本月
+                    case "month":
+                        tempStrart = new DateTimeOffset(year, month, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, DateTime.DaysInMonth(year, month), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //上周
+                    case "week":
+                        DateTimeOffset weekStrart = dateTime.AddDays(-(int)(dateTime.DayOfWeek) + 1);
+                        DateTimeOffset weekEnd = dateTime.AddDays(7 - (int)(dateTime.DayOfWeek));
+                        tempStrart = new DateTimeOffset(weekStrart.Year, weekStrart.Month, weekStrart.Day, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(weekEnd.Year, weekEnd.Month, weekEnd.Day, 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //上周
+                    case "lastweek":
+                        var m = (dateTime.DayOfWeek == DayOfWeek.Sunday ? (DayOfWeek)7 : dateTime.DayOfWeek) - DayOfWeek.Monday;
+                        var s = (dateTime.DayOfWeek == DayOfWeek.Sunday ? (DayOfWeek)7 : dateTime.DayOfWeek) - (DayOfWeek)7;
+                        var Mon = dateTime.AddDays((-7 - m));//星期一
+                        var Sun = dateTime.AddDays((-7 - s));  //星期日
+                        tempStrart = new DateTimeOffset(Mon.Year, Mon.Month, Mon.Day, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(Sun.Year, Sun.Month, Sun.Day, 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //当前小时
+                    case "hour":
+                        tempStrart = new DateTimeOffset(year, month, day, hour, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, day, hour, 59, 59, TimeSpan.Zero);
+
+                        break;
+                    //当天
+                    default:
+                        tempStrart = new DateTimeOffset(year, month, day, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, day, 23, 59, 59, TimeSpan.Zero);
+                        //start = dateLenth ? DateTimeOffset.Parse($"{dayStart}").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{dayStart}").ToUnixTimeSeconds();
+                        //end = dateLenth ? DateTimeOffset.Parse($"{dayEnd}").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{dayEnd}").ToUnixTimeSeconds();
+                        break;
+                }
+
+                start = dateLenth ? tempStrart.ToUnixTimeMilliseconds() : tempStrart.ToUnixTimeSeconds();
+                end = dateLenth ? tempEnd.ToUnixTimeMilliseconds() : tempEnd.ToUnixTimeSeconds();
+
+                return (start, end);
+            }
+            catch (Exception ex)
+            {
+                throw;
+            }
+        }
+
+        /// <summary>
+        /// 将时间戳格式 转换成string类型
+        /// 例:yyyyMMdd,等string类型
+        /// </summary>
+        /// <param name="unixTime"></param>
+        /// <returns></returns>
+        public static (string timeStart,string timeEnd) GetUnixToDate(long start,long end = 0,string types="yyyyMMdd")
+        {
+            string tStart = "";
+            string tEnd = "";
+            DateTimeOffset time = System.TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0));
+            tStart = time.AddMilliseconds(start).ToString($"{types}");
+            if (end > 0) 
+            {
+                tEnd = time.AddMilliseconds(end).ToString($"{types}");
+            }
+
+            return (tStart, tEnd);
+        }
+
+        /// <summary>
+        /// 获取每天的时间
+        /// </summary>
+        /// <param name="dateTime">时间</param>
+        /// <param name="dayNumber">最近几天</param>
+        /// <returns></returns>
+        public static List<string> GetNearDay(DateTimeOffset dateTime,int dayNumber)
+        {
+            List<string> days = new();
+
+            days = Enumerable.Range(1, dayNumber).Select(i => dateTime.Date.AddDays(-i).ToString("yyyyMMdd")).ToList();
+
+            return days;
+        }
+
+
+        public static List<YearMonth> GetYearMonth(List<double> doubles, int year = 0,int month = 0) 
+        {
+            List<YearMonth> months = new();
+            DateTimeOffset dateTime = DateTimeOffset.Now;
+            if (year == 0) 
+                year = dateTime.Year;
+            if(month == 0)
+                month = dateTime.Month;
+
+            List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
+            double[] array = doubles.ToArray();
+            double ser = doubles.Sum();
+            int moth = 1;
+            int primaryD = 0;
+            for (int i = 0; i < isLeapYear.Count; i++)
+            {
+                if (month < moth)
+                    break;
+                double[] temp = new double[isLeapYear[i]];
+                Array.ConstrainedCopy(array, primaryD, temp, 0, isLeapYear[i]);
+                months.Add(new YearMonth() { id = $"{year}-{moth}", cnt = temp.Sum() });
+                moth += 1;
+                primaryD += isLeapYear[i];
+            }
+
+            return months;
+        }
+    }
+}

+ 66 - 2
TEAMModelOS.FunctionV4/HttpTrigger/BIHttpTrigger.cs

@@ -1,9 +1,21 @@
+using System;
 using System.Collections.Generic;
+using System.Dynamic;
+using System.IO;
 using System.Net;
 using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Azure.Cosmos;
+using Azure.Storage.Blobs;
+using Microsoft.AspNetCore.Http;
 using Microsoft.Azure.Functions.Worker;
 using Microsoft.Azure.Functions.Worker.Http;
+using StackExchange.Redis;
 using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BIStatsWay;
 
 namespace TEAMModelOS.FunctionV4.HttpTrigger
 {
@@ -15,7 +27,6 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
         private readonly AzureRedisFactory _azureRedis;
         private readonly HttpClient _httpClient;
 
-
         public BIHttpTrigger(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, HttpClient httpClient)
         {
             _azureCosmos = azureCosmos;
@@ -31,10 +42,63 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
         /// <param name="req"></param>
         /// <returns></returns>
         [Function("stats-sc-info")]
-        public HttpResponseData StatsSchoolInfo([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestData req)
+        public async Task<HttpResponseData> StatsSchoolInfo([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req)
         {
             var response = req.CreateResponse(HttpStatusCode.OK);
 
+            dynamic jsondata = new ExpandoObject();
+            try
+            {
+                string scId = null;
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                var tableClient = _azureStorage.GetCloudTableClient();
+                var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
+                string data = await new StreamReader(req.Body).ReadToEndAsync();
+                var json = JsonDocument.Parse(data).RootElement;
+                jsondata = json;
+                if (json.TryGetProperty("schoolId", out JsonElement _schoolId))
+                {
+                    scId = $"{_schoolId}";
+                }
+                if (string.IsNullOrEmpty(scId))
+                {
+                    return response;
+                }
+
+                bool locKey = await _azureRedis.GetRedisClient(8).KeyExistsAsync($"Train:Statistics:Lock:{scId}");
+                if (!locKey)
+                {
+                    await _azureRedis.GetRedisClient(8).SetAddAsync($"Train:Statistics:Lock:{scId}", new RedisValue(scId));
+                    DateTime minutes = DateTime.UtcNow.AddMinutes(15);   //15分钟
+                    await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Train:Statistics:Lock:{scId}", minutes);
+
+                    bool isExist = true;
+                    StatsInfo statsInfo = new();
+                    var scDataStats = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey("Stats"));
+                    if (scDataStats.Status == 200)
+                    {
+                        using var fileJson = await JsonDocument.ParseAsync(scDataStats.ContentStream);
+                        statsInfo = fileJson.ToObject<StatsInfo>();
+                    }
+                    else                    
+                        isExist = false;
+
+                    statsInfo = await SchoolStatsWay.GetSingleSc(cosmosClient, scId);
+                    statsInfo.upTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+
+                    if (isExist)
+                        statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<StatsInfo>(statsInfo, statsInfo.id, new PartitionKey("Stats"));
+                    else
+                        statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<StatsInfo>(statsInfo, new PartitionKey("Stats"));
+                }
+
+                //保存操作记录
+                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "trigger-schoolStats", $"触发更新统计数据库", _dingDing);
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"stats-sc-info,{ex.Message}\n{ex.StackTrace}\n{jsondata.ToJsonString()}", GroupNames.成都开发測試群組);
+            }
 
             return response;
         }

+ 2 - 2
TEAMModelOS.SDK/Models/Cosmos/BI/BICommon/MonthStartEnd.cs

@@ -6,9 +6,9 @@ using System.Threading.Tasks;
 
 namespace TEAMModelOS.SDK.Models
 {
-    public class MonthStartEnd
+    public class StartEndTime
     {
-        public string yearMonth { get; set; }
+        public string date { get; set; }
 
         public long start { get; set; }
 

+ 19 - 17
TEAMModelBI/Models/FrontModel.cs

@@ -1,19 +1,13 @@
-using TEAMModelOS.SDK.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 
-namespace TEAMModelBI.Models
+namespace TEAMModelOS.SDK.Models.Cosmos.BI
 {
-    /// <summary>
-    /// 前端显示相关的结构
-    /// </summary>
-    public class FrontModel
-    {
-    }
-
-    public class YearMonth
+    public class CurrencyModel
     {
-        public string id { get; set; }
-
-        public double cnt { get; set; }
     }
 
     /// <summary>
@@ -29,6 +23,16 @@ namespace TEAMModelBI.Models
         public long createTime { get; set; }
     }
 
+    /// <summary>
+    /// 
+    /// </summary>
+    public class YearMonth
+    {
+        public string id { get; set; }
+
+        public double cnt { get; set; }
+    }
+
     /// <summary>
     /// 研修活动统计
     /// </summary>
@@ -38,6 +42,8 @@ namespace TEAMModelBI.Models
 
         public string code { get; set; }
 
+        public int totalTime { get; set; }
+
         /// <summary>
         /// 线上观看视频的学时
         /// </summary>
@@ -56,8 +62,4 @@ namespace TEAMModelBI.Models
         /// </summary>
         public Currency currency { get; set; } = new Currency();
     }
-
-
-
-
 }

+ 12 - 12
TEAMModelOS.SDK/Models/Cosmos/BI/StatsInfo.cs

@@ -28,6 +28,11 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// </summary>
         public string name { get; set; }
 
+        /// <summary>
+        /// 空间
+        /// </summary>
+        public int size { get; set; }
+
         /// <summary>
         /// 教师总数
         /// </summary>
@@ -78,11 +83,6 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// </summary>
         public int witRoom { get; set; }
 
-        /// <summary>
-        /// 空间
-        /// </summary>
-        public int size { get; set; }
-
         /// <summary>
         /// 学校创建时间
         /// </summary>
@@ -96,17 +96,17 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// <summary>
         /// 课例活动
         /// </summary>
-        public LessonStats lesson { get; set; }
+        public LessonStats lesson { get; set; } = new LessonStats();
 
         /// <summary>
         /// 活动
         /// </summary>
-        public ActivityStats activity { get; set; }
+        public ActivityStats activity { get; set; } = new ActivityStats();
 
         /// <summary>
         /// 研修统计
         /// </summary>
-        public StudyStats study { get; set; }
+        public StudyStats study { get; set; } = new StudyStats();
     }
 
     /// <summary>
@@ -268,19 +268,19 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// <summary>
         /// 线上研修人数
         /// </summary>
-        public int onlineTime { get; set; }
+        public int online { get; set; }
         /// <summary>
         /// 线下研修人数
         /// </summary>
-        public int offlineTime { get; set; }
+        public int offline { get; set; }
         /// <summary>
         /// 课堂实录人数
         /// </summary>
-        public int classTime { get; set; }
+        public int classRoom { get; set; }
         /// <summary>
         /// 认证材料人数
         /// </summary>
-        public int currency { get; set; }
+        public int submit { get; set; }
         /// <summary>
         /// 未开始的研修人数
         /// </summary>

+ 9 - 6
TEAMModelBI/Tool/CosmosBank/JointlySingleQuery.cs

@@ -1,8 +1,11 @@
 using Azure.Cosmos;
+using System;
 using System.Collections.Generic;
+using System.Linq;
+using System.Text;
 using System.Threading.Tasks;
 
-namespace TEAMModelBI.Tool.CosmosBank
+namespace TEAMModelOS.SDK.Models.Service.BI
 {
     public class JointlySingleQuery
     {
@@ -14,16 +17,16 @@ namespace TEAMModelBI.Tool.CosmosBank
         /// <param name="sqlTxt"></param>
         /// <param name="code"></param>
         /// <returns></returns>
-        public static async Task<int> GetValueInt(CosmosClient cosmosClient, List<string> containerId, string sqlTxt = null, string code = null) 
+        public static async Task<int> GetValueInt(CosmosClient cosmosClient, List<string> containerId, string sqlTxt = null, string code = null)
         {
             int totals = 0;
             string sql = $"select value(count(c.id)) from c";
-            if (!string.IsNullOrEmpty(sqlTxt)) 
+            if (!string.IsNullOrEmpty(sqlTxt))
             {
                 sql = sqlTxt;
             }
 
-            foreach (string conId in containerId) 
+            foreach (string conId in containerId)
             {
                 await foreach (var itemInt in cosmosClient.GetContainer("TEAMModelOS", conId).GetItemQueryIterator<int>(queryText: sql, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
                 {
@@ -31,7 +34,7 @@ namespace TEAMModelBI.Tool.CosmosBank
                 }
             }
 
-            return totals;            
+            return totals;
         }
 
         /// <summary>
@@ -67,7 +70,7 @@ namespace TEAMModelBI.Tool.CosmosBank
         /// <param name="sqlTxt"></param>
         /// <param name="code"></param>
         /// <returns></returns>
-        public static async Task<List<string>> GetListString(CosmosClient cosmosClient, string containerId, string sqlTxt, string code = null) 
+        public static async Task<List<string>> GetListString(CosmosClient cosmosClient, string containerId, string sqlTxt, string code = null)
         {
             List<string> strList = new();
 

+ 95 - 47
TEAMModelBI/Tool/TimeHelper.cs

@@ -1,12 +1,13 @@
 using DocumentFormat.OpenXml.Bibliography;
+using Microsoft.Azure.Amqp.Framing;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Text;
 using System.Threading.Tasks;
-using TEAMModelBI.Models;
-using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
 
-namespace TEAMModelBI.Tool
+namespace TEAMModelOS.SDK.Models.Service.BI
 {
     public static class TimeHelper
     {
@@ -41,10 +42,10 @@ namespace TEAMModelBI.Tool
         /// <param name="time">时间,例如:2022060706</param>
         /// <param name="timeStrType">时间类型: 例如:yyyyMMddHH </param>
         /// <returns></returns>
-        public static (int year,int month,int day, int days, int hour) GetDateTime(string time, string timeStrType = null)  
+        public static (int year, int month, int day, int days, int hour) GetDateTime(string time, string timeStrType = null)
         {
             string type = "yyyyMMddHH";
-            if (!string.IsNullOrEmpty(timeStrType)) 
+            if (!string.IsNullOrEmpty(timeStrType))
             {
                 type = timeStrType;
             }
@@ -75,7 +76,7 @@ namespace TEAMModelBI.Tool
             long start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeMilliseconds();
             if (dateLenth == false) start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeSeconds();
             var ste = dtNew.AddMonths(1).AddDays(-1).Day;
-            long end = new DateTimeOffset(dtNew.Year, dtNew.Month, ste, 23, 59, 59,TimeSpan.Zero).ToUnixTimeMilliseconds();
+            long end = new DateTimeOffset(dtNew.Year, dtNew.Month, ste, 23, 59, 59, TimeSpan.Zero).ToUnixTimeMilliseconds();
             // DateTimeOffset.Parse($"{dt.Year}-{dt.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
             if (dateLenth == false) end = new DateTimeOffset(dtNew.Year, dtNew.Month, dtNew.Day, 23, 59, 59, TimeSpan.Zero).ToUnixTimeSeconds();
             //DateTimeOffset.Parse($"{dt.Year}-{dt.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
@@ -89,16 +90,16 @@ namespace TEAMModelBI.Tool
         /// <param name="date"></param>
         /// <param name="dateLenth"></param>
         /// <returns></returns>
-        public static async Task<List<MonthStartEnd>> GetYearSataMthCtMth(DateTimeOffset date,bool dateLenth = true) 
+        public static async Task<List<StartEndTime>> GetYearSataMthCtMth(DateTimeOffset date, bool dateLenth = true)
         {
             int year = date.Year;
             int mth = date.Month;
             int day = date.Day;
 
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             for (int i = 1; i <= mth; i++)
             {
-                MonthStartEnd monthStartEnd = new() { yearMonth = $"{year}-{i}" };
+                StartEndTime monthStartEnd = new() { date = $"{year}-{i}" };
                 //DateTime dt = DateTime.Parse($"{year}-{i}");
                 DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dtNew.ToUnixTimeMilliseconds();
@@ -132,21 +133,21 @@ namespace TEAMModelBI.Tool
         /// <param name="year">年份</param>
         /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
         /// <returns></returns>
-        public static List<MonthStartEnd> GetYearMonthlyStartEnd(int year, bool dateLenth = true)
+        public static List<StartEndTime> GetYearMonthlyStartEnd(int year, bool dateLenth = true)
         {
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             for (int i = 1; i <= 12; i++)
             {
-                MonthStartEnd monthStartEnd = new MonthStartEnd() { yearMonth = $"{year}-{i}" };
+                StartEndTime monthStartEnd = new() { date = $"{year}-{i}" };
                 //DateTime dt = DateTime.Parse($"{year}-{i}");
                 DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dtNew.ToUnixTimeMilliseconds();
-                if (dateLenth == false) 
+                if (dateLenth == false)
                     start = dtNew.ToUnixTimeSeconds();
                 monthStartEnd.start = start;
                 var ste = dtNew.AddMonths(1).AddDays(-1).Day;
                 long end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
-                if (dateLenth == false) 
+                if (dateLenth == false)
                     end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
                 monthStartEnd.end = end;
                 monthStartEnds.Add(monthStartEnd);
@@ -161,17 +162,17 @@ namespace TEAMModelBI.Tool
         /// <param name="yearMonth">日期</param>
         /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
         /// <returns></returns>
-        public static List<MonthStartEnd> monthsOfYear(string yearMonth, bool dateLenth = true)
+        public static List<StartEndTime> monthsOfYear(string yearMonth, bool dateLenth = true)
         {
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             DateTime dateTime = DateTime.Parse(yearMonth);
 
             int year = dateTime.Year;
             int month = dateTime.Month;
-            List<string> months = new List<string>();
+            List<string> months = new();
             while (year > dateTime.Year - 1 || month > dateTime.Month)
             {
-                MonthStartEnd monthStartEnd = new MonthStartEnd() { yearMonth = $"{year}-{month}" };
+                StartEndTime monthStartEnd = new() { date = $"{year}-{month}" };
 
                 DateTimeOffset dtNew = new(year, month, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dateLenth ? dtNew.ToUnixTimeMilliseconds() : dtNew.ToUnixTimeSeconds();
@@ -181,7 +182,7 @@ namespace TEAMModelBI.Tool
                 monthStartEnd.end = end;
 
                 monthStartEnds.Add(monthStartEnd);
-                
+
                 months.Add($"{year}-{(month < 10 ? "0" : "") + month}");
                 month -= 1;
                 if (month <= 0)
@@ -202,7 +203,7 @@ namespace TEAMModelBI.Tool
         /// <returns></returns>
         public static (long start, long end) GetTermStartOrEnd(DateTimeOffset dateTime, bool dateLenth = true)
         {
-            long start = 0; 
+            long start = 0;
             long end = 0;
             //DateTime dateTime = tempDateTime;
             int year = dateTime.Year;
@@ -312,7 +313,7 @@ namespace TEAMModelBI.Tool
                             if (month <= 8 && month >= 3)
                             {
                                 tempStrart = new DateTimeOffset(year, 3, 1, 0, 0, 0, TimeSpan.Zero);
-                                tempEnd = new DateTimeOffset(year, 8, 31, 23, 59, 59,TimeSpan.Zero);
+                                tempEnd = new DateTimeOffset(year, 8, 31, 23, 59, 59, TimeSpan.Zero);
                             }
                             else
                             {
@@ -321,7 +322,7 @@ namespace TEAMModelBI.Tool
                                 if (month >= 9)
                                 {
                                     tempStrart = new DateTimeOffset(year, 9, 1, 0, 0, 0, TimeSpan.Zero);
-                                    tempEnd = new DateTimeOffset(year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59,TimeSpan.Zero);
+                                    tempEnd = new DateTimeOffset(year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
                                 }
                                 else
                                 {
@@ -388,19 +389,57 @@ namespace TEAMModelBI.Tool
             }
         }
 
+        /// <summary>
+        /// 计算每年获取开始时间
+        /// </summary>
+        /// <param name="dateTime"></param>
+        /// <param name="dateLenth"></param>
+        /// <returns></returns>
+        public static List<StartEndTime> GetYearEveryDay(DateTimeOffset dateTime, bool dateLenth = true,bool isCurrDay = false) 
+        {
+            List<StartEndTime> dayStartEen = new();
+            int year = dateTime.Year;
+            int curry = dateTime.DayOfYear;
+            List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
+            for (int m = 1; m <= 12; m++)
+            {
+                for (int d = 1; d <= isLeapYear[m - 1]; d++)
+                {
+                    if (isCurrDay == true && (curry <= dayStartEen.Count))
+                        break;
+                    DateTimeOffset tempStrart = new(year, m, d, 0, 0, 0, TimeSpan.Zero);
+                    DateTimeOffset tempEnd = new(year, m, d, 23, 59, 59, TimeSpan.Zero);
+
+                    long longStart = dateLenth ? tempStrart.ToUnixTimeMilliseconds() : tempStrart.ToUnixTimeSeconds();
+                    long longEnd = dateLenth ? tempEnd.ToUnixTimeMilliseconds() : tempEnd.ToUnixTimeSeconds();
+
+                    dayStartEen.Add(new StartEndTime() { date = $"{year}-{m}-{d}", start = longStart, end = longEnd });
+                }
+
+                ////DateTime 有方法
+                //DateTime monthStart = new DateTime(year, i, 01);
+                //DateTime monthEnd = dateTime.AddMonths(1);
+
+                //DateTimeOffset tempStrart = new DateTimeOffset(year, i, days, 0, 0, 0, TimeSpan.Zero);
+                //DateTimeOffset tempEnd = new DateTimeOffset(year, i, days, 23, 59, 59, TimeSpan.Zero);
+            }
+
+            return dayStartEen;
+        }
+
         /// <summary>
         /// 将时间戳格式 转换成string类型
         /// 例:yyyyMMdd,等string类型
         /// </summary>
         /// <param name="unixTime"></param>
         /// <returns></returns>
-        public static (string timeStart,string timeEnd) GetUnixToDate(long start,long end = 0,string types="yyyyMMdd")
+        public static (string timeStart, string timeEnd) GetUnixToDate(long start, long end = 0, string types = "yyyyMMdd")
         {
             string tStart = "";
             string tEnd = "";
             DateTimeOffset time = System.TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0));
             tStart = time.AddMilliseconds(start).ToString($"{types}");
-            if (end > 0) 
+            if (end > 0)
             {
                 tEnd = time.AddMilliseconds(end).ToString($"{types}");
             }
@@ -414,7 +453,7 @@ namespace TEAMModelBI.Tool
         /// <param name="dateTime">时间</param>
         /// <param name="dayNumber">最近几天</param>
         /// <returns></returns>
-        public static List<string> GetNearDay(DateTimeOffset dateTime,int dayNumber)
+        public static List<string> GetNearDay(DateTimeOffset dateTime, int dayNumber)
         {
             List<string> days = new();
 
@@ -423,33 +462,42 @@ namespace TEAMModelBI.Tool
             return days;
         }
 
-
-        public static List<YearMonth> GetYearMonth(List<double> doubles, int year = 0,int month = 0) 
+        /// <summary>
+        /// 12个月
+        /// </summary>
+        /// <param name="doubles"></param>
+        /// <param name="year"></param>
+        /// <param name="month"></param>
+        /// <returns></returns>
+        public static List<YearMonth> GetYearMonth(List<double> doubles, int year = 0, int month = 0)
         {
             List<YearMonth> months = new();
-            DateTimeOffset dateTime = DateTimeOffset.Now;
-            if (year == 0) 
-                year = dateTime.Year;
-            if(month == 0)
-                month = dateTime.Month;
-
-            List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
-            double[] array = doubles.ToArray();
-            double ser = doubles.Sum();
-            int moth = 1;
-            int primaryD = 0;
-            for (int i = 0; i < isLeapYear.Count; i++)
+            if (doubles.Count > 0)
             {
-                if (month < moth)
-                    break;
-                double[] temp = new double[isLeapYear[i]];
-                Array.ConstrainedCopy(array, primaryD, temp, 0, isLeapYear[i]);
-                months.Add(new YearMonth() { id = $"{year}-{moth}", cnt = temp.Sum() });
-                moth += 1;
-                primaryD += isLeapYear[i];
+                DateTimeOffset dateTime = DateTimeOffset.Now;
+                if (year == 0)
+                    year = dateTime.Year;
+                if (month == 0)
+                    month = dateTime.Month;
+
+                List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
+                double[] array = doubles.ToArray();
+                double ser = doubles.Sum();
+                int moth = 1;
+                int primaryD = 0;
+                for (int i = 0; i < isLeapYear.Count; i++)
+                {
+                    if (month < moth)
+                        break;
+                    double[] temp = new double[isLeapYear[i]];
+                    Array.ConstrainedCopy(array, primaryD, temp, 0, isLeapYear[i]);
+                    months.Add(new YearMonth() { id = $"{year}-{moth}", cnt = temp.Sum() });
+                    moth += 1;
+                    primaryD += isLeapYear[i];
+                }
             }
-
             return months;
         }
+
     }
 }

+ 8 - 5
TEAMModelBI/Tool/BIStatsWay/ActivityStatsWay.cs

@@ -1,10 +1,13 @@
-using System.Threading.Tasks;
+using Azure.Cosmos;
 using System;
-using TEAMModelBI.Tool.CosmosBank;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
-using Azure.Cosmos;
+using TEAMModelOS.SDK.Models.Service.BI;
 
-namespace TEAMModelBI.Tool.BIStatsWay
+namespace TEAMModelOS.SDK.Models.Service.BIStatsWay
 {
     public static class ActivityStatsWay
     {
@@ -14,7 +17,7 @@ namespace TEAMModelBI.Tool.BIStatsWay
         /// <param name="cosmosClient"></param>
         /// <param name="scId"></param>
         /// <returns></returns>
-        public static async Task<ActivityStats> GetActStats(CosmosClient cosmosClient, string scId)
+        public static async Task<ActivityStats> GetSchoolAll(CosmosClient cosmosClient, string scId)
         {
             ActivityStats actStats = new();
 

+ 9 - 6
TEAMModelBI/Tool/BIStatsWay/LessonRecordStatsWay.cs

@@ -1,12 +1,15 @@
-using System.Threading.Tasks;
+using Azure.Cosmos;
 using System;
-using TEAMModelBI.Tool.CosmosBank;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
-using Azure.Cosmos;
+using TEAMModelOS.SDK.Models.Service.BI;
 
-namespace TEAMModelBI.Tool.BIStatsWay
+namespace TEAMModelOS.SDK.Models.Service.BIStatsWay
 {
-    public  static class LessonRecordStatsWay
+    public static class LessonRecordStatsWay
     {
 
         /// <summary>
@@ -15,7 +18,7 @@ namespace TEAMModelBI.Tool.BIStatsWay
         /// <param name="cosmosClient"></param>
         /// <param name="id"></param>
         /// <returns></returns>
-        public static async Task<LessonStats> GetLessStats(CosmosClient cosmosClient, string id)
+        public static async Task<LessonStats> GetSchoolAll(CosmosClient cosmosClient, string id)
         {
             LessonStats lessStats = new();
 

+ 199 - 0
TEAMModelOS.SDK/Models/Service/BIStatsWay/SchoolStatsWay.cs

@@ -0,0 +1,199 @@
+using Azure.Cosmos;
+using DocumentFormat.OpenXml.Bibliography;
+using DocumentFormat.OpenXml.Math;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
+
+namespace TEAMModelOS.SDK.Models.Service.BIStatsWay
+{
+    public static class SchoolStatsWay
+    {
+
+        /// <summary>
+        /// 统计单个学校
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="scId"></param>
+        /// <returns></returns>
+        public static async Task<StatsInfo> GetSingleSc(CosmosClient cosmosClient, string scId)
+        {
+            StatsInfo statsInfo = new() { id = $"{scId}" };
+
+            DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+            var (dayS, dayE) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间    13位
+            var (lastWeekS, lastWeekE) = TimeHelper.GetStartOrEnd(dateTime, "lastweek");   //计算上周开始/结束时间
+            var (weekS, weekE) = TimeHelper.GetStartOrEnd(dateTime, "week");             //计算本周开始/结束时间
+
+            var (lastTermS, lastTermE) = TimeHelper.GetStartOrEnd(dateTime, "lastterm");   //计算上学期开始/结束时间
+            var (termS, termE) = TimeHelper.GetStartOrEnd(dateTime, "term");   //计算本学期开始/结束时间
+
+            var (lastMthS, LastmthE) = TimeHelper.GetStartOrEnd(dateTime, "lastMonth");  //上月开始/结束时间
+            var (mthS, mthE) = TimeHelper.GetStartOrEnd(dateTime, "month");  //本月开始/结束时间
+
+            var (lastYearS, lastYearE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year - 1}-1-1"), "year"); //计算去年开始/结束时间
+            var (yearS, yearE) = TimeHelper.GetStartOrEnd(dateTime, "year");         //计算今年开始/结束时间
+
+            string currSql = "select value(count(c.id)) from c";
+            string dayWhereSql = $"c.createTime >= {dayS} and c.createTime <= {dayE}";
+            string weekWhereSql = $"c.createTime >= {weekS} and c.createTime <= {weekE}";
+            string monthWhereSql = $"c.createTime >= {mthS} and c.createTime <= {mthE}";
+
+            ScBase scBase = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<ScBase>(statsInfo.id, new PartitionKey("Base"));
+            statsInfo.name = scBase.name;
+            statsInfo.picture = scBase.picture;
+            statsInfo.size = scBase.size;
+            statsInfo.scCreateTime = scBase.createTime;
+
+            string tchSql = $"{currSql} where ARRAY_CONTAINS(c.roles, 'teacher', true) AND c.status = 'join'";
+            statsInfo.tch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", tchSql, code: $"Teacher-{scBase.id}");
+            statsInfo.dayTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and {dayWhereSql} ", code: $"Teacher-{scBase.id}");
+            statsInfo.weekTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {weekWhereSql}", code: $"Teacher-{scBase.id}");
+            statsInfo.monthTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {monthWhereSql}", code: $"Teacher-{scBase.id}");
+
+            statsInfo.stu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", currSql, code: $"Base-{scBase.id}");
+            statsInfo.dayStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {dayWhereSql}", code: $"Base-{scBase.id}");
+            statsInfo.weekStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {weekWhereSql}", code: $"Base-{scBase.id}");
+            statsInfo.monthStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {monthWhereSql}", code: $"Base-{scBase.id}");
+
+            statsInfo.room = await JointlySingleQuery.GetValueInt(cosmosClient, "School", currSql, code: $"Room-{scBase.id}");
+            statsInfo.witRoom = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{currSql} where (c.serial != null or c.serial != '' or IS_DEFINED(c.serial) = true)", code: $"Room-{scBase.id}");
+
+            statsInfo.lesson = await LessonRecordStatsWay.GetSchoolAll(cosmosClient, statsInfo.id);
+            statsInfo.activity = await ActivityStatsWay.GetSchoolAll(cosmosClient, statsInfo.id);
+            statsInfo.study = await StudyStatsWay.GetSchoolAll(cosmosClient, statsInfo.id);
+
+            return statsInfo;
+        }
+
+
+        /// <summary>
+        /// 多个学校统计
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="statsInfos"></param>
+        /// <param name="_httpTrigger"></param>
+        /// <param name="_option"></param>
+        /// <param name="area"></param>
+        /// <returns></returns>
+        public static async Task<StatsInfo> GetAreaStats(CosmosClient cosmosClient, HttpTrigger _httpTrigger, Option _option, List<StatsInfo> statsInfos, List<string> scIds = null, Area area = null) 
+        {
+            StatsInfo areaInfo = new()
+            {
+                id = area == null ? "" : area.id,
+                pk = "Stats",
+                code = "Stats",
+                name = area == null ? "" : area.name,
+                picture = "",
+                tch = statsInfos.Select(s => s.tch).Sum(),
+                dayTch = statsInfos.Select(s => s.dayTch).Sum(),
+                weekTch = statsInfos.Select(s => s.weekTch).Sum(),
+                monthTch = statsInfos.Select(s => s.monthTch).Sum(),
+                stu = statsInfos.Select(s => s.stu).Sum(),
+                dayStu = statsInfos.Select(s => s.dayStu).Sum(),
+                weekStu = statsInfos.Select(s => s.weekStu).Sum(),
+                monthStu = statsInfos.Select(s => s.monthStu).Sum(),
+                room = statsInfos.Select(s => s.room).Sum(),
+                witRoom = statsInfos.Select(s => s.witRoom).Sum(),
+                size = statsInfos.Select(s => s.size).Sum()
+            };
+            areaInfo.lesson.open = statsInfos.Select(s => s.lesson.open).Sum();
+            areaInfo.lesson.less = statsInfos.Select(s => s.lesson.less).Sum();
+            areaInfo.lesson.lastDay = statsInfos.Select(s => s.lesson.lastDay).Sum();
+            areaInfo.lesson.day = statsInfos.Select(s => s.lesson.day).Sum();
+            areaInfo.lesson.lastWeek = statsInfos.Select(s => s.lesson.lastWeek).Sum();
+            areaInfo.lesson.week = statsInfos.Select(s => s.lesson.week).Sum();
+            areaInfo.lesson.lastTerm = statsInfos.Select(s => s.lesson.lastTerm).Sum();
+            areaInfo.lesson.term = statsInfos.Select(s => s.lesson.term).Sum();
+            areaInfo.lesson.lastDayInter = statsInfos.Select(s => s.lesson.lastDayInter).Sum();
+            areaInfo.lesson.dayInter = statsInfos.Select(s => s.lesson.dayInter).Sum();
+            areaInfo.lesson.lastMonthInter = statsInfos.Select(s => s.lesson.lastMonthInter).Sum();
+            areaInfo.lesson.monthInter = statsInfos.Select(s => s.lesson.monthInter).Sum();
+            areaInfo.lesson.lastYearInter = statsInfos.Select(s => s.lesson.lastYearInter).Sum();
+            areaInfo.lesson.yearInter = statsInfos.Select(s => s.lesson.yearInter).Sum();
+
+            areaInfo.activity.cnt = statsInfos.Select(s => s.activity.cnt).Sum();
+            areaInfo.activity.exam = statsInfos.Select(s => s.activity.exam).Sum();
+            areaInfo.activity.survey = statsInfos.Select(s => s.activity.survey).Sum();
+            areaInfo.activity.vote = statsInfos.Select(s => s.activity.vote).Sum();
+            areaInfo.activity.homework = statsInfos.Select(s => s.activity.homework).Sum();
+            areaInfo.activity.lastDay = statsInfos.Select(s => s.activity.lastDay).Sum();
+            areaInfo.activity.dayCnt = statsInfos.Select(s => s.activity.dayCnt).Sum();
+            areaInfo.activity.lastWeek = statsInfos.Select(s => s.activity.lastWeek).Sum();
+            areaInfo.activity.week = statsInfos.Select(s => s.activity.week).Sum();
+            areaInfo.activity.lastTerm = statsInfos.Select(s => s.activity.lastTerm).Sum();
+            areaInfo.activity.term = statsInfos.Select(s => s.activity.term).Sum();
+
+            List<Task<ItemResponse<StatsInfo>>> taskStatsInfos = new();
+
+            foreach (var itemId in scIds)
+            {
+                bool isExist = true;
+                StatsInfo statsInfo = new();
+                var scDataStats = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{itemId}", new PartitionKey("Stats"));
+                if (scDataStats.Status == 200)
+                {
+                    using var fileJson = await JsonDocument.ParseAsync(scDataStats.ContentStream);
+                    statsInfo = fileJson.ToObject<StatsInfo>();
+                }
+                else
+                {
+                    statsInfo.id = itemId;
+                    isExist = false;
+                }
+
+                bool isnew = false;
+                DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+                long now = dateTime.ToUnixTimeMilliseconds();
+
+                if (statsInfo.upTime > 0 && !isnew)
+                {
+                    long timedis = 20 * 60 * 1000;//20分钟
+                    if (now - statsInfo.upTime < timedis)
+                        isnew = true;
+                }
+                if (statsInfo.upTime == 0 && isnew)
+                    statsInfo.upTime = now;
+                if (statsInfo.upTime == 0 && isnew)
+                    statsInfo.upTime = DateTimeOffset.UtcNow.Add(new TimeSpan(-1, 0, 0, 0)).ToUnixTimeMilliseconds();
+                if (!isnew)
+                {
+                    ////Function 处理Function 更新或者新增
+                    //_ = _httpTrigger.RequestHttpTrigger(new { schoolId = $"{itemId}"}, _option.Location, "stats-sc-info");
+
+                    //异步方法处理 同步更新
+                    statsInfo = await SchoolStatsWay.GetSingleSc(cosmosClient, itemId);
+
+                    statsInfo.upTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    if (isExist)
+                        taskStatsInfos.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<StatsInfo>(statsInfo, statsInfo.id, new PartitionKey("Stats")));
+                    else
+                        taskStatsInfos.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<StatsInfo>(statsInfo, new PartitionKey("Stats")));
+                }
+            }
+
+            if (taskStatsInfos.Count < 256)
+                await Task.WhenAll(taskStatsInfos);
+            else 
+            {
+                int pages = (taskStatsInfos.Count + 256) / 256;
+                for (int i = 0; i < pages; i++)
+                {
+                    List<Task<ItemResponse<StatsInfo>>> tempStatsInfos = taskStatsInfos.Skip((i) * 256).Take(256).ToList();
+                    await Task.WhenAll(tempStatsInfos);
+                }
+            }
+
+            return areaInfo;
+        }
+    }
+}

+ 81 - 0
TEAMModelOS.SDK/Models/Service/BIStatsWay/StudyStatsWay.cs

@@ -0,0 +1,81 @@
+using Azure.Cosmos;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+
+namespace TEAMModelOS.SDK.Models.Service.BIStatsWay
+{
+
+    public static class StudyStatsWay
+    {
+        /// <summary>
+        /// 学校研修统计
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="scId"></param>
+        /// <returns></returns>
+        public static async Task<StudyStats> GetSchoolAll(CosmosClient cosmosClient, string scId)
+        {
+            StudyStats studyStats = new();
+            List<AreaStudy> trains = new();
+
+            School school = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>($"{scId}", new PartitionKey("Base"));
+            //cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText:$"select value(c.areaId) from c where c.id='{scId}'", requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")});
+
+            AreaSetting setting = null;
+            var responSett = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"{school.areaId}", new PartitionKey("AreaSetting"));
+            if (responSett.Status == 200)
+            {
+                using var fileJson = await JsonDocument.ParseAsync(responSett.ContentStream);
+                setting = fileJson.ToObject<AreaSetting>();
+
+            }
+            if (setting == null)
+            {
+                setting = new AreaSetting
+                {
+                    allTime = 50,
+                    classTime = 5,
+                    submitTime = 15,
+                    onlineTime = 20,
+                    offlineTime = 10,
+                    lessonMinutes = 45,
+                };
+            }
+
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<AreaStudy>(queryText: $"select c.id,c.code,c.totalTime,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and c.school='{scId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{scId}") }))
+            {
+                trains.Add(item);
+            }
+
+            studyStats.learnTime = trains.Select(s=>s.totalTime).Sum();
+            trains.ForEach(x =>
+            {
+                //线上研修
+                if (x.onlineTime == 0) studyStats.online++; else if (x.onlineTime >= setting.onlineTime) studyStats.online++; else studyStats.online++;
+
+                //线下研修
+                if (x.offlineTime == 0) studyStats.offline++; else if (x.onlineTime >= setting.offlineTime) studyStats.offline++; else studyStats.offline++;
+
+                //课堂实录
+                if (x.classTime == 0) studyStats.classRoom++; else if (x.classTime >= setting.classTime) studyStats.classRoom++; else studyStats.classRoom++;
+
+                //认证材料
+                if (x.currency.submitTime == 0) studyStats.submit++; else if (x.currency.submitTime >= setting.submitTime) studyStats.submit++; else studyStats.submit++;
+
+                if (x.currency.submitTime == 0 && x.classTime == 0 && x.offlineTime == 0 && x.onlineTime == 0) studyStats.notStarted++;
+                else if (x.currency.submitTime >= setting.submitTime && x.classTime >= setting.classTime && x.onlineTime >= setting.offlineTime && x.onlineTime >= setting.onlineTime) studyStats.finish++;
+                else studyStats.ongoing++;
+            });
+
+
+
+            return studyStats;
+        }
+    }
+}