Forráskód Böngészése

Merge branch 'develop' into develop_local

jeff 3 hónapja
szülő
commit
cf95d0c6bc
18 módosított fájl, 404 hozzáadás és 245 törlés
  1. 12 0
      TEAMModelOS.Extension/IES.Exam/IES.ExamLibrary/Models/EvaluationCommon.cs
  2. 22 1
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/BaseController.cs
  3. 54 25
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/ManageController.cs
  4. 48 13
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/StudentController.cs
  5. 0 145
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/AnswerPushService.cs
  6. 2 1
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/CenterServiceConnectionService.cs
  7. 178 0
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/SubjectPushService.cs
  8. 1 1
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/JwtAuthExtension.cs
  9. 5 1
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Models/EvaluationRound.cs
  10. 11 2
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Models/EvaluationStudent.cs
  11. 4 0
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Program.cs
  12. 3 9
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/IndexService.cs
  13. 2 2
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/ManageService.cs
  14. 19 7
      TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/admin/ActivityManage.vue
  15. 9 7
      TEAMModelOS.SDK/Models/Service/EvaluationSyncInfoService.cs
  16. 1 1
      TEAMModelOS/ClientApp/src/view/teachermgmt/components/personnel/Index.vue
  17. 27 24
      TEAMModelOS/Controllers/Client/HiTAControlller.cs
  18. 6 6
      TEAMModelOS/Controllers/Common/ExamController.cs

+ 12 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamLibrary/Models/EvaluationCommon.cs

@@ -202,6 +202,10 @@ namespace IES.ExamServer.Models
         /// </summary>
         public string? subjectId { get; set; }
         /// <summary>
+        /// 乱序作答0 顺序作答,1乱序作答
+        /// </summary>
+        public int disorder { get; set; }
+        /// <summary>
         /// 评测科目名称
         /// </summary>
         public string? subjectName { get; set; }
@@ -306,6 +310,10 @@ namespace IES.ExamServer.Models
         /// 评测类型Exam,投票评选Vote,问卷调查Survey
         /// </summary>
         public string? type { get; set; }
+        /// <summary>
+        /// 乱序作答0 顺序作答,1乱序作答
+        /// </summary>
+        public int disorder { get; set;}
     }
     public class SubjectExamPaper
     {
@@ -329,6 +337,10 @@ namespace IES.ExamServer.Models
         /// 本地路径
         /// </summary>
         public string? local { get; set; }
+        /// <summary>
+        /// 题目数量
+        /// </summary>
+        public int questionCount { get; set; }
     }
     public class EvaluationPaper: SubjectExamPaper
     {

+ 22 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/BaseController.cs

@@ -1,4 +1,7 @@
-using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.DataProtection.KeyManagement;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Primitives;
 
 namespace IES.ExamServer.Controllers
 {
@@ -78,6 +81,24 @@ namespace IES.ExamServer.Controllers
             return HttpContext.Request.Headers["Authorization"].ToString();
         }
 
+        /// <summary>
+        /// 取得驗證金鑰,Authorization
+        /// </summary>        
+        public string? GetXAuthToken()
+        {
+            //return HttpContext.Request.Headers["X-Auth-AuthToken"].ToString();
+            try
+            {
+                if (HttpContext.Request.Headers.TryGetValue("X-Auth-AuthToken", out StringValues value))
+                    return value.ToString();
+                else
+                    return null;
+            }
+            catch
+            {
+                return null;
+            }
+        }
         /// <summary>
         /// 取得JWT驗證金鑰,Authorization Bearer
         /// </summary>

+ 54 - 25
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/ManageController.cs

@@ -50,8 +50,46 @@ namespace IES.ExamServer.Controllers
             _connectionService=connectionService;
             _signalRExamServerHub=signalRExamServerHub;
         }
+        /// <summary>
+        /// 导出数据
+        ///通过线上回传数据需要鉴权验证等操作。
+        ///通过离线包回传数据需要加密操作
+        /// </summary>
+        /// <param name="json"></param>
+        /// <returns></returns>
+        [HttpPost("export-evaluation-result")]
+        [AuthToken("admin", "teacher", "visitor")]
+        public async Task<IActionResult> ExportEvaluationResult(JsonNode json) 
+        {
+            string id = $"{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));
+            return Ok();
+        }
+        /// <summary>
+        /// 手动推送
         ///通过线上回传数据需要鉴权验证等操作。
         ///通过离线包回传数据需要加密操作
+        /// </summary>
+        /// <param name="json"></param>
+        /// <returns></returns>
+        [HttpPost("manual-push")]
+        [AuthToken("admin", "teacher", "visitor")]
+        public async Task<IActionResult> ManualPush(JsonNode json)
+        {
+            string id = $"{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));
+            return Ok();
+        }
+
+
 
         /// <summary>
         /// 清理缓存,列出缓存占用空间,type =list列出,type=clear清理,不能清理近期及正在激活的数据,并且提示清理中暂未上传或者导出的数据。
@@ -62,6 +100,8 @@ namespace IES.ExamServer.Controllers
         [AuthToken("admin", "teacher", "visitor")]
         public async Task<IActionResult> CleanCache(JsonNode json)
         {
+           
+
             return Ok();
         }
 
@@ -108,8 +148,8 @@ namespace IES.ExamServer.Controllers
                     EvaluationClient? evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindOne(x => x.id!.Equals(id) && x.shortCode!.Equals(shortCode));
                     if (teacher != null && evaluationClient!= null)
                     {
-                        var dataInfo=  await GetEvaluationFromCenter(teacher, _configuration, _httpClientFactory, shortCode, evaluationClient.id!);
-                        if (dataInfo.centerCode.Equals("200"))
+                        var dataInfo=  await GetEvaluationFromCenter(GetXAuthToken(), _configuration, _httpClientFactory, shortCode, evaluationClient.id!);
+                        if (dataInfo.centerCode.Equals("200")&& dataInfo.evaluationCloud!=null)
                         {
                             string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
                             var client = _httpClientFactory.CreateClient();
@@ -255,7 +295,9 @@ namespace IES.ExamServer.Controllers
                                 }
                             }
 
-                            (successMsgs, errorMsgs) = await ManageService.CheckFile(evaluationClient, successMsgs, errorMsgs, _signalRExamServerHub, _memoryCache, _logger, deviceId, evaluationPath);
+                            _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Upsert(dataInfo.evaluationCloud!);
+
+                            (successMsgs, errorMsgs) = await ManageService.CheckFile(dataInfo.evaluationCloud!, successMsgs, errorMsgs, _signalRExamServerHub, _memoryCache, _logger, deviceId, evaluationPath);
                             //下载完成后,对数据进行检查,然后在加密压缩。
                             string zipPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "zip");
                             if (!Directory.Exists(zipPath))
@@ -264,6 +306,7 @@ namespace IES.ExamServer.Controllers
                             }
                             string zipFilePath = Path.Combine(zipPath, $"{evaluationClient.id}-{evaluationClient.blobHash}.zip");
                             var zipInfo = ZipHelper.CreatePasswordProtectedZip(evaluationPath, zipFilePath, evaluationClient.openCode!);
+                          
                             if (zipInfo.res)
                             {
                                 successMsgs.Add("评测数据压缩包创建成功!");
@@ -451,7 +494,7 @@ namespace IES.ExamServer.Controllers
                         Teacher? teacher = _liteDBFactory.GetLiteDatabase().GetCollection<Teacher>().FindOne(x => x.id!.Equals(token.id));
                         if (teacher != null)
                         {
-                          (evaluationCloud, centerCode, centerMsg)=  await ManageService.GetEvaluationFromCenter(teacher, _configuration,_httpClientFactory,shortCode,evaluationId);
+                          (evaluationCloud, centerCode, centerMsg)=  await ManageService.GetEvaluationFromCenter(GetXAuthToken(), _configuration,_httpClientFactory,shortCode,evaluationId);
                         }
                         else
                         {
@@ -788,6 +831,7 @@ namespace IES.ExamServer.Controllers
                                             subjectName=subject.subjectName,
                                             paperId=studentPaper.paperId,
                                             paperName=studentPaper.paperName,
+                                            questionCount=studentPaper.questionCount,
                                             id=id,
                                         });
                                         // 移动到下一个试卷
@@ -834,9 +878,8 @@ namespace IES.ExamServer.Controllers
                                         type= evaluationClient.type,
                                         pid= evaluationClient.pid,
                                     };
-                                    var studentPapers = roundStudentPapers.FindAll(x => !string.IsNullOrWhiteSpace(x.studentId) &&  x.studentId.Equals(member.id)
-                                                            &&!string.IsNullOrWhiteSpace(x.evaluationId)  && x.evaluationId.Equals(evaluationClient.id));
-
+                                    var studentPapers = roundStudentPapers.FindAll(x => !string.IsNullOrWhiteSpace(x.studentId) 
+                                    &&  x.studentId.Equals(member.id) &&!string.IsNullOrWhiteSpace(x.evaluationId)  && x.evaluationId.Equals(evaluationClient.id));
                                     if (studentPapers.IsNotEmpty())
                                     {
                                         foreach (var studentPaper in studentPapers)
@@ -851,6 +894,7 @@ namespace IES.ExamServer.Controllers
                                                 subjectName = studentPaper.subjectName,
                                                 paperId = studentPaper.paperId,
                                                 paperName = studentPaper.paperName,
+                                                questionCount=studentPaper.questionCount,
                                                 createTime=now
                                             });
                                         }
@@ -863,8 +907,8 @@ namespace IES.ExamServer.Controllers
                                     studentResult.studentName = member.name;
                                     studentResult.classId = member.classId;
                                     studentResult.className = member.className;
-                                    var studentPapers = roundStudentPapers.FindAll(x => !string.IsNullOrWhiteSpace(x.studentId) &&  x.studentId.Equals(member.id)
-                                                          &&!string.IsNullOrWhiteSpace(x.evaluationId)  && x.evaluationId.Equals(evaluationClient.id));
+                                    var studentPapers = roundStudentPapers.FindAll(x => !string.IsNullOrWhiteSpace(x.studentId)
+                                    &&  x.studentId.Equals(member.id) &&!string.IsNullOrWhiteSpace(x.evaluationId)  && x.evaluationId.Equals(evaluationClient.id));
                                     if (studentPapers.IsNotEmpty())
                                     {
                                         foreach (var studentPaper in studentPapers)
@@ -883,24 +927,13 @@ namespace IES.ExamServer.Controllers
                                                     subjectName = studentPaper.subjectName,
                                                     paperId = studentPaper.paperId,
                                                     paperName = studentPaper.paperName,
+                                                    questionCount= studentPaper.questionCount,
                                                     createTime=now
                                                 };
-                                                //studentResult.subjectResults.Add();
                                             }
-                                            //else
-                                            //{
-                                            //    subjectResult.evaluationId = studentPaper.evaluationId;
-                                            //    subjectResult.examId = studentPaper.examId;
-                                            //    subjectResult.examName = studentPaper.examName;
-                                            //    subjectResult.subjectId = studentPaper.subjectId;
-                                            //    subjectResult.subjectName = studentPaper.subjectName;
-                                            //    subjectResult.paperId = studentPaper.paperId;
-                                            //    subjectResult.paperName = studentPaper.paperName;
-                                            //}
                                             studentResult.subjectResults.Add(subjectResult);
                                         }
                                     }
-                                    //_liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>().Upsert(studentResult);
                                 }
                                 if (studentResult!=null)
                                 {
@@ -909,10 +942,6 @@ namespace IES.ExamServer.Controllers
                             }
                             if (results.Count>0)
                             {
-                                //foreach (var item in results)
-                                //{
-                                //    item.subjectResults= item.subjectResults.DistinctBy(x => x.id).ToList();
-                                //}
                                 _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>().Upsert(results);
                             }
                         }

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

@@ -88,21 +88,55 @@ namespace IES.ExamServer.Controllers
                     }
                     if (!string.IsNullOrWhiteSpace(subjectId)  && !string.IsNullOrWhiteSpace(examId) && !string.IsNullOrWhiteSpace(paperId)&& costTime>0)
                     {
-                        var subjectResult = studentResult.subjectResults.Where(x => subjectId.Equals(x.subjectId) && examId.Equals(x.examId) && paperId.Equals(x.paperId)).FirstOrDefault();
-                        if (subjectResult!=null)
+                       
+                        if (answers!.IsNotEmpty())
                         {
-                            if (answers!=null) 
+                            var subjectExams= evaluationClient.subjects.FindAll(x => examId.Equals(x.examId)&& subjectId.Equals(x.subjectId));
+                            var papers= subjectExams.FirstOrDefault()?.papers.FindAll(x => paperId.Equals(x.paperId));
+                            if (papers.IsNotEmpty())
                             {
-                                subjectResult.answers=answers!;
+                                if (answers!.Count()!=papers!.First()?.questionCount) 
+                                {
+                                    return Ok(new { msg = "提交的答案数量与试卷题目数量不匹配。", code = 5 });
+                                }
+                            }
+                            string subjectResultId = ShaHashHelper.GetSHA1(evaluationClient.id+examId+subjectId+token.id);
+                            var subjectResult = studentResult.subjectResults.Where(x => subjectResultId.Equals(x.id) &&  subjectId.Equals(x.subjectId)
+                                    && examId.Equals(x.examId) && paperId.Equals(x.paperId)).FirstOrDefault();
+                            if (subjectResult!=null)
+                            {
+                                subjectResult.answers=answers;
+                                subjectResult.finished=1;
+                                subjectResult.costTime=costTime;
+                                subjectResult.submitTime=now;
+                                subjectResult.pushed=0;//强制重新推送
+                            }
+                            EvaluationSubjectResult result = new EvaluationSubjectResult()
+                            {
+                                id = subjectResultId,
+                                evaluationId = evaluationId,
+                                examId = examId,
+                                examName = subjectResult?.examName,
+                                subjectId = subjectId,
+                                subjectName = subjectResult?.subjectName,
+                                paperId =paperId,
+                                paperName = subjectResult?.paperName,
+                                createTime=now,
+                                finished=1,
+                                costTime=costTime,
+                                submitTime=now,
+                                answers=answers,
+                                questionCount=papers.IsNotEmpty()? papers!.First().questionCount : 0,
+                                pushed=0//强制重新推送
+                            };
+                            _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationSubjectResult>().Upsert(result);
+
+                            if (_connectionService!.centerIsConnected)
+                            {
+
                             }
-                            subjectResult.finished=1;
-                            subjectResult.costTime=costTime;
-                            subjectResult.submitTime=now;
-                        }
-                        if (_connectionService!.centerIsConnected) 
-                        {
-                        
                         }
+                       
                     }
                     return Ok(new { code = 200, studentResult = studentResult, msg = "提交成功!" });
                 }
@@ -132,10 +166,11 @@ namespace IES.ExamServer.Controllers
         public IActionResult LoadEvaluationResult(JsonNode json)
         {
             string evaluationId = $"{json["evaluationId"]}";
-            var token = GetAuthTokenInfo();
+            var token = GetAuthTokenInfo();//6af32bbd-144e-4366-8bc0-61ba4c85677c
             string resultId = ShaHashHelper.GetSHA1(evaluationId+_connectionService?.serverDevice?.school?.id+token.id);
+            string? scoolId = _connectionService?.serverDevice?.school?.id;
             EvaluationStudentResult studentResult = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>()
-                .FindOne(x=> resultId.Equals(x.id) && token.id.Equals(x.studentId) && evaluationId.Equals(x.evaluationId));
+                .FindOne(x=> resultId.Equals(x.id) && !string.IsNullOrWhiteSpace(x.schoolId) &&  x.schoolId.Equals(scoolId)&& token.id.Equals(x.studentId) && evaluationId.Equals(x.evaluationId));
             if (studentResult!=null)
             {
                 //标记开始作答

+ 0 - 145
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/AnswerPushService.cs

@@ -1,145 +0,0 @@
-using IES.ExamServer.Models;
-using LiteDB;
-using System.Net.Http;
-using System.Text;
-using System.Threading.Channels;
-
-namespace IES.ExamServer.DI
-{
-    public class AnswerPushService: BackgroundService
-    {
-        private readonly DataQueue _dataQueue;
-        private readonly IHttpClientFactory _httpClientFactory;
-        private readonly LiteDBFactory _liteDBFactory;
-        private readonly CenterServiceConnectionService _connectionService;
-        public AnswerPushService(DataQueue dataQueue, IHttpClientFactory httpClientFactory, LiteDBFactory liteDBFactory, CenterServiceConnectionService connectionService)
-        {
-            
-            _dataQueue = dataQueue;
-            _httpClientFactory = httpClientFactory;
-            _liteDBFactory = liteDBFactory;
-            _connectionService = connectionService;
-
-        }
-        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
-        {
-            ///数据中心链接了,开始推送数据
-            if (_connectionService.centerIsConnected) 
-            {
-                // 启动时加载未推送的数据
-                await LoadUnpushedDataAsync(stoppingToken);
-            }
-            while (!stoppingToken.IsCancellationRequested)
-            {
-                // 从 Channel 中读取数据
-                if (await _dataQueue.Reader.WaitToReadAsync(stoppingToken))
-                {
-                    while (_dataQueue.Reader.TryRead(out var data))
-                    {
-
-                        await PushSubjectResultDataToCloudAsync(data, stoppingToken);
-                        await PushMusicAIResultDataToCloudAsync(data, stoppingToken);
-                    }
-                }
-            }
-
-        }
-        private async Task PushMusicAIResultDataToCloudAsync(EvaluationStudentResult data, CancellationToken cancellationToken)
-        {
-
-            if (_connectionService.centerIsConnected)
-            {
-                try
-                {
-                    //  var json = JsonSerializer.Serialize(data);
-                    //var content = new StringContent(json, Encoding.UTF8, "application/json");
-                    var httpClient = _httpClientFactory.CreateClient();
-                    var response = await httpClient.PostAsJsonAsync("", data, cancellationToken);
-
-                    if (response.IsSuccessStatusCode)
-                    {
-                        MarkDataAsPushed(data);
-                        Console.WriteLine($"Data {data.id} pushed successfully.");
-                    }
-                    else
-                    {
-                        Console.WriteLine($"Failed to push data {data.id}. Retrying...");
-                        // 推送失败,重新加入队列
-                        await _dataQueue.Writer.WriteAsync(data, cancellationToken);
-                    }
-                }
-                catch (Exception ex)
-                {
-                    Console.WriteLine($"Error pushing data {data.id}: {ex.Message}");
-                    // 推送失败,重新加入队列
-                    await _dataQueue.Writer.WriteAsync(data, cancellationToken);
-                }
-            }
-        }
-        private async Task PushSubjectResultDataToCloudAsync(EvaluationStudentResult data, CancellationToken cancellationToken)
-        {
-            if (_connectionService.centerIsConnected) 
-            {
-                try
-                {
-                    //  var json = JsonSerializer.Serialize(data);
-                    //var content = new StringContent(json, Encoding.UTF8, "application/json");
-                    var httpClient = _httpClientFactory.CreateClient();
-                    var response = await httpClient.PostAsJsonAsync("", data, cancellationToken);
-
-                    if (response.IsSuccessStatusCode)
-                    {
-                        MarkDataAsPushed(data);
-                        Console.WriteLine($"Data {data.id} pushed successfully.");
-                    }
-                    else
-                    {
-                        Console.WriteLine($"Failed to push data {data.id}. Retrying...");
-                        // 推送失败,重新加入队列
-                        await _dataQueue.Writer.WriteAsync(data, cancellationToken);
-                    }
-                }
-                catch (Exception ex)
-                {
-                    Console.WriteLine($"Error pushing data {data.id}: {ex.Message}");
-                    // 推送失败,重新加入队列
-                    await _dataQueue.Writer.WriteAsync(data, cancellationToken);
-                }
-            }
-        }
-        private void MarkDataAsPushed(EvaluationStudentResult data)
-        {
-            var collection = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>();
-            data.pushed = 1;
-            collection.Upsert(data);
-        }
-        private async Task LoadUnpushedDataAsync(CancellationToken cancellationToken)
-        {
-            var collection = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>();
-            var unpushedData = collection.Find(x => x.pushed!=1);
-
-            // 将未推送的数据写入 Channel
-            await _dataQueue.WriteBatchAsync(unpushedData, cancellationToken);
-        }
-    }
-
-    public class DataQueue
-    {
-        private readonly Channel<EvaluationStudentResult> _channel;
-        public DataQueue() {
-            // 创建一个无界 Channel
-            _channel = Channel.CreateUnbounded<EvaluationStudentResult>();
-        }
-        public ChannelWriter<EvaluationStudentResult> Writer => _channel.Writer;
-        public ChannelReader<EvaluationStudentResult> Reader => _channel.Reader;
-
-        // 批量写入数据
-        public async Task WriteBatchAsync(IEnumerable<EvaluationStudentResult> dataList, CancellationToken cancellationToken = default)
-        {
-            foreach (var data in dataList)
-            {
-                await _channel.Writer.WriteAsync(data, cancellationToken);
-            }
-        }
-    }
-}

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

@@ -25,7 +25,8 @@ namespace IES.ExamServer.DI
         ///  }
         /// </summary>
         public string? musicUrl { get; set; }
-       
+        public string? loginToken { get; set; }
+
         public ServerDevice? serverDevice {  get; set; }
         public bool musicIsConnected
         { get;set;

+ 178 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/SubjectPushService.cs

@@ -0,0 +1,178 @@
+using IES.ExamServer.Helpers;
+using IES.ExamServer.Models;
+using LiteDB;
+using System;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Channels;
+
+namespace IES.ExamServer.DI
+{
+    public class SubjectPushService: BackgroundService
+    {
+        private readonly DataQueue _dataQueue;
+        private readonly IHttpClientFactory _httpClientFactory;
+        private readonly LiteDBFactory _liteDBFactory;
+        private readonly CenterServiceConnectionService _connectionService;
+        private readonly IConfiguration _configuration;
+        public SubjectPushService(DataQueue dataQueue, IHttpClientFactory httpClientFactory, LiteDBFactory liteDBFactory, CenterServiceConnectionService connectionService, IConfiguration configuration)
+        {
+            
+            _dataQueue = dataQueue;
+            _httpClientFactory = httpClientFactory;
+            _liteDBFactory = liteDBFactory;
+            _connectionService = connectionService;
+            _configuration= configuration;
+
+        }
+        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
+        {
+            ///数据中心链接了,开始推送数据
+            if (_connectionService.centerIsConnected) 
+            {
+                // 启动时加载未推送的数据
+                //await LoadUnpushedDataAsync(stoppingToken);
+            }
+            while (!stoppingToken.IsCancellationRequested)
+            {
+                // 从 Channel 中读取数据
+                if (await _dataQueue.Reader.WaitToReadAsync(stoppingToken))
+                {
+                    while (_dataQueue.Reader.TryRead(out var data))
+                    {
+
+                        await PushSubjectResultDataToCloudAsync(data, stoppingToken);
+                       
+                    }
+                }
+            }
+        }
+        
+        private async Task PushSubjectResultDataToCloudAsync((EvaluationStudentResult studentResult, EvaluationSubjectResult subjectResult, string resultId)data, CancellationToken cancellationToken)
+        {
+            if (_connectionService.centerIsConnected) 
+            {
+                try
+                {
+                    //  var json = JsonSerializer.Serialize(data);
+                    //var content = new StringContent(json, Encoding.UTF8, "application/json");
+                    var httpClient = _httpClientFactory.CreateClient();
+
+                    string url = $"{_connectionService.centerUrl}/common/exam/upsert-new-record";
+                    if (httpClient.DefaultRequestHeaders.Contains("X-Auth-AuthToken")) {
+                        httpClient.DefaultRequestHeaders.Remove("X-Auth-AuthToken");
+                    }
+                    httpClient.DefaultRequestHeaders.Add("X-Auth-AuthToken", _connectionService.loginToken);
+                    var response = await httpClient.PostAsJsonAsync(url, new { 
+                        id =data.subjectResult.examId,
+                        answer=data.subjectResult.answers,
+                        subjectId=data.subjectResult.subjectId,
+                        classId=data.studentResult.classId,
+                        ownerId=data.studentResult.ownerId,
+                        paperId=data.subjectResult.paperId,
+                        studentId=data.studentResult.studentId,
+                        studentName=data.studentResult.studentName,
+                    }, cancellationToken);
+
+                    if (response.IsSuccessStatusCode)
+                    {
+                        MarkDataAsPushed(data);
+                        Console.WriteLine($"Data {data.resultId} pushed successfully.");
+                    }
+                    else
+                    {
+                        Console.WriteLine($"Failed to push data {data.resultId}. Retrying...");
+                        // 推送失败,重新加入队列
+                        await _dataQueue.Writer.WriteAsync(data, cancellationToken);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    Console.WriteLine($"Error pushing data {data.resultId}: {ex.Message}");
+                    // 推送失败,重新加入队列
+                    await _dataQueue.Writer.WriteAsync(data, cancellationToken);
+                }
+            }
+        }
+        private void MarkDataAsPushed((EvaluationStudentResult studentResult, EvaluationSubjectResult subjectResult, string resultId) data)
+        {
+            var collection = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>();
+            EvaluationSubjectResult? subjectResult = data.studentResult.subjectResults.Where(x => x.id!.Equals(data.resultId)).FirstOrDefault();
+            if (subjectResult!=null) 
+            {
+                subjectResult.pushed=1;
+                collection.Upsert(data.studentResult);
+                var collectionSub = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationSubjectResult>();
+                var unpushedData = collectionSub.FindOne(x => data.resultId.Equals(x.id));
+                if (unpushedData!=null) 
+                {
+                    unpushedData.pushed=1;
+                    _dataQueue.MarkAsProcessed((unpushedData.id!, unpushedData.examId!, unpushedData.evaluationId!, unpushedData.subjectId!,unpushedData, data.studentResult));
+                }
+            }
+            
+        }
+        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
+    {
+        private readonly Channel<(EvaluationStudentResult studentResult, EvaluationSubjectResult subjectResult, string resultId)> _channel;
+        private readonly HashSet<(string resultId,string examId,string evaluationId,string subjectId, EvaluationSubjectResult subjectResult, EvaluationStudentResult studentResult)> _uniqueIds; // 用于维护唯一性
+
+        public async Task<bool> TryAddAsync((string resultId, string examId, string evaluationId, string subjectId, EvaluationSubjectResult subjectResult, EvaluationStudentResult studentResult) data, CancellationToken cancellationToken = default)
+        {
+            var key = (data.resultId, data.examId,data.evaluationId,data.subjectId,data.subjectResult,data.studentResult); // 复合键
+            lock (_uniqueIds)
+            {
+                if (_uniqueIds.Contains(key))
+                {
+                    return false;
+                }
+                _uniqueIds.Add(key);
+            }
+
+            await _channel.Writer.WriteAsync((data.studentResult,data.subjectResult, data.resultId), cancellationToken);
+            return true;
+        }
+        public DataQueue() {
+            // 创建一个无界 Channel
+            _channel = Channel.CreateUnbounded<(EvaluationStudentResult studentResult, EvaluationSubjectResult subjectResult, string resultId)>();
+            _uniqueIds = new HashSet<(string resultId, string examId, string evaluationId, string subjectId, EvaluationSubjectResult subjectResult, EvaluationStudentResult studentResult)>();
+        }
+        public ChannelWriter<(EvaluationStudentResult studentResult, EvaluationSubjectResult subjectResult, string resultId)> Writer => _channel.Writer;
+        public ChannelReader<(EvaluationStudentResult studentResult, EvaluationSubjectResult subjectResult, string resultId)> Reader => _channel.Reader;
+
+        // 批量写入数据
+        public async Task WriteAsync(( EvaluationStudentResult studentResult, EvaluationSubjectResult subjectResult, string resultId) data, CancellationToken cancellationToken = default)
+        {
+            await _channel.Writer.WriteAsync((data.studentResult,data.subjectResult, data.resultId), cancellationToken);
+        }
+        // 获取当前队列中的未上传数据数量
+        public int GetPendingCount()
+        {
+            return _channel.Reader.Count;
+        }
+        // 从队列中移除数据时,同时从 HashSet 中移除 ID
+        public void MarkAsProcessed((string resultId, string examId, string evaluationId, string subjectId, EvaluationSubjectResult subjectResult, EvaluationStudentResult studentResult) key)
+        {
+            lock (_uniqueIds) // 加锁确保线程安全
+            {
+                _uniqueIds.Remove(key);
+            }
+        }
+    }
+}

+ 1 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/JwtAuthExtension.cs

@@ -46,7 +46,7 @@ namespace IES.ExamServer
                 { "roles",roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student) 
                 { "scope",scope},  //登入者的入口类型。 (teacher 教师端登录的醍摩豆ID、tmduser学生端登录的醍摩豆ID、student学生端登录校内账号的学生ID)
                 { "timezone",timezone},
-               
+                { JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()}
             };
             // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用
             var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));

+ 5 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Models/EvaluationRound.cs

@@ -56,6 +56,10 @@
         /// 进行中  剩下的是未开始
         /// </summary>
         public int doingCount { get; set; }
-       
+        /// <summary>
+        /// 乱序作答0 顺序作答,1乱序作答,此字段仅供监考教师设置,如果评测要求是乱序,监考教师则不能修改为顺序作答,只能是从顺序作答改为乱序作答。
+        /// </summary>
+        public int disorder { get; set; }
+
     }
 }

+ 11 - 2
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Models/EvaluationStudent.cs

@@ -145,7 +145,7 @@
         /// 是否推送0 未推送,1推送
         /// </summary>
         public int pushed { get; set; }
-
+        //public HashSet<string> subjectResultIds= new HashSet<string>();
         public HashSet<EvaluationSubjectResult> subjectResults { get; set; } = new HashSet<EvaluationSubjectResult>();
         public EvaluationMusicAIResult? musicAIResult { get; set; }
         public EvaluationVoteResult? voteResult { get; set; }
@@ -196,6 +196,7 @@
         /// 试卷名称
         /// </summary>
         public string? paperName { get; set; }
+        public int questionCount { get; set;}
     }
 
     public abstract class EvaluationResult 
@@ -220,6 +221,10 @@
         public long submitTime { get; set; }
 
         public long createTime { get; set; }
+        /// <summary>
+        /// 是否推送 0 未推送 1 已推送
+        /// </summary>
+        public int pushed { get; set; }
     }
 
     /// <summary>
@@ -279,7 +284,11 @@
         /// <summary>
         /// 学生答案
         /// </summary>
-        public List<List<string?>> answers { get; set; } = new List<List<string?>>();
+        public List<List<string>>? answers { get; set; } = new List<List<string>>();
+        /// <summary>
+        /// 题目数量
+        /// </summary>
+        public int questionCount { get; set; }
     }
     /// <summary>
     /// 投票作答结果

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

@@ -67,6 +67,10 @@ namespace IES.ExamServer.Server
             // 鬧꿍 ConnectionService 槨데절
             builder.Services.AddSingleton<CenterServiceConnectionService>();
             builder.Services.AddSingleton<ServiceInitializer>();
+            // 鬧꿍 DataQueue 륩蛟
+            builder.Services.AddSingleton<DataQueue>();
+            // 鬧꿍빈憩륩蛟
+            builder.Services.AddHostedService<SubjectPushService>();
             builder.Services.AddCors(options =>
             {
                 //options.AddDefaultPolicy(

+ 3 - 9
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/IndexService.cs

@@ -330,25 +330,19 @@ namespace IES.ExamServer.Services
             //{
             //    throw new Exception("未获取到端口信息!");
             //}
-            var networks = device.networks;
+            var networks = device.networks.ToList();
             if (device.networks.IsNotEmpty()) 
             {
                var order=  device.networks.OrderByDescending(x => x.physical).ToList();
                 for (int i=0; i<order.Count();i++) 
                 {
-                    if (i==0)
-                    {
-                        order[i].domain="exam.habook.local";
-                    }
-                    else {
-                        order[i].domain=$"exam{i}.habook.local";
-                    }
+                    order[i].domain="exam.habook.local";
                 }
                 //优先以物理网卡来生成hash,如果没有则以所有网卡生成hash
                 var physical = order.FindAll(x => x.physical==1);
                 if (physical.IsNotEmpty())
                 {
-                    networks.AddRange(physical);
+                    networks=physical;
                 }
             }
             StringBuilder sb= new StringBuilder();

+ 2 - 2
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/ManageService.cs

@@ -15,7 +15,7 @@ namespace IES.ExamServer.Services
     public class ManageService
     {
 
-        public async static Task<(EvaluationClient? evaluationCloud, string centerCode, string centerMsg)> GetEvaluationFromCenter(Teacher teacher,IConfiguration _configuration,IHttpClientFactory _httpClientFactory, string shortCode, string evaluationId)
+        public async static Task<(EvaluationClient? evaluationCloud, string centerCode, string centerMsg)> GetEvaluationFromCenter(string? x_auth_token, IConfiguration _configuration,IHttpClientFactory _httpClientFactory, string shortCode, string evaluationId)
         {
             EvaluationClient? evaluationCloud = null;
             string centerCode = string.Empty, centerMsg = string.Empty;
@@ -25,7 +25,7 @@ namespace IES.ExamServer.Services
             {
                 client.DefaultRequestHeaders.Remove(Constant._X_Auth_AuthToken);
             }
-            client.DefaultRequestHeaders.Add(Constant._X_Auth_AuthToken, teacher!.x_auth_token);
+            client.DefaultRequestHeaders.Add(Constant._X_Auth_AuthToken, x_auth_token);
             try
             {
                 HttpResponseMessage message = await client.PostAsJsonAsync($"{CenterUrl}/evaluation-sync/find-sync-info", new { shortCode, evaluationId });

+ 19 - 7
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/admin/ActivityManage.vue

@@ -77,7 +77,7 @@
                             </span>
                         </span>
                     </div>
-                    <el-tabs v-model="activeName" @tab-click="handleClick">
+                    <el-tabs v-model="activeName" :before-leave="beforeTabLeave">
                         <el-tab-pane label="活动详情" name="info" class="activity-info">
                             <vuescroll>
                                 <div class="info-tag">时间:
@@ -336,18 +336,19 @@ export default {
                 this.deviceId = res.data.device
             })
         },
-        handleClick(tab, event) {
-            if(tab.name === 'student') {
+        beforeTabLeave(activeName, oldActiveName) {
+            if(activeName === 'student') {
                 if(this.needUpdate.status === 1) {
                     this.$message({
                         message: '活动需更新,请先下载',
                         type: 'warning'
                     });
-                    this.activeName = 'info'
-                    return
+                    return false
+                } else {
+                    if(!this.evaluationClient.openCode) this.isInputOpen = true
+                    else this.getRoundList()
+                    return true
                 }
-                if(!this.evaluationClient.openCode) this.isInputOpen = true
-                else this.getRoundList()
             }
         },
         getNowTime() {
@@ -922,6 +923,7 @@ export default {
             })
         },
         updatePackage() {
+            this.openErrorMsgs = []
             this.isLoading = Loading.service({
                 lock: true,
                 text: '加载中',
@@ -939,6 +941,8 @@ export default {
                             message: '下载失败,请重新下载',
                             type: 'error'
                         });
+                        this.openErrorMsgs = res.result.errorMsgs
+                        this.showErrorMsgs = true
                     } else {
                         this.needUpdate = {status: 0, msg: []}
                         this.$message({
@@ -947,6 +951,13 @@ export default {
                         });
                         this.onSelectAct(this.curIndex)
                     }
+                } else {
+                    this.$message({
+                        message: '下载失败,请重新下载',
+                        type: 'error'
+                    });
+                    this.openErrorMsgs = res.result.errorMsgs
+                    this.showErrorMsgs = true
                 }
             }).finally(() => {
                 this.isLoading.close()
@@ -1022,6 +1033,7 @@ export default {
         },
         delInfo(index) {
             this.openErrorMsgs.splice(index, 1)
+            if(!this.openErrorMsgs.length) this.showErrorMsgs = false
         },
         async openPaper(index, paperIndex) {
             if(this.needUpdate.status === 1) {

+ 9 - 7
TEAMModelOS.SDK/Models/Service/EvaluationSyncInfoService.cs

@@ -156,7 +156,7 @@ namespace TEAMModelOS.SDK.Models.Service
                         if (response.IsSuccessStatusCode)
                         {
                             ExamInfo exam= JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamInfo>();
-                            dataTime= exam._ts*1000;
+                            dataTime = exam._ts*1000;
                             evaluationSyncInfo.name=exam.name;
                             evaluationSyncInfo.subjects = exam.subjects?.Select(x=>new IES.ExamServer.Models.SubjectExam { subjectId=x.id,subjectName=x.name,examId=id,examName=exam.name}).ToList();
                             evaluationSyncInfo.dataTime= DateTimeOffset.Now.ToUnixTimeMilliseconds();
@@ -186,7 +186,7 @@ namespace TEAMModelOS.SDK.Models.Service
                                         subjectName=subject.name,
                                         examId=id,
                                         examName=exam.name,
-                                        papers= group.list.Select(x=>new SubjectExamPaper {paperId= x.id,paperName=x.name, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList(),
+                                        papers= group.list.Select(x=>new SubjectExamPaper {paperId= x.id,paperName=x.name, questionCount=x.answers.IsNotEmpty()?x.answers.Count():0, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList(),
                                     } );
 
                                     EvaluationExam evaluationExam = new EvaluationExam()
@@ -201,7 +201,7 @@ namespace TEAMModelOS.SDK.Models.Service
                                         scope=scope,
                                         stime=stime,
                                         etime=etime,
-                                        papers= group.list.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}", point=x.point,knowledge=x.knowledge,type=x.type,field=x.field }).ToList(),
+                                        papers= group.list.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, questionCount=x.answers.IsNotEmpty() ? x.answers.Count() : 0, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}", point=x.point,knowledge=x.knowledge,type=x.type,field=x.field }).ToList(),
                                     };
                                     evaluationExams.Add(evaluationExam);
                                 }
@@ -217,7 +217,6 @@ namespace TEAMModelOS.SDK.Models.Service
                         if (response.IsSuccessStatusCode) 
                         {
                             ArtEvaluation art = JsonDocument.Parse(response.Content).RootElement.Deserialize<ArtEvaluation>();
-                            
                             // evaluationSyncInfo.subjects = art.subjects?.Select(x => new IES.ExamServer.Models.SubjectExam { id=x.id, name=x.name, examId=id }).ToList();
                             evaluationSyncInfo.name = art.name;
                             evaluationSyncInfo.pid= art.pId;
@@ -247,6 +246,7 @@ namespace TEAMModelOS.SDK.Models.Service
                             {
                                 if (!string.IsNullOrWhiteSpace(item.acId)) 
                                 {
+                                    // item.isOrder=>disorder
                                     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-{ownerId}"));
                                     if (examResponse.IsSuccessStatusCode) 
@@ -256,7 +256,7 @@ namespace TEAMModelOS.SDK.Models.Service
                                         var subjectSync = evaluationSyncInfo.subjects.Find(x => x.examId.Equals(item.acId) && x.subjectId.Equals(item.subject));
                                         if (subjectSync!=null)
                                         {
-                                            subjectSync.papers= papers?.Select(x => new SubjectExamPaper { paperId=x.id, paperName=x.name, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList();
+                                            subjectSync.papers= papers?.Select(x => new SubjectExamPaper { paperId=x.id, paperName=x.name, questionCount=x.answers.IsNotEmpty() ? x.answers.Count() : 0, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList();
                                             subjectSync.subjectName=subject.name;
                                         }
                                         else {
@@ -266,7 +266,8 @@ namespace TEAMModelOS.SDK.Models.Service
                                                 subjectName=subject.name,
                                                 examId=item.acId,
                                                 examName=exam.name,
-                                                papers = papers?.Select(x => new SubjectExamPaper { paperId=x.id, paperName=x.name, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList()
+                                                disorder=item.isOrder.HasValue ? item.isOrder.Value : 0,
+                                                papers = papers?.Select(x => new SubjectExamPaper { paperId=x.id, paperName=x.name, questionCount=x.answers.IsNotEmpty() ? x.answers.Count() : 0, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList()
                                             });
                                         }
                                         dataTime= dataTime<exam._ts*1000 ? exam._ts*1000 : dataTime;
@@ -283,7 +284,8 @@ namespace TEAMModelOS.SDK.Models.Service
                                             scope=scope,
                                             stime=stime,
                                             etime=etime,
-                                            papers= papers.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}", point=x.point, knowledge=x.knowledge, type=x.type, field=x.field }).ToList(),
+                                            disorder=item.isOrder.HasValue?item.isOrder.Value:0,
+                                            papers= papers.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, blob=x.blob, questionCount=x.answers.IsNotEmpty() ? x.answers.Count() : 0, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}", point=x.point, knowledge=x.knowledge, type=x.type, field=x.field }).ToList(),
                                         };
                                         evaluationExams.Add(evaluationExam);
                                     }

+ 1 - 1
TEAMModelOS/ClientApp/src/view/teachermgmt/components/personnel/Index.vue

@@ -622,7 +622,7 @@ export default {
               }
               else {
                 this.$Message.info({
-                  content: this.$t('teachermgmt.message.info13') + ' ' + this.userListImportSuccess[0].name + ' ' + this.$t('teachermgmt.message.info14'),
+                  content: this.$t('teachermgmt.message.info22') + ' ' + this.userListImportSuccess[0].name,
                   duration: 5
                 });
               }

+ 27 - 24
TEAMModelOS/Controllers/Client/HiTAControlller.cs

@@ -418,6 +418,7 @@ namespace TEAMModelOS.Controllers.Client
         [HttpPost("get-teacher-info")]
         public async Task<IActionResult> GetTeacherInfo()
         {
+            string tmid = string.Empty;
             try
             {
                 string id_token = HttpContext.GetXAuth("IdToken");
@@ -426,7 +427,7 @@ namespace TEAMModelOS.Controllers.Client
                 var jwt = new JwtSecurityToken(id_token);
                 if (!jwt.Payload.Iss.Equals("account.teammodel", StringComparison.OrdinalIgnoreCase)) return BadRequest();
                 var id = jwt.Payload.Sub;
-
+                tmid = id;
 
                 var clientc = _azureCosmos.GetCosmosClient();
                 var clientr = _azureRedis.GetRedisClient(8);
@@ -486,29 +487,31 @@ namespace TEAMModelOS.Controllers.Client
                             //學校資料生成
                             dynamic schoolExtobj = new ExpandoObject();
                             var schoolJson = await clientc.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{obj.GetProperty("schoolId")}", new PartitionKey("Base"));
-                            var school = await JsonDocument.ParseAsync(schoolJson.Content);
-                            try
-                            {
-                                schoolExtobj.schoolId = obj.GetProperty("schoolId");
-                            schoolExtobj.name = school.RootElement.GetProperty("name");
-                            schoolExtobj.region = school.RootElement.GetProperty("region");
-                            schoolExtobj.province = school.RootElement.GetProperty("province");
-                            schoolExtobj.city = school.RootElement.GetProperty("city");
-                            schoolExtobj.status = obj.GetProperty("status");
-                            schoolExtobj.picture = school.RootElement.GetProperty("picture");
-                            schoolExtobj.size = new ExpandoObject();
-                            schoolExtobj.size.used = schoolUsedBlob.usedSize + schoolUsedBlob.teach * 1073741824;
-                            long ssize = (school.RootElement.TryGetProperty("size", out JsonElement ssizeJson)) ? ssizeJson.GetInt32() : 0;
-                            schoolExtobj.size.total = ssize * 1073741824;
-                            schoolExtobj.size.avaliable = schoolExtobj.size.total - schoolExtobj.size.used;
-                            schoolExtobj.admin = adminList;
-                            schoolExtobj.courses = coursesch;
-
-                            schools.Add(schoolExtobj);
-                            }
-                            catch (Exception)
+                            if(schoolJson.StatusCode == System.Net.HttpStatusCode.OK)
                             {
-                                await _dingDing.SendBotMsg($"IES5,{_option.Location},HiTA/Debug()\nJson:{schoolJson}\n schoolExtobj:{schoolExtobj}", GroupNames.醍摩豆服務運維群組);
+                                try
+                                {
+                                    var school = await JsonDocument.ParseAsync(schoolJson.Content);
+                                    schoolExtobj.schoolId = obj.GetProperty("schoolId");
+                                    schoolExtobj.name = school.RootElement.GetProperty("name");
+                                    schoolExtobj.region = school.RootElement.GetProperty("region");
+                                    schoolExtobj.province = school.RootElement.GetProperty("province");
+                                    schoolExtobj.city = school.RootElement.GetProperty("city");
+                                    schoolExtobj.status = obj.GetProperty("status");
+                                    schoolExtobj.picture = school.RootElement.GetProperty("picture");
+                                    schoolExtobj.size = new ExpandoObject();
+                                    schoolExtobj.size.used = schoolUsedBlob.usedSize + schoolUsedBlob.teach * 1073741824;
+                                    long ssize = (school.RootElement.TryGetProperty("size", out JsonElement ssizeJson)) ? ssizeJson.GetInt32() : 0;
+                                    schoolExtobj.size.total = ssize * 1073741824;
+                                    schoolExtobj.size.avaliable = schoolExtobj.size.total - schoolExtobj.size.used;
+                                    schoolExtobj.admin = adminList;
+                                    schoolExtobj.courses = coursesch;
+                                    schools.Add(schoolExtobj);
+                                }
+                                catch (Exception)
+                                {
+                                    await _dingDing.SendBotMsg($"IES5,{_option.Location},HiTA/Debug()\nJson:{schoolJson}\n schoolExtobj:{schoolExtobj}", GroupNames.醍摩豆服務運維群組);
+                                }
                             }
                         }
                     }
@@ -692,7 +695,7 @@ namespace TEAMModelOS.Controllers.Client
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"IES5,{_option.Location},HiTA/GetTeachInfo()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},HiTA/GetTeachInfo()\n{ex.Message}\n{ex.StackTrace}\n tmid:{tmid}", GroupNames.醍摩豆服務運維群組);
                 return BadRequest();
             }
         }

+ 6 - 6
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -1603,12 +1603,12 @@ namespace TEAMModelOS.Controllers
         /// <param name="request"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-        [Authorize(Roles = "IES")]
-        [AuthToken(Roles = "student,teacher")]
+        //[Authorize(Roles = "IES")]
+        [AuthToken(Roles = "teacher,visitor")]
         [HttpPost("upsert-new-record")]
         public async Task<IActionResult> upsertNewRecord(JsonElement request)
         {
-
+            await _dingDing.SendBotMsg($"局域网评测端推送学生作答数据:\n{request.ToJsonString()}", GroupNames.成都开发測試群組);
             //评测活动Id
             if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
             //学生作答结果
@@ -1621,8 +1621,8 @@ namespace TEAMModelOS.Controllers
             if (!request.TryGetProperty("ownerId", out JsonElement ownerId)) return BadRequest();
             if (!request.TryGetProperty("paperId", out JsonElement paperId)) return BadRequest();
             if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
-
-            var (userId, name, picture, school) = HttpContext.GetAuthTokenInfo();
+            if (!request.TryGetProperty("studentName", out JsonElement studentName)) return BadRequest();
+           // var (userId, name, picture, school) = HttpContext.GetAuthTokenInfo();
             try
             {
                 var client = _azureCosmos.GetCosmosClient();
@@ -1823,7 +1823,7 @@ namespace TEAMModelOS.Controllers
                     if (!isAns) {
                         if (request.TryGetProperty("artId", out JsonElement artId) && request.TryGetProperty("quotaId", out JsonElement quotaId))
                         {
-                            await getArtInfoAsync(client, artId.GetString(), school, result.sum[newIndex], id.GetString(), subjectId.GetString(), quotaId.GetString(), userId, picture, name, userType, new List<string> { classId.GetString()});
+                            await getArtInfoAsync(client, artId.GetString(), $"{ownerId}", result.sum[newIndex], id.GetString(), subjectId.GetString(), quotaId.GetString(), $"{studentId}", null, $"{studentName}", userType, new List<string> { classId.GetString()});
                         };                  
                     }
                 }