黄贺彬 3 miesięcy temu
rodzic
commit
d3fd014b14

+ 113 - 14
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/ManageController.cs

@@ -14,6 +14,7 @@ using Microsoft.Extensions.Caching.Memory;
 using Microsoft.Extensions.Configuration;
 using System;
 using System.Diagnostics.Eventing.Reader;
+using System.Diagnostics.Metrics;
 using System.Linq.Expressions;
 using System.Net.Http;
 using System.Net.Http.Json;
@@ -63,15 +64,62 @@ namespace IES.ExamServer.Controllers
         /// <returns></returns>
         [HttpPost("export-evaluation-result")]
         [AuthToken("admin", "teacher", "visitor")]
-        public async Task<IActionResult> ExportEvaluationResult(JsonNode json) 
+        public IActionResult ExportEvaluationResult(JsonNode json) 
         {
-            string id = $"{json["evaluationId"]}";
+            string evaluationId = $"{json["evaluationId"]}";
             string shortCode = $"{json["shortCode"]}";
             string openCode = $"{json["openCode"]}";
-            string deviceId = $"{json["deviceId"]}";
+            string? loginToken = HttpContext.GetXAuth("AuthToken");
             EvaluationClient? evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>()
-                .FindOne(x => x.id!.Equals(id) && x.openCode!.Equals(openCode)&& x.shortCode!.Equals(shortCode));
-            return Ok();
+                .FindOne(x => x.id!.Equals(evaluationId) && x.openCode!.Equals(openCode));
+            //已作答
+            int answerCount = 0;
+            //未作答
+            int absentCount = 0;
+            List<SubjectPushData> subjectPushDatas = new List<SubjectPushData>();
+            List<SubjectPushData> subjectPushNew = new List<SubjectPushData>();
+            if (evaluationClient!=null)
+            {
+                var datas = _liteDBFactory.GetLiteDatabase().GetCollection<SubjectPushData>()
+                    .Find(x => !string.IsNullOrWhiteSpace(x.evaluationId) && x.evaluationId!.Equals(evaluationId)).ToList();
+                if (datas.IsNotEmpty())
+                {
+                    subjectPushDatas.AddRange(datas);
+                }
+                var data = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>()
+                   .Find(x => !string.IsNullOrWhiteSpace(x.evaluationId) && x.evaluationId.Equals(evaluationId));
+
+                if (data.IsNotEmpty())
+                {
+                    foreach (var item in data)
+                    {
+                        foreach (var subjectResult in item.subjectResults)
+                        {
+                            if (subjectResult.finished==1)
+                            {
+
+                                SubjectPushData subjectPushData = new SubjectPushData(subjectResult, item);
+                                subjectPushData.loginToken=loginToken;
+                                if (!datas.Exists(x => x.id!.Equals(subjectPushData.id)))
+                                {
+                                    //数据丢失导致的推送SubjectPushData 没有被保存的问题
+                                    subjectPushDatas.Add(subjectPushData);
+                                    subjectPushNew.Add(subjectPushData);
+                                }
+                            }
+                            else { absentCount++; }
+                        }
+                    }
+                }
+                if (subjectPushNew.IsNotEmpty())
+                {
+                    _liteDBFactory.GetLiteDatabase().GetCollection<SubjectPushData>().Upsert(subjectPushNew);
+                }
+            }
+            answerCount=subjectPushDatas.Count(x => x.finished==1 && x.answers.IsNotEmpty());
+            absentCount+=subjectPushDatas.Count()-answerCount;
+            //TODO   以及增加 作答文件的相关数据。
+            return Ok(new { answerCount, absentCount, subjectPushDatas });
         }
         /// <summary>
         /// 手动推送
@@ -84,21 +132,72 @@ namespace IES.ExamServer.Controllers
         [AuthToken("admin", "teacher", "visitor")]
         public async Task<IActionResult> ManualPush(JsonNode json)
         {
-            string id = $"{json["evaluationId"]}";
-            string shortCode = $"{json["shortCode"]}";
+            string evaluationId = $"{json["evaluationId"]}";
+            //string shortCode = $"{json["shortCode"]}";
             string openCode = $"{json["openCode"]}";
             string deviceId = $"{json["deviceId"]}";
             EvaluationClient? evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>()
-                .FindOne(x => x.id!.Equals(id) && x.openCode!.Equals(openCode)&& x.shortCode!.Equals(shortCode));
+                .FindOne(x => x.id!.Equals(evaluationId) && x.openCode!.Equals(openCode));
+            int count = 0;
+            string? loginToken = HttpContext.GetXAuth("AuthToken");
             if (evaluationClient!=null) 
             {
-                //IEnumerable<EvaluationSubjectResult> evaluationSubjectResults=  _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationSubjectResult>().Find(x => x.pushed<=1 &&!string.IsNullOrWhiteSpace(x.evaluationId) && x.evaluationId.Equals(evaluationId));
-                //foreach (var item in evaluationSubjectResults)
-                //{
-                //    _dataQueue.TryAddAsync();
-                //}
+                var datas = _liteDBFactory.GetLiteDatabase().GetCollection<SubjectPushData>()
+                    .Find(x => !string.IsNullOrWhiteSpace(x.evaluationId) && x.evaluationId!.Equals(evaluationId)).ToList();
+                if (datas.IsNotEmpty())
+                {
+                    foreach (var item in datas) 
+                    {
+                        if (item.pushed<=1  && item.finished==1) 
+                        {
+                            item.order=count;
+                            item.loginToken=loginToken;
+                            count++;
+                            //_logger.LogInformation($"推送数据加入队列=>>序号:{subjectPushData.order}--学号:{item.studentId}--姓名:{item.studentName}--科目:{subjectResult.subjectName}");
+                            await _dataQueue.TryAddAsync(item);
+                           
+                        }
+                    }
+                }
+
+                var data =  _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>()
+                    .Find(x =>!string.IsNullOrWhiteSpace(x.evaluationId) && x.evaluationId.Equals(evaluationId) );
+                List<SubjectPushData> subjectPushDatas = new List<SubjectPushData>();
+                if (data.IsNotEmpty()) 
+                {
+                    foreach (var item in data) 
+                    {
+                        foreach (var subjectResult in item.subjectResults) 
+                        {
+                            if ( subjectResult.finished==1)
+                            {
+                               
+                                SubjectPushData subjectPushData=    new SubjectPushData(subjectResult, item);
+                                subjectPushData.order=count;
+                                subjectPushData.loginToken=loginToken;
+                                if (!datas.Exists(x => x.id!.Equals(subjectPushData.id))) 
+                                {
+                                    //数据丢失导致的推送SubjectPushData 没有被保存的问题
+                                    subjectPushDatas.Add(subjectPushData);
+                                    //未被推送的数据
+                                    if (subjectPushData.pushed<=1  && subjectPushData.finished==1)
+                                    {
+                                        count++;
+                                        subjectPushData.pushed=1;
+                                        await _dataQueue.TryAddAsync(subjectPushData);
+                                    }
+                                }
+                               
+                            }
+                        }
+                    }
+                }
+                if (subjectPushDatas.IsNotEmpty()) 
+                {
+                    _liteDBFactory.GetLiteDatabase().GetCollection<SubjectPushData>().Upsert(subjectPushDatas);
+                }
             }
-            return Ok(new { code=200, message="推送成功!" });
+            return Ok(new { code=200, message="推送成功!", count });
         }
 
 

+ 3 - 3
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/StudentController.cs

@@ -227,7 +227,7 @@ namespace IES.ExamServer.Controllers
                             {
                                 studentResult.subjectResults.Add(result);
                             }
-                           
+                            SubjectPushData subjectPushData = new SubjectPushData(result, studentResult);
                             if (_connectionService!.centerIsConnected)
                             {
                                 result.pushed=1;
@@ -235,9 +235,9 @@ namespace IES.ExamServer.Controllers
                                 {
                                     subjectResult!.pushed=1;
                                 }
-                               await _dataQueue.TryAddAsync(new SubjectPushData(result, studentResult));
+                               await _dataQueue.TryAddAsync(subjectPushData);
                             }
-                            _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationSubjectResult>().Upsert(result);
+                            _liteDBFactory.GetLiteDatabase().GetCollection<SubjectPushData>().Upsert(subjectPushData);
                             _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>().Upsert(studentResult);
                            
                         }

+ 1 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/LiteDBFactory.cs

@@ -60,7 +60,7 @@ namespace IES.ExamServer.DI
             if (connectionstrings == null) throw new ArgumentNullException(nameof(connectionstrings));
 
 
-            services.TryAddSingleton<LiteDBFactory>();
+            services.TryAddTransient<LiteDBFactory>();
             //多个连接字符串注入
             connectionstrings.ForEach(connection =>
             {

+ 26 - 29
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/SubjectPushService.cs

@@ -1,6 +1,7 @@
 using IES.ExamServer.Helpers;
 using IES.ExamServer.Models;
 using LiteDB;
+using Microsoft.AspNetCore.Mvc;
 using System;
 using System.Net.Http;
 using System.Text;
@@ -15,7 +16,9 @@ namespace IES.ExamServer.DI
         private readonly LiteDBFactory _liteDBFactory;
         private readonly CenterServiceConnectionService _connectionService;
         private readonly IConfiguration _configuration;
-        public SubjectPushService(DataQueue dataQueue, IHttpClientFactory httpClientFactory, LiteDBFactory liteDBFactory, CenterServiceConnectionService connectionService, IConfiguration configuration)
+        private readonly ILogger<SubjectPushService> _logger;
+        public SubjectPushService(DataQueue dataQueue, IHttpClientFactory httpClientFactory, LiteDBFactory liteDBFactory,
+            CenterServiceConnectionService connectionService, IConfiguration configuration, ILogger<SubjectPushService> logger)
         {
             
             _dataQueue = dataQueue;
@@ -23,6 +26,7 @@ namespace IES.ExamServer.DI
             _liteDBFactory = liteDBFactory;
             _connectionService = connectionService;
             _configuration= configuration;
+            _logger = logger;
 
         }
         protected override async Task ExecuteAsync(CancellationToken stoppingToken)
@@ -62,6 +66,7 @@ namespace IES.ExamServer.DI
                     if (httpClient.DefaultRequestHeaders.Contains("X-Auth-AuthToken")) {
                         httpClient.DefaultRequestHeaders.Remove("X-Auth-AuthToken");
                     }
+                    _logger.LogInformation($"推送数据准备推送=>>序号:{data.order}--学号:{data.studentId}--姓名:{data.studentName}--科目:{data.subjectName}");
                     httpClient.DefaultRequestHeaders.Add("X-Auth-AuthToken",data.loginToken?? _connectionService.loginToken);
                     var response = await httpClient.PostAsJsonAsync(url, new {
                         examId = data.examId,
@@ -81,7 +86,8 @@ namespace IES.ExamServer.DI
                     if (response.IsSuccessStatusCode)
                     {
                         MarkDataAsPushed(data);
-                        Console.WriteLine($"Data {data.studentResultId}{data.subjectResultId} pushed successfully.");
+                        _logger.LogInformation($"推送数据推送成功=>>序号:{data.order}--学号:{data.studentId}--姓名:{data.studentName}--科目:{data.subjectName}");
+                       //Console.WriteLine($"Data {data.studentResultId}{data.subjectResultId} pushed successfully.");
                     }
                     else
                     {
@@ -109,35 +115,26 @@ namespace IES.ExamServer.DI
         }
         private void MarkDataAsPushed(SubjectPushData data )
         {
-            EvaluationStudentResult  studentResult = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>().FindOne(x=>x.id!.Equals(data.studentResultId));
-            EvaluationSubjectResult  subjectResult = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationSubjectResult>().FindOne(x => x.id!.Equals(data.subjectResultId));
-            EvaluationSubjectResult? subjectResultInStundent = studentResult.subjectResults.Where(x => x.id!.Equals(data.subjectResultId)).FirstOrDefault();
-            if (subjectResultInStundent!=null) 
-            {
-                subjectResultInStundent.pushed=1;
-                _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>().Upsert(studentResult);
+            var database = _liteDBFactory.GetLiteDatabase();
+            try {
+                database.BeginTrans();
+                EvaluationStudentResult studentResult = database.GetCollection<EvaluationStudentResult>().FindOne(x => x.id!.Equals(data.studentResultId));
+                if (studentResult!=null)
+                {
+                    studentResult.pushed=2;
+                    database.GetCollection<EvaluationStudentResult>().Upsert(studentResult);
+                }
+                if (data!=null)
+                {
+                    data.pushed=2;
+                    database.GetCollection<SubjectPushData>().Upsert(data);
+                }
+                database.Commit();
             }
-            if (subjectResult!=null) 
-            {
-                subjectResult.pushed=1;
-                _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationSubjectResult>().Upsert(subjectResult);
+            catch(Exception ex ) {
+                database.Rollback();
             }
-            
         }
-        //private async Task LoadUnpushedDataAsync(CancellationToken cancellationToken)
-        //{
-        //    var collection = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationSubjectResult>();
-        //    var unpushedData = collection.Find(x => x.pushed!=1);
-        //    foreach (var data in unpushedData)
-        //    {
-        //        var studentResults  = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>().Find(x => x.subjectResults.Where(x => x.id!.Equals(data.id)).IsNotEmpty()).Distinct();
-        //        // 将未推送的数据写入 Channel
-        //        foreach (var studentResult in studentResults)
-        //        {
-        //            await _dataQueue.WriteAsync((studentResult!,data, data.id!), cancellationToken); 
-        //        }
-        //    }
-        //}
     }
 
     public class DataQueue
@@ -216,7 +213,7 @@ namespace IES.ExamServer.DI
             this.scope = studentResult.scope;
             this.type = studentResult.type;
         }
-
+        public int order { get; set; }
         public string? studentResultId { get; set; }
         public string? subjectResultId { get; set; }
         public string? studentId { get; set; }

+ 41 - 12
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Program.cs

@@ -11,6 +11,7 @@ using System.Text.Unicode;
 using static System.Net.Mime.MediaTypeNames;
 using System.Diagnostics;
 using System.Security.Authentication;
+using Microsoft.Extensions.FileProviders;
 namespace IES.ExamServer.Server
 {
     public class Program
@@ -105,23 +106,51 @@ namespace IES.ExamServer.Server
             var app = builder.Build();
 
             app.UseDefaultFiles();
-            var contentTypeProvider = new FileExtensionContentTypeProvider();
-            contentTypeProvider.Mappings[".txt"] = "text/plain";
-            contentTypeProvider.Mappings[".jpg"] = "image/jpeg";
-            contentTypeProvider.Mappings[".jpeg"] = "image/jpeg";
-            contentTypeProvider.Mappings[".png"] = "image/png";
-            contentTypeProvider.Mappings[".html"] = "text/html";
-            contentTypeProvider.Mappings[".js"] = "application/javascript";
-            contentTypeProvider.Mappings[".css"] = "text/css";
-            contentTypeProvider.Mappings[".mp4"] = "video/mp4";
-            contentTypeProvider.Mappings[".mp3"] = "audio/mpeg";
-            contentTypeProvider.Mappings[".json"] = "application/json";
-            contentTypeProvider.Mappings[".pdf"] = "application/pdf";
+            //var contentTypeProvider = new FileExtensionContentTypeProvider();
+            //contentTypeProvider.Mappings[".txt"] = "text/plain";
+            //contentTypeProvider.Mappings[".jpg"] = "image/jpeg";
+            //contentTypeProvider.Mappings[".jpeg"] = "image/jpeg";
+            //contentTypeProvider.Mappings[".png"] = "image/png";
+            //contentTypeProvider.Mappings[".html"] = "text/html";
+            //contentTypeProvider.Mappings[".js"] = "application/javascript";
+            //contentTypeProvider.Mappings[".css"] = "text/css";
+            //contentTypeProvider.Mappings[".mp4"] = "video/mp4";
+            //contentTypeProvider.Mappings[".mp3"] = "audio/mpeg";
+            //contentTypeProvider.Mappings[".json"] = "application/json";
+            //contentTypeProvider.Mappings[".pdf"] = "application/pdf";
             string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
             if (!Directory.Exists(packagePath))
             {
                 Directory.CreateDirectory(packagePath);
             }
+            //会自动处理文件夹下的子文件夹及文件映射关系。
+            /*
+                请求 URL	映射到的文件路径
+                https://localhost/data/data.json	C:\Users\YourUser\AppData\Local\ExamData\data.json
+                https://localhost/data/abc/a.json	C:\Users\YourUser\AppData\Local\ExamData\abc\a.json
+                https://localhost/data/123/1.json   C:\Users\YourUser\AppData\Local\ExamData\123\1.json
+             */
+            string uploadPath = Path.Combine(localAppDataPath, "ExamServer", "Upload");
+            if (!Directory.Exists(uploadPath))
+            {
+                Directory.CreateDirectory(uploadPath);
+            }
+            app.UseStaticFiles(new StaticFileOptions
+            {
+                FileProvider = new PhysicalFileProvider(uploadPath),
+                RequestPath = "/upload" // 映射请求路径,学生上传文件
+            });
+
+            string answerPath = Path.Combine(localAppDataPath, "ExamServer", "Answer");
+            if (!Directory.Exists(answerPath))
+            {
+                Directory.CreateDirectory(answerPath);
+            }
+            app.UseStaticFiles(new StaticFileOptions
+            {
+                FileProvider = new PhysicalFileProvider(answerPath),
+                RequestPath = "/answer" // 映射请求路径,学生作答文件
+            });
             app.UseStaticFiles();
 
             // Configure the HTTP request pipeline.