using IES.ExamLib.Models; using IES.ExamServer.DI; using IES.ExamServer.DI.SignalRHost; using IES.ExamServer.Filters; using IES.ExamServer.Helper; using IES.ExamServer.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Configuration; using System.Linq.Expressions; using System.Net.Http; 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 _logger; private readonly LiteDBFactory _liteDBFactory; private readonly DataCenterConnectionService _connectionService; private readonly int DelayMicro = 10;//微观数据延迟 private readonly int DelayMacro = 100;//宏观数据延迟 private readonly SignalRExamServerHub _signalRExamServerHub; public ManageController(LiteDBFactory liteDBFactory,ILogger logger, IConfiguration configuration, IHttpClientFactory httpClientFactory, IMemoryCache memoryCache, DataCenterConnectionService connectionService,SignalRExamServerHub signalRExamServerHub) { _logger = logger; _configuration=configuration; _httpClientFactory=httpClientFactory; _memoryCache=memoryCache; _liteDBFactory=liteDBFactory; _connectionService=connectionService; _signalRExamServerHub=signalRExamServerHub; } [HttpPost("download-package")] [AuthToken("admin","teacher")] public async Task 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... //进度条 展示下载文件总大小和已下载,末尾展示 文件总个数和已下载个数 return Ok(); } [HttpPost("check-short-code")] public async Task CheckShortCode(JsonNode json) { string shortCode = $"{json["shortCode"]}"; string evaluationId = $"{json["evaluationId"]}"; Expression> predicate = x => true; if (!string.IsNullOrEmpty(shortCode)) { var codePredicate = ExpressionHelper.Or( 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 evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection().Find(predicate); EvaluationClient? evaluationLocal = null; EvaluationClient? evaluationCloud = null; if (evaluationClients.Count()>0) { evaluationLocal= evaluationClients.First(); } //如果要访问中心,则需要教师登录联网。 var token = GetAuthTokenInfo(); if (token.scope.Equals(ExamConstant.ScopeTeacher)) { if ( _connectionService.dataCenterIsConnected) { Teacher teacher= _liteDBFactory.GetLiteDatabase().GetCollection().FindOne(x => x.id!.Equals(token.id)); string? CenterUrl = _configuration.GetValue("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}/evaluation-sync/find-sync-info",new { shortCode, evaluationId }); if (message.IsSuccessStatusCode) { string content = await message.Content.ReadAsStringAsync(); JsonNode? jsonNode =JsonSerializer.Deserialize(content); if (jsonNode!=null) { evaluationCloud= JsonSerializer.Deserialize(jsonNode["evaluation"]); } } } } //数据,文件,页面 0 没有更新,1 有更新 int data = 0,blob=0,webview=0,status=0; long dataSize = 0, blobSize=0 , webviewSize=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().Insert(evaluationLocal); } List file_intact = new List(); if (evaluationLocal!=null) { //校验本地文件数据 string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package"); if (!Directory.Exists(packagePath)) Directory.CreateDirectory(packagePath); string evaluationPath = Path.Combine(packagePath, evaluationLocal.id!); await Task.Delay(DelayMacro); if (!System.IO.File.Exists(Path.Combine(evaluationPath, "evaluation.json"))) { file_intact.Add(0); } await Task.Delay(DelayMacro); if (!System.IO.File.Exists(Path.Combine(evaluationPath, "groupList.json"))) { file_intact.Add(0); } await Task.Delay(DelayMacro); if (!System.IO.File.Exists(Path.Combine(evaluationPath, "source.json"))) { file_intact.Add(0); } await Task.Delay(DelayMacro); } return Ok(new {code=200, evaluation= evaluationLocal,data,blob,webview,dataSize,blobSize,webviewSize,status }); } /// /// 激活考试 /// /// /// [HttpPost("activate-evaluation")] public IActionResult ActivateEvaluation(JsonNode json) { string id = $"{json["id"]}"; string shortCode = $"{json["shortCode"]}"; if (!string.IsNullOrWhiteSpace(id) && !string.IsNullOrWhiteSpace(shortCode)) { EvaluationClient evaluationClient = _liteDBFactory.GetLiteDatabase().GetCollection().FindOne(x => x.id!.Equals(id) && !string.IsNullOrWhiteSpace(x.shortCode) && x.shortCode.Equals(shortCode)); if (evaluationClient != null) { } } return Ok(); } /// /// 加载本地的活动列表 /// /// /// [HttpPost("list-local-evaluation")] public IActionResult ListLocalEvaluation(JsonNode json) { IEnumerable evaluationClients = _liteDBFactory.GetLiteDatabase().GetCollection().FindAll().OrderByDescending(x=>x.activate).ThenByDescending(x=>x.stime); var result = evaluationClients.Select(client => { var properties = client.GetType().GetProperties(); var anonymousObject = new Dictionary(); 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 }); } } }