using Azure.Cosmos; using Azure.Storage.Blobs.Models; using Microsoft.Extensions.Configuration; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Threading.Tasks; using TEAMModelOS.Models; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Extension; using TEAMModelOS.SDK.Models.Cosmos; using TEAMModelOS.SDK.Models.Cosmos.Student; using static TEAMModelOS.SDK.Models.Teacher; namespace TEAMModelOS.SDK.Models { public static class ThirdService { //自动加入学校,加入培训名单,并根据学科进行分组 public static async Task GetScTeacher(ScBindData scBind, Teacher teacher, AzureStorageFactory _azureStorage, AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, IConfiguration _configuration, DingDing _dingDing) { var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt"); List schools = await table.FindListByDict(new Dictionary { { "PartitionKey", "ScSchool" }, { "RowKey", scBind.sid } }); List scTeachers = await table.FindListByDict(new Dictionary { { "PartitionKey", "ScTeacher" }, { "TID", scBind.userid }, { "RowKey", $"{scBind.pxid}" } }); if (schools.IsNotEmpty()) { ScSchool scSchool = schools[0]; if (!string.IsNullOrEmpty(scSchool.schoolCode)) { try { School school = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync(scSchool.schoolCode, new PartitionKey("Base")); if (school != null) { if (scTeachers.IsNotEmpty()) { if (string.IsNullOrEmpty(scTeachers[0].tmdid)) { scTeachers[0].tmdid = teacher.id; scTeachers[0].schoolCode = scSchool.schoolCode; scTeachers[0].areaId = school.areaId; await table.SaveOrUpdate(scTeachers[0]); } } var sc = teacher.schools.Find(x => x.schoolId.Equals(scSchool.schoolCode)); if (sc != null) { if (string.IsNullOrEmpty(sc.status) || !sc.status.Equals("join")) { sc.status = "join"; try { SchoolTeacher schoolTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync(teacher.id, new PartitionKey($"Teacher-{school.id}")); if (schoolTeacher != null) { if (!schoolTeacher.roles.IsEmpty()) { if (!schoolTeacher.roles.Contains("teacher")) { schoolTeacher.roles.Add("teacher"); } } else { schoolTeacher.roles = new List { "teacher" }; } schoolTeacher.status = "join"; schoolTeacher.pk = "Teacher"; schoolTeacher.name = teacher.name; schoolTeacher.picture = teacher.picture; schoolTeacher.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); schoolTeacher.ttl = -1; schoolTeacher.permissions = schoolTeacher.permissions.IsNotEmpty() ? schoolTeacher.permissions : new List(); await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code)); } } catch (CosmosException) { SchoolTeacher schoolTeacher = new SchoolTeacher { id = teacher.id, code = $"Teacher-{school.id}", roles = new List { "teacher" }, permissions = new List(), pk = "Teacher", name = teacher.name, picture = teacher.picture, status = "join", createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), ttl = -1 }; await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code)); } } } else { teacher.schools.Add(new Teacher.TeacherSchool { schoolId = school.id, name = school.name, areaId = school.areaId, picture = school.picture, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), status = "join" }); SchoolTeacher schoolTeacher = new SchoolTeacher { id = teacher.id, code = $"Teacher-{school.id}", roles = new List { "teacher" }, permissions = new List(), pk = "Teacher", name = teacher.name, picture = teacher.picture, status = "join", createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }; await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code)); } await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync(teacher, teacher.id, new PartitionKey("Base")); //处理培训名单 StringBuilder queryText = new StringBuilder($"SELECT distinct value(c) FROM c where c.type='yxtrain'"); List yxtrain = new List(); await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator(queryText: queryText.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"GroupList-{scSchool.schoolCode}") })) { yxtrain.Add(item); } if (yxtrain.IsNotEmpty()) { string nickname = teacher.name; string groupName = null; string groupId = Guid.NewGuid().ToString(); if (scTeachers.IsNotEmpty()) { if (scBind.pid.Equals("1249")) { groupName = $"第三批教师培训组"; } nickname = scTeachers[0].TeacherName; if (!string.IsNullOrEmpty(groupName)) { var mebers = yxtrain.SelectMany(x => x.members).Where(y => !string.IsNullOrEmpty(y.groupName) && y.groupName.Equals(groupName)); if (mebers != null && mebers.Count() > 0) { groupId = mebers.First().groupId; } } else { groupId = null; } } else { groupId = null; } var meber = yxtrain.SelectMany(x => x.members).Where(y => y.id.Equals(teacher.id)); //不在研修名单 if (meber == null || !meber.Any()) { yxtrain[0].members.Add(new Member { id = teacher.id, type = 1, groupId = groupId, groupName = groupName, nickname = nickname }); await GroupListService.UpsertList(yxtrain[0], _azureCosmos, _configuration, _serviceBus, "web"); } else { if (string.IsNullOrEmpty(meber.First().groupId) || string.IsNullOrEmpty(meber.First().groupName)) { meber.ToList().ForEach(x => { x.groupId = groupId; x.groupName = groupName; x.nickname = string.IsNullOrWhiteSpace(x.nickname) ? nickname : x.nickname; }); await GroupListService.UpsertList(yxtrain[0], _azureCosmos, _configuration, _serviceBus, "web"); } } } else { string nickname = teacher.name; string groupName = null; if (scTeachers.IsNotEmpty()) { groupName = scTeachers[0].TeacherXK; nickname = scTeachers[0].TeacherName; } string groupId = null; if (!string.IsNullOrEmpty(groupName)) { groupId = Guid.NewGuid().ToString(); } GroupList groupList = new() { id = Guid.NewGuid().ToString(), code = $"GroupList-{scSchool.schoolCode}", creatorId = teacher.id, type = "yxtrain", year = DateTimeOffset.UtcNow.Year, expire = 0, members = new List { new Member { id = teacher.id, type = 1, groupId = groupId, groupName = groupName, nickname = nickname } }, scope = "school", school = scSchool.schoolCode, name = "研修名单", pk = "GroupList", ttl = -1 }; await GroupListService.UpsertList(groupList, _azureCosmos, _configuration, _serviceBus, "web"); } } } catch (Exception ex) { await _dingDing.SendBotMsg($"OS\n自动加入学校,加入研修名单出现异常:,{ex.Message}\n{ex.StackTrace}GetScTeacher", GroupNames.醍摩豆服務運維群組); } } } return null; } public static async Task<(string accessConfig, Area area, AreaSetting setting)> GetAccessConfig(CosmosClient client, string standard) { Area area = null; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal"). GetItemQueryIterator($"select value(c) from c where c.standard='{standard}'", requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base-Area") })) { area = item; break; } AreaSetting setting = null; if (area != null) { try { setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync(area.id, new PartitionKey("AreaSetting")); } catch (CosmosException) { setting = null; } } if (setting == null || string.IsNullOrEmpty(setting.accessConfig)) { return (null, null, null); } else { return (setting.accessConfig, area, setting); } } public static async Task> GetDiagnosisList(CosmosClient client, string standard, DingDing _dingDing, AreaSetting setting, HttpClient _httpClient, Teacher teacher, TEAMModelOS.Models.Option _option, AzureStorageFactory _azureStorage) { List abilityNos = new(); var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt"); setting.accessConfig.ToObject().TryGetProperty("config", out JsonElement _config); if ($"{_config}".Equals("scsyxpt")) { var binds = teacher.binds.FindAll(x => x.type.Equals("scsyxpt")); var datas = binds.SelectMany(x => x.data).Where(y => y.Contains("scsyxpt")); HashSet pxids = new(); if (datas != null) { datas.ToList().ForEach(x => { var data = x.ToObject(); if (!string.IsNullOrEmpty(data?.pxid)) { pxids.Add(data.pxid); } }); } foreach (var pxid in pxids) { List teachers = await table.FindListByDict(new Dictionary { { "PartitionKey", "ScTeacher" }, { "PXID", pxid } }); Dictionary dict = new(); if (teachers.IsNotEmpty()) { dict = new Dictionary() { { "accessConfig", setting.accessConfig }, { "pxid", pxid }, { "areaId", setting.id }, { "schoolCode", teachers[0].schoolCode } }; } else { dict = new Dictionary() { { "accessConfig", setting.accessConfig }, { "pxid", pxid }, { "areaId", setting.id } }; } (int status, string json) = await ScsStudyApisService.GetDiagnosisListByProject_V2(_httpClient, _dingDing, _azureStorage, setting.id, setting.accessConfig, pxid, teachers[0].schoolCode); //(int status, string json) = await httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetDiagnosisListByProject_V2"); if (status == 200) { List nos = json.ToObject>(); if (nos.IsNotEmpty()) { abilityNos.AddRange(nos); } } } } //获取能力点 List abilities = null; if (abilityNos.IsNotEmpty()) { abilities = new List(); StringBuilder sql = new StringBuilder($"select value(c) from c where c.no in ({string.Join(",", abilityNos.Select(x => $"'{x}'"))})"); await foreach (var item in client.GetContainer("TEAMModelOS", "Normal") .GetItemQueryIterator(queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{standard}") })) { abilities.Add(item); } } return abilities; } //5.3.1.22学员校本教研PDF(每人可以返回多条)批量回写-UploadSBTARPDFListV2 public async static Task<(int t53122OK, List msgs, List allRightOfflineRecords)> check53122(TeacherTrain teacherTrain, List msgs, string school, string schoolPrefix, string sas, AzureStorageFactory _azureStorage) { int t53122OK = 1; if (teacherTrain.offlineRecords.Count <= 0) { t53122OK = 0; msgs.Add(new CodeValue("offlineRecord-count", $"文件个数为0")); } List allRightOfflineRecords = new List(); var hasUrl = teacherTrain.offlineRecords.Where(x => !string.IsNullOrWhiteSpace(x.url) && x.size > 0); if (!hasUrl.Any()) { t53122OK = 0; msgs.Add(new CodeValue("offlineRecord-url", $"需要上传的校本研修作业至少有一个。")); } if (teacherTrain.offlineReport == null) { t53122OK = 0; msgs.Add(new CodeValue("offlineReport", $"校本研修汇总报告未生成。")); } List unexistUrl = new List(); foreach (var url in hasUrl) { string blobItem = url.url.Replace($"{schoolPrefix}/", ""); bool Exist = await _azureStorage.GetBlobContainerClient(school).GetBlobClient(blobItem).ExistsAsync(); if (!Exist) { unexistUrl.Add($"{url.url}?{sas}"); } else { allRightOfflineRecords.Add(url); } } if (unexistUrl.Any() && hasUrl.Count() > 0 && hasUrl.Count() == unexistUrl.Count) { t53122OK = 0; msgs.Add(new CodeValue("offlineRecord-url-unexist", $"校本研修文件不存在,{string.Join(" , ", unexistUrl)}")); } //不需要检查每一个校本研修的文件记录。 //teacherTrain.offlineRecords.ForEach(x => { // if (string.IsNullOrEmpty(x.url)) { // msgs.Add(new CodeValue("offlineRecord-url", $"链接为空")); // } // if (x.size<=0) // { // msgs.Add(new CodeValue("offlineRecord-size", $"文件大小")); // } //}); return (t53122OK, msgs, allRightOfflineRecords); } //5.3.1.17学员课堂实录批量回写-UploadKTSLList public async static Task<(int t53117OK, List msgs)> check53117(TeacherTrain teacherTrain, List msgs, string school, string schoolPrefix, string sas, AzureStorageFactory _azureStorage) { //校验 基本情况是否满足 int t53117OK = 1; if (teacherTrain.classTime <= 0) { msgs.Add(new CodeValue("classTime", $"未获得学时:{teacherTrain.classTime}")); t53117OK = 0; } if (teacherTrain.teacherClasses.Count() <= 0) { msgs.Add(new CodeValue("teacherClasses", $"未上传课堂实录:{teacherTrain.teacherClasses.Count()}个视频")); t53117OK = 0; } teacherTrain.teacherClasses.ForEach(x => { if (string.IsNullOrWhiteSpace(x.url)) { t53117OK = 0; msgs.Add(new CodeValue("teacherClasses", $"课堂实录链接无效")); } }); List unexistUrl = new List(); foreach (var url in teacherTrain.teacherClasses) { string blobItem = url.url.Replace($"{schoolPrefix}/", ""); bool Exist = await _azureStorage.GetBlobContainerClient(school).GetBlobClient(blobItem).ExistsAsync(); if (!Exist) { unexistUrl.Add($"{url.url}?{sas}"); } } if (unexistUrl.Any()) { t53117OK = 0; msgs.Add(new CodeValue("teacherClasses-url-unexist", $"课堂实录文件不存在,{string.Join(" , ", unexistUrl)}")); } return (t53117OK, msgs); } //5.3.1.12学员培训基本情况批量回写-UpdateTeacherListSituation public static (int t53112OK, List msgs) check53112(TeacherTrain teacherTrain, List msgs) { //校验 基本情况是否满足 int t53112OK = 1; if (teacherTrain.finalScore <= 0) { //总体认定结果0、未认定 1、合格 2、优秀 3、不合格 4、其他 msgs.Add(new CodeValue("finalScore", $"最终评定结果参数:{teacherTrain.finalScore}")); t53112OK = 0; } //if (string.IsNullOrEmpty(teacherTrain.summary) || teacherTrain.summary.Length > 300) //{ // string msg = string.IsNullOrEmpty(teacherTrain.summary) ? "未填写" : teacherTrain.summary.Length > 300 ? "字数超过300." : ""; // msgs.Add(new CodeValue("summary", $"教师培训总结:{msg}")); // t53112OK = 0; //} if (!string.IsNullOrEmpty(teacherTrain.summary) && teacherTrain.summary.Length > 300) { //string msg = string.IsNullOrEmpty(teacherTrain.summary) ? "未填写" : teacherTrain.summary.Length > 300 ? "字数超过300." : ""; msgs.Add(new CodeValue("summary", $"教师培训总结:字数超过300.")); t53112OK = 0; } if (teacherTrain.totalTime <= 0) { msgs.Add(new CodeValue("totalTime", $"未获得学时:{teacherTrain.totalTime}")); t53112OK = 0; } return (t53112OK, msgs); } //5.3.1.13学员能力点测评结果批量回写-UpdateTeacherListDiagnosis public async static Task<(int t53113OK, List msgs, List abilitySubs, List allRightAbility)> check53113(AzureCosmosFactory _azureCosmos, TeacherTrain teacherTrain, ScTeacherDiagnosis diagnosis, List msgs, string school, string schoolPrefix, string sas, AzureStorageFactory _azureStorage) { //校验 基本情况是否满足 int t53113OK = 1; List allRightAbility = new List(); List abilitySubs = new List(); if (teacherTrain.currency.videoTime <= 0) { msgs.Add(new CodeValue("videoTime", $"视频学习时长:{teacherTrain.currency.videoTime}")); t53113OK = 0; } if (teacherTrain.currency.submitTime <= 0) { msgs.Add(new CodeValue("submitTime", $"认证材料学习:{teacherTrain.currency.submitTime}")); t53113OK = 0; } if (teacherTrain.currency.teacherAilities.Count <= 0) { msgs.Add(new CodeValue("teacherAilities", $"已学习能力点:0")); t53113OK = 0; } try { if (diagnosis != null) { if (!string.IsNullOrWhiteSpace(diagnosis.abilityNos)) { List nos = diagnosis.abilityNos.ToObject>(); if (nos.Count > 0 && teacherTrain.currency.teacherAilities.Count > 0) { var notin = nos.Except(teacherTrain.currency.teacherAilities.Select(x => x.no).Where(z => !string.IsNullOrWhiteSpace(z))); if (notin.Any()) { msgs.Add(new CodeValue("diagnosisNos", $"省平台勾选的能力点编号为学习完成:省平台:{string.Join(",", nos.OrderBy(x => x))}" + $" ,已学习:{string.Join(",", teacherTrain.currency.teacherAilities.Select(x => x.no).OrderBy(x => x))} ")); t53113OK = 0; } else { string insql = ""; if (teacherTrain.currency.teacherAilities.IsNotEmpty()) { var abilites = teacherTrain.currency.teacherAilities.Where(c => !string.IsNullOrWhiteSpace(c.no) && nos.Contains(c.no)); insql = $" where c.id in ({string.Join(",", abilites.Select(o => $"'{o.id}'"))})"; } //认证材料 await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher") .GetItemQueryIterator(queryText: $"select value(c) from c {insql}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilitySub-{teacherTrain.school}-{teacherTrain.id}") })) { abilitySubs.Add(item); } if (abilitySubs.Count() <= 3) { abilitySubs.ForEach(ab => { var x = teacherTrain.currency.teacherAilities.Find(x => x.id.Equals(ab.id)); if (x == null || !ab.uploads.Any()) { t53113OK = 0; msgs.Add(new CodeValue("uploads", $"未上传认证材料:{x.no},{x.name}")); } if (x.zpscore <= 0) { t53113OK = 0; msgs.Add(new CodeValue("zpscore", $"认证材料,没有完成自评:{x.no},{x.name},{x.zpscore}")); } if (x.hpscore <= 0) { x.hpscore = 1; } if (x.xzscore <= 0) { x.xzscore = 1; } }); foreach (AbilitySub abilitySub in abilitySubs) { //当前能力点上传的文件是否完全有效 bool isAllRight = true; List urlUn = new List(); foreach (var subUpload in abilitySub.uploads) { foreach (var url in subUpload.urls) { string blobItem = url.url.Replace($"{schoolPrefix}/", ""); bool Exist = await _azureStorage.GetBlobContainerClient(school).GetBlobClient(blobItem).ExistsAsync(); if (!Exist) { isAllRight = false; urlUn.Add($"{url.url}?{sas}"); } } } if (isAllRight) { allRightAbility.Add(abilitySub); } else { t53113OK = 0; var x = teacherTrain.currency.teacherAilities.Find(x => x.id.Equals(abilitySub.id)); msgs.Add(new CodeValue("uploads-url", $"{x.no},{x.name}上传的认证材料文件失效:{string.Join(" , ", urlUn)}")); } } } else { //一个都没上传 if (!abilitySubs.SelectMany(upsl => upsl.uploads).Any()) { t53113OK = 0; msgs.Add(new CodeValue("uploads-all", $"没有上传认证材料。")); } else { //检查上传了认证材料的能力点,超过三个的。 var uploaded = abilitySubs.FindAll(x => x.uploads.Count > 0); //不足三个的则需要记录 if (uploaded.Count < 3) { t53113OK = 0; ///少于三个的,需要判断另外的不满足情况的 abilitySubs.RemoveAll(x => x.uploads.Count > 0); abilitySubs.ForEach(ab => { var x = teacherTrain.currency.teacherAilities.Find(x => x.id.Equals(ab.id)); if (x == null || !ab.uploads.Any()) { t53113OK = 0; msgs.Add(new CodeValue("uploads", $"未上传认证材料:{x.no},{x.name}")); } if (x.zpscore <= 0) { t53113OK = 0; msgs.Add(new CodeValue("zpscore", $"认证材料,没有完成自评:{x.no},{x.name},{x.zpscore}")); } if (x.hpscore <= 0) { t53113OK = 0; //如果只有三个,且互评为未评状态,则直接为合格。 x.hpscore = 1; msgs.Add(new CodeValue("hpscore", $"认证材料,没有完成互评:{x.no},{x.name},{x.hpscore}")); } if (x.xzscore <= 0) { t53113OK = 0; msgs.Add(new CodeValue("xzscore", $"认证材料,没有完成小组评:{x.no},{x.name},{x.xzscore}")); } }); } ///如果上传的文件,失效导致不满足3个能力点 List un_msg = new List(); //检查已经上传的文件是否正确。 foreach (AbilitySub abilitySub in uploaded) { //当前能力点上传的文件是否完全有效 bool isAllRight = true; List urlUn = new List(); foreach (var subUpload in abilitySub.uploads) { foreach (var url in subUpload.urls) { string blobItem = url.url.Replace($"{schoolPrefix}/", ""); bool Exist = await _azureStorage.GetBlobContainerClient(school).GetBlobClient(blobItem).ExistsAsync(); if (!Exist) { isAllRight = false; urlUn.Add($"{url.url}?{sas}"); } } } if (isAllRight) { allRightAbility.Add(abilitySub); } else { var x = teacherTrain.currency.teacherAilities.Find(x => x.id.Equals(abilitySub.id)); un_msg.Add(new CodeValue("uploads-url", $"{x.no},{x.name}上传的认证材料文件失效:{string.Join(" , ", urlUn)}")); } } if (allRightAbility.Count < 3) { t53113OK = 0; msgs.AddRange(un_msg); } } } } } else { msgs.Add(new CodeValue("teacherAilities", $"未同步省平台挑选的能力点")); t53113OK = 0; } } else { msgs.Add(new CodeValue("teacherAilities", $"未同步省平台挑选的能力点")); t53113OK = 0; } } else { msgs.Add(new CodeValue("teacherAilities", $"未同步省平台挑选的能力点")); t53113OK = 0; } } catch (Exception ex) { throw new Exception($"{ex.StackTrace},{ex.Message}"); } if (allRightAbility.Count < 3) { t53113OK = 0; msgs.Add(new CodeValue("uploads-count", $"完整上传且有效的认证材料的 能力点数量小于3,当前数量:{allRightAbility.Count}")); } return (t53113OK, msgs, abilitySubs, allRightAbility); } //推送作答数据 public static async Task<(string id, int code)> pushAnswers(CosmosClient client, AzureStorageFactory _azureStorage, IHttpClientFactory _httpClient, string activityId, string code) { if (string.IsNullOrEmpty(activityId)) { try { ExamInfo info = null; var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(activityId.ToString(), new PartitionKey($"Exam-{code}")); if (response.Status == 200) { using var json = await JsonDocument.ParseAsync(response.ContentStream); info = json.ToObject(); } List classResults = new(); if (info.scope.Equals("school", StringComparison.OrdinalIgnoreCase)) { var queryResult = $"select value(c) where c.examId ='{activityId}' and c.pk = 'ExamClassResult' "; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator(queryText: queryResult, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{info.school}") })) { classResults.Add(item); } } else { var queryResult = $"select value(c) where c.examId ='{activityId}' and c.pk = 'ExamClassResult' "; await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator(queryText: queryResult, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") })) { classResults.Add(item); } } //如果单个活动包含多个科目 var (grade, per) = await GetGradeAsync(client, info); var (currSemester, studyYear, currSemesterDate, date, nextSemester) = SchoolService.GetSemester(per, info.startTime); int no = 0; foreach (var subject in info.subjects) { //获取试题详细信息 BlobDownloadResult index_json; if (info.scope.Equals("school")) { index_json = await _azureStorage.GetBlobContainerClient($"{info.school}").GetBlobClient($"{info.papers[no].blob}/index.json").DownloadContentAsync(); } else { index_json = await _azureStorage.GetBlobContainerClient($"{info.creatorId}").GetBlobClient($"{info.papers[no].blob}/index.json").DownloadContentAsync(); } JsonElement RecordingJson = JsonDocument.Parse(new MemoryStream(Encoding.UTF8.GetBytes(index_json.Content.ToString()))).RootElement; RecordingJson.TryGetProperty("slides", out JsonElement slides); var sdes = slides.ToObject>(); List urls = new(); foreach (var ne in sdes) { if (!ne.type.Equals("compose")) { urls.Add(ne.url); } } // 获取整体的题目ID集合 List ids = new(); List<(string id, string type, double score, int difficulty, string choices, string answer)> itemInfos = new(); int index = 1; foreach (string url in urls) { string id = url.Replace(".json", ""); BlobDownloadResult index_item_json; if (info.scope.Equals("school")) { index_item_json = await _azureStorage.GetBlobContainerClient($"{info.school}").GetBlobClient($"{info.papers[no].blob}/{url}").DownloadContentAsync(); } else { index_item_json = await _azureStorage.GetBlobContainerClient($"{info.creatorId}").GetBlobClient($"{info.papers[no].blob}/{url}").DownloadContentAsync(); } JsonElement itemJson = JsonDocument.Parse(new MemoryStream(Encoding.UTF8.GetBytes(index_item_json.Content.ToString()))).RootElement; itemJson.TryGetProperty("exercise", out JsonElement exercise); var item_json = exercise.ToObject(); string type = item_json.type; int level = item_json.level; double score = item_json.score; var ans = item_json.answer; if (itemJson.TryGetProperty("item", out JsonElement item)) { var itemInfo_json = item.ToObject>(); StringBuilder sb = new(); StringBuilder an = new(); itemInfo_json.FirstOrDefault().option.Select(c => c.code).ToList().ForEach(z => { sb.Append(z); }); ans.ForEach(z => { an.Append(z); }); itemInfos.Add((index.ToString(), type, score, level, sb.ToString(), an.ToString())); } index++; } //学生作答信息 List<(string stuId, List<(string questionNo, double score, string answer)> ansDt)> stuAns = new(); foreach (ExamClassResult classResult in classResults) { if (classResult.subjectId.Equals(subject.id)) { int stuCount = 0; foreach (var stu in classResult.studentIds) { int itemCount = 0; List<(string questionNo, double score, string answer)> ansDt = new(); foreach (var itemNo in classResult.studentAnswers[stuCount]) { ansDt.Add(((itemCount + 1).ToString(), classResult.studentScores[stuCount][itemCount], itemNo)); itemCount++; } stuAns.Add((stu, ansDt)); stuCount++; } } } var jsonString = new { examDate = info.startTime, //todo 不同学段年级数量不一致 grade, subName = subject.name, totalScore = info.papers[no].point.Sum(), termCode = currSemester.start == 1 ? 1 : 2, data = new { items = itemInfos.Select(c => new { questionNo = c.id, c.type, c.score, c.difficulty, c.choices, c.answer }), stuDate = stuAns.Select(c => new { stuNo = c.stuId, scoreData = c.ansDt.Select(z => new { z.questionNo, z.score, z.answer }) }) } }; var key = Md5Hash.GetMd5String("TMD" + info.school); string connect = $"http://www.moofen.net/esi/tmd/exam/{info.school}/{key}"; var htc = _httpClient.CreateClient(); string paramJson = JsonConvert.SerializeObject(jsonString); var content = new StringContent(paramJson, Encoding.UTF8, "application/json"); var ansResponse = await htc.PostAsync(connect, content); if ((int)ansResponse.StatusCode == 200) { return (activityId, 200); } no++; } } catch (CosmosException) { return (activityId, 500); } } return (activityId, 404); } public static async Task<(string gId, Period per)> GetGradeAsync(CosmosClient client, ExamInfo info) { if (info.grades.Count > 0) { var schresponse = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(info.school, new PartitionKey("Base")); string grade = ""; School sc = new(); if (schresponse.Status == 200) { using var schjson = await JsonDocument.ParseAsync(schresponse.ContentStream); sc = schjson.ToObject(); } var period = sc.period.Where(x => x.id.Equals(info.period.id)).FirstOrDefault(); var pType = sc.period.FirstOrDefault(c => c.id.Equals(info.period.id)).periodType; //int pcount = (int)(sc.period.Where(c => c.periodType.Equals("primary")).FirstOrDefault()?.grades.Count); //int jcount = (int)(sc.period.Where(c => c.periodType.Equals("junior")).FirstOrDefault()?.grades.Count); if (pType.Equals("primary")) { grade = (int.Parse(info.grades.FirstOrDefault().id) + 1).ToString(); } else if (pType.Equals("junior")) { grade = (int.Parse(info.grades.FirstOrDefault().id) + 7).ToString(); } else { grade = (int.Parse(info.grades.FirstOrDefault().id) + 10).ToString(); } return (grade, period); } else { return ("", new Period()); } } public static async Task CreateMoofenExam(IHttpClientFactory _httpClient, JsonElement json,DingDing _ding) { string content = string.Empty; try { Dictionary dict = new Dictionary(); if (json.TryGetProperty("examName", out JsonElement examName) && !string.IsNullOrWhiteSpace($"{examName}")) { dict.Add("examName", $"{examName}"); } if (json.TryGetProperty("examCategory", out JsonElement examCategory) && !string.IsNullOrWhiteSpace($"{examCategory}")) { dict.Add("examCategory", $"{examCategory}"); } if (json.TryGetProperty("grade", out JsonElement grade) && !string.IsNullOrWhiteSpace($"{grade}")) { dict.Add("grade", $"{grade}"); } if (json.TryGetProperty("term", out JsonElement term) && !string.IsNullOrWhiteSpace($"{term}")) { dict.Add("term", $"{term}"); } if (json.TryGetProperty("examType", out JsonElement examType) && !string.IsNullOrWhiteSpace($"{examType}")) { dict.Add("examType", $"{examType}"); } if (json.TryGetProperty("examDate", out JsonElement examDate) && !string.IsNullOrWhiteSpace($"{examDate}")) { dict.Add("examDate", $"{examDate}"); } if (json.TryGetProperty("schId", out JsonElement schId) && !string.IsNullOrWhiteSpace($"{schId}")) { dict.Add("schId", $"{schId}"); } if (json.TryGetProperty("boeId", out JsonElement boeId) && !string.IsNullOrWhiteSpace($"{boeId}")) { dict.Add("boeId", $"{boeId}"); } if (json.TryGetProperty("subjects", out JsonElement subjects) && subjects.ValueKind.Equals(JsonValueKind.Array)) { dict.Add("subjects", $"{subjects}"); } dict.Add("signKey", "TMD"); var keys = dict.Keys.OrderBy(x => x); var parmas = string.Join("&", keys.Select(x => $"{x}={dict[x]}")); //var signtime = DateTimeOffset.UtcNow.GetGMTTime(8).ToUnixTimeSeconds(); //parmas = $"{parmas}&signtime={signtime}"; string sign = Md5Hash.Encrypt(parmas); dict.Add("sign", $"{sign}"); dict.Remove("signKey"); //var pkeys = dict.Keys; string url = "https://www.moofen.net/oss/esi/exam/tmodel/create"; //parmas = string.Join("&", pkeys.Select(x => $"{x}={dict[x]}")); var httpClient = _httpClient.CreateClient(); var request = new HttpRequestMessage { Method = new HttpMethod("POST"), RequestUri = new Uri(url), Content = new StringContent(JsonConvert.SerializeObject(dict)) }; // 设置请求头中的Content-Type // httpClient.DefaultRequestHeaders.Add("Content-Type", "application/x-www-form-urlencoded"); var mediaTypeHeader = new MediaTypeHeaderValue("application/json") { CharSet = "UTF-8" }; httpClient.Timeout = new TimeSpan(0,0,10); request.Content.Headers.ContentType = mediaTypeHeader; HttpResponseMessage response = await _httpClient.CreateClient().SendAsync(request); if (response.StatusCode.Equals(HttpStatusCode.OK)) { content = await response.Content.ReadAsStringAsync(); var data = content.ToObject(); if (data.TryGetProperty("data", out JsonElement _data)) { return _data.ToString(); } } } catch (Exception e) { await _ding.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")},ThirdService/CreateMoofenExam()\n{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組); } return ""; } public static async Task> CreateMoofenExamResult(IHttpClientFactory _httpClient, JsonElement json, DingDing _ding) { string content = string.Empty; List ans = new(); try { Dictionary dict = new Dictionary(); if (json.TryGetProperty("examCode", out JsonElement examCode) && !string.IsNullOrWhiteSpace($"{examCode}")) { dict.Add("examCode", $"{examCode}"); } if (json.TryGetProperty("subjects", out JsonElement subjects) && subjects.ValueKind.Equals(JsonValueKind.Array)) { dict.Add("subjects", $"{subjects}"); } dict.Add("signKey", "TMD"); var keys = dict.Keys.OrderBy(x => x); var parmas = string.Join("&", keys.Select(x => $"{x}={dict[x]}")); //var signtime = DateTimeOffset.UtcNow.GetGMTTime(8).ToUnixTimeSeconds(); //parmas = $"{parmas}&signtime={signtime}"; string sign = Md5Hash.Encrypt(parmas); dict.Add("sign", $"{sign}"); dict.Remove("signKey"); //var pkeys = dict.Keys; string url = "https://www.moofen.net/oss/esi/exam/tmodel/result"; //parmas = string.Join("&", pkeys.Select(x => $"{x}={dict[x]}")); var httpClient = _httpClient.CreateClient(); var request = new HttpRequestMessage { Method = new HttpMethod("POST"), RequestUri = new Uri(url), Content = new StringContent(JsonConvert.SerializeObject(dict)) }; // 设置请求头中的Content-Type // httpClient.DefaultRequestHeaders.Add("Content-Type", "application/x-www-form-urlencoded"); var mediaTypeHeader = new MediaTypeHeaderValue("application/json") { CharSet = "UTF-8" }; httpClient.Timeout = new TimeSpan(0, 0, 10); request.Content.Headers.ContentType = mediaTypeHeader; HttpResponseMessage response = await _httpClient.CreateClient().SendAsync(request); if (response.StatusCode.Equals(HttpStatusCode.OK)) { content = await response.Content.ReadAsStringAsync(); var data = content.ToObject(); if (data.TryGetProperty("data", out JsonElement _data)) { ans = _data.ToObject>(); return ans; } } } catch (Exception e) { await _ding.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")},ThirdService/CreateMoofenExamResult()\n{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組); } return ans; } /* private class item { public string questionNo { get; set; } public string type { get; set; } public double score { get; set; } public int difficulty { get; set; } public string choices { get; set; } public string answer { get; set; } }*/ private class itemInfo { public List option { get; set; } = new(); } private class opt { public string code { get; set; } public double value { get; set; } } public class stuAns { public string stuNo { get; set; } public List scoreData { get; set; } = new List(); public string subject { get; set; } } public class moofenAns { public string questionNo { get; set; } public double score { get; set; } public string answer { get; set; } } } }