|
@@ -0,0 +1,651 @@
|
|
|
|
+using IES.ExamLib.Models;
|
|
|
|
+using IES.ExamServer.DI;
|
|
|
|
+using IES.ExamServer.DI.SignalRHost;
|
|
|
|
+using IES.ExamServer.Filters;
|
|
|
|
+using IES.ExamServer.Helper;
|
|
|
|
+using IES.ExamServer.Helpers;
|
|
|
|
+using IES.ExamServer.Models;
|
|
|
|
+using Microsoft.AspNetCore.Mvc;
|
|
|
|
+using Microsoft.AspNetCore.SignalR;
|
|
|
|
+using Microsoft.Extensions.Caching.Memory;
|
|
|
|
+using Microsoft.Extensions.Configuration;
|
|
|
|
+using System.Linq.Expressions;
|
|
|
|
+using System.Net.Http;
|
|
|
|
+using System.Net.Http.Json;
|
|
|
|
+using System.Text.Json;
|
|
|
|
+using System.Text.Json.Nodes;
|
|
|
|
+
|
|
|
|
+namespace IES.ExamServer.Controllers
|
|
|
|
+{
|
|
|
|
+ [ApiController]
|
|
|
|
+ [Route("manage")]
|
|
|
|
+ public class ManageController:BaseController
|
|
|
|
+ {
|
|
|
|
+ private readonly IConfiguration _configuration;
|
|
|
|
+ private readonly IHttpClientFactory _httpClientFactory;
|
|
|
|
+ private readonly IMemoryCache _memoryCache;
|
|
|
|
+ private readonly ILogger<ManageController> _logger;
|
|
|
|
+ private readonly LiteDBFactory _liteDBFactory;
|
|
|
|
+ private readonly CenterServiceConnectionService _connectionService;
|
|
|
|
+ private readonly int DelayMicro = 10;//微观数据延迟
|
|
|
|
+ private readonly int DelayMacro = 100;//宏观数据延迟
|
|
|
|
+ private readonly IHubContext<SignalRExamServerHub> _signalRExamServerHub;
|
|
|
|
+ public ManageController(LiteDBFactory liteDBFactory,ILogger<ManageController> logger, IConfiguration configuration,
|
|
|
|
+ IHttpClientFactory httpClientFactory, IMemoryCache memoryCache, CenterServiceConnectionService connectionService, IHubContext<SignalRExamServerHub> signalRExamServerHub)
|
|
|
|
+ {
|
|
|
|
+ _logger = logger;
|
|
|
|
+ _configuration=configuration;
|
|
|
|
+ _httpClientFactory=httpClientFactory;
|
|
|
|
+ _memoryCache=memoryCache;
|
|
|
|
+ _liteDBFactory=liteDBFactory;
|
|
|
|
+ _connectionService=connectionService;
|
|
|
|
+ _signalRExamServerHub=signalRExamServerHub;
|
|
|
|
+ }
|
|
|
|
+ ///通过线上回传数据需要鉴权验证等操作。
|
|
|
|
+ ///通过离线包回传数据需要加密操作
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 清理缓存,列出缓存占用空间,type =list列出,type=clear清理,不能清理近期及正在激活的数据,并且提示清理中暂未上传或者导出的数据。
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="json"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ [HttpPost("clean-cache")]
|
|
|
|
+ [AuthToken("admin", "teacher", "visitor")]
|
|
|
|
+ public async Task<IActionResult> CleanCache(JsonNode json)
|
|
|
|
+ {
|
|
|
|
+ return Ok();
|
|
|
|
+ }
|
|
|
|
+ [HttpPost("download-package")]
|
|
|
|
+ [AuthToken("admin","teacher")]
|
|
|
|
+ public async Task<IActionResult> DownloadPackage(JsonNode json)
|
|
|
|
+ {
|
|
|
|
+ //C#.NET 6 后端与前端流式通信
|
|
|
|
+ //https://www.doubao.com/chat/collection/687687510791426?type=Thread
|
|
|
|
+ //下载日志记录: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
|
|
|
|
+ {
|
|
|
|
+ "evaluationId":"idssss",
|
|
|
|
+ "shortCode":"1234567890",
|
|
|
|
+ "ownerId":"hbcn/tmdid",
|
|
|
|
+ "data":1,
|
|
|
|
+ "blob":1,
|
|
|
|
+ "webview":1,
|
|
|
|
+ "groupList":1
|
|
|
|
+ }
|
|
|
|
+ */
|
|
|
|
+ //如果要访问中心,则需要教师登录联网。
|
|
|
|
+ var token = GetAuthTokenInfo();
|
|
|
|
+ if (token.scope.Equals(ExamConstant.ScopeTeacher))
|
|
|
|
+ {
|
|
|
|
+ if (_connectionService.centerIsConnected)
|
|
|
|
+ {
|
|
|
|
+ Teacher? teacher = _liteDBFactory.GetLiteDatabase().GetCollection<Teacher>().FindOne(x => x.id!.Equals(token.id));
|
|
|
|
+ if (teacher != null)
|
|
|
|
+ {
|
|
|
|
+ string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
|
|
|
|
+ var client = _httpClientFactory.CreateClient();
|
|
|
|
+ if (client.DefaultRequestHeaders.Contains(Constant._X_Auth_AuthToken))
|
|
|
|
+ {
|
|
|
|
+ client.DefaultRequestHeaders.Remove(Constant._X_Auth_AuthToken);
|
|
|
|
+ }
|
|
|
|
+ client.DefaultRequestHeaders.Add(Constant._X_Auth_AuthToken, teacher.x_auth_token);
|
|
|
|
+ HttpResponseMessage message = await client.PostAsJsonAsync($"{CenterUrl}/blob/sas-read", new { containerName = $"{json["ownerId"]}" });
|
|
|
|
+ string sas = string.Empty;
|
|
|
|
+ string url = string.Empty;
|
|
|
|
+ string cnt = string.Empty;
|
|
|
|
+ if (message.IsSuccessStatusCode)
|
|
|
|
+ {
|
|
|
|
+ //url sas timeout name
|
|
|
|
+ string content = await message.Content.ReadAsStringAsync();
|
|
|
|
+ JsonNode? jsonNode = content.ToObject<JsonNode>();
|
|
|
|
+ if (jsonNode != null)
|
|
|
|
+ {
|
|
|
|
+ sas = $"{jsonNode["sas"]}";
|
|
|
|
+ cnt = $"{jsonNode["name"]}";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ var httpClient= _httpClientFactory.CreateClient();
|
|
|
|
+ if ($"{json["data"]}".Equals("1"))
|
|
|
|
+ {
|
|
|
|
+ await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/package/evaluation.json");
|
|
|
|
+ }
|
|
|
|
+ if ($"{json["groupList"]}".Equals("1"))
|
|
|
|
+ {
|
|
|
|
+ await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/package/grouplist.json");
|
|
|
|
+ }
|
|
|
|
+ if ($"{json["blob"]}".Equals("1"))
|
|
|
|
+ {
|
|
|
|
+ await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/paper");
|
|
|
|
+ }
|
|
|
|
+ if ($"{json["webview"]}".Equals("1"))
|
|
|
|
+ {
|
|
|
|
+ //await httpClient.GetAsync($"{url}/{cnt}/exam/{json["evaluationId"]}/evaluation.json");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return Ok();
|
|
|
|
+ }
|
|
|
|
+ [HttpPost("check-short-code")]
|
|
|
|
+ [AuthToken("admin", "teacher", "visitor")]
|
|
|
|
+ public async Task<IActionResult> CheckShortCode(JsonNode json)
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ string shortCode = $"{json["shortCode"]}";
|
|
|
|
+ string evaluationId = $"{json["evaluationId"]}";
|
|
|
|
+ string deviceId = $"{json["deviceId"]}";
|
|
|
|
+ string centerCode= string.Empty, centerMsg= string.Empty;
|
|
|
|
+ Expression<Func<EvaluationClient, bool>> predicate = x => true;
|
|
|
|
+ int checkTotal = 0, checkSuccess = 0, checkError = 0, checkWarning = 0;
|
|
|
|
+ int msg_status = Constant._Message_status_info;
|
|
|
|
+ if (!string.IsNullOrEmpty(shortCode))
|
|
|
|
+ {
|
|
|
|
+ var codePredicate = ExpressionHelper.Or<EvaluationClient>(
|
|
|
|
+ x => !string.IsNullOrWhiteSpace(x.shortCode) && x.shortCode == shortCode,
|
|
|
|
+ x => !string.IsNullOrWhiteSpace(x.password) && x.password == shortCode
|
|
|
|
+ );
|
|
|
|
+ predicate= predicate.And(codePredicate);
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ return Ok(new { code = 400,msg="必须输入开卷码" });
|
|
|
|
+ }
|
|
|
|
+ if (!string.IsNullOrWhiteSpace(evaluationId))
|
|
|
|
+ {
|
|
|
|
+ predicate= predicate.And(x => x.id!.Equals(evaluationId));
|
|
|
|
+ }
|
|
|
|
+ IEnumerable<EvaluationClient>? evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Find(predicate);
|
|
|
|
+ EvaluationClient? evaluationLocal = null;
|
|
|
|
+ EvaluationClient? evaluationCloud = null;
|
|
|
|
+ if (evaluationClients!=null && evaluationClients.Count()>0)
|
|
|
|
+ {
|
|
|
|
+ evaluationLocal= evaluationClients.First();
|
|
|
|
+ }
|
|
|
|
+ //如果要访问中心,则需要教师登录联网。
|
|
|
|
+ var token = GetAuthTokenInfo();
|
|
|
|
+ if (token.scope.Equals(ExamConstant.ScopeTeacher))
|
|
|
|
+ {
|
|
|
|
+ if (_connectionService.centerIsConnected)
|
|
|
|
+ {
|
|
|
|
+ Teacher? teacher = _liteDBFactory.GetLiteDatabase().GetCollection<Teacher>().FindOne(x => x.id!.Equals(token.id));
|
|
|
|
+ if (teacher != null)
|
|
|
|
+ {
|
|
|
|
+ string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
|
|
|
|
+ var client = _httpClientFactory.CreateClient();
|
|
|
|
+ if (client.DefaultRequestHeaders.Contains(Constant._X_Auth_AuthToken))
|
|
|
|
+ {
|
|
|
|
+ client.DefaultRequestHeaders.Remove(Constant._X_Auth_AuthToken);
|
|
|
|
+ }
|
|
|
|
+ client.DefaultRequestHeaders.Add(Constant._X_Auth_AuthToken, teacher.x_auth_token);
|
|
|
|
+ try {
|
|
|
|
+ HttpResponseMessage message = await client.PostAsJsonAsync($"{CenterUrl}/evaluation-sync/find-sync-info", new { shortCode, evaluationId });
|
|
|
|
+ if (message.IsSuccessStatusCode)
|
|
|
|
+ {
|
|
|
|
+ string content = await message.Content.ReadAsStringAsync();
|
|
|
|
+ JsonNode? jsonNode = content.ToObject<JsonNode>();
|
|
|
|
+ if (jsonNode != null)
|
|
|
|
+ {
|
|
|
|
+ centerCode = $"{jsonNode["code"]}";
|
|
|
|
+ centerMsg = $"{jsonNode["msg"]}";
|
|
|
|
+ if ($"{jsonNode["code"]}".Equals("200"))
|
|
|
|
+ {
|
|
|
|
+ evaluationCloud = jsonNode["evaluation"]?.ToObject<EvaluationClient>();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ centerCode = "500";
|
|
|
|
+ centerMsg = "数据转换异常";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ centerCode = $"{message.StatusCode}";
|
|
|
|
+ centerMsg = "数据中心访问异常";
|
|
|
|
+ }
|
|
|
|
+ } catch (Exception ex) {
|
|
|
|
+ centerCode = $"500";
|
|
|
|
+ centerMsg = $"数据中心访问异常:{ex.Message}";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ centerCode = $"401";
|
|
|
|
+ centerMsg = "当前登录账号未找到";
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ centerCode = $"404";
|
|
|
|
+ centerMsg = "云端数据中心未连接";
|
|
|
|
+ }
|
|
|
|
+ if (centerCode.Equals("200"))
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_success;
|
|
|
|
+ checkTotal++;
|
|
|
|
+ checkSuccess++;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_warning;
|
|
|
|
+ checkTotal++;
|
|
|
|
+ checkWarning++;
|
|
|
|
+ }
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent { dataId=evaluationCloud?.id, dataName=evaluationCloud?.name, messageType=Constant._Message_type_message, status=msg_status, content=$"云端数据检测结果:{centerMsg},状态:{centerCode}" });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //数据,文件,页面 0 没有更新,1 有更新
|
|
|
|
+ int data = 0,blob=0,webview=0, groupList=0, status=0;
|
|
|
|
+ long dataSize = 0, blobSize=0 , webviewSize=0, studentCount=0;
|
|
|
|
+ if (evaluationLocal== null && evaluationCloud==null)
|
|
|
|
+ {
|
|
|
|
+ //线上线下没有数据
|
|
|
|
+ status=1;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ else if (evaluationLocal!=null && evaluationCloud!=null)
|
|
|
|
+ {
|
|
|
|
+ //线上线下有数据
|
|
|
|
+ status = 2;
|
|
|
|
+ if ((!string.IsNullOrWhiteSpace(evaluationLocal.blobHash) && !evaluationLocal.blobHash.Equals(evaluationCloud.blobHash))
|
|
|
|
+ ||(evaluationLocal.blobTime<evaluationCloud.blobTime)
|
|
|
|
+ ||(evaluationLocal.blobCount!= evaluationCloud.blobCount)
|
|
|
|
+ ||(evaluationLocal.blobSize!= evaluationCloud.blobSize))
|
|
|
|
+ {
|
|
|
|
+ blob=1;
|
|
|
|
+ blobSize=evaluationCloud.blobSize;
|
|
|
|
+ }
|
|
|
|
+ if ((evaluationLocal.dataTime<evaluationCloud.dataTime)
|
|
|
|
+ ||(evaluationLocal.dataSize!=evaluationCloud.dataSize)
|
|
|
|
+ ||(evaluationLocal.paperCount!= evaluationCloud.paperCount)
|
|
|
|
+ )
|
|
|
|
+ {
|
|
|
|
+ data=1;
|
|
|
|
+ dataSize=evaluationCloud.dataSize;
|
|
|
|
+ }
|
|
|
|
+ if ((evaluationLocal.webviewCount!=evaluationCloud.webviewCount)
|
|
|
|
+ ||(evaluationLocal.webviewSize!= evaluationCloud.webviewSize)
|
|
|
|
+ ||(evaluationLocal.webviewTime!= evaluationCloud.webviewTime)
|
|
|
|
+ ||(!string.IsNullOrWhiteSpace(evaluationLocal.webviewPath)&& !evaluationLocal.webviewPath.Equals(evaluationCloud.webviewPath)))
|
|
|
|
+ {
|
|
|
|
+ webview=1;
|
|
|
|
+ webviewSize=evaluationCloud.webviewSize;
|
|
|
|
+ }
|
|
|
|
+ if ((evaluationLocal.studentCount!= evaluationCloud.studentCount)||(!$"{evaluationLocal.grouplistHash}".Equals(evaluationCloud.grouplistHash)))
|
|
|
|
+ {
|
|
|
|
+ groupList=1;
|
|
|
|
+ studentCount=evaluationCloud.studentCount;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ else if (evaluationLocal!=null && evaluationCloud==null)
|
|
|
|
+ {
|
|
|
|
+ //线下有数据,线上没有数据,可能没联网。
|
|
|
|
+ status = 3;
|
|
|
|
+ }
|
|
|
|
+ else if (evaluationLocal==null && evaluationCloud!=null)
|
|
|
|
+ {
|
|
|
|
+ //线下没有数据,线上有数据
|
|
|
|
+ evaluationLocal= evaluationCloud;
|
|
|
|
+ blob=1;
|
|
|
|
+ data=1;
|
|
|
|
+ webview=1;
|
|
|
|
+ groupList=1;
|
|
|
|
+ blobSize=evaluationCloud.blobSize;
|
|
|
|
+ dataSize=evaluationCloud.dataSize;
|
|
|
|
+ webviewSize=evaluationCloud.webviewSize;
|
|
|
|
+ studentCount=evaluationCloud.studentCount;
|
|
|
|
+ status = 4;
|
|
|
|
+ _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Insert(evaluationLocal);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (evaluationLocal!=null)
|
|
|
|
+ {
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent {dataId=evaluationLocal.id,dataName=evaluationLocal.name,messageType=Constant._Message_type_message, status=0, content="开始检查评测信息文件.." });
|
|
|
|
+
|
|
|
|
+ //校验本地文件数据
|
|
|
|
+ string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
|
|
|
|
+ if (!Directory.Exists(packagePath))
|
|
|
|
+ {
|
|
|
|
+ Directory.CreateDirectory(packagePath);
|
|
|
|
+ }
|
|
|
|
+ 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))
|
|
|
|
+ {
|
|
|
|
+ groupList=1;
|
|
|
|
+ msg_status=Constant._Message_status_error;
|
|
|
|
+ checkTotal++;
|
|
|
|
+ checkError++;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_success;
|
|
|
|
+ checkTotal++;
|
|
|
|
+ checkSuccess++;
|
|
|
|
+ }
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content=$"评测名单文件:{path_groupList}" });
|
|
|
|
+ //await Task.Delay(DelayMacro);
|
|
|
|
+ string path_source = Path.Combine(evaluationDataPath, "source.json");
|
|
|
|
+ msg_status = Constant._Message_status_info;
|
|
|
|
+ if (!System.IO.File.Exists(path_source))
|
|
|
|
+ {
|
|
|
|
+ data=1;
|
|
|
|
+ msg_status=Constant._Message_status_error;
|
|
|
|
+ checkTotal++;
|
|
|
|
+ checkError++;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_success;
|
|
|
|
+ checkTotal++;
|
|
|
|
+ checkSuccess++;
|
|
|
|
+ }
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content=$"评测原始数据:{path_source}" });
|
|
|
|
+ msg_status =Constant._Message_status_info;
|
|
|
|
+ try {
|
|
|
|
+ //TODO 重整本地文件路径。 文件可能不存在D:\VisualStudioProjects\TEAMModelOS\TEAMModelOS.Extension\IES.Exam\IES.ExamServer\wwwroot\package\exam\6af32bbd-144e-4366-8bc0-61ba4c85677c\evaluation.json
|
|
|
|
+ string path_evaluation = Path.Combine(evaluationDataPath, "evaluation.json");
|
|
|
|
+ if (!System.IO.File.Exists(path_evaluation))
|
|
|
|
+ {
|
|
|
|
+ blob=1;
|
|
|
|
+ data=1;
|
|
|
|
+ msg_status=Constant._Message_status_error;
|
|
|
|
+ checkTotal++;
|
|
|
|
+ checkError++;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_success;
|
|
|
|
+ checkTotal++;
|
|
|
|
+ checkSuccess++;
|
|
|
|
+ }
|
|
|
|
+ //数据格式: [消息][信息/错误/警告][15:43]=>[开始检查评测信息文件...]
|
|
|
|
+ //数据格式: [检查][成功/失败][15:43]=>[评测数据文件:/wwwroot/package/623a9fe6-5445-0938-ff77-aeb80066ef27/evaluation.json]
|
|
|
|
+ //数据格式: [下载][成功/失败][15:43]=>[评测数据文件:/wwwroot/package/623a9fe6-5445-0938-ff77-aeb80066ef27/evaluation.json][1024kb][15ms]
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content=$"评测数据文件:{path_evaluation}" });
|
|
|
|
+ if (System.IO.File.Exists(path_evaluation))
|
|
|
|
+ {
|
|
|
|
+ string evaluation_str = await System.IO.File.ReadAllTextAsync(path_evaluation);
|
|
|
|
+ JsonNode? evaluation_data = evaluation_str.ToObject<JsonNode>();
|
|
|
|
+ if (evaluation_data==null)
|
|
|
|
+ {
|
|
|
|
+ blob=1;
|
|
|
|
+ data=1;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ EvaluationClient? evaluationClient = evaluation_data["evaluationClient"]?.ToObject<EvaluationClient>();
|
|
|
|
+ if (evaluationClient!=null)
|
|
|
|
+ {
|
|
|
|
+ if ((!string.IsNullOrWhiteSpace(evaluationLocal.blobHash) && evaluationLocal.blobHash.Equals(evaluationClient.blobHash))
|
|
|
|
+ &&(evaluationLocal.blobTime==evaluationClient.blobTime)
|
|
|
|
+ &&(evaluationLocal.blobCount== evaluationClient.blobCount)
|
|
|
|
+ &&(evaluationLocal.blobSize== evaluationClient.blobSize)&& (evaluationLocal.dataTime==evaluationClient.dataTime)
|
|
|
|
+ &&(evaluationLocal.dataSize==evaluationClient.dataSize)&&(evaluationLocal.webviewCount==evaluationClient.webviewCount)
|
|
|
|
+ &&(evaluationLocal.webviewSize== evaluationClient.webviewSize)
|
|
|
|
+ &&(evaluationLocal.webviewTime== evaluationClient.webviewTime)
|
|
|
|
+ &&(!string.IsNullOrWhiteSpace(evaluationLocal.webviewPath)&& evaluationLocal.webviewPath.Equals(evaluationClient.webviewPath)))
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_info;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ data=1;
|
|
|
|
+ msg_status=Constant._Message_status_error;
|
|
|
|
+ }
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="校验本地试卷文件..." });
|
|
|
|
+ }
|
|
|
|
+ else { data=1; }
|
|
|
|
+
|
|
|
|
+ List<EvaluationExam>? evaluationExams = evaluation_data["evaluationExams"]?.ToObject<List<EvaluationExam>>();
|
|
|
|
+ if (evaluationExams.IsEmpty())
|
|
|
|
+ {
|
|
|
|
+ blob=1;
|
|
|
|
+ data=1;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ foreach (var evaluationExam in evaluationExams!)
|
|
|
|
+ {
|
|
|
|
+ string path_papers = Path.Combine(evaluationPath, "exams");
|
|
|
|
+ var papers_files = FileHelper.ListAllFiles(path_papers);
|
|
|
|
+ int paperIndex = 0;
|
|
|
|
+ foreach (var paper in evaluationExam.papers)
|
|
|
|
+ {
|
|
|
|
+ paperIndex++;
|
|
|
|
+ List<MessageContent> contents = new List<MessageContent>();
|
|
|
|
+ int paper_error_count = 0;
|
|
|
|
+ foreach (var blobInfo in paper.blobs)
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_info;
|
|
|
|
+ if (!string.IsNullOrWhiteSpace(blobInfo.path))
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ var file = papers_files.Find(x => x.Contains(blobInfo.path));
|
|
|
|
+ if (file!=null)
|
|
|
|
+ {
|
|
|
|
+ msg_status=1;
|
|
|
|
+ msg_status=Constant._Message_status_success;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_error;
|
|
|
|
+ paper_error_count++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ msg_status=Constant._Message_status_warning; ;
|
|
|
|
+ paper_error_count++;
|
|
|
|
+ }
|
|
|
|
+ contents.Add(new MessageContent
|
|
|
|
+ {
|
|
|
|
+ dataId=evaluationLocal.id,
|
|
|
|
+ dataName=evaluationLocal.name,
|
|
|
|
+ messageType=Constant._Message_type_check,
|
|
|
|
+ status=msg_status,
|
|
|
|
+ content=$"试卷文件信息:{paper.paperName}"
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ int paper_msg_status = Constant._Message_status_info;
|
|
|
|
+ if (paper_error_count>0)
|
|
|
|
+ {
|
|
|
|
+ blob=1;
|
|
|
|
+ paper_msg_status=Constant._Message_status_error;
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ paper_msg_status=Constant._Message_status_success;
|
|
|
|
+ }
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent
|
|
|
|
+ {
|
|
|
|
+ dataId=evaluationLocal.id,
|
|
|
|
+ dataName=evaluationLocal.name,
|
|
|
|
+ messageType=Constant._Message_type_message,
|
|
|
|
+ status=paper_msg_status,
|
|
|
|
+ content=$"试卷名称:[{paperIndex}]{evaluationExam.examName}-{evaluationExam.subjectName}-{paper.paperName}\r\n文件数量:{paper.blobs.Count()},检测成功数量:{contents.Count(x => x.status==Constant._Message_status_success)},检测异常数量{contents.Count(x => x.status==Constant._Message_status_error)}",
|
|
|
|
+ contents=contents
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ catch (Exception e) {
|
|
|
|
+ _logger.LogData<object>(new {code=500,msg=e.Message,data = new { content= e.StackTrace } }, evaluationLocal.id!);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ //检查需要更新的项目:
|
|
|
|
+ if (data==1)
|
|
|
|
+ {
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent
|
|
|
|
+ {
|
|
|
|
+ dataId=evaluationLocal.id,
|
|
|
|
+ dataName=evaluationLocal.name,
|
|
|
|
+ messageType=Constant._Message_type_message,
|
|
|
|
+ status=Constant._Message_status_warning,
|
|
|
|
+ content=$"检查到评测数据需要更新。[{dataSize}]"
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ if (blob==1)
|
|
|
|
+ {
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent
|
|
|
|
+ {
|
|
|
|
+ dataId=evaluationLocal.id,
|
|
|
|
+ dataName=evaluationLocal.name,
|
|
|
|
+ messageType=Constant._Message_type_message,
|
|
|
|
+ status=Constant._Message_status_warning,
|
|
|
|
+ content=$"检查到评测试卷需要更新。[{blobSize}]"
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ if (webview==1)
|
|
|
|
+ {
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent
|
|
|
|
+ {
|
|
|
|
+ dataId=evaluationLocal.id,
|
|
|
|
+ dataName=evaluationLocal.name,
|
|
|
|
+ messageType=Constant._Message_type_message,
|
|
|
|
+ status=Constant._Message_status_warning,
|
|
|
|
+ content=$"检查到评测作答页面需要更新。[{webviewSize}]"
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ if (groupList==1)
|
|
|
|
+ {
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent
|
|
|
|
+ {
|
|
|
|
+ dataId=evaluationLocal.id,
|
|
|
|
+ dataName=evaluationLocal.name,
|
|
|
|
+ messageType=Constant._Message_type_message,
|
|
|
|
+ status=Constant._Message_status_warning,
|
|
|
|
+ content=$"检查到评测名单需要更新。[{studentCount}]"
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ int finalStatus = Constant._Message_status_success;
|
|
|
|
+ if (checkWarning>0)
|
|
|
|
+ {
|
|
|
|
+ finalStatus = Constant._Message_status_warning;
|
|
|
|
+ }
|
|
|
|
+ if (checkError>0)
|
|
|
|
+ {
|
|
|
|
+ finalStatus = Constant._Message_status_error;
|
|
|
|
+ }
|
|
|
|
+ await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_check_file,
|
|
|
|
+ new MessageContent {
|
|
|
|
+ dataId=evaluationLocal?.id,
|
|
|
|
+ dataName=evaluationLocal?.name,
|
|
|
|
+ messageType=Constant._Message_type_message,
|
|
|
|
+ status=Constant._Message_status_warning,
|
|
|
|
+ content=$"最终检测结果:总数({checkTotal}),成功({checkSuccess}),警告({checkWarning}),异常({checkError})。"
|
|
|
|
+ });
|
|
|
|
+ return Ok(new {
|
|
|
|
+ code = 200,
|
|
|
|
+ evaluation = evaluationLocal,
|
|
|
|
+ data,
|
|
|
|
+ blob,
|
|
|
|
+ webview,
|
|
|
|
+ dataSize,
|
|
|
|
+ blobSize,
|
|
|
|
+ webviewSize,
|
|
|
|
+ status,
|
|
|
|
+ groupList,
|
|
|
|
+ studentCount,
|
|
|
|
+ checkTotal,
|
|
|
|
+ checkSuccess,
|
|
|
|
+ checkError,
|
|
|
|
+ checkWarning,
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 激活或者取消激活考试
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="json"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ [HttpPost("activate-evaluation")]
|
|
|
|
+ [AuthToken("admin", "teacher", "visitor")]
|
|
|
|
+ public IActionResult ActivateEvaluation(JsonNode json)
|
|
|
|
+ {
|
|
|
|
+ string id = $"{json["id"]}";
|
|
|
|
+ string shortCode = $"{json["shortCode"]}";
|
|
|
|
+ string activateStr = $"{json["activate"]}";
|
|
|
|
+ if (!string.IsNullOrWhiteSpace(id) && !string.IsNullOrWhiteSpace(shortCode))
|
|
|
|
+ {
|
|
|
|
+ EvaluationClient? evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindOne(x => x.id!.Equals(id) && !string.IsNullOrWhiteSpace(x.shortCode) && x.shortCode.Equals(shortCode));
|
|
|
|
+ if (evaluationClient != null)
|
|
|
|
+ {
|
|
|
|
+ IEnumerable<EvaluationClient> evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Find(x=>x.activate==1);
|
|
|
|
+ if (evaluationClients != null && evaluationClients.Count() > 0)
|
|
|
|
+ {
|
|
|
|
+ foreach(EvaluationClient item in evaluationClients)
|
|
|
|
+ {
|
|
|
|
+ item.activate = 0;
|
|
|
|
+ _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Upsert(item);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ int activate = 0;
|
|
|
|
+ if (int.TryParse(activateStr, out int _activate)) {
|
|
|
|
+ activate = _activate;
|
|
|
|
+ }
|
|
|
|
+ evaluationClient.activate = activate;
|
|
|
|
+ _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Upsert(evaluationClient);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return Ok();
|
|
|
|
+ }
|
|
|
|
+ /// <summary>
|
|
|
|
+ /// 加载本地的活动列表
|
|
|
|
+ /// </summary>
|
|
|
|
+ /// <param name="json"></param>
|
|
|
|
+ /// <returns></returns>
|
|
|
|
+ [HttpPost("list-local-evaluation")]
|
|
|
|
+ [AuthToken("admin", "teacher", "visitor")]
|
|
|
|
+ public IActionResult ListLocalEvaluation(JsonNode json)
|
|
|
|
+ {
|
|
|
|
+
|
|
|
|
+ IEnumerable<EvaluationClient>? evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().FindAll().OrderByDescending(x=>x.activate).ThenByDescending(x=>x.stime);
|
|
|
|
+
|
|
|
|
+ if (evaluationClients != null)
|
|
|
|
+ {
|
|
|
|
+ var result = evaluationClients.Select(client =>
|
|
|
|
+ {
|
|
|
|
+ var properties = client.GetType().GetProperties();
|
|
|
|
+ var anonymousObject = new Dictionary<string, object?>();
|
|
|
|
+ foreach (var property in properties)
|
|
|
|
+ {
|
|
|
|
+ if (!property.Name.Equals("password") && !property.Name.Equals("shortCode"))
|
|
|
|
+ {
|
|
|
|
+ anonymousObject[property.Name] = property.GetValue(client);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return anonymousObject;
|
|
|
|
+ });
|
|
|
|
+ return Ok(new { code = 200, evaluation = result });
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ return Ok(new { code = 200, evaluation = new Dictionary<string, object?>() });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|