EvaluationSyncInfoService.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. using Azure.Storage.Blobs.Models;
  2. using IES.ExamServer.Models;
  3. using Microsoft.Azure.Cosmos;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Text.Json;
  9. using System.Text.Json.Nodes;
  10. using System.Threading.Tasks;
  11. using TEAMModelOS.SDK.DI;
  12. using TEAMModelOS.SDK.Extension;
  13. using TEAMModelOS.SDK.Models.Cosmos;
  14. using TEAMModelOS.SDK.Models.Cosmos.Normal;
  15. using TEAMModelOS.SDK.Models.Cosmos.Student;
  16. using TEAMModelOS.SDK.Models.Dtos;
  17. namespace TEAMModelOS.SDK.Models.Service
  18. {
  19. public sealed class EvaluationSyncInfoService
  20. {
  21. /// <summary>
  22. /// 活动数据打包
  23. /// </summary>
  24. /// <param name="id"></param>
  25. /// <param name="scope"></param>
  26. /// <param name="owner"></param>
  27. /// <param name="type"></param>
  28. /// <param name="azureCosmos"></param>
  29. /// <param name="azureStorage"></param>
  30. public static async Task PackageEvaluation( string id,string scope, string owner, string type, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage,CoreAPIHttpService _coreAPIHttpService, DingDing _dingDing)
  31. {
  32. EvaluationSource evaluationSource = new EvaluationSource() { type=type,id=id};
  33. EvaluationSyncInfo evaluationSyncInfo= null;
  34. EvaluationClient evaluationClient = null;
  35. List<EvaluationExam> evaluationExams = new List<EvaluationExam>();
  36. School school = null;
  37. long? dataTime = 0;
  38. long stime = 0;
  39. long etime = 0;
  40. string schoolCode = null;
  41. if (scope.Equals("school"))
  42. {
  43. schoolCode= owner;
  44. school = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(owner, new PartitionKey("Base"));
  45. evaluationSource.school = school;
  46. }
  47. var responseEvaluationSyncInfo = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Normal).ReadItemStreamAsync(id, new PartitionKey("EvaluationSyncInfo"));
  48. if (responseEvaluationSyncInfo.IsSuccessStatusCode)
  49. {
  50. evaluationSyncInfo= JsonDocument.Parse(responseEvaluationSyncInfo.Content).RootElement.Deserialize<EvaluationSyncInfo>();
  51. }
  52. else {
  53. evaluationSyncInfo=new EvaluationSyncInfo {
  54. id = id,
  55. scope = scope,
  56. owner = owner,
  57. type = type,
  58. pk="EvaluationSyncInfo",
  59. code="ActivitySyncInfo",
  60. };
  61. }
  62. switch (true)
  63. {
  64. case bool when (type == "Exam"):
  65. {
  66. string code = $"Exam-{owner}";
  67. var response = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(id, new PartitionKey(code));
  68. if (response.IsSuccessStatusCode)
  69. {
  70. ExamInfo exam= JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamInfo>();
  71. dataTime= exam._ts*1000;
  72. evaluationSyncInfo.name=exam.name;
  73. evaluationSyncInfo.subjects = exam.subjects?.Select(x=>new IES.ExamServer.Models.SubjectExam { subjectId=x.id,subjectName=x.name,examId=id}).ToList();
  74. evaluationSyncInfo.dataTime= DateTimeOffset.Now.ToUnixTimeMilliseconds();
  75. evaluationSyncInfo.scode=exam.code;
  76. stime=exam.startTime;
  77. etime=exam.endTime;
  78. HashSet<string> grouplist = new HashSet<string>();
  79. if (exam.classes.IsNotEmpty()) {
  80. exam.classes.ForEach(x => { grouplist.Add(x); });
  81. }
  82. if (exam.stuLists.IsNotEmpty())
  83. {
  84. exam.stuLists.ForEach(x => { grouplist.Add(x); });
  85. }
  86. evaluationSyncInfo.grouplist=grouplist.ToList() ;
  87. evaluationSyncInfo.paperCount=exam.papers.IsNotEmpty()? exam.papers.Count():0;
  88. foreach (var group in exam.papers.GroupBy(x=>x.subjectId).Select(x=>new { key = x.Key,list= x.ToList()}))
  89. {
  90. var subject= exam.subjects.Find(x => x.id.Equals(group.key));
  91. if (subject!=null)
  92. {
  93. evaluationSyncInfo.subjects.Add(new IES.ExamServer.Models.SubjectExam {
  94. subjectId=subject.id,
  95. subjectName=subject.name,
  96. examId=id,
  97. papers= group.list.Select(x=>new SubjectExamPaper {paperId= x.id,paperName=x.name,blob=x.blob }).ToList(),
  98. } );
  99. EvaluationExam evaluationExam = new EvaluationExam()
  100. {
  101. examId=exam.id,
  102. evaluationId=evaluationSyncInfo.id,
  103. examName=evaluationSyncInfo.name,
  104. subjectId=subject.id,
  105. subjectName=subject.name,
  106. classes= evaluationSyncInfo.grouplist,
  107. owner=owner,
  108. scope=scope,
  109. stime=stime,
  110. etime=etime,
  111. papers= group.list.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, blob=x.blob, point=x.point,knowledge=x.knowledge,type=x.type,field=x.field }).ToList(),
  112. };
  113. evaluationExams.Add(evaluationExam);
  114. }
  115. }
  116. evaluationSource.exam=exam;
  117. }
  118. break;
  119. }
  120. case bool when (type == "Art"):
  121. {
  122. string code = $"Art-{owner}";
  123. var response = await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(id, new PartitionKey(code));
  124. if (response.IsSuccessStatusCode)
  125. {
  126. ArtEvaluation art = JsonDocument.Parse(response.Content).RootElement.Deserialize<ArtEvaluation>();
  127. // evaluationSyncInfo.subjects = art.subjects?.Select(x => new IES.ExamServer.Models.SubjectExam { id=x.id, name=x.name, examId=id }).ToList();
  128. evaluationSyncInfo.name = art.name;
  129. evaluationSyncInfo.pid= art.pId;
  130. evaluationSyncInfo.scode=art.code;
  131. evaluationSyncInfo.dataTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();
  132. HashSet<string> grouplist = new HashSet<string>();
  133. if (art.classes.IsNotEmpty())
  134. {
  135. art.classes.ForEach(x => { grouplist.Add(x); });
  136. }
  137. if (art.stuLists.IsNotEmpty())
  138. {
  139. art.stuLists.ForEach(x => { grouplist.Add(x); });
  140. }
  141. if (art.tchLists.IsNotEmpty())
  142. {
  143. art.tchLists.ForEach(x => { grouplist.Add(x); });
  144. }
  145. evaluationSyncInfo.grouplist=grouplist.ToList();
  146. evaluationSource.art=art;
  147. dataTime= art._ts*1000;
  148. stime=art.startTime;
  149. etime=art.endTime;
  150. var quota_22 = art.settings.Find(x => x.id.Equals("quota_21"));
  151. foreach (var item in quota_22.task)
  152. {
  153. if (!string.IsNullOrWhiteSpace(item.acId))
  154. {
  155. var subject = art.subjects.Find(x => x.id.Equals(item.subject));
  156. var examResponse= await azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).ReadItemStreamAsync(item.acId, new PartitionKey($"Exam-{owner}"));
  157. if (examResponse.IsSuccessStatusCode)
  158. {
  159. ExamInfo exam = JsonDocument.Parse(examResponse.Content).RootElement.Deserialize<ExamInfo>() ;
  160. var papers = exam.papers.FindAll(x => x.subjectId.Equals(item.subject));
  161. evaluationSyncInfo.subjects.Add(new IES.ExamServer.Models.SubjectExam
  162. {
  163. subjectId=item.subject,
  164. subjectName=subject.name,
  165. examId=item.acId,
  166. papers=papers?.Select(x => new SubjectExamPaper { paperId=x.id,paperName=x.name, blob=x.blob }).ToList(),
  167. });
  168. dataTime= dataTime<exam._ts*1000 ? exam._ts*1000 : dataTime;
  169. evaluationSource.artExams.Add(exam);
  170. EvaluationExam evaluationExam = new EvaluationExam()
  171. {
  172. examId=exam.id,
  173. evaluationId=evaluationSyncInfo.id,
  174. examName=evaluationSyncInfo.name,
  175. subjectId=subject.id,
  176. subjectName=subject.name,
  177. classes= evaluationSyncInfo.grouplist,
  178. owner=owner,
  179. scope=scope,
  180. stime=stime,
  181. etime=etime,
  182. papers= papers.Select(x => new EvaluationPaper { paperId= x.id, paperName=x.name, blob=x.blob, point=x.point, knowledge=x.knowledge, type=x.type, field=x.field }).ToList(),
  183. };
  184. evaluationExams.Add(evaluationExam);
  185. }
  186. }
  187. }
  188. }
  189. }
  190. break;
  191. default:
  192. break;
  193. }
  194. if (evaluationSyncInfo.subjects.IsNotEmpty() && evaluationSyncInfo.grouplist.IsNotEmpty())
  195. {
  196. long blobTime =-1;
  197. long blobSize = 0;
  198. long blobCount = 0;
  199. if (!string.IsNullOrWhiteSpace(evaluationSyncInfo.shortCode))
  200. {
  201. evaluationSyncInfo.shortCode = $"{MurmurHash3.Hash32(evaluationSyncInfo.id)}";
  202. }
  203. var listInfo = await GroupListService.GetMemberByListids(_coreAPIHttpService, azureCosmos.GetCosmosClient(), _dingDing, evaluationSyncInfo.grouplist, schoolCode);
  204. evaluationSyncInfo.studentCount = listInfo.rmembers.Count();
  205. evaluationSyncInfo.paperCount =evaluationSyncInfo.subjects.Select(x => x.papers).Count();
  206. var client = azureStorage.GetBlobContainerClient(owner);
  207. foreach (var subject in evaluationSyncInfo.subjects)
  208. {
  209. var evaluationExam = evaluationExams.FindAll(x => x.subjectId.Equals(subject.subjectId)).FirstOrDefault();
  210. foreach (var paper in subject.papers)
  211. {
  212. List<BlobHashInfo> blobs = new List<BlobHashInfo>();
  213. try
  214. {
  215. await foreach (BlobItem blobItem in client.GetBlobsAsync(BlobTraits.None, BlobStates.None, paper.blob))
  216. {
  217. var lastModified = blobItem.Properties.LastModified;
  218. if (lastModified.HasValue)
  219. {
  220. lastModified.Value.ToUnixTimeMilliseconds();
  221. }
  222. var hash = blobItem.Properties.ContentHash;
  223. var path = blobItem.Name;
  224. var size = blobItem.Properties.ContentLength;
  225. blobs.Add(new BlobHashInfo
  226. {
  227. hash = Md5Hash.GetbyteToString(hash),
  228. last = lastModified.HasValue ? lastModified.Value.ToUnixTimeMilliseconds() : 0,
  229. path = path,
  230. size = size.HasValue ? size.Value : 0
  231. });
  232. };
  233. var evaluationPaper= evaluationExam.papers.Find(x => x.paperId.Equals(paper.paperId));
  234. evaluationPaper.blobs=blobs;
  235. }
  236. catch
  237. {
  238. }
  239. long lastTime = blobs.Max(x => x.last);
  240. blobTime= lastTime>blobTime?lastTime:blobTime;
  241. if (blobs.IsNotEmpty())
  242. {
  243. blobSize+=blobs.Sum(x => x.size);
  244. blobCount+=blobs.Count;
  245. var order = blobs.OrderBy(x => $"{x.path}-{x.hash}-{x.size}-{x.last}");
  246. string blobStr = string.Join(",", order.Select(x=> $"{x.path}-{x.hash}-{x.size}-{x.last}"));
  247. // 计算hash,校准路径,文件hash,文件大小,最后修改时间
  248. paper.paperHash= ShaHashHelper.GetSHA1(blobStr);
  249. }
  250. }
  251. }
  252. evaluationSyncInfo.blobTime = blobTime> evaluationSyncInfo.blobTime ? blobTime : evaluationSyncInfo.blobTime;
  253. evaluationSyncInfo.blobSize = blobSize;
  254. evaluationSyncInfo.blobCount = blobCount;
  255. evaluationSyncInfo.blobLastHash = evaluationSyncInfo.blobHash;
  256. evaluationSyncInfo.blobHash = ShaHashHelper.GetSHA1(string.Join("-", evaluationSyncInfo.subjects.SelectMany(x => x.papers).Select(x => x.paperHash)));
  257. evaluationSyncInfo.dataTime = dataTime.Value;
  258. evaluationSource.updateTime = dataTime.Value;
  259. evaluationClient= new EvaluationClient
  260. {
  261. id = evaluationSyncInfo.id,
  262. pid = evaluationSyncInfo.pid,
  263. name = evaluationSyncInfo.name,
  264. type = evaluationSyncInfo.type,
  265. owner = evaluationSyncInfo.owner,
  266. scode = evaluationSyncInfo.scode,
  267. scope = evaluationSyncInfo.scope,
  268. subjects = evaluationSyncInfo.subjects,
  269. dataTime = evaluationSyncInfo.dataTime,
  270. dataSize = evaluationSyncInfo.dataSize,
  271. blobTime = evaluationSyncInfo.blobTime,
  272. blobSize = evaluationSyncInfo.blobSize,
  273. blobCount = evaluationSyncInfo.blobCount,
  274. blobHash = evaluationSyncInfo.blobHash,
  275. blobLastHash = evaluationSyncInfo.blobLastHash,
  276. webviewCount = evaluationSyncInfo.webviewCount,
  277. webviewPath = evaluationSyncInfo.webviewPath,
  278. webviewSize = evaluationSyncInfo.webviewSize,
  279. webviewTime = evaluationSyncInfo.webviewTime,
  280. studentCount = evaluationSyncInfo.studentCount,
  281. paperCount = evaluationSyncInfo.paperCount,
  282. grouplist = evaluationSyncInfo.grouplist,
  283. shortCode = evaluationSyncInfo.shortCode,
  284. stime=stime,
  285. etime=etime
  286. //password = evaluationSyncInfo.password,
  287. //recordUrl = evaluationSyncInfo.recordUrl
  288. };
  289. var groupList = new { members = listInfo.rmembers, groupList= listInfo.groups };
  290. await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(evaluationSource.ToJsonString(),$"package/{id}", "source.json");
  291. await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(groupList.ToJsonString(), $"package/{id}", "groupList.json");
  292. // await azureStorage.GetBlobContainerClient(owner).UploadFileByContainer(evaluationSyncInfo.ToJsonString(), $"package/{id}", "syncinfo.json");
  293. }
  294. }
  295. }
  296. }