瀏覽代碼

Merge branch 'TPE/develop5.0' into TPE/feat/newLogin

osbert 4 年之前
父節點
當前提交
e964914c53
共有 100 個文件被更改,包括 4297 次插入1815 次删除
  1. 28 0
      TEAMModelAPI/appsettings.Development.json
  2. 3 1
      TEAMModelFunction/MonitorCosmosDB.cs
  3. 22 0
      TEAMModelFunction/MonitorServicesBus.cs
  4. 173 0
      TEAMModelFunction/TriggerCorrect.cs
  5. 112 104
      TEAMModelFunction/TriggerExam.cs
  6. 28 0
      TEAMModelOS.SDK/Extension/JwtAuthExtension.cs
  7. 49 0
      TEAMModelOS.SDK/Models/Cosmos/Api/OpenApi.cs
  8. 126 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Correct.cs
  9. 1 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs
  10. 2 1
      TEAMModelOS.SDK/Models/Cosmos/Common/Snode.cs
  11. 1 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs
  12. 20 7
      TEAMModelOS.SDK/Models/Cosmos/Common/Volume.cs
  13. 7 4
      TEAMModelOS.SDK/Models/Cosmos/School/Class.cs
  14. 1 1
      TEAMModelOS.SDK/Models/Cosmos/School/ClassAnalysis.cs
  15. 10 0
      TEAMModelOS.SDK/Models/Cosmos/School/Course.cs
  16. 1 1
      TEAMModelOS.SDK/Models/Cosmos/School/GradeAnalysis.cs
  17. 1 1
      TEAMModelOS.SDK/Models/Cosmos/School/Knowledge.cs
  18. 42 0
      TEAMModelOS.SDK/Models/Cosmos/Teacher/CorrectTask.cs
  19. 149 0
      TEAMModelOS.SDK/Models/Cosmos/Teacher/Favorite.cs
  20. 1 1
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  21. 6 6
      TEAMModelOS/ClientApp/package.json
  22. 3 3
      TEAMModelOS/ClientApp/src/api/courseMgmt.js
  23. 2 0
      TEAMModelOS/ClientApp/src/api/index.js
  24. 22 0
      TEAMModelOS/ClientApp/src/api/mark.js
  25. 95 3
      TEAMModelOS/ClientApp/src/assets/iconfont/demo_index.html
  26. 19 3
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.css
  27. 1 1
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js
  28. 28 0
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.json
  29. 二進制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf
  30. 二進制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff
  31. 二進制
      TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2
  32. 29 28
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  33. 8 3
      TEAMModelOS/ClientApp/src/common/UploadModal.vue
  34. 11 8
      TEAMModelOS/ClientApp/src/components/coursemgt/StudentList.vue
  35. 3 0
      TEAMModelOS/ClientApp/src/css/common-style.less
  36. 6 0
      TEAMModelOS/ClientApp/src/css/dark-iview-form.less
  37. 5 4
      TEAMModelOS/ClientApp/src/css/dark-iview-table.less
  38. 7 0
      TEAMModelOS/ClientApp/src/icons/answersheet/t.svg
  39. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/index.js
  40. 2 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js
  41. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/schoolBaseInfo.js
  42. 16 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/task.js
  43. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/courseManage.js
  44. 7 5
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/cusMgt.js
  45. 9 2
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/evaluation.js
  46. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/index.js
  47. 3 3
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/learnActivity.js
  48. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/schoolBaseInfo.js
  49. 9 4
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/stuAccount.js
  50. 16 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/task.js
  51. 8 6
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/cusMgt.js
  52. 19 11
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/evaluation.js
  53. 2 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/index.js
  54. 2 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js
  55. 8 3
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/stuAccount.js
  56. 16 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/task.js
  57. 10 2
      TEAMModelOS/ClientApp/src/router/routes.js
  58. 17 5
      TEAMModelOS/ClientApp/src/store/module/answerSheet.js
  59. 14 0
      TEAMModelOS/ClientApp/src/store/module/user.js
  60. 9 2
      TEAMModelOS/ClientApp/src/utils/html2pdf.js
  61. 4 2
      TEAMModelOS/ClientApp/src/utils/sheetConfig.js
  62. 719 398
      TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue
  63. 0 103
      TEAMModelOS/ClientApp/src/view/answersheet/BaseObjective.vue
  64. 190 140
      TEAMModelOS/ClientApp/src/view/answersheet/BaseSvgBg.vue
  65. 7 88
      TEAMModelOS/ClientApp/src/view/answersheet/BaseTitleEditor.vue
  66. 1 1
      TEAMModelOS/ClientApp/src/view/answersheet/SheetComplete.vue
  67. 50 38
      TEAMModelOS/ClientApp/src/view/answersheet/SheetObjective.vue
  68. 4 6
      TEAMModelOS/ClientApp/src/view/answersheet/SheetSubjective.vue
  69. 337 127
      TEAMModelOS/ClientApp/src/view/answersheet/index.vue
  70. 5 2
      TEAMModelOS/ClientApp/src/view/classmgt/ManageClass.vue
  71. 1 2
      TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.less
  72. 29 11
      TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue
  73. 1 0
      TEAMModelOS/ClientApp/src/view/evaluation/bank/index.vue
  74. 3 3
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue
  75. 15 2
      TEAMModelOS/ClientApp/src/view/evaluation/index/TestPaper.vue
  76. 1 1
      TEAMModelOS/ClientApp/src/view/evaluation/index/index.vue
  77. 2 22
      TEAMModelOS/ClientApp/src/view/joinclass/JoinClass.vue
  78. 10 7
      TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue
  79. 17 5
      TEAMModelOS/ClientApp/src/view/learnactivity/CreateSchoolEva.vue
  80. 28 0
      TEAMModelOS/ClientApp/src/view/learnactivity/ExamPaperAnalysis.less
  81. 169 123
      TEAMModelOS/ClientApp/src/view/learnactivity/ExamPaperAnalysis.vue
  82. 15 12
      TEAMModelOS/ClientApp/src/view/learnactivity/ManualPaper.vue
  83. 4 4
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue
  84. 31 5
      TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue
  85. 275 0
      TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/Compare.vue
  86. 2 2
      TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkData.vue
  87. 426 128
      TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkSetting.vue
  88. 36 21
      TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkView.vue
  89. 100 0
      TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/ProgPie.vue
  90. 1 5
      TEAMModelOS/ClientApp/src/view/newcourse/ClassTable.less
  91. 100 12
      TEAMModelOS/ClientApp/src/view/newcourse/ClassTable.vue
  92. 16 10
      TEAMModelOS/ClientApp/src/view/newcourse/CoursePlan.less
  93. 111 83
      TEAMModelOS/ClientApp/src/view/newcourse/CoursePlan.vue
  94. 6 0
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.less
  95. 154 96
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue
  96. 3 2
      TEAMModelOS/ClientApp/src/view/newcourse/NewCusMgt.less
  97. 212 115
      TEAMModelOS/ClientApp/src/view/newcourse/NewCusMgt.vue
  98. 15 10
      TEAMModelOS/ClientApp/src/view/newcourse/TeaTable.vue
  99. 1 1
      TEAMModelOS/ClientApp/src/view/newcourse/TimeSetting.vue
  100. 0 0
      TEAMModelOS/ClientApp/src/view/schoolmgmt/ClassroomSetting/ClassroomSetting.less

+ 28 - 0
TEAMModelAPI/appsettings.Development.json

@@ -5,5 +5,33 @@
       "Microsoft": "Warning",
       "Microsoft.Hosting.Lifetime": "Information"
     }
+  },
+  "AllowedHosts": "*",
+  "Option": {
+    "Location": "China-Dep",
+    "LocationNum": "1",
+    "HostName": "localhost:5001",
+    "AllowedHosts": [ "localhost", "*.teammodel.cn", "*.teammodel.net", "*.habookaclass.biz", "test" ],
+    "Issuer": "www.teammodel.cn",
+    "JwtSecretKey": "fXO6ko/qyXeYrkecPeKdgXnuLXf9vMEtnBC9OB3s+aA=",
+    "Exp": 86400,
+    "IdTokenSalt": "8263692E2213497BB55E74792B7900B4",
+    "HttpTrigger": "https://teammodelosfunction-test.chinacloudsites.cn/api/"
+  },
+  "Azure": {
+    "Storage": {
+      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelstorage;AccountKey=Yq7D4dE6cFuer2d2UZIccTA/i0c3sJ/6ITc8tNOyW+K5f+/lWw9GCos3Mxhj47PyWQgDL8YbVD63B9XcGtrMxQ==;EndpointSuffix=core.chinacloudapi.cn"
+    },
+    "Cosmos": {
+      "ConnectionString": "AccountEndpoint=https://cdhabookdep-free.documents.azure.cn:443/;AccountKey=JTUVk92Gjsx17L0xqxn0X4wX2thDPMKiw4daeTyV1HzPb6JmBeHdtFY1MF1jdctW1ofgzqkDMFOtcqS46by31A==;"
+    },
+    "Redis": {
+      "ConnectionString": "106.12.23.251:6379,password=habook,ssl=false,abortConnect=False,writeBuffer=10240"
+    },
+    "ServiceBus": {
+      "ConnectionString": "Endpoint=sb://teammodelos.servicebus.chinacloudapi.cn/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Sy4h4EQ8zP+7w/lOLi1X3tGord/7ShFHimHs1vC50Dc=",
+      "ActiveTask": "dep-active-task",
+      "NoticeTask": "dep-notice-task"
+    }
   }
 }

+ 3 - 1
TEAMModelFunction/MonitorCosmosDB.cs

@@ -57,7 +57,6 @@ namespace TEAMModelFunction
                         { 
                             ///通知接收者的变更
                             return;
-                           
                         }
                         else {
                             ///活动类型的变更
@@ -99,6 +98,9 @@ namespace TEAMModelFunction
                                 case "Survey":
                                     TriggerSurvey.Trigger(_serviceBus, _azureStorage, _dingDing, client, input, data, _azureRedis);
                                     break;
+                                case "Correct":
+                                    TriggerCorrect.Trigger(_serviceBus, _azureStorage, _dingDing, client, input, data, _azureRedis);
+                                    break;
 
                             }
 

+ 22 - 0
TEAMModelFunction/MonitorServicesBus.cs

@@ -12,6 +12,7 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 
 namespace TEAMModelFunction
@@ -73,6 +74,27 @@ namespace TEAMModelFunction
                 await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,VoteBus()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
             }
 
+        }
+        [FunctionName("Correct")]
+        public async Task Correct([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "correct", Connection = "Azure:ServiceBus:ConnectionString")] string msg)
+        {
+            try
+            {
+                var jsonMsg = JsonDocument.Parse(msg);
+                jsonMsg.RootElement.TryGetProperty("id", out JsonElement id);
+                jsonMsg.RootElement.TryGetProperty("progress", out JsonElement progress);
+                jsonMsg.RootElement.TryGetProperty("code", out JsonElement code);
+                //Dictionary<string, object> keyValuePairs = mySbMsg.ToObject<Dictionary<string, object>>();
+                var client = _azureCosmos.GetCosmosClient();
+                Correct correct = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Correct>(id.ToString(), new PartitionKey($"{code}"));
+                correct.progress = progress.ToString();
+                await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(correct, id.ToString(), new PartitionKey($"{code}"));
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-ServiceBus,VoteBus()\n{ex.Message}", GroupNames.醍摩豆服務運維群組);
+            }
+
         }
         [FunctionName("Survey")]
         public async Task Survey([ServiceBusTrigger("%Azure:ServiceBus:ActiveTask%", "survey", Connection = "Azure:ServiceBus:ConnectionString")] string msg)

+ 173 - 0
TEAMModelFunction/TriggerCorrect.cs

@@ -0,0 +1,173 @@
+using Azure.Cosmos;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Azure.Documents;
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
+using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos;
+
+namespace TEAMModelFunction
+{
+    public static class TriggerCorrect
+    {
+        public static async void Trigger(AzureServiceBusFactory _serviceBus, AzureStorageFactory _azureStorage, DingDing _dingDing,
+           CosmosClient client, Document input, TriggerData tdata, AzureRedisFactory _azureRedis)
+        {
+            if ((tdata.status != null && tdata.status.Value == 404) || tdata.ttl > 0)
+            {
+                return;
+            }
+            var adid = tdata.id;
+            var adcode = "";
+            string blobcntr = null;
+            if (tdata.scope == "school")
+            {
+                adcode = $"Activity-{tdata.school}";
+                blobcntr = tdata.school;
+            }
+            else {
+                return;
+            }
+            await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}阅卷配置【{tdata.name}-{tdata.id}-ttl={tdata.ttl}】正在执行", GroupNames.成都开发測試群組);
+            Correct correct = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<Correct>(input.Id, new Azure.Cosmos.PartitionKey($"{tdata.code}"));
+            List<ChangeRecord> correctRecords = await _azureStorage.FindListByDict<ChangeRecord>(new Dictionary<string, object>() { { "RowKey", input.Id }, { "PartitionKey", correct.progress } });
+            if (correct != null) {
+                switch (correct.progress) {
+                    case "pending":
+                        var messageCorrect = new ServiceBusMessage(new { id = input.Id, progress = "going", code = tdata.code }.ToJsonString());
+                        messageCorrect.ApplicationProperties.Add("name", "Correct");
+                        if (correctRecords.Count > 0)
+                        {
+                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageCorrect, DateTimeOffset.FromUnixTimeMilliseconds(tdata.stime));
+                            await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), correctRecords[0].sequenceNumber);
+                            correctRecords[0].sequenceNumber = start;
+                            await _azureStorage.SaveOrUpdate<ChangeRecord>(correctRecords[0]);
+                        }
+                        else
+                        {
+                            long start = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageCorrect, DateTimeOffset.FromUnixTimeMilliseconds(tdata.stime));
+                            ChangeRecord changeRecord = new ChangeRecord
+                            {
+                                RowKey = input.Id,
+                                PartitionKey = "pending",
+                                sequenceNumber = start,
+                                msgId = messageCorrect.MessageId
+                            };
+                            await _azureStorage.Save<ChangeRecord>(changeRecord);
+                        }
+                        break;
+                    case "going":
+                        if (correct.subs.IsNotEmpty()) {
+                            
+                            foreach (var sub in correct.subs) {
+                                ///生成阅卷教师的阅卷任务列表
+                                if (sub.markers.IsNotEmpty()) {
+                                    foreach (var marker in sub.markers) {
+                                        CorrectTask task = new CorrectTask
+                                        {
+                                            ttl = -1,
+                                            pk= "CorrectTask",
+                                            code = "CorrectTask-" + marker.id,
+                                            //评测id 或者阅卷配置id
+                                            id = correct.id,
+                                            //科目
+                                            subject=sub.id,
+                                            //科目名称
+                                            subjectName=sub.name,
+                                            //评测code
+                                            ecode=correct.scode,
+                                            //阅卷配置code
+                                            scode=correct.code,
+                                            //任务名称
+                                            name=correct.name,
+                                            //开始时间
+                                            startTime=correct.startTime,
+                                            //结束时间
+                                            endTime=correct.endTime,
+                                            //批改数量
+                                            count=marker.count
+                                        };
+                                       await  client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<CorrectTask>(task,new Azure.Cosmos.PartitionKey(task.code));
+                                    }
+                                }
+                                //生成异常卷处理人员
+                                //生成仲裁人员
+                                //调用本次考试所涉及的所有已经作答的数据 并生成阅卷池,存入redis
+                                //评测id
+                                string eid = correct.id;
+                                //评测的分区键
+                                string ecode = correct.scode;
+                                //评测科目
+                                string subjectId = sub.id;
+                                //生成临时作答数据存放到redis
+                                var redisClient = _azureRedis.GetRedisClient(8);
+                                ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(eid, new Azure.Cosmos.PartitionKey(ecode));
+                                List<ExamClassResult> classResults = new List<ExamClassResult>();
+
+                                if (info.scope.Equals("school"))
+                                {
+
+                                    await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
+                                    queryText: $"select value(c) from c where c.examId = '{eid}' and c.subjectId = '{subjectId}'",
+                                    requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{info.school}") }))
+                                    {
+                                        classResults.Add(item);
+                                    }
+                                }
+                                else
+                                {
+                                    await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(
+                                        queryText: $"select value(c) from c where c.examId = '{eid}' and c.subjectId = '{subjectId}'",
+                                        requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"ExamClassResult-{info.creatorId}") }))
+                                    {
+                                        classResults.Add(item);
+                                    }
+                                }
+                                List<Task<bool>> tasks = new List<Task<bool>>();
+                                foreach (ExamClassResult examClass in classResults)
+                                {
+                                    foreach (string stuId in examClass.studentIds)
+                                    {
+                                        int index = examClass.studentIds.IndexOf(stuId);
+                                        tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{eid}-{subjectId}", stuId, new { tmdId = "" , ans = examClass.studentAnswers[index][0], score = examClass.studentScores[index] }.ToJsonString()));
+                                    }
+
+                                }
+                                await Task.WhenAll(tasks);
+                            }
+                        }
+                        var messageCorrectEnd = new ServiceBusMessage(new { id = input.Id, progress = "finish", code = tdata.code }.ToJsonString());
+                        messageCorrectEnd.ApplicationProperties.Add("name", "Correct");
+                        if (correctRecords.Count > 0)
+                        {
+                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageCorrectEnd, DateTimeOffset.FromUnixTimeMilliseconds(tdata.etime));
+                            await _serviceBus.GetServiceBusClient().cancelMessage(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), correctRecords[0].sequenceNumber);
+                            correctRecords[0].sequenceNumber = end;
+                            await _azureStorage.SaveOrUpdate<ChangeRecord>(correctRecords[0]);
+                        }
+                        else
+                        {
+                            long end = await _serviceBus.GetServiceBusClient().SendScheduleMessageAsync(Environment.GetEnvironmentVariable("Azure:ServiceBus:ActiveTask"), messageCorrectEnd, DateTimeOffset.FromUnixTimeMilliseconds(tdata.etime));
+                            ChangeRecord changeRecord = new ChangeRecord
+                            {
+                                RowKey = input.Id,
+                                PartitionKey = "going",
+                                sequenceNumber = end,
+                                msgId = messageCorrectEnd.MessageId
+                            };
+                            await _azureStorage.Save<ChangeRecord>(changeRecord);
+                        }
+                        break;
+                    case "finish":
+                        ///暂不处理
+                        break;
+                }
+            }
+        }
+    }
+}

+ 112 - 104
TEAMModelFunction/TriggerExam.cs

@@ -324,7 +324,7 @@ namespace TEAMModelFunction
                         }
                         catch (Exception e)
                         {
-                            await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-评测going状态异常{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組);
+                            await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测going状态异常{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組);
                         }
                         break;
                     case "finish":
@@ -440,7 +440,7 @@ namespace TEAMModelFunction
             }
             catch (Exception e)
             {
-                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-评测结算异常{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組);
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测结算异常{e.Message}\n{e.StackTrace}", GroupNames.成都开发測試群組);
             }
 
         }
@@ -510,7 +510,7 @@ namespace TEAMModelFunction
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-评测作答记录结算异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测作答记录结算异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
             }
         }
 
@@ -523,104 +523,107 @@ namespace TEAMModelFunction
                 int plcount = 0;
                 //存放并去重知识点
                 HashSet<string> kname = new HashSet<string>();
-                info.papers[no].knowledge.ForEach(kno =>
-                {
-                    kno.ForEach(k =>
+                if (info.papers[no].knowledge.Count > 0) {
+                    info.papers[no].knowledge.ForEach(kno =>
                     {
-                        kname.Add(k);
+                        kno.ForEach(k =>
+                        {
+                            kname.Add(k);
+                        });
                     });
-                });
-                List<string> knowledgeName = new List<string>();
-                foreach (string cla in kname)
-                {
-                    knowledgeName.Add(cla);
-                }
-                for (int k = 0; k < knowledgeName.Count; k++)
-                {
-                    if (null == knowledgeName[k])
+                    List<string> knowledgeName = new List<string>();
+                    foreach (string cla in kname)
                     {
-                        knowledgeName.Remove(knowledgeName[k]);
+                        knowledgeName.Add(cla);
+                    }
+                    for (int k = 0; k < knowledgeName.Count; k++)
+                    {
+                        if (null == knowledgeName[k])
+                        {
+                            knowledgeName.Remove(knowledgeName[k]);
+                        }
                     }
-                }
 
-                foreach (ExamClassResult classResult in classResults)
-                {
-                    if (classResult.subjectId.Equals(subject.id))
+                    foreach (ExamClassResult classResult in classResults)
                     {
-                        //List<int> phc = new List<int>();
-                        List<int> ph = new List<int>();
-                        List<int> pl = new List<int>();
-                        List<int> pc = new List<int>();
-                        List<double> persent = new List<double>();
-                        for (int i = 0; i < knowledgeName.Count; i++)
+                        if (classResult.subjectId.Equals(subject.id))
                         {
-                            //初始化单个知识点得分
-                            double score = 0;
-                            double allScore = 0;
-                            int n = 0;
-                            int phCount = 0;
-                            int plCount = 0;
-                            int pCount = 0;
-                            foreach (List<string> str in info.papers[no].knowledge)
+                            //List<int> phc = new List<int>();
+                            List<int> ph = new List<int>();
+                            List<int> pl = new List<int>();
+                            List<int> pc = new List<int>();
+                            List<double> persent = new List<double>();
+                            for (int i = 0; i < knowledgeName.Count; i++)
                             {
-                                if (str.Contains(knowledgeName[i]))
+                                //初始化单个知识点得分
+                                double score = 0;
+                                double allScore = 0;
+                                int n = 0;
+                                int phCount = 0;
+                                int plCount = 0;
+                                int pCount = 0;
+                                foreach (List<string> str in info.papers[no].knowledge)
                                 {
-                                    var itemPersent = str.Count > 0 ? 1 / Convert.ToDouble(str.Count) : 0;
-                                    allScore += info.papers[no].point[n] * itemPersent;
-                                    foreach (string id in classResult.studentIds)
+                                    if (str.Contains(knowledgeName[i]))
                                     {
-                                        int index = classResult.studentIds.IndexOf(id);
-                                        if (classResult.studentScores.Count > 0)
+                                        var itemPersent = str.Count > 0 ? 1 / Convert.ToDouble(str.Count) : 0;
+                                        allScore += info.papers[no].point.Count > 0 ? info.papers[no].point[n] * itemPersent : 0;
+                                        foreach (string id in classResult.studentIds)
                                         {
-                                            if (classResult.studentScores[index].Count > 0)
+                                            int index = classResult.studentIds.IndexOf(id);
+                                            if (classResult.studentScores.Count > 0)
                                             {
-                                                score += classResult.studentScores[index][n] == -1 ? 0 : classResult.studentScores[index][n];
-                                                if (classResult.studentScores[index].Sum() >= rhw && phcount < rhwCount)
+                                                if (classResult.studentScores[index].Count > 0)
                                                 {
-                                                    if (classResult.studentScores[index][n] <= 0)
+                                                    score += classResult.studentScores[index][n] == -1 ? 0 : classResult.studentScores[index][n];
+                                                    if (classResult.studentScores[index].Sum() >= rhw && phcount < rhwCount)
                                                     {
-                                                        phCount++;
+                                                        if (classResult.studentScores[index][n] <= 0)
+                                                        {
+                                                            phCount++;
+                                                        }
+                                                        phcount++;
+                                                        continue;
+                                                    }
+                                                    if (classResult.studentScores[index].Sum() <= rhl && plcount < (info.stuCount - rhlCount))
+                                                    {
+                                                        if (classResult.studentScores[index][n] <= 0)
+                                                        {
+                                                            plCount++;
+                                                        }
+                                                        plcount++;
+                                                        continue;
                                                     }
-                                                    phcount++;
-                                                    continue;
-                                                }
-                                                if (classResult.studentScores[index].Sum() <= rhl && plcount < (info.stuCount - rhlCount))
-                                                {
                                                     if (classResult.studentScores[index][n] <= 0)
                                                     {
-                                                        plCount++;
+                                                        pCount++;
                                                     }
-                                                    plcount++;
-                                                    continue;
-                                                }
-                                                if (classResult.studentScores[index][n] <= 0)
-                                                {
-                                                    pCount++;
                                                 }
                                             }
-                                        }
 
+                                        }
                                     }
+                                    n++;
                                 }
-                                n++;
+                                pc.Add(pCount);
+                                ph.Add(phCount);
+                                pl.Add(plCount);
+                                double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0;
+                                persent.Add(allScore > 0 ? per / allScore : 0);
                             }
-                            pc.Add(pCount);
-                            ph.Add(phCount);
-                            pl.Add(plCount);
-                            double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0;
-                            persent.Add(allScore > 0 ? per / allScore : 0);
+                            classResult.phc = ph;
+                            classResult.plc = pl;
+                            classResult.pc = pc;
+                            classResult.krate = persent;
                         }
-                        classResult.phc = ph;
-                        classResult.plc = pl;
-                        classResult.pc = pc;
-                        classResult.krate = persent;
+                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(classResult, classResult.id, new Azure.Cosmos.PartitionKey($"{classResult.code}"));
                     }
-                    await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(classResult, classResult.id, new Azure.Cosmos.PartitionKey($"{classResult.code}"));
                 }
+                
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-评测知识点结算异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测知识点结算异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
             }
         }
 
@@ -657,53 +660,55 @@ namespace TEAMModelFunction
                             int phCount = 0;
                             int plCount = 0;
                             int pCount = 0;
-                            foreach (int str in info.papers[no].field)
-                            {
-                                if (str == knowledgeName[i])
+                            if (info.papers[no].field.Count > 0) {
+                                foreach (int str in info.papers[no].field)
                                 {
-                                    var itemPersent = 1;
-                                    allScore += info.papers[no].point[n] * itemPersent;
-                                    foreach (string id in classResult.studentIds)
+                                    if (str == knowledgeName[i])
                                     {
-                                        int index = classResult.studentIds.IndexOf(id);
-                                        if (classResult.studentScores.Count > 0)
+                                        var itemPersent = 1;
+                                        allScore += info.papers[no].point.Count > 0 ? info.papers[no].point[n] * itemPersent : 0;
+                                        foreach (string id in classResult.studentIds)
                                         {
-                                            if (classResult.studentScores[index].Count > 0)
+                                            int index = classResult.studentIds.IndexOf(id);
+                                            if (classResult.studentScores.Count > 0)
                                             {
-                                                score += classResult.studentScores[index][n] == -1 ? 0 : classResult.studentScores[index][n];
-                                                if (classResult.studentScores[index].Sum() >= rhw && phcount < rhwCount)
+                                                if (classResult.studentScores[index].Count > 0)
                                                 {
-                                                    if (classResult.studentScores[index][n] <= 0)
+                                                    score += classResult.studentScores[index][n] == -1 ? 0 : classResult.studentScores[index][n];
+                                                    if (classResult.studentScores[index].Sum() >= rhw && phcount < rhwCount)
                                                     {
-                                                        phCount++;
+                                                        if (classResult.studentScores[index][n] <= 0)
+                                                        {
+                                                            phCount++;
+                                                        }
+                                                        phcount++;
+                                                        continue;
+                                                    }
+                                                    if (classResult.studentScores[index].Sum() <= rhl && plcount < (info.stuCount - rhlCount))
+                                                    {
+                                                        if (classResult.studentScores[index][n] <= 0)
+                                                        {
+                                                            plCount++;
+                                                        }
+                                                        plcount++;
+                                                        continue;
                                                     }
-                                                    phcount++;
-                                                    continue;
-                                                }
-                                                if (classResult.studentScores[index].Sum() <= rhl && plcount < (info.stuCount - rhlCount))
-                                                {
                                                     if (classResult.studentScores[index][n] <= 0)
                                                     {
-                                                        plCount++;
+                                                        pCount++;
                                                     }
-                                                    plcount++;
-                                                    continue;
-                                                }
-                                                if (classResult.studentScores[index][n] <= 0)
-                                                {
-                                                    pCount++;
                                                 }
                                             }
                                         }
                                     }
+                                    n++;
                                 }
-                                n++;
-                            }
-                            pc.Add(pCount);
-                            ph.Add(phCount);
-                            pl.Add(plCount);
-                            double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0;
-                            persent.Add(allScore > 0 ? per / allScore : 0);
+                                pc.Add(pCount);
+                                ph.Add(phCount);
+                                pl.Add(plCount);
+                                double per = classResult.studentIds.Count > 0 ? Math.Round(score / classResult.studentIds.Count, 2) : 0;
+                                persent.Add(allScore > 0 ? per / allScore : 0);
+                            }                           
                         }
                         classResult.fphc = ph;
                         classResult.fplc = pl;
@@ -715,7 +720,7 @@ namespace TEAMModelFunction
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-评测认知层次结算异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}-{info.id}-评测认知层次结算异常{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
             }
         }
         //处理选题计数
@@ -841,6 +846,9 @@ namespace TEAMModelFunction
                         csRate.Add(classResult.studentIds.Count > 0 ? Math.Round(classSrate * 1.0 / classResult.studentIds.Count, 2) : 0 / allScore);
 
                     }
+                    else {
+                        csRate.Add(0);
+                    }
 
                     //powSum += Math.Pow(classSrate - result.average, 2);
                     //处理选项计数内容

+ 28 - 0
TEAMModelOS.SDK/Extension/JwtAuthExtension.cs

@@ -42,6 +42,34 @@ namespace TEAMModelOS.SDK.Extension
 
             return serializeToken;
         }
+        public static string CreateAppToken(string issuer, string id,  string salt, string schoolID = "", int expire = 1)
+        {
+            // 設定要加入到 JWT Token 中的聲明資訊(Claims)  
+            var payload = new JwtPayload {
+                { JwtRegisteredClaimNames.Iss, issuer }, //發行者
+                { JwtRegisteredClaimNames.Sub, id }, // 用戶ID                  
+                { JwtRegisteredClaimNames.Azp,schoolID}, // 學校簡碼,如果有的話
+                { JwtRegisteredClaimNames.Exp,DateTimeOffset.UtcNow.AddHours(expire).ToUnixTimeSeconds().ToString()},  // 到期的時間,必須為數字
+                //{ "name",name}, // 用戶的顯示名稱
+                //{ "picture",picture}, // 用戶頭像
+                //{ "roles",roles}, // 登入者的角色,角色類型 (Admin、Teacher、Student) 
+               // { "permissions",permissions} //登入者的權限請求
+            };
+
+            // 建立一組對稱式加密的金鑰,主要用於 JWT 簽章之用
+            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(salt));
+            // HmacSha256 有要求必須要大於 128 bits,所以 salt 不能太短,至少要 16 字元以上
+            // https://stackoverflow.com/questions/47279947/idx10603-the-algorithm-hs256-requires-the-securitykey-keysize-to-be-greater
+            var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
+            var header = new JwtHeader(signingCredentials);
+            var secToken = new JwtSecurityToken(header, payload);
+            // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
+            var tokenHandler = new JwtSecurityTokenHandler();
+            //var securityToken = tokenHandler.CreateToken(tokenDescriptor);
+            var serializeToken = tokenHandler.WriteToken(secToken);
+
+            return serializeToken;
+        }
 
         public static bool ValidateAuthToken(string token, string salt)
         {

+ 49 - 0
TEAMModelOS.SDK/Models/Cosmos/Api/OpenApi.cs

@@ -0,0 +1,49 @@
+using Microsoft.Azure.Cosmos.Table;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+
+namespace TEAMModelOS.SDK.Models
+{
+    /*
+     {
+        "id":"uuid",
+        "code":"base",
+        "pk":"Api",
+        "name": "学校基本信息",
+        "url": "school/get",
+        "method": "GET/POST",
+        "descr": "描述"
+    }
+     */
+    /// <summary>
+    /// 限流方案  漏斗、令牌桶、sentinel
+    /// 平台开放的OpenAIPs
+    /// </summary>
+    [TableName(Name = "OpenApi")]
+    public class OpenApi : TableEntity
+    {
+        public OpenApi() {
+
+            PartitionKey = "OpenApi";
+        } 
+        public string name { get; set; }
+        public string url { get; set; }
+        public string method { get; set; }
+        public string descr { get; set; }
+     
+    }
+
+    public class OpenApp : CosmosEntity {
+        public string name { get; set; }
+        public string descr { get; set; }
+        public List<string> apis { get; set; } = new List<string>();
+        public string school { get; set; }
+        public string token { get; set; }
+        public OpenApp()
+        {
+            pk = "OpenApp";
+        }
+    }
+}

+ 126 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Correct.cs

@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models.Cosmos
+{
+    public  class Correct: CosmosEntity
+    {
+        public Correct()
+        {
+            pk = "Correct";
+
+        }
+        /// <summary>
+        /// 发布层级 类型 school   
+        /// </summary>
+        public string owner { get; set; } = "school";
+        /// <summary>
+        /// 学校编码
+        /// </summary>
+        [Required(ErrorMessage = "school 必须设置")]
+        public string school { get; set; }
+        /// <summary>
+        /// 阅卷名称
+        /// </summary>
+        [Required(ErrorMessage = "name 必须设置")]
+        public string name { get; set; }
+        /// <summary>
+        /// 创建者的id 
+        /// </summary>
+        [Required(ErrorMessage = "creatorId 必须设置")]
+        public string creatorId { get; set; }
+        /// <summary>
+        /// pending 待发布|going 已发布|finish 已结束
+        /// </summary>
+        //[Required(ErrorMessage = "progress 必须设置")]
+        public string progress { get; set; }
+        /// <summary>
+        /// school 
+        /// </summary>
+        [Required(ErrorMessage = "scope 必须设置")]
+        public string scope { get; set; } = "school";
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        public long startTime { get; set; }
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public long createTime { get; set; }
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        public long endTime { get; set; }
+    
+        public int? status { get; set; } = 0;
+        /// <summary>
+        /// 评测的分区键code值
+        /// </summary>
+        public string scode { get; set; }
+        public List<CorSub> subs { get; set; } = new List<CorSub>();
+        /// <summary>
+        /// 阅卷模式,qu按题目,full按人/学生
+        /// </summary>
+        public string mode { get; set; }
+        /// <summary>
+        /// 阅卷次数
+        /// </summary>
+        public int num { get; set; } = 1;
+        /// <summary>
+        /// 是否有异常处理流程 0/1
+        /// </summary>
+        public int isErr { get; set; }
+        /// <summary>
+        /// 是否有仲裁处理流程 0/1
+        /// </summary>
+        public int isArb { get; set; }
+    }
+
+    public class CorSub{
+        /// <summary>
+        /// 科目名称
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 科目id
+        /// </summary>
+        public string id { get; set; }
+        /// <summary>
+        /// 参与阅卷教师醍摩豆id
+        /// </summary>
+        public List<CorTmd> markers { get; set; } = new List<CorTmd>();
+        /// <summary>
+        /// 异常卷处理人员
+        /// </summary>
+        public List<string> err { get; set; } = new List<string>() ;
+        /// <summary>
+        /// 仲裁卷处理人员
+        /// </summary>
+        public List<string> arb { get; set; } = new List<string>() ;
+        /// <summary>
+        /// 分差(仲裁条件)
+        /// </summary>
+        ///public double point { get; set; }
+       
+    }
+    public class CorTmd{
+        /// <summary>
+        /// tmdid
+        /// </summary>
+        public string id { get; set; }
+        /// <summary>
+        /// tmdid名
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 任务量
+        /// </summary>
+        public int count { get; set; }
+        /// <summary>
+        /// 题目分配规则
+        /// </summary>
+        public List<string> qu { get; set; }
+    }
+}

+ 1 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs

@@ -13,6 +13,7 @@ namespace TEAMModelOS.SDK.Models
     public class SyllabusTreeNode{
         public string id { get; set; }
         public string code { get; set; }
+        public string scope { get; set; }
         public SyllabusTreeNode() {
             trees = new List<SyllabusTree>();
         }

+ 2 - 1
TEAMModelOS.SDK/Models/Cosmos/Common/Snode.cs

@@ -36,8 +36,9 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         [Required(ErrorMessage = "{0} 必须填写")]
 
         public int order { get; set; }
-        public List<string> points { get; set; } = new List<string> { "" };
+        //public List<string> points { get; set; } = new List<string> { "" };
         public List<Rnode> rnodes { get; set; } = new List<Rnode>();
+        public List<string> cids { get; set; } = new List<string>();
         //public string code { get; set; }
 
     }

+ 1 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs

@@ -19,6 +19,7 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
         public List<Tnode> children { get; set; }
+      
 
     }
 }

+ 20 - 7
TEAMModelOS.SDK/Models/Cosmos/Common/Volume.cs

@@ -67,24 +67,37 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         /// <summary>
         /// 共编使用者 的醍摩豆id
         /// </summary>
-        public List<string> editors { get; set; }
+       // public List<string> editors { get; set; }
 
         //public int resourceCount { get; set; }
         //public int itemCount { get; set; }
         /// <summary>
-        /// 发布层级 类型 school  teacher
-        /// </summary>
-        public string owner { get; set; }
-        /// <summary>
-        /// 学校编码或教师tmdid
+        /// 学校编码
         /// </summary>
         [Required(ErrorMessage = "school 必须设置")]
         public string school { get; set; }
-        public bool repeat { get; set; }
+       // public bool repeat { get; set; }
         /// <summary>
         /// school|private
         /// </summary>
         [Required(ErrorMessage = "scope 必须设置")]
         public string scope { get; set; }
+        public List<SyllabusAuth> auth { get; set; } = new List<SyllabusAuth>();
+    }
+
+    /// <summary>
+    /// 只要创建课纲的creatorId 才能编辑课纲的分享,共编权限 25600 74200  27500 2000
+    /// ,共编者 谁创建的节点只能谁删除,而且删除时能删除子节点(包含不是自己创建的)。
+    /// </summary>
+    public class SyllabusAuth
+    {
+        public string tmdid { get; set; }
+        public string name { get; set; }
+        public bool coedit { get; set; }
+        public bool share { get; set; }
+        /// <summary>
+        ///分享的节点 all  或者節點id
+        /// </summary>
+        public List<string> snodes { get; set; } = new List<string>();
     }
 }

+ 7 - 4
TEAMModelOS.SDK/Models/Cosmos/School/Class.cs

@@ -50,18 +50,21 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// TBL IRS 类型区分
         /// </summary>
-        public string style { get; set; }
+        //public string style { get; set; }
         public int status { get; set; } = 1;        
-       
+        /// <summary>
+        /// 关联教室的id
+        /// </summary>
+        public string room { get; set; }
         /// <summary>
         /// 教室属性,普通 /专设的教室
         /// </summary>
-        public string openType { get; set; }
+        //public string openType { get; set; }
         public string scope { get; set; }
         /// <summary>
         /// 学生名单数据来源 1是不同学校的学生账号,2是扫码加入的醍摩豆ID
         /// </summary>
-        public int? source { get; set; }
+        //public int? source { get; set; }
         
     }
 }

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

@@ -2,7 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Models.Cosmos.School
+namespace TEAMModelOS.SDK.Models.Cosmos
 {
     public class ClassAnalysis
     {

+ 10 - 0
TEAMModelOS.SDK/Models/Cosmos/School/Course.cs

@@ -65,8 +65,18 @@ namespace TEAMModelOS.SDK.Models
 
     public class Schedule
     {
+        /// <summary>
+        /// 教室
+        /// </summary>
+        public string room { get; set; }
+        /// <summary>
+        /// 班级名单id
+        /// </summary>
         public string classId { get; set; }
         public string teacherId { get; set; }
+        /// <summary>
+        /// 自定义名单
+        /// </summary>
         public string stulist { get; set; }
         public List<timeInfo> time { get; set; } = new List<timeInfo>();
         public string notice { get; set; }

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

@@ -2,7 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Models.Cosmos.School
+namespace TEAMModelOS.SDK.Models.Cosmos
 {
     public class GradeAnalysis
     {

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

@@ -3,7 +3,7 @@ using System.Collections.Generic;
 using System.ComponentModel.DataAnnotations;
 using System.Text;
 
-namespace TEAMModelOS.SDK.Models.Cosmos.School
+namespace TEAMModelOS.SDK.Models.Cosmos
 {
     /// <summary>
     ///Teaching materials 教学材料 --- 知识点,知识块

+ 42 - 0
TEAMModelOS.SDK/Models/Cosmos/Teacher/CorrectTask.cs

@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models
+{
+    public class CorrectTask: CosmosEntity
+    {
+        /// <summary>
+        /// 评测科目
+        /// </summary>
+        public string subjectName  { get; set; }
+        /// <summary>
+        /// 评测科目
+        /// </summary>
+        public string subject { get; set; }
+        /// <summary>
+        /// 评测源数据的 code
+        /// </summary>
+        public string ecode { get; set; }
+        /// <summary>
+        /// 阅卷配置源数据的 code
+        /// </summary>
+        public string scode { get; set; }
+        /// <summary>
+        /// 评测名称
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 开始时间
+        /// </summary>
+        public long startTime { get; set; }
+        /// <summary>
+        /// 结束时间
+        /// </summary>
+        public long endTime { get; set; }
+        /// <summary>
+        /// 阅卷数量
+        /// </summary>
+        public int count { get; set; }
+    }
+}

+ 149 - 0
TEAMModelOS.SDK/Models/Cosmos/Teacher/Favorite.cs

@@ -0,0 +1,149 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Text;
+using TEAMModelOS.SDK.Models.Cosmos.Common;
+
+namespace TEAMModelOS.SDK.Models.Cosmos
+{
+    /// <summary>
+    /// 课纲-我喜欢的,我的收藏
+    /// </summary>
+    public class Favorite : CosmosEntity
+    {
+        public Favorite() {
+            pk = "Favorite";
+            ttl = -1;
+            //code ="Favorite-tmdid"
+        }
+        public SyllabusTree node { get; set; }
+        /// <summary>
+        /// 名称 默认选中节点名称,或者自定义输入名称
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public long createTime { get; set; }
+        /// <summary>
+        /// 引用来源课纲id
+        /// </summary>
+        [Required(ErrorMessage = "引用来源课纲id 必须设置")]
+        public string fromId { get; set; }
+        /// <summary>
+        /// 引用来源 课纲Code 分区键
+        /// </summary>
+        [Required(ErrorMessage = "引用来源课纲code 必须设置")]
+        public string fromCode { get; set; }
+    }
+
+    /*
+     {
+        "id":"课纲册别id",
+        "code":"Share-接收者tmdid",
+        "issuer":"分享者tmdid",
+        "createTime":分享时间,
+        "scode":"引用来源课纲册别code",
+        "scope":"school/private",
+        "school":"hbcn",
+        "issuer":"颁发权限的id"
+    }
+     */
+    /// <summary>
+    /// 主动分享给谁, 分享功能只会发生在个人课纲中
+    /// </summary>
+    public class Share : CosmosEntity {
+        public Share(){
+            pk = "Share";
+        }
+
+        public string scode { get; set; }
+        /// <summary>
+        /// 权限颁发者
+        /// </summary>
+        public string issuer { get; set; }
+        public long  createTime { get; set; }
+        /// <summary>
+        /// 学校编码或教师tmdid
+        /// </summary>
+        [Required(ErrorMessage = "school 必须设置")]
+        public string school { get; set; }
+        /// <summary>
+        /// school|private
+        /// </summary>
+        [Required(ErrorMessage = "scope 必须设置")]
+        public string scope { get; set; }
+        /// <summary>
+        /// 共编
+        /// </summary>
+        public bool coedit { get; set; }
+        /// <summary>
+        /// 分享
+        /// </summary>
+        public bool share { get; set; }
+        /// <summary>
+        /// 课纲名称
+        /// </summary>
+        public string sname { get; set; }
+    }
+         
+    /// <summary>
+    /// 主动分享给谁,当接收者接收并完成相关资源复制后则删除本条数据。
+    /// </summary>
+    public class ShareData
+    {
+        /// <summary>
+        /// 学校编码
+        /// </summary>
+        [Required(ErrorMessage = "school 必须设置")]
+        public string school { get; set; }
+        /// <summary>
+        /// school|private
+        /// </summary>
+        [Required(ErrorMessage = "scope 必须设置")]
+        public string scope { get; set; }
+        /// <summary>
+        /// add/edit/del
+        /// </summary>
+        [Required(ErrorMessage = "opt 必须设置")]
+        public string opt { get; set; }
+        [Required(ErrorMessage = "tmdid 必须设置")]
+        public string tmdid { get; set; }
+        /// <summary>
+        /// tmdname
+        /// </summary>
+        public string name { get; set; }
+        /// <summary>
+        /// 课纲的id
+        /// </summary>
+        [Required(ErrorMessage = "sid 必须设置")]
+        public string sid { get; set; }
+        /// <summary>
+        /// 课纲的分区键
+        /// </summary>
+        [Required(ErrorMessage = "socde 必须设置")]
+        public string scode { get; set; }
+        /// <summary>
+        /// 课纲的名称
+        /// </summary>
+        [Required(ErrorMessage = "sname 必须设置")]
+        public string sname { get; set; }
+        /// <summary>
+        /// 共编权限
+        /// </summary>
+        public bool coedit { get; set; } = false;
+        /// <summary>
+        /// 分享权限
+        /// </summary>
+        public bool share { get; set; } = false;
+        /// <summary>
+        /// 分享的节点 all  或者節點id
+        /// </summary>
+        public List<string> snodes { get; set; } = new List<string>();
+        /// <summary>
+        /// 共编 分享权限颁发者
+        /// </summary>
+        [Required(ErrorMessage = "issuer 必须设置")]
+        public string issuer { get; set; }
+    }
+}

+ 1 - 1
TEAMModelOS.SDK/TEAMModelOS.SDK.csproj

@@ -16,7 +16,7 @@
     <PackageReference Include="Azure.Messaging.ServiceBus" Version="7.1.1" />
     <PackageReference Include="Azure.Storage.Blobs.Batch" Version="12.5.1" />
     <PackageReference Include="Azure.Storage.Queues" Version="12.6.1" />
-    <PackageReference Include="ClouDASLibx" Version="1.2.6" />
+    <PackageReference Include="ClouDASLibx" Version="1.2.7" />
     <PackageReference Include="DocumentFormat.OpenXml" Version="2.12.3" />
     <PackageReference Include="HtmlAgilityPack" Version="1.11.32" />
     <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.10" />

+ 6 - 6
TEAMModelOS/ClientApp/package.json

@@ -34,23 +34,23 @@
 		"firestore": "^1.1.6",
 		"html2canvas": "^1.0.0-rc.7",
 		"imports-loader": "^0.8.0",
-		"jspdf": "^2.3.1",
-		"print-js": "^1.6.0",
-		"snapsvg": "^0.5.1",
 		"increase-memory-limit": "^1.0.7",
 		"js-sha1": "^0.6.0",
 		"json-markup": "^1.1.3",
-		"jsonpath": "^1.0.2",
+		"jsonpath": "^1.1.1",
+		"jspdf": "^2.3.1",
 		"jszip": "^3.4.0",
 		"jwt-decode": "^2.2.0",
 		"konva": "^7.1.1",
 		"less": "^3.9.0",
-		"lodash": "^4.17.20",
+		"lodash": "^4.17.21",
 		"mockjs": "^1.0.1-beta3",
 		"mux.js": "^5.11.0",
 		"node-fetch": "^2.6.1",
 		"oidc-client": "^1.9.1",
+		"print-js": "^1.6.0",
 		"qrcodejs2": "0.0.2",
+		"snapsvg": "^0.5.1",
 		"svg-sprite-loader": "^5.0.0",
 		"unsplash-js": "^6.0.0",
 		"v-calendar": "^1.0.8",
@@ -111,7 +111,7 @@
 		"@vue/cli-plugin-eslint": "^4.0.0",
 		"@vue/cli-plugin-router": "^4.0.4",
 		"@vue/cli-plugin-vuex": "^4.0.4",
-		"@vue/cli-service": "^4.0.0",
+		"@vue/cli-service": "^4.5.13",
 		"aspnet-webpack": "^3.0.0",
 		"autoprefixer": "^9.6.5",
 		"babel-eslint": "^10.0.1",

+ 3 - 3
TEAMModelOS/ClientApp/src/api/courseMgmt.js

@@ -90,9 +90,9 @@ export default {
     findListSummary: function (data) {
         return post('/school/course/get-summary-list', data)
     },
-    //查询课程安排数据 (废弃,已经没有courseManagement结构)
-    findCusByClass: function (data) {
-        return post('/school/course/find-course-by-classId', data)
+    //查询课程安排数据
+    findCusByRoom: function (data) {
+        return post('/school/course/find-course-by-room', data)
     },
     //我的课程页面查询班级相关的校本活动和老师发布的个人活动
     findTchAc: function (data) {

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

@@ -27,6 +27,7 @@ import classroom from './classroom'
 import serviceDriveAuth from './serviceDriveAuth'
 import spaceAuth from './spaceAuth'
 import room from './room'
+import mark from './mark'
 
 export default {
     accessToken,
@@ -55,6 +56,7 @@ export default {
     serviceDriveAuth,
     spaceAuth,
     room,
+    mark,
 
     // 获取登录跳转链接
     getLoginLink: function (data) {

+ 22 - 0
TEAMModelOS/ClientApp/src/api/mark.js

@@ -0,0 +1,22 @@
+import { post } from '@/api/http'
+export default {
+    /*
+     *保存阅卷设置
+     */
+    UpsertMarkSet: function (data) {
+        return post('/school/correct/upsert', data)
+    },
+    /*
+     *根据评测id查询评测阅卷配置信息
+     */
+     FindById: function (data) {
+        return post('/school/correct/find-id', data)
+    },
+    /*
+     *根据评测id查询评测阅卷配置信息
+     */
+     FindTask: function (data) {
+        return post('/school/correct/find-task', data)
+    }
+
+}

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

@@ -54,6 +54,30 @@
       <div class="content unicode" style="display: block;">
           <ul class="icon_lists dib-box">
           
+            <li class="dib">
+              <span class="icon iconfont">&#xe62a;</span>
+                <div class="name">公式</div>
+                <div class="code-name">&amp;#xe62a;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6aa;</span>
+                <div class="name">最低投标</div>
+                <div class="code-name">&amp;#xe6aa;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6ab;</span>
+                <div class="name">最高投标</div>
+                <div class="code-name">&amp;#xe6ab;</div>
+              </li>
+          
+            <li class="dib">
+              <span class="icon iconfont">&#xe6ae;</span>
+                <div class="name">平均不平衡</div>
+                <div class="code-name">&amp;#xe6ae;</div>
+              </li>
+          
             <li class="dib">
               <span class="icon iconfont">&#xe6ac;</span>
                 <div class="name">做任务</div>
@@ -726,9 +750,9 @@
 <pre><code class="language-css"
 >@font-face {
   font-family: 'iconfont';
-  src: url('iconfont.woff2?t=1620299264680') format('woff2'),
-       url('iconfont.woff?t=1620299264680') format('woff'),
-       url('iconfont.ttf?t=1620299264680') format('truetype');
+  src: url('iconfont.woff2?t=1620811886189') format('woff2'),
+       url('iconfont.woff?t=1620811886189') format('woff'),
+       url('iconfont.ttf?t=1620811886189') format('truetype');
 }
 </code></pre>
           <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
@@ -754,6 +778,42 @@
       <div class="content font-class">
         <ul class="icon_lists dib-box">
           
+          <li class="dib">
+            <span class="icon iconfont icon-formula"></span>
+            <div class="name">
+              公式
+            </div>
+            <div class="code-name">.icon-formula
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-lowest"></span>
+            <div class="name">
+              最低投标
+            </div>
+            <div class="code-name">.icon-lowest
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-highest"></span>
+            <div class="name">
+              最高投标
+            </div>
+            <div class="code-name">.icon-highest
+            </div>
+          </li>
+          
+          <li class="dib">
+            <span class="icon iconfont icon-avg"></span>
+            <div class="name">
+              平均不平衡
+            </div>
+            <div class="code-name">.icon-avg
+            </div>
+          </li>
+          
           <li class="dib">
             <span class="icon iconfont icon-task"></span>
             <div class="name">
@@ -1762,6 +1822,38 @@
       <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-formula"></use>
+                </svg>
+                <div class="name">公式</div>
+                <div class="code-name">#icon-formula</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-lowest"></use>
+                </svg>
+                <div class="name">最低投标</div>
+                <div class="code-name">#icon-lowest</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-highest"></use>
+                </svg>
+                <div class="name">最高投标</div>
+                <div class="code-name">#icon-highest</div>
+            </li>
+          
+            <li class="dib">
+                <svg class="icon svg-icon" aria-hidden="true">
+                  <use xlink:href="#icon-avg"></use>
+                </svg>
+                <div class="name">平均不平衡</div>
+                <div class="code-name">#icon-avg</div>
+            </li>
+          
             <li class="dib">
                 <svg class="icon svg-icon" aria-hidden="true">
                   <use xlink:href="#icon-task"></use>

+ 19 - 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=1620299264680') format('woff2'),
-       url('iconfont.woff?t=1620299264680') format('woff'),
-       url('iconfont.ttf?t=1620299264680') format('truetype');
+  src: url('iconfont.woff2?t=1620811886189') format('woff2'),
+       url('iconfont.woff?t=1620811886189') format('woff'),
+       url('iconfont.ttf?t=1620811886189') format('truetype');
 }
 
 .iconfont {
@@ -13,6 +13,22 @@
   -moz-osx-font-smoothing: grayscale;
 }
 
+.icon-formula:before {
+  content: "\e62a";
+}
+
+.icon-lowest:before {
+  content: "\e6aa";
+}
+
+.icon-highest:before {
+  content: "\e6ab";
+}
+
+.icon-avg:before {
+  content: "\e6ae";
+}
+
 .icon-task:before {
   content: "\e6ac";
 }

文件差異過大導致無法顯示
+ 1 - 1
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.js


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

@@ -5,6 +5,34 @@
   "css_prefix_text": "icon-",
   "description": "",
   "glyphs": [
+    {
+      "icon_id": "10352314",
+      "name": "公式",
+      "font_class": "formula",
+      "unicode": "e62a",
+      "unicode_decimal": 58922
+    },
+    {
+      "icon_id": "993785",
+      "name": "最低投标",
+      "font_class": "lowest",
+      "unicode": "e6aa",
+      "unicode_decimal": 59050
+    },
+    {
+      "icon_id": "993787",
+      "name": "最高投标",
+      "font_class": "highest",
+      "unicode": "e6ab",
+      "unicode_decimal": 59051
+    },
+    {
+      "icon_id": "7339863",
+      "name": "平均不平衡",
+      "font_class": "avg",
+      "unicode": "e6ae",
+      "unicode_decimal": 59054
+    },
     {
       "icon_id": "5241258",
       "name": "做任务",

二進制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.ttf


二進制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff


二進制
TEAMModelOS/ClientApp/src/assets/iconfont/iconfont.woff2


+ 29 - 28
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -75,14 +75,16 @@ export default {
     methods: {
         initMenu() {
             this.menuTree = [
+                // 智慧校园
                 {
                     icon: 'iconfont icon-school',
                     name: this.$t('system.menu.smartSc'),
                     router: '',
                     subName: 'smartSchool',
-                    role: 'teacher|admin',
-                    permission: '',
+                    role: 'admin',
+                    permission: 'schoolSetting-read|teacher-read|student-read|classroom-read|auth-read|course-read|syllabus-read|content-read|exercise-read|knowledge-read',
                     child: [
+                        // 基础设置
                         {
                             icon: 'iconfont icon-basic-setting',
                             name: this.$t('system.menu.baseSetting'),
@@ -92,6 +94,7 @@ export default {
                             permission: 'schoolSetting-read|schoolSetting-upd',
                             menuName: 'system'
                         },
+                        // 教师管理
                         {
                             icon: 'iconfont icon-teacher-mgt',
                             name: this.$t('system.menu.teacherMgt'),
@@ -101,6 +104,7 @@ export default {
                             permission: 'teacher-read|teacher-upd',
                             menuName: 'teachermgmt'
                         },
+                        // 学生管理
                         {
                             icon: 'iconfont icon-student-mgt',
                             name: this.$t('system.menu.stuMgt'),
@@ -110,6 +114,7 @@ export default {
                             permission: 'student-upd|student-read',
                             menuName: 'studentAccount'
                         },
+                        // 教室管理
                         {
                             icon: 'iconfont icon-class-mgt',
                             name: this.$t('system.menu.classMgt'),
@@ -119,32 +124,17 @@ export default {
                             permission: 'classroom-upd|classroom-read',
                             menuName: 'classroom'
                         },
+                        // 课程管理
                         {
                             icon: 'iconfont icon-kecheng',
                             name: this.$t('system.menu.cusMgt'),
                             router: '/home/NewCusMgt',
                             tag: '',
                             role: 'admin',
-                            permission: '',
+                            permission: 'course-read|course-upd',
                             menuName: 'NewCusMgt'
                         },
-                        //{
-                        //   icon: 'iconfont icon-time',
-                        //   name: '时段设置',
-                        //   router: '/home/CourseTime',
-                        //   tag:'+',
-                        //   role:'admin',
-                        //   permission:'',
-                        //},
-                        // 排课管理
-                        // {
-                        //     icon: 'iconfont icon-schedule',
-                        //     name: this.$t('system.menu.cusPlanMgt'),
-                        //     router: '/home/NewCoursePlan',
-                        //     tag: 'x',
-                        //     role: 'admin',
-                        //     permission: 'coursePlan-read|coursePlan-upd',
-                        // },
+                        // 授权管理
                         {
                             icon: 'iconfont icon-auth',
                             name: this.$t('system.menu.authMgt'),
@@ -154,44 +144,49 @@ export default {
                             permission: 'auth-read|auth-upd',
                             menuName: 'serviceDriveAuth'
                         },
+                        // 校本课纲
                         {
                             icon: 'iconfont icon-syllabus',
                             name: this.$t('system.menu.scSyllabus'),
                             router: '/home/syllabus',
                             tag: this.$t('system.menu.preview'),
-                            role: 'teacher|admin',
-                            permission: '',
+                            role: 'admin',
+                            permission: 'syllabus-read|syllabus-upd',
                             menuName: 'syllabus'
                         },
+                        // 校本内容
                         {
                             icon: 'iconfont icon-file',
                             name: this.$t('system.menu.scContent'),
                             router: '/home/schoolcontent',
                             tag: '',
-                            role: 'teacher|admin',
-                            permission: '',
+                            role: 'admin',
+                            permission: 'content-read|content-upd',
                             menuName: 'schoolcontent'
                         },
+                        // 校本题库
                         {
                             icon: 'iconfont icon-question-bank',
                             name: this.$t('system.menu.scQuBack'),
                             router: '/home/evaluation/schoolBank',
                             tag: '',
-                            role: 'teacher|admin',
-                            permission: '',
+                            role: 'admin',
+                            permission: 'exercise-read|exercise-upd',
                             menuName: 'schoolBank'
                         },
+                        // 知识点库
                         {
                             icon: 'iconfont icon-k-point',
                             name: this.$t('system.menu.kdBack'),
                             router: '/home/knowledge',
                             tag: '',
-                            role: 'teacher|admin',
-                            permission: '',
+                            role: 'admin',
+                            permission: 'knowledge-read|knowledge-upd',
                             menuName: 'knowledge'
                         }
                     ]
                 },
+                // 统计分析
                 {
                     icon: 'iconfont icon-analysis',
                     name: this.$t('system.menu.staAna'),
@@ -220,6 +215,7 @@ export default {
                         }
                     ]
                 },
+                // 校园活动
                 {
                     icon: 'iconfont icon-activityS',
                     name: this.$t('system.menu.scAc'),
@@ -259,6 +255,7 @@ export default {
                         },
                     ]
                 },
+                // 课程教材
                 {
                     icon: 'iconfont icon-textbook',
                     name: this.$t('system.menu.cusContent'),
@@ -296,6 +293,7 @@ export default {
                         }
                     ]
                 },
+                // 学习活动
                 {
                     icon: 'iconfont icon-activityT',
                     name: this.$t('system.menu.stuAc'),
@@ -351,6 +349,7 @@ export default {
                         }
                     ]
                 },
+                // 我的班级
                 {
                     icon: 'iconfont icon-class-self',
                     name: this.$t('system.menu.myClass'),
@@ -361,6 +360,7 @@ export default {
                     child: [],
                     menuName: 'manageClass'
                 },
+                // 我的课程
                 {
                     icon: 'iconfont icon-course-self',
                     name: this.$t('system.menu.myCus'),
@@ -371,6 +371,7 @@ export default {
                     child: [],
                     menuName: 'myCourse'
                 },
+                // 任务列表
                 {
                     icon: 'iconfont icon-task',
                     name: this.$t('system.menu.taskList'),

+ 8 - 3
TEAMModelOS/ClientApp/src/common/UploadModal.vue

@@ -271,6 +271,7 @@ export default {
         },
         // 确认上传文件
         confirmUpload(file, fileType, index) {
+            console.log(fileType)
             let extension = this.uploadedList[index].extension
             let _this = this
             this.containerClient.upload(file, fileType, {
@@ -338,7 +339,7 @@ export default {
                     }
                 }
             ).finally(() => {
-                if (extension !== 'PPTX' && extension !== 'HTEX') {
+                if (fileType != 'video' && fileType != 'image' && extension !== 'PPTX' && extension !== 'HTEX') {
                     this.counterReduce()
                 }
             })
@@ -364,7 +365,9 @@ export default {
                 err => {
                     console.log(this.$t('updModal.compressImgErr'))
                 }
-            )
+            ).finally(()=>{
+                this.counterReduce()
+            })
         },
         //处理视频封面
         async uploadPoater(file) {
@@ -379,7 +382,9 @@ export default {
                 err => {
                     console.log(this.$t('updModal.posterErr'))
                 }
-            )
+            ).finally(()=>{
+                this.counterReduce()
+            })
         }
     },
     created() {

+ 11 - 8
TEAMModelOS/ClientApp/src/components/coursemgt/StudentList.vue

@@ -1,17 +1,17 @@
 <template>
     <div class="dark-iview-table student-list">
         <div class="student-filter-wrap dark-iview-select dark-iview-input">
-            <span style="margin-top:6px">筛选条件:</span>
+            <span style="margin-top:6px">{{$t('stuAccount.filterLabel')}}</span>
             <!-- 學制Select -->
-            <Select v-model="searchPeriod" style="width:120px;" :placeholder="$t('stuAccount.periodHolder')" clearable @on-change="filterData" not-found-text="暂未归属学校">
+            <Select v-model="searchPeriod" style="width:120px;" :placeholder="$t('stuAccount.periodHolder')" clearable @on-change="filterData" :not-found-text="$t('stuAccount.noSchool')">
                 <Option v-for="(item,index) in periods" :value="item.id" :key="index">{{ item.name }}</Option>
             </Select>
             <!-- 學級Select -->
-            <Select v-model="searchGrade" style="width:120px;margin-left:5px;" :placeholder="$t('stuAccount.gradeHolder')" not-found-text="请先选择学段" clearable @on-change="filterData">
+            <Select v-model="searchGrade" style="width:120px;margin-left:5px;" :placeholder="$t('stuAccount.gradeHolder')" :not-found-text="$t('stuAccount.sltPdFirst')" clearable @on-change="filterData">
                 <Option v-for="(item,index) in filterGrades" :value="item.id" :key="index">{{ item.name }}</Option>
             </Select>
             <!-- 教室Select -->
-            <Select v-model="searchClassroom" ref="classroom" style="width:150px;margin-left:5px;" :placeholder="$t('stuAccount.classroomHolder')" clearable @on-change="filterData" :not-found-text="searchGrade ? '此年级暂无教室':'请先选择年级'">
+            <Select v-model="searchClassroom" ref="classroom" style="width:150px;margin-left:5px;" :placeholder="$t('stuAccount.classroomHolder')" clearable @on-change="filterData" :not-found-text="searchGrade ? $t('stuAccount.noClass'):$t('stuAccount.sltGdFirst')">
                 <Option v-for="(item,index) in filterClasses" :value="item.id" :key="index">{{ item.name }}</Option>
             </Select>
             <!-- 字串模糊搜尋 -->
@@ -19,7 +19,7 @@
         </div>
         <div class="sc-content dark-iview-table" style="position:relative">
             <Scroll :on-reach-bottom="scrollLoad" height="600" :distance-to-edge="[15,15]">
-                <Table ref="selection" :columns="tableColumns" :data="tableShowData" @on-selection-change="getSelectInfo">
+                <Table ref="stuSelection" :columns="tableColumns" :data="tableShowData" @on-selection-change="getSelectInfo">
                     <template slot-scope="{ row,index }" slot="status">
                         <Icon custom="iconfont icon-auth-key" size="25" color="#565656" />
                     </template>
@@ -79,6 +79,10 @@ export default {
         }
     },
     methods: {
+        //清空选择状态
+        clearTable(){
+            this.$refs.stuSelection.selectAll(false)
+        },
         initData() {
             this.tableColumns = [
                 {
@@ -139,6 +143,7 @@ export default {
         },
         /**基础查询数据 */
         baseFindStudent(params) {
+            if (!this.$store.state.user.schoolCode) return
             this.$api.stuAccount.findStudent(this.$store.state.user.schoolCode).then(
                 (res) => {
                     this.tableLoading = false
@@ -209,9 +214,7 @@ export default {
                 let temp = this.tableFilterData.slice(this.pointNum + 1, this.pointNum + this.basicCount)
                 this.pointNum += this.basicCount
                 if (temp.length == 0) {
-                    this.$Message.info('已經到底了')
-                    //多语系后面统一处理
-                    //this.$Message.info(this.$t('已經到底了'))
+                    this.$Message.info(this.$t('stuAccount.isBottom'))
                 } else {
                     this.tableShowData.push(...temp)
                 }

+ 3 - 0
TEAMModelOS/ClientApp/src/css/common-style.less

@@ -52,4 +52,7 @@
     /*pointer-events: none;*/
     cursor: not-allowed !important;
     color: #a5a5a5 !important;
+}
+.ivu-table:before{
+    height: 0px !important;
 }

+ 6 - 0
TEAMModelOS/ClientApp/src/css/dark-iview-form.less

@@ -60,4 +60,10 @@
         color: white;
         border-color: #303030;
     }
+    .ivu-radio-inner:after{
+        background: #1CC0F3;
+    }
+    .ivu-radio-inner{
+        // background: #1CC0F3;
+    }
 }

+ 5 - 4
TEAMModelOS/ClientApp/src/css/dark-iview-table.less

@@ -7,10 +7,6 @@
         background-color: rgba(120,120,120,.5);
     }
 
-    .ivu-table-cell {
-        // padding: 0px;
-    }
-
     .ivu-table-header thead tr th {
         background: none;
         color: white;
@@ -43,3 +39,8 @@
         background: #363636;
     }
 }
+.cus-table{
+    .ivu-table-cell {
+        padding: 0px;
+    }
+}

+ 7 - 0
TEAMModelOS/ClientApp/src/icons/answersheet/t.svg

@@ -0,0 +1,7 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="abcd" version="1.1" viewBox="0 0 150 92" xml:space="preserve">
+	<!-- <rect x="0" y="0" width="150" height="92" style="fill-opacity: 0; stroke-width:13; stroke:black;" /> -->
+  <polyline points="38,0 0,0 0,92 38,92" style="fill-opacity: 0; stroke-width:13; stroke:black;"/>
+  <line x1="0" y1="92" x2="38" y2="92" style="fill-opacity: 0; stroke-width:13; stroke:black;"/>
+  <text x="50%" y="83" font-size="112" text-anchor="middle">T</text>
+  <polyline points="112,0 150,0 150,92 112,92" style="fill-opacity: 0; stroke-width:13; stroke:black;"/>
+</svg>

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

@@ -25,6 +25,7 @@ import system from './system'
 import cusMgt from './cusMgt'
 import home from './home'
 import updModal from './updModal'
+import task from './task'
 
 export default {
   schoolBaseInfo,
@@ -55,6 +56,7 @@ export default {
   home,
   learnActivity,
   updModal,
+  task,
   formConfigP: {
     input: 'Please Enter ',
     select: 'Please Sele',

+ 2 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/learnActivity.js

@@ -12,7 +12,8 @@ export default{
         finish:'已结束',
         endTime:'结束时间:',
         stop:'立即结束',
-        evType:'测试类型:',
+        evType:'评测类型:',
+        evMode:'评测模式:',
         stuCount:'施测人数:',
         nodata:'暂无评测',
         tab1:'评测数据',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/schoolBaseInfo.js

@@ -82,7 +82,7 @@ export default {
   classroomAttr: '教室属性',
   classroomCode: '教室编码',
   classroomName: '教室名称',
-  headmaster: '班主任',
+  headmaster: '班主任',
   setPeriod: '选择教室学段',
   setGrade: '设置教室年级',
   setHiteachCode: 'HiTeach软件序号',

+ 16 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/task.js

@@ -0,0 +1,16 @@
+export default {
+    markTask:'閱卷任務',
+    markStatus1:'進行中',    
+    markStatus2:'已完成',    
+    markStatus3:'已結束',    
+    markMode1:'按題閱卷',    
+    markMode2:'按人閱卷',    
+    mLabel1:'人數',    
+    mLabel2:'已閱',    
+    mLabel3:'未閱',    
+    mLabel4:'進行中',    
+    mLabel5:'題量',    
+    mLabel6:'人數',    
+    markProg:'批閱進度',    
+    mark:'批閱',
+}

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/courseManage.js

@@ -49,7 +49,7 @@ export default {
     classroom: {
         classroomList: '课程名单',
         studentCount: '学生人数:',
-        headmaster: '班主任',
+        headmaster: '班主任',
         classroomManage: '班级管理',
         baseSetting: '基础设置',
         studentList: '学生名单',

+ 7 - 5
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/cusMgt.js

@@ -111,7 +111,9 @@ export default {
     resetPwContent3:'确认批量重置',
     resetPwContent4:'个学生的密码',
     resetPwOk:'重置成功',
-    noMgtClass:'暂无您管理的班级',
+    noMgtClass1:'暂未加入学校',
+    noMgtClass2:'学校暂未设置您为班主任',
+    toJoin:'前往申请加入学校',
     groupNameHolder:'请设置组名',
     edtiGroupName:'修改组名',
     addGroup:'新增组别',
@@ -143,8 +145,8 @@ export default {
     saveLabel:'保存变更',
     addStuList:'添加名单',
     removeList:'移除名单',
-    classLabel:'教室:',
-    nameLabel:'名单:',
+    addrLabel:'上课教室:',
+    nameLabel:'班级名单:',
     defaultList:'默认名单',
     noSet:'未设置',
     defaultTips:'默认名单为教室对应的名单,否则需要指定自定义名单。',
@@ -154,7 +156,7 @@ export default {
     notime1:'暂未设置时段,请先',
     notime2:'设置时段',
     notime3:'再安排上课时段。',
-    listType1:'校本名单',
+    listType1:'班级名单',
     listType2:'自定义名单',
     confirmAdd:'确认添加',
     cancelAdd:'取消添加',
@@ -169,7 +171,7 @@ export default {
     code:'编码',
     className:'班级',
     nameWarning:'请输入名单名称',
-    addOk:'添加成功',
+    updOk:'更新成功',
     setWarning1:'暂无教师信息,无法完成课程时段设置',
     setWarning2:'暂无教室信息,无法完成课程时段设置',
     defaultTitle:'默认名单',

+ 9 - 2
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/evaluation.js

@@ -177,7 +177,8 @@ export default {
 		orderByType:'题型排列',
 		paperDetails:'试卷详情',
 		paperAnalysis:'试卷分析',
-		setPaperScore:'设置试卷总分'
+		setPaperScore:'设置试卷总分',
+		goAnswerSheet:'预览答题卡'
 	},
 	importFile:{
 		uploadSuc:'文件上传解析成功!',
@@ -270,5 +271,11 @@ export default {
 	addTip2:'最多只有10个选项!',
 	addTip3:'至少保留一个正确答案!',
 	addTip4:'至少保留两个选项!',
-	addTip5:'没有查询到题目!'
+	addTip5:'没有查询到题目!',
+	checkList:{
+		title:'试卷双向细目分析表',
+		tip:'提示: a(b) a-配分,b-数量',
+		sum:'合计',
+		none:'无'
+	}
 }

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

@@ -31,6 +31,7 @@ import updModal from './updModal'
 import http from './http'
 import utils from './utils'
 import knowledge from './knowledge'
+import task from './task'
 export default {
   schoolBaseInfo,
   classMgmt,
@@ -65,6 +66,7 @@ export default {
   http,
   utils,
   knowledge,
+  task,
   test: '测试',
   formConfigP: {
     input: '请输入',

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

@@ -222,9 +222,9 @@ export default{
         class:'按班分配',
         scoreDiff:'分差',
         markRole:'阅卷角色',
-        errRole:'异常处理',
-        arb:'仲裁教师',
-        markRole:'阅卷教师',
+        errRole:'异常处理',
+        arb:'仲裁教师',
+        markRole:'阅卷教师',
         noTea:'暂无教师',
         remove:'移除',
         addTea:'添加阅卷老师',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/schoolBaseInfo.js

@@ -104,7 +104,7 @@ export default {
   classroomAttr: '教室属性',
   classroomCode: '教室编码',
   classroomName: '教室名称',
-  headmaster: '班主任',
+  headmaster: '班主任',
   setPeriod: '选择教室学段',
   setGrade: '设置教室年级',
   setHiteachCode: 'HiTeach软件序号',

+ 9 - 4
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/stuAccount.js

@@ -20,7 +20,7 @@ export default {
   searchHolder: '输入关键字或账号资讯搜索',
   periodHolder: '选择学制',
   gradeHolder: '选择年级',
-  classroomHolder: '选择教室',
+  classroomHolder: '选择班级',
   tips1: '请选择需要修改的学生!',
   tips2Title: '删除学生',
   tips2Content1: '确定删除',
@@ -29,8 +29,8 @@ export default {
   tips2Content4: '个学生',
   tips3: '请选择需要删除的学生!',
   sltPdFirst:'请先选择学段',
-  sltGdFirst:'请先选择学段',
-  noClass:'此年级暂无教室',
+  sltGdFirst:'请先选择年级',
+  noClass:'此年级暂无班级',
   noRelClass:'未关联班级',
   resetPw:'重置密码',
   semYear:'學年度:',
@@ -89,5 +89,10 @@ export default {
   authCount: '学校总授权数',
   alreadyUse: '今日已取用授权数',
   mayUse: '可使用授权数',
-  authNum: '各学制授权使用状态'
+  authNum: '各学制授权使用状态',
+
+  //StudentList.vue
+  filterLabel:'筛选条件:',
+  noSchool:'暂未归属学校',
+  isBottom:'已经到底了'
 }

+ 16 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/task.js

@@ -0,0 +1,16 @@
+export default {
+    markTask:'阅卷任务',
+    markStatus1:'进行中',
+    markStatus2:'已完成',
+    markStatus3:'已结束',
+    markMode1:'按题阅卷',
+    markMode2:'按人阅卷',
+    mLabel1:'人数',
+    mLabel2:'已阅',
+    mLabel3:'未阅',
+    mLabel4:'进行中',
+    mLabel5:'题量',
+    mLabel6:'人数',
+    markProg:'批阅进度',
+    mark:'批阅',
+}

+ 8 - 6
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/cusMgt.js

@@ -111,7 +111,9 @@ export default {
     resetPwContent3:'確認批量重置',
     resetPwContent4:'個學生的密碼',
     resetPwOk:'重置成功',
-    noMgtClass: '暫無您管理的班級',
+    noMgtClass1: '暫未加入學校',
+    noMgtClass2: '學校暫未設置您為班主任',
+    toJoin:'前往申請加入學校',
     groupNameHolder: '請設定組名',
     edtiGroupName: '修改組名',
     addGroup: '新增組別',
@@ -143,9 +145,9 @@ export default {
     saveLabel: '儲存變更',
     addStuList: '新增名單',
     removeList: '移除名單',
-    classLabel: '教室:',
-    nameLabel: '名單:',
-    defaultList: '預設名單',
+    addrLabel:'上課教室:',
+    nameLabel:'班級名單:',
+    defaultList: '默認名單',
     noSet: '未設定',
     defaultTips: '預設名單為教室對應的名單,否則需要指定自定義名單。',
     noStu: '暫無學生',
@@ -154,7 +156,7 @@ export default {
     notime1: '暫未設定時段,請先',
     notime2: '設定時段',
     notime3: '再安排上課時段。',
-    listType1: '學校名單',
+    listType1: '班級名單',
     listType2: '自定義名單',
     confirmAdd: '確認新增',
     cancelAdd: '取消新增',
@@ -169,7 +171,7 @@ export default {
     code: '編碼',
     className: '班級',
     nameWarning: '請輸入名單名稱',
-    addOk: '新增成功',
+    updOk: '更新成功',
     setWarning1: '暫無教師資訊,無法完成課程時段設定',
     setWarning2: '暫無教室資訊,無法完成課程時段設定',
     defaultTitle: '預設名單',

+ 19 - 11
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/evaluation.js

@@ -50,10 +50,11 @@ export default {
 	explain: '解析',
 	noExplain: '暫無解析',
 	knowledgePoints: '知識點',
+	field: '認知層次',
 	noPoints: '暫未綁定知識點',
 	updateTime: '更新時間',
-	remove:'移除',
-	choose:'選題',
+	remove: '移除',
+	choose: '選題',
 	isTrue: '正確',
 	isFalse: '錯誤',
 	deleteItem: '刪除',
@@ -78,7 +79,7 @@ export default {
 		field: '關聯認知層次',
 		knowledge: '關聯知識點',
 		choosePoint: '選擇知識點',
-		modify:'修改',
+		modify: '修改',
 		type: '選擇題型',
 		stem: '題幹',
 		option: '選項',
@@ -176,7 +177,8 @@ export default {
 		orderByType: '題型排列',
 		paperDetails: '試卷詳情',
 		paperAnalysis: '試卷分析',
-		setPaperScore: '設定試卷總分'
+		setPaperScore: '設定試卷總分',
+		goAnswerSheet:'預覽答題卡'
 	},
 	importFile: {
 		uploadSuc: '試卷檔案上傳解析成功!',
@@ -213,7 +215,7 @@ export default {
 		tip1:'第',
 		tip2:'題綜合題的配分',
 		tip3:'不足',
-		tip4:'出',
+		tip4:'出',
 		tip5:'請檢查後重試!'
 	},
 	points: {
@@ -264,10 +266,16 @@ export default {
 	formatErrorTip:'請輸入正確格式的網址!',
 	noCompleteTip:'請填寫完整',
 	},
-	completeCount:'填空數量',
-	addTip1:'當前配分超過試卷總分,請重新分配!',
-	addTip2:'最多只有10個選項!',
-	addTip3:'至少保留一個正確答案!',
-	addTip4:'至少保留兩個選項!',
-	addTip5:'沒有査詢到題目!'
+	completeCount: '填空數量',
+	addTip1: '當前配分超過試卷總分,請重新分配!',
+	addTip2: '最多只有10個選項!',
+	addTip3: '至少保留一個正確答案!',
+	addTip4: '至少保留兩個選項!',
+	addTip5: '沒有査詢到題目!',
+	checkList: {
+		title: '試卷雙向細目分析錶',
+		tip: '提示:a(b)a-配分,b-數量',
+		sum: '合計',
+		none: '無'
+	}
 }

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

@@ -31,6 +31,7 @@ import updModal from './updModal'
 import http from './http'
 import utils from './utils'
 import knowledge from './knowledge'
+import task from './task'
 export default {
   
   schoolBaseInfo,
@@ -66,6 +67,7 @@ export default {
   http,
   utils,
   knowledge,
+  task,
   test: '測試',
   formConfigP: {
     input: '請輸入',

+ 2 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/learnActivity.js

@@ -12,7 +12,8 @@ export default {
         finish: '已結束',
         endTime: '結束時間:',
         stop: '立即結束',
-        evType: '評量類型:',
+        evType: '評測類型:',
+        evMode:'評測模式:',
         stuCount: '施測人數:',
         nodata: '暫無評量',
         tab1: '評量數據',

+ 8 - 3
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/stuAccount.js

@@ -20,7 +20,7 @@ export default {
   searchHolder: '輸入關鍵字或帳號資訊搜索',
   periodHolder: '選擇學制',
   gradeHolder: '選擇年級',
-  classroomHolder: '選擇教室',
+  classroomHolder: '選擇班級',
   tips1: '請選擇需要修改的學生!',
   tips2Title: '刪除學生',
   tips2Content1: '確定刪除',
@@ -89,5 +89,10 @@ export default {
   authCount: '學校總授權數',
   alreadyUse: '今日已取用授權數',
   mayUse: '可使用授權數',
-  authNum: '各學制授權使用狀態'
-}
+  authNum: '各學制授權使用狀態',
+  
+  //StudentList.vue
+  filterLabel:'篩選條件:',
+  noSchool:'暫未歸屬學校',
+  isBottom:'已經到底了'
+}

+ 16 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/task.js

@@ -0,0 +1,16 @@
+export default {
+    markTask:'閱卷任務',
+    markStatus1:'進行中',    
+    markStatus2:'已完成',    
+    markStatus3:'已結束',    
+    markMode1:'按題閱卷',    
+    markMode2:'按人閱卷',    
+    mLabel1:'人數',    
+    mLabel2:'已閱',    
+    mLabel3:'未閱',    
+    mLabel4:'進行中',    
+    mLabel5:'題量',    
+    mLabel6:'人數',    
+    markProg:'批閱進度',    
+    mark:'批閱',
+}

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

@@ -311,6 +311,14 @@ export const routes = [
 					activeName: 'personalBank'
 				},
 			},
+			{
+				path: 'answerSheet',
+				name: 'answerSheet',
+				component: resolve => require(['@/view/answersheet/index.vue'], resolve),
+				meta: {
+					activeName: 'schoolBank'
+				},
+			},
 			{
 				path: 'testPaper',
 				name: 'testPaper',
@@ -376,14 +384,14 @@ export const routes = [
 			component: resolve => require(['@/view/task/index.vue'], resolve),
 			meta: {
 				activeName: 'taskList',
-				isKeep: true
+				// isKeep: true
 			}
 		},
 		//自定义名单管理页面
 		{
 			path: 'MgtStuList',
 			name: 'MgtStuList',
-			component: resolve => require(['@/view/newcourse/MgtStuList.vue'], resolve),
+			component: resolve => require(['@/view/student-account/MgtStuList.vue'], resolve),
 			meta: {
 				activeName: 'myCourse'
 			}

+ 17 - 5
TEAMModelOS/ClientApp/src/store/module/answerSheet.js

@@ -28,11 +28,11 @@ export default {
 		pages: 1,
 		isNewPage: false,
 		needFixArr: [26],
+		paperItem:{
+			name:''
+		},
 		editorInfos: {
-			subjectiveEditor1: {
-				height: 200,
-				content: '1111'
-			}
+			
 		},
 		sheetConfig: {
 			// 答题卡宽高
@@ -65,6 +65,9 @@ export default {
 	},
 
 	mutations: {
+		setPaper(state,val){
+			state.paperItem = val
+		},
 		addPage(state) {
 			state.pages++
 		},
@@ -80,13 +83,22 @@ export default {
 		clearFixArr(state) {
 			state.needFixArr = []
 		},
+		clearIsNewPage(state){
+			state.isNewPage = false
+			state.editorInfos = {
+				
+			}
+		},
 		setEditorHeight(state, val) {
 			if (state.editorInfos[val.id]) {
 				state.editorInfos[val.id].height = val.height
+				if(val.content){
+					state.editorInfos[val.id].content = val.content
+				}
 			} else {
 				state.editorInfos[val.id] = {
 					height: val.height,
-					content: ''
+					content: val.content
 				}
 			}
 		}

+ 14 - 0
TEAMModelOS/ClientApp/src/store/module/user.js

@@ -152,6 +152,9 @@ export default {
         },
         getClasses: state => {
             return state.schoolProfile.school_classes
+        },
+        getRooms: state => {
+            return state.schoolProfile.school_rooms
         }
 
     },
@@ -187,6 +190,7 @@ export default {
 			state.schoolProfile.school_courses = undefined // 学校排课
 			state.schoolProfile.school_syllabus = undefined // 校本课纲
 			state.schoolProfile.school_classes = undefined // 学校班级
+			state.schoolProfile.school_rooms = undefined // 学校教室
 			state.schoolProfile.periods = undefined // 學制
 			state.schoolProfile.grades = undefined // 年級
 			state.schoolProfile.school_base = undefined // 区班校基础数据
@@ -208,6 +212,7 @@ export default {
             state.schoolProfile.school_courses = data.school_courses // 学校排课
             state.schoolProfile.school_syllabus = data.school_syllabus // 校本课纲
             state.schoolProfile.school_classes = data.school_classes // 学校班级
+            state.schoolProfile.school_rooms = data.school_rooms // 学校教室
             state.schoolProfile.periods = data.fmtPeriods // 學制
             state.schoolProfile.grades = data.fmtGrades // 年級
             state.schoolProfile.school_base = data.school_base // 区班校基础数据
@@ -605,6 +610,15 @@ export default {
             data.fmtPeriods = fmtPeriods
             data.fmtGrades = fmtGrades
 
+            //处理教室默认上课班级
+            data.school_rooms.forEach(item=>{
+                let classInfo = data.school_classes.find(classItem=>{
+                    return item.id == classItem.room
+                })
+                item.classId = classInfo ? classInfo.id : undefined
+                item.className = classInfo ? classInfo.name : undefined
+            })
+            console.log(data)
             context.commit('setSchoolProfile', data)
         },
         setStudentProfile(context, data) {

+ 9 - 2
TEAMModelOS/ClientApp/src/utils/html2pdf.js

@@ -1,5 +1,6 @@
 // 导出页面为PDF格式
 import JsPDF from 'jspdf'
+import store from '@/store'
 import domtoimage from './dom_to_image';
 export default {
     install(Vue, options) {
@@ -8,7 +9,10 @@ export default {
         }
 
         Vue.prototype.getPdf = () => {
-            var title = '测试答题卡'
+			return new Promise((r,j) => {
+				
+			
+            var title = store.state.answerSheet.paperItem.name
             setTimeout(() => {
                 domtoimage.toJpeg(document.querySelector('#pdfDom'), { bgcolor: '#fff', scale: 4 })
                     .then((pageData) => {
@@ -49,11 +53,13 @@ export default {
                                 }
                             }
                             PDF.save(title + '.pdf')
+							r(200)
                         }
 
                     })
                     .catch(function (error) {
                         console.error('oops, something went wrong!', error);
+						j(error)
                     });
 
                 // html2canvas( document.querySelector('#pdfDom'), {
@@ -96,6 +102,7 @@ export default {
                 //     pdf.save(title + '.pdf')
                 // })
             }, 1000)
-        }
+			})
+		}
     }
 }

+ 4 - 2
TEAMModelOS/ClientApp/src/utils/sheetConfig.js

@@ -11,8 +11,9 @@ const SVG_BORDER_PROP = {
     x:55,
     y:65,
     width:PAPER_W - 55 * 2,
-    height:925
+    height:910
 }
+const SVG_BORDER_MB = PAPER_H - SVG_BORDER_PROP.y - SVG_BORDER_PROP.height
 const CONTENT_MT = 70; // 内容与定位框间隔
 const CONTENT_ML = 50; // 内容与定位框间隔
 
@@ -20,7 +21,7 @@ const CONTENT_START_X = ANCHORPROP.width + ANCHORPROP.gapX + CONTENT_ML; // 内
 const CONTENT_START_Y = ANCHORPROP.height + ANCHORPROP.gapY + CONTENT_MT; // 内容开始y坐标
 
 const INFO_W = PAPER_W - CONTENT_START_X * 2; // 信息框内容宽度
-const INFO_H = 200; // 信息框内容高度
+const INFO_H = 220; // 信息框内容高度
 const INFO_ITEM_GAP = 20; // 个人信息填写区域ITEM上下间隔
 const INFO_ITEM_MARGIN = 40; //个人信息填写区域坐标间隔
 const ID_LENGTH = 8; // 准考证号位数
@@ -41,6 +42,7 @@ export {
     PAPER_H,
     BLOCK_H,
     ANCHORPROP,
+	SVG_BORDER_MB,
     CONTENT_MT,
     CONTENT_ML,
     CONTENT_START_X,

文件差異過大導致無法顯示
+ 719 - 398
TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue


+ 0 - 103
TEAMModelOS/ClientApp/src/view/answersheet/BaseObjective.vue

@@ -1,103 +0,0 @@
-<template>
-  <div class="baseSingle">
-    <svg :id="ids"></svg>
-  </div>
-</template>
- 
-<script>
-import Snap from "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js";
-import {
-  PAPER_W,
-  PAPER_H,
-  CONTENT_MT,
-  CONTENT_ML,
-  ANCHORPROP,
-  CONTENT_START_X,
-  CONTENT_START_Y,
-  INFO_W,
-  INFO_H,
-  INFO_ITEM_GAP,
-  INFO_ITEM_MARGIN,
-  ID_LENGTH,
-  INFO_LEFT_X,
-  INFO_LEFT_W,
-  ID_TITLE_H,
-  ID_TITLE_Y,
-  NUMBER_CELL_H,
-  NUMBER_ITEM_W,
-  NUMBER_ITEM_H,
-  NUMBER_ITEM_MT,
-  NUMBER_ITEM_ML,
-} from "@/utils/sheetConfig.js";
-export default {
-  props: {
-    exerciseItem: {
-      type: Object,
-      default: () => {
-        return {};
-      },
-    },
-    ids: {
-      type: String,
-      default: "",
-    },
-    exerciseIndex: {
-      type: Number,
-      default: 0,
-    },
-  },
-  components: {},
-  data() {
-    return {
-      isShowInfoEdit: false,
-      editModal: false,
-      infoLeftBox: null,
-      idNumberBox: null,
-      snap: null,
-    };
-  },
-  created() {},
-  methods: {
-    doRender(exerciseItem) {
-      //   this.snap = Snap("#" + this.ids);
-      var snap = this.snap;
-      let optionGap = 30;
-      snap
-        .text(0, 20, this.exerciseIndex)
-        .attr({ fontFamily: 'Times New Roman' });
-      for (let index = 0; index < exerciseItem.option.length; index++) {
-        let code = String.fromCharCode(64 + parseInt(index + 1)).toLowerCase();
-        let img = require("../../icons/answersheet/" + code + ".svg");
-        let c3 = snap
-          .image(img, 20 + optionGap * index, 10, NUMBER_ITEM_W, NUMBER_ITEM_H)
-          .attr({
-            crossorigin: "anonymous",
-          });
-      }
-    },
-  },
-  mounted: function () {
-    this.snap = Snap("#" + this.ids);
-    var snap = this.snap;
-  },
-  watch: {
-    exerciseItem: {
-      handler(n) {
-        if (Object.keys(n).length) {
-          this.$nextTick(() => {
-            this.doRender(n);
-          });
-        }
-      },
-      immediate: true,
-    },
-  },
-};
-</script>
-<style scoped>
-.baseSingle svg {
-  width: 100%;
-  height: 20px;
-}
-</style>
- 

+ 190 - 140
TEAMModelOS/ClientApp/src/view/answersheet/BaseSvgBg.vue

@@ -1,151 +1,201 @@
 <template>
-  <div style="width: 100%; height: 100%; overflow: hidden; margin-top: 0;">
-    <svg :id="ids" width="100%" height="100%" style="background: #fff"></svg>
-  </div>
+	<div
+		style="position:relative; width: 100%; height: 100%; overflow: hidden; margin-top: 0;border-bottom: 1px solid #ddd;">
+		<div v-show="ids === 'svg0'" class="sheet-paper-title">
+			<BaseTitleEditor :ids="'sheetName' + ids" :content="sheetPaperName"></BaseTitleEditor>
+		</div>
+		<svg :id="ids" width="100%" height="100%" style="background: #fff"></svg>
+	</div>
 </template>
 
 <script>
-import Snap from "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js";
-import { PAPER_W, PAPER_H, ANCHORPROP, SVG_BORDER_PROP } from "@/utils/sheetConfig.js";
-export default {
-  props: {
-    ids: {
-      type: String,
-      default: "",
-    },
-    total: {
-      type: Number,
-      default: 0,
-    },
-  },
-  datas() {
-    return {
-      pageCount: 1,
-      snap: null,
-      pageBox: null,
-      anchorBox: null,
-    };
-  },
-  created() {},
-  methods: {
-    doRenderPageAnchor(snap) {
-      this.anchorBox.remove(); // 先清除之前的绘制内容
-      this.anchorBox = this.snap.paper.g();
-      let curPage = Number(this.ids.replace("svg", ""));
-      // 将当前页码转换成二进制进行页码锚点绘制
-      let i = (curPage).toString(2)
-      let radixArr = i.length === 1 ? '00' + i : i.length === 2 ? '0' + i : i
-      // 绘制锚点
-      for (let index = 0; index < 3; index++) {
-        this.anchorBox.add(
-          snap
-            .rect(
-              ANCHORPROP.gapX + 55 + 30 * index,
-              PAPER_H - ANCHORPROP.height - ANCHORPROP.gapY,
-              20,
-              10
-            )
-            .attr({ fill: radixArr.split('')[index]  === '1' ? '#000' : "none", stroke: "#000", strokeWidth: 1 })
-        );
-      }
-    },
+	import BaseTitleEditor from './BaseTitleEditor'
+	import Snap from "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js";
+	import {
+		PAPER_W,
+		PAPER_H,
+		ANCHORPROP,
+		SVG_BORDER_PROP
+	} from "@/utils/sheetConfig.js";
+	export default {
+		props: {
+			ids: {
+				type: String,
+				default: "",
+			},
+			total: {
+				type: Number,
+				default: 0,
+			},
+		},
+		datas() {
+			return {
+				pageCount: 1,
+				snap: null,
+				pageBox: null,
+				anchorBox: null,
+				sheetPaperName:''
+			};
+		},
+		components: {
+			BaseTitleEditor
+		},
+		created() {},
+		methods: {
+			doRenderPageAnchor(snap) {
+				this.anchorBox.remove(); // 先清除之前的绘制内容
+				this.anchorBox = this.snap.paper.g();
+				let curPage = Number(this.ids.replace("svg", ""));
+				// 将当前页码转换成二进制进行页码锚点绘制
+				let i = (curPage + 1).toString(2)
+				let radixArr = i.length === 1 ? '00' + i : i.length === 2 ? '0' + i : i
+				// 绘制锚点
+				for (let index = 0; index < 3; index++) {
+					this.anchorBox.add(
+						snap
+						.rect(
+							ANCHORPROP.gapX + 65 + 30 * index,
+							PAPER_H - ANCHORPROP.height - ANCHORPROP.gapY,
+							20,
+							10
+						)
+						.attr({
+							fill: radixArr.split('')[index] === '1' ? '#000' : "none",
+							stroke: "#000",
+							strokeWidth: 1
+						})
+					);
+				}
+			},
 
-    doRenderPage(snap) {
-      this.pageBox.remove(); // 先清除之前的绘制内容
-      this.pageBox = this.snap.paper.g();
-      // 页码
-      var page = snap
-        .text(
-          (PAPER_W - 100) / 2,
-          PAPER_H - 50,
-          `第 ${Number(this.ids.replace("svg", "")) + 1} 页  /  共 ${
+			doRenderPage(snap) {
+				this.pageBox.remove(); // 先清除之前的绘制内容
+				this.pageBox = this.snap.paper.g();
+				// 页码
+				var page = snap
+					.text(
+						(PAPER_W - 100) / 2,
+						PAPER_H - 40,
+						`第 ${Number(this.ids.replace("svg", "")) + 1} 页  /  共 ${
             this.total
           } 页`
-        )
-        .attr({
-          fontSize: 12,
-          fontFamily: "Times New Roman",
-        });
-      this.pageBox.add(page);
-    },
-  },
-  mounted() {
-    var snap = Snap("#" + this.ids);
-    this.pageBox = snap.paper.g();
-    this.anchorBox = snap.paper.g();
-    let anchorProp = ANCHORPROP;
-    // snap
-    //   .rect(SVG_BORDER_PROP.x, SVG_BORDER_PROP.y, SVG_BORDER_PROP.width, SVG_BORDER_PROP.height)
-    //   .attr({ fill: "none", stroke: "#000", strokeWidth: 1 });
+					)
+					.attr({
+						fontSize: 12,
+						fontFamily: "Times New Roman",
+					});
+				this.pageBox.add(page);
+			},
+		},
+		mounted() {
+			var snap = Snap("#" + this.ids);
+			this.pageBox = snap.paper.g();
+			this.anchorBox = snap.paper.g();
+			let anchorProp = ANCHORPROP;
+			// snap
+			//   .rect(SVG_BORDER_PROP.x, SVG_BORDER_PROP.y, SVG_BORDER_PROP.width, SVG_BORDER_PROP.height)
+			//   .attr({ fill: "none", stroke: "#000", strokeWidth: 1 });
 
-    // 画四个锚点
-    snap.rect(
-      anchorProp.gapX,
-      anchorProp.gapY,
-      anchorProp.width,
-      anchorProp.height
-    );
-    snap.rect(
-      anchorProp.gapX - 5,
-      anchorProp.gapY - 5,
-      anchorProp.width + 10,
-      anchorProp.height + 10
-    ).attr({ fill: "none", stroke: "#000", strokeWidth: 4 });
-    snap.rect(
-      anchorProp.gapX,
-      PAPER_H - anchorProp.height - anchorProp.gapY,
-      anchorProp.width,
-      anchorProp.height
-    );
-    snap.rect(
-      anchorProp.gapX - 5,
-      PAPER_H - anchorProp.height - anchorProp.gapY - 5,
-      anchorProp.width + 10,
-      anchorProp.height + 10
-    ).attr({ fill: "none", stroke: "#000", strokeWidth: 4 });
-    snap.rect(
-      PAPER_W - anchorProp.width - anchorProp.gapX,
-      anchorProp.gapY,
-      anchorProp.width,
-      anchorProp.height
-    );
-    snap.rect(
-      PAPER_W - anchorProp.width - anchorProp.gapX - 5,
-      anchorProp.gapY - 5,
-      anchorProp.width + 10,
-      anchorProp.height + 10
-    ).attr({ fill: "none", stroke: "#000", strokeWidth: 4 });
-    snap.rect(
-      PAPER_W - anchorProp.width - anchorProp.gapX,
-      PAPER_H - anchorProp.height - anchorProp.gapY,
-      anchorProp.width,
-      anchorProp.height
-    );
-    snap.rect(
-      PAPER_W - anchorProp.width - anchorProp.gapX - 5,
-      PAPER_H - anchorProp.height - anchorProp.gapY - 5,
-      anchorProp.width + 10,
-      anchorProp.height + 10
-    ).attr({ fill: "none", stroke: "#000", strokeWidth: 4 });
-    if (this.ids === "svg0") {
-      // 标题
-      snap.text((PAPER_W - 128) / 2, 95, "答题卡自动生成").attr({
-        fontSize: 18,
-        fontWeight: 800,
-      });
-    }
-    this.snap = snap;
-    this.doRenderPage(snap);
-    this.doRenderPageAnchor(snap);
+			// 画四个锚点
+			snap.rect(
+				anchorProp.gapX,
+				anchorProp.gapY,
+				anchorProp.width,
+				anchorProp.height
+			);
+			snap.rect(
+				anchorProp.gapX - 5,
+				anchorProp.gapY - 5,
+				anchorProp.width + 10,
+				anchorProp.height + 10
+			).attr({
+				fill: "none",
+				stroke: "#000",
+				strokeWidth: 4
+			});
+			snap.rect(
+				anchorProp.gapX,
+				PAPER_H - anchorProp.height - anchorProp.gapY,
+				anchorProp.width,
+				anchorProp.height
+			);
+			snap.rect(
+				anchorProp.gapX - 5,
+				PAPER_H - anchorProp.height - anchorProp.gapY - 5,
+				anchorProp.width + 10,
+				anchorProp.height + 10
+			).attr({
+				fill: "none",
+				stroke: "#000",
+				strokeWidth: 4
+			});
+			snap.rect(
+				PAPER_W - anchorProp.width - anchorProp.gapX,
+				anchorProp.gapY,
+				anchorProp.width,
+				anchorProp.height
+			);
+			snap.rect(
+				PAPER_W - anchorProp.width - anchorProp.gapX - 5,
+				anchorProp.gapY - 5,
+				anchorProp.width + 10,
+				anchorProp.height + 10
+			).attr({
+				fill: "none",
+				stroke: "#000",
+				strokeWidth: 4
+			});
+			snap.rect(
+				PAPER_W - anchorProp.width - anchorProp.gapX,
+				PAPER_H - anchorProp.height - anchorProp.gapY,
+				anchorProp.width,
+				anchorProp.height
+			);
+			snap.rect(
+				PAPER_W - anchorProp.width - anchorProp.gapX - 5,
+				PAPER_H - anchorProp.height - anchorProp.gapY - 5,
+				anchorProp.width + 10,
+				anchorProp.height + 10
+			).attr({
+				fill: "none",
+				stroke: "#000",
+				strokeWidth: 4
+			});
+			this.snap = snap;
+			this.doRenderPage(snap);
+			this.doRenderPageAnchor(snap);
 
-  },
-  watch: {
-    total(n, o) {
-      this.doRenderPage(this.snap);
-    },
-  },
-};
+		},
+		computed: {
+			paperName() {
+				return this.$store.state.answerSheet.paperItem
+			}
+		},
+		watch: {
+			paperName: {
+				handler(n, o) {
+					this.sheetPaperName = n.name
+				},
+				deep: true,
+				immediate: true
+			},
+			total(n, o) {
+				this.doRenderPage(this.snap);
+			},
+			immediate: true
+		},
+	};
 </script>
 
-<style>
-</style>
+<style lang="less">
+	.sheet-paper-title {
+		position: absolute;
+		top: 70px;
+		left: 80px;
+
+		.w-e-text {
+			font-size:18px !important;
+			text-align: center !important;
+		}
+	}
+</style>

+ 7 - 88
TEAMModelOS/ClientApp/src/view/answersheet/BaseTitleEditor.vue

@@ -60,91 +60,6 @@ export default {
     };
   },
   methods: {
-    doRenderEditor(items) {
-      switch (this.type) {
-        case "0":
-          this.doInsertComplete(items);
-          break;
-        case "1":
-          this.doInsertSubjective(items);
-          break;
-        default:
-          break;
-      }
-    },
-
-    doInsertComplete(items) {
-      // console.log(this.items);
-      let underLineSpaceCount = 45;
-      items.forEach((item, index) => {
-        let addStr = this.items.indexOf(item) + 1 + "";
-        for (let blankIndex = 0; blankIndex < item.blankCount; blankIndex++) {
-          addStr =
-            addStr +
-            '<span class="underline">' +
-            new Array(underLineSpaceCount).fill("&nbsp;").join("") +
-            "</span>";
-        }
-        this.$nextTick(() => {
-          this.myEditor.txt.append(
-            `<span class='complete-item'>${addStr}</span>`
-          );
-        });
-      });
-    },
-
-    // 渲染问答题
-    doInsertSubjective(items) {
-      let subjectiveItem = items[0];
-      let itemOrder = this.allItems.indexOf(subjectiveItem) + 1
-      let addStr = itemOrder + "(" + (subjectiveItem.score+ '分)'); // 渲染题号
-      let defaultBrCounts = 1; // 问答题默认回答区域空行数量
-      let brHtml = new Array(defaultBrCounts).fill("<p><br></p>").join("");
-      this.$nextTick(() => {
-        setTimeout(() => {
-          let isNewPage = this.$store.state.answerSheet.isNewPage
-          let lastBottomGap = 20
-          let Y = this.myEditor.$textElem.elems[0].getBoundingClientRect().top - 20
-          let paperH = PAPER_H
-          let curEditorY = Y > paperH ? Y % paperH : Y ;
-          let curEditorH = this.myEditor.$textElem.elems[0].clientHeight; // 200px
-          console.log('==========================');
-          console.log(itemOrder,this.myEditor.$textElem.elems[0]);
-          console.log(itemOrder,this.myEditor.$textElem.elems[0].getBoundingClientRect());
-          console.log(itemOrder,Y);
-          console.log(itemOrder,curEditorY);
-          console.log(itemOrder,curEditorH);
-          console.log(itemOrder,isNewPage);
-          console.log(itemOrder,curEditorY - SVG_BORDER_PROP.y + curEditorH + lastBottomGap);
-          if (curEditorY - SVG_BORDER_PROP.y + curEditorH + lastBottomGap > SVG_BORDER_PROP.height) {
-            if (!isNewPage) {
-              console.log(itemOrder + '需要处理高度')
-              this.myEditor.config.height = SVG_BORDER_PROP.height - (curEditorY - SVG_BORDER_PROP.y) - lastBottomGap ;
-              // this.myEditor.config.height = 1060.7 - curEditorY - 100 ;
-              this.$store.commit('changeNewPage',true)
-              if(itemOrder  !== this.allItems.length){
-                this.$store.commit('addPage')
-              }
-            } else {
-              // document.getElementById(this.ids).insertBefore('<p>111111111111</p>')
-              console.log('新的开始')
-              document.getElementById(this.ids).style.marginTop =  ((PAPER_H - SVG_BORDER_PROP.height - SVG_BORDER_PROP.y) + SVG_BORDER_PROP.y + 40) + "px";
-              this.$store.commit('changeNewPage',false)
-            }
-          } else {
-            this.$store.commit('changeNewPage',false)
-          }
-          this.$root.$children[0].spinShow = false
-
-          // this.myEditor.txt.append('curEditorY:' + curEditorY + 'px');
-          // this.myEditor.txt.append('height:' + this.myEditor.config.height + 'px');
-
-        }, 30);
-
-        this.myEditor.txt.append(addStr + brHtml);
-      });
-    },
-
     define({ editor, prop, change, validate }) {
       if (typeof validate != "function") {
         validate = function (value) {
@@ -174,6 +89,7 @@ export default {
 
     // 拖拽改变编辑器的高度
     dragReSize(editor) {
+		let that = this
       // 将一个 HTML 字符串转换为由 wangEditor.$(一个类 jQuery 的东东) 包裹的实例对象
       const reel = E.$(
         '<div style="position: absolute;bottom: 0;left: 0;width: 100%;background-color: none;cursor: n-resize;border-top: 3px solid transparent;"></div>'
@@ -189,6 +105,7 @@ export default {
         function mouseup() {
           document.removeEventListener("mousemove", mousemove);
           document.removeEventListener("mouseup", mouseup);
+		  that.$EventBus.$emit('doRefresh')
         }
         // 将鼠标事件绑定到 document 上
         document.addEventListener("mousemove", mousemove);
@@ -211,12 +128,12 @@ export default {
 
     doRenderContent(content){
       this.myEditor.txt.clear()
-      this.myEditor.txt.append(content);
+      this.myEditor.txt.html(content);
     }
   },
   mounted() {
     const editor = new E("#" + this.ids);
-    editor.config.height = this.type === "0" ? "" : 40;
+    editor.config.height = this.type === "0" ? "" : 30;
 
     this.define({
       editor: editor,
@@ -278,6 +195,7 @@ export default {
         })
       },
       immediate: true,
+	  deep:true
     },
   },
 };
@@ -287,7 +205,7 @@ export default {
 .sheet-title-Editor {
   position: relative;
   width: 590px;
-  margin: 2px auto;
+  margin: 10px auto 0 auto;
   border: 0 solid #000 !important;
 }
 
@@ -309,6 +227,7 @@ export default {
 .sheet-title-Editor .w-e-text {
   font-size: 12px;
   padding: 0;
+  overflow: hidden !important;
 }
 
 .sheet-title-Editor .w-e-toolbar .w-e-menu {

+ 1 - 1
TEAMModelOS/ClientApp/src/view/answersheet/SheetComplete.vue

@@ -6,7 +6,7 @@
     @mouseover="isShowInfoEdit = true"
   >
     <!-- <p style="margin-left: 100px; font-weight: bold; color: #000">二、填空题(共{{ completeItems.length }}题,总计 {{ totalScore }} 分)</p> -->
-    <BaseTitleEditor ids="completeTitleEditor" :content="'二、填空题(共' + completeItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor>
+    <!-- <BaseTitleEditor ids="completeTitleEditor" :content="'二、填空题(共' + completeItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor> -->
     <BaseEditor ids="completeEditor" :items="items" type="0"></BaseEditor>
   </div>
 </template>

+ 50 - 38
TEAMModelOS/ClientApp/src/view/answersheet/SheetObjective.vue

@@ -6,7 +6,7 @@
     @mouseover="isShowInfoEdit = true"
   >
     <!-- <p style="margin-left: 100px; font-weight: bold; color: #000">一、选择题</p> -->
-    <BaseTitleEditor ids="objectiveTitleEditor" :content="'一、选择题(共' + objectiveItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor>
+    <!-- <BaseTitleEditor ids="objectiveTitleEditor" :content="'一、选择题(共' + objectiveItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor> -->
     <svg
       id="sheetObjectiveSvg"
       width="100%"
@@ -29,7 +29,6 @@
 <script>
 import BaseTitleEditor from './BaseTitleEditor'
 import Snap from "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js";
-import BaseObjective from "./BaseObjective.vue";
 import {
   PAPER_W,
   PAPER_H,
@@ -63,7 +62,7 @@ export default {
       },
     },
   },
-  components: { BaseObjective,BaseTitleEditor },
+  components: { BaseTitleEditor },
   data() {
     return {
       isShowInfoEdit: false,
@@ -87,27 +86,28 @@ export default {
     onReRender() {
       this.leftItems = JSON.parse(JSON.stringify(this.objectiveItems))
       this.doRenderItems(this.objectiveItems, this.number);
+	  this.$EventBus.$emit('doRefresh')
     },
 
     // 渲染客观题区域边框
     doRenderBorder(items, number, blockCount) {
-      console.log(blockCount);
       let snap = this.snap;
       let objectiveHeight = 40 + this.blockHeight * blockCount;
-      console.log(this.blockHeight);
-      this.svgHeight = objectiveHeight + 40;
+      this.svgHeight = this.anchorRectY + 40;
       // 信息框
       let infoBox = snap
         .rect(CONTENT_START_X, 2, INFO_W, this.anchorRectY + 20)
-        .attr({ fill: "rgba(0,0,0,0)", stroke: "#000", strokeWidth: 1 });
+        .attr({ fill: "rgba(0,0,0,0)", stroke: "#000" });
       this.objectiveGroup.add(infoBox);
     },
 
     // 渲染客观题目
     doRenderItems(items, number) {
       this.blockHeight = 26 * number
-      this.objectiveGroup.remove(); // 先清除之前的绘制内容
-      this.objectiveGroup = this.snap.paper.g();
+      this.objectiveGroup && this.objectiveGroup.remove(); // 先清除之前的绘制内容
+	  if(this.snap) {
+		 this.objectiveGroup = this.snap.paper.g();
+	  }
       let snap = this.snap;
       let MARGIN_LEFT = 25;
       let GAP = 22;
@@ -161,34 +161,37 @@ export default {
             fontFamily: "Times New Roman",
           });
         this.objectiveGroup.add(itemOrder);
-        item.option.forEach((option, optionIndex) => {
-          let code = String.fromCharCode(
-            64 + parseInt(optionIndex + 1)
-          ).toLowerCase();
-          // 渲染选项图片
-          // let img = require("../../icons/answersheet/" + code + ".svg");
-          let img = require('@/icons/answersheet/0.svg');
-          let c3 = snap.image(
-            img,
-            optionX + NUMBER_ITEM_ML + optionGap * optionIndex,
-            optionY - 10,
-            NUMBER_ITEM_W,
-            NUMBER_ITEM_H
-          );
-          this.objectiveGroup.add(c3);
-          
-        });
+		
+			item.option.forEach((option, optionIndex) => {
+			  let code = String.fromCharCode(
+			    64 + parseInt(optionIndex + 1)
+			  ).toLowerCase();
+			  // 渲染选项图片
+			  // let img = require("../../icons/answersheet/" + code + ".svg");
+			  let img = require('@/icons/answersheet/' + code + '.svg');
+			  let trueSvg = require('@/icons/answersheet/t.svg');
+			  let falseSvg = require('@/icons/answersheet/f.svg');
+			  let c3 = snap.image(
+			    item.type !== 'judge' ? img : optionIndex === 0 ? trueSvg : falseSvg,
+			    optionX + NUMBER_ITEM_ML + optionGap * optionIndex,
+			    optionY - 10,
+			    NUMBER_ITEM_W,
+			    NUMBER_ITEM_H
+			  );
+			  this.objectiveGroup.add(c3);
+			});
+        
       });
 
       let diff = this.leftItems.length - this.number
       let refHeight = this.blockHeight * (blockList.length - 1)
       let objectiveHeight = diff > 0 ? refHeight : refHeight - 26 * diff * -1
       this.anchorRectY = startY + GAP * number + objectiveHeight
-      for (let index = 0; index < 25; index++) {
+      for (let index = 0; index < 28; index++) {
         // 渲染选项框横向定位锚点
           this.objectiveGroup.add(
             snap.rect(
-              CONTENT_START_X + MARGIN_LEFT + NUMBER_ITEM_ML + optionGap * index,
+              CONTENT_START_X + MARGIN_LEFT + NUMBER_ITEM_ML + optionGap * (index - 1),
               startY + GAP * number + objectiveHeight,
               NUMBER_ITEM_W,
               NUMBER_ITEM_H
@@ -196,11 +199,15 @@ export default {
           );
       }
       // 添加纵向定位锚点
-      for (let index = 0; index < number; index++) {
-        this.objectiveGroup.add(
-          snap.rect(20, startY + GAP * index - 10, NUMBER_ITEM_W, NUMBER_ITEM_H)
-        );
-      }
+	  let anchorCount = this.objectiveItems.length > number ? number : this.objectiveItems.length
+	  this.blockList.forEach((blockItem,blockIndex) => {
+		  for (let index = 0; index < anchorCount; index++) {
+		    this.objectiveGroup.add(
+		      snap.rect(20, startY + GAP * index - 10 + (this.blockHeight * blockIndex), NUMBER_ITEM_W, NUMBER_ITEM_H)
+		    );
+		  }
+	  })
+      
 
       // 渲染包围框
       this.doRenderBorder(items, number, blockList.length);
@@ -230,7 +237,8 @@ export default {
       // 第几列就取前几列的宽度总和 作为x值
       return columnWidthArr.slice(0, curColumn + 1).length ? columnWidthArr.slice(0, curColumn + 1).reduce((a, b) => a + b) : 0;
     },
-
+	
+	// 判断是否需要换行
     needNewLine(index, number, items) {
       let columnCount = Math.ceil(items.length / number); // 总共多少列
       let curColumn = parseInt(index / number); // 当前index在第几列
@@ -287,11 +295,15 @@ export default {
           this.objectiveItems = n.filter((item) =>
             objectiveArr.includes(item.type)
           );
+		  
           this.blockHeight = 26 * this.number
           this.leftItems = JSON.parse(JSON.stringify(this.objectiveItems)) 
-          this.doRenderItems(this.objectiveItems, this.number);
+		  this.$nextTick(() => {
+			  this.doRenderItems(this.objectiveItems, this.number);
+		  })
         }
       },
+	  immediate:true,
       // 开启深度监听
       deep: true,
     },
@@ -307,9 +319,9 @@ export default {
 </script>
 <style scoped>
 .sheet-objective-container {
-  position: absolute;
-  left: 0;
-  top: 340px;
+  /* position: absolute; */
+  /* left: 0; */
+  /* top: 350px; */
   width: 750px;
 }
 

+ 4 - 6
TEAMModelOS/ClientApp/src/view/answersheet/SheetSubjective.vue

@@ -6,7 +6,7 @@
     @mouseover="isShowInfoEdit = true"
   >
     <!-- <p style="margin:10px 0 10px 100px; font-weight: bold; color: #000">三、问答题(共{{ subjectiveItems.length }}题,总计 {{  totalScore  }} 分)</p> -->
-    <BaseTitleEditor ids="subjectiveTitleEditor" :content="'三、问答题(共' + subjectiveItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor>
+    <!-- <BaseTitleEditor ids="subjectiveTitleEditor" :content="'三、问答题(共' + subjectiveItems.length + '题,总计' + totalScore + '分)'"></BaseTitleEditor> -->
     <div v-if="isRender">
       <BaseEditor
         v-for="(item, index) in subjectiveItems"
@@ -78,7 +78,7 @@ export default {
       setTimeout(() => {
         this.$store.commit('clearFixArr')
         this.$store.commit('clearPage')
-        document.getElementById('pdfDom').scrollIntoView()
+        // document.getElementById('pdfDom').scrollIntoView()
         this.isRender = true
       },)
     });
@@ -94,12 +94,10 @@ export default {
       // 数据变化时执行的逻辑代码
       handler(n, old) {
         if (n.length) {
-          let objectiveArr = ["subjective"];
-          this.subjectiveItems = n.filter((item) =>
-            objectiveArr.includes(item.type)
-          );
+          this.subjectiveItems = n;
         }
       },
+	  immediate:true,
       // 开启深度监听
       deep: true,
     },

+ 337 - 127
TEAMModelOS/ClientApp/src/view/answersheet/index.vue

@@ -1,134 +1,344 @@
 <template>
-  <div class="sheet-container" id="pdfDom" v-if="isRender">
-    <!-- <router-view  v-if="isRouterAlive"/> -->
-    <BaseSvgBg
-      v-for="(page, pageIndex) in pages"
-      :key="pageIndex"
-      :ids="'svg' + pageIndex"
-      :total="pages.length"
-    ></BaseSvgBg>
-    <SheetBaseInfo></SheetBaseInfo>
-    <SheetObjective
-      :items="items"
-      v-show="groupItems.objectiveItems.length"
-      @onRendered="onRendered"
-    ></SheetObjective>
-    <div class="sheet-subjective-wrap" :style="'top:' + subjectiveTop + 'px'">
-      <SheetComplete
-        :items="items"
-        v-if="groupItems.completeItems.length"
-      ></SheetComplete>
-      <SheetSubjective
-        :items="items"
-        v-show="groupItems.subjectiveItems.length"
-      ></SheetSubjective>
-    </div>
-  </div>
+	<div class="sheet-wrap animated fadeIn">
+		<Loading v-if="isLoading"></Loading>
+		<div class="sheet-left">
+			<div class="sheet-container" id="pdfDom" v-if="isRender">
+				<!-- <router-view  v-if="isRouterAlive"/> -->
+				<BaseSvgBg v-for="(page, pageIndex) in pages" :key="pageIndex" :ids="'svg' + pageIndex"
+					:total="pages.length"></BaseSvgBg>
+				<SheetBaseInfo></SheetBaseInfo>
+				
+				
+<!-- 				<SheetObjective :items="items" v-show="groupItems.objectiveItems.length" @onRendered="onRendered">
+				</SheetObjective>
+				<div class="sheet-subjective-wrap" :style="'top:' + subjectiveTop + 'px'">
+					<SheetComplete :items="items" v-if="groupItems.completeItems.length"></SheetComplete>
+					<SheetSubjective :items="groupItems.subjectiveItems" v-show="groupItems.subjectiveItems.length"></SheetSubjective>
+				</div> -->
+				
+				<!-- 绘制主区域 -->
+				<div class="sheet-groups">
+					<div v-for="(group,groupIndex) in groups" :key="groupIndex" class="sheet-group-item">
+						<div v-if="group.type === 'objective'">
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"></BaseTitleEditor>
+							<SheetObjective :items="items" v-show="groupItems.objectiveItems.length" @onRendered="onRendered"></SheetObjective>
+						</div>
+						<div v-else-if="group.type === 'complete'">
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"></BaseTitleEditor>
+							<SheetComplete :items="items" v-if="groupItems.completeItems.length"></SheetComplete>
+						</div>
+						<div v-else>
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"></BaseTitleEditor>
+							<SheetSubjective :items="groupItems.subjectiveItems" v-show="groupItems.subjectiveItems.length"></SheetSubjective>
+						</div>
+					</div>
+				</div>
+				
+			</div>
+		</div>
+		<div class="sheet-right">
+			<Button @click="goBack">返回上级</Button>
+			<Button @click="doDownload" class="btn-download">下载PDF</Button>
+			<div>
+				<p class="sheet-right-title">基础设置</p>
+				<div>
+					<Checkbox v-model="isColumn">客观题竖向排列</Checkbox>
+					<Checkbox v-model="isColumn">自定义页眉</Checkbox>
+					<Checkbox v-model="isColumn">添加二维码</Checkbox>
+					<Checkbox v-model="isColumn">密封线</Checkbox>
+				</div>
+				<p class="sheet-right-title">添加题型</p>
+				<div style="display: flex;flex-wrap: wrap;">
+					<span class="add-block-item"> + 客观题</span>
+					<span class="add-block-item"> + 填空题</span>
+					<span class="add-block-item"> + 简答题</span>
+					<span class="add-block-item"> + 作文(语)</span>
+					<span class="add-block-item"> + 作文(英)</span>
+				</div>
+			</div>
+		</div>
+	</div>
 </template>
- 
+
 <script>
-import Snap from "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js";
-import SheetObjective from "./SheetObjective";
-import SheetBaseInfo from "./SheetBaseInfo";
-import SheetComplete from "./SheetComplete";
-import SheetSubjective from "./SheetSubjective";
-import BaseSvgBg from "./BaseSvgBg";
-import { PAPER_W, PAPER_H, ANCHORPROP, INFO_H } from "@/utils/sheetConfig.js";
-export default {
-  props: {
-    ids: {
-      type: String,
-      default: "",
-    },
-  },
-  provide :function() {
-    return {
-      reload:this.reload
-    }
-},
-  components: {
-    SheetObjective,
-    SheetBaseInfo,
-    SheetComplete,
-    SheetSubjective,
-    BaseSvgBg,
-  },
-  data() {
-    return {
-      isRouterAlive:true,
-      isRender: true,
-      pages: [],
-      items: [],
-      groupItems: {
-        objectiveItems: [],
-        completeItems: [],
-        subjectiveItems: [],
-      },
-      subjectiveTop: 0,
-    };
-  },
-  methods: {
-    reload(){
-        this.isRouterAlive=false;
-        this.$nextTick(function(){
-            this.isRouterAlive=true
-        })
-    },
-    // 客观题渲染完 来决定主观题的TOP值高度
-    onRendered(val) {
-      this.subjectiveTop = val + INFO_H + 220;
-    },
+	import BaseTitleEditor from './BaseTitleEditor'
+	import Snap from "imports-loader?this=>window,fix=>module.exports=0!snapsvg/dist/snap.svg.js";
+	import SheetObjective from "./SheetObjective";
+	import SheetBaseInfo from "./SheetBaseInfo";
+	import SheetComplete from "./SheetComplete";
+	import SheetSubjective from "./SheetSubjective";
+	import BaseSvgBg from "./BaseSvgBg";
+	import {
+		PAPER_W,
+		PAPER_H,
+		ANCHORPROP,
+		INFO_H
+	} from "@/utils/sheetConfig.js";
+	export default {
+		props: {
+			ids: {
+				type: String,
+				default: "",
+			},
+		},
+		provide: function() {
+			return {
+				reload: this.reload
+			}
+		},
+		components: {
+			SheetObjective,
+			SheetBaseInfo,
+			SheetComplete,
+			SheetSubjective,
+			BaseSvgBg,
+			BaseTitleEditor
+		},
+		data() {
+			return {
+				groups:[],
+				isLoading:false,
+				isColumn:false,
+				isRouterAlive: true,
+				isRender: true,
+				pages: [],
+				items: [],
+				groupItems: {
+					objectiveItems: [],
+					completeItems: [],
+					subjectiveItems: [],
+				},
+				subjectiveTop: 0,
+				fromRouter:'',
+				typeList:{
+					objective:'选择题',
+					complete:'填空题',
+					subjective:'简答题'
+				}
+			};
+		},
+		created() {
+			let routerPaper = this.$route.params.paper
+			if(routerPaper){
+				this.$store.commit('clearFixArr')
+				this.$store.commit('clearPage')
+				this.$store.commit('clearIsNewPage')
+				this.$store.commit('setPaper',routerPaper)
+				this.items = routerPaper.item
+			}else{
+				this.goBack()
+			}
+			
+		},
+		methods: {
+			doDownload(){
+				this.isLoading = true
+				this.getPdf().then(res => {
+					this.isLoading = false
+				})
+			},
+			goBack(){
+				this.$router.push({
+					name: this.fromRouter || 'schoolBank',
+					params: {
+						tabName: 'paper'
+					}
+				})
+			},
+			reload() {
+				this.isRouterAlive = false;
+				this.$nextTick(function() {
+					this.isRouterAlive = true
+				})
+			},
+			// 客观题渲染完 来决定主观题的TOP值高度
+			onRendered(val) {
+				console.log('客观题渲染完',val)
+				this.subjectiveTop = val + INFO_H + 200;
+			},
 
-    doRender() {
-      this.groupItems = {
-        objectiveItems: [],
-        completeItems: [],
-        subjectiveItems: [],
-      }
-      this.items = require("@/utils/items.json");
-      let objectiveTypes = ["single", "multiple", "judge"];
-      this.items.forEach((i) => {
-        if (objectiveTypes.includes(i.type)) {
-          this.groupItems.objectiveItems.push(i);
-        } else if (i.type === "complete") {
-          this.groupItems.completeItems.push(i);
-        } else {
-          this.groupItems.subjectiveItems.push(i);
-        }
-      });
-    },
-  },
-  mounted: function () {
-    this.doRender()
-  },
-  computed: {
-    getPage() {
-      return this.$store.state.answerSheet.pages;
-    },
-  },
-  watch: {
-    getPage: {
-      handler(n, o) {
-        this.pages = new Array(n).fill(0);
-      },
-    },
-  },
-};
+			doRender() {
+				this.groupItems = {
+					objectiveItems: [],
+					completeItems: [],
+					subjectiveItems: [],
+				}
+				let objectiveTypes = ["single", "multiple", "judge"];
+				this.items.forEach((i) => {
+					if (objectiveTypes.includes(i.type)) {
+						this.groupItems.objectiveItems.push(i);
+					} else if (i.type === "complete") {
+						this.groupItems.completeItems.push(i);
+					} else {
+						this.groupItems.subjectiveItems.push(i);
+					}
+				});
+				
+				if(this.groupItems.objectiveItems.length){
+					this.groups.push({
+						type:'objective',
+						items: this.groupItems.objectiveItems
+					})
+				}
+				if (this.groupItems.completeItems.length){
+					this.groups.push({
+						type:'complete',
+						items: this.groupItems.completeItems
+					})
+				}
+				if (this.groupItems.subjectiveItems.length){
+					this.groups.push({
+						type:'subjective',
+						items: this.groupItems.subjectiveItems
+					})
+				}
+				console.log(this.groupItems)
+				console.log(this.groups)
+			},
+			/**
+			 * 数字与中文转换
+			 * @param num
+			 */
+			numberConvertToUppercase(num) {
+				num = Number(num)
+				var upperCaseNumber = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '百', '千', '万', '亿']
+				var length = String(num).length
+				if (length === 1) {
+					return upperCaseNumber[num]
+				} else if (length === 2) {
+					if (num === 10) {
+						return upperCaseNumber[num]
+					} else if (num > 10 && num < 20) {
+						return '十' + upperCaseNumber[String(num).charAt(1)]
+					} else {
+						return upperCaseNumber[String(num).charAt(0)] + '十' + upperCaseNumber[String(num).charAt(1)].replace('零', '')
+					}
+				}
+			},
+		},
+		mounted: function() {
+			this.doRender()
+		},
+		beforeRouteEnter (to, from, next){
+		  next(vm => {
+			vm.fromRouter = from.name
+		  })
+		},
+		computed: {
+			getPage() {
+				return this.$store.state.answerSheet.pages;
+			},
+			
+			titleContent(){
+				return (groupIndex,group) => {
+					let totalScore = group.items.length ? group.items.map(i => i.score).reduce((a,b) => a + b) : 0
+					let type = this.typeList[group.type]
+					return this.numberConvertToUppercase(groupIndex + 1) + '、' + type + '(共' + group.items.length +  '题,总计' + totalScore +  '分)' 
+				}
+			}
+		},
+		watch: {
+			getPage: {
+				handler(n, o) {
+					this.pages = new Array(n).fill(0);
+				},
+				immediate:true
+			},
+		},
+	};
 </script>
-<style scoped>
-.sheet-container {
-  position: relative;
-  width: 750px;
-  height: 1060.71px;
-  background: #fff;
-  /* margin: 0 auto; */
-}
+<style scoped lang="less">
+	.sheet-wrap {
+		display: flex;
+		justify-content: space-between;
+		position: relative;
+		width: 100%;
+		
+		.ivu-spin{
+			background-color: #000000 !important;
+		}
+	}
+	
+	.sheet-groups{
+		position: absolute;
+		top: 350px;
+		left: 0;
+		width: 100%;
+	}
+
+	.sheet-right {
+		width: 16%;
+		margin-top: 20px;
+		background-color: #fff;
+		box-shadow: 0 0 5px #000000;
+		position: fixed;
+		top: 70px;
+		right: 10px;
+		height: 88vh;
+		padding: 20px;
+		
+		.ivu-btn{
+			width: 100%;
+			height: 40px;
+			background-color: #00b29a;
+			color: #fff;
+			border: none;
+		}
+		
+		.btn-download{
+			margin-top: 10px;
+			background-color: #00a7ee;
+		}
+		
+		.add-block-item{
+			display: inline-block;
+			margin: 5px;
+			background: #009de8;
+			color: #fff;
+			padding: 6px 15px;
+			border-radius: 4px;
+			cursor: pointer;
+		}
+		
+		&-title{
+			font-size: 14px;
+			font-weight: bold;
+			margin: 15px 5px;
+			
+			&::before{
+				content: '';
+				width: 5px;
+				height: 10px;
+				background-color: #2181ff;
+				display: inline-block;
+				margin-right: 10px;
+			}
+		}
+		
+		.ivu-checkbox-wrapper{
+			margin: 10px;
+		}
+		
+		
+		
+	}
+
+	.sheet-left {
+		width: 70%;
+	}
+
+	.sheet-container {
+		position: relative;
+		width: 750px;
+		height: 1060.71px;
+		background: #fff;
+		margin: 20px auto;
+	}
 
-.sheet-subjective-wrap {
-  position: absolute;
-  top: 580px;
-  left: 0;
-  width: 100%;
-}
+	.sheet-subjective-wrap {
+		position: absolute;
+		top: 580px;
+		left: 0;
+		width: 100%;
+	}
 </style>
- 

+ 5 - 2
TEAMModelOS/ClientApp/src/view/classmgt/ManageClass.vue

@@ -45,7 +45,10 @@
                         <span>{{row.groupName ? row.groupName : $t('cusMgt.noGroup')}}</span>
                     </template>
                 </Table>
-                <EmptyData v-else :textContent="$t('cusMgt.noMgtClass')" :top="150"></EmptyData>
+                <EmptyData v-else :textContent="$store.state.userInfo.hasSchool ? $t('cusMgt.noMgtClass2') : $t('cusMgt.noMgtClass1')" :top="150"></EmptyData>
+                <p style="text-align:center" v-show="!$store.state.userInfo.hasSchool">
+                    <router-link to="/home/settings">{{$t('cusMgt.toJoin')}}</router-link>
+                </p>
             </vuescroll>
         </div>
         <!-- 分组模式 -->
@@ -412,7 +415,7 @@ export default {
                 let num = surplus == 0 ? maxCount : i < surplus ? maxCount : maxCount - 1 //每组实际人数
                 for (let j = 0; j < num; j++) {
                     let startIndex = i + (j * this.groupNum)
-                    this.$set(this.classList[this.curClassIndex].students[startIndex], 'groupId', (i + 1)+'')
+                    this.$set(this.classList[this.curClassIndex].students[startIndex], 'groupId', (i + 1) + '')
                     this.$set(this.classList[this.curClassIndex].students[startIndex], 'groupName', (i + 1) + this.$t('cusMgt.groupUnit'))
                 }
             }

+ 1 - 2
TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.less

@@ -120,7 +120,7 @@
         width: 100%;
         height: 90px;
         background: White;
-        margin-top: 15px;
+        margin-top: 10px;
 		padding-left: 10px;
         .fl-col-center;
         align-items: flex-start;
@@ -222,7 +222,6 @@
 		width: 100%;
 		display: flex;
 		justify-content: center;
-		background-color: #fff;
 	}
 }
 

+ 29 - 11
TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue

@@ -1,7 +1,7 @@
 <template>
 	<div class="pl-container" ref="plContainer">
 		<!-- 条件筛选部分 -->
-		<BaseFilter @onChange="onFilterChange" :isFilterPaper="isFilterPaper"></BaseFilter>
+		<BaseFilter @onChange="onFilterChange" :isFilterPaper="isFilterPaper"  v-if="!isPreview"></BaseFilter>
 
 		<!-- 空数据展示 -->
 		<div v-if="paperList.length === 0" class="no-data-text">
@@ -35,7 +35,7 @@
 							<span>下载试卷</span>
 						</span> -->
 						<!-- <span class="paper-item-tools-edit" @click.stop="renderAnswerSheet(paper)">
-							<Icon type="md-download" />
+							<Icon type="md-eye" />
 							<span>预览答题卡</span>
 						</span> -->
 						<span class="paper-item-tools-edit" @click.stop="goToPaper(paper)"
@@ -59,7 +59,7 @@
 			<!-- 预览试卷部分 -->
 			<div class="pl-review-wrap animated fadeIn" v-if="isPreview">
 				<div class="pl-review-wrap-left">
-					<TestPaper :paper="evaluationInfo" isExamPaper></TestPaper>
+					<TestPaper :paper="evaluationInfo" isExamPaper hidePie></TestPaper>
 				</div>
 
 				<div class="pl-review-wrap-right">
@@ -79,17 +79,16 @@
 				<AnswerSheet></AnswerSheet>
 			</div> -->
 		</div>
-
-
+		
 		<Modal v-model="isShowDownLoad" width="800px"  title="下载试卷" class-name="preview-modal">
 			<DownloadPaper :paper="fullPaperJson"></DownloadPaper>
 		</Modal>
 		
-		<Modal v-model="isShowSheet" width="800px"  title="答题卡" class-name="preview-modal">
+<!-- 		<Modal v-model="isShowSheet" width="800px"  title="答题卡" class-name="preview-modal" >
 			<div v-if="isShowSheet">
 				<AnswerSheet></AnswerSheet>
 			</div>
-		</Modal>
+		</Modal> -->
 
 	</div>
 </template>
@@ -276,9 +275,24 @@
 				console.log('要下载的试卷', fullPaperJson)
 			},
 			
-			renderAnswerSheet(paper){
-				this.isShowSheet = true
-			},
+			// async renderAnswerSheet(paper){
+			// 	this.dataLoading = true
+			// 	try{
+			// 		let fullPaperJson = this.fullPaperJson.id === paper.id ? this.fullPaperJson : await this.$evTools.getFullPaper(paper)
+			// 		// this.isShowSheet = true
+			// 		this.dataLoading = false
+			// 		this.$router.push({
+			// 			name: 'answerSheet',
+			// 			params: {
+			// 				paper: fullPaperJson
+			// 			}
+			// 		})
+			// 	}catch(e){
+			// 		this.$Message.error(this.$t('evaluation.paperList.paperErrorTip'))
+			// 		this.dataLoading = false
+			// 	}
+				
+			// },
 
 			/**
 			 * 删除试卷
@@ -424,7 +438,7 @@
 <style>
 	
 	.preview-modal .ivu-modal-body{
-		height: 650px;
+		/* height: 650px; */
 		overflow: scroll;
 	}
 	
@@ -435,6 +449,10 @@
 		margin: 20px 0;
 		color: #fff;
 	}
+	
+	.pl-review-wrap-left .paper-base-info{
+		top: 50px !important;
+	}
 
 	.pl-container .ivu-checkbox-inner {
 		display: none !important;

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

@@ -76,6 +76,7 @@
 			
 			onShowPaperList(){
 				this.$refs.paperList.isPreview = false
+				this.$refs.paperList.isShowSheet = false
 				this.isShowBackList = false
 			},
 

+ 3 - 3
TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue

@@ -56,7 +56,7 @@
 									<Radio label="import" v-if="!isEditPaper">试题导入</Radio>
 								</RadioGroup>
 							</div> -->
-							<p class="save-tips">* {{ viewModel === 'list' ? $t('evaluation.paperList.saveRule1') : $t('evaluation.paperList.saveRule2') }}
+							<p class="save-tips">* {{ viewModel === 'list' ? $t('evaluation.paperList.saveRule2') : $t('evaluation.paperList.saveRule2') }}
 							</p>
 							<Tabs v-model="activeTab" type="card" class="question-main-tabs" name="createTest">
 								<TabPane :label="$t('evaluation.paperList.tab1')" name="auto" v-if="evaluationInfo.createType == 'auto'" :index="1"
@@ -648,7 +648,7 @@
 									} else {
 										// 只按照默认顺序保存
 										// let saveArr = this.viewModel === 'type' ? arr : list
-										this.doSavePaper(list)
+										this.doSavePaper(arr)
 									}
 								} else {
 									this.$Message.warning(this.$t('evaluation.paperList.noItemTip'))
@@ -673,7 +673,7 @@
 											} else {
 												// 只按照默认顺序保存
 												// let saveArr = this.viewModel === 'type' ? arr : list
-												this.doSavePaper(list)
+												this.doSavePaper(arr)
 											}
 										})
 									},

+ 15 - 2
TEAMModelOS/ClientApp/src/view/evaluation/index/TestPaper.vue

@@ -25,11 +25,13 @@
 							<Button class="base-info-btn" type="info" @click="onCleanPaper" v-show="paperInfo.item.length && !isShowAnalysis">{{$t('evaluation.paperList.cleanItems')}}</Button>
 							<Button class="base-info-btn" type="info" @click="onViewModelChange" v-show="paperInfo.item.length && !isShowAnalysis">{{ `${ viewModel === 'type' ? this.$t('evaluation.paperList.orderByList') : this.$t('evaluation.paperList.orderByType') }` }}</Button>
 							<Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis" v-show="paperInfo.item.length">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
+							<Button class="base-info-btn" type="info" @click="goAnswerSheet" v-show="paperInfo.item.length">{{  $t('evaluation.paperList.goAnswerSheet') }}</Button>
 						</div>
 						<div  v-if="isExamPaper">
 							<Button class="base-info-btn" type="info" @click="onHandleToggle" v-show="paperInfo.item.length && !isShowAnalysis">{{ isAllOpen ? $t('evaluation.index.collapseAll') : $t('evaluation.index.openAll')}}</Button>
 							<Button class="base-info-btn" type="info" @click="onViewModelChange" v-show="paperInfo.item.length && !isShowAnalysis">{{ `${ viewModel === 'type' ? this.$t('evaluation.paperList.orderByList') : this.$t('evaluation.paperList.orderByType') }` }}</Button>
 							<Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis" v-show="paperInfo.item.length && !isHideAnalysis">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
+							<Button class="base-info-btn" type="info" @click="goAnswerSheet" v-show="paperInfo.item.length">{{  $t('evaluation.paperList.goAnswerSheet') }}</Button>
 						</div>
 					</div>
 
@@ -38,7 +40,7 @@
 						<p class="paper-title">{{paperInfo.name}}</p>
 					</div>
 
-					<ExamPaperAnalysis :testPaper="paperInfo" v-if="isShowAnalysis" :hidePie="isExamPaper"></ExamPaperAnalysis>
+					<ExamPaperAnalysis :testPaper="paperInfo" v-if="isShowAnalysis" :hidePie="hidePie"></ExamPaperAnalysis>
 
 					<!-- 题目类型及列表 -->
 					<BaseExerciseList :paper="paperInfo" @dataUpdate="onListUpdate" v-show="!isShowAnalysis" ref="exList" :isShowTools="!isPreview" :isExamPaper="isExamPaper"
@@ -99,6 +101,10 @@
 				type: Boolean,
 				default: false
 			},
+			hidePie:{
+				type: Boolean,
+				default: false
+			},
 			isHideAnalysis:{
 				type: Boolean,
 				default: false
@@ -159,7 +165,14 @@
 
 		},
 		methods: {
-
+			goAnswerSheet(){
+				this.$router.push({
+					name: 'answerSheet',
+					params: {
+						paper: this.paperInfo
+					}
+				})
+			},
 			/**
 			 * 标题切换
 			 * @param e

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

@@ -2,7 +2,7 @@
     <div class="evaluation">
         
         <Loading :top="100" v-show="dataLoading" type="3"></Loading>
-        <vuescroll ref="evScroll">
+        <vuescroll ref="evScroll" id="evScroll">
             <div class="ev-body">
                 <div class="ev-content">
                     <router-view />

+ 2 - 22
TEAMModelOS/ClientApp/src/view/joinclass/JoinClass.vue

@@ -1,17 +1,12 @@
 <template>
     <div>
-        <h1 @click="markStuAnswer">按钮</h1>
         <div style="text-align:center;" id="test-hahah">
             <h1 style="text-align:center;margin-top:100px;font-size:22px;">学生扫码加入名单需要学生端APP对接,学生端APP扫码可以直接读取学生账号信息加入到班级。</h1>
             <!-- <p>{{tId}}</p> -->
             <p data-html2canvas-ignore>教师姓名:{{tName}}</p>
-            <p>教室编码:{{cId}}</p>
-            <p>教室名称:{{cName}}</p>
-
+            <p>名单:{{cName}}</p>
+            <p>编码:{{cId}}</p>
         </div>
-        <Modal v-model="markStatus" fullscreen title="批注">
-            <BaseMyCanvas v-if="markStatus" :bgImg="markBg"></BaseMyCanvas>
-        </Modal>
     </div>
 </template>
 <script>
@@ -23,24 +18,9 @@ export default {
             tName: '',
             cId: '',
             cName: '',
-            markBg:'',
-            markStatus:false
         }
     },
     methods: {
-        // 批注学生作答数据
-        markStuAnswer() {
-            let answer = document.getElementById('test-hahah')
-            console.log(answer)
-            html2canvas(answer).then((canvas) => {
-                // canvas.style.width = "100%"
-                // canvas.style.height = "auto"
-                console.log('111111111')
-                this.markBg = canvas.toDataURL()
-                console.log(this.markBg)
-                this.markStatus = true
-            });
-        },
     },
     created() {
         this.tId = this.$route.query.tId

+ 10 - 7
TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue

@@ -230,7 +230,7 @@ export default {
             },
             dateOpt1: {
                 disabledDate(date) {
-                    let  d = _this.evaluationInfo.startTime ? _this.evaluationInfo.startTime : Date.now()
+                    let d = _this.evaluationInfo.startTime ? _this.evaluationInfo.startTime : Date.now()
                     return d && d > date.valueOf() + 86400000
                 }
             },
@@ -295,8 +295,8 @@ export default {
         }
     },
     methods: {
-        publishChange(data){
-            if(data == 0){
+        publishChange(data) {
+            if (data == 0) {
                 this.startTime = new Date()
                 this.evaluationInfo.startTime = Date.now()
             }
@@ -686,10 +686,13 @@ export default {
                         //发布成功需要备份试卷数据
                         let examId = res.exam.id
                         let privateSas = this.$store.state.privateSas
-                        let schoolSas = {
-                            sas: '?' + this.$store.state.user.schoolProfile.blob_sas,
-                            url: this.$store.state.user.schoolProfile.blob_uri.slice(0, this.$store.state.user.schoolProfile.blob_uri.lastIndexOf(this.$store.state.userInfo.schoolCode) - 1),
-                            name: this.$store.state.userInfo.schoolCode
+                        let schoolSas = {}
+                        if (this.$store.state.userInfo.hasSchool) {
+                            schoolSas = {
+                                sas: '?' + this.$store.state.user.schoolProfile.blob_sas,
+                                url: this.$store.state.user.schoolProfile.blob_uri.slice(0, this.$store.state.user.schoolProfile.blob_uri.lastIndexOf(this.$store.state.userInfo.schoolCode) - 1),
+                                name: this.$store.state.userInfo.schoolCode
+                            }
                         }
                         //校本课程复制到学校容器 个人课程复制到个人容器
                         let targetBlob = undefined

+ 17 - 5
TEAMModelOS/ClientApp/src/view/learnactivity/CreateSchoolEva.vue

@@ -697,18 +697,30 @@ export default {
         csOptions() {
             let data = []
             if (this.evaluationInfo.period.id && this.schoolBase.period.length && this.schoolClasses.length) {
-                let curPd = this.schoolBase.period.filter((item) => {
+                let curPd = this.schoolBase.period.find((item) => {
                     return item.id == this.evaluationInfo.period.id
                 })
-                if (curPd && curPd.length) {
-                    curPd[0].grades.forEach((item, index) => {
+                if (curPd) {
+                    //计算学级逻辑
+                    let date = new Date()
+                    let curYear = date.getFullYear()
+                    let month = date.getMonth() + 1
+                    let start = curPd.semesters.find(item => {
+                        return item.start == 1
+                    })
+                    // 根据入学月份确定当前年级和学级的关系
+                    if (start && month < start.month) {
+                        curYear--
+                    }
+                    curPd.grades.forEach((item, index) => {
                         let dataItem = {
                             id: item.id,
-                            name: item.name,
+                            name: `${item.name}(${curYear - index}级)`,
+                            year:curYear - index,
                             children: []
                         }
                         let child = this.schoolClasses.filter(classItem => {
-                            return classItem.gradeId == item.id
+                            return (classItem.year == curYear - index) && classItem.periodId == this.evaluationInfo.period.id
                         })
                         dataItem.children = child
                         data.push(dataItem)

+ 28 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/ExamPaperAnalysis.less

@@ -16,6 +16,34 @@
 		margin-top: 40px;
 	}
 }
+
+
+
+.checklist-title{
+	display: flex;
+	justify-content: space-between;
+	font-weight: bold;
+	font-size: 16px;
+	margin-bottom: 20px;
+	
+	
+	
+	.checklist-title-left::before{
+		content: '';
+		width: 5px;
+		height: 10px;
+		background-color: #30b8f5;
+		display: inline-block;
+		margin-right: 10px;
+	}
+	
+	.checklist-title-tip{
+		font-size: 14px;
+		color: #747474;
+		font-weight: 400;
+	}
+}
+
 .exam-analysis-title-wrap {
     width: 100%;
     height: 28px;

+ 169 - 123
TEAMModelOS/ClientApp/src/view/learnactivity/ExamPaperAnalysis.vue

@@ -1,7 +1,8 @@
 <template>
 	<div>
 		<div class="exam-analysis-checklist">
-			<p style="margin: 10px 0 20px 0;font-weight: bold;display: flex;justify-content: space-between;"><span>试卷双向细目分析表</span> <span style="color: #919185;">提示: a(b) a-配分,b-数量</span> </p>
+			<p class="checklist-title">
+				<span class="checklist-title-left">{{ $t('evaluation.checkList.title') }}</span> <span class="checklist-title-tip">{{ $t('evaluation.checkList.tip') }}</span> </p>
 			<Table :columns="columns" :data="items"></Table>
 		</div>
 		<div class="exam-analysis-wrap" v-if="!hidePie">
@@ -31,65 +32,70 @@
 					}
 				}
 			},
-			hidePie:{
-				type:Boolean,
-				default:false
+			hidePie: {
+				type: Boolean,
+				default: false
 			}
 		},
-		data() {
+		data(vm) {
 			return {
-				pointList:[],
+				pointList: [],
 				columns: [{
-						title: '',
+						title: vm.$t('evaluation.knowledgePoints'),
 						key: 'name'
 					},
 					{
-						title: '记忆',
+						title: vm.$t('evaluation.level1'),
 						key: 'level1',
-						render:(h,params) => {
-							return h('span', params.row.level1.score + '(' + params.row.level1.count  + ')')
+						render: (h, params) => {
+							return h('span', params.row.level1.score + '(' + params.row.level1.count + ')')
 						}
 					},
 					{
-						title: '理解',
+						title: vm.$t('evaluation.level2'),
 						key: 'level2',
-						render:(h,params) => {
-							return h('span', params.row.level2.score + '(' + params.row.level2.count  + ')')
+						render: (h, params) => {
+							return h('span', params.row.level2.score + '(' + params.row.level2.count + ')')
 						}
 					},
 					{
-						title: '应用',
+						title: vm.$t('evaluation.level3'),
 						key: 'level3',
-						render:(h,params) => {
-							return h('span', params.row.level3.score + '(' + params.row.level3.count  + ')')
+						render: (h, params) => {
+							return h('span', params.row.level3.score + '(' + params.row.level3.count + ')')
 						}
 					},
 					{
-						title: '分析',
+						title: vm.$t('evaluation.level4'),
 						key: 'level4',
-						render:(h,params) => {
-							return h('span', params.row.level4.score + '(' + params.row.level4.count  + ')')
+						render: (h, params) => {
+							return h('span', params.row.level4.score + '(' + params.row.level4.count + ')')
 						}
 					},
 					{
-						title: '评价',
+						title: vm.$t('evaluation.level5'),
 						key: 'level5',
-						render:(h,params) => {
-							return h('span', params.row.level5.score + '(' + params.row.level5.count  + ')')
+						render: (h, params) => {
+							return h('span', params.row.level5.score + '(' + params.row.level5.count + ')')
 						}
 					},
 					{
-						title: '创造',
+						title: vm.$t('evaluation.level6'),
 						key: 'level6',
-						render:(h,params) => {
-							return h('span', params.row.level6.score + '(' + params.row.level6.count  + ')')
+						render: (h, params) => {
+							return h('span', params.row.level6.score + '(' + params.row.level6.count + ')')
 						}
 					},
 					{
-						title: '合计',
+						title: vm.$t('evaluation.checkList.sum'),
 						key: 'level6',
-						render:(h,params) => {
-							return h('span', this.sumScore(params.row) + '(' + this.sumCount(params.row)  + ')')
+						render: (h, params) => {
+							return h('span', {
+								style:{
+									fontWeight:'bold',
+									color:'#37a2da'
+								}
+							}, this.sumScore(params.row) + '(' + this.sumCount(params.row) + ')')
 						}
 					}
 				],
@@ -97,124 +103,157 @@
 			}
 		},
 		methods: {
-			sumScore(row){
-				return row.level1.score + row.level2.score + row.level3.score + row.level4.score + row.level5.score + row.level6.score
+			sumScore(row) {
+				return row.level1.score + row.level2.score + row.level3.score + row.level4.score + row.level5.score + row
+					.level6.score
 			},
-			sumCount(row){
-				return row.level1.count + row.level2.count + row.level3.count + row.level4.count + row.level5.count + row.level6.count
+			sumCount(row) {
+				return row.level1.count + row.level2.count + row.level3.count + row.level4.count + row.level5.count + row
+					.level6.count
 			}
 		},
 		mounted() {
 			let items = []
 			this.testPaper.item.forEach(i => {
-				if(i.type !== 'compose'){
+				if (i.type !== 'compose') {
 					items.push(i)
-				}else{
+				} else {
 					items.push(...i.children)
 				}
 			})
-			if(items.length){
+			if (items.length) {
 				let pointList = [...new Set(items.map(i => i.knowledge).flat(1))]
 				let result = []
-				result.push({
-					name:'无',
-					level1:{
-						score:0,
-						count:0
-					},
-					level2:{
-						score:0,
-						count:0
-					},
-					level3:{
-						score:0,
-						count:0
-					},
-					level4:{
-						score:0,
-						count:0
-					},
-					level5:{
-						score:0,
-						count:0
-					},
-					level6:{
-						score:0,
-						count:0
-					},
-				})
-				pointList.forEach(i => {
+				if (pointList.length) {
 					result.push({
-						name:i,
-						level1:{
-							score:0,
-							count:0
+						name: this.$t('evaluation.checkList.none'),
+						level1: {
+							score: 0,
+							count: 0
 						},
-						level2:{
-							score:0,
-							count:0
+						level2: {
+							score: 0,
+							count: 0
 						},
-						level3:{
-							score:0,
-							count:0
+						level3: {
+							score: 0,
+							count: 0
 						},
-						level4:{
-							score:0,
-							count:0
+						level4: {
+							score: 0,
+							count: 0
 						},
-						level5:{
-							score:0,
-							count:0
+						level5: {
+							score: 0,
+							count: 0
 						},
-						level6:{
-							score:0,
-							count:0
+						level6: {
+							score: 0,
+							count: 0
 						},
 					})
-				})
-				if(pointList.length){
-					pointList.forEach((point,pointIndex) => {
-						items.forEach(item => {
-							if(item.knowledge.includes(point)){
-								result[pointIndex + 1]['level'+ item.field].score += item.score
-								result[pointIndex + 1]['level'+ item.field].count++
-							}
+					pointList.forEach(i => {
+						result.push({
+							name: i,
+							level1: {
+								score: 0,
+								count: 0
+							},
+							level2: {
+								score: 0,
+								count: 0
+							},
+							level3: {
+								score: 0,
+								count: 0
+							},
+							level4: {
+								score: 0,
+								count: 0
+							},
+							level5: {
+								score: 0,
+								count: 0
+							},
+							level6: {
+								score: 0,
+								count: 0
+							},
 						})
 					})
-				}
-				items.forEach(item => {
-					if(!item.knowledge.length){
-						result[0]['level'+ item.field].score += item.score
-						result[0]['level'+ item.field].count++
-					} 
-				})
-				result.push({
-					name:'合计',
-					level1:{
-						score:result.reduce((a,b) => a + b.level1.score,0),
-						count:result.reduce((a,b) => a + b.level1.count,0)
-					},
-					level2:{
-						score:result.reduce((a,b) => a + b.level2.score,0),
-						count:result.reduce((a,b) => a + b.level2.count,0)
-					},
-					level3:{
-						score:result.reduce((a,b) => a + b.level3.score,0),
-						count:result.reduce((a,b) => a + b.level3.count,0)
-					},
-					level4:{
-						score:result.reduce((a,b) => a + b.level4.score,0),
-						count:result.reduce((a,b) => a + b.level4.count,0)
-					},
-					level5:{
-						score:result.reduce((a,b) => a + b.level5.score,0),
-						count:result.reduce((a,b) => a + b.level5.count,0)
-					},
-					level6:{
-						score:result.reduce((a,b) => a + b.level6.score,0),
-						count:result.reduce((a,b) => a + b.level6.count,0)
+					if (pointList.length) {
+						pointList.forEach((point, pointIndex) => {
+							items.forEach(item => {
+								if (item.knowledge && item.knowledge.includes(point)) {
+									result[pointIndex + 1]['level' + item.field].score += item.score
+									result[pointIndex + 1]['level' + item.field].count++
+								}
+							})
+						})
 					}
-				})
+					items.forEach(item => {
+						if (item.knowledge && !item.knowledge.length) {
+							result[0]['level' + item.field].score += item.score
+							result[0]['level' + item.field].count++
+						}
+					})
+					result.push({
+						name: this.$t('evaluation.checkList.sum'),
+						level1: {
+							score: result.reduce((a, b) => a + b.level1.score, 0),
+							count: result.reduce((a, b) => a + b.level1.count, 0)
+						},
+						level2: {
+							score: result.reduce((a, b) => a + b.level2.score, 0),
+							count: result.reduce((a, b) => a + b.level2.count, 0)
+						},
+						level3: {
+							score: result.reduce((a, b) => a + b.level3.score, 0),
+							count: result.reduce((a, b) => a + b.level3.count, 0)
+						},
+						level4: {
+							score: result.reduce((a, b) => a + b.level4.score, 0),
+							count: result.reduce((a, b) => a + b.level4.count, 0)
+						},
+						level5: {
+							score: result.reduce((a, b) => a + b.level5.score, 0),
+							count: result.reduce((a, b) => a + b.level5.count, 0)
+						},
+						level6: {
+							score: result.reduce((a, b) => a + b.level6.score, 0),
+							count: result.reduce((a, b) => a + b.level6.count, 0)
+						}
+					})
+				} else {
+					result.push({
+						name: this.$t('evaluation.checkList.none'),
+						level1: {
+							score: items.filter(i => i.level === 1).reduce((a,b) => a + b.score,0),
+							count: items.filter(i => i.level === 1).length
+						},
+						level2: {
+							score: items.filter(i => i.level === 2).reduce((a,b) => a + b.score,0),
+							count: items.filter(i => i.level === 2).length
+						},
+						level3: {
+							score: items.filter(i => i.level === 3).reduce((a,b) => a + b.score,0),
+							count: items.filter(i => i.level === 3).length
+						},
+						level4: {
+							score: items.filter(i => i.level === 4).reduce((a,b) => a + b.score,0),
+							count: items.filter(i => i.level === 4).length
+						},
+						level5: {
+							score: items.filter(i => i.level === 5).reduce((a,b) => a + b.score,0),
+							count: items.filter(i => i.level === 5).length
+						},
+						level6: {
+							score: items.filter(i => i.level === 6).reduce((a,b) => a + b.score,0),
+							count: items.filter(i => i.level === 6).length
+						},
+					})
+				}
+
 				this.items = result
 			}
 		},
@@ -232,3 +271,10 @@
 <style lang="less" scoped>
 	@import './ExamPaperAnalysis.less';
 </style>
+<style lang="less">
+	.exam-analysis-checklist{
+		.ivu-table-header thead tr th{
+			padding: 15px 0 !important;
+		}
+	}
+</style>

+ 15 - 12
TEAMModelOS/ClientApp/src/view/learnactivity/ManualPaper.vue

@@ -3,7 +3,7 @@
         <vuescroll>
             <div class="manual-filter-wrap">
                 <Row style="width:100%;">
-                    <Col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-show="!source">
+                    <Col :xs="24" :sm="24" :md="24" :lg="12" :xl="12" v-show="!source && $store.state.userInfo.hasSchool">
                     <div class="manual-filter-item">
                         <span class="manual-filter-label">{{$t('learnActivity.manual.source')}}</span>
                         <RadioGroup v-model="scope" style="display:inline-block;" @on-change="checkFirst">
@@ -115,9 +115,9 @@ export default {
             defualt: []
         },
         //设置试卷来源校本/个人试卷库,如果设置了则不会有调整试卷来源的功能,如果没有设置则可以手动挑选试卷来源
-        source:{
-            type:String,
-            default:'' //tmid或schoolId
+        source: {
+            type: String,
+            default: '' //tmid或schoolId
         }
     },
     data() {
@@ -228,10 +228,13 @@ export default {
         this.routeScope = this.$route.name == 'createPrivEva' ? 'private' : 'school'
         this.$store.dispatch('user/getSchoolProfile').then(
             res => {
-                this.schoolBase = res.school_base
-                if (this.routeScope == 'private' && this.schoolBase.period.length) {
-                    this.searchPeriod = this.schoolBase.period[0].id
+                if (res.school_base) {
+                    this.schoolBase = res.school_base
+                    if (this.routeScope == 'private' && this.schoolBase.period.length) {
+                        this.searchPeriod = this.schoolBase.period[0].id
+                    }
                 }
+
             }
         ).finally(() => {
             this.getPaperList()
@@ -281,15 +284,15 @@ export default {
                 this.checkFirst()
             }
         },
-        source:{
-            handler(n,o){
-                if(this.source){
+        source: {
+            handler(n, o) {
+                if (this.source) {
                     this.scope = this.source
-                }else{
+                } else {
                     this.scope = this.$route.name == 'createPrivEva' ? this.$store.state.userInfo.TEAMModelId : this.$store.state.userInfo.schoolCode
                 }
             },
-            immediate:true
+            immediate: true
         }
 
     }

+ 4 - 4
TEAMModelOS/ClientApp/src/view/learnactivity/MgtPrivEva.vue

@@ -287,7 +287,7 @@ export default {
             })
         },
         goToCreate() {
-            if (this.$store.state.user.schoolProfile.school_base != undefined) {
+            // if (this.$store.state.user.schoolProfile.school_base) { //这里判断必须要加入学校才能创建评测
                 if (this.scope == 'school') {
                     this.$router.push({
                         name: 'createSchoolEva'
@@ -297,9 +297,9 @@ export default {
                         name: 'createPrivEva'
                     })
                 }
-            } else {
-                this.$Message.warning(this.$t('learnActivity.mgtScEv.noJoin'))
-            }
+            // } else {
+            //     this.$Message.warning(this.$t('learnActivity.mgtScEv.noJoin'))
+            // }
         },
         editEvaluation() {
             this.$router.push({

+ 31 - 5
TEAMModelOS/ClientApp/src/view/learnactivity/MgtSchoolEva.vue

@@ -72,9 +72,13 @@
                                 </span>
                             </p>
                             <div style="display:inline-flex">
-                                <p class="evaluation-type">
+                                <!-- <p class="evaluation-type">
                                     <Icon type="ios-cube" style="margin-right:5px;" size="14" />
                                     <span>{{$t('learnActivity.mgtScEv.evType')}}{{getTypeLabel(item.type)}}</span>
+                                </p> -->
+                                <p class="evaluation-type">
+                                    <Icon type="ios-cube" style="margin-right:5px;" size="14" />
+                                    <span>{{$t('learnActivity.mgtScEv.evType')}}{{getModeLabel(item.source)}}</span>
                                 </p>
                                 <p class="evaluation-type">
                                     <Icon type="ios-people" style="margin-right:5px;" size="16" />
@@ -116,6 +120,13 @@
                             <Button type="warning" size="small" :loading="scoreLoading" class="mock-tea-scoring" @click="mockScoring">{{$t('learnActivity.mgtScEv.autoScore')}}</Button>
                         </Tooltip>
                     </div>-->
+                    <!-- 保存阅卷配置 -->
+                    <div style="float:right;" class="common-save-btn" v-show="curBarIndex == 2">
+                        <Button class="mock-stu-answer" type="text" :loading="btnLoading" @click="saveMarkSetting" icon="ios-albums-outline">
+                            {{$t('schoolBaseInfo.saveInfo')}}
+                        </Button>
+                    </div>
+
                 </div>
                 <!--试卷信息-->
                 <div :class="curBarIndex == 1 ? 'animated fadeIn evaluation-base-info':'evaluation-base-info animated fadeOutRight'" v-show="curBarIndex == 1">
@@ -144,13 +155,13 @@
                 </div>
                 <!-- 阅卷基础设置 -->
                 <div :class="curBarIndex == 2 ? 'animated fadeIn evaluation-base-info':'evaluation-base-info animated fadeOutRight'" v-show="curBarIndex == 2">
-                    <div class="evaluation-test-paper-header" v-if="evaListShow[curEvaIndex]">
+                    <!-- <div class="evaluation-test-paper-header" v-if="evaListShow[curEvaIndex]">
                         <span>{{$t('learnActivity.mgtScEv.evSubject')}}</span>
                         <span v-for="(item,index) in evaListShow[curEvaIndex].subjects" :key="index" :class="index == curSubIndex ? 'subject-item subject-item-active':'subject-item'" @click="selectSubject(index)">
                             {{item.name}}
                         </span>
-                    </div>
-                    <MarkSetting></MarkSetting>
+                    </div> -->
+                    <MarkSetting ref="markSetting" v-if="evaListShow[curEvaIndex]" :evInfo="evaListShow[curEvaIndex]"></MarkSetting>
                 </div>
                 <!-- 阅卷数据 -->
                 <div :class="curBarIndex == 3 ? 'animated fadeIn evaluation-base-info':'evaluation-base-info animated fadeOutRight'" v-show="curBarIndex == 3">
@@ -172,6 +183,7 @@ export default {
     inject: ['reload'],
     data() {
         return {
+            btnLoading:false,
             keyword: '',
             isSearch: false,
             answerLoading: false,
@@ -199,6 +211,11 @@ export default {
         }
     },
     methods: {
+        //保存阅卷配置
+        saveMarkSetting(){
+            console.log(this.$refs['markSetting'])
+            this.$refs['markSetting'].saveSetting()
+        },
         filterByName() {
             let curPdEv = this.evaluationList.filter(item => item.period.id === this.filterPeriod)
             this.evaListShow = curPdEv.filter(item => {
@@ -315,6 +332,14 @@ export default {
                 }
             }
         },
+        /**获取mode对应的label */
+        getModeLabel(code) {
+            for (let item of this.$GLOBAL.EV_MODE()) {
+                if (item.value == code) {
+                    return item.label
+                }
+            }
+        },
         /**
          * 查找班级课程下的班级
          * */
@@ -434,7 +459,8 @@ export default {
         findEvaluation() {
             let requestData = {
                 code: this.scope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
-                classIds: this.$access.hasRole('admin') ? undefined : this.$store.state.userInfo.teachClasses.concat(this.$store.state.userInfo.mgtClasses)
+                // classIds: this.$access.hasRole('admin') ? undefined : this.$store.state.userInfo.teachClasses.concat(this.$store.state.userInfo.mgtClasses) //查询老师相关班级的评测,现在在课程那里进行查询
+                classIds: undefined
             }
             this.$api.learnActivity.FindExamInfo(requestData).then(
                 res => {

+ 275 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/Compare.vue

@@ -0,0 +1,275 @@
+<template>
+    <div id="data-compare-box"></div>
+</template>
+<script>
+import elementResizeDetectorMaker from "element-resize-detector"
+export default {
+    data() {
+        return {
+            techScoreGau: undefined,
+            xData: [ '最低分', '最高分', '平均分','标准差'],
+            // lineData: [100, 100, 100, 100, 100, 100, 100],
+            myData: [3, 20, 62, 34, 55, 65, 33],
+            allData: [11, 38, 23, 39, 66, 66, 79],
+            timeLineData: [1],
+            legend: ['我的数据', '集体的数据'],
+            background: "#2b2a2f", //背景 
+            textColor: "#fff",
+            lineColor: "rgba(255,255,255,0.2)",
+            colors: [{
+                borderColor: "rgba(227,161,96,1)",
+                start: "rgba(227,161,96,0.8)",
+                end: "rgba(227,161,96,0.3)"
+            },
+            {
+                borderColor: "rgba(0,222,255,1)",
+                start: "rgba(0,222,255,0.3)",
+                end: "rgba(0,222,255,0.8)"
+            }],
+            scale: 2,
+            option: {
+                baseOption: {},
+                options: []
+            }
+        }
+    },
+    mounted() {
+        this.techScoreGau = this.$echarts.init(document.getElementById('data-compare-box'))
+        this.techScoreGau.setOption(this.option)
+        this.erd = elementResizeDetectorMaker()
+        this.erd.listenTo(document.getElementById("data-compare-box"), () => {
+            this.$nextTick(() => {
+                //监听到事件后执行的业务逻辑
+                this.techScoreGau.resize()
+            })
+        })
+    },
+    created() {
+        this.option.baseOption = {
+            backgroundColor: this.background,
+            timeline: {
+                show: false,
+                top: 0,
+                data: []
+            },
+            legend: {
+                top: '5px',
+                left: '5px',
+                itemWidth: 10,
+                itemHeight: 10,
+                icon: 'horizontal',
+                textStyle: {
+                    color: '#ddd',
+                    fontSize: 11,
+                },
+                data: this.legend
+            },
+            grid: [
+                {
+                    show: false,
+                    left: '5%',
+                    top: '40px',
+                    bottom: '0',
+                    containLabel: true,
+                    width: '37%'
+                }, {
+                    show: false,
+                    left: '54%',
+                    top: '40px',
+                    bottom: '0',
+                    width: '0%'
+                },
+                {
+                    show: false,
+                    right: '2%',
+                    top: '40px',
+                    bottom: '0',
+                    containLabel: true,
+                    width: '37%'
+                }
+            ],
+            xAxis: [{
+                type: 'value',
+                inverse: true,
+                axisLine: {
+                    show: false
+                },
+                axisTick: {
+                    show: false
+                },
+                position: 'bottom',
+                axisLabel: {
+                    show: false,
+                    color: this.textColor
+                },
+                splitLine: {
+                    show: false,
+                    lineStyle: {
+                        color: this.lineColor
+                    }
+                },
+            }, {
+                gridIndex: 1,
+                show: false
+            }, {
+                gridIndex: 2,
+                axisLine: {
+                    show: false
+                },
+                axisTick: {
+                    show: false
+                },
+                position: 'bottom',
+                axisLabel: {
+                    show: false,
+                    color: this.textColor
+                },
+                splitLine: {
+                    show: false,
+                    lineStyle: {
+                        color: this.lineColor
+                    }
+                },
+            }],
+            yAxis: [{
+                type: 'category',
+                inverse: true,
+                position: 'right',
+                axisLine: {
+                    show: true,
+                    lineStyle: {
+                        color: this.lineColor
+                    }
+                },
+                axisTick: {
+                    show: false
+                },
+                axisLabel: {
+                    show: false
+                },
+                data: this.xData
+            }, {
+                gridIndex: 1,
+                type: 'category',
+                inverse: true,
+                position: 'left',
+                axisLine: {
+                    show: false
+                },
+                axisTick: {
+                    show: false
+                },
+                axisLabel: {
+                    show: true,
+                    textStyle: {
+                        color: '#ffffff',
+                        fontSize: 11
+                    },
+                    align: "center"
+
+                },
+                data: this.xData.map(function (value) {
+                    return {
+                        value: value,
+                        textStyle: {
+                            align: 'center'
+                        }
+                    }
+                })
+            }, {
+                gridIndex: 2,
+                type: 'category',
+                inverse: true,
+                position: 'left',
+                axisLine: {
+                    show: true,
+                    lineStyle: {
+                        color: this.lineColor
+                    }
+                },
+                axisTick: {
+                    show: false
+                },
+                axisLabel: {
+                    show: false
+
+                },
+                data: this.xData
+            }],
+            series: []
+        }
+        this.option.baseOption.timeline.data.push(this.timeLineData[0])
+        this.option.options.push({
+            series: [{
+                name: "我的数据",
+                type: "bar",
+                barWidth: 20,
+                // stack: "1",
+                itemStyle: {
+                    normal: {
+                        color: new this.$echarts.graphic.LinearGradient(0, 0, 1, 0, [{
+                            offset: 0,
+                            color: this.colors[0].start
+                        },
+                        {
+                            offset: 1,
+                            color: this.colors[0].end
+                        }
+                        ]),
+                    }
+                },
+                label: {
+                    normal: {
+                        position: 'left',
+                        show: true,
+                        color:'#ddd',
+                        fontSize:10
+                    }
+                },
+                data: this.myData,
+                animationEasing: "elasticOut"
+            },
+            {
+                name: "集体的数据",
+                type: "bar",
+                stack: "2",
+                barWidth: 20,
+                xAxisIndex: 2,
+                yAxisIndex: 2,
+                itemStyle: {
+                    normal: {
+                        color: new this.$echarts.graphic.LinearGradient(0, 0, 1, 0, [{
+                            offset: 0,
+                            color: this.colors[1].start
+                        },
+                        {
+                            offset: 1,
+                            color: this.colors[1].end
+                        }
+                        ]),
+                    },
+                },
+                label: {
+                    normal: {
+                        position: 'right',
+                        show: true,
+                        color:'#ddd',
+                        fontSize:10
+                    }
+                },
+                data: this.allData,
+                animationEasing: "elasticOut"
+            }
+            ]
+        })
+    }
+}
+</script>
+<style lang="less" scoped>
+#data-compare-box {
+    width: 400px;
+    height: 200px;
+}
+</style>
+<style>
+</style>

+ 2 - 2
TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkData.vue

@@ -2,7 +2,7 @@
     <div class="mark-data-wrap">
         <vuescroll>
             <!-- 活动阶段 -->
-            <div class="setting-block">
+            <!-- <div class="setting-block">
                 <p class="block-title">{{$t('learnActivity.mark.stage')}}</p>
                 <div class="setting-content step-content">
                     <Steps :current="2" class="mark-step">
@@ -12,7 +12,7 @@
                         <Step :title="$t('learnActivity.mark.data')" content=""></Step>
                     </Steps>
                 </div>
-            </div>
+            </div> -->
             <!-- 数据概览 -->
             <div class="setting-block">
                 <p class="block-title">{{$t('learnActivity.mark.dataView')}}</p>

+ 426 - 128
TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkSetting.vue

@@ -2,97 +2,125 @@
     <div class="mark-setting-wrap dark-iview-form">
         <vuescroll>
             <!-- 基础设置 -->
-            <div class="setting-block" style="display:none">
+            <div class="setting-block">
                 <!-- <p class="block-title">
                     {{$t('learnActivity.mark.baseSetting')}}
                 </p> -->
                 <div class="setting-content">
-                    <Form :model="setting" label-colon :label-width="80">
+                    <Form ref="baseSetting" :model="setting" label-colon :label-width="100" :rules="ruleValidate">
                         <Row>
-                            <Col :md="24" :lg="24" :xl="12" :xxl="12">
-                            <FormItem label="阅卷次数" class="setting-item-wrap">
-                                <InputNumber :max="2" :min="1" v-model="setting.point"></InputNumber>
+                            <!-- 开始时间 -->
+                            <Col :md="24" :lg="24" :xl="12" :xxl="8">
+                            <FormItem label="开始时间" class="setting-item-wrap" prop="startTime">
+                                <DatePicker :options="dateOpt" class="attr-value-wrap" type="datetime" format="yyyy/MM/dd HH:mm" v-model="startTime" split-panels :placeholder="$t('learnActivity.createEv.sTimeHolder')" style="width:100%" @on-change="getDate($event,0)"></DatePicker>
+                            </FormItem>
+                            </Col>
+                            <!-- 结束时间 -->
+                            <Col :md="24" :lg="24" :xl="12" :xxl="8">
+                            <FormItem label="结束时间" class="setting-item-wrap" prop="endTime">
+                                <DatePicker :options="dateOpt1" class="attr-value-wrap" type="datetime" format="yyyy/MM/dd HH:mm" v-model="endTime" split-panels :placeholder="$t('learnActivity.createEv.eTimeHolder')" style="width:100%" @on-change="getDate($event,1)"></DatePicker>
+                            </FormItem>
+                            </Col>
+                            <!-- 分配方式 -->
+                            <Col :md="24" :lg="24" :xl="12" :xxl="8">
+                            <FormItem label="分配方式" class="setting-item-wrap" prop="mode">
+                                <RadioGroup v-model="setting.mode" style="color:white">
+                                    <Radio label="full">按人分配</Radio>
+                                    <Radio label="qu" style="margin-left:20px">按题分配</Radio>
+                                </RadioGroup>
+                            </FormItem>
+                            </Col>
+                            <!-- 阅卷次数 -->
+                            <Col :md="24" :lg="24" :xl="12" :xxl="8">
+                            <FormItem label="阅卷次数" class="setting-item-wrap" prop="num">
+                                <!-- <InputNumber :max="2" class="attr-value-wrap" :min="1" v-model="setting.point"></InputNumber> -->
+                                <RadioGroup v-model="setting.num" style="color:white">
+                                    <Radio :label="1">单评制</Radio>
+                                    <Radio :label="2" style="margin-left:20px">双评制</Radio>
+                                    <Radio :label="3" style="margin-left:20px">三评制</Radio>
+                                </RadioGroup>
                             </FormItem>
                             </Col>
-                            <Col :md="24" :lg="24" :xl="12" :xxl="12">
-                            <FormItem :label="$t('learnActivity.mark.scoreDiff')" class="setting-item-wrap">
-                                <InputNumber :max="2" :min="1" v-model="setting.point"></InputNumber>
+                            <!-- 启用异常处理 -->
+                            <Col :md="24" :lg="24" :xl="12" :xxl="8">
+                            <FormItem label="异常申报" class="setting-item-wrap" prop="isErr">
+                                <RadioGroup v-model="setting.isErr" style="color:white">
+                                    <Radio :label="1">是</Radio>
+                                    <Radio :label="0" style="margin-left:20px">否</Radio>
+                                </RadioGroup>
                             </FormItem>
                             </Col>
+                            <!-- 启用仲裁 -->
+                            <Col :md="24" :lg="24" :xl="12" :xxl="8" v-show="setting.num > 1">
+                            <FormItem label="启用仲裁" class="setting-item-wrap" prop="isArb">
+                                <RadioGroup v-model="setting.isArb" style="color:white">
+                                    <Radio :label="1">是</Radio>
+                                    <Radio :label="0" style="margin-left:20px">否</Radio>
+                                </RadioGroup>
+                            </FormItem>
+                            </Col>
+
                         </Row>
                     </Form>
                 </div>
             </div>
+            <div class="subject-wrap">
+                <span v-for="(item,index) in subjects" :key="index" :class="index == curSubIndex ? 'filter-tab-item filter-tab-item-active':'filter-tab-item'" @click="curSubIndex = index">
+                    {{item.name}}
+                </span>
+            </div>
 
-            <div class="setting-block">
+            <div class="setting-block" id="teacher-wrap">
                 <!-- <p class="block-title">
                     {{$t('learnActivity.mark.markRole')}}
                 </p> -->
-                <div class="setting-content">
-                    <Row>
-                        <Col :md="24" :lg="24" :xl="12" :xxl="12">
-                        <!-- 异常处理老师 -->
-                        <div class="role-item-wrap" style="display:none">
-                            <span class="role-label">{{$t('learnActivity.mark.errRole')}}</span>
-                            <Select v-model="setting.err" style="width:400px" multiple>
-                                <Option value="beijing">New York</Option>
-                                <Option value="shanghai">London</Option>
-                                <Option value="shenzhen">Sydney</Option>
-                            </Select>
-                        </div>
-                        </Col>
-                        <Col :md="24" :lg="24" :xl="12" :xxl="12">
-                        <!-- 仲裁老师 -->
-                        <div class="role-item-wrap" style="display:none">
-                            <span class="role-label">{{$t('learnActivity.mark.arb')}}</span>
-                            <Select v-model="setting.err1" style="width:400px" multiple>
-                                <Option value="beijing">New York</Option>
-                                <Option value="shanghai">London</Option>
-                                <Option value="shenzhen">Sydney</Option>
-                            </Select>
-                        </div>
-                        </Col>
-                    </Row>
-                    <!-- 阅卷老师设置 -->
-                    <div class="role-item-wrap dark-iview-table">
-                        <span class="role-label" style="vertical-align: top;">{{$t('learnActivity.mark.markRole')}}</span>
-                        <div class="scan-tea-table">
-                            <Table :columns="teaCol" :data="teaData" border :no-data-text="$t('learnActivity.mark.noTea')">
-                                <template slot-scope="{ row }" slot="header">
-                                    <PersonalPhoto :name="row.name" :picture="row.picture" />
-                                </template>
-                                <template slot-scope="{ row }" slot="action">
-                                    <Button type="error" size="small">{{$t('learnActivity.mark.remove')}}</Button>
-                                </template>
-                                <template slot-scope="{ row }" slot="num">
-                                    <span>{{`${row.num}/24`}}</span>
-                                </template>
-                            </Table>
-                            <span class="add-tea-btn" @click="addTeaStatus = true">
-                                <Icon type="md-add" />
-                                {{$t('learnActivity.mark.addTea')}}
-                            </span>
-                        </div>
-                    </div>
-                </div>
-            </div>
-            <!-- 题号分配 -->
-            <div class="setting-block" style="display:none">
-                <!-- <p class="block-title">
-                    {{$t('learnActivity.mark.quDistrub')}}
-                </p> -->
-                <div class="setting-content dark-iview-table">
-                    <Table :columns="quCol" :data="quData" border :no-data-text="$t('learnActivity.mark.noTea')">
-                        <template slot-scope="{ row }" slot="quNo">
-                            {{row.quNo.join(',')}}
-                        </template>
-                        <template slot-scope="{ row }" slot="teaNum">
-                            {{row.teachers.length}}
-                        </template>
-                        <template slot-scope="{ row }" slot="teachers">
-                            {{row.teachers.join(',')}}
-                        </template>
-                    </Table>
+                <div class="setting-content" id="teacher-wrap-content">
+                    <Form ref="teacherSet" :model="subsInfo" label-colon :label-width="100" :rules="ruleValidate">
+                        <Row>
+                            <Col :md="24" :lg="24" :xl="24" :xxl="24" v-if="setting.isErr">
+                            <!-- 异常处理老师 -->
+                            <FormItem :label="$t('learnActivity.mark.errRole')" class="setting-item-wrap" prop="err">
+                                <Select v-model="subsInfo.err" style="width:400px" multiple>
+                                    <Option v-for="(item,index) in teacherList" :value="item.id" :key="index">{{item.name}}</Option>
+                                </Select>
+                            </FormItem>
+                            </Col>
+                            <Col :md="24" :lg="24" :xl="24" :xxl="24" v-if="setting.isArb">
+                            <!-- 仲裁老师 -->
+                            <FormItem :label="$t('learnActivity.mark.arb')" class="setting-item-wrap" prop="arb">
+                                <Select v-model="subsInfo.arb" style="width:400px" multiple>
+                                    <Option v-for="(item,index) in teacherList" :value="item.id" :key="index">{{item.name}}</Option>
+                                </Select>
+                            </FormItem>
+                            </Col>
+                            <Col :md="24" :lg="24" :xl="24" :xxl="24">
+                            <!-- 阅卷老师 -->
+                            <FormItem :label="$t('learnActivity.mark.markRole')" class="setting-item-wrap dark-iview-table" prop="markers">
+                                <Table :columns="teaCol" :data="markers" border :no-data-text="$t('learnActivity.mark.noTea')">
+                                    <template slot-scope="{ row }" slot="header">
+                                        <PersonalPhoto :name="row.name" :picture="row.picture" />
+                                    </template>
+                                    <template slot-scope="{ row,index }" slot="action">
+                                        <Button v-show="setting.mode == 'qu'" type="info" size="small" style="margin-right:10px" @click="setQuStatus = true">题号</Button>
+                                        <Button type="error" size="small" @click="removeMarker(row,index)">{{$t('learnActivity.mark.remove')}}</Button>
+                                    </template>
+                                    <template slot-scope="{ row }" slot="count">
+                                        <span>{{`${row.count}/${evInfo.stuCount}`}}</span>
+                                    </template>
+                                    <template slot-scope="{ row }" slot="qu">
+                                        <span :style="{color:setting.mode == 'full' ? '#2db7f5' : row.qu.length ? '#FFFFFF' : '#ed4014'}">
+                                            {{setting.mode == 'full' ? '所有题目' : row.qu.length ? row.qu.join(',') : '暂未设置'}}
+                                        </span>
+                                    </template>
+                                </Table>
+                                <span class="add-tea-btn" @click="addTeaStatus = true">
+                                    <Icon type="md-add" />
+                                    {{$t('learnActivity.mark.addTea')}}
+                                </span>
+                            </FormItem>
+                            </Col>
+                        </Row>
+                    </Form>
                 </div>
             </div>
         </vuescroll>
@@ -106,6 +134,9 @@
                 </template>
             </Table>
         </Modal>
+        <Modal v-model="setQuStatus" title="题号设置" class-name="dark-iview-modal dark-iview-table" @on-ok="okSetQu" :width="1000">
+
+        </Modal>
     </div>
 </template>
 <script>
@@ -114,16 +145,85 @@ import ScanProgress from '../echarts/ScanProgress.vue'
 import CptCount from '../echarts/CptCount.vue'
 import PersonalPhoto from "@/components/public/personalPhoto/Index.vue"
 export default {
+    props: {
+        evInfo: {
+            type: Object,
+            default: () => {
+                return {
+                    id: '',
+                    name: ''
+                }
+            }
+        }
+    },
     data() {
+        let _this = this
         return {
+            ruleValidate: {
+                startTime: [
+                    { required: true, type: 'number', message: '请设置阅卷开始时间', trigger: 'blur' }
+                ],
+                endTime: [
+                    { required: true, type: 'number', message: '请设置阅卷结束时间', trigger: 'blur' }
+                ],
+                mode: [
+                    { required: true, message: '请设置分配方式', trigger: 'change' }
+                ],
+                num: [
+                    { required: true, type: 'number', message: '请设置阅卷次数', trigger: 'change' }
+                ],
+                isErr: [
+                    { required: true, type: 'number', message: '请设置是否有异常申报功能', trigger: 'change' }
+                ],
+                isArb: [
+                    { required: true, type: 'number', message: '请设置分差超过1/6的题目是否需要仲裁', trigger: 'change' }
+                ],
+                arb: [
+                    { required: true, type: 'array', message: '请设置仲裁老师', trigger: 'change' }
+                ],
+                err: [
+                    { required: true, type: 'array', message: '请设置异常处理老师', trigger: 'change' }
+                ],
+                markers: [
+                    { required: true, type: 'array', message: '请设置阅卷老师', trigger: 'change' }
+                ],
+            },
+            setQuStatus: false,
+            curSubIndex: 0,
             setting: {
-                mode: '',//阅卷模式
-                num: 0,//阅卷次数
-                err: [],//处理异常卷人员
-                arb: [],//处理冲裁卷人员
-                marker: [],//阅卷老师
-                point: 2,//分差(仲裁条件)
-                quRule: [],//题目分配规则
+                id: '',
+                code: '',
+                name: '',
+                owner: 'school',
+                school: '',
+                creatorId: '',
+                scope: 'school',
+                startTime: '',
+                createTime: '',
+                endTime: '',
+                scode: '',//评测的分区键
+                mode: 'full',//阅卷模式 按人 full  按题 qu
+                num: 1,//阅卷次数
+                isErr: 0, //是否有异常处理流程 0/1
+                isArb: 0, //是否有仲裁处理流程 0/1
+                subs: [
+                    {
+                        id: '',//科目id,
+                        name: '',//科目名称
+                        markers: [ //阅卷老师
+                            // {
+                            //     id: '',
+                            //     name:'',
+                            //     count: 0, //阅卷量 (学生人数*阅卷次数/阅卷老师人数)
+                            //     qu:[]    //如果是按题分配,这里保存批阅的题号。按人分配默认为空数组
+                            // }
+                        ],
+                        err: [],//处理异常卷人员
+                        arb: [],//处理冲裁卷人员
+                        // point: '',//(仲裁条件)固定条件,只需要设置是否启用仲裁
+                    }
+                ],
+
             },
             addTeaStatus: false,
             teacherList: [],
@@ -174,93 +274,288 @@ export default {
                 },
                 {
                     title: this.$t('learnActivity.mark.markNum'),
-                    slot: 'num',
+                    slot: 'count',
                     align: 'center'
                 },
                 {
-                    title: '',
-                    slot: 'action',
+                    title: '批阅题号',
+                    slot: 'qu',
                     align: 'center'
                 },
-            ],
-            teaData: [],
-            quCol: [
-                {
-                    title: this.$t('learnActivity.mark.quIndex'),
-                    slot: 'quNo',
-                    align: 'center',
-                    width: 180
-                },
-                {
-                    title: this.$t('learnActivity.mark.markNum'),
-                    slot: 'teaNum',
-                    align: 'center',
-                    width: 150
-                },
                 {
-                    title: this.$t('learnActivity.mark.markTea'),
-                    slot: 'teachers',
+                    title: '',
+                    slot: 'action',
+                    align: 'center'
                 },
             ],
-            quData: [
-                {
-                    quNo: [1, 2, 3],
-                    teachers: [
-                        'JK',
-                        '尹航',
-                        '向奕然',
-                        '高嘉妍',
-                        '刘雨菡',
-                        'jefftest',
-                        '李芷萱',
-                    ]
+
+            dateOpt: {
+                disabledDate(date) {
+                    return date && date.valueOf() < Date.now() - 86400000
                 }
-            ]
+            },
+            dateOpt1: {
+                disabledDate(date) {
+                    let d = _this.setting.startTime ? _this.setting.startTime : Date.now()
+                    return d && d > date.valueOf() + 86400000
+                }
+            },
+            startTime: '',
+            endTime: ''
         }
     },
     components: {
         MarkProgress, CptCount, ScanProgress, PersonalPhoto
     },
     methods: {
-        //确认添加老师
-        okAddTea() {
-            let ids = this.teaData.map(item => {
-                return item.id
+        //移除阅卷老师
+        removeMarker(row, index) {
+            this.$Modal.confirm({
+                title: '移除老师',
+                content: `是否确认移除${row.name}?`,
+                okText: '是',
+                cancelText: '否',
+                onOk: () => {
+                    this.markers.splice(index, 1)
+                }
             })
-            this.sltTeachers.forEach(item => {
-                if (ids.indexOf(item.id) == -1) {
-                    this.teaData.push(item)
+
+        },
+        //确认设置阅卷题号
+        okSetQu() {
+
+        },
+        /**
+         * 将日期控件时间格式转成时间戳
+         * @param value
+         * @param flag 0:开始时间 1:结束时间
+         */
+        getDate(value, flag) {
+            if (value.indexOf('00:00') > 0) {
+                value = value.replace('00:00', '23:59:59')
+            }
+            if (flag == 0) {
+                this.startTime = value
+                this.setting.startTime = new Date(value).getTime()
+                if (this.setting.startTime >= this.setting.endTime) {
+                    this.endTime = undefined
+                    this.setting.endTime = undefined
+                }
+            } else if (flag == 1) {
+                this.endTime = value
+                this.setting.endTime = new Date(value).getTime()
+            }
+        },
+        saveSetting() {
+            let full = true
+            //验证基础信息设置
+            this.$refs['baseSetting'].validate((valid) => {
+                if (!valid) {
+                    full = false
+                    this.$Message.error('请完成阅卷基础设置')
                 }
             })
-            this.teaData.map(item => {
-                item.num = 24 / this.teaData.length
+            if (!full) return
+            // 验证学科阅卷相关老师设置 待完善,目前验证了当前学科
+            this.$refs['teacherSet'].validate((valid) => {
+                if (!valid) {
+                    full = false
+                    this.$Message.error('阅卷和相关老师设置')
+                }
             })
+            if (!full) return
+
+            // 通过验证,保存设置
+            this.setting.code = this.$store.state.userInfo.schoolCode
+            console.log(this.setting)
+            this.$api.mark.UpsertMarkSet(this.setting).then(
+                res => {
+                    this.$Message.success('保存成功!')
+                },
+                err => {
+                    this.$Message.error('保存失败!')
+                }
+            )
+        },
+        //确认添加老师
+        okAddTea() {
+            let subject = this.setting.subs.find(item => {
+                return this.subjects[this.curSubIndex].id == item.id
+            })
+            console.log('点前学科', subject)
+            if (subject) {
+                let ids = subject.markers.map(item => {
+                    return item.id
+                })
+                this.sltTeachers.forEach(item => {
+                    if (ids.indexOf(item.id) == -1) {
+                        subject.markers.push({
+                            id: item.id,
+                            name: item.name,
+                            qu: []
+                        })
+                    }
+                })
+                let more = this.evInfo.stuCount % subject.markers.length
+                subject.markers.map((item, index) => {
+                    if (index < more) {
+                        item.count = Math.ceil(this.evInfo.stuCount / subject.markers.length)
+                    } else {
+                        item.count = Math.floor(this.evInfo.stuCount / subject.markers.length)
+                    }
+
+                })
+            }
+            console.log(this.setting)
             this.cancel()
         },
         cancel() {
             this.sltTeachers = []
             this.$refs.sltTea.selectAll(false)
         },
-        
+        //查询评测阅卷配置信息
+        findSettingInfo() {
+            let requestData = {
+                id: this.evInfo.id,
+                code: this.$store.state.userInfo.schoolCode
+            }
+            this.$api.mark.FindById(requestData).then(
+                res => {
+                    if (res.correct) {
+                        this.setting = res.correct
+                    } else {
+                        if (this.evInfo.subjects) {
+                            this.setting.id = this.evInfo.id
+                            this.setting.name = this.evInfo.name
+                            this.setting.school = this.$store.state.userInfo.schoolCode
+                            this.setting.code = this.$store.state.userInfo.schoolCode
+                            this.setting.scode = this.evInfo.code
+                            this.setting.creatorId = this.$store.state.userInfo.TEAMModelId
+                            this.setting.createTime = new Date().getTime()
+                            this.setting.startTime = new Date().getTime()
+                            this.setting.endTime = new Date().getTime() + 86400000 * 2
+                            this.setting.subs = []
+                            this.evInfo.subjects.forEach((item) => {
+                                this.setting.subs.push({
+                                    id: item.id,
+                                    name: item.name,
+                                    markers: []
+                                })
+                            })
+                        }
+                    }
+                },
+                err => {
+
+                }
+            ).finally(() => {
+
+            })
+
+        }
     },
     created() {
         this.$store.dispatch('teachers/getTeacherList').then(res => {
             this.teacherList = this.$store.state.teachers.teacherList.filter(item => {
                 return item.status == 'join'
             })
-            console.log(this.teacherList)
         })
+        //初始化起止时间
+        this.startTime = new Date()
+        this.setting.startTime = new Date().getTime()
+        this.endTime = new Date(new Date(new Date().toLocaleDateString()).getTime() + 3 * 24 * 60 * 60 * 1000 - 1)
+        this.setting.endTime = new Date().getTime() + 3 * 24 * 60 * 60 * 1000 - 1
+    },
+    watch: {
+        'evInfo.id': {
+            handler(n, o) {
+                console.log(this.evInfo)
+                if (this.evInfo.id) {
+                    this.findSettingInfo()
+                } else {
+                    this.$Message.warning('暂无评测id')
+                }
+
+            },
+            deep: true
+        }
+    },
+    computed: {
+        //当前科目的配置信息
+        subsInfo() {
+            let info = {
+                arb: [],
+                err: [],
+                markers: []
+            }
+            if (this.setting.subs && this.subjects && this.subjects[this.curSubIndex]) {
+                let subject = this.setting.subs.find(item => {
+                    return item.id == this.subjects[this.curSubIndex].id
+                })
+                if (subject) {
+                    info = subject
+                }
+            }
+            return info
+        },
+        //从基础信息获取当前学科阅卷老师
+        markers() {
+            let arr = []
+            if (this.setting.subs && this.subjects && this.subjects[this.curSubIndex]) {
+                let subject = this.setting.subs.find(item => {
+                    return item.id == this.subjects[this.curSubIndex].id
+                })
+                if (subject) {
+                    arr = subject.markers
+                }
+            }
+            return arr
+        },
+        //当前评测科目
+        subjects() {
+            if (this.evInfo && this.evInfo.subjects) {
+                return this.evInfo.subjects
+            } else {
+                return []
+            }
+        }
     }
 }
 </script>
 <style scoped lang="less">
+.subject-wrap {
+    margin-top: 30px;
+    color: #a5a5a5;
+}
+#teacher-wrap {
+    margin-top: 0px;
+}
+#teacher-wrap-content {
+    margin-top: 0px;
+    border-top-left-radius: 0px;
+}
+.filter-tab-item {
+    display: inline-block;
+    width: 80px;
+    text-align: center;
+    background: #1a191c;
+    color: #a5a5a5;
+    margin-right: 1px;
+    border-top-right-radius: 15px;
+    padding: 2px 0px;
+    font-size: 12px;
+    cursor: pointer;
+}
+.filter-tab-item-active {
+    background: #2b2a2f;
+    color: white;
+}
 .mark-setting-wrap {
     height: calc(100% - 45px);
     padding-bottom: 5px;
-    color: white;
 }
 .setting-block:first-child {
-    margin-top: 10px;
+    margin-top: 15px;
 }
 
 .setting-content {
@@ -273,9 +568,12 @@ export default {
     margin-top: 5px;
 }
 .setting-item-wrap {
-    margin-bottom: 10px;
     padding-right: 15px;
 }
+.attr-value-wrap {
+    width: 90%;
+    max-width: 180px;
+}
 .block-title {
     color: white;
     border-left: 2px solid #1cc0f3;

+ 36 - 21
TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/MarkView.vue

@@ -2,22 +2,33 @@
     <!-- 未做多语言 -->
     <div class="mark-area">
         <!-- 头部基础信息 -->
-        <div class="mark-header" v-show="markMode == 'paper'">
+        <div class="mark-header">
             <span class="quit-marking-text">
                 <!-- <Icon custom="iconfont icon-quit2" class="quit-marking-icon" title="退出阅卷" @click="test"/> -->
-                <Icon type="ios-arrow-back" class="quit-marking-icon" title="退出阅卷" @click="test" />
+                <Icon type="ios-arrow-back" class="quit-marking-icon" title="退出阅卷" @click="quit" />
                 <!-- 退出阅卷 -->
             </span>
             <span class="info-label">考试名称:</span>
             <span class="info-value">一年级数学期末考试</span>
-            <span class="info-label">学生:</span>
+            <span class="info-label">阅卷方式:</span>
+            <span class="info-value">{{mode == 0 ? '按题阅卷' : '按人阅卷'}}</span>
+            <span class="info-label">学生id:</span>
             <span class="info-value">基金会</span>
-            <span class="info-label">分数:</span>
-            <span class="info-value">82</span>
+            <span class="info-label" v-show="mode == 1">分数:</span>
+            <span class="info-value" v-show="mode == 1">82</span>
             <span class="info-label">当前题号:</span>
             <span class="info-value">{{quIndex}}</span>
+            <span class="info-label">阅卷进度:</span>
+            <span class="info-value">{{`${12}/${41}`}}</span>
             <div class="btn-wrap">
-                <!-- <Button type="text" custom-icon="iconfont icon-exception" class="action-btn" @click="test">异常申报</Button> -->
+                <span class="action-btn">
+                    <Icon type="md-shuffle" class="action-btn-icon" />
+                    切换
+                </span>
+                <span class="action-btn">
+                    <Icon type="md-refresh" class="action-btn-icon" />
+                    回评
+                </span>
                 <span class="action-btn">
                     <Icon custom="iconfont icon-exception" class="action-btn-icon" />
                     异常申报
@@ -40,10 +51,10 @@
                     </div>
                 </Poptip>
                 <Icon custom="iconfont icon-fresh" class="tool-icon" title="清除批注" @click="clear" />
-                <Icon custom="iconfont icon-review" class="tool-icon" title="重阅" />
+                <!-- <Icon custom="iconfont icon-review" class="tool-icon" title="重阅" /> -->
                 <Icon :custom="isFull ? 'iconfont icon-cancel-full' : 'iconfont icon-full-screen'" class="tool-icon" :title="isFull ? '取消全屏' : '全屏'" @click="togglefull" />
             </div>
-            <div class="mark-stage">
+            <div class="mark-stage" :style="{paddingBottom: mode == 1 ? '120px' : '0px'}">
                 <vuescroll ref="canvasScroll">
                     <!-- canvas部分 -->
                     <div class="container-box">
@@ -106,7 +117,7 @@ export default {
             isShowNum: true,
             scores: [],
             qus: [],
-            mode: '',
+            mode: '0',//阅卷模式 1:按人阅卷 0:按题阅卷
             quIndex: 1,
             stage: undefined,
             orgLayer: undefined,
@@ -135,7 +146,6 @@ export default {
             imgs: [],
             curImg: undefined,
             counter: 0,
-            markMode: 'paper', //阅卷模式 paper:按人阅卷 qu:按题阅卷
             isFull: false, //是否为全屏模式
             examData:{
                 name:'期末考试',
@@ -182,12 +192,10 @@ export default {
             imageObj.src = require('@/assets/mark/img' + this.counter % 3 + '.jpg')
             this.stage.add(this.orgLayer)
         },
-        test() {
-            console.log(this.$route)
-            console.log(this.stage)
+        quit() {
             // 返回页面
             this.$router.push({
-                name: this.$route.params.from
+                name: sessionStorage.getItem('markFrom')
             })
         },
         uuid() {
@@ -428,6 +436,8 @@ export default {
             this.mouseStatus = 'oval'
         },
         startOval(current) {
+            console.log('scale', this.scaleDefault)
+            console.log('point', this.clickPoint)
             let _this = this
             //判断rect是否初始化
             let rx = (current.x - _this.clickPoint.x) / _this.scaleDefault * 0.5
@@ -435,8 +445,10 @@ export default {
             if (!this.oval) {
                 this.oval = new Konva.Ellipse({
                     id: this.uuid(),
-                    x: _this.clickPoint.x / _this.scaleDefault,
-                    y: _this.clickPoint.y / _this.scaleDefault,
+                    // x: _this.clickPoint.x / _this.scaleDefault,
+                    // y: _this.clickPoint.y / _this.scaleDefault,
+                    x: _this.clickPoint.x,
+                    y: _this.clickPoint.y,
                     radiusX: rx > 0 ? rx : -rx,
                     radiusY: ry,
                     fill: 'transparent',
@@ -547,6 +559,7 @@ export default {
         },
         // 缩小
         smaller() {
+            console.log(this.stage)
             this.scaleDefault -= this.scaleStep
             if (this.scaleDefault < this.minScale) {
                 this.scaleDefault += this.scaleStep
@@ -560,6 +573,7 @@ export default {
         },
         //放大
         larger() {
+            console.log(this.stage)
             this.scaleDefault += this.scaleStep
             if (this.scaleDefault > this.maxScale) {
                 this.scaleDefault -= this.scaleStep
@@ -725,7 +739,9 @@ export default {
             })
             _this.orgLayer = new Konva.Layer({
             })
+            _this.markLayer = new Konva.Layer()
             _this.stage.add(_this.orgLayer)
+            _this.stage.add(_this.markLayer)
             let img = new Konva.Image({
                 x: 0,
                 y: 0,
@@ -737,7 +753,6 @@ export default {
             _this.orgLayer.batchDraw()
             _this.bundleScoll()
             _this.stage.on('click', (evt) => {
-                console.log('舞台点击实践')
                 _this.tr.nodes([])
             })
             _this.stage.on('mouseover', (evt) => {
@@ -748,7 +763,7 @@ export default {
 
         }
         imageObj.src = require('@/assets/mark/img' + this.counter % 3 + '.jpg')
-        this.markLayer = new Konva.Layer()
+        
 
         this.tr = new Konva.Transformer({
             rotateEnabled: false,
@@ -767,9 +782,9 @@ export default {
 
         //模拟按题阅卷和整体阅卷
         let routeData = this.$route
-        // this.mode = routeData.params.type
+        this.mode = routeData.params.type
         if (routeData.name == 'FullMarkView') this.isFull = true
-        this.mode = 1
+        // this.mode = 1
 
         //监听删除按键,删除图形
         document.onkeydown = e => {
@@ -938,7 +953,7 @@ export default {
     // padding-right: 15px;
 }
 .action-btn {
-    margin-left: 10px;
+    margin-left: 30px;
     cursor: pointer;
 }
 .action-btn-icon {

+ 100 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/markpaper/ProgPie.vue

@@ -0,0 +1,100 @@
+<template>
+    <div id="mark-prog-pie"></div>
+</template>
+<script>
+import elementResizeDetectorMaker from "element-resize-detector"
+export default {
+    data() {
+        return {
+            techScoreGau: undefined,
+            option: {
+                // title: {
+                //     text: '阅卷进度',
+                //     left: 'center',
+                //     textStyle: {
+                //         color: '#ddd',
+                //         fontSize: 12
+                //     }
+                // },
+                tooltip: {
+                    trigger: 'item',
+                    // formatter: '{a} <br/>{b} : {c} ({d}%)'
+                    formatter: '{b} : {c} ({d}%)'
+                },
+                legend: {
+                    top: 10,
+                    itemWidth: 10,
+                    itemHeight: 10,
+                    left: 'center',
+                    data: ['已阅', '进行中', '未阅'],
+                    textStyle: {
+                        color: '#ddd',
+                        fontSize: 11,
+                    },
+                },
+                series: [
+                    {
+                        type: 'pie',
+                        radius: '75%',
+                        center: ['50%', '60%'],
+                        selectedMode: 'single',
+                        data: [
+                            {
+                                value: 510,
+                                name: '已阅',
+                                itemStyle: {
+                                    color: "#9ff080"
+                                },
+                            },
+                            {
+                                value: 434,
+                                name: '进行中',
+                                itemStyle: {
+                                    color: "#5c7bd9"
+                                },
+                            },
+                            {
+                                value: 335,
+                                name: '未阅',
+                                itemStyle: {
+                                    color: "#ffdc60"
+                                },
+                            }
+                        ],
+
+                        label: {
+                            show: false
+                        },
+                        emphasis: {
+                            itemStyle: {
+                                shadowBlur: 10,
+                                shadowOffsetX: 0,
+                                shadowColor: 'rgba(0, 0, 0, 0.5)'
+                            }
+                        }
+                    }
+                ]
+            }
+        }
+    },
+    mounted() {
+        this.techScoreGau = this.$echarts.init(document.getElementById('mark-prog-pie'))
+        this.techScoreGau.setOption(this.option)
+        this.erd = elementResizeDetectorMaker()
+        this.erd.listenTo(document.getElementById("mark-prog-pie"), () => {
+            this.$nextTick(() => {
+                //监听到事件后执行的业务逻辑
+                this.techScoreGau.resize()
+            })
+        })
+    }
+}
+</script>
+<style lang="less" scoped>
+#mark-prog-pie {
+    width: 400px;
+    height: 200px;
+}
+</style>
+<style>
+</style>

+ 1 - 5
TEAMModelOS/ClientApp/src/view/newcourse/ClassTable.less

@@ -11,7 +11,7 @@
     width: 100%;
     // height: ~"calc(100% - 45px)";
     height: 100%;
-    padding: 15px 0px 15px 10px;
+    padding: 15px 0px 15px 0px;
 }
 .sch-title {
     color: white;
@@ -25,10 +25,6 @@
     cursor: pointer;
 }
 
-/*.week-day-cell:hover {
-    background: #404040;
-}*/
-
 .week-day-cell:hover {
     .toggle-status-btn {
         display: inline-block;

+ 100 - 12
TEAMModelOS/ClientApp/src/view/newcourse/ClassTable.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="cus-table-container dark-iview-table">
+    <div class="cus-table-container dark-iview-table cus-table">
         <vuescroll>
             <div class="cus-table-top dark-iview-input dark-iview-select">
                 <div class="class-filter-wrap">
@@ -47,7 +47,7 @@
                         <p :class="['classroom-name']">{{row.weeklies.TUE.teacherName}}</p>
                     </div>
                 </template>
-                <!--星期三-->
+                <!--星期三 -->
                 <template slot-scope="{ row, column }" slot="WED">
                     <div :class="row.weeklies.WED.status == 1 ? 'week-day-cell':'week-day-cell vact-status'">
                         <div class="toggle-status-btn-wrap" v-show="mode == 'set'">
@@ -103,7 +103,7 @@
             </Table>
         </vuescroll>
         <Modal v-model="modalStatus" :title="$t('cusMgt.cusClass')" @on-ok="modalOk" @on-cancel="modalCancel" class-name="dark-iview-modal dark-iview-form dark-iview-select">
-            <Form ref="setCusForm" :model="schd" :label-width="60" label-colon :rules="ruleValidate">
+            <Form ref="setCusForm" :model="schd" :label-width="80" label-colon :rules="ruleValidate">
                 <FormItem :label="$t('cusMgt.course')" prop="setCus">
                     <Select v-show="cusListShow.length" v-model="schd.setCus" filterable style="width:90%;" @on-change="getCusFullInfo">
                         <Option v-for="(item,index) in cusListShow" :key="index" :value="item.id">{{item.name}}</Option>
@@ -114,6 +114,26 @@
                         <Option v-for="(item,index) in cusTeaList" :key="index" :value="item.id" @click.native="setTeaName(item)">{{item.name}}</Option>
                     </Select>
                 </FormItem>
+                <FormItem label="类型">
+                    <RadioGroup v-model="schd.isClass" style="color:white">
+                        <Radio :label="1">
+                            <span>校本班级</span>
+                        </Radio>
+                        <Radio :label="0" style="margin-left:20px">
+                            <span>自定义名单</span>
+                        </Radio>
+                    </RadioGroup>
+                </FormItem>
+                <FormItem label="班级" prop="setTea" v-if="schd.isClass == 1">
+                    <Select v-model="schd.classId" filterable style="width:90%;">
+                        <Option v-for="(item,index) in teaClassList" :key="index" :value="item.id">{{item.name}}</Option>
+                    </Select>
+                </FormItem>
+                <FormItem label="名单" prop="setTea" v-else>
+                    <Select v-model="schd.stulist" filterable style="width:90%;">
+                        <Option v-for="(item,index) in teaStuList" :key="index" :value="item.id">{{item.name}}</Option>
+                    </Select>
+                </FormItem>
             </Form>
         </Modal>
     </div>
@@ -132,7 +152,7 @@ export default {
                 return []
             }
         },
-        classId: {
+        roomId: {
             type: String,
             default: '',
             required: true
@@ -146,11 +166,16 @@ export default {
         return {
             cusList: [],
             classList: [],
+            roomList: [],
+            stuList: [],
             setClass: '',
             schd: {
+                isClass: 1,
                 setCus: '',
                 setTea: '',
-                teaName: ''
+                teaName: '',
+                classId: '',
+                stulist: ''
             },
             ruleValidate: {
                 setCus: [
@@ -219,6 +244,21 @@ export default {
         }
     },
     methods: {
+        //查询名单列表
+        findStuList() {
+            let params = {
+                code: this.$store.state.userInfo.schoolCode,
+                scope: 'school'
+            }
+            this.$api.courseMgmt.findStulist(params).then(
+                res => {
+                    this.stuList = res.stuList
+                },
+                err => {
+                    this.$Message.error('API error')
+                }
+            )
+        },
         //设置教师姓名
         setTeaName(data) {
             this.schd.teaName = data.name
@@ -271,6 +311,8 @@ export default {
                     data.cusId = this.schd.setCus //当前设置的课程
                     data.teaId = this.schd.setTea //当前设置的教师
                     data.teaName = this.schd.teaName //当前设置的教师名字
+                    data.stulist = this.schd.isClass == 1 ? '' : this.schd.stulist
+                    data.classId = this.schd.isClass == 1 ? this.schd.classId : ''
                     data.course = this.cusListShow.find(item => {
                         return item.id == this.schd.setCus
                     })
@@ -334,15 +376,17 @@ export default {
             res => {
                 this.schoolBase = res.school_base
                 this.classList = res.school_classes
+                this.roomList = res.school_rooms
             },
             err => {
                 this.$Message.warning(this.$t('cusMgt.noSchool'))
             }
         )
         this.getCourseList()
+        this.findStuList()
     },
     watch: {
-        classId() {
+        roomId() {
             this.schd = {
                 setCus: '',
                 setTea: ''
@@ -350,6 +394,50 @@ export default {
         }
     },
     computed: {
+        //当前老师班级列表
+        teaClassList() {
+            let curCus = this.cusListShow.find(item => {
+                return item.id == this.schd.setCus
+            })
+            if (curCus && curCus.schedule) {
+                let schedules = curCus.schedule.filter(item=>{
+                    return item.teacherId == this.schd.setTea
+                })
+                let classIds = schedules.map(item => {
+                    return item.classId
+                })
+
+                let classes = this.classList.filter(item => {
+                    return classIds.indexOf(item.id) > -1 
+                })
+                return classes
+            } else {
+                return []
+            }
+
+        },
+        //当前老师班级列表
+        teaStuList() {
+            let curCus = this.cusListShow.find(item => {
+                return item.id == this.schd.setCus
+            })
+            if (curCus && curCus.schedule) {
+                let schedules = curCus.schedule.filter(item=>{
+                    return item.teacherId == this.schd.setTea
+                })
+                let listIds = schedules.map(item => {
+                    return item.stulist
+                })
+
+                let list = this.stuList.filter(item => {
+                    return listIds.indexOf(item.id) > -1
+                })
+                return list
+            } else {
+                return []
+            }
+        },
+
         //当前课程的授课老师
         cusTeaList() {
             if (this.schd.setCus) {
@@ -414,12 +502,12 @@ export default {
                         if (cusItem.schedule) {
                             cusItem.schedule.forEach((schedItem, sIndex) => {
                                 // 只渲染当前班级的schedule
-                                if (schedItem.classId == this.classId) {
-                                    let classInfo = this.classList.find(classItem => {
-                                        return classItem.id == schedItem.classId
+                                if (schedItem.room == this.roomId) {
+                                    let roomInfo = this.roomList.find(roomItem => {
+                                        return roomItem.id == schedItem.room
                                     })
-                                    if (this.classId) {
-                                        if (this.classId != schedItem.classId) {
+                                    if (this.roomId) {
+                                        if (this.roomId != schedItem.room) {
                                             return false
                                         }
                                     }
@@ -428,7 +516,7 @@ export default {
                                             item.weeklies[timeItem.week].courseName = cusItem.name
                                             item.weeklies[timeItem.week].courseId = cusItem.id
                                             item.weeklies[timeItem.week].classId = schedItem.classId
-                                            item.weeklies[timeItem.week].className = classInfo ? classInfo.name : '--'
+                                            item.weeklies[timeItem.week].roomName = roomInfo ? roomInfo.name : '--'
                                             item.weeklies[timeItem.week].teacherName = schedItem.teacherName
                                             item.weeklies[timeItem.week].teacherId = schedItem.teacherId
                                         }

+ 16 - 10
TEAMModelOS/ClientApp/src/view/newcourse/CoursePlan.less

@@ -10,18 +10,15 @@
 .course-plan-container {
     width: 100%;
     height: 100%;
-    display: flex;
-    flex-direction: row;
 
     .class-list-wrap {
-        width: 400px;
-        height: 100%;
-        border-right: 1px solid @borderColor;
+        width: 100%;
+        height: ~"calc(100% - 45px)";
         padding-left: 15px;
     }
 
     .cus-table-wrap {
-        width: ~"calc(100% - 400px)";
+        width: 100%;
         height: 100%;
         padding-left: 15px;
     }
@@ -65,13 +62,14 @@
 }
 
 .class-name {
-    font-size: 20px;
+    font-size: 18px;
     color: white;
-    font-weight: 900;
+    // font-weight: 00;
 }
 .head-teacher{
     color:@second-textColor;
-    margin-top:10px;
+    margin-top:8px;
+    font-size: 12px;
 }
 .cus-table-header {
     width:100%;
@@ -118,7 +116,7 @@
 }
 .cus-table {
     width: ~"calc(100% - 15px)";
-    margin-top: 15px;
+    // margin-top: 15px;
 }
 .sch-title {
     color: white;
@@ -179,4 +177,12 @@
 }
 .cus-table-content{
     height: ~"calc(100% - 45px)";
+}
+.course-table-header{
+    height: 45px;
+    width: 100%;
+    line-height: 45px;
+    border-bottom: 1px solid @borderColor;
+    color: #a5a5a5;
+    padding-left: 10px;
 }

+ 111 - 83
TEAMModelOS/ClientApp/src/view/newcourse/CoursePlan.vue

@@ -1,53 +1,60 @@
 <template>
-    <div class="course-plan-container">
-        <div class="class-list-wrap">
-            <div class="class-list-header">
-                <div v-if="!isSearch">
-                    <BasePdSelect @pd-change="filterByPeriod"></BasePdSelect>
-                    <Icon type="md-search" class="action-btn-icon" @click="toggleSearch" />
-                </div>
-                <div v-else class="dark-iview-input">
-                    <Input icon="ios-close" v-model="classFilter.keyWord" :placeholder="$t('cusMgt.searchHolder')" autofocus style="width:calc(100% - 100px);float:right;margin-top:6px;margin-right:8px" @on-click="toggleSearch" @on-change="onSearchClass" @on-enter="onSearchClass" />
-                </div>
-            </div>
-            <div class="class-list-content">
-                <vuescroll>
-                    <Loading v-show="isListLoading" bgColor="rgba(103, 103, 103, 0.27)"></Loading>
-                    <div class="class-list-item" v-for="(item,index) in classListShow" :key="index" @click="selectClass(index)" :class="curClassIndex == index ? 'block-bg block-bg-active':'block-bg'">
-                        <div class="class-list-item-left">
-                            <p class="class-name">{{item.name}}</p>
-                            <p class="head-teacher">
-                                <span>{{$t('schoolBaseInfo.headmaster')}}</span>
-                                <span class="primary-text-color">{{item.teacher.name}}</span>
-                            </p>
-                        </div>
-                    </div>
-                    <EmptyData v-if="classListShow.length == 0" style="padding-top:120px;"></EmptyData>
-                </vuescroll>
+    <div class="course-plan-container dark-iview-split">
+        <div class="course-table-header">
+            <BasePdSelect @pd-change="filterByPeriod"></BasePdSelect>
+            <div class="action-btn-wrap">
+                <span v-if="$access.can('admin.*|course-upd')" @click="showImportCus()" class="action-btn">
+                    <Icon custom="iconfont icon-upload" size="16" />
+                    <span>{{$t('cusMgt.importLabel')}}</span>
+                </span>
+                <span v-if="$access.can('admin.*|course-upd')" @click="toggleView()" class="action-btn" style="margin-right:40px">
+                    <Icon custom="iconfont icon-kecheng" size="16" />
+                    <span>{{$t('cusMgt.cusMode')}}</span>
+                </span>
             </div>
         </div>
-        <div class="cus-table-wrap">
-            <div class="cus-table-header common-save-btn">
-                <span>{{$t('cusMgt.cusTable')}}</span>
-                <div class="action-btn-wrap">
-                    <span v-if="$access.can('admin.*|course-upd')" @click="showImportCus()" class="action-btn">
-                        <Icon custom="iconfont icon-upload" size="16" />
-                        <span>{{$t('cusMgt.importLabel')}}</span>
-                    </span>
-                    <span v-if="$access.can('admin.*|course-upd')" @click="toggleView()" class="action-btn" style="margin-right:40px">
-                        <Icon custom="iconfont icon-kecheng" size="16" />
-                        <span>{{$t('cusMgt.cusMode')}}</span>
-                    </span>
+        <Split v-model="split1">
+            <div class="class-list-wrap" slot="left">
+                <div class="class-list-header">
+                    <div v-if="!isSearch">
+                        <span>教室</span>
+                        <Icon type="md-search" class="action-btn-icon" @click="toggleSearch" />
+                    </div>
+                    <div v-else class="dark-iview-input">
+                        <Input icon="ios-close" v-model="classFilter.keyWord" :placeholder="$t('cusMgt.searchHolder')" autofocus style="width:calc(100% - 100px);float:right;margin-top:6px;margin-right:8px" @on-click="toggleSearch" @on-change="onSearchClass" @on-enter="onSearchClass" />
+                    </div>
+                </div>
+                <div class="class-list-content">
+                    <vuescroll>
+                        <Loading v-show="isListLoading" bgColor="rgba(103, 103, 103, 0.27)"></Loading>
+                        <div class="class-list-item" v-for="(item,index) in roomListShow" :key="index" @click="selectClass(index)" :class="curClassIndex == index ? 'block-bg block-bg-active':'block-bg'">
+                            <div class="class-list-item-left">
+                                <p class="class-name">{{item.name}}</p>
+                                <p class="head-teacher">
+                                    <span>教室类型:</span>
+                                    <span class="primary-text-color">{{item.style}}</span>
+                                </p>
+                            </div>
+                        </div>
+                        <EmptyData v-if="roomListShow.length == 0" style="padding-top:120px;"></EmptyData>
+                    </vuescroll>
                 </div>
             </div>
-            <div class="cus-table-content dark-iview-table">
-                <vuescroll>
-                    <!-- 班级课程表 -->
-                    <ClassTable v-if="this.classListShow[this.curClassIndex]" :schedData="classCus" :classId="classListShow[curClassIndex].id" :periodId="pdId" @selectCell="selectCell" @cancelCell="cancelCell"></ClassTable>
-                    <Loading v-if="isLoading" bgColor="rgba(103, 103, 103, 0.27)"></Loading>
-                </vuescroll>
+            <div class="cus-table-wrap" slot="right">
+                <!-- <div class="cus-table-header common-save-btn">
+                    <span>{{$t('cusMgt.cusTable')}}</span>
+                    
+                </div> -->
+                <div class="cus-table-content dark-iview-table">
+                    <vuescroll>
+                        <!-- 班级课程表 -->
+                        <ClassTable v-if="this.roomListShow[this.curClassIndex]" :schedData="roomCus" :roomId="roomListShow[curClassIndex].id" :periodId="pdId" @selectCell="selectCell" @cancelCell="cancelCell"></ClassTable>
+                        <Loading v-if="isLoading" bgColor="rgba(103, 103, 103, 0.27)"></Loading>
+                    </vuescroll>
+                </div>
             </div>
-        </div>
+        </Split>
+
         <!--导入课表功能尚未开发-->
         <Modal v-model="importCusStatus" title="导入课表" width="1000" class-name="dark-iview-modal" @on-ok="confImpStatus = true" @on-cancel="cancelImport">
             <ImportExcel ref="impXls" :headerKeys="headerKeys" :headerTitles="headerTitles" @getTableData="getTableData"></ImportExcel>
@@ -80,6 +87,7 @@ export default {
     inject: ['reload'],
     data() {
         return {
+            split1: 0.2,
             pdId: '',
             confImpStatus: false,
             classFilter: {
@@ -100,8 +108,8 @@ export default {
             schoolInfo: {},
             subIndex: 0,
             isListLoading: false,
-            classList: [],
-            classListShow: [],
+            roomList: [],
+            roomListShow: [],
             curClassIndex: 0,
             tableData: [],
             importData: [],
@@ -114,12 +122,12 @@ export default {
             this.pdId = pd
             this.curClassIndex = 0
             if (pd) {
-                this.classListShow = this.classList.filter(item => item.periodId == pd || !item.periodId)
+                this.roomListShow = this.roomList.filter(item => item.periodId == pd || !item.periodId)
             } else {
-                this.classListShow = [...this.classList]
+                this.roomListShow = [...this.roomList]
             }
             // 排序
-            this.classListShow = this.dataSort(this.classListShow)
+            this.roomListShow = this.dataSort(this.roomListShow)
         },
         dataSort(data) {
             switch (this.orderBy) {
@@ -163,7 +171,7 @@ export default {
         },
         //关键字搜索班级
         onSearchClass() {
-            this.classListShow = this.classList.filter((item) => {
+            this.roomListShow = this.roomList.filter((item) => {
                 return item.name.indexOf(this.classFilter.keyWord) !== -1
             })
         },
@@ -183,7 +191,7 @@ export default {
             } else {
                 for (let itemData of data) {
                     //验证班级code
-                    let classroom = this.classList.filter((item) => {
+                    let classroom = this.roomList.filter((item) => {
                         return item.classroomCode == itemData.classroomCode
                     })
                     if (classroom.length == 0) {
@@ -286,8 +294,8 @@ export default {
         },
         selectClass(index) {
             this.curClassIndex = index
-            let classId = this.classListShow[this.curClassIndex].id
-            if (!this.allClassCus[classId]) {
+            let roomId = this.roomListShow[this.curClassIndex].id
+            if (!this.allClassCus[roomId]) {
                 this.isLoading = true
                 this.findClassCus()
             }
@@ -295,17 +303,17 @@ export default {
 
         //根据班级查询课程安排
         findClassCus() {
-            if (this.classListShow.length > 0) {
-                let classId = this.classListShow[this.curClassIndex].id
+            if (this.roomListShow.length > 0) {
+                let roomId = this.roomListShow[this.curClassIndex].id
                 let requestData = {
-                    id: classId,
+                    id: roomId,
                     code: this.$store.state.userInfo.schoolCode,
                     scope: 'school'
                 }
-                this.$api.courseMgmt.findCusByClass(requestData).then(
+                this.$api.courseMgmt.findCusByRoom(requestData).then(
                     (res) => {
                         if (!res.error) {
-                            this.$set(this.allClassCus, classId, res.courses)
+                            this.$set(this.allClassCus, roomId, res.courses)
                             this.isLoading = false
                         } else {
                             this.$Message.error('API error!')
@@ -322,44 +330,64 @@ export default {
         },
         //设置课程事件
         selectCell(data) {
+            console.log('设置数据', data)
             //data里面包含当前课程完整信息
             let course = data.course
             course.schedule = course.schedule || []
+            //先查看是否有还没有设置教室的对应安排
             let schedule = course.schedule.find(item => {
-                return item.classId == this.classListShow[this.curClassIndex].id && item.teacherId == data.teaId
+                // return item.room == this.roomListShow[this.curClassIndex].id && item.teacherId == data.teaId
+                return !item.room && item.teacherId == data.teaId && item.classId == data.classId && item.stulist == data.stulist
             })
+            //1、如果有还未设置教室的课程安排优先使用
             if (schedule) {
+                schedule.room = this.roomListShow[this.curClassIndex].id
                 schedule.time.push({
                     week: data.col,
                     id: data.row.id
                 })
             } else {
-                schedule = {
-                    classId: this.classListShow[this.curClassIndex].id,
-                    notice: '',
-                    stulist: '',
-                    teacherId: data.teaId,
-                    teacherName: data.teaName,
-                    time: []
-                }
-                schedule.time.push({
-                    week: data.col,
-                    id: data.row.id
+
+                schedule = course.schedule.find(item => {
+                    return item.room == this.roomListShow[this.curClassIndex].id && item.teacherId == data.teaId
                 })
-                course.schedule.push(schedule)
+                //2、如果此教室已经有对应的安排则直接添加时间即可
+                if (schedule) {
+                    schedule.time.push({
+                        week: data.col,
+                        id: data.row.id
+                    })
+                } 
+                // 3、如果没有空的课程安排,也没有对应教室的安排,则新建一个schedule
+                else {
+                    schedule = {
+                        room: this.roomListShow[this.curClassIndex].id,
+                        classId: data.classId,
+                        notice: '',
+                        stulist: data.stulist,
+                        teacherId: data.teaId,
+                        teacherName: data.teaName,
+                        time: []
+                    }
+                    schedule.time.push({
+                        week: data.col,
+                        id: data.row.id
+                    })
+                    course.schedule.push(schedule)
+                }
+
             }
             this.updCusInfo(course, 'set')
         },
         //取消设置课程
         cancelCell(data) {
-            let classId = this.classListShow[this.curClassIndex].id
+            let roomId = this.roomListShow[this.curClassIndex].id
             let info = data.row.weeklies[data.col]
-            console.log(data)
-            let cus = this.allClassCus[classId].find(item => {
+            let cus = this.allClassCus[roomId].find(item => {
                 return item.id == info.courseId
             })
             cus.schedule.forEach(schdItem => {
-                if (schdItem.classId == classId && schdItem.teacherId == info.teacherId) {
+                if (schdItem.room == roomId && schdItem.teacherId == info.teacherId) {
                     schdItem.time.forEach((item, index) => {
                         if (item.id == data.row.id && item.week == data.col) {
                             schdItem.time.splice(index, 1)
@@ -379,10 +407,10 @@ export default {
             }).then(
                 res => {
                     this.$Message.success(this.$t('cusMgt.updateOk'))
-                    let classId = this.classListShow[this.curClassIndex].id
+                    let classId = this.roomListShow[this.curClassIndex].id
                     if (type == 'set') {
                         //更新成功后,更新本地数据,刷新课程表
-                        
+
                         this.allClassCus[classId] = this.allClassCus[classId] || []
                         let isExist = false
                         this.allClassCus[classId].forEach((item, index) => {
@@ -417,8 +445,8 @@ export default {
                     this.filterPeriod = this.schoolInfo.period[0].id
                     this.hasTimeTable = this.schoolInfo.period[0].timetable ? true : false
                 }
-                this.classList = res.school_classes
-                this.classListShow = [...this.classList]
+                this.roomList = res.school_rooms
+                this.roomListShow = [...this.roomList]
             },
             err => {
                 this.$Message.warning(this.$t('cusMgt.noSchool'))
@@ -429,10 +457,10 @@ export default {
     },
     computed: {
         //当前班级对应的课程数据
-        classCus() {
-            let classId = this.classListShow[this.curClassIndex].id
-            if (classId && this.allClassCus[classId]) {
-                return this.allClassCus[classId]
+        roomCus() {
+            let roomId = this.roomListShow[this.curClassIndex].id
+            if (roomId && this.allClassCus[roomId]) {
+                return this.allClassCus[roomId]
             } else {
                 return []
             }

+ 6 - 0
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.less

@@ -329,4 +329,10 @@
         width: 100%;
         height: ~"calc(100% - 40px)";
     }
+}
+.qr-code-icon{
+    position: absolute;
+    right: 15px;
+    top: 50%;
+    margin-top: -10px;
 }

+ 154 - 96
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue

@@ -55,18 +55,19 @@
                         <div class="course-classroom-list-content">
                             <vuescroll>
                                 <div v-for="(item,index) in teaClassList" :key="index" @click="changeClassroom(index)" :class="['block-bg','tea-class-item',curClassIndex == index ? 'block-bg-active':'']">
-                                    <p class="class-attr-item" v-show="listType == 'school'">
-                                        <span class="attr-label">{{$t('cusMgt.classLabel')}}</span>
-                                        <span class="class-name">{{item.classId ? item.classInfo.name:'--'}}</span>
-                                    </p>
                                     <p class="class-attr-item">
                                         <span class="attr-label">{{$t('cusMgt.nameLabel')}}</span>
-                                        <span :class="item.stulist ? 'class-name':'def-class-name'">{{item.stulist ? item.listName : $t('cusMgt.defaultList')}}</span>
+                                        <span class="class-name">{{item.classId ? item.classInfo.name: item.listName || '--'}}</span>
                                     </p>
-                                    <p class="class-attr-item" v-show="listType == 'private'">
+                                    <!-- <p class="class-attr-item">
+                                        <span class="attr-label">{{$t('cusMgt.nameLabel')}}</span>
+                                        <span :class="item.stulist ? 'class-name':'def-class-name'">{{item.stulist ? item.listName : $t('cusMgt.defaultList')}}</span>
+                                    </p> -->
+                                    <p class="class-attr-item">
                                         <span class="attr-label">{{$t('cusMgt.stuCount')}}:</span>
                                         <span class="class-name">{{item.students ? item.students.length : 0}}{{$t('unit.text7')}}</span>
                                     </p>
+                                    <Icon size="20" custom="iconfont icon-qr-code" class="qr-code-icon" @click="showQrCode" v-if="listType == 'private'" />
                                 </div>
                                 <EmptyData v-if="teaClassList.length == 0" :top="160" :textContent="$t('cusMgt.noClassList')"></EmptyData>
                             </vuescroll>
@@ -77,12 +78,14 @@
                             <span @click="selectTab('record')" :class="tabName == 'record' ? 'course-classroom-label line-bottom line-bottom-active':'course-classroom-label line-bottom'">{{$t('cusMgt.cusRecord')}}</span>
                             <span @click="selectTab('activity')" :class="tabName == 'activity' ? 'course-classroom-label line-bottom line-bottom-active':'course-classroom-label line-bottom'">{{$t('cusMgt.acRecord')}}</span>
                             <span @click="selectTab('stus')" :class="tabName == 'stus' ? 'course-classroom-label line-bottom line-bottom-active':'course-classroom-label line-bottom'">{{$t('courseManage.classroom.studentList')}}</span>
-                            <div style="float:right;color:white;" v-if="(listType == 'private' && tabName == 'stus') || (listType == 'school' && tabName == 'stus' && classList[curClassIndex].openType == 2)">
+                            <!-- 个人课程时段设置暂不实做 -->
+                            <!-- <span @click="selectTab('time')" :class="tabName == 'time' ? 'course-classroom-label line-bottom line-bottom-active':'course-classroom-label line-bottom'">{{$t('cusMgt.cusTime')}}</span> -->
+                            <div style="float:right;color:white;" v-if="listType == 'private' && tabName == 'stus'">
                                 <span class="action-btn-wrap" @click="delStudents">
                                     <Icon type="md-trash" size="16" />
                                     {{$t('cusMgt.delStu')}}
                                 </span>
-                                <span class="action-btn-wrap" @click="addStuStatus = true" v-if="classList[curClassIndex] && (classList[curClassIndex].openType == 2 || listType == 'private')">
+                                <span class="action-btn-wrap" @click="addStuStatus = true">
                                     <Icon type="md-add" size="16" />
                                     {{$t('cusMgt.addStu')}}
                                 </span>
@@ -203,7 +206,21 @@
                                 <EmptyData v-show="acList.length == 0" :textContent="acTypeLabel + $t('cusMgt.noAc')" :top="150"></EmptyData>
                             </vuescroll>
                         </div>
-                    </div>
+                        <!-- 课程时段 暂不实做-->
+                        <!-- <div v-show="tabName == 'time'" class="animated fadeIn class-record-wrap">
+                            <vuescroll>
+                                <h2 style="margin-top:120px;color:#ddd;text-align:center"> 
+                                    1、如果教师没有加入学校,拿不到时段设置,不能渲染课表;
+                                </h2>
+                                <h2 style="margin-top:20px;color:#ddd;text-align:center">
+                                    2、个人课程没有关联学段,不能确定使用哪个学段的时间;
+                                </h2>
+                                <h2 style="margin-top:20px;color:#ddd;text-align:center">
+                                    3、如果支持老师个人创建时段管理,会不会变成学校可以用的老师都能用。
+                                </h2>
+                            </vuescroll>
+                        </div>-->
+                    </div> 
                 </Split>
             </div>
         </Split>
@@ -288,7 +305,7 @@
                 </FormItem>
             </Form>
             <Form ref="addCusInfo" :model="addCusInfo" :rules="ruleAddCus">
-                <FormItem prop="no" :label="$t('cusMgt.cusCode')">
+                <FormItem :label="$t('cusMgt.cusCode')">
                     <Input type="text" v-model="addCusInfo.no" :placeholder="$t('cusMgt.codeHolder')"></Input>
                 </FormItem>
             </Form>
@@ -413,6 +430,11 @@ export default {
                 }
             ],
             listColumn: [
+                {
+                    type: 'selection',
+                    align: 'center ',
+                    width: '150'
+                },
                 {
                     title: ' ',
                     slot: 'picture',
@@ -736,31 +758,43 @@ export default {
                     content: `${this.$t('cusMgt.delStuContent')}${names.join(', ')}?`,
                     onOk: () => {
                         this.listLoading = true
-                        this.delSelection.forEach(item => {
-                            let index = this.courseListShow[this.curCusIndex].classes[this.curClassIndex].students.findIndex(stu => {
-                                return stu.id == item.id
-                            })
-                            this.courseListShow[this.curCusIndex].classes[this.curClassIndex].students.splice(index, 1)
+                        let delIds = this.delSelection.map(item => {
+                            return item.id
                         })
-                        this.$api.schoolSetting.classUpsert({
-                            classroom: this.courseListShow[this.curCusIndex].classes[this.curClassIndex],
-                            option: 'update',
-                            school_code: this.$store.state.userInfo.TEAMModelId
-                        }).then(
-                            (res) => {
-                                if (!res.error) {
-                                    this.selections = []
-                                    this.$Message.success(this.$t('cusMgt.delOk'))
-                                } else {
-                                    this.$Message.error(this.$t('cusMgt.delErr'))
+                        //删除学生更新stulist
+                        // 当前名单对应的课程安排用于更新UI
+                        let schedule = this.courseListShow[this.curCusIndex].schedule.find(item => {
+                            return item.stulist == this.teaClassList[this.curClassIndex].stulist && item.classId == '' //只有自定名单能添加学生,所以classId == ‘’
+                        })
+                        //当前名单完整信息 用于更新名单API
+                        let stulist = this.stuList.find(item => {
+                            return item.id == this.teaClassList[this.curClassIndex].stulist
+                        })
+                        for (let i = 0; i < stulist.students.length; i++) {
+                            if (delIds.indexOf(stulist.students[i].id) > -1) {
+                                stulist.students.splice(i, 1)
+                                i--
+                            }
+                        }
+                        let params = {
+                            stuList: stulist,
+                            scope: "private"
+                        }
+                        this.$api.courseMgmt.upsertStulist(params).then(
+                            res => {
+                                this.$Message.success(this.$t('cusMgt.delOk'))
+                                for (let i = 0; i < schedule.students.length; i++) {
+                                    if (delIds.indexOf(schedule.students[i].id) > -1) {
+                                        schedule.students.splice(i, 1)
+                                        i--
+                                    }
                                 }
                             },
-                            (err) => {
+                            err => {
                                 this.$Message.error(this.$t('cusMgt.delErr'))
                             }
                         ).finally(() => {
                             this.listLoading = false
-                            this.baseEditStatus = !this.baseEditStatus
                         })
                     }
                 })
@@ -772,62 +806,75 @@ export default {
         //确认添加学生
         confirmAddStu() {
             if (this.selections.length > 0) {
-                if (!this.courseListShow[this.curCusIndex].classes[this.curClassIndex].students) {
-                    this.$set(this.courseListShow[this.curCusIndex].classes[this.curClassIndex], 'students', [])
-                }
-                let stuIds = this.courseListShow[this.curCusIndex].classes[this.curClassIndex].students.map(item => {
-                    return item.id
+                //这里会报错,应该是之前的结构,后面调整结构后没有进行处理 已经没有classes字段
+                // if (!this.courseListShow[this.curCusIndex].classes[this.curClassIndex].students) {
+                //     this.$set(this.courseListShow[this.curCusIndex].classes[this.curClassIndex], 'students', [])
+                // }
+                // let stuIds = this.courseListShow[this.curCusIndex].classes[this.curClassIndex].students.map(item => {
+                //     return item.id
+                // })
+                // 当前名单对应的课程安排用于更新UI
+                let schedule = this.courseListShow[this.curCusIndex].schedule.find(item => {
+                    return item.stulist == this.teaClassList[this.curClassIndex].stulist && item.classId == '' //只有自定名单能添加学生,所以classId == ‘’
                 })
-                if (stuIds.length > 0) {
-                    //如果已经有学生,根据账号去重
-                    let hasRepeat = false
-                    this.selections.forEach(item => {
-                        if (stuIds.indexOf(item.id) == -1) {
-                            this.courseListShow[this.curCusIndex].classes[this.curClassIndex].students.push({
-                                id: item.id,
-                                name: item.name,
-                                no: item.no
-                            })
-                        } else {
-                            hasRepeat = true
-                        }
+                //当前名单完整信息 用于更新名单API
+                let stulist = this.stuList.find(item => {
+                    return item.id == this.teaClassList[this.curClassIndex].stulist
+                })
+                let stuIds = []
+                if (schedule) {
+                    stuIds = schedule.students.map(item => {
+                        return item.id
                     })
-                    if (hasRepeat) {
-                        //this.$Message.warning('已经自动帮您去掉账号重复的学生!')
-                    }
-                } else {
-                    let stus = this.selections.map(item => {
-                        return {
+                }
+                let hasRepeat = false
+                this.selections.forEach(item => {
+                    if (stuIds.indexOf(item.id) == -1) { //如果已经有学生,根据账号去重
+                        schedule.students.push({
                             id: item.id,
+                            code: 'Base-' + this.$store.state.userInfo.schoolCode, //学生所在学校的编码,这里先传当前学校编码,暂无未考虑跨校名单
+                            schoolId: this.$store.state.userInfo.schoolCode, //学生所在学校的编码,这里先传当前学校编码,暂无未考虑跨校名单
                             name: item.name,
-                            no: item.no
-                        }
-                    })
-                    this.courseListShow[this.curCusIndex].classes[this.curClassIndex].students.push(...stus)
-                }
-                //保存操作
-                this.listLoading = true
-                this.courseListShow[this.curCusIndex].code = this.$store.state.userInfo.TEAMModelId
-                this.$api.schoolSetting.classUpsert({
-                    classroom: this.courseListShow[this.curCusIndex].classes[this.curClassIndex],
-                    option: 'update',
-                    'school_code': this.$store.state.userInfo.TEAMModelId
-                }).then(
-                    (res) => {
-                        if (!res.error) {
-                            this.selections.length = 0
-                            this.$Message.success(this.$t('cusMgt.addOk'))
-                        } else {
-                            this.$Message.error(this.$t('cusMgt.delErr'))
-                        }
-                    },
-                    (err) => {
-                        this.$Message.error(this.$t('cusMgt.delErr'))
+                            className: item.className,
+                            classId: item.classId
+                        })
+                        stulist.students.push({
+                            id: item.id,
+                            code: 'Base-' + this.$store.state.userInfo.schoolCode, //学生所在学校的编码,这里先传当前学校编码,暂无未考虑跨校名单
+                            schoolId: this.$store.state.userInfo.schoolCode //学生所在学校的编码,这里先传当前学校编码,暂无未考虑跨校名单
+                        })
+                    } else {
+                        hasRepeat = true
                     }
-                ).finally(() => {
-                    this.listLoading = false
-                    this.baseEditStatus = !this.baseEditStatus
                 })
+                if (hasRepeat) {
+                    //this.$Message.warning('已经自动帮您去掉账号重复的学生!')
+                }
+
+                this.listLoading = true
+                this.saveStuList(stulist)
+                //保存操作 过时的操作逻辑
+                // this.courseListShow[this.curCusIndex].code = this.$store.state.userInfo.TEAMModelId
+                // this.$api.schoolSetting.classUpsert({
+                //     classroom: this.courseListShow[this.curCusIndex].classes[this.curClassIndex],
+                //     option: 'update',
+                //     'school_code': this.$store.state.userInfo.TEAMModelId
+                // }).then(
+                //     (res) => {
+                //         if (!res.error) {
+                //             this.selections.length = 0
+                //             this.$Message.success(this.$t('cusMgt.addOk'))
+                //         } else {
+                //             this.$Message.error(this.$t('cusMgt.delErr'))
+                //         }
+                //     },
+                //     (err) => {
+                //         this.$Message.error(this.$t('cusMgt.delErr'))
+                //     }
+                // ).finally(() => {
+                //     this.listLoading = false
+                //     this.baseEditStatus = !this.baseEditStatus
+                // })
             }
         },
 
@@ -915,15 +962,17 @@ export default {
             })
         },
         showQrCode() {
+            console.log(this.teaClassList)
             this.showQrStatus = true
             let tId = this.$store.state.userInfo.TEAMModelId
             let tName = this.$store.state.userInfo.name
-            let cId = this.classList[this.curClassIndex].id
-            let cName = this.classList[this.curClassIndex].name
+            let cId = this.teaClassList[this.curClassIndex].stulist
+            let cName = this.teaClassList[this.curClassIndex].listName
             this.createQRCode(`http://teammodelos-test.chinacloudsites.cn/joinclass?tId=${tId}&cId=${cId}&tName=${tName}&cName=${cName}`)
         },
         //确认添加自定义名单
         confirmCreateList() {
+            console.log('学生名单', this.createStuList)
             if (!this.listName) {
                 this.$Message.warning(this.$t('cusMgt.nameWarning'))
                 this.modalLoading = false
@@ -935,20 +984,24 @@ export default {
                     name: this.listName,
                     id: this.$tools.guid(),
                     code: this.$store.state.userInfo.TEAMModelId,
-                    students: this.createStuList.map(item => { //这里没有学生名字, 需要先查看id集合再查学生信息?
+                    students: this.createStuList.map(item => {
                         return {
                             id: item.id,
-                            code: item.code //学生所在学校的编码,这里先传当前学校编码,暂无未考虑跨校名单
+                            code: 'Base-' + this.$store.state.userInfo.schoolCode, //学生所在学校的编码,这里先传当前学校编码,暂无未考虑跨校名单
+                            schoolId: this.$store.state.userInfo.schoolCode, //学生所在学校的编码,这里先传当前学校编码,暂无未考虑跨校名单
+                            name: item.name,
+                            className: item.className,
+                            classId: item.classId
                         }
                     }),
                     tmids: [],
                     course: null
                 }
-                this.saveStuList(stuList)
+                this.saveStuList(stuList, true)
             }
         },
         // 保存名单
-        saveStuList(stuList) {
+        saveStuList(stuList, isUpdCus) {
             let params = {
                 stuList,
                 scope: "private"
@@ -957,17 +1010,20 @@ export default {
                 res => {
                     this.newSlStatus = false
                     //TODO 添加到当前课程schedule
-                    this.courseListShow[this.curCusIndex].schedule = this.courseListShow[this.curCusIndex].schedule || []
-                    this.courseListShow[this.curCusIndex].schedule.push({
-                        classId: '',
-                        notice: '',
-                        listName: this.listName,
-                        stulist: stuList.id,
-                        teacherId: this.$store.state.userInfo.TEAMModelId,
-                        teacherName: this.$store.state.userInfo.name,
-                        time: []
-                    })
-                    this.updCusInfo()
+                    if (isUpdCus) {
+                        this.courseListShow[this.curCusIndex].schedule = this.courseListShow[this.curCusIndex].schedule || []
+                        this.courseListShow[this.curCusIndex].schedule.push({
+                            classId: '',
+                            notice: '',
+                            listName: this.listName,
+                            stulist: stuList.id,
+                            teacherId: this.$store.state.userInfo.TEAMModelId,
+                            teacherName: this.$store.state.userInfo.name,
+                            students: stuList.students,
+                            time: []
+                        })
+                        this.updCusInfo()
+                    }
                 },
                 err => {
                     this.modalLoading = false
@@ -975,7 +1031,9 @@ export default {
                         this.modalLoading = true
                     }, 0)
                 }
-            )
+            ).finally(() => {
+                this.listLoading = false
+            })
         },
 
         changeClassroom(index) {

+ 3 - 2
TEAMModelOS/ClientApp/src/view/newcourse/NewCusMgt.less

@@ -206,7 +206,8 @@
 }
 
 .set-stu-list{
-    padding-left: 10px;
+    padding-left: 4px;
+    height: 100%;
 }
 
 .action-btn {
@@ -238,7 +239,7 @@
     }
 }
 .stu-list-table{
-    margin-top: 10px;
+    margin-top: 1px;
 }
 .create-list-icon{
     font-size: 18px;

+ 212 - 115
TEAMModelOS/ClientApp/src/view/newcourse/NewCusMgt.vue

@@ -18,14 +18,6 @@
                     <Icon custom="iconfont icon-schedule" size="16" />
                     <span>{{$t('cusMgt.schdTable')}}</span>
                 </span>
-                <span v-if="$access.can('admin.*|course-upd')" @click="showTime = true" class="action-btn">
-                    <Icon custom="iconfont icon-time" size="16" />
-                    <span>{{$t('cusMgt.timeSetting')}}</span>
-                </span>
-                <span @click="goMgtStuList" :class="courseListShow.length == 0 ? 'action-btn-disabled action-btn':'action-btn'">
-                    <Icon type="ios-people" size="16" />
-                    <span>{{$t('cusMgt.stuListMgt')}}</span>
-                </span>
             </div>
         </div>
         <Split v-model="split1">
@@ -85,12 +77,16 @@
                     <!-- 上课名单、上课时段设置 -->
                     <div slot="right" class="class-setting" v-show="!isAddStuList && !addTeaStatus">
                         <div class="teacher-list-header">
-                            <span @click="curTab = 0" :class="curTab == 0 ? 'tab-label line-bottom line-bottom-active':'tab-label line-bottom'">
+                            <span class="tab-label" style="padding-left:10px">
                                 {{$t('cusMgt.cusNameList')}}
                             </span>
-                            <span @click="selectTab(1)" :class="curTab == 1 ? 'tab-label line-bottom line-bottom-active':'tab-label line-bottom'">
+                            <!-- <span @click="curTab = 0" :class="curTab == 0 ? 'tab-label line-bottom line-bottom-active':'tab-label line-bottom'">
+                                {{$t('cusMgt.cusNameList')}}
+                            </span> -->
+                            <!-- 取消根据老师设置课程时段的功能 -->
+                            <!-- <span @click="selectTab(1)" :class="curTab == 1 ? 'tab-label line-bottom line-bottom-active':'tab-label line-bottom'">
                                 {{$t('cusMgt.cusTime')}}
-                            </span>
+                            </span> -->
                             <div class="action-btn-wrap">
                                 <span class="action-btn" style="margin-right:30px" @click="updCusInfo()" v-if="isUpd">
                                     <Icon type="ios-albums-outline" size="16" />
@@ -101,79 +97,72 @@
                                     <span>{{$t('cusMgt.addStuList')}}</span>
                                 </span>
                                 <span class="action-btn" v-show="curTab == 0" @click="removeStuList">
-                                    <Icon type="md-trash" size="16" />
+                                    <Icon type="md-remove-circle" size="16" />
                                     <span>{{$t('cusMgt.removeList')}}</span>
                                 </span>
                             </div>
                         </div>
-                        <!-- 教师上课时段设置 -->
                         <div class="cus-time-setting">
-                            <!-- 设置授课教室/名单 -->
+                            <!-- 设置上课班级/名单 -->
                             <div class="set-cus-class" v-show="curTab == 0">
                                 <Split v-model="split3" v-show="schdList.length > 0">
-                                    <!-- 教室列表 -->
+                                    <!-- 名单列表 -->
                                     <div slot="left" class="class-list">
                                         <div v-for="(item,index) in schdList" :key="index" @click="selectClass(index)" :class="['block-bg','tea-class-item',curClassIndex == index ? 'block-bg-active':'']">
+                                            <!-- 上课班级/名单 -->
                                             <p class="class-attr-item">
-                                                <span class="attr-label">{{$t('cusMgt.classLabel')}}</span>
-                                                <span class="class-name">{{item.classId ? item.classInfo.name : $t('cusMgt.noSet')}}</span>
-                                                <!-- <span class="class-label" :style="{color:item.type == '专科教室' ? '#2db7f5' : item.type == '普通教室' ? '#19be6b' : '#ff9900',borderColor:item.type == '专科教室' ? '#2db7f5' : item.type == '普通教室' ? '#19be6b' : '#ff9900'}">
-                                                    {{item.type}}
-                                                </span> -->
+                                                <span class="attr-label">{{$t('cusMgt.nameLabel')}} </span>
+                                                <span class="class-name">{{item.classId ? item.classInfo.name : item.listName }}</span>
                                             </p>
                                             <p class="class-attr-item">
-                                                <span class="attr-label">{{$t('cusMgt.nameLabel')}}</span>
-                                                <span :class="item.stulist ? 'class-name':'def-class-name'">{{item.stulist ? item.listName : $t('cusMgt.defaultList')}}</span>
+                                                <span class="attr-label">学生人数:</span>
+                                                <span class="class-name">--人</span>
                                             </p>
+                                            <!-- 上课地点 取消设置上课教室-->
+                                            <!-- <p class="class-attr-item">
+                                                <span class="attr-label">{{$t('cusMgt.addrLabel')}} </span>
+                                                <span :class="item.room ? 'class-name':'def-class-name'">{{item.room && item.roomInfo ? item.roomInfo.name : $t('cusMgt.noSet')}}</span>
+                                            </p> -->
                                         </div>
                                     </div>
                                     <!-- 设置教室名单 -->
                                     <div slot="right" class="set-stu-list dark-iview-table dark-el-cascader" v-if="schdList[curClassIndex]">
-                                        <div class="stu-list-header dark-iview-select">
-                                            <span class="attr-label">{{$t('cusMgt.classLabel')}}</span>
-                                            <el-cascader size="mini" :placeholder="$t('cusMgt.noSet')" :show-all-levels="false" clearable v-model="schdList[curClassIndex].classId" :options="csOptions" :props="props" @change="setClassName($event,'upsert')" style="width:180px;">
-                                            </el-cascader>
-                                            <span class="attr-label" style="margin-left:50px">{{$t('cusMgt.defaultList')}}</span>
-                                            <Tooltip :content="$t('cusMgt.defaultTips')" max-width="200">
-                                                <Icon type="ios-information-circle-outline" style="margin-left:2px;margin-right:5px" />
-                                            </Tooltip>
-                                            <span>
-                                                <i-switch v-model="isDefault" size="small" :before-change="handleSwitch" />
-                                            </span>
-                                            <span v-show="!isDefault" class="attr-label" style="margin-left:50px">{{$t('cusMgt.nameLabel')}}</span>
-                                            <Select ref="sltStuList" v-show="!isDefault" clearable v-model="schdList[curClassIndex].stulist" style="width:200px;margin-right:5px" size="small">
-                                                <Option v-for="(item,index) in stuList" :value="item.id" :key="index" @click.native="updateStuList(item.name)">{{ item.name }}</Option>
+                                        <!-- <div class="stu-list-header dark-iview-select">
+                                            <span class="attr-label">{{$t('cusMgt.addrLabel')}}</span>
+                                            <Select v-model="schdList[curClassIndex].room" style="width:200px" size="small" filterable clearable @on-clear="updCusInfo">
+                                                <Option v-for="item in roomList" :value="item.id" :key="item.id" @click.native="setCusRoom(item)">{{ item.name }}</Option>
                                             </Select>
-                                            <Icon type="md-add-circle" v-show="!isDefault" style="cursor:pointer" @click="addStuListStatus = true" />
-                                        </div>
-                                        <Table v-if="schdList[curClassIndex]" :columns="schdList[curClassIndex].stulist ? listColumn : classColumn" :data="students" class="stu-list-table" :loading="stuLoading" :no-data-text="$t('cusMgt.noStu')">
-                                            <Loading slot="loading" :top="0" bgColor="rgba(103, 103, 103, 0.27)"></Loading>
-                                            <template slot-scope="{ row }" slot="picture">
-                                                <PersonalPhoto :name="row.name" :picture="row.picture" />
-                                            </template>
-                                            <template slot-scope="{ row,index }" slot="no">
-                                                <span>{{row.no}}</span>
-                                            </template>
-                                            <template slot-scope="{ row ,index}" slot="action">
-                                                <div class="item-tools" v-if="$access.can('admin.*|student-upd')">
-                                                    <Icon type="md-create" size="18" color="white" @click="resetNo(index)" :title="$t('schoolBaseInfo.editSeat')" />
-                                                    <Icon type="md-remove-circle" size="18" color="white" style="margin-left:10px" @click="removeStudent(index)" :title="$t('schoolBaseInfo.delStuBtn')" />
-                                                </div>
-                                            </template>
-                                            <template slot-scope="{ row, index }" slot="groupId">
-                                                <span>{{row.groupId ? row.groupId : '- -'}}</span>
-                                            </template>
-                                            <template slot-scope="{ row, index }" slot="groupName">
-                                                <span>{{row.groupName ? row.groupName : $t('cusMgt.noGroup')}}</span>
-                                            </template>
-                                        </Table>
+                                        </div> -->
+                                        <vuescroll>
+                                            <Table v-if="schdList[curClassIndex]" :columns="schdList[curClassIndex].stulist ? listColumn : classColumn" :data="students" class="stu-list-table" :loading="stuLoading" :no-data-text="$t('cusMgt.noStu')">
+                                                <Loading slot="loading" :top="0" bgColor="rgba(103, 103, 103, 0.27)"></Loading>
+                                                <template slot-scope="{ row }" slot="picture">
+                                                    <PersonalPhoto :name="row.name" :picture="row.picture" />
+                                                </template>
+                                                <template slot-scope="{ row,index }" slot="no">
+                                                    <span>{{row.no}}</span>
+                                                </template>
+                                                <template slot-scope="{ row ,index}" slot="action">
+                                                    <div class="item-tools" v-if="$access.can('admin.*|student-upd')">
+                                                        <Icon type="md-create" size="18" color="white" @click="resetNo(index)" :title="$t('schoolBaseInfo.editSeat')" />
+                                                        <Icon type="md-remove-circle" size="18" color="white" style="margin-left:10px" @click="removeStudent(index)" :title="$t('schoolBaseInfo.delStuBtn')" />
+                                                    </div>
+                                                </template>
+                                                <template slot-scope="{ row, index }" slot="groupId">
+                                                    <span>{{row.groupId ? row.groupId : '- -'}}</span>
+                                                </template>
+                                                <template slot-scope="{ row, index }" slot="groupName">
+                                                    <span>{{row.groupName ? row.groupName : $t('cusMgt.noGroup')}}</span>
+                                                </template>
+                                            </Table>
+                                        </vuescroll>
                                     </div>
                                 </Split>
                                 <EmptyData v-show="schdList.length == 0" :textContent="$t('cusMgt.noListTips')"></EmptyData>
                             </div>
-                            <!-- 教师课表 -->
+                            <!-- 教师课表 标准课程取消根据老师设置上课时段的功能,保留以教室为单位设置时段-->
                             <vuescroll v-show="curTab == 1">
-                                <TeaTable style="height: calc(100% - 45px)" :tableLoading="tableLoading" :courseId="courseId" v-if="hasTimeTable" :teaClassList="schdClassList" :teacher="teaList[curTeaIndex] ? teaList[curTeaIndex].id : ''" :periodId="filterPeriod" :schedData="schdData" @selectCell="selectCell" @cancelCell="cancelCell"></TeaTable>
+                                <TeaTable style="height: calc(100% - 45px)" :tableLoading="tableLoading" :courseId="courseId" v-if="hasTimeTable" :teaRoomList="schdRoomList" :teacher="teaList[curTeaIndex] ? teaList[curTeaIndex].id : ''" :periodId="filterPeriod" :schedData="schdData" @selectCell="selectCell" @cancelCell="cancelCell"></TeaTable>
                                 <div v-else>
                                     <p class="no-time-table-tips">
                                         {{filterPeriodName}}{{$t('cusMgt.notime1')}}
@@ -203,9 +192,9 @@
                                     </span>
                                 </div>
                             </div>
-                            <Table ref="sltClass" v-show="addType == 'class'" :columns="classroomCol" :data="calssTable" style="margin-top:10px" @on-selection-change="(selection)=>{sltClass = selection}">
+                            <Table ref="sltClass" v-show="addType == 'class'" :columns="classroomCol" :data="classTableList" style="margin-top:10px" @on-selection-change="(selection)=>{sltClass = selection}">
                                 <template slot-scope="{ row }" slot="grade">
-                                    <span>{{$jsFn.getGradeName(schoolBase,row.gradeId)}}</span>
+                                    <span>{{getGradeByYear(row.year)}}</span>
                                 </template>
                             </Table>
                             <Table ref="sltList" v-show="addType == 'stulist'" :columns="listCol" :data="stuList" style="margin-top:10px" @on-selection-change="(selection)=>{sltList = selection}">
@@ -250,7 +239,7 @@
                 <FormItem :label="$t('cusMgt.cusName')" prop="name">
                     <Input v-model="courseBaseInfo.name" :placeholder="$t('cusMgt.nameHolder')"></Input>
                 </FormItem>
-                <FormItem :label="$t('cusMgt.cusCode')" prop="no">
+                <FormItem :label="$t('cusMgt.cusCode')">
                     <Input v-model="courseBaseInfo.no" :placeholder="$t('cusMgt.codeHolder')"></Input>
                 </FormItem>
                 <FormItem :label="$t('cusMgt.cusPd')" prop="period.id">
@@ -277,10 +266,6 @@
             </div>
             <StudentList @getSelectInfo="(selction)=>{listSelections = selction}"></StudentList>
         </Modal>
-        <!-- 时段设置 -->
-        <Drawer :title="$t('cusMgt.timeSetTitle')" class-name="dark-iview-drawer" :closable="false" v-model="showTime" :width="450">
-            <TimeSetting :periodId="filterPeriod"></TimeSetting>
-        </Drawer>
     </div>
 </template>
 <script>
@@ -308,7 +293,8 @@ export default {
         return {
             tableLoading: false,
             listLoading: false,
-            classList: [],
+            roomList: [],  //教室列表
+            classList: [],  //班级列表
             addType: 'class',
             listName: '',
             addStuListStatus: false,
@@ -521,6 +507,49 @@ export default {
         }
     },
     methods: {
+        //设置上课教室
+        setCusRoom(room) {
+            console.log(room)
+            this.$set(this.schdList[this.curClassIndex], 'roomInfo', {
+                id: room.id,
+                name: room.name
+            })
+            // this.schdList[this.curClassIndex].roomInfo = {
+            //     id:room.id,
+            //     name:room.name
+            // }
+            console.log(this.schdList[this.curClassIndex])
+            this.updCusInfo()
+        },
+        //根据班级学年计算年级
+        getGradeByYear(year) {
+            if (year && this.schoolBase && this.schoolBase.period.length && this.filterPeriod) {
+                let pData = this.schoolBase.period.find(item => {
+                    return item.id == this.filterPeriod
+                })
+                if (pData) {
+                    let date = new Date()
+                    let curYear = date.getFullYear()
+                    let month = date.getMonth() + 1
+                    let start = pData.semesters.find(item => {
+                        return item.start == 1
+                    })
+                    // 根据入学月份确定当前年级和学级的关系
+                    if (start && month < start.month) {
+                        curYear--
+                    }
+                    let res = pData.grades[curYear - year]
+                    if (curYear - year >= pData.grades.length) {
+                        return '已毕业'
+                    }
+                    return res ? res.name : '未入学'
+                } else {
+                    return '- -'
+                }
+            } else {
+                return '- -'
+            }
+        },
         //查询教师课表数据
         async getTeaSchd() {
             let teaId = this.teaList[this.curTeaIndex].id
@@ -588,7 +617,7 @@ export default {
                                 res.courses[0].schedule.forEach(item => {
                                     //补充教室信息
                                     if (item.classId) {
-                                        let classInfo = this.classList.find(classItem => {
+                                        let classInfo = this.roomList.find(classItem => {
                                             return classItem.id == item.classId
                                         })
                                         item.classInfo = {
@@ -676,23 +705,23 @@ export default {
         },
         selectTab(index) {
             this.curTab = index
-            this.setDefClass()
+            // this.setDefClass()
             let teaId = this.teaList[this.curTeaIndex].id
             if (index == 1 && teaId && !this.teaSchds[teaId]) {
                 this.getTeaSchd()
             }
         },
         //设置默认授课教室
-        setDefClass() {
-            if (this.schdList[this.curClassIndex]) {
-                this.setCurClass = this.schdList[this.curClassIndex].classId || ''
-                if (!this.setCurClass && this.schdClassList[0]) {
-                    this.setCurClass = this.schdClassList[0].classId
-                }
-            } else {
-                this.setCurClass = ''
-            }
-        },
+        // setDefClass() {
+        //     if (this.schdList[this.curClassIndex]) {
+        //         this.setCurClass = this.schdList[this.curClassIndex].classId || ''
+        //         if (!this.setCurClass && this.schdRoomList[0]) {
+        //             this.setCurClass = this.schdRoomList[0].classId
+        //         }
+        //     } else {
+        //         this.setCurClass = ''
+        //     }
+        // },
         //设置课程时段
         selectCell(data) {
             let teacher = this.teaList[this.curTeaIndex] ? this.teaList[this.curTeaIndex].id : ''
@@ -705,7 +734,7 @@ export default {
                 return
             }
             let schedule = this.courseListShow[this.curCusIndex].schedule.find(item => {
-                return item.classId == data.setClass && item.teacherId == this.teaList[this.curTeaIndex].id
+                return item.room == data.setClass && item.teacherId == this.teaList[this.curTeaIndex].id
             })
             if (schedule) {
                 schedule.time.push({
@@ -721,7 +750,7 @@ export default {
                 })
                 if (tableData) {
                     let s = tableData.schedule.find(item => {
-                        return item.classId == data.setClass && item.teacherId == this.teaList[this.curTeaIndex].id
+                        return item.room == data.setClass && item.teacherId == this.teaList[this.curTeaIndex].id
                     })
                     if (s) {
                         s.time.push({
@@ -737,7 +766,7 @@ export default {
         //取消课程时段设置
         cancelCell(data) {
             let schedule = this.courseListShow[this.curCusIndex].schedule.find(item => {
-                return item.classId == data.setClass && item.teacherId == this.teaList[this.curTeaIndex].id
+                return item.room == data.setClass && item.teacherId == this.teaList[this.curTeaIndex].id
             })
             if (schedule) {
                 for (let index in schedule.time) {
@@ -755,7 +784,7 @@ export default {
                 })
                 if (tableData) {
                     let s = tableData.schedule.find(item => {
-                        return item.classId == data.setClass && item.teacherId == this.teaList[this.curTeaIndex].id
+                        return item.room == data.setClass && item.teacherId == this.teaList[this.curTeaIndex].id
                     })
                     if (s) {
                         for (let index in s.time) {
@@ -811,12 +840,14 @@ export default {
             this.curClassIndex = 0
             this.curTeaIndex = index
             this.setIsDefault()
-            this.setDefClass()
+            // this.setDefClass()
             this.initStatus()
             //获取老师所有授课数据渲染课程表
-            let teaId = this.teaList[this.curTeaIndex].id
-            if (this.curTab == 1 && teaId && !this.teaSchds[teaId]) {
-                this.getTeaSchd()
+            if (this.teaList.length) {
+                let teaId = this.teaList[this.curTeaIndex].id
+                if (this.curTab == 1 && teaId && !this.teaSchds[teaId]) {
+                    this.getTeaSchd()
+                }
             }
         },
         /**
@@ -836,7 +867,7 @@ export default {
                     }).then(
                         res => {
                             res.stus.forEach(item => {
-                                let classInfo = this.classList.find(classItem => {
+                                let classInfo = this.roomList.find(classItem => {
                                     return classItem.id == item.classId
                                 })
                                 if (classInfo) {
@@ -873,7 +904,7 @@ export default {
         },
         //设置教室名称
         setClassName(data, option) {
-            let curClass = this.classList.find(item => {
+            let curClass = this.roomList.find(item => {
                 return item.id == data
             })
             if (option == 'insert') { //添加名单的逻辑
@@ -915,9 +946,11 @@ export default {
             }
             if (this.addType == 'class' && this.sltClass.length > 0) {
                 //先判断是否有空的schedule(只是添加了老师,没有教室和名单)
+                let emptyIndex = -1
                 this.courseListShow[this.curCusIndex].schedule.forEach((item, index) => {
                     if (item.teacherId == this.schedule.teacherId && !item.stulist && !item.classId) {
-                        this.courseListShow[this.curCusIndex].schedule.splice(index, 1)
+                        // this.courseListShow[this.curCusIndex].schedule.splice(index, 1) //直接删除会改变顺序,产生bug错觉
+                        emptyIndex = index
                     }
                 })
                 this.sltClass.forEach(item => {
@@ -930,18 +963,25 @@ export default {
                             id: item.id,
                             name: item.name
                         }
-                        this.courseListShow[this.curCusIndex].schedule.push(JSON.parse(JSON.stringify(this.schedule)))
+                        if (emptyIndex > -1) {
+                            this.courseListShow[this.curCusIndex].schedule.splice(emptyIndex, 1, JSON.parse(JSON.stringify(this.schedule))) //直接删除会改变顺序,产生bug错觉
+                            emptyIndex = -1
+                        } else {
+                            this.courseListShow[this.curCusIndex].schedule.push(JSON.parse(JSON.stringify(this.schedule)))
+                        }
+
                     }
                 })
                 this.sltClass = []
             } else if (this.addType == 'stulist' && this.sltList.length > 0) {
                 //先判断是否有空的schedule(只是添加了老师,没有教室和名单)
+                let emptyIndex = -1
                 this.courseListShow[this.curCusIndex].schedule.forEach((item, index) => {
                     if (item.teacherId == this.schedule.teacherId && !item.stulist && !item.classId) {
-                        this.courseListShow[this.curCusIndex].schedule.splice(index, 1)
+                        // this.courseListShow[this.curCusIndex].schedule.splice(index, 1)
+                        emptyIndex = index
                     }
                 })
-
                 this.sltList.forEach(item => {
                     let exist = this.courseListShow[this.curCusIndex].schedule.find(schdItem => {
                         return schdItem.stulist == item.id && schdItem.teacherId == this.schedule.teacherId
@@ -949,7 +989,12 @@ export default {
                     if (!exist) {
                         this.schedule.stulist = item.id
                         this.schedule.listName = item.name
-                        this.courseListShow[this.curCusIndex].schedule.push(JSON.parse(JSON.stringify(this.schedule)))
+                        if (emptyIndex > -1) {
+                            this.courseListShow[this.curCusIndex].schedule.splice(emptyIndex, 1, JSON.parse(JSON.stringify(this.schedule))) //直接删除会改变顺序,产生bug错觉
+                            emptyIndex = -1
+                        } else {
+                            this.courseListShow[this.curCusIndex].schedule.push(JSON.parse(JSON.stringify(this.schedule)))
+                        }
                     }
                 })
                 this.sltList = []
@@ -957,6 +1002,7 @@ export default {
                 this.$Message.warning(this.$t('cusMgt.sltListTips'))
                 return
             }
+            console.log('课程信息:', this.courseListShow[this.curCusIndex])
             this.isAddStuList = false
             this.updCusInfo()
             this.initSchedule()
@@ -1033,10 +1079,12 @@ export default {
                 title: this.$t('cusMgt.remvListTitle'),
                 content: `${this.$t('cusMgt.remvListConten')}${this.schdList[this.curClassIndex].listName || this.schdList[this.curClassIndex].classInfo.name}?`,
                 onOk: () => {
+                    let index = this.curClassIndex
+                    this.curClassIndex = 0
+                    let curSchd = this.schdList[index]
                     //如果只有一个名单的时候移除名单则为清空名单,不能真的删除
                     if (this.schdList.length == 1) {
                         for (let i in this.courseListShow[this.curCusIndex].schedule) {
-                            let curSchd = this.schdList[this.curClassIndex]
                             if (this.courseListShow[this.curCusIndex].schedule[i].classId == curSchd.classId && this.courseListShow[this.curCusIndex].schedule[i].stulist == curSchd.stulist) {
                                 this.courseListShow[this.curCusIndex].schedule[i].classId = ''
                                 this.courseListShow[this.curCusIndex].schedule[i].stulist = ''
@@ -1045,11 +1093,12 @@ export default {
                             }
                         }
                     } else {
-                        for (let i in this.courseListShow[this.curCusIndex].schedule) {
-                            let curSchd = this.schdList[this.curClassIndex]
+                        for (let i = 0; i < this.courseListShow[this.curCusIndex].schedule.length; i++) {
+
                             if (this.courseListShow[this.curCusIndex].schedule[i].classId == curSchd.classId && this.courseListShow[this.curCusIndex].schedule[i].stulist == curSchd.stulist) {
                                 this.courseListShow[this.curCusIndex].schedule.splice(i, 1)
-                                break
+                                i--
+                                // break
                             }
                         }
                     }
@@ -1099,15 +1148,16 @@ export default {
             this.courseListShow = this.courseList.filter(item => {
                 return item.period.id == this.filterPeriod
             })
+            this.selectCus(0)
 
             let curGd = this.schoolBase.period.find(item => {
                 return item.id == this.filterPeriod
             })
             if (curGd) {
-                let filters = curGd.grades.map(item => {
+                let filters = curGd.grades.map((item, index) => {
                     return {
                         label: item.name,
-                        value: item.id
+                        value: index + 1
                     }
                 })
                 //年级筛选条件
@@ -1164,6 +1214,7 @@ export default {
                             if (res.courses && res.courses.length > 0) {
                                 res.courses[0].schedule = res.courses[0].schedule ? res.courses[0].schedule : []
                                 res.courses[0].schedule.forEach(item => {
+                                    //补充班级信息
                                     if (item.classId) {
                                         let classInfo = this.classList.find(classItem => {
                                             return classItem.id == item.classId
@@ -1180,6 +1231,7 @@ export default {
                                             }
                                         }
                                     }
+                                    // 补充动态名单信息
                                     if (item.stulist) {
                                         let listInfo = this.stuList.find(listItem => {
                                             return listItem.id == item.stulist
@@ -1190,7 +1242,23 @@ export default {
                                             item.listName = '--'
                                         }
                                     }
-
+                                    // 补充教室信息
+                                    if (item.room) {
+                                        let roomInfo = this.roomList.find(roomItem => {
+                                            return roomItem.id == item.room
+                                        })
+                                        if (roomInfo) {
+                                            item.roomInfo = {
+                                                id: item.room,
+                                                name: roomInfo.name
+                                            }
+                                        } else {
+                                            item.roomInfo = {
+                                                id: item.room,
+                                                name: '--'
+                                            }
+                                        }
+                                    }
                                 })
                             }
                             this.$set(this.courseListShow, this.curCusIndex, res.courses[0])
@@ -1374,7 +1442,7 @@ export default {
                         }).then(
                             res => {
                                 res.stus.forEach(item => {
-                                    let classInfo = this.classList.find(classItem => {
+                                    let classInfo = this.roomList.find(classItem => {
                                         return classItem.id == item.classId
                                     })
                                     if (classInfo) {
@@ -1429,15 +1497,16 @@ export default {
                     this.filterPeriod = this.schoolBase.period[0].id
                     this.hasTimeTable = this.schoolBase.period[0].timetable ? true : false
                 }
+                this.roomList = JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_rooms))
                 this.classList = JSON.parse(JSON.stringify(this.$store.state.user.schoolProfile.school_classes))
                 let curGd = this.schoolBase.period[0].grades
-                let filters = curGd.map(item => {
+                let filters = curGd.map((item, index) => {
                     return {
                         label: item.name,
-                        value: item.id
+                        value: index + 1
                     }
                 })
-                //年级筛选条件
+                //年级筛选条件 现在教室没有年级属性,这里调整为筛选是否有设置上课班级
                 this.classroomCol.push({
                     title: this.$t('cusMgt.gradeLabel'),
                     slot: 'grade',
@@ -1445,7 +1514,24 @@ export default {
                     filters: filters,
                     filterMultiple: false,
                     filterMethod(value, row) {
-                        return row.gradeId == value
+                        let date = new Date()
+                        let curYear = date.getFullYear()
+                        if (this.schoolBase && this.schoolBase.period.length && this.filterPeriod) {
+                            let pData = this.schoolBase.period.find(item => {
+                                return item.id == this.filterPeriod
+                            })
+                            if (pData) {
+                                let month = date.getMonth() + 1
+                                let start = pData.semesters.find(item => {
+                                    return item.start == 1
+                                })
+                                // 根据入学月份确定当前年级和学级的关系
+                                if (start && month < start.month) {
+                                    curYear--
+                                }
+                            }
+                        }
+                        return row.year == curYear - value
                     }
                 })
             },
@@ -1462,6 +1548,14 @@ export default {
         this.findStuList()
     },
     computed: {
+        //当前学段班级列表
+        classTableList() {
+            let data = []
+            data = this.classList.filter(item => {
+                return item.periodId == this.filterPeriod
+            })
+            return data
+        },
         //当前课程id
         courseId() {
             return this.courseListShow[this.curCusIndex] ? this.courseListShow[this.curCusIndex].id : ''
@@ -1474,9 +1568,9 @@ export default {
             return []
         },
         //选择教室名单列表
-        calssTable() {
+        roomTable() {
             let tbData = []
-            tbData = this.classList.filter(item => {
+            tbData = this.roomList.filter(item => {
                 return item.periodId == this.filterPeriod
             })
             return tbData
@@ -1484,7 +1578,7 @@ export default {
         //级联选择年级班级
         csOptions() {
             let data = []
-            if (this.filterPeriod && this.schoolBase.period.length && this.classList.length) {
+            if (this.filterPeriod && this.schoolBase.period.length && this.roomList.length) {
                 let curPd = this.schoolBase.period.filter((item) => {
                     return item.id == this.filterPeriod
                 })
@@ -1495,7 +1589,7 @@ export default {
                             name: item.name,
                             children: []
                         }
-                        let child = this.classList.filter(classItem => {
+                        let child = this.roomList.filter(classItem => {
                             return classItem.gradeId == item.id
                         })
                         dataItem.children = child
@@ -1526,17 +1620,20 @@ export default {
                 let schds = this.courseListShow[this.curCusIndex].schedule.filter(item => {
                     return item.teacherId == this.teaList[this.curTeaIndex].id
                 })
+                //一个班级在不同的教室上课会出现重复的情况,这里用map去重
+                const ids = new Map()
                 return schds.filter(item => {
-                    return (item.classId || item.stulist)
+                    // return (item.classId || item.stulist) && (!ids.has(item.room) && ids.set(item.room, 1))
+                    return (item.classId && !ids.has(item.classId) && ids.set(item.classId, 1)) || (item.stulist  && !ids.has(item.stulist) && ids.set(item.stulist, 1))
                 })
             } else {
                 return []
             }
         },
         //当前老师课程安排,有设置教室的
-        schdClassList() {
+        schdRoomList() {
             return this.schdList.filter(item => {
-                return item.classId
+                return item.room
             })
         },
         //当前课程的授课老师列表

+ 15 - 10
TEAMModelOS/ClientApp/src/view/newcourse/TeaTable.vue

@@ -1,5 +1,5 @@
 <template>
-    <div class="cus-table-container dark-iview-table">
+    <div class="cus-table-container dark-iview-table cus-table">
         <vuescroll>
             <div class="cus-table-top dark-iview-input dark-iview-select">
                 <div class="class-filter-wrap">
@@ -104,10 +104,10 @@
             </Table>
         </vuescroll>
         <Modal v-model="modalStatus" :title="$t('cusMgt.cusClass')" @on-ok="modalOk" @on-cancel="modalCancel" class-name="dark-iview-modal dark-iview-select">
-            <Select v-show="teaClassList.length" v-model="setClass" style="display:inline-block;">
-                <Option v-for="(item,index) in teaClassList" :key="index" :value="item.classId">{{item.classInfo.name}}</Option>
+            <Select v-show="teaRoomList.length" v-model="setClass" style="display:inline-block;">
+                <Option v-for="(item,index) in teaRoomList" :key="index" :value="item.room">{{item.roomInfo.name}}</Option>
             </Select>
-            <p class="no-class-tips" v-show="!teaClassList.length">{{$t('cusMgt.noCourseClass')}}</p>
+            <p class="no-class-tips" v-show="!teaRoomList.length">{{$t('cusMgt.noCourseClass')}}</p>
         </Modal>
     </div>
 </template>
@@ -133,7 +133,7 @@ export default {
             type: String,
             default: ''
         },
-        teaClassList: {
+        teaRoomList: {
             type: Array,
             default: () => {
                 return []
@@ -159,6 +159,7 @@ export default {
                 period: []
             },
             classList: [],
+            roomList:[],
             timeColumns: [
                 {
                     title: ' ',
@@ -224,13 +225,14 @@ export default {
             if (this.curClass) {
                 let data = this._.cloneDeep(this.selectInfo)
                 data.setClass = this.setClass //当前设置的教室
+                console.log('设置数据',data)
                 this.$emit('selectCell', data)
             } else {
                 this.$$Message.warning(this.$t('cusMgt.setClassTips'))
             }
         },
         cancelCell(row, col) {
-            this.$emit('cancelCell', { row, col, setClass: row.weeklies[col].classId })
+            this.$emit('cancelCell', { row, col, setClass: row.weeklies[col].room })
         },
         modalCancel() {
 
@@ -262,8 +264,10 @@ export default {
         //直接读取登录成功拿到得学校基础信息
         this.$store.dispatch('user/getSchoolProfile').then(
             res => {
+                console.log('学校信息',res)
                 this.schoolBase = res.school_base
                 this.classList = res.school_classes
+                this.roomList = res.school_rooms
             },
             err => {
                 this.$Message.warning(this.$t('cusMgt.noSchool'))
@@ -277,6 +281,7 @@ export default {
     },
     computed: {
         timetable() {
+            if(!(this.schoolBase && this.schoolBase.period)) return []
             let curPrd = this.schoolBase.period.find(item => {
                 return item.id == this.periodId
             })
@@ -307,8 +312,8 @@ export default {
                     this.schedData.forEach(cusItem => {
                         if (cusItem && cusItem.schedule) {
                             cusItem.schedule.forEach((schedItem, sIndex) => {
-                                let classInfo = this.classList.find(classItem => {
-                                    return classItem.id == schedItem.classId
+                                let roomInfo = this.roomList.find(roomItem => {
+                                    return roomItem.id == schedItem.room
                                 })
                                 if (this.teacher) {
                                     if (this.teacher != schedItem.teacherId) {
@@ -319,8 +324,8 @@ export default {
                                     if (timeItem.id == item.id) {
                                         item.weeklies[timeItem.week].courseName = cusItem.name
                                         item.weeklies[timeItem.week].courseId = cusItem.id
-                                        item.weeklies[timeItem.week].classId = schedItem.classId
-                                        item.weeklies[timeItem.week].classroomName = classInfo ? classInfo.name : '--'
+                                        item.weeklies[timeItem.week].roomId = schedItem.room
+                                        item.weeklies[timeItem.week].classroomName = roomInfo ? roomInfo.name : '- -'
                                     }
                                 })
                             })

+ 1 - 1
TEAMModelOS/ClientApp/src/view/newcourse/TimeSetting.vue

@@ -11,7 +11,7 @@
                                     <span class="time">{{item.time}}</span>
                                     <span class="content">{{ '('+item.label+')'}}</span>
                                 </div>
-                                <div class="action-box">
+                                <div class="action-box" v-if="$access.ability('admin','schoolSetting-upd').validateAll">
                                     <Icon type="md-add" @click="showAddTime(index)" color="white" size="18" style="cursor:pointer;" />
                                     <Icon type="md-trash" @click="delTimeNode(index)" color="white" size="18" style="cursor:pointer;" />
                                     <Icon type="md-create" @click="editTimeNode(index)" color="white" size="18" style="cursor:pointer;" />

+ 0 - 0
TEAMModelOS/ClientApp/src/view/schoolmgmt/ClassroomSetting/ClassroomSetting.less


部分文件因文件數量過多而無法顯示