CrazyIter_Bin 5 bulan lalu
induk
melakukan
14fbc1279e

+ 5 - 5
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/IndexController.cs

@@ -116,7 +116,7 @@ namespace IES.ExamServer.Controllers
                                     string content = await response.Content.ReadAsStringAsync();
                                     if (!string.IsNullOrWhiteSpace(content))
                                     {
-                                        jsonNode = JsonSerializer.Deserialize<JsonNode>(content);
+                                        jsonNode = content.ToObject<JsonNode>();
                                     }
                                     else
                                     {
@@ -141,7 +141,7 @@ namespace IES.ExamServer.Controllers
                                     string content = await response.Content.ReadAsStringAsync();
                                     if (!string.IsNullOrWhiteSpace(content))
                                     {
-                                        jsonNode = JsonSerializer.Deserialize<JsonNode>(content);
+                                        jsonNode = content.ToObject<JsonNode>();
                                     }
                                     else
                                     {
@@ -160,9 +160,9 @@ namespace IES.ExamServer.Controllers
                     }
                     if (jsonNode != null  && $"{jsonNode["code"]}".Equals("200"))
                     {
-                        token = JsonSerializer.Deserialize<TmdidImplicit>(jsonNode["implicit_token"]);
+                        token =jsonNode["implicit_token"]?.ToObject<TmdidImplicit>(); 
                         x_auth_token = $"{jsonNode["x_auth_token"]}";
-                        schools = JsonSerializer.Deserialize<List<School>>(jsonNode["schools"]);
+                        schools =jsonNode["schools"]?.ToObject<List<School>>(); 
                         var jwt = new JwtSecurityToken(token?.id_token);
                         var id = jwt.Payload.Sub;
                         jwt.Payload.TryGetValue("name", out object? name);
@@ -247,7 +247,7 @@ namespace IES.ExamServer.Controllers
                             if (message.IsSuccessStatusCode)
                             {
                                 string content = await message.Content.ReadAsStringAsync();
-                                JsonNode? jsonNode = JsonSerializer.Deserialize<JsonNode>(content);
+                                JsonNode? jsonNode = content?.ToObject<JsonNode>();
                                 if (jsonNode!=null && int.TryParse($"{jsonNode["send"]}", out int s))
                                 {
                                     send = s;

+ 55 - 21
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/ManageController.cs

@@ -22,13 +22,13 @@ namespace IES.ExamServer.Controllers
         private readonly IConfiguration _configuration;
         private readonly IHttpClientFactory _httpClientFactory;
         private readonly IMemoryCache _memoryCache;
-        private readonly ILogger<ManageController> _logger;
+        private readonly ILogger _logger;
         private readonly LiteDBFactory _liteDBFactory;
         private readonly DataCenterConnectionService _connectionService;
         private readonly int DelayMicro = 10;//微观数据延迟
         private readonly int DelayMacro = 100;//宏观数据延迟
         private readonly SignalRExamServerHub _signalRExamServerHub;
-        public ManageController(LiteDBFactory liteDBFactory,ILogger<ManageController> logger, IConfiguration configuration,
+        public ManageController(LiteDBFactory liteDBFactory,ILogger logger, IConfiguration configuration,
             IHttpClientFactory httpClientFactory, IMemoryCache memoryCache, DataCenterConnectionService connectionService,SignalRExamServerHub signalRExamServerHub)
         {
             _logger = logger;
@@ -100,17 +100,17 @@ namespace IES.ExamServer.Controllers
                     if (message.IsSuccessStatusCode) 
                     {
                         string content = await message.Content.ReadAsStringAsync();
-                        JsonNode? jsonNode =JsonSerializer.Deserialize<JsonNode>(content);
+                        JsonNode? jsonNode =content.ToObject<JsonNode>();
                         if (jsonNode!=null) 
                         {
-                            evaluationCloud= JsonSerializer.Deserialize<EvaluationClient>(jsonNode["evaluation"]);
+                            evaluationCloud=jsonNode["evaluation"]?.ToObject<EvaluationClient>(); 
                         }
                     }
                 }
             }
             //数据,文件,页面 0 没有更新,1 有更新
-            int data = 0,blob=0,webview=0,status=0;
-            long dataSize = 0, blobSize=0 , webviewSize=0;
+            int data = 0,blob=0,webview=0, groupList=0, status=0;
+            long dataSize = 0, blobSize=0 , webviewSize=0, studentCount=0;
             if (evaluationLocal== null && evaluationCloud==null)
             {
                 //线上线下没有数据
@@ -130,7 +130,9 @@ namespace IES.ExamServer.Controllers
                     blobSize=evaluationCloud.blobSize;
                 }
                 if ((evaluationLocal.dataTime<evaluationCloud.dataTime)
-                    ||(evaluationLocal.dataSize!=evaluationCloud.dataSize))
+                    ||(evaluationLocal.dataSize!=evaluationCloud.dataSize)
+                    ||(evaluationLocal.paperCount!= evaluationCloud.paperCount)
+                    )
                 {
                     data=1;
                     dataSize=evaluationCloud.dataSize;
@@ -143,6 +145,11 @@ namespace IES.ExamServer.Controllers
                     webview=1;
                     webviewSize=evaluationCloud.webviewSize;
                 }
+                if ((evaluationLocal.studentCount!= evaluationCloud.studentCount)||(!$"{evaluationLocal.grouplistHash}".Equals(evaluationCloud.grouplistHash)))  
+                {
+                    groupList=1;
+                    studentCount=evaluationCloud.studentCount;
+                }
             }
             else if (evaluationLocal!=null && evaluationCloud==null)
             {
@@ -156,9 +163,11 @@ namespace IES.ExamServer.Controllers
                 blob=1;
                 data=1;
                 webview=1;
+                groupList=1;
                 blobSize=evaluationCloud.blobSize;
                 dataSize=evaluationCloud.dataSize;
                 webviewSize=evaluationCloud.webviewSize;
+                studentCount=evaluationCloud.studentCount;
                 status = 4;
                 _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Insert(evaluationLocal);
             }
@@ -168,7 +177,7 @@ namespace IES.ExamServer.Controllers
 
 
                 await _signalRExamServerHub.SendMessage(deviceId, Constant._Message_grant_type_check_file, 
-                    new MessageContent {messageType=Constant._Message_type_message, status=0, content="开始检查评测信息文件.." });
+                    new MessageContent {dataId=evaluationLocal.id,dataName=evaluationLocal.name,messageType=Constant._Message_type_message, status=0, content="开始检查评测信息文件.." });
                 //校验本地文件数据
                 string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
                 if (!Directory.Exists(packagePath))
@@ -185,12 +194,31 @@ namespace IES.ExamServer.Controllers
                 else 
                 {
                     msg_status=Constant._Message_status_success;
+                    //string jsonData =  await System.IO.File.ReadAllTextAsync(path_evaluation);
+                    //EvaluationClient? evaluationFile =jsonData.ToObject<EvaluationClient>();
+                    //if (evaluationFile!=null)
+                    //{
+                    //    if (evaluationFile.dataSize==evaluationLocal.dataSize )
+                    //    {
+                    //        file_error.Add("evaluation");
+                    //        msg_status=Constant._Message_status_error;
+                    //    }
+                    //    else
+                    //    {
+                    //        msg_status=Constant._Message_status_success;
+                    //    }
+                    //}
+                    //else
+                    //{
+                    //    file_error.Add("evaluation");
+                    //    msg_status=Constant._Message_status_error;
+                    //}
                 }
                 //数据格式:  [消息][信息/错误/警告][15:43]=>[开始检查评测信息文件...]
                 //数据格式:  [检查][成功/失败][15:43]=>[评测数据文件:/wwwroot/package/623a9fe6-5445-0938-ff77-aeb80066ef27/evaluation.json]
                 //数据格式:  [下载][成功/失败][15:43]=>[评测数据文件:/wwwroot/package/623a9fe6-5445-0938-ff77-aeb80066ef27/evaluation.json][1024kb][15ms]
                 await _signalRExamServerHub.SendMessage(deviceId, Constant._Message_grant_type_check_file, 
-                    new MessageContent { messageType= Constant._Message_type_check, status=msg_status,content=$"评测数据文件:{path_evaluation}" });
+                    new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status,content=$"评测数据文件:{path_evaluation}" });
                 //await Task.Delay(DelayMacro);
                 string path_groupList = Path.Combine(evaluationPath, "groupList.json");
                 msg_status =Constant._Message_status_info;
@@ -204,7 +232,7 @@ namespace IES.ExamServer.Controllers
                     msg_status=Constant._Message_status_success;
                 }
                 await _signalRExamServerHub.SendMessage(deviceId, Constant._Message_grant_type_check_file, 
-                    new MessageContent { messageType= Constant._Message_type_check, status=msg_status, content=$"评测名单文件:{path_groupList}" });
+                    new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content=$"评测名单文件:{path_groupList}" });
                 //await Task.Delay(DelayMacro);
                 string path_source = Path.Combine(evaluationPath, "source.json");
                 msg_status = Constant._Message_status_info;
@@ -218,17 +246,17 @@ namespace IES.ExamServer.Controllers
                     msg_status=Constant._Message_status_success;
                 }
                 await _signalRExamServerHub.SendMessage(deviceId, Constant._Message_grant_type_check_file,
-                    new MessageContent { messageType= Constant._Message_type_check, status=msg_status, content=$"评测原始数据:{path_source}" });
+                    new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content=$"评测原始数据:{path_source}" });
                // await Task.Delay(DelayMacro);
                 msg_status =Constant._Message_status_info;
                 try {
 
                     string evaluation_str = await System.IO.File.ReadAllTextAsync(path_evaluation);
-                    JsonNode? evaluation_data = JsonSerializer.Deserialize<JsonNode>(evaluation_str);
+                    JsonNode? evaluation_data = evaluation_str.ToObject<JsonNode>(); 
                     
                     if (evaluation_data!=null) 
                     {
-                        EvaluationClient? evaluationClient = JsonSerializer.Deserialize<EvaluationClient>(evaluation_data["evaluationClient"]);
+                        EvaluationClient? evaluationClient = evaluation_data["evaluationClient"]?.ToObject<EvaluationClient>(); 
                         if (evaluationClient!=null) 
                         {
                             if ((!string.IsNullOrWhiteSpace(evaluationLocal.blobHash) && evaluationLocal.blobHash.Equals(evaluationClient.blobHash))
@@ -247,10 +275,10 @@ namespace IES.ExamServer.Controllers
                                 msg_status=Constant._Message_status_error;
                             }
                             await _signalRExamServerHub.SendMessage(deviceId, Constant._Message_grant_type_check_file,
-                                new MessageContent { messageType=Constant._Message_type_message, status=msg_status, content="校验本地数据文件..." });
+                                new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="校验本地数据文件..." });
                         }
 
-                        List<EvaluationExam>? evaluationExams = JsonSerializer.Deserialize<List<EvaluationExam>>(evaluation_data["evaluationExams"]);
+                        List<EvaluationExam>? evaluationExams = evaluation_data["evaluationExams"]?.ToObject<List<EvaluationExam>>();
                         if (evaluationExams.IsNotEmpty()) 
                         {
                             string path_papers = Path.Combine(evaluationPath, "papers");
@@ -286,7 +314,10 @@ namespace IES.ExamServer.Controllers
                                             msg_status=Constant._Message_status_warning; ;
                                             paper_error_count++;
                                         }
-                                        contents.Add(new MessageContent { messageType=Constant._Message_type_check, status=msg_status, content=$"试卷文件信息:{paper.paperName}" });
+                                        contents.Add(new MessageContent {
+                                            dataId=evaluationLocal.id,
+                                            dataName=evaluationLocal.name,
+                                            messageType=Constant._Message_type_check, status=msg_status, content=$"试卷文件信息:{paper.paperName}" });
                                     }
                                     int paper_msg_status = Constant. _Message_status_info;
                                     if (paper_error_count>0)
@@ -298,6 +329,8 @@ namespace IES.ExamServer.Controllers
                                     }
                                     await _signalRExamServerHub.SendMessage(deviceId, Constant._Message_grant_type_check_file, 
                                         new MessageContent {
+                                            dataId=evaluationLocal.id,
+                                            dataName=evaluationLocal.name,
                                             messageType=Constant._Message_type_message,
                                             status=paper_msg_status,
                                             content=$"试卷名称:[{paperIndex}]{evaluationExam.examName}-{evaluationExam.subjectName}-{paper.paperName}\r\n文件数量:{paper.blobs.Count()},检测成功数量:{contents.Count(x => x.status==Constant._Message_status_success)},检测异常数量{contents.Count(x => x.status==Constant._Message_status_error)}",
@@ -311,13 +344,14 @@ namespace IES.ExamServer.Controllers
                 catch (Exception e) { 
                 
                 }
+                //检测参考名单
                 await _signalRExamServerHub.SendMessage(deviceId, Constant._Message_grant_type_check_file, 
-                    new MessageContent { messageType=Constant._Message_type_message, status=0, content="提取评测数据文件..." });
-                
-
+                    new MessageContent {
+                        dataId=evaluationLocal.id,
+                        dataName=evaluationLocal.name,
+                        messageType=Constant._Message_type_message, status=0, content="提取评测数据文件..." });
             }
-
-            return Ok(new {code=200, evaluation= evaluationLocal,data,blob,webview,dataSize,blobSize,webviewSize,status });
+            return Ok(new {code=200, evaluation= evaluationLocal,data,blob,webview,dataSize,blobSize,webviewSize,status ,groupList,studentCount});
         }
 
         /// <summary>

+ 3 - 5
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/CustomFileLoggerProvider.cs

@@ -168,10 +168,8 @@ namespace IES.ExamServer.DI
         //懒加载
         private static readonly Lazy<Task> _fileLogProcessor = new Lazy<Task>(() => Task.Run(ProcessFileLogs));
         private static readonly Lazy<Task> _consoleLogProcessor = new Lazy<Task>(() => Task.Run(ProcessConsoleLogs));
-        private static readonly JsonSerializerOptions jsonSerializerOptions ;
-        static LoggerExtensions(){
-            jsonSerializerOptions= new JsonSerializerOptions { Encoder=JavaScriptEncoder.Create(UnicodeRanges.All) };
-        }
+       
+        
 
         public static void LogData<T>(this ILogger logger, T data, string id)
         {
@@ -185,7 +183,7 @@ namespace IES.ExamServer.DI
             }
 
             var logFilePath = Path.Combine(logDirectory, $"{id}.log");
-            var logMessage = System.Text.Json.JsonSerializer.Serialize(data, jsonSerializerOptions);
+            var logMessage = data?.ToJsonString();
             _fileLogChannel.Writer.TryWrite($"{logFilePath}|||{DateTime.Now:yyyy-MM-dd HH:mm:ss} [Data] {logMessage}{Environment.NewLine}");
             //_ = Task.Run(async () =>
             //{

+ 32 - 15
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/SignalRHost/SignalRExamServerHub.cs

@@ -36,31 +36,48 @@ namespace IES.ExamServer.DI.SignalRHost
             {
                 signalRClient = _memoryCache.Get<SignalRClient>($"{Constant._KeySignalRClientConnects}:{signalRClient.connid}");
             }
+            int code=0;
+            string msg = "";
+            CheckFileMessageBody messageBody = new CheckFileMessageBody
+            {
+                content = content.content,
+                status = content.status,
+                clientid = clientId,
+                connid = signalRClient?.connid,
+                grant_type = grant_type,
+                time = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
+                type = Constant._Message_type_message,
+                contents = content.contents
+            };
             if (signalRClient != null)
             {
-                try {
+
+                try
+                {
                     switch (true)
                     {
                         case bool when grant_type.Equals(Constant._Message_grant_type_check_file):
                             {
-                                await Clients.Client(signalRClient.connid!).ReceiveMessage(new CheckFileMessageBody
-                                {
-                                    content = content.content,
-                                    status = content.status,
-                                    clientid = clientId,
-                                    connid = signalRClient.connid,
-                                    grant_type = grant_type,
-                                    time = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
-                                    type = Constant._Message_type_message,
-                                    contents = content.contents
-                                });
+                                await Clients.Client(signalRClient.connid!).ReceiveMessage(messageBody);
+                                code=200;
+                                msg = $"发送成功";
                                 break;
                             }
                         default:
                             break;
                     }
-                } catch { }
+                }
+                catch (Exception ex)
+                {
+                    code=500;
+                    msg = $"{ex.Message},{ex.StackTrace}";
+                }
+            }
+            else {
+                code= 400;
+                msg="未连接客户端";
             }
+            _logger.LogData<object>(new {code ,msg,data =  messageBody }, content.dataId!);
         }
 
         /// <summary>
@@ -94,8 +111,8 @@ namespace IES.ExamServer.DI.SignalRHost
                         // 检查文件
                         case bool when grant_type.Equals(Constant._Message_grant_type_check_file):
                             {
-                                _memoryCache.Set($"{Constant._KeySignalRClientClients}:{Constant._Message_grant_type_check_file}:{clientid}", JsonSerializer.Serialize(client));
-                                _memoryCache.Set($"{Constant._KeySignalRClientConnects}:{Constant._Message_grant_type_check_file}:{connid}", JsonSerializer.Serialize(client));
+                                _memoryCache.Set($"{Constant._KeySignalRClientClients}:{Constant._Message_grant_type_check_file}:{clientid}", client);
+                                _memoryCache.Set($"{Constant._KeySignalRClientConnects}:{Constant._Message_grant_type_check_file}:{connid}", client);
                                 await SendConnection(connid, new ConnectionMessageBody
                                 {
                                     connid=connid,

+ 51 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/JsonExtensions.cs

@@ -0,0 +1,51 @@
+using System.Buffers;
+using System.Text;
+using System.Text.Encodings.Web;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using System.Text.Unicode;
+using System.Xml.Linq;
+
+namespace IES.ExamServer
+{
+    public static class JsonExtensions
+    {
+        private static readonly JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions
+        {
+            Encoder = JavaScriptEncoder.Create(UnicodeRanges.All)
+        };
+        public static string ToJsonString(this JsonElement json)
+        {
+            return JsonSerializer.Serialize(json, jsonSerializerOptions);
+        }
+        public static string ToJsonString(this Object obj)
+        {
+            return JsonSerializer.Serialize(obj, jsonSerializerOptions);
+        }
+        public static string ToJsonString(this JsonNode node)
+        {
+            return JsonSerializer.Serialize(node, jsonSerializerOptions);
+        }
+        public static T? ToObject<T>(this JsonElement json) where T : class
+        {
+            return JsonSerializer.Deserialize<T>(json.GetRawText(), jsonSerializerOptions);
+        }
+        public static T? ToObject<T>(this string json) where T : class
+        {
+            try
+            {
+                return JsonSerializer.Deserialize<T>(json, jsonSerializerOptions);
+            }
+            catch (JsonException ex)
+            {
+                return null;
+               // throw new InvalidOperationException("Failed to deserialize JSON.", ex);
+            }
+        }
+
+        public static T? ToObject<T>(this JsonNode json) where T : class
+        {
+            return JsonSerializer.Deserialize<T>(json, jsonSerializerOptions!);
+        }
+    }
+}

+ 5 - 5
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/ShaHashHelper.cs

@@ -8,7 +8,7 @@ namespace IES.ExamServer.Helpers
         public static string GetSHA1(string Code)
         {
             var resbuffer = Encoding.Default.GetBytes(Code);
-            HashAlgorithm iSha = new SHA1CryptoServiceProvider();
+            HashAlgorithm iSha =   SHA1.Create();
             resbuffer = iSha.ComputeHash(resbuffer);
             StringBuilder builder = new StringBuilder();
             for (int i = 0; i < resbuffer.Length; i++)
@@ -21,7 +21,7 @@ namespace IES.ExamServer.Helpers
         public static string GetSHA1(byte[] buffer)
         {
             var resbuffer = buffer;
-            HashAlgorithm iSha = new SHA1CryptoServiceProvider();
+            HashAlgorithm iSha = SHA1.Create();
             resbuffer = iSha.ComputeHash(buffer);
             StringBuilder builder = new StringBuilder();
             for (int i = 0; i < resbuffer.Length; i++)
@@ -38,7 +38,7 @@ namespace IES.ExamServer.Helpers
             stream.Read(buffer, 0, buffer.Length);
             // stream.Close();
             var resbuffer = buffer;
-            HashAlgorithm iSha = new SHA1CryptoServiceProvider();
+            HashAlgorithm iSha = SHA1.Create();
             resbuffer = iSha.ComputeHash(buffer);
             StringBuilder builder = new StringBuilder();
             for (int i = 0; i < resbuffer.Length; i++)
@@ -76,7 +76,7 @@ namespace IES.ExamServer.Helpers
         }
         public static string GetSHA256(byte[] buffer)
         {
-            SHA256Managed Sha256 = new SHA256Managed();
+            var Sha256 = SHA256.Create();
             byte[] resbuffer = Sha256.ComputeHash(buffer);
             StringBuilder builder = new StringBuilder();
             for (int i = 0; i < resbuffer.Length; i++)
@@ -90,7 +90,7 @@ namespace IES.ExamServer.Helpers
 
         public static string GetSHA256(string Code)
         {
-            SHA256Managed Sha256 = new SHA256Managed();
+            var Sha256 = SHA256.Create();
             byte[] resbuffer = Sha256.ComputeHash(Encoding.UTF8.GetBytes(Code));
             StringBuilder builder = new StringBuilder();
             for (int i = 0; i < resbuffer.Length; i++)

+ 3 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/IES.ExamServer.csproj

@@ -14,7 +14,9 @@
 	  <Content Remove="ClientApp\package-lock.json" />
 	  <Content Remove="ClientApp\package.json" />
 	</ItemGroup>
-	
+	<!-- <PropertyGroup>
+		<ApplicationManifest>app.manifest</ApplicationManifest>
+	</PropertyGroup>-->
 	<ItemGroup>
 		<Folder Include="Logs\DataLogs\" />
 		<Folder Include="wwwroot\package\" />

+ 8 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Models/SignalRClient.cs

@@ -88,6 +88,14 @@
         /// 批量信息
         /// </summary>
         public List<MessageContent> contents { get; set; } = new List<MessageContent>();
+        /// <summary>
+        /// 数据id
+        /// </summary>
+        public string? dataId {  get; set; }
+        /// <summary>
+        /// 数据名称
+        /// </summary>
+        public string? dataName {  get; set; }
     }
  
     public class SignalRClient

+ 3 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Program.cs

@@ -18,6 +18,7 @@ using System.Security.Principal;
 using Microsoft.Extensions.FileProviders;
 using System.Text.Encodings.Web;
 using System.Text.Unicode;
+using Microsoft.Extensions.Logging;
 
 namespace IES.ExamServer
 {
@@ -90,6 +91,8 @@ namespace IES.ExamServer
             //builder.Logging.ClearProviders();
             //bool enableConsoleOutput = true;
             //builder.Logging.AddProvider(new CustomFileLoggerProvider(Path.Combine(Directory.GetCurrentDirectory(), "Logs"), enableConsoleOutput));
+            // Ìí¼ÓÈÕÖ¾·þÎñ
+           
             var app = builder.Build();
 
             // Configure the HTTP request pipeline.

+ 7 - 7
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/app.manifest

@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
 <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
-  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
-    <security>
-      <requestedPrivileges>
-		  <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
-      </requestedPrivileges>
-    </security>
-  </trustInfo>
+	<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+		<security>
+			<requestedPrivileges>
+				<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
+			</requestedPrivileges>
+		</security>
+	</trustInfo>
 </assembly>

+ 9 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/appsettings.json

@@ -2,7 +2,15 @@
   "Logging": {
     "LogLevel": {
       "Default": "Information",
-      "Microsoft.AspNetCore": "Warning"
+      "Microsoft.AspNetCore": "Warning",
+      "Microsoft": "Warning",
+      "Microsoft.Hosting.Lifetime": "Information"
+    },
+    "File": {
+      "Path": "Logs/app-.log",
+      "Append": true,
+      "MaxFileSize": 20971520, // 10 MB
+      "MaxRollingFiles": 10 // 保留最近7个文件
     }
   },
   "AllowedHosts": "*",

+ 25 - 6
TEAMModelOS.Extension/IES.ExamLib/Models/EvaluationCommon.cs

@@ -27,6 +27,18 @@ namespace IES.ExamServer.Models
         /// </summary>
         public string? owner { get; set; }
         /// <summary>
+        /// 数据源的id
+        /// </summary>
+        public string? ownerId { get; set; }
+        /// <summary>
+        /// 数据源的名称
+        /// </summary>
+        public string? ownerName { get; set; }
+        /// <summary>
+        /// 数据源的logo
+        /// </summary>
+        public string? ownerPicture { get; set; }
+        /// <summary>
         /// 数据范围
         /// </summary>
         public string? scope { get; set; }
@@ -91,15 +103,23 @@ namespace IES.ExamServer.Models
         /// 名单集合
         /// </summary>
         public List<string> grouplist { get; set; } = new List<string>();
-
+        /// <summary>
+        /// 名单哈希值
+        /// </summary>
+        public string? grouplistHash {  get; set; }
+        /// <summary>
+        /// 数据哈希值
+        /// </summary>
+        public string? dataHash { get; set; }
         /// <summary>
         /// 开卷码
         /// </summary>
         public string? shortCode { get; set; }
+      
     }
 
 
-    public class EvaluationClient: EvaluationMain 
+    public class EvaluationClient : EvaluationMain
     {
         /// <summary>
         /// 开始时间
@@ -120,18 +140,17 @@ namespace IES.ExamServer.Models
         /// <summary>
         /// 激活状态0未激活,1 激活
         /// </summary>
-        public int activate {  get; set; }
+        public int activate { get; set; }
 
     }
     public class SubjectExam
-    { 
+    {
         public string? examId { get; set; }
         public string? subjectId { get; set; }
         public string? subjectName { get; set; }
         public List<SubjectExamPaper> papers { get; set; } = new List<SubjectExamPaper>();
-
     }
-    
+
     public class EvaluationExam 
     {
 

+ 1 - 0
TEAMModelOS.SDK/Models/Cosmos/Normal/EvaluationSyncInfo.cs

@@ -103,5 +103,6 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Normal
         public long updateTime { get; set; }
 
         public School school { get; set; }
+        public TEAMModelOS.SDK.Models.Teacher teacher { get; set; }
     }
 }

+ 83 - 19
TEAMModelOS.SDK/Models/Service/EvaluationSyncInfoService.cs

@@ -4,6 +4,7 @@ using Microsoft.Azure.Cosmos;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection.Metadata.Ecma335;
 using System.Text;
 using System.Text.Json;
 using System.Text.Json.Nodes;
@@ -29,22 +30,35 @@ namespace TEAMModelOS.SDK.Models.Service
         /// <param name="type"></param>
         /// <param name="azureCosmos"></param>
         /// <param name="azureStorage"></param>
-        public static async Task<EvaluationSyncInfo> PackageEvaluation( string id,string scope, string owner, string type, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage,CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing)
+        public static async Task<EvaluationSyncInfo> PackageEvaluation( string id,string scope, string ownerId, string type, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage,CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing)
         {
             EvaluationSource evaluationSource = new EvaluationSource() { type=type,id=id};
             EvaluationSyncInfo evaluationSyncInfo= null;
             EvaluationClient  evaluationClient = null;
             List<EvaluationExam> evaluationExams = new List<EvaluationExam>();
-            School school = null;
+            
             long? dataTime = 0;
             long stime = 0;
             long etime = 0;
+
+            
+            string? ownerName=string.Empty;
+            string? ownerPicture = string.Empty;
             string schoolCode = null;
             if (scope.Equals("school"))
             {
-                schoolCode= owner;
-                school = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(owner, new PartitionKey("Base"));
+                School school = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(ownerId, new PartitionKey("Base"));
+                schoolCode= ownerId;
                 evaluationSource.school = school;
+                ownerName = school.name;
+                ownerPicture = school.picture;
+            }
+            else 
+            {
+                Teacher teacher = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>(ownerId, new PartitionKey("Base"));
+                evaluationSource.teacher = teacher;
+                ownerName = teacher.name;
+                ownerPicture = teacher.picture;
             }
             var responseEvaluationSyncInfo = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemStreamAsync(id, new PartitionKey("EvaluationSyncInfo"));
             if (responseEvaluationSyncInfo.IsSuccessStatusCode)
@@ -55,10 +69,12 @@ namespace TEAMModelOS.SDK.Models.Service
                 evaluationSyncInfo=new EvaluationSyncInfo {
                     id = id,
                     scope = scope,
-                    owner = owner,
                     type = type,
                     pk="EvaluationSyncInfo",
                     code="ActivitySyncInfo",
+                    ownerId = ownerId,
+                    ownerPicture = ownerPicture,
+                    ownerName = ownerName,
                 };
             }
            
@@ -66,7 +82,7 @@ namespace TEAMModelOS.SDK.Models.Service
             {
                 case bool when (type == "Exam"):
                     {
-                        string code = $"Exam-{owner}";
+                        string code = $"Exam-{ownerId}";
                         var response = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(id, new PartitionKey(code));
                         if (response.IsSuccessStatusCode)
                         {
@@ -110,7 +126,7 @@ namespace TEAMModelOS.SDK.Models.Service
                                         subjectId=subject.id,
                                         subjectName=subject.name,
                                         classes= evaluationSyncInfo.grouplist,
-                                        owner=owner,
+                                        owner=exam.owner,
                                         scope=scope,
                                         stime=stime,
                                         etime=etime,
@@ -125,7 +141,7 @@ namespace TEAMModelOS.SDK.Models.Service
                     }
                 case bool when (type == "Art"):
                     {
-                        string code = $"Art-{owner}";
+                        string code = $"Art-{ownerId}";
                         var response = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(id, new PartitionKey(code));
                         if (response.IsSuccessStatusCode) 
                         {
@@ -160,7 +176,7 @@ namespace TEAMModelOS.SDK.Models.Service
                                 if (!string.IsNullOrWhiteSpace(item.acId)) 
                                 {
                                     var subject = art.subjects.Find(x => x.id.Equals(item.subject));
-                                    var examResponse=  await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(item.acId, new PartitionKey($"Exam-{owner}"));
+                                    var examResponse=  await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(item.acId, new PartitionKey($"Exam-{ownerId}"));
 
                                     if (examResponse.IsSuccessStatusCode) 
                                     {
@@ -184,7 +200,7 @@ namespace TEAMModelOS.SDK.Models.Service
                                             subjectId=subject.id,
                                             subjectName=subject.name,
                                             classes= evaluationSyncInfo.grouplist,
-                                            owner=owner,
+                                            owner=exam.owner,
                                             scope=scope,
                                             stime=stime,
                                             etime=etime,
@@ -214,7 +230,7 @@ namespace TEAMModelOS.SDK.Models.Service
                 var listInfo = await GroupListService.GetMemberByListids(_coreAPIHttpService, azureCosmos.GetCosmosClient(), _dingDing, evaluationSyncInfo.grouplist, schoolCode);
                 evaluationSyncInfo.studentCount =  listInfo.rmembers.Count();
                 evaluationSyncInfo.paperCount =evaluationSyncInfo.subjects.Select(x => x.papers).Count();
-                var client = azureStorage.GetBlobContainerClient(owner);
+                var client = azureStorage.GetBlobContainerClient(ownerId);
                 foreach (var subject in evaluationSyncInfo.subjects)
                 {
                     var evaluationExam =  evaluationExams.FindAll(x => x.subjectId.Equals(subject.subjectId)).FirstOrDefault();
@@ -269,6 +285,41 @@ namespace TEAMModelOS.SDK.Models.Service
                 evaluationSyncInfo.blobHash = ShaHashHelper.GetSHA1(string.Join("-", evaluationSyncInfo.subjects.SelectMany(x => x.papers).Select(x => x.paperHash)));
                 evaluationSyncInfo.dataTime = dataTime.Value;
                 evaluationSource.updateTime = dataTime.Value;
+                var groupList = new { members = listInfo.rmembers, groupList = listInfo.groups };
+                {
+                    //计算数据的hash值
+                  
+                    StringBuilder groupListData = new StringBuilder();
+                    //名单的hash值
+                    var orderList = listInfo.groups.OrderBy(x => x.id);
+                    foreach (var item in orderList)
+                    {
+                        groupListData.Append($"{item.id}-{item.name}");
+                        var orderMembers = item.members.OrderBy(x => x.id);
+                        foreach (var member in orderMembers)
+                        {
+                            groupListData.Append($"{member.id}-{member.name}");
+                        }
+                    }
+                    evaluationSyncInfo.grouplistHash= ShaHashHelper.GetSHA1(groupListData.ToString());
+                    var order=  evaluationSyncInfo.subjects.OrderBy(x => x.subjectId);
+                    StringBuilder dataStr = new StringBuilder();
+                    dataStr.Append(evaluationSyncInfo.id);
+                    dataStr.Append(evaluationSyncInfo.name);
+                    dataStr.Append(evaluationSyncInfo.type);
+                    dataStr.Append(evaluationSyncInfo.owner);
+                    dataStr.Append(evaluationSyncInfo.ownerId);
+                    dataStr.Append(evaluationSyncInfo.scode);
+                    dataStr.Append(evaluationSyncInfo.scope);
+                    dataStr.Append(evaluationSyncInfo.grouplistHash);
+                    dataStr.Append(evaluationSyncInfo.blobHash);
+                    dataStr.Append(evaluationSyncInfo.shortCode);
+                    dataStr.Append($"{stime}{etime}");
+                    dataStr.Append(string.Join("", order.Select(x=>x.subjectId)));
+                    //计算dataHash
+                    evaluationSyncInfo.dataHash = ShaHashHelper.GetSHA1(dataStr.ToString());
+                }
+
                 evaluationClient= new EvaluationClient
                 {
                     id = evaluationSyncInfo.id,
@@ -295,18 +346,31 @@ namespace TEAMModelOS.SDK.Models.Service
                     grouplist = evaluationSyncInfo.grouplist,
                     shortCode = evaluationSyncInfo.shortCode,
                     stime=stime,
-                    etime=etime
-
+                    etime=etime,
+                    dataHash = evaluationSyncInfo.dataHash,
+                    grouplistHash = evaluationSyncInfo.grouplistHash,
+                    ownerId = evaluationSyncInfo.ownerId,
+                    ownerPicture =evaluationSyncInfo.ownerPicture,
+                    ownerName = evaluationSyncInfo.ownerName,
                     //password = evaluationSyncInfo.password,
                     //recordUrl = evaluationSyncInfo.recordUrl
                 };
-                var groupList = new { members = listInfo.rmembers, groupList= listInfo.groups };
-                await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(evaluationSource.ToJsonString(),$"package/{id}", "source.json");
-                await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(groupList.ToJsonString(), $"package/{id}", "groupList.json");
-                await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(new { evaluationClient, evaluationExams }.ToJsonString(), $"package/{id}", "evaluation.json");
+                long dataSize = 0;
+                string sourceJson = evaluationSource.ToJsonString();
+                dataSize+=  Encoding.UTF8.GetByteCount(sourceJson);
+                string groupListJson = groupList.ToJsonString();
+                dataSize+=  Encoding.UTF8.GetByteCount(groupListJson);
+                string evaluationJson = new { evaluationClient, evaluationExams }.ToJsonString().ToJsonString();
+                dataSize+=  Encoding.UTF8.GetByteCount(evaluationJson);
+                string evaluationSyncInfoSJson = evaluationSyncInfo.ToJsonString();
+                dataSize+= Encoding.UTF8.GetByteCount(evaluationSyncInfoSJson);
+                evaluationClient.dataSize = dataSize;
+                await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(sourceJson, $"package/{id}", "source.json");
+                await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(groupListJson, $"package/{id}", "groupList.json");
+                await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(new { evaluationClient, evaluationExams }.ToJsonString(), $"package/{id}", "evaluation.json");
+                evaluationSyncInfo.dataSize = dataSize;
+                //学校logo 下载到本地、
                 await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).UpsertItemAsync<EvaluationSyncInfo>(evaluationSyncInfo, new PartitionKey("EvaluationSyncInfo"));
-               
-
                 // await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(evaluationSyncInfo.ToJsonString(), $"package/{id}", "syncinfo.json");
             }
             return evaluationSyncInfo;

+ 19 - 1
TEAMModelOS/Controllers/Both/EvaluationSyncInfoController.cs

@@ -14,6 +14,8 @@ using TEAMModelOS.SDK.Models.Cosmos.Normal;
 using Microsoft.Azure.Cosmos;
 using TEAMModelOS.SDK.Models.Service;
 using TEAMModelOS.SDK.Models.Cosmos;
+using System.Text;
+using System.Linq;
 
 
 namespace TEAMModelOS.Controllers.Both
@@ -58,7 +60,23 @@ namespace TEAMModelOS.Controllers.Both
         //#endif
         public async Task<IActionResult> FindSyncInfo(JsonNode request) 
         {
-
+            EvaluationSyncInfo evaluationSyncInfo =       new EvaluationSyncInfo();
+            var listInfo = await GroupListService.GetMemberByListids(_coreAPIHttpService, _azureCosmos.GetCosmosClient(), _dingDing, evaluationSyncInfo.grouplist, evaluationSyncInfo.owner);
+            //计算数据的hash值
+            var groupList = new { members = listInfo.rmembers, groupList = listInfo.groups };
+            StringBuilder groupListData = new StringBuilder();
+            //名单的hash值
+            var orderList = listInfo.groups.OrderBy(x => x.id);
+            foreach (var item in orderList)
+            {
+                groupListData.Append($"{item.id}-{item.name}");
+                var orderMembers = item.members.OrderBy(x => x.id);
+                foreach (var member in orderMembers)
+                {
+                    groupListData.Append($"{member.id}-{member.name}");
+                }
+            }
+            evaluationSyncInfo.grouplistHash= ShaHashHelper.GetSHA1(groupListData.ToString());
             return Ok();
         }