Browse Source

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

zhouj1203@hotmail.com 1 năm trước cách đây
mục cha
commit
d3c7038879
38 tập tin đã thay đổi với 2112 bổ sung693 xóa
  1. 3 1
      TEAMModelBI/ClientApp/src/view/product/index.vue
  2. 3 3
      TEAMModelBI/TEAMModelBI.csproj
  3. 6 0
      TEAMModelOS.FunctionV4/CosmosDB/CommonTrigger.cs
  4. 146 0
      TEAMModelOS.FunctionV4/CosmosDB/TriggerExamImport.cs
  5. 138 0
      TEAMModelOS.FunctionV4/CosmosDB/TriggerVirtueImport.cs
  6. 3 3
      TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj
  7. 1 1
      TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosExtensions.cs
  8. 1 1
      TEAMModelOS.SDK/Models/Cosmos/School/CourseBase.cs
  9. 12 0
      TEAMModelOS.SDK/Models/Cosmos/School/ExamImport.cs
  10. 5 1
      TEAMModelOS.SDK/Models/Cosmos/Student/OverallEducation.cs
  11. 2 1
      TEAMModelOS/ClientApp/src/api/index.js
  12. 7 0
      TEAMModelOS/ClientApp/src/api/iot.js
  13. 49 3
      TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html
  14. 11 3
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css
  15. 1 1
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js
  16. 14 0
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json
  17. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf
  18. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff
  19. BIN
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2
  20. 18 6
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  21. 9 0
      TEAMModelOS/ClientApp/src/router/routes.js
  22. 12 0
      TEAMModelOS/ClientApp/src/view/areaMgmt/AreaLayout.vue
  23. 490 501
      TEAMModelOS/ClientApp/src/view/coursemgt/NewCusMgt.vue
  24. 10 1
      TEAMModelOS/ClientApp/src/view/coursemgt/components/MemberTable.vue
  25. 668 0
      TEAMModelOS/ClientApp/src/view/iot/areaiot.vue
  26. 1 1
      TEAMModelOS/ClientApp/src/view/iot/echarts/bar/bar.vue
  27. 54 24
      TEAMModelOS/ClientApp/src/view/iot/echarts/barandLine/barandLine.vue
  28. 3 1
      TEAMModelOS/ClientApp/src/view/iot/echarts/circle/index.vue
  29. 118 17
      TEAMModelOS/ClientApp/src/view/iot/schooliot.vue
  30. 24 13
      TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue
  31. 24 13
      TEAMModelOS/ClientApp/src/view/learnactivity/CreateSchoolEva.vue
  32. 23 5
      TEAMModelOS/Controllers/Both/CourseBaseController.cs
  33. 8 3
      TEAMModelOS/Controllers/Both/GroupListController.cs
  34. 237 82
      TEAMModelOS/Controllers/School/ImportExamController.cs
  35. 5 2
      TEAMModelOS/Controllers/School/SchoolController.cs
  36. 4 4
      TEAMModelOS/TEAMModelOS.csproj
  37. 1 1
      TEAMModelOS/appsettings.Development.json
  38. 1 1
      TEAMModelOS/appsettings.json

+ 3 - 1
TEAMModelBI/ClientApp/src/view/product/index.vue

@@ -529,7 +529,7 @@ let productData = ref({
     // { name: '全部', value: 'sourceAll' },
     { name: '学校', value: 'school' },
     { name: '学区', value: 'area' },
-    { name: '城市', value: 'city' }
+    // { name: '城市', value: 'city' }
   ],
   districtName: '地区选择',
   district: [
@@ -880,6 +880,8 @@ function dataInit () {
       let resultColumns=columns.value.findIndex((item)=>{return  item.key==='schoolId'})
       resultColumns !==-1 ? columns.value.splice(1,1):''
       cellWidth.value=(100 / columns.value.length).toFixed(2)
+    }else{
+      filterdata.value=res.data
     }
   }).catch((err) => {
     ElMessage.error('API异常,数据获取失败')

+ 3 - 3
TEAMModelBI/TEAMModelBI.csproj

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

+ 6 - 0
TEAMModelOS.FunctionV4/CosmosDB/CommonTrigger.cs

@@ -108,6 +108,12 @@ namespace TEAMModelOS.FunctionV4
                                     case "Art":
                                         await TriggerArt.Trigger(_coreAPIHttpService, _serviceBus, _azureStorage, _dingDing, client, element, data, _azureRedis, _configuration, _httpTrigger);
                                         break;
+                                    case "ExamImport":
+                                        await TriggerExamImport.Trigger(_coreAPIHttpService, _azureCosmos, _serviceBus, _azureStorage, _dingDing, client, element, data, _httpClient, _configuration);
+                                        break;
+                                    case "VirtueImport":
+                                        await TriggerVirtueImport.Trigger(_coreAPIHttpService, _azureCosmos, _serviceBus, _azureStorage, _dingDing, client, element, data, _httpClient, _configuration);
+                                        break;
                                 }
                             }
                         }

+ 146 - 0
TEAMModelOS.FunctionV4/CosmosDB/TriggerExamImport.cs

@@ -0,0 +1,146 @@
+using Microsoft.Extensions.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK;
+using Azure.Cosmos;
+using System.Net.Http;
+using TEAMModelOS.SDK.Models.Cosmos.School;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models;
+using HTEXLib.COMM.Helpers;
+
+namespace TEAMModelOS.FunctionV4.CosmosDB
+{
+    public class TriggerExamImport
+    {
+        public static async Task Trigger(CoreAPIHttpService _coreAPIHttpService, AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
+            CosmosClient client, JsonElement input, TriggerData data, IHttpClientFactory _httpClient, IConfiguration _configuration)
+        { 
+            ExamImport examImport= input.ToObject<ExamImport>();
+            if (examImport != null) {
+                HashSet<string> ids = new HashSet<string>();
+                foreach (var x in examImport.subjects)
+                {
+                    foreach (var y in x.students)
+                    {
+                        string id = $"{examImport.year}-{examImport.semesterId}-{y.id}";
+                        ids.Add(id);
+                    }
+                }
+                HashSet<OverallEducation> overallEducations = new HashSet<OverallEducation>();
+                string sql = $"select value c from  c where c.id in ({string.Join(",", ids.Select(z => $"'{z}'"))}) and c.periodId='{examImport.periodId}' ";
+                var result = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<OverallEducation>(sql, $"OverallEducation-{examImport.school}");
+                IEnumerable<string> notInDbIds = null;
+                if (result.list.IsNotEmpty())
+                {
+                    notInDbIds= ids.Except(result.list.Select(x => x.id));
+                    overallEducations = new HashSet<OverallEducation>(result.list);
+                }
+                else {
+                    notInDbIds = ids;
+                }
+
+                HashSet<OverallEducation> overallEducationChanged = new HashSet<OverallEducation>();
+                foreach (var x in examImport.subjects)
+                {
+                    foreach (var y in x.students)
+                    {
+                        string id = $"{examImport.year}-{examImport.semesterId}-{y.id}";
+                        var overallEducation =  overallEducations.Where(z => z.id.Equals(id)).FirstOrDefault();
+                        if (overallEducation != null)
+                        {
+                            var exam = overallEducation.intelligence.Find(f => f.examId.Equals(examImport.id));
+                            if (exam != null)
+                            {
+                                var item = exam.itemScore.Find(f => f.id.Equals(x.id));
+                                if (item != null)
+                                {
+                                    item.name= x.name;
+                                    if (item.score != y.score) {
+                                        overallEducationChanged.Add(overallEducation);
+                                        item.score = y.score;
+                                    }
+                                    if (item.totalScore != x.items.Sum(b => b.score)) {
+                                        overallEducationChanged.Add(overallEducation);
+                                        item.totalScore = x.items.Sum(b => b.score);
+                                    }
+                                    item.type = x.name;
+                                }
+                                else {
+                                    overallEducationChanged.Add(overallEducation);
+                                    exam.itemScore.Add(new ItemScore { name = x.name, score = y.score, totalScore = x.items.Sum(b => b.score), type = x.name, id = x.id , time=examImport.time});
+                                }
+                                if (exam.sumScore != examImport.subjects.SelectMany(z => z.students).Where(b => b.id.Equals(y.id)).Sum(v => v.score)) {
+                                    overallEducationChanged.Add(overallEducation);
+                                    exam.sumScore = examImport.subjects.SelectMany(z => z.students).Where(b => b.id.Equals(y.id)).Sum(v => v.score);
+                                }
+                                if (exam.totalScore != examImport.subjects.SelectMany(t => t.items).Sum(n => n.score))
+                                {
+                                    overallEducationChanged.Add(overallEducation);
+                                    exam.totalScore = examImport.subjects.SelectMany(t => t.items).Sum(n => n.score);
+                                }
+                                if (exam.rate != examImport.subjects.SelectMany(z => z.students).Where(b => b.id.Equals(y.id)).Sum(v => v.score) * 1.0 / examImport.subjects.SelectMany(t => t.items).Sum(n => n.score))
+                                {
+                                    overallEducationChanged.Add(overallEducation);
+                                    exam.rate = examImport.subjects.SelectMany(z => z.students).Where(b => b.id.Equals(y.id)).Sum(v => v.score) * 1.0 / examImport.subjects.SelectMany(t => t.items).Sum(n => n.score);
+                                }
+                                exam.examType = examImport.type;
+                                exam.examDate = examImport.time;
+                                exam.examName=examImport.name;
+                            }
+                            else {
+                                overallEducation.intelligence.Add(new EducationScore
+                                {
+                                    examName = examImport.name,
+                                    examId = examImport.id,
+                                    examDate = examImport.time,
+                                    examType = examImport.type,
+                                    totalScore = examImport.subjects.SelectMany(t => t.items).Sum(n => n.score),
+                                    sumScore = examImport.subjects.SelectMany(z => z.students).Where(b => b.id.Equals(y.id)).Sum(v => v.score),
+                                    rate = examImport.subjects.SelectMany(z => z.students).Where(b => b.id.Equals(y.id)).Sum(v => v.score) * 1.0 / examImport.subjects.SelectMany(t => t.items).Sum(n => n.score),
+                                    itemScore = new List<ItemScore> { new ItemScore { name = x.name, score = y.score, totalScore = x.items.Sum(b => b.score), type = x.name , time=examImport.time ,id=x.id} }
+                                });
+                                overallEducationChanged.Add(overallEducation);
+                            }
+                        }
+                        else {
+                            overallEducation = new OverallEducation {
+                                id = id,
+                                code = $"OverallEducation-{examImport.school}",
+                                pk = "OverallEducation",
+                                periodId = examImport.periodId,
+                                year = examImport.year,
+                                semesterId = examImport.semesterId,
+                                schoolCode = examImport.school,
+                                studentId = y.id,
+                                name = y.name,
+                                classId = y.classId,
+                                stuYear = y.stuYear,
+                                intelligence = new List<EducationScore> { new EducationScore {
+                                    examName=examImport.name,
+                                    examId=examImport.id,
+                                    examDate=examImport.time,
+                                    examType=examImport.type,
+                                    totalScore= examImport.subjects.SelectMany(t=>t.items).Sum(n=>n.score),
+                                    sumScore= examImport.subjects.SelectMany(z=>z.students).Where(b=>b.id.Equals(y.id)).Sum(v=>v.score),
+                                    rate=examImport.subjects.SelectMany(z=>z.students).Where(b=>b.id.Equals(y.id)).Sum(v=>v.score) *1.0 / examImport.subjects.SelectMany(t=>t.items).Sum(n=>n.score),
+                                    itemScore= new List<ItemScore>{ new ItemScore { id=x.id, time=examImport.time,name=x.name,score=y.score,totalScore=x.items.Sum(b=>b.score),type=x.name } }
+                                } }
+                            };
+                            overallEducationChanged.Add(overallEducation);
+                            overallEducations.Add(overallEducation);
+                        }
+                    }
+                }
+                foreach (var item in overallEducationChanged) { 
+                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS,Constant.Student).UpsertItemAsync(item,new PartitionKey(item.code));
+                }
+            }
+        }
+    }
+}

+ 138 - 0
TEAMModelOS.FunctionV4/CosmosDB/TriggerVirtueImport.cs

@@ -0,0 +1,138 @@
+using Microsoft.Extensions.Configuration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK;
+using Azure.Cosmos;
+using TEAMModelOS.SDK.Models.Cosmos.School;
+using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Extension;
+using HTEXLib.COMM.Helpers;
+using OpenXmlPowerTools;
+
+namespace TEAMModelOS.FunctionV4.CosmosDB
+{
+    public class TriggerVirtueImport
+    {
+        public static async Task Trigger(CoreAPIHttpService _coreAPIHttpService, AzureCosmosFactory _azureCosmos, AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
+           CosmosClient client, JsonElement input, TriggerData data, IHttpClientFactory _httpClient, IConfiguration _configuration)
+        {
+            VirtueImport virtueImport = input.ToObject<VirtueImport>();
+            if (virtueImport != null)
+            {
+                HashSet<string> ids = new HashSet<string>();
+                foreach (var x in virtueImport.students)
+                {
+                    string id = $"{virtueImport.year}-{virtueImport.semesterId}-{x.id}";
+                    ids.Add(id);
+                }
+                HashSet<OverallEducation> overallEducations = new HashSet<OverallEducation>();
+                string sql = $"select value c from  c where c.id in ({string.Join(",", ids.Select(z => $"'{z}'"))}) and c.periodId='{virtueImport.periodId}' ";
+                var result = await client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<OverallEducation>(sql, $"OverallEducation-{virtueImport.school}");
+                IEnumerable<string> notInDbIds = null;
+                if (result.list.IsNotEmpty())
+                {
+                    notInDbIds = ids.Except(result.list.Select(x => x.id));
+                    overallEducations = new HashSet<OverallEducation>(result.list);
+                }
+                else
+                {
+                    notInDbIds = ids;
+                }
+                HashSet<OverallEducation> overallEducationChanged = new HashSet<OverallEducation>();
+                foreach (var y in virtueImport.students)
+                {
+                    string id = $"{virtueImport.year}-{virtueImport.semesterId}-{y.id}";
+                    var overallEducation = overallEducations.Where(z => z.id.Equals(id)).FirstOrDefault();
+                    if (overallEducation != null)
+                    {
+
+                        var virtue = overallEducation.virtue.Find(f => f.examId.Equals($"{overallEducation.stuYear}-{overallEducation.semesterId}"));
+                        if (virtue != null)
+                        {
+                            y.items.ForEach(z => {
+                                var item = virtue.itemScore.Find(f => f.id.Equals($"{y.date}-{z.code}"));
+                                if (item != null)
+                                {
+                                    item.name = z.code;
+                                    if (item.score != z.value) {
+                                        item.score = z.value;
+                                        overallEducationChanged.Add(overallEducation);
+                                    }
+                                  
+                                    item.type = z.code;
+                                    item.time = y.time;
+                                    item.id = $"{y.date}-{z.code}";
+                                }
+                                else
+                                {
+                                    overallEducationChanged.Add(overallEducation);
+                                    virtue.itemScore.Add(new ItemScore { name = z.code, score = z.value, type = z.code, id = id = $"{y.date}-{z.code}", time=y.time });
+                                }
+                            });
+
+                            if (virtue.sumScore != virtue.itemScore.Sum(z => z.score)) {
+                                overallEducationChanged.Add(overallEducation);
+                                virtue.sumScore = virtue.itemScore.Sum(z => z.score);
+                            }
+                            virtue.examType = virtueImport.type;
+                            virtue.examDate = virtueImport.time;
+                            virtue.examName = $"{overallEducation.stuYear}-{overallEducation.semesterId}";
+                        }
+                        else
+                        {
+                            List<ItemScore> itemScores = y.items.Select(z =>new ItemScore { name = z.code, score = z.value, type = z.code, id = $"{y.date}-{z.code}", time = y.time }).ToList();
+                            overallEducation.virtue.Add(new EducationScore
+                            {
+                                examName = $"{overallEducation.stuYear}-{overallEducation.semesterId}",
+                                examId =$"{overallEducation.stuYear}-{overallEducation.semesterId}",
+                                examDate = virtueImport.time,
+                                examType = virtueImport.type,
+                                sumScore = itemScores.Sum(z => z.score),
+                                itemScore = itemScores
+                            });
+                            overallEducationChanged.Add(overallEducation);
+                        }
+                    }
+                    else
+                    {
+                        List<ItemScore> itemScores = y.items.Select(z => new ItemScore { name = z.code, score = z.value, type = z.code, id = $"{y.date}-{z.code}", time = y.time }).ToList();
+                        overallEducation = new OverallEducation
+                        {
+                            id = id,
+                            code = $"OverallEducation-{virtueImport.school}",
+                            pk = "OverallEducation",
+                            periodId = virtueImport.periodId,
+                            year = virtueImport.year,
+                            semesterId = virtueImport.semesterId,
+                            schoolCode = virtueImport.school,
+                            studentId = y.id,
+                            name = y.name,
+                            classId = y.classId,
+                            stuYear = y.stuYear,
+                            virtue = new List<EducationScore> { new EducationScore {
+                                    examName=$"{y.stuYear}-{virtueImport.semesterId}",
+                                    examId =$"{y.stuYear}-{virtueImport.semesterId}",
+                                    examDate=virtueImport.time,
+                                    examType=virtueImport.type,
+                                    sumScore = itemScores.Sum(z => z.score),
+                                    itemScore = itemScores
+                                }
+                            }
+                        };
+                        overallEducationChanged.Add(overallEducation);
+                        overallEducations.Add(overallEducation);
+                    }
+                }
+                foreach (var item in overallEducationChanged) { 
+                   await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS,Constant.Student).UpsertItemAsync(item,new PartitionKey (item.code));
+                }
+            }
+        }
+    }
+}

+ 3 - 3
TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj

@@ -5,9 +5,9 @@
 		<OutputType>Exe</OutputType>
 		<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
 		<SignAssembly>true</SignAssembly>
-		<Version>5.2209.7</Version>
-		<AssemblyVersion>5.2209.7.1</AssemblyVersion>
-		<FileVersion>5.2209.7.1</FileVersion>
+		<Version>5.2307.12</Version>
+		<AssemblyVersion>5.2307.12.1</AssemblyVersion>
+		<FileVersion>5.2307.12.1</FileVersion>
 		<PackageId>TEAMModelOS.FunctionV4</PackageId>
 		<Authors>teammodel</Authors>
 		<Company>醍摩豆(成都)信息技术有限公司</Company>

+ 1 - 1
TEAMModelOS.SDK/DI/AzureCosmos/AzureCosmosExtensions.cs

@@ -185,7 +185,7 @@ namespace TEAMModelOS.SDK.DI
                     {
                         continuationToken = item.GetContinuationToken();
                     }
-                    RU = item.RU();
+                    RU += item.RU();
                     if (pageSize.HasValue && pageSize.Value >= 0 && list.Count >= pageSize)
                     {
                         break;

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/School/CourseBase.cs

@@ -32,7 +32,7 @@ namespace TEAMModelOS.SDK.Models
         "creatorId": "1595321354",
         "school": "hbcn",
         "color": "red", //用于标记课程表的排课颜色
-        "gradeId": 2, //年级
+        "grades": [0,1,2], //年级
         "status": 1
     }
      */

+ 12 - 0
TEAMModelOS.SDK/Models/Cosmos/School/ExamImport.cs

@@ -151,10 +151,19 @@ namespace TEAMModelOS.SDK.Models.Cosmos.School
         /// 日常考核类型,需要将考核时间碎片化,如德育。
         /// </summary>
         public long time { get; set; }
+        public string date { get; set; }
+        //学生入学年
+        public int stuYear { get; set; }
     }
     public class ItemVlaue
     {
+        /// <summary>
+        /// 细项名称
+        /// </summary>
         public string code { get; set; }
+        /// <summary>
+        /// 细项分数
+        /// </summary>
         public double value { get; set; }
     }
     /// <summary>
@@ -233,6 +242,9 @@ namespace TEAMModelOS.SDK.Models.Cosmos.School
         /// 小题得分,下标0顺序开始 第一题....N
         /// </summary>
         public List<double> scores { get; set; }
+        /// <summary>
+        /// 德育细项
+        /// </summary>
         public List<ItemVlaue> items { get; set; }
         /// <summary>
         /// 日常考核类型,需要将考核时间碎片化,如德育。

+ 5 - 1
TEAMModelOS.SDK/Models/Cosmos/Student/OverallEducation.cs

@@ -128,7 +128,11 @@ namespace TEAMModelOS.SDK.Models
     /// 考核项目数据
     /// </summary>
     public class ItemScore
-    {
+    {  
+        /// <summary>
+        /// 项目id,科目id  ,选填
+        /// </summary>
+        public string id { get; set; }
         /// <summary>
         /// 项目名称
         /// </summary>

+ 2 - 1
TEAMModelOS/ClientApp/src/api/index.js

@@ -42,7 +42,7 @@ import areaArt from './areaArt'
 import dashboard from './dashboard'
 import areaOverview from './areaOverview'
 import newCourse from './newCourse'
-
+import iot from './iot'
 export default {
     accessToken,
     learnActivity,
@@ -85,6 +85,7 @@ export default {
     dashboard,
     areaOverview,
     newCourse,
+    iot,
     // 获取登录跳转链接
     getLoginLink: function (data) {
         return post('api/login/login', data)

+ 7 - 0
TEAMModelOS/ClientApp/src/api/iot.js

@@ -0,0 +1,7 @@
+import { fetch, post } from '@/api/http'
+export default {
+    //iot面板  学校
+    getSchooliot:function(data){
+        return post('/school/init/get-school-iot', data)
+    },
+}

+ 49 - 3
TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html

@@ -54,6 +54,18 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe697;</span>
+                <div class="name">物联网</div>
+                <div class="code-name">&amp;#xe697;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe916;</span>
+                <div class="name">iot 物联网平台</div>
+                <div class="code-name">&amp;#xe916;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe696;</span>
                 <div class="name">星标题目</div>
@@ -1416,9 +1428,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1687773648553') format('woff2'),
-       url('iconfont.woff?t=1687773648553') format('woff'),
-       url('iconfont.ttf?t=1687773648553') format('truetype');
+  src: url('iconfont.woff2?t=1689156682901') format('woff2'),
+       url('iconfont.woff?t=1689156682901') format('woff'),
+       url('iconfont.ttf?t=1689156682901') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -1444,6 +1456,24 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont icon-wulianwang"></span>
+            <div class="name">
+              物联网
+            </div>
+            <div class="code-name">.icon-wulianwang
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-iot"></span>
+            <div class="name">
+              iot 物联网平台
+            </div>
+            <div class="code-name">.icon-iot
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont icon-xingbiaoti-"></span>
             <div class="name">
@@ -3487,6 +3517,22 @@
       <div class="content symbol">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-wulianwang"></use>
+                </svg>
+                <div class="name">物联网</div>
+                <div class="code-name">#icon-wulianwang</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-iot"></use>
+                </svg>
+                <div class="name">iot 物联网平台</div>
+                <div class="code-name">#icon-iot</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#icon-xingbiaoti-"></use>

+ 11 - 3
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css

@@ -1,8 +1,8 @@
 @font-face {
   font-family: "iconfont"; /* Project id 2000444 */
-  src: url('iconfont.woff2?t=1687773648553') format('woff2'),
-       url('iconfont.woff?t=1687773648553') format('woff'),
-       url('iconfont.ttf?t=1687773648553') format('truetype');
+  src: url('iconfont.woff2?t=1689156682901') format('woff2'),
+       url('iconfont.woff?t=1689156682901') format('woff'),
+       url('iconfont.ttf?t=1689156682901') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,14 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-wulianwang:before {
+  content: "\e697";
+}
+
+.icon-iot:before {
+  content: "\e916";
+}
+
 .icon-xingbiaoti-:before {
   content: "\e696";
 }

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 1
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js


+ 14 - 0
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json

@@ -5,6 +5,20 @@
   "css_prefix_text": "icon-",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "11761256",
+      "name": "物联网",
+      "font_class": "wulianwang",
+      "unicode": "e697",
+      "unicode_decimal": 59031
+    },
+    {
+      "icon_id": "9255041",
+      "name": "iot 物联网平台",
+      "font_class": "iot",
+      "unicode": "e916",
+      "unicode_decimal": 59670
+    },
     {
       "icon_id": "3727440",
       "name": "星标题目",

BIN
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf


BIN
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff


BIN
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2


+ 18 - 6
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -622,6 +622,7 @@ export default {
     schoolMenu() {
       let data = !this.$store.state.userInfo.schoolPay
         ? [
+            // 教学看板(国际站单独)
             {
               icon: "iconfont icon-data-count",
               name: this.$t("system.menu.techDash"),
@@ -633,7 +634,18 @@ export default {
               child: [],
               isShow: this.isGlobalSite,
             },
-            //学校管理
+            {
+              icon: "iconfont icon-wulianwang",
+              name: 'iot数据看板',
+              router: "/schooliot",
+              tag: "",
+              role: "admin",
+              permission: "dashboard-read",
+              menuName: "TeacherDashboard",
+              child: [],
+              isShow: this.isGlobalSite,
+            },
+            // 学校管理
             {
               icon: "iconfont icon-school",
               name: this.$t("system.menu.schoolMgt"),
@@ -857,7 +869,7 @@ export default {
                 },
               ],
             },
-            // 课例中心
+            // 课例中心(国际站单独)
             {
               icon: "iconfont icon-research-center",
               name: this.$t("system.menu.research"),
@@ -982,7 +994,7 @@ export default {
                 },
               ],
             },
-            //艺术评测
+            // 艺术评测
             {
               icon: "iconfont icon-yishu",
               name: this.$t("area.base.artData"),
@@ -1038,7 +1050,7 @@ export default {
               role: "admin",
               permission: "",
               subName: "StuDashboard",
-              isShow: this.IES5Menu && this.edition !== "basic",
+              isShow: this.IES5Menu && !this.isGlobalSite && this.edition !== "basic",
               child: [
                 {
                   icon: "iconfont icon-data-count",
@@ -1090,7 +1102,7 @@ export default {
               role: "admin",
               permission: "",
               subName: "TeacherDashboard",
-              isShow: this.IES5Menu,
+              isShow: this.IES5Menu && !this.isGlobalSite,
               child: [
                 {
                   icon: "iconfont icon-data-count",
@@ -1129,7 +1141,7 @@ export default {
                 },
               ],
             },
-            // 学情分析
+            // 学情分析(国际站单独)
             {
               icon: "iconfont icon-xueqing",
               name: this.$t("system.menu.evAna"),

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

@@ -1694,6 +1694,15 @@ export const routes = [{
                 activeName: 'areaIndex'
             }
         },
+        //学区iot数据看板
+        {
+            path: 'areaIot',
+            name: 'areaIot',
+            component: () => import('@/view/iot/areaiot.vue'),
+            meta: {
+                activeName: 'areaIot'
+            }
+        },
         //学校数据统计总览
         {
             path: 'areaSchool',

+ 12 - 0
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaLayout.vue

@@ -269,6 +269,18 @@ export default {
           child: [],
           isShow: !this.$jsFn.checkJinNiu() && !this.$jsFn.checkTrain() && this.$store.state.config.srvAdrType != 'product'
         },
+        //学区iot
+        // {
+        //   icon: 'iconfont icon-iot',
+        //   name: '学区Iot看板',
+        //   router: '/area/areaiot',
+        //   tag: '',
+        //   role: '',
+        //   permission: '',
+        //   menuName: 'areaiot',
+        //   child: [],
+        //   isShow: !this.$jsFn.checkJinNiu() && !this.$jsFn.checkTrain() && this.$store.state.config.srvAdrType != 'product'
+        // },
         // 研修平台
         {
           icon: 'iconfont icon-basic-setting',

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 490 - 501
TEAMModelOS/ClientApp/src/view/coursemgt/NewCusMgt.vue


+ 10 - 1
TEAMModelOS/ClientApp/src/view/coursemgt/components/MemberTable.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="member-table-container">
-    <Table :columns="columns" :data="data" height="750">
+    <Table :columns="columns" :data="data" height="750" :loading="tableLoading">
       <template slot-scope="{ row, index }" slot="header">
         <PersonalPhoto :name="row.name" :picture="row.picture"></PersonalPhoto>
       </template>
@@ -16,6 +16,7 @@ export default {
   },
   data() {
     return {
+      tableLoading:false,
       columns: [
         {
           slot: "header",
@@ -70,5 +71,13 @@ export default {
     console.log(this.members);
     this.data = this.members;
   },
+  watch: {
+    members: {
+      immediate:true,
+      handler(n, o) {
+        this.data = this.members
+      },
+    },
+  },
 };
 </script>

+ 668 - 0
TEAMModelOS/ClientApp/src/view/iot/areaiot.vue

@@ -0,0 +1,668 @@
+<template>
+<div class="schooliotbox">
+    <div class="containerbox">
+        <!--header-->
+            <!--title-->
+            <div class="container-title">
+                <dv-decoration-10 class="dv-dec-10" />
+                <div class="title-center">
+                    <dv-decoration-8 class="dv-dec-8" :color="['#568aea', '#000000']" />
+                    <div class="title-text">
+                        <span class="title-textbox">{{$t('schoolIot.title')}}</span>
+                        <dv-decoration-6 class="dv-dec-6" :reverse="true" :color="['#50e3c2', '#67a1e5']" />
+                    </div>
+                    <dv-decoration-8 class="dv-dec-8" :reverse="true" :color="['#568aea', '#000000']" />
+                </div>
+                <dv-decoration-10 class="dv-dec-10-s" />
+            </div>
+             <!--title end -->
+             <!--school name-->
+             <div class="school-name">
+                <!-- <img :src="schoolInfo.schoolLogo">
+                <span class="schoolbox-name">{{ schoolInfo.schoolName }}</span>
+                <span class="schoolbox-period">{{ schoolInfo.periodName }}</span>
+                <span class="schoolbox-semester">{{ schoolInfo.curSemester }}</span> -->
+                <span class="schoolbox-name">{{ schoolInfo.names }}</span>
+             </div>
+             <!--school name  end-->
+             <!--time-->
+             <div class="timebox">
+                <span class="timebox-text">{{ times.year }} <span style="display: inline-block; margin: 0 5px;color: #0fa2fe;">{{ times.day }}</span> </span>
+             </div>
+             <!--time end-->
+        <!--header end-->
+        <!--containerbody-->
+        <div class="containerbody">
+            <!--containerbody top-->
+            <div class="topbox">
+                <dv-border-box-12>
+                    <div class="topbox-item" v-for="(item,index) in basicaList" :key="index">
+                        <div class="item-title-images">
+                        <div :class="[item.key ==='participationnum' && locals==='en-us' ? 'common-title':'','item-title']">{{item.title}}</div>
+                        <div class="item-images">
+                            <!-- <svg class="analysisicon" aria-hidden="true">
+                            <use :xlink:href="item.icon"></use>
+                            </svg> -->
+                        </div>
+                    </div>
+                        <div :class="[item.key === 'classtime' || item.key === 'participationnum' ? 'item-nums-special':'item-nums']">
+                        <p v-if="item.key === 'classtime' || item.key === 'participationnum'">{{item.value}}<span class="timetag">Min</span><br /><span>{{Math.round(item.value/60)}}<span class="timetag">H</span></span></p>
+                        <p v-else>
+                            <countTo :startVal='0' :endVal='item.value' :duration='1500'  v-show="index !== 0"></countTo>
+                            <span v-show="index ===0">{{item.value}}</span>
+                        </p>
+                        </div>
+                        <div class="totalclass" v-show="item.key === 'roomnum' || item.key === 'teachnum' || item.key === 'studentnum'">
+                        <div v-if="item.key ==='roomnum'">
+                            <p class="totalclass-total">{{$t('schoolIot.basics.classTotals')}}</p>
+                            <p class="totalclass-num">70</p>
+                        </div>
+                        <div v-else-if="item.key ==='teachnum'">
+                            <p class="totalclass-total">{{$t('schoolIot.basics.teachTotals')}}</p>
+                            <p class="totalclass-num">70</p>
+                        </div>    
+                        <div v-else-if="item.key ==='studentnum'">
+                            <p class="totalclass-total">{{$t('schoolIot.basics.studentTotals')}}</p>
+                            <p class="totalclass-num">70</p>
+                        </div>    
+                    </div>
+                    </div>
+                </dv-border-box-12>
+            </div>
+             <!--containerbody top end-->
+             <!--containerbody rests-->
+             <div class="restsbox">
+                <div class="restsbox-left">
+                    <dv-border-box-11 :title="$t('schoolIot.classrooming.title')">
+                        <div class="left-item" v-for="(item,index) in inuseList" :key="index">
+                            <div class="item-img">
+                                <!-- <Icon :custom="item.icon" class="top-header-icon"/> -->
+                                <img :src="item.src"></img>
+                            </div>
+                            <div class="item-box">
+                                <p><countTo :startVal='0' :endVal='item.value' :duration='1500' class="itembox-value"></countTo></p>
+                                <span>{{item.title}}</span>
+                            </div>
+                        </div>
+                    </dv-border-box-11>
+                </div>
+                <div class="restsbox-right">
+                    <dv-border-box-11 :title="$t('schoolIot.device.title')">
+                        <div class="right-box">
+                            <!-- <dv-scroll-board :config="config" style="width:100%;height:100%" /> -->
+                            <div class="right-box-left">
+                                <BaseCircle  circleId="hiteach" chatName="HiTeach" :percent="45" subTitle="45" totalNum="158"></BaseCircle>
+                            </div>
+                            <div class="right-box-left">
+                                <BaseCircle  circleId="hita" chatName="HiTA" :percent="20" subTitle="15" totalNum="60"></BaseCircle>
+                            </div>
+                            <div class="right-box-left">
+                                <BaseCircle  circleId="hitachcc" chatName="HiTeach CC" :percent="10" subTitle="23" totalNum="0"></BaseCircle>
+                            </div>
+                        </div>
+                    </dv-border-box-11>    
+                </div>
+             </div>
+             <!--containerbody rests end-->
+             <!--bottom-->
+             <div class="bottombox">
+                <div class="bottombox-left">
+                    <dv-border-box-12>
+                        <div class="innerbox">
+                            <p class="boxtitles">
+                                <span>{{$t('schoolIot.lessons.title')}}</span>
+                                <dv-decoration-3 style="width:200px;height:20px;"/>
+                            </p>
+                            <div class="innerbox-inside">
+                                <!-- <div class="data-left">
+                                <BaseCircle  circleId="hiteach" chatName="HiTeach" :percent="45" subTitle="45" totalNum="158"></BaseCircle>
+                                </div>
+                                <div class="data-left">
+                                    <BaseCircle  circleId="hita" chatName="HiTA" :percent="20" subTitle="15" totalNum="60"></BaseCircle>
+                                </div>
+                                <div class="data-left">
+                                    <BaseCircle  circleId="hitachcc" chatName="HiTeach CC" :percent="10" subTitle="23" totalNum="80"></BaseCircle>
+                                </div>
+                                <div class="data-left">
+                                    <BaseCircle  circleId="webirs" chatName="WebIRS" :percent="40" subTitle="45" totalNum="77"></BaseCircle>
+                                </div> -->
+                                <barandLine ></barandLine>
+                            </div>
+                            <!-- <dv-decoration-2 :reverse="true" style="width:5px;height:95%;" :dur="5" /> -->
+                            <!-- <div class="data-right">
+                                <div class="data-right-top">
+                                    <YPie title="本月" :pieData="monthData"></YPie>
+                                </div>
+                                <div class="data-right-bottom">
+                                    <YPie title="学期" :pieData="semesterData"></YPie>
+                                </div>
+                            </div> -->
+                        </div>
+                    </dv-border-box-12>    
+                </div>
+                <div class="right-integration">
+                    <div class="bottombox-right">
+                        <dv-border-box-12>
+                            <div class="innerbox">
+                                <p class="boxtitles">
+                                    <span>课堂记录统计</span>
+                                    <dv-decoration-3 style="width:200px;height:20px;"/>
+                                </p>
+                                <div class="barbox">
+                                    <!-- <Bar title="学期" :pieData="bars"></Bar> -->
+                                      <dv-scroll-board :config="config" style="width:100%;height:100%" />
+                                </div>
+                            </div>
+                        </dv-border-box-12>    
+                    </div>
+                    <div class="bottombox-right">
+                        <dv-border-box-12>
+                            <div class="innerbox">
+                                <p class="boxtitles">
+                                    <span>{{$t('schoolIot.morphologyClass.title')}}</span>
+                                    <dv-decoration-3 style="width:200px;height:20px;"/>
+                                </p>
+                                <div class="barbox">
+                                    <Bar title="学期" :pieData="bars"></Bar>
+                                </div>
+                            </div>
+                        </dv-border-box-12>    
+                    </div>
+                </div>
+             </div>
+             <!--bottom end-->
+        </div>
+         <!--containerbodyend-->
+    </div>
+</div>
+</template>
+<script>
+import countTo from 'vue-count-to'
+import BasePie from '@/components/echart/pie/index'
+import YPie from './echarts/pie/index'
+import Bar from './echarts/bar/index'
+import BaseCircle from "./echarts/circle/index";
+import barandLine from './echarts/barandLine/barandLine'
+export default {
+   name:'areaiot',
+   components: {
+    countTo,
+    BasePie,
+    YPie,
+    Bar,
+    BaseCircle,
+    barandLine
+  },
+   data(){
+    return{
+        times:{
+            year:null,
+            month:null,
+            week:null,
+            day:null
+        },
+        weekday: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
+        basicaList:[
+        // { title: '学校简码', icon: '#icon-xuanzexuexiao-01', value: 'hbcn', key: 'code' },
+        { title: this.$t('schoolIot.basics.classnums'), icon: '#icon-shouhuifangzi', value: 65, key: 'roomnum' },
+        { title: this.$t('schoolIot.basics.teachnums'), icon: '#icon-jiaoshijie', value: 158, key: 'teachnum' },
+        { title: this.$t('schoolIot.basics.studentnums'), icon: '#icon-zongrenshu', value: 7603, key: 'studentnum' },
+        { title: this.$t('schoolIot.basics.studentTime'), icon: '#icon-_shijian_xiaoshuai', value: 450, key: 'participationnum' },
+        { title: this.$t('schoolIot.basics.classroomTotal'), icon: '#icon-ketang', value: 45, key: 'classnum' },
+        { title: this.$t('schoolIot.basics.classroomTime'), icon: '#icon--shijian ', value: 648, key: 'classtime' },
+        ],
+        inuseList:[
+        { title: this.$t('schoolIot.classrooming.taskNums'), value: 15, icon: 'iconfont icon-renwu',src:require("@/assets/image/iot/task.png"),class: 'task', textClass: 'task-text' },
+        { title: this.$t('schoolIot.classrooming.productionNums'), value: 10, icon: 'iconfont icon-zuopinzhanshi',src:require("@/assets/image/iot/production.png"),class: 'accomplish', textClass: 'accomplish-text' },
+        { title: this.$t('schoolIot.classrooming.topicNums'), value: 22, icon: 'iconfont icon-xingbiaoti-',src:require("@/assets/image/iot/exam.png"),class: 'topic', textClass: 'topic-text' },
+        { title: this.$t('schoolIot.classrooming.interactionNums'), value: 58, icon: 'iconfont icon-hudongshequ',src:require("@/assets/image/iot/interact.png"),class: 'interaction', textClass: 'interaction-text' },
+        ],
+        config:{
+            header: ['教师','学校','时间','科目'],
+            data: [
+               ['王老师','东城一小','72Min','语文'],
+               ['李老师','锦江四小','32Min','数学'],
+               ['金老师','川师附小','48Min','英语'],
+               ['周老师','川师附小','54Min','数学'],
+               ['郭老师','川师附小','22Min','音乐'],
+               ['秦老师','锦江外国语小学','18Min','美术'],
+               ['晓老师','锦江四小','72Min','英语'],
+               ['车老师','锦江外国语小学','32Min','数学'],
+               ['王老师','锦江外国语小学','48Min','英语'],
+               ['李老师','锦江四小','54Min','语文'],
+            ],
+            index: true,
+            indexHeader:'排名',
+            // columnWidth: [200,200,200,200],
+            align: ['center'],
+            carousel: 'single',
+            headerBGC:'rgba(19, 25, 47, 0.6)',
+            oddRowBGC:'rgba(19, 25, 47, 0.6)',
+            evenRowBGC:'rgba(19, 25, 47, 0.6)',
+            waitTime:'4000'
+        },
+        todayData:[
+            {name:this.$t('schoolIot.device.deviceTotal'),value:58},
+            {name:this.$t('schoolIot.device.deviceOnline'),value:50},
+        ],
+        monthData:[
+            {name:'六年二班',value:120},
+            {name:'三年四班',value:98},
+            {name:'五年三班',value:88},
+            {name:'四年二班',value:75},
+            {name:'二年二班',value:65},
+            {name:'一年五班',value:40},
+        ],
+        semesterData:[
+            {name:'六年二班',value:220},
+            {name:'五年四班',value:150},
+            {name:'六年三班',value:144},
+            {name:'四年二班',value:139},
+            {name:'二年二班',value:98},
+            // {name:'四年五班',value:75},
+            // {name:'九年二班',value:98},
+            // {name:'八年五班',value:75},
+            // {name:'七年二班',value:98},
+            // {name:'十年五班',value:75},
+        ],
+        bars:{
+            xdata:[this.$t('schoolIot.morphologyClass.cooperation'), this.$t('schoolIot.morphologyClass.interaction'), this.$t('schoolIot.morphologyClass.task'), this.$t('schoolIot.morphologyClass.differentiation'),  this.$t('schoolIot.morphologyClass.examination')],
+            value:[254, 3254, 1654, 2454, 757,]
+        },
+        locals:'',
+    }
+   },
+   mounted(){
+    this.timeFn()
+   },
+   created(){
+     this.locals=localStorage.local
+     console.log(this.locals,'语言')
+   },
+   computed: {
+    schoolInfo() {
+    //   let store_user = this.$store.state.user
+    //   let semesterRange = this.$tools.getSemesterTimeRange()
+    //   console.log(store_user,semesterRange)
+    //   return {
+    //     schoolName: store_user.schoolProfile.school_base.name,
+    //     schoolLogo: store_user.schoolProfile.school_base.picture,
+    //     periodName: store_user.curPeriod.name,
+    //     curSemester: semesterRange.name_with_year
+    //   }
+       let areaName=sessionStorage.areaName
+    return{
+        names:areaName
+    }
+    }
+  },
+   methods:{
+    timeFn() {
+      this.timing = setInterval(() => {
+        this.times.day = this.$tools.formatTime(new Date(), 'hh:mm:ss')
+        this.times.year = this.$tools.formatTime(new Date(), 'yyyy-MM-dd')
+        this.times.week = this.weekday[new Date().getDay()]
+      }, 1000)
+    },
+   }
+}
+</script>
+<style scoped>
+.schooliotbox{
+    color: #d3d6dd;
+    width: 100%;
+    height: 100%;
+    overflow: hidden;
+    position: relative;
+}
+.containerbox{
+    width:100%;
+    height:100%;
+    padding: 16px 16px 0 16px;
+    background-image:url('../../assets/image/pageBg.png');
+    background-size: cover;
+    background-position: center center;
+}
+.container-title,.title-center{
+    display: flex;
+    flex-wrap: nowrap;
+}
+.title-text{
+    position: relative;
+    width: 500px;
+    text-align: center;
+    background-size: cover;
+    background-repeat: no-repeat;
+}
+.title-textbox{
+    font-size: 28px;
+    font-weight: bold;
+    position: absolute;
+    letter-spacing: 3px;
+    display: inline-block;
+    background-image: linear-gradient(#00b5ef, #7393a6);
+    -webkit-background-clip: text;
+    background-clip: text;
+    font-family: auto;
+    color: transparent;
+    bottom: 15px;
+    left: 50%;
+    transform: translate(-50%);
+    width: 80%;
+}
+.schooliotbox .dv-dec-10{
+    width:33.3%;
+    height:5px;
+    display: flex;
+}
+.schooliotbox .dv-dec-10-s{
+    transform: rotateY(180deg);
+    width:33.3%;
+    height:5px;
+    display: flex;
+}
+.schooliotbox .dv-dec-8{
+    width: 200px;
+    height: 50px;
+    display: flex;
+}
+.schooliotbox .title-center .dv-dec-6{
+    position: absolute;
+    bottom:0;
+    left:50%;
+    width:250px;
+    height:8px;
+    transform: translate(-50%);
+}
+.school-name{
+    position: absolute;
+    left: 30px;
+    top: 40px;
+    font-size: 20px;
+    font-weight: bold;
+    cursor: pointer;
+    display: flex;
+    align-items: center;
+}
+.school-name img{
+    border-radius: 50%;
+    width: 25px;
+}
+.schoolbox-name{
+    margin: 0 10px;
+}
+.schoolbox-period,.schoolbox-semester{
+    font-size: 12px;
+    background-color: #2d2d2d;
+    display: inline-block;
+    padding: 2px 10px;
+    border-radius: 4px;
+    margin-right: 5px;
+}
+.timebox{
+    position: absolute;
+    right: 30px;
+    top: 30px;
+    font-size: 26px;
+    font-weight: bold;
+    cursor: pointer;
+}
+.timebox-text{
+    font-size: 30px;
+    margin-right: 20px;
+    font-weight: 200;
+    color: #9f9f9f;
+    font-family: 'staticFont';
+}
+.containerbody{
+    margin-top: 20px;
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+}
+.topbox{
+    width:100%;
+    height:15vh;
+    display: flex;
+    flex-wrap: nowrap;
+    justify-content: space-between;
+}
+.topbox-item{
+    display: flex;
+    width: 15%;
+    padding: 8px;
+    flex-direction: column;
+    line-height: 60px;
+    border-radius: 5px;
+    /* box-shadow: 0 2px 5px #e9e9e9; */
+    margin: 0.8%;
+    background-color: rgba(19, 25, 47, 0.6);
+    position:relative;
+}
+.item-title-images {
+  width: 100%;
+  display: flex;
+  flex-wrap: nowrap;
+  justify-content: space-between;
+}
+.item-title-images {
+  width: 100%;
+  display: flex;
+  flex-wrap: nowrap;
+  justify-content: space-between;
+}
+.item-title {
+  font-size: 16px;
+  /* font-weight: bold; */
+  color: #05d5ff;
+}
+.analysisicon {
+  width: 2.3em;
+  height: 2.3em;
+  vertical-align: -0.5em;
+  fill: currentColor;
+  /* overflow: hidden;
+  margin-right: 25px;
+  margin-left: 0px; */
+}
+.item-nums {
+  width: 100%;
+  font-size: 22px;
+  font-weight: bold;
+  color: #d3d6dd;
+  position: relative;
+}
+.item-nums-special {
+  width: 100%;
+  font-size: 20px;
+  font-weight: bold;
+  color: #d3d6dd;
+  line-height: 20px;
+}
+.timetag {
+  font-size: 14px;
+  margin-left: 1%;
+  color: #7f8c8d;
+}
+.restsbox{
+    width:100%;
+    height:21vh;
+    display: flex;
+    flex-wrap: nowrap;
+    justify-content: space-between;
+}
+.restsbox-left,.restsbox-right{
+    width:50%;
+}
+.left-item{
+  width: 21%;
+  display: flex;
+  height: 110px;
+  justify-content: center;
+  align-items: center;
+  border-radius: 5px;
+  background-color: rgba(19, 25, 47, 0.6);
+  margin: 9% 2% 1% 2%;
+}
+.item-img {
+  width: 45%;
+  position:relative
+}
+.item-img img{
+    width:50%;
+    margin-left:15%;
+}
+.inuseicon {
+  width: 3em;
+  height: 3em;
+  vertical-align: -0.5em;
+  fill: currentColor;
+}
+.item-box {
+  padding: 5px 0px;
+}
+.item-img {
+  width: 45%;
+}
+.item-box {
+  width: 54%;
+}
+.item-box p,
+.inuse-total p {
+  font-size: 22px;
+  color: #d3d6dd;
+  font-weight: bold;
+  margin-bottom: 5px;
+}
+.itembox-value{
+  font-size: 22px !important;
+  color: #d3d6dd !important;
+  font-weight: bold;
+  margin-bottom: 5px;
+}
+.item-box span,
+.inuse-total span {
+  font-size: 14px;
+  color: #05d5ff;
+}
+.inuse-total {
+  position: absolute;
+  top: 5%;
+  left: 5%;
+  width: 30%;
+  line-height: 20px;
+  text-align: left;
+}
+.right-box{
+    width:100%;
+    /* padding: 6% 2% 2% 2%; */
+    display: flex;
+}
+.count-num{
+    display: inline-block;
+    margin-top: 5px;
+    font-size: 28px;
+    font-weight: bold;
+}
+.bottombox{
+    width:100%;
+    display: flex;
+    height:49vh;
+}
+.bottombox-left{
+    width:55%;
+    display: flex;
+}
+.innerbox{
+    width:100%;
+    height:100%;
+    padding: 20px 16px;
+    display: flex;
+    flex-wrap: wrap;
+   
+}
+.innerbox-inside{
+    width:100%;
+    height:98%;
+    background-color: rgba(19, 25, 47, 0.6);
+    /* display: flex;
+    flex-wrap: wrap; */
+}
+.bottombox-right{
+    width:100%;
+    height:50%;
+}
+.data-left,.data-right{
+    width:50%;
+    padding: 1%;
+    height:48%;
+}
+.separate-line{
+    width:2px;
+    height:95%;
+    background-color: #fff;
+}
+.boxtitles{
+    width:100%;
+    background-color: rgba(19, 25, 47, 0.6);
+    display: flex;
+    line-height: 20px;
+    padding-left: 1%;
+}
+.data-right{
+    display: flex;
+    flex-wrap: wrap;
+}
+.data-right-top,.data-right-bottom{
+    width:100%;
+    padding: 0%;
+    height:50%;
+}
+.barbox{
+    width:100%;
+    height:95%;
+    background-color: rgba(19, 25, 47, 0.6);
+}
+.top-header-icon {
+  fill: currentColor;
+  overflow: hidden;
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+  font-size: 38px;
+}
+.totalclass{
+    position:absolute;
+    right:3%;
+    bottom:2%;
+    line-height: 40px;
+    text-align: center;
+}
+.totalclass-total{
+    color: #05d5ff;
+    font-size:14px;
+}
+.totalclass-num{
+    font-size:20px;
+    color:#d3d6dd;
+}
+.right-box-left{
+    width:31%;
+    padding: 6% 1% 1% 1%;
+    height:100%;
+}
+.common-title{
+    line-height: 30px !important;
+}
+.right-integration{
+    width:45%;
+    display: flex;
+    flex-wrap: wrap;
+}
+</style>
+<style>
+.schooliotbox .topbox  .border-box-content,.schooliotbox .restsbox .border-box-content{
+    display: flex;
+}
+</style>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/iot/echarts/bar/bar.vue

@@ -142,7 +142,7 @@
 							top:'7%',
 							left:'7%',
 							right:'3%',
-							bottom:'9%'
+							bottom:'15%'
 						},
 						toolbox: {
 							show: false

+ 54 - 24
TEAMModelOS/ClientApp/src/view/iot/echarts/barandLine/barandLine.vue

@@ -15,7 +15,8 @@
           line2: [],
           line3: [],
           line4: [],
-        }
+        },
+        transferJson:[]
       };
     },
     components: {
@@ -26,41 +27,63 @@
         type: Object,
         default: () => ({})
       },
+      baldata: {
+        type: Array,
+        default: () => ([])
+      },
     },
     created() {
       // 获取课例趋势图数据
     //   let trendJson = this.$store.state.dashboard.researchDashboard.trend
      let trendJson=[
-        {name:1,value:[43,5,3,7]},
-        {name:2,value:[15,0,2,5]},
-        {name:3,value:[77,15,30,48]},
-        {name:4,value:[62,15,21,45]},
-        {name:5,value:[33,11,13,27]},
-        {name:6,value:[105,35,43,87]},
-        {name:7,value:[80,30,33,57]},
-        {name:8,value:[70,25,23,62]},
-        {name:9,value:[23,5,13,27]},
-        {name:10,value:[66,18,23,47]},
-        {name:11,value:[55,15,13,37]},
+        // {name:1,value:[43,5,3,7]},
+        // {name:2,value:[15,0,2,5]},
+        // {name:3,value:[77,15,30,48]},
+        // {name:4,value:[62,15,21,45]},
+        // {name:5,value:[33,11,13,27]},
+        // {name:6,value:[105,35,43,87]},
+        // {name:7,value:[80,30,33,57]},
+        // {name:8,value:[70,25,23,62]},
+        // {name:9,value:[23,5,13,27]},
+        // {name:10,value:[66,18,23,47]},
+        // {name:11,value:[55,15,13,37]},
         // {name:12,value:[43,5,3,7]},
         // {name:13,value:[43,5,3,7]},
         // {name:14,value:[43,5,3,7]},
         // {name:15,value:[43,5,3,7]},
         // {name:16,value:[43,5,3,7]},
-     ]
-      if (trendJson) {
-        trendJson.forEach(i => {
-          this.trendData.xData.push(`${this.$t('lessonRecord.echarts.weekUtil')}${i.name}${this.$t('lessonRecord.echarts.week')}`)
-          this.trendData.line1.push(i.value[0])
-          this.trendData.line2.push(i.value[1])
-          this.trendData.line3.push(i.value[2])
-          this.trendData.line4.push(i.value[3])
-        })
+      ]
+      // trendJson=this.transferJson
+      // if (trendJson) {
+      //   trendJson.forEach(i => {
+      //     this.trendData.xData.push(`${this.$t('lessonRecord.echarts.weekUtil')}${i.name}${this.$t('lessonRecord.echarts.week')}`)
+      //     this.trendData.line1.push(i.value[0])
+      //     this.trendData.line2.push(i.value[1])
+      //     this.trendData.line3.push(i.value[2])
+      //     this.trendData.line4.push(i.value[3])
+      //   })
+      // }
+      
+    },
+    methods: {
+      init() {
+        let trendJson=[]
+        trendJson=this.transferJson
+        if (trendJson) {
+          trendJson.forEach(i => {
+            this.trendData.xData.push(`${this.$t('lessonRecord.echarts.weekUtil')}${i.name}${this.$t('lessonRecord.echarts.week')}`)
+            this.trendData.line1.push(i.value[0])
+            this.trendData.line2.push(i.value[1])
+            this.trendData.line3.push(i.value[2])
+            this.trendData.line4.push(i.value[3])
+          })
+        }
       }
     },
     watch: {
       cdata: {
         handler(newData) {
+          console.log(newData,'bal的数据s')
           this.options = {
             tooltip: {
               trigger: "axis",
@@ -258,7 +281,7 @@
             //     }, 
             //     ]
             // },
-            data: [13, 8, 45, 31, 19, 74, 27,30,10,15,13]
+            data:this.trendData.line2
             },
             {  //题目数量
             name: this.$t('schoolIot.lessons.topicNums'),
@@ -320,7 +343,7 @@
             //     }, 
             //     ]
             // },
-            data: [9, 5, 15, 21, 23, 34, 17,20,5,8,9]
+            data:this.trendData.line3
             },
             { //互动数量
             name: this.$t('schoolIot.lessons.interactionNums'),
@@ -382,7 +405,7 @@
             //     }, 
             //     ]
             // },
-            data: [88, 75, 65, 101, 73, 64, 47,40,35,28,19]
+            data: this.trendData.line4
             },
          ]
           }
@@ -390,6 +413,13 @@
         immediate: true,
         deep: true
       },
+      baldata: {
+          handler(newData) {
+            newData.length !==0 ? (this.transferJson=newData,this.init()):''
+          },
+          immediate: true,
+          deep: true
+      }
     },
   }
   </script>

+ 3 - 1
TEAMModelOS/ClientApp/src/view/iot/echarts/circle/index.vue

@@ -32,6 +32,7 @@
     },
     methods: {
       doRender() {
+        console.log('触发方法')
         if(!document.getElementById(this.circleId)) return
         let myChart = this.$echarts.init(document.getElementById(this.circleId))
         let option = {
@@ -123,7 +124,7 @@
         };
         myChart.clear()
         console.log(this.totalNum,'引用的值')
-        if(this.totalNum == 0){
+        if(this.totalNum == 0 && this.chatName ==='HiTeach CC'){
           option.title.splice(2,1)
           option.title[0].top='30%'
           // option.title[1].top='0%'
@@ -143,6 +144,7 @@
         deep: true,
         immediate: true,
         handler(n, o) {
+          console.log('触发time')
           this.doRender()
         }
       }

+ 118 - 17
TEAMModelOS/ClientApp/src/view/iot/schooliot.vue

@@ -54,15 +54,15 @@
                         <div class="totalclass" v-show="item.key === 'roomnum' || item.key === 'teachnum' || item.key === 'studentnum'">
                         <div v-if="item.key ==='roomnum'">
                             <p class="totalclass-total">{{$t('schoolIot.basics.classTotals')}}</p>
-                            <p class="totalclass-num">70</p>
+                            <p class="totalclass-num">{{item.total}}</p>
                         </div>
                         <div v-else-if="item.key ==='teachnum'">
                             <p class="totalclass-total">{{$t('schoolIot.basics.teachTotals')}}</p>
-                            <p class="totalclass-num">70</p>
+                            <p class="totalclass-num">{{item.total}}</p>
                         </div>    
                         <div v-else-if="item.key ==='studentnum'">
                             <p class="totalclass-total">{{$t('schoolIot.basics.studentTotals')}}</p>
-                            <p class="totalclass-num">70</p>
+                            <p class="totalclass-num">{{item.total}}</p>
                         </div>    
                     </div>
                     </div>
@@ -90,13 +90,13 @@
                         <div class="right-box">
                             <!-- <dv-scroll-board :config="config" style="width:100%;height:100%" /> -->
                             <div class="right-box-left">
-                                <BaseCircle  circleId="hiteach" chatName="HiTeach" :percent="45" subTitle="45" totalNum="158"></BaseCircle>
+                                <BaseCircle  circleId="hiteach" chatName="HiTeach" :percent="equipmentData.hiteachPercent" :subTitle="equipmentData.hiteachOnline" :totalNum="equipmentData.hiteachTotal"></BaseCircle>
                             </div>
                             <div class="right-box-left">
-                                <BaseCircle  circleId="hita" chatName="HiTA" :percent="20" subTitle="15" totalNum="60"></BaseCircle>
+                                <BaseCircle  circleId="hita" chatName="HiTA" :percent="equipmentData.hitaPercent" :subTitle="equipmentData.hitaOnline" :totalNum="equipmentData.hitaTotal"></BaseCircle>
                             </div>
                             <div class="right-box-left">
-                                <BaseCircle  circleId="hitachcc" chatName="HiTeach CC" :percent="10" subTitle="23" totalNum="0"></BaseCircle>
+                                <BaseCircle  circleId="hitachcc" chatName="HiTeach CC" :percent="equipmentData.ccPercent" :subTitle="equipmentData.ccOnline" totalNum="0"></BaseCircle>
                             </div>
                         </div>
                     </dv-border-box-11>    
@@ -125,7 +125,7 @@
                                 <div class="data-left">
                                     <BaseCircle  circleId="webirs" chatName="WebIRS" :percent="40" subTitle="45" totalNum="77"></BaseCircle>
                                 </div> -->
-                                <barandLine ></barandLine>
+                                <barandLine :baldata="baldatas"></barandLine>
                             </div>
                             <!-- <dv-decoration-2 :reverse="true" style="width:5px;height:95%;" :dur="5" /> -->
                             <!-- <div class="data-right">
@@ -160,12 +160,12 @@
 </div>
 </template>
 <script>
-import countTo from 'vue-count-to'
-import BasePie from '@/components/echart/pie/index'
-import YPie from './echarts/pie/index'
-import Bar from './echarts/bar/index'
+import BasePie from '@/components/echart/pie/index';
+import countTo from 'vue-count-to';
+import Bar from './echarts/bar/index';
+import barandLine from './echarts/barandLine/barandLine';
 import BaseCircle from "./echarts/circle/index";
-import barandLine from './echarts/barandLine/barandLine'
+import YPie from './echarts/pie/index';
 export default {
    name:'schooliot',
    components: {
@@ -184,11 +184,12 @@ export default {
             week:null,
             day:null
         },
+        weekday: ['周日', '周一', '周二', '周三', '周四', '周五', '周六'],
         basicaList:[
         // { title: '学校简码', icon: '#icon-xuanzexuexiao-01', value: 'hbcn', key: 'code' },
-        { title: this.$t('schoolIot.basics.classnums'), icon: '#icon-shouhuifangzi', value: 65, key: 'roomnum' },
-        { title: this.$t('schoolIot.basics.teachnums'), icon: '#icon-jiaoshijie', value: 158, key: 'teachnum' },
-        { title: this.$t('schoolIot.basics.studentnums'), icon: '#icon-zongrenshu', value: 7603, key: 'studentnum' },
+        { title: this.$t('schoolIot.basics.classnums'), icon: '#icon-shouhuifangzi', value: 65, key: 'roomnum',total:77, },
+        { title: this.$t('schoolIot.basics.teachnums'), icon: '#icon-jiaoshijie', value: 158, key: 'teachnum',total:77, },
+        { title: this.$t('schoolIot.basics.studentnums'), icon: '#icon-zongrenshu', value: 7603, key: 'studentnum',total:77,},
         { title: this.$t('schoolIot.basics.studentTime'), icon: '#icon-_shijian_xiaoshuai', value: 450, key: 'participationnum' },
         { title: this.$t('schoolIot.basics.classroomTotal'), icon: '#icon-ketang', value: 45, key: 'classnum' },
         { title: this.$t('schoolIot.basics.classroomTime'), icon: '#icon--shijian ', value: 648, key: 'classtime' },
@@ -199,6 +200,17 @@ export default {
         { title: this.$t('schoolIot.classrooming.topicNums'), value: 22, icon: 'iconfont icon-xingbiaoti-',src:require("@/assets/image/iot/exam.png"),class: 'topic', textClass: 'topic-text' },
         { title: this.$t('schoolIot.classrooming.interactionNums'), value: 58, icon: 'iconfont icon-hudongshequ',src:require("@/assets/image/iot/interact.png"),class: 'interaction', textClass: 'interaction-text' },
         ],
+        //设备统计
+        equipmentData: {
+          hiteachTotal: 0,
+          hiteachOnline: 0,
+          hiteachPercent:0,
+          hitaTotal: 0,
+          hitaOnline: 0,
+          hitaPercent:0,
+          ccOnline: 0,
+          ccPercent:0,
+        },
         config:{
             header: ['教室', '教师', '时间','科目'],
             data: [
@@ -248,9 +260,10 @@ export default {
         ],
         bars:{
             xdata:[this.$t('schoolIot.morphologyClass.cooperation'), this.$t('schoolIot.morphologyClass.interaction'), this.$t('schoolIot.morphologyClass.task'), this.$t('schoolIot.morphologyClass.differentiation'),  this.$t('schoolIot.morphologyClass.examination')],
-            value:[254, 3254, 1654, 2454, 757,]
+            value:[0, 0, 0, 0, 0,]
         },
-        locals:'',
+      locals: '',
+      baldatas:[],
     }
    },
    mounted(){
@@ -259,11 +272,13 @@ export default {
    created(){
      this.locals=localStorage.local
      console.log(this.locals,'语言')
+     this.init()
    },
    computed: {
     schoolInfo() {
       let store_user = this.$store.state.user
       let semesterRange = this.$tools.getSemesterTimeRange()
+      console.log(this.$store.state.user,'信息')
       return {
         schoolName: store_user.schoolProfile.school_base.name,
         schoolLogo: store_user.schoolProfile.school_base.picture,
@@ -280,6 +295,92 @@ export default {
         this.times.week = this.weekday[new Date().getDay()]
       }, 1000)
     },
+    init(){
+        let userdatas = this.$store.state.user
+        let data={schoolId:userdatas.schoolCode,periodId:userdatas.curPeriod.id}
+        this.$api.iot.getSchooliot(data).then((res)=>{
+          console.log(res, 'iot back')
+          //header基础数据
+          let { classCnt, deviceAuthCnt, teacherShow,teacherCnt, stuShow, studentCnt, stuLessonLengMin, lessonRecord, lessonLengMin } = res
+          this.basicaList[0].value = classCnt
+          this.basicaList[0].total = deviceAuthCnt
+          this.basicaList[1].value= teacherShow
+          this.basicaList[1].total = teacherCnt
+          this.basicaList[2].value = stuShow
+          this.basicaList[2].total = studentCnt
+          this.basicaList[3].value = stuLessonLengMin
+          this.basicaList[4].value = lessonRecord
+          this.basicaList[5].value = lessonLengMin
+          //课中统计 和 设备统计
+          let { mission, missionFin, item, interact, htcDevTotalCnt, htcDevCnt, htaDevTotalCnt, htaDevCnt, htccDevCnt } = res
+          this.inuseList[0].value = mission
+          this.inuseList[1].value = missionFin
+          this.inuseList[2].value = item
+          this.inuseList[3].value = interact
+
+          this.equipmentData.hiteachTotal = htcDevTotalCnt.toString()
+          this.equipmentData.hiteachOnline = htcDevCnt.toString()
+          this.equipmentData.hiteachPercent=Math.round((htcDevCnt/htcDevTotalCnt)*100)
+          this.equipmentData.hitaTotal = htaDevTotalCnt.toString()
+          this.equipmentData.hitaOnline = htaDevCnt.toString()
+          this.equipmentData.hitaPercent=Math.round((htaDevCnt/htaDevTotalCnt)*100)
+          this.equipmentData.ccOnline = htccDevCnt.toString()
+          this.equipmentData.ccPercent = 100
+
+          //多型态课堂
+          let {lTypeCoop,lTypeIact,lTypeMis,lTypeDif,lTypeTst }=res
+          this.bars.value = [lTypeCoop, lTypeIact, lTypeMis, lTypeDif, lTypeTst]
+          //处理课堂及历程统计
+          let time = new Date()
+          let nowTime = this.timeCycle(time.toLocaleString('en-US',{hour12: false}).split(" "))
+          console.log(nowTime, '时间')
+          let startime = new Date(res.sdate);let targettime=new Date(res.edate)
+          let weekNum = this.calculateWeekNumber(startime, targettime)
+          console.log(weekNum, '第几周')
+          let totalData = []
+          for (let i = 1; i <= weekNum; i++){
+            totalData.push({week:i,class:0,works:0,topic:0,interaction:0,})
+          }
+          //循环数据
+          res.iotData.forEach(item => {
+            let times = new Date(item.year + '-' + item.month + '-' + item.day)
+            let returnWeek = this.calculateWeekNumber(startime, times)
+            console.log(returnWeek,'数据属于第几周')
+            let reresultIndex = totalData.findIndex((item) => { return item.week === returnWeek })
+            console.log(reresultIndex,'下标位置')
+            totalData[reresultIndex].class += item.lessonRecord
+            totalData[reresultIndex].works += item.missionFin
+            totalData[reresultIndex].topic += item.item
+            totalData[reresultIndex].interaction += item.interact
+          });
+          console.log(totalData, '结果')
+          //处理成barandline需要的数据
+          let ultimatelyData = []
+          totalData.forEach((item) => { 
+            let valueData=[item.class,item.works,item.topic,item.interaction]
+            ultimatelyData.push({name:item.week,value:valueData})
+          })
+          console.log(ultimatelyData, '最终数据')
+          this.baldatas=ultimatelyData
+        })
+     },
+     //时间转换
+    timeCycle(times) {
+        let time = times[1]
+        let mdy = times[0]
+        mdy = mdy.split('/')
+        let month = parseInt(mdy[0]);
+        let day = parseInt(mdy[1]);
+        let year = parseInt(mdy[2])
+        return year + '-' + month + '-' + day
+    },
+      //处理时间问题
+     calculateWeekNumber(startDate, targetDate) {
+        const oneDay = 24 * 60 * 60 * 1000; // 一天的毫秒数
+        const daysPassed = Math.round((targetDate - startDate) / oneDay);
+        const weekNumber = Math.ceil((daysPassed + startDate.getDay() + 1) / 7);
+        return weekNumber;
+     },
    }
 }
 </script>

+ 24 - 13
TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue

@@ -178,7 +178,8 @@ export default {
       mode: '',
       selectBefore: [],
       stuList: [],
-      showBack: false
+      showBack: false,
+      isComplete: false,
     }
   },
   methods: {
@@ -477,6 +478,7 @@ export default {
 
       this.$api.learnActivity.SaveExamInfo(requestData).then(
         res => {
+          this.isComplete = true
           if (res.error) {
             // this.$Message.error('API ERROR!')
             this.$Message.error(this.$t('learnActivity.mark.saveErr'))
@@ -735,19 +737,28 @@ export default {
     }
   },
   beforeRouteLeave(to, from, next) {
-    this.$Modal.confirm({
-      title: this.$t('evaluation.newExercise.modalTip'),
-      content: this.$t('learnActivity.createEv.unSaveTip'),
-      cancelText: this.$t('auth.cancel'),
-      onOk: () => {
-        if (to.name == 'answerSheet') {
-          from.meta.isKeep = true
-        } else {
-          from.meta.isKeep = false
-        }
-        next()
+    if(this.isComplete) {
+      if (to.name == 'answerSheet') {
+        from.meta.isKeep = true
+      } else {
+        from.meta.isKeep = false
       }
-    })
+      next()
+    } else {
+      this.$Modal.confirm({
+        title: this.$t('evaluation.newExercise.modalTip'),
+        content: this.$t('learnActivity.createEv.unSaveTip'),
+        cancelText: this.$t('auth.cancel'),
+        onOk: () => {
+          if (to.name == 'answerSheet') {
+            from.meta.isKeep = true
+          } else {
+            from.meta.isKeep = false
+          }
+          next()
+        }
+      })
+    }
   }
 }
 </script>

+ 24 - 13
TEAMModelOS/ClientApp/src/view/learnactivity/CreateSchoolEva.vue

@@ -248,7 +248,8 @@ export default {
             befPeriod: {
                 id: '',
                 name: ''
-            }
+            },
+            isComplete: false
         }
     },
     methods: {
@@ -682,6 +683,7 @@ export default {
             
             this.$api.learnActivity.SaveExamInfo(requestData).then(
                 res => {
+                    this.isComplete = true
                     if (res.error) {
                         // this.$Message.error('API ERROR!')
                         this.$Message.error(this.$t('learnActivity.mark.saveErr'))
@@ -968,19 +970,28 @@ export default {
         }
     },
     beforeRouteLeave(to, from, next) {
-        this.$Modal.confirm({
-            title: this.$t('evaluation.newExercise.modalTip'),
-            content: this.$t('learnActivity.createEv.unSaveTip'),
-            cancelText: this.$t('auth.cancel'),
-            onOk: () => {
-                if (to.name == 'answerSheet') {
-                    from.meta.isKeep = true
-                } else {
-                    from.meta.isKeep = false
-                }
-                next()
+        if(this.isComplete) {
+            if (to.name == 'answerSheet') {
+                from.meta.isKeep = true
+            } else {
+                from.meta.isKeep = false
             }
-        })
+            next()
+        } else {
+            this.$Modal.confirm({
+                title: this.$t('evaluation.newExercise.modalTip'),
+                content: this.$t('learnActivity.createEv.unSaveTip'),
+                cancelText: this.$t('auth.cancel'),
+                onOk: () => {
+                    if (to.name == 'answerSheet') {
+                        from.meta.isKeep = true
+                    } else {
+                        from.meta.isKeep = false
+                    }
+                    next()
+                }
+            })
+        }
     }
 }
 </script>

+ 23 - 5
TEAMModelOS/Controllers/Both/CourseBaseController.cs

@@ -124,7 +124,7 @@ namespace TEAMModelOS.Controllers.Both
                             List<CourseBase> courseBases = _courses.ToObject<List<CourseBase>>();
                             //1.检查导入的课程名称是否有效
                             StringBuilder sqlName = new StringBuilder(" select  value c from c ");
-                            sqlName.Append($" where c.name in {string.Join(",",courseBases.Select(z=>$"'{z.name}'"))}    and  c.period.id='{_periodId}' ");
+                            sqlName.Append($" where c.name in( {string.Join(",", courseBases.Select(z => $"'{z.name}'"))} )   and  c.period.id='{_periodId}' ");
                             string tbname =  Constant.School;
                             List<CourseBase> courseBasesDB = new List<CourseBase>();
                             await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname)
@@ -154,8 +154,25 @@ namespace TEAMModelOS.Controllers.Both
                                         {
                                             item.subject.name = subject.name;
                                         }
+                                        else
+                                        {
+                                            return Ok(new { code = 1, msg = "科目不存在", course = item });
+                                        }
                                     }
-                                    else { 
+                                    else {
+                                        return Ok(new { code = 1, msg = "科目不存在", course = item });
+                                    }
+                                    if (!string.IsNullOrWhiteSpace(item.major?.id))
+                                    {
+                                        var major = period.majors.Find(x => x.id.Equals(item.major.id));
+                                        if (major != null)
+                                        {
+                                            item.major.name = major.name;
+                                        }
+                                        else
+                                        {
+                                            return Ok(new { code = 2, msg = "专业不存在", course = item });
+                                        }
                                     }
                                     var dbcoursebase = courseBasesDB.Find(x => x.name.Equals(item.name));
                                     if (dbcoursebase != null)
@@ -167,6 +184,7 @@ namespace TEAMModelOS.Controllers.Both
                                         item.no = string.IsNullOrWhiteSpace(item.no) ? dbcoursebase.no : item.no;
                                         item.grades = !item.grades.Any() ? dbcoursebase.grades : item.grades;
                                     }
+                                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).UpsertItemAsync(item,new PartitionKey(item.code));
                                 }
                             }
                             return Ok(new { course = courseBases });
@@ -646,7 +664,7 @@ namespace TEAMModelOS.Controllers.Both
                                 {
                                     groupLists.Add(item);
                                 }
-                                teachInvalidImports = courseCheckImports.ExceptBy(groupLists.Select(x => x.name), z => z.list);
+                                teachInvalidImports = teachList.ExceptBy(groupLists.Select(x => x.name), z => z.list);
                                 //保留课程名称存在的及醍摩豆ID有效的排课信息
                                 if (teachInvalidImports != null && teachInvalidImports.Any())
                                 {
@@ -911,7 +929,7 @@ namespace TEAMModelOS.Controllers.Both
                                                 groupId=groupId,
                                                 type=item.type,
                                                 teacherId=teacherId,
-                                                times= new List<ScheduleTime> { scheduleTime },
+                                                times = scheduleTime!=null ? new List<ScheduleTime> { scheduleTime }: new List<ScheduleTime> {  },
                                                 school=school,
                                            }
                                         }
@@ -928,7 +946,7 @@ namespace TEAMModelOS.Controllers.Both
                                             groupId = groupId,
                                             type = item.type,
                                             teacherId = teacherId,
-                                            times = new List<ScheduleTime> { scheduleTime },
+                                            times = scheduleTime!=null ? new List<ScheduleTime> { scheduleTime }: new List<ScheduleTime> {  },
                                             school = school,
                                         });
                                     }

+ 8 - 3
TEAMModelOS/Controllers/Both/GroupListController.cs

@@ -330,12 +330,16 @@ namespace TEAMModelOS.Controllers
                         await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<ClassInfo>(queryText: classsql.ToString(),
                             requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Class-{schoolId}") }))
                         {
+                            int scount=0;
                             HashSet<string> groupNames = new HashSet<string>();
-                            string gpsql = $"SELECT distinct c.groupId,c.groupName FROM c where  c.classId='{item.id}'and c.groupName <>null";
+                            string gpsql = $"SELECT distinct c.id,  c.groupId,c.groupName FROM c where  c.classId='{item.id}' ";
                             await foreach (var gp in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryIterator<Student>(queryText: gpsql,
                                 requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Base-{schoolId}") }))
                             {
-                                groupNames.Add(gp.groupName);
+                                if (!string.IsNullOrWhiteSpace(gp.groupName)) {
+                                    groupNames.Add(gp.groupName);
+                                }
+                                scount += 1;
                             }
                             ///行政班(学生搜寻classId动态返回)class
                             GroupListGrp group = new GroupListGrp
@@ -349,7 +353,8 @@ namespace TEAMModelOS.Controllers
                                 type = "class",
                                 year = item.year,
                                 expire=0,
-                                groupName = groupNames
+                                groupName = groupNames,
+                                scount= scount
                             };
                             groupLists.Add(group);
                         }

+ 237 - 82
TEAMModelOS/Controllers/School/ImportExamController.cs

@@ -16,6 +16,7 @@ using System.ComponentModel;
 using System.Linq;
 using System.Runtime.Intrinsics.Arm;
 using System.Text.Json;
+using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using TEAMModelOS.Filter;
 using TEAMModelOS.Models;
@@ -68,66 +69,140 @@ namespace TEAMModelOS.Controllers
         //[Authorize(Roles = "IES")]
         [AuthToken(Roles = "teacher,admin,business")]
         [RequestSizeLimit(102_400_000_00)] //最大10000m左右
-        public async Task<IActionResult> ReadExcelVirtue([FromForm] IFormFile file, [FromForm] string periodId) {
+        public async Task<IActionResult> ReadExcelVirtue([FromForm] IFormFile[] file, [FromForm] string periodId) {
+            var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
             List<KeyValuePair<string, List<string>>> error = new List<KeyValuePair<string, List<string>>>();
             List<KeyValuePair<string, List<string>>> warn = new List<KeyValuePair<string, List<string>>>();
-            var (id, _, _, school) = HttpContext.GetAuthTokenInfo();
+            List<VirtueImport> virtueImports = new List<VirtueImport> { };
+            //德育数据导入
+            School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new Azure.Cosmos.PartitionKey("Base"));
+            Period period = schoolBase.period.Find(x => x.id.Equals(periodId));
+            HashSet<Student> rightStudents = new HashSet<Student>();
+            List<Class> classes = new List<Class>();
+            List<Dictionary<string, object>> students = new List<Dictionary<string, object>>();
             ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
-            List<VirtueImport> virtueImports = new List<VirtueImport> {  };
-            using (ExcelPackage package = new ExcelPackage(file.OpenReadStream())) {
-                ExcelWorksheets sheet = package.Workbook.Worksheets;
-                //德育数据导入
-                School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new Azure.Cosmos.PartitionKey("Base"));
-                Period period = schoolBase.period.Find(x => x.id.Equals(periodId));
-                var daily_sheets = sheet.Where(z => !z.Name.Equals("栏位说明"));
-                HashSet<IdNameCode> rightStudents = new HashSet<IdNameCode>();
-                List<Class> classes = new List<Class>();
-                foreach (var daily_sheet in daily_sheets)
+            foreach (var f in file) {
+                using (ExcelPackage package = new ExcelPackage(f.OpenReadStream()))
                 {
-                    if (DateTimeOffset.TryParse(daily_sheet.Name, out DateTimeOffset sheetNameTime))
+                    ExcelWorksheets sheet = package.Workbook.Worksheets;
+                    var daily_sheets = sheet.Where(z => !z.Name.Equals("栏位说明"));
+                    foreach (var daily_sheet in daily_sheets)
                     {
-
                         var data = GetSubSheetData(daily_sheet, error);
-                        Dictionary<string, object> dailyData = new Dictionary<string, object> { { "subject", "德育" }, { "students", data.students } };
-                        ImportExamSubject importExamDaily = dailyData.ToJsonString().ToObject<ImportExamSubject>();
-                        var subject = period.subjects.Find(z => z.name.Equals(importExamDaily.subject));
-                        if (subject != null)
-                        {
-                            List<ResultImportStudent> examImportStudents = new List<ResultImportStudent>();
-                            //学生
-                            await ExamImportStudent(importExamDaily.students, rightStudents, school, period, examImportStudents, error, warn, classes, daily_sheet.Name);
-                            var semesterData=  SchoolService.GetSemester(period, sheetNameTime.ToUnixTimeMilliseconds());
-                            var group = examImportStudents.GroupBy(x => x.classId).Select(y => new { key = y.Key,list= y.ToList()} );
-                            foreach (var groupData in group) {
-                                VirtueImport virtueImport = new VirtueImport
+                        students.AddRange(data.students);
+                    }
+                }
+            }
+            Dictionary<string, object> dailyData = new Dictionary<string, object> { { "subject", "德育" }, { "students", students } };
+            ImportExamSubject importExamDaily = dailyData.ToJsonString().ToObject<ImportExamSubject>();
+            var subject = period.subjects.Find(z => z.name.Equals(importExamDaily.subject));
+            if (subject != null)
+            {
+                List<ResultImportStudent> examImportStudents = new List<ResultImportStudent>();
+                //学生
+                await ExamImportStudent(importExamDaily.students, rightStudents, school, period, examImportStudents, error, warn, classes,"");
+                List<KeyValuePair<string , (Semester currSemester, int studyYear, DateTimeOffset date, DateTimeOffset nextSemester)>> semesterDatas = new List<KeyValuePair<string, (Semester currSemester, int studyYear, DateTimeOffset date, DateTimeOffset nextSemester)>>();  
+                importExamDaily.students.GroupBy(x => x.time).Select(y => y.Key).ToList().ForEach(time => {
+                    var semesterData = SchoolService.GetSemester(period, time: time);
+                    semesterDatas.Add(new KeyValuePair<string, (Semester currSemester, int studyYear, DateTimeOffset date, DateTimeOffset nextSemester)>(time, semesterData));
+                });
+                var group = examImportStudents.GroupBy(x => new { classId = x.classId, date = x.date }).Select(y => new { key = y.Key, list = y.ToList() });
+                List<string> ids = new List<string>();
+                foreach (var groupData in group)
+                {
+                    var semesterData = semesterDatas.Find(x => x.Key.Equals(groupData.key.date)).Value;
+                    string id = $"{groupData.key.date}-{semesterData.currSemester.id}-{groupData.key.classId}";
+                    ids.Add(id);
+                }
+                if (ids.Any()) {
+                    string idsql = $"select value c from c where c.id in ({string.Join(",",ids.Select(z=>$"'{z}'"))}) ";
+                    var reuslt=  await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList<VirtueImport>(idsql, $"VirtueImport-{school}");
+                    if (reuslt.list.IsNotEmpty()) { virtueImports.AddRange(reuslt.list); }
+                }
+                HashSet<VirtueImport> changeDataVirtueImports = new HashSet<VirtueImport>();
+                foreach (var groupData in group) {
+                    var semesterData = semesterDatas.Find(x => x.Key.Equals(groupData.key.date)).Value;
+                    string id = $"{groupData.key.date}-{semesterData.currSemester.id}-{groupData.key.classId}";
+                    string code = $"VirtueImport-{school}";
+                    var virtueImport = virtueImports.Find(x => x.id.Equals(id));
+                    if (virtueImport != null)
+                    {
+                        groupData.list.ForEach(z => {
+                            var student = virtueImport.students.Find(x => x.id.Equals(z.id) && x.date.Equals(z.date) && x.classId.Equals(z.classId) );
+                            if (student != null)
+                            {
+                                bool hasChange=false;
+                                //此处分数直接覆盖
+                                if (student.items.Count == z.items.Count)
                                 {
-                                    time = sheetNameTime.ToUnixTimeMilliseconds(),
-                                    id = $"{semesterData.studyYear}-{semesterData.currSemester.id}-{groupData.key}",
-                                    code = $"VirtueImport-{school}",
-                                    pk = "VirtueImport",
-                                    ttl = -1,
-                                    semesterId = semesterData.currSemester.id,
-                                    periodId = period.id,
-                                    type = "日常",
-                                    school = school,
-                                    year = semesterData.studyYear,
-                                    classId=groupData.key,
-                                    students = groupData.list,
-                                    name=$"{semesterData.studyYear}-{semesterData.currSemester.name}"
-                                };
-                                virtueImports.Add(virtueImport);
+                                    
+                                    //为节约导入的RU成本开销检查导入分数是否有差异.
+                                    foreach (var item in z.items)
+                                    {
+                                        var noChangeData  = student.items.Find(x => x.code.Equals(item.code) && x.value==item.value );
+                                        //
+                                        if (noChangeData == null)
+                                        {
+                                            hasChange = true;
+                                            break;
+                                        }
+                                    }
+                                }
+                                else {
+                                    //两个的数量不同则是属于要修改的。
+                                    hasChange = true;
+                                }
+                                if (hasChange) {
+                                    student.items = z.items;
+                                    student.classId = z.classId;
+                                    student.date = z.date;
+                                    student.id = z.id;
+                                    student.stuYear = z.stuYear;
+                                    changeDataVirtueImports.Add(virtueImport);
+                                }
                             }
-                        }
-                        else
+                            else {
+                                changeDataVirtueImports.Add(virtueImport);
+                                virtueImport.students.Add(z);
+                            }
+                        });
+                    }
+                    else {
+                        virtueImport = new VirtueImport
                         {
-                            error.Add(new KeyValuePair<string, List<string>>("subject_invalid", new List<string> { importExamDaily.subject }));// 科目不存在
-                        }
+                            id = id,
+                            time = semesterData.date.ToUnixTimeMilliseconds(),
+                            code = code,
+                            pk = "VirtueImport",
+                            ttl = -1,
+                            semesterId = semesterData.currSemester.id,
+                            periodId = period.id,
+                            type = "日常",
+                            school = school,
+                            year = semesterData.studyYear,
+                            classId = groupData.key.classId,
+                            students = groupData.list,
+                            name = $"{semesterData.studyYear}-{semesterData.currSemester.name}-{groupData.key.date}"
+                        };
+                        changeDataVirtueImports.Add(virtueImport);
+                        virtueImports.Add(virtueImport);
                     }
-                    else { 
-                     
+                }
+                if (changeDataVirtueImports.Any())
+                {
+                    double ru = 0;
+                    //196条数据产生RU:2341.739999999998 
+                    foreach (var virtueImport in changeDataVirtueImports) {
+                        Azure.Cosmos.ItemResponse<VirtueImport> a =  await  _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).UpsertItemAsync<VirtueImport>(virtueImport, new Azure.Cosmos.PartitionKey(virtueImport.code));
+                        a.GetRawResponse().Headers.TryGetValue("x-ms-request-charge", out var value);
+                        ru=ru+ Convert.ToDouble(value);
                     }
                 }
             }
+            else
+            {
+                error.Add(new KeyValuePair<string, List<string>>("subject_invalid", new List<string> { importExamDaily.subject }));// 科目不存在
+            }
             return Ok(new { virtueImports, error,warn});
         }
         // [AuthToken(Roles = "teacher,admin")]
@@ -231,15 +306,20 @@ namespace TEAMModelOS.Controllers
                         {
                             if (itemTitle[j].Equals("index"))
                             {
-                                if (int.TryParse(itemDatas[i][j], out int index))
+                                if (!string.IsNullOrWhiteSpace(itemDatas[i][j]))
                                 {
-                                    item.Add(itemTitle[j], index);
+                                    if (int.TryParse(itemDatas[i][j], out int index) && index > 0)
+                                    {
+                                        item.Add(itemTitle[j], index);
+                                    }
+                                    else
+                                    {
+                                        error.Add(new KeyValuePair<string, List<string>>("index_invalid", new List<string> { itemDatas[i][j] }));// 题目序列只能是正整数
+                                    }
                                 }
                                 else {
-
-                                    error.Add(new KeyValuePair<string, List<string>>("index_invalid",new List<string> { itemDatas[i][j] } ));// 题目序列只能是正整数
+                                    item.Add(itemTitle[j], 0);
                                 }
-                                
                             }
                             else if (itemTitle[j].Equals("score") )
                             {
@@ -288,7 +368,8 @@ namespace TEAMModelOS.Controllers
                 Period period = schoolBase.period.Find(x => x.id.Equals(importExam.periodId));
                 if (validData.isVaild)
                 {
-                    string sql = $"select value c from c where c.name ='{importExam.name}'";
+                    var semesterData = SchoolService.GetSemester(period, time: importExam.time);
+                    string sql = $"select value c from c where c.name ='{importExam.name}' and c.periodId='{period.id}' and c.semesterId ='{semesterData.currSemester.id}' ";
                     var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList<ExamImport>(sql, $"ExamImport-{importExam.school}", pageSize: 1);
                    
                     if (string.IsNullOrEmpty(result.continuationToken))
@@ -299,31 +380,37 @@ namespace TEAMModelOS.Controllers
                     {
                         examImport = result.list[0];
                         warn.Add(new KeyValuePair<string, List<string>>("name_update", new List<string> { importExam.name }));//同名评测数据更新
-
                     }
                     if (examImport == null)
                     {
-                        examImport = new ExamImport { name = importExam.name, type = importExam.type, school = importExam.school,periodId=period.id,code= $"ExamImport-{importExam.school}",pk= "ExamImport", };
+                        examImport = new ExamImport
+                        {
+                            year = semesterData.studyYear,
+                            name = importExam.name,
+                            type = importExam.type,
+                            school = importExam.school,
+                            periodId = period.id,
+                            code = $"ExamImport-{importExam.school}",
+                            pk = "ExamImport",
+                            ttl=-1
+                        };
                         if (DateTimeOffset.TryParse(importExam.time, out DateTimeOffset dateTime))
                         {
                             examImport.time = dateTime.ToUnixTimeMilliseconds();
-                            var semesterData= SchoolService.GetSemester(period, examImport.time);
+                           
                             examImport.semesterId = semesterData.currSemester.id;
-                            examImport.id = $"{semesterData.studyYear}-{ShaHashHelper.GetSHA1(examImport.name)}";
+                            examImport.id = $"{semesterData.studyYear}-{ShaHashHelper.GetSHA1($"{period.id}-{semesterData.currSemester.id}-{examImport.name}")}";
                         }
                         else
                         {
                             error.Add(new KeyValuePair<string, List<string>>("time_format", new List<string> { importExam.time }));//  时间格式错误
                         }
                     }
-
-                  
-
                     if (period != null)
                     {
                         //用于处理多学科,不需要重复查询学习基础信息
                         //id  学生id  code 行政班id  name  学生姓名
-                        HashSet<IdNameCode> rightStudents = new HashSet<IdNameCode>();
+                        HashSet<Student> rightStudents = new HashSet<Student>();
                         List<Class> classes = new List<Class>();
                         foreach (var item in importExam.subjects)
                         {
@@ -332,9 +419,45 @@ namespace TEAMModelOS.Controllers
                             {
                                 List<ResultImportStudent> examImportStudents = new List<ResultImportStudent>();
                                 //学生
-                               await  ExamImportStudent(item.students, rightStudents, school, period, examImportStudents, error, warn, classes, item.subject);
-
-                                examImport.subjects.Add(new ExamImportSubject { id = subject.id, name = subject.name, students = examImportStudents, }) ;
+                                await  ExamImportStudent(item.students, rightStudents, school, period, examImportStudents, error, warn, classes, item.subject);
+                                //配分
+                                List<ExamImportItem> examImportItems = new List<ExamImportItem>();
+                                foreach (var itemItem in item.items)
+                                {
+                                    HashSet<string> points = new HashSet<string>() ;
+                                    if (!string.IsNullOrWhiteSpace(itemItem.point)) {
+                                        string[] ps = Regex.Split(itemItem.point, "\\.|\\.|\\、|\\:|\\:|\\,|\\,|\\;|\\;");
+                                        points = ps.Distinct().ToHashSet();
+                                    }
+                                    
+                                    ExamImportItem examImportItem = new ExamImportItem() { 
+                                        point=points,
+                                        index=itemItem.index,
+                                        filed=itemItem.filed,
+                                        type=itemItem.type,
+                                        score=itemItem.score,
+                                    };
+                                    examImportItems.Add(examImportItem);
+                                }
+                                var examImportSubject= examImport.subjects.Find(x => x.id.Equals(subject.id));
+                                if (examImportSubject != null)
+                                {
+                                    examImportSubject.items = examImportItems;
+                                    examImportSubject.name = subject.name;
+                                    foreach (var stu in examImportStudents) {
+                                        var student =  examImportSubject.students.Find(x => x.id.Equals(stu.id));
+                                        if (student != null)
+                                        {
+                                            student = stu;
+                                        }
+                                        else {
+                                            examImportSubject.students.Add(stu);
+                                        }
+                                    }
+                                }
+                                else {
+                                    examImport.subjects.Add(new ExamImportSubject { id = subject.id, name = subject.name, students = examImportStudents, items = examImportItems });
+                                }
                             }
                             else
                             {
@@ -363,11 +486,12 @@ namespace TEAMModelOS.Controllers
                         errorData.Add(new KeyValuePair<string, HashSet<string>>(x.Key,x.Value.ToHashSet()));
                     }
                 });
+                await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).UpsertItemAsync(examImport, new Azure.Cosmos.PartitionKey(examImport.code));
                 return Ok(new { code = 400, error = errorData, examImport });
             } 
         }
 
-        private async Task ExamImportStudent(List<ImportResultStudent> importExamStudents, HashSet<IdNameCode> rightStudents,string  school,
+        private async Task ExamImportStudent(List<ImportResultStudent> importExamStudents, HashSet<Student> rightStudents,string  school,
             Period period, List<ResultImportStudent> examImportStudents, List<KeyValuePair<string, List<string>>> error,
             List<KeyValuePair<string, List<string>>> warn, List<Class> classes, string sheetName)
         {
@@ -380,8 +504,8 @@ namespace TEAMModelOS.Controllers
             if (needSearch.Any())
             {
                 ///在rightStudents找不到的学生需要查询数据库。
-                string stuidsql = $"select c.id,c.classId as code , c.name  from  c where c.id in ({string.Join(",", needSearch.Select(x => $"'{x.id}'"))}) and c.periodId='{period.id}' ";
-                var sturesult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<IdNameCode>(stuidsql, $"Base-{school}");
+                string stuidsql = $"select value c  from  c where c.id in ({string.Join(",", needSearch.Select(x => $"'{x.id}'"))}) and c.periodId='{period.id}' ";
+                var sturesult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<Student>(stuidsql, $"Base-{school}");
                 if (sturesult.list.IsNotEmpty())
                 {
                     sturesult.list.ForEach(x => {
@@ -409,19 +533,25 @@ namespace TEAMModelOS.Controllers
                 if (existStudent .Any())
                 {
                     long time = 0;
-                    if (DateTimeOffset.TryParse(item.time, out DateTimeOffset dateTime))
+                    string date = string.Empty;
+                    DateTimeOffset dateTime = DateTimeOffset.Now;
+                     
+                    if (!string.IsNullOrWhiteSpace(item.time)  &&  DateTimeOffset.TryParse(item.time, out  dateTime))
                     {
                         time = dateTime.ToUnixTimeMilliseconds();
+                        date = dateTime.ToString("yyyy-MM-dd");
                     }
                     examImportStudents.Add(new ResultImportStudent
                     {
                         id = item.id,
                         name = existStudent.First().name,
-                        classId = existStudent.First().code,
+                        classId = existStudent.First().classId,
                         score = item.score,
                         scores = item.scores,
                         time = time,
+                        date = date,
                         items = item.items,
+                        stuYear = existStudent.First().year,
                     });
                 }
             }
@@ -519,8 +649,8 @@ namespace TEAMModelOS.Controllers
                 }
                 if (clzz != null)
                 {
-                    string stuClassIdsql = $"select c.id,c.classId as code , c.name  from  c where c.name  in ({string.Join(",", classStudents.Select(x => $"'{x.name}'"))}) and c.classId ='{clzz.id}' and c.periodId='{period.id}' ";
-                    var sturesult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<IdNameCode>(stuClassIdsql, $"Base-{school}");
+                    string stuClassIdsql = $"select value c  from  c where c.name  in ({string.Join(",", classStudents.Select(x => $"'{x.name}'"))}) and c.classId ='{clzz.id}' and c.periodId='{period.id}' ";
+                    var sturesult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<Student>(stuClassIdsql, $"Base-{school}");
                     //检查重名
                     if (sturesult.list.IsNotEmpty())
                     {
@@ -536,19 +666,24 @@ namespace TEAMModelOS.Controllers
                             {
 
                                 long time = 0;
-                                if (DateTimeOffset.TryParse(stu.time, out DateTimeOffset dateTime))
+                                string date = string.Empty;
+                                DateTimeOffset dateTime = DateTimeOffset.Now;
+                                if (!string.IsNullOrWhiteSpace(stu.time) && DateTimeOffset.TryParse(stu.time, out   dateTime))
                                 {
                                     time = dateTime.ToUnixTimeMilliseconds();
+                                    date = dateTime.ToString("yyyy-MM-dd");
                                 }
                                 examImportStudents.Add(new ResultImportStudent
                                 {
                                     id = student[0].id,
                                     name = student[0].name,
-                                    classId = student[0].code,
+                                    classId = student[0].classId,
                                     score = stu.score,
                                     scores = stu.scores,
                                     time = time,
-                                    items = stu.items
+                                    date = date,
+                                    items = stu.items,
+                                    stuYear = student[0].year,
                                 });
                             }
                         }
@@ -625,20 +760,38 @@ namespace TEAMModelOS.Controllers
                         double score = 0;
                         if (double.TryParse(datas[i][j], out score))
                         {
-                            items.Add(new ItemVlaue() { code = titles[j].Replace("item_", ""), value = score });
+                            //德育细项分数为0 不纳入计算
+                            if (score != 0)
+                            {
+                                items.Add(new ItemVlaue() { code = titles[j].Replace("item_", ""), value = score });
+                            }
+
                         }
                         else if (string.IsNullOrWhiteSpace(datas[i][j]))
                         {
-                            items.Add(new ItemVlaue() { code = titles[j].Replace("item_", ""), value = score });
+                            //德育细项为空 不纳入计算
+                            //items.Add(new ItemVlaue() { code = titles[j].Replace("item_", ""), value = score });
+                        }
+                        else
+                        {
+                            error.Add(new KeyValuePair<string, List<string>>("score_invalid", new List<string> { datas[i][j] }));// 得分只能是数字
+                        }
+
+                    }
+                    else if (titles[j].Equals("time")) {
+
+                        if (!string.IsNullOrWhiteSpace(datas[i][j])  &&   DateTimeOffset.TryParse(datas[i][j], out DateTimeOffset dateTime))
+                        {
+
+                            item.Add(titles[j], dateTime.ToString("yyyy-MM-dd"));
                         }
                         else {
-                            error.Add(new KeyValuePair<string, List<string>>("score_invalid",new List<string> { datas[i][j] }));// 得分只能是数字
+                            error.Add(new KeyValuePair<string, List<string>>("time_format", new List<string> { datas[i][j] }));// 时间格式错误
                         }
-                        
                     }
                     else
                     {
-                        if (titles[j].Equals("score")  )
+                        if (titles[j].Equals("score"))
                         {
                             if (double.TryParse(datas[i][j], out double score))
                             {
@@ -648,14 +801,16 @@ namespace TEAMModelOS.Controllers
                             {
                                 item.Add(titles[j], 0);
                             }
-                            else {
+                            else
+                            {
                                 error.Add(new KeyValuePair<string, List<string>>("score_invalid", new List<string> { datas[i][j] }));// 得分只能是数字
                             }
                         }
-                        else {
+                        else
+                        {
                             item.Add(titles[j], datas[i][j]);
                         }
-                       
+
                     }
                 }
                 var orders = _index_order.OrderBy(x => x.Key).ToList();

+ 5 - 2
TEAMModelOS/Controllers/School/SchoolController.cs

@@ -2109,7 +2109,7 @@ namespace TEAMModelOS.Controllers
                 {
                     classCnt = items;
                 }
-                //教師數
+                //教師數
                 int teacherCnt = 0;
                 sql = $"SELECT VALUE COUNT(c.id) FROM c";
                 await foreach (int items in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<int>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"Teacher-{_schoolId}") }))
@@ -2135,6 +2135,7 @@ namespace TEAMModelOS.Controllers
                 }
 
                 //取得產品分析資訊
+                List<string> tmidList = new List<string>(); ///TMID列表
                 int stuShow = 0; ///學生人次
                 long stuLessonLengMin = 0; ///學生參與總時間數(分)
                 int lessonRecord = 0; ///課堂數
@@ -2171,6 +2172,7 @@ namespace TEAMModelOS.Controllers
                         data.school.areaId = schAreaId;
                         data.school.type = schType;
                         iotData.Add(data);
+                        tmidList = tmidList.Union(data.tmidList).ToList();
                         stuShow += data.stuShow;
                         stuLessonLengMin += data.stuLessonLengMin;
                         lessonRecord += data.lessonRecord;
@@ -2189,6 +2191,7 @@ namespace TEAMModelOS.Controllers
                         lTypeDif += data.lTypeDif;
                     }
                 }
+                int teacherShow = tmidList.Count; ///老師使用人次
                 int htcDevCnt = htcDevList.Count; ///設備統計-HiTeach上線數
                 int htcDevTotalCnt = 0; ///設備統計-HiTeach總設備數
                 sql = $"SELECT VALUE COUNT(1) FROM (SELECT DISTINCT x FROM c JOIN x IN c.deviceList WHERE c.schoolId = '{_schoolId}' AND c.dateUnit = 'day' AND c.toolType = 'HiTeach')";
@@ -2205,7 +2208,7 @@ namespace TEAMModelOS.Controllers
                 }
                 int htccDevCnt = htccDevList.Count; ///設備統計-HiTeachCC上線數
 
-                return Ok(new { sdate=$"{dateFromYear}-{dateFromMonth}-{dateFromDay}", edate=$"{dateToYear}-{dateToMonth}-{dateToDay}", classCnt, teacherCnt, studentCnt, deviceAuthCnt, stuShow, stuLessonLengMin, lessonRecord, lessonLengMin, mission, missionFin, item, interact, htcDevCnt, htcDevTotalCnt, htaDevCnt, htaDevTotalCnt, htccDevCnt, lTypeCoop, lTypeIact, lTypeMis, lTypeTst, lTypeDif, iotData });
+                return Ok(new { sdate=$"{dateFromYear}-{dateFromMonth}-{dateFromDay}", edate=$"{dateToYear}-{dateToMonth}-{dateToDay}", classCnt, teacherCnt, teacherShow, studentCnt, deviceAuthCnt, stuShow, stuLessonLengMin, lessonRecord, lessonLengMin, mission, missionFin, item, interact, htcDevCnt, htcDevTotalCnt, htaDevCnt, htaDevTotalCnt, htccDevCnt, lTypeCoop, lTypeIact, lTypeMis, lTypeTst, lTypeDif, iotData });
             }
             catch (Exception ex)
             {

+ 4 - 4
TEAMModelOS/TEAMModelOS.csproj

@@ -70,11 +70,11 @@
     <SpaRoot>ClientApp\</SpaRoot>
     <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
     <UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-    <Version>5.2307.5</Version>
-    <AssemblyVersion>5.2307.5.1</AssemblyVersion>
-    <FileVersion>5.2307.5.1</FileVersion>
+    <Version>5.2307.12</Version>
+    <AssemblyVersion>5.2307.12.1</AssemblyVersion>
+    <FileVersion>5.2307.12.1</FileVersion>
     <Description>TEAMModelOS(IES5)</Description>
-    <PackageReleaseNotes>IES版本说明版本切换标记5.2307.5.1</PackageReleaseNotes>
+    <PackageReleaseNotes>IES版本说明版本切换标记5.2307.12.1</PackageReleaseNotes>
     <PackageId>TEAMModelOS</PackageId>
     <Authors>teammodel</Authors>
     <Company>醍摩豆(成都)信息技术有限公司</Company>

+ 1 - 1
TEAMModelOS/appsettings.Development.json

@@ -18,7 +18,7 @@
     "IdTokenSalt": "8263692E2213497BB55E74792B7900B4",
     "HttpTrigger": "https://teammodelosfunction-test.chinacloudsites.cn/api/",
     //"HttpTrigger": "http://localhost:7071/api/"
-    "Version": "5.2307.5.1"
+    "Version": "5.2307.12.1"
   },
   "Azure": {
     //测试站数据库

+ 1 - 1
TEAMModelOS/appsettings.json

@@ -18,7 +18,7 @@
     "Exp": 86400,
     "IdTokenSalt": "8263692E2213497BB55E74792B7900B4",
     "HttpTrigger": "https://teammodelosfunction.chinacloudsites.cn/api/",
-    "Version": "5.2307.5.1"
+    "Version": "5.2307.12.1"
   },
   "Azure": {
     "Storage": {