Browse Source

Merge branch 'develop' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into feature/upon_dev/20240229

upon 1 year ago
parent
commit
2acb580d05

+ 8 - 7
TEAMModelBI/Filter/RequestAuditFilter.cs

@@ -150,16 +150,17 @@ namespace TEAMModelOS.Filter
                     p = "bi",
                     //idToken=XAuthIdToken
                 };
-
+                var httpclient = _httpClient.CreateClient();
+                httpclient.Timeout=  TimeSpan.FromSeconds(10);
 #if DEBUG
-                var response = await _httpClient.CreateClient().PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/api/http-log", data);
-                if (response.StatusCode==HttpStatusCode.OK)
-                {
-                    string result = await response.Content.ReadAsStringAsync();
+                var response = await httpclient.PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/api/http-log", data);
+                //if (response.StatusCode==HttpStatusCode.OK)
+                //{
+                //    string result = await response.Content.ReadAsStringAsync();
 
-                }
+                //}
 #else
-            _=  _httpClient.CreateClient().PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/api/http-log",data);
+            _=  httpclient.PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/api/http-log",data);
 #endif
                 //   _ = _httpTrigger.RequestHttpTrigger(data, "China", "http-log");
             }

+ 1 - 0
TEAMModelOS.FunctionV4/Program.cs

@@ -83,6 +83,7 @@ namespace TEAMModelOS.FunctionV4
                services.AddMultipleAzureStorage(storageConnects);
                services.AddHostedService<BlobRootServiceBusSub>();
                services.AddIPSearcher("");
+               services.TryAddSingleton(new Region2LongitudeLatitudeTranslator(""));
            })
            .Build();
             await host.RunAsync();

+ 6 - 0
TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj

@@ -24,6 +24,7 @@
 		<None Remove="Lang\en-us.json" />
 		<None Remove="Lang\zh-cn.json" />
 		<None Remove="Lang\zh-tw.json" />
+		<None Remove="latlng.json" />
 	</ItemGroup>
 	<ItemGroup>
 		<Content Include="Lang\en-us.json">
@@ -41,6 +42,11 @@
 			<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
 			<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
 		</Content>
+ 		<Content Include="latlng.json">
+ 		  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ 		  <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
+ 		  <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+ 		</Content>
 	</ItemGroup>
 
 	<ItemGroup>

+ 118 - 2
TEAMModelOS.FunctionV4/TimeTrigger/IESTimerTrigger.cs

@@ -1,5 +1,6 @@
 using Azure.Cosmos;
 using Azure.Storage.Blobs.Models;
+using Azure.Storage.Blobs.Specialized;
 using DinkToPdf;
 using DinkToPdf.Contracts;
 using HTEXLib.COMM.Helpers;
@@ -7,8 +8,10 @@ using Microsoft.Azure.Cosmos.Table;
 using Microsoft.Azure.Functions.Worker;
 using Microsoft.Azure.Functions.Worker.Http;
 using Microsoft.Extensions.Logging;
+using Microsoft.OData.Edm;
 using StackExchange.Redis;
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -27,6 +30,7 @@ using TEAMModelOS.SDK.Models.Cosmos.Teacher;
 using TEAMModelOS.SDK.Models.Service;
 using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.SDK.Models.Table;
+using static TEAMModelOS.SDK.Models.Service.SystemService;
 using static TEAMModelOS.SDK.Models.Teacher;
 
 namespace TEAMModelOS.FunctionV4.TimeTrigger
@@ -45,7 +49,8 @@ namespace TEAMModelOS.FunctionV4.TimeTrigger
         private readonly SnowflakeId _snowflakeId;
         private readonly IHttpClientFactory _httpClient;
         private IPSearcher _ipSearcher;
-        public IESTimerTrigger(IPSearcher ipSearcher, IHttpClientFactory httpClient,SnowflakeId snowflakeId,IConverter converter, AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis)
+        private readonly Region2LongitudeLatitudeTranslator _longitudeLatitudeTranslator;
+        public IESTimerTrigger(Region2LongitudeLatitudeTranslator longitudeLatitudeTranslator, IPSearcher ipSearcher, IHttpClientFactory httpClient,SnowflakeId snowflakeId,IConverter converter, AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
@@ -55,8 +60,119 @@ namespace TEAMModelOS.FunctionV4.TimeTrigger
             _snowflakeId=snowflakeId;
             _httpClient = httpClient;
             _ipSearcher = ipSearcher;
+            _longitudeLatitudeTranslator = longitudeLatitudeTranslator;
+        }
+        /// <summary>
+        /// 防火墙日志记录文件
+        /// </summary>
+        /// <param name="req"></param>
+        /// <param name="log"></param>
+        /// <returns></returns>
+        [Function("HttpLogCount")]
+        //https://docs.azure.cn/zh-cn/azure-functions/functions-bindings-timer?tabs=in-process&pivots=programming-language-csharp
+        //0 1 * * * * 一天中每小时的第 1 分钟
+        //0 */10 * * * *  每五分钟一次
+        public async Task HttpLogCount([TimerTrigger("0 1 * * * *")] TimerInfo myTimer, ILogger log) {
+            try {
+                string location = Environment.GetEnvironmentVariable("Option:Location");
+                //获取上一个小时的数据
+                var gmt8Time = DateTimeOffset.UtcNow.GetGMTTime(8).AddHours(-1);
+                var appendBlob = _azureStorage.GetBlobContainerClient("0-service-log").GetAppendBlobClient($"http-log/{gmt8Time:yyyy}/{gmt8Time:MM}/{gmt8Time:dd}/{gmt8Time:HH}.log");
+                if (await appendBlob.ExistsAsync())
+                {
+                    BlobDownloadResult result = await appendBlob.DownloadContentAsync();
+                    var content = result.Content.ToString();
+                    content= content.Substring(0, content.Length-2);
+                    if (content.EndsWith("}"))
+                    {
+                        content=$"[{content}]";
+                    }
+                    else
+                    {
+                        content=$"[{content}}}]";
+                    }
+                    var httpLogs = content.ToObject<ConcurrentBag<HttpLog>>();
+                    Parallel.ForEach(httpLogs, item =>
+                    {
+                        item.year = $"{gmt8Time:yyyy}";
+                        item.month = $"{gmt8Time:MM}";
+                        item.day = $"{gmt8Time:dd}";
+                        item.hour =$"{gmt8Time:HH}";
+                    });
+
+                    //  vistsDay.FindAll(x => x.path.Contains("common/exam/upsert-record"))
+
+
+                    (ConcurrentBag<ApiVist> vists, ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)> uuidInfo)   = SystemService.ConvertHttpLog(httpLogs, _ipSearcher, _longitudeLatitudeTranslator);
+                    List<(string tmd, bool exists, string scope)> tmdexists = new List<(string tmd, bool exists, string scope)>();
+                    List<(string sch, bool exists)> schexists = new List<(string sch, bool exists)>();
+                    var tmds = uuidInfo.SelectMany(x => x.tmdid).ToHashSet();
+                    if (tmds.Any())
+                    {
+                        foreach (var tmd in tmds)
+                        {
+                            var exists = await _azureRedis.GetRedisClient().KeyExistsAsync($"Blob:Catalog:{tmd}");
+                            if (exists)
+                            {
+                                tmdexists.Add((tmd, exists, "teacher"));
+                            }
+                            else
+                            {
+                                exists = await _azureRedis.GetRedisClient().KeyExistsAsync($"Login:School:hbcn:student:{tmd}");
+                                tmdexists.Add((tmd, exists, "student"));
+                            }
+                        }
+                    }
+                    var schs = uuidInfo.SelectMany(x => x.school).ToHashSet();
+                    if (schs.Any())
+                    {
+                        foreach (var sch in schs)
+                        {
+                            var exists = await _azureRedis.GetRedisClient().KeyExistsAsync(sch);
+                            schexists.Add((sch, exists));
+                        }
+                    }
+                    foreach (var item in uuidInfo)
+                    {
+                        foreach (var tmd in item.tmdid)
+                        {
+                            var tmdext = tmdexists.Find(x => x.tmd.Equals(tmd));
+                            if (tmdext.tmd!= null  && tmdext.exists)
+                            {
+                                var vist = vists.Where(x => x.id.Equals(item.uuid));
+                                foreach (var vi in vist)
+                                {
+                                    vi.userId=tmd;
+                                    if (string.IsNullOrWhiteSpace(vi.scope))
+                                    {
+                                        vi.scope=tmdext.scope;
+                                    }
+                                }
+                                break;
+                            }
+                        }
+
+                        foreach (var sch in item.school)
+                        {
+                            var schext = schexists.Find(x => x.sch.Equals(sch));
+                            if (schext.sch!= null  && schext.exists)
+                            {
+                                var vist = vists.Where(x => x.id.Equals(item.uuid));
+                                foreach (var vi in vist)
+                                {
+                                    vi.school=sch;
+                                }
+                                
+                                break;
+                            }
+                        }
+                    }
+                }
+            } catch (Exception ex) 
+            {
+               await _dingDing.SendBotMsg($"{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+            }
         }
-      
 
         /// <summary>
         /// 防火墙日志记录文件

File diff suppressed because it is too large
+ 42708 - 0
TEAMModelOS.FunctionV4/latlng.json


+ 9 - 7
TEAMModelOS/Filter/Region2LongitudeLatitudeTranslator.cs

@@ -1,18 +1,21 @@
 using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
 using System.IO;
+using System.Linq;
 using System.Text;
-using System.Text.Json;
-using TEAMModelOS.SDK.Extension;
-using Top.Api;
+using System.Threading.Tasks;
 
-namespace TEAMModelOS.Filter
+namespace TEAMModelOS.SDK.DI
 {
     public class Region2LongitudeLatitudeTranslator
     {
 
         public readonly JArray regionJson;
-        public Region2LongitudeLatitudeTranslator(string configPath) {
-            StreamReader streamReader = new StreamReader(new FileStream(configPath + "/latlng.json", FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
+        public Region2LongitudeLatitudeTranslator(string configPath)
+        {
+            if (configPath == null) throw new ArgumentNullException(nameof(configPath));
+            StreamReader streamReader = new StreamReader(new FileStream(Path.Combine(configPath , "latlng.json"), FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Encoding.UTF8);
             StringBuilder stringBuilder = new StringBuilder();
             string text;
             while ((text = streamReader.ReadLine()) != null)
@@ -22,7 +25,6 @@ namespace TEAMModelOS.Filter
             streamReader.Close();
             string input = stringBuilder.ToString();
             regionJson=  JArray.Parse(input);
-           
         }
     }
 }

+ 562 - 1
TEAMModelOS.SDK/Models/Service/SystemService.cs

@@ -1,7 +1,12 @@
-using System;
+using HTEXLib.COMM.Helpers;
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.IdentityModel.Tokens.Jwt;
 using System.Linq;
 using System.Text;
+using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
@@ -55,5 +60,561 @@ namespace TEAMModelOS.SDK.Models.Service
                 //}
             }
         }
+
+
+        public  static (ConcurrentBag<ApiVist> vists, ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)> uuidInfo) ConvertHttpLog(ConcurrentBag<HttpLog> logs, IPSearcher _ipSearcher, Region2LongitudeLatitudeTranslator _longitudeLatitudeTranslator)
+        {
+            ConcurrentBag<ApiVist> vists = new ConcurrentBag<ApiVist>();
+            ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)> uuidInfo = new ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)>();
+            object lockObj = new object();
+            Parallel.ForEach(logs, async log => {
+                string uuid = Guid.NewGuid().ToString();
+                List<string> schoolMatch = new List<string>();
+                List<string> useridMatch = new List<string>();
+                var vist = new ApiVist()
+                {
+                    id=uuid,
+                    ip=log.ip,
+                    tid=log.tid,
+                    time= log.time,
+                    userId= log.id,
+                    school= log.school,
+                    tname= log.name,
+                    path = log.path,
+                    year=log.year,
+                    month=log.month,
+                    day=log.day,
+                    hour=log.hour
+                };
+                if (string.IsNullOrWhiteSpace(vist.userId))
+                {
+
+                    //var jsonPathContext = new JsonPathContext();
+                    //jsonPathContext.ValueSystem= new JsonTextValueSystem();
+                    string path = "$..['id_token','idToken','idtoken','tmdid','id','teacherId','teacher','tid','tId','userid','userId','code','studentId','student','studentid']";
+
+                    JObject jsonObject = JObject.Parse(log.param.GetRawText());
+                    //var nodes_path = jsonPathContext.SelectNodes(log.param, path);
+
+                    var nodes_path = jsonObject.SelectTokens(path);
+                    foreach (var node in nodes_path)
+                    {
+                        // 只获取是字符串的 
+                        if (node.Type.Equals(JTokenType.String))
+                        {
+                            switch (true)
+                            {
+                                case bool when node.Path.Contains("id_token")||node.Path.Contains("idToken")||node.Path.Contains("idtoken"):
+                                    {
+                                        try
+                                        {
+                                            var jwt = new JwtSecurityToken($"{node}");
+                                            string id = jwt.Payload.Sub;
+                                            var name = jwt.Claims.FirstOrDefault(claim => claim.Type.Equals("name"))?.Value;
+                                            if (!string.IsNullOrWhiteSpace(id) && long.TryParse(id, out long _id))
+                                            {
+                                                useridMatch.Add(id);
+                                            }
+                                        }
+                                        catch (Exception ex) { }
+                                        break;
+                                    }
+                                case bool when node.Path.Contains("tmdid")||node.Path.Contains("id")||node.Path.Contains("teacherId")
+                                ||node.Path.Contains("teacher")||node.Path.Contains("tid")||node.Path.Contains("tId")||node.Path.Contains("userid")
+                                ||node.Path.Contains("userId")||node.Path.Contains("studentId")||node.Path.Contains("student")||node.Path.Contains("studentid"):
+                                    {
+                                        if (!string.IsNullOrWhiteSpace($"{node}") && long.TryParse($"{node}", out long _id))
+                                        {
+                                            useridMatch.Add($"{node}");
+                                        }
+                                        break;
+                                    }
+                                case bool when node.Path.Contains("code"):
+                                    {
+                                        if (!string.IsNullOrWhiteSpace($"{node}"))
+                                        {
+                                            if (long.TryParse($"{node}", out long _id))
+                                            {
+                                                useridMatch.Add($"{node}");
+                                            }
+                                            else
+                                            {
+                                                string[] codes = $"{node}".Split("-");
+                                                foreach (var _code in codes)
+                                                {
+                                                    if (long.TryParse(_code, out long _codeid))
+                                                    {
+                                                        useridMatch.Add($"{_code}");
+                                                        break;
+                                                    }
+                                                }
+                                            }
+                                        }
+                                        break;
+                                    }
+                            }
+                        }
+                    }
+                }
+                if (string.IsNullOrWhiteSpace(vist.school))
+                {
+                    string path = "$..['school','id','schoolId','schoolid','schoolCode','school_code','schoolcode','code']";
+                    JObject jsonObject = JObject.Parse(log.param.GetRawText());
+                    var nodes_path = jsonObject.SelectTokens(path);
+                    foreach (var node in nodes_path)
+                    {
+                        // 只获取是字符串的 
+                        if (node.Type.Equals(JTokenType.String))
+                        {
+                            switch (true)
+                            {
+                                case bool when node.Path.Contains("school")||node.Path.Contains("id")||node.Path.Contains("schoolId")
+                                ||node.Path.Contains("schoolid")||node.Path.Contains("schoolCode")||node.Path.Contains("school_code")||node.Path.Contains("schoolcode"):
+                                    {
+                                        if (!$"{node}".Contains("-")&&  $"{node}".Length<=8)
+                                        {
+                                            schoolMatch.Add($"{node}");
+                                        }
+                                        break;
+                                    }
+                                case bool when node.Path.Contains("code"):
+                                    {
+                                        if (!$"{node}".Contains("-")&&  $"{node}".Length<=8)
+                                        {
+                                            schoolMatch.Add($"{node}");
+                                        }
+                                        else
+                                        {
+                                            string[] codes = $"{node}".Split("-");
+                                            foreach (var _code in codes)
+                                            {
+                                                if ($"{node}".Length<=8)
+                                                {
+                                                    schoolMatch.Add($"{_code}");
+                                                    break;
+                                                }
+                                            }
+                                        }
+                                        break;
+                                    }
+                            }
+                        }
+
+                    }
+                }
+
+
+
+                //处理 client
+                {
+                    if (!string.IsNullOrWhiteSpace(log.client))
+                    {
+                        if (log.client.Equals("IES", StringComparison.OrdinalIgnoreCase))
+                        {
+                            vist.client="ies5";
+                        }
+                        if (log.client.Equals("AClassONE", StringComparison.OrdinalIgnoreCase))
+                        {
+                            vist.client="aclassone";
+                        }
+                        if (log.client.Equals("BB", StringComparison.OrdinalIgnoreCase))
+                        {
+                            vist.client="habb";
+                        }
+                        if (log.client.Equals("HiTool", StringComparison.OrdinalIgnoreCase) ||log.client.Equals("HiTools", StringComparison.OrdinalIgnoreCase))
+                        {
+                            vist.client="hiscan";
+                        }
+                        if (log.client.Equals("HiTA", StringComparison.OrdinalIgnoreCase))
+                        {
+                            vist.client="hita";
+                        }
+                        if (log.client.Equals("HiTeachCC", StringComparison.OrdinalIgnoreCase))
+                        {
+                            vist.client="hiteachcc";
+                        }
+                        if (log.client.Equals("HiTeach", StringComparison.OrdinalIgnoreCase))
+                        {
+                            vist.client="hiteach";
+                        }
+                        if (log.client.Equals("Open", StringComparison.OrdinalIgnoreCase))
+                        {
+                            vist.client="open";
+                        }
+                    }
+                }
+                //补全站点
+                {
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("teammodelos-yx.chinacloudsites.cn")||log.host.Equals("teammodelos.chinacloudsites.cn")
+                        ||log.host.Equals("yx.teammodel.cn")))
+                    {
+                        log.host="IES-正式站";
+                        log.host="www.teammodel.cn";
+                        vist.client="ies5";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                       &&(log.host.Equals("scyx.teammodel.cn")  ||log.host.Equals("jinniu.teammodel.cn")))
+                    {
+                        log.host="研修2.0-正式站";
+                        log.host="scyx.teammodel.cn";
+                        vist.client="ability";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                       &&(log.host.Equals("open.teammodel.cn")))
+                    {
+                        log.host="开放平台-正式站";
+                        log.host="open.teammodel.cn";
+                        vist.client="open";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                       &&(log.host.Equals("open-test.teammodel.cn")  ||log.host.Equals("zhiyin-test.teammodel.cn")))
+                    {
+                        log.host="开放平台-测试站";
+                        log.host="open-test.teammodel.cn";
+                        vist.client="open";
+                    }
+
+                    //
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("teammodelos-rc.chinacloudsites.cn")))
+                    {
+                        log.host="IES-RC站";
+                        log.host="rc.teammodel.cn";
+                        vist.client="ies5";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("teammodelos-test.chinacloudsites.cn")))
+                    {
+                        log.host="IES-测试站";
+                        log.host="test.teammodel.cn";
+                        vist.client="ies5";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("teammodelbi-test.chinacloudsites.cn")))
+                    {
+                        log.host="BI-测试站";
+                        log.host="bitest.teammodel.cn";
+                        vist.client="bi";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("teammodelbi.chinacloudsites.cn")))
+                    {
+                        log.host="BI-正式站";
+                        log.host="bi.teammodel.cn";
+                        vist.client="bi";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("teamcontest.chinacloudsites.cn")))
+                    {
+                        log.host="赛课-正式站";
+                        log.host="contest.teammodel.cn";
+                        vist.client="contest";
+
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("contest.chinacloudsites.cn")))
+                    {
+                        log.host="赛课-正式站";
+                        log.host="contest.teammodel.cn";
+                        vist.client="contest";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("contest-test.chinacloudsites.cn")))
+                    {
+                        log.host="赛课-测试站";
+                        log.host="contest-test.teammodel.cn";
+                        vist.client="contest";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("hiteachcc.chinacloudsites.cn")))
+                    {
+                        log.host="CC-正式站";
+                        log.host="hiteachcc.teammodel.cn";
+                        vist.client="hiteachcc";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("appraisal.chinacloudsites.cn")))
+                    {
+                        log.host="评价-正式站";
+                        log.host="appraisal.teammodel.cn";
+                        vist.client="appraisal";
+                    }
+                    if (!string.IsNullOrWhiteSpace(log.host)
+                        &&(log.host.Equals("appraisal-test.chinacloudsites.cn")))
+                    {
+                        log.host="评价-测试站";
+                        log.host="appraisal-test.teammodel.cn";
+                        vist.client="appraisal";
+                    }
+                    if (log.host.Equals("localhost")  &&  log.p.Equals("appraisal"))
+                    {
+                        log.host="评价-测试站";
+                        log.host="appraisal-test.teammodel.cn";
+                        vist.client="appraisal";
+                    }
+                    if (log.host.Equals("localhost")  &&  log.p.Equals("os"))
+                    {
+                        log.host="IES-测试站";
+                        log.host="test.teammodel.cn";
+                        vist.client="ies5";
+                    }
+                    else if (log.host.Equals("localhost")  && (log.p.Equals("bi")))
+                    {
+                        log.host="BI-测试站";
+                        log.host="bitest.teammodel.cn";
+                        vist.client="bi";
+                    }
+                }
+
+                //补全产品端
+                {
+                    //研修2.0
+                    if (log.path.Contains("research")  || log.path.Contains("study")  || log.path.Contains("standard-file"))
+                    {
+                        vist.client="ability";
+                    }
+
+                    if (log.path.StartsWith("/activity"))
+                    {
+                        vist.client="contest";
+                    }
+                    //小程序
+                    if (log.path.Contains("aclassone"))
+                    {
+                        vist.client="aclassone";
+                    }
+                    //  /// <summary>
+                    /// ExamInfo  qamode   書面問答類型 0:書面問答 1:紙本測驗 2:艺术评测
+                    /// </summary>
+                    //艺术评测
+                    if (log.path.Contains("art") ||log.path.Contains("aclassone/find-children-activity")  ||log.path.Contains("aclassone/find-teacher-activity") ||log.path.Contains("aclassone/find-summary-activity") ||log.path.Contains("aclassone/upload-all") ||log.path.Contains("aclassone/delete"))
+                    {
+                        vist.client="art";
+
+                    }
+
+                    if (log.path.Contains("habb"))
+                    {
+                        vist.client="habb";
+                    }
+                    //阅卷客户端
+                    if (log.path.Contains("hiscan"))
+                    {
+                        vist.client="hiscan";
+                    }
+                    if (log.path.Contains("hita"))
+                    {
+                        vist.client="hita";
+                    }
+                    if (log.path.Contains("hiteachcc"))
+                    {
+                        vist.client="hiteachcc";
+                    }
+                    if (log.path.Contains("sokrate"))
+                    {
+                        vist.client="sokrate";
+                    }
+                    if (log.path.Contains("sokrate") || log.path.Contains("score"))
+                    {
+                        vist.client="sokrate";
+                    }
+
+                    if (log.path.Contains("hiteach"))
+                    {
+                        vist.client="hiteach";
+                    }
+                    ///IES开放平台
+                    if (log.path.Contains("business")  || log.path.Contains("biz") || log.path.Contains("openapi-config")  || log.path.Contains("open-api"))
+                    {
+                        vist.client="open";
+                    }
+                    //从token的role 能否获取 开放平台
+                    //单点登录及第三方接口
+                    if (log.path.Contains("lepei") || log.path.Contains("sc/")  || log.path.Contains("/sso") || log.path.Contains("sc-init") || log.path.Contains("data-push") || log.path.Contains("xkw")|| log.path.Contains("tianbo")
+                        || log.path.Contains("oauth/check-bind")|| log.path.Contains("dingding")  || log.path.Contains("wechat")
+                        )
+                    {
+                        vist.client="sso-third";
+                    }
+                }
+
+                //处理IP转地区
+                vist.region=await _ipSearcher.SearchIpAsync(vist.ip);
+                if (!string.IsNullOrWhiteSpace(vist.region))
+                {
+                    vist.region= vist.region.Replace("省·", "·").Replace("市·", "·").Replace("特别行政区·", "·").Replace("藏族羌族自治州·", "·");
+                    var regions = vist.region.Split("·");
+                    if (regions.Length==4)
+                    {
+                        vist.area=  regions[0];
+                        vist.province   = regions[1];
+                        vist.city = regions[2];
+                    }
+                    if (regions.Length==3)
+                    {
+                        vist.area=  regions[0];
+                        vist.province   = regions[1];
+                    }
+                    if (regions.Length==2)
+                    {
+                        vist.area=  regions[0];
+                        vist.province   = regions[1];
+                    }
+                    if (regions.Length==1)
+                    {
+                        vist.area=  regions[0];
+                    }
+                }
+                //处理地区转经纬度
+                {
+                    IEnumerable<JToken> tokens = default;
+                    if (!string.IsNullOrWhiteSpace(vist.city) && !string.IsNullOrWhiteSpace(vist.province)  && !string.IsNullOrWhiteSpace(vist.area))
+                    {
+                        tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i && @.city=~ /.*{vist.city}/i)]");
+                        if (!(tokens.Any() && tokens.Count()>0))
+                        {
+                            tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i && @.city=~ /.*{vist.province}/i)]");
+                            if (!(tokens.Any() && tokens.Count()>0))
+                            {
+                                tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i || @.city=~ /.*{vist.city}/i)]");
+                            }
+                            if (!(tokens.Any() && tokens.Count()>0))
+                            {
+                                tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i||@.city=~ /.*{vist.province}/i)]");
+                            }
+                        }
+
+                    }
+                    else if (string.IsNullOrWhiteSpace(vist.city) && !string.IsNullOrWhiteSpace(vist.province) && !string.IsNullOrWhiteSpace(vist.area))
+                    {
+                        if (vist.area.Equals("中国"))
+                        {
+                            tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i)]");
+                            if (!(tokens.Any() && tokens.Count()>0))
+                            {
+                                tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i)]");
+                            }
+                        }
+                        else
+                        {
+                            tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i || @.province=~ /.*{vist.province}/i)]");
+                        }
+                    }
+                    else if (!string.IsNullOrWhiteSpace(vist.city) && string.IsNullOrWhiteSpace(vist.province)&& !string.IsNullOrWhiteSpace(vist.area))
+                    {
+                        if (vist.area.Equals("中国"))
+                        {
+                            tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i)]");
+                            if (!(tokens.Any() && tokens.Count()>0))
+                            {
+                                tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i)]");
+                            }
+                        }
+                        else
+                        {
+                            tokens=  _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.city}/i || @.city=~ /.*{vist.province}/i)]");
+                        }
+                    }
+                    else if (string.IsNullOrWhiteSpace(vist.city) && string.IsNullOrWhiteSpace(vist.province)&& !string.IsNullOrWhiteSpace(vist.area))
+                    {
+                        tokens=  _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.country=~ /.*{vist.area}/i && @.m=='1')]");
+                    }
+                    if (tokens!= null && tokens!=default  &&  tokens.Any() && tokens.Count()>0)
+                    {
+                        List<RegionLngLat> regionLngLats = new List<RegionLngLat>();
+                        foreach (JToken token in tokens)
+                        {
+                            regionLngLats.Add(token.ToString().ToObject<RegionLngLat>());
+                        }
+                        var region = regionLngLats.FindAll(x => string.IsNullOrWhiteSpace(x.area));
+                        if (!region.IsNotEmpty())
+                        {
+                            region= regionLngLats.FindAll(x => !string.IsNullOrWhiteSpace(x.m) && x.m.Equals("1"));
+                        }
+                        vist.point= region?.FirstOrDefault();
+                    }
+                }
+                vist.host= log.host;
+                vist.hostName=log.hostName;
+                uuidInfo.Add((uuid, log, useridMatch, schoolMatch));
+                vists.Add(vist);
+            });
+            return (vists, uuidInfo);
+        }
+
+        public class ApiVist
+        {
+            public string id { get; set; }
+            public string path { get; set; }
+            /// <summary>
+            /// 细分
+            /// ies5 ,hiteach,hita,cc,bi,contest,open,aclassone,sokrates,ability,art
+            /// 产品端
+            /// </summary>
+            public string client { get; set; }
+            /// <summary>
+            /// 具体功能
+            /// </summary>
+            public string func { get; set; }
+
+            public string userId { get; set; }
+            public string scope { get; set; }
+            public string tname { get; set; }
+            public string school { get; set; }
+            public string ip { get; set; }
+            public string region { get; set; }
+            public string area { get; set; }
+            public string province { get; set; }
+            public string city { get; set; }
+            public long time { get; set; }
+            /// <summary>
+            /// 
+            /// </summary>
+            public string host { get; set; }
+            public string hostName = "其他";
+            /// <summary>
+            /// tokenid
+            /// </summary>
+            public string tid { get; set; }
+            public string year { get; set; }
+            public string month { get; set; }
+            public string day { get; set; }
+            public string hour { get; set; }
+            public RegionLngLat point { get; set; }
+        }
+
+        public class HttpLog
+        {
+            public string ip { get; set; }
+            public long time { get; set; }
+            public string host { get; set; }
+            public string hostName = "其他";
+            public string tid { get; set; }
+            public string path { get; set; }
+            public string client { get; set; }
+            public JsonElement param { get; set; }
+            public string id { get; set; }
+            public string name { get; set; }
+            public string school { get; set; }
+            public string p { get; set; }
+            // public string ua { get; set; }
+            // public string referer { get; set;  }
+            public string scope { get; set; }
+            public string year { get; set; }
+            public string month { get; set; }
+            public string day { get; set; }
+            public string hour { get; set; }
+
+        }
+        public record RegionLngLat
+        {
+            public string country { get; set; }
+            public string province { get; set; }
+            public string city { get; set; }
+            public string lat { get; set; }
+            public string lng { get; set; }
+            public string area { get; set; }
+            public string m { get; set; } = "0";
+        }
     }
 }

BIN
TEAMModelOS/ClientApp/public/login_bg.jpg


+ 1 - 1
TEAMModelOS/ClientApp/src/common/BaseClassSelectPri.vue

@@ -125,7 +125,7 @@ export default {
         res => {
           let list = res.groupLists.map(item => {
               item.groups = item.groups.filter(groups => {
-                  return groups.teachType === 'teacher'
+                  return groups.teachType === 'teacher' || groups.teachType === 'assistant'
               })
               return item
           })

+ 21 - 2
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -363,6 +363,11 @@
 				let idToken = localStorage.getItem("id_token");
 				return this.$api.login.getCode(idToken);
 			},
+			// 教师个人跳转赛课活动
+			toPrivActivity() {
+				let url = `${window.location.host === 'localhost:5001' ? 'http://localhost:8081' : window.location.origin}/teammodel/home/homePage?token=${localStorage.getItem("auth_token")}`
+				window.open(url, "", "noopener");
+			},
 			//教师个人跳转苏格拉底
 			toPrivSokrate() {
 				this.getLoginCode()
@@ -394,8 +399,8 @@
 						this.toPrivSokrate();
 					} else if (menu.to === "schoolSokrate") {
 						this.toSchoolSokrate();
-					} else if (menu.to === "activity") {
-
+					} else if (menu.to === "privActivity") {
+						this.toPrivActivity()
 					}
 				}
 			},
@@ -1557,6 +1562,20 @@
                 isShow: true
             }, */
 								]
+							},
+							// 活动报名
+							{
+								icon: "iconfont icon-yishu",
+								name: "活动平台",
+								router: "#",
+								tag: "",
+								role: "admin|teacher",
+								permission: "",
+								child: [],
+								menuName: "privActivity",
+								// menuName: 'myCourse',
+								isShow: this.isShowActi,
+								to: "privActivity"
 							}
 					  ];
 				return data;

+ 2 - 1
TEAMModelOS/ClientApp/src/common/PrivateTargetSingle.vue

@@ -112,9 +112,10 @@ export default {
             this.$api.common.getActivityTarget(params).then(
                 res => {
                     // 由于空间问题,先不让协同教师发布评测
+                    // 2024.3.22 放开协同教师发布评测
                     this.allList = res.groupLists.map(item => {
                         item.groups = item.groups.filter(groups => {
-                            return groups.teachType === 'teacher'
+                            return groups.teachType === 'teacher' || groups.teachType === 'assistant'
                         })
                         return item
                     })

+ 117 - 0
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/Cowork.vue

@@ -0,0 +1,117 @@
+<template>
+    <div>
+        <div>
+            <p class="action-type">{{ cowork.coworkType === 'All' ? $t('cusMgt.rcd.coworkAll') : (cowork.coworkType === 'Group' ? $t('cusMgt.rcd.coworkGroup') : $t('cusMgt.rcd.coworkdiff')) }}</p>
+            <div class="cowork-box">
+                <div v-for="(item, index) in coworkData" :key="index" style="">
+                    <img :src="item.snapshotUrl" class="receive-img" alt="" @click="viewImage(item.snapshotUrl)">
+                    <p>
+                        {{ item.title }}
+                        <Tooltip placement="bottom" v-show="cowork.coworkType != 'All'">
+                            <Icon type="ios-contacts" size="20" color="#2D8CF0" />
+                            <template #content>
+                                <span v-for="(stu, sIndex) in item.stuList" :key="sIndex">
+                                    <span v-if="stu">
+                                        {{ stu.name }}
+                                        <span v-show="sIndex != (item.stuList.length - 1)">、</span>
+                                    </span>
+                                </span>
+                            </template>
+                        </Tooltip>
+                    </p>
+                </div>
+            </div>
+        </div>
+        <StudentClient class="receive-student"></StudentClient>
+    </div>
+</template>
+
+<script>
+import StudentClient from '@/view/classrecord/eventchart/StudentClient.vue'
+export default {
+    components: {
+        StudentClient
+    },
+    props: {
+        cowork: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        },
+        students: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        },
+    },
+    data () {
+        return {
+        }
+    },
+    created () {
+    },
+    computed: {
+        coworkData() {
+            if(this.cowork.coworkType === 'All') {
+                return this.cowork.coworkGroupInfoList
+            } else {
+                let data = []
+                let owner = this.students.find(stu => stu.id === this.$store.state.userInfo.sub)
+                data = this.cowork.coworkGroupInfoList.filter(item => {
+                    return (item.members.filter(member => member == owner.seatID)).length
+                })
+                return data
+            }
+        },
+    },
+    methods: {
+        viewImage(url) {
+            this.$hevueImgPreview(url)
+        },
+    },
+    watch: {
+        cowork: {
+            handler(n, o) {
+            },
+            immediate: true,
+            deep: true
+        },
+    }
+}
+</script>
+
+<style lang="less" scoped>
+.action-type {
+    text-align: right;
+    font-weight: bold;
+    margin: 0 10px 5px 0;
+}
+.cowork-box {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: flex-end;
+
+    &>div {
+        margin: 0 10px 15px;
+        text-align: center;
+    }
+
+    .receive-img {
+        max-width: 150px;
+        max-height: 150px;
+        border: 1px solid #eeeeee;
+        cursor: pointer;
+    }
+}
+.cowork-group{
+    width: 400px;
+    height: 300px;
+}
+.cowork-student {
+    width: 300px;
+    height: 300px;
+    margin-right: 10px;
+}
+</style>

+ 44 - 4
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/RecordView.vue

@@ -134,6 +134,7 @@
                                     <Button type="warning" :disabled="!filtertype.irs" @click="filterFn('irs')">{{ $t("cusMgt.rcd.filter4") }}<!-- ({{ filtertype.irs }}) --></Button>
                                     <Button type="warning" :disabled="!filtertype.exam" @click="filterFn('exam')">{{ $t("cusMgt.rcd.filter5") }}<!-- ({{ filtertype.exam }}) --></Button>
                                     <Button type="warning" :disabled="!filtertype.smart" @click="filterFn('smart')">{{ $t('cusMgt.rcd.filter6') }}<!-- ({{ filtertype.exam }}) --></Button>
+                                    <Button type="warning" :disabled="!filtertype.cowork" @click="filterFn('cowork')">{{ $t('cusMgt.rcd.filter7') }}<!-- ({{ filtertype.exam }}) --></Button>
                                 </div>
                             </div>
                         </div>
@@ -158,7 +159,7 @@
                                                             <!-- 即问即答 -->
                                                             <div v-if="currentfilterType === '' || currentfilterType === 'ShowAnsLoad'">
                                                                 <ShowQues class="event-item student-event" v-if="event.Event === 'PopQuesLoad' || event.Event === 'ReAtmpAnsStrt'" :nowStuInfo="nowStuInfo" :evtType="event.Event" :irsData="event.data"></ShowQues>
-                                                                <PopQues class="event-item" v-if="(event.Event === 'PopQuesLoad' || event.Event === 'ReAtmpAnsStrt') && baseData" :evtType="event.Event" :irsData="event.data" :students="baseData.student"></PopQues>
+                                                                <PopQues class="event-item" v-if="(event.Event === 'PopQuesLoad' || event.Event === 'ReAtmpAnsStrt') && baseData && event.data.quesType != 'subjective'" :evtType="event.Event" :irsData="event.data" :students="baseData.student"></PopQues>
                                                             </div>
                                                             <!-- 抢权 -->
                                                             <Buzr class="event-item student-event" v-if="event.Event === 'BuzrAns' && baseData" :buzrData="event.data" :students="baseData.student"></Buzr>
@@ -174,6 +175,8 @@
                                                             <!-- 课中评测 -->
                                                             <Exam class="student-event event-item" :examInfo="event.data" :recordInfo="recordInfo" v-if="event.Event === 'SPQStrt'"></Exam>
                                                             <SmartRating class="event-item student-event" :recordInfo="recordInfo" :smartRate="event.data" :students="baseData.student" :vote="event.vote" :sas="sasRecd" v-else-if="event.Event === 'RatingStart'"></SmartRating>
+                                                            <!-- 协作 -->
+                                                            <Cowork class="event-item student-event" :cowork="event.data" :students="baseData.student" v-else-if="event.Event === 'CoworkLoad'"></Cowork>
                                                         </div>
                                                     </template>
                                                 </div>
@@ -220,12 +223,13 @@ import Pick from './Pick.vue';
 import Exam from './Exam.vue';
 import myWorks from './myWorks.vue';
 import SmartRating from './SmartRating.vue';
+import Cowork from './Cowork.vue';
 
 export default {
     components: {
         RcdPoster,
         Loading,
-        DataCount, ShowQues, PopQues, Buzr, Push, SmartRating,
+        DataCount, ShowQues, PopQues, Buzr, Push, SmartRating, Cowork,
         StuReceive, ReceiveBack, Pick, Exam, myWorks,
     },
     data () {
@@ -289,6 +293,7 @@ export default {
             irsData: [], //irs.json
             taskData: [], //task.json
             smartData: [],//smartRating.json
+            coworkData: [],//Cowork.json
             fnEvents: [], //功能事件
             events: [], //事件ID
             hiTeachEvent: [], //需要解析的事件信息
@@ -305,6 +310,7 @@ export default {
                 irs: 0, //互动
                 exam: 0, //测验
                 smart: 0, //智慧评分
+                cowork: 0, //协作
             },
             myWorks: [],
             haveInteraction: true,
@@ -501,7 +507,7 @@ export default {
             this.taskData = []
             this.smartData = []
             this.baseData = undefined
-            this.filtertype = {push: 0, task: 0, irs: 0, exam: 0, smart: 0}
+            this.filtertype = {push: 0, task: 0, irs: 0, exam: 0, smart: 0, cowork: 0}
             let sas = await this.$tools.getBlobSas(this.recordInfo.scope === 'school' ? this.recordInfo.school : this.recordInfo.tmdid)
             this.sasRecd = sas
             this.recordInfo.eNote = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/Note.pdf?${sas.sas}`
@@ -567,6 +573,21 @@ export default {
             try {
                 let irsUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/IES/IRS.json?${sas.sas}`
                 this.irsData = JSON.parse(await this.$tools.getFile(irsUrl) || '[]')
+                this.irsData.forEach(item => {
+                    item.quesType = item.question?.exercise?.type || ''
+                    item.ansType = item.question?.exercise?.answerType || ''
+                    if(item.quesType === 'subjective' && item.ansType != 'text' && item.ansType != 'text_Image') {
+                        for (const key in item.clientAnswers) {
+                            item.clientAnswers[key] = item.clientAnswers[key].map(ans => {
+                                ans = ans.map(info => {
+                                    info = `${sas.url}/${sas.name}/records/${this.recordInfo.id}${ans}?${sas.sas}`
+                                    return info
+                                })
+                                return ans
+                            })
+                        }
+                    }
+                })
             } catch (e) {
                 this.irsData = []
             }
@@ -600,6 +621,21 @@ export default {
             } catch (e) {
                 this.smartData = []
             }
+            try {
+                let coworkUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/IES/Cowork.json?${sas.sas}`
+                this.coworkData = JSON.parse(await this.$tools.getFile(coworkUrl) || '[]')
+                this.coworkData.forEach(item => {
+                    item.coworkGroupInfoList.forEach(info => {
+                        info.snapshotUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}${info.snapshot}?${sas.sas}`
+                        info.stuList = info.members.map(members => {
+                            return this.baseData.student.find(stu => stu.seatID == members)
+                        })
+                    })
+                })
+            } catch (e) {
+                console.log('15645f6451f', e);
+                this.coworkData = []
+            }
 
             //这里需要判断录制开始的pageid
             let startInfo = pageEvents.find(item => item.Event === 'EzsStartRecord')
@@ -663,7 +699,11 @@ export default {
                                 }
                             }
                             this.filtertype.smart += 1
-                        break
+                            break
+                        case 'cowork':
+                            e.data = this.coworkData.find(t => t.pageID == e.Pgid)
+                            this.filtertype.cowork += 1
+                            break
                         default:
                             break
                     }

+ 115 - 8
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ShowQues.vue

@@ -47,14 +47,43 @@
                 </template>
             </div>
         </div> -->
-        <p class="event-type">{{evtType == 'PopQuesLoad' ? $t("studentWeb.hiteachNote.qA") : $t("studentWeb.hiteachNote.qaAgain")}}:</p>
-        <p class="show-ques" v-if="ansData.length">
-            <span v-for="(ans, index) in ansData" :key="index" v-html="ans"></span>
-        </p>
-        <p class="show-ques" v-else>{{ $t("studentWeb.hiteachNote.noanswer") }}</p>
-        <div style="margin-right: 20px;" v-if="answer.length">
-            <Icon type="md-checkmark-circle" size="18" color="#00ad6c" v-show="isRight" />
-            <Icon type="md-close-circle" size="18" color="#ff5508" v-show="!isRight" />
+        <div>
+            <p class="event-type">
+                {{evtType == 'PopQuesLoad' ? $t("studentWeb.hiteachNote.qA") : $t("studentWeb.hiteachNote.qaAgain")}}
+                <span v-if="irsData.quesType === 'subjective'">({{ $t('evaluation.subjective') }}-{{ $t(`evaluation.newExercise[${irsData.ansType}]`) }})</span>:
+            </p>
+            <div class="show-ques file-box" v-if="ansData.length">
+                <template v-if="irsData.quesType === 'subjective' && irsData.ansType != 'text' && irsData.ansType != 'text_Image'">
+                    <div v-for="(ans, index) in ansData" :key="index">
+                        <img :src="ans" alt="" v-if="irsData.ansType === 'image'">
+                        <audio controls v-if="irsData.ansType === 'audio'">
+                            <source :src="ans">
+                            {{$t('teachContent.notAudio')}}
+                        </audio>
+                        <video v-if="irsData.ansType === 'video'" :src="ans" width="870" controls="controls" style="max-height: 800px;"></video>
+                        <div v-if="irsData.ansType === 'file'" class="repair-link-wrap-item-box">
+                            <div class="file-icon">
+                                <img :src="$tools.getFileThum($tools.getSuffix(ans), getFileName(ans))"/>
+                            </div>
+                            <div class="file-info">
+                                <p class="file-name">{{ getFileName(ans) }}</p>
+                                <div>
+                                    <span @click="onPreview(ans)">{{ $t('ability.review.preview')}}</span>
+                                    <span @click="onDownload(ans)">{{ $t('ability.review.download')}}</span>
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </template>
+                <template v-else>
+                    <span v-for="(ans, index) in ansData" :key="index" v-html="ans"></span>
+                </template>
+            </div>
+            <p class="show-ques" v-else>{{ $t("studentWeb.hiteachNote.noanswer") }}</p>
+            <div style="margin-right: 20px;" v-if="answer.length">
+                <Icon type="md-checkmark-circle" size="18" color="#00ad6c" v-show="isRight" />
+                <Icon type="md-close-circle" size="18" color="#ff5508" v-show="!isRight" />
+            </div>
         </div>
         <div>
             <Icon type="ios-person" class="owner-student-client-icon"/>
@@ -106,6 +135,33 @@ export default {
         TeacherClient,
         StudentClient
     },
+    methods: {
+        getFileName(url) {
+            let text = url.substring(url.lastIndexOf("/Ans/") + 5, url.lastIndexOf("?"))
+            return text
+        },
+        /* 预览 */
+        async onPreview(item){
+            let url = item
+            if (this.$tools.getSuffix(this.getFileName(item)) === 'pdf') {
+                window.open('/web/viewer.html?file=' + encodeURIComponent(url));
+            } else if(item.type === 'doc') {
+                window.open('https://view.officeapps.live.com/op/view.aspx?src=' + escape(url));
+            } else if(item.type === 'image') {
+                this.$hevueImgPreview(url)
+            } else if(item.type === 'link') {
+				window.open(/^(http:|https:)/i.test(url) ? url : "http://" + url)
+            } else {
+                console.log(1111111111111);
+                this.$hevueImgPreview(url)
+            }
+        },
+
+        /* 下载 */
+        async onDownload(item){
+            this.$tools.doDownloadByUrl(item, this.getFileName(item))
+        },
+    },
     watch: {
         irsData: {
             deep: true,
@@ -217,6 +273,50 @@ export default {
 
     .show-ques {
         margin-right: 10px;
+        img {
+            cursor: pointer;
+            width: 120px !important;
+            height: auto;
+        }
+        
+        .repair-link-wrap-item-box {
+            display: flex;
+            position: relative;
+            // background-color: #e3e3e3;
+            border-radius: 5px;
+            padding: 10px 0;
+            font-size: 14px;
+
+            &:hover {
+                background-color: #ebe9e9;
+            }
+
+            .file-icon {
+                img {
+                    width: 45px !important;
+                }
+            }
+
+            .file-info {
+                margin-left: 10px;
+
+                .file-name {
+                    font-weight: bold;
+                    margin-bottom: 5px;
+                }
+
+                span {
+                    color: #16a3b5;
+                    margin-right: 15px;
+                    cursor: pointer;
+                }
+            }
+        }
+    }
+    .file-box {
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: flex-end;
     }
 
 }
@@ -224,5 +324,12 @@ export default {
     margin-right: 20px;
     font-size: 15px;
     font-weight: 600;
+    margin: 0 10px 5px 0;
+}
+</style>
+<style lang="less">
+.show-ques svg{
+    width: 200px;
+    height: auto;
 }
 </style>

+ 2 - 2
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeView.vue

@@ -778,8 +778,8 @@ export default {
         },
         choiceClass(index, data) {
             if(this.isScale) return
-            let newIndex = this.getAllCourse.findIndex(item => {
-                return item.id === data.id
+            let newIndex = data.subjectList ? 0 : this.getAllCourse.findIndex(item => {
+                return item.id === data.id && item.groupId === data.groupId
             })
             // this.$parent.classChange(index + 1)
             this.$store.commit("setNowCourse", undefined)

+ 2 - 1
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/Exam.vue

@@ -58,7 +58,8 @@ export default {
                 query: {
                     examId: this.examDetaiInfo.id,
                     //code: `Exam-${this.$store.state.userInfo.TEAMModelId}`
-                    code: `Exam-${this.recordInfo.tmdid}`
+                    code: `Exam-${this.recordInfo.tmdid}`,
+                    scope: this.examDetaiInfo.scope,
                 }
             })
         },

+ 1 - 0
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/PopQues.vue

@@ -7,6 +7,7 @@
                 <Tooltip :content="$t('talMgmt.text47')">
                 <v-icon class="qu-flip-icon" :style="{'color':isOverview ? '':'#2d8cf0'}" :iconClass="imgSrc" v-show="quType === 'single' || quType === 'multiple' || quType === 'judge'" @click.native="isOverview = !isOverview" />
                 </Tooltip>
+                <span v-if="quType === 'subjective'">({{ $t('evaluation.subjective') }}-{{ $t(`evaluation.newExercise[${answerType}]`) }})</span>
             </p>
             <!-- 统计数据 -->
             <div v-if="isOverview">

+ 1 - 1
TEAMModelOS/ClientApp/src/view/mycourse/discussion/Discussion.vue

@@ -298,7 +298,7 @@ export default {
             }
             this.$api.studentWeb.addTopic(param).then(res => {
                 if(res.debate) {
-                    this.$Message.success(this.editId ? this.$t('evaluation.paperAnalysis.editSuc') : this.$t('cusMgt.shareOk'))
+                    this.$Message.success(this.editId ? this.$t('evaluation.paperList.editSuc') : this.$t('cusMgt.shareOk'))
                     this.topicShow = false
                     if(this.editId) {
                         let editContent = this.discuss.findIndex(item => {

+ 5 - 5
TEAMModelOS/ClientApp/src/view/signupActivity/infoComponent/skContent.vue

@@ -16,17 +16,17 @@
                         <div>
                             <p>{{ $t('activity.registered') }}</p>
                             <p style="color: #14b53b;">
-                                {{ '-' }}
+                                {{ 0 }}
                                 <span style="font-size: 16px; color: #737373;">/{{ contestInfo.sign.limit || $t('lessonRecord.all') }}</span>
                             </p>
                         </div>
                         <div>
                             <p>{{ $t('assessment.hasUpload') }}</p>
-                            <p style="color: #4b93ff;">{{ '-' }}</p>
+                            <p style="color: #4b93ff;">{{ 0 }}</p>
                         </div>
                         <div>
                             <p>{{ $t('activity.reviewed') }}</p>
-                            <p style="color: #ff9900;">{{ '-' }}</p>
+                            <p style="color: #ff9900;">{{ 0 }}</p>
                         </div>
                         <!-- <div>
                             <p>成绩发布</p>
@@ -60,7 +60,7 @@
                             <span>{{ row.uploadContestType === 'file' ? $t('studentWeb.courseContent.type.file') : (row.uploadContestType ? $t('auth.pdName8') : '-') }}</span>
                         </template>
                         <template #uploadContestScore="{row}">
-                            <span>{{ row.uploadContestScore === -1 ? '-' : row.uploadContestScore }}</span>
+                            <span>{{ row.uploadContestScore === -1 ? '未评分' : row.uploadContestScore }}</span>
                         </template>
                         <template #action="{row, index}">
                             <Button type="info" size="small" @click="getTeaInfo(row)" v-show="row.inviteStatus != -2">{{ $t('learnActivity.score.view') }}</Button>
@@ -911,7 +911,7 @@ export default {
                 if(res.code === 200) {
                     let lists = res?.inviteEnrollTeachers.map(item => {
                         item.joinTime = item.signContestTime ? this.$tools.formatTime(item.signContestTime, 'yyyy-MM-dd hh:mm:ss') : '-'
-                        item.uploadTime = item.uploadContestTime ? this.$tools.formatTime(item.uploadContestTime, 'yyyy-MM-dd hh:mm:ss') : '-'
+                        item.uploadTime = item.uploadContestTime ? this.$tools.formatTime(item.uploadContestTime, 'yyyy-MM-dd hh:mm:ss') : '未上传'
                         item.teamNameContest = item.teamNameContest || '-'
                         return item
                     })

+ 4 - 553
TEAMModelOS/Controllers/System/BillController.cs

@@ -43,7 +43,9 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.IP2Region;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BISchool;
+using TEAMModelOS.SDK.Models.Service;
 using Top.Api;
+using static TEAMModelOS.SDK.Models.Service.SystemService;
 
 namespace TEAMModelOS.Controllers
 {
@@ -152,7 +154,7 @@ namespace TEAMModelOS.Controllers
                                 });
                             }
                         });
-                        (ConcurrentBag<ApiVist> vists, ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)> uuidInfo)   =   Convert(logs);
+                        (ConcurrentBag<ApiVist> vists, ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)> uuidInfo)   = SystemService.ConvertHttpLog(logs,_ipSearcher,_longitudeLatitudeTranslator);
                         vistsDay.AddRange(vists);
                         uuidInfos.AddRange(uuidInfo);
                         vistsDay.FindAll(x => x.path.Contains("common/exam/upsert-record"));
@@ -229,484 +231,7 @@ namespace TEAMModelOS.Controllers
 
 
 
-        public (ConcurrentBag<ApiVist> vists, ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)> uuidInfo) Convert(ConcurrentBag<HttpLog> logs)
-        {
-            ConcurrentBag<ApiVist> vists = new ConcurrentBag<ApiVist>();
-            ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)> uuidInfo = new ConcurrentBag<(string uuid, HttpLog httpLog, List<string> tmdid, List<string> school)>();
-            object lockObj = new object();
-            Parallel.ForEach(logs, async log => {
-                string uuid = Guid.NewGuid().ToString();
-                List<string> schoolMatch = new List<string>();
-                List<string> useridMatch = new List<string>();
-                var vist = new ApiVist() {
-                    id=uuid,
-                    ip=log.ip,
-                    tid=log.tid,
-                    time= log.time,
-                    userId= log.id,
-                    school= log.school,
-                    tname= log.name,
-                    path = log.path,
-                    year=log.year,
-                    month=log.month,
-                    day=log.day,
-                    hour=log.hour
-                };
-                if (string.IsNullOrWhiteSpace(vist.userId))
-                {
-
-                    //var jsonPathContext = new JsonPathContext();
-                    //jsonPathContext.ValueSystem= new JsonTextValueSystem();
-                    string path = "$..['id_token','idToken','idtoken','tmdid','id','teacherId','teacher','tid','tId','userid','userId','code','studentId','student','studentid']";
-
-                    JObject jsonObject = JObject.Parse(log.param.GetRawText());
-                    //var nodes_path = jsonPathContext.SelectNodes(log.param, path);
-
-                    var nodes_path = jsonObject.SelectTokens(path);
-                    foreach (var node in nodes_path)
-                    {
-                        // 只获取是字符串的 
-                        if (node.Type.Equals(JTokenType.String))
-                        {
-                            switch (true)
-                            {
-                                case bool when node.Path.Contains("id_token")||node.Path.Contains("idToken")||node.Path.Contains("idtoken"):
-                                    {
-                                        try
-                                        {
-                                            var jwt = new JwtSecurityToken($"{node}");
-                                            string id = jwt.Payload.Sub;
-                                            var name = jwt.Claims.FirstOrDefault(claim => claim.Type.Equals("name"))?.Value;
-                                            if (!string.IsNullOrWhiteSpace(id) && long.TryParse(id, out long _id))
-                                            {
-                                                useridMatch.Add(id);
-                                            }
-                                        }
-                                        catch (Exception ex) { }
-                                        break;
-                                    }
-                                case bool when node.Path.Contains("tmdid")||node.Path.Contains("id")||node.Path.Contains("teacherId")
-                                ||node.Path.Contains("teacher")||node.Path.Contains("tid")||node.Path.Contains("tId")||node.Path.Contains("userid")
-                                ||node.Path.Contains("userId")||node.Path.Contains("studentId")||node.Path.Contains("student")||node.Path.Contains("studentid"):
-                                    {
-                                        if (!string.IsNullOrWhiteSpace($"{node}") && long.TryParse($"{node}", out long _id))
-                                        {
-                                            useridMatch.Add($"{node}");
-                                        }
-                                        break;
-                                    }
-                                case bool when node.Path.Contains("code"):
-                                    {
-                                        if (!string.IsNullOrWhiteSpace($"{node}"))
-                                        {
-                                            if (long.TryParse($"{node}", out long _id))
-                                            {
-                                                useridMatch.Add($"{node}");
-                                            }
-                                            else
-                                            {
-                                                string[] codes = $"{node}".Split("-");
-                                                foreach (var _code in codes)
-                                                {
-                                                    if (long.TryParse(_code, out long _codeid))
-                                                    {
-                                                        useridMatch.Add($"{_code}");
-                                                        break;
-                                                    }
-                                                }
-                                            }
-                                        }
-                                        break;
-                                    }
-                            }
-                        }
-                    }
-                }
-                if (string.IsNullOrWhiteSpace(vist.school))
-                {
-                    string path = "$..['school','id','schoolId','schoolid','schoolCode','school_code','schoolcode','code']";
-                    JObject jsonObject = JObject.Parse(log.param.GetRawText());
-                    var nodes_path = jsonObject.SelectTokens(path);
-                    foreach (var node in nodes_path)
-                    {
-                        // 只获取是字符串的 
-                        if (node.Type.Equals(JTokenType.String))
-                        {
-                            switch (true)
-                            {
-                                case bool when node.Path.Contains("school")||node.Path.Contains("id")||node.Path.Contains("schoolId")
-                                ||node.Path.Contains("schoolid")||node.Path.Contains("schoolCode")||node.Path.Contains("school_code")||node.Path.Contains("schoolcode"):
-                                    {
-                                        if (!$"{node}".Contains("-")&&  $"{node}".Length<=8)
-                                        {
-                                            schoolMatch.Add($"{node}");
-                                        }
-                                        break;
-                                    }
-                                case bool when node.Path.Contains("code"):
-                                    {
-                                        if (!$"{node}".Contains("-")&&  $"{node}".Length<=8)
-                                        {
-                                            schoolMatch.Add($"{node}");
-                                        }
-                                        else
-                                        {
-                                            string[] codes = $"{node}".Split("-");
-                                            foreach (var _code in codes)
-                                            {
-                                                if ($"{node}".Length<=8)
-                                                {
-                                                    schoolMatch.Add($"{_code}");
-                                                    break;
-                                                }
-                                            }
-                                        }
-                                        break;
-                                    }
-                            }
-                        }
-
-                    }
-                }
-
-
-              
-                //处理 client
-                {
-                    if (!string.IsNullOrWhiteSpace(log.client))
-                    {
-                        if (log.client.Equals("IES", StringComparison.OrdinalIgnoreCase))
-                        {
-                            vist.client="ies5";
-                        }
-                        if (log.client.Equals("AClassONE", StringComparison.OrdinalIgnoreCase))
-                        {
-                            vist.client="aclassone";
-                        }
-                        if (log.client.Equals("BB", StringComparison.OrdinalIgnoreCase))
-                        {
-                            vist.client="habb";
-                        }
-                        if (log.client.Equals("HiTool", StringComparison.OrdinalIgnoreCase) ||log.client.Equals("HiTools", StringComparison.OrdinalIgnoreCase))
-                        {
-                            vist.client="hiscan";
-                        }
-                        if (log.client.Equals("HiTA", StringComparison.OrdinalIgnoreCase))
-                        {
-                            vist.client="hita";
-                        }
-                        if (log.client.Equals("HiTeachCC", StringComparison.OrdinalIgnoreCase))
-                        {
-                            vist.client="hiteachcc";
-                        }
-                        if (log.client.Equals("HiTeach", StringComparison.OrdinalIgnoreCase))
-                        {
-                            vist.client="hiteach";
-                        }
-                        if (log.client.Equals("Open", StringComparison.OrdinalIgnoreCase))
-                        {
-                            vist.client="open";
-                        }
-                    }
-                }
-                //补全站点
-                {
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("teammodelos-yx.chinacloudsites.cn")||log.host.Equals("teammodelos.chinacloudsites.cn")
-                        ||log.host.Equals("yx.teammodel.cn")))
-                    {
-                        log.host="IES-正式站";
-                        log.host="www.teammodel.cn";
-                        vist.client="ies5";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                       &&(log.host.Equals("scyx.teammodel.cn")  ||log.host.Equals("jinniu.teammodel.cn")))
-                    {
-                        log.host="研修2.0-正式站";
-                        log.host="scyx.teammodel.cn";
-                        vist.client="ability";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                       &&(log.host.Equals("open.teammodel.cn")))
-                    {
-                        log.host="开放平台-正式站";
-                        log.host="open.teammodel.cn";
-                        vist.client="open";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                       &&(log.host.Equals("open-test.teammodel.cn")  ||log.host.Equals("zhiyin-test.teammodel.cn")))
-                    {
-                        log.host="开放平台-测试站";
-                        log.host="open-test.teammodel.cn";
-                        vist.client="open";
-                    }
-
-                    //
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("teammodelos-rc.chinacloudsites.cn")))
-                    {
-                        log.host="IES-RC站";
-                        log.host="rc.teammodel.cn";
-                        vist.client="ies5";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("teammodelos-test.chinacloudsites.cn")))
-                    {
-                        log.host="IES-测试站";
-                        log.host="test.teammodel.cn";
-                        vist.client="ies5";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("teammodelbi-test.chinacloudsites.cn")))
-                    {
-                        log.host="BI-测试站";
-                        log.host="bitest.teammodel.cn";
-                        vist.client="bi";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("teammodelbi.chinacloudsites.cn")))
-                    {
-                        log.host="BI-正式站";
-                        log.host="bi.teammodel.cn";
-                        vist.client="bi";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("teamcontest.chinacloudsites.cn")))
-                    {
-                        log.host="赛课-正式站";
-                        log.host="contest.teammodel.cn";
-                        vist.client="contest";
-
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("contest.chinacloudsites.cn")))
-                    {
-                        log.host="赛课-正式站";
-                        log.host="contest.teammodel.cn";
-                        vist.client="contest";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("contest-test.chinacloudsites.cn")))
-                    {
-                        log.host="赛课-测试站";
-                        log.host="contest-test.teammodel.cn";
-                        vist.client="contest";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("hiteachcc.chinacloudsites.cn")))
-                    {
-                        log.host="CC-正式站";
-                        log.host="hiteachcc.teammodel.cn";
-                        vist.client="hiteachcc";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host) &&(log.host.Equals("appraisal.chinacloudsites.cn")))
-                    {
-                        log.host="评价-正式站";
-                        log.host="appraisal.teammodel.cn";
-                        vist.client="appraisal";
-                    }
-                    if (!string.IsNullOrWhiteSpace(log.host)
-                        &&(log.host.Equals("appraisal-test.chinacloudsites.cn")))
-                    {
-                        log.host="评价-测试站";
-                        log.host="appraisal-test.teammodel.cn";
-                        vist.client="appraisal";
-                    }
-                    if (log.host.Equals("localhost")  &&  log.p.Equals("appraisal"))
-                    {
-                        log.host="评价-测试站";
-                        log.host="appraisal-test.teammodel.cn";
-                        vist.client="appraisal";
-                    }
-                    if (log.host.Equals("localhost")  &&  log.p.Equals("os"))
-                    {
-                        log.host="IES-测试站";
-                        log.host="test.teammodel.cn";
-                        vist.client="ies5";
-                    }
-                    else if (log.host.Equals("localhost")  && (log.p.Equals("bi")))
-                    {
-                        log.host="BI-测试站";
-                        log.host="bitest.teammodel.cn";
-                        vist.client="bi";
-                    }
-                }
-
-                //补全产品端
-                {
-                    //研修2.0
-                    if (log.path.Contains("research")  || log.path.Contains("study")  || log.path.Contains("standard-file"))
-                    {
-                        vist.client="ability";
-                    }
-
-                    if (log.path.StartsWith("/activity"))
-                    {
-                        vist.client="contest";
-                    }
-                    //小程序
-                    if (log.path.Contains("aclassone"))
-                    {
-                        vist.client="aclassone";
-                    }
-                    //  /// <summary>
-                    /// ExamInfo  qamode   書面問答類型 0:書面問答 1:紙本測驗 2:艺术评测
-                    /// </summary>
-                    //艺术评测
-                    if (log.path.Contains("art") ||log.path.Contains("aclassone/find-children-activity")  ||log.path.Contains("aclassone/find-teacher-activity") ||log.path.Contains("aclassone/find-summary-activity") ||log.path.Contains("aclassone/upload-all") ||log.path.Contains("aclassone/delete"))
-                    {
-                        vist.client="art";
-
-                    }
-
-                    if (log.path.Contains("habb"))
-                    {
-                        vist.client="habb";
-                    }
-                    //阅卷客户端
-                    if (log.path.Contains("hiscan"))
-                    {
-                        vist.client="hiscan";
-                    }
-                    if (log.path.Contains("hita"))
-                    {
-                        vist.client="hita";
-                    }
-                    if (log.path.Contains("hiteachcc"))
-                    {
-                        vist.client="hiteachcc";
-                    }
-                    if (log.path.Contains("sokrate"))
-                    {
-                        vist.client="sokrate";
-                    }
-                    if (log.path.Contains("sokrate") || log.path.Contains("score"))
-                    {
-                        vist.client="sokrate";
-                    }
-
-                    if (log.path.Contains("hiteach"))
-                    {
-                        vist.client="hiteach";
-                    }
-                    ///IES开放平台
-                    if (log.path.Contains("business")  || log.path.Contains("biz") || log.path.Contains("openapi-config")  || log.path.Contains("open-api"))
-                    {
-                        vist.client="open";
-                    }
-                    //从token的role 能否获取 开放平台
-                    //单点登录及第三方接口
-                    if (log.path.Contains("lepei") || log.path.Contains("sc/")  || log.path.Contains("/sso") || log.path.Contains("sc-init") || log.path.Contains("data-push") || log.path.Contains("xkw")|| log.path.Contains("tianbo")
-                        || log.path.Contains("oauth/check-bind")|| log.path.Contains("dingding")  || log.path.Contains("wechat")
-                        )
-                    {
-                        vist.client="sso-third";
-                    }
-                }
-
-                //处理IP转地区
-                vist.region=await _ipSearcher.SearchIpAsync(vist.ip);
-                if (!string.IsNullOrWhiteSpace(vist.region))
-                {
-                    vist.region= vist.region.Replace("省·", "·").Replace("市·", "·").Replace("特别行政区·", "·").Replace("藏族羌族自治州·", "·");
-                    var regions = vist.region.Split("·");
-                    if (regions.Length==4)
-                    {
-                        vist.area=  regions[0];
-                        vist.province   = regions[1];
-                        vist.city = regions[2];
-                    }
-                    if (regions.Length==3)
-                    {
-                        vist.area=  regions[0];
-                        vist.province   = regions[1];
-                    }
-                    if (regions.Length==2)
-                    {
-                        vist.area=  regions[0];
-                        vist.province   = regions[1];
-                    }
-                    if (regions.Length==1)
-                    {
-                        vist.area=  regions[0];
-                    }
-                }
-                //处理地区转经纬度
-                {
-                    IEnumerable<JToken> tokens = default;
-                    if (!string.IsNullOrWhiteSpace(vist.city) && !string.IsNullOrWhiteSpace(vist.province)  && !string.IsNullOrWhiteSpace(vist.area))
-                    {
-                        tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i && @.city=~ /.*{vist.city}/i)]");
-                        if (!(tokens.Any() && tokens.Count()>0))
-                        {
-                            tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i && @.city=~ /.*{vist.province}/i)]");
-                            if (!(tokens.Any() && tokens.Count()>0))
-                            {
-                                tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i || @.city=~ /.*{vist.city}/i)]");
-                            }
-                            if (!(tokens.Any() && tokens.Count()>0))
-                            {
-                                tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i||@.city=~ /.*{vist.province}/i)]");
-                            }
-                        }
-
-                    }
-                    else if (string.IsNullOrWhiteSpace(vist.city) && !string.IsNullOrWhiteSpace(vist.province) && !string.IsNullOrWhiteSpace(vist.area))
-                    {
-                        if (vist.area.Equals("中国"))
-                        {
-                            tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.province}/i)]");
-                            if (!(tokens.Any() && tokens.Count()>0))
-                            {
-                                tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i)]");
-                            }
-                        }
-                        else
-                        {
-                            tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i || @.province=~ /.*{vist.province}/i)]");
-                        }
-                    }
-                    else if (!string.IsNullOrWhiteSpace(vist.city) && string.IsNullOrWhiteSpace(vist.province)&& !string.IsNullOrWhiteSpace(vist.area))
-                    {
-                        if (vist.area.Equals("中国"))
-                        {
-                            tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.province=~ /.*{vist.city}/i)]");
-                            if (!(tokens.Any() && tokens.Count()>0))
-                            {
-                                tokens= _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.province}/i)]");
-                            }
-                        }
-                        else
-                        {
-                            tokens=  _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.city=~ /.*{vist.city}/i || @.city=~ /.*{vist.province}/i)]");
-                        }
-                    }
-                    else if (string.IsNullOrWhiteSpace(vist.city) && string.IsNullOrWhiteSpace(vist.province)&& !string.IsNullOrWhiteSpace(vist.area))
-                    {
-                        tokens=  _longitudeLatitudeTranslator.regionJson.SelectTokens($"$..[?(@.country=~ /.*{vist.area}/i && @.m=='1')]");
-                    }
-                    if (tokens!= null && tokens!=default  &&  tokens.Any() && tokens.Count()>0)
-                    {
-                        List<RegionLngLat> regionLngLats = new List<RegionLngLat>();
-                        foreach (JToken token in tokens)
-                        {
-                            regionLngLats.Add(token.ToString().ToObject<RegionLngLat>());
-                        }
-                        var region = regionLngLats.FindAll(x => string.IsNullOrWhiteSpace(x.area));
-                        if (!region.IsNotEmpty())
-                        {
-                            region= regionLngLats.FindAll(x => !string.IsNullOrWhiteSpace(x.m) && x.m.Equals("1"));
-                        }
-                        vist.point= region?.FirstOrDefault();
-                    }
-                }
-                vist.host= log.host;
-                vist.hostName=log.hostName;
-                uuidInfo.Add((uuid, log, useridMatch, schoolMatch));
-                vists.Add(vist);
-            });
-            return (vists, uuidInfo);
-        }
+      
 
         [HttpPost("report")]
         [EnableCors("AllowSpecificOrigin")]
@@ -1373,78 +898,4 @@ namespace TEAMModelOS.Controllers
         }
     }
 
-    public class ApiVist
-    {
-        public string id { get; set; }
-        public string path { get; set; }
-        /// <summary>
-        /// 细分
-        /// ies5 ,hiteach,hita,cc,bi,contest,open,aclassone,sokrates,ability,art
-        /// 产品端
-        /// </summary>
-        public string client { get; set; }
-        /// <summary>
-        /// 具体功能
-        /// </summary>
-        public string func {  get; set; }
-
-        public string userId { get; set; }
-        public string scope { get; set; }
-        public string tname { get; set; }
-        public string school { get; set; }
-        public string ip { get; set; }
-        public string region { get; set; }
-        public string area { get; set; }
-        public string province { get; set; }
-        public string city { get; set; }
-        public long time { get; set; }
-        /// <summary>
-        /// 
-        /// </summary>
-        public string host { get; set; }
-        public string hostName = "其他";
-        /// <summary>
-        /// tokenid
-        /// </summary>
-        public string tid { get; set; }
-        public string year { get; set; }
-        public string month { get; set; }
-        public string day { get; set; }
-        public string hour { get; set; }
-        public RegionLngLat point { get; set; }
-    }
-
-    public class HttpLog
-    {
-        public string ip { get; set; }
-        public long time { get; set; }
-        public string host { get; set; }
-        public string hostName = "其他";
-        public string tid { get; set; }
-        public string path { get; set; }
-        public string client { get; set; }
-        public JsonElement param { get; set; }
-        public string id { get; set; }
-        public string name { get; set; }
-        public string school { get; set; }
-        public string p { get; set; }
-        // public string ua { get; set; }
-        // public string referer { get; set;  }
-        public string scope { get; set; }
-        public string year { get; set; }
-        public string month { get; set; }
-        public string day { get; set; }
-        public string hour { get; set; }
-
-    }
-    public record RegionLngLat
-    {
-        public string country { get; set; }
-        public string province { get; set; }
-        public string city { get; set; }
-        public string lat { get; set; }
-        public string lng { get; set; }
-        public string area { get; set; }
-        public string m { get; set; } = "0";
-    }
 }

+ 8 - 7
TEAMModelOS/Filter/RequestAuditFilter.cs

@@ -189,16 +189,17 @@ namespace TEAMModelOS.Filter
                     p = "os",
                     //idToken=XAuthIdToken
                 };
-
+                var httpclient=    _httpClient.CreateClient();
+                httpclient.Timeout=  TimeSpan.FromSeconds(10); 
 #if DEBUG
-                var  response = await   _httpClient.CreateClient().PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/api/http-log", data);
-                if (response.StatusCode==HttpStatusCode.OK) 
-                {
-                    string result =   await response.Content.ReadAsStringAsync();
+                var  response = await httpclient.PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/api/http-log", data);
+                //if (response.StatusCode==HttpStatusCode.OK) 
+                //{
+                //    string result =   await response.Content.ReadAsStringAsync();
                     
-                }
+                //}
 #else
-            _=  _httpClient.CreateClient().PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/api/http-log",data);
+            _=  httpclient.PostAsJsonAsync("http://cdhabook.teammodel.cn:8805/api/http-log",data);
 #endif
                 //   _ = _httpTrigger.RequestHttpTrigger(data, "China", "http-log");
             }