CrazyIter_Bin hai 3 meses
pai
achega
6833c17c51

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

@@ -168,6 +168,10 @@ namespace IES.ExamServer.Models
         /// 截至时间,countdownType=1 时有值
         /// </summary>
         public long deadline {  get; set; }
+        /// <summary>
+        /// 开考时间
+        /// </summary>
+        public long startline { get; set; }
 
     }
     public class SubjectExam

+ 65 - 22
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/ManageController.cs

@@ -64,14 +64,14 @@ namespace IES.ExamServer.Controllers
             //下载日志记录:1.步骤,检查,2.获取描述信息,3.分类型,4下载文件,5.前端处理,6.返回结果 , 正在下载...==> [INFO]https://www.doubao.com/chat/collection/687687510791426?type=Thread [Size=180kb] Ok...
             //进度条 展示下载文件总大小和已下载,末尾展示 文件总个数和已下载个数
             //https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.7/signalr.min.js
-            /* int data = 0,blob=0,webview=0, groupList=0
+            /* int data = 0,blob=0, groupList=0
              {
                 "evaluationId":"idssss",
                 "shortCode":"1234567890",
                 "ownerId":"hbcn/tmdid",
                 "data":1,
                 "blob":1,
-                "webview":1,
+              
                 "groupList":1
             }
              */
@@ -119,10 +119,7 @@ namespace IES.ExamServer.Controllers
                         {
                             await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/paper");
                         }
-                        if ($"{json["webview"]}".Equals("1"))
-                        {
-                            //await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/evaluation.json");
-                        }
+                       //下载完成后,对数据进行检查,然后在加密压缩。
                     }
                 }
             }
@@ -132,7 +129,7 @@ namespace IES.ExamServer.Controllers
         [AuthToken("admin", "teacher", "visitor")]
         public async Task<IActionResult> CheckEvaluation(JsonNode json)
         {
-            string shortCode = $"{json["shortCode"]}";
+            string shortCode = $"{json["c"]}";
             string evaluationId = $"{json["evaluationId"]}";
             string checkCenter = $"{json["checkCenter"]}";
             string deviceId = $"{json["deviceId"]}";
@@ -314,15 +311,43 @@ namespace IES.ExamServer.Controllers
 
                 //校验本地文件数据
                 string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
+                string zipPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "zip");
                 if (!Directory.Exists(packagePath))
                 {
                     Directory.CreateDirectory(packagePath);
                 }
+                //判断文件包的压缩包是否存在。
+                if (!System.IO.File.Exists(Path.Combine(zipPath, $"{evaluationLocal.id}-{evaluationLocal}.zip")))
+                {
+                    blob=1;//压缩包不存在
+                    msg_status=Constant._Message_status_error;
+                    checkTotal++;
+                    checkError++;
+                }
+                else
+                {
+                    msg_status=Constant._Message_status_success;
+                    checkTotal++;
+                    checkSuccess++;
+                    //解压操作。
+                   var extractRes=  ZipHelper.ExtractPasswordProtectedZip(Path.Combine(zipPath, $"{evaluationLocal.id}-{evaluationLocal}.zip"), packagePath, evaluationLocal.openCode!);
+                    if (extractRes.res)
+                    {
+                        checkTotal++;
+                        checkSuccess++;
+                    }
+                    else
+                    {
+                        blob=1;//压缩包错误
+                        msg_status=Constant._Message_status_error;
+                        checkTotal++;
+                        checkError++;
+                    }
+                }
+
                 string evaluationPath = Path.Combine(packagePath, evaluationLocal.id!);
                 string evaluationDataPath = Path.Combine(evaluationPath, "data");
-                // await Task.Delay(DelayMacro);
-
-                //await Task.Delay(DelayMacro);
+                
                 string path_groupList = Path.Combine(evaluationDataPath, "groupList.json");
                 msg_status =Constant._Message_status_info;
                 if (!System.IO.File.Exists(path_groupList))
@@ -591,8 +616,17 @@ namespace IES.ExamServer.Controllers
                 checkWarning,
             });
         }
-
-
+        /// <summary>
+        /// 设置评测开考信息(本轮名单,)
+        /// </summary>
+        /// <param name="json"></param>
+        /// <returns></returns>
+        [HttpPost("setting-evaluation")]
+        [AuthToken("admin", "teacher", "visitor")]
+        public IActionResult SettingEvaluation(JsonNode json) 
+        {
+            return Ok();
+        }
 
         /// <summary>
         /// 激活或者取消激活考试
@@ -604,31 +638,40 @@ namespace IES.ExamServer.Controllers
         public IActionResult ActivateEvaluation(JsonNode json)
         {
             string id = $"{json["id"]}";
-            string shortCode = $"{json["shortCode"]}";
+            string openCode = $"{json["openCode"]}";
             string activateStr = $"{json["activate"]}";
-            if (!string.IsNullOrWhiteSpace(id) && !string.IsNullOrWhiteSpace(shortCode)) 
+            if (!string.IsNullOrWhiteSpace(id) && !string.IsNullOrWhiteSpace(openCode))
             {
-                EvaluationClient? evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindOne(x => x.id!.Equals(id) && !string.IsNullOrWhiteSpace(x.shortCode) && x.shortCode.Equals(shortCode));
+                EvaluationClient? evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindOne(x => x.id!.Equals(id) && !string.IsNullOrWhiteSpace(x.openCode) && x.openCode.Equals(openCode));
                 if (evaluationClient != null)
                 {
-                    IEnumerable<EvaluationClient> evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Find(x=>x.activate==1);
-                    if (evaluationClients != null && evaluationClients.Count() > 0) 
+                    IEnumerable<EvaluationClient> evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Find(x => x.activate==1);
+                    if (evaluationClients != null && evaluationClients.Count() > 0)
                     {
-                        foreach(EvaluationClient item in evaluationClients)
+                        foreach (EvaluationClient item in evaluationClients)
                         {
                             item.activate = 0;
                             _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Upsert(item);
                         }
                     }
                     int activate = 0;
-                    if (int.TryParse(activateStr, out int _activate)) {
+                    if (int.TryParse(activateStr, out int _activate))
+                    {
                         activate = _activate;
                     }
                     evaluationClient.activate = activate;
                     _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Upsert(evaluationClient);
+                    return Ok(new { code = 200, msg = "操作成功!" });
+                }
+                else
+                {
+                    return Ok(new { code = 400, msg = "未找到匹配的评测!" });
                 }
             }
-            return Ok();
+            else {
+                return Ok(new { code = 400, msg = "参数错误!" });
+            }
+           
         }
         /// <summary>
         /// 加载本地的活动列表
@@ -650,7 +693,7 @@ namespace IES.ExamServer.Controllers
                     var anonymousObject = new Dictionary<string, object?>();
                     foreach (var property in properties)
                     {
-                        if (!property.Name.Equals("password") && !property.Name.Equals("openCode"))
+                        if (!property.Name.Equals("openCode"))
                         {
                             anonymousObject[property.Name] = property.GetValue(client);
                         }
@@ -660,7 +703,7 @@ namespace IES.ExamServer.Controllers
                 return Ok(new { code = 200, evaluation = result });
             }
             else {
-                return Ok(new { code = 200, evaluation = new Dictionary<string, object?>() });
+                return Ok(new { code = 200, evaluation = new List<EvaluationClient>  ()});
             }
             
         }

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

@@ -1,6 +1,106 @@
-namespace IES.ExamServer.Controllers
+using IES.ExamServer.DI;
+using IES.ExamServer.Models;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Caching.Memory;
+using Microsoft.Extensions.Hosting;
+using System.Text.Json.Nodes;
+
+namespace IES.ExamServer.Controllers
 {
-    public class StudentController
+    [ApiController]
+    [Route("student")]
+    public class StudentController : BaseController
     {
+        private readonly IConfiguration _configuration;
+        private readonly IHttpClientFactory _httpClientFactory;
+        private readonly IMemoryCache _memoryCache;
+        private readonly ILogger<IndexController> _logger;
+        private readonly CenterServiceConnectionService _connectionService;
+        private readonly LiteDBFactory _liteDBFactory;
+        public StudentController(ILogger<IndexController> logger, IConfiguration configuration, IHttpClientFactory httpClientFactory,
+         IMemoryCache memoryCache, CenterServiceConnectionService connectionService, LiteDBFactory liteDBFactory)
+        {
+            _logger = logger;
+            _configuration=configuration;
+            _httpClientFactory=httpClientFactory;
+            _memoryCache=memoryCache;
+            _connectionService=connectionService;
+            _liteDBFactory=liteDBFactory;
+        }
+        [HttpPost("get-activate-evaluation")]
+        public async Task<IActionResult> GetActivateEvaluation(JsonNode json) 
+        {
+            //  _connectionService.serverDevice.school.id?
+
+            try
+            {
+                IEnumerable<EvaluationClient>? evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Find(x =>x.activate==1 );
+                if (evaluationClients != null && evaluationClients.Count() > 0) 
+                {
+                    if (evaluationClients.Count()>1)
+                    {
+                        msg="有多个正在开考的评测,请监考教师重新设置开考评测。";
+                        code=2;
+                    }
+                    else 
+                    {
+                        EvaluationClient evaluationClient = evaluationClients.First();
+                        if (evaluationClient.scope!.Equals("school") ) 
+                        {
+                            if (!evaluationClient!.ownerId!.Equals($"{_connectionService.serverDevice?.school?.id}")) 
+                            {
+                                msg="授权学校与评测归属学校不一致。";
+                                code=3;
+                            }
+                        }
+                        //当前时间
+                        long now = DateTimeOffset.Now.ToUnixTimeMilliseconds();
+                        if (evaluationClient.countdownType>0)
+                        {
+                            if (evaluationClient.startline>now || evaluationClient.stime>now)
+                            {
+                                msg="评测暂未开始。";
+                                code=4;
+                            }
+                            if ((evaluationClient.deadline>0 && evaluationClient.deadline<now)|| evaluationClient.etime<now)
+                            {
+                                msg="评测已经结束。";
+                                code=5;
+                            }
+                        }
+                        else {
+                            if (evaluationClient.stime>now)
+                            {
+                                msg="评测暂未开始。";
+                                code=4;
+                            }
+                            if (evaluationClient.etime<now)
+                            {
+                                msg="评测已经结束。";
+                                code=5;
+                            }
+                        }
+                        var anonymousObject = new Dictionary<string, object?>();
+                        var properties = evaluationClient.GetType().GetProperties();
+                        foreach (var property in properties)
+                        {
+                            if (!property.Name.Equals("shortCode") && !property.Name.Equals("openCode"))
+                            {
+                                anonymousObject[property.Name] = property.GetValue(evaluationClient);
+                            }
+                        }
+                        return Ok(new { evaluationClient = anonymousObject,code =code,msg=msg});
+                    }
+                }
+                else
+                {
+                    msg="暂无正在开考的评测";
+                    code=1;
+                }
+            }
+            catch (Exception ex) { }
+            return Ok();
+        }
+
     }
 }

+ 170 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/ZipHelper.cs

@@ -0,0 +1,170 @@
+
+using System;
+using System.IO;
+using ICSharpCode.SharpZipLib.Zip;
+using ICSharpCode.SharpZipLib.Core;
+namespace IES.ExamServer.Helpers
+{
+    public static class ZipHelper
+    {
+        /*
+        static void Main(string[] args)
+        {
+            string sourceDirectory = "path/to/your/source/directory";
+            string zipFilePath = "protected.zip";
+            string extractPath = "path/to/extract/folder";
+            string password = "yourpassword";
+
+            // 创建带密码的 ZIP 文件
+            bool zipResult = ZipHelper.CreatePasswordProtectedZip(sourceDirectory, zipFilePath, password);
+            if (zipResult)
+            {
+                Console.WriteLine("压缩成功!");
+            }
+            else
+            {
+                Console.WriteLine("压缩失败!");
+            }
+
+            // 解压带密码的 ZIP 文件
+            bool extractResult = ZipHelper.ExtractPasswordProtectedZip(zipFilePath, extractPath, password);
+            if (extractResult)
+            {
+                Console.WriteLine("解压成功!");
+            }
+            else
+            {
+                Console.WriteLine("解压失败!");
+            }
+        }
+        */
+
+        /// <summary>
+        /// 创建带密码的 ZIP 文件
+        /// </summary>
+        /// <param name="sourceDirectory">要压缩的目录路径</param>
+        /// <param name="zipFilePath">生成的 ZIP 文件路径</param>
+        /// <param name="password">ZIP 文件密码</param>
+        /// <returns>是否成功</returns>
+        public static bool CreatePasswordProtectedZip(string sourceDirectory, string zipFilePath, string password)
+        {
+            if (!Directory.Exists(sourceDirectory))
+            {
+                Console.WriteLine("源目录不存在。");
+                return false;
+            }
+
+            try
+            {
+                using (FileStream fsOut = File.Create(zipFilePath))
+                using (ZipOutputStream zipStream = new ZipOutputStream(fsOut))
+                {
+                    zipStream.SetLevel(9); // 设置压缩级别 (0-9)
+                    zipStream.Password = password; // 设置密码
+
+                    CompressFolder(sourceDirectory, zipStream, "");
+                }
+
+                Console.WriteLine($"ZIP 文件已成功创建:{zipFilePath}");
+                return true;
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"创建 ZIP 文件时发生错误:{ex.Message}");
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// 解压带密码的 ZIP 文件
+        /// </summary>
+        /// <param name="zipFilePath">ZIP 文件路径</param>
+        /// <param name="extractPath">解压目标目录</param>
+        /// <param name="password">ZIP 文件密码</param>
+        /// <returns>是否成功</returns>
+        public static (bool res,string msg) ExtractPasswordProtectedZip(string zipFilePath, string extractPath, string password)
+        {
+            if (!File.Exists(zipFilePath))
+            {
+                return (false, "ZIP 文件不存在。");
+            }
+            try
+            {
+                using (ZipInputStream zipInputStream = new ZipInputStream(File.OpenRead(zipFilePath)))
+                {
+                    zipInputStream.Password = password; // 设置解压密码
+
+                    ZipEntry entry;
+                    while ((entry = zipInputStream.GetNextEntry()) != null)
+                    {
+                        string entryFileName = entry.Name;
+                        string fullPath = Path.Combine(extractPath, entryFileName);
+
+                        // 创建目录(如果条目是目录)
+                        string? directoryName = Path.GetDirectoryName(fullPath);
+                        if (!string.IsNullOrEmpty(directoryName) && !Directory.Exists(directoryName))
+                        {
+                            Directory.CreateDirectory(directoryName);
+                        }
+
+                        // 如果是文件,则解压文件
+                        if (!entry.IsDirectory)
+                        {
+                            using (FileStream streamWriter = File.Create(fullPath))
+                            {
+                                byte[] buffer = new byte[4096];
+                                int bytesRead;
+                                while ((bytesRead = zipInputStream.Read(buffer, 0, buffer.Length)) > 0)
+                                {
+                                    streamWriter.Write(buffer, 0, bytesRead);
+                                }
+                            }
+                        }
+                    }
+                }
+
+                return  (true, $"ZIP 文件已成功解压到:{extractPath}");
+            }
+            catch (Exception ex)
+            {
+                return (false, $"解压 ZIP 文件时发生错误:{ex.Message}");
+            }
+        }
+
+        /// <summary>
+        /// 递归压缩文件夹
+        /// </summary>
+        private static void CompressFolder(string path, ZipOutputStream zipStream, string folderName)
+        {
+            foreach (string file in Directory.GetFiles(path))
+            {
+                string fileName = Path.GetFileName(file);
+                string relativePath = Path.Combine(folderName, fileName);
+
+                ZipEntry entry = new ZipEntry(relativePath);
+                entry.DateTime = DateTime.Now;
+                zipStream.PutNextEntry(entry);
+
+                using (FileStream fs = File.OpenRead(file))
+                {
+                    byte[] buffer = new byte[4096];
+                    int bytesRead;
+                    while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
+                    {
+                        zipStream.Write(buffer, 0, bytesRead);
+                    }
+                }
+
+                zipStream.CloseEntry();
+            }
+
+            // 递归处理子目录
+            foreach (string folder in Directory.GetDirectories(path))
+            {
+                string folderNameOnly = Path.GetFileName(folder);
+                string newFolderName = Path.Combine(folderName, folderNameOnly);
+                CompressFolder(folder, zipStream, newFolderName);
+            }
+        }
+    }
+}

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

@@ -22,6 +22,7 @@
 	<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="6.0.36" />
 	<PackageReference Include="NLog" Version="5.3.4" />
 	<PackageReference Include="NLog.Extensions.Logging" Version="5.3.15" />
+	<PackageReference Include="SharpZipLib" Version="1.4.2" />
 	<PackageReference Include="SkiaSharp.QrCode" Version="0.7.0" />
 	<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.3.0" />
 	<PackageReference Include="System.Management" Version="6.0.2" />