SurveyController.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. using Microsoft.Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.AspNetCore.Mvc;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IdentityModel.Tokens.Jwt;
  7. using System.Text;
  8. using System.Text.Json;
  9. using System.Threading.Tasks;
  10. using TEAMModelOS.Models.Dto;
  11. using TEAMModelOS.SDK.Models;
  12. using TEAMModelOS.SDK;
  13. using TEAMModelOS.SDK.DI;
  14. using TEAMModelOS.SDK.DI;
  15. using TEAMModelOS.SDK.Extension;
  16. using TEAMModelOS.Models;
  17. using Microsoft.Extensions.Options;
  18. using TEAMModelOS.Filter;
  19. using Azure.Storage.Blobs.Models;
  20. using TEAMModelOS.SDK.Models.Cosmos.Inner;
  21. using TEAMModelOS.SDK.Module.AzureBlob.Configuration;
  22. using System.Net.Http;
  23. using TEAMModelOS.SDK.Models.Cosmos;
  24. using Azure.Messaging.ServiceBus;
  25. using Azure.Storage.Sas;
  26. using TEAMModelOS.SDK.Models.Cosmos;
  27. using Microsoft.Extensions.Configuration;
  28. using System.IO;
  29. using Microsoft.AspNetCore.Authorization;
  30. using TEAMModelOS.SDK.Services;
  31. using TEAMModelOS.SDK.Models.Service.BI;
  32. namespace TEAMModelOS.Controllers
  33. {
  34. /// <summary>
  35. /// 投票活动
  36. /// </summary>
  37. [ProducesResponseType(StatusCodes.Status200OK)]
  38. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  39. [Route("common/survey")]
  40. [ApiController]
  41. public class SurveyController : ControllerBase
  42. {
  43. private readonly AzureRedisFactory _azureRedis;
  44. private readonly AzureCosmosFactory _azureCosmos;
  45. private readonly SnowflakeId _snowflakeId;
  46. private readonly AzureServiceBusFactory _serviceBus;
  47. private readonly DingDing _dingDing;
  48. private readonly Option _option;
  49. private readonly AzureStorageFactory _azureStorage;
  50. private readonly IHttpClientFactory _clientFactory;
  51. public IConfiguration _configuration { get; set; }
  52. public SurveyController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option,
  53. AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, IHttpClientFactory clientFactory, IConfiguration configuration)
  54. {
  55. _snowflakeId = snowflakeId;
  56. _serviceBus = serviceBus;
  57. _azureCosmos = azureCosmos;
  58. _dingDing = dingDing;
  59. _option = option?.Value;
  60. _azureRedis = azureRedis;
  61. _azureStorage = azureStorage;
  62. _clientFactory = clientFactory;
  63. _configuration = configuration;
  64. }
  65. /// <summary>
  66. /// 新增 或 修改投票活动
  67. /// </summary>
  68. /// <param name="request"></param>
  69. /// <returns></returns>
  70. [ProducesDefaultResponseType]
  71. [HttpPost("upsert")]
  72. [Authorize(Roles = "IES")]
  73. [AuthToken(Roles = "teacher,admin", Permissions = "schoolAc-upd")]
  74. public async Task<IActionResult> Upsert(Survey request)
  75. {
  76. try
  77. {
  78. var client = _azureCosmos.GetCosmosClient();
  79. request.code = request.pk + "-" + request.code;
  80. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  81. request.createTime = now;
  82. request.ttl = -1;
  83. //如果设置的时间是小于当前时间则立即发布
  84. if (request.startTime <= 0)
  85. {
  86. request.startTime = now;
  87. }
  88. if (string.IsNullOrEmpty(request.id))
  89. {
  90. request.id = Guid.NewGuid().ToString();
  91. if (string.IsNullOrEmpty(request.progress))
  92. {
  93. if (request.startTime > now)
  94. {
  95. request.progress = "pending";
  96. }
  97. else
  98. {
  99. request.progress = "going";
  100. }
  101. }
  102. var messageBlob = new ServiceBusMessage();
  103. string blobcntr = null;
  104. if (request.scope.Equals("school"))
  105. {
  106. blobcntr = request.school;
  107. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"survey/{request.id}");
  108. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "insert", root = $"survey", name = $"{request.school}" }, _serviceBus, _configuration, _azureRedis);
  109. }
  110. else
  111. {
  112. blobcntr = request.creatorId;
  113. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"survey/{request.id}");
  114. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "insert", root = $"survey", name = $"{request.creatorId}" }, _serviceBus, _configuration, _azureRedis);
  115. }
  116. request.recordUrl = $"/survey/{request.id}/record.json";
  117. var cods = new { records = new List<string>(), userids = new List<string>(), question = new List<QuestionRecord>() };
  118. await _azureStorage.GetBlobContainerClient(blobcntr).UploadFileByContainer(cods.ToJsonString(), "survey", $"{request.id}/record.json");
  119. request = await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  120. await BIStats.SetTypeAddStats(client, _dingDing, request.school, "Survey", 1);//BI统计增/减量
  121. }
  122. else
  123. {
  124. string blobcntr = null;
  125. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(request.id, new PartitionKey($"{request.code}"));
  126. if (request.scope.Equals("school"))
  127. {
  128. blobcntr = request.school;
  129. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"survey/{request.id}");
  130. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = $"survey", name = $"{request.school}" }, _serviceBus, _configuration, _azureRedis);
  131. }
  132. else
  133. {
  134. blobcntr = request.creatorId;
  135. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"survey/{request.id}");
  136. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "update", root = $"survey", name = $"{request.creatorId}" }, _serviceBus, _configuration, _azureRedis);
  137. }
  138. if (response.StatusCode==System.Net.HttpStatusCode.OK)
  139. {
  140. using var json = await JsonDocument.ParseAsync(response.Content);
  141. var info = json.ToObject<Survey>();
  142. /* if (info.progress.Equals("going"))
  143. {
  144. return Ok(new { v = "活动正在进行中" });
  145. }*/
  146. if (string.IsNullOrEmpty(request.progress))
  147. {
  148. if (request.startTime > now)
  149. {
  150. request.progress = "pending";
  151. }
  152. else
  153. {
  154. request.progress = "going";
  155. }
  156. }
  157. //request.progress = info.progress;
  158. request.recordUrl = $"/survey/{request.id}/record.json";
  159. request = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(request, info.id, new PartitionKey($"{info.code}"));
  160. }
  161. else
  162. {
  163. if (string.IsNullOrEmpty(request.progress))
  164. {
  165. if (request.startTime > now)
  166. {
  167. request.progress = "pending";
  168. }
  169. else
  170. {
  171. request.progress = "going";
  172. }
  173. }
  174. request.recordUrl = $"/survey/{request.id}/record.json";
  175. var cods = new { records = new List<string>(), userids = new List<string>(), question = new List<QuestionRecord>() };
  176. await _azureStorage.GetBlobContainerClient(blobcntr).UploadFileByContainer(cods.ToJsonString(), "survey", $"{request.id}/record.json");
  177. request = await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  178. await BIStats.SetTypeAddStats(client, _dingDing, request.school, "Survey", 1);//BI统计增/减量
  179. }
  180. }
  181. return Ok(new { survey = request });
  182. }
  183. catch (Exception ex)
  184. {
  185. await _dingDing.SendBotMsg($"OS,{_option.Location},common/survey/save()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
  186. return BadRequest(ex.StackTrace);
  187. }
  188. }
  189. /// <summary>
  190. /// 查询问卷调查,用于列表,编辑,查看
  191. /// </summary>
  192. /// <data>
  193. ///Survey-学校/教师编码 活动分区 !"code":"hbcn"/1606285227
  194. ///时间筛选范围开始时间 默认30天之前 ?"stime":1608274766154
  195. ///时间筛选范围结束时间 默认当前时间 ?"etime":1608274766666
  196. ///每页大小 ?"count":10/null/Undefined
  197. ///分页Token ?"continuationToken":Undefined/null/"[{\"token\":\"+RID:~omxMAP3ipcSEEwAAAAAAAA==#RT:2#TRC:20#ISV:2#IEO:65551#QCF:1#FPC:AYQTAAAAAAAAiRMAAAAAAAA=\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]"
  198. /// 当前状态 ?"progress":Undefined/null/"" 表示两种状态都要查询/ "going"/"finish" 表示查询进行中/ 或者已完成 学生端只能查询正在进行或已经结束 going 已发布|finish 已结束
  199. /// </data>
  200. /// <param name="request"></param>
  201. /// <returns></returns>
  202. [ProducesDefaultResponseType]
  203. [HttpPost("find")]
  204. [Authorize(Roles = "IES")]
  205. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-read,schoolAc-upd")]
  206. public async Task<IActionResult> Find(JsonElement request)
  207. {
  208. try
  209. {
  210. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  211. //必须有学校或者教师编码
  212. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  213. //开始时间,
  214. var stimestamp = "";
  215. if (request.TryGetProperty("stime", out JsonElement stime))
  216. {
  217. if (long.TryParse($"{stime}", out long data))
  218. {
  219. stimestamp = $" and c.createTime >= {data} ";
  220. };
  221. };
  222. //默认当前时间
  223. var etimestamp = "";
  224. if (request.TryGetProperty("etime", out JsonElement etime))
  225. {
  226. if (long.TryParse($"{etime}", out long data))
  227. {
  228. etimestamp = $" and c.createTime <= {data} ";
  229. };
  230. };
  231. var progresssql = "";
  232. if (request.TryGetProperty("progress", out JsonElement progress))
  233. {
  234. if (!progress.ValueKind.Equals(JsonValueKind.Undefined) && !progress.ValueKind.Equals(JsonValueKind.Null) && progress.ValueKind.Equals(JsonValueKind.String))
  235. {
  236. progresssql = $" and c.progress='{progress}' ";
  237. }
  238. }
  239. string token = null;
  240. //默认不指定返回大小
  241. int? topcout = null;
  242. if (request.TryGetProperty("count", out JsonElement jcount))
  243. {
  244. if (int.TryParse($"{jcount}", out int data))
  245. {
  246. topcout = data;
  247. }
  248. };
  249. //是否需要进行分页查询,默认不分页
  250. bool iscontinuation = false;
  251. if (topcout != null && topcout.Value > 0)
  252. {
  253. iscontinuation = true;
  254. }
  255. //如果指定了返回大小
  256. if (request.TryGetProperty("token", out JsonElement continuation))
  257. {
  258. //指定了cancellationToken 表示需要进行分页
  259. if (!continuation.ValueKind.Equals(JsonValueKind.Null) && !continuation.ValueKind.Equals(JsonValueKind.Undefined))
  260. {
  261. token = continuation.GetString();
  262. }
  263. };
  264. List<Survey> surveys = new List<Survey>();
  265. var client = _azureCosmos.GetCosmosClient();
  266. var query = $"select c.owner, c.id,c.name,c.code,c.startTime,c.endTime,c.progress,c.classes,c.scope,c.school,c.targetType from c where (c.status<>404 or IS_DEFINED(c.status) = false ) and c.ttl=-1 {stimestamp} {etimestamp} {progresssql} ";
  267. if (string.IsNullOrEmpty(school))
  268. {
  269. query = $"{query} and c.scope='private' ";
  270. }
  271. query = $"{query} order by c.createTime desc ";
  272. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIteratorSql(queryText: query, continuationToken: token,
  273. requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Survey-{code}") }))
  274. {
  275. using var json = await JsonDocument.ParseAsync(item.Content);
  276. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  277. {
  278. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  279. {
  280. if (!string.IsNullOrEmpty(school))
  281. {
  282. obj.TryGetProperty("scope", out JsonElement scope);
  283. obj.TryGetProperty("school", out JsonElement sco);
  284. //只能查出相关学校的
  285. if (!scope.GetString().Equals("private") && !string.IsNullOrEmpty(sco.GetString()) && sco.GetString().Equals(school))
  286. {
  287. surveys.Add(obj.ToObject<Survey>());
  288. }
  289. //和自己私人发布的
  290. if (scope.GetString().Equals("private"))
  291. {
  292. surveys.Add(obj.ToObject<Survey>());
  293. }
  294. }
  295. else
  296. {
  297. surveys.Add(obj.ToObject<Survey>());
  298. }
  299. }
  300. }
  301. if (iscontinuation)
  302. {
  303. token = item.ContinuationToken;
  304. break;
  305. }
  306. }
  307. //var query = $"select c.id,c.name,c.code,c.startTime,c.endTime,c.progress,c.classes from c where c.createTime >= {stimestamp} and c.createTime <= {etimestamp} {progresssql } ";
  308. //await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIteratorSql(queryText: query,
  309. // requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Survey-{code}") }))
  310. //{
  311. // using var json = await JsonDocument.ParseAsync(item.Content);
  312. // if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  313. // {
  314. // foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  315. // {
  316. // surveys.Add(obj.ToObject<JsonElement>());
  317. // }
  318. // //如果需要分页则跳出
  319. // if (iscontinuation)
  320. // {
  321. // continuationToken = item.ContinuationToken;
  322. // break;
  323. // }
  324. // }
  325. //}
  326. return Ok(new { surveys, token });
  327. }
  328. catch (Exception ex)
  329. {
  330. await _dingDing.SendBotMsg($"OS,{_option.Location},common/survey/find()\n", GroupNames.醍摩豆服務運維群組);
  331. return BadRequest(ex.StackTrace);
  332. }
  333. }
  334. ///<summary>
  335. /// 查询问卷调查,用于创建者列表,编辑,查看,作答人员查看
  336. /// </summary>
  337. /// <data>
  338. /// ! "id":"3c075347-75ef-4bcb-ae03-68678d02d5ef",
  339. /// ! "code":"Survey-hbcn"/"code":"Survey-1606285227"
  340. /// </data>
  341. /// <param name="request"></param>
  342. /// <returns></returns>
  343. [ProducesDefaultResponseType]
  344. [HttpPost("find-id")]
  345. [Authorize(Roles = "IES")]
  346. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-read,schoolAc-upd")]
  347. public async Task<IActionResult> FindById(JsonElement request)
  348. {
  349. Survey survey = null;
  350. //活动id
  351. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  352. //活动分区
  353. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  354. try
  355. {
  356. var client = _azureCosmos.GetCosmosClient();
  357. survey = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Survey>(id.GetString(), new PartitionKey($"{code}"));
  358. if (survey != null)
  359. {
  360. return Ok(new { survey, status = 200 });
  361. }
  362. else
  363. {
  364. return Ok(new { survey, status = 404 });
  365. }
  366. }
  367. catch (CosmosException ex)
  368. {
  369. return Ok(new { survey, status = 404 });
  370. }
  371. catch (Exception ex)
  372. {
  373. await _dingDing.SendBotMsg($"OS,{_option.Location},common/survey/find-id\n{ex.Message}\n{ex.StackTrace}\n{id}\n{code} ", GroupNames.醍摩豆服務運維群組);
  374. return Ok(new { survey, status = 404 });
  375. }
  376. }
  377. /// <summary>
  378. /// 删除问卷调查 TODO 使用ttl删除,并处理相关事务逻辑
  379. /// </summary>
  380. /// <param name="request"></param>
  381. /// <returns></returns>
  382. [ProducesDefaultResponseType]
  383. [HttpPost("delete")]
  384. [Authorize(Roles = "IES")]
  385. [AuthToken(Roles = "teacher,admin", Permissions = "schoolAc-upd")]
  386. public async Task<IActionResult> Delete(JsonElement request)
  387. {
  388. try
  389. {
  390. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  391. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  392. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  393. var client = _azureCosmos.GetCosmosClient();
  394. Survey survey = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Survey>(id.GetString(), new PartitionKey($"{code}"));
  395. bool flag = false;
  396. //必须是本人或者这个学校的管理者才能删除
  397. if (survey.creatorId == userid)
  398. {
  399. flag = true;
  400. }
  401. else
  402. {
  403. if (survey.scope.Equals("school") && survey.school.Equals(school))
  404. {
  405. flag = true;
  406. }
  407. }
  408. if (flag)
  409. {
  410. //使用ttl删除,并处理相关事务逻辑
  411. survey.status = 404;
  412. survey = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(survey, survey.id, new PartitionKey($"{survey.code}"));
  413. _azureRedis.GetRedisClient(8).KeyDelete($"Survey:Record:{survey.id}");
  414. _azureRedis.GetRedisClient(8).KeyDelete($"Survey:Submit:{survey.id}");
  415. //删除blob 相关资料
  416. await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, $"{code}".Replace("Survey-", ""), new List<string> { Path.Combine("survey", survey.id) + "/" });
  417. //通知删除信息
  418. await BlobService.RefreshBlobRoot(new BlobRefreshMessage { progress = "delete", root = $"survey", name = $"{code}".Replace("Survey-", "") }, _serviceBus, _configuration, _azureRedis);
  419. await _dingDing.SendBotMsg($"{_option.Location}-问卷调查【{survey.name}-{survey.id}】被删除", GroupNames.醍摩豆服務運維群組);
  420. return Ok(new { flag });
  421. }
  422. else
  423. {
  424. return Ok(new { flag });
  425. }
  426. }
  427. catch (Exception e)
  428. {
  429. return BadRequest(e.StackTrace);
  430. }
  431. }
  432. /// <summary>
  433. /// 问卷答案提交
  434. /// </summary>
  435. /// <redis>
  436. /// Survey:Record:e6b887f8-adb5-3677-bcc7-3b36450909df_Survey-1595321354 {"C":2,"A":2,"other":2}
  437. /// </redis>
  438. /// <param name="request">
  439. /// !"id":"aaaa"
  440. /// !"code":"Survey-hbcn"/"code":"Survey-1606285227"
  441. /// !"record":[["A","B"],["A"],["D"],[],["建议提升服务质量"]]
  442. /// </param>
  443. /// <returns>
  444. /// msgid=0投票失败,1提交成功,2不在时间范围内,3不在发布范围内,6未设置投票项
  445. /// </returns>
  446. [ProducesDefaultResponseType]
  447. [HttpPost("answer")]
  448. [Authorize(Roles = "IES")]
  449. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-upd,schoolAc-read")]
  450. public async Task<IActionResult> Answer(JsonElement request)
  451. {
  452. object userScope = null;
  453. object _standard = null;
  454. string standard = null;
  455. HttpContext?.Items?.TryGetValue("Scope", out userScope);
  456. if (userScope != null && $"{userScope}".Equals(Constant.ScopeTeacher))
  457. {
  458. HttpContext?.Items?.TryGetValue("Standard", out _standard);
  459. standard = _standard != null && string.IsNullOrEmpty($"{userScope}") ? _standard.ToString() : null;
  460. }
  461. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  462. if (request.TryGetProperty("userid", out JsonElement _userid))
  463. {
  464. (int msgid, int taskStatus) = await ActivityStudentService.Answer(_dingDing, _option, request, _azureCosmos, _azureRedis, $"{userid}", school, _azureStorage, standard, _serviceBus, _configuration);
  465. return Ok(new { msgid, taskStatus });
  466. }
  467. else { return Ok(new { msgid = 0 }); }
  468. }
  469. /// <summary>
  470. /// 问卷答案提交
  471. /// </summary>
  472. /// <redis>
  473. /// Survey:Record:e6b887f8-adb5-3677-bcc7-3b36450909df_Survey-1595321354 {"C":2,"A":2,"other":2}
  474. /// </redis>
  475. /// <param name="request">
  476. /// !"id":"aaaa"
  477. /// !"code":"Survey-hbcn"/"code":"Survey-1606285227"
  478. /// </param>
  479. /// <returns>
  480. /// msgid=0投票失败,1提交成功,2不在时间范围内,3不在发布范围内,6未设置投票项
  481. /// </returns>
  482. [ProducesDefaultResponseType]
  483. [HttpPost("answered-list")]
  484. [Authorize(Roles = "IES")]
  485. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-upd,schoolAc-read")]
  486. public async Task<IActionResult> AnsweredList(JsonElement request)
  487. {
  488. // var (userid, _, _, _) = HttpContext.GetAuthTokenInfo();
  489. if (!request.TryGetProperty("id", out JsonElement id))
  490. {
  491. return BadRequest();
  492. }
  493. //活动分区
  494. if (!request.TryGetProperty("code", out JsonElement code))
  495. {
  496. return BadRequest();
  497. }
  498. List<string> userids = new List<string>();
  499. var values = await _azureRedis.GetRedisClient(8).SetMembersAsync($"Survey:Submit:{id}");
  500. if (values != default && values.Length > 0)
  501. {
  502. foreach (var val in values)
  503. {
  504. userids.Add(val);
  505. }
  506. }
  507. return Ok(new { userids = userids });
  508. }
  509. /// <summary>
  510. /// 问卷答案提交
  511. /// </summary>
  512. /// <redis>
  513. /// Survey:Record:e6b887f8-adb5-3677-bcc7-3b36450909df_Survey-1595321354 {"C":2,"A":2,"other":2}
  514. /// </redis>
  515. /// <param name="request">
  516. /// !"id":"aaaa"
  517. /// !"code":"Survey-hbcn"/"code":"Survey-1606285227"
  518. /// </param>
  519. /// <returns>
  520. /// msgid=0投票失败,1提交成功,2不在时间范围内,3不在发布范围内,6未设置投票项
  521. /// </returns>
  522. [ProducesDefaultResponseType]
  523. [HttpPost("answered")]
  524. [Authorize(Roles = "IES")]
  525. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-upd,schoolAc-read")]
  526. public async Task<IActionResult> Answered(JsonElement request)
  527. {
  528. var (userid, _, _, _) = HttpContext.GetAuthTokenInfo();
  529. if (!request.TryGetProperty("id", out JsonElement id))
  530. {
  531. return BadRequest();
  532. }
  533. //活动分区
  534. if (!request.TryGetProperty("code", out JsonElement code))
  535. {
  536. return BadRequest();
  537. }
  538. List<string> userids = new List<string>();
  539. var answered = await _azureRedis.GetRedisClient(8).SetContainsAsync($"Survey:Submit:{id}", userid);
  540. return Ok(new { answered = answered });
  541. }
  542. /// <summary>
  543. /// 问卷记录 当活动没结算且没有BlobUrl时则调用此接口
  544. /// </summary>
  545. /// <redis>
  546. /// {"C":2,"A":2,"other":2}
  547. /// </redis>
  548. /// <param name="request">
  549. /// !"id":"aaaa"
  550. /// !"code":"Survey-hbcn"/"code":"Survey-1606285227"
  551. /// </param>
  552. /// <returns>
  553. /// </returns>
  554. [ProducesDefaultResponseType]
  555. [HttpPost("record")]
  556. [Authorize(Roles = "IES")]
  557. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-upd,schoolAc-read")]
  558. public async Task<IActionResult> Record(JsonElement request)
  559. {
  560. if (!request.TryGetProperty("id", out JsonElement id))
  561. {
  562. return BadRequest();
  563. }
  564. //活动分区
  565. if (!request.TryGetProperty("code", out JsonElement code))
  566. {
  567. return BadRequest();
  568. }
  569. //获取问卷记录
  570. var records = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"Survey:Record:{id}");
  571. List<dynamic> res = new List<dynamic>();
  572. foreach (var rcd in records)
  573. {
  574. var value = rcd.Value.ToString().ToObject<JsonElement>();
  575. res.Add(new { index = rcd.Name.ToString(), ans = value });
  576. }
  577. return Ok(new { records = res });
  578. }
  579. /*[ProducesDefaultResponseType]
  580. [HttpPost("draft-record")]
  581. [Authorize(Roles = "IES")]
  582. [AuthToken(Roles = "teacher,admin,student")]
  583. public async Task<IActionResult> DraftRecord(JsonElement request)
  584. {
  585. try
  586. {
  587. //活动ID
  588. if (!request.TryGetProperty("activityId", out JsonElement activityId))
  589. {
  590. return BadRequest();
  591. }
  592. //学生ID
  593. if (!request.TryGetProperty("stuId", out JsonElement stuId))
  594. {
  595. return BadRequest();
  596. }
  597. if (!request.TryGetProperty("survey", out JsonElement survey))
  598. {
  599. return BadRequest();
  600. }
  601. var client = _azureCosmos.GetCosmosClient();
  602. //获取问卷记录
  603. DraftSurvey draft = new()
  604. {
  605. id = activityId.GetString(),
  606. ttl = -1,
  607. code = $"DraftSurvey-{stuId}",
  608. stuId = stuId.GetString(),
  609. JsonElement = survey
  610. };
  611. await client.GetContainer("TEAMModelOS", "Student").UpsertItemAsync(draft, new PartitionKey($"{draft.code}"));
  612. return Ok(new { records = draft });
  613. }
  614. catch (Exception)
  615. {
  616. return Ok(new { code = 500 });
  617. }
  618. }
  619. [ProducesDefaultResponseType]
  620. [HttpPost("find-draft")]
  621. [Authorize(Roles = "IES")]
  622. [AuthToken(Roles = "teacher,admin,student")]
  623. public async Task<IActionResult> findDraft(JsonElement request)
  624. {
  625. try
  626. {
  627. //活动ID
  628. if (!request.TryGetProperty("id", out JsonElement id))
  629. {
  630. return BadRequest();
  631. }
  632. if (!request.TryGetProperty("stuId", out JsonElement stuId))
  633. {
  634. return BadRequest();
  635. }
  636. var client = _azureCosmos.GetCosmosClient();
  637. var response = await client.GetContainer("TEAMModelOS", "Student").ReadItemStreamAsync(id.GetString(), new PartitionKey($"DraftSurvey-{stuId}"));
  638. DraftSurvey draft = new();
  639. if (response.StatusCode==System.Net.HttpStatusCode.OK)
  640. {
  641. using var json = await JsonDocument.ParseAsync(response.Content);
  642. draft = json.ToObject<DraftSurvey>();
  643. }
  644. return Ok(new { records = draft });
  645. }
  646. catch (Exception)
  647. {
  648. return Ok(new { code = 500 });
  649. }
  650. }*/
  651. }
  652. }