Browse Source

Merge branch 'develop' into develop_local

jeff 2 months ago
parent
commit
4d04dfa311
31 changed files with 1012 additions and 224 deletions
  1. 1 0
      .gitignore
  2. 0 68
      TEAMModelOS.Extension/IES.Exam/IES.ExamClient/certificate.bat
  3. BIN
      TEAMModelOS.Extension/IES.Exam/IES.ExamClient/certificate.cer
  4. 66 12
      TEAMModelOS.Extension/IES.Exam/IES.ExamClient/main.js
  5. 80 4
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/FrameworkController.cs
  6. 11 3
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/IndexController.cs
  7. 78 38
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/ManageController.cs
  8. 186 0
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/MusicAIManageController.cs
  9. 1 0
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/CenterServiceConnectionService.cs
  10. 17 1
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/ServiceInitializer.cs
  11. 5 2
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/SignalRHost/SignalRExamServerHub.cs
  12. 15 0
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/Constant.cs
  13. 55 47
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/ProcessHelper.cs
  14. 4 0
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Models/ServerDevice.cs
  15. 16 2
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Models/SignalRClient.cs
  16. 60 13
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/IndexService.cs
  17. 11 10
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/ManageService.cs
  18. 116 0
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/MusicAIManageService.cs
  19. 1 1
      TEAMModelOS.Extension/IES.Exam/IES.ExamServer/appsettings.json
  20. 74 4
      TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/admin/ActivityManage.vue
  21. 1 1
      TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/student/ActivityAnswer.vue
  22. 100 0
      TEAMModelOS.SDK/Models/Cosmos/Student/AppraiseRecord.cs
  23. 58 0
      TEAMModelOS.SDK/Models/Service/OverallEducationService.cs
  24. 2 2
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  25. 1 1
      TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue
  26. 5 2
      TEAMModelOS/ClientApp/src/store/module/user.js
  27. 4 4
      TEAMModelOS/ClientApp/src/view/areaMgmt/AreaLayout.vue
  28. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/stulist/MgtStuList.vue
  29. 1 1
      TEAMModelOS/Controllers/Both/EvaluationSyncInfoController.cs
  30. 27 0
      TEAMModelOS/Controllers/Common/ActivityController.cs
  31. 15 7
      TEAMModelOS/Controllers/Third/Xkw/XkwOAuth2Controller.cs

+ 1 - 0
.gitignore

@@ -278,3 +278,4 @@ TEAMModelBI/Properties/ServiceDependencies/teammodelbi-RC - Web Deploy/profile.a
 /TEAMModelOS.Extension/IES.Exam/IES.ExamClient/server
 /TEAMModelOS.Extension/IES.Exam/wwwroot
 /TEAMModelOS.Extension/IES.Exam/IES.ExamClient/IES.ExamServer.zip
+/TEAMModelOS.Extension/IES.Exam/IES.ExamServer/start.json

+ 0 - 68
TEAMModelOS.Extension/IES.Exam/IES.ExamClient/certificate.bat

@@ -1,68 +0,0 @@
-@echo off
-echo Configuring hosts file
-
-net session >nul 2>&1
-if %errorLevel% neq 0 (
-    echo Please run this script as an administrator
-    exit /b
-)
-
-set "hostsFile=C:\Windows\System32\drivers\etc\hosts"
-set "newEntry=192.168.8.235 exam.habook.local"
-
-if not exist "%hostsFile%" (
-    echo hosts file does not exist:%hostsFile%
-    exit /b
-)
-
-
-findstr /v /i /c:"exam.habook.local" "%hostsFile%" > "%hostsFile%.tmp"
-if %errorLevel% equ 0 (
-    move /y "%hostsFile%.tmp" "%hostsFile%" >nul 2>&1
-    echo Removed all entries containing exam.habook.local
-) else (
-    echo Failed to remove entries containing exam.habook.local
-    exit /b
-)
-
-
-echo %newEntry% >> "%hostsFile%"
-if %errorLevel% equ 0 (
-    echo Hosts file configured successfully
-) else (
-    echo Hosts file configuration failed
-    exit /b
-)
-
-:ImportCert
-echo Importing certificate
-
-if not exist "%~dp0certificate.cer" (
-    echo Certificate file does not exist:%~dp0certificate.cer
-    exit /b
-)
-
-set "certSubject="
-for /f "tokens=*" %%i in ('certutil -dump "%~dp0certificate.cer" ^| findstr /i "CN="') do (
-    set "certSubject=%%i"
-)
-
-if defined certSubject (
-    echo Deleting existing certificate with the same name
-    certutil -delstore "Root" "%certSubject%"
-    if %errorLevel% equ 0 (
-        echo Existing certificate deleted successfully
-    ) else (
-        echo Failed to delete existing certificate (may not exist)
-    )
-)
-
-echo Importing new certificate
-certutil -addstore -f "Root" "%~dp0certificate.cer"
-if %errorLevel% equ 0 (
-    echo Certificate imported successfully
-) else (
-    echo Certificate import failed
-)
-
-echo All operations completed

BIN
TEAMModelOS.Extension/IES.Exam/IES.ExamClient/certificate.cer


+ 66 - 12
TEAMModelOS.Extension/IES.Exam/IES.ExamClient/main.js

@@ -10,7 +10,7 @@ const { exec } = require('child_process');
 const net = require('net');
 const os = require('os');
 const utils = require('./utils');
-
+const fs = require('fs');
 let win = null;
 let tray = null;
 app.isQuitting = false; // 添加标志位
@@ -33,13 +33,19 @@ const createWindow = async () => {
                 contextIsolation: false,
             },
         });
-        win.webContents.openDevTools(); // 打开开发者工具
+        //win.webContents.openDevTools(); // 打开开发者工具
         //win.webContents.session.setCertificateVerifyProc((request, callback) => {
         //    // 始终返回 0 表示验证通过
         //    callback(0);
         //});///login/admin
         win.maximize();
-        win.loadFile('index.html');
+        if (app.isPackaged) {
+            let indexPath = path.join(constants.serverPath, 'resources', 'index.html');
+            win.loadFile(indexPath);
+        } else {
+            win.loadFile('index.html');
+        }
+       
 
         // 模拟执行业务过程
         StartProcess();
@@ -93,7 +99,7 @@ app.on('window-all-closed', function () {
     }
 });
 
-// 模拟执行业务过程
+// 服务端启动过程
 async function StartProcess() {
     //步骤1 开始检查
     sendLogMessage('检查评测服务是否启动...');
@@ -141,14 +147,62 @@ async function StartProcess() {
         await serverManager.startServer();
         const isServerRunning = await serverManager.checkServerHealth();
         if (isServerRunning) {
-            sendLogMessage('本地IP域名映射配置成功...');
-            sendLogMessage('SSL安全证书安装成功...');
-            sendLogMessage('评测服务启动成功...');
-            sendLogMessage('正在加载登录页面...');
-            utils.delay(2000)
-            win.loadURL(`${constants.baseUrl}/login/admin`, {
-                agent: constants.agent
-            });
+            let startJsonPath = path.join(constants.serverPath, 'server',"wwwroot", 'start.json');
+            //startJsonPath = `"${startJsonPath}"`;
+            // sendLogMessage(`"${startJsonPath}"`);
+            let jump = true;
+            sendLogMessage('确认评测服务启动状态...');
+            if (fs.existsSync(startJsonPath)) {
+                sendLogMessage('检测IP域名映射配置...');
+                sendLogMessage('检测SSL安全证书...');
+
+                // 读取JSON文件
+                const data = fs.readFileSync(`${startJsonPath}`, 'utf8');
+                const jsonData = JSON.parse(data);
+
+                if (jsonData.read === 0) {
+                    // 检查服务启动是否正常
+                    if (jsonData.code_zip === 200 && jsonData.code_cer === 200 && jsonData.code_hosts === 200) {
+                        sendLogMessage('服务启动正常...');
+                    } else {
+                        jump = false;
+                        sendLogMessage('服务启动异常,请检查相关配置。' + JSON.stringify(jsonData) );
+                    }
+                    // IP域名映射是否成功
+                    sendLogMessage(`IP域名映射状态:${jsonData.hosts_msg}`);
+                    // 安全证书是否安装成功
+                    sendLogMessage(`安全证书状态:${jsonData.cer_msg}`);
+                
+                    // 使用的网卡名称及mac
+                    sendLogMessage(`网卡名称:${jsonData.name}`);
+                    sendLogMessage(`MAC地址:${jsonData.mac}`);
+                    // 映射的IP地址是多少
+                    sendLogMessage(`IP地址:${jsonData.ip}`);
+                    // 安全证书是否安装成功
+                    sendLogMessage(`学生的配置文件:${jsonData.zip_msg}`);
+                    // 将read状态改为1,标记已读
+                    jsonData.read = 1;
+                    // 写入start.json
+                    fs.writeFileSync(startJsonPath, JSON.stringify(jsonData, null, 2));
+                   
+                    //sendLogMessage('已标记为已读并更新JSON文件。');
+                } else {
+                   // sendLogMessage('该JSON文件已读,无需再次检查。');
+                }
+            } else {
+                jump = false;
+                sendLogMessage(`指定的JSON文件不存在。${startJsonPath}`);
+            }
+            if (jump) {
+                sendLogMessage('评测服务启动成功...');
+                sendLogMessage('正在加载登录页面...');
+                // 使用 setTimeout 延迟 5 秒后执行 win.loadURL
+                setTimeout(() => {
+                    win.loadURL(`${constants.baseUrl}/login/admin`, {
+                        agent: constants.agent
+                    });
+                }, 3000);
+            }
 
         }
         else {

File diff suppressed because it is too large
+ 80 - 4
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/FrameworkController.cs


+ 11 - 3
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/IndexController.cs

@@ -380,8 +380,16 @@ namespace IES.ExamServer.Controllers
         {
             try
             {
-                var data = await IndexService. ModifyHosts(ip,_memoryCache,_liteDBFactory,_connectionService);
-                return Ok(new { data.code,data.code_zip,data.code_cer,data.code_hosts,data.msg});
+                if (SystemScriptHelper.IsAdministrator())
+                {
+                    var data = await IndexService.ModifyHosts(ip, _memoryCache, _liteDBFactory, _connectionService);
+                    return Ok(new { data.code, data.code_zip, data.code_cer, data.code_hosts, data.msg });
+                }
+                else 
+                {
+                    code = 401;
+                    msg = "请使用管理员身份运行本程序以切换主站";
+                }
             }
             catch (Exception ex)
             {
@@ -389,7 +397,7 @@ namespace IES.ExamServer.Controllers
                 _logger.LogError($"域名IP绑定错误。{ex.Message},{ex.StackTrace}");
                 msg = $"域名IP绑定错误,{ex.Message}";
             }
-            return Ok(new { code = 400, msg = msg });
+            return Ok(new { code = code, msg = msg });
         }
         /// <summary>
         /// 强制重新安装证书

+ 78 - 38
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/ManageController.cs

@@ -264,13 +264,13 @@ namespace IES.ExamServer.Controllers
                         int msg_status = Constant._Message_status_info;
                         string msg_content = msg_status.Equals(Constant._Message_status_success) ? "成功" : "失败";
                         await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                        new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = 0, content = "检测云端数据是否匹配..." });
+                        new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = 0, step=1, content = "检测云端数据是否匹配..." });
                         var dataInfo=  await GetEvaluationFromCenter(GetXAuthToken(), _configuration, _httpClientFactory, shortCode, evaluationClient.id!);
                       
                         if (dataInfo.centerCode.Equals("200")&& dataInfo.evaluationCloud!=null)
                         {
                             await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_success, content = $"云端数据检测结果:{dataInfo.centerMsg},状态:{dataInfo.centerCode}" },true);
+                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_success, step = 1, content = $"云端数据检测结果:{dataInfo.centerMsg},状态:{dataInfo.centerCode}" },true);
                             string? CenterUrl = _configuration.GetValue<string>("ExamServer:CenterUrl");
                             var client = _httpClientFactory.CreateClient();
                             if (client.DefaultRequestHeaders.Contains(Constant._X_Auth_AuthToken))
@@ -306,7 +306,7 @@ namespace IES.ExamServer.Controllers
                             }
                             msg_content = msg_status.Equals(Constant._Message_status_success) ? "成功" : "失败";
                             await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = msg_status, content = $"获取云端下载授权=>{msg_content}" }, true);
+                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = msg_status, step = 1, content = $"获取云端下载授权=>{msg_content}" }, true);
                             var httpClient = _httpClientFactory.CreateClient();
                             string packagePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "package");
                             string evaluationPath = Path.Combine(packagePath, dataInfo.evaluationCloud.id!);
@@ -319,7 +319,7 @@ namespace IES.ExamServer.Controllers
                             }
                            
                             await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_info, content = $"下载前清理资源" });
+                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 1, finish=1,status = Constant._Message_status_info, content = $"下载前清理资源" });
                             string evaluationData = string.Empty;
                             {
                                 //evaluation
@@ -333,13 +333,13 @@ namespace IES.ExamServer.Controllers
                                     await System.IO.File.WriteAllTextAsync(path_evaluation, content);
                                     successMsgs.Add("评测信息文件evaluation.json文件下载成功!");
                                     await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                    new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_success, content = $"评测信息文件evaluation.json文件下载成功!" });
+                                    new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 2, finish = 1, status = Constant._Message_status_success, content = $"评测信息文件evaluation.json文件下载成功!" });
                                 }
                                 else
                                 {
                                     errorMsgs.Add("评测信息文件evaluation.json文件下载失败!");
                                     await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                    new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_error, content = $"评测信息文件evaluation.json文件下载失败!" }, true);
+                                    new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 2, finish = 1, status = Constant._Message_status_error, content = $"评测信息文件evaluation.json文件下载失败!" }, true);
                                 }
 
 
@@ -377,14 +377,14 @@ namespace IES.ExamServer.Controllers
                                     await System.IO.File.WriteAllTextAsync(path_groupList, content);
                                     successMsgs.Add("评测名单grouplist.json文件下载成功!");
                                     await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                   new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_success, content = $"评测名单grouplist.json文件下载成功!" });
+                                   new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 3, finish = 1, status = Constant._Message_status_success, content = $"评测名单grouplist.json文件下载成功!" });
 
                                 }
                                 else
                                 {
                                     errorMsgs.Add("评测名单grouplist.json文件下载失败!");
                                     await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                   new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_error, content = $"评测名单grouplist.json文件下载失败!" }, true);
+                                   new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 3, finish = 1, status = Constant._Message_status_error, content = $"评测名单grouplist.json文件下载失败!" }, true);
 
                                 }
                             }
@@ -410,12 +410,15 @@ namespace IES.ExamServer.Controllers
                                         await Parallel.ForEachAsync(evaluationPaper.blobs, parallelOptions, async (blob, cancellationToken) =>
                                         {
                                             currCount++;
+                                            double size = Math.Round(blob.size * 1.0 / 1024 / 1024, 2);
+                                            string? fileName = Path.GetFileName(blob.path);
                                             try
                                             {
                                                 // 下载 Blob 文件到本地
                                                 //httpClient.Timeout = TimeSpan.FromSeconds(300);
+                                              
                                                 HttpResponseMessage blobMessage = await httpClient.GetAsync($"{url}/{cnt}/{blob.path}?{sas}", cancellationToken);
-                                               
+                                                
                                                 if (blobMessage.IsSuccessStatusCode)
                                                 {
                                                     byte[] bytes = await blobMessage.Content.ReadAsByteArrayAsync(cancellationToken);
@@ -429,20 +432,20 @@ namespace IES.ExamServer.Controllers
                                                         }
                                                         else
                                                         {
-                                                            string? fileName = Path.GetFileName(blob.path);
+                                                           
                                                             await System.IO.File.WriteAllBytesAsync(Path.Combine(path_paper, fileName!), bytes, cancellationToken);
                                                         }
                                                     }
 
                                                     await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_success, content = $"[进度:{currCount}/{blobCount}][大小:{blob.size * 1.0 / 1024 / 1024}kb]{evaluationExam.subjectName},{evaluationPaper.paperName},{blob.path}文件下载成功。" });
+                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 4, status = Constant._Message_status_success, content = $"[进度:{currCount}/{blobCount}][大小:{size}kb]{evaluationExam.subjectName},{evaluationPaper.paperName},{fileName}文件下载成功。" });
                                                 }
                                                 else
                                                 {
                                                     string? error = await blobMessage.Content.ReadAsStringAsync(cancellationToken);
                                                     errorMsgs.Add($"{evaluationExam.subjectName},{evaluationPaper.paperName},{blob.path}文件下载失败,{blobMessage.StatusCode},{error}");
                                                     await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                 new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_error, content = $"[进度:{currCount}/{blobCount}][大小:{blob.size * 1.0 / 1024 / 1024}kb]{evaluationExam.subjectName},{evaluationPaper.paperName},{blob.path}文件下载失败,{blobMessage.StatusCode},{error}" }, true);
+                                 new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 4, status = Constant._Message_status_error, content = $"[进度:{currCount}/{blobCount}][大小:{size}kb]{evaluationExam.subjectName},{evaluationPaper.paperName},{fileName}文件下载失败,{blobMessage.StatusCode},{error}" }, true);
 
                                                     // Console.WriteLine($"Error downloading {blob.path},{blobMessage.StatusCode},{error}");
                                                 }
@@ -451,7 +454,7 @@ namespace IES.ExamServer.Controllers
                                             {
                                                 errorMsgs.Add($"{evaluationExam.subjectName},{evaluationPaper.paperName},{blob.path}文件下载错误,{ex.Message}");
                                                 await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                 new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_error, content = $"[进度:{currCount}/{blobCount}][大小:{blob.size * 1.0 / 1024 / 1024}kb]{evaluationExam.subjectName},{evaluationPaper.paperName},{blob.path}文件下载错误,{ex.Message}" }, true);
+                                 new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 4, status = Constant._Message_status_error, content = $"[进度:{currCount}/{blobCount}][大小:{size}kb]{evaluationExam.subjectName},{evaluationPaper.paperName},{fileName}文件下载错误,{ex.Message}" }, true);
 
                                                 // 处理异常
                                                 //Console.WriteLine($"Error downloading {blob.path}: {ex.Message}");
@@ -462,10 +465,15 @@ namespace IES.ExamServer.Controllers
                             }
 
                             _liteDBFactory.GetLiteDatabase().GetCollection<EvaluationClient>().Upsert(dataInfo.evaluationCloud!);
+                            await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
+                                 new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 4, finish = 1, status = Constant._Message_status_info, content = $"评测试卷下载完成" });
 
-                            (successMsgs, errorMsgs) = await ManageService.CheckFile(dataInfo.evaluationCloud!, successMsgs, errorMsgs, _signalRExamServerHub, _memoryCache, _logger, deviceId, evaluationPath, Constant._Message_grant_type_download_file);
+                            (successMsgs, errorMsgs) = await ManageService.CheckFile(dataInfo.evaluationCloud!, successMsgs, errorMsgs, _signalRExamServerHub, _memoryCache, _logger, deviceId, evaluationPath, Constant._Message_grant_type_download_file,step:5);
+                            
                             await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                   new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_info, content = $"正在创建压缩包,请稍等..." });
+                                    new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 5, finish = 1, status = Constant._Message_status_info, content = $"评测完整性验证完成" });
+                            await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
+                                   new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 6, status = Constant._Message_status_info, content = $"正在创建压缩包,请稍等..." });
 
                             //下载完成后,对数据进行检查,然后在加密压缩。
                             string zipPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "zip");
@@ -479,13 +487,13 @@ namespace IES.ExamServer.Controllers
                             {
                                 successMsgs.Add("评测数据压缩包创建成功!");
                                 await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                   new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_success, content = $"评测数据压缩包创建成功!" });
+                                   new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 6, finish = 1, status = Constant._Message_status_success, content = $"评测数据压缩包创建成功!" });
                             }
                             else
                             {
                                 errorMsgs.Add("评测数据压缩包创建失败!");
                                 await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                  new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_error, content = $"评测数据压缩包创建失败!" }, true);
+                                  new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 6, finish = 1, status = Constant._Message_status_error, content = $"评测数据压缩包创建失败!" }, true);
 
                             }
                         }
@@ -493,7 +501,7 @@ namespace IES.ExamServer.Controllers
                             string content = $"云端数据检测结果:{dataInfo.centerMsg},状态:{dataInfo.centerCode}";
                             errorMsgs.Add(content);
                             await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, Constant._Message_grant_type_download_file,
-                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, status = Constant._Message_status_error, content = content }, true);
+                                new MessageContent { dataId = evaluationClient.id, dataName = evaluationClient.name, messageType = Constant._Message_type_message, step = 1, finish = 1, status = Constant._Message_status_error, content = content }, true);
                         }
                     }
                     else
@@ -559,31 +567,61 @@ namespace IES.ExamServer.Controllers
                     {
                         string key = $"{Constant._KeyEvaluationZipExtract}:{evaluationId}:{openCode}";
                         successMsgs.Add("加载评测试卷文件包!");
-                        //string keyData =  _memoryCache.Get<string>(key);
-                        //if (!string.IsNullOrWhiteSpace(keyData))
-                        //{
-                        //}
-                        //else {
+                        bool needExtract = false;
+                        if (Directory.Exists(evaluationPath))
+                        {
+                            (successMsgs, errorMsgs) = await ManageService.CheckFile(evaluationLocal, successMsgs, errorMsgs, _signalRExamServerHub, _memoryCache, _logger, deviceId, evaluationPath, Constant._Message_grant_type_check_file);
+                            if (errorMsgs.Count() > 0)
+                            {
+                                //删除文件夹
+                                FileHelper.DeleteFolder(evaluationPath);
+                                needExtract = true;
+                            }
+                            else 
+                            {
+                                DirectoryInfo directoryInfo = new DirectoryInfo(evaluationPath);
+                                // 获取文件夹的创建时间
+                                DateTime creationTime = directoryInfo.CreationTime;
+                                // 计算时间差
+                                DateTime currentTime = DateTime.Now;
 
-                            
-                        //}
-                        //删除文件夹
-                        FileHelper.DeleteFolder(evaluationPath);
-                        if (!Directory.Exists(evaluationPath))
+                                TimeSpan timeDifference = currentTime - creationTime;
+
+                                // 判断是否超过两天
+                                if (timeDifference.TotalDays > 2) 
+                                {
+                                    needExtract = true;
+                                }
+                            }
+                        }
+                        else 
                         {
-                            Directory.CreateDirectory(evaluationPath);
+                            needExtract = true;
                         }
-                        //解压文件包
-                        var extractRes = await ZipHelper.ExtractPasswordProtectedZip(Path.Combine(zipPath, $"{evaluationLocal.id}-{evaluationLocal.blobHash}.zip"), evaluationPath, evaluationLocal.openCode!, _signalRExamServerHub,_memoryCache,_logger,deviceId,evaluationLocal);
-                        if (extractRes.res)
+                        if (needExtract) 
                         {
-                            _memoryCache.Set(key,key,TimeSpan.FromSeconds(30));
-                            successMsgs.Add("评测试卷文件包解压成功!");
-                            (successMsgs, errorMsgs) =  await ManageService.CheckFile(evaluationLocal, successMsgs, errorMsgs, _signalRExamServerHub, _memoryCache, _logger, deviceId, evaluationPath, Constant._Message_grant_type_check_file);
+                            FileHelper.DeleteFolder(evaluationPath);
+                            if (!Directory.Exists(evaluationPath))
+                            {
+                                Directory.CreateDirectory(evaluationPath);
+                            }
+                            //解压文件包
+                            var extractRes = await ZipHelper.ExtractPasswordProtectedZip(Path.Combine(zipPath, $"{evaluationLocal.id}-{evaluationLocal.blobHash}.zip"), evaluationPath, evaluationLocal.openCode!, _signalRExamServerHub, _memoryCache, _logger, deviceId, evaluationLocal);
+                            if (extractRes.res)
+                            {
+
+                                successMsgs.Add("评测试卷文件包解压成功!");
+                                (successMsgs, errorMsgs) = await ManageService.CheckFile(evaluationLocal, successMsgs, errorMsgs, _signalRExamServerHub, _memoryCache, _logger, deviceId, evaluationPath, Constant._Message_grant_type_check_file);
+                            }
+                            else
+                            {
+                                errorMsgs.Add("评测试卷文件包解压失败!");
+                                //return Ok(new { code = 3, msg = "评测试卷文件包解压失败!" });
+                            }
                         }
-                        else {
-                            errorMsgs.Add("评测试卷文件包解压失败!");
-                            //return Ok(new { code = 3, msg = "评测试卷文件包解压失败!" });
+                        else
+                        {
+                            successMsgs.Add("评测试卷文件包检测成功!");
                         }
                     }
                     else {
@@ -729,6 +767,8 @@ namespace IES.ExamServer.Controllers
                 result = checkDataResult
             });
         }
+
+
         /// <summary>
         /// 获取当前评测的开考设置信息
         /// </summary>

File diff suppressed because it is too large
+ 186 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Controllers/MusicAIManageController.cs


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

@@ -6,6 +6,7 @@ namespace IES.ExamServer.DI
     {
         private bool _centerIsConnected;
         private bool _notifyIsConnected;
+        public Network? primaryNetwork { get; set; }
        // private bool _musicIsConnected;
         public string? centerUrl { get; set; }
         public string? notifyUrl { get; set; }

+ 17 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/ServiceInitializer.cs

@@ -10,6 +10,7 @@ using IES.ExamServer.Helper;
 using IES.ExamServer.Models;
 using System.Security.Policy;
 using IES.ExamServer.Helpers;
+using System.Text;
 
 namespace IES.ExamServer.DI
 {
@@ -131,7 +132,22 @@ namespace IES.ExamServer.DI
             _cache.Set(Constant._KeyServerDevice, serverDevice);
             _liteDBFactory.GetLiteDatabase().GetCollection<ServerDevice>().Upsert(serverDevice);
             _connectionService.serverDevice = serverDevice;
-            await  IndexService.ModifyHosts(null, _cache, _liteDBFactory, _connectionService);
+            var dataModify =  await  IndexService.ModifyHosts(null, _cache, _liteDBFactory, _connectionService);
+            var dataFile = new {
+                dataModify.code_zip,
+                dataModify.zip_msg,
+                dataModify.code_cer,
+                dataModify.cer_msg,
+                dataModify.code_hosts,
+                dataModify.hosts_msg,
+                name = dataModify.primaryNetwork?.name,
+                mac= dataModify.primaryNetwork?.mac,
+                ip = dataModify.primaryNetwork?.ip,
+                read=0
+            };
+            string startPath = Path.Combine(Directory.GetCurrentDirectory(),"wwwroot","start.json");
+            await File.WriteAllTextAsync(startPath, dataFile.ToJsonString());
+            StringBuilder sb = new StringBuilder();
             _lifetime.ApplicationStarted.Register(() =>
             {
                var serverDevice=  _cache.Get<ServerDevice>(Constant._KeyServerDevice);

+ 5 - 2
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/DI/SignalRHost/SignalRExamServerHub.cs

@@ -15,7 +15,8 @@ namespace IES.ExamServer.DI.SignalRHost
         public async static Task SendMessage(this IHubContext<SignalRExamServerHub> hubContext, IMemoryCache _memoryCache, ILogger logger, string clientId, string grant_type, MessageContent content,bool isLog=false)
         {
             try
-            {//双向检测是否连接。
+            {
+                //双向检测是否连接。
                 SignalRClient signalRClient = _memoryCache.Get<SignalRClient>($"{Constant._KeySignalRClientClients}:{clientId}");
                 if (signalRClient!=null)
                 {
@@ -32,7 +33,9 @@ namespace IES.ExamServer.DI.SignalRHost
                     grant_type = grant_type,
                     time = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
                     type = Constant._Message_type_message,
-                    contents = content.contents
+                    contents = content.contents,
+                    step=content.step,
+                    finish = content.finish
                 };
                 if (signalRClient != null)
                 {

+ 15 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/Constant.cs

@@ -28,6 +28,21 @@ namespace IES.ExamServer.Helper
         public static readonly int _Message_status_success = 1;
         public static readonly int _Message_status_warning = 2;
         #region 智音AI音乐相关常量
+        /// <summary>
+        /// 音乐播放服务
+        /// "MusicAIServer": {
+        ///    "MusicUrl": "https://musicapi.winteach.cn/api/v1",
+        ///    "AppId": "8a68f563f3384662acbc268336b98ae2",
+        ///    "KeyAES": "GcRHG7pGgepXXOOU",
+        ///    "IvAES": "W5yt6WthEs2mQlSn"
+        ///  }
+        /// "MusicAIServer": {
+        ///    "MusicUrl": "https://tmdapi.yosocloud.com/api/v1",
+        ///    "AppId": "8a68f563f3384662acbc268336b98ae2",
+        ///    "KeyAES": "GcRHG7pGgepXXOOU",
+        ///    "IvAES": "W5yt6WthEs2mQlSn"
+        ///  }
+        /// </summary>
         public static readonly string _MusicAIServerAppId = "8a68f563f3384662acbc268336b98ae2";
         public static readonly string _MusicAIServerAESKey = "GcRHG7pGgepXXOOU";
         public static readonly string _MusicAIServerAESIv = "W5yt6WthEs2mQlSn";

+ 55 - 47
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Helpers/ProcessHelper.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using System.Text;
 using System.Text.Json;
 
 namespace IES.ExamServer.Helpers
@@ -10,63 +11,70 @@ namespace IES.ExamServer.Helpers
         {
             int code = 0;
             string msg = string.Empty;
+            try {
 
-            // 创建一个新的 ProcessStartInfo 对象
-            ProcessStartInfo startInfo = new ProcessStartInfo
-            {
-                // 指定要执行的 BAT 文件的路径
-                FileName = "cmd.exe",
-                // 设置命令行参数,使用 /c 表示执行命令后关闭命令提示符窗口
-                Arguments = $"/c {pathBat}",
-                // 设置是否使用操作系统 shell 启动进程
-                UseShellExecute = false,
-                // 设置是否创建新的窗口
-                CreateNoWindow = true,
-                // 重定向标准输出和标准错误输出
-                RedirectStandardOutput = true,
-                RedirectStandardError = true
-            };
-            // 创建一个新的 Process 对象
-            using (Process process = new Process())
-            {
-                // 将 ProcessStartInfo 对象分配给 Process 对象
-                process.StartInfo = startInfo;
+                // 创建一个新的 ProcessStartInfo 对象
+                ProcessStartInfo startInfo = new ProcessStartInfo
+                {
+                    // 指定要执行的 BAT 文件的路径
+                    FileName = "cmd.exe",
+                    // 设置命令行参数,使用 /c 表示执行命令后关闭命令提示符窗口
+                    Arguments = $"/c \"{pathBat}\"", // 用双引号括起路径
+                                                     // 设置是否使用操作系统 shell 启动进程
+                    UseShellExecute = false,
+                    // 设置是否创建新的窗口
+                    CreateNoWindow = true,
+                    // 重定向标准输出和标准错误输出
+                    RedirectStandardOutput = true,
+                    RedirectStandardError = true
+                };
 
-                // 启动进程
-                process.Start();
+                // 创建一个新的 Process 对象
+                using (Process process = new Process())
+                {
+                    // 将 ProcessStartInfo 对象分配给 Process 对象
+                    process.StartInfo = startInfo;
+                    process.StartInfo.StandardOutputEncoding = Encoding.UTF8;
+                    process.StartInfo.StandardErrorEncoding = Encoding.UTF8;
+                    // 启动进程
+                    process.Start();
 
-                // 读取标准输出和标准错误输出
-                string output = process.StandardOutput.ReadToEnd();
-                string error = process.StandardError.ReadToEnd();
+                    // 读取标准输出和标准错误输出
+                    string output = process.StandardOutput.ReadToEnd();
+                    string error = process.StandardError.ReadToEnd();
 
-                // 等待进程执行完成
-                process.WaitForExit();
+                    // 等待进程执行完成
+                    process.WaitForExit();
 
-                // 输出执行结果
-                if (!string.IsNullOrEmpty(output))
-                {
-                    // Console.WriteLine("标准输出:");
-                    // Console.WriteLine(output);
-                    if (output.Contains("successfully", StringComparison.OrdinalIgnoreCase))
+                    // 输出执行结果
+                    if (!string.IsNullOrEmpty(output))
                     {
-                        msg = $"执行成功!";
-                        code = 200;
+                        // Console.WriteLine("标准输出:");
+                        // Console.WriteLine(output);
+                        if (output.Contains("successfully", StringComparison.OrdinalIgnoreCase))
+                        {
+                            msg = $"执行成功!";
+                            code = 200;
+                        }
+                        else
+                        {
+                            msg = $"执行异常:{output}";
+                            code = 1;
+                        }
+
                     }
-                    else
+
+                    if (!string.IsNullOrEmpty(error))
                     {
-                        msg = $"执行异常:{output}";
-                        code = 1;
+                        // Console.WriteLine("错误输出:");
+                        // Console.WriteLine(error);
+                        msg = $"执行失败:{error}";
+                        code = 2;
                     }
-
-                }
-
-                if (!string.IsNullOrEmpty(error))
-                {
-                    // Console.WriteLine("错误输出:");
-                    // Console.WriteLine(error);
-                    msg = $"执行失败:{error}";
-                    code = 2;
                 }
+            } catch (Exception ex) {
+                code = 500;
+                msg = $"{ex.Message},{ex.StackTrace}";
             }
             return (code, msg);
         }

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

@@ -81,6 +81,10 @@ namespace IES.ExamServer.Models
         /// </summary>
         public string? name { get; set; }
         /// <summary>
+        /// 网卡简短名称
+        /// </summary>
+        public string? sname { get; set; }
+        /// <summary>
         /// mac地址
         /// </summary>
         public string? mac { get; set; }

+ 16 - 2
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Models/SignalRClient.cs

@@ -63,8 +63,14 @@
 
     public class CheckFileMessageBody : MessageBody
     {
-       
-       
+        /// <summary>
+        /// 步骤
+        /// </summary>
+        public int step { get; set; }
+        /// <summary>
+        /// 当前步骤是否结束
+        /// </summary>
+        public int finish { get; set; }
     }
     public class MessageContent
     {
@@ -96,6 +102,14 @@
         /// 数据名称
         /// </summary>
         public string? dataName {  get; set; }
+        /// <summary>
+        /// 步骤
+        /// </summary>
+        public int step { get; set; }
+        /// <summary>
+        /// 0 未完成,1完成
+        /// </summary>
+        public int finish { get; set; }
     }
  
     public class SignalRClient

+ 60 - 13
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/IndexService.cs

@@ -26,13 +26,16 @@ namespace IES.ExamServer.Services
         /// <param name="_liteDBFactory"></param>
         /// <param name="connectionService"></param>
         /// <returns></returns>
-        public static async Task<(int code, int code_cer ,int code_hosts,int code_zip, string msg)> ModifyHosts(string? ip,IMemoryCache _memoryCache,LiteDBFactory _liteDBFactory,CenterServiceConnectionService connectionService)
+        public static async Task<(int code, int code_cer ,int code_hosts,int code_zip, string msg,string hosts_msg, string cer_msg,string zip_msg,Network? primaryNetwork)> ModifyHosts(string? ip,IMemoryCache _memoryCache,LiteDBFactory _liteDBFactory,CenterServiceConnectionService connectionService)
         {
-           (string? hostsIp,string hostsMsg) = SystemScriptHelper.FindIpAddressForDomain("exam.habook.local");
+            Network? primaryNetwork = null;
+          
             int code = 0, code_cer = 0,code_hosts=0,code_zip=0 ;
+            string hosts_msg = string.Empty, cer_msg = string.Empty, zip_msg = string.Empty;
             StringBuilder sb = new StringBuilder();
             try
             {
+                (string? hostsIp, string hostsMsg) = SystemScriptHelper.FindIpAddressForDomain("exam.habook.local");
                 string batscriptPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "batscript");
                 if (!Directory.Exists(batscriptPath))
                 {
@@ -55,21 +58,39 @@ namespace IES.ExamServer.Services
                         var res = ProcessHelper.ExecuteProcess(pathBatNew);
                         sb.Append(res.msg);
                         code_cer = res.code;
+                        switch (res.code) 
+                        {
+                            case 200:
+                                cer_msg = "证书安装成功";
+                                break;
+                            case 1:
+                                cer_msg = $"证书安装异常:{res.msg}";
+                                break;
+                            case 2:
+                                cer_msg = $"证书脚本运行异常:{res.msg}";
+                                break;
+                            case 500:
+                                cer_msg = $"证书代码执行异常:{res.msg}";
+                                break;
+
+                        }
                     }
                     else
                     {
                         code_cer = 401;
                         sb.Append("请使用管理员身份运行本程序,如果已经安装过脚本请忽略!");
+                        cer_msg = $"请使用管理员身份安装证书!";
                     }
                 }
                 else
                 {
                     code_cer = 200;
+                    cer_msg = $"证书已经安装!";
                 }
                 //获取主站配置信息。
                 ServerDevice serverDevice = _memoryCache.Get<ServerDevice>(Constant._KeyServerDevice);
                 var primaryNetworks=   _liteDBFactory.GetLiteDatabase().GetCollection<Network>().FindAll().ToList();
-                Network? primaryNetwork = null;
+               
                 //传入的ip为不为空,切换
                 if (!string.IsNullOrWhiteSpace(ip) )
                 {
@@ -126,20 +147,38 @@ namespace IES.ExamServer.Services
                             var resHosts = ProcessHelper.ExecuteProcess(pathBatHostsNew);
                             sb.Append(resHosts.msg);
                             code_hosts = resHosts.code;
+                            switch (resHosts.code)
+                            {
+                                case 200:
+                                    hosts_msg = "IP域名映射成功";
+                                    break;
+                                case 1:
+                                    hosts_msg = $"IP域名映射异常:{resHosts.msg}";
+                                    break;
+                                case 2:
+                                    hosts_msg = $"IP域名映射脚本运行异常:{resHosts.msg}";
+                                    break;
+                                case 500:
+                                    hosts_msg = $"IP域名映射代码执行异常:{resHosts.msg}";
+                                    break;
+
+                            }
                         }
                         else
                         {
                             code_hosts = 401;
                             sb.Append("请使用管理员身份执行本程序!");
+                            hosts_msg = $"请使用管理员身份映射IP域名!";
                         }
                     }
                     else
                     {
                         code_hosts = 200;
                         sb.Append("IP域名映射已存在,无需再次映射!");
+                        hosts_msg = $"IP域名映射已存在,无需再次映射!";
                     }
-                    string scriptPath= Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "script");
-                    if (!Directory.Exists(scriptPath)) 
+                    string scriptPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "script");
+                    if (!Directory.Exists(scriptPath))
                     {
                         Directory.CreateDirectory(scriptPath);
                     }
@@ -150,12 +189,14 @@ namespace IES.ExamServer.Services
                     {
                         code_zip = 200;
                         sb.Append(res.msg);
-                        
+                        zip_msg = res.msg;
+
                     }
                     else
                     {
                         code_zip = 400;
                         sb.Append("脚本文件创建异常!");
+                        zip_msg = res.msg;
                     }
                     serverDevice!.networks.ForEach(x =>
                     {
@@ -163,12 +204,13 @@ namespace IES.ExamServer.Services
                         x.batscriptZip = null;
                         if (x.id!.Equals(primaryNetwork.id))
                         {
-                            x.primary = code_hosts ==200? 1:0;
-                            x.batscriptZip = res.res? "script/student_script.zip" : null;
+                            x.primary = code_hosts == 200 ? 1 : 0;
+                            x.batscriptZip = res.res ? "script/student_script.zip" : null;
                         }
                     });
                     //更新设备的主站设备信息
                     connectionService.serverDevice = serverDevice;
+                    connectionService.primaryNetwork = primaryNetwork;
                     _memoryCache.Set<ServerDevice>(Constant._KeyServerDevice, serverDevice);
                     _liteDBFactory.GetLiteDatabase().GetCollection<ServerDevice>().Upsert(serverDevice);
                     //清理后再保存,保证只有一条主站数据。
@@ -178,14 +220,18 @@ namespace IES.ExamServer.Services
                     code = 200;
                     sb.Append("证书安装成功,域名IP绑定成功,脚本文件创建成功!");
                 }
+                else {
+                    hosts_msg = $"未匹配到可用网卡和IP";
+                    code_hosts = 400;
+                }
             }
             catch (Exception ex)
             {
                 code = 500;
-                //_logger.LogError($"域名IP绑定错误。{ex.Message},{ex.StackTrace}");
-                return (500,code_cer,code_hosts,code_zip, $"域名IP绑定错误,{ex.Message},{ex.StackTrace}");
+               Console.WriteLine($"ip bind error。{ex.Message},{ex.StackTrace}");
+                return (500,code_cer,code_hosts,code_zip, $"域名IP绑定错误,{ex.Message},{ex.StackTrace}",hosts_msg,cer_msg,zip_msg, primaryNetwork);
             }
-            return (code, code_cer, code_hosts, code_zip, sb.ToString());
+            return (code, code_cer, code_hosts, code_zip, sb.ToString(), hosts_msg, cer_msg, zip_msg, primaryNetwork);
         }
 
 
@@ -455,7 +501,8 @@ namespace IES.ExamServer.Services
                     {
                         physical = 1;
                     }
-                    var name = $"{nic.Name}-{nic.Description}";
+                    var name = $"{nic.Description}";
+                    var sname = $"{nic.Name}";
                     var mac = nic.GetPhysicalAddress().ToString();
                     var properties = nic.GetIPProperties();
                     var unicastAddresses = properties.UnicastAddresses;
@@ -464,7 +511,7 @@ namespace IES.ExamServer.Services
                         if (unicast.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                         {
                             var ip = unicast.Address.ToString();
-                            Network network = new Network() {id=ShaHashHelper.GetSHA1($"{mac}-{name}"), mac=mac, ip=ip, name= name, physical=physical };
+                            Network network = new Network() {id=ShaHashHelper.GetSHA1($"{mac}-{sname}-{name}"), mac=mac, ip=ip, name= name,sname=sname, physical=physical };
                             if (!string.IsNullOrWhiteSpace(mac.ToString())  && !mac.Equals("000000000000"))
                             {
                                 device.networks.Add(network);

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

@@ -278,7 +278,7 @@ namespace IES.ExamServer.Services
         /// <param name="_liteDBFactory"></param>
         /// <returns></returns>
         public async static Task<(List<string> successMsgs, List<string> errorMsgs)> CheckFile(EvaluationClient evaluationLocal, List<string> successMsgs,List<string> errorMsgs, IHubContext<SignalRExamServerHub> _signalRExamServerHub, 
-            IMemoryCache _memoryCache, ILogger _logger, string deviceId,string evaluationPath,string grant_type)
+            IMemoryCache _memoryCache, ILogger _logger, string deviceId,string evaluationPath,string grant_type,int step=0)
         {
            
         
@@ -306,7 +306,7 @@ namespace IES.ExamServer.Services
                     
                 }
                 await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, grant_type,
-                    new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content="评测名单文件(groupList.json)" }, true);
+                    new MessageContent { step=step, dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content="评测名单文件(groupList.json)" }, true);
                 content = msg_status.Equals(Constant._Message_status_success) ? "成功" : "失败";
                 if (msg_status.Equals(Constant._Message_status_success)|| msg_status.Equals(Constant._Message_status_info))
                 {
@@ -363,7 +363,7 @@ namespace IES.ExamServer.Services
                     //数据格式:  [检查][成功/失败][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, grant_type,
-                        new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content="评测数据文件(evaluation.json)" }, true);
+                        new MessageContent { step = step, dataId =evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content="评测数据文件(evaluation.json)" }, true);
                     content = msg_status.Equals(Constant._Message_status_success) ? "成功" : "失败";
                     if (msg_status.Equals(Constant._Message_status_success)|| msg_status.Equals(Constant._Message_status_info))
                     {
@@ -383,7 +383,7 @@ namespace IES.ExamServer.Services
                            
                             msg_status=Constant._Message_status_error;
                             await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, grant_type,
-                                new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content="评测数据文件(evaluation.json),文件读取失败!" }, true);
+                                new MessageContent { step = step, dataId =evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content="评测数据文件(evaluation.json),文件读取失败!" }, true);
                             errorMsgs.Add("评测数据文件(evaluation.json),文件读取失败!");
                         }
                         else
@@ -394,7 +394,7 @@ namespace IES.ExamServer.Services
                                
                                 
                                 await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, grant_type,
-                                    new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="评测数据文件(evaluation.json),读取评测基本信息..." }, true);
+                                    new MessageContent { step = step, dataId =evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="评测数据文件(evaluation.json),读取评测基本信息..." }, true);
                                 successMsgs.Add($"评测数据文件(evaluation.json),读取评测基本信息...");
                                 if (!string.IsNullOrWhiteSpace(evaluationLocal.blobHash) && evaluationLocal.blobHash.Equals(evaluationClient.blobHash)
                                     &&(evaluationLocal.blobTime==evaluationClient.blobTime)
@@ -412,7 +412,7 @@ namespace IES.ExamServer.Services
                                 }
 
                                 await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, grant_type,
-                                    new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="评测数据文件(evaluation.json),校验评测基本信息..." }, true);
+                                    new MessageContent { step = step, dataId =evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="评测数据文件(evaluation.json),校验评测基本信息..." }, true);
                                 content = msg_status.Equals(Constant._Message_status_success)||msg_status.Equals(Constant._Message_status_info) ? "成功" : "失败";
                                 if (msg_status.Equals(Constant._Message_status_success)|| msg_status.Equals(Constant._Message_status_info))
                                 {
@@ -429,7 +429,7 @@ namespace IES.ExamServer.Services
                                
                                 msg_status=Constant._Message_status_error;
                                 await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, grant_type,
-                                new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content="评测数据文件(evaluation.json),读取评测基本信息失败!" }, true);
+                                new MessageContent { step = step, dataId =evaluationLocal.id, dataName=evaluationLocal.name, messageType= Constant._Message_type_check, status=msg_status, content="评测数据文件(evaluation.json),读取评测基本信息失败!" }, true);
                                 errorMsgs.Add("评测数据文件(evaluation.json),读取评测基本信息失败!");
                             }
 
@@ -446,14 +446,14 @@ namespace IES.ExamServer.Services
                             {
                                 msg_status=Constant._Message_status_info;
                                 await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, grant_type,
-                                    new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="评测数据文件(evaluation.json),读取评测试卷信息..." }, true);
+                                    new MessageContent { step = step, dataId =evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content="评测数据文件(evaluation.json),读取评测试卷信息..." }, true);
                                 successMsgs.Add($"评测数据文件(evaluation.json),读取评测试卷信息...");
                                 string pattern = @"paper/[^/]+/([^/]+/[^/]+\.[^/]+)";
                                 foreach (var evaluationExam in evaluationExams!)
                                 {
                                     msg_status=Constant._Message_status_info;
                                     await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, grant_type,
-                                        new MessageContent { dataId=evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content=$"校验评测科目试卷:{evaluationExam.subjectName}-{evaluationExam.examName}" }, true);
+                                        new MessageContent { step = step, dataId =evaluationLocal.id, dataName=evaluationLocal.name, messageType=Constant._Message_type_message, status=msg_status, content=$"校验评测科目试卷:{evaluationExam.subjectName}-{evaluationExam.examName}" }, true);
                                     successMsgs.Add($"校验评测科目试卷:{evaluationExam.subjectName}-{evaluationExam.examName}");
                                     string path_papers = Path.Combine(evaluationPath, "papers");
                                     var papers_files = FileHelper.ListAllFiles(path_papers);
@@ -531,7 +531,8 @@ namespace IES.ExamServer.Services
                                         await _signalRExamServerHub.SendMessage(_memoryCache, _logger, deviceId, grant_type,
                                             new MessageContent
                                             {
-                                                dataId=evaluationLocal.id,
+                                                step = step,
+                                                dataId =evaluationLocal.id,
                                                 dataName=evaluationLocal.name,
                                                 messageType=Constant._Message_type_message,
                                                 status=paper_msg_status,

+ 116 - 0
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/Services/MusicAIManageService.cs

@@ -0,0 +1,116 @@
+using IES.ExamServer.DI;
+using IES.ExamServer.Helper;
+using IES.ExamServer.Helpers;
+using Microsoft.AspNetCore.Mvc;
+using System.Net.Http;
+using System.Text;
+using System.Text.Json.Nodes;
+
+namespace IES.ExamServer.Services
+{
+    public static class MusicAIManageService
+    {
+
+        /// <summary>
+        /// 检查云端连接状态
+        /// </summary>
+        /// <param name="json"></param>
+        /// <returns></returns>
+        ///[HttpPost("check-cstatus")]
+        public static async Task<JsonNode> CheckCStatus( IHttpClientFactory _httpClientFactory,CenterServiceConnectionService _connectionService)
+        {
+            JsonNode? json = null;
+            try {
+                HttpClient _httpClient = _httpClientFactory.CreateClient();
+                _httpClient.Timeout = new TimeSpan(0, 0, 5);
+                _httpClient.DefaultRequestHeaders.Add("appId", Constant._MusicAIServerAppId);
+                _httpClient.DefaultRequestHeaders.Add("schoolCode", _connectionService.serverDevice?.school?.id);
+                _httpClient.DefaultRequestHeaders.Add("encrypt", "1");
+                string es = AESHelper.Encrypt("{}");
+                // 创建请求体
+                var content = new StringContent(es, Encoding.UTF8, "application/json");
+                HttpResponseMessage httpResponse = await _httpClient.PutAsync($"{_connectionService.musicUrl}/musicLocalCache/thirdLocalCacheConfig", content);
+                if (httpResponse.IsSuccessStatusCode)
+                {
+                    string res = await httpResponse.Content.ReadAsStringAsync();
+                    res = AESHelper.Decrypt(res.Replace("\"", ""));
+                    json = res?.ToObject<JsonNode>();
+                    //return Ok(res);
+                }
+                else
+                {
+                    string res = await httpResponse.Content.ReadAsStringAsync();
+                    res = AESHelper.Decrypt(res);
+                    //  return Ok(res);
+                }
+            } catch (Exception ex) 
+            {
+                
+            }
+            return json;
+        }
+
+
+    }
+
+    public class MusicAIStatus
+    {
+        /// <summary>
+        /// id
+        /// </summary>
+        public int id { get; set; }
+        /// <summary>
+        /// 醍魔豆研发学校
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 联系人
+        /// </summary>
+        public string contactName { get; set; }
+        /// <summary>
+        /// 编码
+        /// </summary>
+        public string phoneNumber { get; set; }
+        /// <summary>
+        /// 简码
+        /// </summary>
+        public string code { get; set; }
+        /// <summary>
+        /// 类型
+        /// </summary>
+        public string type { get; set; }
+        /// <summary>
+        /// 编号
+        /// </summary>
+        public int serialNumber { get; set; }
+        /// <summary>
+        /// 四川省
+        /// </summary>
+        public string province { get; set; }
+        /// <summary>
+        /// 成都市
+        /// </summary>
+        public string city { get; set; }
+        /// <summary>
+        /// 锦江区
+        /// </summary>
+        public string county { get; set; }
+        /// <summary>
+        /// 地址
+        /// </summary>
+        public string address { get; set; }
+        /// <summary>
+        /// 本地缓存ip
+        /// </summary>
+        public string localCacheIp { get; set; }
+        /// <summary>
+        /// 缓存状态
+        /// </summary>
+        public int cacheStatus { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public string heartTime { get; set; }
+    }
+
+}

+ 1 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamServer/appsettings.json

@@ -30,7 +30,7 @@
     "Delay": 500,
     "CenterUrl": "https://www.teammodel.cn",
     "NotifyUrl": "https://www.winteach.cn",
-    "MusicUrl": "https://musicapi.winteach.cn/api/v1"
+    "MusicUrl": "https://tmdapi.yosocloud.com/api/v1"
   },
   "ExamClient": {
     "Domain": "habook.local"

+ 74 - 4
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/admin/ActivityManage.vue

@@ -273,6 +273,18 @@
         <el-dialog title="试卷详情" width="50%" :visible.sync="isShowPaper" class="test-paper">
             <TestPaper v-if="isShowPaper" :paperInfo="paperInfo"></TestPaper>
         </el-dialog>
+        <el-dialog title="正在下载资源,请勿离开" width="30%" :visible.sync="isUpload" :close-on-click-modal="false" :close-on-press-escape="false" :show-close="false">
+            <el-progress :percentage="uploadProgress" :status="uploadProgress === 100 ? 'success' : null"></el-progress>
+            <p v-for="(item, index) in downloadType" :key="index" style="margin: 10px; font-size: 16px;">
+                <i class="el-icon-success" v-show="item.isOk && !item.errorNum" style="color: #37a326; margin-right: 5px;"></i>
+                <i class="el-icon-warning" v-show="item.isOk && item.errorNum" style="color: #fb652c; margin-right: 5px;"></i>
+                <i class="el-icon-more" v-show="!item.isOk" style="margin-right: 5px;"></i>
+                <span :style="{'color': item.isOk ? (item.errorNum ? '#fb652c' : '#37a326') : ''}">{{ item.type === 1 ? '云端检测' : item.type === 2 ? '下载评测信息文件' : item.type === 3 ? '下载评测名单' : item.type === 4 ? '下载评测试卷' : item.type === 5 ? '检查评测数据完整性' : '打包评测数据' }}</span>
+            </p>
+            <span slot="footer" class="dialog-footer" v-show="uploadProgress === 100">
+                <el-button type="primary" @click="isUpload = false">确定</el-button>
+            </span>
+        </el-dialog>
     </el-container>
 </template>
 
@@ -280,7 +292,7 @@
 import {jwtDecode} from 'jwt-decode'
 import { Loading } from 'element-ui'
 import TestPaper from './TestPaper.vue'
-import vuescroll from 'vuescroll'
+import SignalRService from '@/utils/signalR';
 
 export default {
     components: { TestPaper },
@@ -329,6 +341,15 @@ export default {
                 }
             },
             isPushAnswer: false,
+            isUpload: false,
+            signalR: null,
+            downloadType: [
+                {
+                    isOk: false,
+                    message: '云端检测',
+                    type: 1
+                }
+            ], // 1:检测云端  2:评测信息  3:名单  4:试卷  5:检查数据完整  6:打包
         }
     },
     created() {
@@ -652,12 +673,22 @@ export default {
             })
         },
         updatePackage() {
+            this.downloadType = [
+                {
+                    isOk: false,
+                    message: '云端检测',
+                    type: 1,
+                    errorNum: 0
+                }
+            ]
+            this.createConn()
             this.openErrorMsgs = []
-            this.isLoading = Loading.service({
+            /* this.isLoading = Loading.service({
                 lock: true,
                 text: '资源下载中...',
                 background: 'rgba(0, 0, 0, 0.7)'
-            })
+            }) */
+            this.isUpload = true
             let params = {
                 deviceId: this.deviceId,
                 evaluationId: this.evaluationClient.id,
@@ -690,7 +721,7 @@ export default {
                     this.showErrorMsgs = true
                 }
             }).finally(() => {
-                this.isLoading.close()
+                // this.isLoading.close()
             })
         },
         getRoundList() {
@@ -842,11 +873,50 @@ export default {
                 path: "/login/admin"
             });
         },
+        createConn() {
+            /* 
+                grant_type取值:
+                public static readonly string _Message_grant_type_check_file = "check_file"; //检查文件
+                public static readonly string _Message_grant_type_ies_qrcode_login = "ies_qrcode_login"; //二维码扫描登陆
+                public static readonly string _Message_grant_type_download_file = "download_file"; //下载评测试卷
+                public static readonly string _Message_grant_type_upload_data = "upload_data"; //推送学生作答
+            */
+            let apiPrefix = process.env.NODE_ENV === 'production' ? '' : '/api'
+            this.signalR = new SignalRService()
+            this.signalR.initSignalR(`${apiPrefix}/signalr/exam?grant_type=download_file&clientid=${this.deviceId}`)
+            this.signalR.onReceiveConnection((message) => {
+                console.log('signalr连接结果:', message);
+            })
+            this.signalR.onMessageReceived((message) => {
+                // status: -1 error(红),0 info(黑、白),1 success(绿),2 warning(黄)
+                // this.qrCodeToken = JSON.parse(message.content)
+                console.log('22222222222', message);
+                if(message.step && (message.status && message.status != 1)) {
+                    this.downloadType[0].errorNum ++
+                }
+                if(message.step && message.finish) {
+                    this.downloadType.length ? this.downloadType[0].isOk = true : ''
+                    if(this.downloadType.length != 6) this.downloadType.unshift({
+                        isOk: false,
+                        message: message.content,
+                        type: message.step + 1,
+                        errorNum: 0
+                    })
+                }
+            })
+        },
+        format(percentage) {
+            return percentage === 100 ? '下载成功' : `${percentage}%`;
+        }
     },
     computed: {
         selectGroup() {
             return this.evaluationClient.grouplist.filter(item => this.setAnswerInfo.groupId.includes(item.id))
         },
+        uploadProgress() {
+            let num = this.downloadType.filter(item => item.isOk).length
+            return Math.floor(num / 6 * 100)
+        },
     }
 }
 </script>

+ 1 - 1
TEAMModelOS.Extension/IES.Exam/IES.ExamViews/src/view/student/ActivityAnswer.vue

@@ -333,7 +333,7 @@
             <div v-show="messageType === 3">该评量的作答时间已结束,请交卷(<span style="color: red;">{{ modalSecond }}</span>)</div>
             <div v-show="messageType === 4">暂无试题信息,请重新获取试卷</div>
             <span slot="footer" class="dialog-footer">
-                <el-button type="primary" @click="needCountDown ? submitAns() : quitTest()" v-show="messageType === 1">{{ needCountDown ? '确定交卷' : '确定111' }}</el-button>
+                <el-button type="primary" @click="needCountDown ? submitAns() : quitTest()" v-show="messageType === 1">{{ needCountDown ? '确定交卷' : '确定' }}</el-button>
                 <el-button type="primary" @click="messageType === 4 ? quitTest() : submitAns()" v-show="messageType != 1">{{ messageType === 4 ? '确定' : '确定交卷' }}</el-button>
                 <el-button @click="closeWarmMessage()" v-show="messageType === 1 || messageType === 2">{{ messageType === 1 ? '取消' : undo ? '继续作答' : '否,需再检查' }}</el-button>
             </span>

+ 100 - 0
TEAMModelOS.SDK/Models/Cosmos/Student/AppraiseRecord.cs

@@ -0,0 +1,100 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Student
+{
+
+    public class AppraiseRecordBase: CosmosEntity
+    {
+        /**
+        * 学段 id
+        */
+        public string periodId { get; set; }
+        /**
+        * 班级 id
+        */
+        public string classId { get; set; }
+        public string className { get; set; }
+        /**
+        * 学年(组合 id: 学年-semesterId -> 2023-{semesterId})
+        */
+        public string academicYearId { get; set; }
+        /**
+        * 学生/class id
+        */
+        public string targetId { get; set; }
+        public string targetType { get; set; }
+        /**
+        * 学生/class 名字
+        */
+        public string name { get; set; }
+        /**
+        * 学生/class 头像
+        */
+        public string avatar { get; set; }
+        public string gender { get; set; }
+        /**
+        * 表扬次数
+        */
+        public int praiseCount { get; set; }
+        public int criticizeCount { get; set; }
+        /**
+        * 学生得分
+        */
+        public int score { get; set; }
+    }
+    public class AppraiseRecord : AppraiseRecordBase
+    {
+       
+        public List<AppraiseRecordItem> nodes { get; set; } = new List<AppraiseRecordItem>();
+       
+    }
+
+    public class AppraiseRecordDto : AppraiseRecordBase
+    {
+        public AppraiseRecordItem appraise { get; set; }
+    }
+    public class AppraiseRecordItem
+    {
+        public string id { get; set; }
+        public AppraiseTreeNode appraiseNode { get; set; }
+        /**
+        * 用包装类,这样为 null 时就不会持久化
+        */
+        public bool spread { get; set; }
+        public bool pushParent { get; set; }
+        public string creator { get; set; }
+        public string creatorId { get; set; }
+        public long createTime { get; set; }
+        public string device { get; set; }
+    }
+    public class AppraiseTreeNode
+    {
+        public string id { get; set; }
+        public string pid { get; set; }
+        public string name { get; set; }
+        public string[] path { get; set; }
+        public string logo { get; set; }
+        public string creator { get; set; }
+        public string creatorId { get; set; }
+        public long createTime { get; set; }
+        /**
+        * 排序
+        */
+        public int order { get; set; }
+        /**
+        * 分值
+        */
+        public int score { get; set; }
+        /**
+        * 是否表扬? 默认 true
+        */
+        public bool isPraise { get; set; }
+        public double scoreRate { get; set; }
+
+        public List<AppraiseTreeNode> children { get; set; } = new List<AppraiseTreeNode>();
+    }
+}

+ 58 - 0
TEAMModelOS.SDK/Models/Service/OverallEducationService.cs

@@ -1,17 +1,75 @@
 using Microsoft.Azure.Cosmos;
 using System;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
 using System.Text;
 using System.Text.Json;
+using System.Text.Json.Nodes;
 using System.Threading.Tasks;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.Student;
 
 namespace TEAMModelOS.SDK.Models
 {
     public static class OverallEducationService
     {
+
+        public static async Task<string> GetAppraiseRecord(AzureCosmosFactory _azureCosmosFactory, string schoolId,string _studyYear, string semesterId,List<Student> students,HashSet<string> classIds) 
+        {
+          
+            StringBuilder  sqlQ = new StringBuilder($"SELECT c.targetId,c.classId,c.id,c.academicYearId,  b as  appraise   FROM c join b in c.nodes  where c.code = 'AppraiseRecord-{schoolId}' and ARRAY_Contains(b.appraiseNode.path,'提问能力') ");
+            if (!string.IsNullOrWhiteSpace(_studyYear)&& !string.IsNullOrWhiteSpace(semesterId))
+            {
+                sqlQ.Append($" and c.academicYearId ='{_studyYear}-{semesterId}'");
+            }
+            if (classIds.Count > 0)
+            {
+                sqlQ.Append($" and c.classId in ({string.Join(",",classIds.Select(x=>$"'{x}'"))})");
+            }
+            if (students.Count > 0)
+            {
+                sqlQ.Append($" and c.targetId in ({string.Join(",", students.Select(x => $"'{x.id}'"))})");
+            }
+            List<AppraiseRecordDto> appraiseRecords = new List<AppraiseRecordDto>();
+            var result=  await _azureCosmosFactory.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<AppraiseRecordDto>(sqlQ.ToString(), $"AppraiseRecord-{schoolId}");
+            if (result.list.IsNotEmpty()) 
+            {
+                appraiseRecords.AddRange(result.list);
+            } 
+            // 获取当前文化的日历
+            CultureInfo culture = CultureInfo.CurrentCulture;
+            Calendar calendar = culture.Calendar;
+            Dictionary<string, List<AppraiseRecordDto>> dict = new Dictionary<string, List<AppraiseRecordDto>>();
+            foreach (var appraiseRecord in appraiseRecords) 
+            {
+                var date=   DateTimeOffset.FromUnixTimeMilliseconds(appraiseRecord.appraise.createTime);
+                int year = date.Year;
+                // 计算当前时间是一年中的第几周
+                int weekOfYear = calendar.GetWeekOfYear(date.DateTime, culture.DateTimeFormat.CalendarWeekRule, culture.DateTimeFormat.FirstDayOfWeek);
+                string key = $"{appraiseRecord.targetId}::{year}-{weekOfYear}";
+                if (dict.ContainsKey(key))
+                {
+                    dict[key].Add(appraiseRecord);
+                }
+                else 
+                {
+                    dict[key] = new List<AppraiseRecordDto>() { appraiseRecord };
+                }
+            }
+            foreach (var item in dict) 
+            {
+                //正向评价-负向评价,评价次数
+                int count = item.Value.Where(x => x.appraise.appraiseNode.isPraise).Count() - item.Value.Where(x =>! x.appraise.appraiseNode.isPraise).Count();
+                double score = 100 / (1 + Math.Exp(-0.3 * count));//0.3是斜率,用于处理评分值曲线变化
+                string[] sp = item.Key.Split();
+            }
+            //最新一周的数据 ,检查当前最新一周的数据是否大于历史均值,如果小于,则在平均次数上累加当前一周的数据,如果大于则累计在均值中。以防止当前周将均值拉下去。
+
+            return null;
+        }
+
         public static Dictionary<string, object> GetQueryCond(JsonElement request) {
             Dictionary<string, object> dict = new Dictionary<string, object>();
             if (request.TryGetProperty("periodId", out JsonElement periodId) && !string.IsNullOrWhiteSpace($"{periodId}"))

+ 2 - 2
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -829,7 +829,7 @@
 											isShow: this.IES5Menu
 										},
 										// 苏格拉底
-										{
+										/* {
 											icon: "iconfont icon-course-videos",
 											name: this.$t("system.menu.toSokrates2"),
 											router: "#",
@@ -840,7 +840,7 @@
 											permission: "research-read|research-upd",
 											menuName: "schoolSokrate",
 											isShow: true
-										},
+										}, */
 										// 授权管理
 										{
 											icon: "iconfont icon-auth",

+ 1 - 1
TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue

@@ -30,7 +30,7 @@
 				<DropdownMenu slot="list">
 					<div v-for="(item, index) in periods" :key="index">
 						<DropdownItem :name="index">
-							<div class="school-item" v-if="!item.status">
+							<div class="school-item">
 								<span>{{ item.name }}</span>
 							</div>
 						</DropdownItem>

+ 5 - 2
TEAMModelOS/ClientApp/src/store/module/user.js

@@ -246,6 +246,7 @@ export default {
             state.schoolProfile.periods = data.fmtPeriods // 學制
             state.schoolProfile.grades = data.fmtGrades // 年級
             state.schoolProfile.school_base = data.school_base // 区班校基础数据
+            state.schoolProfile.school_base.period = data.school_base.period.filter(item => !item.status) // 区班校基础数据
             // state.schoolProfile.svcStatus = data.svcStatus //学校购买服务模组状态
             Vue.set(state.schoolProfile, 'svcStatus', data.svcStatus)
             state.schoolProfile.productSum = data.productSum //学校购买服务模组信息
@@ -549,8 +550,10 @@ export default {
             let fmtGrades = [];
 
             data.school_base.period.forEach(item => {
-                // 學制List
-                fmtPeriods.push({ 'id': item.id, 'name': item.name })
+                if(!item.status) {
+                    // 學制List
+                    fmtPeriods.push({ 'id': item.id, 'name': item.name })
+                }
 
                 // 年級List
                 item.grades.forEach((gradeItem, gradeIndex) => {

+ 4 - 4
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaLayout.vue

@@ -490,7 +490,7 @@
 						isShow: this.$store.state.config.srvAdr == "China"
 					},
 										// 苏格拉底
-					{
+					/* {
 						icon: "iconfont icon-course-videos",
 						name: this.$t("system.menu.toSokrates"),
 						router: "#",
@@ -501,7 +501,7 @@
 						menuName: "privSokrate",
 						isShow: !this.$jsFn.checkJinNiu() && !this.$jsFn.checkTrain(),
 						to: "privSokrate"
-					},
+					}, */
 					{
 						icon: "iconfont icon-resource",
 						name: `教师发展`,
@@ -570,7 +570,7 @@
 						],
 						isShow: this.isShowArtMenu
 					},
-					{
+					/* {
 						icon: "iconfont icon-sports",
 						name: this.$t("area.base.sportData"),
 						// router: "/area/areaSport",
@@ -582,7 +582,7 @@
 						child: [],
 						isShow: this.isShowStudentMenu,
 						to: "cdwalker"
-					}
+					} */
 				];
 			},
 			studyMenu() {

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-account/stulist/MgtStuList.vue

@@ -549,7 +549,7 @@ export default {
             this.selections.forEach((item) => {
                 map.set(item.id, item);
             });
-            const sortedArray = this.$refs.studentList.excelFilter.map((id) => map.get(id.id)).filter((item) => item !== undefined)
+            const sortedArray = this.$refs.studentList.excelFilter.length ? this.$refs.studentList.excelFilter.map((id) => map.get(id.id)).filter((item) => item !== undefined) : this.selections
             sortedArray.forEach(item => {
                 if (!ids.includes(item.id)) {
                     let irs = this.getDefIRS()

+ 1 - 1
TEAMModelOS/Controllers/Both/EvaluationSyncInfoController.cs

@@ -186,7 +186,7 @@ namespace TEAMModelOS.Controllers.Both
                 return Ok(new { code = 11, msg = "评测名单文件检测异常!" });
             }
             var  blobSas=   _azureStorage.GetContainerSasUri($"{evaluationClient.ownerId}");
-            evaluationClient.openCode=null;
+            //evaluationClient.openCode=null;
             return Ok(new { code = 200, msg = "检测成功!", evaluation = evaluationClient, blobSas.url, blobSas.name, blobSas.sas });
         }
        

+ 27 - 0
TEAMModelOS/Controllers/Common/ActivityController.cs

@@ -1262,6 +1262,33 @@ namespace TEAMModelOS.Controllers
                                 return Ok(new { code = 200, enroll });
                             }
                             return Ok(new { code = 1, msg = "暂无报名数据!", });
+                        } //获取单个教师的报名数据
+                    case bool when $"{grant_type}".Equals("get-multiple-teacher-enroll", StringComparison.OrdinalIgnoreCase):
+                        {
+                            if (!request.TryGetProperty("teacherIds", out JsonElement _teacherIds)) return BadRequest();
+                            if (!request.TryGetProperty("activityId", out JsonElement _activityId)) return BadRequest();
+
+                            List<string> teacherIds = _teacherIds.ToObject<List<string>>();
+                            List<ActivityEnroll> enrolls = new List<ActivityEnroll>();
+                            if (teacherIds.IsNotEmpty())
+                            {
+                                string sql = $"select value c from c where c.id in ({string.Join(",", teacherIds.Select(x => $"'{x}'"))})";
+                                var result = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<ActivityEnroll>(sql, $"ActivityEnroll-{_activityId.GetString()}");
+                                if (result.list.IsNotEmpty())
+                                {
+                                    enrolls.AddRange(result.list);
+                                }
+                            }
+                            return Ok(new { code =200, enrolls });
+
+                            //ActivityEnroll enroll = null;
+                            //ResponseMessage responseActivityEnroll = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync($"{_teacherId}", new PartitionKey($"ActivityEnroll-{_activityId.GetString()}"));
+                            //if (responseActivityEnroll.StatusCode == System.Net.HttpStatusCode.OK)
+                            //{
+                            //    enroll = JsonDocument.Parse(responseActivityEnroll.Content).RootElement.ToObject<ActivityEnroll>();
+                            //    return Ok(new { code = 200, enroll });
+                            //}
+                           // return Ok(new { code = 1, msg = "暂无报名数据!", });
                         }
                     //获取邀请的教师列表
                     case bool when $"{grant_type}".Equals("invited-teachers", StringComparison.OrdinalIgnoreCase)

+ 15 - 7
TEAMModelOS/Controllers/Third/Xkw/XkwOAuth2Controller.cs

@@ -105,26 +105,34 @@ namespace TEAMModelOS.Controllers
             {
                 return BadRequest();
             }
-            var client = await GetOpenAuthClient(tmdid,authCode.module, accessToken, domain);
-            if (authCode.agree == 1) {
+
+            if (authCode.agree == 1)
+            {
+                var client = await GetOpenAuthClient(tmdid, authCode.module, accessToken, domain);
                 //获取醍摩豆id的手机号
-                var keys =new List<string> { tmdid};
+                var keys = new List<string> { tmdid };
                 var content = new StringContent(keys.ToJsonString(), Encoding.UTF8, "application/json");
                 string ujson = await _coreAPIHttpService.GetUserInfos(content);
                 List<CoreUser> coreUsers = new List<CoreUser>(0);
                 if (!string.IsNullOrWhiteSpace(ujson))
                 {
                     coreUsers = ujson.ToObject<List<CoreUser>>();
-                    if (coreUsers.Any() ) {
+                    if (coreUsers.Any())
+                    {
                         var coreus = coreUsers.Find(x => x.searchKey.Equals(tmdid));
-                        if (coreus != null && !string.IsNullOrWhiteSpace(coreus.mobile)) {
+                        if (coreus != null && !string.IsNullOrWhiteSpace(coreus.mobile))
+                        {
                             client.Extra = coreUsers.Find(x => x.searchKey.Equals(tmdid))?.mobile;
                         }
                     }
                 }
+                string url = client.GetAuthorizationUrl();
+                return Ok(new { redirect = url });
             }
-            string url = client.GetAuthorizationUrl();
-            return Ok(new { redirect = url });
+            else {
+                return Ok(new { redirect = "" });
+            }
+           
         }
        
         [HttpGet("authorize")]