CrazyIter_Bin 2 年之前
父节点
当前提交
a4c15b6b7c

+ 206 - 4
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -33,6 +33,15 @@ using TEAMModelOS.SDK.DI.CoreAPI;
 using DocumentFormat.OpenXml.Office2010.Excel;
 using DocumentFormat.OpenXml.Wordprocessing;
 using System.Xml.Linq;
+using Azure.Storage.Sas;
+using DocumentFormat.OpenXml.Drawing;
+using static TEAMModelOS.FunctionV4.HttpTrigger.IESHttpTrigger;
+using System.Net.Http;
+using System.Web;
+using System.Net;
+using System.Net.Http.Json;
+using Microsoft.Azure.ServiceBus;
+using System.Collections.Concurrent;
 
 namespace TEAMModelOS.FunctionV4.ServiceBus
 {
@@ -49,7 +58,11 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
         private readonly IConfiguration _configuration;
         private readonly IConverter _converter;
         private readonly SnowflakeId _snowflakeId;
-        public ActiveTaskTopic(SnowflakeId snowflakeId, IConverter converter, CoreAPIHttpService coreAPIHttpService, AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IOptionsSnapshot<Option> option, NotificationService notificationService, IConfiguration configuration)
+        private readonly HttpClient _httpClient;
+        public ActiveTaskTopic(SnowflakeId snowflakeId, IConverter converter, CoreAPIHttpService coreAPIHttpService,
+            AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis,
+            AzureServiceBusFactory serviceBus, IOptionsSnapshot<Option> option,
+            NotificationService notificationService, IConfiguration configuration, HttpClient httpClient)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
@@ -62,6 +75,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
             _coreAPIHttpService = coreAPIHttpService;
             _converter = converter;
             _snowflakeId = snowflakeId;
+            _httpClient = httpClient;
         }
         [Function("Exam")]
         public async Task ExamFunc([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "exam", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
@@ -721,22 +735,161 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
             }
         }
         [Function("GenPdf")]
-        public async Task GenPdfFunc([ServiceBusTrigger("%Azure:ServiceBus:GenPdfQueue%", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
+        public async Task GenPdfFunc([ServiceBusTrigger("%Azure:ServiceBus:GenPdfQueue%", Connection = "Azure:ServiceBus:ConnectionString",IsBatched =false)] string msg  ,
+             Int32 deliveryCount,
+              DateTime enqueuedTimeUtc, string messageId, ILogger log
+             )
         {
+            //https://github.com/aafgani/AzFuncWithServiceBus/blob/a0da42f59b5fc45655b73b85bae932e84520db70/ServiceBusTriggerFunction/host.json
+            //  messageHandlerOptions 设置
+            string constring = $"{Environment.GetEnvironmentVariable("Azure:ServiceBus:ConnectionString")}";
+            string queue = $"{Environment.GetEnvironmentVariable("Azure:ServiceBus:GenPdfQueue")}";
+            var client = new QueueClient(constring, queue, ReceiveMode.PeekLock);
             JsonElement element = msg.ToObject<JsonElement>();
+            // https://dotblogs.com.tw/yc421206/2013/04/25/102300
+            // ConcurrentQueue  http://t.zoukankan.com/hohoa-p-12622459.html
             switch (true)
             {
                 case bool when element.TryGetProperty("bizType", out JsonElement _bizType) && $"{_bizType}".Equals("OfflineRecord"):
                     //处理教师线下研修报告的生成。
-                    await GenOfflineRecordPdf(element,msg);
+                    await GenOfflineRecordPdf(element, msg);
                     break;
                 case bool when element.TryGetProperty("bizType", out JsonElement _bizType) && $"{_bizType}".Equals("ArtStudentPdf"):
                     //处理学生艺术评测报告的生成。
+                    long stime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    await _dingDing.SendBotMsg($"{stime}-艺术评测报告生成中...", GroupNames.成都开发測試群組);
+                    await GenArtStudentPdf(element, msg);
+                    long etime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    await _dingDing.SendBotMsg($"{stime}-{etime}艺术评测报告生成完成!", GroupNames.成都开发測試群組);
                     break;
             }
+            //await client.CompleteAsync(message.SystemProperties.LockToken);
+            await  client.CloseAsync();
         }
+        private async Task GenArtStudentPdf(JsonElement json, string msg) {
+            try
+            {
+                //string data = await new StreamReader(req.Body).ReadToEndAsync();
+                //var json = JsonDocument.Parse(data).RootElement;
+                json.TryGetProperty("studentPdfs", out JsonElement _studentPdfs);
+                json.TryGetProperty("artResults", out JsonElement _artResults);
+                json.TryGetProperty("schoolCode", out JsonElement _schoolCode);
+                List<ArtStudentPdf> studentPdfs = _studentPdfs.Deserialize<List<ArtStudentPdf>>();
+                List<StudentArtResult> artResults = _artResults.Deserialize<List<StudentArtResult>>();
+                List<Task<string>> uploads = new List<Task<string>>();
+                studentPdfs.ForEach(x => {
+                    x.blob = $"art/{x.artId}/report/{x.studentId}.json";
+                    uploads.Add(_azureStorage.GetBlobContainerClient($"{_schoolCode}").UploadFileByContainer(x.ToJsonString(), "art", $"{x.artId}/report/{x.studentId}.json", true));
+                });
+                var uploadJsonUrls = await Task.WhenAll(uploads);
+                var list = uploadJsonUrls.ToList();
+                List<string> urls = new List<string>();
+                (string uri, string sas) = _azureStorage.GetBlobContainerSAS($"{_schoolCode}", Azure.Storage.Sas.BlobContainerSasPermissions.Read);
+                studentPdfs.ForEach(x => {
+                    string atrUrl = "https://teammodelos.blob.core.chinacloudapi.cn/0-public/art-report-template/report.html";
+                    var s = _azureStorage.GetBlobSAS($"{_schoolCode}", x.blob, BlobSasPermissions.Read);
+                    s = $"{HttpUtility.UrlEncode($"{s}", Encoding.UTF8)}";
+                    string url = $"{atrUrl}?url={s}&pdfpath={x.artId}/report/{x.studentId}";
+                    urls.Add(url);
+                    //var a = list.Find(l => l.Contains(x.studentId));
+                    //if (a != null) {
+
+                    //    a = $"{HttpUtility.UrlEncode($"{a}?{sas}", Encoding.UTF8)}";
+                    //    string url = $"{atrUrl}?url={a}&pdfpath={x.artId}/report/{x.studentId}";
+                    //    urls.Add(url);
+                    //}
+                });
+                string env = "release";
+                if (Environment.GetEnvironmentVariable("Option:Location").Contains("Test", StringComparison.CurrentCultureIgnoreCase) ||
+                    Environment.GetEnvironmentVariable("Option:Location").Contains("Dep", StringComparison.CurrentCultureIgnoreCase))
+                {
+                    env = "develop";
+                }
+                int psize = 20;
+                List<string> resUrls = new List<string>();
+                if (urls.Count <= psize)
+                {
+                    var screenshot = new ScreenshotDto
+                    {
+                        width = 1080,
+                        height = 1920,
+                        urls = urls,
+                        fileNameKey = "pdfpath",
+                        cnt = $"{_schoolCode}",
+                        root = "art",
+                        pagesize = 5,
+                        env = env
+                    };
+                    var st = screenshot.ToJsonString();
+                    await _dingDing.SendBotMsg($"艺术评测报告生成中:\n{st}", GroupNames.成都开发測試群組);
+                    var httpResponse = await _httpClient.PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/screen/screenshot-pdf",
+                       screenshot
+                    );
 
-
+                    if (httpResponse.StatusCode == HttpStatusCode.OK)
+                    {
+                        JsonElement json_res = await httpResponse.Content.ReadFromJsonAsync<JsonElement>();
+                        resUrls = json_res.GetProperty("urls").Deserialize<List<string>>();
+                        await UpdatePdfBlob(artResults, resUrls);
+                    }
+                }
+                else
+                {
+                    int pages = (urls.Count + psize) / psize;
+                    for (int i = 0; i < pages; i++)
+                    {
+                        var lists = urls.Skip((i) * psize).Take(psize).ToList();
+                        var screenshot = new ScreenshotDto
+                        {
+                            width = 1080,
+                            height = 1920,
+                            urls = lists,
+                            fileNameKey = "pdfpath",
+                            cnt = $"{_schoolCode}",
+                            root = "art",
+                            pagesize = 5,
+                            env = env
+                        };
+                        var st = screenshot.ToJsonString();
+                        //  await _dingDing.SendBotMsg($"艺术评测报告生成中:\n{st}", GroupNames.成都开发測試群組);
+                        var httpResponse = await _httpClient.PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/screen/screenshot-pdf",
+                           screenshot
+                        );
+                        if (httpResponse.StatusCode == HttpStatusCode.OK)
+                        {
+                            JsonElement json_res = await httpResponse.Content.ReadFromJsonAsync<JsonElement>();
+                            resUrls = json_res.GetProperty("urls").Deserialize<List<string>>();
+                            await UpdatePdfBlob(artResults, resUrls);
+                        }
+                    }
+                }
+               // await response.WriteAsJsonAsync(new { data = new { count = studentPdfs.Count, resUrls } });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"{ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
+            }
+        }
+        //https://teammodeltest.blob.core.chinacloudapi.cn/hbcn/art/e864a924-e644-42dc-87c4-e970e6185065/report/202201001.pdf
+        private async Task UpdatePdfBlob(List<StudentArtResult> studentArts, List<string> urls)
+        {
+            List<Task<ItemResponse<StudentArtResult>>> artResults = new List<Task<ItemResponse<StudentArtResult>>>();
+            urls.ForEach(z => {
+                var res = studentArts.FindAll(x => z.Contains(x.artId) && z.Contains($"{x.studentId}"));
+                if (res.Any())
+                {
+                    if (string.IsNullOrWhiteSpace(res[0].blob))
+                    {
+                        res[0].blob = $"art/{res[0].artId}/report/{res[0].studentId}.pdf";
+                        artResults.Add(_azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync(res[0], res[0].id, new PartitionKey(res[0].code)));
+                    }
+                }
+            });
+            if (artResults.Any())
+            {
+                await Task.WhenAll(artResults);
+            }
+        }
         private async Task GenOfflineRecordPdf(JsonElement element,string msg) {
             try
             {
@@ -1363,6 +1516,55 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                                 }
                                             });
                                         }
+                                        //计算TP灯
+                                        {
+                                            int T = -1;
+                                            int P = -1;
+                                            if (lessonRecord.clientInteractionAverge <= 0)
+                                            {
+                                                T = 0;
+                                            }
+                                            else if (lessonRecord.clientInteractionAverge >= 1 && lessonRecord.clientInteractionAverge <= 2)
+                                            {
+                                                T = 1;
+                                            }
+                                            else
+                                            {
+                                                T = 2;
+                                            }
+                                            if (lessonRecord.examCount > 0)
+                                            {
+                                                //有评测次数大于0则P是直接绿灯
+                                                P = 2;
+                                            }
+                                            else {
+                                               
+                                                int a = lessonRecord.collateTaskCount;
+                                                int b = lessonRecord.pushCount;
+                                                int c = lessonRecord.examCount;
+                                                switch (true) { 
+                                                    case bool when T == 0:
+                                                        P = 0;
+                                                        break;
+                                                    case bool when T == 1|| T == 2:
+                                                        if (a == 0 && b == 0 && c == 0)
+                                                        {
+                                                            P = 0;
+                                                        }
+                                                        else if ((a > 0 && b > 0) || (a > 0 && c > 0) || (b > 0 && c > 0))
+                                                        {
+                                                            P = 2;
+                                                        }
+                                                        else
+                                                        {
+                                                            P = 1;
+                                                        }
+                                                        break;
+                                                }
+                                            }
+                                            lessonRecord.tLevel = T;
+                                            lessonRecord.pLevel = P;
+                                        }
                                         //LessonStudentRecord lessonStudentRecord = new LessonStudentRecord
                                         //{
                                         //    clientSummaryList = lessonBase.report.clientSummaryList,

+ 2 - 0
TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj

@@ -45,6 +45,7 @@
 		<!--<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.10" />-->
 		<!--<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.0.1" />-->
 		<!--<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.3.0" />-->
+		<!--<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.11.0" />-->
 		<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.3.0" OutputItemType="Analyzer" />
 		<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.6.0" />
 		<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
@@ -54,6 +55,7 @@
 		<!--<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.CosmosDB" Version="3.0.9" />-->
 		<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs" Version="5.0.0" />
 		<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.1.0" />
+		<PackageReference Include="Microsoft.Azure.ServiceBus" Version="5.2.0" />
 		<PackageReference Include="SPS.SBCompressor" Version="0.6.0" />
 		<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
 	</ItemGroup>

+ 10 - 0
TEAMModelOS.FunctionV4/host.json

@@ -1,5 +1,15 @@
 {
   "version": "2.0",
+  "extensions": {
+    "serviceBus": {
+      //"prefetchCount": 100,
+      "messageHandlerOptions": {
+        "autoComplete": false,
+        "maxAutoRenewDuration": "00:55:00",
+        "maxConcurrentCalls": 5
+      }
+    }
+  },
   "cosmosDB": {
     "connectionMode": "Direct",
     "protocol": "Tcp"

+ 8 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs

@@ -55,6 +55,14 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public int pScore { get; set; }
         /// <summary>
+        ///选填  t灯,科技应用 0红灯,1 黄灯,2绿灯
+        /// </summary>
+        public int tLevel { get; set; }
+        /// <summary>
+        ///选填   p灯,教法应用 0红灯,1 黄灯,2绿灯
+        /// </summary>
+        public int pLevel { get; set; }
+        /// <summary>
         ///选填  选用IES5的课程id 
         /// </summary>
         public string courseId { get; set; }

+ 522 - 1
TEAMModelOS.SDK/Models/Service/ArtService.cs

@@ -1,9 +1,19 @@
-using HTEXLib.COMM.Helpers;
+using Azure.Cosmos;
+using Azure.Messaging.ServiceBus;
+using HTEXLib.COMM.Helpers;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Hosting;
 using System;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Text;
+using System.Text.Json;
 using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.Common;
 
 namespace TEAMModelOS.SDK.Models.Service
 {
@@ -68,5 +78,516 @@ namespace TEAMModelOS.SDK.Models.Service
             }
             return nodes;
         }
+
+        public async static Task<List<ArtStudentPdf>> GenArtPDF(List<StudentArtResult> artResults,string _artId,string _schoolId,string head_lang ,AzureCosmosFactory _azureCosmos, 
+            IWebHostEnvironment _environment, CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing, AzureServiceBusFactory _serviceBus, IConfiguration _configuration) {
+            var client = _azureCosmos.GetCosmosClient();
+            School school = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>($"{_schoolId}", new PartitionKey("Base"));
+            string path = Path.Combine(_environment.ContentRootPath, $"Lang/{head_lang}.json");
+            string comment1 = "";
+            string comment2 = "";
+            string comment3 = "";
+            string comment4 = "";
+            string comment5 = "";
+            string comment_subject_music = "";
+            string comment_subject_painting = "";
+            var jsonDoc = readFileJson(path);
+            if (jsonDoc != null)
+            {
+                if (jsonDoc.RootElement.TryGetProperty("art-template-comment1", out JsonElement _c1))
+                {
+                    comment1 = $"{_c1}";
+                }
+                if (jsonDoc.RootElement.TryGetProperty("art-template-comment2", out JsonElement _c2))
+                {
+                    comment2 = $"{_c2}";
+                }
+                if (jsonDoc.RootElement.TryGetProperty("art-template-comment3", out JsonElement _c3))
+                {
+                    comment3 = $"{_c3}";
+                }
+                if (jsonDoc.RootElement.TryGetProperty("art-template-comment4", out JsonElement _c4))
+                {
+                    comment4 = $"{_c4}";
+                }
+                if (jsonDoc.RootElement.TryGetProperty("art-template-comment5", out JsonElement _c5))
+                {
+                    comment5 = $"{_c5}";
+                }
+                if (jsonDoc.RootElement.TryGetProperty("art-template-subject_music", out JsonElement _subject_music))
+                {
+                    comment_subject_music = $"{_subject_music}";
+                }
+                if (jsonDoc.RootElement.TryGetProperty("art-template-subject_painting", out JsonElement _subject_painting))
+                {
+                    comment_subject_painting = $"{_subject_painting}";
+                }
+            }
+            ArtEvaluation art = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ArtEvaluation>($"{_artId}", new PartitionKey($"Art-{_schoolId}"));
+            ArtSetting artSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<ArtSetting>($"{school.areaId}", new PartitionKey($"ArtSetting"));
+
+            var allExamIds = art.settings.SelectMany(x => x.task).Where(z => z.type == 1);
+            var subjects = art.subjects;
+            //获取学校的所有艺术科目的uuid,并映射找到相应的知识点,知识块。
+            var schoolSubjects = school.period.SelectMany(x => x.subjects).Where(s => !string.IsNullOrWhiteSpace(s.bindId) && subjects.Select(z => z.id).Contains(s.bindId));
+            StringBuilder sql = new StringBuilder($"select value(c) from c");
+            List<KeyValuePair<string, List<Block>>> subjectBindBlocks = new List<KeyValuePair<string, List<Block>>>();
+            foreach (var schSub in schoolSubjects)
+            {
+                List<Block> blocks = new List<Block>();
+                string code = $"Knowledge-{_schoolId}-{schSub.id}";
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School")
+                    .GetItemQueryIterator<Knowledge>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+                {
+                    item.blocks.ForEach(x =>
+                    {
+                        var block = blocks.Find(z => z.name.Equals(x.name));
+                        if (block != null)
+                        {
+                            block.points.AddRange(x.points);
+                        }
+                        else
+                        {
+                            blocks.Add(x);
+                        }
+                    });
+                }
+                subjectBindBlocks.Add(new KeyValuePair<string, List<Block>>(schSub.bindId, blocks));
+            }
+            List<ExamInfo> exams = new List<ExamInfo>();
+            List<ExamResult> examResults = new();
+            if (allExamIds.Any())
+            {
+                var queryExam = $"select  value c  from c where c.id  in  ({string.Join(",", allExamIds.Select(x => $"'{x.acId}'"))}) ";
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamInfo>(queryText: queryExam, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{_schoolId}") }))
+                {
+                    exams.Add(item);
+                }
+                foreach (var allexamId in allExamIds)
+                {
+                    var queryResult = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.paper,c.classes,c.sRate,c.average,c.standard,c.lostStus,c.record,c.phc,c.plc,c.examId from c where c.examId = '{allexamId.acId}' and c.subjectId = '{allexamId.subject}' ";
+                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamResult>(queryText: queryResult, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{allexamId.acId}") }))
+                    {
+                        examResults.Add(item);
+                    }
+                }
+            }
+            (List<RMember> rmembers, List<RGroupList> groups) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, art.classes, art.school);
+            List<ArtStudentPdf> studentPdfs = new List<ArtStudentPdf>();
+            artResults.ForEach(x =>
+            {
+                var allSubject = x.results.GroupBy(g => g.quotaId).Select(s => new { key = s.Key, list = s.ToList() }).ToList();
+                var groupSubject = x.results.GroupBy(g => $"{g.quotaId}-{g.subjectId}").Select(s => new { key = s.Key, list = s.ToList() }).ToList();
+                //综合-所有科目的艺术评测指标维度。
+                List<ArtQuotaPdf> allSubjectArtQuotaPdfs = new List<ArtQuotaPdf>();
+                allSubject.ForEach(a =>
+                {
+
+                    ArtQuotaPdf artPdf = new ArtQuotaPdf();
+                    List<ArtQuota> parents = ArtService.GetParentByChildId(artSetting.quotas, $"{a.key}");
+                    parents.ForEach(x =>
+                    {
+                        switch (true)
+                        {
+                            case bool when x.level == 1:
+                                artPdf.quota1 = x.id;
+                                artPdf.quotaN1 = x.name;
+                                artPdf.quotaP1 = x.percent;
+                                if (a.key.Equals(x.id))
+                                {
+                                    artPdf.quotaName = x.name;
+                                }
+                                break;
+                            case bool when x.level == 2:
+                                artPdf.quota2 = x.id;
+                                artPdf.quotaN2 = x.name;
+                                artPdf.quotaP2 = x.percent;
+                                if (a.key.Equals(x.id))
+                                {
+                                    artPdf.quotaName = x.name;
+                                }
+                                break;
+                            case bool when x.level == 3:
+                                artPdf.quota3 = x.id;
+                                artPdf.quotaN3 = x.name;
+                                artPdf.quotaP3 = x.percent;
+                                if (a.key.Equals(x.id))
+                                {
+                                    artPdf.quotaName = x.name;
+                                }
+                                break;
+                        }
+                    });
+                    var noneScore = a.list.FindAll(x => x.score == -1);
+                    if (!noneScore.IsNotEmpty())
+                    {
+                        //全部未打分。
+                        if (noneScore.Count >= art.subjects.Count)
+                        {
+                            artPdf.quotaId = a.key;
+                            artPdf.score = 0;
+                            artPdf.scoreData = "-";
+                            artPdf.percent = "0";
+                        }
+                        else
+                        {
+                            //有一部分打分的,只算有分的平均分。
+                            var hasScore = a.list.FindAll(x => x.score >= 0);
+                            if (hasScore.IsNotEmpty())
+                            {
+                                var avgScore = hasScore.Sum(x => x.score) * 1.0 / a.list.Count;
+                                var avg = decimal.Round(decimal.Parse($"{avgScore}"), 2);
+                                artPdf.quotaId = a.key;
+                                artPdf.score = double.Parse($"{avg}");
+                                artPdf.scoreData = $"{avg}";
+                                artPdf.percent = $"{avg}";
+                            }
+                            else
+                            {
+                                artPdf.quotaId = a.key;
+                                artPdf.score = 0;
+                                artPdf.scoreData = "-";
+                                artPdf.percent = "0";
+                            }
+                        }
+                    }
+                    else
+                    {
+                        artPdf.quotaId = a.key;
+                        artPdf.score = 0;
+                        artPdf.scoreData = "-";
+                        artPdf.percent = "0";
+                    }
+                    allSubjectArtQuotaPdfs.Add(artPdf);
+                });
+                string level = "";
+                double allScore = 0;
+                if (allSubjectArtQuotaPdfs.Any())
+                {
+                    allScore = allSubjectArtQuotaPdfs.Sum(a => a.score) / allSubjectArtQuotaPdfs.Count;
+                }
+
+                if (allScore >= 100)
+                {
+                    allScore = 100;
+                    level = "优秀(A+)";
+                }
+                if (allScore <= 0)
+                {
+                    allScore = 0;
+                    level = "待及格(D)";
+                }
+                if (allScore < 100)
+                {
+                    artSetting.reviewLevel.ForEach(r =>
+                    {
+                        if (r.value[0] <= allScore && r.value[1] > allScore)
+                        {
+                            level = r.code;
+                        }
+                    });
+                }
+                var rmbs = rmembers.FindAll(r => r.id.Equals(x.studentId) && r.type == 2 && x.code.Equals(x.school));
+                if (rmbs.IsNotEmpty())
+                {
+                    x.studentName = rmbs[0].name;
+                }
+                List<string> classNames = new List<string>();
+                HashSet<string> periodIds = new HashSet<string>();
+                x.classIds.ForEach(c =>
+                {
+                    var gps = groups.FindAll(g => g.id.Equals(c));
+                    if (gps.IsNotEmpty())
+                    {
+                        classNames.Add(gps[0].name);
+                        if (!string.IsNullOrWhiteSpace(gps[0].periodId))
+                        {
+                            periodIds.Add(gps[0].periodId);
+                        }
+                    }
+                });
+                allSubjectArtQuotaPdfs.ForEach(x => x.level = level);
+                var allSubjectQuotas = allSubjectArtQuotaPdfs.OrderBy(o => o.quota1).ThenBy(o => o.quota2).ThenBy(o => o.quota3);
+
+                StringBuilder comment = new StringBuilder();
+                switch (true)
+                {
+                    case bool when level.Contains("(A+)"):
+                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优异"));
+                        break;
+                    case bool when level.Contains("(A)"):
+                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优秀"));
+                        break;
+                    case bool when level.Contains("(B+)"):
+                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优良"));
+                        break;
+                    case bool when level.Contains("(B)"):
+                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现良好"));
+                        break;
+                    case bool when level.Contains("(C+)"):
+                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "还需加强"));
+                        break;
+                    case bool when level.Contains("(C)"):
+                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "有待提高"));
+                        break;
+                    case bool when level.Contains("(D)"):
+                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "还需努力"));
+                        break;
+                }
+                var score80 = allSubjectArtQuotaPdfs.Where(x => x.score >= 80);
+                if (score80.Any())
+                {
+                    List<string> quota = new List<string>();
+                    var quota3s = score80.Where(c => !string.IsNullOrWhiteSpace(c.quota3)).Select(z => z.quotaN3);
+                    if (quota3s.Any())
+                    {
+                        quota.AddRange(quota3s);
+                    }
+                    var quota2s = score80.Where(c => string.IsNullOrWhiteSpace(c.quota3) && !string.IsNullOrWhiteSpace(c.quota2)).Select(z => z.quotaN2);
+                    if (quota2s.Any())
+                    {
+                        quota.AddRange(quota2s);
+                    }
+                    comment.Append(comment2.Replace("{quotasHigh}", string.Join("、", quota)));
+                }
+                var score60 = allSubjectArtQuotaPdfs.Where(x => x.score < 60);
+                if (score60.Any())
+                {
+                    List<string> quota = new List<string>();
+                    var quota3s = score60.Where(c => !string.IsNullOrWhiteSpace(c.quota3)).Select(z => z.quotaN3);
+                    if (quota3s.Any())
+                    {
+                        quota.AddRange(quota3s);
+                    }
+                    var quota2s = score60.Where(c => string.IsNullOrWhiteSpace(c.quota3) && !string.IsNullOrWhiteSpace(c.quota2)).Select(z => z.quotaN2);
+                    if (quota2s.Any())
+                    {
+                        quota.AddRange(quota2s);
+                    }
+                    comment.Append(comment3.Replace("{quotasLow}", string.Join("、", quota)));
+                }
+                string periodId = "";
+                string periodName = "";
+                if (periodIds.Any())
+                {
+                    var ps = school.period.FindAll(x => periodIds.Contains(x.id));
+                    if (ps.Any())
+                    {
+                        periodName = String.Join(",", ps.Select(x => x.name));
+                        periodId = String.Join(",", ps.Select(x => x.id));
+                    }
+                }
+                List<ArtSubjectPdf> subjectPdfs = new List<ArtSubjectPdf>();
+                exams.ForEach(exam => {
+                    var result = examResults.FindAll(e => e.examId.Equals(exam.id));
+                    if (result.Any())
+                    {
+                        var datas = DoKnowledgePoint(result.First(), exam, x.studentId);
+                        if (exam.subjects.Any())
+                        {
+                            ArtSubjectPdf artSubjectPdf = new ArtSubjectPdf()
+                            {
+                                subjectId = exam.subjects.First().id,
+                                subjectName = exam.subjects.First().name
+                            };
+
+                            datas.pointScores.Value.ForEach(k => {
+                                var artPointPdfs = GetBlockAndDimension(k.score, k.tscore, artSubjectPdf.subjectId, k.name, subjectBindBlocks, artSetting);
+                                artSubjectPdf.pointPdfs.AddRange(artPointPdfs);
+                            });
+                            var pointHigh = artSubjectPdf.pointPdfs.Where(z => z.percent >= 0.8).Select(z => z.point).ToHashSet();
+                            var pointLow = artSubjectPdf.pointPdfs.Where(z => z.percent < 0.6).Select(z => z.point).ToHashSet();
+                            StringBuilder comment = new StringBuilder();
+                            if (pointHigh.Any())
+                            {
+                                comment.Append(comment4.Replace("{pointHigh}", string.Join("、", pointHigh)));
+                            }
+                            if (pointLow.Any())
+                            {
+                                comment.Append(comment5.Replace("{pointLow}", string.Join("、", pointLow)));
+                            }
+                            if (artSubjectPdf.subjectId.Equals("subject_music"))
+                            {
+                                comment.Append(comment_subject_music);
+                            }
+                            if (artSubjectPdf.subjectId.Equals("subject_painting"))
+                            {
+                                comment.Append(comment_subject_painting);
+                            }
+                            artSubjectPdf.comment = comment.ToString();
+                            subjectPdfs.Add(artSubjectPdf);
+                        }
+                    }
+                });
+                ArtStudentPdf studentPdf = new ArtStudentPdf
+                {
+                    artId = art.id,
+                    schoolCode = school.id,
+                    schoolName = school.name,
+                    periodId = periodId,
+                    periodName = periodName,
+                    studentId = x.studentId,
+                    studentName = x.studentName,
+                    picture = x.picture,
+                    classNames = classNames,
+                    artName = art.name,
+                    level = level,
+                    score = allScore,
+                    allSubjectQuotas = allSubjectQuotas.ToList(),
+                    comment = comment.ToString(),
+                    subjectPdfs = subjectPdfs,
+                };
+                studentPdfs.Add(studentPdf);
+            });
+            // _ = _httpTrigger.RequestHttpTrigger(new { studentPdfs = studentPdfs, artResults, schoolCode = $"{_schoolId}" }, _option.Location, "gen-art-pdf");
+            var messageBlobPDF = new ServiceBusMessage(new { studentPdfs = studentPdfs, artResults, schoolCode = $"{_schoolId}", bizType = "ArtStudentPdf" }.ToJsonString());
+            var GenPdfQueue = _configuration.GetValue<string>("Azure:ServiceBus:GenPdfQueue");
+            await _serviceBus.GetServiceBusClient().SendMessageAsync(GenPdfQueue, messageBlobPDF);
+            return studentPdfs;
+        }
+        private static  JsonDocument readFileJson(string path)
+        {
+            var sampleJson = System.IO.File.ReadAllBytes(path).AsSpan();
+            Utf8JsonReader reader = new Utf8JsonReader(sampleJson);
+            if (JsonDocument.TryParseValue(ref reader, out JsonDocument jsonDoc))
+            {
+                return jsonDoc;
+            }
+            else
+            {
+                return null;
+            }
+
+        }
+        //获取本次评测所有科目结算结果
+        /* List<ExamResult> examResults = new();
+         ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(examId.ToString(), new PartitionKey($"Exam-{code}"));
+         var query = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.paper,c.classes,c.sRate,c.average,c.standard,c.lostStus,c.record,c.phc,c.plc from c where c.examId = '{examId}' and c.subjectId = '{subjectId}' ";
+         await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamResult>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{examId}") }))
+                 {
+                     examResults.Add(item);
+                 }*/
+        private static (KeyValuePair<string, List<string>> knowledgeName,
+            KeyValuePair<string, List<(string name, double score)>> pointScore,
+            KeyValuePair<string, List<(string name, double score)>> pointTScore,
+            KeyValuePair<string, List<(string name, double score, double tscore)>> pointScores) DoKnowledgePoint(ExamResult exam, ExamInfo info, string studentId)
+        {
+            HashSet<string> knowledge = new();
+            List<double> point = new();
+            List<List<double>> result = new();
+            List<ClassRange> classes = new();
+
+            //定位试卷信息
+            int index = 0;
+            foreach (ExamSubject subject in info.subjects)
+            {
+                if (subject.id.Equals(exam.subjectId))
+                {
+                    break;
+                }
+                else
+                {
+                    index++;
+                }
+            }
+            if (info.papers[index].knowledge != null && info.papers[index].knowledge.Count > 0)
+            {
+                info.papers[index].knowledge.ForEach(k =>
+                {
+                    k.ForEach(e =>
+                    {
+                        knowledge.Add(e);
+                    });
+                });
+            }
+            else
+            {
+                return (default, default, default, default);
+            }
+            point = info.papers[index].point;
+            result = exam.studentScores;
+            classes = exam.classes;
+
+            List<string> knowledgeName = new List<string>();
+            foreach (string cla in knowledge)
+            {
+                knowledgeName.Add(cla);
+            }
+            for (int k = 0; k < knowledgeName.Count; k++)
+            {
+                if (null == knowledgeName[k])
+                {
+                    knowledgeName.Remove(knowledgeName[k]);
+                }
+            }
+            List<double> knowScore = new();
+            //学生得分情况
+            List<(string name, double score)> pointScore = new();
+            List<(string name, double score)> pointTScore = new();
+            List<(string name, double score, double tscore)> pointScores = new();
+            for (int k = 0; k < knowledgeName.Count; k++)
+            {
+                double OnePoint = 0;
+                List<string> itemNo = new();
+                int n = 0;
+                double scores = 0;
+                info.papers[index].knowledge.ForEach(kno =>
+                {
+                    if (kno.Contains(knowledgeName[k]))
+                    {
+                        var itemPersent = kno.Count > 0 ? 1 / Convert.ToDouble(kno.Count) : 0;
+                        OnePoint += point[n] * itemPersent;
+                        int stuIndex = exam.studentIds.IndexOf(studentId);
+                        if (exam.studentScores[stuIndex][n] > 0)
+                        {
+                            scores += exam.studentScores[stuIndex][n] * itemPersent;
+                        }
+                    }
+                    n++;
+                });
+                //单个知识点的配分
+                pointScore.Add((knowledgeName[k], OnePoint));
+                pointTScore.Add((knowledgeName[k], scores));
+                pointScores.Add((knowledgeName[k], OnePoint, scores));
+
+            }
+            KeyValuePair<string, List<string>> key1 = new(exam.subjectId, knowledgeName);
+            KeyValuePair<string, List<(string name, double score)>> key2 = new(exam.subjectId, pointScore);
+            KeyValuePair<string, List<(string name, double score)>> key3 = new(exam.subjectId, pointTScore);
+            KeyValuePair<string, List<(string name, double score, double tscore)>> key4 = new(exam.subjectId, pointScores);
+            return (key1, key2, key3, key4);
+        }
+        private static List<ArtPointPdf> GetBlockAndDimension(double score, double tscore, string subjectId, string point, List<KeyValuePair<string, List<Block>>> subjectBindBlocks, ArtSetting artSetting)
+        {
+            var block = subjectBindBlocks.Find(z => z.Key.Equals(subjectId));
+            List<ArtPointPdf> artPointPdfs = new List<ArtPointPdf>();
+            if (!string.IsNullOrWhiteSpace(block.Key))
+            {
+                block.Value.ForEach(z => {
+                    if (z.points.Contains(point))
+                    {
+                        var dims = artSetting.dimensions.FindAll(m => m.blocks.Contains(z.name));
+                        if (dims.Any())
+                        {
+                            foreach (var dim in dims)
+                            {
+                                artPointPdfs.Add(
+                                    new ArtPointPdf
+                                    {
+                                        dimension = dim.dimension,
+                                        block = z.name,
+                                        point = point,
+                                        totalScore = score,
+                                        score = tscore,
+                                        percent = score > 0 ? tscore * 1.0 / score : 0,
+                                    }
+                                );
+                            }
+                        }
+                    }
+                });
+            }
+            return artPointPdfs;
+        }
     }
 }

+ 11 - 4
TEAMModelOS.SDK/Models/Service/LessonService.cs

@@ -62,8 +62,17 @@ namespace TEAMModelOS.SDK.Models.Service
             }
             if (request.TryGetProperty("doubleGreen", out JsonElement doubleGreen) && doubleGreen.GetBoolean())
             {
-                dict.Add(">=.tScore", 70);
-                dict.Add(">=.pScore", 70);
+                dict.Add("=.tLevel", 2);
+                dict.Add("=.pLevel", 2);
+                //dict.Add(">=.tScore", 70);
+                //dict.Add(">=.pScore", 70);
+            }
+            if (request.TryGetProperty("doubleRed", out JsonElement doubleRed) && doubleRed.GetBoolean())
+            {
+                dict.Add("=.tLevel", 0);
+                dict.Add("=.pLevel", 0);
+                //dict.Add(">=.tScore", 70);
+                //dict.Add(">=.pScore", 70);
             }
             if (request.TryGetProperty("quality", out JsonElement quality) && quality.GetBoolean())
             {
@@ -600,8 +609,6 @@ namespace TEAMModelOS.SDK.Models.Service
                         save = false;
                         school_lesson_expire = Constant.school_lesson_expire;
                     }
-
-                   
                 }
                 if (!save && school_lesson_expire > 0)
                 {

+ 38 - 516
TEAMModelOS/Controllers/School/ArtReviewController.cs

@@ -1,5 +1,6 @@
 using Azure;
 using Azure.Cosmos;
+using Azure.Messaging.ServiceBus;
 using DinkToPdf.Contracts;
 using HTEXLib.COMM.Helpers;
 using Microsoft.AspNetCore.Hosting;
@@ -65,23 +66,6 @@ namespace TEAMModelOS.Controllers
             _converter = converter;
             _httpTrigger = httpTrigger;
         }
-        [HttpPost("get-parents")]
-        public async Task<IActionResult> GetParents(JsonElement request)
-        {
-            if (!request.TryGetProperty("areaId", out JsonElement _areaId))
-            {
-                return BadRequest();
-            }
-            if (!request.TryGetProperty("cid", out JsonElement cid))
-            {
-                return BadRequest();
-            }
-            var client = _azureCosmos.GetCosmosClient();
-            ArtSetting artSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<ArtSetting>($"{_areaId}", new PartitionKey($"ArtSetting"));
-
-            List<ArtQuota> parents = ArtService.GetParentByChildId(artSetting.quotas, $"{cid}");
-            return Ok(parents);
-        }
         /// <summary>
         /// 
         /// </summary>
@@ -118,47 +102,7 @@ namespace TEAMModelOS.Controllers
             {
                 return BadRequest();
             }
-            School school = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>($"{_schoolId}", new PartitionKey("Base"));
-            string path = Path.Combine(_environment.ContentRootPath, $"Lang/{head_lang}.json");
-            string comment1 = "";
-            string comment2 = "";
-            string comment3 = "";
-            string comment4 = "";
-            string comment5 = "";
-            string comment_subject_music = "";
-            string comment_subject_painting = "";
-            var jsonDoc = readFileJson(path);
-            if (jsonDoc != null)
-            {
-                if (jsonDoc.RootElement.TryGetProperty("art-template-comment1", out JsonElement _c1))
-                {
-                    comment1 = $"{_c1}";
-                }
-                if (jsonDoc.RootElement.TryGetProperty("art-template-comment2", out JsonElement _c2))
-                {
-                    comment2 = $"{_c2}";
-                }
-                if (jsonDoc.RootElement.TryGetProperty("art-template-comment3", out JsonElement _c3))
-                {
-                    comment3 = $"{_c3}";
-                }
-                if (jsonDoc.RootElement.TryGetProperty("art-template-comment4", out JsonElement _c4))
-                {
-                    comment4 = $"{_c4}";
-                }
-                if (jsonDoc.RootElement.TryGetProperty("art-template-comment5", out JsonElement _c5))
-                {
-                    comment5 = $"{_c5}";
-                }
-                if (jsonDoc.RootElement.TryGetProperty("art-template-subject_music", out JsonElement _subject_music))
-                {
-                    comment_subject_music = $"{_subject_music}";
-                }
-                if (jsonDoc.RootElement.TryGetProperty("art-template-subject_painting", out JsonElement _subject_painting))
-                {
-                    comment_subject_painting = $"{_subject_painting}";
-                }
-            }
+
             List<string> studentIds = new List<string>();
             if (request.TryGetProperty("studentIds", out JsonElement _studentIds) && _studentIds.ValueKind.Equals(JsonValueKind.Array))
             {
@@ -167,368 +111,19 @@ namespace TEAMModelOS.Controllers
             var client = _azureCosmos.GetCosmosClient();
 
             string query = $" select value c from c where c.school  = '{_schoolId}' ";
-            if (studentIds.Any()) {
+            if (studentIds.Any())
+            {
                 query = $" select value c from c where c.school  = '{_schoolId}' and c.studentId in ({string.Join(",", studentIds.Select(z => $"'{z}'"))})";
             }
             List<StudentArtResult> artResults = new List<StudentArtResult>();
-            ArtEvaluation art = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ArtEvaluation>($"{_artId}", new PartitionKey($"Art-{_schoolId}"));
-            ArtSetting artSetting = await client.GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemAsync<ArtSetting>($"{_areaId}", new PartitionKey($"ArtSetting"));
             await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<StudentArtResult>
-                (queryText: query, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtResult-{_artId}") }))
+              (queryText: query, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtResult-{_artId}") }))
             {
                 artResults.Add(item);
             }
-            var allExamIds= art.settings.SelectMany(x => x.task).Where(z => z.type==1);
-            var subjects = art.subjects;
-            //获取学校的所有艺术科目的uuid,并映射找到相应的知识点,知识块。
-            var schoolSubjects= school.period.SelectMany(x => x.subjects).Where(s => !string.IsNullOrWhiteSpace(s.bindId) && subjects.Select(z=>z.id).Contains(s.bindId));
-            StringBuilder sql = new StringBuilder($"select value(c) from c");
-            List<KeyValuePair<string, List<Block>>> subjectBindBlocks = new List<KeyValuePair<string, List<Block>>>();
-            foreach (var schSub in schoolSubjects) {
-                List<Block> blocks = new List<Block>();
-                string code = $"Knowledge-{_schoolId}-{schSub.id}";
-                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School")
-                    .GetItemQueryIterator<Knowledge>(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
-                {
-                    item.blocks.ForEach(x =>
-                    {
-                        var block = blocks.Find(z => z.name.Equals(x.name));
-                        if (block != null)
-                        {
-                            block.points.AddRange(x.points);
-                        }
-                        else {
-                            blocks.Add(x);
-                        }
-                    });
-                }
-                subjectBindBlocks.Add(new KeyValuePair<string, List<Block>>(schSub.bindId, blocks));
-            }
-            List<ExamInfo> exams = new List<ExamInfo>();
-            List<ExamResult> examResults = new();
-            if (allExamIds.Any()) {
-                var queryExam = $"select  value c  from c where c.id  in  ({string.Join(",",allExamIds.Select(x=>$"'{x.acId}'"))}) ";
-                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamInfo>(queryText: queryExam, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{_schoolId}") }))
-                {
-                    exams.Add(item);
-                }
-                foreach (var allexamId in allExamIds) {
-                    var queryResult = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.paper,c.classes,c.sRate,c.average,c.standard,c.lostStus,c.record,c.phc,c.plc,c.examId from c where c.examId = '{allexamId.acId}' and c.subjectId = '{allexamId.subject}' ";
-                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamResult>(queryText: queryResult, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{allexamId.acId}") }))
-                    {
-                        examResults.Add(item);
-                    }
-                }
-            }
-            (List<RMember> rmembers, List<RGroupList> groups) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, art.classes, art.school);
-            List<ArtStudentPdf> studentPdfs = new List<ArtStudentPdf>();
-            artResults.ForEach(x =>
-            {
-                var allSubject = x.results.GroupBy(g => g.quotaId).Select(s => new { key = s.Key, list = s.ToList() }).ToList();
-                var groupSubject = x.results.GroupBy(g => $"{g.quotaId}-{g.subjectId}").Select(s => new { key = s.Key, list = s.ToList() }).ToList();
-                //综合-所有科目的艺术评测指标维度。
-                List<ArtQuotaPdf> allSubjectArtQuotaPdfs = new List<ArtQuotaPdf>();
-                allSubject.ForEach(a =>
-                {
-
-                    ArtQuotaPdf artPdf = new ArtQuotaPdf();
-                    List<ArtQuota> parents = ArtService.GetParentByChildId(artSetting.quotas, $"{a.key}");
-                    parents.ForEach(x =>
-                    {
-                        switch (true)
-                        {
-                            case bool when x.level == 1:
-                                artPdf.quota1 = x.id;
-                                artPdf.quotaN1 = x.name;
-                                artPdf.quotaP1 = x.percent;
-                                if (a.key.Equals(x.id))
-                                {
-                                    artPdf.quotaName = x.name;
-                                }
-                                break;
-                            case bool when x.level == 2:
-                                artPdf.quota2 = x.id;
-                                artPdf.quotaN2 = x.name;
-                                artPdf.quotaP2 = x.percent;
-                                if (a.key.Equals(x.id))
-                                {
-                                    artPdf.quotaName = x.name;
-                                }
-                                break;
-                            case bool when x.level == 3:
-                                artPdf.quota3 = x.id;
-                                artPdf.quotaN3 = x.name;
-                                artPdf.quotaP3 = x.percent;
-                                if (a.key.Equals(x.id))
-                                {
-                                    artPdf.quotaName = x.name;
-                                }
-                                break;
-                        }
-                    });
-                    var noneScore = a.list.FindAll(x => x.score == -1);
-                    if (!noneScore.IsNotEmpty())
-                    {
-                        //全部未打分。
-                        if (noneScore.Count >= art.subjects.Count)
-                        {
-                            artPdf.quotaId = a.key;
-                            artPdf.score = 0;
-                            artPdf.scoreData = "-";
-                            artPdf.percent = "0";
-                        }
-                        else
-                        {
-                            //有一部分打分的,只算有分的平均分。
-                            var hasScore = a.list.FindAll(x => x.score >= 0);
-                            if (hasScore.IsNotEmpty())
-                            {
-                                var avgScore = hasScore.Sum(x => x.score) * 1.0 / a.list.Count;
-                                var avg = decimal.Round(decimal.Parse($"{avgScore}"), 2);
-                                artPdf.quotaId = a.key;
-                                artPdf.score = double.Parse($"{avg}");
-                                artPdf.scoreData = $"{avg}";
-                                artPdf.percent = $"{avg}";
-                            }
-                            else
-                            {
-                                artPdf.quotaId = a.key;
-                                artPdf.score = 0;
-                                artPdf.scoreData = "-";
-                                artPdf.percent = "0";
-                            }
-                        }
-                    }
-                    else
-                    {
-                        artPdf.quotaId = a.key;
-                        artPdf.score = 0;
-                        artPdf.scoreData = "-";
-                        artPdf.percent = "0";
-                    }
-                    allSubjectArtQuotaPdfs.Add(artPdf);
-                });
-                string level = "";
-                double allScore = 0;
-                if (allSubjectArtQuotaPdfs.Any())
-                {
-                    allScore = allSubjectArtQuotaPdfs.Sum(a => a.score) / allSubjectArtQuotaPdfs.Count;
-                }
-
-                if (allScore >= 100)
-                {
-                    allScore = 100;
-                    level = "优秀(A+)";
-                }
-                if (allScore <= 0)
-                {
-                    allScore = 0;
-                    level = "待及格(D)";
-                }
-                if (allScore < 100)
-                {
-                    artSetting.reviewLevel.ForEach(r =>
-                    {
-                        if (r.value[0] <= allScore && r.value[1] > allScore)
-                        {
-                            level = r.code;
-                        }
-                    });
-                }
-                var rmbs = rmembers.FindAll(r => r.id.Equals(x.studentId) && r.type == 2 && x.code.Equals(x.school));
-                if (rmbs.IsNotEmpty())
-                {
-                    x.studentName = rmbs[0].name;
-                }
-                List<string> classNames = new List<string>();
-                HashSet<string> periodIds = new HashSet<string>();
-                x.classIds.ForEach(c =>
-                {
-                    var gps = groups.FindAll(g => g.id.Equals(c));
-                    if (gps.IsNotEmpty())
-                    {
-                        classNames.Add(gps[0].name);
-                        if (!string.IsNullOrWhiteSpace(gps[0].periodId))
-                        {
-                            periodIds.Add(gps[0].periodId);
-                        }
-                    }
-                });
-                allSubjectArtQuotaPdfs.ForEach(x => x.level = level);
-                var allSubjectQuotas = allSubjectArtQuotaPdfs.OrderBy(o => o.quota1).ThenBy(o => o.quota2).ThenBy(o => o.quota3);
-
-                StringBuilder comment = new StringBuilder();
-                switch (true)
-                {
-                    case bool when level.Contains("(A+)"):
-                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优异"));
-                        break;
-                    case bool when level.Contains("(A)"):
-                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优秀"));
-                        break;
-                    case bool when level.Contains("(B+)"):
-                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现优良"));
-                        break;
-                    case bool when level.Contains("(B)"):
-                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "表现良好"));
-                        break;
-                    case bool when level.Contains("(C+)"):
-                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "还需加强"));
-                        break;
-                    case bool when level.Contains("(C)"):
-                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "有待提高"));
-                        break;
-                    case bool when level.Contains("(D)"):
-                        comment.Append(comment1.Replace("{studentName}", x.studentName).Replace("{level}", "还需努力"));
-                        break;
-                }
-                var score80 = allSubjectArtQuotaPdfs.Where(x => x.score >= 80);
-                if (score80.Any())
-                {
-                    List<string> quota = new List<string>();
-                    var quota3s = score80.Where(c => !string.IsNullOrWhiteSpace(c.quota3)).Select(z => z.quotaN3);
-                    if (quota3s.Any())
-                    {
-                        quota.AddRange(quota3s);
-                    }
-                    var quota2s = score80.Where(c => string.IsNullOrWhiteSpace(c.quota3) && !string.IsNullOrWhiteSpace(c.quota2)).Select(z => z.quotaN2);
-                    if (quota2s.Any())
-                    {
-                        quota.AddRange(quota2s);
-                    }
-                    comment.Append(comment2.Replace("{quotasHigh}", string.Join("、", quota)));
-                }
-                var score60 = allSubjectArtQuotaPdfs.Where(x => x.score < 60);
-                if (score60.Any())
-                {
-                    List<string> quota = new List<string>();
-                    var quota3s = score60.Where(c => !string.IsNullOrWhiteSpace(c.quota3)).Select(z => z.quotaN3);
-                    if (quota3s.Any())
-                    {
-                        quota.AddRange(quota3s);
-                    }
-                    var quota2s = score60.Where(c => string.IsNullOrWhiteSpace(c.quota3) && !string.IsNullOrWhiteSpace(c.quota2)).Select(z => z.quotaN2);
-                    if (quota2s.Any())
-                    {
-                        quota.AddRange(quota2s);
-                    }
-                    comment.Append(comment3.Replace("{quotasLow}", string.Join("、", quota)));
-                }
-                string periodId = "";
-                string periodName = "";
-                if (periodIds.Any())
-                {
-                    var ps = school.period.FindAll(x => periodIds.Contains(x.id));
-                    if (ps.Any())
-                    {
-                        periodName = String.Join(",", ps.Select(x => x.name));
-                        periodId = String.Join(",", ps.Select(x => x.id));
-                    }
-                }
-                List<ArtSubjectPdf> subjectPdfs = new List<ArtSubjectPdf>();
-                exams.ForEach(exam => {
-                    var result= examResults.FindAll(e => e.examId.Equals(exam.id));
-                    if (result.Any()) {
-                        var datas =  DoKnowledgePoint(result.First(), exam, x.studentId);
-                        if (exam.subjects.Any()) {
-                            ArtSubjectPdf artSubjectPdf = new ArtSubjectPdf() {
-                                subjectId= exam.subjects.First().id,
-                                subjectName=exam.subjects.First().name
-                            };
-                           
-                            datas.pointScores.Value.ForEach(k => {
-                                var  artPointPdfs=GetBlockAndDimension(k.score,k.tscore ,artSubjectPdf.subjectId,k.name,subjectBindBlocks,artSetting);
-                                artSubjectPdf.pointPdfs.AddRange(artPointPdfs);
-                            });
-                            var pointHigh= artSubjectPdf.pointPdfs.Where(z => z.percent >= 0.8).Select(z=>z.point).ToHashSet();
-                            var pointLow = artSubjectPdf.pointPdfs.Where(z => z.percent < 0.6).Select(z => z.point).ToHashSet();
-                            StringBuilder comment = new StringBuilder();
-                            if (pointHigh.Any()) {
-                                comment.Append(comment4.Replace("{pointHigh}", string.Join("、", pointHigh)));
-                            }
-                            if (pointLow.Any())
-                            {
-                                comment.Append(comment5.Replace("{pointLow}", string.Join("、", pointLow)));
-                            }
-                            if (artSubjectPdf.subjectId.Equals("subject_music")) {
-                                comment.Append(comment_subject_music);
-                            }
-                            if (artSubjectPdf.subjectId.Equals("subject_painting"))
-                            {
-                                comment.Append(comment_subject_painting);
-                            }
-                            artSubjectPdf.comment = comment.ToString();
-                            subjectPdfs.Add(artSubjectPdf);
-                        }
-                    }
-                });
-                ArtStudentPdf studentPdf = new ArtStudentPdf
-                {
-                    artId = art.id,
-                    schoolCode = school.id,
-                    schoolName = school.name,
-                    periodId = periodId,
-                    periodName = periodName,
-                    studentId = x.studentId,
-                    studentName = x.studentName,
-                    picture = x.picture,
-                    classNames = classNames,
-                    artName = art.name,
-                    level = level,
-                    score = allScore,
-                    allSubjectQuotas = allSubjectQuotas.ToList(),
-                    comment = comment.ToString(),
-                    subjectPdfs= subjectPdfs,
-                };
-                studentPdfs.Add(studentPdf);
-            });
-            _ = _httpTrigger.RequestHttpTrigger(new { studentPdfs = studentPdfs, artResults, schoolCode = $"{_schoolId}" }, _option.Location, "gen-art-pdf");
-            return Ok(new { count = studentPdfs.Count(), studentIds=studentPdfs.Select(z=>z.studentId)});
-        }
-
-        private List<ArtPointPdf> GetBlockAndDimension(double score,double tscore ,string subjectId , string point, List<KeyValuePair<string, List<Block>>> subjectBindBlocks, ArtSetting artSetting) {
-            var block=  subjectBindBlocks.Find(z => z.Key.Equals(subjectId));
-            List<ArtPointPdf> artPointPdfs = new List<ArtPointPdf>();
-            if (!string.IsNullOrWhiteSpace(block.Key)) {
-                block.Value.ForEach(z => {
-                    if (z.points.Contains(point)) {
-                        var dims = artSetting.dimensions.FindAll(m => m.blocks.Contains(z.name));
-                        if (dims.Any()) {
-                            foreach (var dim in dims) {
-                                artPointPdfs.Add(
-                                    new ArtPointPdf
-                                    {
-                                        dimension = dim.dimension,
-                                        block = z.name,
-                                        point = point,
-                                        totalScore = score,
-                                        score = tscore,
-                                        percent = score > 0 ? tscore * 1.0 / score : 0,
-                                    }
-                                );
-                            }
-                        }
-                    }
-                });
-            }
-            return artPointPdfs;
+            List<ArtStudentPdf> studentPdfs = await ArtService.GenArtPDF(artResults, $"{_artId}", $"{_schoolId}", head_lang, _azureCosmos, _environment, _coreAPIHttpService, _dingDing, _serviceBus, _configuration);
+            return Ok(new { count = studentPdfs.Count(), studentIds = studentPdfs.Select(z => z.studentId) });
         }
-        private JsonDocument readFileJson(string path)
-        {
-            var sampleJson = System.IO.File.ReadAllBytes(path).AsSpan();
-            Utf8JsonReader reader = new Utf8JsonReader(sampleJson);
-            if (JsonDocument.TryParseValue(ref reader, out JsonDocument jsonDoc))
-            {
-                return jsonDoc;
-            }
-            else
-            {
-                return null;
-            }
-
-        }
-
-
         /// <summary>
         /// 
         /// </summary>
@@ -541,7 +136,15 @@ namespace TEAMModelOS.Controllers
         public async Task<IActionResult> Review(JsonElement request)
         {
             var client = _azureCosmos.GetCosmosClient();
-
+            string head_lang = "";
+            if (HttpContext.Request.Headers.TryGetValue("lang", out var _lang))
+            {
+                head_lang = $"{_lang}";
+            }
+            if (string.IsNullOrWhiteSpace(head_lang))
+            {
+                head_lang = _option.Location.Contains("China") ? "zh-cn" : "en-us";
+            }
             if (!request.TryGetProperty("opt", out JsonElement _opt))
             {
                 return BadRequest();
@@ -677,7 +280,7 @@ namespace TEAMModelOS.Controllers
                                     }
                                 }
                             }
-
+                          ;
                             if (subjects.IsNotEmpty())
                             {
                                 var subjectScore = subjects.Select(s => new
@@ -685,11 +288,11 @@ namespace TEAMModelOS.Controllers
                                     id = s,
                                     name = As.Where(a => a.subjectId.Equals(s)).Select(x => x.score)
                                 });
-                                return Ok(new { subjectScore, scores, results, status = 1, continuationToken });
+                                return Ok(new { subjectScore, scores, results = results.OrderBy(z => z.studentId), status = 1, continuationToken });
                             }
                             else
                             {
-                                return Ok(new { scores, results, status = 1, continuationToken });
+                                return Ok(new { scores, results = results.OrderBy(z => z.studentId), status = 1, continuationToken });
                             }
 
                         }
@@ -779,10 +382,28 @@ namespace TEAMModelOS.Controllers
                                         });
                                     }
                                 });
+                                List<StudentArtResult> artResults = new List<StudentArtResult>();
+                                ArtEvaluation art = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ArtEvaluation>($"{_artId}", new PartitionKey($"Art-{school}"));
+                                //科目数量
+                                var scount = art.subjects.Count;
+                                //指标数量
+                                var qcount = art.settings.Count;
+                                //需要进行的打分项
+                                var tcount = scount * qcount;
                                 foreach (var rs in studentArtResults)
                                 {
+                                    //已经打分的数量
+                                    var rcount = rs.results.Where(z => z.score > -1).Count();
+                                    if (rcount == tcount)
+                                    {
+                                        artResults.Add(rs);
+                                        //已经打分的数量等于总的打分项,则发起报告生成。
+                                    }
                                     await client.GetContainer(Constant.TEAMModelOS, Constant.Student).ReplaceItemAsync(rs, rs.id, new PartitionKey(rs.code));
                                 }
+                                if (artResults.Any()) {
+                                    List<ArtStudentPdf> studentPdfs = await ArtService.GenArtPDF(artResults, $"{_artId}", $"{school}", head_lang, _azureCosmos, _environment, _coreAPIHttpService, _dingDing, _serviceBus, _configuration);
+                                }
                                 return Ok(new { results = studentArtResults, status = 1 });
                             }
                             break;
@@ -791,108 +412,9 @@ namespace TEAMModelOS.Controllers
             }
             catch (Exception ex)
             {
-
+              await  _dingDing.SendBotMsg($"艺术评测审核异常:{ex.Message}\n{ex.StackTrace}\n{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
             }
             return Ok();
-        }             
-        //获取本次评测所有科目结算结果
-       /* List<ExamResult> examResults = new();
-        ExamInfo info = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ExamInfo>(examId.ToString(), new PartitionKey($"Exam-{code}"));
-        var query = $"select c.id,c.name,c.subjectId,c.studentScores,c.studentIds,c.paper,c.classes,c.sRate,c.average,c.standard,c.lostStus,c.record,c.phc,c.plc from c where c.examId = '{examId}' and c.subjectId = '{subjectId}' ";
-        await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamResult>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamResult-{examId}") }))
-                {
-                    examResults.Add(item);
-                }*/
-    private static (KeyValuePair<string, List<string>> knowledgeName, 
-            KeyValuePair<string, List<(string name, double score)>> pointScore,
-            KeyValuePair<string, List<(string name, double score)>> pointTScore,
-            KeyValuePair<string, List<(string name, double score,double tscore)>> pointScores) DoKnowledgePoint(ExamResult exam, ExamInfo info, string studentId)
-        {
-            HashSet<string> knowledge = new();
-            List<double> point = new();
-            List<List<double>> result = new();
-            List<ClassRange> classes = new();
-
-            //定位试卷信息
-            int index = 0;
-            foreach (ExamSubject subject in info.subjects)
-            {
-                if (subject.id.Equals(exam.subjectId))
-                {
-                    break;
-                }
-                else
-                {
-                    index++;
-                }
-            }
-            if (info.papers[index].knowledge != null && info.papers[index].knowledge.Count > 0)
-            {
-                info.papers[index].knowledge.ForEach(k =>
-                {
-                    k.ForEach(e =>
-                    {
-                        knowledge.Add(e);
-                    });
-                });
-            }
-            else
-            {
-                return (default, default, default,default);
-            }
-            point = info.papers[index].point;
-            result = exam.studentScores;
-            classes = exam.classes;
-
-            List<string> knowledgeName = new List<string>();
-            foreach (string cla in knowledge)
-            {
-                knowledgeName.Add(cla);
-            }
-            for (int k = 0; k < knowledgeName.Count; k++)
-            {
-                if (null == knowledgeName[k])
-                {
-                    knowledgeName.Remove(knowledgeName[k]);
-                }
-            }
-            List<double> knowScore = new();
-            //学生得分情况
-            List<(string name, double score)> pointScore = new();
-            List<(string name, double score)> pointTScore = new();
-            List<(string name, double score,double tscore)> pointScores = new();
-            for (int k = 0; k < knowledgeName.Count; k++)
-            {
-                double OnePoint = 0;
-                List<string> itemNo = new();
-                int n = 0;
-                double scores = 0;
-                info.papers[index].knowledge.ForEach(kno =>
-                {
-                    if (kno.Contains(knowledgeName[k]))
-                    {
-                        var itemPersent = kno.Count > 0 ? 1 / Convert.ToDouble(kno.Count) : 0;
-                        OnePoint += point[n] * itemPersent;
-                        int stuIndex = exam.studentIds.IndexOf(studentId);
-                        if (exam.studentScores[stuIndex][n] > 0)
-                        {
-                            scores += exam.studentScores[stuIndex][n] * itemPersent;
-                        }
-                    }
-                    n++;
-                });
-                //单个知识点的配分
-                pointScore.Add((knowledgeName[k], OnePoint));
-                pointTScore.Add((knowledgeName[k], scores));
-                pointScores.Add((knowledgeName[k], OnePoint, scores));
-
-            }
-            KeyValuePair<string, List<string>> key1 = new(exam.subjectId, knowledgeName);
-            KeyValuePair<string, List<(string name, double score)>> key2 = new(exam.subjectId, pointScore);
-            KeyValuePair<string, List<(string name, double score)>> key3 = new(exam.subjectId, pointTScore);
-            KeyValuePair<string, List<(string name, double score,double  tscore)>> key4 = new(exam.subjectId, pointScores);
-            return (key1, key2, key3, key4 );
         }
     }
-
 }

+ 1 - 1
TEAMModelOS/Controllers/System/BlobController.cs

@@ -267,7 +267,7 @@ namespace TEAMModelOS.Controllers
                 }
             }
             catch (Exception  ex){
-                await _dingDing.SendBotMsg($"IES5,{_option.Location},blon/used-space()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},blob/used-space()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
             }
             return BadRequest();
         }

+ 148 - 0
TEAMModelOS/Controllers/XTest/FixLessonRecordController.cs

@@ -0,0 +1,148 @@
+using Azure.Cosmos;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Newtonsoft.Json;
+using StackExchange.Redis;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Json;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK;
+using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.Common;
+using TEAMModelOS.SDK.Models.Service;
+
+using HTEXLib.COMM.Helpers;
+using Azure.Storage.Blobs.Models;
+using Azure.Storage.Blobs;
+using System.Security.Cryptography;
+using Azure;
+using Microsoft.Extensions.Options;
+using Microsoft.Extensions.Configuration;
+using TEAMModelOS.Models;
+using System.Text.RegularExpressions;
+using TEAMModelOS.SDK.Services;
+using Azure.Messaging.ServiceBus;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using static ICSharpCode.SharpZipLib.Zip.ZipEntryFactory;
+using Azure.Storage.Sas;
+using DocumentFormat.OpenXml.Drawing.Diagrams;
+using TEAMModelOS.SDK.Models.Dtos;
+using DocumentFormat.OpenXml.Bibliography;
+using System.Formats.Asn1;
+
+namespace TEAMModelOS.Controllers.XTest
+{
+    [Route("fix-lesson-record")]
+    [ApiController]
+    public class FixLessonRecordController : ControllerBase
+    {
+        private readonly HttpClient _httpClient;
+        private readonly IConfiguration _configuration;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly AzureRedisFactory _azureRedis;
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly HttpTrigger _httpTrigger;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        public FixLessonRecordController(HttpClient httpClient, HttpTrigger httpTrigger, AzureServiceBusFactory serviceBus, AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService)
+        {
+            _azureCosmos = azureCosmos;
+            _azureRedis = azureRedis;
+            _azureStorage = azureStorage;
+            _dingDing = dingDing;
+            _option = option?.Value;
+            _configuration = configuration;
+            _serviceBus = serviceBus;
+            _httpTrigger = httpTrigger;
+            _coreAPIHttpService = coreAPIHttpService;
+            _httpClient = httpClient;
+        }
+        /// <summary>
+        ///
+        /// </summary>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("fix-tplevel")]
+        public async Task<IActionResult> FixTPlevel(JsonElement json)
+        {
+            var client = _azureCosmos.GetCosmosClient();
+            string sql = " SELECT distinct value(c)  FROM c  where c.pk='LessonRecord'  ";
+            List<LessonRecord> lessonRecords = new List<LessonRecord>();
+            await foreach (var lessonRecord in client.GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<LessonRecord>(queryText: sql))
+            { 
+                //计算TP灯
+                {
+                    int T = -1;
+                    int P = -1;
+                    if (lessonRecord.clientInteractionAverge <= 0)
+                    {
+                        T = 0;
+                    }
+                    else if (lessonRecord.clientInteractionAverge >= 1 && lessonRecord.clientInteractionAverge <= 2)
+                    {
+                        T = 1;
+                    }
+                    else
+                    {
+                        T = 2;
+                    }
+                    if (lessonRecord.examCount > 0)
+                    {
+                        //有评测次数大于0则P是直接绿灯
+                        P = 2;
+                    }
+                    else
+                    {
+
+                        int a = lessonRecord.collateTaskCount;
+                        int b = lessonRecord.pushCount;
+                        int c = lessonRecord.examCount;
+                        switch (true)
+                        {
+                            case bool when T == 0:
+                                P = 0;
+                                break;
+                            case bool when T == 1 || T == 2:
+                                if (a == 0 && b == 0 && c == 0)
+                                {
+                                    P = 0;
+                                }
+                                else if ((a > 0 && b > 0) || (a > 0 && c > 0) || (b > 0 && c > 0))
+                                {
+                                    P = 2;
+                                }
+                                else
+                                {
+                                    P = 1;
+                                }
+                                break;
+                        }
+                    }
+                    lessonRecord.tLevel = T;
+                    lessonRecord.pLevel = P;
+                }
+                lessonRecords.Add(lessonRecord);
+            }
+            var datas = lessonRecords.GroupBy(z => z.code).Select(x => new { key = x.Key, list = x.ToList() });
+            foreach (var item in datas) {
+                List<Task<ItemResponse<LessonRecord>>> responses = new List<Task<ItemResponse<LessonRecord>>>();
+                item.list.ForEach(z => {
+                    responses.Add(_azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(z, z.id, new PartitionKey(z.code)));
+                });
+                await Task.WhenAll(responses);
+            }
+            return Ok();
+        }
+    }
+}