SurveyController.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. using 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.Context.Constant.Common;
  14. using TEAMModelOS.SDK.DI;
  15. using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
  16. using TEAMModelOS.SDK.Extension;
  17. using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
  18. using TEAMModelOS.Models;
  19. using Microsoft.Extensions.Options;
  20. using TEAMModelOS.Filter;
  21. namespace TEAMModelOS.Controllers
  22. {
  23. /// <summary>
  24. /// 投票活动
  25. /// </summary>
  26. [ProducesResponseType(StatusCodes.Status200OK)]
  27. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  28. //[Authorize(Roles = "IES5")]
  29. [Route("common/survey")]
  30. [ApiController]
  31. public class SurveyController : ControllerBase
  32. {
  33. private readonly AzureCosmosFactory _azureCosmos;
  34. private readonly SnowflakeId _snowflakeId;
  35. private readonly AzureServiceBusFactory _serviceBus;
  36. private readonly DingDing _dingDing;
  37. private readonly Option _option;
  38. public SurveyController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option)
  39. {
  40. _snowflakeId= snowflakeId;
  41. _serviceBus = serviceBus;
  42. _azureCosmos = azureCosmos;
  43. _dingDing = dingDing;
  44. _option = option?.Value;
  45. }
  46. /// <summary>
  47. /// 新增 或 修改投票活动
  48. /// </summary>
  49. /// <param name="request"></param>
  50. /// <returns></returns>
  51. [ProducesDefaultResponseType]
  52. [HttpPost("upsert")]
  53. public async Task<IActionResult> Upsert(Survey request) {
  54. try {
  55. var client = _azureCosmos.GetCosmosClient();
  56. request.code = request.pk + "-" + request.code;
  57. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  58. request.createTime = now;
  59. if (string.IsNullOrEmpty(request.id))
  60. {
  61. request.id = Guid.NewGuid().ToString();
  62. if (request.startTime < now)
  63. {
  64. request.progress = "pending";
  65. }
  66. else
  67. {
  68. request.progress = "going";
  69. }
  70. request = await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  71. }
  72. else {
  73. Survey info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Survey>(request.id, new PartitionKey($"{request.code}"));
  74. if (info.progress.Equals("going"))
  75. {
  76. return Ok(new { v = "活动正在进行中" });
  77. }
  78. request.progress = info.progress;
  79. request = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(request, info.id, new PartitionKey($"{info.code}"));
  80. }
  81. return Ok(new { survey = request});
  82. } catch (Exception ex) {
  83. await _dingDing.SendBotMsg($"OS,{_option.Location},common/survey/save()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  84. return BadRequest(ex.StackTrace);
  85. }
  86. }
  87. /// <summary>
  88. /// 查询问卷调查,用于列表,编辑,查看
  89. /// </summary>
  90. /// <data>
  91. ///Survey-学校/教师编码 活动分区 !"code":"hbcn"/1606285227
  92. ///时间筛选范围开始时间 默认30天之前 ?"stime":1608274766154
  93. ///时间筛选范围结束时间 默认当前时间 ?"etime":1608274766666
  94. ///每页大小 ?"count":10/null/Undefined
  95. ///分页Token ?"continuationToken":Undefined/null/"[{\"token\":\"+RID:~omxMAP3ipcSEEwAAAAAAAA==#RT:2#TRC:20#ISV:2#IEO:65551#QCF:1#FPC:AYQTAAAAAAAAiRMAAAAAAAA=\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]"
  96. /// 当前状态 ?"progress":Undefined/null/"" 表示两种状态都要查询/ "going"/"finish" 表示查询进行中/ 或者已完成 学生端只能查询正在进行或已经结束 going 已发布|finish 已结束
  97. /// </data>
  98. /// <param name="request"></param>
  99. /// <returns></returns>
  100. [ProducesDefaultResponseType]
  101. [HttpPost("find")]
  102. public async Task<IActionResult> Find(JsonElement requert)
  103. {
  104. try {
  105. //必须有学校或者教师编码
  106. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  107. //开始时间,默认最近三十天
  108. var stimestamp = DateTimeOffset.UtcNow.AddDays(-30).ToUnixTimeMilliseconds();
  109. if (requert.TryGetProperty("stime", out JsonElement stime))
  110. {
  111. if (!stime.ValueKind.Equals(JsonValueKind.Undefined) && stime.TryGetInt64(out long data))
  112. {
  113. stimestamp = data;
  114. };
  115. };
  116. //默认当前时间
  117. var etimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  118. if (requert.TryGetProperty("etime", out JsonElement etime))
  119. {
  120. if (!etime.ValueKind.Equals(JsonValueKind.Undefined) && etime.TryGetInt64(out long data))
  121. {
  122. etimestamp = data;
  123. };
  124. };
  125. var progresssql = "";
  126. if (!requert.TryGetProperty("progress", out JsonElement progress))
  127. {
  128. if (!progress.ValueKind.Equals(JsonValueKind.Undefined) && !progress.ValueKind.Equals(JsonValueKind.Null) && progress.ValueKind.Equals(JsonValueKind.String))
  129. {
  130. progresssql = $" and c.progress='{progresssql}' ";
  131. }
  132. }
  133. string continuationToken = null;
  134. //默认不指定返回大小
  135. int? topcout = null;
  136. if (requert.TryGetProperty("count", out JsonElement jcount))
  137. {
  138. if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && jcount.TryGetInt32(out int data))
  139. {
  140. topcout = data;
  141. }
  142. };
  143. //是否需要进行分页查询,默认不分页
  144. bool iscontinuation = false;
  145. //如果指定了返回大小
  146. if (requert.TryGetProperty("continuationToken", out JsonElement continuation))
  147. {
  148. //指定了cancellationToken 表示需要进行分页
  149. if (!continuation.ValueKind.Equals(JsonValueKind.Null) && !continuation.ValueKind.Equals(JsonValueKind.Undefined))
  150. {
  151. continuationToken = continuation.GetString();
  152. iscontinuation = true;
  153. }
  154. };
  155. List<object> surveys = new List<object>();
  156. var client = _azureCosmos.GetCosmosClient();
  157. var query = $"select c.id,c.name,c.code,c.startTime,c.endTime,c.progress from c where c.createTime >= {stimestamp} and c.createTime <= {etimestamp} {progresssql } ";
  158. await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: query,
  159. requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Vote-{code}") }))
  160. {
  161. using var json = await JsonDocument.ParseAsync(item.ContentStream);
  162. if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
  163. {
  164. foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
  165. {
  166. surveys.Add(obj.ToObject<JsonElement>());
  167. }
  168. //如果需要分页则跳出
  169. if (iscontinuation)
  170. {
  171. continuationToken = item.GetContinuationToken();
  172. break;
  173. }
  174. }
  175. }
  176. return Ok(new { surveys, continuationToken });
  177. } catch (Exception ex) {
  178. await _dingDing.SendBotMsg($"OS,{_option.Location},common/survey/find()\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  179. return BadRequest(ex.StackTrace);
  180. }
  181. }
  182. ///<summary>
  183. /// 查询问卷调查,用于创建者列表,编辑,查看,作答人员查看
  184. /// </summary>
  185. /// <data>
  186. /// ! "id":"3c075347-75ef-4bcb-ae03-68678d02d5ef",
  187. /// ! "code":"Survey-hbcn"/"code":"Survey-1606285227"
  188. /// </data>
  189. /// <param name="request"></param>
  190. /// <returns></returns>
  191. [ProducesDefaultResponseType]
  192. [HttpPost("find-id")]
  193. public async Task<IActionResult> FindById(JsonElement requert)
  194. {
  195. try
  196. {
  197. var client = _azureCosmos.GetCosmosClient();
  198. //活动id
  199. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  200. //活动分区
  201. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  202. Survey survey = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Survey>(id.GetString(), new PartitionKey($"{code}"));
  203. if (survey != null)
  204. {
  205. return Ok(new { survey });
  206. }
  207. else
  208. {
  209. return BadRequest("id,code不存在!");
  210. }
  211. }
  212. catch (Exception ex)
  213. {
  214. await _dingDing.SendBotMsg($"OS,{_option.Location},common/survey/find-id()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
  215. return BadRequest(ex.StackTrace);
  216. }
  217. }
  218. /// <summary>
  219. /// 删除问卷调查 TODO 使用ttl删除,并处理相关事务逻辑
  220. /// </summary>
  221. /// <param name="request"></param>
  222. /// <returns></returns>
  223. [ProducesDefaultResponseType]
  224. [HttpPost("delete")]
  225. [AuthToken(Roles = "admin,teacher")]
  226. public async Task<IActionResult> Delete(JsonElement request)
  227. {
  228. try
  229. {
  230. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  231. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  232. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  233. var client = _azureCosmos.GetCosmosClient();
  234. Survey survey = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Survey>(id.GetString(), new PartitionKey($"{code}"));
  235. bool flag = false;
  236. //必须是本人或者这个学校的管理者才能删除
  237. if (survey.creatorId == userid)
  238. {
  239. flag = true;
  240. }
  241. else
  242. {
  243. if (survey.scope == "school" && survey.owner.Equals(school))
  244. {
  245. flag = true;
  246. }
  247. }
  248. if (flag)
  249. {
  250. //使用ttl删除,并处理相关事务逻辑
  251. survey.ttl = 1;
  252. survey = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(survey, survey.id, new PartitionKey($"{survey.code}"));
  253. return Ok(new { flag });
  254. }
  255. else
  256. {
  257. return Ok(new { flag });
  258. }
  259. }
  260. catch (Exception e)
  261. {
  262. return BadRequest(e.StackTrace);
  263. }
  264. }
  265. }
  266. }