黄贺彬 3 달 전
부모
커밋
31079f707a

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

@@ -131,6 +131,15 @@ namespace IES.ExamServer.Models
         /// 开卷码
         /// </summary>
         public string? openCode { get; set; }
+        /// <summary>
+        /// 技能考试截止时间0 未设置
+        /// </summary>
+        public long examDeadline { get; set; }
+        /// <summary>
+        /// 开启重复作答0 未开启,1 开启
+        /// </summary>
+        public int reanswer { get; set; }
+
     }
 
     public class EvaluationGroupListDto

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

@@ -7,6 +7,7 @@ using IES.ExamServer.Helper;
 using IES.ExamServer.Helpers;
 using IES.ExamServer.Models;
 using IES.ExamServer.Services;
+using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.SignalR;
 using Microsoft.Extensions.Caching.Memory;
@@ -675,17 +676,17 @@ namespace IES.ExamServer.Controllers
                     bool isAllContained = setting.groupList.All(x => evaluationClient.grouplist.Any(y => y.id == x.id));
                     if (isAllContained && evaluationClient.grouplist.IsNotEmpty())
                     {
-                        
+                        var ids= setting.groupList.Select(x => x.id).OrderBy(x=>x);
                         //增加排序,保证id的唯一性
-                        setting.id=ShaHashHelper.GetSHA1($"{evaluationClient.id}_{string.Join("", setting.groupList.Select(x => x.id)).OrderBy(x => x)}");
+                        setting.id=ShaHashHelper.GetSHA1($"{evaluationClient.id}_{string.Join("", ids) }");
                         setting.createTime= DateTimeOffset.Now.ToUnixTimeMilliseconds();
                       
                         _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationRoundSetting>().Upsert(setting);
                         _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Upsert(evaluationClient);
                         /// 分配试卷
-                       
-                        var (roundStudentPapers, members, results,code,msg) = AssignStudentPaper(evaluationClient, setting);
-                        return Ok(new { code = code, msg =msg , setting, results });
+                        var(roundStudentPapers, members, results, code, msg)=    ManageService.AssignStudentPaper(evaluationClient, setting,_connectionService, _liteDBFactory, _logger);
+                        //var (roundStudentPapers, members, results,code,msg) = AssignStudentPaper(evaluationClient, setting);
+                        return Ok(new { code = code, msg =msg , setting, results, roundStudentPapers });
                     }
                     else
                     {

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

@@ -180,7 +180,7 @@ namespace IES.ExamServer.Controllers
                        
                     //    return Ok(new { msg = "已过截止时间。", code = 2 });
                     //}
-                    if (!string.IsNullOrWhiteSpace(subjectId)  && !string.IsNullOrWhiteSpace(examId) && !string.IsNullOrWhiteSpace(paperId)&& costTime>0)
+                    if (!string.IsNullOrWhiteSpace(subjectId)  && !string.IsNullOrWhiteSpace(examId) && !string.IsNullOrWhiteSpace(paperId))
                     {
                        
                         if (answers!.IsNotEmpty())

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

@@ -12,11 +12,12 @@ using System.Threading.Tasks;
 
 namespace IES.ExamServer.DI
 {
-    public class LiteDBFactory
+    public class LiteDBFactory : IDisposable
     {
         private readonly IServiceProvider _services;
         private readonly IOptionsMonitor<LiteDBFactoryOptions> _optionsMonitor;
         private readonly ILogger _logger;
+        private bool _disposed;
         private ConcurrentDictionary<string, LiteDatabase> LiteDatabases { get; } = new ConcurrentDictionary<string, LiteDatabase>();
         public LiteDBFactory(IServiceProvider services, IOptionsMonitor<LiteDBFactoryOptions> optionsMonitor, ILogger<LiteDBFactory> logger)
         {
@@ -33,6 +34,18 @@ namespace IES.ExamServer.DI
             //return new LiteDatabase(_optionsMonitor.Get(name).Connectionstring);
             return LiteDatabases.GetOrAdd(name, x => new LiteDatabase(_optionsMonitor.Get(name).Connectionstring));
         }
+
+        public void Dispose()
+        {
+            if (_disposed) return;
+
+            foreach (var db in LiteDatabases.Values)
+            {
+                db.Dispose();
+            }
+
+            _disposed = true;
+        }
     }
     public class LiteDBFactoryOptions
     {
@@ -47,7 +60,7 @@ namespace IES.ExamServer.DI
             if (connectionstrings == null) throw new ArgumentNullException(nameof(connectionstrings));
 
 
-            services.TryAddTransient<LiteDBFactory>();
+            services.TryAddSingleton<LiteDBFactory>();
             //多个连接字符串注入
             connectionstrings.ForEach(connection =>
             {

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

@@ -15,6 +15,213 @@ namespace IES.ExamServer.Services
     public class ManageService
     {
 
+
+        public static (List<EvaluationStudentPaper> roundStudentPapers, List<EvaluationMember> members, List<EvaluationStudentResult> results, int code, string msg)
+          AssignStudentPaper(EvaluationClient evaluationClient, EvaluationRoundSetting setting, CenterServiceConnectionService _connectionService,LiteDBFactory _liteDBFactory,ILogger _logger)
+        {
+            int code = 200;
+            string msg = string.Empty;
+            List<EvaluationStudentPaper> roundStudentPapers = new List<EvaluationStudentPaper>();
+            List<EvaluationMember> members = new List<EvaluationMember>();
+            List<EvaluationStudentResult> results = new List<EvaluationStudentResult>();
+            string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
+            string evaluationPath = Path.Combine(packagePath, evaluationClient.id!);
+            string evaluationDataPath = Path.Combine(evaluationPath, "data");
+            string path_groupList = Path.Combine(evaluationDataPath, "groupList.json");
+            if (System.IO.File.Exists(path_groupList)) 
+            {
+                JsonNode? jsonNode = System.IO.File.ReadAllText(path_groupList).ToObject<JsonNode>();
+                if (jsonNode!=null && jsonNode["groupList"]!=null)
+                {
+                    List<EvaluationGroupList>? groupList = jsonNode["groupList"]?.ToObject<List<EvaluationGroupList>>();
+                    if (groupList!=null)
+                    {
+                        bool isAllContained = setting.groupList.All(x => groupList.Any(y => y.id == x.id));
+                        if (isAllContained)
+                        {
+                            foreach (var item in setting.groupList)
+                            {
+                                EvaluationGroupList? groupListItem = groupList.Find(x => x.id == item.id);
+                                if (groupListItem!=null)
+                                {
+                                    groupListItem.members.ForEach(x =>
+                                    {
+                                        x.schoolId=_connectionService?.serverDevice?.school?.id;
+                                        x.evaluationId=evaluationClient.id;
+                                        x.classId= groupListItem.id;
+                                        x.periodId= groupListItem.periodId;
+                                        x.roundId=setting.id;
+                                        x.className= groupListItem.name;
+                                        x.year= groupListItem.year;
+                                    });
+                                    members.AddRange(groupListItem.members);
+                                }
+                            }
+                            var database = _liteDBFactory.GetLiteDatabase();
+                            try 
+                            {
+                                
+                                var transaction = database.BeginTrans();
+
+                                //清空数据库,重新插入
+                                database.GetCollection<EvaluationMember>().DeleteAll();
+                                //插入
+                                database.GetCollection<EvaluationMember>().Upsert(members);
+                                foreach (var subject in evaluationClient.subjects) 
+                                {
+                                    var studentPaperIds = members.Select(x => ShaHashHelper.GetSHA1($"{evaluationClient.id}{subject.examId}{subject.subjectId}{x.id}")).ToList() ;
+                                    List<EvaluationStudentPaper> evaluationStudentPapers = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentPaper>()
+                                        .Find(x => studentPaperIds.Contains(x.id!)).ToList();
+                                    List<EvaluationStudentPaper> studentPapers = new List<EvaluationStudentPaper>();
+                                    int paperIndex = 0;
+                                    int paperCount = subject.papers.Count();
+                                    //先把试卷顺序打乱
+                                    subject.papers =subject.papers.OrderBy(x => Guid.NewGuid().ToString()).ToList();
+                                    //将学生顺序打乱
+                                    members = members.OrderBy(x => Guid.NewGuid().ToString()).ToList();
+                                    foreach (var member in members) 
+                                    {
+                                        SubjectExamPaper subjectExamPaper = subject.papers[paperIndex];
+                                        string studentPaperId = ShaHashHelper.GetSHA1($"{evaluationClient.id}{subject.examId}{subject.subjectId}{member.id}");
+                                        var paper = evaluationStudentPapers.Find(x => x.id!.Equals(studentPaperId));
+                                        if (paper==null)
+                                        {
+                                            EvaluationStudentPaper studentPaper = new EvaluationStudentPaper
+                                            {
+                                                studentId=member.id,
+                                                studentName=member.name,
+                                                classId=member.classId,
+                                                className=member.className,
+                                                evaluationId=evaluationClient.id,
+                                                examId=subject.examId,
+                                                examName=subject.examName,
+                                                subjectId=subject.subjectId,
+                                                subjectName=subject.subjectName,
+                                                paperId=subjectExamPaper.paperId,
+                                                paperName=subjectExamPaper.paperName,
+                                                questionCount=subjectExamPaper.questionCount,
+                                                id=studentPaperId,
+                                            };
+                                            studentPapers.Add(studentPaper);
+                                            // 移动到下一个试卷
+                                            paperIndex = (paperIndex + 1) % paperCount;
+                                        }
+                                    }
+                                    if (studentPapers.Count>0)
+                                    {
+                                        _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentPaper>().Upsert(studentPapers);
+                                        roundStudentPapers.AddRange(studentPapers);
+                                    }
+                                    if (evaluationStudentPapers!=null && evaluationStudentPapers.Count()>0)
+                                    {
+                                        roundStudentPapers.AddRange(evaluationStudentPapers);
+                                    }
+                                }
+                                long now = DateTimeOffset.Now.ToUnixTimeMilliseconds();
+                                IEnumerable<EvaluationStudentResult> studentResults = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>()
+                                    .Find(x => members.Select(x => x.id).Contains(x.studentId)&&!string.IsNullOrWhiteSpace(x.evaluationId)  && x.evaluationId.Equals(evaluationClient.id));
+                                foreach (var member in members)
+                                {
+                                    EvaluationStudentResult? studentResult = null;
+                                    //sha1(evaluationId-schoolId-studentId)
+                                    string resultId = ShaHashHelper.GetSHA1(evaluationClient.id+_connectionService?.serverDevice?.school?.id+member.id);
+                                    var result = studentResults.Where(x => x.id!.Equals(resultId)    && !string.IsNullOrWhiteSpace(x.studentId)  && x.studentId.Equals(member.id));
+                                    if (result==null || result.Count()==0)
+                                    {
+                                        studentResult = new EvaluationStudentResult()
+                                        {
+                                            id = resultId,
+                                            evaluationId = evaluationClient.id,
+                                            schoolId = _connectionService?.serverDevice?.school?.id,
+                                            studentId = member.id,
+                                            studentName = member.name,
+                                            classId = member.classId,
+                                            className = member.className,
+                                            ownerId= evaluationClient.ownerId,
+                                            scope= evaluationClient.scope,
+                                            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));
+                                        if (studentPapers.IsNotEmpty())
+                                        {
+                                            foreach (var studentPaper in studentPapers)
+                                            {
+                                                studentResult.subjectResults.Add(new EvaluationSubjectResult()
+                                                {
+                                                    id = ShaHashHelper.GetSHA1(evaluationClient.id+studentPaper.examId+studentPaper.subjectId+member.id),
+                                                    evaluationId = studentPaper.evaluationId,
+                                                    examId = studentPaper.examId,
+                                                    examName = studentPaper.examName,
+                                                    subjectId = studentPaper.subjectId,
+                                                    subjectName = studentPaper.subjectName,
+                                                    paperId = studentPaper.paperId,
+                                                    paperName = studentPaper.paperName,
+                                                    questionCount=studentPaper.questionCount,
+                                                    createTime=now
+                                                });
+                                            }
+                                        }
+                                        // _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>().Upsert(studentResult);
+                                    }
+                                    else
+                                    {
+                                        studentResult = result.First();
+                                        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));
+                                        if (studentPapers.IsNotEmpty())
+                                        {
+                                            foreach (var studentPaper in studentPapers)
+                                            {
+                                                string subjectResultId = ShaHashHelper.GetSHA1(evaluationClient.id+studentPaper.examId+studentPaper.subjectId+member.id);
+                                                var subjectResult = studentResult.subjectResults.Where(x => x.id!.Equals(subjectResultId)).FirstOrDefault();
+                                                if (subjectResult==null)
+                                                {
+                                                    subjectResult=  new EvaluationSubjectResult()
+                                                    {
+                                                        id = ShaHashHelper.GetSHA1(evaluationClient.id+studentPaper.examId+studentPaper.subjectId+member.id),
+                                                        evaluationId = studentPaper.evaluationId,
+                                                        examId = studentPaper.examId,
+                                                        examName = studentPaper.examName,
+                                                        subjectId = studentPaper.subjectId,
+                                                        subjectName = studentPaper.subjectName,
+                                                        paperId = studentPaper.paperId,
+                                                        paperName = studentPaper.paperName,
+                                                        questionCount= studentPaper.questionCount,
+                                                        createTime=now
+                                                    };
+                                                }
+                                                studentResult.subjectResults.Add(subjectResult);
+                                            }
+                                        }
+                                    }
+                                    if (studentResult!=null)
+                                    {
+                                        results.Add(studentResult);
+                                    }
+                                }
+                                if (results.Count>0)
+                                {
+                                    _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationStudentResult>().Upsert(results);
+                                }
+                                database.Commit();
+
+                            } catch (Exception ex) {
+                                database.Rollback();
+                                _logger.LogError($"Transaction failed: {ex.Message}");
+                                throw; // 重新抛出异常
+                            }
+
+                        }
+                    }
+                }
+            }
+            return (roundStudentPapers, members, results, code, msg);
+        }
         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;

+ 4 - 0
TEAMModelOS.SDK/Models/Service/EvaluationSyncInfoService.cs

@@ -237,6 +237,7 @@ namespace TEAMModelOS.SDK.Models.Service
                                 art.tchLists.ForEach(x => { grouplist.Add(x); });
                             }
                             evaluationSyncInfo.grouplist=grouplist.Select(x => new EvaluationGroupListDto { id = x }).ToList();
+                            evaluationSyncInfo.examDeadline=art.examDeadline;
                             evaluationSource.art=art;
                             dataTime= art._ts*1000;
                             stime=art.startTime;
@@ -502,6 +503,9 @@ namespace TEAMModelOS.SDK.Models.Service
                     ownerPicture =evaluationSyncInfo.ownerPicture,
                     ownerName = evaluationSyncInfo.ownerName,
                     music = evaluationSyncInfo.music,
+                    reanswer = evaluationSyncInfo.reanswer,
+                    examDeadline = evaluationSyncInfo.examDeadline,
+
                     //password = evaluationSyncInfo.password,
                     //recordUrl = evaluationSyncInfo.recordUrl
                 };

+ 0 - 113
TEAMModelOS/Properties/ServiceDependencies/teammodelos-yx - Web Deploy/profile.arm.json

@@ -1,113 +0,0 @@
-{
-  "$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
-  "contentVersion": "1.0.0.0",
-  "metadata": {
-    "_dependencyType": "compute.appService.windows"
-  },
-  "parameters": {
-    "resourceGroupName": {
-      "type": "string",
-      "defaultValue": "TEAMModelChengdu",
-      "metadata": {
-        "description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking."
-      }
-    },
-    "resourceGroupLocation": {
-      "type": "string",
-      "defaultValue": "",
-      "metadata": {
-        "description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support."
-      }
-    },
-    "resourceName": {
-      "type": "string",
-      "defaultValue": "yx",
-      "metadata": {
-        "description": "Name of the main resource to be created by this template."
-      }
-    },
-    "resourceLocation": {
-      "type": "string",
-      "defaultValue": "[parameters('resourceGroupLocation')]",
-      "metadata": {
-        "description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there."
-      }
-    }
-  },
-  "variables": {
-    "appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]",
-    "appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]"
-  },
-  "resources": [
-    {
-      "type": "Microsoft.Resources/resourceGroups",
-      "name": "[parameters('resourceGroupName')]",
-      "location": "[parameters('resourceGroupLocation')]",
-      "apiVersion": "2019-10-01"
-    },
-    {
-      "type": "Microsoft.Resources/deployments",
-      "name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]",
-      "resourceGroup": "[parameters('resourceGroupName')]",
-      "apiVersion": "2019-10-01",
-      "dependsOn": [
-        "[parameters('resourceGroupName')]"
-      ],
-      "properties": {
-        "mode": "Incremental",
-        "template": {
-          "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
-          "contentVersion": "1.0.0.0",
-          "resources": [
-            {
-              "location": "[parameters('resourceLocation')]",
-              "name": "[parameters('resourceName')]",
-              "type": "Microsoft.Web/sites",
-              "apiVersion": "2015-08-01",
-              "tags": {
-                "[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty"
-              },
-              "dependsOn": [
-                "[variables('appServicePlan_ResourceId')]"
-              ],
-              "kind": "app",
-              "properties": {
-                "name": "[parameters('resourceName')]",
-                "kind": "app",
-                "httpsOnly": true,
-                "reserved": false,
-                "serverFarmId": "[variables('appServicePlan_ResourceId')]",
-                "siteConfig": {
-                  "metadata": [
-                    {
-                      "name": "CURRENT_STACK",
-                      "value": "dotnetcore"
-                    }
-                  ]
-                }
-              },
-              "identity": {
-                "type": "SystemAssigned"
-              }
-            },
-            {
-              "location": "[parameters('resourceLocation')]",
-              "name": "[variables('appServicePlan_name')]",
-              "type": "Microsoft.Web/serverFarms",
-              "apiVersion": "2015-08-01",
-              "sku": {
-                "name": "S1",
-                "tier": "Standard",
-                "family": "S",
-                "size": "S1"
-              },
-              "properties": {
-                "name": "[variables('appServicePlan_name')]"
-              }
-            }
-          ]
-        }
-      }
-    }
-  ]
-}