Jelajahi Sumber

Merge branch 'develop' into cmy/develop-bi

chenmy 2 tahun lalu
induk
melakukan
78021eca67
27 mengubah file dengan 1537 tambahan dan 421 penghapusan
  1. 212 200
      TEAMModelBI/Controllers/BINormal/BatchAreaController.cs
  2. 1 1
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  3. 115 0
      TEAMModelBI/Controllers/Census/ItemSticsController.cs
  4. 108 1
      TEAMModelBI/Controllers/Census/PaperController.cs
  5. 3 3
      TEAMModelBI/TEAMModelBI.csproj
  6. 12 0
      TEAMModelOS/ClientApp/public/lang/en-US.js
  7. 12 0
      TEAMModelOS/ClientApp/public/lang/zh-CN.js
  8. 12 0
      TEAMModelOS/ClientApp/public/lang/zh-TW.js
  9. 3 0
      TEAMModelOS/ClientApp/src/api/areaArt.js
  10. 198 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewMobile.less
  11. 432 0
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewMobile.vue
  12. TEMPAT SAMPAH
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-en-us.png
  13. TEMPAT SAMPAH
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-zh-cn.png
  14. TEMPAT SAMPAH
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-zh-tw.png
  15. TEMPAT SAMPAH
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-en-us.png
  16. TEMPAT SAMPAH
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-zh-cn.png
  17. TEMPAT SAMPAH
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-zh-tw.png
  18. 10 0
      TEAMModelOS/ClientApp/src/router/routes.js
  19. 29 19
      TEAMModelOS/ClientApp/src/view/areaArtExam/Mgt.vue
  20. 27 6
      TEAMModelOS/ClientApp/src/view/artexam/Create.vue
  21. 113 114
      TEAMModelOS/ClientApp/src/view/artexam/QuoTree.vue
  22. 10 3
      TEAMModelOS/ClientApp/src/view/auth/Product.vue
  23. 75 0
      TEAMModelOS/ClientApp/src/view/sso/StudentIndex.vue
  24. 22 16
      TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue
  25. 63 2
      TEAMModelOS/Controllers/Client/HiTAControlller.cs
  26. 78 14
      TEAMModelOS/Controllers/Common/AreaController.cs
  27. 2 42
      TEAMModelOS/Controllers/Common/ArtController.cs

+ 212 - 200
TEAMModelBI/Controllers/BINormal/BatchAreaController.cs

@@ -242,6 +242,13 @@ namespace TEAMModelBI.Controllers.BINormal
                         return Ok(new { state = 1, message = "新创区的standard已存在请检查" });
                 }
 
+                //查询新的区级名称是否存在
+                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: $"select value(c) from c where c.name='{name}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
+                {
+                    if (item.name.Equals($"{standard}"))
+                        return Ok(new { state = 1, message = "区级名称相同,请检测区级名称!" });
+                }
+
                 //区级的ID
                 string areaId = Guid.NewGuid().ToString();
                 Area addArea = new()
@@ -1028,7 +1035,7 @@ namespace TEAMModelBI.Controllers.BINormal
             try
             {
                 string _oldId = "bde5c011-2ae4-461a-b46c-5483ba72ae45";
-                string _oldStandard = "standard27";
+                //string _oldStandard = "standard27";
                 string standardFileId = "02944f32-f534-3397-ea56-e6f1fc6c3714";
                 string standard = "standard2";
 
@@ -1047,252 +1054,257 @@ namespace TEAMModelBI.Controllers.BINormal
 
                 var table = tableClient.GetTableReference("IESLogin");
 
-                var responseSet = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{_oldId}", new PartitionKey("AreaSetting"));
-                if (responseSet.Status == 200)
-                {
-                    using var fileJson = await JsonDocument.ParseAsync(responseSet.ContentStream);
-                    AreaSetting delSet = fileJson.ToObject<AreaSetting>();
-                    if (!string.IsNullOrEmpty(delSet.accessConfig))
-                        return Ok(new { state = 401, msg = "区域已经规定了,不能切换能能力" });
-                }
-
-                List<string> abilityIds = new List<string>();  //册别的ID集合
-
-                //查询册别信息
-                await foreach (var tempAbility in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{_oldStandard}") }))
-                {
-                    abilityIds.Add(tempAbility.id);  //查询出来册别ID添加册别ID集合
-                }
-                //删除册别
-                if (abilityIds.IsNotEmpty())
-                {
-                    var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityIds, $"Ability-{_oldStandard}");
-                }
-
-                List<string> abilityTaskIds = new List<string>();  //章节ID集合
-                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{_oldStandard}") }))
-                {
-                    abilityTaskIds.Add(item.id);   //查询出来的章节信息ID添加到战绩集合
-                }
-                //删除章节
-                if (abilityTaskIds.IsNotEmpty())
-                {
-                    var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityTaskIds, $"AbilityTask-{_oldStandard}");
-                }
-                List<Task<ItemResponse<Ability>>> abilities = new();      //存储册别数据
-                List<Task<ItemResponse<AbilityTask>>> abilityTasks = new();  //存储章节
-
-                List<string> repeatAbilityId = new();
-                List<string> repeatAbilityTaskId = new();
-
-                foreach (var newstand in copyStand)
+                Area area = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>($"{_oldId}", new PartitionKey("Base-Area"));
+                if (area != null)
                 {
-                    try
+                    var responseSet = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{_oldId}", new PartitionKey("AreaSetting"));
+                    if (responseSet.Status == 200)
                     {
-                        //查询要复制区域的能力标准点 
-                        await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{newstand.standard}") }))
-                        {
-                            if (!string.IsNullOrEmpty(item.blob))
-                                item.blob = item.blob.Replace($"/{newstand.standard}/", $"/{_oldStandard}/");
+                        using var fileJson = await JsonDocument.ParseAsync(responseSet.ContentStream);
+                        AreaSetting delSet = fileJson.ToObject<AreaSetting>();
+                        if (!string.IsNullOrEmpty(delSet.accessConfig))
+                            return Ok(new { state = 401, msg = "区域已经规定了,不能切换能能力" });
+                    }
 
-                            item.standard = $"{_oldStandard}";
-                            item.code = $"Ability-{_oldStandard}";
-                            item.school = $"{_oldStandard}";
+                    List<string> abilityIds = new();  //册别的ID集合
 
-                            //添加区能力标准点
-                            //abilities.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}")));
-                            //await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}"));
+                    //查询册别信息
+                    await foreach (var tempAbility in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{area.standard}") }))
+                    {
+                        abilityIds.Add(tempAbility.id);  //查询出来册别ID添加册别ID集合
+                    }
+                    //删除册别
+                    if (abilityIds.IsNotEmpty())
+                    {
+                        var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityIds, $"Ability-{area.standard}");
+                    }
 
-                            var respond = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(item.id, new PartitionKey(item.code));
-                            if (respond.Status != 200)
-                                abilities.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}")));
-                            else
-                                repeatAbilityId.Add(item.id);
-                        }
+                    List<string> abilityTaskIds = new List<string>();  //章节ID集合
+                    await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{area.standard}") }))
+                    {
+                        abilityTaskIds.Add(item.id);   //查询出来的章节信息ID添加到战绩集合
                     }
-                    catch
+                    //删除章节
+                    if (abilityTaskIds.IsNotEmpty())
                     {
-                        return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
+                        var sresponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemsStreamAsync(abilityTaskIds, $"AbilityTask-{area.standard}");
                     }
+                    List<Task<ItemResponse<Ability>>> abilities = new();      //存储册别数据
+                    List<Task<ItemResponse<AbilityTask>>> abilityTasks = new();  //存储章节
 
-                    try
+                    List<string> repeatAbilityId = new();
+                    List<string> repeatAbilityTaskId = new();
+
+                    foreach (var newstand in copyStand)
                     {
-                        if (abilities.Count < 256)
+                        try
                         {
-                            await Task.WhenAll(abilities);
+                            //查询要复制区域的能力标准点 
+                            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Ability>(queryText: $"select value(c) from c", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Ability-{newstand.standard}") }))
+                            {
+                                if (!string.IsNullOrEmpty(item.blob))
+                                    item.blob = item.blob.Replace($"/{newstand.standard}/", $"/{area.standard}/");
+
+                                item.standard = $"{area.standard}";
+                                item.code = $"Ability-{area.standard}";
+                                item.school = $"{area.standard}";
+
+                                //添加区能力标准点
+                                //abilities.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}")));
+                                //await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{_oldStandard}"));
+
+                                var respond = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(item.id, new PartitionKey(item.code));
+                                if (respond.Status != 200)
+                                    abilities.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(item, new PartitionKey($"Ability-{area.standard}")));
+                                else
+                                    repeatAbilityId.Add(item.id);
+                            }
                         }
-                        else
+                        catch
                         {
-                            int pages = (abilities.Count + 255) / 256;
-                            for (int i = 0; i < pages; i++)
+                            return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
+                        }
+
+                        try
+                        {
+                            if (abilities.Count < 256)
                             {
-                                List<Task<ItemResponse<Ability>>> tempAbility = abilities.Skip((i) * 256).Take(256).ToList();
-                                await Task.WhenAll(tempAbility);
+                                await Task.WhenAll(abilities);
+                            }
+                            else
+                            {
+                                int pages = (abilities.Count + 255) / 256;
+                                for (int i = 0; i < pages; i++)
+                                {
+                                    List<Task<ItemResponse<Ability>>> tempAbility = abilities.Skip((i) * 256).Take(256).ToList();
+                                    await Task.WhenAll(tempAbility);
+                                }
                             }
                         }
-                    }
-                    catch
-                    {
-                        return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
-                    }
+                        catch
+                        {
+                            return Ok(new { state = 200, msg = "创区成功,能力标准点复制失败,遗留数据影响!" });
+                        }
 
-                    try
-                    {
-                        //微能力点
-                        await foreach (var atask in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{newstand.standard}") }))
+                        try
                         {
-                            List<Tnode> tnodes = new();
-                            foreach (Tnode tnode in atask.children)
+                            //微能力点
+                            await foreach (var atask in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AbilityTask>(queryText: $"select value(c) from c ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"AbilityTask-{newstand.standard}") }))
                             {
-                                if (tnode.rnodes != null)
+                                List<Tnode> tnodes = new();
+                                foreach (Tnode tnode in atask.children)
                                 {
-                                    List<Rnode> rnodes = new();
-                                    foreach (Rnode rnode in tnode.rnodes)
+                                    if (tnode.rnodes != null)
                                     {
-                                        if (!string.IsNullOrEmpty($"{rnode.link}"))
+                                        List<Rnode> rnodes = new();
+                                        foreach (Rnode rnode in tnode.rnodes)
                                         {
-                                            rnode.link = rnode.link.Replace($"/{newstand.standard}/", $"/{_oldStandard}/");
+                                            if (!string.IsNullOrEmpty($"{rnode.link}"))
+                                            {
+                                                rnode.link = rnode.link.Replace($"/{newstand.standard}/", $"/{area.standard}/");
+                                            }
+                                            rnodes.Add(rnode);
                                         }
-                                        rnodes.Add(rnode);
+                                        tnode.rnodes = rnodes;
                                     }
-                                    tnode.rnodes = rnodes;
+                                    tnodes.Add(tnode);
                                 }
-                                tnodes.Add(tnode);
-                            }
 
-                            atask.children = tnodes;
-                            atask.code = $"AbilityTask-{_oldStandard}";
-                            atask.standard = $"{_oldStandard}";
-                            atask.codeval = $"{_oldStandard}";
-
-                            var respond = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(atask.id, new PartitionKey(atask.code));
-                            if (respond.Status != 200)
-                                ////添加区能力标准点中的节点 
-                                //abilityTasks.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(atask, new PartitionKey($"AbilityTask-{_oldStandard}")));
-                                await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(atask, new PartitionKey($"AbilityTask-{_oldStandard}"));
-                            else
-                                repeatAbilityTaskId.Add(atask.id);
+                                atask.children = tnodes;
+                                atask.code = $"AbilityTask-{area.standard}";
+                                atask.standard = $"{area.standard}";
+                                atask.codeval = $"{area.standard}";
+
+                                var respond = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(atask.id, new PartitionKey(atask.code));
+                                if (respond.Status != 200)
+                                    ////添加区能力标准点中的节点 
+                                    //abilityTasks.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(atask, new PartitionKey($"AbilityTask-{_oldStandard}")));
+                                    await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(atask, new PartitionKey($"AbilityTask-{area.standard}"));
+                                else
+                                    repeatAbilityTaskId.Add(atask.id);
+                            }
+                        }
+                        catch
+                        {
+                            return Ok(new { state = 200, msg = "创区成功,能力标准创建成功,微能力点复制失败,遗留数据影响!" });
                         }
-                    }
-                    catch
-                    {
-                        return Ok(new { state = 200, msg = "创区成功,能力标准创建成功,微能力点复制失败,遗留数据影响!" });
-                    }
 
-                    //发送消息分区键
-                    string partitionCode = "DelBeforeCopyAbility-mark";
-
-                    //执行复制操作
-                    BatchCopyFile batchCopyFile = new();
-                    batchCopyFile.blobCntr = "teammodelos";
-                    batchCopyFile.oldFileName = $"{newstand.standard}";
-                    batchCopyFile.newFileName = $"{_oldStandard}";
-                    batchCopyFile.tmdid = $"{_tmdId}";
-                    batchCopyFile.tmdIds = new List<string> { $"{_tmdId}" };
-                    batchCopyFile.codeKey = partitionCode;
-                    batchCopyFile.tmdName = $"{_tmdName}";
-                    var messageBatchCopyFile = new ServiceBusMessage(batchCopyFile.ToJsonString());
-                    messageBatchCopyFile.ApplicationProperties.Add("name", "CopyStandardFile");
-                    try
-                    {
-                        //await _serviceBus.GetServiceBusClient().SendMessageAsync(activeTask, messageBatchCopyFile);  //先执行删除操作,在执行复制  单一
-                        await serBusClient.SendMessageAsync(activeTask, messageBatchCopyFile);  //先执行删除操作,在执行复制
-                    }
-                    catch (Exception)
-                    {
-                        return Ok(new { state = 201, msg = "能力点复制成功,复制能力点的文件失败," });
-                    }
+                        //发送消息分区键
+                        string partitionCode = "DelBeforeCopyAbility-mark";
+
+                        //执行复制操作
+                        BatchCopyFile batchCopyFile = new();
+                        batchCopyFile.blobCntr = "teammodelos";
+                        batchCopyFile.oldFileName = $"{newstand.standard}";
+                        batchCopyFile.newFileName = $"{area.standard}";
+                        batchCopyFile.tmdid = $"{_tmdId}";
+                        batchCopyFile.tmdIds = new List<string> { $"{_tmdId}" };
+                        batchCopyFile.codeKey = partitionCode;
+                        batchCopyFile.tmdName = $"{_tmdName}";
+                        var messageBatchCopyFile = new ServiceBusMessage(batchCopyFile.ToJsonString());
+                        messageBatchCopyFile.ApplicationProperties.Add("name", "CopyStandardFile");
+                        try
+                        {
+                            //await _serviceBus.GetServiceBusClient().SendMessageAsync(activeTask, messageBatchCopyFile);  //先执行删除操作,在执行复制  单一
+                            await serBusClient.SendMessageAsync(activeTask, messageBatchCopyFile);  //先执行删除操作,在执行复制
+                        }
+                        catch (Exception)
+                        {
+                            return Ok(new { state = 201, msg = "能力点复制成功,复制能力点的文件失败," });
+                        }
 
-                    //发送消息实体
-                    Notification notification = new()
-                    {
-                        hubName = "hita",
-                        type = "msg",
-                        from = $"BI:{_option.Location}:private",
-                        to = new List<string> { $"{_tmdId}" },
-                        label = $"{partitionCode}_start",
-                        body = new { location = _option.Location, biz = partitionCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
-                        expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
-                    };
+                        //发送消息实体
+                        Notification notification = new()
+                        {
+                            hubName = "hita",
+                            type = "msg",
+                            from = $"BI:{_option.Location}:private",
+                            to = new List<string> { $"{_tmdId}" },
+                            label = $"{partitionCode}_start",
+                            body = new { location = _option.Location, biz = partitionCode, tmdid = $"{_tmdId}", tmdname = $"{_tmdName}", status = 1, time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() }.ToJsonString(),
+                            expires = DateTimeOffset.UtcNow.AddDays(7).ToUnixTimeSeconds()
+                        };
 
-                    var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
-                    var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
-                    var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
-                    var location = _option.Location;
-                    await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //发送站内发送消息
-                }
+                        var url = _configuration.GetValue<string>("HaBookAuth:CoreService:sendnotification");
+                        var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+                        var clientSecret = _configuration.GetValue<string>("HaBookAuth:CoreService:clientSecret");
+                        var location = _option.Location;
+                        await _notificationService.SendNotification(clientID, clientSecret, location, url, notification); //发送站内发送消息
+                    }
 
-                StandardFile saveFile = new();
-                //新政策文件
-                await foreach (StandardFile standardFile in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<StandardFile>(queryText: $"select value(c) from c where  c.id='{standardFileId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StandardFile") }))
-                {
-                    if (standardFile != null)
+                    StandardFile saveFile = new();
+                    //新政策文件
+                    await foreach (StandardFile standardFile in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<StandardFile>(queryText: $"select value(c) from c where  c.id='{standardFileId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"StandardFile") }))
                     {
-                        standardFile.standard = $"{_oldStandard}";
-                        standardFile.id = $"{_oldId}";
+                        if (standardFile != null)
+                        {
+                            standardFile.standard = $"{area.standard}";
+                            standardFile.id = $"{_oldId}";
 
-                        saveFile = standardFile;
+                            saveFile = standardFile;
+                        }
                     }
-                }
 
-                StandardFile tempFile = new();
-                if (saveFile.id != null)
-                {
-                    var respFile = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(saveFile.id, new PartitionKey("StandardFile"));
-                    if (respFile.Status == 200)
+                    StandardFile tempFile = new();
+                    if (saveFile.id != null)
                     {
-                        using var json = await JsonDocument.ParseAsync(respFile.ContentStream);
-                        tempFile = json.ToObject<StandardFile>();
-                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemAsync<StandardFile>(tempFile.id, new PartitionKey("StandardFile"));
-                    }
+                        var respFile = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(saveFile.id, new PartitionKey("StandardFile"));
+                        if (respFile.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(respFile.ContentStream);
+                            tempFile = json.ToObject<StandardFile>();
+                            await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemAsync<StandardFile>(tempFile.id, new PartitionKey("StandardFile"));
+                        }
 
-                    tempFile = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveFile, new PartitionKey($"StandardFile")); // 需要删除原来的政策文件数据在进行添加
-                }
+                        tempFile = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveFile, new PartitionKey($"StandardFile")); // 需要删除原来的政策文件数据在进行添加
+                    }
 
-                //if (tempFile.id != null)
-                //{
-                //    if (tempFile.id.Equals(saveFile.id))
-                //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<StandardFile>(saveFile, saveFile.id, new PartitionKey("StandardFile")); //直接替换以前的数据
-                //    else
-                //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveFile, new PartitionKey($"StandardFile")); // 需要删除原来的政策文件数据在进行添加
-                //}
+                    //if (tempFile.id != null)
+                    //{
+                    //    if (tempFile.id.Equals(saveFile.id))
+                    //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<StandardFile>(saveFile, saveFile.id, new PartitionKey("StandardFile")); //直接替换以前的数据
+                    //    else
+                    //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveFile, new PartitionKey($"StandardFile")); // 需要删除原来的政策文件数据在进行添加
+                    //}
 
-                //新的区域设置
-                AreaSetting saveSetting = new();
-                await foreach (AreaSetting areaSetting in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AreaSetting>(queryText: $"select value(c) from c where c.id='{standardFileId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("AreaSetting") }))
-                {
-                    if (areaSetting != null)
+                    //新的区域设置
+                    AreaSetting saveSetting = new();
+                    await foreach (AreaSetting areaSetting in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AreaSetting>(queryText: $"select value(c) from c where c.id='{standardFileId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("AreaSetting") }))
                     {
-                        areaSetting.accessConfig = null;
-                        areaSetting.id = $"{_oldId}";
+                        if (areaSetting != null)
+                        {
+                            areaSetting.accessConfig = null;
+                            areaSetting.id = $"{_oldId}";
 
-                        saveSetting = areaSetting;
+                            saveSetting = areaSetting;
+                        }
                     }
-                }
 
-                AreaSetting tempSetting = new();
-                if (saveSetting.id != null)
-                {
-                    var respSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(saveSetting.id, new PartitionKey("AreaSetting"));
-                    if (respSetting.Status == 200)
+                    AreaSetting tempSetting = new();
+                    if (saveSetting.id != null)
                     {
-                        using var json = await JsonDocument.ParseAsync(respSetting.ContentStream);
-                        tempSetting = json.ToObject<AreaSetting>();
-                        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemAsync<AreaSetting>(saveSetting.id, new PartitionKey("AreaSetting"));
+                        var respSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync(saveSetting.id, new PartitionKey("AreaSetting"));
+                        if (respSetting.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(respSetting.ContentStream);
+                            tempSetting = json.ToObject<AreaSetting>();
+                            await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").DeleteItemAsync<AreaSetting>(saveSetting.id, new PartitionKey("AreaSetting"));
+                        }
+
+                        tempSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
                     }
+                    //if (tempSetting.id != null)
+                    //{
+                    //    if (tempSetting.id.Equals(saveSetting.id))
+                    //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<AreaSetting>(saveSetting, saveSetting.id, new PartitionKey($"AreaSetting"));   //直接替换以前的数据
+                    //    else
+                    //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
+                    //}
 
-                    tempSetting = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
+                    return Ok(new { state = RespondCode.Ok, repeatAbilityId, repeatAbilityTaskId });
                 }
-
-                //if (tempSetting.id != null)
-                //{
-                //    if (tempSetting.id.Equals(saveSetting.id))
-                //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<AreaSetting>(saveSetting, saveSetting.id, new PartitionKey($"AreaSetting"));   //直接替换以前的数据
-                //    else
-                //        await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").CreateItemAsync(saveSetting, new PartitionKey($"AreaSetting"));  //需要删除原来的区域设置数据在进行添加
-                //}
-
-                return Ok(new { state = RespondCode.Ok, repeatAbilityId, repeatAbilityTaskId });
+                else
+                    return Ok(new { state = RespondCode.NotFound, msg = "标准为空"}) ;
 
             }
             catch (Exception ex)

+ 1 - 1
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -114,7 +114,7 @@ namespace TEAMModelBI.Controllers.BISchool
                 }
                 else
                 {
-                    sqltxt.Append($" WHERE c.areaId ='' and c.standard = ''");
+                    sqltxt.Append($" WHERE c.areaId ='' or c.areaId = null");
                 }
 
                 List<NotAreaSchool> tempNotAreaSchools = new();

+ 115 - 0
TEAMModelBI/Controllers/Census/ItemSticsController.cs

@@ -13,6 +13,10 @@ using System.Text;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Context.BI;
+using Azure.Core;
+using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
+using TEAMModelOS.SDK.Context.Constant;
+using DocumentFormat.OpenXml.Wordprocessing;
 
 namespace TEAMModelBI.Controllers.Census
 {
@@ -33,6 +37,117 @@ namespace TEAMModelBI.Controllers.Census
             _option = option?.Value;
         }
 
+        /// <summary>
+        /// 查询学校试题
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-list")]
+        public async Task<IActionResult> GetList(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("code", out JsonElement code)) return BadRequest();
+            jsonElement.TryGetProperty("scope", out JsonElement scope);
+            Dictionary<string, object> dic = new();
+            if (jsonElement.TryGetProperty("periodId", out JsonElement periodId))
+                dic.Add("periodId", periodId);
+            if (jsonElement.TryGetProperty("subjectId", out JsonElement subjectId))
+                dic.Add("subjectId", subjectId);
+            if (jsonElement.TryGetProperty("gradeIds", out JsonElement gradeIds))
+                dic.Add("gradeIds", gradeIds);
+            if (jsonElement.TryGetProperty("type", out JsonElement type))
+                dic.Add("type", type);
+            if (jsonElement.TryGetProperty("level", out JsonElement level))
+                dic.Add("level", level);
+            if (jsonElement.TryGetProperty("field", out JsonElement field))
+                dic.Add("field", field);
+            if (jsonElement.TryGetProperty("isSort", out JsonElement isSort))
+            {
+                if (!string.IsNullOrEmpty($"{isSort}"))
+                {
+                    if (bool.Parse($"{isSort}") == true)
+                        dic.Add("@DESC", "createTime");
+                    else
+                        dic.Add("@ASC", "createTime");
+                }
+                else
+                    dic.Add("@ASC", "createTime");
+            }
+            if (jsonElement.TryGetProperty("pid", out JsonElement pd))
+            {
+                if (pd.ValueKind != JsonValueKind.Null)
+                    dic.Add("pid", pd.ToString());
+                else
+                    dic.Add("pid", null);
+            }
+
+            var cosmosClinet = _azureCosmos.GetCosmosClient();
+            StringBuilder sql = new("select c.id,c.code,c.repairResource, c.periodId,c.question,c.useCount,c.level,c.field,c.knowledge,c.type,c.option,c.createTime,c.answer,c.explain,c.children,c.score,c.gradeIds,c.subjectId,c.blob,c.scope from c ");
+            AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dic, sql);
+            List<object> items = new();
+            if (scope.ToString().Equals("private"))
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
+                {
+                    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())
+                        {
+                            items.Add(obj.ToObject<object>());
+                        }
+                    }
+                }
+            }
+            else if (scope.ToString().Equals("school"))
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
+                {
+                    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())
+                        {
+                            items.Add(obj.ToObject<object>());
+                        }
+                    }
+                }
+            }
+            else
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
+                {
+                    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())
+                        {
+                            items.Add(obj.ToObject<object>());
+                        }
+                    }
+                }
+
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Item-{code}") }))
+                {
+                    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())
+                        {
+                            items.Add(obj.ToObject<object>());
+                        }
+                    }
+                }
+            }
+
+            return Ok(new { state = RespondCode.Ok ,cnt = items.Count, items });
+        }
+
+
         /// <summary>
         /// 查询所有试题数量
         /// </summary>

+ 108 - 1
TEAMModelBI/Controllers/Census/PaperController.cs

@@ -11,7 +11,9 @@ using TEAMModelBI.Models;
 using TEAMModelBI.Tool;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.BI;
+using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 
@@ -37,6 +39,96 @@ namespace TEAMModelBI.Controllers.Census
             _option = option?.Value;
         }
 
+        /// <summary>
+        /// 查询学校试卷列表
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-list")]
+        public async Task<IActionResult> GetList(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("code", out JsonElement code)) return BadRequest();
+            jsonElement.TryGetProperty("scope", out JsonElement scope);
+            Dictionary<string, object> dic = new();
+            if (jsonElement.TryGetProperty("periodId", out JsonElement periodId))
+                dic.Add("periodId", periodId);
+            if (jsonElement.TryGetProperty("subjectId", out JsonElement subjectId))
+                dic.Add("subjectId", subjectId);
+            if (jsonElement.TryGetProperty("gradeIds", out JsonElement gradeIds))
+                dic.Add("gradeIds", gradeIds);
+            if (jsonElement.TryGetProperty("isSort", out JsonElement isSort))
+            {
+                if (!string.IsNullOrEmpty($"{isSort}"))
+                {
+                    if (bool.Parse($"{isSort}") == true)
+                        dic.Add("@DESC", "createTime");
+                    else
+                        dic.Add("@ASC", "createTime");
+                }
+                else
+                    dic.Add("@ASC", "createTime");
+            }
+
+            var cosmosClinet = _azureCosmos.GetCosmosClient();
+            StringBuilder sql = new("select value(c) from c ");
+            AzureCosmosQuery cosmosDbQuery = SQLHelper.GetSQL(dic, sql);
+
+            List<Paper> papers = new();
+            if (scope.ToString().Equals("school"))
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Paper>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
+                {
+                    papers.Add(item);
+                }
+            }
+            else if (scope.ToString().Equals("private"))
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Paper>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
+                {
+                    papers.Add(item);
+                }
+            }
+            else
+            {
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<Paper>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
+                {
+                    papers.Add(item);
+                }
+                await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<Paper>(queryDefinition: cosmosDbQuery.CosmosQueryDefinition, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{code}") }))
+                {
+                    papers.Add(item);
+                }
+            }
+
+            return Ok(new { state = RespondCode.Ok,cnt = papers.Count, papers });
+        }
+
+        /// <summary>
+        /// 复制试卷信息到另外一个学校
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("copy-infos")]
+        public async Task<IActionResult> CopyInfos(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("papers", out JsonElement jsPapers)) return BadRequest();
+
+            List<CopyPaper> papers = jsPapers.ToObject<List<CopyPaper>>();
+
+            var cosmosClinet = _azureCosmos.GetCosmosClient();
+            foreach (var cItem in papers)
+            {
+                Paper paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Paper>(cItem.oldId, new PartitionKey($"Paper-{cItem.oldSc}"));
+                
+
+            }
+
+            return Ok(new { state = RespondCode.Ok});
+        }
+
+
         /// <summary>
         /// 查询试卷的数量统计集合
         /// </summary>
@@ -315,7 +407,7 @@ namespace TEAMModelBI.Controllers.Census
             //if ($"{site}".Equals(BIConst.Global))
             //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
 
-            List<object> paperInfos = new List<object>();
+            List<object> paperInfos = new();
             string sqlTxt = $"select * from c where c.id='{paperId}' and c.pk='Paper'";
 
             if (!string.IsNullOrEmpty($"{isPersonal}"))
@@ -371,5 +463,20 @@ namespace TEAMModelBI.Controllers.Census
             public Dictionary<string, long> yearPaper { get; set; }
         }
 
+
+        public record CopyPaper 
+        {
+            public string oldId { get; set; }
+            public string oldSc { get; set; }
+            public string newId { get; set; }
+            public string newSc { get; set; }
+            public string newPrdId { get; set; }
+            public string newSubId { get; set; }
+            public string newGrId { get; set; }
+            public string isKlogger { get; set; }
+
+
+        }
+
     }
 }

+ 3 - 3
TEAMModelBI/TEAMModelBI.csproj

@@ -59,9 +59,9 @@
 		<SpaRoot>ClientApp\</SpaRoot>
 		<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
 		<UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-		<Version>1.2210.14</Version>
-		<AssemblyVersion>1.2210.14.1</AssemblyVersion>
-		<FileVersion>1.2210.14.1</FileVersion>
+		<Version>1.2210.19</Version>
+		<AssemblyVersion>1.2210.19.1</AssemblyVersion>
+		<FileVersion>1.2210.19.1</FileVersion>
 		<Description>TEAMModelBI(BI)</Description>
 		<PackageReleaseNotes>BI版本说明版本切换标记2022000908</PackageReleaseNotes>
 		<PackageId>TEAMModelBI</PackageId>

+ 12 - 0
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -504,6 +504,7 @@ const LANG_EN_US = {
         hadExp: '(Expired)',
         unused: '(Not activated)',
         forever: '(Permanent)',
+        longTime:'Long term authorization',
         useInfo: 'Use Status:',
         unband: 'Unbind Device',
         cancel: 'Cancel',
@@ -4211,6 +4212,17 @@ const LANG_EN_US = {
                 title1: "Recent",
                 title2: "Due Today",
             },
+            menus: {
+                title1: "My courses(as trainee)",
+                title2: "Login Guide",
+            },
+            loginGuidance: {
+                tips1: "Login on computer guide",
+                tips2: "Browse ",
+                tips5: " and click on Student to enter the login page",
+                tips3: "Type your registered account/password, or select 3rd party account provider to login with your TEAM Model ID",
+                tips4: "Use the account/password assigned by the school to login",
+            },
         },
         public: {
             noData: 'No data yet',

+ 12 - 0
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -504,6 +504,7 @@ const LANG_ZH_CN = {
         hadExp: '(已到期)',
         unuse: '(未启用)',
         forever: '(永久授权)',
+        longTime:'长期授权',
         useInfo: '使用状况:',
         unband: '解绑设备',
         cancel: '取消',
@@ -4214,6 +4215,17 @@ const LANG_ZH_CN = {
                 title1: "近期",
                 title2: "今日到期",
             },
+            menus: {
+                title1: "参与课程",
+                title2: "登录指引",
+            },
+            loginGuidance: {
+                tips1: "电脑端登录指引",
+                tips2: "浏览 ",
+                tips5: " 点击学生身份,进入学生登录页面",
+                tips3: "使用注册过的手机号,或选择微信进行醍摩豆账号登录",
+                tips4: "使用学校分配的账号密码进行校内账号登录",
+            },
         },
         public: {
             noData: '暂无数据',

+ 12 - 0
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -504,6 +504,7 @@ const LANG_ZH_TW = {
         hadExp: '(已到期)',
         unuse: '(未啟用)',
         forever: '(永久授權)',
+        longTime:'長期授權',
         useInfo: '使用狀況:',
         unband: '解綁設備',
         cancel: '取消',
@@ -4215,6 +4216,17 @@ const LANG_ZH_TW = {
                 title1: "近期",
                 title2: "今日到期",
             },
+            menus: {
+                title1: "參與課程",
+                title2: "登入指引",
+            },
+            loginGuidance: {
+                tips1: "電腦端登入使用流程",
+                tips2: "瀏覽 ",
+                tips2: " 選擇學生生身份,進入學生登入頁面",
+                tips3: "使用註冊過的帳密,或選擇第三方進行醍摩豆帳號登入",
+                tips4: "使用學校分配的學生帳密來進行校內帳號登入",
+            },
         },
         public: {
             noData: '暫無資料',

+ 3 - 0
TEAMModelOS/ClientApp/src/api/areaArt.js

@@ -27,6 +27,9 @@ export default {
     delArt: function (data) {
         return post('/common/art/delete', data)
     },
+    delAreaArt: function (data) {
+        return post('/school/area/delete-art', data)
+    },
     /* 艺术评测考核页面 */
     findArtResults: function (data) {
         return post('/school/art/review', data)

+ 198 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewMobile.less

@@ -0,0 +1,198 @@
+.home-view {
+    padding: 0.7rem 1rem;
+
+    .home-card {
+        margin-top: 15px;
+        box-shadow: 0px 2px 13px rgba(0, 0, 0, 0.1);
+        border: 1px solid rgba(0, 0, 0, 0.2);
+        border-radius: 5px;
+        background-color: #fff;
+        padding: 15px;
+
+        &:hover {
+            box-shadow: 0px 2px 30px rgba(0, 0, 0, 0.2);
+        }
+    }
+
+    .home-head {
+        margin-top: 0;
+        height: 400px;
+        overflow: hidden;
+        padding-bottom: 10px;
+        // display: flex;
+
+        .home-join {
+            height: calc(100% - 40px);
+            margin-bottom: 10px;
+        }
+
+        .join-class {
+            display: inline-block;
+            width: 18%;
+            border-radius: 10px;
+            border: 1px solid #f4f7f4;
+            padding: 10px;
+            margin: 5px 15px 10px;
+            cursor: pointer;
+            background-color: #f4f7f4;
+
+            .class-name {
+                // color: #02B35A;
+                font-size: 16px;
+                font-weight: bold;
+                overflow: hidden;
+                text-overflow: ellipsis;
+                white-space: nowrap;
+                margin-bottom: 10px;
+            }
+
+            .class-number-time {
+                display: flex;
+                justify-content: space-between;
+            }
+
+            .paper-item-school {
+                font-weight: bolder;
+                height: 20px;
+                line-height: 18px;
+                // padding: 5px 2px;
+                // margin-top: 10px;
+                // margin-right: 20px;
+                margin-bottom: 5px;
+                // cursor: pointer;
+                display: inline-flex;
+                font-size: 12px;
+
+                &>span {
+                    padding: 0 5px;
+                    white-space: pre;
+                }
+
+                .paper-owner {
+                    background-color: #ababab;
+                    color: #fff;
+                    border-radius: 5px 0 0 5px;
+                }
+
+                .paper-extType {
+                    border: 1px solid #ababab;
+                    border-radius: 0 5px 5px 0;
+                    border-left: none;
+                }
+
+                .paper-source {
+                    border: 1px solid #ababab;
+                    // border-radius: 0 5px 5px 0;
+                }
+            }
+
+            &:hover {
+                background: linear-gradient(-270deg, #fafafa, #d4ede1);
+                color: #03966a;
+            }
+        }
+    }
+
+    .home-list-title {
+        font-size: 16px;
+        // margin-bottom: 15px;
+        display: flex;
+        justify-content: space-between;
+    }
+
+    .other-box {
+        height: 455px;
+    }
+
+    .no-data {
+        text-align: center;
+        min-height: 455px;
+        padding-top: 80px;
+
+        img {
+            width: 50%;
+        }
+    }
+
+    .no-data-notice {
+
+        text-align: center;
+        min-height: 212px;
+        // padding-top: 40px;
+
+        img {
+            width: 40%;
+        }
+    }
+
+    .list-new {
+        display: flex;
+        align-items: center;
+        border-bottom: 1px solid rgba(0, 0, 0, .1);
+        padding: 15px 10px;
+
+        .list-new-test {
+            display: flex;
+            justify-content: space-between;
+            flex-direction: column;
+        }
+
+        .list-new-img {
+            width: 50%;
+            margin-right: 5px;
+
+            &>img {
+                width: 100%;
+                min-width: 9.5rem;
+                min-height: 4.5rem;
+            }
+        }
+
+        .list-new-icon {
+            margin-right: 15px;
+        }
+    }
+
+    .demo-carousel {
+        margin-bottom: 20px;
+        text-align: center;
+
+        img {
+            width: 100%;
+        }
+    }
+
+    .home-menu {
+        position: absolute;
+        top: 13px;
+        z-index: 99;
+    }
+}
+
+@media screen and (max-width: 1280px) {
+    .home-view {
+        .home-list-title {
+            display: block;
+        }
+
+        .activity-box {
+            height: 305px;
+        }
+
+        .other-box {
+            height: 330px;
+        }
+
+        .home-head .join-class {
+            width: 30%;
+        }
+    }
+}
+
+@media screen and (max-width: 574px) {
+    .home-view {
+        .home-head .join-class {
+            width: 90%;
+        }
+    }
+}

+ 432 - 0
TEAMModelOS/ClientApp/src/components/student-web/HomeView/HomeViewMobile.vue

@@ -0,0 +1,432 @@
+<template>
+    <div class="home-view">
+        <div class="home-menu">
+            <Dropdown trigger="click" @on-click="menuVisible">
+                <a href="javascript:void(0)" class="sidebar-toggle">
+                    <Icon class="menu-icon" type="md-menu" color="#02b35a" />
+                </a>
+                <template #list>
+                    <DropdownMenu>
+                        <DropdownItem :name="item.name" v-for="item in menus" :key="item.name">{{ item.value }}</DropdownItem>
+                    </DropdownMenu>
+                </template>
+            </Dropdown>
+        </div>
+        <div style="overflow: hidden; height: 92vh;">
+            <vuescroll ref="datawrap">
+                <div class="home-head home-card" id="Card1">
+                    <p class="home-title-name">
+                        {{ $t("studentWeb.home.title.joinClass") }}
+                        <Icon type="md-add-circle" color="#02B35A" size="17" title="加入课程" @click="addCourse = true" />
+                    </p>
+                    <div class="home-join" v-if="getAllCourse.length">
+                        <vuescroll>
+                            <div class="join-class" v-for="(item, index) in getAllCourse" :key="index">
+                                <p class="class-name" :title="`${item.name} - ${item.listName}`">{{ item.name }} - {{ item.listName }}</p>
+                                <p class="class-number-time">
+                                    <!-- <span>{{ '班级人数' }}</span> -->
+                                    <span class="paper-item-school">
+                                        <span class="paper-owner" v-if="item.scope === 'school'" style="background-color: #88a1d8;">{{ $t('studentWeb.public.school') }}</span>
+                                        <span class="paper-owner" v-else>{{ $t('studentWeb.public.private') }}</span>
+                                        <span class="paper-extType">
+                                            {{ item.teacherName }}
+                                        </span>
+                                    </span>
+                                    <span>{{ item.courseAddDate }}</span>
+                                </p>
+                            </div>
+                        </vuescroll>
+                    </div>
+                </div>
+                <div class="home-card" id="Card2">
+                    <p class="home-title-name">{{ $t("studentWeb.home.title.classRecord") }}</p>
+                    <div v-if="classRecord.length" class="other-box">
+                        <vuescroll>
+                            <div v-for="(classRecord, cIndex) in classRecord" :key="cIndex" class="list-new">
+                                <!-- <div style="display: flex;"> -->
+                                    <div class="list-new-img">
+                                        <img :src="classRecord.CoverImage ? classRecord.CoverImage : './noData.png'" alt="">
+                                        <p class="list-item-time">{{ classRecord.startTime }}</p>
+                                    </div>
+                                    <div class="list-new-test">
+                                        <p>{{ classRecord.name }}</p>
+                                        <p class="list-item-time" style="color: #76ae38;">{{ classRecord.classNames }}</p>
+                                        <span>
+                                            <Icon type="md-time" color="#24B880" />
+                                            {{ classRecord.time }}
+                                        </span>
+                                    </div>
+                                <!-- </div> -->
+                            </div>
+                        </vuescroll>
+                    </div>
+                    <div v-else class="no-data">
+                        <img src="./noData.png" alt="">
+                        <p>{{ $t("studentWeb.public.noData") }}</p>
+                    </div>
+                </div>
+                <div class="home-card" id="Card3">
+                    <div class="home-list-title">
+                        <p class="home-title-name">{{ $t("studentWeb.home.title.notice1") }}</p>
+                        <div class="select-time">
+                            <Select v-model="timeSelect" size="small" style="width: 100px;">
+                                <Option value="all">{{ $t("studentWeb.home.timeType.title1") }}</Option>
+                                <Option value="today">{{ $t("studentWeb.home.timeType.title2") }}</Option>
+                            </Select>
+                        </div>
+                    </div>
+                    <div class="other-box">
+                        <vuescroll>
+                            <div v-if="!allNotice.length" class="no-data-notice">
+                                <img src="./noData.png" alt="">
+                                <p>{{ $t("studentWeb.public.noData") }}</p>
+                            </div>
+                            <div v-else>
+                                <div v-for="(cNotice, nIndex) in allNotice" :key="nIndex" class="list-new" @click="getNoticeInfo(cNotice)">
+                                    <div class="list-new-icon">
+                                        <Icon custom="iconfont icon-notify" size="30" />
+                                    </div>
+                                    <div class="list-new-test">
+                                        <p class="list-item-title">
+                                            <span>{{ cNotice.title }}</span>
+                                        </p>
+                                        <p>
+                                            {{ cNotice.content }}
+                                        </p>
+                                        <p class="list-item-time">
+                                            {{ cNotice.start }} ~ {{ cNotice.end }}
+                                        </p>
+                                    </div>
+                                </div>
+                            </div>
+                        </vuescroll>
+                    </div>
+                </div>
+                <div class="home-card" id="Card4">
+                <p class="home-title-name">{{ $t("studentWeb.home.loginGuidance.tips1") }}</p>
+                <Carousel>
+                    <CarouselItem>
+                        <div class="demo-carousel">
+                            <img :src="require(`./login-${language}.png`)" alt="">
+                            <span>
+                                {{ $t("studentWeb.home.loginGuidance.tips2") }}
+                                {{ loginUrl }}
+                                {{ $t("studentWeb.home.loginGuidance.tips5") }}
+                            </span>
+                        </div>
+                    </CarouselItem>
+                    <CarouselItem>
+                        <div class="demo-carousel">
+                            <img :src="require(`./student-${language}.png`)" alt="">
+                            <span>{{ $t("studentWeb.home.loginGuidance.tips3") }}</span>
+                        </div>
+                    </CarouselItem>
+                    <CarouselItem>
+                        <div class="demo-carousel">
+                            <img :src="require(`./student-${language}.png`)" alt="">
+                            <span>{{ $t("studentWeb.home.loginGuidance.tips4") }}</span>
+                        </div>
+                    </CarouselItem>
+                </Carousel>
+                </div>
+            </vuescroll>
+        </div>
+    </div>
+</template>
+
+<script>
+import BlobTool from "@/utils/blobTool.js"
+import { mapGetters, mapState } from 'vuex'
+export default {
+    data () {
+        return {
+            MyNo: "11", //接收NavBar 選定的那一頁icon標示
+            MyName: "",
+            isLoading: false,
+            groups: {
+                school: [],
+                private: [],
+            },
+            classIds: [],
+            classRecord: [], //课堂记录
+            activityList: [], //活动
+            classNotice: [], //班级公告
+            courseNotice: [], //课程公告
+            allNotice: [],
+            timeSelect: "all",
+            menus: [{
+                    name: '1',
+                    value: this.$t("studentWeb.home.menus.title1")
+                }, {
+                    name: '2',
+                    value: this.$t("studentWeb.courseContent.classRecord")
+                }, {
+                    name: '3',
+                    value: this.$t("studentWeb.home.title.notice1")
+                }, {
+                    name: '4',
+                    value: this.$t("studentWeb.home.menus.title2")
+                }
+            ],
+        }
+    },
+    mounted () {
+        this.MyName = this.$t("studentWeb.homeViewTitle")
+        this.$emit("onNavNo", this.MyNo)
+        this.$emit("onNavName", this.MyName)
+        this.getGroupList()
+        console.log(window.location.host);
+    },
+    methods: {
+        getGroupList() {
+            // return new Promise(resolve => {
+                this.isLoading = true
+                this.groups = {
+                    school: [],
+                    private: [],
+                }
+                this.classRecord = []
+                // this.getSas(this.userInfo.azp)
+                this.$api.studentWeb.getAllGrouplist({}).then(res => {
+                    if(res.groups.length) {
+                        let groupIds = []
+                        this.classIds = [...res.groups]
+                        res.groups.forEach(item => {
+                            if(item.scope === 'school') {
+                                this.groups.school.push(item.id)
+                            } else if(item.scope === 'private') {
+                                this.groups.private.push(item.id)
+                            }
+                            groupIds.push(item.id)
+                        })
+                        this.getSchool("school", this.groups.school)
+                        this.getNotice(groupIds)
+                    }
+                }).finally(() => {
+                    // resolve(groups)
+                })
+            // })
+        },
+        getNotice(classes) {
+            this.classNotice = []
+            this.courseNotice = []
+            this.$api.studentWeb.getAllNotice({classes}).then(async res => {
+                // type:class(班级公告)  course(课程公告)
+                if(res.notices.length) {
+                    let teaIds = []
+                    res.notices.forEach(item => {
+                        teaIds.push(item.creatorId)
+                    })
+                    let teaidNames = await this.getTeacherName(teaIds)
+                    res.notices.forEach(item => {
+                        item.start = this.dateFormat(item.startTime)
+                        item.end = this.dateFormat(item.endTime)
+                        item.className = []
+                        item.classes.forEach(classes => {
+                            let names = this.classIds.find(ids => {
+                                return ids.id === classes
+                            })
+                            if(names) {
+                                item.className.push(names.name)
+                            }
+                        })
+                        let nameIds = teaidNames.find(names => {
+                            return names.id === item.creatorId
+                        })
+                        item.teacherName = !nameIds ? undefined : nameIds.name
+                        if(item.type === "class") {
+                            this.classNotice.push(item)
+                        } else {
+                            this.courseNotice.push(item)
+                        }
+                        this.allNotice = this.classNotice.concat(this.courseNotice)
+                    })
+                }
+            })
+        },
+        getSchool(type, groupIds, end) {
+            if(groupIds.length) {
+                let param = {
+                    scope: type, //school:传school,private:传tmdid
+                    school: type === "school" ? this.userInfo.azp : "",
+                    category: [],
+                    subjectId: [],
+                    grade: [],
+                    doubleGreen: false,
+                    quality: false,
+                    DESC: "startTime",
+                    pageCount: 999, //返回六条数据(分页)
+                    // week: true,
+                    today: false,
+                    continuationToken: null, //返回的有值的话,下次查询就要用这个值
+                    groupIds,
+                }
+                this.$api.studentWeb.getClassRecord(param).then(async res => {
+                    if(res.lessonRecords.length) {
+                        let creatId = []
+                        let sasInfo = undefined
+                        if(type === "school") {
+                            sasInfo = await this.getSas(this.userInfo.azp)
+                        }
+                        res.lessonRecords.forEach(item => {
+                            item.startTime = this.dateFormat(item.startTime)
+                            let sec = item.duration % 60
+                            let min = parseInt(item.duration / 60)
+                            let mins = min >= 60 ? min % 60 : min
+                            let hour = parseInt(min / 60)
+                            item.time = `${hour < 10 ? ('0' + hour) : hour}:${mins < 10 ? ('0' + mins) : mins}:${sec < 10 ? ('0' + sec) : sec}`
+                            if(type === "school") {
+                                item.eNote = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Note.pdf?${sasInfo.sas}`
+                                item.CoverImage = `${sasInfo.url}/${sasInfo.name}/records/${item.id}/Record/CoverImage.jpg?${sasInfo.sas}`
+                            } else {
+                                if(!creatId.includes(item.tmdid)) {
+                                    creatId.push(item.tmdid)
+                                }
+                                item.eNote = ""
+                                item.CoverImage = ""
+                            }
+                            let className = this.getAllCourse.find(course => {
+                                return item.courseId === course.id || item.courseId === course.subject.id
+                            })
+                            item.classNames = className ? className.name : ""
+                            item.myNote = []
+                            this.classRecord.push(item)
+                        })
+                        if(type === "private") {
+                            creatId.forEach(async item => {
+                                let sasInfoP = await this.getSas(item)
+                                this.classRecord = this.classRecord.map(record => {
+                                    if(record.scope === "private" && record.tmdid === item) {
+                                        record.eNote = `${sasInfoP.url}/${sasInfoP.name}/records/${record.id}/Note.pdf?${sasInfoP.sas}`
+                                        record.CoverImage = `${sasInfoP.url}/${sasInfoP.name}/records/${record.id}/Record/CoverImage.jpg?${sasInfoP.sas}`
+                                    }
+                                    return record
+                                })
+                                await this.getTrainFiles(sasInfoP, "private")
+                            })
+                        } else {
+                            this.getTrainFiles(sasInfo, "school")
+                        }
+                    }
+                    if(!end) {
+                        this.getSchool("private", this.groups.private, true)
+                    }
+                }).finally(() => {
+                    this.isLoading = false
+                })
+            } else if(!end) {
+                this.getSchool("private", this.groups.private, true)
+            }
+        },
+        // 查找活动的视频和文件
+        getTrainFiles(sasInfo, scope) {
+            return new Promise((r, j) => {
+                let blobTool = new BlobTool(sasInfo.url, sasInfo.name, "?" + sasInfo.sas, scope)
+                let promiseArr = []
+                let recList = [...this.classRecord]
+                if(scope === "school") {
+                    recList.forEach((item, index) => {
+                        promiseArr.push(new Promise((r, j) => {
+                            blobTool.listBlob({
+                                prefix: `records/${item.id}/Clients/${this.userInfo.sub}/Task/NoteSelfNote`
+                            }).then(
+                                res => {
+                                    let imgList = []
+                                    res.blobList.forEach(list => {
+                                        imgList.push(`${list.url}?${sasInfo.sas}`)
+                                    })
+                                    this.classRecord[index].myNote = imgList
+                                    r(res)
+                                },
+                                err => {
+
+                                }
+                            )
+                        }))
+                    })
+                } else {
+                    recList.forEach((item, index) => {
+                        if(item.scope === "private" && item.tmdid === sasInfo.name) {
+                            promiseArr.push(new Promise((r, j) => {
+                                blobTool.listBlob({
+                                    prefix: `records/${item.id}/Clients/${this.userInfo.sub}/Task/NoteSelfNote`
+                                }).then(
+                                    res => {
+                                        let imgList = []
+                                        res.blobList.forEach(list => {
+                                            imgList.push(`${list.url}?${sasInfo.sas}`)
+                                        })
+                                        this.classRecord[index].myNote = imgList
+                                        r(res)
+                                    },
+                                    err => {
+
+                                    }
+                                )
+                            }))
+                        }
+                    })
+                }
+                Promise.all(promiseArr).then(res => {
+                })
+            })
+        },
+        getTeacherName(id) {
+            return new Promise((r, j) => {
+                this.$api.studentWeb.getTeacherName({id}).then(res => {
+                    r(res)
+                }).catch(e => {
+                    j(e)
+                })
+            })
+        },
+        //时间格式化处理
+        dateFormat(timestamp) {
+            var date = new Date(timestamp)
+            var Y = date.getFullYear() + '-'
+            var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'
+            var D = (date.getDate() < 10 ? '0' + (date.getDate()) : date.getDate()) + ' '
+            var H = (date.getHours() < 10 ? '0' + date.getHours() : date.getHours()) + ":"
+            var Min = (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
+            var S = (date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds()) + " "
+            return Y + M + D + H + Min;
+        },
+        getSas(info) {
+            return new Promise(async (r, j) => {
+                let code = info
+                let sasInfo = await this.$tools.getBlobSas(code)
+                r(sasInfo)
+            })
+        },
+        menuVisible(value) {
+            // document.getElementById(`Card${value}`).scrollIntoView({behavior: "smooth", inline: "nearest"})
+            
+            this.$refs["datawrap"].scrollIntoView('#Card' + value, 0)
+        },
+    },
+    computed: {
+        ...mapGetters(['getAllCourse']),
+        ...mapState({userInfo: state => state.userInfo,}),
+        language() {
+            return localStorage.getItem('local')
+        },
+        loginUrl() {
+            return window.location.host
+        },
+    }
+}
+</script>
+
+<style lang="less" scoped>
+@import './HomeViewMobile.less';
+.home-view {
+    .home-title-name {
+        font-size: 16px;
+        border-left: 5px solid #24b880;
+        padding-left: 10px;
+        height: 20px;
+        line-height: 20px;
+        margin-bottom: 10px;
+    }
+}
+</style>

TEMPAT SAMPAH
TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-en-us.png


TEMPAT SAMPAH
TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-zh-cn.png


TEMPAT SAMPAH
TEAMModelOS/ClientApp/src/components/student-web/HomeView/login-zh-tw.png


TEMPAT SAMPAH
TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-en-us.png


TEMPAT SAMPAH
TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-zh-cn.png


TEMPAT SAMPAH
TEAMModelOS/ClientApp/src/components/student-web/HomeView/student-zh-tw.png


+ 10 - 0
TEAMModelOS/ClientApp/src/router/routes.js

@@ -110,6 +110,11 @@ export const routes = [{
     path: '/sso',
     component: () => import('@/view/sso/Index.vue')
 },
+//单点登录-学生端
+{
+    path: '/student',
+    component: () => import('@/view/sso/StudentIndex.vue')
+},
 {
     path: '/schoolList',
     component: () => import('@/view/Home'),
@@ -1361,6 +1366,11 @@ export const routes = [{
             path: "homeView",
             component: () => import('@/components/student-web/HomeView/newHomeView'),
         },
+        {
+            name: "HomeViewMobile",
+            path: "homeViewMobile",
+            component: () => import('@/components/student-web/HomeView/HomeViewMobile'),
+        },
         {
             name: "courseList",
             path: "courseList",

+ 29 - 19
TEAMModelOS/ClientApp/src/view/areaArtExam/Mgt.vue

@@ -34,14 +34,14 @@
                         评价指标
                     </span>
                 </div>
-                <DataView v-model="schoolId" @on-school-change="handleSchoolChange(1)" :artInfo="artInfo" :quotaFirstLevel="quotaFirstLevel" :classList="classList" v-if="curBarIndex === 0" :schoolList="schoolList"></DataView>
+                <DataView v-model="schoolId" @on-school-change="handleSchoolChange(1)" :artInfo="artInfo" :quotaFirstLevel="quotaFirstLevel" :classList="classList" v-if="curBarIndex === 0" :schoolList="schoolListShow"></DataView>
                 <div v-else-if="curBarIndex === 1" class="quo-detail-wrap">
                     <vuescroll style="background:white">
                         <Tabs v-model="tabName" style="padding: 0px 10px;margin-top:15px">
                             <template slot="extra">
                                 <div class="art-filter-wrap">
                                     <Select v-model="schoolId" style="width: 200px;margin-right:10px" placeholder="学校" transfer @on-change="handleSchoolChange(2)">
-                                        <Option v-for="item in schoolList" :value="item.id" :key="item.id">{{ item.name }}</Option>
+                                        <Option v-for="item in schoolListShow" :value="item.id" :key="item.id">{{ item.name }}</Option>
                                     </Select>
                                     <Select v-model="classId" style="width: 200px;margin-right:10px" placeholder="班级">
                                         <Option v-for="item in classList" :value="item.id" :key="item.id">{{ item.name }}</Option>
@@ -72,9 +72,9 @@ export default {
     },
     data() {
         return {
-            hasPublish:true,
-            schoolId:'',
-            schoolList:[],
+            hasPublish: true,
+            schoolId: '',
+            schoolList: [],
             tabName: '',
             split: 0.2,
             artList: [],
@@ -120,21 +120,31 @@ export default {
         },
         subjectList() {
             return this.artInfo?.subjects || []
+        },
+        schoolListShow() {
+            if (this.artList[this.curIndex].sc && this.schoolList.length) {
+                let data = this.schoolList.filter(item => {
+                    let has = this.artList[this.curIndex].sc?.find(s => item.id === s.code)
+                    return !!has
+                })
+                return data
+            }
+            return this.schoolList
         }
     },
     methods: {
-        handleSchoolChange(value){
+        handleSchoolChange(value) {
             console.log(value)
             this.findArtSummary()
         },
-        getAreaSchoolList(){
+        getAreaSchoolList() {
             this.$api.areaArt.findAreaSchoolList({
-                id:sessionStorage.getItem('areaId')
+                id: sessionStorage.getItem('areaId')
             }).then(
-                res=>{
+                res => {
                     this.schoolList = res.sc
                 },
-                err=>{
+                err => {
                     this.$Message.error("获取学校列表失败")
                 }
             )
@@ -169,9 +179,9 @@ export default {
                 onOk: () => {
                     let requestData = {
                         id: this.artList[this.curIndex].id,
-                        code: this.$store.state.userInfo.schoolCode
+                        areaId: sessionStorage.getItem('areaId')
                     }
-                    this.$api.areaArt.delArt(requestData).then(
+                    this.$api.areaArt.delAreaArt(requestData).then(
                         res => {
                             this.$Message.success(this.$t('ae.ae33'))
                             let index = this.curIndex
@@ -191,7 +201,7 @@ export default {
             this.subjectId = ''
             this.curIndex = index
             //TODO过滤学校
-            this.schoolId = this.schoolList[0] ?  this.schoolList[0].id : ''
+            this.schoolId = this.schoolListShow[0] ? this.schoolListShow[0].id : ''
             this.findArtSummary()
         },
         toCreate() {
@@ -213,9 +223,9 @@ export default {
             )
         },
         findArtSummary() {
-            if(!this.schoolId) return
-            let sArt = this.artList[this.curIndex].sc?.find(item=>item.code === this.schoolId)
-            if(!sArt) return
+            if (!this.schoolId) return
+            let sArt = this.artList[this.curIndex].sc?.find(item => item.code === this.schoolId)
+            if (!sArt) return
             let sId = sArt.id
             this.classList = []
             let params = {
@@ -235,7 +245,7 @@ export default {
                     this.classes = []
                     if (this.artInfo?.classes?.length) {
                         this.getClassList()
-                    }else{
+                    } else {
                         this.hasPublish = false
                     }
                 },
@@ -303,7 +313,7 @@ export default {
             handler(n, o) {
                 if (n && n.length) {
                     this.classId = n[0].id
-                }else{
+                } else {
                     this.classId = ''
                 }
             }
@@ -323,7 +333,7 @@ export default {
 </script>
 
 <style lang="less" scoped>
-.art-exam-list-wrap{
+.art-exam-list-wrap {
     height: 100%;
 }
 .quo-detail-wrap {

+ 27 - 6
TEAMModelOS/ClientApp/src/view/artexam/Create.vue

@@ -44,6 +44,11 @@
                     <FormItem :label="$t('ae.ae7')" prop="time" style="margin-top: 30px">
                         <DatePicker v-model="artInfo.time" transfer type="datetimerange" placement="bottom-start" :placeholder="$t('ae.ae8')" @on-change="handleSetTime" style="width: 100%"></DatePicker>
                     </FormItem>
+                    <FormItem label="学校" style="margin-top: 30px">
+                        <Select v-model="artInfo.schools" style="" multiple placeholder="请选择施测学校,默认所有学校">
+                            <Option v-for="item in schoolList" :value="item.id" :key="item.id">{{ item.name }}</Option>
+                        </Select>
+                    </FormItem>
                 </Form>
                 <!-- 高级设置 -->
                 <Form ref="seniorInfo" :model="artInfo" :rules="trainRule" :label-width="100" class="art-form" label-colon v-show="step == 1">
@@ -120,6 +125,7 @@ export default {
         };
         let _this = this
         return {
+            schoolList:[],
             examInfoList:[],
             isArea: false,
             defaultQuos: ['quota_2'],
@@ -151,7 +157,8 @@ export default {
                 time: [],
                 targets: [],
                 subjects: [],
-                setting: []
+                setting: [],
+                schools:[]
             },
             settingDetail: {},
             baseRule: {
@@ -290,8 +297,7 @@ export default {
             })
         },
         handleCheckChange(data) {
-            if (!this.settingDetail[data.quoid])
-                this.settingDetail[data.quoid] = {}
+            if (!this.settingDetail[data.quoid])this.settingDetail[data.quoid] = {}
             this.settingDetail[data.quoid]["checked"] = data.data
         },
         handleTypeChange(data) {
@@ -448,7 +454,8 @@ export default {
                     promise = this.$api.areaArt.saveAreaArt({
                         id: sessionStorage.getItem("areaId"),
                         art: params,
-                        artExam:this.examInfoList
+                        artExam:this.examInfoList,
+                        schoolId: this.artInfo.schools.length ? this.artInfo.schools : undefined
                     })
                 } else {
                     promise = this.$api.areaArt.saveArt({
@@ -669,7 +676,6 @@ export default {
         },
         checkSettingInfo() {
             let isErr = false
-            console.log(this.settingDetail)
             let settings = Object.keys(this.settingDetail)
             if (!settings.length || (settings.length != this.artInfo.setting.length)) {
                 return this.$Message.error(this.$t('ae.ae39'))
@@ -726,13 +732,28 @@ export default {
         treeChange(data) {
             console.log(data)
             this.artInfo.targets = data.map((item) => item[1])
-        }
+        },
+        getAreaSchoolList(){
+            this.$api.areaArt.findAreaSchoolList({
+                id:sessionStorage.getItem('areaId')
+            }).then(
+                res=>{
+                    this.schoolList = res.sc
+                },
+                err=>{
+                    this.$Message.error("获取学校列表失败")
+                }
+            )
+        },
     },
     created() {
         this.getAreaSetting()
         console.log(this.$route)
         // 判断是否为区级发布
         this.isArea = this.$route.name === 'areaCreateArtMgt'
+        if(this.isArea){
+            this.getAreaSchoolList()
+        }
     }
 }
 </script>

+ 113 - 114
TEAMModelOS/ClientApp/src/view/artexam/QuoTree.vue

@@ -1,123 +1,122 @@
 <template>
-	<el-tree
-		show-checkbox
-		:data="treeData"
-		:props="defaultProps"
-		class="quo-tree"
-		node-key="id"
-		ref="tree"
-		:render-content="renderContent"
-        @check="hanldeCheckChange"
-		:render-after-expand="false"
-		:default-checked-keys="['quota_21','quota_22']"
-	></el-tree>
+    <el-tree show-checkbox :data="treeData" :props="defaultProps" class="quo-tree" node-key="id" ref="quota-tree" :render-content="renderContent" @check="hanldeCheckChange" :render-after-expand="false"></el-tree>
 </template>
 
 <script>
 import ExamSubject from "./ExamSubject.vue"
 import WorkSubject from "./WorkSubject.vue"
 export default {
-	components: {
-		ExamSubject,
-		WorkSubject
-	},
-	props: {
-		quoid: {
-			type: String,
-			default: ""
-		},
-		treeData: {
-			type: Array,
-			default: () => {
-				return []
-			}
-		},
-		subjects: {
-			type: Array,
-			default: () => {
-				return []
-			}
-		}
-	},
-	data() {
-		return {
-			defaultProps: {
-				children: "children",
-				label: "name"
-			},
-			settingMap: {}
-		}
-	},
-	methods: {
-		renderContent(h, { node, data, store }) {
-			console.log(arguments)
-			let _this = this
-			// 不是最后一个节点则直接渲染label
-			if (node.childNodes.length) {
-				return h("span", {}, node.label)
-			} else {
-				return h(
-					"div",
-					{
-						style: {
-							width: "100%"
-						}
-					},
-					[
-						h("span", node.label),
-						h('Tag',{
-							class: "type-setting",
-							props:{
-								color:'primary'
-							},
-							style: {
-								display: node.checked && (node.data.type == 1 || node.data.type == 2) ? undefined : "none"
-							}
-						},node.data.type == 1 ? _this.$t('ae.ae0') : node.data.type == 2 ? _this.$t('ae.ae1') : ''),
-						node.checked && node.data.type === 1
-							? h(ExamSubject, {
-									props:{
-										subjects: _this.subjects
-									},
-									on: {
-										"on-set-exam": (data) => {
-											console.log(data)
-											_this.$set(_this.settingMap,node.data.id,data)
-										}
-									}
-							  })
-							: undefined,
-						node.checked && node.data.type === 2
-							? h(WorkSubject, {
-									props:{
-										subjects: _this.subjects
-									},
-									on:{
-										"on-set-work": (data) => {
-											console.log(data)
-											_this.$set(_this.settingMap,node.data.id,data)
-										}
-									}
-							  })
-							: undefined
-					]
-				)
-			}
-		},
-        hanldeCheckChange(data,status){
-            this.$emit('on-check-change',{
-                quoid:this.quoid,
-                data:status
+    components: {
+        ExamSubject,
+        WorkSubject
+    },
+    props: {
+        quoid: {
+            type: String,
+            default: ""
+        },
+        treeData: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        },
+        subjects: {
+            type: Array,
+            default: () => {
+                return []
+            }
+        }
+    },
+    data() {
+        return {
+            defaultProps: {
+                children: "children",
+                label: "name"
+            },
+            settingMap: {}
+        }
+    },
+    methods: {
+        renderContent(h, { node, data, store }) {
+            console.log(arguments)
+            let _this = this
+            // 不是最后一个节点则直接渲染label
+            if (node.childNodes.length) {
+                return h("span", {}, node.label)
+            } else {
+                return h(
+                    "div",
+                    {
+                        style: {
+                            width: "100%"
+                        }
+                    },
+                    [
+                        h("span", node.label),
+                        h('Tag', {
+                            class: "type-setting",
+                            props: {
+                                color: 'primary'
+                            },
+                            style: {
+                                display: node.checked && (node.data.type == 1 || node.data.type == 2) ? undefined : "none"
+                            }
+                        }, node.data.type == 1 ? _this.$t('ae.ae0') : node.data.type == 2 ? _this.$t('ae.ae1') : ''),
+                        node.checked && node.data.type === 1
+                            ? h(ExamSubject, {
+                                props: {
+                                    subjects: _this.subjects
+                                },
+                                on: {
+                                    "on-set-exam": (data) => {
+                                        console.log(data)
+                                        _this.$set(_this.settingMap, node.data.id, data)
+                                    }
+                                }
+                            })
+                            : undefined,
+                        node.checked && node.data.type === 2
+                            ? h(WorkSubject, {
+                                props: {
+                                    subjects: _this.subjects
+                                },
+                                on: {
+                                    "on-set-work": (data) => {
+                                        console.log(data)
+                                        _this.$set(_this.settingMap, node.data.id, data)
+                                    }
+                                }
+                            })
+                            : undefined
+                    ]
+                )
+            }
+        },
+        hanldeCheckChange(data, status) {
+            this.$emit('on-check-change', {
+                quoid: this.quoid,
+                data: status
+            })
+        }
+    },
+    mounted() {
+        let quaTree = this.$refs['quota-tree']
+        if (this.quoid === 'quota_2' && quaTree) {
+            quaTree.setCheckedKeys(['quota_21', 'quota_22'])
+            this.hanldeCheckChange(undefined, {
+                checkedKeys: quaTree.getCheckedKeys(),
+                checkedNodes: quaTree.getCheckedNodes()
             })
         }
-	},
-    watch:{
-        settingMap:{
-            deep:true,
-            handler(n,o){
-                this.$emit('on-setting-change',{
-                    quoid:this.quoid,
-                    data:n
+    },
+    watch: {
+        settingMap: {
+            deep: true,
+            handler(n, o) {
+                this.$emit('on-setting-change', {
+                    quoid: this.quoid,
+                    data: n
                 })
             }
         },
@@ -130,10 +129,10 @@ export default {
 </style>
 <style lang="less">
 .type-setting {
-	float: right;
+    float: right;
 }
 .quo-tree .el-tree-node__content {
-	height: fit-content;
-	align-items: baseline;
+    height: fit-content;
+    align-items: baseline;
 }
 </style>

+ 10 - 3
TEAMModelOS/ClientApp/src/view/auth/Product.vue

@@ -31,7 +31,7 @@
                             </Button>
                             <p class="product-status" style="margin-top:5px" v-show="item.isPay">
                                 <!-- 时间 -->
-                                <span>
+                                <span v-if="!item.isFov">
                                     {{$t('auth.expired')}}
                                     <span class="expire-time">
                                         {{$jsFn.dateFormat(item.start)}}
@@ -41,6 +41,9 @@
                                         {{$jsFn.dateFormat(item.end)}}
                                     </span>
                                 </span>
+                                <span v-else style="color:#2db7f5;font-weight:800;font-size:18px">
+                                    {{$t('auth.longTime')}}
+                                </span>
                             </p>
                         </div>
                     </div>
@@ -248,6 +251,7 @@ export default {
                     name: this.$t('auth.module1'),
                     start: 0,
                     end: 0,
+                    isFov: false,
                     image: require("@/assets/image/module2.jpg"),
                     content: this.$t('auth.content1'),
                     isPay: 0,
@@ -260,6 +264,7 @@ export default {
                     name: this.$t('auth.module2'),
                     start: 0,
                     end: 0,
+                    isFov: false,
                     image: require("@/assets/image/module1.jpg"),
                     content: this.$t('auth.content2'),
                     isPay: 0,
@@ -272,6 +277,7 @@ export default {
                     name: this.$t('auth.module3'),
                     start: 0,
                     end: 0,
+                    isFov: false,
                     image: require("@/assets/image/module3.jpg"),
                     content: this.$t('auth.content3'),
                     isPay: 0,
@@ -365,8 +371,9 @@ export default {
                 let svc = services.find(s => s.prodCode == item.prodCode)
                 if (svc) {
                     item.isPay = 1
-                    item.start = svc.avaliableStartDate 
-                    item.end = svc.avaliableEndDate 
+                    item.start = svc.avaliableStartDate
+                    item.end = svc.avaliableEndDate
+                    item.isFov = new Date(svc.avaliableEndDate * 1000).getFullYear() >= 2200 ? true : false
                 }
             })
             //获取学校规模授权数量

+ 75 - 0
TEAMModelOS/ClientApp/src/view/sso/StudentIndex.vue

@@ -0,0 +1,75 @@
+<template>
+    <div class="sso-container">
+        <img class="tmd-logo" src="/favicon.ico" alt="">
+        <h1 class="title">学生端登录</h1>
+    </div>
+</template>
+
+<script>
+import jwtDecode from 'jwt-decode'
+export default {
+    data () {
+        return {
+            routerData: undefined,
+        }
+    },
+    created () {
+        this.routerData = this.$route.query
+        if(this.routerData.code) {
+            this.checkIESCode(this.routerData.code)
+        } else {
+            this.$Message.error({
+                content: '跳转参数错误,验证失败',
+                duration: 2
+            })
+        }
+    },
+    methods: {
+        checkIESCode(code) {
+            //获取登录信息
+            let addr = this.$store.state.config.srvAdr
+            let host = addr == 'Global' ? this.$store.state.config.Global.coreAPIUrl : this.$store.state.config.China.coreAPIUrl
+            let clientId = addr == 'Global' ? this.$store.state.config.Global.clientID : this.$store.state.config.China.clientID
+            this.$api.service.getToken(host, {
+                grant_type: "authorization_code",
+                client_id: clientId,
+                code: code
+            }).then(
+                res => {
+                    if (!res.error) {
+                        this.$loginTools.stuLoginById(res)
+                        this.$router.push({
+                            path: '/studentWeb/homeViewMobile',
+                            // query: {code: code}
+                        })
+                    } else {
+                        this.$Message.error(this.$t('cusMgt.join.getErr'))
+                    }
+                },
+                err => {
+                    this.$Message.error(this.$t('cusMgt.join.getErr'))
+                }
+            )
+        },
+    }
+}
+</script>
+
+<style scoped lang="less">
+.sso-container {
+    display: flex;
+    flex-direction: row;
+    justify-content: center;
+    align-items: center;
+    width: 100%;
+    height: 100%;
+    background-image: url("../../assets/image/bak_light.jpg");
+    .title {
+        color: #f0f0f0;
+        margin-left: 30px;
+    }
+    .tmd-logo {
+        width: 40px;
+    }
+}
+</style>

+ 22 - 16
TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue

@@ -4,11 +4,11 @@
         <div class="myNav">
             <div>
                 <span @click="clickSidebarToggle()" v-if="MyNo != '1' && MyNo != '4' && MyNo != 'X' && MyNo != '7' && MyNo != '8'" class="sidebar-toggle">
-                    <Icon class="menu-icon" type="md-menu" :class="{'menu-icon-close': this.$store.getters.getSidebarisOpen == false}" />
+                    <Icon class="menu-icon" type="md-menu" :class="{'menu-icon-close': this.$store.getters.getSidebarisOpen == false}" v-if="MyNo != '11'" />
                 </span>
                 <span :class="['mytitle', {'no-show-title': MyNo === '1'}]">{{ MyName }}</span>
             </div>
-            <div :class="courseList.length && !onlySystem ? 'selectClass' : 'addClass'">
+            <div :class="courseList.length && !onlySystem ? 'selectClass' : 'addClass'" v-if="MyNo != '11'">
                 <template v-if="courseList.length && !onlySystem">
                     <Select v-model="selectClass" style="width:250px" clearable filterable :placeholder="$t('cusMgt.sltCusTips')" @on-change="classChange">
                         <Option v-for="(item, cIndex) in courseList" :value="cIndex + 1" :label="item.showName" :key="cIndex">
@@ -110,7 +110,7 @@
                     <div id="stuPhoto">
                         <img v-if="userInfo.picture" :src="userInfo.picture" alt="" width="35" height="35" />
                             <PersonalPhoto v-if="!userInfo.picture && userInfo.name !== undefined" class="avatar-link" :width="'35px'" :height="'35px'" :fontSize="'0.8rem'" :name="userInfo.name" color="#00AD6C" />
-                        <span style="margin-left: 5px;">{{ userInfo.name }}</span>
+                        <span style="margin-left: 5px;" v-if="windowWidth >= 852">{{ userInfo.name }}</span>
                     </div>
                     <div id="profile-pop">
                         <div class="profile-name">
@@ -121,19 +121,15 @@
                             </template>
                         </div>
                         <template v-if="windowWidth < 852">
-                            <div class="profile-pop-item" @click="goto('/studentWeb/homeView')">
+                            <div class="profile-pop-item" @click="goto('/studentWeb/homeView')" v-if="MyNo != '11'">
                                 <svg-icon icon-class="home" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.type.home') }}
                             </div>
-                            <div class="profile-pop-item" @click="goto('/studentWeb/achievement')">
-                                <Icon custom="iconfont icon-chengjitongji" size="16" class="profile-pop-icon" style="font-weight: bold;" />
-                                {{ $t('studentWeb.type.achievement') }}
-                            </div>
                             <!-- <div class="profile-pop-item" @click="goto('/studentWeb/wrongQues')">
                                 <Icon custom="iconfont icon-cuotiji" size="16" class="profile-pop-icon" />
                                 {{ $t('studentWeb.type.wrongTopic') }}
                             </div> -->
-                            <div class="profile-pop-item" @click="goto('/studentWeb/eventView')">
+                            <div class="profile-pop-item" @click="goto('/studentWeb/eventView')" v-if="MyNo != '11'">
                                 <svg-icon icon-class="selflearning" style="margin-left: 3px; margin-right: -3px;" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.type.activity') }}
                             </div>
@@ -141,20 +137,24 @@
                                 <svg-icon icon-class="course" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.course') }}
                             </div> -->
-                            <div class="profile-pop-item" @click="goto('/studentWeb/classRecord')" v-show="selectClass">
-                                <svg-icon icon-class="course" style="margin-left: 2px; margin-right: -2px;" class="profile-pop-icon profile-pop-icon-1" />
-                                {{ $t('studentWeb.courseContent.classRecord') }}
+                            <div class="profile-pop-item" @click="goto('/studentWeb/homeworkView')" v-show="selectClass">
+                                <svg-icon icon-class="doc" class="profile-pop-icon profile-pop-icon-1" />
+                                {{ $t('studentWeb.type.homework') }}
                             </div>
                             <div class="profile-pop-item" @click="goto('/studentWeb/examView')" v-show="selectClass">
                                 <svg-icon icon-class="test" style="margin-left: 2px; margin-right: -2px;" class="profile-pop-icon profile-pop-icon-1" />
                                 {{ $t('studentWeb.type.exam') }}
                             </div>
-                            <div class="profile-pop-item" @click="goto('/studentWeb/homeworkView')" v-show="selectClass">
-                                <svg-icon icon-class="doc" class="profile-pop-icon profile-pop-icon-1" />
-                                {{ $t('studentWeb.type.homework') }}
+                            <div class="profile-pop-item" @click="goto('/studentWeb/classRecord')" v-show="selectClass && !onlySystem && !courseList[selectClass - 1].isSystem">
+                                <svg-icon icon-class="course" style="margin-left: 2px; margin-right: -2px;" class="profile-pop-icon profile-pop-icon-1" />
+                                {{ $t('studentWeb.courseContent.classRecord') }}
+                            </div>
+                            <div class="profile-pop-item" @click="goto('/studentWeb/achievement')" v-show="selectClass">
+                                <Icon custom="iconfont icon-chengjitongji" size="16" class="profile-pop-icon" style="font-weight: bold;" />
+                                {{ $t('studentWeb.type.achievement') }}
                             </div>
                         </template>
-                        <div class="profile-pop-item" @click="goto(getSrvAdr, true)">
+                        <div class="profile-pop-item" @click="goto(getSrvAdr, true)" v-if="MyNo != '11'">
                             <Icon custom="iconfont icon-ketanghudonghangwei" size="16" class="profile-pop-icon" style="font-weight: bold;" />
                             {{ $t('studentWeb.type.classInteraction') }}
                         </div>
@@ -602,6 +602,7 @@ export default {
                                         listName: listName ? listName.name : "",
                                         showName: `${item.course.name}(${sch.teacherName}-${listName ? listName.name : ""})`,
                                         courseAddDate,
+                                        createTime: item.stuCourse.createTime,
                                     })
                                 }
                             })
@@ -628,6 +629,7 @@ export default {
                                 listName: this.user.studentProfile.classinfo.name,
                                 showName: `基本课程-系统(系统-${this.user.studentProfile.classinfo.name})`,
                                 courseAddDate: "",
+                                createTime: 0,
                                 isSystem: true,
                             }
                             this.courseList.unshift(admClass)
@@ -656,10 +658,14 @@ export default {
                         listName: this.user.studentProfile.classinfo.name,
                         showName: `基本课程-系统(系统-${this.user.studentProfile.classinfo.name})`,
                         courseAddDate: "",
+                        createTime: 0,
                         isSystem: true,
                     }
                     this.courseList.push(admClass)
                 }
+                this.courseList.sort(function (a, b) {
+                    return b.createTime - a.createTime //时间正序
+                })
                 this.$store.commit("setAllCourse", this.courseList)
             })
         },

+ 63 - 2
TEAMModelOS/Controllers/Client/HiTAControlller.cs

@@ -89,7 +89,7 @@ namespace TEAMModelOS.Controllers.Client
         /// <returns></returns>
         [ProducesDefaultResponseType]
         [HttpGet("join-school")]
-        //[Authorize(Roles = "HiTA")]
+        [Authorize(Roles = "HiTA")]
         public async Task<IActionResult> ScanCodeJoinSchool([FromQuery] HiTAJoinSchool join)
         {
             string school = join.school;
@@ -235,7 +235,7 @@ namespace TEAMModelOS.Controllers.Client
             return Ok(new { schoolTeacher.roles, schoolTeacher.status, school = $"{school}", schoolInfo.name, schoolInfo.picture });
         }
 
-        //[Authorize(Roles = "HiTA")]
+        [Authorize(Roles = "HiTA")]
         [ProducesResponseType(StatusCodes.Status200OK)]
         [ProducesResponseType(StatusCodes.Status400BadRequest)]
         [ProducesDefaultResponseType]
@@ -517,5 +517,66 @@ namespace TEAMModelOS.Controllers.Client
                 return BadRequest();
             }
         }
+
+        [Authorize(Roles = "HiTA")]
+        [ProducesResponseType(StatusCodes.Status200OK)]
+        [ProducesResponseType(StatusCodes.Status400BadRequest)]
+        [ProducesDefaultResponseType]
+        [HttpPost("get-school-list")]
+        public async Task<IActionResult> GetSchoolListByRegion(JsonElement request)
+        {
+            try
+            {
+                //參數取得
+                if (!request.TryGetProperty("regionName", out JsonElement regionNameJson)) return BadRequest();
+                if (!request.TryGetProperty("provinceName", out JsonElement provinceNameJson)) return BadRequest();
+                if (!request.TryGetProperty("cityName", out JsonElement cityNameJson)) return BadRequest();
+                if (string.IsNullOrWhiteSpace(Convert.ToString(regionNameJson))) return BadRequest();
+                string regionName = Convert.ToString(regionNameJson);
+                string provinceName = (provinceNameJson.ValueKind.Equals(JsonValueKind.Null)) ? null : Convert.ToString(provinceNameJson);
+                string cityName = (cityNameJson.ValueKind.Equals(JsonValueKind.Null)) ? null : Convert.ToString(cityNameJson);
+                regionName = regionName.Replace("地區", "").Replace("地区", "");
+                if (!string.IsNullOrWhiteSpace(provinceName)) provinceName = provinceName.Replace("省", "");
+                if (!string.IsNullOrWhiteSpace(cityName)) cityName = cityName.Replace("市", "");
+                //省 市
+
+                //取得學校資訊
+                List<SchoolSimple> schoolList = new List<SchoolSimple>();
+                var clientc = _azureCosmos.GetCosmosClient();
+                string querySchoolSelect = $"SELECT c.id, c.name FROM c";
+                string querySchoolWhere1 = $"CONTAINS(c.region, '{regionName}')"; //依據地理資料(國省市)
+                querySchoolWhere1 += (provinceName != null) ? $" AND CONTAINS(c.province, '{provinceName}')" : $" AND IS_NULL(c.province)";
+                querySchoolWhere1 += (cityName != null) ? $" AND CONTAINS(c.city, '{cityName}')" : $" AND IS_NULL(c.city)";
+                string querySchoolWhere2 = "IS_NULL(c.region)"; //無任何地理資料
+                string querySchoolWhere = $" WHERE ({querySchoolWhere1}) OR ({querySchoolWhere2})";
+                string querySchool = $"{querySchoolSelect}{querySchoolWhere}";
+                await foreach (var item in clientc.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryStreamIterator(querySchool, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
+                {
+                    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())
+                        {
+                            SchoolSimple sch = new SchoolSimple();
+                            sch.id = Convert.ToString(obj.GetProperty("id"));
+                            sch.name = Convert.ToString(obj.GetProperty("name"));
+                            schoolList.Add(sch);
+                        }
+                    }
+                }
+                return Ok(schoolList);
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"IES5,{_option.Location},HiTA/GetSchoolListByRegion()\n{ex.Message}\n{ex.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest();
+            }
+        }
+
+        private class SchoolSimple
+        {
+            public string id { get; set; }
+            public string name { get; set; }
+        }
     }
 }

+ 78 - 14
TEAMModelOS/Controllers/Common/AreaController.cs

@@ -631,7 +631,7 @@ namespace TEAMModelOS.Controllers
                     x.name,
                     startTime = x.stime,
                     endTime = x.etime,
-                    sc = artSc.Where(c => c.pd.Equals(x.id)).Select(p => new {p.id,p.code })
+                    sc = artSc.Where(c => c.pd.Equals(x.id)).Select(p => new { p.id, p.code })
                 });
                 return Ok(new { arts });
             }
@@ -673,12 +673,13 @@ namespace TEAMModelOS.Controllers
                 }
                 ArtSetting setting = await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<ArtSetting>($"{id}", partitionKey: new PartitionKey("ArtSetting"));
                 List<ArtEvaluation> arts = new();
-                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ArtEvaluation>(queryText: $"SELECT  top 1 *  FROM c order by c.createTime", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Art-{id}") }))
+                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ArtEvaluation>(queryText: $"SELECT  top 1 *  FROM c order by c.createTime desc", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Art-{id}") }))
                 {
                     arts.Add(item);
                 }
                 List<(string id, string code, List<Tasks> settings)> artSchools = new();
-                if (arts.Any()) {
+                if (arts.Any())
+                {
                     string ql = $"select c.id,c.school,c.settings from c where  c.pk = 'Art' and c.pId = '{arts[0].id}'";
                     await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: ql))
                     {
@@ -698,6 +699,7 @@ namespace TEAMModelOS.Controllers
                 }
 
                 var ped = baseInfo.Select(x => x.periods).ToList();
+                var scode = baseInfo.Where(x => x.periods.Count >= 2).FirstOrDefault();
                 double scxCount = 0;
                 double sccCount = 0;
                 List<string> perxId = new();
@@ -724,7 +726,16 @@ namespace TEAMModelOS.Controllers
                 //班级总数
                 List<string> classes = await getStudentsAsync(perxId, client, "Class", "School");
                 List<string> classesc = await getStudentsAsync(percId, client, "Class", "School");
-                await foreach (var ss in schoolTask(artSchools, client, baseInfo, arts[0],setting)) {
+                //先获取不同学段和科目的知识占比
+                List<(string subId, List<(string name, List<string> kno)> knos)> xkno = new();
+                List<(string subId, List<(string name, List<string> kno)> knos)> ckno = new();
+                foreach (var artSubject in arts[0].subjects)
+                {
+                    xkno.Add(await getKnowledge(scode.id, client, artSubject.id, perxId[0]));
+                    ckno.Add(await getKnowledge(scode.id, client, artSubject.id, percId[0]));
+                }
+                await foreach (var ss in schoolTask(artSchools, client, baseInfo, arts[0], setting, xkno,ckno))
+                {
 
                 }
 
@@ -738,9 +749,10 @@ namespace TEAMModelOS.Controllers
             }
 
         }
-        private async IAsyncEnumerable<(string code, List<(string suject,List<double> scores)> )> schoolTask(List<(string id, string code, List<Tasks> settings)> artSchools, CosmosClient client, List<(string id, string name, List<Period> periods)> baseInfo,ArtEvaluation art, ArtSetting setting)
+        private async IAsyncEnumerable<(string code, List<(string suject, List<double> scores)>)> schoolTask(List<(string id, string code, List<Tasks> settings)> artSchools, CosmosClient client, List<(string id, string name, List<Period> periods)> baseInfo, ArtEvaluation art, ArtSetting setting,
+            List<(string subId, List<(string name, List<string> kno)> knos)> spId, List<(string subId, List<(string name, List<string> kno)> knos)> cpId)
         {
-            foreach (var (id, code,settings) in artSchools)
+            foreach (var (id, code, settings) in artSchools)
             {
                 string queryScore = $" select c.studentId,c.classIds,c.totalScore,c.subjectScores,c.results from c ";
                 List<ArtSubjectScore> As = new();
@@ -768,15 +780,31 @@ namespace TEAMModelOS.Controllers
                     }
                 }
                 var sbScore = As.GroupBy(x => x.subjectId).Select(c => new { subjectId = c.Key, list = c.ToList().Select(a => a.score) });
-                List < (string suject, List<double> scores)> scs = new();
-                foreach (var subjectScore in sbScore) {
+                List<(string suject, List<double> scores)> scs = new();
+                foreach (var subjectScore in sbScore)
+                {
                     scs.Add((subjectScore.subjectId, subjectScore.list.ToList()));
                 }
                 //List<(string subId, List<(string name, List<string> kno)> values)> bk = new();
                 var pers = baseInfo.Where(x => x.id.Equals(code)).FirstOrDefault().periods;
-                foreach (var perId in pers) {
-                    foreach (var sj in art.subjects) { 
-                        (string subId, List<(string name, List<string> kno)> knos) = await getKnowledge(code, client, sj.id, perId.id);
+                List<(string sb, string pId)> pn = new();
+                List<(string code, string perName,string subjectId, List<(string name, double score, List<string> dim)> blocks, List<(string name, double score, List<string> kno)> knos)> perMore = new();
+                foreach (var perId in pers)
+                {
+                    foreach (var sj in art.subjects)
+                    {
+                        List<(string name, List<string> kno)> knos = new();
+                        if (perId.name.Contains("小学"))
+                        {
+                            knos = spId.Where(s => s.subId.Equals(sj.id)).FirstOrDefault().knos;
+                        }
+                        else if (perId.name.Contains("初中"))
+                        {
+                            knos = cpId.Where(s => s.subId.Equals(sj.id)).FirstOrDefault().knos;
+                        }
+                        else {
+                            break;
+                        }                     
                         var examId = settings.SelectMany(s => s.task).Where(a => a.type == 1 && a.subject.Equals(sj.id)).FirstOrDefault().acId;
                         List<ExamResult> examResults = new();
                         List<KeyValuePair<string, List<(string name, double score)>>> pointPersent = new();
@@ -809,12 +837,22 @@ namespace TEAMModelOS.Controllers
                             x.score,
                             dimension = setting.dimensions.Where(s => s.blocks.Contains(x.name)).Select(x => x.dimension)
                         });
+                        List<(string name, double score, List<string> dim)> blocks = new();
+                        foreach (var bk in blk) {
+                            blocks.Add((bk.name,bk.score,bk.dimension.ToList()));
+                        }
                         var kno = key4.Value.Select(x => new
                         {
                             x.name,
                             x.score,
                             block = knos.Where(v => v.kno.Contains(x.name)).Select(x => x.name)
                         });
+                        List<(string name, double score, List<string> dim)> knoMore = new();
+                        foreach (var bk in kno)
+                        {
+                            knoMore.Add((bk.name, bk.score, bk.block.ToList()));
+                        }
+                        perMore.Add((code,perId.name,sj.id,blocks, knoMore));
                     }
                 }
                 //获奖次数
@@ -846,7 +884,7 @@ namespace TEAMModelOS.Controllers
                 }
                 yield return (code, scs);
             }
-            
+
         }
 
         private static async Task<(string subId, List<(string name, List<string> kno)>)> getKnowledge(string school, CosmosClient client, string subjectBid, string pId)
@@ -1012,7 +1050,7 @@ namespace TEAMModelOS.Controllers
             return (key1, key2, key3, key4);
         }
 
-        private async Task<List<string>> getStudentsAsync(List<string> ids, CosmosClient client,string pk,string source)
+        private async Task<List<string>> getStudentsAsync(List<string> ids, CosmosClient client, string pk, string source)
         {
             try
             {
@@ -1095,7 +1133,33 @@ namespace TEAMModelOS.Controllers
                 {
                     foreach ((string s, string c) in ids)
                     {
-                        await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(s.ToString(), new PartitionKey($"{c}"));
+                        var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(s.ToString(), new PartitionKey($"Art-{c}"));
+                        if (sresponse.Status == 200) {
+                            using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
+                            ArtEvaluation art = json.ToObject<ArtEvaluation>();
+                            art.status = 404;
+                            foreach (var info in art.settings)
+                            {
+                                foreach (var acs in info.task)
+                                {
+                                    if (!string.IsNullOrEmpty(acs.acId))
+                                    {
+                                        if (acs.type == 1)
+                                        {
+                                            Azure.Response eresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(acs.acId, new PartitionKey($"Exam-{code}"));
+                                            if (response.Status == 200)
+                                            {
+                                                ExamInfo data = JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamInfo>();
+                                                data.status = 404;
+                                                await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Exam-{code}"));
+                                            }
+                                        }                                      
+                                    }
+
+                                }
+                            }
+                            await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(art, art.id, new PartitionKey($"{art.code}"));
+                        }                       
                     }
                 }
                 return Ok(new { id, code = response.Status });

+ 2 - 42
TEAMModelOS/Controllers/Common/ArtController.cs

@@ -466,51 +466,11 @@ namespace TEAMModelOS.Controllers.Common
                                             data.status = 404;
                                             await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Exam-{code}"));
                                         }
-                                    }
-                                    if (acs.type == 2)
-                                    {
-                                        Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(acs.acId, new PartitionKey($"Homework-{code}"));
-                                        if (response.Status == 200)
-                                        {
-                                            Homework data = JsonDocument.Parse(response.Content).RootElement.Deserialize<Homework>();
-                                            data.status = 404;
-                                            await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Homework-{code}"));
-                                        }
-                                    }
+                                    }                                    
                                 }
 
                             }
-                        }
-                        /*if (!string.IsNullOrEmpty(art.examId))
-                        {
-                            Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.examId, new PartitionKey($"Exam-{code}"));
-                            if (response.Status == 200)
-                            {
-                                ExamLite data = JsonDocument.Parse(response.Content).RootElement.Deserialize<ExamLite>();
-                                data.status = 404;
-                                await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Exam-{code}"));
-                            }
-                        }
-                        if (!string.IsNullOrEmpty(art.surveyId))
-                        {
-                            Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.surveyId, new PartitionKey($"Survey-{code}"));
-                            if (response.Status == 200)
-                            {
-                                Survey data = JsonDocument.Parse(response.Content).RootElement.Deserialize<Survey>();
-                                data.status = 404;
-                                await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Survey-{code}"));
-                            }
-                        }
-                        if (!string.IsNullOrEmpty(art.workId))
-                        {
-                            Azure.Response response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.workId, new PartitionKey($"Homework-{code}"));
-                            if (response.Status == 200)
-                            {
-                                Homework data = JsonDocument.Parse(response.Content).RootElement.Deserialize<Homework>();
-                                data.status = 404;
-                                await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(data, data.id, new PartitionKey($"Homework-{code}"));
-                            }
-                        }*/
+                        }                      
                         await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(art, art.id, new PartitionKey($"{art.code}"));
                     }