VoteController.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  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.Text.Json;
  7. using System.Threading.Tasks;
  8. using TEAMModelOS.SDK.Models;
  9. using TEAMModelOS.SDK.DI;
  10. using TEAMModelOS.SDK.Extension;
  11. using TEAMModelOS.Models;
  12. using Microsoft.Extensions.Options;
  13. using TEAMModelOS.Filter;
  14. using TEAMModelOS.Services.Common;
  15. using Azure.Messaging.ServiceBus;
  16. using Microsoft.Extensions.Configuration;
  17. namespace TEAMModelOS.Controllers
  18. {
  19. /// <summary>
  20. /// 投票活动
  21. /// </summary>
  22. [ProducesResponseType(StatusCodes.Status200OK)]
  23. [ProducesResponseType(StatusCodes.Status400BadRequest)]
  24. //[Authorize(Roles = "IES5")]
  25. [Route("common/vote")]
  26. [ApiController]
  27. public class VoteController : ControllerBase
  28. {
  29. private readonly AzureRedisFactory _azureRedis;
  30. private readonly AzureCosmosFactory _azureCosmos;
  31. private readonly SnowflakeId _snowflakeId;
  32. private readonly AzureServiceBusFactory _serviceBus;
  33. private readonly DingDing _dingDing;
  34. private readonly Option _option;
  35. private readonly AzureStorageFactory _azureStorage;
  36. public IConfiguration _configuration { get; set; }
  37. public VoteController(AzureCosmosFactory azureCosmos, AzureServiceBusFactory serviceBus, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option,
  38. AzureRedisFactory azureRedis, AzureStorageFactory azureStorage, IConfiguration configuration)
  39. {
  40. _azureCosmos = azureCosmos;
  41. _serviceBus = serviceBus;
  42. _snowflakeId = snowflakeId;
  43. _dingDing = dingDing;
  44. _option = option?.Value;
  45. _azureRedis = azureRedis;
  46. _azureStorage = azureStorage;
  47. _configuration = configuration;
  48. }
  49. /// <summary>
  50. /// 新增 或 修改投票活动
  51. /// </summary>
  52. /// <param name="request"></param>
  53. /// <returns></returns>
  54. [ProducesDefaultResponseType]
  55. [HttpPost("upsert")]
  56. [AuthToken(Roles = "teacher,admin",Permissions = "schoolAc-upd")]
  57. public async Task<IActionResult> Upsert(Vote request)
  58. {
  59. try
  60. {
  61. //新增Vote
  62. var client = _azureCosmos.GetCosmosClient();
  63. request.code = request.pk + "-" + request.code;
  64. request.ttl = -1;
  65. long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  66. request.createTime = now;
  67. //如果设置的时间是小于当前时间则立即发布
  68. if (request.startTime <= 0) {
  69. request.startTime = now;
  70. }
  71. if (string.IsNullOrEmpty(request.id))
  72. {
  73. request.id = Guid.NewGuid().ToString();
  74. if (request.startTime > now)
  75. {
  76. request.progress = "pending";
  77. }
  78. else {
  79. request.progress = "going";
  80. }
  81. string blobcntr = null;
  82. var messageBlob = new ServiceBusMessage();
  83. if (request.scope.Equals("school"))
  84. {
  85. blobcntr = request.school;
  86. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"vote/{request.id}");
  87. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "insert", root = $"vote/{request.id}", name = $"{request.school}" }.ToJsonString());
  88. }
  89. else
  90. {
  91. blobcntr = request.creatorId;
  92. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"vote/{request.id}");
  93. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "insert", root = $"vote/{request.id}", name = $"{request.creatorId}" }.ToJsonString());
  94. }
  95. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  96. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  97. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  98. string url = $"/vote/{request.id}/record.json";
  99. request.recordUrl = url;
  100. await _azureStorage.UploadFileByContainer(blobcntr, new { options = new List<string>(), records = new List<VoteRecord>() }.ToJsonString(), "vote", $"{request.id}/record.json");
  101. request = await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  102. }
  103. else
  104. {
  105. var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(request.id, new PartitionKey($"{request.code}"));
  106. var messageBlob = new ServiceBusMessage();
  107. string blobcntr = null;
  108. if (request.scope.Equals("school"))
  109. {
  110. blobcntr = request.school;
  111. request.size = await _azureStorage.GetBlobContainerClient(request.school).GetBlobsSize($"vote/{request.id}");
  112. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"vote/{request.id}", name = $"{request.school}" }.ToJsonString());
  113. }
  114. else
  115. {
  116. blobcntr = request.creatorId;
  117. request.size = await _azureStorage.GetBlobContainerClient(request.creatorId).GetBlobsSize($"vote/{request.id}");
  118. messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = $"vote/{request.id}", name = $"{request.creatorId}" }.ToJsonString());
  119. }
  120. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  121. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  122. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  123. if (response.Status == 200)
  124. {
  125. using var json = await JsonDocument.ParseAsync(response.ContentStream);
  126. var info = json.ToObject<Vote>();
  127. if (info.progress.Equals("going"))
  128. {
  129. return Ok(new { v = "活动正在进行中" });
  130. }
  131. if (request.startTime > now)
  132. {
  133. request.progress = "pending";
  134. }
  135. else
  136. {
  137. request.progress = "going";
  138. }
  139. request.progress = info.progress;
  140. string url = $"/vote/{request.id}/record.json";
  141. request.recordUrl = url;
  142. request = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(request, info.id, new PartitionKey($"{info.code}"));
  143. }
  144. else
  145. {
  146. if (request.startTime > now)
  147. {
  148. request.progress = "pending";
  149. }
  150. else
  151. {
  152. request.progress = "going";
  153. }
  154. string url = $"/vote/{request.id}/record.json";
  155. request.recordUrl = url;
  156. await _azureStorage.UploadFileByContainer(blobcntr, new { options = new List<string>(), records = new List<VoteRecord>() }.ToJsonString(), "vote", $"{request.id}/record.json");
  157. request = await client.GetContainer(Constant.TEAMModelOS, "Common").CreateItemAsync(request, new PartitionKey($"{request.code}"));
  158. }
  159. }
  160. return Ok(new { vote = request });
  161. }
  162. catch (Exception e)
  163. {
  164. await _dingDing.SendBotMsg($"OS,{_option.Location},common/vote/save()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
  165. return BadRequest(e.StackTrace);
  166. }
  167. }
  168. /// <summary>
  169. /// 查询投票活动,用于列表,编辑,查看
  170. /// </summary>
  171. /// <data>
  172. ///Vote-学校/教师编码 活动分区 !"code":"hbcn"/1606285227
  173. ///时间筛选范围开始时间 默认30天之前 ?"stime":1608274766154
  174. ///时间筛选范围结束时间 默认当前时间 ?"etime":1608274766666
  175. ///每页大小 ?"count":10/null/Undefined
  176. ///分页Token ?"continuationToken":Undefined/null/"[{\"token\":\"+RID:~omxMAP3ipcSEEwAAAAAAAA==#RT:2#TRC:20#ISV:2#IEO:65551#QCF:1#FPC:AYQTAAAAAAAAiRMAAAAAAAA=\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]"
  177. /// 当前状态 ?"progress":Undefined/null/"" 表示两种状态都要查询/ "going"/"finish" 表示查询进行中/ 或者已完成 学生端只能查询正在进行或已经结束 going 已发布|finish 已结束
  178. /// </data>
  179. /// <param name="request"></param>
  180. /// <returns></returns>
  181. [ProducesDefaultResponseType]
  182. [HttpPost("find")]
  183. [AuthToken(Roles = "teacher,admin", Permissions = "schoolAc-read,schoolAc-upd")]
  184. public async Task<IActionResult> Find(JsonElement requert)
  185. {
  186. try
  187. {
  188. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  189. //必须有学校或者教师编码
  190. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  191. //开始时间,默认最近三十天
  192. var stimestamp = DateTimeOffset.UtcNow.AddDays(-30).ToUnixTimeMilliseconds();
  193. if (requert.TryGetProperty("stime", out JsonElement stime)) {
  194. if (long.TryParse($"{stime}", out long data))
  195. {
  196. stimestamp = data;
  197. };
  198. };
  199. //默认当前时间
  200. var etimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
  201. if (requert.TryGetProperty("etime", out JsonElement etime))
  202. {
  203. if (long.TryParse($"{etime}", out long data))
  204. {
  205. etimestamp = data;
  206. };
  207. };
  208. var progresssql = "";
  209. if (requert.TryGetProperty("progress", out JsonElement progress))
  210. {
  211. if (!progress.ValueKind.Equals(JsonValueKind.Undefined) && !progress.ValueKind.Equals(JsonValueKind.Null) && progress.ValueKind.Equals(JsonValueKind.String))
  212. {
  213. progresssql = $" and c.progress='{progress}' ";
  214. }
  215. }
  216. string continuationToken = null;
  217. //默认不指定返回大小
  218. int? topcout=null;
  219. if (requert.TryGetProperty("count", out JsonElement jcount)) {
  220. if (int.TryParse($"{jcount}", out int data))
  221. {
  222. topcout = data;
  223. }
  224. };
  225. //是否需要进行分页查询,默认不分页
  226. // bool iscontinuation = false;
  227. //如果指定了返回大小
  228. if (requert.TryGetProperty("continuationToken", out JsonElement continuation))
  229. {
  230. //指定了cancellationToken 表示需要进行分页
  231. if (!continuation.ValueKind.Equals(JsonValueKind.Null) && !continuation.ValueKind.Equals(JsonValueKind.Undefined))
  232. {
  233. continuationToken = continuation.GetString();
  234. // iscontinuation = true;
  235. }
  236. };
  237. List<Vote> votes = new List<Vote>();
  238. var client = _azureCosmos.GetCosmosClient();
  239. var query = $"select c.owner,c.id,c.name,c.code,c.startTime,c.endTime,c.progress ,c.scope,c.school from c where c.createTime >= {stimestamp} and c.createTime <= {etimestamp} {progresssql } and c.ttl=-1 ";
  240. if (string.IsNullOrEmpty(school))
  241. {
  242. query = $"{query} and c.scope='private' ";
  243. }
  244. await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<Vote>(queryText: query,
  245. requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Vote-{code}") }))
  246. {
  247. if (!string.IsNullOrEmpty(school))
  248. {
  249. //只能查出相关学校的
  250. if (!item.scope.Equals("private") && !string.IsNullOrEmpty(item.school) && item.school.Equals(school))
  251. {
  252. votes.Add(item);
  253. }
  254. //和自己私人发布的
  255. if (item.scope.Equals("private"))
  256. {
  257. votes.Add(item);
  258. }
  259. }
  260. else
  261. {
  262. votes.Add(item);
  263. }
  264. }
  265. return Ok(new { votes, continuationToken });
  266. }
  267. catch (Exception ex)
  268. {
  269. await _dingDing.SendBotMsg($"OS,{_option.Location},common/vote/find()\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
  270. return BadRequest(ex.StackTrace);
  271. }
  272. }
  273. ///<summary>
  274. /// 查询投票活动,用于创建者列表,编辑,查看,投票人员查看
  275. /// </summary>
  276. /// <data>
  277. /// ! "id":"3c075347-75ef-4bcb-ae03-68678d02d5ef",
  278. /// ! "code":"Vote-hbcn"/"code":"Vote-1606285227"
  279. /// </data>
  280. /// <param name="request"></param>
  281. /// <returns></returns>
  282. [ProducesDefaultResponseType]
  283. [HttpPost("find-id")]
  284. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-read,schoolAc-upd")]
  285. public async Task<IActionResult> FindById(JsonElement requert)
  286. {
  287. Vote vote = null;
  288. //活动id
  289. if (!requert.TryGetProperty("id", out JsonElement id)) return BadRequest();
  290. //活动分区
  291. if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
  292. try
  293. {
  294. var client = _azureCosmos.GetCosmosClient();
  295. vote = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Vote>(id.GetString(), new PartitionKey($"{code}"));
  296. if (vote != null)
  297. {
  298. return Ok(new { vote, status = 200 });
  299. }
  300. else
  301. {
  302. return Ok(new { vote, status = 404 });
  303. }
  304. }
  305. catch (Exception ex)
  306. {
  307. await _dingDing.SendBotMsg($"OS,{_option.Location},common/vote/find-id()\n{ex.Message}\n{requert.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
  308. return Ok(new { vote,status=404 });
  309. }
  310. }
  311. /// <summary>
  312. /// 删除投票活动 TODO 使用ttl删除,并处理相关事务逻辑
  313. /// </summary>
  314. /// <param name="request"></param>
  315. /// <returns></returns>
  316. [ProducesDefaultResponseType]
  317. [HttpPost("delete")]
  318. [AuthToken(Roles = "teacher,admin", Permissions = "schoolAc-upd")]
  319. public async Task<IActionResult> Delete(JsonElement request)
  320. {
  321. try
  322. {
  323. var (userid, _, _,school) = HttpContext.GetAuthTokenInfo();
  324. if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
  325. if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
  326. var client = _azureCosmos.GetCosmosClient();
  327. Vote vote =await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<Vote>(id.GetString(), new PartitionKey($"{code}") );
  328. bool flag = false;
  329. //必须是本人或者这个学校的管理者才能删除
  330. if (vote.creatorId == userid)
  331. {
  332. flag = true;
  333. }
  334. else {
  335. if (vote.scope == "school"&& vote.school.Equals(school)) {
  336. flag = true;
  337. }
  338. }
  339. if (flag)
  340. {
  341. //使用ttl删除,并处理相关事务逻辑
  342. vote.ttl = 1;
  343. vote.status = 404;
  344. vote = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(vote,vote.id, new PartitionKey($"{vote.code}"));
  345. await _dingDing.SendBotMsg($"{_option.Location}-投票活动【{vote.name}-{vote.id}-ttl={vote.ttl}】正在操作", GroupNames.成都开发測試群組);
  346. _azureRedis.GetRedisClient(8).KeyDelete($"Vote:Record:{vote.id}");
  347. _azureRedis.GetRedisClient(8).KeyDelete($"Vote:Count:{vote.id}");
  348. await _dingDing.SendBotMsg($"{_option.Location}-投票活动【{vote.name}-{vote.id}】被删除", GroupNames.成都开发測試群組);
  349. //删除blob 相关资料
  350. await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, $"{code}".Replace("Vote-",""), new List<string> { $"vote/{vote.id}" });
  351. //通知删除信息
  352. var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "delete", root = $"vote/{vote.id}", name = $"{code}" }.ToJsonString());
  353. messageBlob.ApplicationProperties.Add("name", "BlobRoot");
  354. var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
  355. await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
  356. return Ok(new { flag });
  357. }
  358. else {
  359. return Ok(new { flag });
  360. }
  361. }
  362. catch (Exception e)
  363. {
  364. await _dingDing.SendBotMsg($"{_option.Location}-投票活动{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組);
  365. return BadRequest(e.StackTrace);
  366. }
  367. }
  368. /// <summary>
  369. /// 投票记录 当活动没结算且没有BlobUrl时则调用此接口
  370. /// </summary>
  371. /// <redis>
  372. /// 投票活动选项计数器 使用SortedSet(有序集合)ZSET 数据集合 使用命令 ZINCRBY key:"Vote:Count:AAA",value:"A",score:1
  373. /// 投票活动 投票记录 使用Hash(哈希表)使用命令 key:"Vote:Record:AAA",feild:15283771540-20210105,value:"{"opt":["A","C","A"],"time":1608274766154}"
  374. /// </redis>
  375. /// <param name="request">
  376. /// !"id":"aaaa"
  377. /// !"code":"Vote-hbcn"/"code":"Vote-1606285227"
  378. /// </param>
  379. /// <returns>
  380. /// </returns>
  381. [ProducesDefaultResponseType]
  382. [HttpPost("record")]
  383. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-read,schoolAc-upd")]
  384. public async Task<IActionResult> Record(JsonElement request)
  385. {
  386. if (!request.TryGetProperty("id", out JsonElement id))
  387. {
  388. return BadRequest();
  389. }
  390. //活动分区
  391. if (!request.TryGetProperty("code", out JsonElement code))
  392. {
  393. return BadRequest();
  394. }
  395. //获取投票活动的所有投票记录
  396. var records = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"Vote:Record:{id}");
  397. //获取投票活动的选项及投票数
  398. var counts = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Vote:Count:{id}");
  399. List<dynamic> options = new List<dynamic>();
  400. if (counts != null && counts.Length > 0)
  401. {
  402. foreach (var count in counts)
  403. {
  404. options.Add(new { code = count.Element.ToString(), count = (int)count.Score });
  405. }
  406. }
  407. List<JsonElement> res = new List<JsonElement>();
  408. foreach (var rcd in records)
  409. {
  410. var value = rcd.Value.ToString().ToObject<JsonElement>();
  411. res.Add(value);
  412. }
  413. return Ok(new { options, records= res});
  414. }
  415. /// <summary>
  416. /// 个人已投票记录查询
  417. /// </summary>
  418. /// <param name="request"></param>
  419. /// <returns></returns>
  420. [ProducesDefaultResponseType]
  421. [HttpPost("decided")]
  422. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-read,schoolAc-upd")]
  423. public async Task<IActionResult> Decided(JsonElement request)
  424. {
  425. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  426. if (!request.TryGetProperty("id", out JsonElement id))
  427. {
  428. return BadRequest();
  429. }
  430. //活动分区
  431. if (!request.TryGetProperty("code", out JsonElement code))
  432. {
  433. return BadRequest();
  434. }
  435. //获取投票活动的所有投票记录
  436. var records = await _azureRedis.GetRedisClient(8).HashGetAllAsync($"Vote:Record:{id}:{userid}");
  437. List<JsonElement> res = new List<JsonElement>();
  438. foreach (var rcd in records)
  439. {
  440. var value = rcd.Value.ToString().ToObject<JsonElement>();
  441. res.Add(value);
  442. }
  443. return Ok(new { records= res });
  444. }
  445. /// <summary>
  446. /// 投票
  447. /// </summary>
  448. /// <redis>
  449. /// 投票活动选项计数器 使用SortedSet(有序集合)ZSET 数据集合 使用命令 ZINCRBY key:"Vote:Count:AAA",value:"A",score:1
  450. /// 投票活动 投票记录 使用Hash(哈希表)使用命令 key:"Vote:Record:AAA",feild:15283771540-20210105,value:"{"opt":["A","C","A"],"time":1608274766154}"
  451. /// </redis>
  452. /// <param name="request">
  453. /// !"id":"aaaa"
  454. /// !"code":"Vote-hbcn"/"code":"Vote-1606285227"
  455. /// !"option":{"A":5,"B":6}/{"1":5,"2":8}
  456. /// </param>
  457. /// <returns>
  458. /// msgid=0投票失败,1投票成功,2不在时间范围内,3不在发布范围内,4投票周期内重复投票,5周期内的可投票数不足
  459. ///
  460. /// </returns>
  461. [ProducesDefaultResponseType]
  462. [HttpPost("decide")]
  463. [AuthToken(Roles = "teacher,admin,student", Permissions = "schoolAc-read,schoolAc-upd")]
  464. public async Task<IActionResult> Decide(JsonElement request)
  465. {
  466. object userScope = null;
  467. object _standard = null;
  468. string standard = null;
  469. HttpContext?.Items?.TryGetValue("Scope", out userScope);
  470. if (userScope != null && $"{userScope}".Equals(Constant.ScopeTeacher))
  471. {
  472. HttpContext?.Items?.TryGetValue("Standard", out _standard);
  473. standard = _standard != null && string.IsNullOrEmpty($"{userScope}") ? _standard.ToString() : null;
  474. }
  475. var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
  476. (int msgid,int taskStatus) = await ActivityStudentService.Decide(_dingDing,_option, request, _azureCosmos, _azureRedis ,_azureStorage, userid, school, standard,_serviceBus,_configuration);
  477. return Ok(new { msgid, taskStatus });
  478. }
  479. /// <summary>
  480. /// 投票
  481. /// </summary>
  482. /// <redis>
  483. /// 投票活动选项计数器 使用SortedSet(有序集合)ZSET 数据集合 使用命令 ZINCRBY key:"Vote:Count:AAA",value:"A",score:1
  484. /// 投票活动 投票记录 使用Hash(哈希表)使用命令 key:"Vote:Record:AAA",feild:15283771540-20210105,value:"{"opt":["A","C","A"],"time":1608274766154}"
  485. /// </redis>
  486. /// <param name="request">
  487. /// !"id":"aaaa"
  488. /// !"code":"Vote-hbcn"/"code":"Vote-1606285227"
  489. /// !"option":{"A":5,"B":6}/{"1":5,"2":8}
  490. /// !"userid":"15283771540"
  491. /// </param>
  492. /// <returns>
  493. /// msgid=0投票失败,1投票成功,2不在时间范围内,3不在发布范围内,4投票周期内重复投票,5周期内的可投票数不足,6未设置投票项
  494. /// </returns>
  495. //[ProducesDefaultResponseType]
  496. //[HttpPost("decide-mock")]
  497. //public async Task<IActionResult> DecideMock(JsonElement request)
  498. //{
  499. // if (request.TryGetProperty("userid", out JsonElement userid)&& request.TryGetProperty("school", out JsonElement _school))
  500. // {
  501. // (int msgid, int taskStatus) = await ActivityStudentService.Decide(_dingDing,_option,request, _azureCosmos, _azureRedis, _azureStorage, $"{userid}",$"{_school}");
  502. // return Ok(new { msgid ,taskStatus });
  503. // }
  504. // else { return Ok(new { msgid = 0 }); }
  505. //}
  506. }
  507. }