瀏覽代碼

Merge branch 'develop6.0-tmd' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop6.0-tmd

zhouj1203@hotmail.com 3 年之前
父節點
當前提交
4ff4516111
共有 44 個文件被更改,包括 2798 次插入883 次删除
  1. 1 0
      TEAMModelBI/ClientApp/src/App.vue
  2. 1 1
      TEAMModelBI/ClientApp/src/view/login.vue
  3. 399 0
      TEAMModelBI/Controllers/BINormal/AppCompanyController.cs
  4. 135 0
      TEAMModelBI/Controllers/BINormal/BIOpenApiController.cs
  5. 163 0
      TEAMModelBI/Controllers/BINormal/CompanyController.cs
  6. 109 96
      TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs
  7. 1 2
      TEAMModelBI/Controllers/BIStudent/StudentController.cs
  8. 311 43
      TEAMModelBI/Controllers/BITest/TestController.cs
  9. 9 9
      TEAMModelBI/Controllers/DingDingStruc/TableDingDingInfoController.cs
  10. 113 6
      TEAMModelBI/Controllers/LoginController.cs
  11. 0 1
      TEAMModelBI/TEAMModelBI.csproj
  12. 23 27
      TEAMModelBI/Tool/Extension/GenerateRandom.cs
  13. 1 2
      TEAMModelBI/Tool/Extension/JwtAuth.cs
  14. 10 2
      TEAMModelOS.FunctionV4/CosmosDB/TriggerCorrect.cs
  15. 8 1
      TEAMModelOS.FunctionV4/CosmosDB/TriggerExam.cs
  16. 8 1
      TEAMModelOS.FunctionV4/CosmosDB/TriggerExamLite.cs
  17. 8 1
      TEAMModelOS.FunctionV4/CosmosDB/TriggerHomework.cs
  18. 7 1
      TEAMModelOS.FunctionV4/CosmosDB/TriggerStudy.cs
  19. 8 1
      TEAMModelOS.FunctionV4/CosmosDB/TriggerSurvey.cs
  20. 8 1
      TEAMModelOS.FunctionV4/CosmosDB/TriggerVote.cs
  21. 16 14
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  22. 7 8
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs
  23. 253 0
      TEAMModelOS.SDK/Models/Cosmos/BI/AppCompany.cs
  24. 62 0
      TEAMModelOS.SDK/Models/Cosmos/BI/BIOpenApi.cs
  25. 56 0
      TEAMModelOS.SDK/Models/Cosmos/BI/Company.cs
  26. 11 2
      TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs
  27. 667 582
      TEAMModelOS/ClientApp/src/components/homework/BaseHwForm.vue
  28. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/homework.js
  29. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/index.js
  30. 48 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/lessonRecord.js
  31. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/homework.js
  32. 3 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/index.js
  33. 48 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/lessonRecord.js
  34. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/homework.js
  35. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/index.js
  36. 48 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/lessonRecord.js
  37. 2 4
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue
  38. 1 1
      TEAMModelOS/ClientApp/src/view/evaluation/bank/PaperDownload.vue
  39. 1 1
      TEAMModelOS/ClientApp/src/view/evaluation/bank/index.vue
  40. 74 2
      TEAMModelOS/ClientApp/src/view/homework/ManageHomeWork.vue
  41. 1 2
      TEAMModelOS/ClientApp/src/view/jyzx/classMemoir.vue
  42. 3 0
      TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.less
  43. 148 71
      TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.vue
  44. 16 1
      TEAMModelOS/Controllers/Both/LessonRecordController.cs

+ 1 - 0
TEAMModelBI/ClientApp/src/App.vue

@@ -11,5 +11,6 @@ export default {
 <style>
 #app {
     min-width: 1280px;
+    max-width: 1920px;
 }
 </style>

+ 1 - 1
TEAMModelBI/ClientApp/src/view/login.vue

@@ -133,7 +133,7 @@ export default {
                 localStorage.setItem('blobInfo', JSON.stringify(blobInfos))
                 getOrganization()
                 Allpermission()
-                // router.push('/dashboard')
+                router.push('/dashboard')
             }
         }
         //获取组织架构

+ 399 - 0
TEAMModelBI/Controllers/BINormal/AppCompanyController.cs

@@ -0,0 +1,399 @@
+using Azure.Cosmos;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelBI.Filter;
+using TEAMModelBI.Tool.Extension;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service;
+
+namespace TEAMModelBI.Controllers.BINormal
+{
+    [Route("appcompany")]
+    [ApiController]
+    public class AppCompanyController : ControllerBase
+    {
+        public readonly AzureCosmosFactory _azureCosmos;
+        public readonly AzureStorageFactory _azureStorage;
+        public readonly DingDing _dingDing;
+        public readonly Option _option;
+        private readonly IConfiguration _configuration;
+        private readonly NotificationService _notificationService;
+
+        public AppCompanyController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
+        {
+            _azureCosmos = azureCosmos;
+            _azureStorage = azureStorage;
+            _dingDing = dingDing;
+            _option = option?.Value;
+            _configuration = configuration;
+            _notificationService = notificationService;
+        }
+
+        /// <summary>
+        /// 查询应用信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-info")]
+        public async Task<IActionResult> GetInfo(JsonElement jsonElement)
+        {
+            jsonElement.TryGetProperty("appId", out JsonElement appId);
+            jsonElement.TryGetProperty("eid", out JsonElement eid);
+            jsonElement.TryGetProperty("audit", out JsonElement audit);
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            StringBuilder sqlTxt = new($"select c.id,c.pk,c.code,c.name,c.descr,c.picture,c.jwtKey,c.status,c.audit,c.refuseDesc,c.gateways,c.apis,c.webhookDomain,c.webHooks,c.schools from c where c.pk='App'");
+            if (!string.IsNullOrEmpty($"{appId}"))
+            {
+                sqlTxt.Append($" and id='{appId}'");
+            }
+            if (!string.IsNullOrEmpty($"{audit}")) 
+            {
+                sqlTxt.Append($" and audit='{audit}'");
+            }
+
+            List<ReadCompany> appCompanys = new();
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryStreamIterator(queryText: sqlTxt.ToString(), requestOptions: string.IsNullOrEmpty($"{eid}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"App-{eid}") }))
+            {
+                using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        ReadCompany readCompany = new()
+                        {
+                            id = obj.GetProperty("id").GetString(),
+                            pk = obj.GetProperty("pk").GetString(),
+                            code = obj.GetProperty("code").GetString(),
+                            name = obj.GetProperty("name").GetString(),
+                            descr = obj.GetProperty("descr").GetString(),
+                            picture = obj.GetProperty("picture").GetString(),
+                            jwtKey = obj.GetProperty("jwtKey").GetString(),
+                            status = obj.GetProperty("status").GetInt32(),
+                            audit = obj.GetProperty("audit").GetInt32(),
+                            refuseDesc = obj.GetProperty("refuseDesc").GetString(),
+                            gateways = obj.GetProperty("gateways").GetString(),
+                            apis = obj.GetProperty("apis").ToObject<List<AppApiState>>(),
+                            webhookDomain = obj.GetProperty("webhookDomain").GetString(),
+                            webHooks = obj.GetProperty("webHooks").ToObject<List<WebHookState>>(),
+                            schools = obj.GetProperty("schools").ToObject<List<ApplySchool>>()
+                        };
+
+                        appCompanys.Add(readCompany);
+                    }
+                }
+            }
+
+            return Ok(new { state = 200, appCompanys });
+        }
+
+        /// <summary>
+        /// 新增或者修改应用
+        /// </summary>
+        /// <param name="appCompany"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [AuthToken(Roles = "assist")]
+        [HttpPost("set-info")]
+        public async Task<IActionResult> SetAppInfo(AppCompany appCompany)
+        {
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            StringBuilder stringBuilder = new();
+
+            //新建
+            if (string.IsNullOrEmpty($"{appCompany.id}"))
+            {
+                appCompany.id = GenerateRandom.StrRandom(8, large: true, small: true);
+                appCompany.code = $"App-{appCompany.code}";
+                appCompany.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                appCompany.status = -1;
+                appCompany.audit = -1;
+                appCompany = await cosmosClient.GetContainer("TEAMModelOS", "Normal").CreateItemAsync<AppCompany>(appCompany, new PartitionKey(appCompany.code));
+            }
+            //修改
+            else
+            {
+                var response = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(appCompany.id, new PartitionKey(appCompany.code));
+                if (response.Status == 200)
+                {
+                    appCompany.pk = "App";
+                    appCompany.ttl = -1;
+                    appCompany = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<AppCompany>(appCompany, appCompany.id, new PartitionKey(appCompany.code));
+                }
+                else return Ok(new { state = 404, msg = "未找到该id相关的企业应用信息" });
+            }
+
+            return Ok(new { state = 200, appCompany });
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [HttpPost("get-applyapi")]
+        public async Task<IActionResult> SetAuditApp(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("appIds", out JsonElement appIds)) return BadRequest();
+            if (!jsonElement.TryGetProperty("isAudit", out JsonElement isAudit)) return BadRequest();
+            jsonElement.TryGetProperty("refuseDesc", out JsonElement refuseDesc);
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            List<AppIdOrCode> idOrCode = appIds.ToObject<List<AppIdOrCode>>();
+            List<AppIdOrCode> haveIds = new();
+            if (idOrCode.Count > 0)
+            {
+                foreach (var idCode in idOrCode)
+                {
+                    AppCompany appCompany = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemAsync<AppCompany>(idCode.id, new PartitionKey(idCode.code));
+                    //var response = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(idCode.id, new PartitionKey(idCode.code));
+                    if (bool.Parse($"{isAudit}") == true)
+                    {
+                        appCompany.audit = 1;
+                    }
+                    else
+                    {
+                        appCompany.audit = 0;
+                        appCompany.refuseDesc = $"{refuseDesc}";
+                    }
+                    try
+                    {
+                        await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<AppCompany>(appCompany, appCompany.id, new PartitionKey(idCode.code));
+                    }
+                    catch 
+                    {
+                        haveIds.Add(idCode);
+                    }
+                }
+            }
+            else return Ok(new { state = 404, msg = "appIds参数错误" });
+
+            return Ok(new { state = 200});
+        }
+
+
+        /// <summary>
+        /// 应用申请Api接口信息
+        /// 审核应用api接口信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-applyapi")]
+        public async Task<IActionResult> SetApplyApi(JsonElement jsonElement)
+        {
+            if (!jsonElement.TryGetProperty("appId", out JsonElement appId)) return BadRequest();
+            if (!jsonElement.TryGetProperty("appCode", out JsonElement appCode)) return BadRequest();
+            if (!jsonElement.TryGetProperty("apiIds", out JsonElement apiIds)) return BadRequest();
+            if (!jsonElement.TryGetProperty("operate", out JsonElement operate)) return BadRequest();
+
+            List<string> tempApi = apiIds.ToObject<List<string>>();
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            List<string> haveApi = new();  //存在api接口
+            List<string> sendWhom = new();//消息分发给谁   待完善
+            string bizcode = "";  //消息名称
+
+            AppCompany appCompany = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemAsync<AppCompany>($"{appId}", new PartitionKey($"{appCode}"));
+
+            if (appCompany != null)
+            {
+                switch (operate.GetString())
+                {
+                    case "apply":
+                        jsonElement.TryGetProperty("applyDesc", out JsonElement applyDesc);
+                        tempApi.ForEach(x =>
+                        {
+                            var strt = appCompany.apis.Find(y => y.no.Equals($"{x}")).no;
+                            if (strt == null)
+                            {
+                                appCompany.apis.Add(new AppApiState() { no = $"{x}", applyDesc = $"{applyDesc}", status = -1 });
+                            }
+                            else haveApi.Add(x);
+                        });
+                        sendWhom = new List<string> { "1528783103", "1636016499" };
+                        bizcode = "applyapi";
+
+                        break;
+                    case "audit":
+                        jsonElement.TryGetProperty("isAudit", out JsonElement isAudit);
+                        jsonElement.TryGetProperty("refuseDesc", out JsonElement refuseDesc);
+                        tempApi.ForEach(x =>
+                        {
+                            var temp = appCompany.apis.Find(n => n.no == x);
+                            if (temp != null)
+                            {
+                                AppApiState appApiState = appCompany.apis.Single(a => a.no == x);
+                                if (bool.Parse($"{isAudit}") == true)
+                                {
+                                    appApiState.status = 1;
+                                    appApiState.refuseDesc = null;
+                                }
+                                else
+                                {
+                                    appApiState.status = 0;
+                                    appApiState.refuseDesc = $"{refuseDesc}";
+                                }
+                            }
+                            else haveApi.Add(x);
+                        });
+
+                        sendWhom = new List<string> { "1528783103", "1636016499" };
+                        bizcode = "auditapi";
+
+                        break;
+                    default:
+                        return Ok(new { state = 400, msg = "operate参数错误" });
+                }
+
+                appCompany = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<AppCompany>(appCompany, appCompany.id, new PartitionKey(appCompany.code));
+            }
+            //发送消息
+            var location = _option.Location;
+            Notification notification = new()
+            {
+                hubName = bizcode,
+                type = "msg",
+                from = $"BI:{_option.Location}:private",
+                to = sendWhom,
+                label = $"{bizcode}-appCompany",
+                body = new { location = location, biz = bizcode, appid = appCompany.id, appName = appCompany.name, status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
+            };
+
+            var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
+            var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+            var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");         
+            await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //站内发送消息
+
+            if (haveApi.Count > 0)
+                return Ok(new { state = 201, haveApi , appCompany});
+            else return Ok(new { state = 200, appCompany });
+        }
+
+        /// <summary>
+        /// 应用申请学校
+        /// 应用审核申请的学校
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-auditschool")]
+        public async Task<IActionResult> SetAuditSchool(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("appId", out JsonElement appId)) return BadRequest();
+            if (!jsonElement.TryGetProperty("appCode", out JsonElement appCode)) return BadRequest();
+            if (!jsonElement.TryGetProperty("schooCode", out JsonElement schooCode)) return BadRequest();
+            if(!jsonElement.TryGetProperty("operate", out JsonElement operate)) return BadRequest();
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            List<string> haveSchool = new();
+            List<string> sendWhom = new();//消息分发给谁   待完善
+            string bizcode = "";  //消息名称
+
+            AppCompany appCompany = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemAsync<AppCompany>($"{appId}", new PartitionKey($"{appCode}"));
+            if (appCompany != null) 
+            {
+                switch (operate.GetString())
+                {
+                    case "apply":
+                        var aSchool = appCompany.schools.Find(x => x.id.Equals($"{schooCode}"));
+                        if (aSchool == null)
+                        {
+                            jsonElement.TryGetProperty("name", out JsonElement name);
+                            jsonElement.TryGetProperty("picture", out JsonElement picture);
+                            appCompany.schools.Add(new ApplySchool() { id = $"{schooCode}", name = $"{name}", picture = $"{picture}" });
+                        }
+                        else haveSchool.Add(schooCode.GetString());
+                        sendWhom = new List<string> { "1528783103", "1636016499" };
+                        bizcode = "applyschool";
+
+                        break;
+                    case "audit":
+                        jsonElement.TryGetProperty("isAudit", out JsonElement isAudit);
+                        jsonElement.TryGetProperty("refuseDesc", out JsonElement refuseDesc);
+                        var applySchool = appCompany.schools.Find(x => x.id.Equals($"{schooCode}"));
+                        if (applySchool != null)
+                        {
+                            if (bool.Parse($"{isAudit}") == true)
+                            {
+                                applySchool.status = 1;
+                                applySchool.refuseDesc = null;
+                            }
+                            else
+                            {
+                                applySchool.status = 0;
+                                applySchool.refuseDesc = $"{refuseDesc}";
+                            }
+                        }
+                        else haveSchool.Add(schooCode.GetString());
+                        sendWhom = new List<string> { "1528783103", "1636016499" };
+                        bizcode = "auditschool";
+
+                        break;
+                    default:
+                        return Ok(new { state = 400, msg = "operate参数错误" });
+                }
+
+                appCompany = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<AppCompany>(appCompany, appCompany.id, new PartitionKey(appCompany.code));
+            }
+            else return Ok(new { state = 404, msg = "未找到该应用" });
+
+            //发送消息
+            var location = _option.Location;
+            Notification notification = new()
+            {
+                hubName = bizcode,
+                type = "msg",
+                from = $"BI:{_option.Location}:private",
+                to = sendWhom,
+                label = $"{bizcode}-appCompany",
+                body = new { location = location, biz = bizcode, appid = appCompany.id, appName = appCompany.name, status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
+            };
+
+            var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
+            var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+            var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
+            await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //站内发送消息
+
+            return Ok(new { state = 200 , appCompany });
+        }
+
+        public record AppIdOrCode 
+        {
+            public string id { get; set; }
+            public string code { get; set; }
+        }
+
+        /// <summary>
+        /// 显示应用
+        /// </summary>
+        public record ReadCompany
+        {
+            public string id { get; set; }
+            public string pk { get; set; }
+            public string code { get; set; }
+            public string name { get; set; }
+            public string descr { get; set; }
+            public string picture { get; set; }
+            public string jwtKey { get; set; }
+            public int status { get; set; }
+            public int audit { get; set; }
+            public string refuseDesc { get; set; }
+            public string gateways { get; set; }
+            public List<AppApiState> apis { get; set; }
+            public string webhookDomain { get; set; }
+            public List<WebHookState> webHooks { get; set; }
+            public List<ApplySchool> schools { get; set; }
+        }
+
+    }
+}

+ 135 - 0
TEAMModelBI/Controllers/BINormal/BIOpenApiController.cs

@@ -0,0 +1,135 @@
+using Azure.Cosmos;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+
+namespace TEAMModelBI.Controllers.BINormal
+{
+    [Route("openapi")]
+    [ApiController]
+    public class BIOpenApiController : ControllerBase
+    {
+        public readonly AzureCosmosFactory _azureCosmos;
+        public readonly AzureStorageFactory _azureStorage;
+        public readonly DingDing _dingDing;
+        public readonly Option _option;
+
+        public BIOpenApiController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option) 
+        {
+            _azureCosmos = azureCosmos;
+            _azureStorage = azureStorage;
+            _dingDing = dingDing;
+            _option = option?.Value;        
+        }
+
+        /// <summary>
+        /// 查询所有开放API列表
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-infos")]
+        public async Task<IActionResult> GetOpenApi(JsonElement jsonElement) 
+        {
+            jsonElement.TryGetProperty("id", out JsonElement id);
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            StringBuilder sqlTxt = new("select c.id,c.code,c.pk,c.name,c.rw,c.method,c.url,c.descr,c.type,c.descrUrl,c.createTime from c where c.pk='Api' ");
+            if (!string.IsNullOrEmpty($"{id}")) 
+            {
+                sqlTxt.Append($" and c.id='{id}'");
+            }
+
+            List<ReadApi> openApis = new();
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryStreamIterator(queryText:sqlTxt.ToString(),requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Api")}))
+            {
+                using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt32() > 0) 
+                {
+                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        ReadApi readApi = new()
+                        {
+                            id = obj.GetProperty("id").GetString(),
+                            pk = obj.GetProperty("pk").GetString(),
+                            code = obj.GetProperty("code").GetString(),
+                            name = obj.GetProperty("name").GetString(),
+                            rw = obj.GetProperty("rw").GetString(),
+                            method= obj.GetProperty("method").GetString(),
+                            url = obj.GetProperty("url").GetString(),
+                            descr = obj.GetProperty("descr").GetString(),
+                            type = obj.GetProperty("type").GetInt32(),
+                            descrUrl=obj.GetProperty("descrUrl").GetString(),
+                            createTime = obj.GetProperty("createTime").GetInt64()
+                        };
+                        openApis.Add(readApi);
+                    }
+                }
+            }
+
+            return Ok(new { state = 200, openApis });
+        }
+
+        /// <summary>
+        /// 新增和修改Api信息
+        /// </summary>
+        /// <param name="openApi"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-api")]
+        public async Task<IActionResult> SetOpenApi(BIOpenApi  openApi) 
+        {
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            if (string.IsNullOrEmpty(openApi.id))
+            {
+                openApi.id = Guid.NewGuid().ToString();
+                openApi.code = "Api";
+                openApi.pk = "Api";
+                openApi.type = string.IsNullOrEmpty($"{openApi.type}") ? openApi.type : 1;
+                openApi.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                openApi = await cosmosClient.GetContainer("TEAMModelOS", "Normal").CreateItemAsync<BIOpenApi>(openApi, new PartitionKey("Api"));
+            }
+            else 
+            {
+                var response = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(openApi.id, new PartitionKey("Api"));
+                if (response.Status == 200)
+                {
+                    openApi.ttl = -1;
+                    openApi.pk = "Api";
+                    openApi.code = "Api";
+                    openApi = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<BIOpenApi>(openApi, openApi.id, new PartitionKey("Api"));
+                }
+                else return Ok(new { state = 404, msg = "未找到该id相关的Api信息" });
+            }
+
+            return Ok(new { state = 200 , openApi });
+        }
+
+
+
+
+
+        public record ReadApi
+        {
+            public string id { get; set; }
+            public string code { get; set; }
+            public string pk { get; set; }
+            public string name { get; set; }
+            public string rw { get; set; }
+            public string method { get; set; }
+            public string url { get; set; }
+            public string descr { get; set; }
+            public int type { get; set; }
+            public string descrUrl { get; set; }
+            public long createTime { get; set; }
+        }
+
+    }
+}

+ 163 - 0
TEAMModelBI/Controllers/BINormal/CompanyController.cs

@@ -0,0 +1,163 @@
+using Azure.Cosmos;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelBI.Filter;
+using TEAMModelBI.Tool.Extension;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service;
+
+namespace TEAMModelBI.Controllers.BINormal
+{
+    [Route("company")]
+    [ApiController]
+    public class CompanyController : ControllerBase
+    {
+        public readonly AzureCosmosFactory _azureCosmos;
+        public readonly AzureStorageFactory _azureStorage;
+        public readonly DingDing _dingDing;
+        public readonly Option _option;
+        private readonly IWebHostEnvironment _environment; //读取文件
+
+        public CompanyController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, IWebHostEnvironment environment)
+        {
+            _azureCosmos = azureCosmos;
+            _azureStorage = azureStorage;
+            _dingDing = dingDing;
+            _option = option?.Value;
+            _environment = environment;
+        }
+
+        /// <summary>
+        /// 查询企业信息结集合  若传ID查查询该账户的企业信息
+        /// </summary>
+        /// <param name="jsonElenent"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-info")]
+        public async Task<IActionResult> GetInfo(JsonElement jsonElenent)
+        {
+            jsonElenent.TryGetProperty("eid", out JsonElement eid);
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            List<ReadCompany> companys = new();
+            StringBuilder sqlTxt = new("select c.id,c.pk,c.code,c.name,c.credit,c.picture,c.emall,c.mobile,c.password from c");
+            if (!string.IsNullOrEmpty($"{eid}"))
+            {
+                sqlTxt.Append($" where c.id='{eid}'");
+            }
+
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryStreamIterator(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Company") }))
+            {
+                using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        ReadCompany readCompany = new()
+                        {
+                            id= obj.GetProperty("id").GetString(),
+                            pk = obj.GetProperty("pk").GetString(),
+                            code = obj.GetProperty("code").GetString(),
+                            name = obj.GetProperty("name").GetString(),
+                            credit = obj.GetProperty("credit").GetString(),
+                            picture = obj.GetProperty("picture").GetString(),
+                            emall = obj.GetProperty("emall").GetString(),
+                            mobile = obj.GetProperty("mobile").GetString(),
+                        };
+                        companys.Add(readCompany);
+                    }
+                }
+            }
+
+            return Ok(new { state = 200, companys });
+        }
+
+        /// <summary>
+        /// 新增企业信息和修改企业信息
+        /// </summary>
+        /// <param name="appCompany"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-info")]
+        public async Task<IActionResult> SetCompany(Company company)
+        {
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            string salt = Utils.CreatSaltString(8);
+            //新增企业信息
+            if (string.IsNullOrEmpty(company.id))
+            {
+                //company.id = Guid.NewGuid().ToString();
+
+                CreateSchoolInfo createCompanyCode = new CreateSchoolInfo()
+                {
+                    province = "",
+                    id = "",
+                    name = company.name,
+                    city = "",
+                    aname = "",
+                    createCount = 0,
+                };
+
+                //生成企业ID
+                bool tempStaus = true;
+                do {
+                    createCompanyCode = await SchoolCode.GenerateSchoolCode(createCompanyCode, _dingDing, _environment);
+                    var companyState = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"{createCompanyCode.id}", new PartitionKey("Company"));
+                    if (companyState.Status != 200) tempStaus = false;
+                    else createCompanyCode.createCount = createCompanyCode.createCount >= 3 ? createCompanyCode.createCount = 3 : createCompanyCode.createCount += 1;
+                } while (tempStaus);
+
+                if (createCompanyCode.id != null)
+                {
+                    company.id = createCompanyCode.id;
+                    company.code = "Company";
+                    company.salt = salt;
+                    company.password = string.IsNullOrWhiteSpace(company.password) ? Utils.HashedPassword("123456", salt) : Utils.HashedPassword(company.password, salt);//Password,若梦没有则是默认密码:123456
+                    company.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    await cosmosClient.GetContainer("TEAMModelOS", "Normal").CreateItemAsync<Company>(company, new PartitionKey(company.code));
+                }
+            }
+            //修改企业信息
+            else
+            {
+                var respone = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(company.id, new PartitionKey($""));
+                if (respone.Status == 200)
+                {
+                    company.pk = "Company";
+                    company.code = "Company";
+                    company.ttl = -1;
+                    company.salt = salt;
+                    company.password = string.IsNullOrWhiteSpace(company.password) ? Utils.HashedPassword("123456", salt) : Utils.HashedPassword(company.password, salt);//Password,若梦没有则是默认密码:123456
+                    company = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<Company>(company, company.id, new PartitionKey(company.code));
+                }
+                else return Ok(new { state = 404, msg = "未找到该id相关的企业信息" });
+            }
+
+            return Ok(new { state = 200, company });
+        }
+
+        public record ReadCompany
+        {
+            public string id { get; set; }
+            public string pk { get; set; }
+            public string code { get; set; }
+            public string name { get; set; }
+            public string credit { get; set; }
+            public string picture { get; set; }
+            public string emall { get; set; }
+            public string mobile { get; set; }
+        }
+
+
+}
+}

+ 109 - 96
TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs

@@ -137,7 +137,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 if (!jsonElement.TryGetProperty("paramPower", out JsonElement paramPower)) return Ok(new { state = 1, message = "paramPower参数错误!" });
                 
                 var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
-                List<Exist> havepower = new List<Exist>(); //已存在的
+                List<Exist> havepower = new(); //已存在的
                 var client = _azureCosmos.GetCosmosClient();
 
                 StringBuilder stringBuilder = new StringBuilder($"{_tmdName}【{_tmdId}】账户操作:");
@@ -192,7 +192,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 //保存操作记录
                 await _azureStorage.SaveBILog("school-update", stringBuilder?.ToString(), _dingDing, httpContext: HttpContext);
 
-                return Ok(new { state = 200, havepower = havepower });
+                return Ok(new { state = 200, havepower });
             }
             catch (Exception ex)
             {
@@ -389,8 +389,7 @@ namespace TEAMModelBI.Controllers.BISchool
             {
                 jsonElement.TryGetProperty("schoolCode", out JsonElement _schoolCode);
                 var cosmosClient = _azureCosmos.GetCosmosClient();
-                List<School> schools = new List<School>();
-                List<SchoolAssist> schoolAssists = new List<SchoolAssist>();
+                List<SchoolAssist> schoolAssists = new();
                 //StringBuilder stringBuilder = new StringBuilder("select value(c) from c");
                 StringBuilder stringBuilder = new StringBuilder("select c.id,c.code,c.schoolCode,c.name,c.region,c.province,c.city,c.dist,c.size,c.address,c.picture,c.type,c.scale,c.areaId,c.standard from c");
 
@@ -399,99 +398,91 @@ namespace TEAMModelBI.Controllers.BISchool
                     stringBuilder.Append($" where c.id='{_schoolCode}'");
                 }
 
-                await foreach (var itemSchool in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: stringBuilder.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                //await foreach (var itemSchool in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: stringBuilder.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                //{
+                //    SchoolAssist schoolAssist = new()
+                //    {
+                //        id = itemSchool.id,
+                //        code = itemSchool.code,
+                //        schoolCode = itemSchool.schoolCode,
+                //        name = itemSchool.name,
+                //        region = itemSchool.region,
+                //        province = itemSchool.province,
+                //        city = itemSchool.city,
+                //        dist = itemSchool.dist,
+                //        size = itemSchool.size,
+                //        address = itemSchool.address,
+                //        picture = itemSchool.picture,
+                //        type = itemSchool.type,
+                //        scale = itemSchool.scale,
+                //        areaId = itemSchool.areaId,
+                //        standard = itemSchool.standard
+                //    };
+
+                //    var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(itemSchool.id, new PartitionKey("ProductSum"));
+                //    if (response.Status == 200)
+                //    {
+                //        using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                //        schoolAssist.serial = json.RootElement.GetProperty("serial").GetArrayLength();
+                //        schoolAssist.service = json.RootElement.GetProperty("service").GetArrayLength();
+                //        schoolAssist.hard = json.RootElement.GetProperty("hard").GetArrayLength();
+                //    }
+
+                //    schoolAssist.assists = await CommonFind.FindSchoolRoles(cosmosClient, itemSchool.id, "assist");
+
+                //    schoolAssists.Add(schoolAssist);
+                //}
+                //return Ok(new { state = 200, schoolAssists });
+
+                await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
                 {
-                    SchoolAssist schoolAssist = new SchoolAssist()
-                    {
-                        id = itemSchool.id,
-                        code = itemSchool.code,
-                        schoolCode = itemSchool.schoolCode,
-                        name = itemSchool.name,
-                        region = itemSchool.region,
-                        province = itemSchool.province,
-                        city = itemSchool.city,
-                        dist = itemSchool.dist,
-                        size = itemSchool.size,
-                        address = itemSchool.address,
-                        picture = itemSchool.picture,
-                        type = itemSchool.type,
-                        scale = itemSchool.scale,
-                        areaId = itemSchool.areaId,
-                        standard = itemSchool.standard
-                    };
-
-                    var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(itemSchool.id, new PartitionKey("ProductSum"));
-                    if (response.Status == 200)
+                    using var jsonSchool = await JsonDocument.ParseAsync(itemSchool.ContentStream);
+                    foreach (var objSchool in jsonSchool.RootElement.GetProperty("Documents").EnumerateArray())
                     {
-                        using var json = await JsonDocument.ParseAsync(response.ContentStream);
-                        schoolAssist.serial = json.RootElement.GetProperty("serial").GetArrayLength();
-                        schoolAssist.service = json.RootElement.GetProperty("service").GetArrayLength();
-                        schoolAssist.hard = json.RootElement.GetProperty("hard").GetArrayLength();
-
-                        //json.RootElement.TryGetProperty("serial", out JsonElement _serial);
-                        //json.RootElement.TryGetProperty("service", out JsonElement _service);
-                        //json.RootElement.TryGetProperty("hard", out JsonElement _hard);
-                        //schoolAssist.serial = _serial.GetArrayLength();
-                        //schoolAssist.service = _service.GetArrayLength();
-                        //schoolAssist.hard = _hard.GetArrayLength();
-                    }
+                        var schoolId = objSchool.GetProperty("id").GetString();
+                        SchoolAssist schoolAssist = new()
+                        {
+                            id = schoolId,
+                            code = objSchool.GetProperty("code").GetString(),
+                            schoolCode = objSchool.GetProperty("schoolCode").GetString(),
+                            name = objSchool.GetProperty("name").GetString(),
+                            region = objSchool.GetProperty("region").GetString(),
+                            province = objSchool.GetProperty("province").GetString(),
+                            city = objSchool.GetProperty("city").GetString(),
+                            dist = objSchool.GetProperty("dist").GetString(),
+                            size = objSchool.GetProperty("size").GetInt32(),
+                            address = objSchool.GetProperty("address").GetString(),
+                            picture = objSchool.GetProperty("picture").GetString(),
+                            type = objSchool.GetProperty("type").GetInt32(),
+                            //scale = objSchool.GetProperty("scale").GetInt32(),
+                            areaId = objSchool.GetProperty("areaId").GetString(),
+                            standard = objSchool.GetProperty("standard").GetString(),
+                        };
 
-                    schoolAssist.assists = await CommonFind.FindSchoolRoles(cosmosClient, itemSchool.id, "assist");
+                        try { schoolAssist.scale = objSchool.GetProperty("scale").GetInt32(); }
+                        catch { schoolAssist.scale = 0; }
 
-                    schoolAssists.Add(schoolAssist);
-                }
-                return Ok(new { state = 200, schoolAssists });
+                        //var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(schoolId, new PartitionKey("ProductSum"));
+                        //if (response.Status == 200)
+                        //{
+                        //    using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                        //    schoolAssist.serial = json.RootElement.GetProperty("serial").GetArrayLength();
+                        //    schoolAssist.service = json.RootElement.GetProperty("service").GetArrayLength();
+                        //    schoolAssist.hard = json.RootElement.GetProperty("hard").GetArrayLength();
+                        //}
 
-                //await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
-                //{
-                //    using var jsonSchool = await JsonDocument.ParseAsync(itemSchool.ContentStream);
-                //    foreach (var objSchool in jsonSchool.RootElement.GetProperty("Documents").EnumerateArray())
-                //    {
-                //        var schoolId = objSchool.GetProperty("id").GetString();
-                //        SchoolAssist schoolAssist = new SchoolAssist
-                //        {
-                //            id = schoolId,
-                //            code = objSchool.GetProperty("code").GetString(),
-                //            schoolCode = objSchool.GetProperty("schoolCode").GetString(),
-                //            name = objSchool.GetProperty("name").GetString(),
-                //            region = objSchool.GetProperty("region").GetString(),
-                //            province = objSchool.GetProperty("province").GetString(),
-                //            city = objSchool.GetProperty("city").GetString(),
-                //            dist = objSchool.GetProperty("dist").GetString(),
-                //            size = objSchool.GetProperty("size").GetInt32(),
-                //            address = objSchool.GetProperty("address").GetString(),
-                //            picture = objSchool.GetProperty("picture").GetString(),
-                //            type = objSchool.GetProperty("type").GetInt32(),
-                //            //scale = objSchool.GetProperty("scale").GetInt32(),
-                //            areaId = objSchool.GetProperty("areaId").GetString(),
-                //            standard = objSchool.GetProperty("standard").GetString(),
-                //        };
+                        //schoolAssist.assists = await CommonFind.FindSchoolRoles(cosmosClient, schoolId, "assist");
+                        schoolAssists.Add(schoolAssist);
+                    }
+                }
 
-                //        try { schoolAssist.scale = objSchool.GetProperty("scale").GetInt32(); }
-                //        catch { schoolAssist.scale = 0; }
+                List<SchoolAssist> tempSchoolAssists = new();
+                await foreach (var temp in GetSchools(cosmosClient, schoolAssists)) 
+                {
+                    tempSchoolAssists.AddRange(temp);
+                }
 
-                //        var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(schoolId, new PartitionKey("ProductSum"));
-                //        if (response.Status == 200)
-                //        {
-                //            using var json = await JsonDocument.ParseAsync(response.ContentStream);
-                //            schoolAssist.serial = json.RootElement.GetProperty("serial").GetArrayLength();
-                //            schoolAssist.service = json.RootElement.GetProperty("service").GetArrayLength();
-                //            schoolAssist.hard = json.RootElement.GetProperty("hard").GetArrayLength();
-
-                //            //json.RootElement.TryGetProperty("serial", out JsonElement _serial);
-                //            //json.RootElement.TryGetProperty("service", out JsonElement _service);
-                //            //json.RootElement.TryGetProperty("hard", out JsonElement _hard);
-                //            //schoolAssist.serial = _serial.GetArrayLength();
-                //            //schoolAssist.service = _service.GetArrayLength();
-                //            //schoolAssist.hard = _hard.GetArrayLength();
-                //        }
-
-                //        schoolAssist.assists = await CommonFind.FindSchoolRoles(cosmosClient, schoolId, "assist");
-
-                //        schoolAssists.Add(schoolAssist);
-                //    }
-                //}
-                //return Ok(new { state = 200, schoolAssists });
+                return Ok(new { state = 200, schoolAssists = tempSchoolAssists });
 
             }
             catch (Exception ex)
@@ -501,6 +492,33 @@ namespace TEAMModelBI.Controllers.BISchool
             }
         }
 
+        /// <summary>
+        /// 使用yieId 关键字 本地效率未测出
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="schoolAssists"></param>
+        /// <returns></returns>
+        private async IAsyncEnumerable<List<SchoolAssist>> GetSchools(CosmosClient cosmosClient,List<SchoolAssist> schoolAssists)
+        {
+            List<SchoolAssist> tempSchoolAssists = new();
+            foreach (var temp in schoolAssists)
+            {
+                var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(temp.id, new PartitionKey("ProductSum"));
+                if (response.Status == 200)
+                {
+                    using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                    temp.serial = json.RootElement.GetProperty("serial").GetArrayLength();
+                    temp.service = json.RootElement.GetProperty("service").GetArrayLength();
+                    temp.hard = json.RootElement.GetProperty("hard").GetArrayLength();
+                }
+
+                temp.assists = await CommonFind.FindSchoolRoles(cosmosClient, temp.id, "assist");
+                tempSchoolAssists.Add(temp);
+            }
+
+           yield return tempSchoolAssists;
+        }
+
         /// <summary>
         /// 取得学校所有顾问列表
         /// </summary>
@@ -1020,12 +1038,6 @@ namespace TEAMModelBI.Controllers.BISchool
 
         }
 
-        public class Assist
-        {
-            public string tmdId { get; set; }
-            public string tmdName { get; set; }
-        }
-
 
         /// <summary>
         /// 创建多个学校实体
@@ -1101,5 +1113,6 @@ namespace TEAMModelBI.Controllers.BISchool
             public string name { get; set; }
         }
 
+
     }
 }

+ 1 - 2
TEAMModelBI/Controllers/BIStudent/StudentController.cs

@@ -38,10 +38,9 @@ namespace TEAMModelBI.Controllers.BIStudent
         {
             if (!jsonElement.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
             jsonElement.TryGetProperty("code", out JsonElement code);
-
             var cosmosClient = _azureCosmos.GetCosmosClient();
             List<object> objs = new List<object>();
-            await foreach (var item in cosmosClient.GetContainer("", "").GetItemQueryStreamIterator(queryText: $"", requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Student").GetItemQueryStreamIterator(queryText: $"select value(c) from c where c.id='{studentId}'", requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
             {
                 using var json = await JsonDocument.ParseAsync(item.ContentStream);
                 if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetInt16() > 0) 

+ 311 - 43
TEAMModelBI/Controllers/BITest/TestController.cs

@@ -39,6 +39,11 @@ using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
 using System.IdentityModel.Tokens.Jwt;
 using TEAMModelBI.Tool.Extension;
+using System.IO;
+using static TEAMModelBI.Controllers.BISchool.BatchSchoolController;
+using System.Net.Http;
+using System.Net.Http.Json;
+using System.Net;
 
 namespace TEAMModelBI.Controllers.BITest
 {
@@ -53,8 +58,10 @@ namespace TEAMModelBI.Controllers.BITest
         private readonly IWebHostEnvironment _environment; //读取文件
         //读取配置文件
         private readonly IConfiguration _configuration;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly HttpClient _httpClient;
 
-        public TestController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IWebHostEnvironment hostingEnvironment, IConfiguration configuration)
+        public TestController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IWebHostEnvironment hostingEnvironment, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, HttpClient httpClient)
         {
             _azureCosmos = azureCosmos;
             _dingDing = dingDing;
@@ -62,6 +69,8 @@ namespace TEAMModelBI.Controllers.BITest
             _option = option?.Value;
             _environment = hostingEnvironment;
             _configuration = configuration;
+            _coreAPIHttpService = coreAPIHttpService;
+            _httpClient = httpClient;
         }
 
         /// <summary>
@@ -316,6 +325,205 @@ namespace TEAMModelBI.Controllers.BITest
 
         }
 
+        /// <summary>
+        /// 获取在职ID
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("get-onthejob")]
+        public async Task<IActionResult> GetOnTheJob() 
+        {
+
+            string appKey = _configuration["DingDingAuth:appKey"];
+            string appSecret = _configuration["DingDingAuth:appSecret"];
+            string agentld = _configuration["DingDingAuth:Agentld"];
+
+            //获取access_token
+            IDingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
+            OapiGettokenRequest request = new OapiGettokenRequest() { Appkey = appKey, Appsecret = appSecret };
+            request.SetHttpMethod("Get");
+            OapiGettokenResponse response = client.Execute(request);
+            if (response.IsError)
+            {
+                return BadRequest();
+            }
+
+            //access_token的有效期为7200秒(2小时),有效期内重复获取会返回相同结果并自动续期,过期后获取会返回新的access_token
+            string access_token = response.AccessToken;
+
+            //bool vars = false;
+            //long offst = 1;
+            //do
+            //{
+            //    IDingTalkClient jobclient = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/queryonjob");
+            //    OapiSmartworkHrmEmployeeQueryonjobRequest jobreq = new OapiSmartworkHrmEmployeeQueryonjobRequest { StatusList = "2,3,-1", Offset = offst, Size = 50 };   //2:试用期 3:正式 5:待离职 -1:无状态
+            //    OapiSmartworkHrmEmployeeQueryonjobResponse jobrsp = jobclient.Execute(jobreq, access_token);
+
+            //    if (jobrsp.Result.NextCursor > 0)
+            //        offst += 1;
+            //    else vars = true;
+            //} while (vars);
+
+            IDingTalkClient jobclient = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/smartwork/hrm/employee/queryonjob");
+            OapiSmartworkHrmEmployeeQueryonjobRequest jobreq = new OapiSmartworkHrmEmployeeQueryonjobRequest { StatusList = "2,3,-1", Offset = 1, Size = 50 };   //2:试用期 3:正式 5:待离职 -1:无状态
+            OapiSmartworkHrmEmployeeQueryonjobResponse jobrsp = jobclient.Execute(jobreq, access_token);
+            if (jobrsp.SubErrCode == "60011")
+            {
+                return Ok(new { state = 200, msg = jobrsp.SubErrMsg });
+            }
+                foreach (var item in jobrsp.Result.DataList)
+                {
+                    
+                }
+
+            var ser = jobrsp.Result.DataList;  // jobrsp.Body.GetEnumerator("result");
+
+            return Ok(new { state = 200, jobrsp.Body, ser });
+        }
+
+        /// <summary>
+        /// 测试 使用yield 优化
+        /// 依据学校编号查询学校信息;若是没有传学校编号,则查询所有学校信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-schoolsinfo")]
+        public async Task<IActionResult> GetSchoolsInfo(JsonElement jsonElement)
+        {
+            try
+            {
+                jsonElement.TryGetProperty("schoolCode", out JsonElement _schoolCode);
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                List<SchoolAssist> schoolAssists = new();
+                //StringBuilder stringBuilder = new StringBuilder("select value(c) from c");
+                StringBuilder stringBuilder = new StringBuilder("select c.id,c.code,c.schoolCode,c.name,c.region,c.province,c.city,c.dist,c.size,c.address,c.picture,c.type,c.scale,c.areaId,c.standard from c");
+
+                if (!string.IsNullOrEmpty($"{_schoolCode}"))
+                {
+                    stringBuilder.Append($" where c.id='{_schoolCode}'");
+                }
+
+                //await foreach (var itemSchool in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: stringBuilder.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                //{
+                //    SchoolAssist schoolAssist = new()
+                //    {
+                //        id = itemSchool.id,
+                //        code = itemSchool.code,
+                //        schoolCode = itemSchool.schoolCode,
+                //        name = itemSchool.name,
+                //        region = itemSchool.region,
+                //        province = itemSchool.province,
+                //        city = itemSchool.city,
+                //        dist = itemSchool.dist,
+                //        size = itemSchool.size,
+                //        address = itemSchool.address,
+                //        picture = itemSchool.picture,
+                //        type = itemSchool.type,
+                //        scale = itemSchool.scale,
+                //        areaId = itemSchool.areaId,
+                //        standard = itemSchool.standard
+                //    };
+
+                //    var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(itemSchool.id, new PartitionKey("ProductSum"));
+                //    if (response.Status == 200)
+                //    {
+                //        using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                //        schoolAssist.serial = json.RootElement.GetProperty("serial").GetArrayLength();
+                //        schoolAssist.service = json.RootElement.GetProperty("service").GetArrayLength();
+                //        schoolAssist.hard = json.RootElement.GetProperty("hard").GetArrayLength();
+                //    }
+
+                //    schoolAssist.assists = await CommonFind.FindSchoolRoles(cosmosClient, itemSchool.id, "assist");
+
+                //    schoolAssists.Add(schoolAssist);
+                //}
+                //return Ok(new { state = 200, schoolAssists });
+
+                await foreach (var itemSchool in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base") }))
+                {
+                    using var jsonSchool = await JsonDocument.ParseAsync(itemSchool.ContentStream);
+                    foreach (var objSchool in jsonSchool.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        var schoolId = objSchool.GetProperty("id").GetString();
+                        SchoolAssist schoolAssist = new()
+                        {
+                            id = schoolId,
+                            code = objSchool.GetProperty("code").GetString(),
+                            schoolCode = objSchool.GetProperty("schoolCode").GetString(),
+                            name = objSchool.GetProperty("name").GetString(),
+                            region = objSchool.GetProperty("region").GetString(),
+                            province = objSchool.GetProperty("province").GetString(),
+                            city = objSchool.GetProperty("city").GetString(),
+                            dist = objSchool.GetProperty("dist").GetString(),
+                            size = objSchool.GetProperty("size").GetInt32(),
+                            address = objSchool.GetProperty("address").GetString(),
+                            picture = objSchool.GetProperty("picture").GetString(),
+                            type = objSchool.GetProperty("type").GetInt32(),
+                            //scale = objSchool.GetProperty("scale").GetInt32(),
+                            areaId = objSchool.GetProperty("areaId").GetString(),
+                            standard = objSchool.GetProperty("standard").GetString(),
+                        };
+
+                        try { schoolAssist.scale = objSchool.GetProperty("scale").GetInt32(); }
+                        catch { schoolAssist.scale = 0; }
+
+                        //var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(schoolId, new PartitionKey("ProductSum"));
+                        //if (response.Status == 200)
+                        //{
+                        //    using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                        //    schoolAssist.serial = json.RootElement.GetProperty("serial").GetArrayLength();
+                        //    schoolAssist.service = json.RootElement.GetProperty("service").GetArrayLength();
+                        //    schoolAssist.hard = json.RootElement.GetProperty("hard").GetArrayLength();
+                        //}
+
+                        //schoolAssist.assists = await CommonFind.FindSchoolRoles(cosmosClient, schoolId, "assist");
+                        schoolAssists.Add(schoolAssist);
+                    }
+                }
+
+                List<SchoolAssist> tempSchoolAssists = new();
+                await foreach (var temp in GetSchools(cosmosClient, schoolAssists))
+                {
+                    tempSchoolAssists.AddRange(temp);
+                }
+
+                return Ok(new { state = 200, schoolAssists = tempSchoolAssists });
+
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location}  /batchschool/get-schoolsinfo  \n {ex.Message}{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
+        /// <summary>
+        /// 使用yield 优化
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="schoolAssists"></param>
+        /// <returns></returns>
+        private async IAsyncEnumerable<List<SchoolAssist>> GetSchools(CosmosClient cosmosClient, List<SchoolAssist> schoolAssists)
+        {
+            List<SchoolAssist> tempSchoolAssists = new();
+            foreach (var temp in schoolAssists)
+            {
+                var response = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(temp.id, new PartitionKey("ProductSum"));
+                if (response.Status == 200)
+                {
+                    using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                    temp.serial = json.RootElement.GetProperty("serial").GetArrayLength();
+                    temp.service = json.RootElement.GetProperty("service").GetArrayLength();
+                    temp.hard = json.RootElement.GetProperty("hard").GetArrayLength();
+                }
+
+                temp.assists = await CommonFind.FindSchoolRoles(cosmosClient, temp.id, "assist");
+                tempSchoolAssists.Add(temp);
+            }
+
+            yield return tempSchoolAssists;
+        }
+
         /// <summary>
         /// 赋值默认的顾问角色和BI默认的功能权限
         /// </summary>
@@ -696,40 +904,6 @@ namespace TEAMModelBI.Controllers.BITest
             
         }
         
-        /// <summary>
-        /// 测试获取传过来的头部
-        /// </summary>
-        /// <param name="jsonElement"></param>
-        /// <returns></returns>
-        [ProducesDefaultResponseType]
-        [HttpPost("get-xauth")]
-        public async Task<IActionResult> GetXAuth(JsonElement jsonElement) 
-        {
-            string authHeader = this.Request.Headers["Authorization"];//Header中的token
-            string _auth = HttpContext.GetXAuth("AuthToken");
-
-            //var (id, name, pic, did, dname, dpic) = HttpJwtAnalysis.GetAuthTokenInfo(HttpContext);
-
-
-            //var (tmdId, tmdName) = HttpJwtAnalysis.JwtXAuth(_auth, _option);
-            var (tmdId, tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(_auth, _option);
-
-            // var (id, name) = httpXAuth(_auth, _option);
-
-            //string id = null;
-            //string name = null;
-
-            //if (!string.IsNullOrWhiteSpace(_auth) && JwtAuthExtension.ValidateApiToken(_auth, _option.JwtSecretKey))
-            //{
-            //    var jwt = new JwtSecurityTokenHandler().ReadJwtToken(_auth);
-            //    id = jwt.Payload.Sub;
-            //    name = jwt.Claims.FirstOrDefault(claim => claim.Type.Equals("name"))?.Value;
-            //}
-
-            return Ok(new { state = 200, tmdId, tmdName });
-
-        }
-
         /// <summary>
         /// 测试CosmosDB分页查询
         /// </summary>
@@ -760,18 +934,112 @@ namespace TEAMModelBI.Controllers.BITest
             return Ok(new { state = 200, schools });
         }
 
+        /// <summary>
+        /// 测试隐式登录
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost("get-implicit")]
+        public async Task<IActionResult> GetImplicit()
+        {
+            var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+            var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
+
+            var location = _option.Location;
+            if (location.Contains("China"))
+            {
+                location = "China";
+            }
+            else if (location.Contains("Global"))
+            {
+                location = "Global";
+            }
+
+            var token = await CoreTokenExtensions.CreateAccessToken(clientID, clientSecret, location);
+            if (_httpClient.DefaultRequestHeaders.Contains("Authorization"))
+            {
+                _httpClient.DefaultRequestHeaders.Remove("Authorization");
+            }
+
+            _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token.AccessToken}");
+            var url = _configuration.GetValue<string>("HaBookAuth:CoreAPI");
+            url = $"{url}/oauth2/implicit";
+            Dictionary<string, string> data = new()
+            {
+                { "grant_type", "implicit" },
+                { "client_id", clientID },
+                { "account", "1636016499" },
+                { "nonce", Guid.NewGuid().ToString() }
+            };
+
+            HttpResponseMessage responseMessage = await _httpClient.PostAsJsonAsync(url, data);
+            if (responseMessage.StatusCode == HttpStatusCode.OK) //BI连接字符
+            {
+                string content = await responseMessage.Content.ReadAsStringAsync();
+
+
+            }
+
+            return Ok(new { state = 200, token, responseMessage });
+        }
+
+        /// <summary>
+        /// 测试
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
         [HttpPost("get-test")]
-        public async Task<IActionResult> GetTest(JsonElement jsonElement) 
+        public async Task<IActionResult> GetTest(JsonElement jsonElement)
         {
-            if (!jsonElement.TryGetProperty("size", out JsonElement size)) return BadRequest();
-            string temps = GenerateRandom.StrRandom(int.Parse($"{size}"), small:true);
+            List<Test> list1 = new List<Test>();
+            list1.Add(new Test { score = 10, name = "001" });
+            list1.Add(new Test { score = 20, name = "002" });
+            list1.Add(new Test { score = 30, name = "003" });
+            list1.Add(new Test { score = 40, name = "004" });
+            list1.Add(new Test { score = 50, name = "005" });
+            list1.Add(new Test { score = 60, name = "006" });
+
+            List<Test> list2 = new List<Test>();
+            list2.Add(new Test { score = 40, name = "004" });
+            list2.Add(new Test { score = 50, name = "005" });
+            list2.Add(new Test { score = 60, name = "006" });
+            list2.Add(new Test { score = 70, name = "007" });
+            list2.Add(new Test { score = 80, name = "008" });
+            list2.Add(new Test { score = 90, name = "009" });
+            list2.Add(new Test { score = 100, name = "010" });
+
+            //list3 return 2
+            List<Test> list3 = list1.Where(x => !list2.Any(x2 => x.score == x2.score && x.name==x2.name)).ToList();
+            //list4 return 2
+            List<Test> list4 = list1.Where(x => list2.All(x2 => x.score != x2.score)).ToList();
+
+            List<Test> temp = list1.Where(p => !list2.Select(b => b.score).Contains(p.score)).ToList();
+
+            //List<Test> mergedList = new List<Test>(list1);
+            //mergedList.AddRange(list2.Except(list1));
+
+            // var mergedList = list1.Union(list2);
+
+            var en2 = list1.Concat(list2).Except(list1.Intersect(list2));// 容斥原理
+
+            var bingji = list1.Union(list2).ToList();//并(全)集
 
-            RNGCryptoServiceProvider csp = new RNGCryptoServiceProvider();
-            byte[] byteCsp = new byte[int.Parse($"{size}")];
-            csp.GetBytes(byteCsp);
-            string lo = BitConverter.ToString(byteCsp);
+            var cha = bingji.GroupBy(x => x.score).Select(c => c.First()).ToList();
 
-            return Ok(new { state = 200, temps, byteCsp, csp, lo });
+
+            var jiaoji = list1.Intersect(list2).ToList();//交集
+            var chaji = list1.Except(list2).ToList();//差集
+
+            List<Test> have = list1.Where(a => !list2.Exists(t => a.score == t.score)).ToList();
+            have.AddRange(list2.Where(a => !list1.Exists(t => a.score == t.score)).ToList());
+
+            return Ok(new { state = 200, have,  en2, bingji, cha, jiaoji, chaji, list3, list4, temp, list1 });
+        }
+
+        public class Test
+        {
+            public int age { get; set; }
+            public string name { get; set; }
+            public int score { get; set; }
         }
 
         public class strend

+ 9 - 9
TEAMModelBI/Controllers/DingDingStruc/TableDingDingInfoController.cs

@@ -56,7 +56,7 @@ namespace TEAMModelBI.Controllers.DingDingStruc
         /// </summary>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-        //[AuthToken(Roles = "assist")]
+        [AuthToken(Roles = "assist")]
         [HttpPost("get-dingdingusers")]
         public async Task<IActionResult> GetDingDingUser(JsonElement jsonElement)
         {
@@ -164,14 +164,14 @@ namespace TEAMModelBI.Controllers.DingDingStruc
 
                 var tempddUserInfos = ddUserInfos.GroupBy(c => c.RowKey).Select(c => c.First()).ToList();//去重
                 //List<DingDingUserInfo> TempdingDingUserInfos = await _azureStorage.SaveOrUpdateAll(dingDingUserInfos);  //只是保存至Table
-                ////待测试验证嘛
-                //var users = await table.FindListByDict<DingDingUserInfo>(new Dictionary<string, object> { { "PartitionKey", $"{divide}" } });
-                //var stet = users.Where(c => !tempddUserInfos.Contains(c));
-                //var temp = users.Union(tempddUserInfos).Except(users.Intersect(tempddUserInfos));
-                //return Ok(new { state = 200 });
-
-                List<DingDingUserInfo> TempdingDingUserInfos = await table.SaveOrUpdateAll(tempddUserInfos);  //保存和修改至Table
-                return Ok(new { state = 200, UserInfo = TempdingDingUserInfos });
+                //查询数据的数据 并和钉钉查询的数据对比,找出不同的数据,并删除  待后期测试
+                var users = await table.FindListByDict<DingDingUserInfo>(new Dictionary<string, object> { { "PartitionKey", $"{divide}" } });
+                List<DingDingUserInfo> existsUserInfo = users.Where(u => !tempddUserInfos.Exists(e => u.RowKey.Equals(e.RowKey) && u.PartitionKey.Equals(e.PartitionKey))).ToList();
+                existsUserInfo.AddRange(tempddUserInfos.Where(e => !users.Exists(u => e.RowKey.Equals(u.RowKey) && e.PartitionKey.Equals(u.PartitionKey))).ToList());
+                var noExisits = await table.DeleteAll(existsUserInfo);
+
+                List<DingDingUserInfo> UserInfo = await table.SaveOrUpdateAll(tempddUserInfos);  //保存和修改至Table
+                return Ok(new { state = 200, UserInfo, noExisits });
             }
             catch (Exception ex)
             {

+ 113 - 6
TEAMModelBI/Controllers/LoginController.cs

@@ -32,6 +32,7 @@ using System.Net.Http.Json;
 using TEAMModelBI.Filter;
 using TEAMModelBI.Models.Extension;
 using TEAMModelOS.SDK;
+using Microsoft.AspNetCore.Hosting;
 //using static DingTalk.Api.Response.OapiV2UserGetResponse;
 
 namespace TEAMModelBI.Controllers
@@ -53,10 +54,11 @@ namespace TEAMModelBI.Controllers
         //隐式登录
         private readonly CoreAPIHttpService _aoreAPIHttpService;
         private readonly IHttpClientFactory _http;
+        private readonly IWebHostEnvironment _environment; //读取文件
 
         string type = "ddteammodel";
 
-        public LoginController(IConfiguration configuration, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, CoreAPIHttpService aoreAPIHttpService, IHttpClientFactory http)
+        public LoginController(IConfiguration configuration, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, CoreAPIHttpService aoreAPIHttpService, IHttpClientFactory http, IWebHostEnvironment environment)
         {
             _configuration = configuration;
             _azureCosmos = azureCosmos;
@@ -65,6 +67,7 @@ namespace TEAMModelBI.Controllers
             _option = option?.Value;
             _aoreAPIHttpService = aoreAPIHttpService;
             _http = http;
+            _environment = environment;
         }
 
         /// <summary>
@@ -158,7 +161,7 @@ namespace TEAMModelBI.Controllers
                             //id_token = JwtAuthExtension.CreateAuthToken(_option.HostName, item.tmdId?.ToString(), item.tmdName?.ToString(), item.picture?.ToString(), _option.JwtSecretKey, Website: "BI", scope: $"assist", roles: roles?.ToArray(), permissions: permissions?.ToArray(), ddsub: item.RowKey?.ToString());
 
                             //自己写的
-                            id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, item.tmdId?.ToString(), item.tmdName?.ToString(), item.picture?.ToString(), item.RowKey?.ToString(), item.name?.ToString(), item.avatar?.ToString(), _option.JwtSecretKey, scope: "assist", Website: "BI", roles: roles?.ToArray(), permissions: permissions?.ToArray(), expire: 3);
+                            id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, item.tmdId?.ToString(), item.tmdName?.ToString(), item.picture?.ToString(), _option.JwtSecretKey, scope: "assist", Website: "BI", item.RowKey?.ToString(), item.name?.ToString(), item.avatar?.ToString(), roles: roles?.ToArray(), permissions: permissions?.ToArray(), expire: 3);
 
                             (osblob_uri, osblob_sas) = roles.Contains("assist") ? _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete) : _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
                         }
@@ -279,9 +282,9 @@ namespace TEAMModelBI.Controllers
                         roles = !string.IsNullOrEmpty($"{itemUser.roles}") ? new List<string>(itemUser.roles.Split(",")) : new List<string>();
 
                         //保存操作记录
-                        await _azureStorage.SaveBILog("tabledd-update", $"{itemUser.tmdName}【{itemUser.tmdId}】醍摩豆账号和{itemUser.name}【{itemUser.RowKey}】钉钉账户绑定成功", _dingDing, httpContext: HttpContext);
+                        await _azureStorage.SaveBILog("tabledd-update", $"{itemUser.tmdName}【{itemUser.tmdId}】醍摩豆账号和{itemUser.name}【{itemUser.RowKey}】钉钉账户绑定成功", _dingDing, tid: itemUser.tmdId, tname: itemUser.name, twebsite: "BI", httpContext: HttpContext);
 
-                        id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, itemUser.tmdId?.ToString(), itemUser.tmdName?.ToString(), itemUser.picture?.ToString(), itemUser.RowKey?.ToString(), itemUser.name?.ToString(), itemUser.avatar?.ToString(), _option.JwtSecretKey, scope: "assist", Website: "BI", roles: roles?.ToArray(), permissions: permissions?.ToArray(), expire: 3);
+                        id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, itemUser.tmdId?.ToString(), itemUser.tmdName?.ToString(), itemUser.picture?.ToString(), _option.JwtSecretKey, scope: "assist", Website: "BI", itemUser.RowKey?.ToString(), itemUser.name?.ToString(), itemUser.avatar?.ToString(), roles: roles?.ToArray(), permissions: permissions?.ToArray(), expire: 3);
                     }
                 }
 
@@ -362,7 +365,7 @@ namespace TEAMModelBI.Controllers
                                 ddUserInfos = await table.UpdateAll<DingDingUserInfo>(ddUserInfos);
 
                                 //保存操作记录
-                                await _azureStorage.SaveBILog("tabledd-update", $"{tmdName}【{tmdId}】醍摩豆账号和{itemUser.name}【{itemUser.RowKey}】钉钉账户绑定成功", _dingDing, httpContext: HttpContext);
+                                await _azureStorage.SaveBILog("tabledd-update", $"{tmdName}【{tmdId}】醍摩豆账号和{itemUser.name}【{itemUser.RowKey}】钉钉账户绑定成功", _dingDing, tid: itemUser.tmdId, tname: itemUser.name, twebsite: "BI", httpContext: HttpContext);
                             }
                             else return Ok(new { state = 400, message = "该手机没有注册醍摩豆账号信息" });
                         }
@@ -371,7 +374,7 @@ namespace TEAMModelBI.Controllers
                     ////在IES5 的基础上增加参数
                     //id_token = JwtAuthExtension.CreateAuthToken(_option.HostName, itemUser.tmdId?.ToString(), itemUser.tmdName?.ToString(), itemUser.picture?.ToString(), _option.JwtSecretKey,Website: "BI", scope: $"assist", roles: roles?.ToArray(), permissions: permissions?.ToArray(), ddsub: itemUser.RowKey?.ToString());
                     //自己写的
-                    id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, itemUser.tmdId?.ToString(), itemUser.tmdName?.ToString(), itemUser.picture?.ToString(), itemUser.RowKey?.ToString(), itemUser.name?.ToString(), itemUser.avatar?.ToString(), _option.JwtSecretKey, scope: "assist", Website: "BI", roles: roles?.ToArray(), permissions: permissions?.ToArray(), expire: 3);
+                    id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, itemUser.tmdId?.ToString(), itemUser.tmdName?.ToString(), itemUser.picture?.ToString(), _option.JwtSecretKey, scope: "assist", Website: "BI", itemUser.RowKey?.ToString(), itemUser.name?.ToString(), itemUser.avatar?.ToString(), roles: roles?.ToArray(), permissions: permissions?.ToArray(), expire: 3);
                 }
 
                 var (osblob_uri, osblob_sas) = roles.Contains("assist") ? _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete) : _azureStorage.GetBlobContainerSAS("teammodelos", BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List);
@@ -385,6 +388,110 @@ namespace TEAMModelBI.Controllers
             }
         }
 
+        /// <summary>
+        /// 企业登录
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-commpany")]
+        public async Task<IActionResult> GetCommpanyLogin(JsonElement jsonElement)
+        {
+            if (!jsonElement.TryGetProperty("account", out JsonElement accout)) return BadRequest();
+            if (!jsonElement.TryGetProperty("password", out JsonElement password)) return BadRequest();
+
+            StringBuilder sqlTxt = new($"select value(c) from c");
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            var temps = $"{accout}".Contains($"@");
+            if (temps)
+                sqlTxt.Append($" where c.emall='{accout}'");
+            else
+                sqlTxt.Append($" where c.mobile='{accout}'");
+
+            Company company = new();
+            List<Company> companies = new();
+            string id_token = "";
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryIterator<Company>(queryText: sqlTxt.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Company") })) 
+            {
+                companies.Add(item);
+            }
+            if (companies.Count > 0)
+            {
+                foreach (var item in companies)
+                {
+                    var hashedPw = Utils.HashedPassword(password.ToString(), item.salt.ToString());
+                    if (hashedPw.Equals(item.password))
+                    {
+                        company = item;
+                        id_token = JwtAuth.CreateAuthTokenBI(_option.HostName, item.id?.ToString(), item.name?.ToString(), company.picture?.ToString(), _option.JwtSecretKey, scope: "company", Website: "BI", expire: 3);
+                    }
+                }
+            }
+            else return Ok(new { state = 404 });
+
+            //保存操作记录
+            await _azureStorage.SaveBILog("tabledd-update", $"{company.name}【{company.id}】登录商务智能开放平台", _dingDing, tid: company.id, tname: company.name, twebsite: "BI", httpContext: HttpContext);
+
+            return Ok(new { error = 200, id_token, company });
+        }
+
+        /// <summary>
+        /// 企业注册信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [HttpPost("set-registered")]
+        public async Task<IActionResult> SetRegistered(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("name", out JsonElement name)) return BadRequest();
+            if (!jsonElement.TryGetProperty("credit", out JsonElement credit)) return BadRequest();
+            if (!jsonElement.TryGetProperty("mobile", out JsonElement mobile)) return BadRequest();
+            if (!jsonElement.TryGetProperty("password", out JsonElement password)) return BadRequest();
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            string salt = Utils.CreatSaltString(8);
+
+            string sqltxt = $"select value(c) from c where c.mobile='{mobile}'";
+            await foreach (var item in  cosmosClient.GetContainer("TEAMModelOS", "Normal").GetItemQueryStreamIterator(queryText: sqltxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Company") }))
+            {
+                using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    return Ok(new { state = 201, msg = "手机号已存在," });
+                }
+            }
+
+            CreateSchoolInfo createCompanyCode = new CreateSchoolInfo()
+            {
+                province = "",
+                id = "",
+                name = $"{name}",
+                city = "",
+                aname = "",
+                createCount = 0,
+            };
+
+            //生成企业ID
+            bool tempStaus = true;
+            do
+            {
+                createCompanyCode = await SchoolCode.GenerateSchoolCode(createCompanyCode, _dingDing, _environment);
+                var companyState = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"{createCompanyCode.id}", new PartitionKey("Company"));
+                if (companyState.Status != 200) tempStaus = false;
+                else createCompanyCode.createCount = createCompanyCode.createCount >= 3 ? createCompanyCode.createCount = 3 : createCompanyCode.createCount += 1;
+            } while (tempStaus);
+
+            Company company = new() { name = $"{name}", credit = $"{credit}", mobile = $"{mobile}", salt = salt, password = Utils.HashedPassword($"{password}", salt), pk = "Company", code = "Company", createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() };
+
+            company = await cosmosClient.GetContainer("TEAMModelOS", "Normal").CreateItemAsync<Company>(company, new PartitionKey("Company"));
+
+            //保存操作记录
+            await _azureStorage.SaveBILog("tabledd-update", $"{company.name}【{company.id}】注册商务智能开放平台", _dingDing, tid: company.id, tname: company.name, twebsite: "BI", httpContext: HttpContext);
+
+            return Ok(new { state = 200, company });
+        }
+
+
         public record DingDingbinds
         {
             public string type { get; set; }

+ 0 - 1
TEAMModelBI/TEAMModelBI.csproj

@@ -27,7 +27,6 @@
 	</ItemGroup>
 
 	<ItemGroup>
-		<Folder Include="Controllers\Normal\" />
 		<Folder Include="wwwroot\" />
 	</ItemGroup>
 	<PropertyGroup>

+ 23 - 27
TEAMModelBI/Tool/Extension/GenerateRandom.cs

@@ -2,6 +2,7 @@
 using System.Linq;
 using System.Security.Cryptography;
 using System.Text;
+using System.Threading;
 
 namespace TEAMModelBI.Tool.Extension
 {
@@ -19,8 +20,7 @@ namespace TEAMModelBI.Tool.Extension
         /// <returns></returns>
         public static string Number(int Length, bool Sleep = false)
         {
-            if (Sleep)
-                System.Threading.Thread.Sleep(3);
+            if (Sleep) Thread.Sleep(3);
             string result = "";
             Random random = new Random();
             for (int i = 0; i < Length; i++)
@@ -38,15 +38,14 @@ namespace TEAMModelBI.Tool.Extension
         /// <returns></returns>
         public static string StrNumberUpeper(int Length, bool Sleep = false)
         {
-            if (Sleep) System.Threading.Thread.Sleep(3);
+            if (Sleep) Thread.Sleep(3);
             var numUpper = ch_Number.Concat(ch_Upper).ToArray();
-            StringBuilder result = new StringBuilder();
-            int n = numUpper.Length;
-            Random random = new Random(~unchecked((int)DateTime.Now.Ticks));
+            StringBuilder result = new();
+            int l = numUpper.Length;
+            Random random = new(~unchecked((int)DateTime.Now.Ticks));
             for (int i = 0; i < Length; i++)
             {
-                int rnd = random.Next(0, n);
-                result.Append(numUpper[rnd]);
+                result.Append(numUpper[random.Next(0, l)]);
             }
             return result.ToString();
         }
@@ -59,14 +58,13 @@ namespace TEAMModelBI.Tool.Extension
         /// <returns></returns>
         public static string StrLower(int length, bool sleep = false)
         {
-            if (sleep) System.Threading.Thread.Sleep(3);
-            StringBuilder result = new StringBuilder();
-            int n = ch_Lower.Length;
-            Random random = new Random(~unchecked((int)DateTime.Now.Ticks));
+            if (sleep) Thread.Sleep(3);
+            StringBuilder result = new();
+            int l = ch_Lower.Length;
+            Random random = new(~unchecked((int)DateTime.Now.Ticks));
             for (int i = 0; i < length; i++)
             {
-                int rnd = random.Next(0, n);
-                result.Append(ch_Lower[rnd]);
+                result.Append(ch_Lower[random.Next(0, l)]);
             }
 
             return result.ToString();
@@ -80,16 +78,15 @@ namespace TEAMModelBI.Tool.Extension
         /// <returns></returns>
         public static string StrAll(int length, bool sleep = false)
         {
-            if (sleep) System.Threading.Thread.Sleep(3);
-            StringBuilder result = new StringBuilder();
+            if (sleep) Thread.Sleep(3);
+            StringBuilder result = new();
             var temp = ch_Number.Concat(ch_Upper).ToArray();
             var allchar = ch_Number.Concat(temp).ToArray();
             int l = allchar.Length;
-            Random random = new Random(~unchecked((int)DateTime.Now.Ticks));
-            for (int i = 0; i < length; i++) 
+            Random random = new(~unchecked((int)DateTime.Now.Ticks));
+            for (int i = 0; i < length; i++)
             {
-                int rnd = random.Next(0, l);
-                result.Append(allchar[rnd]);
+                result.Append(allchar[random.Next(0, l)]);
             }
 
             return result.ToString();
@@ -105,19 +102,18 @@ namespace TEAMModelBI.Tool.Extension
         /// <returns></returns>
         public static string StrRandom(int length, bool sleep = false, bool large = false, bool small = false)
         {
-            if (sleep) System.Threading.Thread.Sleep(3);
+            if (sleep) Thread.Sleep(3);
             char[] ch = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
 
-            if (large == true) { ch = ch.Concat(ch_Upper).ToArray(); }
-            if (small == true) { ch = ch.Concat(ch_Lower).ToArray(); }
+            if (large == true) ch = ch.Concat(ch_Upper).ToArray();
+            if (small == true) ch = ch.Concat(ch_Lower).ToArray();
 
-            StringBuilder result = new StringBuilder();
+            StringBuilder result = new();
             int l = ch.Length;
-            Random random = new Random(~unchecked((int)DateTime.Now.Ticks));
+            Random random = new(~unchecked((int)DateTime.Now.Ticks));
             for (int i = 0; i < length; i++)
             {
-                int rnd = random.Next(0, l);
-                result.Append(ch[rnd]);
+                result.Append(ch[random.Next(0, l)]);
             }
 
             return result.ToString();

+ 1 - 2
TEAMModelBI/Tool/Extension/JwtAuth.cs

@@ -26,7 +26,7 @@ namespace TEAMModelBI.Models.Extension
         /// <param name="schools"></param>
         /// <param name="expire">到期时间</param>
         /// <returns></returns>
-        public static string CreateAuthTokenBI(string issuser, string id, string name, string picture, string did, string dname, string dpicture, string salt, string scope, string Website, string unitid = "", string[] roles = null, string[] permissions = null, string[] schools = null, int expire = 1)
+        public static string CreateAuthTokenBI(string issuser, string id, string name, string picture, string salt, string scope, string Website, string did = null, string dname = null, string dpicture = null, string unitid = "", string[] roles = null, string[] permissions = null, int expire = 1)
         {
             var payload = new JwtPayload
             {
@@ -41,7 +41,6 @@ namespace TEAMModelBI.Models.Extension
                 { "ddsub",did } ,  //登陆者的钉钉用户id
                 { "ddname",dname } ,  //登陆者的钉钉用户名称
                 { "ddpicture",dpicture },  //登陆者的钉钉用户头像
-                { "schools",schools}, //登陆者的授权
                 { "scope",scope}, //
                 { JwtRegisteredClaimNames.Website,Website}, // 平台站点
             };

+ 10 - 2
TEAMModelOS.FunctionV4/CosmosDB/TriggerCorrect.cs

@@ -30,8 +30,16 @@ namespace TEAMModelOS.FunctionV4
                 await ActivityService.DeleteActivity(_coreAPIHttpService, client, _dingDing, data);
                 var table_cancel = _azureStorage.GetCloudTableClient().GetTableReference("ChangeRecord");
                 List<ChangeRecord> records = await table_cancel.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", tdata.id } });
-                foreach (var record in records) {
-                    await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                foreach (var record in records)
+                {
+                    try
+                    {
+                        await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                    }
+                    catch (Exception)
+                    {
+                        continue;
+                    }
                 }
                 return;
             }

+ 8 - 1
TEAMModelOS.FunctionV4/CosmosDB/TriggerExam.cs

@@ -36,7 +36,14 @@ namespace TEAMModelOS.FunctionV4
                     List<ChangeRecord> records = await table_cancel.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", data.id } });
                     foreach (var record in records)
                     {
-                        await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        try
+                        {
+                            await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        }
+                        catch (Exception)
+                        {
+                            continue;
+                        }
                     }
                     return;
                 }

+ 8 - 1
TEAMModelOS.FunctionV4/CosmosDB/TriggerExamLite.cs

@@ -34,7 +34,14 @@ namespace TEAMModelOS.FunctionV4
                     List<ChangeRecord> records = await table_cancel.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", tdata.id } });
                     foreach (var record in records)
                     {
-                        await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        try
+                        {
+                            await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        }
+                        catch (Exception)
+                        {
+                            continue;
+                        }
                     }
                     return;
                 }

+ 8 - 1
TEAMModelOS.FunctionV4/CosmosDB/TriggerHomework.cs

@@ -34,7 +34,14 @@ namespace TEAMModelOS.FunctionV4
                     List<ChangeRecord> records = await table_cancel.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", tdata.id } });
                     foreach (var record in records)
                     {
-                        await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        try
+                        {
+                            await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        }
+                        catch (Exception)
+                        {
+                            continue;
+                        }
                     }
                     return;
                 }

+ 7 - 1
TEAMModelOS.FunctionV4/CosmosDB/TriggerStudy.cs

@@ -34,7 +34,13 @@ namespace TEAMModelOS.FunctionV4
                     List<ChangeRecord> records = await table_cancel.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", tdata.id } });
                     foreach (var record in records)
                     {
-                        await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        try
+                        {
+                            await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        }
+                        catch (Exception ) {
+                            continue;
+                        }
                     }
                     return;
                 }

+ 8 - 1
TEAMModelOS.FunctionV4/CosmosDB/TriggerSurvey.cs

@@ -42,7 +42,14 @@ namespace TEAMModelOS.FunctionV4
                     List<ChangeRecord> records = await table_cancel.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", tdata.id } });
                     foreach (var record in records)
                     {
-                        await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        try
+                        {
+                            await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        }
+                        catch (Exception)
+                        {
+                            continue;
+                        }
                     }
                     return;
                 }

+ 8 - 1
TEAMModelOS.FunctionV4/CosmosDB/TriggerVote.cs

@@ -39,7 +39,14 @@ namespace TEAMModelOS.FunctionV4
                     List<ChangeRecord> records = await table_cancel.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", tdata.id } });
                     foreach (var record in records)
                     {
-                        await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        try
+                        {
+                            await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), record.sequenceNumber);
+                        }
+                        catch (Exception)
+                        {
+                            continue;
+                        }
                     }
                     return;
                 }

+ 16 - 14
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -969,21 +969,23 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 {
                                     BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/{_lessonId}/IES/base.json").DownloadContentAsync();
                                     LessonBase lessonBase = baseblobDownload.Content.ToObjectFromJson<LessonBase>();
-                                    if (lessonBase != null)
+                                    if (lessonBase != null  && lessonBase.summary!=null)
                                     {
-                                        lessonRecord.attendCount = lessonRecord.attendCount;
-                                        lessonRecord.clientCount = lessonRecord.clientCount;
-                                        lessonRecord.attendRate = lessonRecord.attendRate;
-                                        lessonRecord.groupCount = lessonRecord.groupCount;
-                                        lessonRecord.collateTaskCount = lessonRecord.collateTaskCount;
-                                        lessonRecord.collateCount = lessonRecord.collateCount;
-                                        lessonRecord.pushCount = lessonRecord.pushCount;
-                                        lessonRecord.totalPoint = lessonRecord.totalPoint;
-                                        lessonRecord.examQuizCount = lessonRecord.examQuizCount;
-                                        lessonRecord.interactionCount = lessonRecord.interactionCount;
-                                        lessonRecord.examPointRate = lessonRecord.examPointRate;
-                                        lessonRecord.clientInteractionCount = lessonRecord.clientInteractionCount;
-                                        lessonRecord.clientInteractionAverge = lessonRecord.clientInteractionAverge;
+                                        lessonRecord.attendCount = lessonBase.summary.attendCount;
+                                        lessonRecord.clientCount = lessonBase.summary.clientCount;
+                                        lessonRecord.attendRate = lessonBase.summary.attendRate;
+                                        lessonRecord.groupCount = lessonBase.summary.groupCount;
+                                        lessonRecord.collateTaskCount = lessonBase.summary.collateTaskCount;
+                                        lessonRecord.collateCount = lessonBase.summary.collateCount;
+                                        lessonRecord.pushCount = lessonBase.summary.pushCount;
+                                        lessonRecord.totalPoint = lessonBase.summary.totalPoint;
+                                        lessonRecord.examQuizCount = lessonBase.summary.examQuizCount;
+                                        lessonRecord.interactionCount = lessonBase.summary.interactionCount;
+                                        lessonRecord.examPointRate = lessonBase.summary.examPointRate;
+                                        lessonRecord.clientInteractionCount = lessonBase.summary.clientInteractionCount;
+                                        lessonRecord.clientInteractionAverge = lessonBase.summary.clientInteractionAverge;
+                                        lessonRecord.examCount = lessonBase.summary.examCount;
+                                        lessonRecord.totalInteractPoint = lessonBase.summary.totalInteractPoint;
                                     }
                                     msgs.Add(update);
                                 }

+ 7 - 8
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs

@@ -406,24 +406,23 @@ namespace TEAMModelOS.SDK.DI
         /// <param name="option"></param>
         /// <param name="httpContext"></param>
         /// <returns></returns>
-        public static async Task SaveBILog(this AzureStorageFactory azureStorage, string type, string msg, DingDing dingDing, string scope = null, Option option = null, HttpContext httpContext = null)
+        public static async Task SaveBILog(this AzureStorageFactory azureStorage, string type, string msg, DingDing dingDing, string tid = null, string tname = null, string twebsite = null, string scope = null, Option option = null, HttpContext httpContext = null)
         {
             var table = azureStorage.GetCloudTableClient().GetTableReference("BIOptLog");
             BIOptLog biLog = new() { RowKey = Guid.NewGuid().ToString() };
             try
             {
-                object id = null, name = null, ddid = null, ddname = null, school = null, website = null;
+                object id = null, name = null, ddid = null, ddname = null, website = null;
                 httpContext?.Items.TryGetValue("ID", out id);
                 httpContext?.Items.TryGetValue("Name", out name);
                 httpContext?.Items.TryGetValue("DDId", out ddid);
                 httpContext?.Items.TryGetValue("DDName", out ddname);
-                httpContext?.Items.TryGetValue("School", out school);
                 httpContext?.Items.TryGetValue("Website", out website);
-                biLog.tmdId = id != null ? $"{id}" : biLog.tmdId;
-                biLog.name = name != null ? $"{name}" : biLog.name;
-                biLog.school = school != null ? $"{school}" : biLog.school;
-                biLog.PartitionKey = type != null ? $"{website}-Log-{type}" : $"{website}-Log-Default";
-                biLog.platform = website != null ? $"{website}" : "Default";
+                string site = twebsite != null ? twebsite : $"{website}";
+                biLog.tmdId = id != null ? $"{id}" : tid;
+                biLog.name = name != null ? $"{name}" : tname;
+                biLog.PartitionKey = type != null ? $"{site}-Log-{type}" : $"{site}-Log-Default";
+                biLog.platform = site != null ? site : "Default";
                 biLog.msg = msg;
                 biLog.type = type;
                 biLog.scope = scope;

+ 253 - 0
TEAMModelOS.SDK/Models/Cosmos/BI/AppCompany.cs

@@ -0,0 +1,253 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.BI
+{
+    /// <summary>
+    /// 应用基础
+    /// </summary>
+    public class AppBase : CosmosEntity
+    {
+        public AppBase()
+        {
+            pk = "App";
+        }
+
+        /// <summary>
+        /// 应用名称
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string name { get; set; }
+
+        /// <summary>
+        /// 应用类型
+        /// </summary>
+        public int type { get; set; }
+
+        /// <summary>
+        /// 应用描述
+        /// </summary>
+        public string descr { get; set; }
+
+        /// <summary>
+        /// 应用图标
+        /// </summary>
+        public string picture { get; set; }
+
+        /// <summary>
+        /// 应用秘钥
+        /// </summary>
+        public string jwtKey { get; set; }
+
+        /// <summary>
+        /// 应用状态   -1内测中,0已下架,1已上架
+        /// </summary>
+        public int status { get; set; }
+
+        /// <summary>
+        /// 应用到期时间
+        /// </summary>
+        public long expiresTime { get; set; }
+
+        /// <summary>
+        /// 应用创建时间
+        /// </summary>
+        public long createTime { get; set; }
+    }
+
+    /// <summary>
+    /// 企业应用
+    /// </summary>
+    public class AppCompany : AppBase
+    {
+        /// <summary>
+        /// 应用审核状态 -1待审核,0审核被拒绝,1审核通过   
+        /// </summary>
+        public int audit { get; set; }
+
+        /// <summary>
+        /// 应用审核状态描述
+        /// </summary>
+        public string refuseDesc { get; set; }
+
+        /// <summary>
+        /// 应用的回调网关
+        /// </summary>
+        public string gateways { get; set; }
+
+        /// <summary>
+        /// 开放接口申请状态
+        /// </summary>
+        public List<AppApiState> apis { get; set; } = new List<AppApiState>();
+
+        /// <summary>
+        /// 企业默认的通知回调地址
+        /// </summary>
+        public string webhookDomain { get; set; }
+
+        /// <summary>
+        /// 开放平台 通知回调地址
+        /// </summary>
+        public List<WebHookState> webHooks { get; set; } = new List<WebHookState>();
+
+        /// <summary>
+        /// 开放学校
+        /// </summary>
+        public List<ApplySchool> schools { get; set; } = new List<ApplySchool>();
+    }
+
+    /// <summary>
+    /// 开发接口状态
+    /// </summary>
+    public class AppApiState
+    {
+        /// <summary>
+        /// 接口编号
+        /// </summary>
+        public string no { get; set; }
+        /// <summary>
+        /// 申请原因描述
+        /// </summary>
+        public string applyDesc { get; set; }
+
+        /// <summary>
+        /// 审核状态 -1待审核,0审核被拒绝,1审核通过
+        /// </summary>
+        public int status { get; set; }
+
+        /// <summary>
+        /// 审核拒绝原因
+        /// </summary>
+        public string refuseDesc { get; set; }
+    }
+
+    /// <summary>
+    /// 消息回调地址
+    /// </summary>
+    public class WebHookState
+    {
+        /// <summary>
+        /// 编号
+        /// </summary>
+        public string no { get; set; }
+        /// <summary>
+        /// 接口名
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 申请原因描述
+        /// </summary>
+        public string applyDesc { get; set; }
+        /// <summary>
+        /// 审核状态  -1待审核,0审核被拒绝,1审核通过
+        /// </summary>
+        public int status { get; set; }
+
+        /// <summary>
+        /// 审核拒绝原因
+        /// </summary>
+        public string refuseDesc   { get; set; }
+    }
+
+    /// <summary>
+    /// 开放学校
+    /// </summary>
+    public class ApplySchool 
+    {
+        public string id { get; set; }
+
+        public string name { get; set; }
+
+        public string picture { get; set; }
+
+        /// <summary>
+        /// 审核状态 -1待审核,0审核被拒绝,1审核通过
+        /// </summary>
+        public int status { get; set; } = -1;
+        /// <summary>
+        /// 审核拒绝原因
+        /// </summary>
+        public string refuseDesc { get; set; }
+    }
+
+    /// <summary>
+    /// 学校应用
+    /// </summary>
+    public class AppSchool : AppBase
+    {
+        /// <summary>
+        /// 企业ID
+        /// </summary>
+        public string eid { get; set; }
+
+        /// <summary>
+        /// 白名单列表
+        /// </summary>
+        public List<string> whitelist { get; set; } 
+
+        /// <summary>
+        /// 企业审核-1学校申请待审核,0学校申请被拒绝,1审核通过,或者邀请学校时,企业默认通过
+        /// </summary>
+        public int eaudit { get; set; }
+
+        /// <summary>
+        /// 企业审核拒绝原因
+        /// </summary>
+        public string erefuseDesc { get; set; }
+
+        /// <summary>
+        /// 学校审核-1被企业邀请,0拒绝邀请,1邀请通过或学校向企业申请,学校默认通过
+        /// </summary>
+        public int saudit { get; set;}
+
+        /// <summary>
+        /// 学校审核拒绝原因
+        /// </summary>
+        public string srefuseDesc { get; set;}
+
+        /// <summary>
+        /// 平台审核-1待审核,0审核被拒绝,1审核通过, 最终  eaudit saudit 都为1 则 paudit=1通过  最终jwtKey 生成 jwt
+        /// </summary>
+        public int paudit { get; set;}
+
+        /// <summary>
+        /// 平台审核拒绝原因
+        /// </summary>
+        public string prefuseDesc { get; set; }
+
+        /// <summary>
+        /// 学校API
+        /// </summary>
+        public List<schoolApi> schoolApis { get; set; }
+
+        /// <summary>
+        /// 开放平台 通知回调地址
+        /// </summary>
+        public List<WebHookState> webHookStates { get; set; }
+
+        /// <summary>
+        /// 企业为学校私有化部署的通知回调地址
+        /// </summary>
+        public string webhookDomain { get; set; }
+    }
+
+    /// <summary>
+    /// 学校应用接口
+    /// </summary>
+    public class schoolApi 
+    {
+        /// <summary>
+        /// 接口编号
+        /// </summary>
+        public string no { get; set; }
+
+        /// <summary>
+        /// 接口名称
+        /// </summary>
+        public string name { get; set; }
+    }
+}

+ 62 - 0
TEAMModelOS.SDK/Models/Cosmos/BI/BIOpenApi.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.BI
+{
+    public class BIOpenApi:CosmosEntity
+    {
+        public BIOpenApi() 
+        {
+            pk = "Api";
+        }
+
+        /// <summary>
+        /// 接口名称
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string name { get; set; }
+
+        /// <summary>
+        /// 接口读写
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string rw { get; set; }
+
+        /// <summary>
+        /// 接口访问类型  get post 
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string method {get; set; }
+
+        /// <summary>
+        /// 接口地址
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string url { get; set; }
+
+        /// <summary>
+        /// 接口描述
+        /// </summary>
+        public string descr { get; set; }
+
+        /// <summary>
+        /// 接口类型  1 api   2 webhook(通知)
+        /// </summary>
+        public int type { get; set; }
+
+        /// <summary>
+        /// 接口文档地址
+        /// </summary>
+        public string descrUrl { get; set; }
+
+        /// <summary>
+        /// 接口创建时间
+        /// </summary>
+        public long createTime { get; set; }
+
+    }
+}

+ 56 - 0
TEAMModelOS.SDK/Models/Cosmos/BI/Company.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.BI
+{
+    public class Company :CosmosEntity
+    {
+        public Company() 
+        {
+            pk = "Company";
+        }
+
+        /// <summary>
+        /// 企业名称
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string name { get; set; }
+
+        /// <summary>
+        /// 统一社会信用代码
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string credit { get; set; }
+
+        /// <summary>
+        /// 企业log
+        /// </summary>
+        public string picture { get; set; }
+
+        /// <summary>
+        /// 企业邮箱
+        /// </summary>
+        public string emall { get; set; }
+
+        /// <summary>
+        /// 联系方式
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string mobile { get; set; }
+
+        /// <summary>
+        /// 密码
+        /// </summary>
+        public string password { get; set; }
+
+        public string salt { get; set; }
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public long createTime { get; set; }
+    }
+}

+ 11 - 2
TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs

@@ -169,6 +169,10 @@ namespace TEAMModelOS.SDK.Models
         /// 学生互动率
         /// </summary>
         public int clientInteractionAverge { get; set; } = 0;
+
+        public int examCount { get; set; }
+        public double totalInteractPoint { get; set; } = 0;
+
     }
     public class LessonTC
     {
@@ -251,8 +255,10 @@ namespace TEAMModelOS.SDK.Models
         /// 
         /// </summary>
         public string endTime { get; set; }
-         
-
+        /// <summary>
+        /// 出席人数
+        /// </summary>
+        public int attendCount { get; set; } = 0;
         /// <summary>
         /// 总人数
         /// </summary>
@@ -269,6 +275,8 @@ namespace TEAMModelOS.SDK.Models
         /// 任务总数,作品收集任务数
         /// </summary>
         public int collateTaskCount { get; set; } = 0;
+
+        public double totalInteractPoint { get; set; } = 0;
         /// <summary>
         /// 作品总数
         /// </summary>
@@ -301,6 +309,7 @@ namespace TEAMModelOS.SDK.Models
         /// 学生互动率
         /// </summary>
         public int clientInteractionAverge { get; set; } = 0;
+        public int examCount { get; set; }
     }
 
     public class QuizSummaryList

文件差異過大導致無法顯示
+ 667 - 582
TEAMModelOS/ClientApp/src/components/homework/BaseHwForm.vue


+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/homework.js

@@ -1,4 +1,6 @@
 export default {
+	notPreview:'該文件暫不支持預覽,請保存活動後重試!',
+	chooseContent:'從站內資源挑選',
 	notFoundData:'未查詢到作答數據',
 	copyAc:'復製活動',
 	modifyAcName:'修改活動名稱',

+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/index.js

@@ -46,6 +46,7 @@ import homework from './homework';
 import researchCenter from './researchCenter';
 import platform from './platform';
 import auth from './auth';
+import lessonRecord from './lessonRecord';
 export default {
   schoolBaseInfo,
   classMgmt,
@@ -95,6 +96,7 @@ export default {
   researchCenter,
   platform,
   auth,
+  lessonRecord,
   test: 'Testing',
   formConfigP: {
     input: 'Please Enter ',

+ 48 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/lessonRecord.js

@@ -0,0 +1,48 @@
+export default {
+	count1:'課堂記錄總數',
+	count2:'教師數',
+	count3:'累計任務數',
+	count4:'累計作品數',
+	count5:'累計測驗總題數',
+	count6:'累計互動總數',
+	count7:'本學期新增課堂記錄數',
+	export:'導出數據',
+	tagMg:'類別管理',
+	tchName:'教師',
+	lessonName:'課堂名稱',
+	lessonNamePlace:'請輸入課例名稱...',
+	grade:'年級',
+	subject:'科目',
+	search:'查詢',
+	reset:'重置',
+	resultTip1:'共查詢到',
+	resultTip2:'條課堂記錄',
+	action1:'下載總表',
+	action2:'預覽筆記',
+	action3:'刪除課例',
+	tagTitle:'課例類別管理',
+	addNewTag:'添加新類別',
+	cancel:'取消',
+	save:'保存變更',
+	className:'班級',
+	date:'日期',
+	attendCount:'出席率',
+	groupCount:'小組數',
+	totalPoint:'總計分',
+	collateTaskCount:'任務總數',
+	collateCount:'作品總數',
+	pushCount:'推送總數',
+	score:'總互動分',
+	interactionCount:'互動題數',
+	clientInteractionCount:'互動總數',
+	examQuizCount:'測驗總題數',
+	examPointRate:'測驗得分率',
+	action:'操作',
+	allTable:'課例數據匯總表',
+	delTip:'確定刪除課堂記錄',
+	delSuc:'刪除成功!',
+	tagTip1:'請將類別填寫完整',
+	tagTip2:'已存在相同類別',
+	tagTip3:'不能存在空類別',
+	saveSuc:'保存成功'
+}

+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/homework.js

@@ -1,4 +1,6 @@
 export default {
+	notPreview:'该文件暂不支持预览,请保存活动后重试!',
+	chooseContent:'从站内资源挑选',
 	notFoundData:'未查询到作答数据',
 	copyAc:'复制活动',
 	modifyAcName:'修改活动名称',

+ 3 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/index.js

@@ -46,6 +46,8 @@ import area from './area';
 import researchCenter from './researchCenter';
 import platform from './platform';
 import auth from './auth';
+import lessonRecord from './lessonRecord';
+
 export default {
   schoolBaseInfo,
   classMgmt,
@@ -95,6 +97,7 @@ export default {
   researchCenter,
   platform,
   auth,
+  lessonRecord,
   test: '测试',
   formConfigP: {
     input: '请输入',

+ 48 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/lessonRecord.js

@@ -0,0 +1,48 @@
+export default {
+	count1:'课堂记录总数',
+	count2:'教师数',
+	count3:'累计任务数',
+	count4:'累计作品数',
+	count5:'累计测验总题数',
+	count6:'累计互动总数',
+	count7:'本学期新增课堂记录数',
+	export:'导出数据',
+	tagMg:'类别管理',
+	tchName:'教师',
+	lessonName:'课堂名称',
+	lessonNamePlace:'请输入课例名称...',
+	grade:'年级',
+	subject:'科目',
+	search:'查询',
+	reset:'重置',
+	resultTip1:'共查询到',
+	resultTip2:'条课堂记录',
+	action1:'下载总表',
+	action2:'预览笔记',
+	action3:'删除课例',
+	tagTitle:'课例类别管理',
+	addNewTag:'添加新类别',
+	cancel:'取消',
+	save:'保存变更',
+	className:'班级',
+	date:'日期',
+	attendCount:'出席率',
+	groupCount:'小组数',
+	totalPoint:'总计分',
+	collateTaskCount:'任务总数',
+	collateCount:'作品总数',
+	pushCount:'推送总数',
+	score:'总互动分',
+	interactionCount:'互动题数',
+	clientInteractionCount:'互动总数',
+	examQuizCount:'测验总题数',
+	examPointRate:'测验得分率',
+	action:'操作',
+	allTable:'课例数据汇总表',
+	delTip:'确定删除课堂记录',
+	delSuc:'删除成功!',
+	tagTip1:'请将类别填写完整',
+	tagTip2:'已存在相同类别',
+	tagTip3:'不能存在空类别',
+	saveSuc:'保存成功'
+}

+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/homework.js

@@ -1,4 +1,6 @@
 export default {
+	notPreview:'該文件暫不支持預覽,請保存活動後重試!',
+	chooseContent:'從站內資源挑選',
 	notFoundData:'未查詢到作答數據',
 	copyAc:'復製活動',
 	modifyAcName:'修改活動名稱',

+ 2 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/index.js

@@ -46,6 +46,7 @@ import homework from './homework';
 import researchCenter from './researchCenter';
 import platform from './platform';
 import auth from './auth';
+import lessonRecord from './lessonRecord';
 export default {
   schoolBaseInfo,
   classMgmt,
@@ -95,6 +96,7 @@ export default {
   researchCenter,
   platform,
   auth,
+  lessonRecord,
   test: '測試',
   formConfigP: {
     input: '請輸入',

+ 48 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/lessonRecord.js

@@ -0,0 +1,48 @@
+export default {
+	count1:'課堂記錄總數',
+	count2:'教師數',
+	count3:'累計任務數',
+	count4:'累計作品數',
+	count5:'累計測驗總題數',
+	count6:'累計互動總數',
+	count7:'本學期新增課堂記錄數',
+	export:'導出數據',
+	tagMg:'類別管理',
+	tchName:'教師',
+	lessonName:'課堂名稱',
+	lessonNamePlace:'請輸入課例名稱...',
+	grade:'年級',
+	subject:'科目',
+	search:'查詢',
+	reset:'重置',
+	resultTip1:'共查詢到',
+	resultTip2:'條課堂記錄',
+	action1:'下載總表',
+	action2:'預覽筆記',
+	action3:'刪除課例',
+	tagTitle:'課例類別管理',
+	addNewTag:'添加新類別',
+	cancel:'取消',
+	save:'保存變更',
+	className:'班級',
+	date:'日期',
+	attendCount:'出席率',
+	groupCount:'小組數',
+	totalPoint:'總計分',
+	collateTaskCount:'任務總數',
+	collateCount:'作品總數',
+	pushCount:'推送總數',
+	score:'總互動分',
+	interactionCount:'互動題數',
+	clientInteractionCount:'互動總數',
+	examQuizCount:'測驗總題數',
+	examPointRate:'測驗得分率',
+	action:'操作',
+	allTable:'課例數據匯總表',
+	delTip:'確定刪除課堂記錄',
+	delSuc:'刪除成功!',
+	tagTip1:'請將類別填寫完整',
+	tagTip2:'已存在相同類別',
+	tagTip3:'不能存在空類別',
+	saveSuc:'保存成功'
+}

+ 2 - 4
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue

@@ -1,4 +1,4 @@
-<template>
+<template>
     <div class="class-record-container">
         <vuescroll ref="pagewrap">
             <div>
@@ -399,9 +399,7 @@ export default {
             this.openImageViewer = false
         },
         goBack() {
-            this.$router.push({
-                path: '/home/myCourse'
-            })
+            this.$router.go(-1)
         },
     },
     computed: {

+ 1 - 1
TEAMModelOS/ClientApp/src/view/evaluation/bank/PaperDownload.vue

@@ -146,7 +146,7 @@
 		},
 		data(vm) {
 			return {
-				curPage:0,
+				curPage:1,
 				curEditType:'',
 				curEditDom:null,
 				myEditor:null,

+ 1 - 1
TEAMModelOS/ClientApp/src/view/evaluation/bank/index.vue

@@ -48,7 +48,7 @@
 					<span
 						style="display: inline-block;margin-bottom: 2px;">{{ $t('evaluation.index.addExercise') }}</span>
 				</span>
-				<span @click="goCreatePaper('import',true)" class="bank-tools-btn" v-show="$access.can('admin.*||exercise-upd')">
+				<span @click="goCreatePaper('import',true)" class="bank-tools-btn" v-show="$access.can('admin.*||exercise-upd') || !isSchool">
 					<Icon type="md-folder" size="16" />
 					<span>{{ $t('evaluation.index.importCreate') }}</span>
 				</span>

+ 74 - 2
TEAMModelOS/ClientApp/src/view/homework/ManageHomeWork.vue

@@ -149,7 +149,7 @@
 				<p class="activity-info-item-content" v-if="currentVote.attachments.length">
 				<p v-for="(item,index) in currentVote.attachments" :key="index">
 					<span class="name"
-						style="display: block;margin: 10px;color: #005CC5;cursor: pointer;font-size: 14px;text-decoration: underline;">{{ item.name }}</span>
+						style="display: block;margin: 10px;color: #005CC5;cursor: pointer;font-size: 14px;text-decoration: underline;" @click="onPreview(item)">{{ item.name }}</span>
 				</p>
 				</p>
 			</div>
@@ -164,6 +164,20 @@
 			</div>
 		</Drawer>
 		
+		<div v-if="previewStatus" class="image-viewer">
+			<div style="width:fit-content;position:relative;margin:auto;">
+				<Icon type="md-close" class="close-icon" @click="previewStatus = false" />
+				<video v-if="previewFile.type == 'video'" id="previewVideo" :src="previewFile.url" width="870"
+					controls="controls" style="max-height: 800px;">
+					{{$t('teachContent.tips8')}}
+				</video>
+				<audio v-else-if="previewFile.type == 'audio'" controls>
+					<source :src="previewFile.url">
+					{{$t('teachContent.notAudio')}}
+				</audio>
+			</div>
+		</div>
+		
 		<!-- 修改活动结束时间 -->
 		<Modal v-model="editTimeStatus" footer-hide className="ed-name-modal">
 		    <div slot="header" class="modal-header">
@@ -210,6 +224,8 @@
 		},
 		data() {
 			return {
+				previewStatus:false,
+				previewFile:null,
 				editTime:null,
 				editTimeStatus:false,
 				editNameStatus:false,
@@ -350,6 +366,28 @@
 			        }
 			    })
 			},
+			/* 预览 */
+			async onPreview(item){
+				console.log(item)
+				let previewFile = this._.cloneDeep(item)
+				let addSasUrl = await this.$tools.getFileSas(item.url)
+				let url = addSasUrl.url
+				previewFile.url = url
+				if (this.getSuffix(item.name) === '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)
+					this.isShowDetail = false
+				}else if(item.type === 'link'){
+					window.open(/^(http:|https:)/i.test(url) ? url : "http://" + url)
+				}else{
+					this.previewFile = previewFile
+					this.previewStatus = true
+					this.isShowDetail = false
+				}
+			},
 			/* 导出表格 */
 			exportTable(){
 				const params = {
@@ -799,6 +837,11 @@
 			        }
 			    }
 			},
+			getSuffix() {
+				return name => {
+					return name.substr(name.lastIndexOf(".") + 1)
+				}
+			}
 		},
 		watch: {
 			$route: {
@@ -813,7 +856,36 @@
 <style lang="less" scoped>
 	@import "../vote/ManageVote.less";
 </style>
-<style>
+<style lang="less">
+	.hw-container .image-viewer {
+		background-color: rgba(0, 0, 0, 0.8);
+		z-index: 9999;
+		width: 100%;
+		height: 100%;
+		position: fixed;
+		top: 0;
+		left: 0;
+		overflow-y: scroll;
+		overflow-x: hidden;
+		text-align: center;
+		/*display: flex;
+	    justify-content: center;
+	    align-items: center;*/
+		padding: 50px;
+		padding-top: 8%;
+	
+		.close-icon {
+			position: absolute;
+			right: -16px;
+			top: -16px;
+			font-size: 24px;
+			color: black;
+			cursor: pointer;
+			border-radius: 50px;
+			background: white;
+			padding: 2px;
+		}
+	}
 	.hw-container .dark-iview-split .ivu-split-trigger {
 		border-color: #dadada !important;
 		background: none;

+ 1 - 2
TEAMModelOS/ClientApp/src/view/jyzx/classMemoir.vue

@@ -350,7 +350,7 @@ export default {
             ).then(
                 res => {
                     console.log(res, '同组数据')
-                    if (res.groupMembers.length != 0) {
+                    if (res.groupMembers) {
                         res.groupMembers.forEach((i) => {
                             i.vtime = this.formatDate(i.vtime)
                             i.vsize = this.formatSize(i.vsize)
@@ -359,7 +359,6 @@ export default {
                     } else {
                         this.$Message.info(this.$t("jyzx.classRecord.message6"))
                     }
-                   
                 },
                 error => {
 

+ 3 - 0
TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.less

@@ -66,6 +66,9 @@
 	}
 	
 	.tools-bar{
+		position: absolute;
+		right: 20px;
+		top:0;
 		display: flex;
 		margin: 20px 0;
 		

+ 148 - 71
TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.vue

@@ -6,69 +6,69 @@
 				<span class="analysis-item-title">{{ item }}</span>
 				<span class="analysis-item-value">{{ analysisCount[index] }}</span>
 			</span>
-			
+		</div>
+		<div class="tools-bar">
+			<!-- <div class="tool-item" @click="onAddVideo">
+				<Icon type="md-add" />
+				<span>添加课例</span>
+			</div> -->
+			<div class="tool-item">
+				<Icon type="md-download" @click="exportTable()"/>
+				<span>{{ $t('lessonRecord.export') }}</span>
+			</div>
+			<div class="tool-item" @click="onTagMgClick">
+				<Icon type="md-settings" />
+				<span>{{ $t('lessonRecord.tagMg') }}</span>
+			</div>
+			<!-- <div class="tool-item">
+				<Icon type="ios-paper-plane" />
+				<span>分享至公开课</span>
+			</div> -->
 		</div>
 		<div class="filter-box">
 			<div style="display: flex;">
 				<div class="filter-item">
-					<span class="filter-item-title">授课教师</span>
+					<span class="filter-item-title">{{ $t('lessonRecord.tchName') }}</span>
 					<!-- <Input v-model="filterJson.tName" placeholder="请输入教师名称..." /> -->
 					<BaseSelectTch @onTchSelect="onTchSelect" ref="tchSelect"></BaseSelectTch>
 				</div>
 				<div class="filter-item">
-					<span class="filter-item-title">课例名称</span>
-					<Input v-model="filterJson.vName" placeholder="请输入课例名称..." />
+					<span class="filter-item-title">{{ $t('lessonRecord.lessonName') }}</span>
+					<Input v-model="filterJson.vName" :placeholder="$t('lessonRecord.lessonNamePlace')" />
 				</div>
 				<div class="filter-item">
-					<span class="filter-item-title">归属年级</span>
+					<span class="filter-item-title">{{ $t('lessonRecord.grade') }}</span>
 					<Select v-model="filterJson.gradeId" clearable>
 						<Option v-for="(item,index) in curPeriod.grades" :value="index + ''" :key="index">{{ item }}
 						</Option>
 					</Select>
 				</div>
 				<div class="filter-item">
-					<span class="filter-item-title">归属科目</span>
+					<span class="filter-item-title">{{ $t('lessonRecord.subject') }}</span>
 					<Select v-model="filterJson.subjectId">
 						<Option v-for="item in curPeriod.subjects" :value="item.id" :key="item.id">{{ item.name }}
 						</Option>
 					</Select>
 				</div>
 				<div class="filter-item">
-					<Button type="primary" shape="circle" @click="doSearch">查询</Button>
-					<Button type="info" shape="circle" @click="doReset">重置</Button>
+					<Button type="primary" shape="circle" @click="doSearch">{{ $t('lessonRecord.search') }}</Button>
+					<Button type="info" shape="circle" @click="doReset">{{ $t('lessonRecord.reset') }}</Button>
 				</div>
 				<div style="margin-right: 10px;">
-					<span>共查询到 <span style="font-size: 18px;font-weight: bold;color: #28b989;">{{ totalNum.count }}
-						</span>条课堂记录</span>
-					<span class="tool-item" style="margin-left: 20px;cursor: pointer;" @click="downloadTable()">
+					<span>{{ $t('lessonRecord.resultTip1') }} <span style="font-size: 18px;font-weight: bold;color: #28b989;">{{ totalNum.count }}
+						</span>{{ $t('lessonRecord.resultTip2') }}</span>
+					<!-- <span class="tool-item" style="margin-left: 20px;cursor: pointer;" @click="exportTable()">
 						<Icon type="md-download" />
 						<span>导出数据</span>
-					</span>	
+					</span>	 -->
 				</div>
 			</div>
 
 		</div>
-		<!-- <div class="tools-bar">
-			<div class="tool-item" @click="onAddVideo">
-				<Icon type="md-add" />
-				<span>添加课例</span>
-			</div>
-			<div class="tool-item">
-				<Icon type="md-download" />
-				<span>导出数据</span>
-			</div>
-			<div class="tool-item" @click="onTagMgClick">
-				<Icon type="md-settings" />
-				<span>类别管理</span>
-			</div>
-			<div class="tool-item">
-				<Icon type="ios-paper-plane" />
-				<span>分享至公开课</span>
-			</div>
-		</div> -->
+		
 		<div class="table-box">
 			<Scroll :on-reach-bottom="getMore" height="700" :distance-to-edge="[15, 15]">
-				<Table stripe :columns="tableColumnNew" :data="tableData" :loading="tableLoading">
+				<Table stripe :columns="tableColumnNew" :data="tableData" :loading="tableLoading" ref="tableRef">
 					<template slot-scope="{ row,index }" slot="tmdname">
 						<span>
 							{{ row.tmdname || row.tmdid }}
@@ -88,16 +88,22 @@
 					<template slot-scope="{ row }" slot="grade">
 						<span>{{ row.grade.map(i => curPeriod.grades[+i]).join(',') }}</span>
 					</template>
+					<template slot-scope="{ row }" slot="className">
+						<span>{{ row.groupIds.join(',') }}</span>
+					</template>
 					<template slot-scope="{ row }" slot="startTime">
-						<span>{{ $tools.formatTime(row.startTime) }}</span>
+						<span>{{ $tools.formatTime(row.startTime,'yyyy-MM-dd hh:mm') }}</span>
 					</template>
 					<template slot-scope="{ row }" slot="action">
 						<!-- <Icon class="action-icon" type="ios-paper-plane" color="#27a3cf"/>
 						<Icon class="action-icon" type="md-play" color="#34cf97" @click="doPlay(row)" />
 						<Icon class="action-icon" type="md-create" color="#3197e5" @click="doEdit(row)" />
 						<Icon class="action-icon" type="md-trash" color="#e25255" @click="doDelete(row)" /> -->
-						<Button size="small" type="success" style="margin-right: 5px;" @click="downloadTable">下载总表</Button>
-						<Button size="small" type="primary" @click="downloadTable">预览笔记</Button>
+						<!-- <Icon class="action-icon" type="md-play" color="#34cf97" @click="doPlay(row)" /> -->
+						<Icon class="action-icon" type="ios-paper-plane" color="#27a3cf" @click="goDetails(row)"/>
+						<Icon type="md-download" class="action-icon" color="#34cf97" @click="downloadTable(row)" :title="$t('lessonRecord.action1')"/>
+						<Icon type="md-eye" class="action-icon" color="#3197e5" @click="downloadNote(row)" :title="$t('lessonRecord.action2')"/>
+						<Icon class="action-icon" type="md-trash" color="#e25255" @click="doDelete(row)" :title="$t('lessonRecord.action3')"/>
 					</template>
 				</Table>
 			</Scroll>
@@ -116,7 +122,7 @@
 		<!-- 类别管理弹窗 -->
 		<Modal v-model="categoryModal" transfer width="660" class="research-modal">
 			<div slot="header">
-				课例类别管理
+				{{ $t('lessonRecord.tagTitle') }}
 			</div>
 			<div class="tags-box">
 				<span class="tags-item" v-for="(item,index) in tags" :key="index">
@@ -128,12 +134,12 @@
 				</span>
 				<span class="tags-item" @click="onAddTag">
 					<Icon type="md-add" style="margin: 0 5px 0 0;color: #70b1e7;"></Icon>
-					<span>添加新类别</span>
+					<span>{{ $t('lessonRecord.addNewTag') }}</span>
 				</span>
 			</div>
 			<div slot="footer">
-				<Button @click="categoryModal = false">取消</Button>
-				<Button type="primary" @click="onSettingTags" :loading="tagLoading">保存变更</Button>
+				<Button @click="categoryModal = false">{{ $t('lessonRecord.cancel') }}</Button>
+				<Button type="primary" @click="onSettingTags" :loading="tagLoading">{{ $t('lessonRecord.save') }}</Button>
 			</div>
 		</Modal>
 	</div>
@@ -146,9 +152,9 @@
 			BaseTypeMgmt,
 			BaseForm
 		},
-		data() {
+		data(vm) {
 			return {
-				analysisArr:['课堂记录总数','教师数','累计任务数','累计作品数','累计互动总数','本学期新增课堂记录数'],
+				analysisArr:[vm.$t('lessonRecord.count1'),vm.$t('lessonRecord.count2'),vm.$t('lessonRecord.count3'),vm.$t('lessonRecord.count4'),vm.$t('lessonRecord.count5'),vm.$t('lessonRecord.count6'),vm.$t('lessonRecord.count7')],
 				analysisCount:[],
 				isEdit: false,
 				editLoading: false,
@@ -231,100 +237,157 @@
 				],
 				tableColumnNew:[
 					{
-						title: '班级',
-						key: 'className',
+						title: vm.$t('lessonRecord.lessonName'),
+						key: 'name',
 						ellipsis:true,
+						width:200
 					},
 					{
-						title: '教师名称',
+						title: vm.$t('lessonRecord.tchName'),
 						key: 'tmdname',
 						ellipsis:true,
+						width:100
 					},
 					{
-						title: '课堂名称',
-						key: 'name',
+						title: vm.$t('lessonRecord.className'),
+						slot: 'className',
 						ellipsis:true,
+						width:200
+					},
+					{
+						title: vm.$t('lessonRecord.subject'),
+						slot: 'subject',
+					},
+					{
+						title: vm.$t('lessonRecord.grade'),
+						slot: 'grade',
+						width:120
 					},
 					{
-						title: '日期',
+						title: vm.$t('lessonRecord.date'),
 						slot: 'startTime',
 						ellipsis:true,
-						width:200
+						width:150
 					},
 					{
-						title: '出席率',
+						title: vm.$t('lessonRecord.attendCount'),
 						key: 'attendCount',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '小组数',
+						title: vm.$t('lessonRecord.groupCount'),
 						key: 'groupCount',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '总计分',
+						title: vm.$t('lessonRecord.totalPoint'),
 						key: 'totalPoint',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '任务总数',
+						title: vm.$t('lessonRecord.collateTaskCount'),
 						key: 'collateTaskCount',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '作品总数',
+						title: vm.$t('lessonRecord.collateCount'),
 						key: 'collateCount',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '推送总数',
+						title: vm.$t('lessonRecord.pushCount'),
 						key: 'pushCount',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '总互动分',
+						title: vm.$t('lessonRecord.score'),
 						key: 'score',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '互动题数',
+						title: vm.$t('lessonRecord.interactionCount'),
 						key: 'interactionCount',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '互动总数',
+						title: vm.$t('lessonRecord.clientInteractionCount'),
 						key: 'clientInteractionCount',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '测验总题数',
+						title: vm.$t('lessonRecord.examQuizCount'),
 						key: 'examQuizCount',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '测验得分率',
+						title: vm.$t('lessonRecord.examPointRate'),
 						key: 'examPointRate',
+						sortable:true,
 						ellipsis:true,
 					},
 					{
-						title: '操作',
+						title: vm.$t('lessonRecord.action'),
 						slot: 'action',
 						className: "table-action",
-						width:200
+						width:150
 					}
 				],
 				originList: []
 			}
 		},
 		created() {
-			this.initFilter()
-			this.initTags()
-			this.getAnalysisCount()
+			// this.initFilter()
+			// this.initTags()
+			// this.getAnalysisCount()
 		},
 		methods: {
-			downloadTable(){
-				this.$Message.warning('暂未处理')
+			/* 导出表格 */
+			exportTable(){
+				this.$refs.tableRef.exportCsv({
+					filename: this.$t('lessonRecord.allTable')
+				});
+			},
+			/* 下载课例总表 */
+			downloadTable(row){
+				console.log(row);
+				let blobInfo = row.scope == 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+				let url = `${blobInfo.blob_uri}/records/${row.id}/IES/summary.xlsx?${blobInfo.blob_sas}`
+				const downloadRes = async () => {
+				    let response = await fetch(url); // 内容转变成blob地址
+				    let blob = await response.blob(); // 创建隐藏的可下载链接
+				    let objectUrl = window.URL.createObjectURL(blob);
+				    let a = document.createElement('a');
+				    a.href = objectUrl;
+				    a.download = row.name + '.xlsx';
+				    a.click()
+				    a.remove();
+				}
+				downloadRes();
 			},
+			/* 预览课例笔记 */
+			downloadNote(row){
+				console.log(row);
+				// let blobInfo = row.scope == 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+				// let url = `${blobInfo.blob_uri}/records/${row.id}/Note.pdf?${blobInfo.blob_sas}`
+				// window.open('/web/viewer.html?file=' + encodeURIComponent(url));
+				this.$router.push({
+					name:'classRecord',
+					params:{
+						record:row
+					}
+				})
+			},
+			/* 获取课例统计数据 */
 			getAnalysisCount(){
 				let semesterRange = this.$tools.getSemesterTimeRange()
 				this.$api.lessonRecord.getAnalysisCount({
@@ -333,6 +396,7 @@
 					"code": this.$store.state.user.schoolCode,
 					"periodId":this.$store.state.user.curPeriod.id
 				}).then(res => {
+					console.log(res)
 					this.analysisCount = Object.values(res)
 				})
 			},
@@ -506,7 +570,7 @@
 			doDelete(item) {
 				this.$Modal.confirm({
 					title: this.$t('evaluation.newExercise.modalTip'),
-					content: `确定删除课堂记录【${ item.name }】?`,
+					content: `${ this.$t('lessonRecord.delTip') }【${ item.name }】?`,
 					onOk: () => {
 						this.$api.lessonRecord.delRcd({
 							"scope": item.scope,
@@ -516,7 +580,7 @@
 							"school": this.$store.state.userInfo.schoolCode
 						}).then(res => {
 							if (!res.error) {
-								this.$Message.success('删除成功!')
+								this.$Message.success(this.$t('lessonRecord.delSuc'))
 								this.doFilter()
 							}
 						})
@@ -551,11 +615,11 @@
 			/* 确认修改 */
 			onConfirmInput() {
 				if (!this.curEditTag.replace(/(^\s*)|(\s*$)/g, "")) {
-					this.$Message.warning('请将类别填写完整!')
+					this.$Message.warning(this.$t('lessonRecord.tagTip1'))
 					return
 				}
 				if (this.tags.includes(this.curEditTag)) {
-					this.$Message.warning('已存在相同类别!')
+					this.$Message.warning(this.$t('lessonRecord.tagTip2'))
 					return
 				}
 				this.tags[this.curEditIndex] = this.curEditTag
@@ -569,7 +633,7 @@
 			/* 添加新类别 */
 			onAddTag() {
 				if (this.tags.some(i => i.replace(/(^\s*)|(\s*$)/g, "") == '')) {
-					this.$Message.warning('不能存在空类别!')
+					this.$Message.warning(this.$t('lessonRecord.tagTip3'))
 				} else {
 					this.tags.push('')
 					this.curEditTag = ''
@@ -586,7 +650,7 @@
 					lessonTag: saveTags
 				}).then(res => {
 					if (!res.error) {
-						this.$Message.success('保存成功!')
+						this.$Message.success(this.$t('lessonRecord.saveSuc'))
 						this.tagLoading = false
 						this.categoryModal = false
 					}
@@ -598,6 +662,19 @@
 				return this.$store.state.user.curPeriod
 			},
 		},
+		watch:{
+			'$store.state.user.curPeriod': {
+				deep: true,
+				immediate: true,
+				handler(n, o) {
+					if (n) {
+						this.initFilter()
+						this.initTags()
+						this.getAnalysisCount()
+					}
+				}
+			}
+		}
 
 	}
 </script>

+ 16 - 1
TEAMModelOS/Controllers/Both/LessonRecordController.cs

@@ -318,6 +318,7 @@ namespace TEAMModelOS.Controllers
             AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dict, sql);
             string tbname = "";
             string code = "";
+            string school = null;
             if (_scope.GetString().Equals("school"))
             {
                 if (!request.TryGetProperty("school", out JsonElement _school)) return BadRequest();
@@ -325,6 +326,7 @@ namespace TEAMModelOS.Controllers
                 {
                     code = $"LessonRecord-{_school}";
                     tbname = "School";
+                    school = $"{_school}";
                 }
                 else
                 {
@@ -388,6 +390,19 @@ namespace TEAMModelOS.Controllers
                         });
                     }
                 }
+                var groupIds = lessonRecords.SelectMany(x => x.groupIds);
+                if (groupIds.Any()) {
+                   List<GroupListDto> groupLists= await GroupListService.GetGroupListListids(_azureCosmos.GetCosmosClient(), _dingDing, groupIds.ToList(), school);
+                    lessonRecords.ForEach(x => {
+                        List<string> groupNmae = new List<string>();
+                        x.groupIds.ForEach(y => {
+                           var dto= groupLists.Find(z => z.id.Equals(y));
+                           string name  = dto != null ? dto.name : "-";
+                            groupNmae.Add(name);
+                        });
+                        x.groupIds = groupNmae;
+                    });
+                }
                 return Ok(new { currCount = lessonRecords.Count, continuationToken, lessonRecords });
             }
             catch (Exception ex)
@@ -555,7 +570,7 @@ namespace TEAMModelOS.Controllers
             }
             if (request.TryGetProperty("subjectId", out JsonElement subjectId))
             {
-                dict.Add("subjectId[*]", subjectId);
+                dict.Add("subjectId", subjectId);
             }
             if (request.TryGetProperty("groupIds", out JsonElement groupIds))
             {