EvaluationSyncInfoService.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. using Azure.Storage.Blobs.Models;
  2. using IES.ExamLibrary.Models;
  3. using IES.ExamServer.Models;
  4. using Microsoft.Azure.Cosmos;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.IO;
  8. using System.Linq;
  9. using System.Net.Http;
  10. using System.Text;
  11. using System.Text.Json;
  12. using System.Threading.Tasks;
  13. using TEAMModelOS.SDK.DI;
  14. using TEAMModelOS.SDK.Extension;
  15. using TEAMModelOS.SDK.Models.Cosmos;
  16. using TEAMModelOS.SDK.Models.Cosmos.Normal;
  17. namespace TEAMModelOS.SDK.Models.Service
  18. {
  19. public sealed class EvaluationSyncInfoService
  20. {
  21. /// <summary>
  22. /// 重新对名单的hash值计算,1因为可能会存在临时将学生加入名单,而没有修改评测信息的情况。
  23. /// </summary>
  24. /// <param name="evaluationSyncInfo"></param>
  25. /// <param name="_coreAPIHttpService"></param>
  26. /// <param name="_azureCosmos"></param>
  27. /// <param name="_dingDing"></param>
  28. /// <returns></returns>
  29. public static async Task<(EvaluationSyncInfo evaluation, bool change,string newGrouplistHash, List<RMember> members, List<RGroupList> groupLists)> CheckEvaluationGroupList(EvaluationSyncInfo evaluationSyncInfo, CoreAPIHttpService _coreAPIHttpService, AzureCosmosFactory _azureCosmos, DingDing _dingDing)
  30. {
  31. var listInfo = await GroupListService.GetMemberByListids(_coreAPIHttpService, _azureCosmos.GetCosmosClient(), _dingDing, evaluationSyncInfo.grouplist.Select(x=>x.id).ToList(), evaluationSyncInfo.ownerId);
  32. //计算数据的hash值
  33. StringBuilder groupListData = new StringBuilder();
  34. //名单的hash值
  35. var orderList = listInfo.groups.OrderBy(x => x.id);
  36. foreach (var item in orderList)
  37. {
  38. groupListData.Append($"{item.id}-{item.name}");
  39. var orderMembers = item.members.OrderBy(x => x.id);
  40. foreach (var member in orderMembers)
  41. {
  42. groupListData.Append($"{member.id}-{member.name}");
  43. }
  44. }
  45. bool change = false;
  46. string grouplistHash = ShaHashHelper.GetSHA1(groupListData.ToString());
  47. if (!evaluationSyncInfo.grouplistHash .Equals(grouplistHash))
  48. {
  49. evaluationSyncInfo.grouplistHash = grouplistHash;
  50. change = true;
  51. }
  52. return (evaluationSyncInfo,change, grouplistHash,listInfo.rmembers, listInfo.groups);
  53. }
  54. /// <summary>
  55. /// 活动数据打包
  56. /// </summary>
  57. /// <param name="id"></param>
  58. /// <param name="scope"></param>
  59. /// <param name="owner"></param>
  60. /// <param name="type"></param>
  61. /// <param name="azureCosmos"></param>
  62. /// <param name="azureStorage"></param>
  63. public static async Task<EvaluationSyncInfo> PackageEvaluation( string id,string scope, string ownerId, string type, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage,
  64. CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing, IHttpClientFactory _httpClientFactory)
  65. {
  66. EvaluationSource evaluationSource = new EvaluationSource() { type=type,id=id};
  67. EvaluationSyncInfo evaluationSyncInfo= null;
  68. EvaluationClient evaluationClient = null;
  69. List<EvaluationExam> evaluationExams = new List<EvaluationExam>();
  70. long? dataTime = 0;
  71. long stime = 0;
  72. long etime = 0;
  73. string? ownerName=string.Empty;
  74. string? ownerPicture = string.Empty;
  75. string schoolCode = null;
  76. if (scope.Equals("school"))
  77. {
  78. try {
  79. School school = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(ownerId, new PartitionKey("Base"));
  80. schoolCode= ownerId;
  81. evaluationSource.school = school;
  82. ownerName = school.name;
  83. ownerPicture = school.picture;
  84. //if (!string.IsNullOrWhiteSpace(ownerPicture))
  85. //{
  86. // //学校logo 下载到本地、
  87. // HttpResponseMessage message = await _httpClientFactory.CreateClient().GetAsync(ownerPicture);
  88. // if (message.IsSuccessStatusCode)
  89. // {
  90. // string base64Prefix = "data:image/jpeg;base64,";
  91. // byte[] fileBytes = await message.Content.ReadAsByteArrayAsync();
  92. // ownerPicture =$"{base64Prefix}{Convert.ToBase64String(fileBytes)}";
  93. // }
  94. //}
  95. }
  96. catch (Exception ex) {
  97. await _dingDing.SendBotMsg($"打包评测数据,获取学校信息报错,{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  98. return null;
  99. }
  100. }
  101. else
  102. {
  103. try {
  104. Teacher teacher = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>(ownerId, new PartitionKey("Base"));
  105. evaluationSource.teacher = teacher;
  106. ownerName = teacher.name;
  107. ownerPicture = teacher.picture;
  108. //if (!string.IsNullOrWhiteSpace(ownerPicture))
  109. //{
  110. // //学校logo 下载到本地、
  111. // HttpResponseMessage message = await _httpClientFactory.CreateClient().GetAsync(ownerPicture);
  112. // if (message.IsSuccessStatusCode)
  113. // {
  114. // string base64Prefix = "data:image/jpeg;base64,";
  115. // byte[] fileBytes = await message.Content.ReadAsByteArrayAsync();
  116. // ownerPicture =$"{base64Prefix}{Convert.ToBase64String(fileBytes)}";
  117. // }
  118. //}
  119. }
  120. catch (Exception ex) {
  121. await _dingDing.SendBotMsg($"打包评测数据,获取教师信息报错,{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  122. return null;
  123. }
  124. }
  125. var responseEvaluationSyncInfo = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemStreamAsync(id, new PartitionKey("EvaluationSyncInfo"));
  126. if (responseEvaluationSyncInfo.IsSuccessStatusCode)
  127. {
  128. evaluationSyncInfo= JsonDocument.Parse(responseEvaluationSyncInfo.Content).RootElement.Deserialize<EvaluationSyncInfo>();
  129. }
  130. else {
  131. evaluationSyncInfo=new EvaluationSyncInfo {
  132. id = id,
  133. scope = scope,
  134. type = type,
  135. pk="EvaluationSyncInfo",
  136. code="EvaluationSyncInfo",
  137. ownerId = ownerId,
  138. ownerPicture = ownerPicture,
  139. ownerName = ownerName,
  140. };
  141. }
  142. switch (true)
  143. {
  144. case bool when (type == "Exam"):
  145. {
  146. string code = $"Exam-{ownerId}";
  147. var response = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(id, new PartitionKey(code));
  148. if (response.IsSuccessStatusCode)
  149. {
  150. ExamInfo exam= JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamInfo>();
  151. dataTime = exam._ts*1000;
  152. evaluationSyncInfo.name=exam.name;
  153. evaluationSyncInfo.subjects = exam.subjects?.Select(x=>new IES.ExamServer.Models.SubjectExam { subjectId=x.id,subjectName=x.name,examId=id,examName=exam.name}).ToList();
  154. evaluationSyncInfo.dataTime= DateTimeOffset.Now.ToUnixTimeMilliseconds();
  155. evaluationSyncInfo.scode=exam.code;
  156. evaluationSyncInfo.owner=exam.owner;
  157. stime=exam.startTime;
  158. etime=exam.endTime;
  159. HashSet<string> grouplist = new HashSet<string>();
  160. if (exam.classes.IsNotEmpty()) {
  161. exam.classes.ForEach(x => { grouplist.Add(x); });
  162. }
  163. if (exam.stuLists.IsNotEmpty())
  164. {
  165. exam.stuLists.ForEach(x => { grouplist.Add(x); });
  166. }
  167. evaluationSyncInfo.grouplist=grouplist.Select(x=> new EvaluationGroupListDto { id=x}).ToList() ;
  168. evaluationSyncInfo.paperCount=exam.papers.IsNotEmpty()? exam.papers.Count():0;
  169. foreach (var group in exam.papers.GroupBy(x=>x.subjectId).Select(x=>new { key = x.Key,list= x.ToList()}))
  170. {
  171. var subject= exam.subjects.Find(x => x.id.Equals(group.key));
  172. if (subject!=null)
  173. {
  174. evaluationSyncInfo.subjects.Add(new IES.ExamServer.Models.SubjectExam {
  175. subjectId=subject.id,
  176. subjectName=subject.name,
  177. examId=id,
  178. examName=exam.name,
  179. papers= group.list.Select(x=>new SubjectExamPaper {paperId= x.id,paperName=x.name,limitTime=x.time, questionCount=x.answers.IsNotEmpty()?x.answers.Count():0, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList(),
  180. } );
  181. EvaluationExam evaluationExam = new EvaluationExam()
  182. {
  183. examId=exam.id,
  184. evaluationId=evaluationSyncInfo.id,
  185. examName=evaluationSyncInfo.name,
  186. subjectId=subject.id,
  187. subjectName=subject.name,
  188. classes= evaluationSyncInfo.grouplist,
  189. owner=exam.owner,
  190. scope=scope,
  191. stime=stime,
  192. etime=etime,
  193. papers= group.list.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, limitTime=x.time, questionCount=x.answers.IsNotEmpty() ? x.answers.Count() : 0, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}", point=x.point,knowledge=x.knowledge,type=x.type,field=x.field }).ToList(),
  194. };
  195. evaluationExams.Add(evaluationExam);
  196. }
  197. }
  198. evaluationSource.exam=exam;
  199. }
  200. break;
  201. }
  202. case bool when (type == "Art"):
  203. {
  204. string code = $"Art-{ownerId}";
  205. var response = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(id, new PartitionKey(code));
  206. if (response.IsSuccessStatusCode)
  207. {
  208. ArtEvaluation art = JsonDocument.Parse(response.Content).RootElement.Deserialize<ArtEvaluation>();
  209. // evaluationSyncInfo.subjects = art.subjects?.Select(x => new IES.ExamServer.Models.SubjectExam { id=x.id, name=x.name, examId=id }).ToList();
  210. evaluationSyncInfo.name = art.name;
  211. evaluationSyncInfo.pid= art.pId;
  212. evaluationSyncInfo.scode=art.code;
  213. evaluationSyncInfo.dataTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  214. evaluationSyncInfo.owner=art.owner;
  215. HashSet<string> grouplist = new HashSet<string>();
  216. if (art.classes.IsNotEmpty())
  217. {
  218. art.classes.ForEach(x => { grouplist.Add(x); });
  219. }
  220. if (art.stuLists.IsNotEmpty())
  221. {
  222. art.stuLists.ForEach(x => { grouplist.Add(x); });
  223. }
  224. if (art.tchLists.IsNotEmpty())
  225. {
  226. art.tchLists.ForEach(x => { grouplist.Add(x); });
  227. }
  228. evaluationSyncInfo.grouplist=grouplist.Select(x => new EvaluationGroupListDto { id = x }).ToList();
  229. evaluationSyncInfo.examDeadline=art.examDeadline;
  230. evaluationSource.art=art;
  231. dataTime= art._ts*1000;
  232. stime=art.startTime;
  233. etime=art.endTime;
  234. var quota_21 = art.settings.Find(x => x.id.Equals("quota_21"));
  235. foreach (var item in quota_21.task)
  236. {
  237. if (!string.IsNullOrWhiteSpace(item.acId))
  238. {
  239. // item.isOrder=>disorder
  240. var subject = art.subjects.Find(x => x.id.Equals(item.subject));
  241. var examResponse= await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(item.acId, new PartitionKey($"Exam-{ownerId}"));
  242. if (examResponse.IsSuccessStatusCode)
  243. {
  244. ExamInfo exam = JsonDocument.Parse(examResponse.Content).RootElement.Deserialize<ExamInfo>() ;
  245. var papers = exam.papers.FindAll(x => x.subjectId.Equals(item.subject));
  246. var subjectSync = evaluationSyncInfo.subjects.Find(x => x.examId.Equals(item.acId) && x.subjectId.Equals(item.subject));
  247. if (subjectSync!=null)
  248. {
  249. subjectSync.papers= papers?.Select(x => new SubjectExamPaper { paperId=x.id, limitTime=x.time, paperName=x.name, questionCount=x.answers.IsNotEmpty() ? x.answers.Count() : 0, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList();
  250. subjectSync.subjectName=subject.name;
  251. }
  252. else {
  253. evaluationSyncInfo.subjects.Add(new IES.ExamServer.Models.SubjectExam
  254. {
  255. subjectId=item.subject,
  256. subjectName=subject.name,
  257. examId=item.acId,
  258. examName=exam.name,
  259. disorder=item.isOrder.HasValue ? item.isOrder.Value : 0,
  260. papers = papers?.Select(x => new SubjectExamPaper { paperId=x.id, paperName=x.name, limitTime=x.time, questionCount=x.answers.IsNotEmpty() ? x.answers.Count() : 0, blob=x.blob, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}" }).ToList()
  261. });
  262. }
  263. dataTime= dataTime<exam._ts*1000 ? exam._ts*1000 : dataTime;
  264. evaluationSource.artExams.Add(exam);
  265. EvaluationExam evaluationExam = new EvaluationExam()
  266. {
  267. examId=exam.id,
  268. evaluationId=evaluationSyncInfo.id,
  269. examName=evaluationSyncInfo.name,
  270. subjectId=subject.id,
  271. subjectName=subject.name,
  272. classes= evaluationSyncInfo.grouplist,
  273. owner=exam.owner,
  274. scope=scope,
  275. stime=stime,
  276. etime=etime,
  277. disorder=item.isOrder.HasValue?item.isOrder.Value:0,
  278. papers= papers.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, blob=x.blob, limitTime=x.time, questionCount=x.answers.IsNotEmpty() ? x.answers.Count() : 0, local=$"package/{evaluationSyncInfo.id}/papers/{x.id}", point=x.point, knowledge=x.knowledge, type=x.type, field=x.field }).ToList(),
  279. };
  280. evaluationExams.Add(evaluationExam);
  281. }
  282. }
  283. }
  284. var quota_22 = art.settings.Find(x => x.id.Equals("quota_22"));
  285. if (quota_22!=null)
  286. {
  287. foreach (var item in quota_22.task)
  288. {
  289. //获取基本技能(智音音乐曲目)
  290. if (item.subject.Equals("subject_music"))
  291. {
  292. string AIMuiscId = string.Empty;
  293. if (!string.IsNullOrWhiteSpace(art.pId))
  294. {
  295. AIMuiscId=art.pId;
  296. }
  297. else {
  298. AIMuiscId=art.id;
  299. }
  300. var artMusicResponse = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(AIMuiscId, new PartitionKey("ArtMusic"));
  301. if (artMusicResponse.IsSuccessStatusCode)
  302. {
  303. ArtMusic artMusic = JsonDocument.Parse(artMusicResponse.Content).RootElement.Deserialize<ArtMusic>() ;
  304. if (artMusic!=null)
  305. {
  306. evaluationSyncInfo.music= new MusicAI()
  307. {
  308. taskId=item.acId,
  309. examId= art.id,
  310. examName= art.name,
  311. pid=art.pId,
  312. questionId=artMusic.questionId,
  313. questionName=artMusic.questionName,
  314. mustSong=artMusic.mustSong?.Select(x=>new AISong { songId=x.songId,songName=x.songName}).ToList(),
  315. optionSong=artMusic.optionSong?.Select(x => new AISong { songId=x.songId, songName=x.songName }).ToList(),
  316. };
  317. }
  318. }
  319. }
  320. }
  321. }
  322. }
  323. }
  324. break;
  325. default:
  326. break;
  327. }
  328. if (evaluationSyncInfo.subjects.IsNotEmpty() && evaluationSyncInfo.grouplist.IsNotEmpty())
  329. {
  330. long blobTime =-1;
  331. long blobSize = 0;
  332. long blobCount = 0;
  333. if (string.IsNullOrWhiteSpace(evaluationSyncInfo.shortCode))
  334. {
  335. evaluationSyncInfo.shortCode = $"{MurmurHash3.Hash32(evaluationSyncInfo.id)}";
  336. }
  337. if (string.IsNullOrWhiteSpace(evaluationSyncInfo.openCode))
  338. {
  339. StringBuilder builder = new StringBuilder();
  340. for (var i = 0; i < 6; i++)
  341. {
  342. var chars = ExamConstant.AZ_19NI1O0[Random.Shared.Next(0, ExamConstant.AZ_19NI1O0.Length)];
  343. builder.Append(chars);
  344. }
  345. evaluationSyncInfo.openCode = builder.ToString();
  346. }
  347. var listInfo = await GroupListService.GetMemberByListids(_coreAPIHttpService, azureCosmos.GetCosmosClient(), _dingDing, evaluationSyncInfo.grouplist.Select(x=>x.id).ToList(), schoolCode);
  348. foreach (var item in evaluationSyncInfo.grouplist)
  349. {
  350. item.name=listInfo.groups.Find(x => x.id.Equals(item.id))?.name;
  351. }
  352. evaluationSyncInfo.studentCount = listInfo.rmembers.Count();
  353. evaluationSyncInfo.paperCount =evaluationSyncInfo.subjects.SelectMany(x => x.papers).Count();
  354. var client = azureStorage.GetBlobContainerClient(ownerId);
  355. foreach (var subject in evaluationSyncInfo.subjects)
  356. {
  357. var evaluationExam = evaluationExams.FindAll(x => x.subjectId.Equals(subject.subjectId)).FirstOrDefault();
  358. foreach (var paper in subject.papers)
  359. {
  360. EvaluationPaper evaluationPaper = null;
  361. List<BlobHashInfo> blobs = new List<BlobHashInfo>();
  362. try
  363. {
  364. await foreach (BlobItem blobItem in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, !string.IsNullOrWhiteSpace(paper.blob)&& paper.blob.StartsWith("/")?paper.blob.Substring(1):paper.blob ))
  365. {
  366. var lastModified = blobItem.Properties.LastModified;
  367. if (lastModified.HasValue)
  368. {
  369. lastModified.Value.ToUnixTimeMilliseconds();
  370. }
  371. var hash = blobItem.Properties.ContentHash;
  372. var path = blobItem.Name;
  373. var ext = Path.GetExtension(path);
  374. string fileName = Path.GetFileName(path);
  375. if (ext.ToUpper().Equals(ext))
  376. {
  377. string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
  378. fileName= $"{fileNameWithoutExtension!}_1{ext}";
  379. }
  380. var size = blobItem.Properties.ContentLength;
  381. blobs.Add(new BlobHashInfo
  382. {
  383. hash = Md5Hash.GetbyteToString(hash),
  384. last = lastModified.HasValue ? lastModified.Value.ToUnixTimeMilliseconds() : 0 ,
  385. path = path,
  386. size = size.HasValue ? size.Value : 0,
  387. local=$"package/{evaluationSyncInfo.id}/papers/{paper.paperId}/{fileName}"
  388. });
  389. };
  390. evaluationPaper = evaluationExam.papers.Find(x => x.paperId.Equals(paper.paperId));
  391. evaluationPaper.blobs=blobs;
  392. }
  393. catch(Exception ex )
  394. {
  395. await _dingDing.SendBotMsg($"数据打包异常,试卷检测异常,{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
  396. }
  397. long lastTime = blobs.Max(x => x.last);
  398. blobTime= lastTime>blobTime?lastTime:blobTime;
  399. if (blobs.IsNotEmpty())
  400. {
  401. blobSize+=blobs.Sum(x => x.size);
  402. blobCount+=blobs.Count;
  403. var order = blobs.OrderBy(x => $"{x.path}-{x.hash}-{x.size}-{x.last}");
  404. string blobStr = string.Join(",", order.Select(x=> $"{x.path}-{x.hash}-{x.size}-{x.last}"));
  405. // 计算hash,校准路径,文件hash,文件大小,最后修改时间
  406. string paperHash = ShaHashHelper.GetSHA1(blobStr);
  407. paper.paperHash= paperHash;
  408. evaluationPaper.paperHash= paperHash;
  409. }
  410. }
  411. }
  412. evaluationSyncInfo.blobTime = blobTime> evaluationSyncInfo.blobTime ? blobTime : evaluationSyncInfo.blobTime;
  413. evaluationSyncInfo.blobSize = blobSize;
  414. evaluationSyncInfo.blobCount = blobCount;
  415. evaluationSyncInfo.blobLastHash = evaluationSyncInfo.blobHash;
  416. evaluationSyncInfo.blobHash = ShaHashHelper.GetSHA1(string.Join("-", evaluationSyncInfo.subjects.SelectMany(x => x.papers).Select(x => x.paperHash).OrderBy(x=>x)));
  417. evaluationSyncInfo.dataTime = dataTime.Value;
  418. evaluationSource.updateTime = dataTime.Value;
  419. var groupList = new { members = listInfo.rmembers, groupList = listInfo.groups };
  420. {
  421. //计算数据的hash值
  422. StringBuilder groupListData = new StringBuilder();
  423. //名单的hash值
  424. var orderList = listInfo.groups.OrderBy(x => x.id);
  425. foreach (var item in orderList)
  426. {
  427. groupListData.Append($"{item.id}-{item.name}");
  428. var orderMembers = item.members.OrderBy(x => x.id);
  429. foreach (var member in orderMembers)
  430. {
  431. groupListData.Append($"{member.id}-{member.name}");
  432. }
  433. }
  434. evaluationSyncInfo.grouplistHash= ShaHashHelper.GetSHA1(groupListData.ToString());
  435. var order= evaluationSyncInfo.subjects.OrderBy(x => x.subjectId);
  436. StringBuilder dataStr = new StringBuilder();
  437. dataStr.Append(evaluationSyncInfo.id);
  438. dataStr.Append(evaluationSyncInfo.name);
  439. dataStr.Append(evaluationSyncInfo.type);
  440. dataStr.Append(evaluationSyncInfo.owner);
  441. dataStr.Append(evaluationSyncInfo.ownerId);
  442. dataStr.Append(evaluationSyncInfo.scode);
  443. dataStr.Append(evaluationSyncInfo.scope);
  444. dataStr.Append(evaluationSyncInfo.grouplistHash);
  445. dataStr.Append(evaluationSyncInfo.blobHash);
  446. dataStr.Append(evaluationSyncInfo.shortCode);
  447. dataStr.Append(evaluationSyncInfo.openCode);
  448. dataStr.Append($"{stime}{etime}");
  449. dataStr.Append(string.Join("", order.Select(x=>x.subjectId).OrderBy(x=>x)));
  450. if (evaluationSyncInfo.music!=null)
  451. {
  452. dataStr.Append($"{evaluationSyncInfo.music.questionId}{string.Join("", evaluationSyncInfo.music.mustSong?.Select(x=>x.songId).OrderBy(x=>x))}{string.Join("",evaluationSyncInfo.music.optionSong?.Select(x=>x.songId).OrderBy(x=>x))}");
  453. }
  454. //计算dataHash
  455. evaluationSyncInfo.dataHash = ShaHashHelper.GetSHA1(dataStr.ToString());
  456. }
  457. evaluationClient= new EvaluationClient
  458. {
  459. id = evaluationSyncInfo.id,
  460. pid = evaluationSyncInfo.pid,
  461. name = evaluationSyncInfo.name,
  462. type = evaluationSyncInfo.type,
  463. owner = evaluationSyncInfo.owner,
  464. scode = evaluationSyncInfo.scode,
  465. scope = evaluationSyncInfo.scope,
  466. subjects = evaluationSyncInfo.subjects,
  467. dataTime = evaluationSyncInfo.dataTime,
  468. dataSize = evaluationSyncInfo.dataSize,
  469. blobTime = evaluationSyncInfo.blobTime,
  470. blobSize = evaluationSyncInfo.blobSize,
  471. blobCount = evaluationSyncInfo.blobCount,
  472. blobHash = evaluationSyncInfo.blobHash,
  473. blobLastHash = evaluationSyncInfo.blobLastHash,
  474. //webviewCount = evaluationSyncInfo.webviewCount,
  475. //webviewPath = evaluationSyncInfo.webviewPath,
  476. //webviewSize = evaluationSyncInfo.webviewSize,
  477. //webviewTime = evaluationSyncInfo.webviewTime,
  478. studentCount = evaluationSyncInfo.studentCount,
  479. paperCount = evaluationSyncInfo.paperCount,
  480. grouplist = evaluationSyncInfo.grouplist,
  481. shortCode = evaluationSyncInfo.shortCode,
  482. openCode = evaluationSyncInfo.openCode,
  483. stime=stime,
  484. etime=etime,
  485. dataHash = evaluationSyncInfo.dataHash,
  486. grouplistHash = evaluationSyncInfo.grouplistHash,
  487. ownerId = evaluationSyncInfo.ownerId,
  488. ownerPicture =evaluationSyncInfo.ownerPicture,
  489. ownerName = evaluationSyncInfo.ownerName,
  490. music = evaluationSyncInfo.music,
  491. reanswer = evaluationSyncInfo.reanswer,
  492. examDeadline = evaluationSyncInfo.examDeadline,
  493. //password = evaluationSyncInfo.password,
  494. //recordUrl = evaluationSyncInfo.recordUrl
  495. };
  496. if (!string.IsNullOrWhiteSpace(ownerPicture))
  497. {
  498. //教师头像或学校logo 下载转为Base64
  499. HttpResponseMessage message = await _httpClientFactory.CreateClient().GetAsync(ownerPicture);
  500. if (message.IsSuccessStatusCode)
  501. {
  502. string base64Prefix = "data:image/jpeg;base64,";
  503. byte[] fileBytes = await message.Content.ReadAsByteArrayAsync();
  504. ownerPicture =$"{base64Prefix}{Convert.ToBase64String(fileBytes)}";
  505. evaluationClient.ownerPicture = ownerPicture;
  506. }
  507. }
  508. long dataSize = 0;
  509. string sourceJson = evaluationSource.ToJsonString();
  510. dataSize+= Encoding.UTF8.GetByteCount(sourceJson);
  511. string groupListJson = groupList.ToJsonString();
  512. dataSize+= Encoding.UTF8.GetByteCount(groupListJson);
  513. string evaluationJson = new { evaluationClient, evaluationExams }.ToJsonString().ToJsonString();
  514. dataSize+= Encoding.UTF8.GetByteCount(evaluationJson);
  515. string evaluationSyncInfoSJson = evaluationSyncInfo.ToJsonString();
  516. dataSize+= Encoding.UTF8.GetByteCount(evaluationSyncInfoSJson);
  517. evaluationClient.dataSize = dataSize;
  518. //重组blob路径,使之适配局域网端读取。
  519. //evaluationClient.subjects.ForEach(x => {
  520. // x.papers.ForEach(y => {
  521. // y.blob=$"package/{evaluationClient.id}/papers/{y.paperId}";
  522. // });
  523. //});
  524. //evaluationExams.ForEach(x => {
  525. // x.papers.ForEach(y => {
  526. // y.blob=$"package/{evaluationClient.id}/papers/{y.paperId}";
  527. // });
  528. //});
  529. //evaluationSyncInfo.subjects.ForEach(x => {
  530. // x.papers.ForEach(y => {
  531. // y.blob=$"package/{evaluationClient.id}/papers/{y.paperId}";
  532. // });
  533. //});
  534. await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(sourceJson, $"package/{id}/data", "source.json");
  535. await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(groupListJson, $"package/{id}/data", "grouplist.json");
  536. await azureStorage.GetBlobContainerClient(ownerId).UploadFileByContainer(new { evaluationClient, evaluationExams }.ToJsonString(), $"package/{id}/data", "evaluation.json");
  537. evaluationSyncInfo.dataSize = dataSize;
  538. await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).UpsertItemAsync<EvaluationSyncInfo>(evaluationSyncInfo, new PartitionKey("EvaluationSyncInfo"));
  539. // await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(evaluationSyncInfo.ToJsonString(), $"package/{id}", "syncinfo.json");
  540. }
  541. return evaluationSyncInfo;
  542. }
  543. }
  544. }