TriggerSurvey.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. using Azure.Cosmos;
  2. using Azure.Messaging.ServiceBus;
  3. using Azure.Storage.Blobs.Models;
  4. using Microsoft.Azure.Documents;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Net.Http;
  8. using System.Text;
  9. using System.Text.Json;
  10. using System.Threading.Tasks;
  11. using TEAMModelOS.SDK.DI;
  12. using TEAMModelOS.SDK.Extension;
  13. using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
  14. using TEAMModelOS.SDK.Models;
  15. using TEAMModelOS.SDK.Models.Cosmos;
  16. using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
  17. using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
  18. namespace TEAMModelFunction
  19. {
  20. public class TriggerSurvey
  21. {
  22. public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
  23. CosmosClient client, Document input, string code, long stime, long etime, string school,AzureRedisFactory _azureRedis, System.Net.Http.IHttpClientFactory _clientFactory)
  24. {
  25. Survey survey = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Survey>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
  26. List<ChangeRecord> changeRecords = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", survey.progress } });
  27. if (survey.ttl >= 1)
  28. {
  29. //TODO 处理TTL删除业务
  30. return;
  31. }
  32. switch (survey.progress)
  33. {
  34. case "pending":
  35. var messageSurvey = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
  36. messageSurvey.ApplicationProperties.Add("name", "Survey");
  37. if (changeRecords.Count > 0)
  38. {
  39. await _serviceBus.GetServiceBusClient().cancelMessage("active-task", changeRecords[0].sequenceNumber);
  40. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurvey, DateTimeOffset.FromUnixTimeMilliseconds(stime));
  41. changeRecords[0].sequenceNumber = start;
  42. await _azureStorage.SaveOrUpdate<ChangeRecord>(changeRecords[0]);
  43. }
  44. else
  45. {
  46. long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurvey, DateTimeOffset.FromUnixTimeMilliseconds(stime));
  47. ChangeRecord changeRecord = new ChangeRecord
  48. {
  49. RowKey = input.Id,
  50. PartitionKey = "pending",
  51. sequenceNumber = start,
  52. msgId = messageSurvey.MessageId
  53. };
  54. await _azureStorage.Save<ChangeRecord>(changeRecord);
  55. }
  56. break;
  57. case "going":
  58. ActivityData data;
  59. if (survey.scope == "school")
  60. {
  61. data = new ActivityData
  62. {
  63. id = survey.id,
  64. code = $"Activity-{survey.owner}",
  65. type = "survey",
  66. name = survey.name,
  67. startTime = survey.startTime,
  68. endTime = survey.endTime,
  69. scode = survey.code,
  70. scope = survey.scope,
  71. classes = survey.classes.IsNotEmpty() ? survey.classes : new List<string> { "" },
  72. tmdids = survey.tmdids.IsNotEmpty() ? survey.tmdids : new List<string> { "" },
  73. progress = "going",
  74. owner = survey.owner,
  75. subjects = new List<string> { "" }
  76. };
  77. await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
  78. }
  79. else if (survey.scope == "private")
  80. {
  81. data = new ActivityData
  82. {
  83. id = survey.id,
  84. code = $"Activity-Common",
  85. type = "survey",
  86. name = survey.name,
  87. startTime = survey.startTime,
  88. endTime = survey.endTime,
  89. scode = survey.code,
  90. scope = survey.scope,
  91. progress = "going",
  92. classes = survey.classes.IsNotEmpty() ? survey.classes : new List<string> { "" },
  93. owner = survey.owner,
  94. tmdids = new List<string> { "" },
  95. subjects = new List<string> { "" }
  96. };
  97. await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
  98. }
  99. var messageSurveyEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
  100. messageSurveyEnd.ApplicationProperties.Add("name", "Survey");
  101. if (changeRecords.Count > 0)
  102. {
  103. long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurveyEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
  104. await _serviceBus.GetServiceBusClient().cancelMessage("active-task", changeRecords[0].sequenceNumber);
  105. changeRecords[0].sequenceNumber = end;
  106. await _azureStorage.SaveOrUpdate<ChangeRecord>(changeRecords[0]);
  107. }
  108. else
  109. {
  110. long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageSurveyEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
  111. ChangeRecord changeRecord = new ChangeRecord
  112. {
  113. RowKey = input.Id,
  114. PartitionKey = "going",
  115. sequenceNumber = end,
  116. msgId = messageSurveyEnd.MessageId
  117. };
  118. await _azureStorage.Save<ChangeRecord>(changeRecord);
  119. }
  120. break;
  121. case "finish":
  122. var records = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"Survey:Record:{survey.id}");
  123. List<dynamic> recs = new List<dynamic>();
  124. foreach (var rcd in records)
  125. {
  126. var value = rcd.Value.ToString().ToObject<JsonElement>();
  127. recs.Add(new { index = rcd.Name.ToString(), ans = value });
  128. }
  129. var cods = new { records = recs };
  130. //问卷整体情况
  131. await _azureStorage.UploadFileByContainer(survey.owner, cods.ToJsonString(), "survey", $"{survey.id}/record.json");
  132. //结算每道题的答题情况
  133. var ContainerClient = _azureStorage.GetBlobContainerClient(survey.owner);
  134. var route = ContainerClient.Uri.ToString();
  135. List<BlobItem> items = await ContainerClient.List($"survey/{survey.id}/urecord");
  136. List<SurveyRecord> surveyRecords = new List<SurveyRecord>();
  137. //获取
  138. foreach (BlobItem item in items)
  139. {
  140. BlobAuth blobAuth = _azureStorage.GetBlobSasUriRead(survey.owner, $"{item.Name}");
  141. var url = $"{route}/{item.Name}?{blobAuth.sas}";
  142. var response = await _clientFactory.CreateClient().GetAsync(new Uri(url));
  143. var json = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
  144. var Record = json.RootElement.ToObject<SurveyRecord>();
  145. surveyRecords.Add(Record);
  146. }
  147. List<Task<string>> tasks = new List<Task<string>>();
  148. for (int index = 0; index < survey.ans.Count; index++)
  149. {
  150. string url = $"{survey.id}/qrecord/{index}.json";
  151. QuestionRecord question = new QuestionRecord() { index = index };
  152. foreach (SurveyRecord record in surveyRecords)
  153. {
  154. if (record.ans.Count == survey.ans.Count)
  155. {
  156. foreach (var an in record.ans[index])
  157. {
  158. //
  159. if (question.opt.ContainsKey(an))
  160. {
  161. if (question.opt[an] != null)
  162. {
  163. question.opt[an].Add(record.userid);
  164. }
  165. else
  166. {
  167. question.opt[an] = new HashSet<string>() { record.userid };
  168. }
  169. }
  170. else
  171. {
  172. if (survey.ans[index].Contains(an))
  173. {
  174. //如果是客观题code
  175. question.opt.Add(an, new HashSet<string> { record.userid });
  176. }
  177. else
  178. {
  179. //如果不是客观code
  180. question.other[record.userid] = an;
  181. }
  182. }
  183. }
  184. }
  185. }
  186. tasks.Add(_azureStorage.UploadFileByContainer(survey.owner, question.ToJsonString(), "survey", url, false));
  187. }
  188. await Task.WhenAll(tasks);
  189. if (string.IsNullOrEmpty(survey.recordUrl)) {
  190. survey.recordUrl = $"/survey/{survey.id}/record.json";
  191. await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync<Survey>(survey, survey.id, new Azure.Cosmos.PartitionKey(survey.code));
  192. }
  193. //更新结束状态
  194. if (survey.scope == "school")
  195. {
  196. data = new ActivityData
  197. {
  198. id = survey.id,
  199. code = $"Activity-{survey.owner}",
  200. type = "survey",
  201. name = survey.name,
  202. startTime = survey.startTime,
  203. endTime = survey.endTime,
  204. scode = survey.code,
  205. scope = survey.scope,
  206. progress = "finish",
  207. classes = survey.classes.IsNotEmpty() ? survey.classes : new List<string> { "" },
  208. tmdids = survey.tmdids.IsNotEmpty() ? survey.tmdids : new List<string> { "" },
  209. owner = survey.owner,
  210. subjects = new List<string> { "" }
  211. };
  212. await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<ActivityData>(data, data.id, new Azure.Cosmos.PartitionKey(data.code));
  213. }
  214. else if (survey.scope == "private")
  215. {
  216. //更新结束状态
  217. data = new ActivityData
  218. {
  219. id = survey.id,
  220. code = $"Activity-Common",
  221. type = "survey",
  222. name = survey.name,
  223. startTime = survey.startTime,
  224. endTime = survey.endTime,
  225. scode = survey.code,
  226. scope = survey.scope,
  227. progress = "finish",
  228. classes = survey.classes.IsNotEmpty() ? survey.classes : new List<string> { "" },
  229. owner = survey.owner,
  230. tmdids = new List<string> { "" },
  231. subjects = new List<string> { "" }
  232. };
  233. await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<ActivityData>(data, data.id, new Azure.Cosmos.PartitionKey(data.code));
  234. }
  235. break;
  236. }
  237. }
  238. }
  239. /**
  240. * {survey.id}/qrecord/{index}.json
  241. {
  242. "opt": {
  243. "A": [
  244. "userid1",
  245. "userid2",
  246. "userid3"
  247. ],
  248. "B": [
  249. "userid1",
  250. "userid2",
  251. "userid3"
  252. ]
  253. },
  254. "other": {
  255. "userid1": "建议XXXX1",
  256. "userid2": "建议XXXX2"
  257. }
  258. }
  259. **/
  260. public class QuestionRecord {
  261. public int index { get; set; }
  262. public Dictionary<string, HashSet<string>> opt { get; set; } = new Dictionary<string, HashSet<string>>();
  263. public Dictionary<string, string> other { get; set; } = new Dictionary<string, string>();
  264. }
  265. }