CrazyIter_Bin пре 4 година
родитељ
комит
fad2394926

+ 4 - 3
TEAMModelFunction/MonitorCosmosDB.cs

@@ -21,14 +21,15 @@ namespace TEAMModelFunction
         private readonly AzureServiceBusFactory _serviceBus;
         private readonly AzureStorageFactory _azureStorage;
         private readonly DingDing _dingDing;
-
-        public MonitorCosmosDB(IHttpClientFactory clientFactory, AzureCosmosFactory azureCosmos, AzureServiceBusFactory azureServiceBus, AzureStorageFactory azureStorage, DingDing dingDing)
+        private readonly AzureRedisFactory _azureRedis;
+        public MonitorCosmosDB(IHttpClientFactory clientFactory, AzureCosmosFactory azureCosmos, AzureServiceBusFactory azureServiceBus, AzureStorageFactory azureStorage, DingDing dingDing, AzureRedisFactory azureRedis)
         {
             _clientFactory = clientFactory;
             _azureCosmos = azureCosmos;
             _serviceBus = azureServiceBus;
             _azureStorage = azureStorage;
             _dingDing = dingDing;
+            _azureRedis = azureRedis;
         }
 
         [FunctionName("Common")]
@@ -63,7 +64,7 @@ namespace TEAMModelFunction
                                 TriggerExam.Trigger(_azureCosmos, _serviceBus, _azureStorage, _dingDing, client,input,code,stime,etime,school);
                                 break;
                             case "Vote":
-                                TriggerVote.Trigger(_azureCosmos, _serviceBus, _azureStorage, _dingDing, client, input, code, stime, etime, school);
+                                TriggerVote.Trigger(_azureCosmos, _serviceBus, _azureStorage, _dingDing, client, input, code, stime, etime, school, _azureRedis);
                                 break;
                             case "Survey":
                                 TriggerSurvey.Trigger(_azureCosmos, _serviceBus, _azureStorage, _dingDing, client, input, code, stime, etime, school);

+ 1 - 0
TEAMModelFunction/Startup.cs

@@ -21,6 +21,7 @@ namespace TEAMModelFunction
             builder.Services.AddAzureServiceBus(Environment.GetEnvironmentVariable("Azure:ServiceBus:ConnectionString"));
             builder.Services.AddAzureStorage(Environment.GetEnvironmentVariable("Azure:Starage:ConnectionString"));
             builder.Services.AddAzureCosmos(Environment.GetEnvironmentVariable("Azure:Cosmos:ConnectionString"));
+            builder.Services.AddAzureRedis(Environment.GetEnvironmentVariable("Azure:Redis:ConnectionString"));
         }
     }
 }

+ 109 - 84
TEAMModelFunction/TriggerVote.cs

@@ -17,99 +17,124 @@ namespace TEAMModelFunction
     {
 
         public static async void Trigger(AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
-            CosmosClient client, Document input, string code, long stime, long etime, string school)
+            CosmosClient client, Document input, string code, long stime, long etime, string school, AzureRedisFactory _azureRedis)
         {
             Vote vote = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Vote>(input.Id, new Azure.Cosmos.PartitionKey($"{code}"));
             List<ChangeRecord> voteRecords = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", vote.progress } });
             //ChangeRecord voteRecord = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ChangeRecord>(input.Id, new Azure.Cosmos.PartitionKey($"{vote.progress}"));
-            switch (vote.progress)
+            if (vote.ttl >= 1)
             {
-                case "pending":
-                    var messageVote = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
-                    messageVote.ApplicationProperties.Add("name", "Vote");
-                    if (voteRecords.Count > 0)
-                    {
-                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVote, DateTimeOffset.FromUnixTimeMilliseconds(stime));
-                        await _serviceBus.GetServiceBusClient().cancelMessage("active-task", voteRecords[0].sequenceNumber);
-                        voteRecords[0].sequenceNumber = start;
-                        await _azureStorage.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
-                        //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(voteRecord, voteRecord.id, new Azure.Cosmos.PartitionKey($"{voteRecord.code}"));
-                    }
-                    else
-                    {
-                        long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVote, DateTimeOffset.FromUnixTimeMilliseconds(stime));
-                        ChangeRecord changeRecord = new ChangeRecord
+                //TODO  处理TTL删除业务
+                _azureRedis.GetRedisClient(8).KeyDelete($"Vote:Record:{vote.id}_{vote.code}");
+                _azureRedis.GetRedisClient(8).KeyDelete($"Vote:Count:{vote.id}_{vote.code}");
+                return;
+            }
+            else {
+                switch (vote.progress)
+                {
+                    case "pending":
+                        var messageVote = new ServiceBusMessage(new { id = input.Id, progress = "going", code = code }.ToJsonString());
+                        messageVote.ApplicationProperties.Add("name", "Vote");
+                        if (voteRecords.Count > 0)
+                        {
+                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVote, DateTimeOffset.FromUnixTimeMilliseconds(stime));
+                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", voteRecords[0].sequenceNumber);
+                            voteRecords[0].sequenceNumber = start;
+                            await _azureStorage.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
+                            //await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(voteRecord, voteRecord.id, new Azure.Cosmos.PartitionKey($"{voteRecord.code}"));
+                        }
+                        else
+                        {
+                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVote, DateTimeOffset.FromUnixTimeMilliseconds(stime));
+                            ChangeRecord changeRecord = new ChangeRecord
+                            {
+                                RowKey = input.Id,
+                                PartitionKey = "pending",
+                                sequenceNumber = start,
+                                msgId = messageVote.MessageId
+                            };
+                            await _azureStorage.Save<ChangeRecord>(changeRecord);
+                            //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
+                        }
+                        break;
+                    case "going":
+                        var tcode = code.Replace("Vote-", "");
+                        ActivityData data;
+                        if (vote.scope == "school" || vote.scope == "teacher")
                         {
-                            RowKey = input.Id,
-                            PartitionKey = "pending",
-                            sequenceNumber = start,
-                            msgId = messageVote.MessageId
-                        };
-                        await _azureStorage.Save<ChangeRecord>(changeRecord);
-                        //await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(changeRecord, new Azure.Cosmos.PartitionKey($"{changeRecord.code}"));
-                    }
-                    break;
-                case "going":
-                    var tcode = code.Replace("Vote-", "");
-                    ActivityData data ; 
-                    if (vote.scope == "school" || vote.scope == "teacher")
-                    {
-                        data = new ActivityData
+                            data = new ActivityData
+                            {
+                                id = vote.id,
+                                code = $"Activity-{tcode}",
+                                type = "vote",
+                                name = vote.name,
+                                startTime = vote.startTime,
+                                endTime = vote.endTime,
+                                scode = vote.code,
+                                scope = vote.scope,
+                                classes = vote.classes,
+                                tmdids = vote.tmdids
+                            };
+                            await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
+                        }
+                        else if (vote.scope == "private")
                         {
-                            id = vote.id,
-                            code = $"Activity-{tcode}",
-                            type = "vote",
-                            name = vote.name,
-                            startTime = vote.startTime,
-                            endTime = vote.endTime,
-                            scode = vote.code,
-                            scope = vote.scope,
-                            classes = vote.classes,
-                            tmdids = vote.tmdids
-                        };
-                        await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
-                    }
-                    else if(vote.scope== "private")
-                    {
-                        data = new ActivityData
+                            data = new ActivityData
+                            {
+                                id = vote.id,
+                                code = $"Activity-Common",
+                                type = "vote",
+                                name = vote.name,
+                                startTime = vote.startTime,
+                                endTime = vote.endTime,
+                                scode = vote.code,
+                                scope = vote.scope,
+                                classes = vote.classes,
+                                // tmdids = vote.tmdids
+                            };
+                            await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
+                        }
+                        var messageVoteEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
+                        messageVoteEnd.ApplicationProperties.Add("name", "Vote");
+                        if (voteRecords.Count > 0)
                         {
-                            id = vote.id,
-                            code = $"Activity-Common",
-                            type = "vote",
-                            name = vote.name,
-                            startTime = vote.startTime,
-                            endTime = vote.endTime,
-                            scode = vote.code,
-                            scope = vote.scope,
-                            classes = vote.classes,
-                           // tmdids = vote.tmdids
-                        };
-                        await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<ActivityData>(data, new Azure.Cosmos.PartitionKey(data.code));
-                    }
-                    var messageVoteEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = code }.ToJsonString());
-                    messageVoteEnd.ApplicationProperties.Add("name", "Vote");
-                    if (voteRecords.Count > 0)
-                    {
-                        long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
-                        await _serviceBus.GetServiceBusClient().cancelMessage("active-task", voteRecords[0].sequenceNumber);
-                        voteRecords[0].sequenceNumber = end;
-                        await _azureStorage.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
-                    }
-                    else
-                    {
-                        long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
-                        ChangeRecord changeRecord = new ChangeRecord
+                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
+                            await _serviceBus.GetServiceBusClient().cancelMessage("active-task", voteRecords[0].sequenceNumber);
+                            voteRecords[0].sequenceNumber = end;
+                            await _azureStorage.SaveOrUpdate<ChangeRecord>(voteRecords[0]);
+                        }
+                        else
                         {
-                            RowKey = input.Id,
-                            PartitionKey = "going",
-                            sequenceNumber = end,
-                            msgId = messageVoteEnd.MessageId
-                        };
-                        await _azureStorage.Save<ChangeRecord>(changeRecord);
-                    }
-                    break;
-                case "finish":
-                    break;
+                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync("active-task", messageVoteEnd, DateTimeOffset.FromUnixTimeMilliseconds(etime));
+                            ChangeRecord changeRecord = new ChangeRecord
+                            {
+                                RowKey = input.Id,
+                                PartitionKey = "going",
+                                sequenceNumber = end,
+                                msgId = messageVoteEnd.MessageId
+                            };
+                            await _azureStorage.Save<ChangeRecord>(changeRecord);
+                        }
+                        break;
+                    case "finish":
+                        //获取投票活动的所有投票记录
+                        var records= _azureRedis.GetRedisClient(8).HashValues($"Vote:Record:{vote.id}_{vote.code}");
+                        //获取投票活动的选项及投票数
+                        var counts= _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Vote:Count:{vote.id}_{vote.code}");
+                        if (counts != null && counts.Length > 0) {
+                            foreach (var count in counts) {
+                                vote.options.ForEach(x => {
+                                    if (x.code.Equals(count.Element.ToString())) {
+                                        x.count = (int)count.Score;
+                                    }
+                                });
+                            }
+                        }
+                        foreach (var rcd in records) {
+                            
+                        }
+                        break;
+                }
             }
         }
     }

+ 1 - 0
TEAMModelFunction/local.settings.json

@@ -5,6 +5,7 @@
     "Azure:Starage:ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelstorage;AccountKey=Yq7D4dE6cFuer2d2UZIccTA/i0c3sJ/6ITc8tNOyW+K5f+/lWw9GCos3Mxhj47PyWQgDL8YbVD63B9XcGtrMxQ==;EndpointSuffix=core.chinacloudapi.cn",
     "Azure:ServiceBus:ConnectionString": "Endpoint=sb://teammodelos.servicebus.chinacloudapi.cn/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Sy4h4EQ8zP+7w/lOLi1X3tGord/7ShFHimHs1vC50Dc=",
     "Azure:Cosmos:ConnectionString": "AccountEndpoint=https://teammodelos.documents.azure.cn:443/;AccountKey=clF73GwPECfP1lKZTCvs8gLMMyCZig1HODFbhDUsarsAURO7TcOjVz6ZFfPqr1HzYrfjCXpMuVD5TlEG5bFGGg==;",
+    "Azure:Redis:ConnectionString": "CoreRedisCN.redis.cache.chinacloudapi.cn:6380,password=LyJWP1ORJdv+poXWofAF97lhCEQPg1wXWqvtzXGXQuE=,ssl=True,abortConnect=False",
     "FUNCTIONS_WORKER_RUNTIME": "dotnet",
     "ScanModel": "TEAMModelOS",
     "Database": "TEAMModelOS"

+ 4 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Vote.cs

@@ -104,6 +104,10 @@ namespace TEAMModelOS.SDK.Models
         /// 投票对象描述
         /// </summary>
         public string desc { get; set; }
+        /// <summary>
+        /// 得票数量
+        /// </summary>
+        public int? count { get; set; } 
     }
     
 }

+ 39 - 277
TEAMModelOS/Controllers/Common/VoteController.cs

@@ -24,6 +24,7 @@ using Microsoft.AspNetCore.Authorization;
 using TEAMModelOS.Filter;
 using StackExchange.Redis;
 using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
+using TEAMModelOS.Services.Common;
 
 namespace TEAMModelOS.Controllers.Learn
 {
@@ -54,8 +55,6 @@ namespace TEAMModelOS.Controllers.Learn
             _option = option?.Value;
             _azureRedis = azureRedis;
         }
-
-
         /// <summary>
         /// 新增 或 修改投票活动
         /// </summary>
@@ -186,122 +185,6 @@ namespace TEAMModelOS.Controllers.Learn
                 return BadRequest(ex.StackTrace);
             }
         }
-        /// <summary>
-        /// 查询投票活动,用于教师投票的列表
-        /// </summary>
-        /// <data>
-        ///Common-学生/教师编码 对象分区       !"code":"habook01"/"1606285227" 
-        ///时间筛选范围开始时间 默认30天之前   ?"stime":1608274766154  
-        ///时间筛选范围结束时间 默认当前时间   ?"etime":1608274766666 
-        ///每页大小     ?"count":10/null/Undefined  
-        ///分页Token    ?"continuationToken":Undefined/null/"[{\"token\":\"+RID:~omxMAP3ipcSEEwAAAAAAAA==#RT:2#TRC:20#ISV:2#IEO:65551#QCF:1#FPC:AYQTAAAAAAAAiRMAAAAAAAA=\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]"
-        /// </data>
-        /// <param name="request"></param>
-        /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("find-tch")]
-        [AuthToken(Roles = "teacher")]
-        public async Task<IActionResult> FindTch(JsonElement requert)
-        {
-            (List<ActivityData> datas, string continuationToken) = await FindByRole("Teacher", requert);
-            return Ok(new { datas, continuationToken });
-        }
-
-        /// <summary>
-        /// 查询投票活动,用于学生可以投票的列表
-        /// </summary>
-        /// </summary>
-        /// <data>
-        ///Common-学生/教师编码 对象分区       !"code":"habook01"/"1606285227" 
-        //////Common-学生/教师编码 对象分区    ?"type":"vote"/"exam"/"homework"/"learn"/"survey"" // vote投票 survey问卷 exam评测 learn学习活动 homework作业活动
-        ///时间筛选范围开始时间 默认30天之前   ?"stime":1608274766154  
-        ///时间筛选范围结束时间 默认当前时间   ?"etime":1608274766666 
-        ///每页大小     ?"count":10/null/Undefined  
-        ///分页Token    ?"continuationToken":Undefined/null/"[{\"token\":\"+RID:~omxMAP3ipcSEEwAAAAAAAA==#RT:2#TRC:20#ISV:2#IEO:65551#QCF:1#FPC:AYQTAAAAAAAAiRMAAAAAAAA=\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]"
-        /// </data>
-        /// <param name="request"></param>
-        /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("find-stu")]
-        [AuthToken(Roles = "student")]
-        public async Task<IActionResult> FindStu(JsonElement requert)
-        {
-            (List<ActivityData> datas, string continuationToken)  =await  FindByRole("Student", requert);
-            return Ok(new { datas, continuationToken });
-        }
-
-        public async Task<(List<ActivityData> datas, string continuationToken)> FindByRole(string containerId, JsonElement requert) {
-            //开始时间,默认最近三十天
-            var stimestamp = DateTimeOffset.UtcNow.AddDays(-30).ToUnixTimeMilliseconds();
-            if (!requert.TryGetProperty("stime", out JsonElement stime))
-            {
-                if (stime.TryGetInt64(out long data))
-                {
-                    stimestamp = data;
-                };
-            };
-            if (!requert.TryGetProperty("type", out JsonElement type))
-            {
-                if (stime.TryGetInt64(out long data))
-                {
-                    stimestamp = data;
-                };
-            };
-            //默认当前时间
-            var etimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-            if (!requert.TryGetProperty("etime", out JsonElement etime))
-            {
-                if (etime.TryGetInt64(out long data))
-                {
-                    etimestamp = data;
-                };
-
-            };
-            string continuationToken = null;
-            //默认不指定返回大小
-            int? topcout = null;
-            if (!requert.TryGetProperty("count", out JsonElement jcount))
-            {
-                if (jcount.TryGetInt32(out int data))
-                {
-                    topcout = data;
-                };
-            };
-            //是否需要进行分页查询,默认不分页
-            bool iscontinuation = false;
-            //如果指定了返回大小
-            if (!requert.TryGetProperty("continuationToken", out JsonElement continuation))
-            {
-                //指定了cancellationToken 表示需要进行分页
-                if (!continuation.ValueKind.Equals(JsonValueKind.Null) && !continuation.ValueKind.Equals(JsonValueKind.String))
-                {
-                    continuationToken = continuation.GetString();
-                    iscontinuation = true;
-                }
-            };
-            List<ActivityData> datas = new List<ActivityData>();
-            var query = $"select value(c) from c where c.createTime >= {stimestamp} and c.createTime <= {etimestamp} ";
-            var client = _azureCosmos.GetCosmosClient();
-            var (id, _, _, _) = HttpContext.GetAuthTokenInfo();
-            await foreach (var item in client.GetContainer("TEAMModelOS", containerId).GetItemQueryStreamIterator(query, continuationToken: continuationToken, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Common-{id}") }))
-            {
-                using var json = await JsonDocument.ParseAsync(item.ContentStream);
-                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
-                {
-                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
-                    {
-                        datas.Add(obj.ToObject<ActivityData>());
-                    }
-                    //如果需要分页则跳出
-                    if (iscontinuation)
-                    {
-                        continuationToken = item.GetContinuationToken();
-                        break;
-                    }
-                }
-            }
-            return (datas, continuationToken);
-        }
         ///<summary>
         /// 查询投票活动,用于创建者列表,编辑,查看,投票人员查看
         /// </summary>
@@ -347,25 +230,46 @@ namespace TEAMModelOS.Controllers.Learn
         }
 
         /// <summary>
-        /// 删除投票活动
+        /// 删除投票活动  TODO 使用ttl删除,并处理相关事务逻辑
         /// </summary>
         /// <param name="request"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("delete")]
+        [AuthToken(Roles = "admin,teacher")]
         public async Task<IActionResult> Delete(JsonElement request)
         {
-
             try
             {
+                var (userid, _, _,school) = HttpContext.GetAuthTokenInfo();
                 if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
                 if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
-                if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
                 var client = _azureCosmos.GetCosmosClient();
-                var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
-                return Ok(new { code = response.Status });
-               
-
+                
+                Vote vote =await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Vote>(id.GetString(), new PartitionKey($"{code}") );
+                bool flag = false;
+                //必须是本人或者这个学校的管理者才能删除
+                if (vote.creatorId == userid)
+                {
+                    flag = true;
+                }
+                else {
+                    if (vote.scope == "school"&& vote.code.Replace("Vote-", "").Equals(school)) {
+                        flag = true;
+                    }
+                }
+                if (flag)
+                { 
+                    //使用ttl删除,并处理相关事务逻辑
+                    vote.ttl = 1;
+                    vote = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(vote, vote.id, new PartitionKey($"{vote.code}"));
+                    return Ok(new { flag });
+                }
+                else {
+                    return Ok(new { flag });
+                }
+                //var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"{code}"));
+                //   return Ok(new { code = response.Status });
             }
             catch (Exception e)
             {
@@ -376,169 +280,27 @@ namespace TEAMModelOS.Controllers.Learn
         /// <summary>
         /// 投票
         /// </summary>
-        /// <data>
-        /// !"id":"aaaa"
-        /// !"code":"Vote-hbcn"/"code":"Vote-1606285227"
-        /// !"option":["A","B","B"]/["1","2","3"]
-        /// </data>
         /// <redis>
         /// 投票活动选项计数器 使用SortedSet(有序集合)ZSET 数据集合 使用命令 ZINCRBY  key:"Vote:Count:AAA",value:"A",score:1
         /// 投票活动 投票记录  使用Hash(哈希表)使用命令 key:"Vote:Record:AAA",feild:15283771540-20210105,value:"{"opt":["A","C","A"],"time":1608274766154}"
         /// </redis>
-        /// <param name="request"></param>
-        /// <returns></returns>
+        /// <param name="request">
+        /// !"id":"aaaa"
+        /// !"code":"Vote-hbcn"/"code":"Vote-1606285227"
+        /// !"option":["A","B","B"]/["1","2","3"]
+        /// </param>
+        /// <returns>
+        /// msgid=0投票失败,1投票成功,2不在时间范围内,3不在发布范围内,4投票周期内重复投票,5周期内的可投票数不足,6未设置投票项
+        /// </returns>
         [ProducesDefaultResponseType]
         [HttpPost("decide")]
+        [AuthToken(Roles = "teacher,student")]
         public async Task<IActionResult> UpsertRecord(JsonElement request)
         {
-            DateTimeOffset now = DateTimeOffset.UtcNow;
-            
-            long curr= now.ToUnixTimeMilliseconds();
             var (userid, _, _, _) = HttpContext.GetAuthTokenInfo();
-            byte msgid =0;//投票失败,1投票成功,2不在时间范围内,3不在发布范围内,4投票周期内重复投票,5周期内的可投票数不足,6未设置投票项
-            //活动id
-            if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
-            //活动分区
-            if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
-            List<string> option = new List<string>() ;
-            if (request.TryGetProperty("option", out JsonElement joption)) {
-                option= joption.ToObject<List<string>>();
-                if (option.IsEmpty()) {
-                    msgid = 6;
-                    return Ok( new { msgid});
-                }
-            }
-            else {
-                return BadRequest();
-            }
-            VoteRecord record = null;
-            try {
-                //1.再次检查投票
-                var client = _azureCosmos.GetCosmosClient();
-                Vote vote = null;
-                ///TODO 检查是否在投票范围内,包括在tmdids 及班级  但是需要处理认证金钥中的班级问题
-                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<Vote>(queryText: $"select c.progress,c.times,c.voteNum,c.startTime,c.endTime from c where c.id = '{id}'",
-                    requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
-                {
-                    vote = item;
-                    break;
-                }
-                if (vote != null)
-                {
-                    //判断投票时间是否在起止时间内
-                    if (curr >= vote.startTime && curr <= vote.endTime)
-                    {
-                       
-                        //如果是只能投票一次的活动则直接获取Redis的第一条
-                        if (vote.times.Equals("once"))
-                        {
-                            //只能投一次
-                            string Field = $"{userid}-once";
-                            RedisValue[] values = _azureRedis.GetRedisClient(8).HashValues($"Vote:Record:{vote.id}");
-                            if (values != null)
-                            {
-                                record = values[0].ToString().ToObject<VoteRecord>();
-                                msgid=await VoteIng(vote, record, msgid, option, Field, curr);
-                            }
-                            else {
-                                msgid = 1;
-                            }
-                        } 
-                        else if (vote.times.Equals("day"))
-                        {
-                            //周期内每天
-                            string Field= $"{userid}-day-{now.ToString("yyyyMMdd")}";
-                            RedisValue value= _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}", Field);
-                            record = value.ToString().ToObject<VoteRecord>();
-                            msgid = await VoteIng(vote, record, msgid, option, Field, curr);
-                        }
-                        else if (vote.times.Equals("week"))
-                        {
-                            //自然周
-                            string Field = $"{userid}-week-{now.ToString("yyyy")}{GetWeek(now)}";
-                            RedisValue value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}", Field);
-                            record = value.ToString().ToObject<VoteRecord>();
-                            msgid = await VoteIng(vote, record, msgid, option, Field, curr);
-
-                        }
-                        else if (vote.times.Equals("month"))
-                        {
-                            //月份
-                            string Field = $"{userid}-month-{now.ToString("yyyyMM")}";
-                            RedisValue value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}", Field);
-                            record = value.ToString().ToObject<VoteRecord>();
-                            msgid = await VoteIng(vote, record, msgid, option, Field, curr);
-                        }
-                        else if (vote.times.Equals("year"))
-                        {
-                            //年份
-                            string Field = $"{userid}-year-{now.ToString("yyyy")}";
-                            RedisValue value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}", Field);
-                            record = value.ToString().ToObject<VoteRecord>();
-                            msgid = await VoteIng(vote, record, msgid, option, Field,curr);
-                        }
-                    }
-                    else 
-                    {
-                        msgid = 2;
-                    }
-                }
-            }
-            catch (Exception e) {
-            }
+            int msgid = await ActivityService.Decide(request, _azureCosmos, _azureRedis, userid);
             return Ok(new { msgid });
         }
 
-        public async Task<byte> VoteIng(Vote vote, VoteRecord record,byte msgid,List<string> option,string Field ,long curr) {
-            if (record != null)
-            {
-                //处理记录投票+当前设置的投票是否小于等于周期内最大投票数
-                if (record.opt.Count + option.Count <= vote.voteNum)
-                {
-                    record.opt.AddRange(option);
-                    record.time = curr;
-                    bool status = await _azureRedis.GetRedisClient(8).HashSetAsync($"Vote:Record:{vote.id}", Field, record.ToJsonString());
-                    if (status)
-                    {
-                        msgid = 1;
-                    }
-                }
-                else
-                {
-                    msgid = 5;
-                }
-            }
-            else {
-                record = new VoteRecord { opt = option, time = curr };
-                bool status = await _azureRedis.GetRedisClient(8).HashSetAsync($"Vote:Record:{vote.id}", Field, record.ToJsonString());
-                if (status)
-                {
-                    msgid = 1;
-                }
-            }
-            return msgid;
-        }
-        /// <summary>
-        /// 获取时间的在当年的第几周
-        /// </summary>
-        /// <param name="dt"></param>
-        /// <returns></returns>
-        public static int GetWeek(DateTimeOffset dt)
-        {
-            DateTimeOffset time = Convert.ToDateTime(dt.ToString("yyyy") + "-01-01");
-            TimeSpan ts = dt - time;
-            int iii = (int)time.DayOfWeek;
-            int day = int.Parse(ts.TotalDays.ToString("F0"));
-            if (iii == 0)
-            {
-                day--;
-            }
-            else
-            {
-                day = day - (7 - iii) - 1;
-            }
-            int week = ((day + 7) / 7) + 1;
-            return week;
-        }
     }
 }

+ 11 - 9
TEAMModelOS/Controllers/School/StudentCommonController.cs

@@ -22,33 +22,35 @@ namespace TEAMModelOS.Controllers
     public class StudentCommonController :ControllerBase
     {
         private readonly AzureCosmosFactory _azureCosmos;
-
-        public StudentCommonController(AzureCosmosFactory azureCosmos)
+        private readonly AzureRedisFactory _azureRedis;
+        public StudentCommonController(AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis)
         {
+           
             _azureCosmos = azureCosmos;
+            _azureRedis = azureRedis;
         }
         /// <summary>
-        /// 查询投票活动,用于教师投票的列表
+        /// 查询活动所有活动类型的列表,学生端
         /// </summary>
-        /// <data>
+        /// <param name="request">
         ///加入的班级信息                      ?classes:[{"classid":"S-C-00001","scope":"school"},{"classid":"P-C-00004","scope":"private"}]
         ///活动类型                            ?"type":"vote"/"exam"/"homework"/"learn"/"survey"" // vote投票 survey问卷 exam评测 learn学习活动 homework作业活动
         ///时间筛选范围开始时间 默认30天之前   ?"stime":1608274766154  
         ///时间筛选范围结束时间 默认当前时间   ?"etime":1608274766666 
-        ///是否展示列表的 Tips                 ? true/false
+        ///是否展示列表的 Tips                 ? "tips":true/false
         ///每页大小     ?"count":10/null/Undefined  
         ///分页Token    ?"continuationToken":Undefined/null/"[{\"token\":\"+RID:~omxMAP3ipcSEEwAAAAAAAA==#RT:2#TRC:20#ISV:2#IEO:65551#QCF:1#FPC:AYQTAAAAAAAAiRMAAAAAAAA=\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]"
-        /// </data>
-        /// <param name="request"></param>
+        /// </param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("find-activity")]
-        [AuthToken(Roles = "teacher")]
+        [AuthToken(Roles = "student")]
         public async Task<IActionResult> FindTch(JsonElement requert)
         {
             var (id, _, _, _) = HttpContext.GetAuthTokenInfo();
-            (List<ActivityData> datas, string continuationToken) = await ActivityService.FindByRole("School", requert, id, _azureCosmos);
+            (List<ActivityData> datas, string continuationToken) = await ActivityService.FindByRole("School", requert, id, _azureCosmos,_azureRedis);
             return Ok(new { datas, continuationToken });
         }
+        
     }
 }

+ 8 - 7
TEAMModelOS/Controllers/Teacher/TeacherCommonController.cs

@@ -24,15 +24,16 @@ namespace TEAMModelOS.Controllers
     public class TeacherCommonController: ControllerBase
     {
         private readonly AzureCosmosFactory _azureCosmos;
-      
-        public TeacherCommonController(AzureCosmosFactory azureCosmos  )
+        private readonly AzureRedisFactory _azureRedis;
+        public TeacherCommonController(AzureCosmosFactory azureCosmos, AzureRedisFactory azureRedis)
         {
             _azureCosmos = azureCosmos;
+            _azureRedis = azureRedis;
         }
         /// <summary>
-        /// 查询投票活动,用于教师投票的列表
+        /// 查询活动所有活动类型的列表,教师
         /// </summary>
-        /// <data>
+        /// <param name="request">
         ///加入的班级信息                      ?classes:[{"classid":"S-C-00001","scope":"school"},{"classid":"P-C-00004","scope":"private"}]
         ///活动类型                            ?"type":"vote"/"exam"/"homework"/"learn"/"survey"" // vote投票 survey问卷 exam评测 learn学习活动 homework作业活动
         ///时间筛选范围开始时间 默认30天之前   ?"stime":1608274766154  
@@ -40,8 +41,7 @@ namespace TEAMModelOS.Controllers
         ///是否展示列表的 Tips                 ? "tips":true/false
         ///每页大小     ?"count":10/null/Undefined  
         ///分页Token    ?"continuationToken":Undefined/null/"[{\"token\":\"+RID:~omxMAP3ipcSEEwAAAAAAAA==#RT:2#TRC:20#ISV:2#IEO:65551#QCF:1#FPC:AYQTAAAAAAAAiRMAAAAAAAA=\",\"range\":{\"min\":\"\",\"max\":\"FF\"}}]"
-        /// </data>
-        /// <param name="request"></param>
+        /// </param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpPost("find-activity")]
@@ -49,8 +49,9 @@ namespace TEAMModelOS.Controllers
         public async Task<IActionResult> FindTch(JsonElement requert)
         {
             var (id, _, _, _) = HttpContext.GetAuthTokenInfo();
-            (List<ActivityData> datas, string continuationToken) = await ActivityService.FindByRole("Teacher", requert, id, _azureCosmos);
+            (List<ActivityData> datas, string continuationToken) = await ActivityService.FindByRole("Teacher", requert, id, _azureCosmos,_azureRedis);
             return Ok(new { datas, continuationToken });
         }
+       
     }
 }

+ 302 - 42
TEAMModelOS/Services/Common/ActivityService.cs

@@ -10,6 +10,8 @@ using TEAMModelOS.SDK.DI;
 using HTEXLib.COMM.Helpers;
 using System.Text;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
+using StackExchange.Redis;
 
 namespace TEAMModelOS.Services.Common
 {
@@ -21,8 +23,179 @@ namespace TEAMModelOS.Services.Common
         /// </summary>
         /// <param name="data"></param>
         /// <returns></returns>
-        delegate dynamic DoActivityTips(ActivityData data, AzureCosmosFactory _azureCosmos,string id);
-        public static async Task<(List<ActivityData> datas, string continuationToken)> FindByRole(string containerId, JsonElement requert, string id, AzureCosmosFactory _azureCosmos)
+        delegate dynamic DoActivityTips(ActivityData data, AzureCosmosFactory _azureCosmos,string id, AzureRedisFactory _azureRedis);
+
+        public static async Task<int> Decide(JsonElement request,AzureCosmosFactory _azureCosmos,AzureRedisFactory _azureRedis,string userid ) {
+
+            DateTimeOffset now = DateTimeOffset.UtcNow;
+            long curr = now.ToUnixTimeMilliseconds();
+            byte msgid = 0;//0投票失败,1投票成功,2不在时间范围内,3不在发布范围内,4投票周期内重复投票,5周期内的可投票数不足,6未设置投票项
+            //活动id
+            if (!request.TryGetProperty("id", out JsonElement id)) {
+                return msgid;
+            }
+            //活动分区
+            if (!request.TryGetProperty("code", out JsonElement code)) {
+                return msgid;
+            }
+            List<string> option = new List<string>();
+            if (request.TryGetProperty("option", out JsonElement joption))
+            {
+                option = joption.ToObject<List<string>>();
+                if (option.IsEmpty())
+                {
+                    msgid = 6;
+                    return msgid; 
+                }
+            }
+            else
+            {
+                return msgid;
+            }
+         
+            try
+            {
+                //1.再次检查投票
+                var client = _azureCosmos.GetCosmosClient();
+                Vote vote = null;
+                ///TODO 检查是否在投票范围内,包括在tmdids 及班级  但是需要处理认证金钥中的班级问题
+                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<Vote>(queryText: $"select c.progress,c.times,c.voteNum,c.startTime,c.endTime from c where c.id = '{id}'",
+                    requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+                {
+                    vote = item;
+                    break;
+                }
+                if (vote != null)
+                {
+                    //判断投票时间是否在起止时间内
+                    if (curr >= vote.startTime && curr <= vote.endTime)
+                    {
+                        string Field = "";
+                        RedisValue value;
+                        switch (vote.times) {
+                            case "once":
+                                // //如果是只能投票一次的活动则直接获取Redis的第一条 只能投一次
+                                Field = $"{userid}-once";
+                                RedisValue[] values = _azureRedis.GetRedisClient(8).HashValues($"Vote:Record:{vote.id}_{vote.code}");
+                                if (values != null  && values.Length > 0)
+                                {
+                                    msgid = await VoteIng(vote, values[0], msgid, option, Field, curr, _azureRedis);
+                                }
+                                else
+                                {
+                                    msgid = 1;
+                                }
+                                break;
+                            case "day": //周期内每天
+                                Field = $"{userid}-day-{now.ToString("yyyyMMdd")}";
+                                value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}_{vote.code}", Field);
+                                msgid = await VoteIng(vote, value, msgid, option, Field, curr, _azureRedis);
+                                break;
+                            case "week": //自然周
+                                Field = $"{userid}-week-{now.ToString("yyyy")}{GetWeek(now)}";
+                                value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}_{vote.code}", Field);
+                                msgid = await VoteIng(vote, value, msgid, option, Field, curr, _azureRedis); 
+                                break;
+                            case "month":  //月份
+                                Field = $"{userid}-month-{now.ToString("yyyyMM")}";
+                                value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}_{vote.code}", Field);
+                                msgid = await VoteIng(vote, value, msgid, option, Field, curr, _azureRedis); 
+                                break;
+                            case "year"://年份
+                                Field = $"{userid}-year-{now.ToString("yyyy")}";
+                                value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}_{vote.code}", Field);
+                                msgid = await VoteIng(vote, value, msgid, option, Field, curr, _azureRedis);
+                                break;
+                        }
+                    }
+                    else
+                    {
+                        msgid = 2;
+                    }
+                }
+            }
+            catch (Exception e)
+            {
+            }
+            return msgid;
+        }
+        public static async Task<byte> VoteIng(Vote vote, RedisValue value, byte msgid, List<string> option, string Field, long curr, AzureRedisFactory _azureRedis)
+        {
+            if (!value.IsNullOrEmpty)
+            {
+                VoteRecord record=value.ToString().ToObject<VoteRecord>();
+                //处理记录投票+当前设置的投票是否小于等于周期内最大投票数
+                if (record.opt.Count + option.Count <= vote.voteNum)
+                {
+                    record.opt.AddRange(option);
+                    record.time = curr;
+                    //保存投票记录
+                    bool status = await _azureRedis.GetRedisClient(8).HashSetAsync($"Vote:Record:{vote.id}_{vote.code}", Field, record.ToJsonString());
+                    //当前投票分组计数存入活动的Redis
+                    var group_opt= option.GroupBy(x => x);
+                    foreach (var opt in group_opt) {
+                        await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Vote:Count:{vote.id}_{vote.code}", opt.Key, opt.Count());
+                    }
+                    if (status)
+                    {
+                        msgid = 1;
+                    }
+                }
+                else
+                {
+                    msgid = 5;
+                }
+            }
+            else
+            {
+                //保存投票记录
+                VoteRecord record = new VoteRecord { opt = option, time = curr };
+                bool status = await _azureRedis.GetRedisClient(8).HashSetAsync($"Vote:Record:{vote.id}_{vote.code}", Field, record.ToJsonString());
+                //当前投票分组计数存入活动的Redis
+                var group_opt = option.GroupBy(x => x);
+                foreach (var opt in group_opt)
+                {
+                    await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Vote:Count:{vote.id}_{vote.code}", opt.Key, opt.Count());
+                }
+                if (status)
+                {
+                    msgid = 1;
+                }
+            }
+            return msgid;
+        }
+        /// <summary>
+        /// 获取时间的在当年的第几周
+        /// </summary>
+        /// <param name="dt"></param>
+        /// <returns></returns>
+        public static int GetWeek(DateTimeOffset dt)
+        {
+            DateTimeOffset time = Convert.ToDateTime(dt.ToString("yyyy") + "-01-01");
+            TimeSpan ts = dt - time;
+            int iii = (int)time.DayOfWeek;
+            int day = int.Parse(ts.TotalDays.ToString("F0"));
+            if (iii == 0)
+            {
+                day--;
+            }
+            else
+            {
+                day = day - (7 - iii) - 1;
+            }
+            int week = ((day + 7) / 7) + 1;
+            return week;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="containerId">容器</param>
+        /// <param name="requert"></param>
+        /// <param name="id">登录者ID</param>
+        /// <param name="_azureCosmos"></param>
+        /// <returns></returns>
+        public static async Task<(List<ActivityData> datas, string continuationToken)> FindByRole(string containerId, JsonElement requert, string id, AzureCosmosFactory _azureCosmos,AzureRedisFactory _azureRedis)
         {
             //开始时间,默认最近三十天
             var stimestamp = DateTimeOffset.UtcNow.AddDays(-30).ToUnixTimeMilliseconds();
@@ -35,10 +208,10 @@ namespace TEAMModelOS.Services.Common
             } 
             if (!requert.TryGetProperty("type", out JsonElement type))
             {
-                if (stime.TryGetInt64(out long data))
-                {
-                    stimestamp = data;
-                } 
+                //if (stime.TryGetInt64(out long data))
+                //{
+                //    stimestamp = data;
+                //} 
             } 
             //默认当前时间,  未开始的不能查询
             var etimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
@@ -48,7 +221,6 @@ namespace TEAMModelOS.Services.Common
             //    {
             //        etimestamp = data;
             //    };
-
             //};
             string continuationToken = null;
             //默认不指定返回大小
@@ -94,8 +266,6 @@ namespace TEAMModelOS.Services.Common
             }
             
             List<ActivityData> datas = new List<ActivityData>();
-            
-            
             var client = _azureCosmos.GetCosmosClient();
             await foreach (var item in client.GetContainer("TEAMModelOS", containerId).GetItemQueryStreamIterator(query, continuationToken: continuationToken, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Common-{id}") }))
             {
@@ -123,69 +293,159 @@ namespace TEAMModelOS.Services.Common
                     tips = jtips.GetBoolean();
                 }
             }
-            DoActivityTips activityTips;
-            dynamic res = default;
-            foreach (var data in datas)
+            if (tips)
             {
-                switch (data.type)
+                DoActivityTips activityTips;
+                dynamic res = default;
+                foreach (var data in datas)
                 {
+                    switch (data.type)
+                    {
                         //投票
-                    case "vote":
-                        activityTips = DoVoteTips;
-                        res = activityTips(data,_azureCosmos,  id );
-                        break;
+                        case "vote":
+                            activityTips = DoVoteTips;
+                            //msgid, //0不能投票,1可以投票,2不在时间范围内,3周期内的可投票数不足
+                            //voteCount 可用投票数
+                            res = activityTips(data, _azureCosmos, id, _azureRedis);
+                            break;
                         //问卷
-                    case "survey":
-                        activityTips = DoSurveyTips;
-                        res = activityTips(data, _azureCosmos,id);
-                        break;
+                        case "survey":
+                            //msgid 0 已作答, 1未作答,2,未完成
+                            activityTips = DoSurveyTips;
+                            res = activityTips(data, _azureCosmos, id, _azureRedis);
+                            break;
                         //评测
-                    case "exam":
-                        activityTips = DoExamTips;
-                        res = activityTips(data, _azureCosmos, id);
-                        break;
+                        case "exam":
+                            //msgid 0 已作答, 1未作答,2,未完成, 用时间控制 相关发布状态,并且展示相应的结果
+                            activityTips = DoExamTips;
+                            res = activityTips(data, _azureCosmos, id, _azureRedis);
+                            break;
                         //学习活动
-                    case "learn":
-                        activityTips = DoLearnTips;
-                        res = activityTips(data, _azureCosmos, id);
-                        break;
+                        case "learn":
+                            //msgid 0 已完成, 1未开始,2,未完成
+                            activityTips = DoLearnTips;
+                            res = activityTips(data, _azureCosmos, id, _azureRedis);
+                            break;
                         //作业活动
-                    case "homework":
-                        activityTips = DoHomeworkTips;
-                        res = activityTips(data, _azureCosmos, id);
-                        break;
-                    default: break;
+                        case "homework":
+                            //msgid 0 已作答, 1未作答,2,未完成,3已批改,且有错误,4已批改,已完成
+                            //index:0,1,5 错误题序
+                            activityTips = DoHomeworkTips;
+                            res = activityTips(data, _azureCosmos, id, _azureRedis);
+                            break;
+                        default: break;
+                    }
                 }
             }
             return (datas, continuationToken);
         }
-        private async static Task<dynamic> DoVoteTips(ActivityData commonData , AzureCosmosFactory _azureCosmos,string id )
+        private async static Task<dynamic> DoVoteTips(ActivityData commonData , AzureCosmosFactory _azureCosmos,string userid,AzureRedisFactory _azureRedis)
         {
             Vote vote=null;
             var client = _azureCosmos.GetCosmosClient();
-            RedisHelper.HGet($"Vote:{id}","");
             await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<Vote>($"select value c from c where c.id='{commonData.id}'", 
                 requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(commonData.scode) }))
             {
                 vote = item;
                 break;
             }
-            
-            return null;
+            byte msgid = 0;
+            int voteCount = 0;
+            if (vote != null) {
+                DateTimeOffset now = DateTimeOffset.UtcNow;
+                long curr = now.ToUnixTimeMilliseconds();
+                //判断投票时间是否在起止时间内
+                if (curr >= vote.startTime && curr <= vote.endTime)
+                {
+                    string Field = "";
+                    RedisValue value = default;
+                    switch (vote.times)
+                    {
+                        case "once":
+                            // //如果是只能投票一次的活动则直接获取Redis的第一条 只能投一次
+                            Field = $"{userid}-once";
+                            RedisValue[] values = _azureRedis.GetRedisClient(8).HashValues($"Vote:Record:{vote.id}_{vote.code}");
+                            if (values != null && values.Length>0)
+                            {
+                                value = values[0];
+                            }
+                            break;
+                        case "day": //周期内每天
+                            Field = $"{userid}-day-{now.ToString("yyyyMMdd")}";
+                            value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}_{vote.code}", Field);
+                            break;
+                        case "week": //自然周
+                            Field = $"{userid}-week-{now.ToString("yyyy")}{GetWeek(now)}";
+                            value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}_{vote.code}", Field);
+                            
+                            break;
+                        case "month":  //月份
+                            Field = $"{userid}-month-{now.ToString("yyyyMM")}";
+                            value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}_{vote.code}", Field);
+                           
+                            break;
+                        case "year"://年份
+                            Field = $"{userid}-year-{now.ToString("yyyy")}";
+                            value = _azureRedis.GetRedisClient(8).HashGet($"Vote:Record:{vote.id}_{vote.code}", Field);
+                           
+                            break;
+                    }
+                    if (value != default && value.IsNullOrEmpty)
+                    {
+                        List<string> opt = null;
+                        JsonElement record = value.ToString().ToObject<JsonElement>();
+                        if (record.TryGetProperty("opt", out JsonElement jopt)) {
+                            opt = jopt.ToObject<List<string>>();
+                        }
+                        if (opt != null)
+                        {
+                            //处理记录投票是否小于等于周期内最大投票数
+                            if (opt.Count <= vote.voteNum)
+                            {
+                                voteCount = vote.voteNum - opt.Count;
+                                msgid = 1;
+                            }
+                            else
+                            {
+                                //3周期内的可投票数不足
+                                msgid = 3;
+                                voteCount = 0;
+                            }
+                        }
+                        else {
+                            msgid = 1;
+                            voteCount = vote.voteNum;
+                        }
+                    }
+                    else {
+                        //未投票,可以投票
+                        msgid = 1;
+                        voteCount = vote.voteNum;
+                    }
+                }
+                else
+                {
+                    msgid = 2; 
+                    voteCount = 0;
+
+                }
+            }
+            return new {msgid,voteCount };
         }
-        private static dynamic DoHomeworkTips(ActivityData commonData, AzureCosmosFactory _azureCosmos, string id)
+
+        private static dynamic DoHomeworkTips(ActivityData commonData, AzureCosmosFactory _azureCosmos, string id, AzureRedisFactory _azureRedis)
         {
             return null;
         }
-        private static dynamic DoLearnTips(ActivityData commonData, AzureCosmosFactory _azureCosmos, string id)
+        private static dynamic DoLearnTips(ActivityData commonData, AzureCosmosFactory _azureCosmos, string id, AzureRedisFactory _azureRedis)
         {
             return null;
         }
-        private static dynamic DoExamTips(ActivityData commonData, AzureCosmosFactory _azureCosmos, string id)
+        private static dynamic DoExamTips(ActivityData commonData, AzureCosmosFactory _azureCosmos, string id, AzureRedisFactory _azureRedis)
         {
             return null;
         }
-        private static dynamic DoSurveyTips(ActivityData commonData, AzureCosmosFactory _azureCosmos, string id)
+        private static dynamic DoSurveyTips(ActivityData commonData, AzureCosmosFactory _azureCosmos, string id, AzureRedisFactory _azureRedis)
         {
             return null;
         }