CrazyIter_Bin 2 anos atrás
pai
commit
436d3fc494

+ 12 - 8
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -1203,7 +1203,10 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
             {
                 return;
             }
-
+            if (!string.IsNullOrWhiteSpace(school)&& school.Equals("habook"))
+            {
+               await _dingDing.SendBotMsg($"研发学校课堂记录事件触发:\n{msg}", GroupNames.成都开发測試群組);
+            }
             var client = _azureCosmos.GetCosmosClient();
 
             if ($"{scope}".Equals("school") && !string.IsNullOrEmpty($"{school}"))
@@ -1302,13 +1305,15 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 break;
                             //更新 基础统计信息
                             case "up-base":
+                              
                                 //如果有更新 则去读取/{_lessonId}/IES/base.json
                                 try {
                                     BlobDownloadResult timelineblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/records/{_lessonId}/IES/TimeLine.json").DownloadContentAsync();
                                     TimeLineData timeLineData = timelineblobDownload.Content.ToObjectFromJson<TimeLineData>();
                                     lessonRecord.hitaClientCmpCount = timeLineData.events.Where(z => !string.IsNullOrWhiteSpace(z.WrkCmpSrcType) && z.WrkCmpSrcType.Equals("HitaClientCmp")).Count();
                                     //lessonRecord.collateTaskCount = lessonRecord.hitaClientCmpCount;
-                                } catch {
+                                } catch (Exception ex ){
+                                    await _dingDing.SendBotMsg($"TimeLine.json转换异常,{ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
                                 }
 
                                 try
@@ -1462,13 +1467,12 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 }
                                 catch (Exception ex)
                                 {
-                                    if (!ex.Message.Contains("exist")) {
-                                        await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}课程读取base.json,{_lessonId}\n{ex.Message}\n{ex.StackTrace}\n\n{lessonRecord.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
-                                    }
-                                    
+                                    //if (!ex.Message.Contains("exist")) {
+                                    //    await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}课程读取base.json,{_lessonId}\n{ex.Message}\n{ex.StackTrace}\n\n{lessonRecord.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
+                                    //}
+                                    await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}课程读取base.json,{_lessonId}\n{ex.Message}\n{ex.StackTrace}\n\n{lessonRecord.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
                                 }
-
-                                await BIStats.SetTypeAddStats(client, _dingDing,lessonRecord.school, "Less", 0, 1, lessonRecord.clientInteractionCount);//BI统计增/减量
+                               // await BIStats.SetTypeAddStats(client, _dingDing,lessonRecord.school, "Less", 0, 1, lessonRecord.clientInteractionCount);//BI统计增/减量
                                 break;
                             //更新 时间线
                             case "up-TimeLine":

+ 10 - 0
TEAMModelOS.SDK/Models/Cosmos/School/SchoolSetting.cs

@@ -35,6 +35,16 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public HashSet<string> lessonTag { get; set; } = new HashSet<string>();
         public LessonSetting lessonSetting { get; set; }= new LessonSetting();
+        public OverallEducationSetting overallEducationSetting { get; set; } = new OverallEducationSetting();
+    }
+    public class OverallEducationSetting
+    {
+        // newest avg sum 
+        public string sports { get; set; } = "newest";
+        public string art { get; set; } = "newest";
+        public string labour { get; set; } = "newest";
+        public string intelligence { get; set; } = "newest";
+        public string virtue { get; set; } = "newest";  
     }
     public class LessonSetting
     {

+ 2 - 1
TEAMModelOS.SDK/Models/Cosmos/Student/OverallEducation.cs

@@ -37,6 +37,7 @@ namespace TEAMModelOS.SDK.Models
         /// 学生姓名
         /// </summary>
         public string name { get; set; }
+        public string picture { get; set; }
         /// <summary>
         /// 所属行政班
         /// </summary>
@@ -66,7 +67,7 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public List<EducationScore> art { get; set; } = new List<EducationScore>();
         /// <summary>
-        /// 劳动
+        /// 劳动 
         /// </summary>
         public List<EducationScore> labour { get; set; } = new List<EducationScore>();
 

+ 229 - 4
TEAMModelOS/Controllers/Student/OverallEducationController.cs

@@ -1,5 +1,6 @@
 using Azure.Cosmos;
 using DocumentFormat.OpenXml.Drawing.Charts;
+using DocumentFormat.OpenXml.Office2013.Drawing.Chart;
 using HTEXLib.COMM.Helpers;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
@@ -139,6 +140,7 @@ namespace TEAMModelOS.Controllers
             json.TryGetProperty("year", out JsonElement _year);
             var client = _azureCosmos.GetCosmosClient();
             School school = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{_school}", new PartitionKey("Base"));
+            SchoolSetting schoolSetting = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolSetting>($"{_school}", new PartitionKey("SchoolSetting"));
             Dictionary<string, object> dict = OverallEducationService.GetQueryCond(json);
 #region  此处代码用于处理 根据年级 学段获取 相关的班级。
             List<int > years = null ;
@@ -186,14 +188,237 @@ namespace TEAMModelOS.Controllers
             string oesql = $"select value c from c where c.semesterId='{_semesterId}' and  c.year={_year} and c.periodId='{_periodId}' " +
                 $"and c.classId in {string.Join(",",classes.Select(z=>$"'{z}'"))} ";
             var oeresults = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<OverallEducation>(oesql, $"OverallEducation-{_school}");
-            double excellence_count = 0;
-            double pass_Count = 0;
             double dataCount = 0;
+            double sports_count90 = 0;
+            double sports_count60 = 0;
+            double sports_count = 0;
+            double art_count90 = 0;
+            double art_count60 = 0;
+            double art_count = 0;
+            double intelligence_count90 = 0;
+            double intelligence_count60 = 0;
+            double intelligence_count = 0;
+            double labour_count90 = 0;
+            double labour_count60 = 0;
+            double labour_count = 0;
+            double virtue_count90 = 0;
+            double virtue_count60 = 0;
+            double virtue_count = 0;
+            List<(double score, OverallEducation student)> ranking = new List<(double score, OverallEducation student)>();
+            List<(string classId, double last, double best, double sum, double avg)> classDatas = new List<(string classId, double last, double best, double sum, double avg)>();
             if (oeresults.list.IsNotEmpty()) {
-                dataCount=oeresults.list.Count();
+                dataCount = oeresults.list.Count();
+              
+                oeresults.list.ForEach(z => { 
+                    double score = 0;
+                    //体育
+                    {
+                        if (schoolSetting.overallEducationSetting.sports.Equals("avg"))
+                        {
+                            score += z.sports.Average(x => x.sumScore);
+                        }
+                        else if (schoolSetting.overallEducationSetting.sports.Equals("newest"))
+                        {
+                            score += z.sports.OrderByDescending(x => x.examDate).First().sumScore;
+                        }
+                        else if (schoolSetting.overallEducationSetting.sports.Equals("sum"))
+                        {
+                            score += z.sports.Sum(x => x.sumScore);
+                        }
+                    }
+                    //劳动
+                    {
+                        if (schoolSetting.overallEducationSetting.labour.Equals("avg"))
+                        {
+                            score += z.labour.Average(x => x.sumScore);
+                        }
+                        else if (schoolSetting.overallEducationSetting.labour.Equals("newest"))
+                        {
+                            score += z.labour.OrderByDescending(x => x.examDate).First().sumScore;
+                        }
+                        else if (schoolSetting.overallEducationSetting.labour.Equals("sum"))
+                        {
+                            score += z.labour.Sum(x => x.sumScore);
+                        }
+                    }
+                    //智育
+                    {
+                        if (schoolSetting.overallEducationSetting.intelligence.Equals("avg"))
+                        {
+                            score += z.intelligence.Average(x => x.sumScore);
+                        }
+                        else if (schoolSetting.overallEducationSetting.intelligence.Equals("newest"))
+                        {
+                            score += z.intelligence.OrderByDescending(x => x.examDate).First().sumScore;
+                        }
+                        else if (schoolSetting.overallEducationSetting.intelligence.Equals("sum"))
+                        {
+                            score += z.intelligence.Sum(x => x.sumScore);
+                        }
+                    }
+                    //艺术
+                    {
+                        if (schoolSetting.overallEducationSetting.art.Equals("avg"))
+                        {
+                            score += z.art.Average(x => x.sumScore);
+                        }
+                        else if (schoolSetting.overallEducationSetting.art.Equals("newest"))
+                        {
+                            score += z.art.OrderByDescending(x => x.examDate).First().sumScore;
+                        }
+                        else if (schoolSetting.overallEducationSetting.art.Equals("sum"))
+                        {
+                            score += z.art.Sum(x => x.sumScore);
+                        }
+                    }
+                    //德育
+                    {
+                        if (schoolSetting.overallEducationSetting.virtue.Equals("avg"))
+                        {
+                            score += z.virtue.Average(x => x.sumScore);
+                        }
+                        else if (schoolSetting.overallEducationSetting.virtue.Equals("newest"))
+                        {
+                            score += z.virtue.OrderByDescending(x => x.examDate).First().sumScore;
+                        }
+                        else if (schoolSetting.overallEducationSetting.virtue.Equals("sum"))
+                        {
+                            score += z.virtue.Sum(x => x.sumScore);
+                        }
+                    }
+                    ranking.Add((score, z));
+                });
+                
+                var classGroup= ranking.GroupBy(x => x.student.classId).Select(g => new {key =  g.Key,list = g.ToList()});
+                classGroup.ToList().ForEach(x => {
+                    var key = x.key;
+                    var sort = x.list.OrderBy(o => o.score);
+                    double last = sort.First().score;
+                    double best = sort.Last().score;
+                    double sum = x.list.Select(s => s.score).Sum();
+                    double avg = x.list.Count()>0 ? sum/x.list.Count():0;
+                    classDatas.Add((key, last, best, sum, avg));
+                });
+                ranking= ranking.OrderByDescending(x=>x.score).Take(10).ToList();
+                #region  体育
+                sports_count = oeresults.list.Where(z => z.sports.IsNotEmpty()).Count();
+                if (schoolSetting.overallEducationSetting.sports.Equals("avg"))
+                {
+                    
+                    sports_count90 = oeresults.list.Where(z => z.sports.IsNotEmpty() && z.sports.Average(x => x.sumScore) >= 90).Count();
+                    sports_count60 = oeresults.list.Where(z => z.sports.IsNotEmpty() && z.sports.Average(x => x.sumScore) >= 60).Count();
+                }
+                else if (schoolSetting.overallEducationSetting.sports.Equals("newest"))
+                {
+                    sports_count90 = oeresults.list.Where(z => z.sports.IsNotEmpty() && z.sports.OrderByDescending(x => x.examDate).First().sumScore >= 90).Count();
+                    sports_count60 = oeresults.list.Where(z => z.sports.IsNotEmpty() && z.sports.OrderByDescending(x => x.examDate).First().sumScore >= 60).Count();
+                }
+                else if (schoolSetting.overallEducationSetting.sports.Equals("sum"))
+                {
+                    sports_count90 = oeresults.list.Where(z => z.sports.IsNotEmpty() && z.sports.Sum(x => x.sumScore) >= 90).Count();
+                    sports_count60 = oeresults.list.Where(z => z.sports.IsNotEmpty() && z.sports.Sum(x => x.sumScore) >= 60).Count();
+                }
+                #endregion
+                #region 艺术
+                art_count = oeresults.list.Where(z => z.art.IsNotEmpty()).Count();
+                if (schoolSetting.overallEducationSetting.art.Equals("avg"))
+                {
+                    art_count90 = oeresults.list.Where(z => z.art.IsNotEmpty() && z.art.Average(x => x.sumScore) >= 90).Count();
+                    art_count60 = oeresults.list.Where(z => z.art.IsNotEmpty() && z.art.Average(x => x.sumScore) >= 60).Count();
 
+                }
+                else if (schoolSetting.overallEducationSetting.art.Equals("newest"))
+                {
+                    art_count90 = oeresults.list.Where(z => z.art.IsNotEmpty() && z.art.OrderByDescending(x => x.examDate).First().sumScore >= 90).Count();
+                    art_count60 = oeresults.list.Where(z => z.art.IsNotEmpty() && z.art.OrderByDescending(x => x.examDate).First().sumScore >= 60).Count();
+                }
+                else if (schoolSetting.overallEducationSetting.art.Equals("sum"))
+                {
+                    art_count90 = oeresults.list.Where(z => z.art.IsNotEmpty() && z.art.Sum(x => x.sumScore) >= 90).Count();
+                    art_count60 = oeresults.list.Where(z => z.art.IsNotEmpty() && z.art.Sum(x => x.sumScore) >= 60).Count();
+                }
+                #endregion
+                #region 智育
+                intelligence_count = oeresults.list.Where(z => z.intelligence.IsNotEmpty()).Count();
+                if (schoolSetting.overallEducationSetting.intelligence.Equals("avg"))
+                {
+                    intelligence_count90 = oeresults.list.Where(z => z.intelligence.IsNotEmpty() && z.intelligence.Average(x => x.sumScore) >= 90).Count();
+                    intelligence_count60 = oeresults.list.Where(z => z.intelligence.IsNotEmpty() && z.intelligence.Average(x => x.sumScore) >= 60).Count();
+
+                }
+                else if (schoolSetting.overallEducationSetting.intelligence.Equals("newest"))
+                {
+                    intelligence_count90 = oeresults.list.Where(z => z.intelligence.IsNotEmpty() && z.intelligence.OrderByDescending(x => x.examDate).First().sumScore >= 90).Count();
+                    intelligence_count60 = oeresults.list.Where(z => z.intelligence.IsNotEmpty() && z.intelligence.OrderByDescending(x => x.examDate).First().sumScore >= 60).Count();
+                }
+                else if (schoolSetting.overallEducationSetting.intelligence.Equals("sum"))
+                {
+                    intelligence_count90 = oeresults.list.Where(z => z.intelligence.IsNotEmpty() && z.intelligence.Sum(x => x.sumScore) >= 90).Count();
+                    intelligence_count60 = oeresults.list.Where(z => z.intelligence.IsNotEmpty() && z.intelligence.Sum(x => x.sumScore) >= 60).Count();
+                }
+                #endregion
+                #region 劳动
+                labour_count = oeresults.list.Where(z => z.labour.IsNotEmpty()).Count();
+                if (schoolSetting.overallEducationSetting.labour.Equals("avg"))
+                {
+                    labour_count90 = oeresults.list.Where(z => z.labour.IsNotEmpty() && z.labour.Average(x => x.sumScore) >= 90).Count();
+                    labour_count60 = oeresults.list.Where(z => z.labour.IsNotEmpty() && z.labour.Average(x => x.sumScore) >= 60).Count();
+
+                }
+                else if (schoolSetting.overallEducationSetting.labour.Equals("newest"))
+                {
+                    labour_count90 = oeresults.list.Where(z => z.labour.IsNotEmpty() && z.labour.OrderByDescending(x => x.examDate).First().sumScore >= 90).Count();
+                    labour_count60 = oeresults.list.Where(z => z.labour.IsNotEmpty() && z.labour.OrderByDescending(x => x.examDate).First().sumScore >= 60).Count();
+                }
+                else if (schoolSetting.overallEducationSetting.labour.Equals("sum"))
+                {
+                    labour_count90 = oeresults.list.Where(z => z.labour.IsNotEmpty() && z.labour.Sum(x => x.sumScore) >= 90).Count();
+                    labour_count60 = oeresults.list.Where(z => z.labour.IsNotEmpty() && z.labour.Sum(x => x.sumScore) >= 60).Count();
+                }
+                #endregion
+                #region 德育
+                virtue_count = oeresults.list.Where(z => z.virtue.IsNotEmpty()).Count();
+                if (schoolSetting.overallEducationSetting.virtue.Equals("avg"))
+                {
+                    virtue_count90 = oeresults.list.Where(z => z.virtue.IsNotEmpty() && z.virtue.Average(x => x.sumScore) >= 90).Count();
+                    virtue_count60 = oeresults.list.Where(z => z.virtue.IsNotEmpty() && z.virtue.Average(x => x.sumScore) >= 60).Count();
+
+                }
+                else if (schoolSetting.overallEducationSetting.virtue.Equals("newest"))
+                {
+                    virtue_count90 = oeresults.list.Where(z => z.virtue.IsNotEmpty() && z.virtue.OrderByDescending(x => x.examDate).First().sumScore >= 90).Count();
+                    virtue_count60 = oeresults.list.Where(z => z.virtue.IsNotEmpty() && z.virtue.OrderByDescending(x => x.examDate).First().sumScore >= 60).Count();
+                }
+                else if (schoolSetting.overallEducationSetting.virtue.Equals("sum"))
+                {
+                    virtue_count90 = oeresults.list.Where(z => z.virtue.IsNotEmpty() && z.virtue.Sum(x => x.sumScore) >= 90).Count();
+                    virtue_count60 = oeresults.list.Where(z => z.virtue.IsNotEmpty() && z.virtue.Sum(x => x.sumScore) >= 60).Count();
+                }
+                #endregion
             }
-            return Ok(new { studentCount ,classCount=classes.Count, grade=years.Count });
+            return Ok(new {
+                studentCount,
+                classCount = classes.Count,
+                gradeCount = years.Count,
+                dataCount,
+                sports_count60,
+                sports_count90,
+                art_count60,
+                art_count90,
+                labour_count60,
+                labour_count90,
+                virtue_count60,
+                virtue_count90,
+                intelligence_count60,
+                intelligence_count90,
+                sports_count,
+                art_count,
+                intelligence_count,
+                virtue_count,
+                labour_count,
+                ranking=ranking.Select(x=>new { score=x.score,student=x.student }),
+                classDatas= classDatas.Select(z=>new { z.classId,z.last,z.best,z.avg})
+            });
         }
     }
 }

+ 234 - 0
TEAMModelOS/Properties/Startup.cs

@@ -0,0 +1,234 @@
+using Lib.AspNetCore.ServerSentEvents;
+using Microsoft.AspNetCore.Authentication.JwtBearer;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.SpaServices;
+using Microsoft.Azure.Cosmos.Table;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.IdentityModel.Tokens;
+using System;
+using System.Collections.Generic;
+using System.IdentityModel.Tokens.Jwt;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI.Multiple;
+using TEAMModelBI.Models;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Filter;
+using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions;
+using TEAMModelOS.SDK.Models;
+using VueCliMiddleware;
+using System.Net.Http;
+
+namespace TEAMModelBI
+{
+    public class Startup
+    {
+        public IWebHostEnvironment environment { get; set; }
+        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
+        public Startup(IConfiguration configuration,IWebHostEnvironment env)
+        {
+            Configuration = configuration;
+            environment = env;
+        }
+
+        public IConfiguration Configuration { get; }
+
+        // This method gets called by the runtime. Use this method to add services to the container.
+        public void ConfigureServices(IServiceCollection services)
+        {
+            // true,默認情況下,聲明映射將以舊格式映射聲明名稱,以適應較早的SAML應用程序,RoleClaimType = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role'
+            // false,RoleClaimType = 'roles'             
+            JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
+            services.AddAuthentication(options => options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme)
+                .AddJwtBearer(options => //AzureADJwtBearer
+                {
+                    //options.SaveToken = true; //驗證令牌由服務器生成才有效,不適用於服務重啟或分布式架構
+                    options.Authority = Configuration["Option:Authority"];
+                    options.Audience = Configuration["Option:Audience"];
+                    options.RequireHttpsMetadata = true;
+                    options.TokenValidationParameters = new TokenValidationParameters
+                    {
+                        RoleClaimType = "roles",
+                        ValidAudiences = new string[] { Configuration["Option:Audience"], $"api://{Configuration["Option:Audience"]}" }
+                    };
+                    options.Events = new JwtBearerEvents();
+                    //下列事件有需要紀錄則打開
+                    //options.Events.OnMessageReceived = async context => { await Task.FromResult(0); };
+                    //options.Events.OnForbidden = async context => { await Task.FromResult(0); };
+                    //options.Events.OnChallenge = async context => { await Task.FromResult(0); };
+                    //options.Events.OnAuthenticationFailed = async context => { await Task.FromResult(0); };
+                    options.Events.OnTokenValidated = async context =>
+                    {
+                        if (!context.Principal.Claims.Any(x => x.Type.Equals("http://schemas.microsoft.com/identity/claims/scope")) //ClaimConstants.Scope
+                        && !context.Principal.Claims.Any(y => y.Type.Equals("roles"))) //ClaimConstants.Roles //http://schemas.microsoft.com/ws/2008/06/identity/claims/role
+                        {
+                            //TODO 需處理額外授權非角色及範圍的訪問異常紀錄
+                            throw new UnauthorizedAccessException("Neither scope or roles claim was found in the bearer token.");
+                        }
+                        await Task.FromResult(0);
+                    };
+                });
+            //設定跨域請求
+            services.AddCors(options =>
+            {
+                options.AddPolicy(MyAllowSpecificOrigins,
+                builder =>
+                {
+                    builder.WithOrigins("http://teammodelos-test.chinacloudsites.cn",
+                                        "https://www.teammodel.cn", "https://localhost:5001",
+                                        "http://localhost:5000")
+                                       
+                    .AllowAnyHeader()
+                    .AllowAnyMethod();
+                });
+            });
+
+            //Table和blob注入
+            List<(string name, string connectionString)> storageConnects = new();
+            storageConnects.Add(("Default", Configuration.GetValue<string>("Azure:Storage:ConnectionString")));      //大路站ClientString
+            storageConnects.Add(("Global", Configuration.GetValue<string>("GlobalAzure:Storage:ConnectionString"))); //国际站ClientString
+
+            storageConnects.Add(("LogChina", Configuration.GetValue<string>("Azure:LogStorage:ConnectionString"))); //防火墙日志 大陆站ClientString
+            storageConnects.Add(("LogGlobal", Configuration.GetValue<string>("GlobalAzure:LogStorage:ConnectionString"))); //防火墙日志  国际站ClientString
+            services.AddMultipleAzureStorage(storageConnects);
+
+            //cosmosDB注入
+            List<(string name,string connectionString)> cosmosDBConnects = new();
+            cosmosDBConnects.Add(("Default", Configuration.GetValue<string>("Azure:Cosmos:ConnectionString")));      //大路站ClientString
+            cosmosDBConnects.Add(("Global", Configuration.GetValue<string>("GlobalAzure:Cosmos:ConnectionString"))); //国际站ClientString
+            services.AddMultipleAzureCosmos(cosmosDBConnects);
+
+            //redis注入
+            List<(string name, string connectionString)> redisConnects = new();
+            redisConnects.Add(("Default", Configuration.GetValue<string>("Azure:Redis:ConnectionString")));
+            redisConnects.Add(("Global", Configuration.GetValue<string>("GlobalAzure:Redis:ConnectionString")));
+            services.AddMultipleAzureRedis(redisConnects);
+
+            //serverBus 注入 
+            List<(string name, string connectionString)> funConnects = new();
+            funConnects.Add(("Default", Configuration.GetValue<string>("Azure:ServiceBus:ConnectionString")));
+            funConnects.Add(("Global", Configuration.GetValue<string>("GlobalAzure:ServiceBus:ConnectionString")));
+            services.AddMultipleAzureServiceBus(funConnects);
+            
+            //单一注入
+            //services.AddAzureStorage(Configuration.GetValue<string>("Azure:Storage:ConnectionString"));
+            //services.AddAzureCosmos(Configuration.GetValue<string>("Azure:Cosmos:ConnectionString"));
+            //services.AddAzureRedis(Configuration.GetValue<string>("Azure:Redis:ConnectionString"));
+            //services.AddAzureServiceBus(Configuration.GetValue<string>("Azure:ServiceBus:ConnectionString"));     
+
+            services.AddSnowflakeId(Convert.ToInt64(Configuration.GetValue<string>("Option:LocationNum")), 1);
+            services.AddHttpClient();
+            services.AddHttpClient<DingDing>();
+            //services.AddCoreAPIHttpService(Configuration);
+            services.AddHttpClient<CoreAPIHttpService>().ConfigureHttpMessageHandlerBuilder(builder =>
+            {
+                builder.PrimaryHandler = new HttpClientHandler
+                {
+                    ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
+                };
+            });
+            services.AddHttpClient<HttpTrigger>();
+            services.AddMemoryCache();
+            services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = false; });
+            services.Configure<SysConfig>(Configuration.GetSection("sysConfig"));  //注册连接
+            //HttpContextAccessor,并用来访问HttpContext。(提供組件或非控制器服務存取HttpContext)
+            services.AddHttpContextAccessor();
+            services.Configure<Option>(options => Configuration.GetSection("Option").Bind(options));
+            services.AddControllers();
+
+            string path = $"{ environment.ContentRootPath}/JsonFile/Core";
+            services.AddIPSearcher(path);
+            services.AddSpaStaticFiles(configuration =>
+            {
+                configuration.RootPath = "ClientApp";
+            });
+            services.AddServerSentEvents(o =>
+            {
+                o.KeepaliveMode = ServerSentEventsKeepaliveMode.Always;
+                o.OnClientConnected = async (service, client) =>
+                {
+                    //if (client.Request.Headers.TryGetValue("X-Auth-Name", out StringValues name))
+                    //{
+                    //    client.Client.SetProperty("NAME", name.ToString());
+                    //}
+                    //if (client.Request.Headers.TryGetValue("X-Auth-DID", out StringValues did))
+                    //{
+                    //    client.Client.SetProperty("DID", did.ToString());
+                    //}
+                    //if (client.Request.Headers.TryGetValue("X-Auth-CID", out StringValues cid))
+                    //{
+                    //    client.Client.SetProperty("CID", cid.ToString());
+                    //}
+                    //if (client.Request.Headers.TryGetValue("X-Auth-PIN", out StringValues pin))
+                    //{
+                    //    client.Client.SetProperty("PIN", pin.ToString());
+                    //}
+                    //if (client.Request.Headers.TryGetValue("X-Auth-APP", out StringValues app))
+                    //{
+                    //    client.Client.SetProperty("APP", app.ToString());
+                    //}
+
+                    await client.Client.SendEventAsync(new { sid = client.Client.Id.ToString() }.ToJsonString());
+                };
+            });
+            //等保安全性验证。
+            services.AddScoped<SecurityHeadersAttribute>();
+            services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
+        }
+
+        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
+        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+        {
+            if (env.IsDevelopment())
+            {
+                app.UseDeveloperExceptionPage();
+            }
+
+            app.UseRouting();
+            //以下需要按照順序載入中間件  如果应用调用 UseStaticFiles,请将 UseStaticFiles 置于 UseRouting之前。
+            app.UseStaticFiles();
+            app.UseSpaStaticFiles();
+            app.UseCors(MyAllowSpecificOrigins); //使用跨域設定
+            app.UseHttpsRedirection(); //開發中暫時關掉
+            //如果应用使用身份验证/授权功能(如 AuthorizePage 或 [Authorize]),请将对 UseAuthentication 和 UseAuthorization的
+            //调用放在之后、UseRouting 和 UseCors,但在 UseEndpoints之前
+            app.UseAuthentication();
+            app.UseAuthorization();
+            app.UseEndpoints(endpoints =>
+            {
+                endpoints.MapControllers();
+                endpoints.MapServerSentEvents("/service/sse", new ServerSentEventsOptions
+                {
+                    //Authorization = ServerSentEventsAuthorization.Default,
+                    OnPrepareAccept = response =>
+                    {
+                        response.Headers.Append("Cache-Control", "no-cache");
+                        response.Headers.Append("X-Accel-Buffering", "no");
+                    }
+                });
+#if DEBUG
+                endpoints.MapToVueCliProxy(
+                    "{*path}",
+                    new SpaOptions { SourcePath = "ClientApp" },
+                    npmScript: (System.Diagnostics.Debugger.IsAttached) ? "serve" : null,
+                    // regex: "Compiled successfully",
+                    forceKill: true
+                    );
+#else
+                endpoints.MapFallbackToFile("index.html");
+#endif
+
+            });
+
+
+        }
+    }
+}